home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Internet Business Development Kit / PRODUCT_CD.iso / sqlsvr / esqlc / esql / samples.c / example5.sqc < prev    next >
Encoding:
Text File  |  1995-12-19  |  13.4 KB  |  544 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. //  FILE: example5.sqc
  4. //              
  5. //      Sample Embedded SQL for C application
  6. //
  7. //  FUNCTIONS:
  8. //
  9. //      main() - Main program
  10. //      ErrorHandler - Embedded SQL for C error handler
  11. //
  12. //  COMMENTS:
  13. //
  14. //      Copyright (C) 1992 - 1994 Microsoft Corporation
  15. //
  16. ///////////////////////////////////////////////////////////////////////////////
  17.  
  18. #include <stddef.h>         // standard C run-time header
  19. #include <stdio.h>          // standard C run-time header
  20. #include "gcutil.h"         // utility header
  21.  
  22. // GLOBAL VARIABLES
  23.  
  24. #define STRUCTURE   // See comments in the singleton_select procedure.
  25. #define DEF_PUBNAME 'Yoyodyne Publishing'
  26. #define DATELEN 26
  27.  
  28. EXEC SQL BEGIN DECLARE SECTION;
  29. char title_id[99];
  30.  
  31. struct
  32. {
  33.     char len;
  34.     char data[23];
  35. } myvarchar;
  36.  
  37. struct tr
  38. {
  39.     char title_id[7];
  40.     char title[81];
  41.     double price;
  42.     long royalty;
  43.     char pubdate[27];
  44. };
  45.  
  46. struct
  47. {
  48.     short title_id_ind;
  49.     short title_ind;
  50.     short pricenul;
  51.     short royaltynul;
  52.     short pubdate_ind;
  53. } tr_ind;
  54.  
  55. EXEC SQL END DECLARE SECTION;
  56.  
  57. /* These lines show that the pre-compiler can deal with typedef'd data. */
  58.  
  59. typedef double BUCKS;
  60. typedef char BYTE;
  61. typedef BYTE YAHOO;
  62. typedef YAHOO CHRSTR;
  63. typedef CHRSTR STRING;
  64. typedef BUCKS DOLLARINOS;
  65.  
  66. typedef struct tr T_RECORD;
  67.  
  68. EXEC SQL BEGIN DECLARE SECTION;
  69.  
  70. YAHOO title[81];                // Resolves to a character array.
  71. BUCKS price = 2.99;             // Resolves to double.
  72. DOLLARINOS *pprice = &price;    // Resolves also to double.
  73. long royalty;
  74. char pubdate[DATELEN + 1];
  75.  
  76. int yy(double *);
  77. int ss(BUCKS *);
  78.  
  79. int pricenul;
  80. int royaltynul;
  81. int loginame;
  82.  
  83. char pubname[4 * 10 + 1];
  84. char pubname2[] = "Shaw Enterprises";
  85. char city[21] = "Pardess Hanna";
  86. char state[3] = "WA";
  87.  
  88. typedef T_RECORD T_REC_ORD;
  89.  
  90. char cmdbuf[81];
  91.  
  92. T_RECORD t_rec;
  93.  
  94. EXEC SQL END DECLARE SECTION;
  95.  
  96. // function prototypes (instead of header file)
  97. void ErrorHandler (void);
  98. void singleton_select(T_REC_ORD *pt_rec_param);
  99. void cursor_select();
  100. void cursor_exec();
  101. void static_insert(char *p_pubname2);
  102. void dynamic_insert();
  103. void date_formats();
  104. void printline();
  105. void date_formats();
  106. void print_t_rec();
  107. unsigned validId(char *pubid);
  108.  
  109. ///////////////////////////////////////////////////////////////////////////////
  110. //
  111. //  FUNCTION: main()
  112. //
  113. //      Main application
  114. //
  115. //  PARAMETERS:
  116. //
  117. //      argc - count of command line args
  118. //      argv - array of command line argument strings
  119. //      envp - array of environment strings
  120. //
  121. //  RETURNS: 0 if successful, 1 if error
  122. //
  123. //  COMMENTS:
  124. //
  125. ///////////////////////////////////////////////////////////////////////////////
  126.  
  127. int main (
  128.     int argc,
  129.     char** argv,
  130.     char** envp)
  131. {
  132.     int nRet;           // for return values
  133.  
  134.     EXEC SQL BEGIN DECLARE SECTION;
  135.     // for CONNECT TO
  136.     char szServerDatabase[(SQLID_MAX * 2)+2] = "";
  137.     char szLoginPassword[(SQLID_MAX * 2)+2] = "";
  138.  
  139.     T_REC_ORD *pt_rec = &t_rec;
  140.     EXEC SQL END DECLARE SECTION;
  141.  
  142.     // install Embedded SQL for C error handler
  143.     EXEC SQL WHENEVER SQLERROR CALL ErrorHandler();
  144.     // set Embedded SQL for C options
  145.     EXEC SQL SET OPTION LOGINTIME 10;
  146.     EXEC SQL SET OPTION QUERYTIME 100;
  147.  
  148.     // display logo
  149.     printf("Sample Embedded SQL for C application\n");
  150.  
  151.     // get info for CONNECT TO statement
  152.     nRet = GetConnectToInfo(argc, argv,
  153.         szServerDatabase,
  154.         szLoginPassword);
  155.     if (!nRet)
  156.     {
  157.         return (1);
  158.     }
  159.  
  160.     // attempt connection to SQL Server
  161.     EXEC SQL CONNECT TO :szServerDatabase
  162.         USER :szLoginPassword;
  163.     if (SQLCODE == 0)
  164.     {
  165.         printf("Connection to SQL Server established\n");
  166.     }
  167.     else
  168.     {
  169.         // problem connecting to SQL Server
  170.         printf("ERROR: Connection to SQL Server failed\n");
  171.         return (1);
  172.     }
  173.  
  174.     EXEC SQL SET CURSORTYPE CUR_BROWSE;
  175.  
  176.     exec sql select max(name) into :myvarchar from sysobjects;
  177.  
  178.     printf("%.*s\n", myvarchar.len, myvarchar.data);
  179.  
  180.     singleton_select(pt_rec);
  181.     cursor_exec();
  182.     cursor_select();
  183.     static_insert("Morris, Marshall, Faulkner & Co, Publishers");
  184.     dynamic_insert();
  185.     date_formats();
  186.  
  187.     printf("\n===================== THE END ======================\n");
  188.  
  189.     // disconnect from SQL Server
  190.     EXEC SQL DISCONNECT ALL;
  191.  
  192.     return (0);
  193. }
  194.  
  195. ///////////////////////////////////////////////////////////////////////////////
  196. //
  197. //  FUNCTION: ErrorHandler()
  198. //
  199. //      Called on Embedded SQL for C error, displays fields from SQLCA
  200. //
  201. //  PARAMETERS: none
  202. //
  203. //  RETURNS: none
  204. //
  205. //  COMMENTS:
  206. //
  207. ///////////////////////////////////////////////////////////////////////////////
  208.  
  209. void ErrorHandler (void)
  210. {
  211.     // display error information from SQLCA
  212.     printf("Error Handler called:\n");
  213.     printf("    SQL Code = %li\n", SQLCODE);
  214.     printf("    SQL Server Message %li: '%Fs'\n", SQLERRD1, SQLERRMC);
  215. }
  216.  
  217. #ifdef STRUCTURE
  218. /* Test of singleton select, selecting into a structure. */
  219. void singleton_select(T_REC_ORD *pt_rec_param)
  220. {
  221.  
  222.     printf("\n============= TEST OF SINGLETON-SELECT =============\n");
  223.     /* Just do this once - loop to make sure they enter something */
  224.     do {
  225.         printf("Enter TitleId (such as BU1032 or PC9999): ");
  226.         gets(title_id);
  227.     } while (strlen(title_id) == 0);
  228.  
  229.  
  230.     EXEC SQL
  231.         SELECT title_id, title, price, royalty, pubdate
  232.         INTO :pt_rec_param:tr_ind
  233.         FROM titles
  234.         WHERE title_id = :title_id;
  235.  
  236.  
  237.     if (SQLCODE == 0 || SQLCODE == 1 ) {
  238.         print_t_rec();
  239.         printf("%s\n\n", pt_rec_param->title);
  240.     } else if (SQLCODE == 100 && title_id[0] > ' ') {
  241.         printf("No row with that ID\n");
  242.     }
  243.  
  244. }
  245.  
  246. #else
  247. /* This is effectively the same as the above procedure, but selects
  248.  * into individual fields of the structure.
  249.  * Remove the #ifdef if you wish to replace the structure form.
  250.  */
  251.  
  252. void singleton_select(T_REC_ORD *pt_rec_param)
  253. {
  254.  
  255.     printf("\n============= TEST OF SINGLETON-SELECT =============\n");
  256.     /* Just do this once - loop to make sure they enter something */
  257.     do {
  258.         printf("Enter TitleId (such as BU1032 or PC9999): ");
  259.         gets(title_id);
  260.     } while (strlen(title_id) == 0);
  261.  
  262.     EXEC SQL
  263.         SELECT title_id, title, price, royalty, pubdate
  264.         INTO  :pt_rec_param->title_id, :pt_rec_param->title,
  265.             :pt_rec_param->price:pricenul, :pt_rec_param->royalty
  266.             :royaltynul,
  267.             :pt_rec_param->pubdate
  268.         FROM titles
  269.         WHERE title_id = :title_id;
  270.  
  271.  
  272.     if (SQLCODE == 0 || SQLCODE == 1 ) {
  273.         print_t_rec();
  274.         printf("%s\n\n", pt_rec_param->title);
  275.     } else if (SQLCODE == 100 && title_id[0] > ' ') {
  276.         printf("No row with that ID\n");
  277.     }
  278.  
  279. }
  280. #endif  // STRUCTURE
  281.  
  282.  
  283. /* Note that whitespace is ignored. */
  284. EXEC SQL DECLARE C1 CURSOR FOR
  285.     SELECT title_id, title, price, royalty, pubdate
  286.     FROM   titles
  287.     WHERE  price <= :*pprice + 2;
  288.  
  289.  
  290. void cursor_select()
  291. {
  292.     unsigned short book_ct = 0;
  293.     char buff[80];
  294.     EXEC SQL WHENEVER NOT FOUND GOTO DONE;
  295.     price = 0.00;       // initialize it
  296.  
  297.     printf("\n=============== TEST OF CURSOR SELECT ==============\n");
  298.  
  299.     /* loop to make sure user enters something */
  300.     do {
  301.         printf("Enter max price [1.50 - 22.95] (I will add 2 to it): ");
  302.         gets(buff);
  303.         sscanf(buff, "%lf", &price);
  304.     } while (price == 0.00);
  305.  
  306.     printf("Listing publications whose price is <= %f\n", price+2);
  307.     EXEC SQL OPEN C1;
  308.     if (SQLCODE) {
  309.         ErrorHandler();
  310.     }
  311.  
  312.     /* Loop terminated via the 'WHENEVER NOT FOUND GOTO DONE' condition. */
  313.     for (;;) {
  314.         EXEC SQL FETCH C1
  315.         INTO :title_id, :title, :price:pricenul,
  316.             :royalty:royaltynul, :pubdate;
  317.  
  318.         printline();
  319.         printf("%s\n\n", title);
  320.         book_ct++;      // Keep count of publications selected
  321.     }
  322.  
  323. DONE:
  324.     printf("\nTotal of %d publications\n\n", book_ct);
  325.     EXEC SQL CLOSE C1;
  326.  
  327.     EXEC SQL WHENEVER NOT FOUND CONTINUE;
  328. }
  329.  
  330. void cursor_exec()
  331. {
  332.     EXEC SQL BEGIN DECLARE SECTION;
  333.     /* The following data items are used in the ESQL statement(s). */
  334.     int spid;
  335.     char status[11];
  336.     char loginame[13];
  337.     char host_name[11];
  338.     char blk[7];
  339.     char dbname[11];
  340.     char cmd[17];
  341.     EXEC SQL END DECLARE SECTION;
  342.  
  343.     printf("\n=============== TEST OF STATIC CURSOR ==============\n");
  344.  
  345.     EXEC SQL DECLARE C_2 CURSOR FOR STMT1;
  346.     strcpy(cmdbuf, "sp_who");
  347.     EXEC SQL PREPARE STMT1 FROM :cmdbuf;
  348.     EXEC SQL OPEN C_2;
  349.  
  350.     EXEC SQL WHENEVER NOT FOUND GOTO DONE;
  351.  
  352.     printf(" SPID\tLOGINAME\tHOSTNAME\tDBNAME\t\tCMD\n");
  353.     while (SQLCODE == 0) {
  354.         EXEC SQL FETCH C_2 INTO
  355.         :spid, :status, :loginame, :host_name, :blk, :dbname, :cmd;
  356.  
  357.         printf("%4d\t%-12s\t%-10s\t%-10s\t%-18s\n",
  358.             spid, loginame, host_name, dbname, cmd);
  359.  
  360.     }
  361.  
  362. DONE:
  363.  
  364.     EXEC SQL CLOSE C_2;
  365.  
  366.     printf("\n");
  367.  
  368.     EXEC SQL WHENEVER NOT FOUND CONTINUE;
  369.  
  370. }
  371.  
  372.  
  373. /* Note the placing of the Begin declare section. The function parameter
  374. ** itself is a host variable.
  375. */
  376.  
  377. EXEC SQL BEGIN DECLARE SECTION;
  378. void static_insert(char *p_pubname2)
  379. {
  380.  
  381.     printf("\n=============== TEST OF STATIC INSERT ==============\n");
  382.  
  383.     do {
  384.         printf("Enter new publisher name: ");
  385.         gets(pubname);
  386.     } while (strlen(pubname) == 0);
  387.  
  388.     EXEC SQL BEGIN TRAN
  389.         INSERT INTO publishers (pub_id, pub_name, city, state) 
  390.             VALUES ("9989", :pubname, :city, :state)
  391.         INSERT INTO publishers (pub_id, pub_name, city, state) 
  392.             VALUES ("9987", DEF_PUBNAME, :city, :state)
  393.         INSERT INTO publishers (pub_id, pub_name, city, state) 
  394.             VALUES ("9988", :p_pubname2, :city, :state)
  395.         COMMIT TRAN
  396.     ;
  397.  
  398.     if (SQLCODE == 0) {
  399.         printf("Select pub_id between '9980' and '9989' with ISQL; ");
  400.         printf("press Enter when done: ");
  401.         gets(pubname);
  402.     } else {
  403.         ErrorHandler();
  404.     }
  405.  
  406.     strcpy(cmdbuf, "delete publishers where pub_id between '9980' and '9989'");
  407.     EXEC SQL EXECUTE IMMEDIATE :cmdbuf;
  408. }
  409. EXEC SQL END DECLARE SECTION;
  410.  
  411.  
  412. void dynamic_insert()
  413. {
  414.     EXEC SQL BEGIN DECLARE SECTION;
  415.     char pubid[5];
  416.     int statenul = -1;
  417.     EXEC SQL END DECLARE SECTION;
  418.  
  419.     printf("\n=============== TEST OF DYNAMIC INSERT =============\n");
  420.  
  421.     strcpy(cmdbuf, "insert publishers (pub_id, pub_name, city, state) values(?,?,?,?)");
  422.     EXEC SQL PREPARE STMT1 FROM :cmdbuf;
  423.  
  424.     if (SQLCODE != 0)
  425.         ErrorHandler();
  426.     else {
  427.         strcpy(pubname, "Dynamic Publisher");
  428.         do {
  429.             printf("Enter new publisher id (998\?): ");
  430.             gets(pubid);
  431.         } while (!validId(pubid));
  432.  
  433.         EXEC SQL EXECUTE STMT1 USING
  434.             :pubid, :pubname, :city, :state:statenul;
  435.  
  436.  
  437.         if (SQLCODE == 0) {
  438.             printf("Select pub_id = <your pub_id> with ISQL; ");
  439.             printf("press Enter when done: ");
  440.             gets(pubname);
  441.         } else
  442.             ErrorHandler();
  443.     }
  444.  
  445.     strcpy(cmdbuf, "delete publishers where pub_id between '9980' and '9989'");
  446.     EXEC SQL EXECUTE IMMEDIATE :cmdbuf;
  447.  
  448. }
  449.  
  450.  
  451. void date_formats()
  452. {
  453.     EXEC SQL BEGIN DECLARE SECTION;
  454.     char date1[DATELEN];
  455.     char date2[20];
  456.     char date3[20];
  457.     char time1[20];
  458.     EXEC SQL END DECLARE SECTION;
  459.  
  460.     printf("\n=============== TEST OF DATE FORMATS  ==============\n");
  461.  
  462.     EXEC SQL
  463.         select  getdate(), ord_date,
  464.             convert(char(8),ord_date,3),
  465.             substring(convert(char(26),ord_date),13,7)
  466.         INTO    :date1, :date2, :date3, :time1 FROM sales
  467.         WHERE stor_id='6380' and ord_num='6871' and title_id='BU1032';
  468.  
  469.     if (SQLCODE == 0) {
  470.         printf("\n");
  471.         printf("Full Date: %s\n", date1);
  472.         printf("Without Time: %s\n", date2);
  473.         printf("Format 3 Date: %s\n", date3);
  474.         printf("Time only: %s\n", time1);
  475.     } else {
  476.         ErrorHandler();
  477.     }
  478.  
  479. }
  480.  
  481. void printline()
  482. {
  483.     char dprice[11];
  484.     char droyalty[6];
  485.  
  486.     if (pricenul < 0)
  487.         strcpy(dprice, "No Price  ");
  488.     else
  489.         sprintf(dprice, "%10.2f", price);
  490.  
  491.     if (royaltynul < 0)
  492.         strcpy(droyalty, "None ");
  493.     else
  494.         sprintf(droyalty, "%5ld", royalty);
  495.  
  496.     printf("%6s %10s %5s %26s\n",
  497.         title_id, dprice, droyalty, pubdate);
  498.  
  499. }
  500.  
  501.  
  502. void print_t_rec()
  503. {
  504.     char dprice[11];
  505.     char droyalty[6];
  506.  
  507.     if (tr_ind.pricenul < 0)
  508.         strcpy(dprice, "No Price  ");
  509.     else
  510.         sprintf(dprice, "%10.2f", t_rec.price);
  511.  
  512.     if (tr_ind.royaltynul < 0)
  513.         strcpy(droyalty, "None ");
  514.     else
  515.         sprintf(droyalty, "%5ld", t_rec.royalty);
  516.  
  517.     printf("%6s %10s %5s %26s\n",
  518.         t_rec.title_id, dprice, droyalty, t_rec.pubdate);
  519.  
  520. }
  521.  
  522.  
  523. // Check that given string is '9', '9', [0-9], [0-9]
  524.  
  525. #define ISNUM(c) ((c) >= '0' && (c) <= '9')
  526.  
  527. unsigned validId( char *pubid )
  528. {
  529.     unsigned rc = 0;        // return code
  530.  
  531.     if ( *pubid++ == '9' && *pubid++ == '9') {
  532.         // passed first part - check remaining characters
  533.         char ch3 = *pubid++;
  534.         char ch4 = *pubid++;
  535.         if (ISNUM(ch3) && ISNUM(ch4)) {
  536.             // just check that 4 characters is all we have
  537.             if (*pubid == '\0') {
  538.                 rc = 1;
  539.             }
  540.         }
  541.     }
  542.     return rc;
  543. }
  544.