X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9556da13bab524ea9404eb0992ba14cbb08b0588..56b9925b116dfa58028fccb2556852f2da2ab9ac:/src/common/db.cpp diff --git a/src/common/db.cpp b/src/common/db.cpp index 93d1c6a74c..49078ccb84 100644 --- a/src/common/db.cpp +++ b/src/common/db.cpp @@ -34,53 +34,29 @@ // SYNOPSIS START // SYNOPSIS STOP */ +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) + #pragma implementation "db.h" +#endif #include "wx/wxprec.h" - -// Use this line for wxWindows v1.x -//#include "wx_ver.h" -// Use this line for wxWindows v2.x -#include "wx/version.h" - -#if wxMAJOR_VERSION == 2 - #ifdef __GNUG__ - #pragma implementation "db.h" - #endif +#ifdef __BORLANDC__ + #pragma hdrstop #endif #ifdef DBDEBUG_CONSOLE #include "wx/ioswrap.h" #endif -#ifdef __BORLANDC__ - #pragma hdrstop -#endif //__BORLANDC__ - -#if wxMAJOR_VERSION == 2 - #ifndef WX_PRECOMP - #include "wx/string.h" - #include "wx/object.h" - #include "wx/list.h" - #include "wx/utils.h" - #include "wx/msgdlg.h" - #include "wx/log.h" - #endif - #include "wx/filefn.h" - #include "wx/wxchar.h" -#endif - - -#if wxMAJOR_VERSION == 1 -# if defined(wx_msw) || defined(wx_x) -# ifdef WX_PRECOMP -# include "wx_prec.h" -# else -# include "wx.h" -# endif -# endif -# define wxUSE_ODBC 1 +#ifndef WX_PRECOMP + #include "wx/string.h" + #include "wx/object.h" + #include "wx/list.h" + #include "wx/utils.h" + #include "wx/log.h" #endif +#include "wx/filefn.h" +#include "wx/wxchar.h" #if wxUSE_ODBC @@ -90,14 +66,13 @@ #include #include -#if wxMAJOR_VERSION == 1 - #include "db.h" -#elif wxMAJOR_VERSION == 2 - #include "wx/db.h" -#endif +#include "wx/db.h" -WXDLLEXPORT_DATA(wxDbList*) PtrBegDbList = 0; +// DLL options compatibility check: +#include "wx/app.h" +WX_CHECK_BUILD_OPTIONS("wxODBC") +WXDLLIMPEXP_DATA_ODBC(wxDbList*) PtrBegDbList = 0; wxChar const *SQL_LOG_FILENAME = wxT("sqllog.txt"); wxChar const *SQL_CATALOG_FILENAME = wxT("catalog.txt"); @@ -121,6 +96,7 @@ static wxString SQLLOGfn = SQL_LOG_FILENAME; // connection wxChar DBerrorList[DB_MAX_ERROR_HISTORY][DB_MAX_ERROR_MSG_LEN]; + // This type defines the return row-struct form // SQLTablePrivileges, and is used by wxDB::TablePrivileges. typedef struct @@ -138,30 +114,34 @@ typedef struct /********** wxDbConnectInf Constructor - form 1 **********/ wxDbConnectInf::wxDbConnectInf() { + Henv = 0; + freeHenvOnDestroy = FALSE; + Initialize(); } // Constructor /********** wxDbConnectInf Constructor - form 2 **********/ -wxDbConnectInf::wxDbConnectInf(HENV Henv, const wxString &Dsn, const wxString &UserID, - const wxString &Password, const wxString &DefaultDir, - const wxString &FileType, const wxString &Description) +wxDbConnectInf::wxDbConnectInf(HENV henv, const wxString &dsn, const wxString &userID, + const wxString &password, const wxString &defaultDir, + const wxString &fileType, const wxString &description) { - wxASSERT(Dsn.Length()); + Henv = 0; + freeHenvOnDestroy = FALSE; Initialize(); - if (Henv) - SetHenv(Henv); + if (henv) + SetHenv(henv); else AllocHenv(); - SetDsn(Dsn); - SetUserID(UserID); - SetPassword(Password); - SetDescription(Description); - SetFileType(FileType); - SetDefaultDir(DefaultDir); + SetDsn(dsn); + SetUserID(userID); + SetPassword(password); + SetDescription(description); + SetFileType(fileType); + SetDefaultDir(defaultDir); } // wxDbConnectInf Constructor @@ -180,6 +160,9 @@ bool wxDbConnectInf::Initialize() { freeHenvOnDestroy = FALSE; + if (freeHenvOnDestroy && Henv) + FreeHenv(); + Henv = 0; Dsn[0] = 0; Uid[0] = 0; @@ -243,7 +226,7 @@ void wxDbConnectInf::SetUserID(const wxString &uid) void wxDbConnectInf::SetPassword(const wxString &password) { wxASSERT(password.Length() < sizeof(AuthStr)); - + wxStrcpy(AuthStr,password); } // wxDbConnectInf::SetPassword() @@ -313,6 +296,8 @@ int wxDbColFor::Format(int Nation, int dbDataType, SWORD sqlDataType, i_dbDataType = DB_DATA_TYPE_VARCHAR; if (i_sqlDataType == SQL_REAL) i_dbDataType = DB_DATA_TYPE_FLOAT; + if (i_sqlDataType == SQL_C_BINARY) + i_dbDataType = DB_DATA_TYPE_BLOB; } if ((i_dbDataType == DB_DATA_TYPE_INTEGER) && (i_sqlDataType == SQL_C_DOUBLE)) @@ -357,6 +342,9 @@ int wxDbColFor::Format(int Nation, int dbDataType, SWORD sqlDataType, s_Field = wxT("%02d/%02d/%04d %02d:%02d:%02d.%03d"); } break; + case DB_DATA_TYPE_BLOB: + s_Field.Printf(wxT("Unable to format(%d)-SQL(%d)"),dbDataType,sqlDataType); // + break; default: s_Field.Printf(wxT("Unknown Format(%d)-SQL(%d)"),dbDataType,sqlDataType); // break; @@ -368,6 +356,21 @@ int wxDbColFor::Format(int Nation, int dbDataType, SWORD sqlDataType, /********** wxDbColInf Constructor **********/ wxDbColInf::wxDbColInf() +{ + Initialize(); +} // wxDbColInf::wxDbColInf() + + +/********** wxDbColInf Destructor ********/ +wxDbColInf::~wxDbColInf() +{ + if (pColFor) + delete pColFor; + pColFor = NULL; +} // wxDbColInf::~wxDbColInf() + + +bool wxDbColInf::Initialize() { catalog[0] = 0; schema[0] = 0; @@ -387,26 +390,15 @@ wxDbColInf::wxDbColInf() FkCol = 0; FkTableName[0] = 0; pColFor = NULL; -} // wxDbColInf::wxDbColInf() - -/********** wxDbColInf Destructor ********/ -wxDbColInf::~wxDbColInf() -{ - if (pColFor) - delete pColFor; - pColFor = NULL; -} // wxDbColInf::~wxDbColInf() + return TRUE; +} // wxDbColInf::Initialize() /********** wxDbTableInf Constructor ********/ wxDbTableInf::wxDbTableInf() { - tableName[0] = 0; - tableType[0] = 0; - tableRemarks[0] = 0; - numCols = 0; - pColInf = NULL; + Initialize(); } // wxDbTableInf::wxDbTableInf() @@ -419,6 +411,18 @@ wxDbTableInf::~wxDbTableInf() } // wxDbTableInf::~wxDbTableInf() +bool wxDbTableInf::Initialize() +{ + tableName[0] = 0; + tableType[0] = 0; + tableRemarks[0] = 0; + numCols = 0; + pColInf = NULL; + + return TRUE; +} // wxDbTableInf::Initialize() + + /********** wxDbInf Constructor *************/ wxDbInf::wxDbInf() { @@ -436,27 +440,44 @@ wxDbInf::~wxDbInf() /********** wxDbInf::Initialize() *************/ -void wxDbInf::Initialize() +bool wxDbInf::Initialize() { catalog[0] = 0; schema[0] = 0; numTables = 0; pTableInf = NULL; + + return TRUE; } // wxDbInf::Initialize() -/********** wxDb Constructors **********/ +/********** wxDb Constructor **********/ wxDb::wxDb(const HENV &aHenv, bool FwdOnlyCursors) { // Copy the HENV into the db class henv = aHenv; fwdOnlyCursors = FwdOnlyCursors; - Initialize(); + + initialize(); } // wxDb::wxDb() -/********** wxDb::Initialize() **********/ -void wxDb::Initialize() +/********** wxDb Destructor **********/ +wxDb::~wxDb() +{ + wxASSERT_MSG(!IsCached(),wxT("Cached connections must not be manually deleted, use\nwxDbFreeConnection() or wxDbCloseConnections().")); + + if (IsOpen()) + { + Close(); + } +} // wxDb destructor + + + +/********** PRIVATE! wxDb::initialize PRIVATE! **********/ +/********** wxDb::initialize() **********/ +void wxDb::initialize() /* * Private member function that sets all wxDb member variables to * known values at creation of the wxDb @@ -469,11 +490,11 @@ void wxDb::Initialize() nTables = 0; dbmsType = dbmsUNIDENTIFIED; - wxStrcpy(sqlState,wxT("")); - wxStrcpy(errorMsg,wxT("")); + wxStrcpy(sqlState,wxEmptyString); + wxStrcpy(errorMsg,wxEmptyString); nativeError = cbErrorMsg = 0; for (i = 0; i < DB_MAX_ERROR_HISTORY; i++) - wxStrcpy(errorList[i], wxT("")); + wxStrcpy(errorList[i], wxEmptyString); // Init typeInf structures typeInfVarchar.TypeName.Empty(); @@ -500,6 +521,12 @@ void wxDb::Initialize() typeInfDate.CaseSensitive = 0; typeInfDate.MaximumScale = 0; + typeInfBlob.TypeName.Empty(); + typeInfBlob.FsqlType = 0; + typeInfBlob.Precision = 0; + typeInfBlob.CaseSensitive = 0; + typeInfBlob.MaximumScale = 0; + // Error reporting is turned OFF by default silent = TRUE; @@ -512,7 +539,8 @@ void wxDb::Initialize() // Mark database as not open as of yet dbIsOpen = FALSE; -} // wxDb::Initialize() + dbIsCached = FALSE; +} // wxDb::initialize() /********** PRIVATE! wxDb::convertUserID PRIVATE! **********/ @@ -534,7 +562,8 @@ const wxChar *wxDb::convertUserID(const wxChar *userID, wxString &UserID) UserID.Empty(); // dBase does not use user names, and some drivers fail if you try to pass one - if (Dbms() == dbmsDBASE) + if ( Dbms() == dbmsDBASE + || Dbms() == dbmsXBASE_SEQUITER ) UserID.Empty(); // Oracle user names may only be in uppercase, so force @@ -547,7 +576,7 @@ const wxChar *wxDb::convertUserID(const wxChar *userID, wxString &UserID) /********** wxDb::Open() **********/ -bool wxDb::Open(const wxString &Dsn, const wxString &Uid, const wxString &AuthStr) +bool wxDb::Open(const wxString &Dsn, const wxString &Uid, const wxString &AuthStr, bool failOnDataTypeUnsupported) { wxASSERT(Dsn.Length()); dsn = Dsn; @@ -571,29 +600,20 @@ bool wxDb::Open(const wxString &Dsn, const wxString &Uid, const wxString &AuthSt } // Connect to the data source - retcode = SQLConnect(hdbc, (UCHAR FAR *) dsn.c_str(), SQL_NTS, - (UCHAR FAR *) uid.c_str(), SQL_NTS, - (UCHAR FAR *) authStr.c_str(), SQL_NTS); + retcode = SQLConnect(hdbc, (SQLTCHAR FAR *) dsn.c_str(), SQL_NTS, + (SQLTCHAR FAR *) uid.c_str(), SQL_NTS, + (SQLTCHAR FAR *) authStr.c_str(), SQL_NTS); -/* - if (retcode == SQL_SUCCESS_WITH_INFO) - DispAllErrors(henv, hdbc); - else if (retcode != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); - - if (retcode == SQL_ERROR) - return(DispAllErrors(henv, hdbc)); -*/ - if ((retcode != SQL_SUCCESS) && + if ((retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO)) - return(DispAllErrors(henv, hdbc)); + return(DispAllErrors(henv, hdbc)); /* If using Intersolv branded ODBC drivers, this is the place where you would substitute your branded driver license information - SQLSetConnectOption(hdbc, 1041, (UDWORD) wxT("")); - SQLSetConnectOption(hdbc, 1042, (UDWORD) wxT("")); + SQLSetConnectOption(hdbc, 1041, (UDWORD) wxEmptyString); + SQLSetConnectOption(hdbc, 1042, (UDWORD) wxEmptyString); */ // Mark database as open @@ -608,13 +628,13 @@ bool wxDb::Open(const wxString &Dsn, const wxString &Uid, const wxString &AuthSt return(FALSE); // Query the data source for inf. about itself - if (!getDbInfo()) + if (!getDbInfo(failOnDataTypeUnsupported)) return(FALSE); // Query the data source regarding data type information // - // The way I determined which SQL data types to use was by calling SQLGetInfo + // The way it was determined which SQL data types to use was by calling SQLGetInfo // for all of the possible SQL data types to see which ones were supported. If // a type is not supported, the SQLFetch() that's called from getDataTypeInfo() // fails with SQL_NO_DATA_FOUND. This is ugly because I'm sure the three SQL data @@ -663,12 +683,14 @@ bool wxDb::Open(const wxString &Dsn, const wxString &Uid, const wxString &AuthSt // Float if (!getDataTypeInfo(SQL_DOUBLE,typeInfFloat)) - if (!getDataTypeInfo(SQL_REAL,typeInfFloat)) if (!getDataTypeInfo(SQL_FLOAT,typeInfFloat)) if (!getDataTypeInfo(SQL_DECIMAL,typeInfFloat)) if (!getDataTypeInfo(SQL_NUMERIC,typeInfFloat)) - return(FALSE); + { + if (failOnDataTypeUnsupported) + return(FALSE); + } else typeInfFloat.FsqlType = SQL_NUMERIC; else @@ -686,7 +708,10 @@ bool wxDb::Open(const wxString &Dsn, const wxString &Uid, const wxString &AuthSt // If SQL_INTEGER is not supported, use the floating point // data type to store integers as well as floats if (!getDataTypeInfo(typeInfFloat.FsqlType, typeInfInteger)) - return(FALSE); + { + if (failOnDataTypeUnsupported) + return(FALSE); + } else typeInfInteger.FsqlType = typeInfFloat.FsqlType; } @@ -694,26 +719,50 @@ bool wxDb::Open(const wxString &Dsn, const wxString &Uid, const wxString &AuthSt typeInfInteger.FsqlType = SQL_INTEGER; // Date/Time - if (Dbms() != dbmsDBASE) + if (!getDataTypeInfo(SQL_TIMESTAMP,typeInfDate)) { - if (! getDataTypeInfo(SQL_TIMESTAMP,typeInfDate)) - return(FALSE); + if (!getDataTypeInfo(SQL_DATE,typeInfDate)) + { +#ifdef SQL_DATETIME + if (getDataTypeInfo(SQL_DATETIME,typeInfDate)) + { + typeInfDate.FsqlType = SQL_TIME; + } + else +#endif // SQL_DATETIME defined + { + if (failOnDataTypeUnsupported) + return(FALSE); + } + } else - typeInfDate.FsqlType = SQL_TIMESTAMP; + typeInfDate.FsqlType = SQL_DATE; } else + typeInfDate.FsqlType = SQL_TIMESTAMP; + + + if (!getDataTypeInfo(SQL_LONGVARBINARY, typeInfBlob)) { - if (!getDataTypeInfo(SQL_DATE,typeInfDate)) - return(FALSE); + if (!getDataTypeInfo(SQL_VARBINARY,typeInfBlob)) + { + if (failOnDataTypeUnsupported) + return(FALSE); + } else - typeInfDate.FsqlType = SQL_DATE; + typeInfBlob.FsqlType = SQL_VARBINARY; } + else + typeInfBlob.FsqlType = SQL_LONGVARBINARY; + +//typeInfBlob.TypeName = "BLOB"; #ifdef DBDEBUG_CONSOLE cout << wxT("VARCHAR DATA TYPE: ") << typeInfVarchar.TypeName << endl; cout << wxT("INTEGER DATA TYPE: ") << typeInfInteger.TypeName << endl; cout << wxT("FLOAT DATA TYPE: ") << typeInfFloat.TypeName << endl; cout << wxT("DATE DATA TYPE: ") << typeInfDate.TypeName << endl; + cout << wxT("BLOB DATA TYPE: ") << typeInfBlob.TypeName << endl; cout << endl; #endif @@ -753,19 +802,19 @@ bool wxDb::Open(wxDb *copyDb) } // Connect to the data source - retcode = SQLConnect(hdbc, (UCHAR FAR *) dsn.c_str(), SQL_NTS, - (UCHAR FAR *) uid.c_str(), SQL_NTS, - (UCHAR FAR *) authStr.c_str(), SQL_NTS); + retcode = SQLConnect(hdbc, (SQLTCHAR FAR *) dsn.c_str(), SQL_NTS, + (SQLTCHAR FAR *) uid.c_str(), SQL_NTS, + (SQLTCHAR FAR *) authStr.c_str(), SQL_NTS); - if (retcode == SQL_ERROR) - return(DispAllErrors(henv, hdbc)); + if (retcode == SQL_ERROR) + return(DispAllErrors(henv, hdbc)); /* If using Intersolv branded ODBC drivers, this is the place where you would substitute your branded driver license information - SQLSetConnectOption(hdbc, 1041, (UDWORD) wxT("")); - SQLSetConnectOption(hdbc, 1042, (UDWORD) wxT("")); + SQLSetConnectOption(hdbc, 1041, (UDWORD) wxEmptyString); + SQLSetConnectOption(hdbc, 1042, (UDWORD) wxEmptyString); */ // Mark database as open @@ -841,11 +890,19 @@ bool wxDb::Open(wxDb *copyDb) typeInfDate.CaseSensitive = copyDb->typeInfDate.CaseSensitive; typeInfDate.MaximumScale = copyDb->typeInfDate.MaximumScale; + // Blob + typeInfBlob.FsqlType = copyDb->typeInfBlob.FsqlType; + typeInfBlob.TypeName = copyDb->typeInfBlob.TypeName; + typeInfBlob.Precision = copyDb->typeInfBlob.Precision; + typeInfBlob.CaseSensitive = copyDb->typeInfBlob.CaseSensitive; + typeInfBlob.MaximumScale = copyDb->typeInfBlob.MaximumScale; + #ifdef DBDEBUG_CONSOLE cout << wxT("VARCHAR DATA TYPE: ") << typeInfVarchar.TypeName << endl; cout << wxT("INTEGER DATA TYPE: ") << typeInfInteger.TypeName << endl; cout << wxT("FLOAT DATA TYPE: ") << typeInfFloat.TypeName << endl; cout << wxT("DATE DATA TYPE: ") << typeInfDate.TypeName << endl; + cout << wxT("BLOB DATA TYPE: ") << typeInfBlob.TypeName << endl; cout << endl; #endif @@ -869,7 +926,7 @@ bool wxDb::setConnectionOptions(void) SQLSetConnectOption(hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF); SQLSetConnectOption(hdbc, SQL_OPT_TRACE, SQL_OPT_TRACE_OFF); -// SQLSetConnectOption(hdbc, SQL_TXN_ISOLATION, SQL_TXN_READ_COMMITTED); // No dirty reads +// SQLSetConnectOption(hdbc, SQL_TXN_ISOLATION, SQL_TXN_READ_COMMITTED); // No dirty reads // By default, MS Sql Server closes cursors on commit and rollback. The following // call to SQLSetConnectOption() is needed to force SQL Server to preserve cursors @@ -923,19 +980,31 @@ bool wxDb::setConnectionOptions(void) /********** wxDb::getDbInfo() **********/ -bool wxDb::getDbInfo(void) +bool wxDb::getDbInfo(bool failOnDataTypeUnsupported) { SWORD cb; RETCODE retcode; if (SQLGetInfo(hdbc, SQL_SERVER_NAME, (UCHAR*) dbInf.serverName, 80, &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_DATABASE_NAME, (UCHAR*) dbInf.databaseName, 128, &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_DBMS_NAME, (UCHAR*) dbInf.dbmsName, 40, &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } // 16-Mar-1999 // After upgrading to MSVC6, the original 20 char buffer below was insufficient, @@ -943,93 +1012,219 @@ bool wxDb::getDbInfo(void) retcode = SQLGetInfo(hdbc, SQL_DBMS_VER, (UCHAR*) dbInf.dbmsVer, 64, &cb); if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_ACTIVE_CONNECTIONS, (UCHAR*) &dbInf.maxConnections, sizeof(dbInf.maxConnections), &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_ACTIVE_STATEMENTS, (UCHAR*) &dbInf.maxStmts, sizeof(dbInf.maxStmts), &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_DRIVER_NAME, (UCHAR*) dbInf.driverName, 40, &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_DRIVER_ODBC_VER, (UCHAR*) dbInf.odbcVer, 60, &cb) == SQL_ERROR) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } retcode = SQLGetInfo(hdbc, SQL_ODBC_VER, (UCHAR*) dbInf.drvMgrOdbcVer, 60, &cb); if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_DRIVER_VER, (UCHAR*) dbInf.driverVer, 60, &cb) == SQL_ERROR) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_ODBC_API_CONFORMANCE, (UCHAR*) &dbInf.apiConfLvl, sizeof(dbInf.apiConfLvl), &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_ODBC_SAG_CLI_CONFORMANCE, (UCHAR*) &dbInf.cliConfLvl, sizeof(dbInf.cliConfLvl), &cb) != SQL_SUCCESS) -// return(DispAllErrors(henv, hdbc)); { // Not all drivers support this call - Nick Gorham(unixODBC) dbInf.cliConfLvl = 0; + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; } if (SQLGetInfo(hdbc, SQL_ODBC_SQL_CONFORMANCE, (UCHAR*) &dbInf.sqlConfLvl, sizeof(dbInf.sqlConfLvl), &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_OUTER_JOINS, (UCHAR*) dbInf.outerJoins, 2, &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + // TODO: BugTracker# 785080 : fails with mysql 4 on linux - edr + // TODO: dbInf.outerJoins[0]='N'; + // TODO: dbInf.outerJoins[1]='\x0'; + + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_PROCEDURES, (UCHAR*) dbInf.procedureSupport, 2, &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + // TODO: BugTracker# 785080 : fails with mysql 4 on linux - edr + // TODO: dbInf.procedureSupport[0]='N'; + // TODO: dbInf.procedureSupport[1]='\x0'; + + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_ACCESSIBLE_TABLES, (UCHAR*) dbInf.accessibleTables, 2, &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + // TODO: BugTracker# 785080 : fails with mysql 4 on linux - edr + // TODO: dbInf.accessibleTables[0]='N'; + // TODO: dbInf.accessibleTables[1]='\x0'; + + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_CURSOR_COMMIT_BEHAVIOR, (UCHAR*) &dbInf.cursorCommitBehavior, sizeof(dbInf.cursorCommitBehavior), &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_CURSOR_ROLLBACK_BEHAVIOR, (UCHAR*) &dbInf.cursorRollbackBehavior, sizeof(dbInf.cursorRollbackBehavior), &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_NON_NULLABLE_COLUMNS, (UCHAR*) &dbInf.supportNotNullClause, sizeof(dbInf.supportNotNullClause), &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_ODBC_SQL_OPT_IEF, (UCHAR*) dbInf.supportIEF, 2, &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + // TODO: BugTracker# 785080 : fails with mysql 4 on linux - edr + // TODO: dbInf.supportIEF[0]='N'; + // TODO: dbInf.supportIEF[1]='\x0'; + + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_DEFAULT_TXN_ISOLATION, (UCHAR*) &dbInf.txnIsolation, sizeof(dbInf.txnIsolation), &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_TXN_ISOLATION_OPTION, (UCHAR*) &dbInf.txnIsolationOptions, sizeof(dbInf.txnIsolationOptions), &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_FETCH_DIRECTION, (UCHAR*) &dbInf.fetchDirections, sizeof(dbInf.fetchDirections), &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_LOCK_TYPES, (UCHAR*) &dbInf.lockTypes, sizeof(dbInf.lockTypes), &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_POS_OPERATIONS, (UCHAR*) &dbInf.posOperations, sizeof(dbInf.posOperations), &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_POSITIONED_STATEMENTS, (UCHAR*) &dbInf.posStmts, sizeof(dbInf.posStmts), &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_SCROLL_CONCURRENCY, (UCHAR*) &dbInf.scrollConcurrency, sizeof(dbInf.scrollConcurrency), &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_SCROLL_OPTIONS, (UCHAR*) &dbInf.scrollOptions, sizeof(dbInf.scrollOptions), &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_STATIC_SENSITIVITY, (UCHAR*) &dbInf.staticSensitivity, sizeof(dbInf.staticSensitivity), &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_TXN_CAPABLE, (UCHAR*) &dbInf.txnCapable, sizeof(dbInf.txnCapable), &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } if (SQLGetInfo(hdbc, SQL_LOGIN_TIMEOUT, (UCHAR*) &dbInf.loginTimeout, sizeof(dbInf.loginTimeout), &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return FALSE; + } #ifdef DBDEBUG_CONSOLE cout << wxT("***** DATA SOURCE INFORMATION *****") << endl; @@ -1247,8 +1442,10 @@ bool wxDb::getDataTypeInfo(SWORD fSqlType, wxDbSqlTypeInfo &structSQLTypeInfo) // Get information about the data type specified if (SQLGetTypeInfo(hstmt, fSqlType) != SQL_SUCCESS) return(DispAllErrors(henv, hdbc, hstmt)); + // Fetch the record - if ((retcode = SQLFetch(hstmt)) != SQL_SUCCESS) + retcode = SQLFetch(hstmt); + if (retcode != SQL_SUCCESS) { #ifdef DBDEBUG_CONSOLE if (retcode == SQL_NO_DATA_FOUND) @@ -1260,6 +1457,7 @@ bool wxDb::getDataTypeInfo(SWORD fSqlType, wxDbSqlTypeInfo &structSQLTypeInfo) } wxChar typeName[DB_TYPE_NAME_LEN+1]; + // Obtain columns from the record if (SQLGetData(hstmt, 1, SQL_C_CHAR, (UCHAR*) typeName, DB_TYPE_NAME_LEN, &cbRet) != SQL_SUCCESS) return(DispAllErrors(henv, hdbc, hstmt)); @@ -1348,18 +1546,18 @@ void wxDb::Close(void) #ifdef __WXDEBUG__ wxTablesInUse *tiu; wxNode *pNode; - pNode = TablesInUse.First(); + pNode = TablesInUse.GetFirst(); wxString s,s2; while (pNode) { - tiu = (wxTablesInUse *)pNode->Data(); + tiu = (wxTablesInUse *)pNode->GetData(); if (tiu->pDb == this) { s.Printf(wxT("(%-20s) tableID:[%6lu] pDb:[%p]"), tiu->tableName,tiu->tableID,tiu->pDb); s2.Printf(wxT("Orphaned found using pDb:[%p]"),this); - wxLogDebug (s,s2); + wxLogDebug (s.c_str(),s2.c_str()); } - pNode = pNode->Next(); + pNode = pNode->GetNext(); } #endif @@ -1368,7 +1566,7 @@ void wxDb::Close(void) for (i = 0; i < DB_MAX_ERROR_HISTORY; i++) wxStrcpy(DBerrorList[i], errorList[i]); - dbmsType = dbmsUNIDENTIFIED; + dbmsType = dbmsUNIDENTIFIED; dbIsOpen = FALSE; } // wxDb::Close() @@ -1422,7 +1620,7 @@ bool wxDb::DispAllErrors(HENV aHenv, HDBC aHdbc, HSTMT aHstmt) { wxString odbcErrMsg; - while (SQLError(aHenv, aHdbc, aHstmt, (UCHAR FAR *) sqlState, &nativeError, (UCHAR FAR *) errorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &cbErrorMsg) == SQL_SUCCESS) + while (SQLError(aHenv, aHdbc, aHstmt, (SQLTCHAR FAR *) sqlState, &nativeError, (SQLTCHAR FAR *) errorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &cbErrorMsg) == SQL_SUCCESS) { odbcErrMsg.Printf(wxT("SQL State = %s\nNative Error Code = %li\nError Message = %s\n"), sqlState, nativeError, errorMsg); logError(odbcErrMsg, sqlState); @@ -1441,7 +1639,7 @@ bool wxDb::DispAllErrors(HENV aHenv, HDBC aHdbc, HSTMT aHstmt) } } - return(FALSE); // This function always returns false. + return(FALSE); // This function always returns FALSE. } // wxDb::DispAllErrors() @@ -1449,7 +1647,7 @@ bool wxDb::DispAllErrors(HENV aHenv, HDBC aHdbc, HSTMT aHstmt) /********** wxDb::GetNextError() **********/ bool wxDb::GetNextError(HENV aHenv, HDBC aHdbc, HSTMT aHstmt) { - if (SQLError(aHenv, aHdbc, aHstmt, (UCHAR FAR *) sqlState, &nativeError, (UCHAR FAR *) errorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &cbErrorMsg) == SQL_SUCCESS) + if (SQLError(aHenv, aHdbc, aHstmt, (SQLTCHAR FAR *) sqlState, &nativeError, (SQLTCHAR FAR *) errorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &cbErrorMsg) == SQL_SUCCESS) return(TRUE); else return(FALSE); @@ -1736,7 +1934,7 @@ bool wxDb::Grant(int privileges, const wxString &tableName, const wxString &user } sqlStmt += wxT(" ON "); - sqlStmt += tableName; + sqlStmt += SQLTableName(tableName); sqlStmt += wxT(" TO "); sqlStmt += userList; @@ -1805,7 +2003,7 @@ bool wxDb::DropView(const wxString &viewName) cout << endl << sqlStmt.c_str() << endl; #endif - if (SQLExecDirect(hstmt, (UCHAR FAR *) sqlStmt.c_str(), SQL_NTS) != SQL_SUCCESS) + if (SQLExecDirect(hstmt, (SQLTCHAR FAR *) sqlStmt.c_str(), SQL_NTS) != SQL_SUCCESS) { // Check for "Base table not found" error and ignore GetNextError(henv, hdbc, hstmt); @@ -1823,7 +2021,7 @@ bool wxDb::DropView(const wxString &viewName) } // Commit the transaction - if (! CommitTrans()) + if (!CommitTrans()) return(FALSE); return TRUE; @@ -1834,9 +2032,16 @@ bool wxDb::DropView(const wxString &viewName) /********** wxDb::ExecSql() **********/ bool wxDb::ExecSql(const wxString &pSqlStmt) { + RETCODE retcode; + SQLFreeStmt(hstmt, SQL_CLOSE); - if (SQLExecDirect(hstmt, (UCHAR FAR *) pSqlStmt.c_str(), SQL_NTS) == SQL_SUCCESS) + + retcode = SQLExecDirect(hstmt, (SQLTCHAR FAR *) pSqlStmt.c_str(), SQL_NTS); + if (retcode == SQL_SUCCESS || + (Dbms() == dbmsDB2 && (retcode == SQL_SUCCESS_WITH_INFO || retcode == SQL_NO_DATA_FOUND))) + { return(TRUE); + } else { DispAllErrors(henv, hdbc, hstmt); @@ -1878,7 +2083,7 @@ bool wxDb::GetData(UWORD colNo, SWORD cType, PTR pData, SDWORD maxLen, SDWORD FA /********** wxDb::GetKeyFields() **********/ -int wxDb::GetKeyFields(const wxString &tableName, wxDbColInf* colInf, int noCols) +int wxDb::GetKeyFields(const wxString &tableName, wxDbColInf* colInf, UWORD noCols) { wxChar szPkTable[DB_MAX_TABLE_NAME_LEN+1]; /* Primary key table name */ wxChar szFkTable[DB_MAX_TABLE_NAME_LEN+1]; /* Foreign key table name */ @@ -1888,7 +2093,7 @@ int wxDb::GetKeyFields(const wxString &tableName, wxDbColInf* colInf, int noCols wxChar szFkCol[DB_MAX_COLUMN_NAME_LEN+1]; /* Foreign key column */ SQLRETURN retcode; SDWORD cb; - int i; + SWORD i; wxString tempStr; /* * ----------------------------------------------------------------------- @@ -1909,7 +2114,7 @@ int wxDb::GetKeyFields(const wxString &tableName, wxDbColInf* colInf, int noCols retcode = SQLPrimaryKeys(hstmt, NULL, 0, /* Catalog name */ NULL, 0, /* Schema name */ - (UCHAR FAR *) tableName.c_str(), SQL_NTS); /* Table name */ + (SQLTCHAR FAR *) tableName.c_str(), SQL_NTS); /* Table name */ /*---------------------------------------------------------------------*/ /* Fetch and display the result set. This will be a list of the */ @@ -1936,7 +2141,7 @@ int wxDb::GetKeyFields(const wxString &tableName, wxDbColInf* colInf, int noCols retcode = SQLForeignKeys(hstmt, NULL, 0, /* Primary catalog */ NULL, 0, /* Primary schema */ - (UCHAR FAR *)tableName.c_str(), SQL_NTS,/* Primary table */ + (SQLTCHAR FAR *)tableName.c_str(), SQL_NTS,/* Primary table */ NULL, 0, /* Foreign catalog */ NULL, 0, /* Foreign schema */ NULL, 0); /* Foreign table */ @@ -1982,7 +2187,7 @@ int wxDb::GetKeyFields(const wxString &tableName, wxDbColInf* colInf, int noCols NULL, 0, /* Primary table */ NULL, 0, /* Foreign catalog */ NULL, 0, /* Foreign schema */ - (UCHAR *)tableName.c_str(), SQL_NTS);/* Foreign table */ + (SQLTCHAR *)tableName.c_str(), SQL_NTS);/* Foreign table */ /*---------------------------------------------------------------------*/ /* Fetch and display the result set. This will be all of the */ @@ -2046,8 +2251,8 @@ wxDbColInf *wxDb::GetColumns(wxChar *tableName[], const wxChar *userID) * to avoid undesired unbinding of columns. */ { - int noCols = 0; - int colNo = 0; + UWORD noCols = 0; + UWORD colNo = 0; wxDbColInf *colInf = 0; RETCODE retcode; @@ -2073,8 +2278,8 @@ wxDbColInf *wxDb::GetColumns(wxChar *tableName[], const wxChar *userID) if (!colInf) break; // Mark the end of the array - wxStrcpy(colInf[noCols].tableName,wxT("")); - wxStrcpy(colInf[noCols].colName,wxT("")); + wxStrcpy(colInf[noCols].tableName,wxEmptyString); + wxStrcpy(colInf[noCols].colName,wxEmptyString); colInf[noCols].sqlDataType = 0; } // Loop through each table name @@ -2099,8 +2304,8 @@ wxDbColInf *wxDb::GetColumns(wxChar *tableName[], const wxChar *userID) { retcode = SQLColumns(hstmt, NULL, 0, // All qualifiers - (UCHAR *) UserID.c_str(), SQL_NTS, // Owner - (UCHAR *) TableName.c_str(), SQL_NTS, + (SQLTCHAR *) UserID.c_str(), SQL_NTS, // Owner + (SQLTCHAR *) TableName.c_str(), SQL_NTS, NULL, 0); // All columns } else @@ -2108,7 +2313,7 @@ wxDbColInf *wxDb::GetColumns(wxChar *tableName[], const wxChar *userID) retcode = SQLColumns(hstmt, NULL, 0, // All qualifiers NULL, 0, // Owner - (UCHAR *) TableName.c_str(), SQL_NTS, + (SQLTCHAR *) TableName.c_str(), SQL_NTS, NULL, 0); // All columns } if (retcode != SQL_SUCCESS) @@ -2157,13 +2362,14 @@ wxDbColInf *wxDb::GetColumns(wxChar *tableName[], const wxChar *userID) #endif colInf[colNo].dbDataType = DB_DATA_TYPE_VARCHAR; } - else if (!wxStricmp(typeInfInteger.TypeName,colInf[colNo].typeName)) + else if (!wxStricmp(typeInfInteger.TypeName, colInf[colNo].typeName)) colInf[colNo].dbDataType = DB_DATA_TYPE_INTEGER; - else if (!wxStricmp(typeInfFloat.TypeName,colInf[colNo].typeName)) + else if (!wxStricmp(typeInfFloat.TypeName, colInf[colNo].typeName)) colInf[colNo].dbDataType = DB_DATA_TYPE_FLOAT; - else if (!wxStricmp(typeInfDate.TypeName,colInf[colNo].typeName)) + else if (!wxStricmp(typeInfDate.TypeName, colInf[colNo].typeName)) colInf[colNo].dbDataType = DB_DATA_TYPE_DATE; - + else if (!wxStricmp(typeInfBlob.TypeName, colInf[colNo].typeName)) + colInf[colNo].dbDataType = DB_DATA_TYPE_BLOB; colNo++; } } @@ -2187,7 +2393,7 @@ wxDbColInf *wxDb::GetColumns(wxChar *tableName[], const wxChar *userID) /********** wxDb::GetColumns() **********/ -wxDbColInf *wxDb::GetColumns(const wxString &tableName, int *numCols, const wxChar *userID) +wxDbColInf *wxDb::GetColumns(const wxString &tableName, UWORD *numCols, const wxChar *userID) // // Same as the above GetColumns() function except this one gets columns // only for a single table, and if 'numCols' is not NULL, the number of @@ -2203,8 +2409,8 @@ wxDbColInf *wxDb::GetColumns(const wxString &tableName, int *numCols, const wxCh // to avoid undesired unbinding of columns. { - int noCols = 0; - int colNo = 0; + UWORD noCols = 0; + UWORD colNo = 0; wxDbColInf *colInf = 0; RETCODE retcode; @@ -2230,8 +2436,8 @@ wxDbColInf *wxDb::GetColumns(const wxString &tableName, int *numCols, const wxCh if (!colInf) break; // Mark the end of the array - wxStrcpy(colInf[noCols].tableName, wxT("")); - wxStrcpy(colInf[noCols].colName, wxT("")); + wxStrcpy(colInf[noCols].tableName, wxEmptyString); + wxStrcpy(colInf[noCols].colName, wxEmptyString); colInf[noCols].sqlDataType = 0; } @@ -2253,8 +2459,8 @@ wxDbColInf *wxDb::GetColumns(const wxString &tableName, int *numCols, const wxCh { retcode = SQLColumns(hstmt, NULL, 0, // All qualifiers - (UCHAR *) UserID.c_str(), SQL_NTS, // Owner - (UCHAR *) TableName.c_str(), SQL_NTS, + (SQLTCHAR *) UserID.c_str(), SQL_NTS, // Owner + (SQLTCHAR *) TableName.c_str(), SQL_NTS, NULL, 0); // All columns } else @@ -2262,7 +2468,7 @@ wxDbColInf *wxDb::GetColumns(const wxString &tableName, int *numCols, const wxCh retcode = SQLColumns(hstmt, NULL, 0, // All qualifiers NULL, 0, // Owner - (UCHAR *) TableName.c_str(), SQL_NTS, + (SQLTCHAR *) TableName.c_str(), SQL_NTS, NULL, 0); // All columns } if (retcode != SQL_SUCCESS) @@ -2314,7 +2520,7 @@ wxDbColInf *wxDb::GetColumns(const wxString &tableName, int *numCols, const wxCh // Determine the wxDb data type that is used to represent the native data type of this data source colInf[colNo].dbDataType = 0; - if (!wxStricmp(typeInfVarchar.TypeName,colInf[colNo].typeName)) + if (!wxStricmp(typeInfVarchar.TypeName, colInf[colNo].typeName)) { #ifdef _IODBC_ // IODBC does not return a correct columnSize, so we set @@ -2328,12 +2534,14 @@ wxDbColInf *wxDb::GetColumns(const wxString &tableName, int *numCols, const wxCh colInf[colNo].dbDataType = DB_DATA_TYPE_VARCHAR; } - else if (!wxStricmp(typeInfInteger.TypeName,colInf[colNo].typeName)) + else if (!wxStricmp(typeInfInteger.TypeName, colInf[colNo].typeName)) colInf[colNo].dbDataType = DB_DATA_TYPE_INTEGER; - else if (!wxStricmp(typeInfFloat.TypeName,colInf[colNo].typeName)) + else if (!wxStricmp(typeInfFloat.TypeName, colInf[colNo].typeName)) colInf[colNo].dbDataType = DB_DATA_TYPE_FLOAT; - else if (!wxStricmp(typeInfDate.TypeName,colInf[colNo].typeName)) + else if (!wxStricmp(typeInfDate.TypeName, colInf[colNo].typeName)) colInf[colNo].dbDataType = DB_DATA_TYPE_DATE; + else if (!wxStricmp(typeInfBlob.TypeName, colInf[colNo].typeName)) + colInf[colNo].dbDataType = DB_DATA_TYPE_BLOB; colNo++; } @@ -2386,7 +2594,7 @@ wxDbColInf *wxDb::GetColumns(const wxString &tableName, int *numCols, const wxCh typedef struct { - int noCols; + UWORD noCols; wxDbColInf *colInf; } _TableColumns; @@ -2397,7 +2605,7 @@ wxDbColInf *wxDb::GetColumns(wxChar *tableName[], const wxChar *userID) // The last array element of the tableName[] argument must be zero (null). // This is how the end of the array is detected. - int noCols = 0; + UWORD noCols = 0; // How many tables ? int tbl; @@ -2420,8 +2628,8 @@ wxDbColInf *wxDb::GetColumns(wxChar *tableName[], const wxChar *userID) wxDbColInf *colInf = new wxDbColInf[noCols+1]; // Mark the end of the array - wxStrcpy(colInf[noCols].tableName, wxT("")); - wxStrcpy(colInf[noCols].colName, wxT("")); + wxStrcpy(colInf[noCols].tableName, wxEmptyString); + wxStrcpy(colInf[noCols].colName, wxEmptyString); colInf[noCols].sqlDataType = 0; // Merge ... @@ -2456,8 +2664,8 @@ wxDbColInf *wxDb::GetColumns(const wxString &tableName, int *numCols, const wxCh // by this function. This function should use its own wxDb instance // to avoid undesired unbinding of columns. { - SWORD noCols = 0; - int colNo = 0; + UWORD noCols = 0; + UWORD colNo = 0; wxDbColInf *colInf = 0; RETCODE retcode; @@ -2483,8 +2691,8 @@ wxDbColInf *wxDb::GetColumns(const wxString &tableName, int *numCols, const wxCh if (!colInf) break; // Mark the end of the array - wxStrcpy(colInf[noCols].tableName, wxT("")); - wxStrcpy(colInf[noCols].colName, wxT("")); + wxStrcpy(colInf[noCols].tableName, wxEmptyString); + wxStrcpy(colInf[noCols].colName, wxEmptyString); colInf[noCols].sqlDataType = 0; } @@ -2591,6 +2799,9 @@ wxDbColInf *wxDb::GetColumns(const wxString &tableName, int *numCols, const wxCh case SQL_DATE: colInf[colNo].dbDataType = DB_DATA_TYPE_DATE; break; + case SQL_BINARY: + colInf[colNo].dbDataType = DB_DATA_TYPE_BLOB; + break; #ifdef __WXDEBUG__ default: wxString errMsg; @@ -2626,7 +2837,7 @@ wxDbColInf *wxDb::GetColumns(const wxString &tableName, int *numCols, const wxCh // Build a generic SELECT statement which returns 0 rows wxString Stmt; - Stmt.Printf(wxT("select * from %s where 0=1"), tableName); + Stmt.Printf(wxT("select * from \"%s\" where 0=1"), tableName); // Execute query if (SQLExecDirect(hstmt, (UCHAR FAR *) Stmt.c_str(), SQL_NTS) != SQL_SUCCESS) @@ -2714,7 +2925,7 @@ int wxDb::GetColumnCount(const wxString &tableName, const wxChar *userID) * to avoid undesired unbinding of columns. */ { - int noCols = 0; + UWORD noCols = 0; RETCODE retcode; @@ -2741,8 +2952,8 @@ int wxDb::GetColumnCount(const wxString &tableName, const wxChar *userID) { retcode = SQLColumns(hstmt, NULL, 0, // All qualifiers - (UCHAR *) UserID.c_str(), SQL_NTS, // Owner - (UCHAR *) TableName.c_str(), SQL_NTS, + (SQLTCHAR *) UserID.c_str(), SQL_NTS, // Owner + (SQLTCHAR *) TableName.c_str(), SQL_NTS, NULL, 0); // All columns } else @@ -2750,7 +2961,7 @@ int wxDb::GetColumnCount(const wxString &tableName, const wxChar *userID) retcode = SQLColumns(hstmt, NULL, 0, // All qualifiers NULL, 0, // Owner - (UCHAR *) TableName.c_str(), SQL_NTS, + (SQLTCHAR *) TableName.c_str(), SQL_NTS, NULL, 0); // All columns } if (retcode != SQL_SUCCESS) @@ -2832,7 +3043,7 @@ wxDbInf *wxDb::GetCatalog(const wxChar *userID) { retcode = SQLTables(hstmt, NULL, 0, // All qualifiers - (UCHAR *) UserID.c_str(), SQL_NTS, // User specified + (SQLTCHAR *) UserID.c_str(), SQL_NTS, // User specified NULL, 0, // All tables NULL, 0); // All columns } @@ -2919,9 +3130,9 @@ bool wxDb::Catalog(const wxChar *userID, const wxString &fileName) wxChar colName[DB_MAX_COLUMN_NAME_LEN+1]; SWORD sqlDataType; wxChar typeName[30+1]; - SWORD precision, length; + SDWORD precision, length; - FILE *fp = fopen(fileName.c_str(),wxT("wt")); + FILE *fp = wxFopen(fileName.c_str(),wxT("wt")); if (fp == NULL) return(FALSE); @@ -2933,11 +3144,12 @@ bool wxDb::Catalog(const wxChar *userID, const wxString &fileName) if (!UserID.IsEmpty() && Dbms() != dbmsMY_SQL && Dbms() != dbmsACCESS && + Dbms() != dbmsINTERBASE && Dbms() != dbmsMS_SQL_SERVER) { retcode = SQLColumns(hstmt, NULL, 0, // All qualifiers - (UCHAR *) UserID.c_str(), SQL_NTS, // User specified + (SQLTCHAR *) UserID.c_str(), SQL_NTS, // User specified NULL, 0, // All tables NULL, 0); // All columns } @@ -2960,38 +3172,42 @@ bool wxDb::Catalog(const wxChar *userID, const wxString &fileName) tblNameSave.Empty(); int cnt = 0; - while ((retcode = SQLFetch(hstmt)) == SQL_SUCCESS) + while (TRUE) { + retcode = SQLFetch(hstmt); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) + break; + if (wxStrcmp(tblName, tblNameSave.c_str())) { if (cnt) - fputs(wxT("\n"), fp); - fputs(wxT("================================ "), fp); - fputs(wxT("================================ "), fp); - fputs(wxT("===================== "), fp); - fputs(wxT("========= "), fp); - fputs(wxT("=========\n"), fp); + wxFputs(wxT("\n"), fp); + wxFputs(wxT("================================ "), fp); + wxFputs(wxT("================================ "), fp); + wxFputs(wxT("===================== "), fp); + wxFputs(wxT("========= "), fp); + wxFputs(wxT("=========\n"), fp); outStr.Printf(wxT("%-32s %-32s %-21s %9s %9s\n"), wxT("TABLE NAME"), wxT("COLUMN NAME"), wxT("DATA TYPE"), wxT("PRECISION"), wxT("LENGTH")); - fputs(outStr.c_str(), fp); - fputs(wxT("================================ "), fp); - fputs(wxT("================================ "), fp); - fputs(wxT("===================== "), fp); - fputs(wxT("========= "), fp); - fputs(wxT("=========\n"), fp); + wxFputs(outStr.c_str(), fp); + wxFputs(wxT("================================ "), fp); + wxFputs(wxT("================================ "), fp); + wxFputs(wxT("===================== "), fp); + wxFputs(wxT("========= "), fp); + wxFputs(wxT("=========\n"), fp); tblNameSave = tblName; } - GetData(3,SQL_C_CHAR, (UCHAR *)tblName, DB_MAX_TABLE_NAME_LEN+1, &cb); - GetData(4,SQL_C_CHAR, (UCHAR *)colName, DB_MAX_COLUMN_NAME_LEN+1,&cb); - GetData(5,SQL_C_SSHORT,(UCHAR *)&sqlDataType,0, &cb); - GetData(6,SQL_C_CHAR, (UCHAR *)typeName, sizeof(typeName), &cb); - GetData(7,SQL_C_SSHORT,(UCHAR *)&precision, 0, &cb); - GetData(8,SQL_C_SSHORT,(UCHAR *)&length, 0, &cb); + GetData(3,SQL_C_CHAR, (UCHAR *) tblName, DB_MAX_TABLE_NAME_LEN+1, &cb); + GetData(4,SQL_C_CHAR, (UCHAR *) colName, DB_MAX_COLUMN_NAME_LEN+1,&cb); + GetData(5,SQL_C_SSHORT,(UCHAR *)&sqlDataType, 0, &cb); + GetData(6,SQL_C_CHAR, (UCHAR *) typeName, sizeof(typeName), &cb); + GetData(7,SQL_C_SLONG, (UCHAR *)&precision, 0, &cb); + GetData(8,SQL_C_SLONG, (UCHAR *)&length, 0, &cb); - outStr.Printf(wxT("%-32s %-32s (%04d)%-15s %9d %9d\n"), + outStr.Printf(wxT("%-32s %-32s (%04d)%-15s %9ld %9ld\n"), tblName, colName, sqlDataType, typeName, precision, length); - if (fputs(outStr.c_str(), fp) == EOF) + if (wxFputs(outStr.c_str(), fp) == EOF) { SQLFreeStmt(hstmt, SQL_CLOSE); fclose(fp); @@ -3013,7 +3229,7 @@ bool wxDb::Catalog(const wxChar *userID, const wxString &fileName) bool wxDb::TableExists(const wxString &tableName, const wxChar *userID, const wxString &tablePath) /* - * Table name can refer to a table, view, alias or synonym. Returns true + * Table name can refer to a table, view, alias or synonym. Returns TRUE * if the object exists in the database. This function does not indicate * whether or not the user has privleges to query or perform other functions * on the table. @@ -3059,12 +3275,15 @@ bool wxDb::TableExists(const wxString &tableName, const wxChar *userID, const wx if (!UserID.IsEmpty() && Dbms() != dbmsMY_SQL && Dbms() != dbmsACCESS && - Dbms() != dbmsMS_SQL_SERVER) + Dbms() != dbmsMS_SQL_SERVER && + Dbms() != dbmsDB2 && + Dbms() != dbmsINTERBASE && + Dbms() != dbmsPERVASIVE_SQL) { retcode = SQLTables(hstmt, NULL, 0, // All qualifiers - (UCHAR *) UserID.c_str(), SQL_NTS, // Only tables owned by this user - (UCHAR FAR *)TableName.c_str(), SQL_NTS, + (SQLTCHAR *) UserID.c_str(), SQL_NTS, // Only tables owned by this user + (SQLTCHAR FAR *)TableName.c_str(), SQL_NTS, NULL, 0); // All table types } else @@ -3072,7 +3291,7 @@ bool wxDb::TableExists(const wxString &tableName, const wxChar *userID, const wx retcode = SQLTables(hstmt, NULL, 0, // All qualifiers NULL, 0, // All owners - (UCHAR FAR *)TableName.c_str(), SQL_NTS, + (SQLTCHAR FAR *)TableName.c_str(), SQL_NTS, NULL, 0); // All table types } if (retcode != SQL_SUCCESS) @@ -3094,7 +3313,7 @@ bool wxDb::TableExists(const wxString &tableName, const wxChar *userID, const wx /********** wxDb::TablePrivileges() **********/ bool wxDb::TablePrivileges(const wxString &tableName, const wxString &priv, const wxChar *userID, - const wxChar *schema, const wxString &tablePath) + const wxChar *schema, const wxString &WXUNUSED(tablePath)) { wxASSERT(tableName.Length()); @@ -3108,8 +3327,9 @@ bool wxDb::TablePrivileges(const wxString &tableName, const wxString &priv, cons wxString TableName; - wxString UserID; + wxString UserID,Schema; convertUserID(userID,UserID); + convertUserID(schema,Schema); TableName = tableName; // Oracle and Interbase table names are uppercase only, so force @@ -3120,54 +3340,64 @@ bool wxDb::TablePrivileges(const wxString &tableName, const wxString &priv, cons SQLFreeStmt(hstmt, SQL_CLOSE); - if (!schema) + // Some databases cannot accept a user name when looking up table names, + // so we use the call below that leaves out the user name + if (!Schema.IsEmpty() && + Dbms() != dbmsMY_SQL && + Dbms() != dbmsACCESS && + Dbms() != dbmsMS_SQL_SERVER) { retcode = SQLTablePrivileges(hstmt, NULL, 0, // Catalog - NULL, 0, // Schema - (UCHAR FAR *)TableName.c_str(), SQL_NTS); + (SQLTCHAR FAR *)Schema.c_str(), SQL_NTS, // Schema + (SQLTCHAR FAR *)TableName.c_str(), SQL_NTS); } else { retcode = SQLTablePrivileges(hstmt, NULL, 0, // Catalog - (UCHAR FAR *)schema, SQL_NTS, // Schema - (UCHAR FAR *)TableName.c_str(), SQL_NTS); + NULL, 0, // Schema + (SQLTCHAR FAR *)TableName.c_str(), SQL_NTS); } #ifdef DBDEBUG_CONSOLE - fprintf(stderr ,wxT("SQLTablePrivileges() returned %i \n"),retcode); + wxFprintf(stderr ,wxT("SQLTablePrivileges() returned %i \n"),retcode); #endif if ((retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO)) return(DispAllErrors(henv, hdbc, hstmt)); + bool failed = FALSE; retcode = SQLFetch(hstmt); while (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) { if (SQLGetData(hstmt, 1, SQL_C_CHAR, (UCHAR*) result.tableQual, sizeof(result.tableQual), &cbRetVal) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc, hstmt)); + failed = TRUE; - if (SQLGetData(hstmt, 2, SQL_C_CHAR, (UCHAR*) result.tableOwner, sizeof(result.tableOwner), &cbRetVal) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc, hstmt)); + if (!failed && SQLGetData(hstmt, 2, SQL_C_CHAR, (UCHAR*) result.tableOwner, sizeof(result.tableOwner), &cbRetVal) != SQL_SUCCESS) + failed = TRUE; - if (SQLGetData(hstmt, 3, SQL_C_CHAR, (UCHAR*) result.tableName, sizeof(result.tableName), &cbRetVal) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc, hstmt)); + if (!failed && SQLGetData(hstmt, 3, SQL_C_CHAR, (UCHAR*) result.tableName, sizeof(result.tableName), &cbRetVal) != SQL_SUCCESS) + failed = TRUE; - if (SQLGetData(hstmt, 4, SQL_C_CHAR, (UCHAR*) result.grantor, sizeof(result.grantor), &cbRetVal) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc, hstmt)); + if (!failed && SQLGetData(hstmt, 4, SQL_C_CHAR, (UCHAR*) result.grantor, sizeof(result.grantor), &cbRetVal) != SQL_SUCCESS) + failed = TRUE; - if (SQLGetData(hstmt, 5, SQL_C_CHAR, (UCHAR*) result.grantee, sizeof(result.grantee), &cbRetVal) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc, hstmt)); + if (!failed && SQLGetData(hstmt, 5, SQL_C_CHAR, (UCHAR*) result.grantee, sizeof(result.grantee), &cbRetVal) != SQL_SUCCESS) + failed = TRUE; - if (SQLGetData(hstmt, 6, SQL_C_CHAR, (UCHAR*) result.privilege, sizeof(result.privilege), &cbRetVal) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc, hstmt)); + if (!failed && SQLGetData(hstmt, 6, SQL_C_CHAR, (UCHAR*) result.privilege, sizeof(result.privilege), &cbRetVal) != SQL_SUCCESS) + failed = TRUE; - if (SQLGetData(hstmt, 7, SQL_C_CHAR, (UCHAR*) result.grantable, sizeof(result.grantable), &cbRetVal) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc, hstmt)); + if (!failed && SQLGetData(hstmt, 7, SQL_C_CHAR, (UCHAR*) result.grantable, sizeof(result.grantable), &cbRetVal) != SQL_SUCCESS) + failed = TRUE; + if (failed) + { + return(DispAllErrors(henv, hdbc, hstmt)); + } #ifdef DBDEBUG_CONSOLE - fprintf(stderr,wxT("Scanning %s privilege on table %s.%s granted by %s to %s\n"), + wxFprintf(stderr,wxT("Scanning %s privilege on table %s.%s granted by %s to %s\n"), result.privilege,result.tableOwner,result.tableName, result.grantor, result.grantee); #endif @@ -3201,6 +3431,34 @@ bool wxDb::TablePrivileges(const wxString &tableName, const wxString &priv, cons } // wxDb::TablePrivileges +const wxString wxDb::SQLTableName(const wxChar *tableName) +{ + wxString TableName; + + if (Dbms() == dbmsACCESS) + TableName = _T("\""); + TableName += tableName; + if (Dbms() == dbmsACCESS) + TableName += _T("\""); + + return TableName; +} // wxDb::SQLTableName() + + +const wxString wxDb::SQLColumnName(const wxChar *colName) +{ + wxString ColName; + + if (Dbms() == dbmsACCESS) + ColName = _T("\""); + ColName += colName; + if (Dbms() == dbmsACCESS) + ColName += _T("\""); + + return ColName; +} // wxDb::SQLColumnName() + + /********** wxDb::SetSqlLogging() **********/ bool wxDb::SetSqlLogging(wxDbSqlLogState state, const wxString &filename, bool append) { @@ -3211,7 +3469,7 @@ bool wxDb::SetSqlLogging(wxDbSqlLogState state, const wxString &filename, bool a { if (fpSqlLog == 0) { - fpSqlLog = fopen(filename, (append ? wxT("at") : wxT("wt"))); + fpSqlLog = wxFopen(filename, (append ? wxT("at") : wxT("wt"))); if (fpSqlLog == NULL) return(FALSE); } @@ -3240,11 +3498,11 @@ bool wxDb::WriteSqlLog(const wxString &logMsg) if (fpSqlLog == 0 || sqlLogState == sqlLogOFF) return(FALSE); - if (fputs(wxT("\n"), fpSqlLog) == EOF) + if (wxFputs(wxT("\n"), fpSqlLog) == EOF) return(FALSE); - if (fputs(logMsg, fpSqlLog) == EOF) + if (wxFputs(logMsg, fpSqlLog) == EOF) return(FALSE); - if (fputs(wxT("\n"), fpSqlLog) == EOF) + if (wxFputs(wxT("\n"), fpSqlLog) == EOF) return(FALSE); return(TRUE); @@ -3303,7 +3561,16 @@ wxDBMS wxDb::Dbms(void) * * DB2 * - Primary keys must be declared as NOT NULL + * - Table and index names must not be longer than 13 characters in length (technically + * table names can be up to 18 characters, but the primary index is created using the + * base table name plus "_PIDX", so the limit if the table has a primary index is 13. + * + * PERVASIVE SQL * + * INTERBASE + * - Columns that are part of primary keys must be defined as being NOT NULL + * when they are created. Some code is added in ::CreateIndex to try to adjust the + * column definition if it is not defined correctly, but it is experimental */ { // Should only need to do this once for each new database connection @@ -3336,18 +3603,22 @@ wxDBMS wxDb::Dbms(void) { if (!wxStrncmp(dbInf.driverName, wxT("oplodbc"), 7) || !wxStrncmp(dbInf.driverName, wxT("OLOD"), 4)) - return ((wxDBMS)(dbmsMS_SQL_SERVER)); - else - return ((wxDBMS)(dbmsType = dbmsSYBASE_ASE)); + return ((wxDBMS)(dbmsMS_SQL_SERVER)); + else + return ((wxDBMS)(dbmsType = dbmsSYBASE_ASE)); } if (!wxStricmp(dbInf.dbmsName,wxT("Microsoft SQL Server"))) return((wxDBMS)(dbmsType = dbmsMS_SQL_SERVER)); - if (!wxStricmp(dbInf.dbmsName,wxT("MySQL"))) - return((wxDBMS)(dbmsType = dbmsMY_SQL)); - if (!wxStricmp(dbInf.dbmsName,wxT("PostgreSQL"))) // v6.5.0 + + baseName[10] = 0; + if (!wxStricmp(baseName,wxT("PostgreSQL"))) // v6.5.0 return((wxDBMS)(dbmsType = dbmsPOSTGRES)); + baseName[9] = 0; + if (!wxStricmp(baseName,wxT("Pervasive"))) + return((wxDBMS)(dbmsType = dbmsPERVASIVE_SQL)); + baseName[8] = 0; if (!wxStricmp(baseName,wxT("Informix"))) return((wxDBMS)(dbmsType = dbmsINFORMIX)); @@ -3355,16 +3626,18 @@ wxDBMS wxDb::Dbms(void) baseName[6] = 0; if (!wxStricmp(baseName,wxT("Oracle"))) return((wxDBMS)(dbmsType = dbmsORACLE)); - if (!wxStricmp(dbInf.dbmsName,wxT("ACCESS"))) + if (!wxStricmp(baseName,wxT("ACCESS"))) return((wxDBMS)(dbmsType = dbmsACCESS)); - if (!wxStricmp(dbInf.dbmsName,wxT("MySQL"))) - return((wxDBMS)(dbmsType = dbmsMY_SQL)); if (!wxStricmp(baseName,wxT("Sybase"))) return((wxDBMS)(dbmsType = dbmsSYBASE_ASE)); baseName[5] = 0; if (!wxStricmp(baseName,wxT("DBASE"))) return((wxDBMS)(dbmsType = dbmsDBASE)); + if (!wxStricmp(baseName,wxT("xBase"))) + return((wxDBMS)(dbmsType = dbmsXBASE_SEQUITER)); + if (!wxStricmp(baseName,wxT("MySQL"))) + return((wxDBMS)(dbmsType = dbmsMY_SQL)); baseName[3] = 0; if (!wxStricmp(baseName,wxT("DB2"))) @@ -3387,60 +3660,73 @@ bool wxDb::ModifyColumn(const wxString &tableName, const wxString &columnName, // Must specify a columnLength if modifying a VARCHAR type column if (dataType == DB_DATA_TYPE_VARCHAR && !columnLength) return FALSE; - + wxString dataTypeName; - wxString sqlStmt; + wxString sqlStmt; wxString alterSlashModify; - switch(dataType) - { - case DB_DATA_TYPE_VARCHAR : - dataTypeName = typeInfVarchar.TypeName; - break; - case DB_DATA_TYPE_INTEGER : - dataTypeName = typeInfInteger.TypeName; - break; - case DB_DATA_TYPE_FLOAT : - dataTypeName = typeInfFloat.TypeName; - break; - case DB_DATA_TYPE_DATE : - dataTypeName = typeInfDate.TypeName; - break; - default: - return FALSE; - } + switch(dataType) + { + case DB_DATA_TYPE_VARCHAR : + dataTypeName = typeInfVarchar.TypeName; + break; + case DB_DATA_TYPE_INTEGER : + dataTypeName = typeInfInteger.TypeName; + break; + case DB_DATA_TYPE_FLOAT : + dataTypeName = typeInfFloat.TypeName; + break; + case DB_DATA_TYPE_DATE : + dataTypeName = typeInfDate.TypeName; + break; + case DB_DATA_TYPE_BLOB : + dataTypeName = typeInfBlob.TypeName; + break; + default: + return FALSE; + } - // Set the modify or alter syntax depending on the type of database connected to - switch (Dbms()) - { - case dbmsORACLE : - alterSlashModify = "MODIFY"; - break; - case dbmsMS_SQL_SERVER : - alterSlashModify = "ALTER COLUMN"; - break; - case dbmsUNIDENTIFIED : + // Set the modify or alter syntax depending on the type of database connected to + switch (Dbms()) + { + case dbmsORACLE : + alterSlashModify = _T("MODIFY"); + break; + case dbmsMS_SQL_SERVER : + alterSlashModify = _T("ALTER COLUMN"); + break; + case dbmsUNIDENTIFIED : return FALSE; - case dbmsSYBASE_ASA : - case dbmsSYBASE_ASE : - case dbmsMY_SQL : - case dbmsPOSTGRES : - case dbmsACCESS : - case dbmsDBASE : - default : - alterSlashModify = "MODIFY"; - break; - } + case dbmsSYBASE_ASA : + case dbmsSYBASE_ASE : + case dbmsMY_SQL : + case dbmsPOSTGRES : + case dbmsACCESS : + case dbmsDBASE : + case dbmsXBASE_SEQUITER : + default : + alterSlashModify = _T("MODIFY"); + break; + } - // create the SQL statement - sqlStmt.Printf(wxT("ALTER TABLE %s %s %s %s"), tableName.c_str(), alterSlashModify.c_str(), - columnName.c_str(), dataTypeName.c_str()); + // create the SQL statement + if ( Dbms() == dbmsMY_SQL ) + { + sqlStmt.Printf(wxT("ALTER TABLE %s %s %s %s"), tableName.c_str(), alterSlashModify.c_str(), + columnName.c_str(), dataTypeName.c_str()); + } + else + { + sqlStmt.Printf(wxT("ALTER TABLE \"%s\" \"%s\" \"%s\" %s"), tableName.c_str(), alterSlashModify.c_str(), + columnName.c_str(), dataTypeName.c_str()); + } // For varchars only, append the size of the column - if (dataType == DB_DATA_TYPE_VARCHAR) + if (dataType == DB_DATA_TYPE_VARCHAR && + (Dbms() != dbmsMY_SQL || dataTypeName != _T("text"))) { wxString s; - s.Printf(wxT("(%d)"), columnLength); + s.Printf(wxT("(%lu)"), columnLength); sqlStmt += s; } @@ -3451,13 +3737,13 @@ bool wxDb::ModifyColumn(const wxString &tableName, const wxString &columnName, sqlStmt += optionalParam; } - return ExecSql(sqlStmt); + return ExecSql(sqlStmt); } // wxDb::ModifyColumn() /********** wxDbGetConnection() **********/ -wxDb WXDLLEXPORT *wxDbGetConnection(wxDbConnectInf *pDbConfig, bool FwdOnlyCursors) +wxDb WXDLLIMPEXP_ODBC *wxDbGetConnection(wxDbConnectInf *pDbConfig, bool FwdOnlyCursors) { wxDbList *pList; @@ -3509,7 +3795,7 @@ wxDb WXDLLEXPORT *wxDbGetConnection(wxDbConnectInf *pDbConfig, bool FwdOnlyCurso // Initialize new node in the linked list pList->PtrNext = 0; pList->Free = FALSE; - pList->Dsn = pDbConfig->GetDsn(); //glt - will this assignment work? + pList->Dsn = pDbConfig->GetDsn(); pList->Uid = pDbConfig->GetUserID(); pList->AuthStr = pDbConfig->GetPassword(); @@ -3525,6 +3811,7 @@ wxDb WXDLLEXPORT *wxDbGetConnection(wxDbConnectInf *pDbConfig, bool FwdOnlyCurso // Connect to the datasource if (opened) { + pList->PtrDb->setCached(TRUE); // Prevent a user from deleting a cached connection pList->PtrDb->SetSqlLogging(SQLLOGstate,SQLLOGfn,TRUE); return(pList->PtrDb); } @@ -3545,7 +3832,7 @@ wxDb WXDLLEXPORT *wxDbGetConnection(wxDbConnectInf *pDbConfig, bool FwdOnlyCurso /********** wxDbFreeConnection() **********/ -bool WXDLLEXPORT wxDbFreeConnection(wxDb *pDb) +bool WXDLLIMPEXP_ODBC wxDbFreeConnection(wxDb *pDb) { wxDbList *pList; @@ -3563,7 +3850,7 @@ bool WXDLLEXPORT wxDbFreeConnection(wxDb *pDb) /********** wxDbCloseConnections() **********/ -void WXDLLEXPORT wxDbCloseConnections(void) +void WXDLLIMPEXP_ODBC wxDbCloseConnections(void) { wxDbList *pList, *pNext; @@ -3573,6 +3860,7 @@ void WXDLLEXPORT wxDbCloseConnections(void) pNext = pList->PtrNext; // Save the pointer to next pList->PtrDb->CommitTrans(); // Commit any open transactions on wxDb object pList->PtrDb->Close(); // Close the wxDb object + pList->PtrDb->setCached(FALSE); // Allows deletion of the wxDb instance delete pList->PtrDb; // Deletes the wxDb object delete pList; // Deletes the linked list object } @@ -3584,7 +3872,7 @@ void WXDLLEXPORT wxDbCloseConnections(void) /********** wxDbConnectionsInUse() **********/ -int WXDLLEXPORT wxDbConnectionsInUse(void) +int WXDLLIMPEXP_ODBC wxDbConnectionsInUse(void) { wxDbList *pList; int cnt = 0; @@ -3601,6 +3889,54 @@ int WXDLLEXPORT wxDbConnectionsInUse(void) } // wxDbConnectionsInUse() + +/********** wxDbLogExtendedErrorMsg() **********/ +// DEBUG ONLY function +const wxChar* WXDLLIMPEXP_ODBC wxDbLogExtendedErrorMsg(const wxChar *userText, + wxDb *pDb, + const wxChar *ErrFile, + int ErrLine) +{ + static wxString msg; + msg = userText; + + wxString tStr; + + if (ErrFile || ErrLine) + { + msg += wxT("File: "); + msg += ErrFile; + msg += wxT(" Line: "); + tStr.Printf(wxT("%d"),ErrLine); + msg += tStr.c_str(); + msg += wxT("\n"); + } + + msg.Append (wxT("\nODBC errors:\n")); + msg += wxT("\n"); + + // Display errors for this connection + int i; + for (i = 0; i < DB_MAX_ERROR_HISTORY; i++) + { + if (pDb->errorList[i]) + { + msg.Append(pDb->errorList[i]); + if (wxStrcmp(pDb->errorList[i],wxT("")) != 0) + msg.Append(wxT("\n")); + // Clear the errmsg buffer so the next error will not + // end up showing the previous error that have occurred + wxStrcpy(pDb->errorList[i],wxT("")); + } + } + msg += wxT("\n"); + + wxLogDebug(msg.c_str()); + + return msg.c_str(); +} // wxDbLogExtendedErrorMsg() + + /********** wxDbSqlLog() **********/ bool wxDbSqlLog(wxDbSqlLogState state, const wxChar *filename) { @@ -3715,8 +4051,8 @@ bool wxDbGetDataSource(HENV henv, wxChar *Dsn, SWORD DsnMax, wxChar *DsDesc, { SWORD cb1,cb2; - if (SQLDataSources(henv, direction, (UCHAR FAR *) Dsn, DsnMax, &cb1, - (UCHAR FAR *) DsDesc, DsDescMax, &cb2) == SQL_SUCCESS) + if (SQLDataSources(henv, direction, (SQLTCHAR FAR *) Dsn, DsnMax, &cb1, + (SQLTCHAR FAR *) DsDesc, DsDescMax, &cb2) == SQL_SUCCESS) return(TRUE); else return(FALSE); @@ -3745,22 +4081,22 @@ bool GetDataSource(HENV henv, char *Dsn, SWORD DsnMax, char *DsDesc, SWORD DsDes return wxDbGetDataSource(henv, Dsn, DsnMax, DsDesc, DsDescMax, direction); } /***** DEPRECATED: use wxDbGetConnection() *****/ -wxDb WXDLLEXPORT *GetDbConnection(DbStuff *pDbStuff, bool FwdOnlyCursors) +wxDb WXDLLIMPEXP_ODBC *GetDbConnection(DbStuff *pDbStuff, bool FwdOnlyCursors) { return wxDbGetConnection((wxDbConnectInf *)pDbStuff, FwdOnlyCursors); } /***** DEPRECATED: use wxDbFreeConnection() *****/ -bool WXDLLEXPORT FreeDbConnection(wxDb *pDb) +bool WXDLLIMPEXP_ODBC FreeDbConnection(wxDb *pDb) { return wxDbFreeConnection(pDb); } /***** DEPRECATED: use wxDbCloseConnections() *****/ -void WXDLLEXPORT CloseDbConnections(void) +void WXDLLIMPEXP_ODBC CloseDbConnections(void) { wxDbCloseConnections(); } /***** DEPRECATED: use wxDbConnectionsInUse() *****/ -int WXDLLEXPORT NumberDbConnectionsInUse(void) +int WXDLLIMPEXP_ODBC NumberDbConnectionsInUse(void) { return wxDbConnectionsInUse(); }