Приложение 5. Пример разбора спецификации выборки данных

#include < stdio.h >
#include < stdlib.h >
#include < string.h >
#include "decimals.h"
#include "inter.h"
#include "tick.h"

#ifdef WIN32
#include < float.h >
#define isnan(f)   _isnan(f)
#define isinf(f) (!_finite(f))
#endif

#include "exlib.h"

void PrintError(TCBL*pCBL);
void PrintResult(L_BYTE*Buf, L_BYTE*VarBuf);
void Print_value(L_CHAR*text, P_TYPE Type, L_BYTE*Buf);

char Query_Create_Table[]="create or replace table TEST (C1 char(10),"
  "C2 int,C3 real,C4 date,C5 decimal,C6 byte(10),C7 smallint,C8 double,"
  "C9 bigint,C10 varchar(10),C11 varbyte(10),C12 boolean,C13 nchar(10),"
  "C14 nchar varying(10), C15 BLOB, C16 extfile);";

char Query_Create_TabNan[]="create or replace table TESTnan ("
  "C1 int,C2 real,C3 double);";

char Query_Insert_Table1[]="insert into test values ('azzabyybcc',12,-12.345670,"
  "to_date('1998-12-01','YYYY-MM-DD'), 12.34,"
  "hex('FFFEFDFCFBFAF9F8F7F6'),30000,30.01,182834584,"
  "'azzabyybcc',hex('FFFEFDFCFBFAF9F8F7F6'),"
  "true,n'абвгдеж',n'abcdefg', NULL, extfile('1.txt'));";

char Query_Insert_Table[]="insert into test values "
  "(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
  NULL,NULL,NULL,NULL,NULL);";

char Query_InsNaN_Table[]="insert into test(c3,c8) "
"values ( cast HEXTORAW('0000807F00000000') as real,"
"cast HEXTORAW('000000000000F07F0000000000000000') as double);";

char Query_InsNaN1_Table[]="insert into test(c3,c8) "
"values ( cast HEXTORAW('000080FF00000000') as real,"
"cast HEXTORAW('000000000000F0FF0000000000000000') as DOUBLE);";

char Query_InsNaN2_Table[]="insert into test(c3,c8) "
"values ( cast HEXTORAW('0000C0FF00000000') as real,"
"cast HEXTORAW('000000000000F8FF0000000000000000') as DOUBLE);";

void PrintResult(L_BYTE*Buf,L_BYTE*VarBuf)
{
  L_WORD *pCntArg;
  P_TYPE Type;
  L_WORD i;
  L_CHAR str[100];
  L_BYTE *ptr;
  L_BYTE *ptr1;
  L_BYTE *ptr2;

  pCntArg = (L_WORD *) Buf;

  ptr1 = Buf+sizeof(L_WORD);
  ptr = ptr1+*pCntArg*sizeof(P_TYPE);

  VarBuf += 2*sizeof(WORD);

  for (i = 0; i <  *pCntArg; ++i)
  {
    if ((L_WORD)VarBuf[i])
      sprintf(str, "field %d:< NULL >\n", i + 1);
    else
      sprintf(str, "field %d:\n", i + 1);

    Type = *(P_TYPE*)ptr1;
    ptr2 = ptr;

    if ( Type.ntyp == DT_VARCHAR ||
         Type.ntyp == DT_VARBYTE ||
         Type.ntyp == DT_NVARCHAR )
      ptr2 += 2;

    Print_value(str, Type, ptr2);
    ptr += Type.length;
    if ( Type.ntyp == DT_VARCHAR ||
         Type.ntyp == DT_VARBYTE ||
         Type.ntyp == DT_NVARCHAR )
      ptr += 2;
    ptr1 += sizeof(P_TYPE);
  }
}

