Освобождение памяти дескриптора
Назначение
Освобождение памяти, ранее выделенной под дескриптор.
Синтаксис
< освобождение памяти дескриптора >::= EXEC SQL DEALLOCATE DESCRIPTOR < имя дескриптора >
Описание
-
< Имя дескриптора >
должно ссылаться на ранее созданный дескриптор. -
Конструкция
< освобождение памяти дескриптора >
освобождает ранее выделенную оперативную память для< имя дескриптора >
в пределах видимости этой переменной. -
Контроль повторного освобождения выделенной для дескриптора памяти не производится.
Примечание
В ранних версиях прекомпилятора освобождение памяти, занятой дескриптором, осуществлялось с помощью явного вызова функции sqlclu()
. В новых проектах использование этой функции строго не рекомендуется.
Пример
#include < stdlib.h > #include < stdio.h > #include < string.h > #if defined(VXWORKS) #include "vxstart.h" #endif #ifdef _DOS_ #include < conio.h > #endif EXEC LINTER IFDEF SQL; EXEC SQL INCLUDE SQLCA; EXEC LINTER ENDIF; EXEC SQL BEGIN DECLARE SECTION; char *user = "SYSTEM"; char *pswd = "MANAGER8"; char szSQL[4096] = {0}; char buf[65535] = {0}; int i = 0; int colCount = 0; int type = 0; int length = 0; int shift = 0; char * p = 0; DESCRIPTOR selectOutDesc; EXEC SQL END DECLARE SECTION; char *aszTypes[] = { "UNKNOWN", "CHAR","INT","SMALLINT","BIGINT","DOUBLE","REAL","DATE","DECIMAL", "BYTE","BLOB","VARCHAR","VARBYTE","BOOL","NCHAR","NVARCHAR","EXTFILE" }; int pcc2index(int pcc) { switch (pcc) { case 14 : return 9; case 15 : return 12; case 31 : return 10; case 16 : return 13; case 1 : return 1; case 12 : return 11; case 3 : return 8; case 9 : return 7; case 8 : return 5; case 6 : return 6; case 7 : return 6; case 4 : return 2; case 2 : return 8; case 5 : return 3; default : return 0; } } int align4(int shift) { return shift % 4 ? shift + 4 - shift % 4 : shift; } void printAnswer() { char szMask[200]; char szLen[20]; int i = 0; float _f = 0; int _i = 0; L_WORD varcharlen = 0; shift = 0; for (i = 1; i < = colCount; i++) { p = &buf[shift]; EXEC SQL GET DESCRIPTOR :selectOutDesc VALUE :i :type = TYPE, :length = LENGTH, :p = DATA; switch (type) { case 1: /*char*/ printf("%s ", &(buf[shift])); break; case 4: /*int*/ memcpy(&_i, &(buf[shift]), sizeof(_i)); printf("%d ", _i); break; case 6: /*dbl*/ memcpy(&_f, &(buf[shift]), sizeof(_f)); printf("%g ", _f); break; } shift += align4(length); } printf("\n"); } #if defined(VXWORKS) MainStart(pcc_sample, 1024*32, UninitLinterClient) #else int main() #endif { char c = 0; printf("Создание соединения..."); EXEC SQL WHENEVER SQLERROR GOTO not_conn; EXEC SQL CONNECT AUTOCOMMIT :user IDENTIFIED BY :pswd; printf("готово.\n"); printf("Выделение памяти под дескриптор..."); EXEC SQL ALLOCATE DESCRIPTOR :selectOutDesc; printf("готово.\n"); printf("Введите SELECT-запрос: >"); gets(szSQL); printf("Открытие оператора...", szSQL); EXEC SQL WHENEVER SQLERROR GOTO not_st_opened; EXEC SQL PREPARE ST_SEL FROM :szSQL; printf("готово.\n"); printf("Заполнение дескриптора..."); EXEC SQL WHENEVER SQLERROR GOTO not_desc_created; EXEC SQL DESCRIBE OUTPUT ST_SEL INTO SQL DESCRIPTOR :selectOutDesc; printf("готово.\n"); EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL GET DESCRIPTOR :selectOutDesc :colCount = COUNT; printf("Полей (столбцов) в выборке: = %d\n", colCount); for (i = 1; i < = colCount; i++) { EXEC SQL GET DESCRIPTOR :selectOutDesc VALUE :i :type = TYPE; EXEC SQL GET DESCRIPTOR :selectOutDesc VALUE :i :length = LENGTH; printf("Столбец %i. Тип %d, %s Длина %d\n", i, type, aszTypes[pcc2index(type)], length); } printf("Привязка буфера..."); shift = 0; for (i = 1; i < = colCount; i++) { p = &(buf[shift]); EXEC SQL GET DESCRIPTOR :selectOutDesc VALUE :i :length = LENGTH, :type = TYPE; if (type == PCC_CHR_TYP) length++; /* под тип CHAR нужно резервировать на 1 байт больше для места под 0-терминатор */ EXEC SQL SET DESCRIPTOR :selectOutDesc VALUE :i DATA = :p, LENGTH = :length; shift += align4(length); } printf("готово.\n"); printf("Открытие курсора..."); EXEC SQL WHENEVER SQLERROR GOTO not_cur_opened; EXEC SQL DECLARE CUR_SEL CURSOR FOR ST_SEL; EXEC SQL OPEN CUR_SEL; printf("готово.\n"); EXEC SQL WHENEVER SQLERROR GOTO not_fetched; for (i = 1; ;i++) { memset(buf, 0, sizeof(buf)); EXEC SQL FETCH CUR_SEL ABSOLUTE :i USING SQL DESCRIPTOR :selectOutDesc; if (ErrPCI_) { if (ErrPCI_ == 3000) printf("No more records\n"); else printf("Error code: %d\n", ErrPCI_); break; } printAnswer(); } printf("Освобождение памяти дескриптора..."); EXEC SQL DEALLOCATE DESCRIPTOR :selectOutDesc; /* EXEC SQL DEALLOCATE :CUR_SEL;*/ printf("готово.\n"); return 0; not_conn: printf("Не удалось создать соединение\n"); printf("Код ошибки: %d\n", ErrPCI_); return 1; not_selected: printf("Не удалось создать выборку\n"); printf("Код ошибки: %d\n", ErrPCI_); return 1; not_st_opened: printf("Не удалось открыть оператор\n"); printf("Код ошибки: %d\n", ErrPCI_); return 1; not_desc_created: printf("Не удалось создать дескриптор\n"); printf("Код ошибки: %d\n", ErrPCI_); not_cur_opened: printf("Не удалось открыть курсор\n"); printf("Код ошибки: %d\n", ErrPCI_); return 1; not_fetched: printf("Не удалось переместиться по выборке\n"); printf("Код ошибки: %d\n", ErrPCI_); return 1; }