]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/db.cpp
Correct signature of HitTest()
[wxWidgets.git] / src / common / db.cpp
index da7698256d406799a89615c12d48e4fb0b54807d..cf4f9a28b9b6d4b2c771560cc795b88fd278079c 100644 (file)
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
-// Name:        db.cpp
+// Name:        src/common/db.cpp
 // Purpose:     Implementation of the wxDb class.  The wxDb class represents a connection
 //              to an ODBC data source.  The wxDb class allows operations on the data
 //              source such as opening and closing the data source.
 // Purpose:     Implementation of the wxDb class.  The wxDb class represents a connection
 //              to an ODBC data source.  The wxDb class allows operations on the data
 //              source such as opening and closing the data source.
 // Licence:     wxWindows licence
 ///////////////////////////////////////////////////////////////////////////////
 
 // Licence:     wxWindows licence
 ///////////////////////////////////////////////////////////////////////////////
 
-/*
-// SYNOPSIS START
-// SYNOPSIS STOP
-*/
-#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
-    #pragma implementation "db.h"
-#endif
-
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
     #pragma hdrstop
 #endif
 
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
     #pragma hdrstop
 #endif
 
-#ifdef DBDEBUG_CONSOLE
-    #include "wx/ioswrap.h"
-#endif
+#if wxUSE_ODBC
 
 #ifndef WX_PRECOMP
 
 #ifndef WX_PRECOMP
-    #include "wx/string.h"
     #include "wx/object.h"
     #include "wx/list.h"
     #include "wx/object.h"
     #include "wx/list.h"
+    #include "wx/string.h"
     #include "wx/utils.h"
     #include "wx/log.h"
     #include "wx/utils.h"
     #include "wx/log.h"
+    #include "wx/app.h"
 #endif
 #endif
-#include "wx/filefn.h"
-#include "wx/wxchar.h"
 
 
-#if wxUSE_ODBC
+#ifdef DBDEBUG_CONSOLE
+    #include "wx/ioswrap.h"
+#endif
+
+#include "wx/filefn.h"
+#include "wx/crt.h"
 
 #include <stdio.h>
 #include <string.h>
 
 #include <stdio.h>
 #include <string.h>
 
 #include "wx/db.h"
 
 
 #include "wx/db.h"
 
+// FIXME-UTF8: get rid of this after switching to Unicode-only builds:
+#if wxUSE_UNICODE
+    #define WXSQLCAST(s) ((SQLTCHAR FAR *)(wchar_t*)(s).wchar_str())
+#else
+    #define WXSQLCAST(s) ((SQLTCHAR FAR *)(char*)(s).char_str())
+#endif
+
 // DLL options compatibility check:
 // DLL options compatibility check:
-#include "wx/app.h"
 WX_CHECK_BUILD_OPTIONS("wxODBC")
 
 WXDLLIMPEXP_DATA_ODBC(wxDbList*) PtrBegDbList = 0;
 WX_CHECK_BUILD_OPTIONS("wxODBC")
 
 WXDLLIMPEXP_DATA_ODBC(wxDbList*) PtrBegDbList = 0;
@@ -69,7 +69,10 @@ wxChar const *SQL_LOG_FILENAME         = wxT("sqllog.txt");
 wxChar const *SQL_CATALOG_FILENAME     = wxT("catalog.txt");
 
 #ifdef __WXDEBUG__
 wxChar const *SQL_CATALOG_FILENAME     = wxT("catalog.txt");
 
 #ifdef __WXDEBUG__
+    #include "wx/thread.h"
+
     extern wxList TablesInUse;
     extern wxList TablesInUse;
+    extern wxCriticalSection csTablesInUse;
 #endif
 
 // SQL Log defaults to be used by GetDbConnection
 #endif
 
 // SQL Log defaults to be used by GetDbConnection
@@ -85,7 +88,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
 // 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
 
 
 // This type defines the return row-struct form
@@ -179,7 +182,7 @@ bool wxDbConnectInf::AllocHenv()
     // Initialize the ODBC Environment for Database Operations
     if (SQLAllocEnv(&Henv) != SQL_SUCCESS)
     {
     // 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;
     }
 
         return false;
     }
 
@@ -204,33 +207,37 @@ void wxDbConnectInf::FreeHenv()
 
 void wxDbConnectInf::SetDsn(const wxString &dsn)
 {
 
 void wxDbConnectInf::SetDsn(const wxString &dsn)
 {
-    wxASSERT(dsn.Length() < sizeof(Dsn));
+    wxASSERT(dsn.length() < WXSIZEOF(Dsn));
 
 
-    wxStrcpy(Dsn,dsn);
+    wxStrncpy(Dsn, dsn, WXSIZEOF(Dsn)-1);
+    Dsn[WXSIZEOF(Dsn)-1] = 0;  // Prevent buffer overrun
 }  // wxDbConnectInf::SetDsn()
 
 
 void wxDbConnectInf::SetUserID(const wxString &uid)
 {
 }  // wxDbConnectInf::SetDsn()
 
 
 void wxDbConnectInf::SetUserID(const wxString &uid)
 {
-    wxASSERT(uid.Length() < sizeof(Uid));
-    wxStrcpy(Uid, uid);
+    wxASSERT(uid.length() < WXSIZEOF(Uid));
+    wxStrncpy(Uid, uid, WXSIZEOF(Uid)-1);
+    Uid[WXSIZEOF(Uid)-1] = 0;  // Prevent buffer overrun
 }  // wxDbConnectInf::SetUserID()
 
 
 void wxDbConnectInf::SetPassword(const wxString &password)
 {
 }  // wxDbConnectInf::SetUserID()
 
 
 void wxDbConnectInf::SetPassword(const wxString &password)
 {
-    wxASSERT(password.Length() < sizeof(AuthStr));
+    wxASSERT(password.length() < WXSIZEOF(AuthStr));
 
 
-    wxStrcpy(AuthStr, password);
+    wxStrncpy(AuthStr, password, WXSIZEOF(AuthStr)-1);
+    AuthStr[WXSIZEOF(AuthStr)-1] = 0;  // Prevent buffer overrun
 }  // wxDbConnectInf::SetPassword()
 
 void wxDbConnectInf::SetConnectionStr(const wxString &connectStr)
 {
 }  // wxDbConnectInf::SetPassword()
 
 void wxDbConnectInf::SetConnectionStr(const wxString &connectStr)
 {
-    wxASSERT(connectStr.Length() < sizeof(ConnectionStr));
+    wxASSERT(connectStr.length() < WXSIZEOF(ConnectionStr));
 
     useConnectionStr = wxStrlen(connectStr) > 0;
 
 
     useConnectionStr = wxStrlen(connectStr) > 0;
 
-    wxStrcpy(ConnectionStr, connectStr);
+    wxStrncpy(ConnectionStr, connectStr, WXSIZEOF(ConnectionStr)-1);
+    ConnectionStr[WXSIZEOF(ConnectionStr)-1] = 0;  // Prevent buffer overrun
 }  // wxDbConnectInf::SetConnectionStr()
 
 
 }  // wxDbConnectInf::SetConnectionStr()
 
 