void Print_value(L_CHAR*text, P_TYPE Type, L_BYTE*ptr)
{
  L_WORD i;
  L_CHAR StrBuf[4000];
  L_WORD SmallBuf;
  L_LONG IntBuf;
  L_REAL RealBuf;
  L_DOUBLE DblBuf;
  L_DECIMAL DecBuf;
  L_DOUBLE NumBuf;

  printf(text);
  printf("typ = %d, len = %d ", (L_WORD)Type.ntyp, (L_WORD)Type.length);
  switch (Type.ntyp)
  {
    case DT_CHAR:
    case DT_VARCHAR:
      memcpy(StrBuf, ptr, Type.length);
      StrBuf[Type.length] = 0;
      printf("value = '%s'",StrBuf);
    break;
    case DT_INTEGER:
      if (Type.length == sizeof(L_WORD))
      {
         memcpy(&SmallBuf, ptr, sizeof(L_WORD));
         printf("value = %d", SmallBuf);
      }
      else
      {
         memcpy(&IntBuf, ptr, sizeof(L_LONG));
         printf("value = %ld", IntBuf);
      }
    break;
    case DT_REAL:
      if (Type.length == sizeof(L_REAL))
      {
         memcpy(&RealBuf, ptr, sizeof(L_REAL));
         if (isnan(RealBuf))
           printf("value = %4s", RealBuf  > 0 ? "nan" : "-nan");
         else
           if (isinf(RealBuf))
             printf("value = %4s", RealBuf  > 0 ? "inf" : "-inf");
           else
             printf("value = %g", RealBuf);
      }
      else
      {
         memcpy(&DblBuf, ptr, sizeof(L_DOUBLE));
         if (isnan(DblBuf))
           printf("value = %4s", DblBuf  > 0 ? "nan" : "-nan");
         else
           if (isinf(DblBuf))
             printf("value = %4s", DblBuf  > 0 ? "inf" : "-inf");
           else
             printf("value = %g", DblBuf);
      }
    break;
    case DT_DATE:
      memcpy(DecBuf, ptr, sizeof(L_DECIMAL));
      TICKTOSTRF(DecBuf, "value = dd.mm.yyyy:hh:mi:ss", StrBuf);
      printf(StrBuf);
    break;
    case DT_DECIMAL:
      memcpy(DecBuf, ptr, sizeof(L_DECIMAL));
      DecToDbl(DecBuf, &NumBuf);
      printf("value = %g", NumBuf);
    break;
    case DT_BYTE:
    case DT_VARBYTE:
    case DT_NCHAR:
    case DT_NVARCHAR:
      printf("value = ' ");
      for (i = 0; i <  Type.length; ++i)
        printf("%2x ", (L_WORD) ptr[i]);
      printf(" ' ");
    break;
    case DT_BLOB:
      printf("@:BLOB:@");
    break;
    case DT_EXTFILE:
      printf("@:EXTFILE:@");
    break;
    case DT_BOOL:
    {
      byte qqq = 0;
      memcpy(&qqq, ptr, 1);
      if (qqq)
        printf("value = < TRUE > ");
      else
        printf("value = < FALSE > ");
     }
     break;
  }
  printf("\n");
}

void main()
{
  TCBL CBLconnect;
  L_CHAR Name_Pass[] = "SYSTEM/MANAGER8";
  L_CHAR Node[] = " ";
  L_WORD Priority = 0;
  L_LONG PrzExe = M_EXCLUSIVE | Q_ENCODE | M_SPEC;
  L_LONG Err;
  L_CHAR Query[] = "select * from test;";
  L_CHAR QueryNaN[] = "select c3,c8 from test where c3 is nan or c8 is nan;";
  L_BYTE Buf[4096];
  L_BYTE VarBuf[20];

  Err=LinterOPEN(&CBLconnect, Name_Pass, Node,Priority, PrzExe);

  if (Err != NORMAL)
    PrintError(&CBLconnect);

  printf("Connect to RDBMS Linter\n");

  Err= LinterNotSelect(&CBLconnect, Query_Create_Table);
  if (Err != NORMAL)
    PrintError(&CBLconnect);

  Err= LinterNotSelect(&CBLconnect, Query_Insert_Table);
  if (Err != NORMAL)
    PrintError(&CBLconnect);

  Err= LinterNotSelect(&CBLconnect, Query_Insert_Table1);
  if (Err != NORMAL)
    PrintError(&CBLconnect);

  Err=LinterSLCT(&CBLconnect, PrzExe, Query, Buf,sizeof(Buf), VarBuf);
  if (Err != NORMAL)
    PrintError(&CBLconnect);
  else
  {
    printf("First Selected Row:\n");
    PrintResult(Buf,VarBuf);
  }

  Err=LinterGETL(&CBLconnect, Buf,sizeof(Buf), VarBuf);
  if (Err != NORMAL)
    PrintError(&CBLconnect);
  else
  {
    printf("\nLast Selected Row:\n");
    PrintResult(Buf,VarBuf);
  }

  Err= LinterNotSelect(&CBLconnect, Query_InsNaN_Table);
  if (Err != NORMAL)
    PrintError(&CBLconnect);

  Err= LinterNotSelect(&CBLconnect, Query_InsNaN1_Table);
  if (Err != NORMAL)
    PrintError(&CBLconnect);

  Err= LinterNotSelect(&CBLconnect, Query_InsNaN2_Table);
  if (Err != NORMAL)
    PrintError(&CBLconnect);

  Err=LinterSLCT(&CBLconnect, PrzExe, QueryNaN, Buf,sizeof(Buf), VarBuf);
  if (Err != NORMAL)
    PrintError(&CBLconnect);
  else
  {
    printf("\nFirst Selected NaN values:\n");
    PrintResult(Buf,VarBuf);
  }

  Err=LinterGETN(&CBLconnect, Buf,sizeof(Buf), VarBuf);
  if (Err != NORMAL)
    PrintError(&CBLconnect);
  else
  {
    printf("Next Selected NaN values:\n");
    PrintResult(Buf,VarBuf);
  }

  Err=LinterGETL(&CBLconnect, Buf,sizeof(Buf), VarBuf);
  if (Err != NORMAL)
    PrintError(&CBLconnect);
  else
  {
    printf("Last Selected NaN values:\n");
    PrintResult(Buf,VarBuf);
  }

  printf("End Example\n");
}

