Освобождение памяти дескриптора
Назначение
Освобождение памяти, ранее выделенной под дескриптор.
Синтаксис
<освобождение памяти дескриптора>::= 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;
}