|
Программирование >> Oracle
Внешние процедуры на языке С 1317 Обратите внимание, как я позаботился о возвращении управления из данной функции только в одном месте. Если возврат управления происходит в нескольких местах, не забудьте в каждом из них вызывать функцию term(myCtx). Теперь переходим к остальным функциям. Следующая функция обрабатывает даты, переданные как параметры в режиме IN и OUT. Мы будем: принимать параметр типа DATE в режиме IN; форматировать его как строку с помощью соответствующих функций библиотеки OCI для трассировки (для работы с данными типа DATE предлагается около 16 функций OCI); добавлять один месяц к дате с помощью соответствующей функции OCI; присваивать новую дату параметру, переданному в режиме OUT; преобразовывать только что присвоенную дату в строку и выдавать ее; наконец, вызывать функцию term и возвращать управление. #ifdef WIN NT declspec (dllexport) #endif void pass date (OCIExtProcContext * ctx /* CONTEXT */, OCIDate * p idate /* OCIDATE */, short p idate i /* INDICATOR short */, OCIDate * p odate /* OCIDATE */, short * p odate i /* INDICATOR short */ char buffer[255]; ub4 buff len; char * fmt = dd-mon-yyyy hh24:mi:ss ; myCtxStruct *myCtx; if ((myCtx = init( ctx )) = NULL) return; debugf(myCtx, Вход в функцию Pass Date ) ; if (p idate i = OCI IND NOTNULL) buff len = sizeof(buffer); if (OCIDateToText(myCtx->errhp, p idate, fmt, strlen(fmt), NULL, -1, &buff len, buffer) != OCI SUCCESS) raise application error(myCtx,ERROR OCI ERROR, %s , lastOciError(myCtx)); else debugf(myCtx, Входной параметр типа date ел значение %.*s , buff len, buffer) ; if (OCIDateAddMonths(myCtx->errhp, p idate, 1, p odate) != OCI SUCCESS) 1318 Глава 18 raise application error(myCtx,ERROR OCI ERROR, %s ,lastOciError(myCtx)); else *p odate i = OCI IND NOTNULL; buff len = sizeof(buffer); if (OCIDateToText(myCtx->errhp, p odate, fmt, strlen(fmt), NULL, -1, &buff len,buffer) ! = OCI SUCCESS) raise application error (myCtx,ERROR OCI ERROR, %s ,lastOciError(myCtx)); else { debugf(myCtx, В1ходной параметр типа date получил значение %.*s , buff len, buffer) ; term(myCtx);} Теперь разберемся, что необходимо для приема и передачи строк. Работать со строками несколько проще, чем с данными типа NUMBER и DATE, поскольку они передаются просто как строки ASCII, завершаемые нулем. Для всех строк, передаваемых в режиме OUT, будет использоваться параметр MAXLEN. Параметр MAXLEN задает для возвращаемой строки максимальный размер буфера, который может изменяться при каждом вызове. Дело в том, что буфер предоставляет вызывающая среда, и при каждом вызове может передаваться в режиме OUT другой параметр другого размера. В рез-тате внешняя процедура сможет учесть размер и предотвратить переполнение буфера. Она проинформирует вызывающую среду о том, что предоставлен слишком маленький буфер, и сообщит, какого размера он должен быть. #ifdef WIN NT declspec (dllexport) #endif void pass str (OCIExtProcContext * ctx /* CONTEXT */, char * p istr /* STRING */, short p istr i /* INDICATOR short */, char * p ostr /* STRING */, short * p ostr i /* INDICATOR short */, int * p ostr ml /* MAXLEN int */ myCtxStruct *myCtx; if ((myCtx = init(ctx)) = NULL) return; Внешние процедуры на языке С 1319 debugf(myCtx, Вход в функцию Pass Str ) ; (p istr i = OCI IND NOTNULL) l istr l = (*p ostr ml strlen(p istr); > l istr l) strcpy(p ostr, p istr) ; strupr(p ostr); *p ostr i = OCI IND NOTNULL; else { raise application error(myCtx, ERROR STR TOO SMALL, в1ходной буфер размером %d байт должен быть длиной не ->менее%d байт , *p ostr ml, l istr l+l); term(myCtx); На примере следующей функции я продемонстрирую использование типа binaryinteger. Тип binaryinteger в PL/SQL представляет 32-битовое целое число со знаком. Передать его проще всего. Значения этого типа передаются естественным для программиста на языке С образом. Эта функция просто проверит входное значение и присвоит его (умноженное на 10) выходному параметру: #ifdef WIN NT declspec (dllexport) #endif void pass int (OCIExtProcContext int short int * short p iINT p iINT i P oINT p oINT i /* CONTEXT */, /* int */, /* INDICATOR short /* int */, /* INDICATOR short myCtxStruct*myCtx; if ((myCtx = init(ctx)) NULL ) return; debugf(myCtx, Вход в функцию Pass Int ) ; (p iINT i == OCI IND NOTNULL) < debugf(myCtx, Первый параметр типа INT еет значение %d , p iINT) ; *p oINT = p iINT*10; *p oINT i = OCI IND NOTNULL; debugf(myCtx, Устанавливаем выходному параметру типа INT ->значение%d , *p oINT) ;
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |