1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        wx/db.h
3 // Purpose:     Header file wxDb class.  The wxDb class represents a connection
4 //              to an ODBC data source.  The wxDb class allows operations on the data
5 //              source such as opening and closing the data source.
6 // Author:      Doug Card
7 // Modified by: George Tasker
8 //              Bart Jourquin
9 //              Mark Johnson, wxWindows@mj10777.de
10 // Mods:        Dec, 1998:
11 //                -Added support for SQL statement logging and database cataloging
12 //                     April, 1999
13 //                -Added QUERY_ONLY mode support to reduce default number of cursors
14 //                -Added additional SQL logging code
15 //                -Added DEBUG-ONLY tracking of Ctable objects to detect orphaned DB connections
16 //                -Set ODBC option to only read committed writes to the DB so all
17 //                     databases operate the same in that respect
18 //
19 // Created:     9.96
20 // RCS-ID:      $Id: db.h 56697 2008-11-07 22:45:47Z VZ $
21 // Copyright:   (c) 1996 Remstar International, Inc.
22 // Licence:     wxWindows licence
23 ///////////////////////////////////////////////////////////////////////////////
24 
25 #ifndef _WX_DB_H_
26 #define _WX_DB_H_
27 
28 
29 // BJO 20000503: introduce new GetColumns members which are more database independent and
30 //               return columns in the order they were created
31 #define OLD_GETCOLUMNS 1
32 #define EXPERIMENTAL_WXDB_FUNCTIONS 1
33 
34 #include "wx/defs.h"
35 #include "wx/string.h"
36 
37 #if defined(__VISUALC__)
38     // we need to include standard Windows headers but we can't include
39     // <windows.h> directly when using MFC because it includes it itself in a
40     // different manner
41     #if wxUSE_MFC
42         #include <afxwin.h>
43     #else // !wxUSE_MFC
44         #include "wx/msw/wrapwin.h"
45     #endif // wxUSE_MFC/!wxUSE_MFC
46 
47     // If you use the wxDbCreateDataSource() function with MSW/VC6,
48     // you cannot use the iODBC headers, you must use the VC headers,
49     // plus the odbcinst.h header - gt Nov 2 2000
50     //
51     // Must add "odbccp32.lib" in \wx2\wxWidgets\src\makevc.env to the WINLIBS= line
52     //
53     #include "sql.h"
54     #include "sqlext.h"
55     //#if wxUSE_UNICODE
56     //    #include <sqlucode.h>
57     //#endif
58     #include "odbcinst.h"
59 #else
60     #if defined(__WINDOWS__) && ( defined(HAVE_W32API_H) || defined(__BORLANDC__)  || defined (__DMC__))
61         #include "wx/msw/wrapwin.h"
62     #endif
63     extern "C" {
64     #if defined(wxUSE_BUILTIN_IODBC) && wxUSE_BUILTIN_IODBC
65         // Use the ones from the library
66         #include "wx/isql.h"
67         #include "wx/isqlext.h"
68         // Not available in v2.x of iODBC
69         #ifndef __WXMSW__
70           #if wxUSE_UNICODE
71           typedef wxChar SQLTCHAR;
72           #else
73           typedef UCHAR SQLTCHAR;
74           #endif
75         #endif
76     #else // !wxUSE_BUILTIN_IODBC
77         // SQL headers define BOOL if it's not defined yet but BOOL is also
78         // defined in many other places on other systems (Motif, at least on
79         // OpenVMS; Cocoa and X11) so prevent the problem by defining it before
80         // including these headers
81         #ifndef BOOL
82             #define BOOL int
83             #include <sql.h>
84             #include <sqlext.h>
85             #undef BOOL
86         #else
87             #include <sql.h>
88             #include <sqlext.h>
89         #endif
90     #endif // wxUSE_BUILTIN_IODBC/!wxUSE_BUILTIN_IODBC
91     }
92 #endif
93 
94 #if wxUSE_UNICODE
95 #define SQL_C_WXCHAR SQL_C_WCHAR
96 #else
97 #define SQL_C_WXCHAR SQL_C_CHAR
98 #endif
99 
100 #ifdef __DIGITALMARS__
101 #if wxUSE_UNICODE
102 typedef wxChar SQLTCHAR;
103 #else
104 typedef UCHAR SQLTCHAR;
105 #endif
106 #endif
107 
108 typedef float SFLOAT;
109 typedef double SDOUBLE;
110 typedef unsigned int UINT;
111 #define ULONG UDWORD
112 
113 #ifndef wxODBC_FWD_ONLY_CURSORS
114 #define wxODBC_FWD_ONLY_CURSORS 1
115 #endif
116 
117 enum enumDummy {enumDum1};
118 
119 #ifndef SQL_C_BOOLEAN
120     #define SQL_C_BOOLEAN(datatype) (sizeof(datatype) == 1 ? SQL_C_UTINYINT : (sizeof(datatype) == 2 ? SQL_C_USHORT : SQL_C_ULONG))
121 #endif
122 
123 #ifndef SQL_C_ENUM
124     #define SQL_C_ENUM (sizeof(enumDummy) == 2 ? SQL_C_USHORT : SQL_C_ULONG)
125 #endif
126 
127 // NOTE: If SQL_C_BLOB is defined, and it is not SQL_C_BINARY, iODBC 2.x
128 //       may not function correctly.  Likely best to use SQL_C_BINARY direct
129 #ifndef SQL_C_BLOB
130     #ifdef SQL_C_BINARY
131         #define SQL_C_BLOB SQL_C_BINARY
132     #endif
133 #endif
134 
135 #ifndef _WIN64
136 #ifndef SQLLEN
137 #define SQLLEN SQLINTEGER
138 #endif
139 #ifndef SQLULEN
140 #define SQLULEN SQLUINTEGER
141 #endif
142 #endif
143 
144 const int wxDB_PATH_MAX                 = 254;
145 
146 extern WXDLLIMPEXP_DATA_ODBC(wxChar const *) SQL_LOG_FILENAME;
147 extern WXDLLIMPEXP_DATA_ODBC(wxChar const *) SQL_CATALOG_FILENAME;
148 
149 // Database Globals
150 const int DB_TYPE_NAME_LEN            = 40;
151 const int DB_MAX_STATEMENT_LEN        = 4096;
152 const int DB_MAX_WHERE_CLAUSE_LEN     = 2048;
153 const int DB_MAX_ERROR_MSG_LEN        = 512;
154 const int DB_MAX_ERROR_HISTORY        = 5;
155 const int DB_MAX_TABLE_NAME_LEN       = 128;
156 const int DB_MAX_COLUMN_NAME_LEN      = 128;
157 
158 const int DB_DATA_TYPE_VARCHAR        = 1;
159 const int DB_DATA_TYPE_INTEGER        = 2;
160 const int DB_DATA_TYPE_FLOAT          = 3;
161 const int DB_DATA_TYPE_DATE           = 4;
162 const int DB_DATA_TYPE_BLOB           = 5;
163 const int DB_DATA_TYPE_MEMO           = 6;
164 
165 const int DB_SELECT_KEYFIELDS         = 1;
166 const int DB_SELECT_WHERE             = 2;
167 const int DB_SELECT_MATCHING          = 3;
168 const int DB_SELECT_STATEMENT         = 4;
169 
170 const int DB_UPD_KEYFIELDS            = 1;
171 const int DB_UPD_WHERE                = 2;
172 
173 const int DB_DEL_KEYFIELDS            = 1;
174 const int DB_DEL_WHERE                = 2;
175 const int DB_DEL_MATCHING             = 3;
176 
177 const int DB_WHERE_KEYFIELDS          = 1;
178 const int DB_WHERE_MATCHING           = 2;
179 
180 const int DB_GRANT_SELECT             = 1;
181 const int DB_GRANT_INSERT             = 2;
182 const int DB_GRANT_UPDATE             = 4;
183 const int DB_GRANT_DELETE             = 8;
184 const int DB_GRANT_ALL                = DB_GRANT_SELECT | DB_GRANT_INSERT | DB_GRANT_UPDATE | DB_GRANT_DELETE;
185 
186 // ODBC Error codes (derived from ODBC SqlState codes)
187 enum wxODBC_ERRORS
188 {
189     DB_FAILURE                        = 0,
190     DB_SUCCESS                        = 1,
191     DB_ERR_NOT_IN_USE,
192     DB_ERR_GENERAL_WARNING,                            // SqlState = '01000'
193     DB_ERR_DISCONNECT_ERROR,                           // SqlState = '01002'
194     DB_ERR_DATA_TRUNCATED,                             // SqlState = '01004'
195     DB_ERR_PRIV_NOT_REVOKED,                           // SqlState = '01006'
196     DB_ERR_INVALID_CONN_STR_ATTR,                      // SqlState = '01S00'
197     DB_ERR_ERROR_IN_ROW,                               // SqlState = '01S01'
198     DB_ERR_OPTION_VALUE_CHANGED,                       // SqlState = '01S02'
199     DB_ERR_NO_ROWS_UPD_OR_DEL,                         // SqlState = '01S03'
200     DB_ERR_MULTI_ROWS_UPD_OR_DEL,                      // SqlState = '01S04'
201     DB_ERR_WRONG_NO_OF_PARAMS,                         // SqlState = '07001'
202     DB_ERR_DATA_TYPE_ATTR_VIOL,                        // SqlState = '07006'
203     DB_ERR_UNABLE_TO_CONNECT,                          // SqlState = '08001'
204     DB_ERR_CONNECTION_IN_USE,                          // SqlState = '08002'
205     DB_ERR_CONNECTION_NOT_OPEN,                        // SqlState = '08003'
206     DB_ERR_REJECTED_CONNECTION,                        // SqlState = '08004'
207     DB_ERR_CONN_FAIL_IN_TRANS,                         // SqlState = '08007'
208     DB_ERR_COMM_LINK_FAILURE,                          // SqlState = '08S01'
209     DB_ERR_INSERT_VALUE_LIST_MISMATCH,                 // SqlState = '21S01'
210     DB_ERR_DERIVED_TABLE_MISMATCH,                     // SqlState = '21S02'
211     DB_ERR_STRING_RIGHT_TRUNC,                         // SqlState = '22001'
212     DB_ERR_NUMERIC_VALUE_OUT_OF_RNG,                   // SqlState = '22003'
213     DB_ERR_ERROR_IN_ASSIGNMENT,                        // SqlState = '22005'
214     DB_ERR_DATETIME_FLD_OVERFLOW,                      // SqlState = '22008'
215     DB_ERR_DIVIDE_BY_ZERO,                             // SqlState = '22012'
216     DB_ERR_STR_DATA_LENGTH_MISMATCH,                   // SqlState = '22026'
217     DB_ERR_INTEGRITY_CONSTRAINT_VIOL,                  // SqlState = '23000'
218     DB_ERR_INVALID_CURSOR_STATE,                       // SqlState = '24000'
219     DB_ERR_INVALID_TRANS_STATE,                        // SqlState = '25000'
220     DB_ERR_INVALID_AUTH_SPEC,                          // SqlState = '28000'
221     DB_ERR_INVALID_CURSOR_NAME,                        // SqlState = '34000'
222     DB_ERR_SYNTAX_ERROR_OR_ACCESS_VIOL,                // SqlState = '37000'
223     DB_ERR_DUPLICATE_CURSOR_NAME,                      // SqlState = '3C000'
224     DB_ERR_SERIALIZATION_FAILURE,                      // SqlState = '40001'
225     DB_ERR_SYNTAX_ERROR_OR_ACCESS_VIOL2,               // SqlState = '42000'
226     DB_ERR_OPERATION_ABORTED,                          // SqlState = '70100'
227     DB_ERR_UNSUPPORTED_FUNCTION,                       // SqlState = 'IM001'
228     DB_ERR_NO_DATA_SOURCE,                             // SqlState = 'IM002'
229     DB_ERR_DRIVER_LOAD_ERROR,                          // SqlState = 'IM003'
230     DB_ERR_SQLALLOCENV_FAILED,                         // SqlState = 'IM004'
231     DB_ERR_SQLALLOCCONNECT_FAILED,                     // SqlState = 'IM005'
232     DB_ERR_SQLSETCONNECTOPTION_FAILED,                 // SqlState = 'IM006'
233     DB_ERR_NO_DATA_SOURCE_DLG_PROHIB,                  // SqlState = 'IM007'
234     DB_ERR_DIALOG_FAILED,                              // SqlState = 'IM008'
235     DB_ERR_UNABLE_TO_LOAD_TRANSLATION_DLL,             // SqlState = 'IM009'
236     DB_ERR_DATA_SOURCE_NAME_TOO_LONG,                  // SqlState = 'IM010'
237     DB_ERR_DRIVER_NAME_TOO_LONG,                       // SqlState = 'IM011'
238     DB_ERR_DRIVER_KEYWORD_SYNTAX_ERROR,                // SqlState = 'IM012'
239     DB_ERR_TRACE_FILE_ERROR,                           // SqlState = 'IM013'
240     DB_ERR_TABLE_OR_VIEW_ALREADY_EXISTS,               // SqlState = 'S0001'
241     DB_ERR_TABLE_NOT_FOUND,                            // SqlState = 'S0002'
242     DB_ERR_INDEX_ALREADY_EXISTS,                       // SqlState = 'S0011'
243     DB_ERR_INDEX_NOT_FOUND,                            // SqlState = 'S0012'
244     DB_ERR_COLUMN_ALREADY_EXISTS,                      // SqlState = 'S0021'
245     DB_ERR_COLUMN_NOT_FOUND,                           // SqlState = 'S0022'
246     DB_ERR_NO_DEFAULT_FOR_COLUMN,                      // SqlState = 'S0023'
247     DB_ERR_GENERAL_ERROR,                              // SqlState = 'S1000'
248     DB_ERR_MEMORY_ALLOCATION_FAILURE,                  // SqlState = 'S1001'
249     DB_ERR_INVALID_COLUMN_NUMBER,                      // SqlState = 'S1002'
250     DB_ERR_PROGRAM_TYPE_OUT_OF_RANGE,                  // SqlState = 'S1003'
251     DB_ERR_SQL_DATA_TYPE_OUT_OF_RANGE,                 // SqlState = 'S1004'
252     DB_ERR_OPERATION_CANCELLED,                        // SqlState = 'S1008'
253     DB_ERR_INVALID_ARGUMENT_VALUE,                     // SqlState = 'S1009'
254     DB_ERR_FUNCTION_SEQUENCE_ERROR,                    // SqlState = 'S1010'
255     DB_ERR_OPERATION_INVALID_AT_THIS_TIME,             // SqlState = 'S1011'
256     DB_ERR_INVALID_TRANS_OPERATION_CODE,               // SqlState = 'S1012'
257     DB_ERR_NO_CURSOR_NAME_AVAIL,                       // SqlState = 'S1015'
258     DB_ERR_INVALID_STR_OR_BUF_LEN,                     // SqlState = 'S1090'
259     DB_ERR_DESCRIPTOR_TYPE_OUT_OF_RANGE,               // SqlState = 'S1091'
260     DB_ERR_OPTION_TYPE_OUT_OF_RANGE,                   // SqlState = 'S1092'
261     DB_ERR_INVALID_PARAM_NO,                           // SqlState = 'S1093'
262     DB_ERR_INVALID_SCALE_VALUE,                        // SqlState = 'S1094'
263     DB_ERR_FUNCTION_TYPE_OUT_OF_RANGE,                 // SqlState = 'S1095'
264     DB_ERR_INF_TYPE_OUT_OF_RANGE,                      // SqlState = 'S1096'
265     DB_ERR_COLUMN_TYPE_OUT_OF_RANGE,                   // SqlState = 'S1097'
266     DB_ERR_SCOPE_TYPE_OUT_OF_RANGE,                    // SqlState = 'S1098'
267     DB_ERR_NULLABLE_TYPE_OUT_OF_RANGE,                 // SqlState = 'S1099'
268     DB_ERR_UNIQUENESS_OPTION_TYPE_OUT_OF_RANGE,        // SqlState = 'S1100'
269     DB_ERR_ACCURACY_OPTION_TYPE_OUT_OF_RANGE,          // SqlState = 'S1101'
270     DB_ERR_DIRECTION_OPTION_OUT_OF_RANGE,              // SqlState = 'S1103'
271     DB_ERR_INVALID_PRECISION_VALUE,                    // SqlState = 'S1104'
272     DB_ERR_INVALID_PARAM_TYPE,                         // SqlState = 'S1105'
273     DB_ERR_FETCH_TYPE_OUT_OF_RANGE,                    // SqlState = 'S1106'
274     DB_ERR_ROW_VALUE_OUT_OF_RANGE,                     // SqlState = 'S1107'
275     DB_ERR_CONCURRENCY_OPTION_OUT_OF_RANGE,            // SqlState = 'S1108'
276     DB_ERR_INVALID_CURSOR_POSITION,                    // SqlState = 'S1109'
277     DB_ERR_INVALID_DRIVER_COMPLETION,                  // SqlState = 'S1110'
278     DB_ERR_INVALID_BOOKMARK_VALUE,                     // SqlState = 'S1111'
279     DB_ERR_DRIVER_NOT_CAPABLE,                         // SqlState = 'S1C00'
280     DB_ERR_TIMEOUT_EXPIRED                             // SqlState = 'S1T00'
281 };
282 
283 #ifndef MAXNAME
284     #define MAXNAME         31
285 #endif
286 
287 #ifndef SQL_MAX_AUTHSTR_LEN
288     // There does not seem to be a standard for this, so I am
289     // defaulting to the value that MS uses
290     #define SQL_MAX_AUTHSTR_LEN MAXNAME
291 #endif
292 
293 #ifndef SQL_MAX_CONNECTSTR_LEN
294     // There does not seem to be a standard for this, so I am
295     // defaulting to the value that MS recommends
296     #define SQL_MAX_CONNECTSTR_LEN 1024
297 #endif
298 
299 
300 class WXDLLIMPEXP_ODBC wxDbConnectInf
301 {
302     private:
303         bool freeHenvOnDestroy;
304         bool useConnectionStr;
305 
306     public:
307         HENV Henv;
308         wxChar Dsn[SQL_MAX_DSN_LENGTH+1];                  // Data Source Name
309         wxChar Uid[SQL_MAX_USER_NAME_LEN+1];               // User ID
310         wxChar AuthStr[SQL_MAX_AUTHSTR_LEN+1];             // Authorization string (password)
311         wxChar ConnectionStr[SQL_MAX_CONNECTSTR_LEN+1];    // Connection string (password)
312 
313         wxString Description;                              // Not sure what the max length is
314         wxString FileType;                                 // Not sure what the max length is
315 
316         // Optionals needed for some databases like dBase
317         wxString DefaultDir;                               // Directory that db file resides in
318 
319     public:
320 
321         wxDbConnectInf();
322         wxDbConnectInf(HENV henv, const wxString &dsn, const wxString &userID=wxEmptyString,
323                        const wxString &password=wxEmptyString, const wxString &defaultDir=wxEmptyString,
324                        const wxString &description=wxEmptyString, const wxString &fileType=wxEmptyString);
325 
326         ~wxDbConnectInf();
327 
328         bool             Initialize();
329 
330         bool             AllocHenv();
331         void             FreeHenv();
332 
333         // Accessors
GetHenv()334         const HENV       &GetHenv()          { return Henv; }
335 
GetDsn()336         const wxChar    *GetDsn()           { return Dsn; }
337 
GetUid()338         const wxChar    *GetUid()           { return Uid; }
GetUserID()339         const wxChar    *GetUserID()        { return Uid; }
340 
GetAuthStr()341         const wxChar    *GetAuthStr()       { return AuthStr; }
GetPassword()342         const wxChar    *GetPassword()      { return AuthStr; }
343 
GetConnectionStr()344         const wxChar    *GetConnectionStr() { return ConnectionStr; }
UseConnectionStr()345         bool             UseConnectionStr() { return useConnectionStr; }
346 
GetDescription()347         const wxChar    *GetDescription()   { return Description; }
GetFileType()348         const wxChar    *GetFileType()      { return FileType; }
GetDefaultDir()349         const wxChar    *GetDefaultDir()    { return DefaultDir; }
350 
SetHenv(const HENV henv)351         void             SetHenv(const HENV henv)               { Henv = henv; }
352 
353         void             SetDsn(const wxString &dsn);
354 
355         void             SetUserID(const wxString &userID);
SetUid(const wxString & uid)356         void             SetUid(const wxString &uid)            { SetUserID(uid); }
357 
358         void             SetPassword(const wxString &password);
SetAuthStr(const wxString & authstr)359         void             SetAuthStr(const wxString &authstr)    { SetPassword(authstr); }
360 
361         void             SetConnectionStr(const wxString &connectStr);
362 
SetDescription(const wxString & desc)363         void             SetDescription(const wxString &desc)   { Description   = desc;     }
SetFileType(const wxString & fileType)364         void             SetFileType(const wxString &fileType)  { FileType      = fileType; }
SetDefaultDir(const wxString & defDir)365         void             SetDefaultDir(const wxString &defDir)  { DefaultDir    = defDir;   }
366 };  // class wxDbConnectInf
367 
368 
369 struct WXDLLIMPEXP_ODBC wxDbSqlTypeInfo
370 {
371     wxString    TypeName;
372     SWORD       FsqlType;
373     long        Precision;
374     short       CaseSensitive;
375     short       MaximumScale;
376 };
377 
378 
379 class WXDLLIMPEXP_ODBC wxDbColFor
380 {
381 public:
382     wxString       s_Field;              // Formatted String for Output
383     wxString       s_Format[7];          // Formatted Objects - TIMESTAMP has the biggest (7)
384     wxString       s_Amount[7];          // Formatted Objects - amount of things that can be formatted
385     int            i_Amount[7];          // Formatted Objects - TT MM YYYY HH MM SS m
386     int            i_Nation;             // 0 = timestamp , 1=EU, 2=UK, 3=International, 4=US
387     int            i_dbDataType;         // conversion of the 'sqlDataType' to the generic data type used by these classes
388     SWORD          i_sqlDataType;
389 
390     wxDbColFor();
~wxDbColFor()391     ~wxDbColFor(){}
392 
393     void           Initialize();
394     int            Format(int Nation, int dbDataType, SWORD sqlDataType, short columnLength, short decimalDigits);
395 };
396 
397 
398 class WXDLLIMPEXP_ODBC wxDbColInf
399 {
400 public:
401     wxChar       catalog[128+1];
402     wxChar       schema[128+1];
403     wxChar       tableName[DB_MAX_TABLE_NAME_LEN+1];
404     wxChar       colName[DB_MAX_COLUMN_NAME_LEN+1];
405     SWORD        sqlDataType;
406     wxChar       typeName[128+1];
407     SWORD        columnLength;
408     SWORD        bufferSize;
409     short        decimalDigits;
410     short        numPrecRadix;
411     short        nullable;
412     wxChar       remarks[254+1];
413     int          dbDataType;  // conversion of the 'sqlDataType' to the generic data type used by these classes
414  // mj10777.19991224 : new
415     int          PkCol;       // Primary key column       0=No; 1= First Key, 2 = Second Key etc.
416     wxChar       PkTableName[DB_MAX_TABLE_NAME_LEN+1]; // Tables that use this PKey as a FKey
417     int          FkCol;       // Foreign key column       0=No; 1= First Key, 2 = Second Key etc.
418     wxChar       FkTableName[DB_MAX_TABLE_NAME_LEN+1]; // Foreign key table name
419     wxDbColFor  *pColFor;                              // How should this columns be formatted
420 
421     wxDbColInf();
422     ~wxDbColInf();
423 
424     bool Initialize();
425 };
426 
427 
428 class WXDLLIMPEXP_ODBC wxDbTableInf        // Description of a Table
429 {
430 public:
431     wxChar      tableName[DB_MAX_TABLE_NAME_LEN+1];
432     wxChar      tableType[254+1];           // "TABLE" or "SYSTEM TABLE" etc.
433     wxChar      tableRemarks[254+1];
434     UWORD       numCols;                    // How many Columns does this Table have: GetColumnCount(..);
435     wxDbColInf *pColInf;                    // pColInf = NULL ; User can later call GetColumns(..);
436 
437     wxDbTableInf();
438     ~wxDbTableInf();
439 
440     bool             Initialize();
441 };
442 
443 
444 class WXDLLIMPEXP_ODBC wxDbInf     // Description of a Database
445 {
446 public:
447     wxChar        catalog[128+1];
448     wxChar        schema[128+1];
449     int           numTables;           // How many tables does this database have
450     wxDbTableInf *pTableInf;           // pTableInf = new wxDbTableInf[numTables];
451 
452     wxDbInf();
453     ~wxDbInf();
454 
455     bool          Initialize();
456 };
457 
458 
459 enum wxDbSqlLogState
460 {
461     sqlLogOFF,
462     sqlLogON
463 };
464 
465 // These are the databases currently tested and working with these classes
466 // See the comments in wxDb::Dbms() for exceptions/issues with
467 // each of these database engines
468 enum wxDBMS
469 {
470     dbmsUNIDENTIFIED,
471     dbmsORACLE,
472     dbmsSYBASE_ASA,        // Adaptive Server Anywhere
473     dbmsSYBASE_ASE,        // Adaptive Server Enterprise
474     dbmsMS_SQL_SERVER,
475     dbmsMY_SQL,
476     dbmsPOSTGRES,
477     dbmsACCESS,
478     dbmsDBASE,
479     dbmsINFORMIX,
480     dbmsVIRTUOSO,
481     dbmsDB2,
482     dbmsINTERBASE,
483     dbmsPERVASIVE_SQL,
484     dbmsXBASE_SEQUITER,
485     dbmsFIREBIRD,
486     dbmsMAXDB,
487     dbmsFuture1,
488     dbmsFuture2,
489     dbmsFuture3,
490     dbmsFuture4,
491     dbmsFuture5,
492     dbmsFuture6,
493     dbmsFuture7,
494     dbmsFuture8,
495     dbmsFuture9,
496     dbmsFuture10
497 };
498 
499 
500 // The wxDb::errorList is copied to this variable when the wxDb object
501 // is closed.  This way, the error list is still available after the
502 // database object is closed.  This is necessary if the database
503 // connection fails so the calling application can show the operator
504 // why the connection failed.  Note: as each wxDb object is closed, it
505 // will overwrite the errors of the previously destroyed wxDb object in
506 // this variable.
507 
508 extern WXDLLIMPEXP_DATA_ODBC(wxChar)
509     DBerrorList[DB_MAX_ERROR_HISTORY][DB_MAX_ERROR_MSG_LEN+1];
510 
511 
512 class WXDLLIMPEXP_ODBC wxDb
513 {
514 private:
515     bool             dbIsOpen;
516     bool             dbIsCached;      // Was connection created by caching functions
517     bool             dbOpenedWithConnectionString;  // Was the database connection opened with a connection string
518     wxString         dsn;             // Data source name
519     wxString         uid;             // User ID
520     wxString         authStr;         // Authorization string (password)
521     wxString         inConnectionStr; // Connection string used to connect to the database
522     wxString         outConnectionStr;// Connection string returned by the database when a connection is successfully opened
523     FILE            *fpSqlLog;        // Sql Log file pointer
524     wxDbSqlLogState  sqlLogState;     // On or Off
525     bool             fwdOnlyCursors;
526     wxDBMS           dbmsType;        // Type of datasource - i.e. Oracle, dBase, SQLServer, etc
527 
528     // Private member functions
529     bool             getDbInfo(bool failOnDataTypeUnsupported=true);
530     bool             getDataTypeInfo(SWORD fSqlType, wxDbSqlTypeInfo &structSQLTypeInfo);
531     bool             setConnectionOptions(void);
532     void             logError(const wxString &errMsg, const wxString &SQLState);
533     const wxChar    *convertUserID(const wxChar *userID, wxString &UserID);
534     bool             determineDataTypes(bool failOnDataTypeUnsupported);
535     void             initialize();
536     bool             open(bool failOnDataTypeUnsupported=true);
537 
538 #if !wxODBC_BACKWARD_COMPATABILITY
539     // ODBC handles
540     HENV  henv;        // ODBC Environment handle
541     HDBC  hdbc;        // ODBC DB Connection handle
542     HSTMT hstmt;       // ODBC Statement handle
543 
544     //Error reporting mode
545     bool silent;
546 
547     // Number of Ctable objects connected to this db object.  FOR INTERNAL USE ONLY!!!
548     unsigned int nTables;
549 
550     // Information about logical data types VARCHAR, INTEGER, FLOAT and DATE.
551      //
552     // This information is obtained from the ODBC driver by use of the
553     // SQLGetTypeInfo() function.  The key piece of information is the
554     // type name the data source uses for each logical data type.
555     // e.g. VARCHAR; Oracle calls it VARCHAR2.
556     wxDbSqlTypeInfo typeInfVarchar;
557     wxDbSqlTypeInfo typeInfInteger;
558     wxDbSqlTypeInfo typeInfFloat;
559     wxDbSqlTypeInfo typeInfDate;
560     wxDbSqlTypeInfo typeInfBlob;
561     wxDbSqlTypeInfo typeInfMemo;
562 #endif
563 
564 public:
565 
setCached(bool cached)566     void             setCached(bool cached)  { dbIsCached = cached; }  // This function must only be called by wxDbGetConnection() and wxDbCloseConnections!!!
IsCached()567     bool             IsCached() { return dbIsCached; }
568 
GetDataTypeInfo(SWORD fSqlType,wxDbSqlTypeInfo & structSQLTypeInfo)569     bool             GetDataTypeInfo(SWORD fSqlType, wxDbSqlTypeInfo &structSQLTypeInfo)
570                             { return getDataTypeInfo(fSqlType, structSQLTypeInfo); }
571 
572 #if wxODBC_BACKWARD_COMPATABILITY
573     // ODBC handles
574     HENV  henv;        // ODBC Environment handle
575     HDBC  hdbc;        // ODBC DB Connection handle
576     HSTMT hstmt;       // ODBC Statement handle
577 
578     //Error reporting mode
579     bool silent;
580 
581     // Number of Ctable objects connected to this db object.  FOR INTERNAL USE ONLY!!!
582     unsigned int nTables;
583 #endif
584 
585     // The following structure contains database information gathered from the
586     // datasource when the datasource is first opened.
587     struct
588     {
589         wxChar dbmsName[40];                             // Name of the dbms product
590         wxChar dbmsVer[64];                              // Version # of the dbms product
591         wxChar driverName[40];                           // Driver name
592         wxChar odbcVer[60];                              // ODBC version of the driver
593         wxChar drvMgrOdbcVer[60];                        // ODBC version of the driver manager
594         wxChar driverVer[60];                            // Driver version
595         wxChar serverName[80];                           // Server Name, typically a connect string
596         wxChar databaseName[128];                        // Database filename
597         wxChar outerJoins[2];                            // Indicates whether the data source supports outer joins
598         wxChar procedureSupport[2];                      // Indicates whether the data source supports stored procedures
599         wxChar accessibleTables[2];                      // Indicates whether the data source only reports accessible tables in SQLTables.
600         UWORD  maxConnections;                           // Maximum # of connections the data source supports
601         UWORD  maxStmts;                                 // Maximum # of HSTMTs per HDBC
602         UWORD  apiConfLvl;                               // ODBC API conformance level
603         UWORD  cliConfLvl;                               // Indicates whether the data source is SAG compliant
604         UWORD  sqlConfLvl;                               // SQL conformance level
605         UWORD  cursorCommitBehavior;                     // Indicates how cursors are affected by a db commit
606         UWORD  cursorRollbackBehavior;                   // Indicates how cursors are affected by a db rollback
607         UWORD  supportNotNullClause;                     // Indicates if data source supports NOT NULL clause
608         wxChar supportIEF[2];                            // Integrity Enhancement Facility (Referential Integrity)
609         UDWORD txnIsolation;                             // Default transaction isolation level supported by the driver
610         UDWORD txnIsolationOptions;                      // Transaction isolation level options available
611         UDWORD fetchDirections;                          // Fetch directions supported
612         UDWORD lockTypes;                                // Lock types supported in SQLSetPos
613         UDWORD posOperations;                            // Position operations supported in SQLSetPos
614         UDWORD posStmts;                                 // Position statements supported
615         UDWORD scrollConcurrency;                        // Concurrency control options supported for scrollable cursors
616         UDWORD scrollOptions;                            // Scroll Options supported for scrollable cursors
617         UDWORD staticSensitivity;                        // Indicates if additions, deletions and updates can be detected
618         UWORD  txnCapable;                               // Indicates if the data source supports transactions
619         UDWORD loginTimeout;                             // Number seconds to wait for a login request
620     } dbInf;
621 
622     // ODBC Error Inf.
623     SWORD  cbErrorMsg;
624     int    DB_STATUS;
625 #ifdef __VMS
626    // The DECC compiler chokes when in db.cpp the array is accessed outside
627    // its bounds. Maybe this change should also applied for other platforms.
628     wxChar errorList[DB_MAX_ERROR_HISTORY][DB_MAX_ERROR_MSG_LEN+1];
629 #else
630     wxChar errorList[DB_MAX_ERROR_HISTORY][DB_MAX_ERROR_MSG_LEN];
631 #endif
632     wxChar errorMsg[SQL_MAX_MESSAGE_LENGTH];
633     SQLINTEGER nativeError;
634     wxChar sqlState[20];
635 
636 #if wxODBC_BACKWARD_COMPATABILITY
637     // Information about logical data types VARCHAR, INTEGER, FLOAT and DATE.
638      //
639     // This information is obtained from the ODBC driver by use of the
640     // SQLGetTypeInfo() function.  The key piece of information is the
641     // type name the data source uses for each logical data type.
642     // e.g. VARCHAR; Oracle calls it VARCHAR2.
643     wxDbSqlTypeInfo typeInfVarchar;
644     wxDbSqlTypeInfo typeInfInteger;
645     wxDbSqlTypeInfo typeInfFloat;
646     wxDbSqlTypeInfo typeInfDate;
647     wxDbSqlTypeInfo typeInfBlob;
648 #endif
649 
650     // Public member functions
651     wxDb(const HENV &aHenv, bool FwdOnlyCursors=(bool)wxODBC_FWD_ONLY_CURSORS);
652     ~wxDb();
653 
654     // Data Source Name, User ID, Password and whether open should fail on data type not supported
655     bool         Open(const wxString& inConnectStr, bool failOnDataTypeUnsupported=true);
656                     ///This version of Open will open the odbc source selection dialog. Cast a wxWindow::GetHandle() to SQLHWND to use.
657     bool         Open(const wxString& inConnectStr, SQLHWND parentWnd, bool failOnDataTypeUnsupported=true);
658     bool         Open(const wxString &Dsn, const wxString &Uid, const wxString &AuthStr, bool failOnDataTypeUnsupported=true);
659     bool         Open(wxDbConnectInf *dbConnectInf, bool failOnDataTypeUnsupported=true);
660     bool         Open(wxDb *copyDb);  // pointer to a wxDb whose connection info should be copied rather than re-queried
661     void         Close(void);
662     bool         CommitTrans(void);
663     bool         RollbackTrans(void);
664     bool         DispAllErrors(HENV aHenv, HDBC aHdbc = SQL_NULL_HDBC, HSTMT aHstmt = SQL_NULL_HSTMT);
665     bool         GetNextError(HENV aHenv, HDBC aHdbc = SQL_NULL_HDBC, HSTMT aHstmt = SQL_NULL_HSTMT);
666     void         DispNextError(void);
667     bool         CreateView(const wxString &viewName, const wxString &colList, const wxString &pSqlStmt, bool attemptDrop=true);
668     bool         DropView(const wxString &viewName);
669     bool         ExecSql(const wxString &pSqlStmt);
670     bool         ExecSql(const wxString &pSqlStmt, wxDbColInf** columns, short& numcols);
671     bool         GetNext(void);
672     bool         GetData(UWORD colNo, SWORD cType, PTR pData, SDWORD maxLen, SQLLEN FAR *cbReturned);
673     bool         Grant(int privileges, const wxString &tableName, const wxString &userList = wxT("PUBLIC"));
674     int          TranslateSqlState(const wxString &SQLState);
675     wxDbInf     *GetCatalog(const wxChar *userID=NULL);
676     bool         Catalog(const wxChar *userID=NULL, const wxString &fileName=SQL_CATALOG_FILENAME);
677     int          GetKeyFields(const wxString &tableName, wxDbColInf* colInf, UWORD noCols);
678 
679     wxDbColInf  *GetColumns(wxChar *tableName[], const wxChar *userID=NULL);
680     wxDbColInf  *GetColumns(const wxString &tableName, UWORD *numCols, const wxChar *userID=NULL);
681 
682     int             GetColumnCount(const wxString &tableName, const wxChar *userID=NULL);
GetDatabaseName(void)683     const wxChar   *GetDatabaseName(void)  {return dbInf.dbmsName;}
GetDataSource(void)684     const wxString &GetDataSource(void)    {return dsn;}
GetDatasourceName(void)685     const wxString &GetDatasourceName(void){return dsn;}
GetUsername(void)686     const wxString &GetUsername(void)      {return uid;}
GetPassword(void)687     const wxString &GetPassword(void)      {return authStr;}
GetConnectionInStr(void)688     const wxString &GetConnectionInStr(void)  {return inConnectionStr;}
GetConnectionOutStr(void)689     const wxString &GetConnectionOutStr(void) {return outConnectionStr;}
IsOpen(void)690     bool            IsOpen(void)           {return dbIsOpen;}
OpenedWithConnectionString(void)691     bool            OpenedWithConnectionString(void) {return dbOpenedWithConnectionString;}
GetHENV(void)692     HENV            GetHENV(void)          {return henv;}
GetHDBC(void)693     HDBC            GetHDBC(void)          {return hdbc;}
GetHSTMT(void)694     HSTMT           GetHSTMT(void)         {return hstmt;}
GetTableCount()695     int             GetTableCount()        {return nTables;}  // number of tables using this connection
GetTypeInfVarchar()696     wxDbSqlTypeInfo GetTypeInfVarchar()    {return typeInfVarchar;}
GetTypeInfInteger()697     wxDbSqlTypeInfo GetTypeInfInteger()    {return typeInfInteger;}
GetTypeInfFloat()698     wxDbSqlTypeInfo GetTypeInfFloat()      {return typeInfFloat;}
GetTypeInfDate()699     wxDbSqlTypeInfo GetTypeInfDate()       {return typeInfDate;}
GetTypeInfBlob()700     wxDbSqlTypeInfo GetTypeInfBlob()       {return typeInfBlob;}
GetTypeInfMemo()701     wxDbSqlTypeInfo GetTypeInfMemo()       {return typeInfMemo;}
702 
703     // tableName can refer to a table, view, alias or synonym
704     bool         TableExists(const wxString &tableName, const wxChar *userID=NULL,
705                              const wxString &tablePath=wxEmptyString);
706     bool         TablePrivileges(const wxString &tableName, const wxString &priv,
707                                  const wxChar *userID=NULL, const wxChar *schema=NULL,
708                                  const wxString &path=wxEmptyString);
709 
710     // These two functions return the table name or column name in a form ready
711     // for use in SQL statements.  For example, if the datasource allows spaces
712     // in the table name or column name, the returned string will have the
713     // correct enclosing marks around the name to allow it to be properly
714     // included in a SQL statement
715     const wxString  SQLTableName(const wxChar *tableName);
716     const wxString  SQLColumnName(const wxChar *colName);
717 
718     void         LogError(const wxString &errMsg, const wxString &SQLState = wxEmptyString)
719                         { logError(errMsg, SQLState); }
SetDebugErrorMessages(bool state)720     void         SetDebugErrorMessages(bool state) { silent = !state; }
721     bool         SetSqlLogging(wxDbSqlLogState state, const wxString &filename = SQL_LOG_FILENAME,
722                                bool append = false);
723     bool         WriteSqlLog(const wxString &logMsg);
724 
725     wxDBMS       Dbms(void);
726     bool         ModifyColumn(const wxString &tableName, const wxString &columnName,
727                               int dataType, ULONG columnLength=0,
728                               const wxString &optionalParam=wxEmptyString);
729 
FwdOnlyCursors(void)730     bool         FwdOnlyCursors(void)  {return fwdOnlyCursors;}
731 
732     // return the string with all special SQL characters escaped
733     wxString     EscapeSqlChars(const wxString& value);
734 
735     // These two functions are provided strictly for use by wxDbTable.
736     // DO NOT USE THESE FUNCTIONS, OR MEMORY LEAKS MAY OCCUR
incrementTableCount()737     void         incrementTableCount() { nTables++; return; }
decrementTableCount()738     void         decrementTableCount() { nTables--; return; }
739 
740 };  // wxDb
741 
742 
743 // This structure forms a node in a linked list.  The linked list of "DbList" objects
744 // keeps track of allocated database connections.  This allows the application to
745 // open more than one database connection through ODBC for multiple transaction support
746 // or for multiple database support.
747 struct wxDbList
748 {
749     wxDbList *PtrPrev;       // Pointer to previous item in the list
750     wxString  Dsn;           // Data Source Name
751     wxString  Uid;           // User ID
752     wxString  AuthStr;       // Authorization string (password)
753     wxString  ConnectionStr; // Connection string used instead of DSN
754     wxDb     *PtrDb;         // Pointer to the wxDb object
755     bool      Free;          // Is item free or in use?
756     wxDbList *PtrNext;       // Pointer to next item in the list
757 };
758 
759 
760 #ifdef __WXDEBUG__
761 #include "wx/object.h"
762 class wxTablesInUse : public wxObject
763 {
764     public:
765         const wxChar  *tableName;
766         ULONG          tableID;
767         class wxDb    *pDb;
768 };  // wxTablesInUse
769 #endif
770 
771 
772 // The following routines allow a user to get new database connections, free them
773 // for other code segments to use, or close all of them when the application has
774 // completed.
775 wxDb  WXDLLIMPEXP_ODBC *wxDbGetConnection(wxDbConnectInf *pDbConfig, bool FwdOnlyCursors=(bool)wxODBC_FWD_ONLY_CURSORS);
776 bool  WXDLLIMPEXP_ODBC  wxDbFreeConnection(wxDb *pDb);
777 void  WXDLLIMPEXP_ODBC  wxDbCloseConnections(void);
778 int   WXDLLIMPEXP_ODBC  wxDbConnectionsInUse(void);
779 
780 
781 // Writes a message to the wxLog window (stdout usually) when an internal error
782 // situation occurs.  This function only works in DEBUG builds
783 const wxChar WXDLLIMPEXP_ODBC *
784 wxDbLogExtendedErrorMsg(const wxChar *userText,
785                         wxDb *pDb,
786                         const wxChar *ErrFile,
787                         int ErrLine);
788 
789 
790 // This function sets the sql log state for all open wxDb objects
791 bool WXDLLIMPEXP_ODBC
792 wxDbSqlLog(wxDbSqlLogState state, const wxString &filename = SQL_LOG_FILENAME);
793 
794 
795 #if 0
796 // MSW/VC6 ONLY!!!  Experimental
797 int WXDLLEXPORT wxDbCreateDataSource(const wxString &driverName, const wxString &dsn, const wxString &description=wxEmptyString,
798                                      bool sysDSN=false, const wxString &defDir=wxEmptyString, wxWindow *parent=NULL);
799 #endif
800 
801 // This routine allows you to query a driver manager
802 // for a list of available datasources.  Call this routine
803 // the first time using SQL_FETCH_FIRST.  Continue to call it
804 // using SQL_FETCH_NEXT until you've exhausted the list.
805 bool WXDLLIMPEXP_ODBC
806 wxDbGetDataSource(HENV henv, wxChar *Dsn, SWORD DsnMaxLength, wxChar *DsDesc,
807                   SWORD DsDescMaxLength, UWORD direction = SQL_FETCH_NEXT);
808 
809 
810 // Change this to 0 to remove use of all deprecated functions
811 #if wxODBC_BACKWARD_COMPATABILITY
812 //#################################################################################
813 //############### DEPRECATED functions for backward compatibility #################
814 //#################################################################################
815 
816 // Backward compability structures/classes.  This will eventually go away
817 const int DB_PATH_MAX      = wxDB_PATH_MAX;
818 
819 typedef wxDb                 wxDB;
820 typedef wxDbTableInf         wxTableInf;
821 typedef wxDbColInf           wxColInf;
822 typedef wxDbColInf           CcolInf;
823 typedef wxDbColFor           wxColFor;
824 typedef wxDbSqlTypeInfo      SqlTypeInfo;
825 typedef wxDbSqlTypeInfo      wxSqlTypeInfo;
826 typedef enum wxDbSqlLogState sqlLog;
827 typedef enum wxDbSqlLogState wxSqlLogState;
828 typedef enum wxDBMS          dbms;
829 typedef enum wxDBMS          DBMS;
830 typedef wxODBC_ERRORS        ODBC_ERRORS;
831 typedef wxDbConnectInf       DbStuff;
832 typedef wxDbList             DbList;
833 #ifdef __WXDEBUG__
834 typedef wxTablesInUse        CstructTablesInUse;
835 #endif
836 
837 // Deprecated function names that are replaced by the function names listed above
838 wxDB  WXDLLIMPEXP_ODBC
839 *GetDbConnection(DbStuff *pDbStuff, bool FwdOnlyCursors=(bool)wxODBC_FWD_ONLY_CURSORS);
840 bool  WXDLLIMPEXP_ODBC  FreeDbConnection(wxDB *pDb);
841 void  WXDLLIMPEXP_ODBC  CloseDbConnections(void);
842 int   WXDLLIMPEXP_ODBC  NumberDbConnectionsInUse(void);
843 
844 bool SqlLog(sqlLog state, const wxChar *filename = SQL_LOG_FILENAME);
845 
846 bool WXDLLIMPEXP_ODBC
847 GetDataSource(HENV henv, char *Dsn, SWORD DsnMaxLength, char *DsDesc, SWORD DsDescMaxLength,
848               UWORD direction = SQL_FETCH_NEXT);
849 
850 #endif  // Deprecated structures/classes/functions
851 
852 #endif // _WX_DB_H_
853 
854