|
Программирование >> Oracle
Внешние процедуры на языке С 1311 myCtxStruct *myCtx = NULL; OCIEnv *envhp; OCISvcCtx *svchp; OCIError *errhp; ub4 key = 1; if (OCIExtProcGetEnv( ctx, &envhp, &svchp, &errhp ) != OCI SUCCESS) OCIExtProcRaiseExcpWithMsg(ctx,20000, не удалось подключиться к ОCI ,0); return NULL; /* - замените представленный выше вызов OCIExtProcGetEnv() следующим- - при использовании Pro*С - EXEC SQL REGISTER CONNECT USING :ctx; if (sqlca.sqlcode < 0) OCIExtProcRaiseExcpWithMsg(ctx,20000,sqlca.sqlerrm.sqlernnc,70); return NULL; if ((SQLEnvGet(0, &envhp) != OCI SUCCESS) (OCIHandleAlloc(envhp, (dvoid**)&errhp, OCI HTYPE ERROR,0,0) != OCI SUCCESS) (SQLSvcCtxGet(0, NULL, 0, &svchp) != OCI SUCCESS)) OCIExtProcRaiseExcpWithMsg(ctx,20000, не удалось получить среду ->OCI ,0); return NULL; Получив среду OCI, необходимо вызвать функцию OCIContextGetValue() для получения контекста. Эта функция принимает среду OCI и ключ и пытается получить указатель. Ключ в данном случае - 64-битовое число. Можно сохранять сколько угодно контекстов, но в этот раз мы будем использовать один. if (OCIContextGetValue(envhp, errhp, (ubl*)&key, sizeof(key), (dvoid**)&myCtx) != OCI SUCCESS) OCIExtProcRaiseExcpWithMsg(ctx,20000, не удалось получить контекст OCI ,0); return NULL; При получении указателя NULL (это происходит, если контекст еще не установлен), мы выделяем достаточный объем памяти для контекста и сохраняем его в контексте. Для выделения блока памяти, который остается действительным на все время существования процесса, вызывается функция OCIMemoryAllocate. После того как память выделена, она сохраняется в контексте с помощью вызова функции OCIContextSetValue. Эта функция на время сеанса сопоставляет указатель (который не будет изменяться) выбранному ключу. Следующий вызов функции OCIContextGetValue с тем же ключом в пределах того же сеанса позволит получить этот указатель. 1312 Глава 18 if (myCtx = NULL) { if (OCIMemoryAlloc(envhp, errhp, (dvoid**)&myCtx, OCI DURATION PROCESS, sizeof(myCtxStruct), OCI MEMORY CLEARED) ! = OCI SUCCESS) OCIExtProcRaiseExcpWithMsg(ctx,20000, не удалось поучить память OCI ,0); return NULL; myCtx->ctx = ctx; myCtx->envhp = envhp; myCtx->svchp = svchp; myCtx->errhp = errhp; if ( OCIContextSetValue(envhp, errhp, OCI DURATION SESSION, (ubl*)&key, sizeof(key), myCtx ) != OCI SUCCESS) raise application error(myCtx, 20000, %s , lastOciError(myCtx)); return NULL; Продолжаем, поскольку получение указателя NLLL означает, что параметры еще не обработаны. Мы обработаем их в следующем блоке кода. Для обработки файлов, правила построения которых аналогичны файлу параметров инициализации Oracle, используются предоставляемые библиотекой OCI функции управления параметрами. параметров инициализации описан в главе 2. Я обычно использую этот файл для управления выдачей трассировочной и отладочной информации и задания стандартных значений для других переменных, используемых в программе. Файл параметров инициализации для данного примера может выглядеть следующим образом: debugf = true debugf filename =extproc2.log debugf path = /tmp/ Он включает выдачу трассировочной информации (debugf = true) в файл /tmp/ extproc2.log. Можно добавить в этот файл дополнительные параметры и изменить код функции init так, чтобы можно было читать их и устанавливать соответствующие значения в контексте сеанса. Процесс чтения и обработки файла параметров инициализации состоит из следующих шагов. 1. Вызов функции OCIExtractInit для инициализации библиотеки обработки параметров. 2. Вызов функции OCIExtractSetNumKeys для передачи библиотеке OCI количества запрашиваемых имен. Оно должно совпадать с количеством параметров в файле параметров. 3. Вызов функции OCIExtractSetKey столько раз, сколько бгло указано в вызове функции OCIExtractSetNumKeys(). Внешние процедуры на языке С 1313 4. Вызов функции OCIExtractFromFile для обработки файла параметров. 5. Вызов функции OCIExtractTo<тип данных> для поочередного получения значений параметров. 6. Вызов функции OCIExtractTerm для завершения работы библиотеки обработки параметров и освобождения выделенных ей системных ресурсов. if ((OCIExtractInit(envhp, errhp) != OCI SUCCESS) (OCIExtractSetNumKeys(envhp, errhp, 3) != OCI SUCCESS) (OCIExtractSetKey(envhp, errhp, debugf , OCI EXTRACT TYPE BOOLEAN, 0, &false, NULL, NULL) != OCI SUCCESS) (OCIExtractSetKey( envhp, errhp, debugf filename , OCI EXTRACT TYPE STRING, 0, extproc.log , NULL, NULL) != OCI SUCCESS) (OCIExtractSetKey( envhp, errhp, debugf path , OCI EXTRACT TYPE STRING, 0, , NULL, NULL) != OCI SUCCESS) (OCIExtractFromFile(envhp, errhp, 0, INI FILE NAME) != OCI SUCCESS) (OCIExtractToBool(envhp, errhp, debugf , 0, &myCtx->debugf flag) != OCI SUCCESS) (OCIExtractToStr(envhp, errhp, debugf filename , 0, myCtx->debugf filename, sizeof(myCtx->debugf filename)) != OCI SUCCESS) (OCIExtractToStr(envhp, errhp, debugf path , 0, myCtx->debugf path, sizeof(myCtx->debugf path)) != OCI SUCCESS) (OCIExtractTerm(envhp, errhp) != OCI SUCCESS)) raise application error(myCtx, 20000, %s , lastOciError(myCtx)); return NULL; Далее следует блок кода, который будет выполняться при втором и последующих вызовах функции init в сеансе. Поскольку функция OCIContextGetValue для второго и последующих вызовов возвращает контекст, мы просто устанавливаем на него соответствующие указатели в структуре: else myCtx->ctx = ctx; myCtx->envhp = envhp; myCtx->svchp = svchp; myCtx->errhp = errhp;
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |