Освобождение памяти дескриптора

Назначение

Освобождение памяти, ранее выделенной под дескриптор.

Синтаксис
 
< освобождение памяти дескриптора >::=
EXEC SQL DEALLOCATE DESCRIPTOR < имя дескриптора > 
Описание
  1. < Имя дескриптора > должно ссылаться на ранее созданный дескриптор.

  2. Конструкция < освобождение памяти дескриптора > освобождает ранее выделенную оперативную память для < имя дескриптора > в пределах видимости этой переменной.

  3. Контроль повторного освобождения выделенной для дескриптора памяти не производится.

Примечание

В ранних версиях прекомпилятора освобождение памяти, занятой дескриптором, осуществлялось с помощью явного вызова функции 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;
}