home *** CD-ROM | disk | FTP | other *** search
/ Freelog 42 / Freelog042.iso / Alu / Ancestrologie / Sources / InterBase_WI-V6.0.1-server.ZIP / examples / gpre / dynfull.e < prev    next >
Encoding:
Text File  |  2001-01-05  |  9.9 KB  |  497 lines

  1. /*
  2.  *  Program type:   Embedded Dynamic SQL
  3.  *
  4.  *    Description:
  5.  *        This program prompts for and executes unknown SQL statements.
  6.  * The contents of this file are subject to the Interbase Public
  7.  * License Version 1.0 (the "License"); you may not use this file
  8.  * except in compliance with the License. You may obtain a copy
  9.  * of the License at http://www.Inprise.com/IPL.html
  10.  *
  11.  * Software distributed under the License is distributed on an
  12.  * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
  13.  * or implied. See the License for the specific language governing
  14.  * rights and limitations under the License.
  15.  *
  16.  * The Original Code was created by Inprise Corporation
  17.  * and its predecessors. Portions created by Inprise Corporation are
  18.  *
  19.  * Copyright (C) 2000 Inprise Corporation
  20.  * All Rights Reserved.
  21.  * Contributor(s): ______________________________________.
  22.  */
  23.  
  24. #include "example.h"
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <time.h>
  29. #include <ctype.h>
  30. #include <ibase.h>
  31. #include "align.h"
  32.  
  33. #define    MAXLEN    1024
  34. #define EOF -1
  35.  
  36. void process_statement (XSQLDA **sqlda, char *query);
  37. void print_column (XSQLVAR *var);
  38. int get_statement (char *buf);
  39.  
  40. typedef struct vary {
  41.     short       vary_length;
  42.     char        vary_string [1];
  43. } VARY;
  44.  
  45. #ifndef ISC_INT64_FORMAT
  46.  
  47. /* Define a format string for printf.  Printing of 64-bit integers
  48.    is not standard between platforms */
  49.  
  50. #if (defined(_MSC_VER) && defined(WIN32)) || (defined(__BORLANDC__) && defined(__WIN32__))
  51. #define    ISC_INT64_FORMAT    "I64"
  52. #else
  53. #define    ISC_INT64_FORMAT    "ll"
  54. #endif
  55. #endif
  56.  
  57. EXEC SQL
  58.     SET SQL DIALECT 3;
  59.  
  60. EXEC SQL
  61.     SET DATABASE db = COMPILETIME "employee.gdb";
  62.  
  63.  
  64.  
  65. int main(ARG(int, argc), ARG(char **, argv))
  66. ARGLIST(int argc)
  67. ARGLIST(char **argv)
  68. {
  69.     char    query[MAXLEN];
  70.     XSQLDA    *sqlda;
  71.     char    db_name[128];
  72.  
  73.     if (argc < 2)
  74.     {
  75.         printf("Enter the database name:  ");
  76.         gets(db_name);
  77.     }
  78.     else
  79.         strcpy(db_name, *(++argv));
  80.  
  81.     EXEC SQL
  82.         CONNECT :db_name AS db;
  83.  
  84.     if (SQLCODE)
  85.     {
  86.         printf("Could not open database %s\n", db_name);
  87.         return(1);
  88.     }
  89.  
  90.     /*
  91.      *    Allocate enough space for 20 fields.
  92.      *    If more fields get selected, re-allocate SQLDA later.
  93.      */
  94.     sqlda = (XSQLDA *) malloc(XSQLDA_LENGTH (20));
  95.     sqlda->sqln = 20;
  96.     sqlda->version = 1;
  97.  
  98.  
  99.     /*
  100.      *    Process SQL statements.
  101.      */
  102.     while (get_statement(query))
  103.     {
  104.         process_statement(&sqlda, query);
  105.     }
  106.  
  107.     EXEC SQL
  108.         DISCONNECT db;
  109.  
  110.     return(0);
  111. }
  112.  
  113.  
  114. void process_statement(ARG(XSQLDA ISC_FAR * ISC_FAR *, sqldap), 
  115.         ARG(char ISC_FAR *, query))
  116.     ARGLIST(XSQLDA    **sqldap)
  117.     ARGLIST(char    *query)
  118. {
  119.     long    buffer[MAXLEN];
  120.     XSQLVAR    *var;
  121.     XSQLDA *sqlda;
  122.     short    num_cols, i;
  123.     short    length, alignment, type, offset;
  124.  
  125.     sqlda = *sqldap;
  126.     EXEC SQL
  127.         WHENEVER SQLERROR GO TO Error;
  128.  
  129.     /* Start a transaction for each statement */
  130.  
  131.     EXEC SQL
  132.         SET TRANSACTION;
  133.  
  134.     EXEC SQL
  135.         PREPARE q INTO SQL DESCRIPTOR sqlda FROM :query;
  136.  
  137.     EXEC SQL
  138.         DESCRIBE q INTO SQL DESCRIPTOR sqlda;
  139.  
  140.     /*
  141.      *    Execute a non-select statement.
  142.      */
  143.     if (!sqlda->sqld)
  144.     {
  145.         EXEC SQL
  146.             EXECUTE q;
  147.  
  148.         EXEC SQL
  149.             COMMIT;
  150.  
  151.     return ;
  152.     }
  153.  
  154.     /*
  155.      *    Process select statements.
  156.      */
  157.  
  158.     num_cols = sqlda->sqld;
  159.  
  160.     /* Need more room. */
  161.     if (sqlda->sqln < num_cols)
  162.     {
  163.         free(sqlda);
  164.         sqlda = (XSQLDA *) malloc(XSQLDA_LENGTH (num_cols));
  165.         sqlda->sqln = num_cols;
  166.         sqlda->sqld = num_cols;
  167.         sqlda->version = 1;
  168.  
  169.         EXEC SQL
  170.             DESCRIBE q INTO SQL DESCRIPTOR sqlda;
  171.  
  172.         num_cols = sqlda->sqld;
  173.     }
  174.  
  175.     /* Open the cursor. */
  176.     EXEC SQL
  177.         DECLARE c CURSOR FOR q;
  178.     EXEC SQL
  179.         OPEN c;
  180.  
  181.     /*
  182.      *     Set up SQLDA.
  183.      */
  184.     for (var = sqlda->sqlvar, offset = 0, i = 0; i < num_cols; var++, i++)
  185.     {
  186.         length = alignment = var->sqllen;
  187.         type = var->sqltype & ~1;
  188.  
  189.         if (type == SQL_TEXT)
  190.             alignment = 1;
  191.         else if (type == SQL_VARYING)
  192.         {   
  193.             /* Allow space for vary's strlen & space to insert
  194.                a null byte for printing */
  195.             length += sizeof (short) + 1;
  196.             alignment = sizeof (short);
  197.         }   
  198.         offset = ALIGN (offset, alignment);
  199.         var->sqldata = (char*) buffer + offset;
  200.         offset += length;
  201.         offset = ALIGN (offset, sizeof (short));
  202.         var->sqlind = (short*) ((char*) buffer + offset);
  203.         offset += sizeof  (short);
  204.     }
  205.  
  206.     /*
  207.      *    Print rows.
  208.      */
  209.     while (SQLCODE == 0)
  210.     {
  211.         EXEC SQL
  212.             FETCH c USING SQL DESCRIPTOR sqlda;
  213.  
  214.         if (SQLCODE == 100)
  215.             break;
  216.  
  217.         for (i = 0; i < num_cols; i++)
  218.         {
  219.             print_column(&sqlda->sqlvar[i]);
  220.         }
  221.         printf("\n");
  222.     }
  223.  
  224.     EXEC SQL
  225.         CLOSE c;
  226.  
  227.     EXEC SQL
  228.         COMMIT;
  229.     return;
  230.  
  231. Error:
  232.  
  233.     EXEC SQL
  234.         WHENEVER SQLERROR CONTINUE;
  235.  
  236.     printf("Statement failed.  SQLCODE = %d\n", SQLCODE);
  237.     fflush (stdout);
  238.     isc_print_status(gds__status);
  239.  
  240.     EXEC SQL
  241.         ROLLBACK;
  242.  
  243.     return;
  244. }
  245.  
  246.  
  247. /*
  248.  *    Print column's data.
  249.  */
  250. void print_column(ARG(XSQLVAR ISC_FAR *, var))
  251. ARGLIST(XSQLVAR    *var)
  252. {
  253.     short        dtype;
  254.     char        data[MAXLEN], *p;
  255.     char        blob_s[20], date_s[25];
  256.     VARY        *vary;
  257.     short        len; 
  258.     struct tm    times;
  259.     ISC_QUAD    bid;
  260.  
  261.     dtype = var->sqltype & ~1;
  262.     p = data;
  263.  
  264.     if ((var->sqltype & 1) && (*var->sqlind < 0))
  265.     {
  266.         switch (dtype)
  267.         {
  268.             case SQL_TEXT:
  269.             case SQL_VARYING:
  270.                 len = var->sqllen;
  271.                 break;
  272.             case SQL_SHORT:
  273.                 len = 6;
  274.                 if (var->sqlscale > 0) len += var->sqlscale;
  275.                 break;
  276.             case SQL_LONG:
  277.                 len = 11;
  278.                 if (var->sqlscale > 0) len += var->sqlscale;
  279.                 break;
  280.             case SQL_INT64:
  281.                 len = 21;
  282.                 if (var->sqlscale > 0) len += var->sqlscale;
  283.                 break;
  284.             case SQL_FLOAT:
  285.                 len = 15;
  286.                 break;
  287.             case SQL_DOUBLE:
  288.                 len = 24;
  289.                 break;
  290.             case SQL_TIMESTAMP:
  291.                 len = 24;
  292.                 break;
  293.             case SQL_TYPE_DATE:
  294.                 len = 10;
  295.                 break;
  296.             case SQL_TYPE_TIME:
  297.                 len = 13;
  298.                 break;
  299.             case SQL_BLOB:
  300.             case SQL_ARRAY:
  301.             default:
  302.                 len = 17;
  303.                 break;
  304.         }
  305.         if ((dtype == SQL_TEXT) || (dtype == SQL_VARYING))
  306.             sprintf(p, "%-*s ", len, "NULL");
  307.         else
  308.             sprintf(p, "%*s ", len, "NULL");
  309.     }
  310.     else
  311.     {
  312.         switch (dtype)
  313.         {
  314.             case SQL_TEXT:
  315.                 sprintf(p, "%.*s ", var->sqllen, var->sqldata);
  316.                 break;
  317.  
  318.             case SQL_VARYING:
  319.                 vary = (VARY*) var->sqldata;
  320.                 vary->vary_string[vary->vary_length] = '\0';
  321.                 sprintf(p, "%-*s ", var->sqllen, vary->vary_string);
  322.                 break;
  323.  
  324.             case SQL_SHORT:
  325.             case SQL_LONG:
  326.             case SQL_INT64:
  327.                 {
  328.                 ISC_INT64    value;
  329.                 short        field_width;
  330.                 short        dscale;
  331.                 switch (dtype)
  332.                     {
  333.                     case SQL_SHORT:
  334.                     value = (ISC_INT64) *(short *) var->sqldata;
  335.                     field_width = 6;
  336.                     break;
  337.                     case SQL_LONG:
  338.                     value = (ISC_INT64) *(long *) var->sqldata;
  339.                     field_width = 11;
  340.                     break;
  341.                     case SQL_INT64:
  342.                     value = (ISC_INT64) *(ISC_INT64 *) var->sqldata;
  343.                     field_width = 21;
  344.                     break;
  345.                     }
  346.                 dscale = var->sqlscale;
  347.                 if (dscale < 0)
  348.                     {
  349.                     ISC_INT64    tens;
  350.                     short    i;
  351.  
  352.                     tens = 1;
  353.                     for (i = 0; i > dscale; i--)
  354.                     tens *= 10;
  355.  
  356.                     if (value >= 0)
  357.                     sprintf (p, "%*" ISC_INT64_FORMAT "d.%0*" ISC_INT64_FORMAT "d",
  358.                         field_width - 1 + dscale, 
  359.                         (ISC_INT64) value / tens,
  360.                         -dscale, 
  361.                         (ISC_INT64) value % tens);
  362.                     else if ((value / tens) != 0)
  363.                     sprintf (p, "%*" ISC_INT64_FORMAT "d.%0*" ISC_INT64_FORMAT "d",
  364.                         field_width - 1 + dscale, 
  365.                         (ISC_INT64) (value / tens),
  366.                         -dscale, 
  367.                         (ISC_INT64) -(value % tens));
  368.                     else
  369.                     sprintf (p, "%*s.%0*" ISC_INT64_FORMAT "d",
  370.                         field_width - 1 + dscale, 
  371.                         "-0",
  372.                         -dscale, 
  373.                         (ISC_INT64) -(value % tens));
  374.                     }
  375.                 else if (dscale)
  376.                     sprintf (p, "%*" ISC_INT64_FORMAT "d%0*d", 
  377.                         field_width, 
  378.                         (ISC_INT64) value,
  379.                         dscale, 0);
  380.                 else
  381.                     sprintf (p, "%*" ISC_INT64_FORMAT "d%",
  382.                         field_width, 
  383.                         (ISC_INT64) value);
  384.                 };
  385.                 break;
  386.  
  387.             case SQL_FLOAT:
  388.                 sprintf(p, "%15g ", *(float *) (var->sqldata));
  389.                 break;
  390.  
  391.             case SQL_DOUBLE:
  392.                 sprintf(p, "%24g ", *(double *) (var->sqldata));
  393.                 break;
  394.  
  395.             case SQL_TIMESTAMP:
  396.                 isc_decode_timestamp((ISC_TIMESTAMP *)var->sqldata, ×);
  397.                 sprintf(date_s, "%04d-%02d-%02d %02d:%02d:%02d.%04d",
  398.                         times.tm_year + 1900,
  399.                         times.tm_mon+1,
  400.                         times.tm_mday,
  401.                         times.tm_hour,
  402.                         times.tm_min,
  403.                         times.tm_sec,
  404.                         ((ISC_TIMESTAMP *)var->sqldata)->timestamp_time % 10000);
  405.                 sprintf(p, "%*s ", 24, date_s);
  406.                 break;
  407.  
  408.             case SQL_TYPE_DATE:
  409.                 isc_decode_sql_date((ISC_DATE *)var->sqldata, ×);
  410.                 sprintf(date_s, "%04d-%02d-%02d",
  411.                         times.tm_year + 1900,
  412.                         times.tm_mon+1,
  413.                         times.tm_mday);
  414.                 sprintf(p, "%*s ", 10, date_s);
  415.                 break;
  416.  
  417.             case SQL_TYPE_TIME:
  418.                 isc_decode_sql_time((ISC_TIME *)var->sqldata, ×);
  419.                 sprintf(date_s, "%02d:%02d:%02d.%04d",
  420.                         times.tm_hour,
  421.                         times.tm_min,
  422.                         times.tm_sec,
  423.                         (*((ISC_TIME *)var->sqldata)) % 10000);
  424.                 sprintf(p, "%*s ", 13, date_s);
  425.                 break;
  426.  
  427.             case SQL_BLOB:
  428.             case SQL_ARRAY:
  429.                 bid = *(ISC_QUAD *) var->sqldata;
  430.                 sprintf(blob_s, "%08x:%08x", bid.gds_quad_high, bid.gds_quad_low);
  431.  
  432.                 sprintf(p, "%17s ", blob_s);
  433.                 break;
  434.  
  435.             default:
  436.                 break;
  437.         }
  438.     }
  439.  
  440.     while (*p)
  441.     {
  442.         putchar(*p++);
  443.     }
  444.     
  445. }
  446.  
  447.  
  448. /*
  449.  *    Prompt for and get input.
  450.  *    Statements are terminated by a semicolon.
  451.  */
  452. int get_statement(ARG(char ISC_FAR *, buf))
  453.     ARGLIST(char    *buf)
  454. {
  455.     short    c;
  456.     char    *p;
  457.     int        cnt;
  458.  
  459.     p = buf;
  460.     cnt = 0;
  461.     printf("SQL> ");
  462.  
  463.     for (;;)
  464.     {
  465.         if ((c = getchar()) == EOF)
  466.             return 0;
  467.  
  468.         if (c == '\n')
  469.         {
  470.             /* accept "quit" or "exit" to terminate application */
  471.  
  472.             if (!strncmp(buf, "exit;", 5))
  473.                 return 0;
  474.             if (!strncmp(buf, "quit;", 5))
  475.                 return 0;
  476.  
  477.             /* Search back through any white space looking for ';'.*/
  478.             while (cnt && isspace(*(p - 1)))
  479.             {
  480.                 p--;
  481.                 cnt--;
  482.             }
  483.             if (*(p - 1) == ';')
  484.             {
  485.                 *p++ = '\0';
  486.                 return 1;
  487.             }
  488.  
  489.             *p++ = ' ';
  490.             printf("CON> ");
  491.         }
  492.         else
  493.             *p++ = c;
  494.         cnt++;
  495.     }
  496. }
  497.