@@ -283,14 +290,23 @@ int wxDbColFor::Format(int Nation, int dbDataType, SWORD sqlDataType,
 
     if (i_dbDataType == 0)                                        // Filter unsupported dbDataTypes
     {
 
     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;
         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)
         if (i_sqlDataType == SQL_REAL)
             i_dbDataType = DB_DATA_TYPE_FLOAT;
         if (i_sqlDataType == SQL_C_BINARY)
@@ -313,8 +329,7 @@ int wxDbColFor::Format(int Nation, int dbDataType, SWORD sqlDataType,
         case DB_DATA_TYPE_FLOAT:
             if (decimalDigits == 0)
                 decimalDigits = 2;
         case DB_DATA_TYPE_FLOAT:
             if (decimalDigits == 0)
                 decimalDigits = 2;
-            tempStr = wxT("%");
-            tempStr.Printf(wxT("%s%d.%d"), tempStr.c_str(),columnLength, decimalDigits);
+            tempStr.Printf(wxT("%%%d.%d"), columnLength, decimalDigits);
             s_Field.Printf(wxT("%sf"), tempStr.c_str());
             break;
         case DB_DATA_TYPE_DATE:
             s_Field.Printf(wxT("%sf"), tempStr.c_str());
             break;
         case DB_DATA_TYPE_DATE:
@@ -523,6 +538,12 @@ void wxDb::initialize()
     typeInfBlob.CaseSensitive = 0;
     typeInfBlob.MaximumScale  = 0;
 
     typeInfBlob.CaseSensitive = 0;
     typeInfBlob.MaximumScale  = 0;
 
+    typeInfMemo.TypeName.Empty();
+    typeInfMemo.FsqlType      = 0;
+    typeInfMemo.Precision     = 0;
+    typeInfMemo.CaseSensitive = 0;
+    typeInfMemo.MaximumScale  = 0;
+
     // Error reporting is turned OFF by default
     silent = true;
 
     // Error reporting is turned OFF by default
     silent = true;
 
@@ -546,7 +567,7 @@ void wxDb::initialize()
 //       immediately, as the value is not good after
 //       this function has left scope.
 //
 //       immediately, as the value is not good after
 //       this function has left scope.
 //
-const wxChar *wxDb::convertUserID(const wxChar *userID, wxString &UserID)
+void wxDb::convertUserID(const wxChar *userID, wxString &UserID)
 {
     if (userID)
     {
 {
     if (userID)
     {
@@ -563,39 +584,92 @@ const wxChar *wxDb::convertUserID(const wxChar *userID, wxString &UserID)
          || Dbms() == dbmsXBASE_SEQUITER )
         UserID.Empty();
 
          || 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();
         UserID = UserID.Upper();
-
-    return UserID.c_str();
 }  // wxDb::convertUserID()
 
 
 }  // wxDb::convertUserID()
 
 
-bool wxDb::open(bool failOnDataTypeUnsupported)
+bool wxDb::determineDataTypes(bool failOnDataTypeUnsupported)
 {
 {
-/*
-    If using Intersolv branded ODBC drivers, this is the place where you would substitute
-    your branded driver license information
+    size_t iIndex;
 
 
-    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 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
+        SQL_VARCHAR,
+#if wxUSE_UNICODE && defined(SQL_WVARCHAR)
+        SQL_WCHAR,
+#endif
+        SQL_CHAR
+    };
 
 
-    // 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 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
+    };
 
 
-    // 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 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
+    };
 
 
-    // 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 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
+    };
+
+    // 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
+    };
+
+    // 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 MEMO column types
+    // (a type which allow to store large strings; like VARCHAR just with a bigger precision)
+    //
+    // 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 PossibleSqlMemoTypes[] = {
+        SQL_LONGVARCHAR,
+    };
 
 
-    // Query the data source for inf. about itself
-    if (!getDbInfo(failOnDataTypeUnsupported))
-        return false;
 
     // Query the data source regarding data type information
 
 
     // Query the data source regarding data type information
 
@@ -604,7 +678,7 @@ bool wxDb::open(bool failOnDataTypeUnsupported)
     // 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
     // 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:
     //
     // 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:
     //
@@ -638,41 +712,41 @@ bool wxDb::open(bool failOnDataTypeUnsupported)
     // SQL_DOUBLE             type name = 'DOUBLE', Precision = 15
     // SQL_INTEGER            type name = 'LONG', Precision = 10
 
     // 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))
-                    {
-                        if (failOnDataTypeUnsupported)
-                            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))
         {
             if (failOnDataTypeUnsupported)
         if (!getDataTypeInfo(typeInfFloat.FsqlType, typeInfInteger))
         {
             if (failOnDataTypeUnsupported)
@@ -681,46 +755,64 @@ bool wxDb::open(bool failOnDataTypeUnsupported)
         else
             typeInfInteger.FsqlType = typeInfFloat.FsqlType;
     }
         else
             typeInfInteger.FsqlType = typeInfFloat.FsqlType;
     }
-    else
-        typeInfInteger.FsqlType = SQL_INTEGER;
 
 
-    // Date/Time
-    if (!getDataTypeInfo(SQL_TIMESTAMP,typeInfDate))
-    {
-        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_DATE;
-    }
-    else
-        typeInfDate.FsqlType = SQL_TIMESTAMP;
+    // --------------- Date/Time ---------------
+    for (iIndex = 0; iIndex < WXSIZEOF(PossibleSqlDateTypes) &&
+                     !getDataTypeInfo(PossibleSqlDateTypes[iIndex], typeInfDate); ++iIndex)
+    {}
 
 
+    if (iIndex < WXSIZEOF(PossibleSqlDateTypes))
+        typeInfDate.FsqlType = PossibleSqlDateTypes[iIndex];
+    else if (failOnDataTypeUnsupported)
+        return false;
 
 
-    if (!getDataTypeInfo(SQL_LONGVARBINARY, typeInfBlob))
-    {
-        if (!getDataTypeInfo(SQL_VARBINARY,typeInfBlob))
-        {
-            if (failOnDataTypeUnsupported)
-                return false;
-        }
-        else
-            typeInfBlob.FsqlType = SQL_VARBINARY;
-    }
-    else
-        typeInfBlob.FsqlType = SQL_LONGVARBINARY;
+    // --------------- 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;
 
 
+    // --------------- MEMO ---------------
+    for (iIndex = 0; iIndex < WXSIZEOF(PossibleSqlMemoTypes) &&
+                     !getDataTypeInfo(PossibleSqlMemoTypes[iIndex], typeInfMemo); ++iIndex)
+    {}
+
+    if (iIndex < WXSIZEOF(PossibleSqlMemoTypes))
+        typeInfMemo.FsqlType = PossibleSqlMemoTypes[iIndex];
+    else if (failOnDataTypeUnsupported)
+        return false;
+
+    return true;
+}  // wxDb::determineDataTypes
+
+
+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;
 
 #ifdef DBDEBUG_CONSOLE
     cout << wxT("VARCHAR DATA TYPE: ") << typeInfVarchar.TypeName << endl;
@@ -728,6 +820,7 @@ bool wxDb::open(bool failOnDataTypeUnsupported)
     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 << wxT("FLOAT   DATA TYPE: ") << typeInfFloat.TypeName << endl;
     cout << wxT("DATE    DATA TYPE: ") << typeInfDate.TypeName << endl;
     cout << wxT("BLOB    DATA TYPE: ") << typeInfBlob.TypeName << endl;
+    cout << wxT("MEMO    DATA TYPE: ") << typeInfMemo.TypeName << endl;
     cout << endl;
 #endif
 
     cout << endl;
 #endif
 
@@ -737,10 +830,15 @@ bool wxDb::open(bool failOnDataTypeUnsupported)
 
 bool wxDb::Open(const wxString& inConnectStr, bool failOnDataTypeUnsupported)
 {
 
 bool wxDb::Open(const wxString& inConnectStr, bool failOnDataTypeUnsupported)
 {
-    wxASSERT(inConnectStr.Length());
-    dsn        = wxT("");
-    uid        = wxT("");
-    authStr    = wxT("");
+    wxASSERT(inConnectStr.length());
+    return Open(inConnectStr, NULL, failOnDataTypeUnsupported);
+}
+
+bool wxDb::Open(const wxString& inConnectStr, SQLHWND parentWnd, bool failOnDataTypeUnsupported)
+{
+    dsn        = wxEmptyString;
+    uid        = wxEmptyString;
+    authStr    = wxEmptyString;
 
     RETCODE retcode;
 
 
     RETCODE retcode;
 
@@ -766,9 +864,9 @@ bool wxDb::Open(const wxString& inConnectStr, bool failOnDataTypeUnsupported)
 
     inConnectionStr = inConnectStr;
 
 
     inConnectionStr = inConnectStr;
 
-    retcode = SQLDriverConnect(hdbc, NULL, (SQLTCHAR FAR *)inConnectionStr.c_str(),
-                        (SWORD)inConnectionStr.Length(), (SQLTCHAR FAR *)outConnectBuffer,
-                        sizeof(outConnectBuffer), &outConnectBufferLen, SQL_DRIVER_COMPLETE );
+    retcode = SQLDriverConnect(hdbc, parentWnd, WXSQLCAST(inConnectionStr),
+                        (SWORD)inConnectionStr.length(), (SQLTCHAR FAR *)outConnectBuffer,
+                        WXSIZEOF(outConnectBuffer), &outConnectBufferLen, SQL_DRIVER_COMPLETE );
 
     if ((retcode != SQL_SUCCESS) &&
         (retcode != SQL_SUCCESS_WITH_INFO))
 
     if ((retcode != SQL_SUCCESS) &&
         (retcode != SQL_SUCCESS_WITH_INFO))
@@ -784,13 +882,13 @@ bool wxDb::Open(const wxString& inConnectStr, bool failOnDataTypeUnsupported)
 /********** wxDb::Open() **********/
 bool wxDb::Open(const wxString &Dsn, const wxString &Uid, const wxString &AuthStr, bool failOnDataTypeUnsupported)
 {
 /********** wxDb::Open() **********/
 bool wxDb::Open(const wxString &Dsn, const wxString &Uid, const wxString &AuthStr, bool failOnDataTypeUnsupported)
 {
-    wxASSERT(Dsn.Length());
+    wxASSERT(!Dsn.empty());
     dsn        = Dsn;
     uid        = Uid;
     authStr    = AuthStr;
 
     dsn        = Dsn;
     uid        = Uid;
     authStr    = AuthStr;
 
-    inConnectionStr = wxT("");
-    outConnectionStr = wxT("");
+    inConnectionStr = wxEmptyString;
+    outConnectionStr = wxEmptyString;
 
     RETCODE retcode;
 
 
     RETCODE retcode;
 
@@ -811,9 +909,10 @@ bool wxDb::Open(const wxString &Dsn, const wxString &Uid, const wxString &AuthSt
     }
 
     // Connect to the data source
     }
 
     // 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);
+    retcode = SQLConnect(hdbc,
+                         WXSQLCAST(dsn), SQL_NTS,
+                         WXSQLCAST(uid), SQL_NTS,
+                         WXSQLCAST(authStr), SQL_NTS);
 
     if ((retcode != SQL_SUCCESS) &&
         (retcode != SQL_SUCCESS_WITH_INFO))
 
     if ((retcode != SQL_SUCCESS) &&
         (retcode != SQL_SUCCESS_WITH_INFO))
@@ -830,7 +929,7 @@ bool wxDb::Open(wxDbConnectInf *dbConnectInf, bool failOnDataTypeUnsupported)
 
     // Use the connection string if one is present
     if (dbConnectInf->UseConnectionStr())
 
     // Use the connection string if one is present
     if (dbConnectInf->UseConnectionStr())
-        return Open(GetConnectionInStr(), failOnDataTypeUnsupported);
+        return Open(dbConnectInf->GetConnectionStr(), failOnDataTypeUnsupported);
     else
         return Open(dbConnectInf->GetDsn(), dbConnectInf->GetUserID(),
                     dbConnectInf->GetPassword(), failOnDataTypeUnsupported);
     else
         return Open(dbConnectInf->GetDsn(), dbConnectInf->GetUserID(),
                     dbConnectInf->GetPassword(), failOnDataTypeUnsupported);
@@ -871,9 +970,9 @@ bool wxDb::Open(wxDb *copyDb)
 
         inConnectionStr = copyDb->GetConnectionInStr();
 
 
         inConnectionStr = copyDb->GetConnectionInStr();
 
-        retcode = SQLDriverConnect(hdbc, NULL, (SQLTCHAR FAR *)inConnectionStr.c_str(),
-                            (SWORD)inConnectionStr.Length(), (SQLTCHAR FAR *)outConnectBuffer,
-                            sizeof(outConnectBuffer), &outConnectBufferLen, SQL_DRIVER_COMPLETE);
+        retcode = SQLDriverConnect(hdbc, NULL, WXSQLCAST(inConnectionStr),
+                            (SWORD)inConnectionStr.length(), (SQLTCHAR FAR *)outConnectBuffer,
+                            WXSIZEOF(outConnectBuffer), &outConnectBufferLen, SQL_DRIVER_COMPLETE);
 
         if ((retcode != SQL_SUCCESS) &&
             (retcode != SQL_SUCCESS_WITH_INFO))
 
         if ((retcode != SQL_SUCCESS) &&
             (retcode != SQL_SUCCESS_WITH_INFO))
@@ -886,9 +985,10 @@ bool wxDb::Open(wxDb *copyDb)
     else
     {
         // Connect to the data source
     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);
+        retcode = SQLConnect(hdbc,
+                             WXSQLCAST(dsn), SQL_NTS,
+                             WXSQLCAST(uid), SQL_NTS,
+                             WXSQLCAST(authStr), SQL_NTS);
     }
 
     if ((retcode != SQL_SUCCESS) &&
     }
 
     if ((retcode != SQL_SUCCESS) &&
@@ -983,12 +1083,20 @@ bool wxDb::Open(wxDb *copyDb)
     typeInfBlob.CaseSensitive    = copyDb->typeInfBlob.CaseSensitive;
     typeInfBlob.MaximumScale     = copyDb->typeInfBlob.MaximumScale;
 
     typeInfBlob.CaseSensitive    = copyDb->typeInfBlob.CaseSensitive;
     typeInfBlob.MaximumScale     = copyDb->typeInfBlob.MaximumScale;
 
+    // Memo
+    typeInfMemo.FsqlType         = copyDb->typeInfMemo.FsqlType;
+    typeInfMemo.TypeName         = copyDb->typeInfMemo.TypeName;
+    typeInfMemo.Precision        = copyDb->typeInfMemo.Precision;
+    typeInfMemo.CaseSensitive    = copyDb->typeInfMemo.CaseSensitive;
+    typeInfMemo.MaximumScale     = copyDb->typeInfMemo.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;
 #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 << wxT("MEMO    DATA TYPE: ") << typeInfMemo.TypeName << endl;
     cout << endl;
 #endif
 
     cout << endl;
 #endif
 
@@ -1013,8 +1121,8 @@ bool wxDb::setConnectionOptions(void)
     if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
         return(DispAllErrors(henv, hdbc));
 
     if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
         return(DispAllErrors(henv, hdbc));
 
-    retcode = SQLSetConnectOption(hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF);
-    retcode = 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
 //  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
@@ -1026,7 +1134,7 @@ bool wxDb::setConnectionOptions(void)
     {
         const long SQL_PRESERVE_CURSORS = 1204L;
         const long SQL_PC_ON = 1L;
     {
         const long SQL_PRESERVE_CURSORS = 1204L;
         const long SQL_PC_ON = 1L;
-        retcode = SQLSetConnectOption(hdbc, SQL_PRESERVE_CURSORS, SQL_PC_ON);
+        /* retcode = */ SQLSetConnectOption(hdbc, SQL_PRESERVE_CURSORS, SQL_PC_ON);
     }
 
     // Display the connection options to verify them
     }
 
     // Display the connection options to verify them
@@ -1541,7 +1649,7 @@ bool wxDb::getDataTypeInfo(SWORD fSqlType, wxDbSqlTypeInfo &structSQLTypeInfo)
  * wxDbSqlTypeInfo is a structure that is filled in with data type information,
  */
     RETCODE retcode;
  * wxDbSqlTypeInfo is a structure that is filled in with data type information,
  */
     RETCODE retcode;
-    SDWORD  cbRet;
+    SQLLEN  cbRet;
 
     // Get information about the data type specified
     if (SQLGetTypeInfo(hstmt, fSqlType) != SQL_SUCCESS)
 
     // Get information about the data type specified
     if (SQLGetTypeInfo(hstmt, fSqlType) != SQL_SUCCESS)
@@ -1553,7 +1661,7 @@ bool wxDb::getDataTypeInfo(SWORD fSqlType, wxDbSqlTypeInfo &structSQLTypeInfo)
     {
 #ifdef DBDEBUG_CONSOLE
         if (retcode == SQL_NO_DATA_FOUND)
     {
 #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);
 #endif
         DispAllErrors(henv, hdbc, hstmt);
         SQLFreeStmt(hstmt, SQL_CLOSE);
@@ -1648,20 +1756,24 @@ void wxDb::Close(void)
     wxASSERT(nTables == 0);
 
 #ifdef __WXDEBUG__
     wxASSERT(nTables == 0);
 
 #ifdef __WXDEBUG__
-    wxTablesInUse *tiu;
-    wxList::compatibility_iterator pNode;
-    pNode = TablesInUse.GetFirst();
-    wxString s,s2;
-    while (pNode)
     {
     {
-        tiu = (wxTablesInUse *)pNode->GetData();
-        if (tiu->pDb == this)
+        wxCriticalSectionLocker lock(csTablesInUse);
+        wxTablesInUse *tiu;
+        wxList::compatibility_iterator pNode;
+        pNode = TablesInUse.GetFirst();
+        wxString s,s2;
+        while (pNode)
         {
         {
-            s.Printf(wxT("(%-20s)     tableID:[%6lu]     pDb:[%p]"), tiu->tableName,tiu->tableID,tiu->pDb);
-            s2.Printf(wxT("Orphaned table found using pDb:[%p]"),this);
-            wxLogDebug(s.c_str(),s2.c_str());
+            tiu = (wxTablesInUse *)pNode->GetData();
+            if (tiu->pDb == this)
+            {
+                s.Printf(wxT("(%-20s)     tableID:[%6lu]     pDb:[%p]"),
+                        tiu->tableName, tiu->tableID, wx_static_cast(void*, tiu->pDb));
+                s2.Printf(wxT("Orphaned table found using pDb:[%p]"), wx_static_cast(void*, this));
+                wxLogDebug(s.c_str(),s2.c_str());
+            }
+            pNode = pNode->GetNext();
         }
         }
-        pNode = pNode->GetNext();
     }
 #endif
 
     }
 #endif
 
@@ -1710,27 +1822,24 @@ 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
 /*
  * 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.
  *
  *
  * 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 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
  * 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;
 
  */
 {
     wxString odbcErrMsg;
 
-#ifdef __VMS
-   while (SQLError(aHenv, aHdbc, aHstmt, (SQLTCHAR FAR *) sqlState, (SQLINTEGER *) &nativeError, (SQLTCHAR FAR *) errorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &cbErrorMsg) == SQL_SUCCESS)
-#else
-   while (SQLError(aHenv, aHdbc, aHstmt, (SQLTCHAR FAR *) sqlState, (long*) &nativeError, (SQLTCHAR FAR *) errorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &cbErrorMsg) == SQL_SUCCESS)
-#endif
+   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);
+        odbcErrMsg.Printf(wxT("SQL State = %s\nNative Error Code = %li\nError Message = %s\n"),
+                          sqlState, (long)nativeError, errorMsg);
         logError(odbcErrMsg, sqlState);
         if (!silent)
         {
         logError(odbcErrMsg, sqlState);
         if (!silent)
         {
@@ -1755,11 +1864,7 @@ bool wxDb::DispAllErrors(HENV aHenv, HDBC aHdbc, HSTMT aHstmt)
 /********** wxDb::GetNextError() **********/
 bool wxDb::GetNextError(HENV aHenv, HDBC aHdbc, HSTMT aHstmt)
 {
 /********** wxDb::GetNextError() **********/
 bool wxDb::GetNextError(HENV aHenv, HDBC aHdbc, HSTMT aHstmt)
 {
-#ifdef __VMS
-   if (SQLError(aHenv, aHdbc, aHstmt, (SQLTCHAR FAR *) sqlState, (SQLINTEGER *) &nativeError, (SQLTCHAR FAR *) errorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &cbErrorMsg) == SQL_SUCCESS)
-#else
-   if (SQLError(aHenv, aHdbc, aHstmt, (SQLTCHAR FAR *) sqlState, (long*) &nativeError, (SQLTCHAR FAR *) errorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &cbErrorMsg) == SQL_SUCCESS)
-#endif
+   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 true;
     else
         return false;
@@ -1772,7 +1877,8 @@ void wxDb::DispNextError(void)
 {
     wxString odbcErrMsg;
 
 {
     wxString odbcErrMsg;
 
-    odbcErrMsg.Printf(wxT("SQL State = %s\nNative Error Code = %li\nError Message = %s\n"), sqlState, nativeError, errorMsg);
+    odbcErrMsg.Printf(wxT("SQL State = %s\nNative Error Code = %li\nError Message = %s\n"),
+                      sqlState, (long)nativeError, errorMsg);
     logError(odbcErrMsg, sqlState);
 
     if (silent)
     logError(odbcErrMsg, sqlState);
 
     if (silent)
@@ -1795,7 +1901,7 @@ void wxDb::DispNextError(void)
 /********** wxDb::logError() **********/
 void wxDb::logError(const wxString &errMsg, const wxString &SQLState)
 {
 /********** wxDb::logError() **********/
 void wxDb::logError(const wxString &errMsg, const wxString &SQLState)
 {
-    wxASSERT(errMsg.Length());
+    wxASSERT(errMsg.length());
 
     static int pLast = -1;
     int dbStatus;
 
     static int pLast = -1;
     int dbStatus;
@@ -1803,14 +1909,15 @@ void wxDb::logError(const wxString &errMsg, const wxString &SQLState)
     if (++pLast == DB_MAX_ERROR_HISTORY)
     {
         int i;
     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[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 (SQLState.length())
         if ((dbStatus = TranslateSqlState(SQLState)) != DB_ERR_FUNCTION_SEQUENCE_ERROR)
             DB_STATUS = dbStatus;
 
         if ((dbStatus = TranslateSqlState(SQLState)) != DB_ERR_FUNCTION_SEQUENCE_ERROR)
             DB_STATUS = dbStatus;
 
@@ -2075,7 +2182,7 @@ bool wxDb::CreateView(const wxString &viewName, const wxString &colList,
     sqlStmt  = wxT("CREATE VIEW ");
     sqlStmt += viewName;
 
     sqlStmt  = wxT("CREATE VIEW ");
     sqlStmt += viewName;
 
-    if (colList.Length())
+    if (colList.length())
     {
         sqlStmt += wxT(" (");
         sqlStmt += colList;
     {
         sqlStmt += wxT(" (");
         sqlStmt += colList;
@@ -2115,7 +2222,7 @@ bool wxDb::DropView(const wxString &viewName)
     cout << endl << sqlStmt.c_str() << endl;
 #endif
 
     cout << endl << sqlStmt.c_str() << endl;
 #endif
 
-    if (SQLExecDirect(hstmt, (SQLTCHAR FAR *) sqlStmt.c_str(), SQL_NTS) != SQL_SUCCESS)
+    if (SQLExecDirect(hstmt, WXSQLCAST(sqlStmt), SQL_NTS) != SQL_SUCCESS)
     {
         // Check for "Base table not found" error and ignore
         GetNextError(henv, hdbc, hstmt);
     {
         // Check for "Base table not found" error and ignore
         GetNextError(henv, hdbc, hstmt);
@@ -2148,7 +2255,7 @@ bool wxDb::ExecSql(const wxString &pSqlStmt)
 
     SQLFreeStmt(hstmt, SQL_CLOSE);
 
 
     SQLFreeStmt(hstmt, SQL_CLOSE);
 
-    retcode = SQLExecDirect(hstmt, (SQLTCHAR FAR *) pSqlStmt.c_str(), SQL_NTS);
+    retcode = SQLExecDirect(hstmt, WXSQLCAST(pSqlStmt), SQL_NTS);
     if (retcode == SQL_SUCCESS ||
         (Dbms() == dbmsDB2 && (retcode == SQL_SUCCESS_WITH_INFO || retcode == SQL_NO_DATA_FOUND)))
     {
     if (retcode == SQL_SUCCESS ||
         (Dbms() == dbmsDB2 && (retcode == SQL_SUCCESS_WITH_INFO || retcode == SQL_NO_DATA_FOUND)))
     {
@@ -2163,6 +2270,105 @@ bool wxDb::ExecSql(const wxString &pSqlStmt)
 }  // wxDb::ExecSql()
 
 
 }  // 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;
+    SQLLEN Sqllen;
+    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, &Sqllen) != 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, &Sqllen) != SQL_SUCCESS)
+        {
+            DispAllErrors(henv, hdbc, hstmt);
+            delete[] pColInf;
+            return false;
+        }
+
+        switch (Sqllen)
+        {
+#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_LONGVARCHAR:
+                pColInf[colNum].dbDataType = DB_DATA_TYPE_MEMO;
+                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)Sqllen);
+                wxLogDebug(errMsg,wxT("ODBC DEBUG MESSAGE"));
+#endif
+        }
+    }
+
+    *columns = pColInf;
+    return true;
+}  // wxDb::ExecSql()
+
 /********** wxDb::GetNext()  **********/
 bool wxDb::GetNext(void)
 {
 /********** wxDb::GetNext()  **********/
 bool wxDb::GetNext(void)
 {
@@ -2178,7 +2384,7 @@ bool wxDb::GetNext(void)
 
 
 /********** wxDb::GetData()  **********/
 
 
 /********** wxDb::GetData()  **********/
-bool wxDb::GetData(UWORD colNo, SWORD cType, PTR pData, SDWORD maxLen, SDWORD FAR *cbReturned)
+bool wxDb::GetData(UWORD colNo, SWORD cType, PTR pData, SDWORD maxLen, SQLLEN FAR *cbReturned)
 {
     wxASSERT(pData);
     wxASSERT(cbReturned);
 {
     wxASSERT(pData);
     wxASSERT(cbReturned);
@@ -2205,11 +2411,10 @@ 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 */
     SWORD        iKeySeq;
     wxChar       szPkTable[DB_MAX_TABLE_NAME_LEN+1];  /* Primary key table name */
     wxChar       szFkTable[DB_MAX_TABLE_NAME_LEN+1];  /* Foreign key table name */
     SWORD        iKeySeq;
-//    SQLSMALLINT  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;
     wxChar       szPkCol[DB_MAX_COLUMN_NAME_LEN+1];   /* Primary key column     */
     wxChar       szFkCol[DB_MAX_COLUMN_NAME_LEN+1];   /* Foreign key column     */
     SQLRETURN    retcode;
-    SDWORD       cb;
+    SQLLEN       cb;
     SWORD        i;
     wxString     tempStr;
     /*
     SWORD        i;
     wxString     tempStr;
     /*
@@ -2231,7 +2436,7 @@ int wxDb::GetKeyFields(const wxString &tableName, wxDbColInf* colInf, UWORD noCo
     retcode = SQLPrimaryKeys(hstmt,
                              NULL, 0,                               /* Catalog name  */
                              NULL, 0,                               /* Schema name   */
     retcode = SQLPrimaryKeys(hstmt,
                              NULL, 0,                               /* Catalog name  */
                              NULL, 0,                               /* Schema name   */
-                             (SQLTCHAR FAR *) tableName.c_str(), SQL_NTS); /* Table name    */
+                             WXSQLCAST(tableName), SQL_NTS); /* Table name    */
 
     /*---------------------------------------------------------------------*/
     /* Fetch and display the result set. This will be a list of the        */
 
     /*---------------------------------------------------------------------*/
     /* Fetch and display the result set. This will be a list of the        */
@@ -2258,7 +2463,7 @@ int wxDb::GetKeyFields(const wxString &tableName, wxDbColInf* colInf, UWORD noCo
     retcode = SQLForeignKeys(hstmt,
                              NULL, 0,                            /* Primary catalog */
                              NULL, 0,                            /* Primary schema  */
     retcode = SQLForeignKeys(hstmt,
                              NULL, 0,                            /* Primary catalog */
                              NULL, 0,                            /* Primary schema  */
-                             (SQLTCHAR FAR *)tableName.c_str(), SQL_NTS,/* Primary table   */
+                             WXSQLCAST(tableName), SQL_NTS,/* Primary table   */
                              NULL, 0,                            /* Foreign catalog */
                              NULL, 0,                            /* Foreign schema  */
                              NULL, 0);                           /* Foreign table   */
                              NULL, 0,                            /* Foreign catalog */
                              NULL, 0,                            /* Foreign schema  */
                              NULL, 0);                           /* Foreign table   */
@@ -2279,17 +2484,20 @@ int wxDb::GetKeyFields(const wxString &tableName, wxDbColInf* colInf, UWORD noCo
             GetData( 5, SQL_C_SSHORT, &iKeySeq,     0,                         &cb);
             GetData( 7, SQL_C_WXCHAR,  szFkTable,   DB_MAX_TABLE_NAME_LEN+1,   &cb);
             GetData( 8, SQL_C_WXCHAR,  szFkCol,     DB_MAX_COLUMN_NAME_LEN+1,  &cb);
             GetData( 5, SQL_C_SSHORT, &iKeySeq,     0,                         &cb);
             GetData( 7, SQL_C_WXCHAR,  szFkTable,   DB_MAX_TABLE_NAME_LEN+1,   &cb);
             GetData( 8, SQL_C_WXCHAR,  szFkCol,     DB_MAX_COLUMN_NAME_LEN+1,  &cb);
-            tempStr.Printf(wxT("%s[%s] "),tempStr.c_str(),szFkTable);  // [ ] in case there is a blank in the Table name
+            tempStr << _T('[') << szFkTable << _T(']');  // [ ] in case there is a blank in the Table name
         }  // if
     }  // while
 
     tempStr.Trim();     // Get rid of any unneeded blanks
         }  // if
     }  // while
 
     tempStr.Trim();     // Get rid of any unneeded blanks
-    if (!tempStr.IsEmpty())
+    if (!tempStr.empty())
     {
         for (i=0; i<noCols; i++)
         {   // Find the Column name
             if (!wxStrcmp(colInf[i].colName, szPkCol))           // We have found the Column, store the Information
     {
         for (i=0; i<noCols; i++)
         {   // Find the Column name
             if (!wxStrcmp(colInf[i].colName, szPkCol))           // We have found the Column, store the Information
-                wxStrcpy(colInf[i].PkTableName, tempStr.c_str());  // Name of the Tables where this Primary Key is used as a Foreign Key
+            {
+                wxStrncpy(colInf[i].PkTableName, tempStr.c_str(), DB_MAX_TABLE_NAME_LEN);  // Name of the Tables where this Primary Key is used as a Foreign Key
+                colInf[i].PkTableName[DB_MAX_TABLE_NAME_LEN] = 0;  // Prevent buffer overrun
+            }
         }
     }  // if
 
         }
     }  // if
 
@@ -2304,7 +2512,7 @@ int wxDb::GetKeyFields(const wxString &tableName, wxDbColInf* colInf, UWORD noCo
                              NULL, 0,                             /* Primary table     */
                              NULL, 0,                             /* Foreign catalog   */
                              NULL, 0,                             /* Foreign schema    */
                              NULL, 0,                             /* Primary table     */
                              NULL, 0,                             /* Foreign catalog   */
                              NULL, 0,                             /* Foreign schema    */
-                             (SQLTCHAR *)tableName.c_str(), SQL_NTS);/* Foreign table     */
+                             WXSQLCAST(tableName), SQL_NTS);/* Foreign table     */
 
     /*---------------------------------------------------------------------*/
     /*  Fetch and display the result set. This will be all of the          */
 
     /*---------------------------------------------------------------------*/
     /*  Fetch and display the result set. This will be all of the          */
@@ -2325,7 +2533,8 @@ int wxDb::GetKeyFields(const wxString &tableName, wxDbColInf* colInf, UWORD noCo
                 if (!wxStrcmp(colInf[i].colName,szFkCol))       // We have found the (Foreign Key) Column
                 {
                     colInf[i].FkCol = iKeySeq;                  // Which Foreign Key is this (first, second usw.) ?
                 if (!wxStrcmp(colInf[i].colName,szFkCol))       // We have found the (Foreign Key) Column
                 {
                     colInf[i].FkCol = iKeySeq;                  // Which Foreign Key is this (first, second usw.) ?
-                    wxStrcpy(colInf[i].FkTableName,szPkTable);  // Name of the Table where this Foriegn is the Primary Key
+                    wxStrncpy(colInf[i].FkTableName, szFkTable, DB_MAX_TABLE_NAME_LEN);  // Name of the Table where this Foriegn is the Primary Key
+                    colInf[i].FkTableName[DB_MAX_TABLE_NAME_LEN] = 0;  // Prevent buffer overrun
                 } // if
             }  // for
         }  // if
                 } // if
             }  // for
         }  // if
@@ -2344,7 +2553,7 @@ wxDbColInf *wxDb::GetColumns(wxChar *tableName[], const wxChar *userID)
  *        1) The last array element of the tableName[] argument must be zero (null).
  *            This is how the end of the array is detected.
  *        2) This function returns an array of wxDbColInf structures.  If no columns
  *        1) The last array element of the tableName[] argument must be zero (null).
  *            This is how the end of the array is detected.
  *        2) This function returns an array of wxDbColInf structures.  If no columns
- *            were found, or an error occured, this pointer will be zero (null).  THE
+ *            were found, or an error occurred, this pointer will be zero (null).  THE
  *            CALLING FUNCTION IS RESPONSIBLE FOR DELETING THE MEMORY RETURNED WHEN IT
  *            IS FINISHED WITH IT.  i.e.
  *
  *            CALLING FUNCTION IS RESPONSIBLE FOR DELETING THE MEMORY RETURNED WHEN IT
  *            IS FINISHED WITH IT.  i.e.
  *
@@ -2372,7 +2581,7 @@ wxDbColInf *wxDb::GetColumns(wxChar *tableName[], const wxChar *userID)
     wxDbColInf *colInf = 0;
 
     RETCODE  retcode;
     wxDbColInf *colInf = 0;
 
     RETCODE  retcode;
-    SDWORD   cb;
+    SQLLEN   cb;
 
     wxString TableName;
 
 
     wxString TableName;
 
@@ -2394,8 +2603,8 @@ wxDbColInf *wxDb::GetColumns(wxChar *tableName[], const wxChar *userID)
             if (!colInf)
                 break;
             // Mark the end of the array
             if (!colInf)
                 break;
             // Mark the end of the array
-            wxStrcpy(colInf[noCols].tableName,wxEmptyString);
-            wxStrcpy(colInf[noCols].colName,wxEmptyString);
+            wxStrcpy(colInf[noCols].tableName, wxEmptyString);
+            wxStrcpy(colInf[noCols].colName, wxEmptyString);
             colInf[noCols].sqlDataType = 0;
         }
         // Loop through each table name
             colInf[noCols].sqlDataType = 0;
         }
         // Loop through each table name
@@ -2406,6 +2615,7 @@ wxDbColInf *wxDb::GetColumns(wxChar *tableName[], const wxChar *userID)
             // 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) ||
             // 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();
 
                 (Dbms() == dbmsINTERBASE))
                 TableName = TableName.Upper();
 
@@ -2413,15 +2623,15 @@ wxDbColInf *wxDb::GetColumns(wxChar *tableName[], const wxChar *userID)
 
             // MySQL, SQLServer, and Access cannot accept a user name when looking up column names, so we
             // use the call below that leaves out the user name
 
             // MySQL, SQLServer, and Access cannot accept a user name when looking up column 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)
             {
                 retcode = SQLColumns(hstmt,
                                      NULL, 0,                                // All qualifiers
                 Dbms() != dbmsMY_SQL &&
                 Dbms() != dbmsACCESS &&
                 Dbms() != dbmsMS_SQL_SERVER)
             {
                 retcode = SQLColumns(hstmt,
                                      NULL, 0,                                // All qualifiers
-                                     (SQLTCHAR *) UserID.c_str(), SQL_NTS,      // Owner
-                                     (SQLTCHAR *) TableName.c_str(), SQL_NTS,
+                                     WXSQLCAST(UserID), SQL_NTS,      // Owner
+                                     WXSQLCAST(TableName), SQL_NTS,
                                      NULL, 0);                               // All columns
             }
             else
                                      NULL, 0);                               // All columns
             }
             else
@@ -2429,11 +2639,11 @@ wxDbColInf *wxDb::GetColumns(wxChar *tableName[], const wxChar *userID)
                 retcode = SQLColumns(hstmt,
                                      NULL, 0,                                // All qualifiers
                                      NULL, 0,                                // Owner
                 retcode = SQLColumns(hstmt,
                                      NULL, 0,                                // All qualifiers
                                      NULL, 0,                                // Owner
-                                     (SQLTCHAR *) TableName.c_str(), SQL_NTS,
+                                     WXSQLCAST(TableName), SQL_NTS,
                                      NULL, 0);                               // All columns
             }
             if (retcode != SQL_SUCCESS)
                                      NULL, 0);                               // All columns
             }
             if (retcode != SQL_SUCCESS)
-            {  // Error occured, abort
+            {  // Error occurred, abort
                 DispAllErrors(henv, hdbc, hstmt);
                 if (colInf)
                     delete [] colInf;
                 DispAllErrors(henv, hdbc, hstmt);
                 if (colInf)
                     delete [] colInf;
@@ -2491,7 +2701,7 @@ wxDbColInf *wxDb::GetColumns(wxChar *tableName[], const wxChar *userID)
                 }
             }
             if (retcode != SQL_NO_DATA_FOUND)
                 }
             }
             if (retcode != SQL_NO_DATA_FOUND)
-            {  // Error occured, abort
+            {  // Error occurred, abort
                 DispAllErrors(henv, hdbc, hstmt);
                 if (colInf)
                     delete [] colInf;
                 DispAllErrors(henv, hdbc, hstmt);
                 if (colInf)
                     delete [] colInf;
@@ -2530,7 +2740,7 @@ wxDbColInf *wxDb::GetColumns(const wxString &tableName, UWORD *numCols, const wx
     wxDbColInf *colInf = 0;
 
     RETCODE  retcode;
     wxDbColInf *colInf = 0;
 
     RETCODE  retcode;
-    SDWORD   cb;
+    SQLLEN   cb;
 
     wxString TableName;
 
 
     wxString TableName;
 
@@ -2554,13 +2764,14 @@ wxDbColInf *wxDb::GetColumns(const wxString &tableName, UWORD *numCols, const wx
             // Mark the end of the array
             wxStrcpy(colInf[noCols].tableName, wxEmptyString);
             wxStrcpy(colInf[noCols].colName, wxEmptyString);
             // Mark the end of the array
             wxStrcpy(colInf[noCols].tableName, wxEmptyString);
             wxStrcpy(colInf[noCols].colName, wxEmptyString);
-            colInf[noCols].sqlDataType  = 0;
+            colInf[noCols].sqlDataType = 0;
         }
 
         TableName = tableName;
         // 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) ||
         }
 
         TableName = tableName;
         // 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();
 
             (Dbms() == dbmsINTERBASE))
             TableName = TableName.Upper();
 
@@ -2568,15 +2779,15 @@ wxDbColInf *wxDb::GetColumns(const wxString &tableName, UWORD *numCols, const wx
 
         // MySQL, SQLServer, and Access cannot accept a user name when looking up column names, so we
         // use the call below that leaves out the user name
 
         // MySQL, SQLServer, and Access cannot accept a user name when looking up column 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)
         {
             retcode = SQLColumns(hstmt,
                                  NULL, 0,                                // All qualifiers
             Dbms() != dbmsMY_SQL &&
             Dbms() != dbmsACCESS &&
             Dbms() != dbmsMS_SQL_SERVER)
         {
             retcode = SQLColumns(hstmt,
                                  NULL, 0,                                // All qualifiers
-                                 (SQLTCHAR *) UserID.c_str(), SQL_NTS,    // Owner
-                                 (SQLTCHAR *) TableName.c_str(), SQL_NTS,
+                                 WXSQLCAST(UserID), SQL_NTS,    // Owner
+                                 WXSQLCAST(TableName), SQL_NTS,
                                  NULL, 0);                               // All columns
         }
         else
                                  NULL, 0);                               // All columns
         }
         else
@@ -2584,11 +2795,11 @@ wxDbColInf *wxDb::GetColumns(const wxString &tableName, UWORD *numCols, const wx
             retcode = SQLColumns(hstmt,
                                  NULL, 0,                                 // All qualifiers
                                  NULL, 0,                                 // Owner
             retcode = SQLColumns(hstmt,
                                  NULL, 0,                                 // All qualifiers
                                  NULL, 0,                                 // Owner
-                                 (SQLTCHAR *) TableName.c_str(), SQL_NTS,
+                                 WXSQLCAST(TableName), SQL_NTS,
                                  NULL, 0);                                // All columns
         }
         if (retcode != SQL_SUCCESS)
                                  NULL, 0);                                // All columns
         }
         if (retcode != SQL_SUCCESS)
-        {  // Error occured, abort
+        {  // Error occurred, abort
             DispAllErrors(henv, hdbc, hstmt);
             if (colInf)
                 delete [] colInf;
             DispAllErrors(henv, hdbc, hstmt);
             if (colInf)
                 delete [] colInf;
@@ -2664,7 +2875,7 @@ wxDbColInf *wxDb::GetColumns(const wxString &tableName, UWORD *numCols, const wx
             }
         }
         if (retcode != SQL_NO_DATA_FOUND)
             }
         }
         if (retcode != SQL_NO_DATA_FOUND)