Результаты выполнения примера.

Connect to RDBMS Linter
First Selected Row:
field 1:< NULL >
typ = 1, len = 10 value = '          '
field 2:< NULL >
typ = 2, len = 4 value = 0
field 3:< NULL >
typ = 3, len = 4 value = 0
field 4:< NULL >
typ = 4, len = 16 VALUE = 00.00.0000:00:00:00
field 5:< NULL >
typ = 5, len = 16 value = 0
field 6:< NULL >
typ = 6, len = 10 value = '  0  0  0  0  0  0  0  0  0  0  '
field 7:< NULL >
typ = 2, len = 2 value = 0
field 8:< NULL >
typ = 3, len = 8 value = 0
field 9:< NULL >
typ = 2, len = 8 value = 0
field 10:< NULL >
typ = 8, len = 10 value = ''
field 11:< NULL >
typ = 9, len = 10 value = '  0  0  0  0  0  0  0  0  0  0  '
field 12:< NULL >
typ = 10, len = 1 value = < FALSE >
field 13:< NULL >
typ = 11, len = 20 value = ' 20  0 20  0 20  0 20  0 20  0 20  0 20  0 20  0 20  0 20  0  '
field 14:< NULL >
typ = 12, len = 20 value = '  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  '
field 15:
typ = 7, len = 24 @:BLOB:@
field 16:< NULL >
typ = 13, len = 522 @:EXTFILE:@

Last Selected Row:
field 1:
typ = 1, len = 10 value = 'azzabyybcc'
field 2:
typ = 2, len = 4 value = 12
field 3:
typ = 3, len = 4 value = -12.3457
field 4:
typ = 4, len = 16 VALUE = 01.12.1998:00:00:00
field 5:
typ = 5, len = 16 value = 12.34
field 6:
typ = 6, len = 10 value = ' ff fe fd fc fb fa f9 f8 f7 f6  '
field 7:
typ = 2, len = 2 value = 30000
field 8:
typ = 3, len = 8 value = 30.01
field 9:
typ = 2, len = 8 value = 182834584
field 10:
typ = 8, len = 10 value = 'azzabyybcc'
field 11:
typ = 9, len = 10 value = ' ff fe fd fc fb fa f9 f8 f7 f6  '
field 12:
typ = 10, len = 1 value = < TRUE >
field 13:
typ = 11, len = 20 value = ' 30  4 31  4 32  4 33  4 34  4 35  4 36  4 20  0 20  0 20  0  '
field 14:
typ = 12, len = 20 value = ' 61  0 62  0 63  0 64  0 65  0 66  0 67  0  0  0  0  0  0  0  '
field 15:
typ = 7, len = 24 @:BLOB:@
field 16:
typ = 13, len = 522 @:EXTFILE:@

First Selected NaN values:
field 1:
typ = 3, len = 4 value =  inf
field 2:
typ = 3, len = 8 value =  inf
Next Selected NaN values:
field 1:
typ = 3, len = 4 value = -inf
field 2:
typ = 3, len = 8 value = -inf
Last Selected NaN values:
field 1:
typ = 3, len = 4 value = -nan
field 2:
typ = 3, len = 8 value = -nan
End Example