X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/2c257434c3a44066bac6f25fb502d3e165232e43..169d1d643c0ee0c90fa8e393b5298606bbb68cfd:/src/common/db.cpp diff --git a/src/common/db.cpp b/src/common/db.cpp index a4717bd380..4affce0b64 100644 --- a/src/common/db.cpp +++ b/src/common/db.cpp @@ -18,23 +18,14 @@ // Created: 9.96 // RCS-ID: $Id$ // Copyright: (c) 1996 Remstar International, Inc. -// Licence: wxWindows licence, plus: -// Notice: This class library and its intellectual design are free of charge for use, -// modification, enhancement, debugging under the following conditions: -// 1) These classes may only be used as part of the implementation of a -// wxWindows-based application -// 2) All enhancements and bug fixes are to be submitted back to the wxWindows -// user groups free of all charges for use with the wxWindows library. -// 3) These classes may not be distributed as part of any other class library, -// DLL, text (written or electronic), other than a complete distribution of -// the wxWindows GUI development toolkit. +// Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// /* // SYNOPSIS START // SYNOPSIS STOP */ -#ifdef __GNUG__ +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "db.h" #endif @@ -53,7 +44,6 @@ #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" @@ -69,8 +59,11 @@ #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"); @@ -92,7 +85,7 @@ static wxString SQLLOGfn = SQL_LOG_FILENAME; // will overwrite the errors of the previously destroyed wxDb object in // this variable. NOTE: This occurs during a CLOSE, not a FREEing of the // connection -wxChar DBerrorList[DB_MAX_ERROR_HISTORY][DB_MAX_ERROR_MSG_LEN]; +wxChar DBerrorList[DB_MAX_ERROR_HISTORY][DB_MAX_ERROR_MSG_LEN+1]; // This type defines the return row-struct form @@ -165,10 +158,13 @@ bool wxDbConnectInf::Initialize() Dsn[0] = 0; Uid[0] = 0; AuthStr[0] = 0; + ConnectionStr[0] = 0; Description.Empty(); FileType.Empty(); DefaultDir.Empty(); + useConnectionStr = false; + return true; } // wxDbConnectInf::Initialize() @@ -183,7 +179,7 @@ bool wxDbConnectInf::AllocHenv() // Initialize the ODBC Environment for Database Operations if (SQLAllocEnv(&Henv) != SQL_SUCCESS) { - wxLogDebug(wxT("A problem occured while trying to get a connection to the data source")); + wxLogDebug(wxT("A problem occurred while trying to get a connection to the data source")); return false; } @@ -210,14 +206,16 @@ void wxDbConnectInf::SetDsn(const wxString &dsn) { wxASSERT(dsn.Length() < sizeof(Dsn)); - wxStrcpy(Dsn,dsn); + wxStrncpy(Dsn, dsn, sizeof(Dsn)-1); + Dsn[sizeof(Dsn)-1] = 0; // Prevent buffer overrun } // wxDbConnectInf::SetDsn() void wxDbConnectInf::SetUserID(const wxString &uid) { wxASSERT(uid.Length() < sizeof(Uid)); - wxStrcpy(Uid,uid); + wxStrncpy(Uid, uid, sizeof(Uid)-1); + Uid[sizeof(Uid)-1] = 0; // Prevent buffer overrun } // wxDbConnectInf::SetUserID() @@ -225,9 +223,19 @@ void wxDbConnectInf::SetPassword(const wxString &password) { wxASSERT(password.Length() < sizeof(AuthStr)); - wxStrcpy(AuthStr,password); + wxStrncpy(AuthStr, password, sizeof(AuthStr)-1); + AuthStr[sizeof(AuthStr)-1] = 0; // Prevent buffer overrun } // wxDbConnectInf::SetPassword() +void wxDbConnectInf::SetConnectionStr(const wxString &connectStr) +{ + wxASSERT(connectStr.Length() < sizeof(ConnectionStr)); + + useConnectionStr = wxStrlen(connectStr) > 0; + + wxStrncpy(ConnectionStr, connectStr, sizeof(ConnectionStr)-1); + ConnectionStr[sizeof(ConnectionStr)-1] = 0; // Prevent buffer overrun +} // wxDbConnectInf::SetConnectionStr() /********** wxDbColFor Constructor **********/ @@ -237,11 +245,6 @@ wxDbColFor::wxDbColFor() } // wxDbColFor::wxDbColFor() -wxDbColFor::~wxDbColFor() -{ -} // wxDbColFor::~wxDbColFor() - - /********** wxDbColFor::Initialize() **********/ void wxDbColFor::Initialize() { @@ -262,7 +265,7 @@ void wxDbColFor::Initialize() /********** wxDbColFor::Format() **********/ int wxDbColFor::Format(int Nation, int dbDataType, SWORD sqlDataType, - short columnSize, short decimalDigits) + short columnLength, short decimalDigits) { // ---------------------------------------------------------------------------------------- // -- 19991224 : mj10777 : Create @@ -284,14 +287,23 @@ int wxDbColFor::Format(int Nation, int dbDataType, SWORD sqlDataType, if (i_dbDataType == 0) // Filter unsupported dbDataTypes { - if ((i_sqlDataType == SQL_VARCHAR) || (i_sqlDataType == SQL_LONGVARCHAR)) + if ((i_sqlDataType == SQL_VARCHAR) +#if wxUSE_UNICODE + #if defined(SQL_WCHAR) + || (i_sqlDataType == SQL_WCHAR) + #endif + #if defined(SQL_WVARCHAR) + || (i_sqlDataType == SQL_WVARCHAR) + #endif +#endif + || (i_sqlDataType == SQL_LONGVARCHAR)) i_dbDataType = DB_DATA_TYPE_VARCHAR; if ((i_sqlDataType == SQL_C_DATE) || (i_sqlDataType == SQL_C_TIMESTAMP)) i_dbDataType = DB_DATA_TYPE_DATE; if (i_sqlDataType == SQL_C_BIT) i_dbDataType = DB_DATA_TYPE_INTEGER; if (i_sqlDataType == SQL_NUMERIC) - i_dbDataType = DB_DATA_TYPE_VARCHAR; + i_dbDataType = DB_DATA_TYPE_VARCHAR; // glt - ??? is this right? if (i_sqlDataType == SQL_REAL) i_dbDataType = DB_DATA_TYPE_FLOAT; if (i_sqlDataType == SQL_C_BINARY) @@ -315,8 +327,8 @@ int wxDbColFor::Format(int Nation, int dbDataType, SWORD sqlDataType, if (decimalDigits == 0) decimalDigits = 2; tempStr = wxT("%"); - tempStr.Printf(wxT("%s%d.%d"),tempStr.c_str(),columnSize,decimalDigits); - s_Field.Printf(wxT("%sf"),tempStr.c_str()); + tempStr.Printf(wxT("%s%d.%d"), tempStr.c_str(),columnLength, decimalDigits); + s_Field.Printf(wxT("%sf"), tempStr.c_str()); break; case DB_DATA_TYPE_DATE: if (i_Nation == 0) // timestamp YYYY-MM-DD HH:MM:SS.SSS (tested for SYBASE) @@ -341,17 +353,16 @@ int wxDbColFor::Format(int Nation, int dbDataType, SWORD sqlDataType, } break; case DB_DATA_TYPE_BLOB: - s_Field.Printf(wxT("Unable to format(%d)-SQL(%d)"),dbDataType,sqlDataType); // + 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); // + s_Field.Printf(wxT("Unknown Format(%d)-SQL(%d)"), dbDataType,sqlDataType); // break; }; - return true; + return TRUE; } // wxDbColFor::Format() - /********** wxDbColInf Constructor **********/ wxDbColInf::wxDbColInf() { @@ -376,8 +387,8 @@ bool wxDbColInf::Initialize() colName[0] = 0; sqlDataType = 0; typeName[0] = 0; - columnSize = 0; - bufferLength = 0; + columnLength = 0; + bufferSize = 0; decimalDigits = 0; numPrecRadix = 0; nullable = 0; @@ -538,6 +549,7 @@ void wxDb::initialize() // Mark database as not open as of yet dbIsOpen = false; dbIsCached = false; + dbOpenedWithConnectionString = false; } // wxDb::initialize() @@ -560,82 +572,88 @@ 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 - // the name to uppercase - if (Dbms() == dbmsORACLE) + // Some databases require user names to be specified in uppercase, + // so force the name to uppercase + if ((Dbms() == dbmsORACLE) || + (Dbms() == dbmsMAXDB)) UserID = UserID.Upper(); return UserID.c_str(); } // wxDb::convertUserID() -/********** wxDb::Open() **********/ -bool wxDb::Open(const wxString &Dsn, const wxString &Uid, const wxString &AuthStr) +bool wxDb::determineDataTypes(bool failOnDataTypeUnsupported) { - wxASSERT(Dsn.Length()); - dsn = Dsn; - uid = Uid; - authStr = AuthStr; - - RETCODE retcode; + size_t iIndex; - if (!FwdOnlyCursors()) - { - // Specify that the ODBC cursor library be used, if needed. This must be - // specified before the connection is made. - retcode = SQLSetConnectOption(hdbc, SQL_ODBC_CURSORS, SQL_CUR_USE_IF_NEEDED); - -#ifdef DBDEBUG_CONSOLE - if (retcode == SQL_SUCCESS) - cout << wxT("SQLSetConnectOption(CURSOR_LIB) successful") << endl; - else - cout << wxT("SQLSetConnectOption(CURSOR_LIB) failed") << endl; + // These are the possible SQL types we check for use against the datasource we are connected + // to for the purpose of determining which data type to use for the basic character strings + // column types + // + // NOTE: The first type in this enumeration that is determined to be supported by the + // datasource/driver is the one that will be used. + SWORD PossibleSqlCharTypes[] = { +#if wxUSE_UNICODE && defined(SQL_WVARCHAR) + SQL_WVARCHAR, #endif - } - - // 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); - -/* - 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) && - (retcode != SQL_SUCCESS_WITH_INFO)) - return(DispAllErrors(henv, hdbc)); - -/* - If using Intersolv branded ODBC drivers, this is the place where you would substitute - your branded driver license information + SQL_VARCHAR, +#if wxUSE_UNICODE && defined(SQL_WVARCHAR) + SQL_WCHAR, +#endif + SQL_CHAR + }; - SQLSetConnectOption(hdbc, 1041, (UDWORD) wxEmptyString); - SQLSetConnectOption(hdbc, 1042, (UDWORD) wxEmptyString); -*/ + // These are the possible SQL types we check for use against the datasource we are connected + // to for the purpose of determining which data type to use for the basic non-floating point + // column types + // + // NOTE: The first type in this enumeration that is determined to be supported by the + // datasource/driver is the one that will be used. + SWORD PossibleSqlIntegerTypes[] = { + SQL_INTEGER + }; - // Mark database as open - dbIsOpen = true; + // These are the possible SQL types we check for use against the datasource we are connected + // to for the purpose of determining which data type to use for the basic floating point number + // column types + // + // NOTE: The first type in this enumeration that is determined to be supported by the + // datasource/driver is the one that will be used. + SWORD PossibleSqlFloatTypes[] = { + SQL_DOUBLE, + SQL_REAL, + SQL_FLOAT, + SQL_DECIMAL, + SQL_NUMERIC + }; - // Allocate a statement handle for the database connection - if (SQLAllocStmt(hdbc, &hstmt) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + // These are the possible SQL types we check for use agains the datasource we are connected + // to for the purpose of determining which data type to use for the date/time column types + // + // NOTE: The first type in this enumeration that is determined to be supported by the + // datasource/driver is the one that will be used. + SWORD PossibleSqlDateTypes[] = { + SQL_TIMESTAMP, + SQL_DATE, +#ifdef SQL_DATETIME + SQL_DATETIME +#endif + }; - // Set Connection Options - if (!setConnectionOptions()) - return(false); + // These are the possible SQL types we check for use agains the datasource we are connected + // to for the purpose of determining which data type to use for the BLOB column types. + // + // NOTE: The first type in this enumeration that is determined to be supported by the + // datasource/driver is the one that will be used. + SWORD PossibleSqlBlobTypes[] = { + SQL_LONGVARBINARY, + SQL_VARBINARY + }; - // Query the data source for inf. about itself - if (!getDbInfo()) - return(false); // Query the data source regarding data type information @@ -644,7 +662,7 @@ bool wxDb::Open(const wxString &Dsn, const wxString &Uid, const wxString &AuthSt // 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 - // types I've selected below will not alway's be what we want. These are just + // types I've selected below will not always be what we want. These are just // what happened to work against an Oracle 7/Intersolv combination. The following is // a complete list of the results I got back against the Oracle 7 database: // @@ -678,73 +696,97 @@ bool wxDb::Open(const wxString &Dsn, const wxString &Uid, const wxString &AuthSt // SQL_DOUBLE type name = 'DOUBLE', Precision = 15 // SQL_INTEGER type name = 'LONG', Precision = 10 - // VARCHAR = Variable length character string - if (!getDataTypeInfo(SQL_VARCHAR, typeInfVarchar)) - if (!getDataTypeInfo(SQL_CHAR, typeInfVarchar)) - return(false); - else - typeInfVarchar.FsqlType = SQL_CHAR; - else - typeInfVarchar.FsqlType = SQL_VARCHAR; + // Query the data source for info about itself + if (!getDbInfo(failOnDataTypeUnsupported)) + return false; - // 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); - else - typeInfFloat.FsqlType = SQL_NUMERIC; - else - typeInfFloat.FsqlType = SQL_DECIMAL; - else - typeInfFloat.FsqlType = SQL_FLOAT; - else - typeInfFloat.FsqlType = SQL_REAL; - else - typeInfFloat.FsqlType = SQL_DOUBLE; + // --------------- Varchar - (Variable length character string) --------------- + for (iIndex = 0; iIndex < WXSIZEOF(PossibleSqlCharTypes) && + !getDataTypeInfo(PossibleSqlCharTypes[iIndex], typeInfVarchar); ++iIndex) + {} - // Integer - if (!getDataTypeInfo(SQL_INTEGER, typeInfInteger)) + if (iIndex < WXSIZEOF(PossibleSqlCharTypes)) + typeInfVarchar.FsqlType = PossibleSqlCharTypes[iIndex]; + else if (failOnDataTypeUnsupported) + return false; + + // --------------- Float --------------- + for (iIndex = 0; iIndex < WXSIZEOF(PossibleSqlFloatTypes) && + !getDataTypeInfo(PossibleSqlFloatTypes[iIndex], typeInfFloat); ++iIndex) + {} + + if (iIndex < WXSIZEOF(PossibleSqlFloatTypes)) + typeInfFloat.FsqlType = PossibleSqlFloatTypes[iIndex]; + else if (failOnDataTypeUnsupported) + return false; + + // --------------- Integer ------------- + for (iIndex = 0; iIndex < WXSIZEOF(PossibleSqlIntegerTypes) && + !getDataTypeInfo(PossibleSqlIntegerTypes[iIndex], typeInfInteger); ++iIndex) + {} + + if (iIndex < WXSIZEOF(PossibleSqlIntegerTypes)) + typeInfInteger.FsqlType = PossibleSqlIntegerTypes[iIndex]; + else if (failOnDataTypeUnsupported) { - // If SQL_INTEGER is not supported, use the floating point - // data type to store integers as well as floats + // If no non-floating point data types are supported, we'll + // use the type assigned for floats to store integers as well if (!getDataTypeInfo(typeInfFloat.FsqlType, typeInfInteger)) - return(false); + { + if (failOnDataTypeUnsupported) + return false; + } else typeInfInteger.FsqlType = typeInfFloat.FsqlType; } - else - typeInfInteger.FsqlType = SQL_INTEGER; - // Date/Time - if (Dbms() != dbmsDBASE) - { - if (!getDataTypeInfo(SQL_TIMESTAMP,typeInfDate)) - return(false); - else - typeInfDate.FsqlType = SQL_TIMESTAMP; - } - else - { - if (!getDataTypeInfo(SQL_DATE,typeInfDate)) - return(false); - else - typeInfDate.FsqlType = SQL_DATE; - } + // --------------- Date/Time --------------- + for (iIndex = 0; iIndex < WXSIZEOF(PossibleSqlDateTypes) && + !getDataTypeInfo(PossibleSqlDateTypes[iIndex], typeInfDate); ++iIndex) + {} - if (!getDataTypeInfo(SQL_LONGVARBINARY, typeInfBlob)) - { - if (!getDataTypeInfo(SQL_VARBINARY,typeInfBlob)) - return(false); - else - typeInfBlob.FsqlType = SQL_VARBINARY; - } - else - typeInfBlob.FsqlType = SQL_LONGVARBINARY; + if (iIndex < WXSIZEOF(PossibleSqlDateTypes)) + typeInfDate.FsqlType = PossibleSqlDateTypes[iIndex]; + else if (failOnDataTypeUnsupported) + return false; + + // --------------- BLOB --------------- + for (iIndex = 0; iIndex < WXSIZEOF(PossibleSqlBlobTypes) && + !getDataTypeInfo(PossibleSqlBlobTypes[iIndex], typeInfBlob); ++iIndex) + {} + + if (iIndex < WXSIZEOF(PossibleSqlBlobTypes)) + typeInfBlob.FsqlType = PossibleSqlBlobTypes[iIndex]; + else if (failOnDataTypeUnsupported) + return false; + + return true; +} // wxDb::determineDataTypes -//typeInfBlob.TypeName = "BLOB"; + +bool wxDb::open(bool failOnDataTypeUnsupported) +{ +/* + If using Intersolv branded ODBC drivers, this is the place where you would substitute + your branded driver license information + + SQLSetConnectOption(hdbc, 1041, (UDWORD) wxEmptyString); + SQLSetConnectOption(hdbc, 1042, (UDWORD) wxEmptyString); +*/ + + // Mark database as open + dbIsOpen = true; + + // Allocate a statement handle for the database connection + if (SQLAllocStmt(hdbc, &hstmt) != SQL_SUCCESS) + return(DispAllErrors(henv, hdbc)); + + // Set Connection Options + if (!setConnectionOptions()) + return false; + + if (!determineDataTypes(failOnDataTypeUnsupported)) + return false; #ifdef DBDEBUG_CONSOLE cout << wxT("VARCHAR DATA TYPE: ") << typeInfVarchar.TypeName << endl; @@ -756,23 +798,123 @@ bool wxDb::Open(const wxString &Dsn, const wxString &Uid, const wxString &AuthSt #endif // Completed Successfully - return(true); + return true; +} + +bool wxDb::Open(const wxString& inConnectStr, bool failOnDataTypeUnsupported) +{ + wxASSERT(inConnectStr.Length()); + return Open(inConnectStr, NULL, failOnDataTypeUnsupported); +} + +bool wxDb::Open(const wxString& inConnectStr, SQLHWND parentWnd, bool failOnDataTypeUnsupported) +{ + dsn = wxT(""); + uid = wxT(""); + authStr = wxT(""); + + RETCODE retcode; + + if (!FwdOnlyCursors()) + { + // Specify that the ODBC cursor library be used, if needed. This must be + // specified before the connection is made. + retcode = SQLSetConnectOption(hdbc, SQL_ODBC_CURSORS, SQL_CUR_USE_IF_NEEDED); + +#ifdef DBDEBUG_CONSOLE + if (retcode == SQL_SUCCESS) + cout << wxT("SQLSetConnectOption(CURSOR_LIB) successful") << endl; + else + cout << wxT("SQLSetConnectOption(CURSOR_LIB) failed") << endl; +#else + wxUnusedVar(retcode); +#endif + } + + // Connect to the data source + SQLTCHAR outConnectBuffer[SQL_MAX_CONNECTSTR_LEN+1]; // MS recommends at least 1k buffer + short outConnectBufferLen; + + inConnectionStr = inConnectStr; + + retcode = SQLDriverConnect(hdbc, parentWnd, (SQLTCHAR FAR *)inConnectionStr.c_str(), + (SWORD)inConnectionStr.Length(), (SQLTCHAR FAR *)outConnectBuffer, + sizeof(outConnectBuffer), &outConnectBufferLen, SQL_DRIVER_COMPLETE ); + + if ((retcode != SQL_SUCCESS) && + (retcode != SQL_SUCCESS_WITH_INFO)) + return(DispAllErrors(henv, hdbc)); + + outConnectBuffer[outConnectBufferLen] = 0; + outConnectionStr = outConnectBuffer; + dbOpenedWithConnectionString = true; + + return open(failOnDataTypeUnsupported); +} + +/********** wxDb::Open() **********/ +bool wxDb::Open(const wxString &Dsn, const wxString &Uid, const wxString &AuthStr, bool failOnDataTypeUnsupported) +{ + wxASSERT(Dsn.Length()); + dsn = Dsn; + uid = Uid; + authStr = AuthStr; + + inConnectionStr = wxT(""); + outConnectionStr = wxT(""); + + RETCODE retcode; + + if (!FwdOnlyCursors()) + { + // Specify that the ODBC cursor library be used, if needed. This must be + // specified before the connection is made. + retcode = SQLSetConnectOption(hdbc, SQL_ODBC_CURSORS, SQL_CUR_USE_IF_NEEDED); + +#ifdef DBDEBUG_CONSOLE + if (retcode == SQL_SUCCESS) + cout << wxT("SQLSetConnectOption(CURSOR_LIB) successful") << endl; + else + cout << wxT("SQLSetConnectOption(CURSOR_LIB) failed") << endl; +#else + wxUnusedVar( retcode ); +#endif + } + + // Connect to the data source + 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) && + (retcode != SQL_SUCCESS_WITH_INFO)) + return(DispAllErrors(henv, hdbc)); + + return open(failOnDataTypeUnsupported); } // wxDb::Open() -bool wxDb::Open(wxDbConnectInf *dbConnectInf) +bool wxDb::Open(wxDbConnectInf *dbConnectInf, bool failOnDataTypeUnsupported) { - return Open(dbConnectInf->GetDsn(), dbConnectInf->GetUserID(), - dbConnectInf->GetPassword()); + wxASSERT(dbConnectInf); + + // Use the connection string if one is present + if (dbConnectInf->UseConnectionStr()) + return Open(GetConnectionInStr(), failOnDataTypeUnsupported); + else + return Open(dbConnectInf->GetDsn(), dbConnectInf->GetUserID(), + dbConnectInf->GetPassword(), failOnDataTypeUnsupported); } // wxDb::Open() bool wxDb::Open(wxDb *copyDb) { - dsn = copyDb->GetDatasourceName(); - uid = copyDb->GetUsername(); - authStr = copyDb->GetPassword(); + dsn = copyDb->GetDatasourceName(); + uid = copyDb->GetUsername(); + authStr = copyDb->GetPassword(); + inConnectionStr = copyDb->GetConnectionInStr(); + outConnectionStr = copyDb->GetConnectionOutStr(); RETCODE retcode; @@ -787,15 +929,41 @@ bool wxDb::Open(wxDb *copyDb) cout << wxT("SQLSetConnectOption(CURSOR_LIB) successful") << endl; else cout << wxT("SQLSetConnectOption(CURSOR_LIB) failed") << endl; +#else + wxUnusedVar( retcode ); #endif } - // 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); + if (copyDb->OpenedWithConnectionString()) + { + // Connect to the data source + SQLTCHAR outConnectBuffer[SQL_MAX_CONNECTSTR_LEN+1]; + short outConnectBufferLen; + + inConnectionStr = copyDb->GetConnectionInStr(); + + retcode = SQLDriverConnect(hdbc, NULL, (SQLTCHAR FAR *)inConnectionStr.c_str(), + (SWORD)inConnectionStr.Length(), (SQLTCHAR FAR *)outConnectBuffer, + sizeof(outConnectBuffer), &outConnectBufferLen, SQL_DRIVER_COMPLETE); + + if ((retcode != SQL_SUCCESS) && + (retcode != SQL_SUCCESS_WITH_INFO)) + return(DispAllErrors(henv, hdbc)); - if (retcode == SQL_ERROR) + outConnectBuffer[outConnectBufferLen] = 0; + outConnectionStr = outConnectBuffer; + dbOpenedWithConnectionString = true; + } + else + { + // Connect to the data source + 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) && + (retcode != SQL_SUCCESS_WITH_INFO)) return(DispAllErrors(henv, hdbc)); /* @@ -815,7 +983,7 @@ bool wxDb::Open(wxDb *copyDb) // Set Connection Options if (!setConnectionOptions()) - return(false); + return false; // Instead of Querying the data source for info about itself, it can just be copied // from the wxDb instance that was passed in (copyDb). @@ -896,7 +1064,7 @@ bool wxDb::Open(wxDb *copyDb) #endif // Completed Successfully - return(true); + return true; } // wxDb::Open() 2 @@ -910,11 +1078,14 @@ bool wxDb::setConnectionOptions(void) // I need to get the DBMS name here, because some of the connection options // are database specific and need to call the Dbms() function. - if (SQLGetInfo(hdbc, SQL_DBMS_NAME, (UCHAR*) dbInf.dbmsName, 40, &cb) != SQL_SUCCESS) + RETCODE retcode; + + retcode = SQLGetInfo(hdbc, SQL_DBMS_NAME, (UCHAR *) dbInf.dbmsName, sizeof(dbInf.dbmsName), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) return(DispAllErrors(henv, hdbc)); - SQLSetConnectOption(hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF); - SQLSetConnectOption(hdbc, SQL_OPT_TRACE, SQL_OPT_TRACE_OFF); + /* retcode = */ SQLSetConnectOption(hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF); + /* retcode = */ SQLSetConnectOption(hdbc, SQL_OPT_TRACE, SQL_OPT_TRACE_OFF); // 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 @@ -926,7 +1097,7 @@ bool wxDb::setConnectionOptions(void) { const long SQL_PRESERVE_CURSORS = 1204L; const long SQL_PC_ON = 1L; - SQLSetConnectOption(hdbc, SQL_PRESERVE_CURSORS, SQL_PC_ON); + /* retcode = */ SQLSetConnectOption(hdbc, SQL_PRESERVE_CURSORS, SQL_PC_ON); } // Display the connection options to verify them @@ -934,15 +1105,17 @@ bool wxDb::setConnectionOptions(void) long l; cout << wxT("****** CONNECTION OPTIONS ******") << endl; - if (SQLGetConnectOption(hdbc, SQL_AUTOCOMMIT, &l) != SQL_SUCCESS) + retcode = SQLGetConnectOption(hdbc, SQL_AUTOCOMMIT, &l); + if (retcode != SQL_SUCCESS) return(DispAllErrors(henv, hdbc)); cout << wxT("AUTOCOMMIT: ") << (l == SQL_AUTOCOMMIT_OFF ? "OFF" : "ON") << endl; - if (SQLGetConnectOption(hdbc, SQL_ODBC_CURSORS, &l) != SQL_SUCCESS) + retcode = SQLGetConnectOption(hdbc, SQL_ODBC_CURSORS, &l); + if (retcode != SQL_SUCCESS) return(DispAllErrors(henv, hdbc)); cout << wxT("ODBC CURSORS: "); switch(l) - { + { case(SQL_CUR_USE_IF_NEEDED): cout << wxT("SQL_CUR_USE_IF_NEEDED"); break; @@ -952,10 +1125,11 @@ bool wxDb::setConnectionOptions(void) case(SQL_CUR_USE_DRIVER): cout << wxT("SQL_CUR_USE_DRIVER"); break; - } - cout << endl; + } + cout << endl; - if (SQLGetConnectOption(hdbc, SQL_OPT_TRACE, &l) != SQL_SUCCESS) + retcode = SQLGetConnectOption(hdbc, SQL_OPT_TRACE, &l) + if (retcode != SQL_SUCCESS) return(DispAllErrors(henv, hdbc)); cout << wxT("TRACING: ") << (l == SQL_OPT_TRACE_OFF ? wxT("OFF") : wxT("ON")) << endl; @@ -963,119 +1137,269 @@ bool wxDb::setConnectionOptions(void) #endif // Completed Successfully - return(true); + return true; } // wxDb::setConnectionOptions() /********** 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)); + retcode = SQLGetInfo(hdbc, SQL_SERVER_NAME, (UCHAR*) dbInf.serverName, sizeof(dbInf.serverName), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return false; + } - if (SQLGetInfo(hdbc, SQL_DATABASE_NAME, (UCHAR*) dbInf.databaseName, 128, &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + retcode = SQLGetInfo(hdbc, SQL_DATABASE_NAME, (UCHAR*) dbInf.databaseName, sizeof(dbInf.databaseName), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return false; + } - if (SQLGetInfo(hdbc, SQL_DBMS_NAME, (UCHAR*) dbInf.dbmsName, 40, &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + retcode = SQLGetInfo(hdbc, SQL_DBMS_NAME, (UCHAR*) dbInf.dbmsName, sizeof(dbInf.dbmsName), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return false; + } // 16-Mar-1999 // After upgrading to MSVC6, the original 20 char buffer below was insufficient, // causing database connectivity to fail in some cases. - retcode = SQLGetInfo(hdbc, SQL_DBMS_VER, (UCHAR*) dbInf.dbmsVer, 64, &cb); - + retcode = SQLGetInfo(hdbc, SQL_DBMS_VER, (UCHAR*) dbInf.dbmsVer, sizeof(dbInf.dbmsVer), &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)); + retcode = SQLGetInfo(hdbc, SQL_ACTIVE_CONNECTIONS, (UCHAR*) &dbInf.maxConnections, sizeof(dbInf.maxConnections), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + 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)); + retcode = SQLGetInfo(hdbc, SQL_ACTIVE_STATEMENTS, (UCHAR*) &dbInf.maxStmts, sizeof(dbInf.maxStmts), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return false; + } - if (SQLGetInfo(hdbc, SQL_DRIVER_NAME, (UCHAR*) dbInf.driverName, 40, &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + retcode = SQLGetInfo(hdbc, SQL_DRIVER_NAME, (UCHAR*) dbInf.driverName, sizeof(dbInf.driverName), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + 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)); + retcode = SQLGetInfo(hdbc, SQL_DRIVER_ODBC_VER, (UCHAR*) dbInf.odbcVer, sizeof(dbInf.odbcVer), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return false; + } - retcode = SQLGetInfo(hdbc, SQL_ODBC_VER, (UCHAR*) dbInf.drvMgrOdbcVer, 60, &cb); + retcode = SQLGetInfo(hdbc, SQL_ODBC_VER, (UCHAR*) dbInf.drvMgrOdbcVer, sizeof(dbInf.drvMgrOdbcVer), &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)); + retcode = SQLGetInfo(hdbc, SQL_DRIVER_VER, (UCHAR*) dbInf.driverVer, sizeof(dbInf.driverVer), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + 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)); + retcode = SQLGetInfo(hdbc, SQL_ODBC_API_CONFORMANCE, (UCHAR*) &dbInf.apiConfLvl, sizeof(dbInf.apiConfLvl), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return false; + } + + retcode = SQLGetInfo(hdbc, SQL_ODBC_SAG_CLI_CONFORMANCE, (UCHAR*) &dbInf.cliConfLvl, sizeof(dbInf.cliConfLvl), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + // Not all drivers support this call - Nick Gorham(unixODBC) + dbInf.cliConfLvl = 0; + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return false; + } + + retcode = SQLGetInfo(hdbc, SQL_ODBC_SQL_CONFORMANCE, (UCHAR*) &dbInf.sqlConfLvl, sizeof(dbInf.sqlConfLvl), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return false; + } + + retcode = SQLGetInfo(hdbc, SQL_OUTER_JOINS, (UCHAR*) dbInf.outerJoins, sizeof(dbInf.outerJoins), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + 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)); + retcode = SQLGetInfo(hdbc, SQL_PROCEDURES, (UCHAR*) dbInf.procedureSupport, sizeof(dbInf.procedureSupport), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) { - // 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)); - - if (SQLGetInfo(hdbc, SQL_OUTER_JOINS, (UCHAR*) dbInf.outerJoins, 2, &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); - - if (SQLGetInfo(hdbc, SQL_PROCEDURES, (UCHAR*) dbInf.procedureSupport, 2, &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); - - if (SQLGetInfo(hdbc, SQL_ACCESSIBLE_TABLES, (UCHAR*) dbInf.accessibleTables, 2, &cb) != SQL_SUCCESS) - return(DispAllErrors(henv, hdbc)); + retcode = SQLGetInfo(hdbc, SQL_ACCESSIBLE_TABLES, (UCHAR*) dbInf.accessibleTables, sizeof(dbInf.accessibleTables), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + 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)); + retcode = SQLGetInfo(hdbc, SQL_CURSOR_COMMIT_BEHAVIOR, (UCHAR*) &dbInf.cursorCommitBehavior, sizeof(dbInf.cursorCommitBehavior), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + 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)); + retcode = SQLGetInfo(hdbc, SQL_CURSOR_ROLLBACK_BEHAVIOR, (UCHAR*) &dbInf.cursorRollbackBehavior, sizeof(dbInf.cursorRollbackBehavior), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + 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)); + retcode = SQLGetInfo(hdbc, SQL_NON_NULLABLE_COLUMNS, (UCHAR*) &dbInf.supportNotNullClause, sizeof(dbInf.supportNotNullClause), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + 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)); + retcode = SQLGetInfo(hdbc, SQL_ODBC_SQL_OPT_IEF, (UCHAR*) dbInf.supportIEF, sizeof(dbInf.supportIEF), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + 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)); + retcode = SQLGetInfo(hdbc, SQL_DEFAULT_TXN_ISOLATION, (UCHAR*) &dbInf.txnIsolation, sizeof(dbInf.txnIsolation), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + 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)); + retcode = SQLGetInfo(hdbc, SQL_TXN_ISOLATION_OPTION, (UCHAR*) &dbInf.txnIsolationOptions, sizeof(dbInf.txnIsolationOptions), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + 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)); + retcode = SQLGetInfo(hdbc, SQL_FETCH_DIRECTION, (UCHAR*) &dbInf.fetchDirections, sizeof(dbInf.fetchDirections), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + 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)); + retcode = SQLGetInfo(hdbc, SQL_LOCK_TYPES, (UCHAR*) &dbInf.lockTypes, sizeof(dbInf.lockTypes), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + 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)); + retcode = SQLGetInfo(hdbc, SQL_POS_OPERATIONS, (UCHAR*) &dbInf.posOperations, sizeof(dbInf.posOperations), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + 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)); + retcode = SQLGetInfo(hdbc, SQL_POSITIONED_STATEMENTS, (UCHAR*) &dbInf.posStmts, sizeof(dbInf.posStmts), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + 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)); + retcode = SQLGetInfo(hdbc, SQL_SCROLL_CONCURRENCY, (UCHAR*) &dbInf.scrollConcurrency, sizeof(dbInf.scrollConcurrency), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + 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)); + retcode = SQLGetInfo(hdbc, SQL_SCROLL_OPTIONS, (UCHAR*) &dbInf.scrollOptions, sizeof(dbInf.scrollOptions), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + 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)); + retcode = SQLGetInfo(hdbc, SQL_STATIC_SENSITIVITY, (UCHAR*) &dbInf.staticSensitivity, sizeof(dbInf.staticSensitivity), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + 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)); + retcode = SQLGetInfo(hdbc, SQL_TXN_CAPABLE, (UCHAR*) &dbInf.txnCapable, sizeof(dbInf.txnCapable), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + 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)); + retcode = SQLGetInfo(hdbc, SQL_LOGIN_TIMEOUT, (UCHAR*) &dbInf.loginTimeout, sizeof(dbInf.loginTimeout), &cb); + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO ) + { + DispAllErrors(henv, hdbc); + if (failOnDataTypeUnsupported) + return false; + } #ifdef DBDEBUG_CONSOLE cout << wxT("***** DATA SOURCE INFORMATION *****") << endl; @@ -1273,7 +1597,7 @@ bool wxDb::getDbInfo(void) #endif // Completed Successfully - return(true); + return true; } // wxDb::getDbInfo() @@ -1293,21 +1617,24 @@ 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) - cout << wxT("SQL_NO_DATA_FOUND fetching inf. about data type.") << endl; + cout << wxT("SQL_NO_DATA_FOUND fetching information about data type.") << endl; #endif DispAllErrors(henv, hdbc, hstmt); SQLFreeStmt(hstmt, SQL_CLOSE); - return(false); + return false; } 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) + if (SQLGetData(hstmt, 1, SQL_C_WXCHAR, typeName, sizeof(typeName), &cbRet) != SQL_SUCCESS) return(DispAllErrors(henv, hdbc, hstmt)); structSQLTypeInfo.TypeName = typeName; @@ -1358,7 +1685,7 @@ bool wxDb::getDataTypeInfo(SWORD fSqlType, wxDbSqlTypeInfo &structSQLTypeInfo) return(DispAllErrors(henv, hdbc, hstmt)); // Completed Successfully - return(true); + return true; } // wxDb::getDataTypeInfo() @@ -1393,19 +1720,19 @@ void wxDb::Close(void) #ifdef __WXDEBUG__ wxTablesInUse *tiu; - wxNode *pNode; - pNode = TablesInUse.First(); + wxList::compatibility_iterator pNode; + 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); + s2.Printf(wxT("Orphaned table found using pDb:[%p]"),this); + wxLogDebug(s.c_str(),s2.c_str()); } - pNode = pNode->Next(); + pNode = pNode->GetNext(); } #endif @@ -1431,7 +1758,7 @@ bool wxDb::CommitTrans(void) } // Completed successfully - return(true); + return true; } // wxDb::CommitTrans() @@ -1444,7 +1771,7 @@ bool wxDb::RollbackTrans(void) return(DispAllErrors(henv, hdbc)); // Completed successfully - return(true); + return true; } // wxDb::RollbackTrans() @@ -1454,22 +1781,22 @@ bool wxDb::DispAllErrors(HENV aHenv, HDBC aHdbc, HSTMT aHstmt) /* * This function is called internally whenever an error condition prevents the user's * request from being executed. This function will query the datasource as to the - * actual error(s) that just occured on the previous request of the datasource. + * actual error(s) that just occurred on the previous request of the datasource. * * The function will retrieve each error condition from the datasource and * Printf the codes/text values into a string which it then logs via logError(). * If in DBDEBUG_CONSOLE mode, the constructed string will be displayed in the console * window and program execution will be paused until the user presses a key. * - * This function always returns a false, so that functions which call this function + * This function always returns false, so that functions which call this function * can have a line like "return (DispAllErrors(henv, hdbc));" to indicate the failure - * of the users request, so that the calling code can then process the error msg log + * of the user's request, so that the calling code can then process the error message log. */ { 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); if (!silent) @@ -1487,7 +1814,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() @@ -1495,10 +1822,10 @@ 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) - return(true); + 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); + return false; } // wxDb::GetNextError() @@ -1539,12 +1866,13 @@ void wxDb::logError(const wxString &errMsg, const wxString &SQLState) if (++pLast == DB_MAX_ERROR_HISTORY) { int i; - for (i = 0; i < DB_MAX_ERROR_HISTORY; i++) + for (i = 0; i < DB_MAX_ERROR_HISTORY-1; i++) wxStrcpy(errorList[i], errorList[i+1]); pLast--; } - wxStrcpy(errorList[pLast], errMsg); + wxStrncpy(errorList[pLast], errMsg, DB_MAX_ERROR_MSG_LEN); + errorList[pLast][DB_MAX_ERROR_MSG_LEN] = 0; if (SQLState.Length()) if ((dbStatus = TranslateSqlState(SQLState)) != DB_ERR_FUNCTION_SEQUENCE_ERROR) @@ -1782,7 +2110,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; @@ -1851,7 +2179,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); @@ -1863,14 +2191,14 @@ bool wxDb::DropView(const wxString &viewName) DispNextError(); DispAllErrors(henv, hdbc, hstmt); RollbackTrans(); - return(false); + return false; } } } // Commit the transaction if (!CommitTrans()) - return(false); + return false; return true; @@ -1884,30 +2212,126 @@ bool wxDb::ExecSql(const wxString &pSqlStmt) SQLFreeStmt(hstmt, SQL_CLOSE); - retcode = SQLExecDirect(hstmt, (UCHAR FAR *) pSqlStmt.c_str(), SQL_NTS); + 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); + return true; } else { DispAllErrors(henv, hdbc, hstmt); - return(false); + return false; } } // wxDb::ExecSql() +/********** wxDb::ExecSql() with column info **********/ +bool wxDb::ExecSql(const wxString &pSqlStmt, wxDbColInf** columns, short& numcols) +{ + //execute the statement first + if (!ExecSql(pSqlStmt)) + return false; + + SWORD noCols; + if (SQLNumResultCols(hstmt, &noCols) != SQL_SUCCESS) + { + DispAllErrors(henv, hdbc, hstmt); + return false; + } + + if (noCols == 0) + return false; + else + numcols = noCols; + + // Get column information + short colNum; + wxChar name[DB_MAX_COLUMN_NAME_LEN+1]; + SWORD Sword; + SDWORD Sdword; + wxDbColInf* pColInf = new wxDbColInf[noCols]; + + // Fill in column information (name, datatype) + for (colNum = 0; colNum < noCols; colNum++) + { + if (SQLColAttributes(hstmt, (UWORD)(colNum+1), SQL_COLUMN_NAME, + name, sizeof(name), + &Sword, &Sdword) != SQL_SUCCESS) + { + DispAllErrors(henv, hdbc, hstmt); + delete[] pColInf; + return false; + } + + wxStrncpy(pColInf[colNum].colName, name, DB_MAX_COLUMN_NAME_LEN); + pColInf[colNum].colName[DB_MAX_COLUMN_NAME_LEN] = 0; // Prevent buffer overrun + + if (SQLColAttributes(hstmt, (UWORD)(colNum+1), SQL_COLUMN_TYPE, + NULL, 0, &Sword, &Sdword) != SQL_SUCCESS) + { + DispAllErrors(henv, hdbc, hstmt); + delete[] pColInf; + return false; + } + + switch (Sdword) + { +#if wxUSE_UNICODE + #if defined(SQL_WCHAR) + case SQL_WCHAR: + #endif + #if defined(SQL_WVARCHAR) + case SQL_WVARCHAR: + #endif +#endif + case SQL_VARCHAR: + case SQL_CHAR: + pColInf[colNum].dbDataType = DB_DATA_TYPE_VARCHAR; + break; + case SQL_TINYINT: + case SQL_SMALLINT: + case SQL_INTEGER: + case SQL_BIT: + pColInf[colNum].dbDataType = DB_DATA_TYPE_INTEGER; + break; + case SQL_DOUBLE: + case SQL_DECIMAL: + case SQL_NUMERIC: + case SQL_FLOAT: + case SQL_REAL: + pColInf[colNum].dbDataType = DB_DATA_TYPE_FLOAT; + break; + case SQL_DATE: + case SQL_TIMESTAMP: + pColInf[colNum].dbDataType = DB_DATA_TYPE_DATE; + break; + case SQL_BINARY: + pColInf[colNum].dbDataType = DB_DATA_TYPE_BLOB; + break; +#ifdef __WXDEBUG__ + default: + wxString errMsg; + errMsg.Printf(wxT("SQL Data type %ld currently not supported by wxWidgets"), (long)Sdword); + wxLogDebug(errMsg,wxT("ODBC DEBUG MESSAGE")); +#endif + } + } + + *columns = pColInf; + return true; +} // wxDb::ExecSql() + /********** wxDb::GetNext() **********/ bool wxDb::GetNext(void) { if (SQLFetch(hstmt) == SQL_SUCCESS) - return(true); + return true; else { DispAllErrors(henv, hdbc, hstmt); - return(false); + return false; } } // wxDb::GetNext() @@ -1919,12 +2343,17 @@ bool wxDb::GetData(UWORD colNo, SWORD cType, PTR pData, SDWORD maxLen, SDWORD FA wxASSERT(pData); wxASSERT(cbReturned); - if (SQLGetData(hstmt, colNo, cType, pData, maxLen, cbReturned) == SQL_SUCCESS) - return(true); + long bufferSize = maxLen; + + if (cType == SQL_C_WXCHAR) + bufferSize = maxLen * sizeof(wxChar); + + if (SQLGetData(hstmt, colNo, cType, pData, bufferSize, cbReturned) == SQL_SUCCESS) + return true; else { DispAllErrors(henv, hdbc, hstmt); - return(false); + return false; } } // wxDb::GetData() @@ -1935,8 +2364,7 @@ int wxDb::GetKeyFields(const wxString &tableName, wxDbColInf* colInf, UWORD noCo { wxChar szPkTable[DB_MAX_TABLE_NAME_LEN+1]; /* Primary key table name */ wxChar szFkTable[DB_MAX_TABLE_NAME_LEN+1]; /* Foreign key table name */ - short iKeySeq; -// SQLSMALLINT iKeySeq; + SWORD iKeySeq; wxChar szPkCol[DB_MAX_COLUMN_NAME_LEN+1]; /* Primary key column */ wxChar szFkCol[DB_MAX_COLUMN_NAME_LEN+1]; /* Foreign key column */ SQLRETURN retcode; @@ -1962,7 +2390,7 @@ int wxDb::GetKeyFields(const wxString &tableName, wxDbColInf* colInf, UWORD noCo 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 */ @@ -1973,7 +2401,7 @@ int wxDb::GetKeyFields(const wxString &tableName, wxDbColInf* colInf, UWORD noCo retcode = SQLFetch(hstmt); if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) { - GetData( 4, SQL_C_CHAR, szPkCol, DB_MAX_COLUMN_NAME_LEN+1, &cb); + GetData( 4, SQL_C_WXCHAR, szPkCol, DB_MAX_COLUMN_NAME_LEN+1, &cb); GetData( 5, SQL_C_SSHORT, &iKeySeq, 0, &cb); //------- for (i=0;inumTables == 0) { - GetData( 1, SQL_C_CHAR, (UCHAR*) pDbInf->catalog, 128+1, &cb); - GetData( 2, SQL_C_CHAR, (UCHAR*) pDbInf->schema, 128+1, &cb); + GetData( 1, SQL_C_WXCHAR, (UCHAR*) pDbInf->catalog, 128+1, &cb); + GetData( 2, SQL_C_WXCHAR, (UCHAR*) pDbInf->schema, 128+1, &cb); } pDbInf->numTables++; // Counter for Tables } // if (pass == 1) @@ -2931,9 +3377,9 @@ wxDbInf *wxDb::GetCatalog(const wxChar *userID) noTab = 0; } // if (pDbInf->pTableInf == NULL) // Has the Table Array been created - GetData( 3, SQL_C_CHAR, (UCHAR*) (pDbInf->pTableInf+noTab)->tableName, DB_MAX_TABLE_NAME_LEN+1, &cb); - GetData( 4, SQL_C_CHAR, (UCHAR*) (pDbInf->pTableInf+noTab)->tableType, 30+1, &cb); - GetData( 5, SQL_C_CHAR, (UCHAR*) (pDbInf->pTableInf+noTab)->tableRemarks, 254+1, &cb); + GetData( 3, SQL_C_WXCHAR, (UCHAR*) (pDbInf->pTableInf+noTab)->tableName, DB_MAX_TABLE_NAME_LEN+1, &cb); + GetData( 4, SQL_C_WXCHAR, (UCHAR*) (pDbInf->pTableInf+noTab)->tableType, 30+1, &cb); + GetData( 5, SQL_C_WXCHAR, (UCHAR*) (pDbInf->pTableInf+noTab)->tableRemarks, 254+1, &cb); noTab++; } // if @@ -2944,7 +3390,7 @@ wxDbInf *wxDb::GetCatalog(const wxChar *userID) // Query how many columns are in each table for (noTab=0;noTabnumTables;noTab++) { - (pDbInf->pTableInf+noTab)->numCols = GetColumnCount((pDbInf->pTableInf+noTab)->tableName,UserID); + (pDbInf->pTableInf+noTab)->numCols = (UWORD)GetColumnCount((pDbInf->pTableInf+noTab)->tableName,UserID); } return pDbInf; @@ -2978,26 +3424,27 @@ 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); + return false; SQLFreeStmt(hstmt, SQL_CLOSE); wxString UserID; convertUserID(userID,UserID); - if (!UserID.IsEmpty() && + if (!UserID.empty() && Dbms() != dbmsMY_SQL && Dbms() != dbmsACCESS && + Dbms() != dbmsFIREBIRD && 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 } @@ -3013,49 +3460,53 @@ bool wxDb::Catalog(const wxChar *userID, const wxString &fileName) { DispAllErrors(henv, hdbc, hstmt); fclose(fp); - return(false); + return false; } wxString outStr; 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; + + GetData(3,SQL_C_WXCHAR, (UCHAR *) tblName, DB_MAX_TABLE_NAME_LEN+1, &cb); + GetData(4,SQL_C_WXCHAR, (UCHAR *) colName, DB_MAX_COLUMN_NAME_LEN+1,&cb); + GetData(5,SQL_C_SSHORT, (UCHAR *)&sqlDataType, 0, &cb); + GetData(6,SQL_C_WXCHAR, (UCHAR *) typeName, sizeof(typeName), &cb); + GetData(7,SQL_C_SLONG, (UCHAR *)&precision, 0, &cb); + GetData(8,SQL_C_SLONG, (UCHAR *)&length, 0, &cb); + 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); - - 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); - return(false); + return false; } cnt++; } @@ -3108,6 +3559,7 @@ bool wxDb::TableExists(const wxString &tableName, const wxChar *userID, const wx // Oracle and Interbase table names are uppercase only, so force // the name to uppercase just in case programmer forgot to do this if ((Dbms() == dbmsORACLE) || + (Dbms() == dbmsFIREBIRD) || (Dbms() == dbmsINTERBASE)) TableName = TableName.Upper(); @@ -3116,18 +3568,19 @@ bool wxDb::TableExists(const wxString &tableName, const wxChar *userID, const wx // 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 (!UserID.IsEmpty() && + if (!UserID.empty() && Dbms() != dbmsMY_SQL && Dbms() != dbmsACCESS && Dbms() != dbmsMS_SQL_SERVER && Dbms() != dbmsDB2 && + Dbms() != dbmsFIREBIRD && 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 @@ -3135,7 +3588,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) @@ -3150,14 +3603,14 @@ bool wxDb::TableExists(const wxString &tableName, const wxChar *userID, const wx SQLFreeStmt(hstmt, SQL_CLOSE); - return(true); + return true; } // wxDb::TableExists() /********** 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()); @@ -3179,6 +3632,7 @@ bool wxDb::TablePrivileges(const wxString &tableName, const wxString &priv, cons // Oracle and Interbase table names are uppercase only, so force // the name to uppercase just in case programmer forgot to do this if ((Dbms() == dbmsORACLE) || + (Dbms() == dbmsFIREBIRD) || (Dbms() == dbmsINTERBASE)) TableName = TableName.Upper(); @@ -3186,54 +3640,54 @@ bool wxDb::TablePrivileges(const wxString &tableName, const wxString &priv, cons // 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() && + if (!Schema.empty() && Dbms() != dbmsMY_SQL && Dbms() != dbmsACCESS && Dbms() != dbmsMS_SQL_SERVER) { retcode = SQLTablePrivileges(hstmt, NULL, 0, // Catalog - (UCHAR FAR *)Schema.c_str(), SQL_NTS, // 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 NULL, 0, // Schema - (UCHAR FAR *)TableName.c_str(), SQL_NTS); + (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)); + 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) + if (SQLGetData(hstmt, 1, SQL_C_WXCHAR, (UCHAR*) result.tableQual, sizeof(result.tableQual), &cbRetVal) != SQL_SUCCESS) failed = true; - if (!failed && SQLGetData(hstmt, 2, SQL_C_CHAR, (UCHAR*) result.tableOwner, sizeof(result.tableOwner), &cbRetVal) != SQL_SUCCESS) + if (!failed && SQLGetData(hstmt, 2, SQL_C_WXCHAR, (UCHAR*) result.tableOwner, sizeof(result.tableOwner), &cbRetVal) != SQL_SUCCESS) failed = true; - if (!failed && SQLGetData(hstmt, 3, SQL_C_CHAR, (UCHAR*) result.tableName, sizeof(result.tableName), &cbRetVal) != SQL_SUCCESS) + if (!failed && SQLGetData(hstmt, 3, SQL_C_WXCHAR, (UCHAR*) result.tableName, sizeof(result.tableName), &cbRetVal) != SQL_SUCCESS) failed = true; - if (!failed && SQLGetData(hstmt, 4, SQL_C_CHAR, (UCHAR*) result.grantor, sizeof(result.grantor), &cbRetVal) != SQL_SUCCESS) + if (!failed && SQLGetData(hstmt, 4, SQL_C_WXCHAR, (UCHAR*) result.grantor, sizeof(result.grantor), &cbRetVal) != SQL_SUCCESS) failed = true; - if (!failed && SQLGetData(hstmt, 5, SQL_C_CHAR, (UCHAR*) result.grantee, sizeof(result.grantee), &cbRetVal) != SQL_SUCCESS) + if (!failed && SQLGetData(hstmt, 5, SQL_C_WXCHAR, (UCHAR*) result.grantee, sizeof(result.grantee), &cbRetVal) != SQL_SUCCESS) failed = true; - if (!failed && SQLGetData(hstmt, 6, SQL_C_CHAR, (UCHAR*) result.privilege, sizeof(result.privilege), &cbRetVal) != SQL_SUCCESS) + if (!failed && SQLGetData(hstmt, 6, SQL_C_WXCHAR, (UCHAR*) result.privilege, sizeof(result.privilege), &cbRetVal) != SQL_SUCCESS) failed = true; - if (!failed && SQLGetData(hstmt, 7, SQL_C_CHAR, (UCHAR*) result.grantable, sizeof(result.grantable), &cbRetVal) != SQL_SUCCESS) + if (!failed && SQLGetData(hstmt, 7, SQL_C_WXCHAR, (UCHAR*) result.grantable, sizeof(result.grantable), &cbRetVal) != SQL_SUCCESS) failed = true; if (failed) @@ -3241,7 +3695,7 @@ bool wxDb::TablePrivileges(const wxString &tableName, const wxString &priv, cons 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 @@ -3275,6 +3729,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) { @@ -3285,9 +3767,9 @@ bool wxDb::SetSqlLogging(wxDbSqlLogState state, const wxString &filename, bool a { if (fpSqlLog == 0) { - fpSqlLog = fopen(filename, (append ? wxT("at") : wxT("wt"))); + fpSqlLog = wxFopen(filename.c_str(), (append ? wxT("at") : wxT("wt"))); if (fpSqlLog == NULL) - return(false); + return false; } } else // sqlLogOFF @@ -3295,13 +3777,13 @@ bool wxDb::SetSqlLogging(wxDbSqlLogState state, const wxString &filename, bool a if (fpSqlLog) { if (fclose(fpSqlLog)) - return(false); + return false; fpSqlLog = 0; } } sqlLogState = state; - return(true); + return true; } // wxDb::SetSqlLogging() @@ -3312,16 +3794,16 @@ bool wxDb::WriteSqlLog(const wxString &logMsg) wxASSERT(logMsg.Length()); if (fpSqlLog == 0 || sqlLogState == sqlLogOFF) - return(false); + return false; - if (fputs(wxT("\n"), fpSqlLog) == EOF) - return(false); - if (fputs(logMsg, fpSqlLog) == EOF) - return(false); - if (fputs(wxT("\n"), fpSqlLog) == EOF) - return(false); + if (wxFputs(wxT("\n"), fpSqlLog) == EOF) + return false; + if (wxFputs(logMsg, fpSqlLog) == EOF) + return false; + if (wxFputs(wxT("\n"), fpSqlLog) == EOF) + return false; - return(true); + return true; } // wxDb::WriteSqlLog() @@ -3365,7 +3847,7 @@ wxDBMS wxDb::Dbms(void) * * MY_SQL * - If a column is part of the Primary Key, the column cannot be NULL - * - Cannot support selecting for update [::CanSelectForUpdate()]. Always returns false + * - Cannot support selecting for update [::CanSelectForUpdate()]. Always returns FALSE * - Columns that are part of primary or secondary 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 @@ -3395,8 +3877,16 @@ wxDBMS wxDb::Dbms(void) if (dbmsType != dbmsUNIDENTIFIED) return(dbmsType); +#ifdef DBDEBUG_CONSOLE + // When run in console mode, use standard out to display errors. + cout << "Database connecting to: " << dbInf.dbmsName << endl; +#endif // DBDEBUG_CONSOLE + + wxLogDebug(wxT("Database connecting to: ")); + wxLogDebug(dbInf.dbmsName); + wxChar baseName[25+1]; - wxStrncpy(baseName,dbInf.dbmsName,25); + wxStrncpy(baseName, dbInf.dbmsName, 25); baseName[25] = 0; // RGG 20001025 : add support for Interbase @@ -3426,32 +3916,39 @@ wxDBMS wxDb::Dbms(void) 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(dbInf.dbmsName,wxT("Pervasive"))) + if (!wxStricmp(baseName,wxT("Pervasive"))) return((wxDBMS)(dbmsType = dbmsPERVASIVE_SQL)); baseName[8] = 0; if (!wxStricmp(baseName,wxT("Informix"))) return((wxDBMS)(dbmsType = dbmsINFORMIX)); + if (!wxStricmp(baseName,wxT("Firebird"))) + return((wxDBMS)(dbmsType = dbmsFIREBIRD)); + 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)); + if (!wxStricmp(baseName,wxT("MaxDB"))) + return((wxDBMS)(dbmsType = dbmsMAXDB)); baseName[3] = 0; if (!wxStricmp(baseName,wxT("DB2"))) @@ -3504,10 +4001,10 @@ bool wxDb::ModifyColumn(const wxString &tableName, const wxString &columnName, switch (Dbms()) { case dbmsORACLE : - alterSlashModify = "MODIFY"; + alterSlashModify = _T("MODIFY"); break; case dbmsMS_SQL_SERVER : - alterSlashModify = "ALTER COLUMN"; + alterSlashModify = _T("ALTER COLUMN"); break; case dbmsUNIDENTIFIED : return false; @@ -3517,20 +4014,30 @@ bool wxDb::ModifyColumn(const wxString &tableName, const wxString &columnName, case dbmsPOSTGRES : case dbmsACCESS : case dbmsDBASE : + case dbmsXBASE_SEQUITER : default : - alterSlashModify = "MODIFY"; + alterSlashModify = _T("MODIFY"); break; } // create the SQL statement - sqlStmt.Printf(wxT("ALTER TABLE %s %s %s %s"), tableName.c_str(), alterSlashModify.c_str(), + 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; } @@ -3547,7 +4054,7 @@ bool wxDb::ModifyColumn(const wxString &tableName, const wxString &columnName, /********** wxDbGetConnection() **********/ -wxDb WXDLLEXPORT *wxDbGetConnection(wxDbConnectInf *pDbConfig, bool FwdOnlyCursors) +wxDb WXDLLIMPEXP_ODBC *wxDbGetConnection(wxDbConnectInf *pDbConfig, bool FwdOnlyCursors) { wxDbList *pList; @@ -3565,17 +4072,42 @@ wxDb WXDLLEXPORT *wxDbGetConnection(wxDbConnectInf *pDbConfig, bool FwdOnlyCurso // The database connection must be for the same datasource // name and must currently not be in use. if (pList->Free && - (pList->PtrDb->FwdOnlyCursors() == FwdOnlyCursors) && - (!wxStrcmp(pDbConfig->GetDsn(), pList->Dsn))) // Found a free connection + (pList->PtrDb->FwdOnlyCursors() == FwdOnlyCursors)) { - pList->Free = false; - return(pList->PtrDb); + if (pDbConfig->UseConnectionStr()) + { + if (pList->PtrDb->OpenedWithConnectionString() && + (!wxStrcmp(pDbConfig->GetConnectionStr(), pList->ConnectionStr))) + { + // Found a free connection + pList->Free = false; + return(pList->PtrDb); + } + } + else + { + if (!pList->PtrDb->OpenedWithConnectionString() && + (!wxStrcmp(pDbConfig->GetDsn(), pList->Dsn))) + { + // Found a free connection + pList->Free = false; + return(pList->PtrDb); + } + } } - if (!wxStrcmp(pDbConfig->GetDsn(), pList->Dsn) && - !wxStrcmp(pDbConfig->GetUserID(), pList->Uid) && - !wxStrcmp(pDbConfig->GetPassword(), pList->AuthStr)) - matchingDbConnection = pList->PtrDb; + if (pDbConfig->UseConnectionStr()) + { + if (!wxStrcmp(pDbConfig->GetConnectionStr(), pList->ConnectionStr)) + matchingDbConnection = pList->PtrDb; + } + else + { + if (!wxStrcmp(pDbConfig->GetDsn(), pList->Dsn) && + !wxStrcmp(pDbConfig->GetUserID(), pList->Uid) && + !wxStrcmp(pDbConfig->GetPassword(), pList->AuthStr)) + matchingDbConnection = pList->PtrDb; + } } // No available connections. A new connection must be made and @@ -3597,18 +4129,28 @@ wxDb WXDLLEXPORT *wxDbGetConnection(wxDbConnectInf *pDbConfig, bool FwdOnlyCurso } // Initialize new node in the linked list - pList->PtrNext = 0; - pList->Free = false; - pList->Dsn = pDbConfig->GetDsn(); - pList->Uid = pDbConfig->GetUserID(); - pList->AuthStr = pDbConfig->GetPassword(); + pList->PtrNext = 0; + pList->Free = false; + pList->Dsn = pDbConfig->GetDsn(); + pList->Uid = pDbConfig->GetUserID(); + pList->AuthStr = pDbConfig->GetPassword(); + pList->ConnectionStr = pDbConfig->GetConnectionStr(); pList->PtrDb = new wxDb(pDbConfig->GetHenv(), FwdOnlyCursors); - bool opened = false; + bool opened; if (!matchingDbConnection) - opened = pList->PtrDb->Open(pDbConfig->GetDsn(), pDbConfig->GetUserID(), pDbConfig->GetPassword()); + { + if (pDbConfig->UseConnectionStr()) + { + opened = pList->PtrDb->Open(pDbConfig->GetConnectionStr()); + } + else + { + opened = pList->PtrDb->Open(pDbConfig->GetDsn(), pDbConfig->GetUserID(), pDbConfig->GetPassword()); + } + } else opened = pList->PtrDb->Open(matchingDbConnection); @@ -3616,7 +4158,7 @@ wxDb WXDLLEXPORT *wxDbGetConnection(wxDbConnectInf *pDbConfig, bool FwdOnlyCurso if (opened) { pList->PtrDb->setCached(true); // Prevent a user from deleting a cached connection - pList->PtrDb->SetSqlLogging(SQLLOGstate,SQLLOGfn,true); + pList->PtrDb->SetSqlLogging(SQLLOGstate, SQLLOGfn, true); return(pList->PtrDb); } else // Unable to connect, destroy list item @@ -3624,11 +4166,12 @@ wxDb WXDLLEXPORT *wxDbGetConnection(wxDbConnectInf *pDbConfig, bool FwdOnlyCurso if (pList->PtrPrev) pList->PtrPrev->PtrNext = 0; else - PtrBegDbList = 0; // Empty list again - pList->PtrDb->CommitTrans(); // Commit any open transactions on wxDb object - pList->PtrDb->Close(); // Close the wxDb object - delete pList->PtrDb; // Deletes the wxDb object - delete pList; // Deletes the linked list object + PtrBegDbList = 0; // Empty list again + + pList->PtrDb->CommitTrans(); // Commit any open transactions on wxDb object + pList->PtrDb->Close(); // Close the wxDb object + delete pList->PtrDb; // Deletes the wxDb object + delete pList; // Deletes the linked list object return(0); } @@ -3636,7 +4179,7 @@ wxDb WXDLLEXPORT *wxDbGetConnection(wxDbConnectInf *pDbConfig, bool FwdOnlyCurso /********** wxDbFreeConnection() **********/ -bool WXDLLEXPORT wxDbFreeConnection(wxDb *pDb) +bool WXDLLIMPEXP_ODBC wxDbFreeConnection(wxDb *pDb) { wxDbList *pList; @@ -3648,13 +4191,13 @@ bool WXDLLEXPORT wxDbFreeConnection(wxDb *pDb) } // Never found the database object, return failure - return(false); + return false; } // wxDbFreeConnection() /********** wxDbCloseConnections() **********/ -void WXDLLEXPORT wxDbCloseConnections(void) +void WXDLLIMPEXP_ODBC wxDbCloseConnections(void) { wxDbList *pList, *pNext; @@ -3676,7 +4219,7 @@ void WXDLLEXPORT wxDbCloseConnections(void) /********** wxDbConnectionsInUse() **********/ -int WXDLLEXPORT wxDbConnectionsInUse(void) +int WXDLLIMPEXP_ODBC wxDbConnectionsInUse(void) { wxDbList *pList; int cnt = 0; @@ -3696,8 +4239,10 @@ int WXDLLEXPORT wxDbConnectionsInUse(void) /********** wxDbLogExtendedErrorMsg() **********/ // DEBUG ONLY function -const wxChar WXDLLEXPORT *wxDbLogExtendedErrorMsg(const wxChar *userText, wxDb *pDb, - char *ErrFile, int ErrLine) +const wxChar WXDLLIMPEXP_ODBC *wxDbLogExtendedErrorMsg(const wxChar *userText, + wxDb *pDb, + const wxChar *ErrFile, + int ErrLine) { static wxString msg; msg = userText; @@ -3716,7 +4261,7 @@ const wxChar WXDLLEXPORT *wxDbLogExtendedErrorMsg(const wxChar *userText, wxDb * 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++) @@ -3724,11 +4269,11 @@ const wxChar WXDLLEXPORT *wxDbLogExtendedErrorMsg(const wxChar *userText, wxDb * if (pDb->errorList[i]) { msg.Append(pDb->errorList[i]); - if (wxStrcmp(pDb->errorList[i],wxT("")) != 0) + if (wxStrcmp(pDb->errorList[i], wxEmptyString) != 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("")); + wxStrcpy(pDb->errorList[i], wxEmptyString); } } msg += wxT("\n"); @@ -3748,14 +4293,14 @@ bool wxDbSqlLog(wxDbSqlLogState state, const wxChar *filename) for (pList = PtrBegDbList; pList; pList = pList->PtrNext) { if (!pList->PtrDb->SetSqlLogging(state,filename,append)) - return(false); + return false; append = true; } SQLLOGstate = state; SQLLOGfn = filename; - return(true); + return true; } // wxDbSqlLog() @@ -3771,7 +4316,7 @@ int wxDbCreateDataSource(const wxString &driverName, const wxString &dsn, const * ODBC driver must be ODBC 3.0 compliant to use this function */ { - int result = false; + int result = FALSE; //!!!! ONLY FUNCTIONAL UNDER MSW with VC6 !!!! #ifdef __VISUALC__ @@ -3788,7 +4333,7 @@ int wxDbCreateDataSource(const wxString &driverName, const wxString &dsn, const // embedded nulls in strings setupStr.Printf(wxT("DSN=%s%cDescription=%s%cDefaultDir=%s%c"),dsn,2,description,2,defDir,2); - // Replace the separator from above with the '\0' seperator needed + // Replace the separator from above with the '\0' separator needed // by the SQLConfigDataSource() function int k; do @@ -3827,14 +4372,14 @@ int wxDbCreateDataSource(const wxString &driverName, const wxString &dsn, const } } else - result = true; + result = TRUE; #else // Using iODBC/unixODBC or some other compiler which does not support the APIs // necessary to use this function, so this function is not supported #ifdef __WXDEBUG__ wxLogDebug(wxT("wxDbCreateDataSource() not available except under VC++/MSW"),wxT("ODBC DEBUG MESSAGE")); #endif - result = false; + result = FALSE; #endif // __VISUALC__ return result; @@ -3844,20 +4389,22 @@ int wxDbCreateDataSource(const wxString &driverName, const wxString &dsn, const /********** wxDbGetDataSource() **********/ -bool wxDbGetDataSource(HENV henv, wxChar *Dsn, SWORD DsnMax, wxChar *DsDesc, - SWORD DsDescMax, DWORD direction) +bool wxDbGetDataSource(HENV henv, wxChar *Dsn, SWORD DsnMaxLength, wxChar *DsDesc, + SWORD DsDescMaxLength, UWORD direction) /* * Dsn and DsDesc will contain the data source name and data source * description upon return */ { SWORD cb1,cb2; + SWORD lengthDsn = (SWORD)(DsnMaxLength*sizeof(wxChar)); + SWORD lengthDsDesc = (SWORD)(DsDescMaxLength*sizeof(wxChar)); - if (SQLDataSources(henv, direction, (UCHAR FAR *) Dsn, DsnMax, &cb1, - (UCHAR FAR *) DsDesc, DsDescMax, &cb2) == SQL_SUCCESS) - return(true); + if (SQLDataSources(henv, direction, (SQLTCHAR FAR *) Dsn, lengthDsn, &cb1, + (SQLTCHAR FAR *) DsDesc, lengthDsDesc, &cb2) == SQL_SUCCESS) + return true; else - return(false); + return false; } // wxDbGetDataSource() @@ -3868,7 +4415,7 @@ bool wxDbGetDataSource(HENV henv, wxChar *Dsn, SWORD DsnMax, wxChar *DsDesc, ******************************************************************** * * The following functions are all DEPRECATED and are included for - * backward compatability reasons only + * backward compatibility reasons only * ******************************************************************** ********************************************************************/ @@ -3883,22 +4430,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(); }