SQLEXAMP.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:14k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /* SQLEXAMP.C - Copyright (c) 1990 - 1995 by Craig Henry.  This program may
  2. ** be freely distributed and copied, without charge.  However, any attempt to
  3. ** charge for this program will be considered a copyright infringement and
  4. ** will be prosecuted to the fullest extent.
  5. **
  6. ** This program provides a simple example of logging onto a SQL Server,
  7. ** sending down commands, retrieving metadata, and result rows.  Formatting
  8. ** and printing those results on the console.
  9. **
  10. */
  11. #if defined(DBNTWIN32)
  12. #include <windows.h>
  13. #endif
  14. #include "stdio.h" // include standard header
  15. #include "sqlfront.h" // include dblib macro/manifest defines
  16. #include "sqldb.h" // include dblib datatype, prottypes, etc
  17. #include "string.h" // include for string functions
  18. #include "malloc.h" // include for malloc and free
  19. // prototypes for internal functions
  20. extern int DetermineRowSize(DBPROCESS *,int);
  21. extern RETCODE PrintHeaders(DBPROCESS *);
  22. extern RETCODE PrintRow(DBPROCESS *);
  23. /*
  24. ** DetermineRowSize(DBPROCESS *,int)
  25. **
  26. ** This function returns either the size of all columns in the row, converted
  27. ** to character data (SQLCHAR) with one space between each column, or
  28. ** if col is non-zero, the length of the input column converted to string.
  29. ** It is used to build the header strings, and each row of data, and is
  30. ** called to allocate the memory needed for each row, and determine how
  31. ** much of that space is to be used for each column
  32. */
  33. int DetermineRowSize(dbproc,col)
  34. DBPROCESS *dbproc; // The SQL Server connection structure
  35. int col; // column size to get, 0 for all
  36. {
  37.     int x,cols; // counters
  38.     int length=0; // total length of column(row).
  39.     int namelength; // length of name of column
  40.     int prlength; // printable length
  41.     char *name; // pointer to column name
  42.     if(!col)         // get number of columns
  43.        cols = dbnumcols(dbproc);
  44.     // count from 1 to numcols if col is 0, else x will = col only
  45.     for(x=((col) ? col : 1);x<=((col) ? col : cols);x++)
  46.     {
  47.         switch(dbcoltype(dbproc,x)) // get column type, determine SQLCHAR
  48.         { // converted length
  49. case SQLNUMERIC:
  50. case SQLDECIMAL:
  51. {
  52. DBCOL Col;
  53. dbcolinfo(dbproc,CI_REGULAR,x,0,&Col);
  54. prlength = Col.Precision + 2;
  55. }
  56. break;
  57.     case SQLBIT: // The PR... values are found in the
  58.         prlength = PRBIT; // SQLDB.H header file.
  59.         break;
  60.     case SQLINT1:
  61.             prlength = PRINT1;
  62.         break;
  63.     case SQLINT2:
  64.            prlength = PRINT2;
  65.         break;
  66.     case SQLINT4:
  67.         prlength = PRINT4;
  68.         break;
  69.     case SQLFLT8:
  70.         prlength = PRFLT8;
  71.         break;
  72.     case SQLDATETIME:
  73.         prlength = PRDATETIME;
  74.         break;
  75.     case SQLMONEY:
  76.         prlength = PRMONEY;
  77.         break;
  78.             case SQLVARBINARY : // VARBINARY IMAGE, and BINARY
  79.             case SQLBINARY: // convert to 2 times length
  80.             case SQLIMAGE:
  81.                 prlength = dbcollen(dbproc,x)*2;
  82.                 break;
  83.     default :
  84.         prlength = dbcollen(dbproc,x);  // other types are maximum of
  85.         break;  // actual column length
  86.         }
  87.         name = (char *)dbcolname(dbproc,x);  // names may be longer than
  88.         namelength =  (name) ? strlen(name) : 0; // column so use name len if
  89.         if(prlength<namelength)  // longer of two.
  90.            length+=namelength+1;  // add one for space between
  91.         else  // columns
  92.            length+=prlength+1;
  93.     }
  94.     return length; // return the length of the
  95.      // field
  96. }
  97. /*
  98. ** RETCODE PrintHeaders(DBPROCESS *)
  99. **
  100. ** This function builds the string that contains the names of each column,
  101. ** and a string containing '=' as a separator line.  It does this by finding
  102. ** the print size of each column, allocating a buffer to hold all column names
  103. ** plus one space between each column name, then copying that name into the
  104. ** appropriate location into the buffer.  Finally the two lines are
  105. ** printed.
  106. */
  107. RETCODE PrintHeaders(dbproc)
  108. DBPROCESS *dbproc; // The SQL Server connection structure pointer
  109. {
  110.     int x,cols,size; // counters
  111.     char *header; // pointer for separator buffer
  112.     char *colnames; // pointer for column name buffer
  113.     char *colname; // scratch pointers
  114.     char *ptr,*hptr;
  115.     size = DetermineRowSize(dbproc,0); // get size of buffers
  116.     ptr = colnames = malloc(size+1);  // get name buffer
  117.     hptr = header = malloc(size+1);  // get separator buf
  118.     memset (header,' ',size); // set buffers to all spaces
  119.     memset (colnames,' ',size);
  120.     cols = dbnumcols(dbproc); // get number of columns
  121.     for(x=1;x<=cols;x++) // loop on all columns
  122.     {
  123.         size = DetermineRowSize(dbproc,x);  // get size of this column
  124.         colname = (char *)dbcolname(dbproc,x); // get column name
  125.         strncpy(ptr,colname,strlen(colname)); // copy name
  126.         memset(hptr,'=',size-1); // set ='s in separator line
  127.         hptr+=size; // move to next position
  128.         ptr+=size; // move to next position
  129.     }
  130.     *ptr = ''; // null term both strings
  131.     *hptr = '';
  132.     printf("%sn",colnames); // print both strings
  133.     printf("%sn",header);
  134.     free(colnames); // free both buffers
  135.     free(header);
  136.     return SUCCEED; // done
  137. }
  138. /*
  139. ** RETCODE PrintRow(DBPROCESS *)
  140. **
  141. ** This function prints out one row.  dbnextrow() must be called to fetch the
  142. ** row to print.  This routine could be used to print the current row as
  143. ** many times as wanted, as the current row data is always available until
  144. ** dbnextrow() is called to fetch the next row.  This routine works like
  145. ** PrintHeaders above, but each column's data is obtained instead of a row
  146. ** name, and converted to a string.  It is then set into the buffer.
  147. */
  148. RETCODE PrintRow(dbproc)
  149. DBPROCESS *dbproc; // SQL Server connection structure
  150. {
  151.     int x,cols,size,datasize,colwidth,coltype; // counters
  152.     char *datavals; // data buffer pointer
  153.     char *data; // column data pointer
  154.     char *ptr; // scratch pointer
  155.  colwidth = DetermineRowSize(dbproc,0);
  156.     ptr = datavals = malloc(colwidth+1); // get buffer
  157.     cols = dbnumcols(dbproc); // get number of columns
  158.     for(x=1;x<=cols;x++) // do all columns
  159.     {
  160.     coltype = dbcoltype(dbproc,x);
  161.         size = DetermineRowSize(dbproc,x); // determine size of this column
  162.         memset(ptr,' ',size); // set it to spaces
  163.         data = (char *)dbdata(dbproc,x); // get pointer to column's data
  164.         if(data == (BYTE *)NULL) // if NULL, use "NULL"
  165.         {
  166.             strncpy(ptr,"NULL",4); // set NULL into buffer
  167.             ptr += size; // point past this column in output buf
  168.         }
  169.         else // else have data, so convert to char
  170.         {
  171.             datasize = dbconvert(dbproc,coltype,data,dbdatlen(dbproc,x),
  172.                 SQLCHAR,ptr,(DBINT)size-1);
  173. if (datasize < size && (coltype == SQLNUMERIC || coltype == SQLDECIMAL || coltype == SQLINT1 ||
  174.     coltype == SQLINT2 || coltype == SQLINT4 || coltype == SQLFLT8 || coltype == SQLFLT4))
  175. {
  176. memmove(ptr+size-1-datasize,ptr,datasize);
  177. memset(ptr,' ',size-1-datasize);
  178. }
  179.             ptr+=size;
  180.         }
  181.     }
  182.     *ptr = ''; // null term string
  183.     printf("%sn",datavals); // print row
  184.     free(datavals); // free buffer
  185.     return SUCCEED; // done
  186. }
  187. /*
  188. **
  189. ** The below main is a mini isql interpreter and as such is only
  190. ** used for demonstration purposes.  Command line args include the Server
  191. ** name as arg 1, User ID as arg 2, assumes the password is null.
  192. ** This routine requests opens the connection after obtaining the login record
  193. ** and filling it with the necessary info.  Once the connection is established
  194. ** it accpets command input, set's it into the dbproc.  On "go" it executes
  195. ** the command against the server, processes each results set and then returns
  196. ** to accepting command input.  If "quit" or "exit" is input the program
  197. ** is terminated.  This interpreter will not process COMPUTE statements,
  198. ** and will not work with commands that return text/image data.
  199. */
  200. int main(argc, argv)
  201. int argc;
  202. char *argv[];
  203. {
  204.     LOGINREC *login; // login rec pointer
  205.     DBPROCESS *dbproc; // SQL Server connection structure pointer
  206.     char cmd[150]; // command buffer
  207.     char server[30]; // server name buffer
  208.     int x=1; // command line counter
  209.     STATUS retc; // return code
  210.     const char * sqlversion; // pointer for version string
  211.     int err_handler(DBPROCESS*, int, int, int, char*, char*);
  212.     int msg_handler(DBPROCESS*, DBINT, int, int, char*);
  213.     *server = ''; // null start these two buffers
  214.     *cmd = '';
  215.     if(argc == 1) // if no server name, request it
  216.     {
  217. printf("Enter Server Name: ");
  218. gets(server);
  219.     }
  220.     else // else it was input as first arg
  221.        strcpy(server,argv[1]);
  222.     if(argc < 2) // if no login id, request it
  223.     {
  224.        printf("Enter User Name: ");
  225.        gets(cmd);
  226.     }
  227.     else // otherwise it was input as second arg.
  228.        strcpy(cmd,argv[2]);
  229.     // check to see if communications layer was loaded (DOS ONLY)
  230.     if((sqlversion = dbinit()) == (BYTE *)NULL)
  231.     {
  232.        // DOS TSR (DBNMPIPE.EXE) is not loaded, don't bother going any farther
  233.        printf("Error in DB-Library initialization, exitingn");
  234.        return 1;
  235.     }
  236.     else
  237.        printf("DB-Library version: %sn",sqlversion); // print dblib version
  238.     dbsettime(30); // set timeouts to 30 seconds
  239.     
  240.     // set error/msg handlers for this program
  241.     dbmsghandle((DBMSGHANDLE_PROC)msg_handler);
  242.     dberrhandle((DBERRHANDLE_PROC)err_handler);
  243.     
  244.     login = dblogin(); // get a login rec
  245.     DBSETLUSER(login,cmd); // set login id
  246.     DBSETLHOST(login,"SQL EXAMPLE"); // set host name for sp_who
  247.     DBSETLVERSION(login, DBVER60);
  248.     // open connection to requested server.  Pass null server name for local
  249.     // connection, if name not entered.
  250.     if((dbproc = dbopen(login,(*server) ? server : (char *)NULL)) == (DBPROCESS *)NULL)
  251.     {
  252.         // no one answered, so couldn't connect or error occurred
  253. printf("Login failedn");
  254. return 1;
  255.     }
  256.     else
  257.     {
  258.         // loop on command input until quit or exit appears in first 4 bytes.
  259. while((strnicmp(cmd,"quit",4) != 0) && (strnicmp(cmd,"exit",4)!=0))
  260. {
  261.    printf("%d> ",x++); // print command prompt
  262.    gets(cmd); // get command
  263.    if(strnicmp(cmd,"go",2) == 0) // is it go
  264.    {
  265.       if(dbsqlexec(dbproc) == FAIL) // execute command
  266.               {
  267.                  // problem occurred, just try another command
  268.                  printf("Error in executing command batch!n");
  269.                  x = 1;
  270.                  continue;
  271.               }
  272.               // command executed correctly, get results information
  273.       while((retc = dbresults(dbproc)) != NO_MORE_RESULTS)
  274.       {
  275.  if (retc == FAIL) // if error get out of loop
  276.      break;
  277.  // headers and data could be printed here with only two
  278.                  // function calls, dbprhead(dbproc), and dbprrow(dbproc),
  279.                  // which would output the headers, and all the data to
  280.                  // standard output.  However, that isn't very informative
  281.                  // toward understanding how this data is obtained and
  282.                  // processed, so I do it the hard way, one column at a time.
  283.                  PrintHeaders(dbproc); // print header data
  284.                  // loop on each row, until all read
  285.                  while((retc= dbnextrow(dbproc))!=NO_MORE_ROWS)
  286.                  {
  287.                     if(retc == FAIL) // if fail, then clear
  288.                     { // connection completely, just
  289.                        dbcancel(dbproc); // in case.
  290.                        break;
  291.                     }
  292.                     else
  293.                         PrintRow(dbproc); // else print the current row
  294.                  }
  295.  if(DBCOUNT(dbproc) == 1L) // print the row count
  296.       printf("(1 row effected)n");
  297.   else
  298.       printf("(%ld rows effected)n",DBCOUNT(dbproc));
  299.       } // end while(dbresults())
  300.               x = 1; // reset command line counter
  301.    }
  302.    else
  303.    {
  304.       strcat(cmd," "); // go not detected, so put space
  305.       dbcmd(dbproc,cmd); // between each command and set in
  306.    } // dbproc.
  307.         } // end while()
  308.         dbclose(dbproc); // quit/exit input, close connection
  309.         // print adios and exit.
  310.         printf("SQL Server Connection to %s closed, bye bye.n",server);
  311. return 0;
  312.      }
  313. }
  314. /*
  315. ** msg_handler(char *buffer, long len);
  316. **
  317. ** This routine is a local isql message handler call back function that
  318. ** is invoked whenever the SQL Server is sending a message back to
  319. ** the program.
  320. **
  321. */
  322. int msg_handler(dbproc, Msg, State, Severity, Message)
  323. DBPROCESS *dbproc; // SQL Server connection structure
  324. DBINT Msg; // SQL Server message number
  325. int State; // State of the message
  326. int Severity; // Severity of the message
  327. char *Message; // The message itself (read only)
  328. {
  329.     printf("Message No.: %ld, Msg. State: %d, Msg. Severity: %dn",
  330. Msg,State,Severity);
  331.     if(Message != NULL)
  332.        printf("%sn",Message);
  333.     return (0);
  334. }
  335. /*
  336. ** err_handler(char *buffer, long len);
  337. **
  338. ** This routine is a local error handler called by dblib if an internal
  339. ** error occurs, also to notify when a server message has been sent, which is
  340. ** obtained through the above message handler.
  341. **
  342. */
  343. int err_handler(dbproc, Severity,dberr, oserr, errstr, oserrstr)
  344. DBPROCESS *dbproc; // SQL Server connection structure
  345. int Severity; // Severity of Dblib error
  346. int dberr; // dblib error, all dblib errors start at 10000
  347. int oserr; // OS error from, C runtime
  348. char *errstr; // dblib error string
  349. char *oserrstr; // OS error string (if any)
  350. {
  351.     printf("DB-LIBRARY Error - Severity: %d, Error No: %d, OS Error No: %dn",
  352.        Severity, dberr, oserr);
  353.     if(errstr != NULL)
  354.        printf("%sn",errstr);
  355.     if(oserrstr != NULL)
  356.        printf("%sn",oserrstr);
  357.     return INT_CANCEL;
  358. }
  359. /*****************************************************************************/
  360. /*======================== E N D - O F - F I L E ============================*/
  361. /*****************************************************************************/