-        {  // Error occured, abort
+        {  // Error occurred, abort
             DispAllErrors(henv, hdbc, hstmt);
             if (colInf)
                 delete [] colInf;
             DispAllErrors(henv, hdbc, hstmt);
             if (colInf)
                 delete [] colInf;
@@ -2693,7 +2904,7 @@ wxDbColInf *wxDb::GetColumns(const wxString &tableName, UWORD *numCols, const wx
 /*
     BJO 20000503
     These are tentative new GetColumns members which should be more database
 /*
     BJO 20000503
     These are tentative new GetColumns members which should be more database
-    independant and which always returns the columns in the order they were
+    independent and which always returns the columns in the order they were
     created.
 
     - The first one (wxDbColInf *wxDb::GetColumns(wxChar *tableName[], const
     created.
 
     - The first one (wxDbColInf *wxDb::GetColumns(wxChar *tableName[], const
@@ -2746,7 +2957,7 @@ wxDbColInf *wxDb::GetColumns(wxChar *tableName[], const wxChar *userID)
     // Mark the end of the array
     wxStrcpy(colInf[noCols].tableName, wxEmptyString);
     wxStrcpy(colInf[noCols].colName, wxEmptyString);
     // Mark the end of the array
     wxStrcpy(colInf[noCols].tableName, wxEmptyString);
     wxStrcpy(colInf[noCols].colName, wxEmptyString);
-    colInf[noCols].sqlDataType  = 0;
+    colInf[noCols].sqlDataType = 0;
 
     // Merge ...
     int offset = 0;
 
     // Merge ...
     int offset = 0;
@@ -2816,6 +3027,7 @@ wxDbColInf *wxDb::GetColumns(const wxString &tableName, int *numCols, const wxCh
         // 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) ||
         // 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();
 
             (Dbms() == dbmsINTERBASE))
             TableName = TableName.Upper();
 
@@ -2823,7 +3035,7 @@ wxDbColInf *wxDb::GetColumns(const wxString &tableName, int *numCols, const wxCh
 
         // MySQL, SQLServer, and Access cannot accept a user name when looking up column names, so we
         // use the call below that leaves out the user name
 
         // MySQL, SQLServer, and Access cannot accept a user name when looking up column 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() != dbmsMY_SQL &&
             Dbms() != dbmsACCESS &&
             Dbms() != dbmsMS_SQL_SERVER)
@@ -2843,7 +3055,7 @@ wxDbColInf *wxDb::GetColumns(const wxString &tableName, int *numCols, const wxCh
                                  NULL, 0);                             // All columns
         }
         if (retcode != SQL_SUCCESS)
                                  NULL, 0);                             // All columns
         }
         if (retcode != SQL_SUCCESS)
-        {  // Error occured, abort
+        {  // Error occurred, abort
             DispAllErrors(henv, hdbc, hstmt);
             if (colInf)
                 delete [] colInf;
             DispAllErrors(henv, hdbc, hstmt);
             if (colInf)
                 delete [] colInf;
@@ -2895,14 +3107,25 @@ wxDbColInf *wxDb::GetColumns(const wxString &tableName, int *numCols, const wxCh
                     // Get the intern datatype
                     switch (colInf[colNo].sqlDataType)
                     {
                     // Get the intern datatype
                     switch (colInf[colNo].sqlDataType)
                     {
+#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:
                             colInf[colNo].dbDataType = DB_DATA_TYPE_VARCHAR;
                         break;
                         case SQL_VARCHAR:
                         case SQL_CHAR:
                             colInf[colNo].dbDataType = DB_DATA_TYPE_VARCHAR;
                         break;
-
+                        case SQL_LONGVARCHAR:
+                            colInf[colNo].dbDataType = DB_DATA_TYPE_MEMO;
+                            break;
                         case SQL_TINYINT:
                         case SQL_SMALLINT:
                         case SQL_INTEGER:
                         case SQL_TINYINT:
                         case SQL_SMALLINT:
                         case SQL_INTEGER:
+                        case SQL_BIT:
                             colInf[colNo].dbDataType = DB_DATA_TYPE_INTEGER;
                             break;
                         case SQL_DOUBLE:
                             colInf[colNo].dbDataType = DB_DATA_TYPE_INTEGER;
                             break;
                         case SQL_DOUBLE:
@@ -2913,6 +3136,7 @@ wxDbColInf *wxDb::GetColumns(const wxString &tableName, int *numCols, const wxCh
                             colInf[colNo].dbDataType = DB_DATA_TYPE_FLOAT;
                             break;
                         case SQL_DATE:
                             colInf[colNo].dbDataType = DB_DATA_TYPE_FLOAT;
                             break;
                         case SQL_DATE:
+                        case SQL_TIMESTAMP:
                             colInf[colNo].dbDataType = DB_DATA_TYPE_DATE;
                             break;
                         case SQL_BINARY:
                             colInf[colNo].dbDataType = DB_DATA_TYPE_DATE;
                             break;
                         case SQL_BINARY:
@@ -2930,7 +3154,7 @@ wxDbColInf *wxDb::GetColumns(const wxString &tableName, int *numCols, const wxCh
             }
         }
         if (retcode != SQL_NO_DATA_FOUND)
             }
         }
         if (retcode != SQL_NO_DATA_FOUND)
-        {  // Error occured, abort
+        {  // Error occurred, abort
             DispAllErrors(henv, hdbc, hstmt);
             if (colInf)
                 delete [] colInf;
             DispAllErrors(henv, hdbc, hstmt);
             if (colInf)
                 delete [] colInf;
@@ -3054,6 +3278,7 @@ int wxDb::GetColumnCount(const wxString &tableName, const wxChar *userID)
     // 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) ||
     // 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();
 
         (Dbms() == dbmsINTERBASE))
         TableName = TableName.Upper();
 
@@ -3061,15 +3286,15 @@ int wxDb::GetColumnCount(const wxString &tableName, const wxChar *userID)
 
     // MySQL, SQLServer, and Access cannot accept a user name when looking up column names, so we
     // use the call below that leaves out the user name
 
     // MySQL, SQLServer, and Access cannot accept a user name when looking up column 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)
     {
         retcode = SQLColumns(hstmt,
                              NULL, 0,                                // All qualifiers
         Dbms() != dbmsMY_SQL &&
         Dbms() != dbmsACCESS &&
         Dbms() != dbmsMS_SQL_SERVER)
     {
         retcode = SQLColumns(hstmt,
                              NULL, 0,                                // All qualifiers
-                             (SQLTCHAR *) UserID.c_str(), SQL_NTS,      // Owner
-                             (SQLTCHAR *) TableName.c_str(), SQL_NTS,
+                             WXSQLCAST(UserID), SQL_NTS,      // Owner
+                             WXSQLCAST(TableName), SQL_NTS,
                              NULL, 0);                               // All columns
     }
     else
                              NULL, 0);                               // All columns
     }
     else
@@ -3077,11 +3302,11 @@ int wxDb::GetColumnCount(const wxString &tableName, const wxChar *userID)
         retcode = SQLColumns(hstmt,
                              NULL, 0,                                // All qualifiers
                              NULL, 0,                                // Owner
         retcode = SQLColumns(hstmt,
                              NULL, 0,                                // All qualifiers
                              NULL, 0,                                // Owner
-                             (SQLTCHAR *) TableName.c_str(), SQL_NTS,
+                             WXSQLCAST(TableName), SQL_NTS,
                              NULL, 0);                               // All columns
     }
     if (retcode != SQL_SUCCESS)
                              NULL, 0);                               // All columns
     }
     if (retcode != SQL_SUCCESS)
-    {  // Error occured, abort
+    {  // Error occurred, abort
         DispAllErrors(henv, hdbc, hstmt);
         SQLFreeStmt(hstmt, SQL_CLOSE);
         return(-1);
         DispAllErrors(henv, hdbc, hstmt);
         SQLFreeStmt(hstmt, SQL_CLOSE);
         return(-1);
@@ -3092,7 +3317,7 @@ int wxDb::GetColumnCount(const wxString &tableName, const wxChar *userID)
         noCols++;
 
     if (retcode != SQL_NO_DATA_FOUND)
         noCols++;
 
     if (retcode != SQL_NO_DATA_FOUND)
-    {  // Error occured, abort
+    {  // Error occurred, abort
         DispAllErrors(henv, hdbc, hstmt);
         SQLFreeStmt(hstmt, SQL_CLOSE);
         return(-1);
         DispAllErrors(henv, hdbc, hstmt);
         SQLFreeStmt(hstmt, SQL_CLOSE);
         return(-1);
@@ -3113,7 +3338,7 @@ wxDbInf *wxDb::GetCatalog(const wxChar *userID)
  * --          : uses SQLTables and fills pTableInf;              ------
  * --          : pColInf is set to NULL and numCols to 0;         ------
  * --          : returns pDbInf (wxDbInf)                         ------
  * --          : uses SQLTables and fills pTableInf;              ------
  * --          : pColInf is set to NULL and numCols to 0;         ------
  * --          : returns pDbInf (wxDbInf)                         ------
- * --            - if unsuccesfull (pDbInf == NULL)               ------
+ * --            - if unsuccessful (pDbInf == NULL)               ------
  * --          : pColInf can be filled with GetColumns(..);       ------
  * --          : numCols   can be filled with GetColumnCount(..); ------
  * ---------------------------------------------------------------------
  * --          : pColInf can be filled with GetColumns(..);       ------
  * --          : numCols   can be filled with GetColumnCount(..); ------
  * ---------------------------------------------------------------------
@@ -3131,7 +3356,7 @@ wxDbInf *wxDb::GetCatalog(const wxChar *userID)
     int      noTab = 0;     // Counter while filling table entries
     int      pass;
     RETCODE  retcode;
     int      noTab = 0;     // Counter while filling table entries
     int      pass;
     RETCODE  retcode;
-    SDWORD   cb;
+    SQLLEN   cb;
     wxString tblNameSave;
 
     wxString UserID;
     wxString tblNameSave;
 
     wxString UserID;
@@ -3154,14 +3379,14 @@ wxDbInf *wxDb::GetCatalog(const wxChar *userID)
         SQLFreeStmt(hstmt, SQL_CLOSE);   // Close if Open
         tblNameSave.Empty();
 
         SQLFreeStmt(hstmt, SQL_CLOSE);   // Close if Open
         tblNameSave.Empty();
 
-        if (!UserID.IsEmpty() &&
+        if (!UserID.empty() &&
             Dbms() != dbmsMY_SQL &&
             Dbms() != dbmsACCESS &&
             Dbms() != dbmsMS_SQL_SERVER)
         {
             retcode = SQLTables(hstmt,
                                 NULL, 0,                             // All qualifiers
             Dbms() != dbmsMY_SQL &&
             Dbms() != dbmsACCESS &&
             Dbms() != dbmsMS_SQL_SERVER)
         {
             retcode = SQLTables(hstmt,
                                 NULL, 0,                             // All qualifiers
-                                (SQLTCHAR *) UserID.c_str(), SQL_NTS,   // User specified
+                                WXSQLCAST(UserID), SQL_NTS,   // User specified
                                 NULL, 0,                             // All tables
                                 NULL, 0);                            // All columns
         }
                                 NULL, 0,                             // All tables
                                 NULL, 0);                            // All columns
         }
@@ -3239,10 +3464,10 @@ bool wxDb::Catalog(const wxChar *userID, const wxString &fileName)
  *       to avoid undesired unbinding of columns.
  */
 {
  *       to avoid undesired unbinding of columns.
  */
 {
-    wxASSERT(fileName.Length());
+    wxASSERT(fileName.length());
 
     RETCODE   retcode;
 
     RETCODE   retcode;
-    SDWORD    cb;
+    SQLLEN    cb;
     wxChar    tblName[DB_MAX_TABLE_NAME_LEN+1];
     wxString  tblNameSave;
     wxChar    colName[DB_MAX_COLUMN_NAME_LEN+1];
     wxChar    tblName[DB_MAX_TABLE_NAME_LEN+1];
     wxString  tblNameSave;
     wxChar    colName[DB_MAX_COLUMN_NAME_LEN+1];
@@ -3259,15 +3484,16 @@ bool wxDb::Catalog(const wxChar *userID, const wxString &fileName)
     wxString UserID;
     convertUserID(userID,UserID);
 
     wxString UserID;
     convertUserID(userID,UserID);
 
-    if (!UserID.IsEmpty() &&
+    if (!UserID.empty() &&
         Dbms() != dbmsMY_SQL &&
         Dbms() != dbmsACCESS &&
         Dbms() != dbmsMY_SQL &&
         Dbms() != dbmsACCESS &&
+        Dbms() != dbmsFIREBIRD &&
         Dbms() != dbmsINTERBASE &&
         Dbms() != dbmsMS_SQL_SERVER)
     {
         retcode = SQLColumns(hstmt,
                              NULL, 0,                                // All qualifiers
         Dbms() != dbmsINTERBASE &&
         Dbms() != dbmsMS_SQL_SERVER)
     {
         retcode = SQLColumns(hstmt,
                              NULL, 0,                                // All qualifiers
-                             (SQLTCHAR *) UserID.c_str(), SQL_NTS,      // User specified
+                             WXSQLCAST(UserID), SQL_NTS,      // User specified
                              NULL, 0,                                // All tables
                              NULL, 0);                               // All columns
     }
                              NULL, 0,                                // All tables
                              NULL, 0);                               // All columns
     }
@@ -3358,14 +3584,14 @@ bool wxDb::TableExists(const wxString &tableName, const wxChar *userID, const wx
  *        userID != ""    ... UserID set equal to 'userID'
  */
 {
  *        userID != ""    ... UserID set equal to 'userID'
  */
 {
-    wxASSERT(tableName.Length());
+    wxASSERT(tableName.length());
 
     wxString TableName;
 
     if (Dbms() == dbmsDBASE)
     {
         wxString dbName;
 
     wxString TableName;
 
     if (Dbms() == dbmsDBASE)
     {
         wxString dbName;
-        if (tablePath.Length())
+        if (tablePath.length())
             dbName.Printf(wxT("%s/%s.dbf"), tablePath.c_str(), tableName.c_str());
         else
             dbName.Printf(wxT("%s.dbf"), tableName.c_str());
             dbName.Printf(wxT("%s/%s.dbf"), tablePath.c_str(), tableName.c_str());
         else
             dbName.Printf(wxT("%s.dbf"), tableName.c_str());
@@ -3382,6 +3608,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) ||
     // 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();
 
         (Dbms() == dbmsINTERBASE))
         TableName = TableName.Upper();
 
@@ -3390,18 +3617,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
 
     // 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() != dbmsMY_SQL &&
         Dbms() != dbmsACCESS &&
         Dbms() != dbmsMS_SQL_SERVER &&
         Dbms() != dbmsDB2 &&
+        Dbms() != dbmsFIREBIRD &&
         Dbms() != dbmsINTERBASE &&
         Dbms() != dbmsPERVASIVE_SQL)
     {
         retcode = SQLTables(hstmt,
                             NULL, 0,                                  // All qualifiers
         Dbms() != dbmsINTERBASE &&
         Dbms() != dbmsPERVASIVE_SQL)
     {
         retcode = SQLTables(hstmt,
                             NULL, 0,                                  // All qualifiers
-                            (SQLTCHAR *) UserID.c_str(), SQL_NTS,        // Only tables owned by this user
-                            (SQLTCHAR FAR *)TableName.c_str(), SQL_NTS,
+                            WXSQLCAST(UserID), SQL_NTS,        // Only tables owned by this user
+                            WXSQLCAST(TableName), SQL_NTS,
                             NULL, 0);                                 // All table types
     }
     else
                             NULL, 0);                                 // All table types
     }
     else
@@ -3409,7 +3637,7 @@ bool wxDb::TableExists(const wxString &tableName, const wxChar *userID, const wx
         retcode = SQLTables(hstmt,
                             NULL, 0,                                  // All qualifiers
                             NULL, 0,                                  // All owners
         retcode = SQLTables(hstmt,
                             NULL, 0,                                  // All qualifiers
                             NULL, 0,                                  // All owners
-                            (SQLTCHAR FAR *)TableName.c_str(), SQL_NTS,
+                            WXSQLCAST(TableName), SQL_NTS,
                             NULL, 0);                                 // All table types
     }
     if (retcode != SQL_SUCCESS)
                             NULL, 0);                                 // All table types
     }
     if (retcode != SQL_SUCCESS)
@@ -3433,10 +3661,10 @@ bool wxDb::TableExists(const wxString &tableName, const wxChar *userID, const wx
 bool wxDb::TablePrivileges(const wxString &tableName, const wxString &priv, const wxChar *userID,
                             const wxChar *schema, const wxString &WXUNUSED(tablePath))
 {
 bool wxDb::TablePrivileges(const wxString &tableName, const wxString &priv, const wxChar *userID,
                             const wxChar *schema, const wxString &WXUNUSED(tablePath))
 {
-    wxASSERT(tableName.Length());
+    wxASSERT(tableName.length());
 
     wxDbTablePrivilegeInfo  result;
 
     wxDbTablePrivilegeInfo  result;
-    SDWORD  cbRetVal;
+    SQLLEN  cbRetVal;
     RETCODE retcode;
 
     // We probably need to be able to dynamically set this based on
     RETCODE retcode;
 
     // We probably need to be able to dynamically set this based on
@@ -3453,6 +3681,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) ||
     // 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();
 
         (Dbms() == dbmsINTERBASE))
         TableName = TableName.Upper();
 
@@ -3460,22 +3689,22 @@ 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
 
     // 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
         Dbms() != dbmsMY_SQL &&
         Dbms() != dbmsACCESS &&
         Dbms() != dbmsMS_SQL_SERVER)
     {
         retcode = SQLTablePrivileges(hstmt,
                                      NULL, 0,                                    // Catalog
-                                     (SQLTCHAR FAR *)Schema.c_str(), SQL_NTS,               // Schema
-                                     (SQLTCHAR FAR *)TableName.c_str(), SQL_NTS);
+                                     WXSQLCAST(Schema), SQL_NTS,               // Schema
+                                     WXSQLCAST(TableName), SQL_NTS);
     }
     else
     {
         retcode = SQLTablePrivileges(hstmt,
                                      NULL, 0,                                    // Catalog
                                      NULL, 0,                                    // Schema
     }
     else
     {
         retcode = SQLTablePrivileges(hstmt,
                                      NULL, 0,                                    // Catalog
                                      NULL, 0,                                    // Schema
-                                     (SQLTCHAR FAR *)TableName.c_str(), SQL_NTS);
+                                     WXSQLCAST(TableName), SQL_NTS);
     }
 
 #ifdef DBDEBUG_CONSOLE
     }
 
 #ifdef DBDEBUG_CONSOLE
@@ -3581,13 +3810,13 @@ const wxString wxDb::SQLColumnName(const wxChar *colName)
 bool wxDb::SetSqlLogging(wxDbSqlLogState state, const wxString &filename, bool append)
 {
     wxASSERT(state == sqlLogON  || state == sqlLogOFF);
 bool wxDb::SetSqlLogging(wxDbSqlLogState state, const wxString &filename, bool append)
 {
     wxASSERT(state == sqlLogON  || state == sqlLogOFF);
-    wxASSERT(state == sqlLogOFF || filename.Length());
+    wxASSERT(state == sqlLogOFF || filename.length());
 
     if (state == sqlLogON)
     {
         if (fpSqlLog == 0)
         {
 
     if (state == sqlLogON)
     {
         if (fpSqlLog == 0)
         {
-            fpSqlLog = wxFopen(filename, (append ? wxT("at") : wxT("wt")));
+            fpSqlLog = wxFopen(filename.c_str(), (append ? wxT("at") : wxT("wt")));
             if (fpSqlLog == NULL)
                 return false;
         }
             if (fpSqlLog == NULL)
                 return false;
         }
@@ -3611,7 +3840,7 @@ bool wxDb::SetSqlLogging(wxDbSqlLogState state, const wxString &filename, bool a
 /********** wxDb::WriteSqlLog() **********/
 bool wxDb::WriteSqlLog(const wxString &logMsg)
 {
 /********** wxDb::WriteSqlLog() **********/
 bool wxDb::WriteSqlLog(const wxString &logMsg)
 {
-    wxASSERT(logMsg.Length());
+    wxASSERT(logMsg.length());
 
     if (fpSqlLog == 0 || sqlLogState == sqlLogOFF)
         return false;
 
     if (fpSqlLog == 0 || sqlLogState == sqlLogOFF)
         return false;
@@ -3697,8 +3926,16 @@ wxDBMS wxDb::Dbms(void)
     if (dbmsType != dbmsUNIDENTIFIED)
         return(dbmsType);
 
     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];
     wxChar baseName[25+1];
-    wxStrncpy(baseName,dbInf.dbmsName,25);
+    wxStrncpy(baseName, dbInf.dbmsName, 25);
     baseName[25] = 0;
 
     // RGG 20001025 : add support for Interbase
     baseName[25] = 0;
 
     // RGG 20001025 : add support for Interbase
@@ -3741,6 +3978,9 @@ wxDBMS wxDb::Dbms(void)
     if (!wxStricmp(baseName,wxT("Informix")))
         return((wxDBMS)(dbmsType = dbmsINFORMIX));
 
     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));
     baseName[6] = 0;
     if (!wxStricmp(baseName,wxT("Oracle")))
         return((wxDBMS)(dbmsType = dbmsORACLE));
@@ -3756,10 +3996,12 @@ wxDBMS wxDb::Dbms(void)
         return((wxDBMS)(dbmsType = dbmsXBASE_SEQUITER));
     if (!wxStricmp(baseName,wxT("MySQL")))
         return((wxDBMS)(dbmsType = dbmsMY_SQL));
         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")))
 
     baseName[3] = 0;
     if (!wxStricmp(baseName,wxT("DB2")))
-        return((wxDBMS)(dbmsType = dbmsDBASE));
+        return((wxDBMS)(dbmsType = dbmsDB2));
 
     return((wxDBMS)(dbmsType = dbmsUNIDENTIFIED));
 
 
     return((wxDBMS)(dbmsType = dbmsUNIDENTIFIED));
 
@@ -3770,8 +4012,8 @@ bool wxDb::ModifyColumn(const wxString &tableName, const wxString &columnName,
                         int dataType, ULONG columnLength,
                         const wxString &optionalParam)
 {
                         int dataType, ULONG columnLength,
                         const wxString &optionalParam)
 {
-    wxASSERT(tableName.Length());
-    wxASSERT(columnName.Length());
+    wxASSERT(tableName.length());
+    wxASSERT(columnName.length());
     wxASSERT((dataType == DB_DATA_TYPE_VARCHAR && columnLength > 0) ||
              dataType != DB_DATA_TYPE_VARCHAR);
 
     wxASSERT((dataType == DB_DATA_TYPE_VARCHAR && columnLength > 0) ||
              dataType != DB_DATA_TYPE_VARCHAR);
 
@@ -3849,7 +4091,7 @@ bool wxDb::ModifyColumn(const wxString &tableName, const wxString &columnName,
     }
 
     // for passing things like "NOT NULL"
     }
 
     // for passing things like "NOT NULL"
-    if (optionalParam.Length())
+    if (optionalParam.length())
     {
         sqlStmt += wxT(" ");
         sqlStmt += optionalParam;
     {
         sqlStmt += wxT(" ");
         sqlStmt += optionalParam;
@@ -3859,6 +4101,28 @@ bool wxDb::ModifyColumn(const wxString &tableName, const wxString &columnName,
 
 } // wxDb::ModifyColumn()
 
 
 } // wxDb::ModifyColumn()
 
+/********** wxDb::EscapeSqlChars() **********/
+wxString wxDb::EscapeSqlChars(const wxString& valueOrig)
+{
+    wxString value(valueOrig);
+    switch (Dbms())
+    {
+        case dbmsACCESS:
+            // Access doesn't seem to care about backslashes, so only escape single quotes.
+            value.Replace(wxT("'"), wxT("''"));
+            break;
+
+        default:
+            // All the others are supposed to be the same for now, add special
+            // handling for them if necessary
+            value.Replace(wxT("\\"), wxT("\\\\"));
+            value.Replace(wxT("'"), wxT("\\'"));
+            break;
+    }
+
+    return value;
+} // wxDb::EscapeSqlChars()
+
 
 /********** wxDbGetConnection() **********/
 wxDb WXDLLIMPEXP_ODBC *wxDbGetConnection(wxDbConnectInf *pDbConfig, bool FwdOnlyCursors)
 
 /********** wxDbGetConnection() **********/
 wxDb WXDLLIMPEXP_ODBC *wxDbGetConnection(wxDbConnectInf *pDbConfig, bool FwdOnlyCursors)
@@ -4076,11 +4340,11 @@ const wxChar WXDLLIMPEXP_ODBC *wxDbLogExtendedErrorMsg(const wxChar *userText,
         if (pDb->errorList[i])
         {
             msg.Append(pDb->errorList[i]);
         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
                 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");
         }
     }
     msg += wxT("\n");
@@ -4140,7 +4404,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);
 
     // 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
     // by the SQLConfigDataSource() function
     int k;
     do
@@ -4204,9 +4468,11 @@ bool wxDbGetDataSource(HENV henv, wxChar *Dsn, SWORD DsnMaxLength, wxChar *DsDes
  */
 {
     SWORD cb1,cb2;
  */
 {
     SWORD cb1,cb2;
+    SWORD lengthDsn = (SWORD)(DsnMaxLength*sizeof(wxChar));
+    SWORD lengthDsDesc = (SWORD)(DsDescMaxLength*sizeof(wxChar));
 
 
-    if (SQLDataSources(henv, direction, (SQLTCHAR FAR *) Dsn, DsnMaxLength*sizeof(wxChar), &cb1,
-                             (SQLTCHAR FAR *) DsDesc, DsDescMaxLength*sizeof(wxChar), &cb2) == SQL_SUCCESS)
+    if (SQLDataSources(henv, direction, (SQLTCHAR FAR *) Dsn, lengthDsn, &cb1,
+                       (SQLTCHAR FAR *) DsDesc, lengthDsDesc, &cb2) == SQL_SUCCESS)
         return true;
     else
         return false;
         return true;
     else
         return false;
@@ -4220,7 +4486,7 @@ bool wxDbGetDataSource(HENV henv, wxChar *Dsn, SWORD DsnMaxLength, wxChar *DsDes
  ********************************************************************
  *
  * The following functions are all DEPRECATED and are included for
  ********************************************************************
  *
  * The following functions are all DEPRECATED and are included for
- * backward compatability reasons only
+ * backward compatibility reasons only
  *
  ********************************************************************
  ********************************************************************/
  *
  ********************************************************************
  ********************************************************************/