home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1996 February / PCWK0296.iso / po7_win / db / rdbms71 / cdemo2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-07  |  12.6 KB  |  505 lines

  1. #ifdef RCSID
  2. static char *RCSid = 
  3.    "$Header: cdemo2.c 7010300.1 94/02/24 18:40:41 snataraj Generic<base> $ ";
  4. #endif /* RCSID */
  5.  
  6. /* Copyright (c) 1991 by Oracle Corporation */
  7. /*
  8.    NAME
  9.      cdemo2.c - C demo Program # 2
  10.    MODIFIED   (MM/DD/YY)
  11.     emendez    02/07/94 -  fix for bug 196094
  12.     emendez    02/02/94 -  Fix for bug 157576
  13.     gdoherty   01/31/94 -  make oci header inclusion for ansi or k+r adaptive
  14.     tssmith    03/29/93 -  Removing ANSI material 
  15.     lfeng      03/08/93 -  merge changes from branch 1.6.312.1 
  16.     lfeng      02/10/93 -  portability mods 
  17.     rkooi2     11/27/92 -  Changing e... datatypes to s... 
  18.     lfeng      11/20/92 -  add portability mods
  19.     rkooi2     10/22/92 -  Changes for portability 
  20.     rkooi2     10/18/92 -  Changes to make it portable 
  21.     sjain      08/18/92 -  Changge connect to conect_user
  22.     sjain      03/16/92 -  Creation 
  23. */
  24.  
  25. /* This program accepts arbitrary SQL statements from the user,
  26.    and processes the statement.  Statements may be entered on
  27.    multiple lines, and must be terminated by a semi-colon.
  28.    If a query, the results are printed. */
  29.  
  30. #include <stdio.h>
  31. #include <ctype.h>
  32. #include <string.h>
  33.  
  34.  
  35. /* Include OCI-specific headers. */
  36. #include <oratypes.h>
  37. #include <ocidfn.h>
  38. #ifdef __STDC__
  39. #include <ociapr.h>
  40. #else
  41. #include <ocikpr.h>
  42. #endif
  43. #include <ocidem.h>
  44.  
  45.  
  46. /* Constants used in this program. */
  47. #define MAX_BINDS               12
  48. #define MAX_ITEM_BUFFER_SIZE    33
  49. #define MAX_SELECT_LIST_SIZE    12
  50. #define MAX_SQL_IDENTIFIER      31
  51.  
  52. #define PARSE_NO_DEFER           0
  53. #define PARSE_V7_LNG             2
  54.  
  55.  
  56. /* Define one logon data area and one cursor data area
  57.    Also define a host data area for orlon.
  58.    (See ocidfn.h for declarations). */
  59. Lda_Def lda;
  60. Cda_Def cda;
  61. ub1     hda[HDA_SIZE];
  62.  
  63. /* Declare an array of bind values. */
  64. text bind_values[MAX_BINDS][MAX_ITEM_BUFFER_SIZE];
  65.  
  66. /* Declare structures for query information. */
  67. struct describe
  68. {
  69.     sb4             dbsize;
  70.     sb2             dbtype;
  71.     sb1             buf[MAX_ITEM_BUFFER_SIZE];
  72.     sb4             buflen;
  73.     sb4             dsize;
  74.     sb2             precision;
  75.     sb2             scale;
  76.     sb2             nullok;
  77. };
  78.  
  79. struct define 
  80. {
  81.     ub1             buf[MAX_ITEM_BUFFER_SIZE];
  82.     float           flt_buf;
  83.     sword           int_buf;
  84.     sb2             indp;
  85.     ub2             col_retlen, col_retcode;
  86. };
  87.  
  88.  
  89. /* Define arrays of describe and define structs. */
  90. struct describe desc[MAX_SELECT_LIST_SIZE];
  91. struct define   def[MAX_SELECT_LIST_SIZE];
  92.  
  93. /*  Declare this programs functions. */
  94. sword  connect_user();
  95. sword  describe_define();
  96. sword  do_binds();
  97. void   do_exit();
  98. void   oci_error();
  99. sword  get_sql_statement();
  100. void   print_header();
  101. void   print_rows();
  102.  
  103. /* Globals */
  104. static text sql_statement[2048];
  105. static sword sql_function;
  106. static sword numwidth = 8;
  107.  
  108.  
  109. main()
  110. {
  111.     sword col, errno, n, ncols;
  112.     text *cp;
  113.  
  114.     /* Connect to ORACLE. */
  115.     if (connect_user())
  116.         exit(-1);
  117.  
  118.     /* Open a cursor, exit on error (unrecoverable). */
  119.     if (oopen(&cda, &lda, (text *) 0, -1, -1, (text *) 0, -1))
  120.     {
  121.         printf("Error opening cursor.  Exiting...\n");
  122.         ologof(&lda);
  123.         exit(-1);
  124.     }
  125.  
  126.     /* Process user's SQL statements. */
  127.  
  128.     for (;;)
  129.     {
  130.         /* Get the statement, exit on "exit". */
  131.         if (get_sql_statement())
  132.             do_exit(0);
  133.  
  134.         /* Parse the statement; do not defer the parse,
  135.            so that errors come back right away. */
  136.         if (oparse(&cda, (text *) sql_statement, (sb4) -1,
  137.                  (sword) PARSE_NO_DEFER, (ub4) PARSE_V7_LNG))
  138.         {
  139.             oci_error(&cda);
  140.             continue;
  141.         }
  142.  
  143.         /* Save the SQL function code right after parse. */
  144.         sql_function = cda.ft;
  145.  
  146.         /* Bind any input variables. */
  147.         if ((ncols = do_binds(&cda, sql_statement)) == -1)
  148.             continue;
  149.  
  150.         /* If the statement is a query, describe and define
  151.            all select-list items before doing the oexec. */
  152.         if (sql_function == FT_SELECT)
  153.             if ((ncols = describe_define(&cda)) == -1)
  154.                 continue;
  155.  
  156.         /* Execute the statement. */
  157.         if (oexec(&cda))
  158.         {
  159.             oci_error(&cda);
  160.             continue;
  161.         }
  162.  
  163.         /* Fetch and display the rows for the query. */
  164.         if (sql_function == FT_SELECT)
  165.         {
  166.             print_header(ncols);
  167.             print_rows(&cda, ncols);
  168.         }
  169.  
  170.         /* Print the rows-processed count. */
  171.         if (sql_function == FT_SELECT ||
  172.             sql_function == FT_UPDATE ||
  173.             sql_function == FT_DELETE ||
  174.             sql_function == FT_INSERT)
  175.             printf("\n%d row%c processed.\n", cda.rpc, 
  176.                    cda.rpc == 1 ? '\0' : 's');
  177.         else
  178.             printf("\nStatement processed.\n");
  179.  
  180.     } /* end for (;;) */
  181.  
  182.  
  183. }     /* end main() */
  184.  
  185.  
  186. sword
  187. connect_user()
  188. {
  189.     text username[132];
  190.     text password[132];
  191.     sword n;
  192.  
  193.     /* Three tries to connect. */
  194.     for (n = 3; --n >= 0; )
  195.     {
  196.         printf("Username: ");
  197.         gets((char *) username);
  198.         printf("Password: ");
  199.         gets((char *) password);
  200.  
  201.         if (orlon(&lda, hda, username, -1, password, -1, -1))
  202.         {
  203.             printf("Cannot connect as %s.\n", username);
  204.             printf("Try again.\n\n");
  205.         }
  206.         else
  207.         {
  208.             return 0;
  209.         }
  210.     }
  211.     printf("Connection failed.  Exiting...\n");
  212.     return -1;
  213. }
  214.  
  215.  
  216. /*  Describe select-list items. */
  217.  
  218. sword
  219. describe_define(cda)
  220. Cda_Def *cda;
  221. {
  222.     sword col, deflen, deftyp;
  223.     static ub1 *defptr;
  224.  
  225.     /* Describe the select-list items. */
  226.     for (col = 0; col < MAX_SELECT_LIST_SIZE; col++)
  227.     {
  228.         desc[col].buflen = MAX_ITEM_BUFFER_SIZE;
  229.         if (odescr(cda, col + 1, &desc[col].dbsize,
  230.                    &desc[col].dbtype, &desc[col].buf[0],
  231.                    &desc[col].buflen, &desc[col].dsize,
  232.                    &desc[col].precision, &desc[col].scale,
  233.                    &desc[col].nullok))
  234.         {
  235.             /* Break on end of select list. */
  236.             if (cda->rc == VAR_NOT_IN_LIST)
  237.                 break;
  238.             else
  239.             {
  240.                 oci_error(cda);
  241.                 return -1;
  242.             }
  243.         }
  244.         /* adjust sizes and types for display */
  245.         switch (desc[col].dbtype)
  246.         {
  247.         case NUMBER_TYPE:
  248.             desc[col].dbsize = numwidth;
  249.             /* Handle NUMBER with scale as float. */
  250.             if (desc[col].scale != 0)
  251.             {
  252.                 defptr = (ub1 *) &def[col].flt_buf;
  253.                 deflen = (sword) sizeof(float);
  254.                 deftyp = FLOAT_TYPE;
  255.                 desc[col].dbtype = FLOAT_TYPE;
  256.             }
  257.             else
  258.             {
  259.                 defptr = (ub1 *) &def[col].int_buf;
  260.                 deflen = (sword) sizeof(sword);
  261.                 deftyp = INT_TYPE;
  262.                 desc[col].dbtype = INT_TYPE;
  263.             }
  264.             break;
  265.         default:
  266.             if (desc[col].dbtype == DATE_TYPE)
  267.                 desc[col].dbsize = 9;
  268.             if (desc[col].dbtype == ROWID_TYPE)
  269.                 desc[col].dbsize = 18;
  270.             defptr = def[col].buf;
  271.             deflen = desc[col].dbsize > MAX_ITEM_BUFFER_SIZE ?
  272.               MAX_ITEM_BUFFER_SIZE : desc[col].dbsize + 1;
  273.             deftyp = STRING_TYPE;
  274.             break;
  275.         }
  276.         if (odefin(cda, col + 1,
  277.                    defptr, deflen, deftyp,
  278.                    -1, &def[col].indp, (text *) 0, -1, -1,
  279.                    &def[col].col_retlen,
  280.                    &def[col].col_retcode))
  281.         {
  282.             oci_error(cda);
  283.             return -1;
  284.         }
  285.     }
  286.     return col;
  287. }
  288.  
  289.  
  290. /*  Bind input variables. */
  291.  
  292. sword
  293. do_binds(cda, stmt_buf)
  294. Cda_Def *cda;
  295. text *stmt_buf;
  296. {
  297.     sword i, in_literal, n;
  298.     text *cp, *ph;
  299.  
  300.     /* Find and bind input variables for placeholders. */
  301.     for (i = 0, in_literal = FALSE, cp = stmt_buf;
  302.               *cp && i < MAX_BINDS; cp++)
  303.     {
  304.         if (*cp == '\'')
  305.             in_literal = ~in_literal;
  306.         if (*cp == ':' && !in_literal)
  307.         {
  308.             for (ph = ++cp, n = 0;
  309.                  *cp && (isalnum(*cp) || *cp == '_')
  310.                      && n < MAX_SQL_IDENTIFIER;
  311.                  cp++, n++
  312.                 )
  313.                 ;
  314.             *cp = '\0';
  315.             printf("Enter value for %s: ", ph);
  316.             gets((char *) &bind_values[i][0]);
  317.  
  318.             /* Do the bind, using obndrv().
  319.                NOTE:  the bind variable address must be static.
  320.                This would not work if bind_values were an
  321.                auto on the do_binds stack. */
  322.             if (obndrv(cda, ph, -1, &bind_values[i][0], -1, VARCHAR2_TYPE,
  323.                        -1, (sb2 *) 0, (text *) 0, -1, -1))
  324.             {
  325.                 oci_error(cda);
  326.                 return -1;
  327.             }
  328.             i++;
  329.         }   /* end if (*cp == ...) */
  330.     }       /* end for () */
  331.     return i;
  332. }
  333.  
  334.  
  335.  
  336. /*  Clean up and exit.  LDA and CDA are
  337.     global. */
  338. void
  339. do_exit(rv)
  340. sword rv;
  341. {
  342.     if (oclose(&cda))
  343.         fputs("Error closing cursor!\n", stdout);
  344.     if (ologof(&lda))
  345.         fputs("Error logging off!\n", stdout);
  346.     exit(rv);
  347. }
  348.  
  349.  
  350. void
  351. oci_error(cda)
  352. Cda_Def *cda;
  353. {
  354.     text msg[512];
  355.     sword n;
  356.  
  357.     fputs("\n-- ORACLE ERROR --\n", stderr);
  358.     n = oerhms(&lda, cda->rc, msg, (sword) sizeof (msg));
  359.     fprintf(stderr, "%.*s", n, msg);
  360.     fprintf(stderr, "Processing OCI function %s\n",
  361.             oci_func_tab[cda->fc]);
  362.     fprintf(stderr, "Do you want to continue? [yn]: ");
  363.     fgets((char *) msg, (int) sizeof (msg), stdin);
  364.     if (*msg != '\n' && *msg != 'y' && *msg != 'Y')
  365.         do_exit(1);
  366.     fputc('\n', stdout);
  367. }
  368.  
  369.  
  370. sword
  371. get_sql_statement()
  372. {
  373.     text cbuf[1024];
  374.     text *cp;
  375.     sword stmt_level;
  376.  
  377.  
  378.     for (stmt_level = 1; ;)
  379.     {
  380.         if (stmt_level == 1)
  381.         {
  382.             /* Init statement buffer and print prompt. */
  383.             *sql_statement = '\0';
  384.             fputs("\nOCISQL> ", stdout);
  385.         }
  386.         else
  387.         {
  388.             printf("%3d     ", stmt_level);
  389.         }
  390.  
  391.         /* Get (part of) a SQL statement. */
  392.         gets((char *) cbuf);
  393.         if (*cbuf == '\0')
  394.             continue;
  395.         if (strncmp((char *) cbuf, "exit", 4) == 0)
  396.             return -1;
  397.  
  398.         /* Concatenate to statement buffer. */
  399.         if (stmt_level > 1)
  400.             strcat((char *) sql_statement, " ");
  401.         strcat((char *) sql_statement, (char *) cbuf);
  402.  
  403.         /* Check for possible terminator. */
  404.         cp = &sql_statement[strlen((char *) sql_statement) - 1];
  405.         
  406.         while (isspace(*cp))
  407.             cp--;
  408.         if (*cp == ';')
  409.         {
  410.             *cp = '\0';
  411.             break;
  412.         }
  413.         stmt_level++;
  414.     }
  415.     return 0;
  416. }
  417.  
  418.  
  419. void
  420. print_header(ncols)
  421. sword ncols;
  422. {
  423.     sword col, n;
  424.  
  425.     fputc('\n', stdout);
  426.  
  427.     for (col = 0; col < ncols; col++)
  428.     {
  429.         n = desc[col].dbsize - desc[col].buflen;
  430.         if (desc[col].dbtype == FLOAT_TYPE ||
  431.             desc[col].dbtype == INT_TYPE)
  432.         {
  433.             printf("%*c", n, ' ');
  434.             printf("%*.*s", desc[col].buflen,
  435.                    desc[col].buflen, desc[col].buf);
  436.         }
  437.         else
  438.         {
  439.             printf("%*.*s", desc[col].buflen,
  440.                    desc[col].buflen, desc[col].buf);
  441.             printf("%*c", n, ' ');
  442.         }
  443.         fputc(' ', stdout);
  444.     }            
  445.     fputc('\n', stdout);
  446.  
  447.     for (col = 0; col < ncols; col++)
  448.     {
  449.         for (n = desc[col].dbsize; --n >= 0; )
  450.             fputc('-', stdout);
  451.         fputc(' ', stdout);
  452.     }
  453.     fputc('\n', stdout);
  454. }
  455.  
  456.  
  457. void
  458. print_rows(cda, ncols)
  459. Cda_Def *cda;
  460. sword ncols;
  461. {
  462.     sword col, n;
  463.  
  464.     for (;;)
  465.     {
  466.         fputc('\n', stdout);
  467.         /* Fetch a row.  Break on end of fetch,
  468.            disregard null fetch "error". */
  469.         if (ofetch(cda))
  470.         {
  471.             if (cda->rc == NO_DATA_FOUND)
  472.                 break;
  473.             if (cda->rc != NULL_VALUE_RETURNED)
  474.                 oci_error(cda);
  475.         }
  476.         for (col = 0; col < ncols ; col++)
  477.         {
  478.             /* Check col. return code for null.  If
  479.                null, print n spaces, else print value. */
  480.             if (def[col].indp < 0)
  481.                 printf("%*c", desc[col].dbsize, ' ');
  482.             else
  483.             {
  484.                 switch (desc[col].dbtype)
  485.                 {
  486.                 case FLOAT_TYPE:
  487.                     printf("%*.*f", numwidth, 2, def[col].flt_buf);
  488.                     break;
  489.                 case INT_TYPE:
  490.                     printf("%*d", numwidth, def[col].int_buf);
  491.                     break;
  492.                 default:
  493.                     printf("%s", def[col].buf);
  494.                     n = desc[col].dbsize - strlen(def[col].buf);
  495.                     if (n > 0)
  496.                         printf("%*c", n, ' ');
  497.                     break;
  498.                 }
  499.             }
  500.             fputc(' ', stdout);
  501.         }
  502.     }  /* end for (;;) */
  503. }
  504.  
  505.