home *** CD-ROM | disk | FTP | other *** search
/ Shareware Supreme Volume 6 #1 / swsii.zip / swsii / 215 / DDJWIN.ZIP / SQL.ASC < prev    next >
Text File  |  1993-08-31  |  53KB  |  1,827 lines

  1. _A GENERIC SQL CLASS LIBRARY_
  2. by Ken North
  3.  
  4. [LISTING ONE]
  5.  
  6. ///////////////////////////////////////////////////
  7. // FILE NAME:  dbObject.h   TITLE:  database class
  8. // AUTHOR: Ken North     Resource Group, Inc.   
  9. //                       2604B El Camino Real, #351
  10. // copyright(c)1992      Carlsbad, CA 92008
  11. ///////////////////////////////////////////////////
  12.  
  13. #ifndef __DBOBJECT_H
  14. #define __DBOBJECT_H
  15.  
  16. class dbObject 
  17. {
  18.     int     ReferenceTotal;
  19.  
  20. protected:
  21.  
  22. public:
  23.  
  24.     dbObject();
  25.     virtual ~dbObject();
  26.  
  27.     virtual void IncrementRefs();
  28.     virtual int DecrementRefs();
  29. };
  30.  
  31. #endif
  32.  
  33.  
  34.  
  35.  
  36. [LISTING TWO]
  37.  
  38. ///////////////////////////////////////////////////
  39. // FILE NAME: dbObject.cpp  TITLE: base class
  40. // AUTHOR: Ken North     Resource Group, Inc.   
  41. //                       2604B El Camino Real, #351
  42. // copyright(c)1992      Carlsbad, CA 92008
  43. ///////////////////////////////////////////////////
  44. //  SYNOPSIS:
  45. //  implementation of dbObject class 
  46. ///////////////////////////////////////////////////
  47.  
  48. #undef DEBUG
  49. #undef DEBUG1
  50.  
  51. #include <windows.h>
  52. #include <string.h>
  53. #include "sql.h"  
  54. #include "sqlext.h"  
  55. #include "sqldefs.h"
  56. #include "dbobject.h"  
  57.  
  58. ////////////////////////////////////////////////////
  59. //  FUNCTION NAME: dbObject
  60. //  SYNOPSIS:
  61. //  define dbObject, SQL base class constructor
  62. ////////////////////////////////////////////////////
  63.  
  64. dbObject :: dbObject()
  65. {
  66.     ReferenceTotal = 1;     // referenced by self
  67. }
  68.  
  69. ///////////////////////////////////////////////////
  70. //  FUNCTION NAME: ~dbObject
  71. //  define dbObject, SQL data base class destructor
  72. ///////////////////////////////////////////////////
  73.  
  74. dbObject :: ~dbObject()
  75. {
  76. //  this is a point where error handler should be
  77. //  invoked if the reference total > 1 or < 0
  78. //      systemError();
  79. }
  80.  
  81. ////////////////////////////////////////////////////////////////////////
  82. //  FUNCTION NAME: IncrementRefs -- increment object reference total
  83. ////////////////////////////////////////////////////////////////////////
  84. void dbObject :: IncrementRefs()
  85. {
  86.     ReferenceTotal++;
  87. }
  88.  
  89. //////////////////////////////////////////////////////////////////////////
  90. //  FUNCTION NAME: IncrementRefs -- increment object reference total
  91. //////////////////////////////////////////////////////////////////////////
  92. int dbObject :: DecrementRefs()
  93. {
  94. //  if the reference total < 0
  95. //      {
  96. //      systemError();
  97. //      }       
  98.     return(--ReferenceTotal);
  99. }
  100.  
  101. [LISTING THREE]
  102.  
  103. ///////////////////////////////////////////////////
  104. // FILE NAME: database.cpp  TITLE: data base class
  105. // AUTHOR: Ken North     Resource Group, Inc.
  106. //                       2604B El Camino Real, #351
  107. // copyright(c)1992      Carlsbad, CA 92008
  108. //  SYNOPSIS: implementation of database class
  109. ///////////////////////////////////////////////////
  110.  
  111. #undef DEBUG
  112. #undef DEBUG1
  113.  
  114. #include <windows.h>
  115. #include <string.h>
  116. #include "sql.h"
  117. #include "sqlext.h"
  118. #include "gendefs.h"
  119. #include "sqldefs.h"
  120. #include "dbobject.h"
  121. #include "sqldb.h"
  122.  
  123. #ifndef __RGSTRING_H
  124. #include "rgstring.h"
  125. #endif
  126.  
  127. HDBC    dbDataBase::ODBCLinkHandle[]
  128.     = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  129. int dbDataBase::nDefinedSources = 0;
  130. int dbDataBase::ActiveLinks = 0;
  131. char dbDataBase::DataSourceList[] = "None";
  132. UCHAR dbDataBase::ODBCLinkList[] = "None";
  133.  
  134.                 /* standard return code for calls */
  135. extern  char    ErrStat;
  136.                 /*  large / huge model */
  137. extern  char    MemModel;
  138.  
  139. ////////////////////////////////////////////////////
  140. //  FUNCTION NAME: dbDataBase
  141. //  SYNOPSIS: dbDataBase class constructor
  142. ////////////////////////////////////////////////////
  143. dbDataBase::dbDataBase(HENV AppEnv)
  144.         : dbObject()
  145. {
  146.     //  save application environment handle
  147.     henv = AppEnv;
  148.  
  149.     //  initialize status and error info
  150.     StatusReturned = SQL_SUCCESS;
  151.     InitODBCErrorInfo();
  152. }
  153.  
  154. ///////////////////////////////////////////////////////////
  155. //  FUNCTION NAME: ~DataBase -- DataBase class destructor
  156. //////////////////////////////////////////////////////////
  157.  
  158. dbDataBase :: ~dbDataBase()
  159. {
  160. }
  161.  
  162. //////////////////////////////////////////////////////////////////////////
  163. //  FUNCTION NAME: InitODBCErrorInfo -- initialize ODBC error information
  164. //////////////////////////////////////////////////////////////////////////
  165. void dbDataBase::InitODBCErrorInfo()
  166. {
  167.     err.ErrStatus       = 0;
  168.     err.ErrorMsgLength  = 0;
  169.     err.ErrorMsgMax     = 0;
  170.     err.NativeError     = 0;
  171.     memset(err.szSQLState,'\x0',
  172.                     sizeof(err.szSQLState));
  173.     memset(err.ErrorMsg,'\x0',
  174.                     sizeof(err.ErrorMsg));
  175. }
  176. /***************************************************
  177. * FUNCTION NAME: MatchLinkName
  178. * SYNOPSIS: scan the active link list (ODBCLinkList) to find 
  179. *  the link that matches the selected link name 
  180. *  (from disconnect dialog box)
  181. *****************************************************/
  182. int dbDataBase::MatchLinkName(UCHAR *LinkToDrop)
  183. {
  184. int     tdx;                    /* link index */
  185. int     toff;                   /* link offset */
  186. UCHAR   NameToTest[LINK_NAME_LEN+1];
  187.  
  188.                 /* string position to begin search */
  189. unsigned short  StartPos=0;     
  190.  
  191.             /* position found: result of the search */
  192. unsigned short  SearchResult;   
  193.  
  194.  
  195.     for (tdx=0;tdx < ActiveLinks;tdx++)
  196.         {
  197.         toff = tdx * LINK_NAME_LEN;
  198.         memset(NameToTest,'\x0',LINK_NAME_LEN+1);
  199.         substr_n((char *)ODBCLinkList, 
  200.                 (char *)NameToTest,
  201.                 toff, LINK_NAME_LEN ) ;
  202.         SearchResult =
  203.             left_srch((char *)NameToTest, 
  204.                     (char *)LinkToDrop, StartPos);
  205.         if (ErrStat == SUCCESS)
  206.             {
  207.             return tdx;
  208.             }
  209.         }
  210.     return OOPS;
  211. }
  212.     
  213.  
  214.  
  215.  
  216. [LISTING FOUR]
  217.  
  218. ////////////////////////////////////////////////////
  219. // FILE NAME:  connect.h   TITLE:  SQL connection
  220. // AUTHOR: Ken North     Resource Group, Inc.   
  221. //                       2604B El Camino Real, #351
  222. // copyright(c)1992      Carlsbad, CA 92008
  223. ////////////////////////////////////////////////////
  224.  
  225. #ifndef __CONNECT_H
  226. #define __CONNECT_H
  227.  
  228. #ifndef __SQLDB_H
  229. #include "sqldb.h"
  230. #endif
  231.  
  232. #ifndef __DATASOUR_H
  233. #include "datasour.h"
  234. #endif
  235.  
  236. #ifndef __DBPROFIL_H
  237. #include "dbprofil.h"
  238. #endif
  239.  
  240. #ifndef __ODERROR_H
  241. #include "oderror.h"
  242. #endif
  243.  
  244. #ifndef __DSINFO_H
  245. #include "DSInfo.h"     /*  data source information */
  246. #endif
  247.     /* Connection is a child of data source */
  248. class dbConnection : public dbDataSource 
  249. {
  250.  
  251. protected:
  252.  
  253.     HENV    henv;
  254.     POINTER cstr;
  255.  
  256. public:
  257.  
  258.     RETCODE Status;
  259.     RETCODE ErrStatus;
  260.     HDBC    hdbc;
  261.     UCHAR   far *conec;
  262.     static UCHAR    ConnectionString[CONECLEN];
  263.     static UCHAR    szConnStrOut[CONECLEN];
  264.             /* the next two variables are used for situations */
  265.             /* where a connection's values are subsets of a  */
  266.             /* data source's values             */
  267.     SDWORD  ConnTableCount;  /* number of tables for this connection */
  268.     char    ConnTableList[DS_TABLE_LIST_LEN];  
  269.  
  270.     dbConnection(HENV);
  271.     virtual ~dbConnection();
  272.  
  273.     HDBC AllocateConnection(void);
  274.     POINTER BuildBrowseConnectString(char *);
  275.     virtual POINTER BuildConnectString(char *);
  276.     RETCODE BrowseConnect();
  277.     virtual RETCODE Connect(UCHAR *, UCHAR *);
  278.     virtual int Disconnect(UCHAR *);
  279.     RETCODE DriverConnect(UCHAR *);
  280.     void InitConnData(void);
  281.     void dbConnection::GetErrorInfo(void);
  282.     RETCODE PASCAL ProfileDataSource(DataSourceInfo *);
  283. };
  284. #endif
  285.  
  286.  
  287. [LISTING FIVE]
  288.  
  289. ///////////////////////////////////////////////////////////////////
  290. //  FILE NAME:  connect.cpp    TITLE: database connection
  291. // AUTHOR: Ken North     Resource Group, Inc.
  292. //                       2604B El Camino Real, #351
  293. // copyright(c)1992      Carlsbad, CA 92008
  294. ///////////////////////////////////////////////////////////////////
  295. //  SYNOPSIS: implementation of SQL connection class
  296. ///////////////////////////////////////////////////////////////////
  297.  
  298. #include <stdio.h>
  299. #include <string.h>
  300. #include <windows.h>
  301. #include <dos.h>
  302. #include <malloc.h>
  303. #include "sql.h"
  304. #include "sqlext.h"
  305. #include "sqldefs.h"
  306. #include "gendefs.h"
  307. #include "sqldb.h"
  308. #include "dboption.h"
  309. #include "oderror.h"
  310.  
  311. #ifndef __DATASOUR_H
  312. #include "datasour.h"
  313. #endif
  314.  
  315. #ifndef __DSINFO_H
  316. #include "DSInfo.h"     /* data source information  */
  317. #endif
  318.  
  319. #include "connect.h"
  320.  
  321. UCHAR dbConnection::ConnectionString[]="None";
  322. UCHAR dbConnection::szConnStrOut[]="";
  323.         /* constructor for dbConnection class       */
  324. dbConnection::dbConnection(HENV AppEnv)
  325.         : dbDataSource(AppEnv)
  326. {
  327.     henv = AppEnv;      /* save environment handle */
  328.     InitODBCErrorInfo();
  329.     Status = SQL_SUCCESS;
  330. }
  331. ///////////////////////////////////////////////////////////////////
  332. // FUNCTION NAME: ~dbConnection
  333. // SYNOPSIS: destructor for dbConnection
  334. ///////////////////////////////////////////////////////////////////
  335. dbConnection::~dbConnection()
  336. {
  337. }
  338. ///////////////////////////////////////////////////////////////////
  339. // FUNCTION NAME: AllocateConnection
  340. // SYNOPSIS: allocates a connection handle
  341. ///////////////////////////////////////////////////////////////////
  342. HDBC dbConnection::AllocateConnection()
  343. {
  344.             /* get connection handle */
  345.     Status = SQLAllocConnect(henv, &hdbc);
  346.     if (Status != SQL_SUCCESS)
  347.       {
  348.       return NULL;
  349.       };
  350.     return hdbc;
  351. }
  352. ///////////////////////////////////////////////////////////////////
  353. // FUNCTION NAME: Connect
  354. // SYNOPSIS: connect to SQL data source
  355. ///////////////////////////////////////////////////////////////////
  356. RETCODE dbConnection::Connect(UCHAR *Userid, UCHAR *Password)
  357. {
  358. SWORD cbConnStrOut;
  359.     memset(ConnectionString,'\x0',sizeof(ConnectionString));
  360.     memset(szConnStrOut,'\x0',sizeof(szConnStrOut));
  361.     strcpy((char *)ConnectionString,"DSN=");
  362.     strncat((char *)ConnectionString,(char *)TrimmedDSName,
  363.             strlen((char *)TrimmedDSName));
  364.             /* ODBC driver connect  */
  365.     Status = SQLDriverConnect (hdbc,
  366.             NULL,
  367.             ConnectionString,
  368.             SQL_NTS,
  369.             szConnStrOut,
  370.             CONECLEN,
  371.             &cbConnStrOut,
  372.             SQL_DRIVER_COMPLETE);
  373.     if (Status != SQL_SUCCESS)
  374.         {
  375.                 /* ODBC connect */
  376.         Status = SQLConnect (hdbc,
  377.                 DSName,
  378.                 SQL_NTS,
  379.                 Userid,
  380.                 SQL_NTS,
  381.                 Password,
  382.                 SQL_NTS);
  383.         if (Status != SQL_SUCCESS)
  384.           {
  385.           err.ErrorMsgMax = SQL_MAX_MESSAGE_LENGTH - 1;
  386.           ErrStatus = SQLError(henv,
  387.                 hdbc,
  388.                 SQL_NULL_HSTMT,
  389.                 &err.szSQLState[0],
  390.                 &err.NativeError,
  391.                 &err.ErrorMsg[0],
  392.                 err.ErrorMsgMax,
  393.                 &err.ErrorMsgLength);
  394.           }
  395.         }
  396.     ODBCLinkHandle[ActiveLinks] = hdbc;  /* add handle to active list */
  397.     if (ActiveLinks < 1)
  398.         {
  399.         strncpy((char *)ODBCLinkList,(char *)DSName,
  400.             SQL_MAX_DSN_LENGTH);
  401.         }
  402.     else
  403.         {
  404.         strncat((char *)ODBCLinkList,(char *)DSName,sizeof(DSName));
  405.         }
  406.     ActiveLinks++;
  407.     return Status;
  408. }
  409. ///////////////////////////////////////////////////////////////////
  410. // FUNCTION NAME: BuildConnectString
  411. // SYNOPSIS: build connection string for ODBC driver
  412. //  return far pointer to connection string
  413. ///////////////////////////////////////////////////////////////////
  414. POINTER dbConnection::BuildConnectString(char *str)
  415. {
  416.     UCHAR far *conec;
  417.  
  418.     conec = (UCHAR far *) malloc(CONECLEN);
  419.     movedata(FP_SEG(str), FP_OFF(str),
  420.         FP_SEG(conec), FP_OFF(conec),
  421.         1+strlen(str));
  422.     return conec;
  423. }
  424. ///////////////////////////////////////////////////////////////////
  425. // FUNCTION NAME: Disconnect
  426. // SYNOPSIS: terminate the SQL connection
  427. ///////////////////////////////////////////////////////////////////
  428. int dbConnection::Disconnect(UCHAR *LinkToDrop)
  429. {
  430.  
  431. int i;
  432. int j;
  433. int nLink;      /* index to hdbc to drop */
  434. int offset;
  435.  
  436. HDBC    ConnHandle;
  437.  
  438.     nLink = MatchLinkName(LinkToDrop);
  439.     if (nLink < 0)
  440.         {
  441.         return OOPS;
  442.         }
  443.     ConnHandle = ODBCLinkHandle[nLink];
  444.             /* ODBC disconnect          */
  445.     Status = SQLDisconnect(ConnHandle);
  446.     if (Status)
  447.         return Status;
  448.  
  449.         /* compress the list of active links and active handles */
  450.     for (i=nLink; i < ActiveLinks;i++)
  451.         {
  452.         ODBCLinkHandle[i] = ODBCLinkHandle[i+1];
  453.         }
  454.     offset = nLink * LINK_NAME_LEN;
  455.     j = offset;
  456.     while ( ODBCLinkList[j+LINK_NAME_LEN] != '\0')
  457.         {
  458.         ODBCLinkList[j] = ODBCLinkList[j+LINK_NAME_LEN];
  459.         j++;
  460.         }
  461.     ODBCLinkList[j] = '\0';
  462.     --ActiveLinks;
  463.             /* free conn handle     */
  464.     Status = SQLFreeConnect(ConnHandle);
  465.     if (Status)
  466.         return Status;
  467.  
  468.     return SQL_SUCCESS;
  469. }
  470. ///////////////////////////////////////////////////////////////////
  471. // FUNCTION NAME: ProfileDataSource
  472. // SYNOPSIS: information about driver and data source
  473. ///////////////////////////////////////////////////////////////////
  474. RETCODE PASCAL dbConnection::ProfileDataSource( DataSourceInfo *inf )
  475. {
  476.     /* implementation of error handling is left to the user, since      */
  477.     /* the user interface may vary. Using QuickWin or EasyWin, you can  */
  478.     /* use printf statements. If you are writing a typical Windows app, */
  479.     /* you can use MessageBox or BWCCMessageBox to display errors       */
  480.  
  481.     Status = SQL_SUCCESS;
  482.     Status = SQLGetInfo(hdbc,
  483.         SQL_DRIVER_NAME,
  484.         &inf->DriverName,
  485.         sizeof(inf->DriverName),
  486.         NULL);
  487.     if (Status != SQL_SUCCESS)
  488.         {
  489.         GetErrorInfo();
  490.         }
  491.     Status = SQL_SUCCESS;
  492.     Status = SQLGetInfo(hdbc,
  493.         SQL_ACTIVE_STATEMENTS,
  494.         (PTR)&inf->ActiveStatements,
  495.         sizeof(inf->ActiveStatements),
  496.         NULL);
  497.     if (Status != SQL_SUCCESS)
  498.         {
  499.         GetErrorInfo();
  500.         }
  501.     Status = SQL_SUCCESS;
  502.     Status = SQLGetInfo(hdbc,
  503.         SQL_ACTIVE_CONNECTIONS,
  504.         (PTR)&inf->ActiveConnections,
  505.         sizeof(inf->ActiveConnections),
  506.         NULL);
  507.     if (Status != SQL_SUCCESS)
  508.         {
  509.         GetErrorInfo();
  510.         }
  511.     Status = SQL_SUCCESS;
  512.     Status = SQLGetInfo(hdbc,
  513.         SQL_DRIVER_VER,
  514.         &inf->DriverVersion,
  515.         sizeof(inf->DriverVersion),
  516.         NULL);
  517.     if (Status != SQL_SUCCESS)
  518.         {
  519.         GetErrorInfo();
  520.         }
  521.     Status = SQL_SUCCESS;
  522.     Status = SQLGetInfo(hdbc,
  523.         SQL_SERVER_NAME,
  524.         &inf->ServerName,
  525.         sizeof(inf->ServerName),
  526.         NULL);
  527.     if (Status != SQL_SUCCESS)
  528.         {
  529.         GetErrorInfo();
  530.         }
  531.     Status = SQL_SUCCESS;
  532.     Status = SQLGetInfo(hdbc,
  533.         SQL_USER_NAME,
  534.         &inf->UserName,
  535.         sizeof(inf->UserName),
  536.         NULL);
  537.     if (Status != SQL_SUCCESS)
  538.         {
  539.         GetErrorInfo();
  540.         }
  541.     Status = SQL_SUCCESS;
  542.     Status = SQLGetInfo(hdbc,
  543.         SQL_ODBC_API_CONFORMANCE,
  544.         (PTR)&inf->ODBC_API_Level,
  545.         sizeof(inf->ODBC_API_Level),
  546.         NULL);
  547.     if (Status != SQL_SUCCESS)
  548.         {
  549.         GetErrorInfo();
  550.         }
  551.  
  552.     Status = SQL_SUCCESS;
  553.     Status = SQLGetInfo(hdbc,
  554.         SQL_ODBC_SAG_CLI_CONFORMANCE,
  555.         (PTR)&inf->ODBC_SAG_Level,
  556.         sizeof(inf->ODBC_SAG_Level),
  557.         NULL);
  558.     if (Status != SQL_SUCCESS)
  559.         {
  560.         GetErrorInfo();
  561.         }
  562.     Status = SQL_SUCCESS;
  563.     Status = SQLGetInfo(hdbc,
  564.         SQL_ODBC_SQL_CONFORMANCE,
  565.         (PTR)&inf->ODBC_SQL_Level,
  566.         sizeof(inf->ODBC_SQL_Level),
  567.         NULL);
  568.     if (Status != SQL_SUCCESS)
  569.         {
  570.         GetErrorInfo();
  571.         }
  572.     Status = SQL_SUCCESS;
  573.     Status = SQLGetInfo(hdbc,
  574.         SQL_DATABASE_NAME,
  575.         &inf->DatabaseName,
  576.         sizeof(inf->DatabaseName),
  577.         NULL);
  578.     if (Status != SQL_SUCCESS)
  579.         {
  580.         GetErrorInfo();
  581.         }
  582.     Status = SQL_SUCCESS;
  583.     Status = SQLGetInfo(hdbc,
  584.         SQL_DBMS_NAME,
  585.         &inf->DBMSName,
  586.         sizeof(inf->DBMSName),
  587.         NULL);
  588.     if (Status != SQL_SUCCESS)
  589.         {
  590.         GetErrorInfo();
  591.         }
  592.     Status = SQL_SUCCESS;
  593.     Status = SQLGetInfo(hdbc,
  594.         SQL_DBMS_VER,
  595.         &inf->DBMSVersion,
  596.         sizeof(inf->DBMSVersion),
  597.         NULL);
  598.     if (Status != SQL_SUCCESS)
  599.         {
  600.         GetErrorInfo();
  601.         }
  602.             /* IEF ? */
  603.     Status = SQL_SUCCESS;
  604.     Status = SQLGetInfo(hdbc,
  605.         SQL_ODBC_SQL_OPT_IEF,
  606.         &inf->IEFSupport,
  607.         sizeof(inf->IEFSupport),
  608.         NULL);
  609.     if (Status != SQL_SUCCESS)
  610.         {
  611.         GetErrorInfo();
  612.         }
  613.             /* Support Procedures ? */
  614.     Status = SQL_SUCCESS;
  615.     Status = SQLGetInfo(hdbc,
  616.         SQL_PROCEDURES,
  617.         &inf->Procedures,
  618.         sizeof(inf->Procedures),
  619.         NULL);
  620.     if (Status != SQL_SUCCESS)
  621.         {
  622.         GetErrorInfo();
  623.         }
  624.             /* detect changes in rows between fetches ? */
  625.     Status = SQL_SUCCESS;
  626.     Status = SQLGetInfo(hdbc,
  627.         SQL_ROW_UPDATES,
  628.         &inf->RowUpdates,
  629.         sizeof(inf->RowUpdates),
  630.         NULL);
  631.     if (Status != SQL_SUCCESS)
  632.         {
  633.         GetErrorInfo();
  634.         }
  635.             /* all tables accessible */
  636.     Status = SQL_SUCCESS;
  637.     Status = SQLGetInfo(hdbc,
  638.         SQL_ACCESSIBLE_TABLES,
  639.         &inf->AccessibleTables,
  640.         sizeof(inf->AccessibleTables),
  641.         NULL);
  642.     if (Status != SQL_SUCCESS)
  643.         {
  644.         GetErrorInfo();
  645.         }
  646.     if(inf->AccessibleProcedures[0] == 'Y')
  647.         {
  648.             /* all procedures accessible */
  649.         Status = SQL_SUCCESS;
  650.         Status = SQLGetInfo(hdbc,
  651.             SQL_ACCESSIBLE_PROCEDURES,
  652.             &inf->AccessibleProcedures,
  653.             sizeof(inf->AccessibleProcedures),
  654.             NULL);
  655.         if (Status != SQL_SUCCESS)
  656.             {
  657.             GetErrorInfo();
  658.             }
  659.         }
  660.     Status = SQL_SUCCESS;
  661.     Status = SQLGetInfo(hdbc,
  662.         SQL_CONCAT_NULL_BEHAVIOR,
  663.         (PTR)&inf->ConcatNullBehavior,
  664.         sizeof(inf->ConcatNullBehavior),
  665.         NULL);
  666.     if (Status != SQL_SUCCESS)
  667.         {
  668.         GetErrorInfo();
  669.         }
  670.     Status = SQL_SUCCESS;
  671.     Status = SQLGetInfo(hdbc,
  672.         SQL_CURSOR_COMMIT_BEHAVIOR,
  673.         (PTR)&inf->CursorCommitBehavior,
  674.         sizeof(inf->CursorCommitBehavior),
  675.         NULL);
  676.     if (Status != SQL_SUCCESS)
  677.         {
  678.         GetErrorInfo();
  679.         }
  680.     Status = SQL_SUCCESS;
  681.     Status = SQLGetInfo(hdbc,
  682.         SQL_CURSOR_ROLLBACK_BEHAVIOR,
  683.         (PTR)&inf->CursorRollbackBehavior,
  684.         sizeof(inf->CursorRollbackBehavior),
  685.         NULL);
  686.     if (Status != SQL_SUCCESS)
  687.         {
  688.         GetErrorInfo();
  689.         }
  690.     Status = SQL_SUCCESS;
  691.     Status = SQLGetInfo(hdbc,
  692.         SQL_DATA_SOURCE_READ_ONLY,
  693.         &inf->DSReadOnly,
  694.         sizeof(inf->DSReadOnly),
  695.         NULL);
  696.     if (Status != SQL_SUCCESS)
  697.         {
  698.         GetErrorInfo();
  699.         }
  700.     Status = SQL_SUCCESS;
  701.     Status = SQLGetInfo(hdbc,
  702.         SQL_MAX_COLUMN_NAME_LEN,
  703.         (PTR)&inf->MaxColNameLen,
  704.         sizeof(inf->MaxColNameLen),
  705.         NULL);
  706.     if (Status != SQL_SUCCESS)
  707.         {
  708.         GetErrorInfo();
  709.         }
  710.     Status = SQL_SUCCESS;
  711.     Status = SQLGetInfo(hdbc,
  712.         SQL_MAX_CURSOR_NAME_LEN,
  713.         (PTR)&inf->MaxCursorNameLen,
  714.         sizeof(inf->MaxCursorNameLen),
  715.         NULL);
  716.     if (Status != SQL_SUCCESS)
  717.         {
  718.         GetErrorInfo();
  719.         }
  720.     Status = SQL_SUCCESS;
  721.     Status = SQLGetInfo(hdbc,
  722.         SQL_MAX_OWNER_NAME_LEN,
  723.         (PTR)&inf->MaxOwnerNameLen,
  724.         sizeof(inf->MaxOwnerNameLen),
  725.         NULL);
  726.     if (Status != SQL_SUCCESS)
  727.         {
  728.         GetErrorInfo();
  729.         }
  730.  
  731.     Status = SQL_SUCCESS;
  732.     Status = SQLGetInfo(hdbc,
  733.         SQL_MAX_PROCEDURE_NAME_LEN,
  734.         (PTR)&inf->MaxProcedureNameLen,
  735.         sizeof(inf->MaxProcedureNameLen),
  736.         NULL);
  737.     if (Status != SQL_SUCCESS)
  738.         {
  739.         GetErrorInfo();
  740.         }
  741.     Status = SQL_SUCCESS;
  742.     Status = SQLGetInfo(hdbc,
  743.         SQL_MAX_QUALIFIER_NAME_LEN,
  744.         (PTR)&inf->MaxQualifierNameLen,
  745.         sizeof(inf->MaxQualifierNameLen),
  746.         NULL);
  747.     if (Status != SQL_SUCCESS)
  748.         {
  749.         GetErrorInfo();
  750.         }
  751.  
  752.     Status = SQL_SUCCESS;
  753.     Status = SQLGetInfo(hdbc,
  754.         SQL_MAX_TABLE_NAME_LEN,
  755.         (PTR)&inf->MaxTableNameLen,
  756.         sizeof(inf->MaxTableNameLen),
  757.         NULL);
  758.     if (Status != SQL_SUCCESS)
  759.         {
  760.         GetErrorInfo();
  761.         }
  762.     Status = SQL_SUCCESS;
  763.     Status = SQLGetInfo(hdbc,
  764.         SQL_MULT_RESULT_SETS,
  765.         &inf->MultipleResultSets,
  766.         sizeof(inf->MultipleResultSets),
  767.         NULL);
  768.     if (Status != SQL_SUCCESS)
  769.         {
  770.         GetErrorInfo();
  771.         }
  772.     Status = SQL_SUCCESS;
  773.     Status = SQLGetInfo(hdbc,
  774.         SQL_MULTIPLE_ACTIVE_TXN,
  775.         &inf->MultipleActiveTransactions,
  776.         sizeof(inf->MultipleActiveTransactions),
  777.         NULL);
  778.     if (Status != SQL_SUCCESS)
  779.         {
  780.         GetErrorInfo();
  781.         }
  782.     Status = SQL_SUCCESS;
  783.     Status = SQLGetInfo(hdbc,
  784.         SQL_OUTER_JOINS,
  785.         &inf->OuterJoins,
  786.         sizeof(inf->OuterJoins),
  787.         NULL);
  788.     if (Status != SQL_SUCCESS)
  789.         {
  790.         GetErrorInfo();
  791.         }
  792.     Status = SQL_SUCCESS;
  793.     Status = SQLGetInfo(hdbc,
  794.         SQL_OWNER_TERM,
  795.         &inf->OwnerTerm,
  796.         sizeof(inf->OwnerTerm),
  797.         NULL);
  798.     if (Status != SQL_SUCCESS)
  799.         {
  800.         GetErrorInfo();
  801.         }
  802.     Status = SQL_SUCCESS;
  803.     Status = SQLGetInfo(hdbc,
  804.         SQL_PROCEDURE_TERM,
  805.         &inf->ProcTerm,
  806.         sizeof(inf->ProcTerm),
  807.         NULL);
  808.     if (Status != SQL_SUCCESS)
  809.         {
  810.         GetErrorInfo();
  811.         }
  812.     Status = SQL_SUCCESS;
  813.     Status = SQLGetInfo(hdbc,
  814.         SQL_QUALIFIER_TERM,
  815.         &inf->QualifierTerm,
  816.         sizeof(inf->QualifierTerm),
  817.         NULL);
  818.     if (Status != SQL_SUCCESS)
  819.         {
  820.         GetErrorInfo();
  821.         }
  822.     Status = SQL_SUCCESS;
  823.     Status = SQLGetInfo(hdbc,
  824.         SQL_EXPRESSIONS_IN_ORDERBY,
  825.         &inf->OrderBy,
  826.         sizeof(inf->OrderBy),
  827.         NULL);
  828.     if (Status != SQL_SUCCESS)
  829.         {
  830.         GetErrorInfo();
  831.         }
  832.     Status = SQL_SUCCESS;
  833.     Status = SQLGetInfo(hdbc,
  834.         SQL_TXN_CAPABLE,
  835.         (PTR)&inf->TransCapable,
  836.         sizeof(inf->TransCapable),
  837.         NULL);
  838.     if (Status != SQL_SUCCESS)
  839.         {
  840.         GetErrorInfo();
  841.         }
  842.  
  843.     if (Status != SQL_SUCCESS)
  844.       return Status;
  845.     return(SQL_SUCCESS);
  846. }
  847. ///////////////////////////////////////////////////////////////////
  848. // FUNCTION NAME: GetErrorInfo
  849. // SYNOPSIS: check SQLError info
  850. ///////////////////////////////////////////////////////////////////
  851. void dbConnection::GetErrorInfo()
  852. {
  853.     /* implementation of error handling is left to the user, since      */
  854.     /* the user interface may vary. Using QuickWin or EasyWin, you can  */
  855.     /* use printf statements. If you are writing a typical Windows app, */
  856.     /* you can use MessageBox or BWCCMessageBox to display errors       */
  857.       err.ErrorMsgMax = SQL_MAX_MESSAGE_LENGTH - 1;
  858.       ErrStatus = SQLError(henv,
  859.             hdbc,
  860.             SQL_NULL_HSTMT,
  861.             &err.szSQLState[0],
  862.             &err.NativeError,
  863.             &err.ErrorMsg[0],
  864.             err.ErrorMsgMax,
  865.             &err.ErrorMsgLength);
  866. }
  867. ///////////////////////////////////////////////////
  868. // FUNCTION NAME: InitConnData
  869. // SYNOPSIS: initialize conn data
  870. ///////////////////////////////////////////////////
  871. void dbConnection::InitConnData()
  872. {
  873.     Status = 0;
  874.     ErrStatus = 0;
  875.     cstr = NULL;
  876.     ConnTableCount = 0;
  877.     memset(ConnectionString,'\x0',sizeof(ConnectionString));
  878.     memset(ConnTableList,'\x0',sizeof(ConnTableList));
  879. }
  880.  
  881.  
  882.  
  883. [LISTING SIX]
  884.  
  885. ///////////////////////////////////////////////////
  886. // FILE NAME: request.h        TITLE:  SQL request
  887. // AUTHOR: Ken North     Resource Group, Inc.   
  888. //                       2604B El Camino Real, #351
  889. // copyright(c)1992      Carlsbad, CA 92008
  890. ///////////////////////////////////////////////////
  891.  
  892. #ifndef __REQUEST_H
  893. #define __REQUEST_H
  894.  
  895. #ifndef __CONNECT_H
  896. #include "connect.h"
  897. #endif
  898.  
  899. #ifndef __DBOPTION_H
  900. #include "dboption.h"
  901. #endif
  902.  
  903. #ifndef __RQOPTION_H
  904. #include "rqoption.h"
  905. #endif
  906.  
  907. #ifndef __TABLESET_H
  908. #include "tableset.h"
  909. #endif
  910.             // dbRequest is a child of dbConnection
  911. class dbRequest : public dbConnection {
  912. protected:
  913.     UCHAR   Statement[MAXSQL];
  914.     UCHAR   *stmt;
  915.     RETCODE Status;
  916.                 // exceeds max statement length for d.b. driver 
  917.     BOOL    ExceedsMax; 
  918.  
  919.     HENV    henv;
  920.     HSTMT   hAStmt;
  921.  
  922.     CURNAME ACursor;    /* for named cursors            */
  923.     UCHAR   CursorName[CURSOR_NAME_LEN];    
  924. public:
  925.     UCHAR far *stptr;
  926.     HSTMT   hstmt;
  927.  
  928.     DataBaseOptions *dbopt;     // options for this database
  929.  
  930.     RequestOptions OptionInfo;      // options for this request
  931.  
  932.     dbRequest(HENV, HDBC, DataBaseOptions *, UCHAR *);
  933.     virtual ~dbRequest();
  934.  
  935.     virtual HSTMT AllocateStatement(HDBC);
  936.     virtual POINTER BuildRequest(BOOL);
  937.     virtual RETCODE ExecuteStatement(POINTER);
  938.     virtual SWORD FindNumberOfColumns(HSTMT);
  939.     virtual CURNAME GetCursorforRequest(HDBC);
  940.     SDWORD GetTableList(char *);
  941.     void InitTableResultSet(TableResultSet *);
  942.     virtual int TerminateStatement(HSTMT);
  943. };
  944. #endif
  945.  
  946.  
  947. [LISTING SEVEN]
  948.  
  949. /////////////////////////////////////////////////////////////////////
  950. // FILE NAME: request.cpp   TITLE: SQL request
  951. // AUTHOR: Ken North     Resource Group, Inc.   
  952. //                       2604B El Camino Real, #351
  953. // copyright(c)1992      Carlsbad, CA 92008
  954. /////////////////////////////////////////////////////////////////////
  955. //  SYNOPSIS: SQL request class
  956. /////////////////////////////////////////////////////////////////////
  957.  
  958. #include <windows.h>
  959. #include <stdio.h>
  960. #include <dos.h>
  961. #include <stdlib.h>
  962. #include <string.h>
  963. #include <malloc.h>
  964. #include "sql.h"            
  965. #include "sqlext.h"
  966. #include "gendefs.h"
  967. #include "sqldefs.h"
  968. #include "sqldb.h"
  969. #include "connect.h"
  970. #include "dboption.h"           /* database options */
  971.  
  972. #ifndef __ODERROR_H
  973. #include "oderror.h"
  974. #endif
  975.  
  976. #ifndef __RGSTRING_H
  977. #include "rgstring.h"
  978. #endif
  979.  
  980. #include "request.h"
  981.  
  982. extern  char    ErrStat;    /* return code for string calls */
  983. extern  char    MemModel;   /*  large / huge model */
  984.         /* Constructor for the 'Request' class: */
  985. dbRequest :: dbRequest( HENV envhandle,
  986.                         HDBC connhandle,
  987.                         DataBaseOptions *opt, 
  988.                         UCHAR *SQLstring )
  989.            : dbConnection(envhandle)
  990. {
  991.             // save SQL string and options
  992.     dbopt = opt;  
  993.     strcpy((char *)Statement,(char *)SQLstring);
  994.     stmt = &Statement[0];
  995.                 // set request environment handle
  996.     henv = envhandle; 
  997.                 // set request connection handle
  998.     hdbc = connhandle; 
  999.  
  1000. }
  1001. /////////////////////////////////////////////////////////////////////
  1002. // FUNCTION NAME: ~dbRequest
  1003. // SYNOPSIS: destructor
  1004. /////////////////////////////////////////////////////////////////////
  1005. dbRequest::~dbRequest()
  1006. {
  1007.     free(stptr);
  1008. }
  1009. /////////////////////////////////////////////////////////////////////
  1010. // FUNCTION NAME: BuildRequest
  1011. // SYNOPSIS: prepare an SQL request
  1012. /////////////////////////////////////////////////////////////////////
  1013. POINTER dbRequest::BuildRequest( BOOL ExceedsMax )
  1014. {
  1015.     if (dbopt->AllocStmtHandle)
  1016.         {
  1017.         hAStmt = AllocateStatement(hdbc);
  1018.         }
  1019.     if (OptionInfo.UseCursor)
  1020.         {
  1021.         ACursor = GetCursorforRequest(hdbc);
  1022.         }
  1023.     stptr = (UCHAR far *) malloc(MAXSQL);
  1024.     movedata(FP_SEG(stmt), FP_OFF(stmt),
  1025.             FP_SEG(stptr), FP_OFF(stptr),
  1026.             1+strlen((char *)stmt));
  1027.     return stptr;
  1028. }
  1029. /////////////////////////////////////////////////////////////////////
  1030. // FUNCTION NAME: ExecuteStatement
  1031. // SYNOPSIS: executes a direct or prepared request
  1032. /////////////////////////////////////////////////////////////////////
  1033. RETCODE dbRequest::ExecuteStatement( POINTER stptr )
  1034. {
  1035.     Status = SQLExecDirect (hAStmt, 
  1036.                         stptr,
  1037.                         SQL_NTS );
  1038.     if (Status != SQL_SUCCESS)
  1039.       {
  1040.       return Status;
  1041.       };
  1042.     return SQL_SUCCESS;
  1043. }
  1044. /////////////////////////////////////////////////////////////////////
  1045. // FUNCTION NAME: FindNumberOfColumns
  1046. // SYNOPSIS: get the number of columns in the request
  1047. /////////////////////////////////////////////////////////////////////
  1048. SWORD dbRequest::FindNumberOfColumns( HSTMT hstmt )
  1049. {
  1050. SWORD   n;
  1051.  
  1052.     Status = SQLNumResultCols (hAStmt, &n);
  1053.     if (Status != SQL_SUCCESS)
  1054.       {
  1055.       return Status;
  1056.       };
  1057.     return n;
  1058. }
  1059. /////////////////////////////////////////////////////////////////////
  1060. // FUNCTION NAME: GetTableList
  1061. // SYNOPSIS: get the tables for this SQL data source
  1062. /////////////////////////////////////////////////////////////////////
  1063. SDWORD dbRequest::GetTableList(char *TableList)
  1064. {
  1065. SDWORD      nTables=0;
  1066. SDWORD  QualifierLength;
  1067. SDWORD  OwnerLength;
  1068. SDWORD  NameLength;
  1069. SDWORD  TypeLength;
  1070. SDWORD  RemarksLength;
  1071.  
  1072. UCHAR  FAR *szTableQualifier=NULL;
  1073. SWORD      cbTableQualifier=0;
  1074. UCHAR  FAR *szTableOwner=NULL;
  1075. SWORD      cbTableOwner=0;
  1076. UCHAR  FAR *szTableName=NULL;
  1077. SWORD      cbTableName=0;
  1078. UCHAR  FAR *szTableType=NULL;
  1079. SWORD      cbTableType=0; 
  1080.  
  1081. TableResultSet  *rset;
  1082. char NameString[TABLE_NAME_LEN+1];
  1083.  
  1084.     rset = new(TableResultSet);
  1085.     if(!rset)
  1086.         return NO_MEMORY;
  1087.     InitTableResultSet(rset);
  1088.     Status = SQL_SUCCESS;
  1089.     ErrStatus = 0;
  1090.     Status = SQLTables( hstmt,
  1091.         szTableQualifier,
  1092.         cbTableQualifier,
  1093.         szTableOwner,
  1094.         cbTableOwner,
  1095.         szTableName,
  1096.         cbTableName,
  1097.         szTableType,
  1098.         cbTableType);
  1099.     if(Status == SQL_ERROR)
  1100.         {
  1101.         err.ErrorMsgMax = SQL_MAX_MESSAGE_LENGTH - 1;
  1102.         ErrStatus = SQLError(henv,
  1103.             hdbc,
  1104.             SQL_NULL_HSTMT,
  1105.             &err.szSQLState[0],
  1106.             &err.NativeError,
  1107.             &err.ErrorMsg[0],
  1108.             err.ErrorMsgMax,
  1109.             &err.ErrorMsgLength);
  1110.         if (ErrStatus < 1)
  1111.             return Status;
  1112.         }
  1113.     Status = SQL_SUCCESS;
  1114.     Status=SQLBindCol(hstmt, 1, SQL_C_CHAR,
  1115.         &rset->TABLE_QUALIFIER, 
  1116.         sizeof(rset->TABLE_QUALIFIER), &QualifierLength);
  1117.     if(Status == SQL_ERROR)
  1118.         {
  1119.         err.ErrorMsgMax = SQL_MAX_MESSAGE_LENGTH - 1;
  1120.         ErrStatus = SQLError(henv,
  1121.             hdbc,
  1122.             SQL_NULL_HSTMT,
  1123.             &err.szSQLState[0],
  1124.             &err.NativeError,
  1125.             &err.ErrorMsg[0],
  1126.             err.ErrorMsgMax,
  1127.             &err.ErrorMsgLength);
  1128.         if (ErrStatus < 1)
  1129.             return Status;
  1130.         }
  1131.     Status = SQL_SUCCESS;
  1132.     ErrStatus = 0;
  1133.     Status=SQLBindCol(hstmt, 2, SQL_C_CHAR,
  1134.         &rset->TABLE_OWNER, 
  1135.         sizeof(rset->TABLE_OWNER), &OwnerLength);
  1136.     if(Status == SQL_ERROR)
  1137.         {
  1138.         err.ErrorMsgMax = SQL_MAX_MESSAGE_LENGTH - 1;
  1139.         ErrStatus = SQLError(henv,
  1140.             hdbc,
  1141.             SQL_NULL_HSTMT,
  1142.             &err.szSQLState[0],
  1143.             &err.NativeError,
  1144.             &err.ErrorMsg[0],
  1145.             err.ErrorMsgMax,
  1146.             &err.ErrorMsgLength);
  1147.         if (ErrStatus < 1)
  1148.             return Status;
  1149.         }
  1150.     Status = SQL_SUCCESS;
  1151.     ErrStatus = 0;
  1152.     Status=SQLBindCol(hstmt, 3, SQL_C_CHAR,
  1153.         &rset->TABLE_NAME, 
  1154.         sizeof(rset->TABLE_NAME), &NameLength);
  1155.     if(Status == SQL_ERROR)
  1156.         {
  1157.         err.ErrorMsgMax = SQL_MAX_MESSAGE_LENGTH - 1;
  1158.         ErrStatus = SQLError(henv,
  1159.             hdbc,
  1160.             SQL_NULL_HSTMT,
  1161.             &err.szSQLState[0],
  1162.             &err.NativeError,
  1163.             &err.ErrorMsg[0],
  1164.             err.ErrorMsgMax,
  1165.             &err.ErrorMsgLength);
  1166.         if (ErrStatus < 1)
  1167.             return Status;
  1168.         }
  1169.     Status = SQL_SUCCESS;
  1170.     ErrStatus = 0;
  1171.     Status=SQLBindCol(hstmt, 4, SQL_C_CHAR,
  1172.         &rset->TABLE_TYPE, 
  1173.         sizeof(rset->TABLE_TYPE), &TypeLength);
  1174.     if(Status == SQL_ERROR)
  1175.         {
  1176.         err.ErrorMsgMax = SQL_MAX_MESSAGE_LENGTH - 1;
  1177.         ErrStatus = SQLError(henv,
  1178.             hdbc,
  1179.             SQL_NULL_HSTMT,
  1180.             &err.szSQLState[0],
  1181.             &err.NativeError,
  1182.             &err.ErrorMsg[0],
  1183.             err.ErrorMsgMax,
  1184.             &err.ErrorMsgLength);
  1185.         if (ErrStatus < 1)
  1186.             return Status;
  1187.         }
  1188.  
  1189.     Status = SQL_SUCCESS;
  1190.     ErrStatus = 0;
  1191.     Status=SQLBindCol(hstmt, 5, SQL_C_CHAR,
  1192.         &rset->REMARKS, 
  1193.         sizeof(rset->REMARKS), &RemarksLength);
  1194.     if(Status == SQL_ERROR)
  1195.         {
  1196.         err.ErrorMsgMax = SQL_MAX_MESSAGE_LENGTH - 1;
  1197.         ErrStatus = SQLError(henv,
  1198.             hdbc,
  1199.             SQL_NULL_HSTMT,
  1200.             &err.szSQLState[0],
  1201.             &err.NativeError,
  1202.             &err.ErrorMsg[0],
  1203.             err.ErrorMsgMax,
  1204.             &err.ErrorMsgLength);
  1205.         if (ErrStatus < 1)
  1206.             return Status;
  1207.         }
  1208.         /*  Loop to fetch data for SQLTables  */
  1209.     while (Status != SQL_NO_DATA_FOUND)
  1210.         {
  1211.         InitTableResultSet(rset);
  1212.         Status = SQL_SUCCESS;
  1213.         ErrStatus = 0;
  1214.         Status = SQLFetch(hstmt);
  1215.         if(Status == SQL_ERROR)
  1216.             {
  1217.             err.ErrorMsgMax = SQL_MAX_MESSAGE_LENGTH - 1;
  1218.             ErrStatus = SQLError(henv,
  1219.                 hdbc,
  1220.                 SQL_NULL_HSTMT,
  1221.                 &err.szSQLState[0],
  1222.                 &err.NativeError,
  1223.                 &err.ErrorMsg[0],
  1224.                 err.ErrorMsgMax,
  1225.                 &err.ErrorMsgLength);
  1226.             if (ErrStatus < 1)
  1227.                 return Status;
  1228.             }
  1229.         strcpy(NameString,(char *)rset->TABLE_NAME);
  1230.         right_fill(NameString,SPACE,TABLE_NAME_LEN);
  1231.         strncat(TableList,NameString,TABLE_NAME_LEN);
  1232.         nTables++;
  1233.         }
  1234.     return nTables;
  1235. }
  1236. /////////////////////////////////////////////////////////////////////
  1237. // FUNCTION NAME: InitTableResultSet
  1238. // SYNOPSIS: initialize result set for GetTables
  1239. /////////////////////////////////////////////////////////////////////
  1240. void dbRequest::InitTableResultSet(TableResultSet *rs)
  1241. {
  1242.     memset(rs->TABLE_QUALIFIER,'\x0',sizeof(rs->TABLE_QUALIFIER));
  1243.     memset(rs->TABLE_OWNER,'\x0',sizeof(rs->TABLE_OWNER));
  1244.     memset(rs->TABLE_NAME,'\x0',sizeof(rs->TABLE_NAME));
  1245.     memset(rs->TABLE_TYPE,'\x0',sizeof(rs->TABLE_TYPE));
  1246.     memset(rs->REMARKS,'\x0',sizeof(rs->REMARKS));
  1247. }
  1248. /////////////////////////////////////////////////////////////////////
  1249. // FUNCTION NAME: TerminateStatement
  1250. // SYNOPSIS: terminate the statement
  1251. /////////////////////////////////////////////////////////////////////
  1252. RETCODE dbRequest::TerminateStatement(HSTMT hstmt)
  1253. {
  1254.     Status = SQLFreeStmt(hstmt, SQL_DROP);
  1255.     if (Status)
  1256.         return Status;
  1257.     else
  1258.         return SQL_SUCCESS;
  1259. }
  1260. /////////////////////////////////////////////////////////////////////
  1261. // FUNCTION NAME: AllocateStatement
  1262. // SYNOPSIS: allocates a statement handle
  1263. /////////////////////////////////////////////////////////////////////
  1264. HSTMT dbRequest::AllocateStatement(HDBC hdbc)
  1265. {
  1266.     Status = SQLAllocStmt(hdbc, &hstmt);
  1267.     if (Status != SQL_SUCCESS)
  1268.       {
  1269.       return NULL;
  1270.       };
  1271.     return hstmt;
  1272. }
  1273. /////////////////////////////////////////////////////////////////////
  1274. // FUNCTION NAME: GetCursorforRequest
  1275. // SYNOPSIS: gets a cursor for this request
  1276. /////////////////////////////////////////////////////////////////////
  1277. CURNAME dbRequest::GetCursorforRequest(HDBC hdbc)
  1278. {
  1279.     return NULL;
  1280. }
  1281.  
  1282.  
  1283.  
  1284. [LISTING EIGHT]
  1285.  
  1286. /////////////////////////////////////////////////////////////////////
  1287. // FILE NAME:  column.h   TITLE:  SQL column class
  1288. // AUTHOR: Ken North     Resource Group, Inc.   
  1289. //                       2604B El Camino Real, #351
  1290. //  copyright(c)1992     Carlsbad, CA 92008
  1291. /////////////////////////////////////////////////////////////////////
  1292.  
  1293. #ifndef __COLUMN_H
  1294. #define __COLUMN_H
  1295.  
  1296. #ifndef __DBOPTION_H
  1297. #include "dboption.h"
  1298. #endif
  1299.  
  1300. #ifndef __REQUEST_H
  1301. #include "request.h"
  1302. #endif
  1303.  
  1304. #ifndef __COLDESC_H
  1305. #include "coldesc.h"
  1306. #endif
  1307.         /* 'dbColumn' is a child of 'dbRequest' */
  1308. class dbColumn : public dbRequest {
  1309. protected:
  1310.     HSTMT   hstmt;
  1311. public:
  1312.     RETCODE     Status;
  1313.                   /* column info for this request */
  1314.     ColumnDesc  ColumnInfo[MAXFIELD];
  1315.  
  1316.     dbColumn(HENV, HDBC,  DataBaseOptions *, HSTMT, UCHAR *, UWORD);
  1317.     virtual ~dbColumn();
  1318.  
  1319.     virtual int Describe(UWORD, ColumnDesc *);
  1320.     virtual char * DecodeODBCDataType(SWORD);
  1321. };
  1322. #endif
  1323.  
  1324.  
  1325.  
  1326. [LISTING NINE]
  1327.  
  1328. /////////////////////////////////////////////////////////////////////
  1329. // FILE NAME: column.cpp    TITLE: database column 
  1330. // AUTHOR: Ken North     Resource Group, Inc.   
  1331. //                       2604B El Camino Real, #351
  1332. // copyright(c)1992      Carlsbad, CA 92008
  1333. // 
  1334. /////////////////////////////////////////////////////////////////////
  1335. //  SYNOPSIS: implementation of SQL column class 
  1336. /////////////////////////////////////////////////////////////////////
  1337.  
  1338. #include <windows.h>
  1339. #include <stdio.h>
  1340. #include <dos.h>
  1341. #include <stdlib.h>
  1342. #include <string.h>
  1343. #include <malloc.h>
  1344. #include "sql.h"
  1345. #include "sqlext.h"
  1346. #include "sqldefs.h"
  1347. #include "sqldb.h"
  1348. #include "connect.h"
  1349. #include "dboption.h"
  1350. #include "rqoption.h"
  1351. #include "request.h"
  1352. #include "column.h"
  1353.         /* Constructor for the 'dbColumn' class: */
  1354. dbColumn :: dbColumn( HENV envhandle,
  1355.                HDBC connhandle,
  1356.                DataBaseOptions *opt,
  1357.                HSTMT hStatement,
  1358.                UCHAR *SQLstring,
  1359.                UWORD ColumnPosition )
  1360.  : dbRequest( envhandle, connhandle, opt, SQLstring)
  1361. {
  1362.     hstmt = hStatement;
  1363. }
  1364. /////////////////////////////////////////////////////////////////////
  1365. // FUNCTION NAME: ~dbColumn
  1366. // SYNOPSIS: destructor for dbColumn
  1367. /////////////////////////////////////////////////////////////////////
  1368. dbColumn::~dbColumn()
  1369. {
  1370.  
  1371. }
  1372. /////////////////////////////////////////////////////////////////////
  1373. // FUNCTION NAME: Describe
  1374. // SYNOPSIS: get a column description
  1375. /////////////////////////////////////////////////////////////////////
  1376. RETCODE dbColumn::Describe( UWORD ColumnPosition, ColumnDesc *fi)
  1377. {
  1378. UCHAR FAR *col;
  1379. SWORD NameBufLen=NAMELENGTH;
  1380. SWORD ncount;
  1381.         /* get the column name, type, width, etc. */
  1382.     Status = SQLDescribeCol ( hstmt,
  1383.             ColumnPosition,
  1384.             &fi->Name[0],
  1385.             NameBufLen,
  1386.             &ncount,
  1387.             &fi->DataType,
  1388.             &fi->Precision,
  1389.             &fi->Scale,
  1390.             &fi->Nullable);
  1391.     if (Status != SQL_SUCCESS)
  1392.         {
  1393.         return Status;
  1394.         }
  1395.     return SQL_SUCCESS;
  1396. }
  1397. /////////////////////////////////////////////////////////////////////
  1398. // FUNCTION NAME: DecodeODBCDataType
  1399. // SYNOPSIS: return description of data type
  1400. /////////////////////////////////////////////////////////////////////
  1401. char *dbColumn::DecodeODBCDataType(SWORD DataType)
  1402. {
  1403. static char Type[20];
  1404.  
  1405.     strcpy((char *)Type,"Unknown");
  1406.     if (DataType == SQL_CHAR)
  1407.         strcpy((char *)Type,"character");
  1408.     if (DataType == SQL_VARCHAR)
  1409.         strcpy((char *)Type,"variable len char");
  1410.     if (DataType == SQL_LONGVARCHAR)
  1411.         strcpy((char *)Type,"long variable char");
  1412.     if (DataType == SQL_DECIMAL)
  1413.         strcpy((char *)Type,"decimal");
  1414.     if (DataType == SQL_NUMERIC)
  1415.         strcpy((char *)Type,"numeric");
  1416.     if (DataType == SQL_BIT)
  1417.         strcpy((char *)Type,"bit");
  1418.     if (DataType == SQL_TINYINT)
  1419.         strcpy((char *)Type,"tiny integer");
  1420.     if (DataType == SQL_SMALLINT)
  1421.         strcpy((char *)Type,"small integer");
  1422.     if (DataType == SQL_INTEGER)
  1423.         strcpy((char *)Type,"integer");
  1424.     if (DataType == SQL_BIGINT)
  1425.         strcpy((char *)Type,"big integer");
  1426.     if (DataType == SQL_REAL)
  1427.         strcpy((char *)Type,"real");
  1428.     if (DataType == SQL_FLOAT)
  1429.         strcpy((char *)Type,"float");
  1430.     if (DataType == SQL_DOUBLE)
  1431.         strcpy((char *)Type,"double");
  1432.     if (DataType == SQL_BINARY)
  1433.         strcpy((char *)Type,"binary");
  1434.     if (DataType == SQL_VARBINARY)
  1435.         strcpy((char *)Type,"variable binary");
  1436.     if (DataType == SQL_LONGVARBINARY)
  1437.         strcpy((char *)Type,"long variable binary");
  1438.     if (DataType == SQL_DATE)
  1439.         strcpy((char *)Type,"date");
  1440.     if (DataType == SQL_TIME)
  1441.         strcpy((char *)Type,"time");
  1442.     if (DataType == SQL_TIMESTAMP)
  1443.         strcpy((char *)Type,"timestamp");
  1444.     return Type;
  1445. }
  1446.  
  1447.  
  1448.  
  1449. [LISTING TEN]
  1450.  
  1451. ///////////////////////////////////////////////////
  1452. // FILE NAME:  blob.h   TITLE:  SQL blob class
  1453. // AUTHOR: Ken North     Resource Group, Inc.   
  1454. //                       2604B El Camino Real, #351
  1455. // copyright(c)1992      Carlsbad, CA 92008
  1456. ///////////////////////////////////////////////////
  1457.  
  1458. #ifndef __BLOB_H
  1459. #define __BLOB_H
  1460.  
  1461. #ifndef __DBOPTION_H
  1462. #include "dboption.h"
  1463. #endif
  1464.  
  1465. #ifndef __REQUEST_H
  1466. #include "request.h"
  1467. #endif
  1468.         /* 'dbBlob' is a child of 'dbRequest' */
  1469. class dbBlob : public dbRequest {
  1470. protected:
  1471.     HSTMT   hstmt;
  1472. public:
  1473.     RETCODE     Status;
  1474.     dbBlob(HENV, HDBC,  DataBaseOptions *, HSTMT, UCHAR *);
  1475.     virtual ~dbBlob();
  1476.  
  1477. };
  1478. #endif
  1479.  
  1480.  
  1481.  
  1482. [LISTING ELEVEN]
  1483.  
  1484. ///////////////////////////////////////////////////
  1485. // FILE NAME: blob.cpp  TITLE: database blob 
  1486. // AUTHOR: Ken North     Resource Group, Inc.   
  1487. //                       2604B El Camino Real, #351
  1488. // copyright(c)1992  Carlsbad, CA 92008
  1489. //  SYNOPSIS: implementation of SQL blob class 
  1490. ///////////////////////////////////////////////////
  1491.  
  1492. #include <windows.h>
  1493. #include <stdio.h>
  1494. #include <dos.h>
  1495. #include <stdlib.h>
  1496. #include <string.h>
  1497. #include <malloc.h>
  1498. #include "sql.h"
  1499. #include "sqlext.h"
  1500. #include "sqldefs.h"
  1501. #include "sqldb.h"
  1502. #include "connect.h"
  1503. #include "dboption.h"
  1504. #include "rqoption.h"
  1505. #include "request.h"
  1506. #include "blob.h"
  1507.         /* Constructor for the 'dbBLOB' class: */
  1508. dbBlob :: dbBlob( HENV envhandle,
  1509.                     HDBC connhandle, 
  1510.                        DataBaseOptions *opt, 
  1511.                        HSTMT hStatement, 
  1512.                        UCHAR *SQLstring)
  1513.  : dbRequest( envhandle, connhandle, opt, SQLstring)
  1514. {
  1515.     hstmt = hStatement;
  1516. }
  1517. ///////////////////////////////////////////////////
  1518. // FUNCTION NAME: ~dbBLOB
  1519. // SYNOPSIS: destructor for dbBLOB
  1520. ///////////////////////////////////////////////////
  1521. dbBlob::~dbBlob()
  1522. {
  1523. }
  1524.  
  1525.  
  1526.  
  1527. [LISTING TWELVE]
  1528. ///////////////////////////////////////////////////////////////////
  1529. //  FILE NAME:  SQLstruc.cpp       TITLE: SQL data dictionary
  1530. //  AUTHOR: Ken North     Resource Group, Inc., 2604B El Camino Real, #351
  1531. //  copyright(c)1992      Carlsbad, CA 92008
  1532. //  SYNOPSIS: display dictionary (structure) info for SQL table
  1533. ///////////////////////////////////////////////////////////////////
  1534.  
  1535. #include <stdio.h>
  1536. #include <stdlib.h>
  1537. #include <conio.h>
  1538. #include <string.h>
  1539. #include <windows.h>
  1540. #include "qeapi.h"   
  1541.  
  1542. #ifndef __QEDEFS_H
  1543. #include "qedefs.h"         /* QELIB definitions */
  1544. #endif
  1545.  
  1546. #ifndef __SQLDB_H
  1547. #include "sqldb.h"          /* database class    */
  1548. #endif
  1549.  
  1550. #ifndef __CONNECT_H
  1551. #include "connect.h"    
  1552. #endif
  1553.  
  1554. #ifndef __RQOPTION_H
  1555. #include "rqoption.h"       /* request options   */
  1556. #endif
  1557.  
  1558. #ifndef __DATASRC_H
  1559. #include "datasrc.h"        /* data source      */
  1560. #endif
  1561.  
  1562. #ifndef __REQUEST_H
  1563. #include "request.h"
  1564. #endif
  1565.  
  1566. #ifndef __COLUMN_H
  1567. #include "column.h"     
  1568. #endif
  1569.  
  1570. #ifndef __BLOB_H
  1571. #include "blob.h"
  1572. #endif
  1573.  
  1574. #ifndef __COLDESC_H
  1575. #include "coldesc.h"        /* column or field description */
  1576. #endif
  1577.  
  1578. #include "sqlstruc.h"
  1579.  
  1580. static char DBDriver [9];
  1581. static char DBDictPath[80];
  1582. static char DBTable[31];
  1583. static char DBUserid[31];
  1584. static char DBPassword[PASSWORDLEN];
  1585.  
  1586. static char SQLString[MAXSQL];
  1587. static char FldName[DISPLAYLEN+1];
  1588.  
  1589. char    *driver;
  1590. char    *table;
  1591. char    *dict;
  1592. char    *userid;
  1593. char    *password;
  1594.  
  1595. ColumnDesc *fi;
  1596.  
  1597. void main (int argc, char *argv[])
  1598. {
  1599. dbDataBase *db;
  1600. dbConnection *connection;
  1601. dbRequest *request;
  1602. dbColumn *column;
  1603. dbBlob   *BLOB;
  1604.  
  1605. HSTMT   hstmt;
  1606. POINTER statement;
  1607.                 // exceeds max SQL stmt. length 
  1608. BOOL    ExceedsMax=FALSE; 
  1609.  
  1610. int nColumns;       /* number of columns */
  1611. int ColumnPosition;
  1612. int ColumnCount;
  1613. int flen;               /* string length of field name */
  1614. int i;                  /* blank fill loop index       */
  1615. int TotalLength;        /* sum of field lengths        */
  1616.  
  1617. char    *ColumnDataType;
  1618.     memset(DBDriver,'\x0',sizeof(DBDriver));
  1619.     memset(DBDictPath,'\x0',sizeof(DBDictPath));
  1620.     memset(DBTable,'\x0',sizeof(DBTable));
  1621.     memset(DBUserid,'\x0',sizeof(DBUserid));
  1622.     memset(DBPassword,'\x0',sizeof(DBPassword));
  1623.     memset(SQLString,'\x0',sizeof(SQLString));
  1624.             /* point to strings */
  1625.     table       = &DBTable[0];
  1626.     dict        = &DBDictPath[0];
  1627.     driver      = &DBDriver[0];
  1628.     userid      = &DBUserid[0];
  1629.     password    = &DBPassword[0];
  1630.         /* data source includes a driver and path */
  1631.         /* Using ODBC, data source info is in a file    */
  1632.         /* For this example, prompt for relevant info   */
  1633.     DataSource source;
  1634.     memset(source.DBDictPath,'\x0',sizeof(source.DBDictPath));
  1635.     memset(source.DBDataPath,'\x0',sizeof(source.DBDataPath));
  1636.     memset(source.DBDriver,'\x0',sizeof(source.DBDriver));
  1637.     memset(source.DBUserid,'\x0',sizeof(source.DBUserid));
  1638.     memset(source.DBDataBase,'\x0',sizeof(source.DBDataBase));
  1639.     memset(source.DBServer,'\x0',sizeof(source.DBServer));
  1640.  
  1641.     db = new(dbDataBase);
  1642.     db->StatusReturned = SQL_SUCCESS;
  1643.             /* define options for this database */
  1644.     db->Options.AllocConnHandle    = FALSE;
  1645.     db->Options.AllocEnvHandle     = FALSE;
  1646.     db->Options.AllocStmtHandle    = FALSE;
  1647.     db->Options.UseCursor          = FALSE;
  1648.     db->opt = &db->Options; /* point to database options */
  1649.  
  1650.     GetArgs(argc,argv[1],argv[2],argv[3],
  1651.         table,dict,driver);
  1652.             /* make selection of database type */
  1653.     strcpy (source.DBDriver, driver);
  1654.         /* for dBASE and Paradox databases, the table structure */
  1655.         /* or dictionary info is in the same directory as data */
  1656.     strcpy (source.DBDictPath, DBDictPath);
  1657.     strcpy (source.DBDataPath, DBDictPath);
  1658.             /*****************************/
  1659.             /*  connect to datasource    */
  1660.             /*****************************/
  1661.     connection = new(dbConnection);
  1662.     connection->hdbc = connection->Connect( source, password );
  1663.     if ((connection->hdbc == NOHANDLE))
  1664.         {
  1665.         printf ("\n<SQLStruc> ERROR %d: Unable to connect to %s",
  1666.                 connection->hdbc, source.DBDriver);
  1667.         exit (1);
  1668.         }
  1669.             /*****************************/
  1670.             /*  statement / request      */
  1671.             /*****************************/
  1672.     strcpy(SQLString,"SELECT * FROM ");
  1673.     strcat(SQLString,source.DBDataPath);
  1674.             /* terminate the SQL string */
  1675.     SQLString[strlen(SQLString)] = '\x5c';
  1676.     strcat(SQLString,DBTable);
  1677.     request = new dbRequest(connection->hdbc, db->opt, SQLString);
  1678.             /* define options for this request */
  1679.     request->OptionInfo.UseDirectExec      = TRUE;
  1680.     request->OptionInfo.UseNamedCursor     = FALSE;
  1681.     request->OptionInfo.UseTransaction     = FALSE;
  1682.             /* build a valid SQL request/statement string     */
  1683.             /* Note: statement length may be an issue in some */
  1684.             /* SQL libraries                  */
  1685.     statement =
  1686.         request->BuildRequest(ExceedsMax);
  1687.     request->hstmt = request->ExecuteStatement(statement);
  1688.     nColumns = request->FindNumberOfColumns(request->hstmt);
  1689.  
  1690.     ColumnPosition = 0;
  1691.     ColumnCount = 0;
  1692.     TotalLength = 0;
  1693.     column = new dbColumn( connection->hdbc, db->opt, 
  1694.                                request->hstmt, SQLString, ColumnPosition);
  1695.                     /************************/
  1696.                     /*  get description */
  1697.                     /************************/
  1698.     printf ("\nStructure for table: %s\n", DBTable);
  1699.     printf ("Field        Field Name            Type   Width  Dec\n");
  1700.     db->StatusReturned = SQL_SUCCESS;
  1701.     do
  1702.         {
  1703.                     /* point to column descriptor */
  1704.         fi = &column->ColumnInfo[ColumnPosition];
  1705.         db->StatusReturned = SQL_SUCCESS;
  1706.         db->StatusReturned =
  1707.             column->Describe(ColumnPosition+1, fi);
  1708.         if ((db->StatusReturned != SQL_SUCCESS))
  1709.             {
  1710.             if (db->StatusReturned == ENDFILE)
  1711.                 {
  1712.                 break;
  1713.                 }
  1714.             else
  1715.                 {
  1716.                 printf
  1717.                 ("\n<SQLStruc> ERROR: getting column data for 
  1718.                                                            %s\n", SQLString);
  1719.                 exit (1);
  1720.                 }
  1721.             };
  1722.         ColumnCount++;          /* update field count */
  1723.         TotalLength +=
  1724.             column->ColumnInfo[ColumnPosition].Length;
  1725.             /* data type is specific to the SQL library */
  1726.         ColumnDataType = column->DecodeQEDataType(fi->DataType);
  1727.         strcpy(FldName,fi->Name);
  1728.         flen = strlen(fi->Name);
  1729.         for ( i=flen; i < DISPLAYLEN; i++ );
  1730.             {
  1731.             FldName[i]='\x20';
  1732.             }
  1733.         FldName[DISPLAYLEN]='\x0';
  1734.         printf ("\n %3d  %20.20s  %12.12s  %5d  %2d", ColumnCount,
  1735.                               FldName, ColumnDataType,
  1736.                               fi->Length, fi->Scale);
  1737.         ColumnPosition++;
  1738.         }
  1739.     while (ColumnPosition < nColumns);
  1740.     printf ("\nTotal: %d\n",TotalLength);
  1741.                 // terminate request
  1742.     db->StatusReturned = 
  1743.             request->TerminateStatement(request->hstmt);
  1744.                     /************************/
  1745.                     /*  disconnect          */
  1746.                     /************************/
  1747.     db->StatusReturned = connection->Disconnect();
  1748.     if ((db->StatusReturned != SQL_SUCCESS))
  1749.         {
  1750.         printf ("\n<SQLStruc> ERROR %d: Disconnecting from %s",
  1751.                 db->StatusReturned, source.DBDriver);
  1752.         exit (1);
  1753.         }
  1754. }
  1755. /**************************************************
  1756. * FUNCTION NAME: GetArgs
  1757. * AUTHOR: Ken North 
  1758. * SYNOPSIS: get table name and dictionary path from  command line or user
  1759. ***************************************************/
  1760. void GetArgs(int argc, char *arg1, char *arg2, 
  1761.         char *arg3, char *table, char *dict, char *driver)
  1762. {
  1763. static char name [80]; 
  1764.   if (argc > 1)
  1765.     {
  1766.     memset(name,'\x0',sizeof(name));
  1767.     if (*arg1 == '?')
  1768.       {
  1769.       printf("\n  Usage: SQLSTRUC table \
  1770.  dictionarypath\n");
  1771.       printf ("\n SQLSTRUC    SQL \
  1772. data definitions\n");
  1773.       printf("   (Requires QELIB DLL\
  1774. or QExxx.DLL)\n\n");
  1775.       printf
  1776.       ("    To display a data dictionary screen, \
  1777.       type:\n");
  1778.       printf
  1779.       ("       SQLSTRUC table dictpath driver| \
  1780. MORE\n\n");
  1781.       printf
  1782.       ("    To list to a file, type:\n");
  1783.       printf
  1784.       ("       SQLSTRUC table dictpath driver> \
  1785. listfile\n\n\n");
  1786.       exit(1);
  1787.       }         
  1788.     strcpy (name, arg1);
  1789.     strupr (name);  /* translate to upper case */
  1790.     strcpy(table,name) ;    /* copy name to table */
  1791.     memset(name,'\x0',sizeof(name));
  1792.     }
  1793.   if (argc > 2)
  1794.     {
  1795.     strcpy (name, arg2);
  1796.     strupr (name);  /* translate to upper case */
  1797.     strcpy(dict,name) ;
  1798.     memset(name,'\x0',sizeof(name));
  1799.     }
  1800.   if (argc > 3)
  1801.     {
  1802.     strcpy (name, arg3);
  1803.     strupr (name); /* translate to upper case */
  1804.     strcpy(driver,name) ;
  1805.     }
  1806.   if (argc < 2)
  1807.     {
  1808.     printf ("Table name ? ");
  1809.     gets (name);
  1810.     strupr (name);  /* translate to upper case */
  1811.     strcpy(table,name) ;
  1812.     memset(name,'\x0',sizeof(name)); /* zero name */
  1813.     printf ("Dictionary pathname ? ");
  1814.     gets (name);
  1815.     strupr (name);
  1816.     strcpy(dict,name) ;
  1817.     memset(name,'\x0',sizeof(name)); /* zero name */
  1818.     printf ("Database driver ? ");
  1819.     gets (name);
  1820.     strupr (name); 
  1821.     strcpy(driver,name) ;
  1822.     }
  1823. }
  1824.  
  1825.  
  1826.  
  1827.