home *** CD-ROM | disk | FTP | other *** search
/ PC World 1999 May / PCWorld_1999-05_cd.bin / software / Vyzkuste / inprise / INTRBASE_55 / EXAMPLES / API / DYNFULL.E < prev    next >
Text File  |  1998-10-18  |  7KB  |  380 lines

  1. /*
  2.  *  Program type:   Embedded Dynamic SQL
  3.  *
  4.  *    Description:
  5.  *        This program prompts for and executes unknown SQL statements.
  6.  */
  7.  
  8. #include "example.h"
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <time.h>
  12. #include <ctype.h>
  13. #include <ibase.h>
  14. #include "align.h"
  15.  
  16. #define    MAXLEN    1024
  17. #define EOF -1
  18.  
  19. void process_statement PROTO((XSQLDA **sqlda, char *query));
  20. void print_column PROTO((XSQLVAR *var));
  21. int get_statement PROTO((char *buf));
  22.  
  23. typedef struct vary {
  24.     short       vary_length;
  25.     char        vary_string [1];
  26. } VARY;
  27.  
  28. EXEC SQL
  29.     SET DATABASE db = COMPILETIME "employee.gdb";
  30.  
  31.  
  32.  
  33. int main(ARG(int, argc), ARG(char **, argv))
  34. ARGLIST(int argc)
  35. ARGLIST(char **argv)
  36. {
  37.     char    query[MAXLEN];
  38.     XSQLDA    *sqlda;
  39.     char    db_name[128];
  40.  
  41.     if (argc < 2)
  42.     {
  43.         printf("Enter the database name:  ");
  44.         gets(db_name);
  45.     }
  46.     else
  47.         strcpy(db_name, *(++argv));
  48.  
  49.        EXEC SQL
  50.             SET TRANSACTION;
  51.  
  52.  
  53.     EXEC SQL
  54.         CONNECT :db_name AS db;
  55.  
  56.     if (SQLCODE)
  57.     {
  58.         printf("Could not open database %s\n", db_name);
  59.         return(1);
  60.     }
  61.  
  62.     EXEC SQL
  63.         COMMIT;
  64.  
  65.  
  66.     /*
  67.      *    Allocate enough space for 20 fields.
  68.      *    If more fields get selected, re-allocate SQLDA later.
  69.      */
  70.     sqlda = (XSQLDA *) malloc(XSQLDA_LENGTH (20));
  71.     sqlda->sqln = 20;
  72.     sqlda->version = 1;
  73.  
  74.  
  75.     /*
  76.      *    Process SQL statements.
  77.      */
  78.     while (get_statement(query))
  79.     {
  80.         process_statement(&sqlda, query);
  81.     }
  82.  
  83.     EXEC SQL
  84.         DISCONNECT db;
  85.  
  86.     return(0);
  87. }
  88.  
  89.  
  90. void process_statement(ARG(XSQLDA ISC_FAR * ISC_FAR *, sqldap), 
  91.         ARG(char ISC_FAR *, query))
  92.     ARGLIST(XSQLDA    **sqldap)
  93.     ARGLIST(char    *query)
  94. {
  95.     long    buffer[MAXLEN];
  96.     XSQLVAR    *var;
  97.     XSQLDA *sqlda;
  98.     short    num_cols, i;
  99.     short    length, alignment, type, offset;
  100.  
  101.     sqlda = *sqldap;
  102.     EXEC SQL
  103.         WHENEVER SQLERROR GO TO Error;
  104.  
  105. /*     Start transaction only when needed. */
  106.  
  107.         if ( !gds__trans )
  108.          {
  109.         EXEC SQL
  110.             SET TRANSACTION;
  111.          }
  112.  
  113.     EXEC SQL
  114.         PREPARE q INTO SQL DESCRIPTOR sqlda FROM :query;
  115.  
  116.     EXEC SQL
  117.         DESCRIBE q INTO SQL DESCRIPTOR sqlda;
  118.  
  119.     /*
  120.      *    Execute a non-select statement.
  121.      */
  122.     if (!sqlda->sqld)
  123.     {
  124.         EXEC SQL
  125.             EXECUTE q;
  126.  
  127.     return ;
  128.     }
  129.  
  130.     /*
  131.      *    Process select statements.
  132.      */
  133.  
  134.     num_cols = sqlda->sqld;
  135.  
  136.     /* Need more room. */
  137.     if (sqlda->sqln < num_cols)
  138.     {
  139.         free(sqlda);
  140.         sqlda = (XSQLDA *) malloc(XSQLDA_LENGTH (num_cols));
  141.         sqlda->sqln = num_cols;
  142.         sqlda->sqld = num_cols;
  143.         sqlda->version = 1;
  144.  
  145.         EXEC SQL
  146.             DESCRIBE q INTO SQL DESCRIPTOR sqlda;
  147.  
  148.         num_cols = sqlda->sqld;
  149.     }
  150.  
  151.     /* Open the cursor. */
  152.     EXEC SQL
  153.         DECLARE c CURSOR FOR q;
  154.     EXEC SQL
  155.         OPEN c;
  156.  
  157.     /*
  158.      *     Set up SQLDA.
  159.      */
  160.     for (var = sqlda->sqlvar, offset = 0, i = 0; i < num_cols; var++, i++)
  161.     {
  162.         length = alignment = var->sqllen;
  163.         type = var->sqltype & ~1;
  164.  
  165.         if (type == SQL_TEXT)
  166.             alignment = 1;
  167.         else if (type == SQL_VARYING)
  168.         {   
  169.             length += sizeof (short);
  170.             alignment = sizeof (short);
  171.         }   
  172.         offset = ALIGN (offset, alignment);
  173.         var->sqldata = (char*) buffer + offset;
  174.         offset += length;
  175.         offset = ALIGN (offset, sizeof (short));
  176.         var->sqlind = (short*) ((char*) buffer + offset);
  177.         offset += sizeof  (short);
  178.     }
  179.  
  180.     /*
  181.      *    Print rows.
  182.      */
  183.     while (SQLCODE == 0)
  184.     {
  185.         EXEC SQL
  186.             FETCH c USING SQL DESCRIPTOR sqlda;
  187.  
  188.         if (SQLCODE == 100)
  189.             break;
  190.  
  191.         for (i = 0; i < num_cols; i++)
  192.         {
  193.             print_column(&sqlda->sqlvar[i]);
  194.         }
  195.         printf("\n");
  196.     }
  197.  
  198.     EXEC SQL
  199.         CLOSE c;
  200.  
  201.     EXEC SQL
  202.         COMMIT;
  203.     return;
  204.  
  205. Error:
  206.  
  207.  
  208.        EXEC SQL
  209.            WHENEVER SQLERROR CONTINUE;
  210.  
  211.     printf("Statement failed.  SQLCODE = %d\n", SQLCODE);
  212.     isc_print_status(gds__status);
  213. }
  214.  
  215.  
  216. /*
  217.  *    Print column's data.
  218.  */
  219. void print_column(ARG(XSQLVAR ISC_FAR *, var))
  220. ARGLIST(XSQLVAR    *var)
  221. {
  222.     short        dtype;
  223.     char        data[MAXLEN], *p;
  224.     char        blob_s[20], date_s[20];
  225.     VARY        *vary;
  226.     short        len; struct tm    times;
  227.     ISC_QUAD    bid;
  228.  
  229.     dtype = var->sqltype & ~1;
  230.     p = data;
  231.  
  232.     if ((var->sqltype & 1) && (*var->sqlind < 0))
  233.     {
  234.         switch (dtype)
  235.         {
  236.             case SQL_TEXT:
  237.             case SQL_VARYING:
  238.                 len = var->sqllen;
  239.                 break;
  240.             case SQL_SHORT:
  241.                 len = 6;
  242.                 break;
  243.             case SQL_LONG:
  244.                 len = 10;
  245.                 break;
  246.             case SQL_FLOAT:
  247.             case SQL_DOUBLE:
  248.                 len = 22;
  249.                 break;
  250.             case SQL_DATE:
  251.                 len = 10;
  252.                 break;
  253.             case SQL_BLOB:
  254.             case SQL_ARRAY:
  255.             default:
  256.                 len = 17;
  257.                 break;
  258.         }
  259.         if ((dtype == SQL_TEXT) || (dtype == SQL_VARYING))
  260.             sprintf(p, "%-*s ", len, "NULL");
  261.         else
  262.             sprintf(p, "%*s ", len, "NULL");
  263.     }
  264.     else
  265.     {
  266.         switch (dtype)
  267.         {
  268.             case SQL_TEXT:
  269.                 sprintf(p, "%.*s ", var->sqllen, var->sqldata);
  270.                 break;
  271.  
  272.             case SQL_VARYING:
  273.                 vary = (VARY*) var->sqldata;
  274.                 vary->vary_string[vary->vary_length] = '\0';
  275.                 sprintf(p, "%-*s ", var->sqllen, vary->vary_string);
  276.                 break;
  277.  
  278.             case SQL_SHORT:
  279.                 sprintf(p, "%6d ", *(short *) (var->sqldata));
  280.                 break;
  281.  
  282.             case SQL_LONG:
  283. #if !(defined __osf__ && defined __alpha)
  284.                 sprintf(p, "%10d ", *(long *) (var->sqldata));
  285. #else
  286.                 sprintf(p, "%10d ", *(int *) (var->sqldata));
  287. #endif
  288.                 break;
  289.  
  290.             case SQL_FLOAT:
  291.                 sprintf(p, "%22f ", *(float *) (var->sqldata));
  292.                 break;
  293.  
  294.             case SQL_DOUBLE:
  295.                 /* Detect numeric/decimal scale and handle format */
  296.                 if (var->sqlscale)
  297.                     sprintf(p, "%22.*f ", -var->sqlscale, 
  298.                         *(double *) (var->sqldata));
  299.                 else
  300.                     sprintf(p, "%22f ", 
  301.                         *(double *) (var->sqldata));
  302.                 break;
  303.  
  304.             case SQL_DATE:
  305.                 isc_decode_date((ISC_QUAD *)var->sqldata, ×);
  306.                 sprintf(date_s, "%2d/%d/%2d",
  307.                         times.tm_mday, times.tm_mon+1, times.tm_year);
  308.                 sprintf(p, "%*s ", 10, date_s);
  309.                 break;
  310.  
  311.             case SQL_BLOB:
  312.             case SQL_ARRAY:
  313.                 bid = *(ISC_QUAD *) var->sqldata;
  314.                 sprintf(blob_s, "%x:%x", bid.gds_quad_high, bid.gds_quad_low);
  315.                 sprintf(p, "%17s ", blob_s);
  316.                 break;
  317.  
  318.             default:
  319.                 break;
  320.         }
  321.     }
  322.  
  323.     while (*p)
  324.     {
  325.         putchar(*p++);
  326.     }
  327.     
  328. }
  329.  
  330.  
  331. /*
  332.  *    Prompt for and get input.
  333.  *    Statements are terminated by a semicolon.
  334.  */
  335. int get_statement(ARG(char ISC_FAR *, buf))
  336.     ARGLIST(char    *buf)
  337. {
  338.     short    c;
  339.     char    *p;
  340.     int        cnt;
  341.  
  342.     p = buf;
  343.     cnt = 0;
  344.     printf("SQL> ");
  345.  
  346.     for (;;)
  347.     {
  348.         if ((c = getchar()) == EOF)
  349.             return 0;
  350.  
  351.         if (c == '\n')
  352.         {
  353.             /* accept "quit" or "exit" to terminate application */
  354.  
  355.             if (!strncmp(buf, "exit;", 5))
  356.                 return 0;
  357.             if (!strncmp(buf, "quit;", 5))
  358.                 return 0;
  359.  
  360.             /* Search back through any white space looking for ';'.*/
  361.             while (cnt && isspace(*(p - 1)))
  362.             {
  363.                 p--;
  364.                 cnt--;
  365.             }
  366.             if (*(p - 1) == ';')
  367.             {
  368.                 *p++ = '\0';
  369.                 return 1;
  370.             }
  371.  
  372.             *p++ = ' ';
  373.             printf("CON> ");
  374.         }
  375.         else
  376.             *p++ = c;
  377.         cnt++;
  378.     }
  379. }
  380.