]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/db.cpp
Give wxListBox a GetClassDefaultAttributes so wxCalendarCtrl (and
[wxWidgets.git] / src / common / db.cpp
index 963f6e349763382a7fa4c18a3056f30684bc1db9..8403a4ca4232b533fb2f2e4af1f575cf2499e25e 100644 (file)
 // Notice:      This class library and its intellectual design are free of charge for use,
 //              modification, enhancement, debugging under the following conditions:
 //              1) These classes may only be used as part of the implementation of a
 // Notice:      This class library and its intellectual design are free of charge for use,
 //              modification, enhancement, debugging under the following conditions:
 //              1) These classes may only be used as part of the implementation of a
-//                 wxWindows-based application
-//              2) All enhancements and bug fixes are to be submitted back to the wxWindows
-//                 user groups free of all charges for use with the wxWindows library.
+//                 wxWidgets-based application
+//              2) All enhancements and bug fixes are to be submitted back to the wxWidgets
+//                 user groups free of all charges for use with the wxWidgets library.
 //              3) These classes may not be distributed as part of any other class library,
 //                 DLL, text (written or electronic), other than a complete distribution of
 //              3) These classes may not be distributed as part of any other class library,
 //                 DLL, text (written or electronic), other than a complete distribution of
-//                 the wxWindows GUI development toolkit.
+//                 the wxWidgets GUI development toolkit.
 ///////////////////////////////////////////////////////////////////////////////
 
 /*
 // SYNOPSIS START
 // SYNOPSIS STOP
 */
 ///////////////////////////////////////////////////////////////////////////////
 
 /*
 // SYNOPSIS START
 // SYNOPSIS STOP
 */
+#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
+    #pragma implementation "db.h"
+#endif
 
 #include "wx/wxprec.h"
 
 
 #include "wx/wxprec.h"
 
-
-// Use this line for wxWindows v1.x
-//#include "wx_ver.h"
-// Use this line for wxWindows v2.x
-#include "wx/version.h"
-
-#if wxMAJOR_VERSION == 2
-    #ifdef __GNUG__
-        #pragma implementation "db.h"
-    #endif
+#ifdef __BORLANDC__
+    #pragma hdrstop
 #endif
 
 #ifdef DBDEBUG_CONSOLE
     #include "wx/ioswrap.h"
 #endif
 
 #endif
 
 #ifdef DBDEBUG_CONSOLE
     #include "wx/ioswrap.h"
 #endif
 
-#ifdef    __BORLANDC__
-    #pragma hdrstop
-#endif  //__BORLANDC__
-
-#if wxMAJOR_VERSION == 2
-    #ifndef WX_PRECOMP
-        #include "wx/string.h"
-        #include "wx/object.h"
-        #include "wx/list.h"
-        #include "wx/utils.h"
-        #include "wx/msgdlg.h"
-        #include "wx/log.h"
-    #endif
-    #include "wx/filefn.h"
-    #include "wx/wxchar.h"
-#endif
-
-
-#if wxMAJOR_VERSION == 1
-#    if defined(wx_msw) || defined(wx_x)
-#        ifdef WX_PRECOMP
-#            include "wx_prec.h"
-#        else
-#            include "wx.h"
-#        endif
-#    endif
-#    define wxUSE_ODBC 1
+#ifndef WX_PRECOMP
+    #include "wx/string.h"
+    #include "wx/object.h"
+    #include "wx/list.h"
+    #include "wx/utils.h"
+    #include "wx/log.h"
 #endif
 #endif
+#include "wx/filefn.h"
+#include "wx/wxchar.h"
 
 #if wxUSE_ODBC
 
 
 #if wxUSE_ODBC
 
 #include <stdlib.h>
 #include <ctype.h>
 
 #include <stdlib.h>
 #include <ctype.h>
 
-#if   wxMAJOR_VERSION == 1
-    #include "db.h"
-#elif wxMAJOR_VERSION == 2
-    #include "wx/db.h"
-#endif
+#include "wx/db.h"
 
 
-WXDLLEXPORT_DATA(wxDbList*) PtrBegDbList = 0;
+// DLL options compatibility check:
+#include "wx/app.h"
+WX_CHECK_BUILD_OPTIONS("wxODBC")
 
 
+WXDLLIMPEXP_DATA_ODBC(wxDbList*) PtrBegDbList = 0;
 
 
-char const *SQL_LOG_FILENAME         = "sqllog.txt";
-char const *SQL_CATALOG_FILENAME     = "catalog.txt";
+wxChar const *SQL_LOG_FILENAME         = wxT("sqllog.txt");
+wxChar const *SQL_CATALOG_FILENAME     = wxT("catalog.txt");
 
 #ifdef __WXDEBUG__
     extern wxList TablesInUse;
 
 #ifdef __WXDEBUG__
     extern wxList TablesInUse;
@@ -109,8 +84,6 @@ char const *SQL_CATALOG_FILENAME     = "catalog.txt";
 // SQL Log defaults to be used by GetDbConnection
 wxDbSqlLogState SQLLOGstate = sqlLogOFF;
 
 // SQL Log defaults to be used by GetDbConnection
 wxDbSqlLogState SQLLOGstate = sqlLogOFF;
 
-//char SQLLOGfn[wxDB_PATH_MAX+1] = SQL_LOG_FILENAME;
-//wxChar *SQLLOGfn         = (wxChar*) SQL_LOG_FILENAME;
 static wxString SQLLOGfn = SQL_LOG_FILENAME;
 
 // The wxDb::errorList is copied to this variable when the wxDb object
 static wxString SQLLOGfn = SQL_LOG_FILENAME;
 
 // The wxDb::errorList is copied to this variable when the wxDb object
@@ -121,7 +94,8 @@ 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
-char DBerrorList[DB_MAX_ERROR_HISTORY][DB_MAX_ERROR_MSG_LEN];
+wxChar DBerrorList[DB_MAX_ERROR_HISTORY][DB_MAX_ERROR_MSG_LEN];
+
 
 // This type defines the return row-struct form
 // SQLTablePrivileges, and is used by wxDB::TablePrivileges.
 
 // This type defines the return row-struct form
 // SQLTablePrivileges, and is used by wxDB::TablePrivileges.
@@ -137,104 +111,171 @@ typedef struct
 } wxDbTablePrivilegeInfo;
 
 
 } wxDbTablePrivilegeInfo;
 
 
-/********** wxDbColFor Constructor **********/
-wxDbColFor::wxDbColFor()
+/********** wxDbConnectInf Constructor - form 1 **********/
+wxDbConnectInf::wxDbConnectInf()
 {
 {
-    s_Field = "";
-    int i;
-    for (i=0;i<7;i++)
+    Henv = 0;
+    freeHenvOnDestroy = FALSE;
+
+    Initialize();
+}  // Constructor
+
+
+/********** wxDbConnectInf Constructor - form 2 **********/
+wxDbConnectInf::wxDbConnectInf(HENV henv, const wxString &dsn, const wxString &userID,
+                       const wxString &password, const wxString &defaultDir,
+                       const wxString &fileType, const wxString &description)
+{
+    Henv = 0;
+    freeHenvOnDestroy = FALSE;
+
+    Initialize();
+
+    if (henv)
+        SetHenv(henv);
+    else
+        AllocHenv();
+
+    SetDsn(dsn);
+    SetUserID(userID);
+    SetPassword(password);
+    SetDescription(description);
+    SetFileType(fileType);
+    SetDefaultDir(defaultDir);
+}  // wxDbConnectInf Constructor
+
+
+wxDbConnectInf::~wxDbConnectInf()
+{
+    if (freeHenvOnDestroy)
     {
     {
-        s_Format[i] = "";
-        s_Amount[i] = "";
-        i_Amount[i] = 0;
+        FreeHenv();
     }
     }
-    i_Nation      = 0;                     // 0=EU, 1=UK, 2=International, 3=US
-    i_dbDataType  = 0;
-    i_sqlDataType = 0;
-    Format(1,DB_DATA_TYPE_VARCHAR,0,0,0);  // the Function that does the work
-}  // wxDbColFor::wxDbColFor()
+}  // wxDbConnectInf Destructor
 
 
 
 
-wxDbColFor::~wxDbColFor()
+
+/********** wxDbConnectInf::Initialize() **********/
+bool wxDbConnectInf::Initialize()
 {
 {
-}  // wxDbColFor::~wxDbColFor()
+    freeHenvOnDestroy = FALSE;
 
 
+    if (freeHenvOnDestroy && Henv)
+        FreeHenv();
 
 
-/********** wxDbColInf Con / Destructor **********/
-wxDbColInf::wxDbColInf()
+    Henv = 0;
+    Dsn[0] = 0;
+    Uid[0] = 0;
+    AuthStr[0] = 0;
+    ConnectionStr[0] = 0;
+    Description.Empty();
+    FileType.Empty();
+    DefaultDir.Empty();
+
+    useConnectionStr = FALSE;
+
+    return TRUE;
+}  // wxDbConnectInf::Initialize()
+
+
+/********** wxDbConnectInf::AllocHenv() **********/
+bool wxDbConnectInf::AllocHenv()
 {
 {
-    catalog[0]      = 0;
-    schema[0]       = 0;
-    tableName[0]    = 0;
-    colName[0]      = 0;
-    sqlDataType     = 0;
-    typeName[0]     = 0;
-    columnSize      = 0;
-    bufferLength    = 0;
-    decimalDigits   = 0;
-    numPrecRadix    = 0;
-    nullable        = 0;
-    remarks[0]      = 0;
-    dbDataType      = 0;
-    PkCol           = 0;
-    PkTableName[0]  = 0;
-    FkCol           = 0;
-    FkTableName[0]  = 0;
-    pColFor         = NULL;
-}  // wxDbColInf::wxDbColFor()
+    // This is here to help trap if you are getting a new henv
+    // without releasing an existing henv
+    wxASSERT(!Henv);
+
+    // 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"));
+        return FALSE;
+    }
 
 
+    freeHenvOnDestroy = TRUE;
 
 
-wxDbColInf::~wxDbColInf()
+    return TRUE;
+}  // wxDbConnectInf::AllocHenv()
+
+
+void wxDbConnectInf::FreeHenv()
 {
 {
-    if (pColFor)
-        delete pColFor;
-    pColFor = NULL;
-}  // wxDbColInf::~wxDbColInf()
+    wxASSERT(Henv);
 
 
+    if (Henv)
+        SQLFreeEnv(Henv);
 
 
-/********** wxDbTableInf Constructor ********/
-wxDbTableInf::wxDbTableInf()
+    Henv = 0;
+    freeHenvOnDestroy = FALSE;
+
+}  // wxDbConnectInf::FreeHenv()
+
+
+void wxDbConnectInf::SetDsn(const wxString &dsn)
 {
 {
-    tableName[0]    = 0;
-    tableType[0]    = 0;
-    tableRemarks[0] = 0;
-    numCols         = 0;
-    pColInf         = NULL;
-}  // wxDbTableInf::wxDbTableFor()
+    wxASSERT(dsn.Length() < sizeof(Dsn));
 
 
+    wxStrcpy(Dsn,dsn);
+}  // wxDbConnectInf::SetDsn()
 
 
-/********** wxDbTableInf Constructor ********/
-wxDbTableInf::~wxDbTableInf()
+
+void wxDbConnectInf::SetUserID(const wxString &uid)
 {
 {
-    if (pColInf)
-        delete [] pColInf;
-    pColInf = NULL;
-}  // wxDbTableInf::~wxDbTableInf()
+    wxASSERT(uid.Length() < sizeof(Uid));
+    wxStrcpy(Uid, uid);
+}  // wxDbConnectInf::SetUserID()
 
 
 
 
-/********** wxDbInf Constructor *************/
-wxDbInf::wxDbInf()
+void wxDbConnectInf::SetPassword(const wxString &password)
 {
 {
-    catalog[0]      = 0;
-    schema[0]       = 0;
-    numTables       = 0;
-    pTableInf       = NULL;
-}  // wxDbInf::wxDbFor()
+    wxASSERT(password.Length() < sizeof(AuthStr));
 
 
+    wxStrcpy(AuthStr, password);
+}  // wxDbConnectInf::SetPassword()
 
 
-/********** wxDbInf Destructor *************/
-wxDbInf::~wxDbInf()
+void wxDbConnectInf::SetConnectionStr(const wxString &connectStr)
 {
 {
-  if (pTableInf)
-    delete [] pTableInf;
-  pTableInf = NULL;
-}  // wxDbInf::~wxDbInf()
+    wxASSERT(connectStr.Length() < sizeof(ConnectionStr));
+    
+    useConnectionStr = wxStrlen(connectStr) > 0;
+
+    wxStrcpy(ConnectionStr, connectStr);
+}  // wxDbConnectInf::SetConnectionStr()
+
+
+/********** wxDbColFor Constructor **********/
+wxDbColFor::wxDbColFor()
+{
+    Initialize();
+}  // wxDbColFor::wxDbColFor()
+
+
+wxDbColFor::~wxDbColFor()
+{
+}  // wxDbColFor::~wxDbColFor()
 
 
 
 
-/*************************************************/
+/********** wxDbColFor::Initialize() **********/
+void wxDbColFor::Initialize()
+{
+    s_Field.Empty();
+    int i;
+    for (i=0; i<7; i++)
+    {
+        s_Format[i].Empty();
+        s_Amount[i].Empty();
+        i_Amount[i] = 0;
+    }
+    i_Nation      = 0;                     // 0=EU, 1=UK, 2=International, 3=US
+    i_dbDataType  = 0;
+    i_sqlDataType = 0;
+    Format(1,DB_DATA_TYPE_VARCHAR,0,0,0);  // the Function that does the work
+}  // wxDbColFor::Initialize()
 
 
 
 
-int wxDbColFor::Format(int Nation,int dbDataType,SWORD sqlDataType,short columnSize,short decimalDigits)
+/********** wxDbColFor::Format() **********/
+int wxDbColFor::Format(int Nation, int dbDataType, SWORD sqlDataType,
+                       short columnSize, short decimalDigits)
 {
     // ----------------------------------------------------------------------------------------
     // -- 19991224 : mj10777 : Create
 {
     // ----------------------------------------------------------------------------------------
     // -- 19991224 : mj10777 : Create
@@ -248,16 +289,17 @@ int wxDbColFor::Format(int Nation,int dbDataType,SWORD sqlDataType,short columnS
     // ----------------------------------------------------------------------------------------
     // There should also be a function to scan in a string to fill the variable
     // ----------------------------------------------------------------------------------------
     // ----------------------------------------------------------------------------------------
     // There should also be a function to scan in a string to fill the variable
     // ----------------------------------------------------------------------------------------
-    wxString Temp0;
+    wxString tempStr;
     i_Nation      = Nation;                                       // 0 = timestamp , 1=EU, 2=UK, 3=International, 4=US
     i_dbDataType  = dbDataType;
     i_sqlDataType = sqlDataType;
     s_Field.Printf(wxT("%s%d"),s_Amount[1].c_str(),i_Amount[1]);  // OK for VARCHAR, INTEGER and FLOAT
     i_Nation      = Nation;                                       // 0 = timestamp , 1=EU, 2=UK, 3=International, 4=US
     i_dbDataType  = dbDataType;
     i_sqlDataType = sqlDataType;
     s_Field.Printf(wxT("%s%d"),s_Amount[1].c_str(),i_Amount[1]);  // OK for VARCHAR, INTEGER and FLOAT
+
     if (i_dbDataType == 0)                                        // Filter unsupported dbDataTypes
     {
         if ((i_sqlDataType == SQL_VARCHAR) || (i_sqlDataType == SQL_LONGVARCHAR))
             i_dbDataType = DB_DATA_TYPE_VARCHAR;
     if (i_dbDataType == 0)                                        // Filter unsupported dbDataTypes
     {
         if ((i_sqlDataType == SQL_VARCHAR) || (i_sqlDataType == SQL_LONGVARCHAR))
             i_dbDataType = DB_DATA_TYPE_VARCHAR;
-        if (i_sqlDataType == SQL_C_DATE)
+        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;
             i_dbDataType = DB_DATA_TYPE_DATE;
         if (i_sqlDataType == SQL_C_BIT)
             i_dbDataType = DB_DATA_TYPE_INTEGER;
@@ -265,48 +307,55 @@ int wxDbColFor::Format(int Nation,int dbDataType,SWORD sqlDataType,short columnS
             i_dbDataType = DB_DATA_TYPE_VARCHAR;
         if (i_sqlDataType == SQL_REAL)
             i_dbDataType = DB_DATA_TYPE_FLOAT;
             i_dbDataType = DB_DATA_TYPE_VARCHAR;
         if (i_sqlDataType == SQL_REAL)
             i_dbDataType = DB_DATA_TYPE_FLOAT;
+        if (i_sqlDataType == SQL_C_BINARY)
+            i_dbDataType = DB_DATA_TYPE_BLOB;
     }
     }
+
     if ((i_dbDataType == DB_DATA_TYPE_INTEGER) && (i_sqlDataType == SQL_C_DOUBLE))
     {   // DBASE Numeric
         i_dbDataType = DB_DATA_TYPE_FLOAT;
     }
     if ((i_dbDataType == DB_DATA_TYPE_INTEGER) && (i_sqlDataType == SQL_C_DOUBLE))
     {   // DBASE Numeric
         i_dbDataType = DB_DATA_TYPE_FLOAT;
     }
-    switch(i_dbDataType)     // -A-> Still a lot of proper formatting to do
+
+    switch(i_dbDataType)     // TBD: Still a lot of proper formatting to do
     {
         case DB_DATA_TYPE_VARCHAR:
     {
         case DB_DATA_TYPE_VARCHAR:
-            s_Field = "%s";
+            s_Field = wxT("%s");
             break;
         case DB_DATA_TYPE_INTEGER:
             break;
         case DB_DATA_TYPE_INTEGER:
-            s_Field = "%d";
+            s_Field = wxT("%d");
             break;
         case DB_DATA_TYPE_FLOAT:
             if (decimalDigits == 0)
                 decimalDigits = 2;
             break;
         case DB_DATA_TYPE_FLOAT:
             if (decimalDigits == 0)
                 decimalDigits = 2;
-            Temp0 = "%";
-            Temp0.Printf(wxT("%s%d.%d"),Temp0.c_str(),columnSize,decimalDigits);
-            s_Field.Printf(wxT("%sf"),Temp0.c_str());
+            tempStr = wxT("%");
+            tempStr.Printf(wxT("%s%d.%d"),tempStr.c_str(),columnSize,decimalDigits);
+            s_Field.Printf(wxT("%sf"),tempStr.c_str());
             break;
         case DB_DATA_TYPE_DATE:
             if (i_Nation == 0)      // timestamp       YYYY-MM-DD HH:MM:SS.SSS (tested for SYBASE)
             {
             break;
         case DB_DATA_TYPE_DATE:
             if (i_Nation == 0)      // timestamp       YYYY-MM-DD HH:MM:SS.SSS (tested for SYBASE)
             {
-                s_Field = "%04d-%02d-%02d %02d:%02d:%02d.%03d";
+                s_Field = wxT("%04d-%02d-%02d %02d:%02d:%02d.%03d");
             }
             if (i_Nation == 1)      // European        DD.MM.YYYY HH:MM:SS.SSS
             {
             }
             if (i_Nation == 1)      // European        DD.MM.YYYY HH:MM:SS.SSS
             {
-                s_Field = "%02d.%02d.%04d %02d:%02d:%02d.%03d";
+                s_Field = wxT("%02d.%02d.%04d %02d:%02d:%02d.%03d");
             }
             if (i_Nation == 2)      // UK              DD/MM/YYYY HH:MM:SS.SSS
             {
             }
             if (i_Nation == 2)      // UK              DD/MM/YYYY HH:MM:SS.SSS
             {
-                s_Field = "%02d/%02d/%04d %02d:%02d:%02d.%03d";
+                s_Field = wxT("%02d/%02d/%04d %02d:%02d:%02d.%03d");
             }
             if (i_Nation == 3)      // International   YYYY-MM-DD HH:MM:SS.SSS
             {
             }
             if (i_Nation == 3)      // International   YYYY-MM-DD HH:MM:SS.SSS
             {
-                s_Field = "%04d-%02d-%02d %02d:%02d:%02d.%03d";
+                s_Field = wxT("%04d-%02d-%02d %02d:%02d:%02d.%03d");
             }
             if (i_Nation == 4)      // US              MM/DD/YYYY HH:MM:SS.SSS
             {
             }
             if (i_Nation == 4)      // US              MM/DD/YYYY HH:MM:SS.SSS
             {
-                s_Field = "%02d/%02d/%04d %02d:%02d:%02d.%03d";
+                s_Field = wxT("%02d/%02d/%04d %02d:%02d:%02d.%03d");
             }
             break;
             }
             break;
+          case DB_DATA_TYPE_BLOB:
+            s_Field.Printf(wxT("Unable to format(%d)-SQL(%d)"),dbDataType,sqlDataType);        //
+                break;
         default:
             s_Field.Printf(wxT("Unknown Format(%d)-SQL(%d)"),dbDataType,sqlDataType);        //
             break;
         default:
             s_Field.Printf(wxT("Unknown Format(%d)-SQL(%d)"),dbDataType,sqlDataType);        //
             break;
@@ -315,16 +364,130 @@ int wxDbColFor::Format(int Nation,int dbDataType,SWORD sqlDataType,short columnS
 }  // wxDbColFor::Format()
 
 
 }  // wxDbColFor::Format()
 
 
-/********** wxDb Constructors **********/
-wxDb::wxDb(HENV &aHenv, bool FwdOnlyCursors)
+
+/********** wxDbColInf Constructor **********/
+wxDbColInf::wxDbColInf()
+{
+    Initialize();
+}  // wxDbColInf::wxDbColInf()
+
+
+/********** wxDbColInf Destructor ********/
+wxDbColInf::~wxDbColInf()
+{
+    if (pColFor)
+        delete pColFor;
+    pColFor = NULL;
+}  // wxDbColInf::~wxDbColInf()
+
+
+bool wxDbColInf::Initialize()
+{
+    catalog[0]      = 0;
+    schema[0]       = 0;
+    tableName[0]    = 0;
+    colName[0]      = 0;
+    sqlDataType     = 0;
+    typeName[0]     = 0;
+    columnSize      = 0;
+    bufferLength    = 0;
+    decimalDigits   = 0;
+    numPrecRadix    = 0;
+    nullable        = 0;
+    remarks[0]      = 0;
+    dbDataType      = 0;
+    PkCol           = 0;
+    PkTableName[0]  = 0;
+    FkCol           = 0;
+    FkTableName[0]  = 0;
+    pColFor         = NULL;
+
+    return TRUE;
+}  // wxDbColInf::Initialize()
+
+
+/********** wxDbTableInf Constructor ********/
+wxDbTableInf::wxDbTableInf()
+{
+    Initialize();
+}  // wxDbTableInf::wxDbTableInf()
+
+
+/********** wxDbTableInf Constructor ********/
+wxDbTableInf::~wxDbTableInf()
+{
+    if (pColInf)
+        delete [] pColInf;
+    pColInf = NULL;
+}  // wxDbTableInf::~wxDbTableInf()
+
+
+bool wxDbTableInf::Initialize()
+{
+    tableName[0]    = 0;
+    tableType[0]    = 0;
+    tableRemarks[0] = 0;
+    numCols         = 0;
+    pColInf         = NULL;
+
+    return TRUE;
+}  // wxDbTableInf::Initialize()
+
+
+/********** wxDbInf Constructor *************/
+wxDbInf::wxDbInf()
+{
+    Initialize();
+}  // wxDbInf::wxDbInf()
+
+
+/********** wxDbInf Destructor *************/
+wxDbInf::~wxDbInf()
+{
+  if (pTableInf)
+    delete [] pTableInf;
+  pTableInf = NULL;
+}  // wxDbInf::~wxDbInf()
+
+
+/********** wxDbInf::Initialize() *************/
+bool wxDbInf::Initialize()
+{
+    catalog[0]      = 0;
+    schema[0]       = 0;
+    numTables       = 0;
+    pTableInf       = NULL;
+
+    return TRUE;
+}  // wxDbInf::Initialize()
+
+
+/********** wxDb Constructor **********/
+wxDb::wxDb(const HENV &aHenv, bool FwdOnlyCursors)
 {
     // Copy the HENV into the db class
     henv = aHenv;
     fwdOnlyCursors = FwdOnlyCursors;
 {
     // Copy the HENV into the db class
     henv = aHenv;
     fwdOnlyCursors = FwdOnlyCursors;
+
     initialize();
 } // wxDb::wxDb()
 
 
     initialize();
 } // wxDb::wxDb()
 
 
+/********** wxDb Destructor **********/
+wxDb::~wxDb()
+{
+    wxASSERT_MSG(!IsCached(),wxT("Cached connections must not be manually deleted, use\nwxDbFreeConnection() or wxDbCloseConnections()."));
+
+    if (IsOpen())
+    {
+        Close();
+    }
+}  // wxDb destructor
+
+
+
+/********** PRIVATE! wxDb::initialize PRIVATE! **********/
+/********** wxDb::initialize() **********/
 void wxDb::initialize()
 /*
  * Private member function that sets all wxDb member variables to
 void wxDb::initialize()
 /*
  * Private member function that sets all wxDb member variables to
@@ -338,37 +501,43 @@ void wxDb::initialize()
     nTables       = 0;
     dbmsType      = dbmsUNIDENTIFIED;
 
     nTables       = 0;
     dbmsType      = dbmsUNIDENTIFIED;
 
-    wxStrcpy(sqlState,wxT(""));
-    wxStrcpy(errorMsg,wxT(""));
+    wxStrcpy(sqlState,wxEmptyString);
+    wxStrcpy(errorMsg,wxEmptyString);
     nativeError = cbErrorMsg = 0;
     for (i = 0; i < DB_MAX_ERROR_HISTORY; i++)
     nativeError = cbErrorMsg = 0;
     for (i = 0; i < DB_MAX_ERROR_HISTORY; i++)
-        wxStrcpy(errorList[i], wxT(""));
+        wxStrcpy(errorList[i], wxEmptyString);
 
     // Init typeInf structures
 
     // Init typeInf structures
-    wxStrcpy(typeInfVarchar.TypeName,wxT(""));
+    typeInfVarchar.TypeName.Empty();
     typeInfVarchar.FsqlType      = 0;
     typeInfVarchar.Precision     = 0;
     typeInfVarchar.CaseSensitive = 0;
     typeInfVarchar.MaximumScale  = 0;
 
     typeInfVarchar.FsqlType      = 0;
     typeInfVarchar.Precision     = 0;
     typeInfVarchar.CaseSensitive = 0;
     typeInfVarchar.MaximumScale  = 0;
 
-    wxStrcpy(typeInfInteger.TypeName,wxT(""));
+    typeInfInteger.TypeName.Empty();
     typeInfInteger.FsqlType      = 0;
     typeInfInteger.Precision     = 0;
     typeInfInteger.CaseSensitive = 0;
     typeInfInteger.MaximumScale  = 0;
 
     typeInfInteger.FsqlType      = 0;
     typeInfInteger.Precision     = 0;
     typeInfInteger.CaseSensitive = 0;
     typeInfInteger.MaximumScale  = 0;
 
-    wxStrcpy(typeInfFloat.TypeName,wxT(""));
+    typeInfFloat.TypeName.Empty();
     typeInfFloat.FsqlType      = 0;
     typeInfFloat.Precision     = 0;
     typeInfFloat.CaseSensitive = 0;
     typeInfFloat.MaximumScale  = 0;
 
     typeInfFloat.FsqlType      = 0;
     typeInfFloat.Precision     = 0;
     typeInfFloat.CaseSensitive = 0;
     typeInfFloat.MaximumScale  = 0;
 
-    wxStrcpy(typeInfDate.TypeName,wxT(""));
+    typeInfDate.TypeName.Empty();
     typeInfDate.FsqlType      = 0;
     typeInfDate.Precision     = 0;
     typeInfDate.CaseSensitive = 0;
     typeInfDate.MaximumScale  = 0;
 
     typeInfDate.FsqlType      = 0;
     typeInfDate.Precision     = 0;
     typeInfDate.CaseSensitive = 0;
     typeInfDate.MaximumScale  = 0;
 
+    typeInfBlob.TypeName.Empty();
+    typeInfBlob.FsqlType      = 0;
+    typeInfBlob.Precision     = 0;
+    typeInfBlob.CaseSensitive = 0;
+    typeInfBlob.MaximumScale  = 0;
+
     // Error reporting is turned OFF by default
     silent = TRUE;
 
     // Error reporting is turned OFF by default
     silent = TRUE;
 
@@ -381,57 +550,51 @@ void wxDb::initialize()
 
     // Mark database as not open as of yet
     dbIsOpen = FALSE;
 
     // Mark database as not open as of yet
     dbIsOpen = FALSE;
+    dbIsCached = FALSE;
+    dbOpenedWithConnectionString = FALSE;
 }  // wxDb::initialize()
 
 
 }  // wxDb::initialize()
 
 
-/********** wxDb::Open() **********/
-bool wxDb::Open(char *Dsn, char *Uid, char *AuthStr)
+/********** PRIVATE! wxDb::convertUserID PRIVATE! **********/
+//
+// NOTE: Return value from this function MUST be copied
+//       immediately, as the value is not good after
+//       this function has left scope.
+//
+const wxChar *wxDb::convertUserID(const wxChar *userID, wxString &UserID)
 {
 {
-    assert(Dsn && wxStrlen(Dsn));
-    dsn        = Dsn;
-    uid        = Uid;
-    authStr    = AuthStr;
-
-    RETCODE retcode;
-
-    if (!FwdOnlyCursors())
+    if (userID)
     {
     {
-        // Specify that the ODBC cursor library be used, if needed.  This must be
-        // specified before the connection is made.
-        retcode = SQLSetConnectOption(hdbc, SQL_ODBC_CURSORS, SQL_CUR_USE_IF_NEEDED);
-
-#ifdef DBDEBUG_CONSOLE
-        if (retcode == SQL_SUCCESS)
-            cout << "SQLSetConnectOption(CURSOR_LIB) successful" << endl;
+        if (!wxStrlen(userID))
+            UserID = uid;
         else
         else
-            cout << "SQLSetConnectOption(CURSOR_LIB) failed" << endl;
-#endif
+            UserID = userID;
     }
     }
+    else
+        UserID.Empty();
 
 
-    // Connect to the data source
-    retcode = SQLConnect(hdbc, (UCHAR FAR *) dsn, SQL_NTS,
-                         (UCHAR FAR *) uid, SQL_NTS,
-                         (UCHAR FAR *) authStr,SQL_NTS);
+    // dBase does not use user names, and some drivers fail if you try to pass one
+    if ( Dbms() == dbmsDBASE
+         || Dbms() == dbmsXBASE_SEQUITER )
+        UserID.Empty();
 
 
-/*
-    if (retcode == SQL_SUCCESS_WITH_INFO)
-        DispAllErrors(henv, hdbc);
-    else if (retcode != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    // Oracle user names may only be in uppercase, so force
+    // the name to uppercase
+    if (Dbms() == dbmsORACLE)
+        UserID = UserID.Upper();
 
 
-       if (retcode == SQL_ERROR)
-               return(DispAllErrors(henv, hdbc));
-*/
-       if ((retcode != SQL_SUCCESS) &&
-        (retcode != SQL_SUCCESS_WITH_INFO))
-               return(DispAllErrors(henv, hdbc));
+    return UserID.c_str();
+}  // wxDb::convertUserID()
 
 
+
+bool wxDb::open(bool failOnDataTypeUnsupported)
+{
 /*
     If using Intersolv branded ODBC drivers, this is the place where you would substitute
     your branded driver license information
 
 /*
     If using Intersolv branded ODBC drivers, this is the place where you would substitute
     your branded driver license information
 
-    SQLSetConnectOption(hdbc, 1041, (UDWORD) "");
-    SQLSetConnectOption(hdbc, 1042, (UDWORD) "");
+    SQLSetConnectOption(hdbc, 1041, (UDWORD) wxEmptyString);
+    SQLSetConnectOption(hdbc, 1042, (UDWORD) wxEmptyString);
 */
 
     // Mark database as open
 */
 
     // Mark database as open
@@ -446,13 +609,13 @@ bool wxDb::Open(char *Dsn, char *Uid, char *AuthStr)
         return(FALSE);
 
     // Query the data source for inf. about itself
         return(FALSE);
 
     // Query the data source for inf. about itself
-    if (!getDbInfo())
+    if (!getDbInfo(failOnDataTypeUnsupported))
         return(FALSE);
 
     // Query the data source regarding data type information
 
     //
         return(FALSE);
 
     // Query the data source regarding data type information
 
     //
-    // The way I determined which SQL data types to use was by calling SQLGetInfo
+    // The way it was determined which SQL data types to use was by calling SQLGetInfo
     // for all of the possible SQL data types to see which ones were supported.  If
     // a type is not supported, the SQLFetch() that's called from getDataTypeInfo()
     // fails with SQL_NO_DATA_FOUND.  This is ugly because I'm sure the three SQL data
     // 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
@@ -501,12 +664,14 @@ bool wxDb::Open(char *Dsn, char *Uid, char *AuthStr)
 
     // Float
     if (!getDataTypeInfo(SQL_DOUBLE,typeInfFloat))
 
     // 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 (!getDataTypeInfo(SQL_REAL,typeInfFloat))
             if (!getDataTypeInfo(SQL_FLOAT,typeInfFloat))
                 if (!getDataTypeInfo(SQL_DECIMAL,typeInfFloat))
                     if (!getDataTypeInfo(SQL_NUMERIC,typeInfFloat))
-                        return(FALSE);
+                    {
+                        if (failOnDataTypeUnsupported)
+                            return(FALSE);
+                    }
                     else
                         typeInfFloat.FsqlType = SQL_NUMERIC;
                 else
                     else
                         typeInfFloat.FsqlType = SQL_NUMERIC;
                 else
@@ -524,7 +689,10 @@ bool wxDb::Open(char *Dsn, char *Uid, char *AuthStr)
         // If SQL_INTEGER is not supported, use the floating point
         // data type to store integers as well as floats
         if (!getDataTypeInfo(typeInfFloat.FsqlType, typeInfInteger))
         // If SQL_INTEGER is not supported, use the floating point
         // data type to store integers as well as floats
         if (!getDataTypeInfo(typeInfFloat.FsqlType, typeInfInteger))
-            return(FALSE);
+        {
+            if (failOnDataTypeUnsupported)
+                return(FALSE);
+        }
         else
             typeInfInteger.FsqlType = typeInfFloat.FsqlType;
     }
         else
             typeInfInteger.FsqlType = typeInfFloat.FsqlType;
     }
@@ -532,40 +700,165 @@ bool wxDb::Open(char *Dsn, char *Uid, char *AuthStr)
         typeInfInteger.FsqlType = SQL_INTEGER;
 
     // Date/Time
         typeInfInteger.FsqlType = SQL_INTEGER;
 
     // Date/Time
-    if (Dbms() != dbmsDBASE)
+    if (!getDataTypeInfo(SQL_TIMESTAMP,typeInfDate))
     {
     {
-        if (! getDataTypeInfo(SQL_TIMESTAMP,typeInfDate))
-            return(FALSE);
+        if (!getDataTypeInfo(SQL_DATE,typeInfDate))
+        {
+#ifdef SQL_DATETIME
+            if (getDataTypeInfo(SQL_DATETIME,typeInfDate))
+            {
+                typeInfDate.FsqlType = SQL_TIME;
+            }
+            else
+#endif // SQL_DATETIME defined
+            {
+                if (failOnDataTypeUnsupported)
+                    return(FALSE);
+            }
+        }
         else
         else
-            typeInfDate.FsqlType = SQL_TIMESTAMP;
+            typeInfDate.FsqlType = SQL_DATE;
     }
     else
     }
     else
+        typeInfDate.FsqlType = SQL_TIMESTAMP;
+
+
+    if (!getDataTypeInfo(SQL_LONGVARBINARY, typeInfBlob))
     {
     {
-        if (!getDataTypeInfo(SQL_DATE,typeInfDate))
-            return(FALSE);
+        if (!getDataTypeInfo(SQL_VARBINARY,typeInfBlob))
+        {
+            if (failOnDataTypeUnsupported)
+                return(FALSE);
+        }
         else
         else
-            typeInfDate.FsqlType = SQL_DATE;
+            typeInfBlob.FsqlType = SQL_VARBINARY;
     }
     }
+    else
+        typeInfBlob.FsqlType = SQL_LONGVARBINARY;
+
 
 #ifdef DBDEBUG_CONSOLE
 
 #ifdef DBDEBUG_CONSOLE
-    cout << "VARCHAR DATA TYPE: " << typeInfVarchar.TypeName << endl;
-    cout << "INTEGER DATA TYPE: " << typeInfInteger.TypeName << endl;
-    cout << "FLOAT   DATA TYPE: " << typeInfFloat.TypeName << endl;
-    cout << "DATE    DATA TYPE: " << typeInfDate.TypeName << endl;
+    cout << wxT("VARCHAR DATA TYPE: ") << typeInfVarchar.TypeName << endl;
+    cout << wxT("INTEGER DATA TYPE: ") << typeInfInteger.TypeName << endl;
+    cout << wxT("FLOAT   DATA TYPE: ") << typeInfFloat.TypeName << endl;
+    cout << wxT("DATE    DATA TYPE: ") << typeInfDate.TypeName << endl;
+    cout << wxT("BLOB    DATA TYPE: ") << typeInfBlob.TypeName << endl;
     cout << endl;
 #endif
 
     // Completed Successfully
     return(TRUE);
     cout << endl;
 #endif
 
     // Completed Successfully
     return(TRUE);
+}
+
+bool wxDb::Open(const wxString& inConnectStr, bool failOnDataTypeUnsupported)
+{
+    wxASSERT(inConnectStr.Length());
+    dsn        = wxT("");
+    uid        = wxT("");
+    authStr    = wxT("");
+
+    RETCODE retcode;
+
+    if (!FwdOnlyCursors())
+    {
+        // Specify that the ODBC cursor library be used, if needed.  This must be
+        // specified before the connection is made.
+        retcode = SQLSetConnectOption(hdbc, SQL_ODBC_CURSORS, SQL_CUR_USE_IF_NEEDED);
+
+#ifdef DBDEBUG_CONSOLE
+        if (retcode == SQL_SUCCESS)
+            cout << wxT("SQLSetConnectOption(CURSOR_LIB) successful") << endl;
+        else
+            cout << wxT("SQLSetConnectOption(CURSOR_LIB) failed") << endl;
+#else
+        wxUnusedVar(retcode);
+#endif
+    }
+
+    // Connect to the data source
+    SQLTCHAR outConnectBuffer[SQL_MAX_CONNECTSTR_LEN+1];  // MS recommends at least 1k buffer
+    short outConnectBufferLen;
+
+    inConnectionStr = inConnectStr;
+
+    retcode = SQLDriverConnect(hdbc, NULL, (SQLTCHAR FAR *)inConnectionStr.c_str(),
+                        inConnectionStr.Length(), (SQLTCHAR FAR *)outConnectBuffer,
+                        sizeof(outConnectBuffer), &outConnectBufferLen, SQL_DRIVER_COMPLETE );
+
+    if ((retcode != SQL_SUCCESS) &&
+        (retcode != SQL_SUCCESS_WITH_INFO))
+        return(DispAllErrors(henv, hdbc));
+
+    outConnectBuffer[outConnectBufferLen] = 0;
+    outConnectionStr = outConnectBuffer;
+    dbOpenedWithConnectionString = TRUE;
+
+    return open(failOnDataTypeUnsupported);
+}
+
+/********** wxDb::Open() **********/
+bool wxDb::Open(const wxString &Dsn, const wxString &Uid, const wxString &AuthStr, bool failOnDataTypeUnsupported)
+{
+    wxASSERT(Dsn.Length());
+    dsn        = Dsn;
+    uid        = Uid;
+    authStr    = AuthStr;
+
+    inConnectionStr = wxT("");
+    outConnectionStr = wxT("");
+
+    RETCODE retcode;
+
+    if (!FwdOnlyCursors())
+    {
+        // Specify that the ODBC cursor library be used, if needed.  This must be
+        // specified before the connection is made.
+        retcode = SQLSetConnectOption(hdbc, SQL_ODBC_CURSORS, SQL_CUR_USE_IF_NEEDED);
+
+#ifdef DBDEBUG_CONSOLE
+        if (retcode == SQL_SUCCESS)
+            cout << wxT("SQLSetConnectOption(CURSOR_LIB) successful") << endl;
+        else
+            cout << wxT("SQLSetConnectOption(CURSOR_LIB) failed") << endl;
+#else
+        wxUnusedVar( retcode );
+#endif
+    }
+
+    // Connect to the data source
+    retcode = SQLConnect(hdbc, (SQLTCHAR FAR *) dsn.c_str(), SQL_NTS,
+                         (SQLTCHAR FAR *) uid.c_str(), SQL_NTS,
+                         (SQLTCHAR FAR *) authStr.c_str(), SQL_NTS);
+
+    if ((retcode != SQL_SUCCESS) &&
+        (retcode != SQL_SUCCESS_WITH_INFO))
+        return(DispAllErrors(henv, hdbc));
+
+    return open(failOnDataTypeUnsupported);
 
 } // wxDb::Open()
 
 
 
 } // wxDb::Open()
 
 
+bool wxDb::Open(wxDbConnectInf *dbConnectInf, bool failOnDataTypeUnsupported)
+{
+    wxASSERT(dbConnectInf);
+
+    // Use the connection string if one is present
+    if (dbConnectInf->UseConnectionStr())
+        return Open(GetConnectionInStr(), failOnDataTypeUnsupported);
+    else
+        return Open(dbConnectInf->GetDsn(), dbConnectInf->GetUserID(),
+                    dbConnectInf->GetPassword(), failOnDataTypeUnsupported);
+}  // wxDb::Open()
+
+
 bool wxDb::Open(wxDb *copyDb)
 {
 bool wxDb::Open(wxDb *copyDb)
 {
-    dsn        = (char *)copyDb->GetDatasourceName();
-    uid        = (char *)copyDb->GetUsername();
-    authStr    = (char *)copyDb->GetPassword();
+    dsn              = copyDb->GetDatasourceName();
+    uid              = copyDb->GetUsername();
+    authStr          = copyDb->GetPassword();
+    inConnectionStr  = copyDb->GetConnectionInStr();
+    outConnectionStr = copyDb->GetConnectionOutStr();
 
     RETCODE retcode;
 
 
     RETCODE retcode;
 
@@ -577,26 +870,52 @@ bool wxDb::Open(wxDb *copyDb)
 
 #ifdef DBDEBUG_CONSOLE
         if (retcode == SQL_SUCCESS)
 
 #ifdef DBDEBUG_CONSOLE
         if (retcode == SQL_SUCCESS)
-            cout << "SQLSetConnectOption(CURSOR_LIB) successful" << endl;
+            cout << wxT("SQLSetConnectOption(CURSOR_LIB) successful") << endl;
         else
         else
-            cout << "SQLSetConnectOption(CURSOR_LIB) failed" << endl;
+            cout << wxT("SQLSetConnectOption(CURSOR_LIB) failed") << endl;
+#else
+        wxUnusedVar( retcode );
 #endif
     }
 
 #endif
     }
 
-    // Connect to the data source
-    retcode = SQLConnect(hdbc, (UCHAR FAR *) dsn, SQL_NTS,
-                         (UCHAR FAR *) uid, SQL_NTS,
-                         (UCHAR FAR *) authStr, SQL_NTS);
+    if (copyDb->OpenedWithConnectionString())
+    {
+        // Connect to the data source
+        SQLTCHAR outConnectBuffer[SQL_MAX_CONNECTSTR_LEN+1];
+        short outConnectBufferLen;
+
+        inConnectionStr = copyDb->GetConnectionInStr();
+
+        retcode = SQLDriverConnect(hdbc, NULL, (SQLTCHAR FAR *)inConnectionStr.c_str(),
+                            inConnectionStr.Length(), (SQLTCHAR FAR *)outConnectBuffer,
+                            sizeof(outConnectBuffer), &outConnectBufferLen, SQL_DRIVER_COMPLETE);
 
 
-       if (retcode == SQL_ERROR)
-               return(DispAllErrors(henv, hdbc));
+        if ((retcode != SQL_SUCCESS) &&
+            (retcode != SQL_SUCCESS_WITH_INFO))
+            return(DispAllErrors(henv, hdbc));
+
+        outConnectBuffer[outConnectBufferLen] = 0;
+        outConnectionStr = outConnectBuffer;
+        dbOpenedWithConnectionString = TRUE;
+    }
+    else
+    {
+        // Connect to the data source
+        retcode = SQLConnect(hdbc, (SQLTCHAR FAR *) dsn.c_str(), SQL_NTS,
+                             (SQLTCHAR FAR *) uid.c_str(), SQL_NTS,
+                             (SQLTCHAR FAR *) authStr.c_str(), SQL_NTS);
+    }
+
+    if ((retcode != SQL_SUCCESS) &&
+        (retcode != SQL_SUCCESS_WITH_INFO))
+        return(DispAllErrors(henv, hdbc));
 
 /*
     If using Intersolv branded ODBC drivers, this is the place where you would substitute
     your branded driver license information
 
 
 /*
     If using Intersolv branded ODBC drivers, this is the place where you would substitute
     your branded driver license information
 
-    SQLSetConnectOption(hdbc, 1041, (UDWORD) "");
-    SQLSetConnectOption(hdbc, 1042, (UDWORD) "");
+    SQLSetConnectOption(hdbc, 1041, (UDWORD) wxEmptyString);
+    SQLSetConnectOption(hdbc, 1042, (UDWORD) wxEmptyString);
 */
 
     // Mark database as open
 */
 
     // Mark database as open
@@ -645,38 +964,46 @@ bool wxDb::Open(wxDb *copyDb)
     dbInf.loginTimeout = copyDb->dbInf.loginTimeout;
 
     // VARCHAR = Variable length character string
     dbInf.loginTimeout = copyDb->dbInf.loginTimeout;
 
     // VARCHAR = Variable length character string
-    typeInfVarchar.FsqlType = copyDb->typeInfVarchar.FsqlType;
-    wxStrcpy(typeInfVarchar.TypeName, copyDb->typeInfVarchar.TypeName);
+    typeInfVarchar.FsqlType         = copyDb->typeInfVarchar.FsqlType;
+    typeInfVarchar.TypeName         = copyDb->typeInfVarchar.TypeName;
     typeInfVarchar.Precision        = copyDb->typeInfVarchar.Precision;
     typeInfVarchar.CaseSensitive    = copyDb->typeInfVarchar.CaseSensitive;
     typeInfVarchar.MaximumScale     = copyDb->typeInfVarchar.MaximumScale;
 
     // Float
     typeInfVarchar.Precision        = copyDb->typeInfVarchar.Precision;
     typeInfVarchar.CaseSensitive    = copyDb->typeInfVarchar.CaseSensitive;
     typeInfVarchar.MaximumScale     = copyDb->typeInfVarchar.MaximumScale;
 
     // Float
-    typeInfFloat.FsqlType = copyDb->typeInfFloat.FsqlType;
-    wxStrcpy(typeInfFloat.TypeName, copyDb->typeInfFloat.TypeName);
+    typeInfFloat.FsqlType         = copyDb->typeInfFloat.FsqlType;
+    typeInfFloat.TypeName         = copyDb->typeInfFloat.TypeName;
     typeInfFloat.Precision        = copyDb->typeInfFloat.Precision;
     typeInfFloat.CaseSensitive    = copyDb->typeInfFloat.CaseSensitive;
     typeInfFloat.MaximumScale     = copyDb->typeInfFloat.MaximumScale;
 
     // Integer
     typeInfFloat.Precision        = copyDb->typeInfFloat.Precision;
     typeInfFloat.CaseSensitive    = copyDb->typeInfFloat.CaseSensitive;
     typeInfFloat.MaximumScale     = copyDb->typeInfFloat.MaximumScale;
 
     // Integer
-    typeInfInteger.FsqlType = copyDb->typeInfInteger.FsqlType;
-    wxStrcpy(typeInfInteger.TypeName, copyDb->typeInfInteger.TypeName);
+    typeInfInteger.FsqlType         = copyDb->typeInfInteger.FsqlType;
+    typeInfInteger.TypeName         = copyDb->typeInfInteger.TypeName;
     typeInfInteger.Precision        = copyDb->typeInfInteger.Precision;
     typeInfInteger.CaseSensitive    = copyDb->typeInfInteger.CaseSensitive;
     typeInfInteger.MaximumScale     = copyDb->typeInfInteger.MaximumScale;
 
     // Date/Time
     typeInfInteger.Precision        = copyDb->typeInfInteger.Precision;
     typeInfInteger.CaseSensitive    = copyDb->typeInfInteger.CaseSensitive;
     typeInfInteger.MaximumScale     = copyDb->typeInfInteger.MaximumScale;
 
     // Date/Time
-    typeInfDate.FsqlType = copyDb->typeInfDate.FsqlType;
-    wxStrcpy(typeInfDate.TypeName, copyDb->typeInfDate.TypeName);
+    typeInfDate.FsqlType         = copyDb->typeInfDate.FsqlType;
+    typeInfDate.TypeName         = copyDb->typeInfDate.TypeName;
     typeInfDate.Precision        = copyDb->typeInfDate.Precision;
     typeInfDate.CaseSensitive    = copyDb->typeInfDate.CaseSensitive;
     typeInfDate.MaximumScale     = copyDb->typeInfDate.MaximumScale;
 
     typeInfDate.Precision        = copyDb->typeInfDate.Precision;
     typeInfDate.CaseSensitive    = copyDb->typeInfDate.CaseSensitive;
     typeInfDate.MaximumScale     = copyDb->typeInfDate.MaximumScale;
 
+    // Blob
+    typeInfBlob.FsqlType         = copyDb->typeInfBlob.FsqlType;
+    typeInfBlob.TypeName         = copyDb->typeInfBlob.TypeName;
+    typeInfBlob.Precision        = copyDb->typeInfBlob.Precision;
+    typeInfBlob.CaseSensitive    = copyDb->typeInfBlob.CaseSensitive;
+    typeInfBlob.MaximumScale     = copyDb->typeInfBlob.MaximumScale;
+
 #ifdef DBDEBUG_CONSOLE
 #ifdef DBDEBUG_CONSOLE
-    cout << "VARCHAR DATA TYPE: " << typeInfVarchar.TypeName << endl;
-    cout << "INTEGER DATA TYPE: " << typeInfInteger.TypeName << endl;
-    cout << "FLOAT   DATA TYPE: " << typeInfFloat.TypeName << endl;
-    cout << "DATE    DATA TYPE: " << typeInfDate.TypeName << endl;
+    cout << wxT("VARCHAR DATA TYPE: ") << typeInfVarchar.TypeName << endl;
+    cout << wxT("INTEGER DATA TYPE: ") << typeInfInteger.TypeName << endl;
+    cout << wxT("FLOAT   DATA TYPE: ") << typeInfFloat.TypeName << endl;
+    cout << wxT("DATE    DATA TYPE: ") << typeInfDate.TypeName << endl;
+    cout << wxT("BLOB    DATA TYPE: ") << typeInfBlob.TypeName << endl;
     cout << endl;
 #endif
 
     cout << endl;
 #endif
 
@@ -700,7 +1027,7 @@ bool wxDb::setConnectionOptions(void)
 
     SQLSetConnectOption(hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF);
     SQLSetConnectOption(hdbc, SQL_OPT_TRACE, SQL_OPT_TRACE_OFF);
 
     SQLSetConnectOption(hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF);
     SQLSetConnectOption(hdbc, SQL_OPT_TRACE, SQL_OPT_TRACE_OFF);
-//     SQLSetConnectOption(hdbc, SQL_TXN_ISOLATION, SQL_TXN_READ_COMMITTED);  // No dirty reads
+//  SQLSetConnectOption(hdbc, SQL_TXN_ISOLATION, SQL_TXN_READ_COMMITTED);  // No dirty reads
 
     // By default, MS Sql Server closes cursors on commit and rollback.  The following
     // call to SQLSetConnectOption() is needed to force SQL Server to preserve cursors
 
     // By default, MS Sql Server closes cursors on commit and rollback.  The following
     // call to SQLSetConnectOption() is needed to force SQL Server to preserve cursors
@@ -717,32 +1044,32 @@ bool wxDb::setConnectionOptions(void)
     // Display the connection options to verify them
 #ifdef DBDEBUG_CONSOLE
     long l;
     // Display the connection options to verify them
 #ifdef DBDEBUG_CONSOLE
     long l;
-    cout << "****** CONNECTION OPTIONS ******" << endl;
+    cout << wxT("****** CONNECTION OPTIONS ******") << endl;
 
     if (SQLGetConnectOption(hdbc, SQL_AUTOCOMMIT, &l) != SQL_SUCCESS)
         return(DispAllErrors(henv, hdbc));
 
     if (SQLGetConnectOption(hdbc, SQL_AUTOCOMMIT, &l) != SQL_SUCCESS)
         return(DispAllErrors(henv, hdbc));
-    cout << "AUTOCOMMIT: " << (l == SQL_AUTOCOMMIT_OFF ? "OFF" : "ON") << endl;
+    cout << wxT("AUTOCOMMIT: ") << (l == SQL_AUTOCOMMIT_OFF ? "OFF" : "ON") << endl;
 
     if (SQLGetConnectOption(hdbc, SQL_ODBC_CURSORS, &l) != SQL_SUCCESS)
         return(DispAllErrors(henv, hdbc));
 
     if (SQLGetConnectOption(hdbc, SQL_ODBC_CURSORS, &l) != SQL_SUCCESS)
         return(DispAllErrors(henv, hdbc));
-    cout << "ODBC CURSORS: ";
+    cout << wxT("ODBC CURSORS: ");
     switch(l)
         {
         case(SQL_CUR_USE_IF_NEEDED):
     switch(l)
         {
         case(SQL_CUR_USE_IF_NEEDED):
-            cout << "SQL_CUR_USE_IF_NEEDED";
+            cout << wxT("SQL_CUR_USE_IF_NEEDED");
             break;
         case(SQL_CUR_USE_ODBC):
             break;
         case(SQL_CUR_USE_ODBC):
-            cout << "SQL_CUR_USE_ODBC";
+            cout << wxT("SQL_CUR_USE_ODBC");
             break;
         case(SQL_CUR_USE_DRIVER):
             break;
         case(SQL_CUR_USE_DRIVER):
-            cout << "SQL_CUR_USE_DRIVER";
+            cout << wxT("SQL_CUR_USE_DRIVER");
             break;
         }
         cout << endl;
 
     if (SQLGetConnectOption(hdbc, SQL_OPT_TRACE, &l) != SQL_SUCCESS)
         return(DispAllErrors(henv, hdbc));
             break;
         }
         cout << endl;
 
     if (SQLGetConnectOption(hdbc, SQL_OPT_TRACE, &l) != SQL_SUCCESS)
         return(DispAllErrors(henv, hdbc));
-    cout << "TRACING: " << (l == SQL_OPT_TRACE_OFF ? "OFF" : "ON") << endl;
+    cout << wxT("TRACING: ") << (l == SQL_OPT_TRACE_OFF ? wxT("OFF") : wxT("ON")) << endl;
 
     cout << endl;
 #endif
 
     cout << endl;
 #endif
@@ -754,303 +1081,453 @@ bool wxDb::setConnectionOptions(void)
 
 
 /********** wxDb::getDbInfo() **********/
 
 
 /********** wxDb::getDbInfo() **********/
-bool wxDb::getDbInfo(void)
+bool wxDb::getDbInfo(bool failOnDataTypeUnsupported)
 {
     SWORD cb;
     RETCODE retcode;
 
 {
     SWORD cb;
     RETCODE retcode;
 
-    if (SQLGetInfo(hdbc, SQL_SERVER_NAME, (UCHAR*) dbInf.serverName, 80, &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_SERVER_NAME, (UCHAR*) dbInf.serverName, 80, &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_DATABASE_NAME, (UCHAR*) dbInf.databaseName, 128, &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_DATABASE_NAME, (UCHAR*) dbInf.databaseName, 128, &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_DBMS_NAME, (UCHAR*) dbInf.dbmsName, 40, &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_DBMS_NAME, (UCHAR*) dbInf.dbmsName, 40, &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
     // 16-Mar-1999
     // After upgrading to MSVC6, the original 20 char buffer below was insufficient,
     // causing database connectivity to fail in some cases.
     retcode = SQLGetInfo(hdbc, SQL_DBMS_VER, (UCHAR*) dbInf.dbmsVer, 64, &cb);
 
     // 16-Mar-1999
     // After upgrading to MSVC6, the original 20 char buffer below was insufficient,
     // causing database connectivity to fail in some cases.
     retcode = SQLGetInfo(hdbc, SQL_DBMS_VER, (UCHAR*) dbInf.dbmsVer, 64, &cb);
-
     if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
     if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
-        return(DispAllErrors(henv, hdbc));
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_ACTIVE_CONNECTIONS, (UCHAR*) &dbInf.maxConnections, sizeof(dbInf.maxConnections), &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_ACTIVE_CONNECTIONS, (UCHAR*) &dbInf.maxConnections, sizeof(dbInf.maxConnections), &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_ACTIVE_STATEMENTS, (UCHAR*) &dbInf.maxStmts, sizeof(dbInf.maxStmts), &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_ACTIVE_STATEMENTS, (UCHAR*) &dbInf.maxStmts, sizeof(dbInf.maxStmts), &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_DRIVER_NAME, (UCHAR*) dbInf.driverName, 40, &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_DRIVER_NAME, (UCHAR*) dbInf.driverName, 40, &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_DRIVER_ODBC_VER, (UCHAR*) dbInf.odbcVer, 60, &cb) == SQL_ERROR)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_DRIVER_ODBC_VER, (UCHAR*) dbInf.odbcVer, 60, &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
     retcode = SQLGetInfo(hdbc, SQL_ODBC_VER, (UCHAR*) dbInf.drvMgrOdbcVer, 60, &cb);
     if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
 
     retcode = SQLGetInfo(hdbc, SQL_ODBC_VER, (UCHAR*) dbInf.drvMgrOdbcVer, 60, &cb);
     if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
-        return(DispAllErrors(henv, hdbc));
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_DRIVER_VER, (UCHAR*) dbInf.driverVer, 60, &cb) == SQL_ERROR)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_DRIVER_VER, (UCHAR*) dbInf.driverVer, 60, &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_ODBC_API_CONFORMANCE, (UCHAR*) &dbInf.apiConfLvl, sizeof(dbInf.apiConfLvl), &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_ODBC_API_CONFORMANCE, (UCHAR*) &dbInf.apiConfLvl, sizeof(dbInf.apiConfLvl), &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_ODBC_SAG_CLI_CONFORMANCE, (UCHAR*) &dbInf.cliConfLvl, sizeof(dbInf.cliConfLvl), &cb) != SQL_SUCCESS)
-//        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_ODBC_SAG_CLI_CONFORMANCE, (UCHAR*) &dbInf.cliConfLvl, sizeof(dbInf.cliConfLvl), &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
     {
         // Not all drivers support this call - Nick Gorham(unixODBC)
         dbInf.cliConfLvl = 0;
     {
         // Not all drivers support this call - Nick Gorham(unixODBC)
         dbInf.cliConfLvl = 0;
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
     }
 
     }
 
-    if (SQLGetInfo(hdbc, SQL_ODBC_SQL_CONFORMANCE, (UCHAR*) &dbInf.sqlConfLvl, sizeof(dbInf.sqlConfLvl), &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_ODBC_SQL_CONFORMANCE, (UCHAR*) &dbInf.sqlConfLvl, sizeof(dbInf.sqlConfLvl), &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_OUTER_JOINS, (UCHAR*) dbInf.outerJoins, 2, &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_OUTER_JOINS, (UCHAR*) dbInf.outerJoins, 2, &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_PROCEDURES, (UCHAR*) dbInf.procedureSupport, 2, &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_PROCEDURES, (UCHAR*) dbInf.procedureSupport, 2, &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_ACCESSIBLE_TABLES, (UCHAR*) dbInf.accessibleTables, 2, &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_ACCESSIBLE_TABLES, (UCHAR*) dbInf.accessibleTables, 2, &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_CURSOR_COMMIT_BEHAVIOR, (UCHAR*) &dbInf.cursorCommitBehavior, sizeof(dbInf.cursorCommitBehavior), &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_CURSOR_COMMIT_BEHAVIOR, (UCHAR*) &dbInf.cursorCommitBehavior, sizeof(dbInf.cursorCommitBehavior), &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_CURSOR_ROLLBACK_BEHAVIOR, (UCHAR*) &dbInf.cursorRollbackBehavior, sizeof(dbInf.cursorRollbackBehavior), &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_CURSOR_ROLLBACK_BEHAVIOR, (UCHAR*) &dbInf.cursorRollbackBehavior, sizeof(dbInf.cursorRollbackBehavior), &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_NON_NULLABLE_COLUMNS, (UCHAR*) &dbInf.supportNotNullClause, sizeof(dbInf.supportNotNullClause), &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_NON_NULLABLE_COLUMNS, (UCHAR*) &dbInf.supportNotNullClause, sizeof(dbInf.supportNotNullClause), &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_ODBC_SQL_OPT_IEF, (UCHAR*) dbInf.supportIEF, 2, &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_ODBC_SQL_OPT_IEF, (UCHAR*) dbInf.supportIEF, 2, &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_DEFAULT_TXN_ISOLATION, (UCHAR*) &dbInf.txnIsolation, sizeof(dbInf.txnIsolation), &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_DEFAULT_TXN_ISOLATION, (UCHAR*) &dbInf.txnIsolation, sizeof(dbInf.txnIsolation), &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_TXN_ISOLATION_OPTION, (UCHAR*) &dbInf.txnIsolationOptions, sizeof(dbInf.txnIsolationOptions), &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_TXN_ISOLATION_OPTION, (UCHAR*) &dbInf.txnIsolationOptions, sizeof(dbInf.txnIsolationOptions), &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_FETCH_DIRECTION, (UCHAR*) &dbInf.fetchDirections, sizeof(dbInf.fetchDirections), &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_FETCH_DIRECTION, (UCHAR*) &dbInf.fetchDirections, sizeof(dbInf.fetchDirections), &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_LOCK_TYPES, (UCHAR*) &dbInf.lockTypes, sizeof(dbInf.lockTypes), &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_LOCK_TYPES, (UCHAR*) &dbInf.lockTypes, sizeof(dbInf.lockTypes), &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_POS_OPERATIONS, (UCHAR*) &dbInf.posOperations, sizeof(dbInf.posOperations), &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_POS_OPERATIONS, (UCHAR*) &dbInf.posOperations, sizeof(dbInf.posOperations), &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_POSITIONED_STATEMENTS, (UCHAR*) &dbInf.posStmts, sizeof(dbInf.posStmts), &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_POSITIONED_STATEMENTS, (UCHAR*) &dbInf.posStmts, sizeof(dbInf.posStmts), &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_SCROLL_CONCURRENCY, (UCHAR*) &dbInf.scrollConcurrency, sizeof(dbInf.scrollConcurrency), &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_SCROLL_CONCURRENCY, (UCHAR*) &dbInf.scrollConcurrency, sizeof(dbInf.scrollConcurrency), &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_SCROLL_OPTIONS, (UCHAR*) &dbInf.scrollOptions, sizeof(dbInf.scrollOptions), &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_SCROLL_OPTIONS, (UCHAR*) &dbInf.scrollOptions, sizeof(dbInf.scrollOptions), &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_STATIC_SENSITIVITY, (UCHAR*) &dbInf.staticSensitivity, sizeof(dbInf.staticSensitivity), &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_STATIC_SENSITIVITY, (UCHAR*) &dbInf.staticSensitivity, sizeof(dbInf.staticSensitivity), &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_TXN_CAPABLE, (UCHAR*) &dbInf.txnCapable, sizeof(dbInf.txnCapable), &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_TXN_CAPABLE, (UCHAR*) &dbInf.txnCapable, sizeof(dbInf.txnCapable), &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 
-    if (SQLGetInfo(hdbc, SQL_LOGIN_TIMEOUT, (UCHAR*) &dbInf.loginTimeout, sizeof(dbInf.loginTimeout), &cb) != SQL_SUCCESS)
-        return(DispAllErrors(henv, hdbc));
+    retcode = SQLGetInfo(hdbc, SQL_LOGIN_TIMEOUT, (UCHAR*) &dbInf.loginTimeout, sizeof(dbInf.loginTimeout), &cb);
+    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+       {
+               DispAllErrors(henv, hdbc);
+               if (failOnDataTypeUnsupported)
+                       return FALSE;
+       }
 
 #ifdef DBDEBUG_CONSOLE
 
 #ifdef DBDEBUG_CONSOLE
-    cout << "***** DATA SOURCE INFORMATION *****" << endl;
-    cout << "SERVER Name: " << dbInf.serverName << endl;
-    cout << "DBMS Name: " << dbInf.dbmsName << "; DBMS Version: " << dbInf.dbmsVer << endl;
-    cout << "ODBC Version: " << dbInf.odbcVer << "; Driver Version: " << dbInf.driverVer << endl;
+    cout << wxT("***** DATA SOURCE INFORMATION *****") << endl;
+    cout << wxT(wxT("SERVER Name: ") << dbInf.serverName << endl;
+    cout << wxT("DBMS Name: ") << dbInf.dbmsName << wxT("; DBMS Version: ") << dbInf.dbmsVer << endl;
+    cout << wxT("ODBC Version: ") << dbInf.odbcVer << wxT("; Driver Version: ") << dbInf.driverVer << endl;
 
 
-    cout << "API Conf. Level: ";
+    cout << wxT("API Conf. Level: ");
     switch(dbInf.apiConfLvl)
     {
     switch(dbInf.apiConfLvl)
     {
-        case SQL_OAC_NONE:      cout << "None";       break;
-        case SQL_OAC_LEVEL1:    cout << "Level 1";    break;
-        case SQL_OAC_LEVEL2:    cout << "Level 2";    break;
+        case SQL_OAC_NONE:      cout << wxT("None");       break;
+        case SQL_OAC_LEVEL1:    cout << wxT("Level 1");    break;
+        case SQL_OAC_LEVEL2:    cout << wxT("Level 2");    break;
     }
     cout << endl;
 
     }
     cout << endl;
 
-    cout << "SAG CLI Conf. Level: ";
+    cout << wxT("SAG CLI Conf. Level: ");
     switch(dbInf.cliConfLvl)
     {
     switch(dbInf.cliConfLvl)
     {
-        case SQL_OSCC_NOT_COMPLIANT:    cout << "Not Compliant";    break;
-        case SQL_OSCC_COMPLIANT:        cout << "Compliant";        break;
+        case SQL_OSCC_NOT_COMPLIANT:    cout << wxT("Not Compliant");    break;
+        case SQL_OSCC_COMPLIANT:        cout << wxT("Compliant");        break;
     }
     cout << endl;
 
     }
     cout << endl;
 
-    cout << "SQL Conf. Level: ";
+    cout << wxT("SQL Conf. Level: ");
     switch(dbInf.sqlConfLvl)
     {
     switch(dbInf.sqlConfLvl)
     {
-        case SQL_OSC_MINIMUM:     cout << "Minimum Grammar";     break;
-        case SQL_OSC_CORE:        cout << "Core Grammar";        break;
-        case SQL_OSC_EXTENDED:    cout << "Extended Grammar";    break;
+        case SQL_OSC_MINIMUM:     cout << wxT("Minimum Grammar");     break;
+        case SQL_OSC_CORE:        cout << wxT("Core Grammar");        break;
+        case SQL_OSC_EXTENDED:    cout << wxT("Extended Grammar");    break;
     }
     cout << endl;
 
     }
     cout << endl;
 
-    cout << "Max. Connections: "       << dbInf.maxConnections   << endl;
-    cout << "Outer Joins: "            << dbInf.outerJoins       << endl;
-    cout << "Support for Procedures: " << dbInf.procedureSupport << endl;
-    cout << "All tables accessible : " << dbInf.accessibleTables << endl;
-    cout << "Cursor COMMIT Behavior: ";
+    cout << wxT("Max. Connections: ")       << dbInf.maxConnections   << endl;
+    cout << wxT("Outer Joins: ")            << dbInf.outerJoins       << endl;
+    cout << wxT("Support for Procedures: ") << dbInf.procedureSupport << endl;
+    cout << wxT("All tables accessible : ") << dbInf.accessibleTables << endl;
+    cout << wxT("Cursor COMMIT Behavior: ");
     switch(dbInf.cursorCommitBehavior)
     {
     switch(dbInf.cursorCommitBehavior)
     {
-        case SQL_CB_DELETE:        cout << "Delete cursors";      break;
-        case SQL_CB_CLOSE:         cout << "Close cursors";       break;
-        case SQL_CB_PRESERVE:      cout << "Preserve cursors";    break;
+        case SQL_CB_DELETE:        cout << wxT("Delete cursors");      break;
+        case SQL_CB_CLOSE:         cout << wxT("Close cursors");       break;
+        case SQL_CB_PRESERVE:      cout << wxT("Preserve cursors");    break;
     }
     cout << endl;
 
     }
     cout << endl;
 
-    cout << "Cursor ROLLBACK Behavior: ";
+    cout << wxT("Cursor ROLLBACK Behavior: ");
     switch(dbInf.cursorRollbackBehavior)
     {
     switch(dbInf.cursorRollbackBehavior)
     {
-        case SQL_CB_DELETE:      cout << "Delete cursors";      break;
-        case SQL_CB_CLOSE:       cout << "Close cursors";       break;
-        case SQL_CB_PRESERVE:    cout << "Preserve cursors";    break;
+        case SQL_CB_DELETE:      cout << wxT("Delete cursors");      break;
+        case SQL_CB_CLOSE:       cout << wxT("Close cursors");       break;
+        case SQL_CB_PRESERVE:    cout << wxT("Preserve cursors");    break;
     }
     cout << endl;
 
     }
     cout << endl;
 
-    cout << "Support NOT NULL clause: ";
+    cout << wxT("Support NOT NULL clause: ");
     switch(dbInf.supportNotNullClause)
     {
     switch(dbInf.supportNotNullClause)
     {
-        case SQL_NNC_NULL:        cout << "No";        break;
-        case SQL_NNC_NON_NULL:    cout << "Yes";       break;
+        case SQL_NNC_NULL:        cout << wxT("No");        break;
+        case SQL_NNC_NON_NULL:    cout << wxT("Yes");       break;
     }
     cout << endl;
 
     }
     cout << endl;
 
-    cout << "Support IEF (Ref. Integrity): " << dbInf.supportIEF   << endl;
-    cout << "Login Timeout: "                << dbInf.loginTimeout << endl;
+    cout << wxT("Support IEF (Ref. Integrity): ") << dbInf.supportIEF   << endl;
+    cout << wxT("Login Timeout: ")                << dbInf.loginTimeout << endl;
 
 
-    cout << endl << endl << "more ..." << endl;
+    cout << endl << endl << wxT("more ...") << endl;
     getchar();
 
     getchar();
 
-    cout << "Default Transaction Isolation: ";
+    cout << wxT("Default Transaction Isolation: ";
     switch(dbInf.txnIsolation)
     {
     switch(dbInf.txnIsolation)
     {
-        case SQL_TXN_READ_UNCOMMITTED:  cout << "Read Uncommitted";    break;
-        case SQL_TXN_READ_COMMITTED:    cout << "Read Committed";      break;
-        case SQL_TXN_REPEATABLE_READ:   cout << "Repeatable Read";     break;
-        case SQL_TXN_SERIALIZABLE:      cout << "Serializable";        break;
+        case SQL_TXN_READ_UNCOMMITTED:  cout << wxT("Read Uncommitted");    break;
+        case SQL_TXN_READ_COMMITTED:    cout << wxT("Read Committed");      break;
+        case SQL_TXN_REPEATABLE_READ:   cout << wxT("Repeatable Read");     break;
+        case SQL_TXN_SERIALIZABLE:      cout << wxT("Serializable");        break;
 #ifdef ODBC_V20
 #ifdef ODBC_V20
-        case SQL_TXN_VERSIONING:        cout << "Versioning";          break;
+        case SQL_TXN_VERSIONING:        cout << wxT("Versioning");          break;
 #endif
     }
     cout << endl;
 
 #endif
     }
     cout << endl;
 
-    cout << "Transaction Isolation Options: ";
+    cout << wxT("Transaction Isolation Options: ");
     if (dbInf.txnIsolationOptions & SQL_TXN_READ_UNCOMMITTED)
     if (dbInf.txnIsolationOptions & SQL_TXN_READ_UNCOMMITTED)
-        cout << "Read Uncommitted, ";
+        cout << wxT("Read Uncommitted, ");
     if (dbInf.txnIsolationOptions & SQL_TXN_READ_COMMITTED)
     if (dbInf.txnIsolationOptions & SQL_TXN_READ_COMMITTED)
-        cout << "Read Committed, ";
+        cout << wxT("Read Committed, ");
     if (dbInf.txnIsolationOptions & SQL_TXN_REPEATABLE_READ)
     if (dbInf.txnIsolationOptions & SQL_TXN_REPEATABLE_READ)
-        cout << "Repeatable Read, ";
+        cout << wxT("Repeatable Read, ");
     if (dbInf.txnIsolationOptions & SQL_TXN_SERIALIZABLE)
     if (dbInf.txnIsolationOptions & SQL_TXN_SERIALIZABLE)
-        cout << "Serializable, ";
+        cout << wxT("Serializable, ");
 #ifdef ODBC_V20
     if (dbInf.txnIsolationOptions & SQL_TXN_VERSIONING)
 #ifdef ODBC_V20
     if (dbInf.txnIsolationOptions & SQL_TXN_VERSIONING)
-        cout << "Versioning";
+        cout << wxT("Versioning");
 #endif
     cout << endl;
 
 #endif
     cout << endl;
 
-    cout << "Fetch Directions Supported:" << endl << "   ";
+    cout << wxT("Fetch Directions Supported:") << endl << wxT("   ");
     if (dbInf.fetchDirections & SQL_FD_FETCH_NEXT)
     if (dbInf.fetchDirections & SQL_FD_FETCH_NEXT)
-        cout << "Next, ";
+        cout << wxT("Next, ");
     if (dbInf.fetchDirections & SQL_FD_FETCH_PRIOR)
     if (dbInf.fetchDirections & SQL_FD_FETCH_PRIOR)
-        cout << "Prev, ";
+        cout << wxT("Prev, ");
     if (dbInf.fetchDirections & SQL_FD_FETCH_FIRST)
     if (dbInf.fetchDirections & SQL_FD_FETCH_FIRST)
-        cout << "First, ";
+        cout << wxT("First, ");
     if (dbInf.fetchDirections & SQL_FD_FETCH_LAST)
     if (dbInf.fetchDirections & SQL_FD_FETCH_LAST)
-        cout << "Last, ";
+        cout << wxT("Last, ");
     if (dbInf.fetchDirections & SQL_FD_FETCH_ABSOLUTE)
     if (dbInf.fetchDirections & SQL_FD_FETCH_ABSOLUTE)
-        cout << "Absolute, ";
+        cout << wxT("Absolute, ");
     if (dbInf.fetchDirections & SQL_FD_FETCH_RELATIVE)
     if (dbInf.fetchDirections & SQL_FD_FETCH_RELATIVE)
-        cout << "Relative, ";
+        cout << wxT("Relative, ");
 #ifdef ODBC_V20
     if (dbInf.fetchDirections & SQL_FD_FETCH_RESUME)
 #ifdef ODBC_V20
     if (dbInf.fetchDirections & SQL_FD_FETCH_RESUME)
-        cout << "Resume, ";
+        cout << wxT("Resume, ");
 #endif
     if (dbInf.fetchDirections & SQL_FD_FETCH_BOOKMARK)
 #endif
     if (dbInf.fetchDirections & SQL_FD_FETCH_BOOKMARK)
-        cout << "Bookmark";
+        cout << wxT("Bookmark");
     cout << endl;
 
     cout << endl;
 
-    cout << "Lock Types Supported (SQLSetPos): ";
+    cout << wxT("Lock Types Supported (SQLSetPos): ");
     if (dbInf.lockTypes & SQL_LCK_NO_CHANGE)
     if (dbInf.lockTypes & SQL_LCK_NO_CHANGE)
-        cout << "No Change, ";
+        cout << wxT("No Change, ");
     if (dbInf.lockTypes & SQL_LCK_EXCLUSIVE)
     if (dbInf.lockTypes & SQL_LCK_EXCLUSIVE)
-        cout << "Exclusive, ";
+        cout << wxT("Exclusive, ");
     if (dbInf.lockTypes & SQL_LCK_UNLOCK)
     if (dbInf.lockTypes & SQL_LCK_UNLOCK)
-        cout << "UnLock";
+        cout << wxT("UnLock");
     cout << endl;
 
     cout << endl;
 
-    cout << "Position Operations Supported (SQLSetPos): ";
+    cout << wxT("Position Operations Supported (SQLSetPos): ");
     if (dbInf.posOperations & SQL_POS_POSITION)
     if (dbInf.posOperations & SQL_POS_POSITION)
-        cout << "Position, ";
+        cout << wxT("Position, ");
     if (dbInf.posOperations & SQL_POS_REFRESH)
     if (dbInf.posOperations & SQL_POS_REFRESH)
-        cout << "Refresh, ";
+        cout << wxT("Refresh, ");
     if (dbInf.posOperations & SQL_POS_UPDATE)
     if (dbInf.posOperations & SQL_POS_UPDATE)
-        cout << "Upd, ";
+        cout << wxT("Upd, "));
     if (dbInf.posOperations & SQL_POS_DELETE)
     if (dbInf.posOperations & SQL_POS_DELETE)
-        cout << "Del, ";
+        cout << wxT("Del, ");
     if (dbInf.posOperations & SQL_POS_ADD)
     if (dbInf.posOperations & SQL_POS_ADD)
-        cout << "Add";
+        cout << wxT("Add");
     cout << endl;
 
     cout << endl;
 
-    cout << "Positioned Statements Supported: ";
+    cout << wxT("Positioned Statements Supported: ");
     if (dbInf.posStmts & SQL_PS_POSITIONED_DELETE)
     if (dbInf.posStmts & SQL_PS_POSITIONED_DELETE)
-        cout << "Pos delete, ";
+        cout << wxT("Pos delete, ");
     if (dbInf.posStmts & SQL_PS_POSITIONED_UPDATE)
     if (dbInf.posStmts & SQL_PS_POSITIONED_UPDATE)
-        cout << "Pos update, ";
+        cout << wxT("Pos update, ");
     if (dbInf.posStmts & SQL_PS_SELECT_FOR_UPDATE)
     if (dbInf.posStmts & SQL_PS_SELECT_FOR_UPDATE)
-        cout << "Select for update";
+        cout << wxT("Select for update");
     cout << endl;
 
     cout << endl;
 
-    cout << "Scroll Concurrency: ";
+    cout << wxT("Scroll Concurrency: ");
     if (dbInf.scrollConcurrency & SQL_SCCO_READ_ONLY)
     if (dbInf.scrollConcurrency & SQL_SCCO_READ_ONLY)
-        cout << "Read Only, ";
+        cout << wxT("Read Only, ");
     if (dbInf.scrollConcurrency & SQL_SCCO_LOCK)
     if (dbInf.scrollConcurrency & SQL_SCCO_LOCK)
-        cout << "Lock, ";
+        cout << wxT("Lock, ");
     if (dbInf.scrollConcurrency & SQL_SCCO_OPT_ROWVER)
     if (dbInf.scrollConcurrency & SQL_SCCO_OPT_ROWVER)
-        cout << "Opt. Rowver, ";
+        cout << wxT("Opt. Rowver, ");
     if (dbInf.scrollConcurrency & SQL_SCCO_OPT_VALUES)
     if (dbInf.scrollConcurrency & SQL_SCCO_OPT_VALUES)
-        cout << "Opt. Values";
+        cout << wxT("Opt. Values");
     cout << endl;
 
     cout << endl;
 
-    cout << "Scroll Options: ";
+    cout << wxT("Scroll Options: ");
     if (dbInf.scrollOptions & SQL_SO_FORWARD_ONLY)
     if (dbInf.scrollOptions & SQL_SO_FORWARD_ONLY)
-        cout << "Fwd Only, ";
+        cout << wxT("Fwd Only, ");
     if (dbInf.scrollOptions & SQL_SO_STATIC)
     if (dbInf.scrollOptions & SQL_SO_STATIC)
-        cout << "Static, ";
+        cout << wxT("Static, ");
     if (dbInf.scrollOptions & SQL_SO_KEYSET_DRIVEN)
     if (dbInf.scrollOptions & SQL_SO_KEYSET_DRIVEN)
-        cout << "Keyset Driven, ";
+        cout << wxT("Keyset Driven, ");
     if (dbInf.scrollOptions & SQL_SO_DYNAMIC)
     if (dbInf.scrollOptions & SQL_SO_DYNAMIC)
-        cout << "Dynamic, ";
+        cout << wxT("Dynamic, ");
     if (dbInf.scrollOptions & SQL_SO_MIXED)
     if (dbInf.scrollOptions & SQL_SO_MIXED)
-        cout << "Mixed";
+        cout << wxT("Mixed");
     cout << endl;
 
     cout << endl;
 
-    cout << "Static Sensitivity: ";
+    cout << wxT("Static Sensitivity: ");
     if (dbInf.staticSensitivity & SQL_SS_ADDITIONS)
     if (dbInf.staticSensitivity & SQL_SS_ADDITIONS)
-        cout << "Additions, ";
+        cout << wxT("Additions, ");
     if (dbInf.staticSensitivity & SQL_SS_DELETIONS)
     if (dbInf.staticSensitivity & SQL_SS_DELETIONS)
-        cout << "Deletions, ";
+        cout << wxT("Deletions, ");
     if (dbInf.staticSensitivity & SQL_SS_UPDATES)
     if (dbInf.staticSensitivity & SQL_SS_UPDATES)
-        cout << "Updates";
+        cout << wxT("Updates");
     cout << endl;
 
     cout << endl;
 
-    cout << "Transaction Capable?: ";
+    cout << wxT("Transaction Capable?: ");
     switch(dbInf.txnCapable)
     {
     switch(dbInf.txnCapable)
     {
-        case SQL_TC_NONE:          cout << "No";            break;
-        case SQL_TC_DML:           cout << "DML Only";      break;
-        case SQL_TC_DDL_COMMIT:    cout << "DDL Commit";    break;
-        case SQL_TC_DDL_IGNORE:    cout << "DDL Ignore";    break;
-        case SQL_TC_ALL:           cout << "DDL & DML";     break;
+        case SQL_TC_NONE:          cout << wxT("No");            break;
+        case SQL_TC_DML:           cout << wxT("DML Only");      break;
+        case SQL_TC_DDL_COMMIT:    cout << wxT("DDL Commit");    break;
+        case SQL_TC_DDL_IGNORE:    cout << wxT("DDL Ignore");    break;
+        case SQL_TC_ALL:           cout << wxT("DDL & DML");     break;
     }
     cout << endl;
 
     }
     cout << endl;
 
@@ -1078,40 +1555,53 @@ bool wxDb::getDataTypeInfo(SWORD fSqlType, wxDbSqlTypeInfo &structSQLTypeInfo)
     // Get information about the data type specified
     if (SQLGetTypeInfo(hstmt, fSqlType) != SQL_SUCCESS)
         return(DispAllErrors(henv, hdbc, hstmt));
     // Get information about the data type specified
     if (SQLGetTypeInfo(hstmt, fSqlType) != SQL_SUCCESS)
         return(DispAllErrors(henv, hdbc, hstmt));
+
     // Fetch the record
     // Fetch the record
-    if ((retcode = SQLFetch(hstmt)) != SQL_SUCCESS)
+    retcode = SQLFetch(hstmt);
+    if (retcode != SQL_SUCCESS)
     {
 #ifdef DBDEBUG_CONSOLE
         if (retcode == SQL_NO_DATA_FOUND)
     {
 #ifdef DBDEBUG_CONSOLE
         if (retcode == SQL_NO_DATA_FOUND)
-            cout << "SQL_NO_DATA_FOUND fetching inf. about data type." << endl;
+            cout << wxT("SQL_NO_DATA_FOUND fetching inf. about data type.") << endl;
 #endif
         DispAllErrors(henv, hdbc, hstmt);
         SQLFreeStmt(hstmt, SQL_CLOSE);
         return(FALSE);
     }
 #endif
         DispAllErrors(henv, hdbc, hstmt);
         SQLFreeStmt(hstmt, SQL_CLOSE);
         return(FALSE);
     }
+
+    wxChar typeName[DB_TYPE_NAME_LEN+1];
+
     // Obtain columns from the record
     // Obtain columns from the record
-    if (SQLGetData(hstmt, 1, SQL_C_CHAR, (UCHAR*) structSQLTypeInfo.TypeName, DB_TYPE_NAME_LEN, &cbRet) != SQL_SUCCESS)
+    if (SQLGetData(hstmt, 1, SQL_C_CHAR, (UCHAR*) typeName, DB_TYPE_NAME_LEN, &cbRet) != SQL_SUCCESS)
         return(DispAllErrors(henv, hdbc, hstmt));
 
         return(DispAllErrors(henv, hdbc, hstmt));
 
+    structSQLTypeInfo.TypeName = typeName;
+
     // BJO 20000503: no more needed with new GetColumns...
 #if  OLD_GETCOLUMNS
     // BJO 991209
     if (Dbms() == dbmsMY_SQL)
     {
     // BJO 20000503: no more needed with new GetColumns...
 #if  OLD_GETCOLUMNS
     // BJO 991209
     if (Dbms() == dbmsMY_SQL)
     {
-        if (!wxStrcmp(structSQLTypeInfo.TypeName, "middleint")) wxStrcpy(structSQLTypeInfo.TypeName, "mediumint");
-        if (!wxStrcmp(structSQLTypeInfo.TypeName, "middleint unsigned")) wxStrcpy(structSQLTypeInfo.TypeName, "mediumint unsigned");
-        if (!wxStrcmp(structSQLTypeInfo.TypeName, "integer")) wxStrcpy(structSQLTypeInfo.TypeName, "int");
-        if (!wxStrcmp(structSQLTypeInfo.TypeName, "integer unsigned")) wxStrcpy(structSQLTypeInfo.TypeName, "int unsigned");
-        if (!wxStrcmp(structSQLTypeInfo.TypeName, "middleint")) wxStrcpy(structSQLTypeInfo.TypeName, "mediumint");
-        if (!wxStrcmp(structSQLTypeInfo.TypeName, "varchar")) wxStrcpy(structSQLTypeInfo.TypeName, "char");
+        if (structSQLTypeInfo.TypeName == wxT("middleint"))
+            structSQLTypeInfo.TypeName = wxT("mediumint");
+        else if (structSQLTypeInfo.TypeName == wxT("middleint unsigned"))
+            structSQLTypeInfo.TypeName = wxT("mediumint unsigned");
+        else if (structSQLTypeInfo.TypeName == wxT("integer"))
+            structSQLTypeInfo.TypeName = wxT("int");
+        else if (structSQLTypeInfo.TypeName == wxT("integer unsigned"))
+            structSQLTypeInfo.TypeName = wxT("int unsigned");
+        else if (structSQLTypeInfo.TypeName == wxT("middleint"))
+            structSQLTypeInfo.TypeName = wxT("mediumint");
+        else if (structSQLTypeInfo.TypeName == wxT("varchar"))
+            structSQLTypeInfo.TypeName = wxT("char");
     }
 
     // BJO 20000427 : OpenLink driver
     }
 
     // BJO 20000427 : OpenLink driver
-    if (!wxStrncmp(dbInf.driverName, "oplodbc", 7) ||
-        !wxStrncmp(dbInf.driverName, "OLOD", 4))
+    if (!wxStrncmp(dbInf.driverName, wxT("oplodbc"), 7) ||
+        !wxStrncmp(dbInf.driverName, wxT("OLOD"), 4))
     {
     {
-        if (!wxStrcmp(structSQLTypeInfo.TypeName, "double precision"))
-            wxStrcpy(structSQLTypeInfo.TypeName, "real");
+        if (structSQLTypeInfo.TypeName == wxT("double precision"))
+            structSQLTypeInfo.TypeName = wxT("real");
     }
 #endif
 
     }
 #endif
 
@@ -1164,32 +1654,32 @@ void wxDb::Close(void)
         DispAllErrors(henv, hdbc);
 
     // There should be zero Ctable objects still connected to this db object
         DispAllErrors(henv, hdbc);
 
     // There should be zero Ctable objects still connected to this db object
-    assert(nTables == 0);
+    wxASSERT(nTables == 0);
 
 #ifdef __WXDEBUG__
     wxTablesInUse *tiu;
 
 #ifdef __WXDEBUG__
     wxTablesInUse *tiu;
-    wxNode *pNode;
-    pNode = TablesInUse.First();
+    wxList::compatibility_iterator pNode;
+    pNode = TablesInUse.GetFirst();
     wxString s,s2;
     while (pNode)
     {
     wxString s,s2;
     while (pNode)
     {
-        tiu = (wxTablesInUse *)pNode->Data();
+        tiu = (wxTablesInUse *)pNode->GetData();
         if (tiu->pDb == this)
         {
         if (tiu->pDb == this)
         {
-            s.sprintf(wxT("(%-20s)     tableID:[%6lu]     pDb:[%p]"), tiu->tableName,tiu->tableID,tiu->pDb);
-            s2.sprintf(wxT("Orphaned found using pDb:[%p]"),this);
-            wxLogDebug (s.c_str(),s2.c_str());
+            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());
         }
         }
-        pNode = pNode->Next();
+        pNode = pNode->GetNext();
     }
 #endif
 
     // Copy the error messages to a global variable
     int i;
     for (i = 0; i < DB_MAX_ERROR_HISTORY; i++)
     }
 #endif
 
     // Copy the error messages to a global variable
     int i;
     for (i = 0; i < DB_MAX_ERROR_HISTORY; i++)
-        wxStrcpy(DBerrorList[i],errorList[i]);
+        wxStrcpy(DBerrorList[i], errorList[i]);
 
 
-    dbmsType   = dbmsUNIDENTIFIED;
+    dbmsType = dbmsUNIDENTIFIED;
     dbIsOpen = FALSE;
 
 } // wxDb::Close()
     dbIsOpen = FALSE;
 
 } // wxDb::Close()
@@ -1232,7 +1722,7 @@ bool wxDb::DispAllErrors(HENV aHenv, HDBC aHdbc, HSTMT aHstmt)
  * actual error(s) that just occured on the previous request of the datasource.
  *
  * The function will retrieve each error condition from the datasource and
  * actual error(s) that just occured on the previous request of the datasource.
  *
  * The function will retrieve each error condition from the datasource and
- * sprintf the codes/text values into a string which it then logs via logError().
+ * 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.
  *
  * 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.
  *
@@ -1243,26 +1733,26 @@ bool wxDb::DispAllErrors(HENV aHenv, HDBC aHdbc, HSTMT aHstmt)
 {
     wxString odbcErrMsg;
 
 {
     wxString odbcErrMsg;
 
-    while (SQLError(aHenv, aHdbc, aHstmt, (UCHAR FAR *) sqlState, &nativeError, (UCHAR FAR *) errorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &cbErrorMsg) == SQL_SUCCESS)
+    while (SQLError(aHenv, aHdbc, aHstmt, (SQLTCHAR FAR *) sqlState, &nativeError, (SQLTCHAR FAR *) errorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &cbErrorMsg) == SQL_SUCCESS)
     {
     {
-        odbcErrMsg.sprintf("SQL State = %s\nNative Error Code = %li\nError Message = %s\n", sqlState, nativeError, errorMsg);
-        logError(odbcErrMsg.c_str(), sqlState);
+        odbcErrMsg.Printf(wxT("SQL State = %s\nNative Error Code = %li\nError Message = %s\n"), sqlState, nativeError, errorMsg);
+        logError(odbcErrMsg, sqlState);
         if (!silent)
         {
 #ifdef DBDEBUG_CONSOLE
             // When run in console mode, use standard out to display errors.
             cout << odbcErrMsg.c_str() << endl;
         if (!silent)
         {
 #ifdef DBDEBUG_CONSOLE
             // When run in console mode, use standard out to display errors.
             cout << odbcErrMsg.c_str() << endl;
-            cout << "Press any key to continue..." << endl;
+            cout << wxT("Press any key to continue...") << endl;
             getchar();
 #endif
 
 #ifdef __WXDEBUG__
             getchar();
 #endif
 
 #ifdef __WXDEBUG__
-            wxLogDebug(odbcErrMsg.c_str(),wxT("ODBC DEBUG MESSAGE from DispAllErrors()"));
+            wxLogDebug(odbcErrMsg,wxT("ODBC DEBUG MESSAGE from DispAllErrors()"));
 #endif
         }
     }
 
 #endif
         }
     }
 
-    return(FALSE);  // This function always returns false.
+    return(FALSE);  // This function always returns FALSE.
 
 } // wxDb::DispAllErrors()
 
 
 } // wxDb::DispAllErrors()
 
@@ -1270,7 +1760,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)
 {
-    if (SQLError(aHenv, aHdbc, aHstmt, (UCHAR FAR *) sqlState, &nativeError, (UCHAR FAR *) errorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &cbErrorMsg) == SQL_SUCCESS)
+    if (SQLError(aHenv, aHdbc, aHstmt, (SQLTCHAR FAR *) sqlState, &nativeError, (SQLTCHAR FAR *) errorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &cbErrorMsg) == SQL_SUCCESS)
         return(TRUE);
     else
         return(FALSE);
         return(TRUE);
     else
         return(FALSE);
@@ -1283,8 +1773,8 @@ void wxDb::DispNextError(void)
 {
     wxString odbcErrMsg;
 
 {
     wxString odbcErrMsg;
 
-    odbcErrMsg.sprintf("SQL State = %s\nNative Error Code = %li\nError Message = %s\n", sqlState, nativeError, errorMsg);
-    logError(odbcErrMsg.c_str(), sqlState);
+    odbcErrMsg.Printf(wxT("SQL State = %s\nNative Error Code = %li\nError Message = %s\n"), sqlState, nativeError, errorMsg);
+    logError(odbcErrMsg, sqlState);
 
     if (silent)
         return;
 
     if (silent)
         return;
@@ -1292,7 +1782,7 @@ void wxDb::DispNextError(void)
 #ifdef DBDEBUG_CONSOLE
     // When run in console mode, use standard out to display errors.
     cout << odbcErrMsg.c_str() << endl;
 #ifdef DBDEBUG_CONSOLE
     // When run in console mode, use standard out to display errors.
     cout << odbcErrMsg.c_str() << endl;
-    cout << "Press any key to continue..."  << endl;
+    cout << wxT("Press any key to continue...")  << endl;
     getchar();
 #endif
 
     getchar();
 #endif
 
@@ -1304,9 +1794,9 @@ void wxDb::DispNextError(void)
 
 
 /********** wxDb::logError() **********/
 
 
 /********** wxDb::logError() **********/
-void wxDb::logError(const char *errMsg, const char *SQLState)
+void wxDb::logError(const wxString &errMsg, const wxString &SQLState)
 {
 {
-    assert(errMsg && wxStrlen(errMsg));
+    wxASSERT(errMsg.Length());
 
     static int pLast = -1;
     int dbStatus;
 
     static int pLast = -1;
     int dbStatus;
@@ -1321,7 +1811,7 @@ void wxDb::logError(const char *errMsg, const char *SQLState)
 
     wxStrcpy(errorList[pLast], errMsg);
 
 
     wxStrcpy(errorList[pLast], errMsg);
 
-    if (SQLState && wxStrlen(SQLState))
+    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;
 
@@ -1332,7 +1822,7 @@ void wxDb::logError(const char *errMsg, const char *SQLState)
 
 
 /**********wxDb::TranslateSqlState()  **********/
 
 
 /**********wxDb::TranslateSqlState()  **********/
-int wxDb::TranslateSqlState(const wxChar *SQLState)
+int wxDb::TranslateSqlState(const wxString &SQLState)
 {
     if (!wxStrcmp(SQLState, wxT("01000")))
         return(DB_ERR_GENERAL_WARNING);
 {
     if (!wxStrcmp(SQLState, wxT("01000")))
         return(DB_ERR_GENERAL_WARNING);
@@ -1520,60 +2010,61 @@ int wxDb::TranslateSqlState(const wxChar *SQLState)
 
 
 /**********  wxDb::Grant() **********/
 
 
 /**********  wxDb::Grant() **********/
-bool wxDb::Grant(int privileges, const char *tableName, const char *userList)
+bool wxDb::Grant(int privileges, const wxString &tableName, const wxString &userList)
 {
     wxString sqlStmt;
 
     // Build the grant statement
 {
     wxString sqlStmt;
 
     // Build the grant statement
-    sqlStmt  = "GRANT ";
+    sqlStmt  = wxT("GRANT ");
     if (privileges == DB_GRANT_ALL)
     if (privileges == DB_GRANT_ALL)
-        sqlStmt += "ALL";
+        sqlStmt += wxT("ALL");
     else
     {
         int c = 0;
         if (privileges & DB_GRANT_SELECT)
         {
     else
     {
         int c = 0;
         if (privileges & DB_GRANT_SELECT)
         {
-            sqlStmt += "SELECT";
+            sqlStmt += wxT("SELECT");
             c++;
         }
         if (privileges & DB_GRANT_INSERT)
         {
             if (c++)
             c++;
         }
         if (privileges & DB_GRANT_INSERT)
         {
             if (c++)
-                sqlStmt += ", ";
-            sqlStmt += "INSERT";
+                sqlStmt += wxT(", ");
+            sqlStmt += wxT("INSERT");
         }
         if (privileges & DB_GRANT_UPDATE)
         {
             if (c++)
         }
         if (privileges & DB_GRANT_UPDATE)
         {
             if (c++)
-                sqlStmt += ", ";
-            sqlStmt += "UPDATE";
+                sqlStmt += wxT(", ");
+            sqlStmt += wxT("UPDATE");
         }
         if (privileges & DB_GRANT_DELETE)
         {
             if (c++)
         }
         if (privileges & DB_GRANT_DELETE)
         {
             if (c++)
-                sqlStmt += ", ";
-            sqlStmt += "DELETE";
+                sqlStmt += wxT(", ");
+            sqlStmt += wxT("DELETE");
         }
     }
 
         }
     }
 
-    sqlStmt += " ON ";
-    sqlStmt += tableName;
-    sqlStmt += " TO ";
+    sqlStmt += wxT(" ON ");
+    sqlStmt += SQLTableName(tableName);
+    sqlStmt += wxT(" TO ");
     sqlStmt += userList;
 
 #ifdef DBDEBUG_CONSOLE
     cout << endl << sqlStmt.c_str() << endl;
 #endif
 
     sqlStmt += userList;
 
 #ifdef DBDEBUG_CONSOLE
     cout << endl << sqlStmt.c_str() << endl;
 #endif
 
-    WriteSqlLog(sqlStmt.c_str());
+    WriteSqlLog(sqlStmt);
 
 
-    return(ExecSql(sqlStmt.c_str()));
+    return(ExecSql(sqlStmt));
 
 }  // wxDb::Grant()
 
 
 /********** wxDb::CreateView() **********/
 
 }  // wxDb::Grant()
 
 
 /********** wxDb::CreateView() **********/
-bool wxDb::CreateView(const char *viewName, const char *colList, const char *pSqlStmt, bool attemptDrop)
+bool wxDb::CreateView(const wxString &viewName, const wxString &colList,
+                      const wxString &pSqlStmt, bool attemptDrop)
 {
     wxString sqlStmt;
 
 {
     wxString sqlStmt;
 
@@ -1582,32 +2073,32 @@ bool wxDb::CreateView(const char *viewName, const char *colList, const char *pSq
         return FALSE;
 
     // Build the create view statement
         return FALSE;
 
     // Build the create view statement
-    sqlStmt  = "CREATE VIEW ";
+    sqlStmt  = wxT("CREATE VIEW ");
     sqlStmt += viewName;
 
     sqlStmt += viewName;
 
-    if (wxStrlen(colList))
+    if (colList.Length())
     {
     {
-        sqlStmt += " (";
+        sqlStmt += wxT(" (");
         sqlStmt += colList;
         sqlStmt += colList;
-        sqlStmt += ")";
+        sqlStmt += wxT(")");
     }
 
     }
 
-    sqlStmt += " AS ";
+    sqlStmt += wxT(" AS ");
     sqlStmt += pSqlStmt;
 
     sqlStmt += pSqlStmt;
 
-    WriteSqlLog(sqlStmt.c_str());
+    WriteSqlLog(sqlStmt);
 
 #ifdef DBDEBUG_CONSOLE
     cout << sqlStmt.c_str() << endl;
 #endif
 
 
 #ifdef DBDEBUG_CONSOLE
     cout << sqlStmt.c_str() << endl;
 #endif
 
-    return(ExecSql(sqlStmt.c_str()));
+    return(ExecSql(sqlStmt));
 
 }  // wxDb::CreateView()
 
 
 /********** wxDb::DropView()  **********/
 
 }  // wxDb::CreateView()
 
 
 /********** wxDb::DropView()  **********/
-bool wxDb::DropView(const char *viewName)
+bool wxDb::DropView(const wxString &viewName)
 {
 /*
  * NOTE: This function returns TRUE if the View does not exist, but
 {
 /*
  * NOTE: This function returns TRUE if the View does not exist, but
@@ -1615,18 +2106,17 @@ bool wxDb::DropView(const char *viewName)
  *            below for any other databases when those databases are defined
  *       to handle this situation consistently
  */
  *            below for any other databases when those databases are defined
  *       to handle this situation consistently
  */
-//    char sqlStmt[DB_MAX_STATEMENT_LEN];
     wxString sqlStmt;
 
     wxString sqlStmt;
 
-    sqlStmt.sprintf("DROP VIEW %s", viewName);
+    sqlStmt.Printf(wxT("DROP VIEW %s"), viewName.c_str());
 
 
-    WriteSqlLog(sqlStmt.c_str());
+    WriteSqlLog(sqlStmt);
 
 #ifdef DBDEBUG_CONSOLE
     cout << endl << sqlStmt.c_str() << endl;
 #endif
 
 
 #ifdef DBDEBUG_CONSOLE
     cout << endl << sqlStmt.c_str() << endl;
 #endif
 
-    if (SQLExecDirect(hstmt, (UCHAR FAR *) sqlStmt.c_str(), SQL_NTS) != SQL_SUCCESS)
+    if (SQLExecDirect(hstmt, (SQLTCHAR FAR *) sqlStmt.c_str(), SQL_NTS) != SQL_SUCCESS)
     {
         // Check for "Base table not found" error and ignore
         GetNextError(henv, hdbc, hstmt);
     {
         // Check for "Base table not found" error and ignore
         GetNextError(henv, hdbc, hstmt);
@@ -1644,7 +2134,7 @@ bool wxDb::DropView(const char *viewName)
     }
 
     // Commit the transaction
     }
 
     // Commit the transaction
-    if (! CommitTrans())
+    if (!CommitTrans())
         return(FALSE);
 
     return TRUE;
         return(FALSE);
 
     return TRUE;
@@ -1653,11 +2143,18 @@ bool wxDb::DropView(const char *viewName)
 
 
 /********** wxDb::ExecSql()  **********/
 
 
 /********** wxDb::ExecSql()  **********/
-bool wxDb::ExecSql(const char *pSqlStmt)
+bool wxDb::ExecSql(const wxString &pSqlStmt)
 {
 {
+    RETCODE retcode;
+
     SQLFreeStmt(hstmt, SQL_CLOSE);
     SQLFreeStmt(hstmt, SQL_CLOSE);
-    if (SQLExecDirect(hstmt, (UCHAR FAR *) pSqlStmt, SQL_NTS) == SQL_SUCCESS)
+
+    retcode = SQLExecDirect(hstmt, (SQLTCHAR FAR *) pSqlStmt.c_str(), SQL_NTS);
+    if (retcode == SQL_SUCCESS ||
+        (Dbms() == dbmsDB2 && (retcode == SQL_SUCCESS_WITH_INFO || retcode == SQL_NO_DATA_FOUND)))
+    {
         return(TRUE);
         return(TRUE);
+    }
     else
     {
         DispAllErrors(henv, hdbc, hstmt);
     else
     {
         DispAllErrors(henv, hdbc, hstmt);
@@ -1684,8 +2181,8 @@ bool wxDb::GetNext(void)
 /********** wxDb::GetData()  **********/
 bool wxDb::GetData(UWORD colNo, SWORD cType, PTR pData, SDWORD maxLen, SDWORD FAR *cbReturned)
 {
 /********** wxDb::GetData()  **********/
 bool wxDb::GetData(UWORD colNo, SWORD cType, PTR pData, SDWORD maxLen, SDWORD FAR *cbReturned)
 {
-    assert(pData);
-    assert(cbReturned);
+    wxASSERT(pData);
+    wxASSERT(cbReturned);
 
     if (SQLGetData(hstmt, colNo, cType, pData, maxLen, cbReturned) == SQL_SUCCESS)
         return(TRUE);
 
     if (SQLGetData(hstmt, colNo, cType, pData, maxLen, cbReturned) == SQL_SUCCESS)
         return(TRUE);
@@ -1699,38 +2196,38 @@ bool wxDb::GetData(UWORD colNo, SWORD cType, PTR pData, SDWORD maxLen, SDWORD FA
 
 
 /********** wxDb::GetKeyFields() **********/
 
 
 /********** wxDb::GetKeyFields() **********/
-int wxDb::GetKeyFields(char *tableName, wxDbColInf* colInf, int noCols)
+int wxDb::GetKeyFields(const wxString &tableName, wxDbColInf* colInf, UWORD noCols)
 {
 {
-    char         szPkTable[DB_MAX_TABLE_NAME_LEN+1];  /* Primary key table name */
-    char         szFkTable[DB_MAX_TABLE_NAME_LEN+1];  /* Foreign key table name */
+    wxChar       szPkTable[DB_MAX_TABLE_NAME_LEN+1];  /* Primary key table name */
+    wxChar       szFkTable[DB_MAX_TABLE_NAME_LEN+1];  /* Foreign key table name */
     short        iKeySeq;
 //    SQLSMALLINT  iKeySeq;
     short        iKeySeq;
 //    SQLSMALLINT  iKeySeq;
-    char         szPkCol[DB_MAX_COLUMN_NAME_LEN+1];   /* Primary key column     */
-    char         szFkCol[DB_MAX_COLUMN_NAME_LEN+1];   /* Foreign key column     */
+    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;
     SQLRETURN    retcode;
     SDWORD       cb;
-    int          i;
-    wxString     Temp0;
+    SWORD        i;
+    wxString     tempStr;
     /*
     /*
-     * ---------------------------------------------------------------------
-     * -- 19991224 : mj10777 : Create                         ------
-     * --          : Three things are done and stored here :          ------
-     * --          : 1) which Column(s) is/are Primary Key(s)         ------
-     * --          : 2) which tables use this Key as a Foreign Key    ------
-     * --          : 3) which columns are Foreign Key and the name    ------
-     * --          :     of the Table where the Key is the Primary Key -----
-     * --          : Called from GetColumns(char *tableName,          ------
-     * --                           int *numCols,const char *userID ) ------
-     * ---------------------------------------------------------------------
+     * -----------------------------------------------------------------------
+     * -- 19991224 : mj10777 : Create                                   ------
+     * --          : Three things are done and stored here :            ------
+     * --          : 1) which Column(s) is/are Primary Key(s)           ------
+     * --          : 2) which tables use this Key as a Foreign Key      ------
+     * --          : 3) which columns are Foreign Key and the name      ------
+     * --          :     of the Table where the Key is the Primary Key  -----
+     * --          : Called from GetColumns(const wxString &tableName,  ------
+     * --                           int *numCols,const wxChar *userID ) ------
+     * -----------------------------------------------------------------------
      */
 
     /*---------------------------------------------------------------------*/
     /* Get the names of the columns in the primary key.                    */
     /*---------------------------------------------------------------------*/
     retcode = SQLPrimaryKeys(hstmt,
      */
 
     /*---------------------------------------------------------------------*/
     /* Get the names of the columns in the primary key.                    */
     /*---------------------------------------------------------------------*/
     retcode = SQLPrimaryKeys(hstmt,
-                             NULL, 0,                       /* Catalog name  */
-                             NULL, 0,                       /* Schema name   */
-                             (UCHAR *) tableName, SQL_NTS); /* Table name    */
+                             NULL, 0,                               /* Catalog name  */
+                             NULL, 0,                               /* Schema name   */
+                             (SQLTCHAR FAR *) tableName.c_str(), 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        */
@@ -1755,18 +2252,18 @@ int wxDb::GetKeyFields(char *tableName, wxDbColInf* colInf, int noCols)
     /* Get all the foreign keys that refer to tableName primary key.       */
     /*---------------------------------------------------------------------*/
     retcode = SQLForeignKeys(hstmt,
     /* Get all the foreign keys that refer to tableName primary key.       */
     /*---------------------------------------------------------------------*/
     retcode = SQLForeignKeys(hstmt,
-                             NULL, 0,                       /* Primary catalog */
-                             NULL, 0,                       /* Primary schema  */
-                             (UCHAR *)tableName, SQL_NTS,   /* Primary table   */
-                             NULL, 0,                       /* Foreign catalog */
-                             NULL, 0,                       /* Foreign schema  */
-                             NULL, 0);                      /* Foreign table   */
+                             NULL, 0,                            /* Primary catalog */
+                             NULL, 0,                            /* Primary schema  */
+                             (SQLTCHAR FAR *)tableName.c_str(), SQL_NTS,/* Primary table   */
+                             NULL, 0,                            /* Foreign catalog */
+                             NULL, 0,                            /* Foreign schema  */
+                             NULL, 0);                           /* Foreign table   */
 
     /*---------------------------------------------------------------------*/
     /* Fetch and display the result set. This will be all of the foreign   */
     /* keys in other tables that refer to the tableName  primary key.      */
     /*---------------------------------------------------------------------*/
 
     /*---------------------------------------------------------------------*/
     /* Fetch and display the result set. This will be all of the foreign   */
     /* keys in other tables that refer to the tableName  primary key.      */
     /*---------------------------------------------------------------------*/
-    Temp0.Empty();
+    tempStr.Empty();
     szPkCol[0] = 0;
     while ((retcode == SQL_SUCCESS) || (retcode == SQL_SUCCESS_WITH_INFO))
     {
     szPkCol[0] = 0;
     while ((retcode == SQL_SUCCESS) || (retcode == SQL_SUCCESS_WITH_INFO))
     {
@@ -1778,37 +2275,38 @@ int wxDb::GetKeyFields(char *tableName, wxDbColInf* colInf, int noCols)
             GetData( 5, SQL_C_SSHORT, &iKeySeq,    0,                        &cb);
             GetData( 7, SQL_C_CHAR,   szFkTable,   DB_MAX_TABLE_NAME_LEN+1,  &cb);
             GetData( 8, SQL_C_CHAR,   szFkCol,     DB_MAX_COLUMN_NAME_LEN+1, &cb);
             GetData( 5, SQL_C_SSHORT, &iKeySeq,    0,                        &cb);
             GetData( 7, SQL_C_CHAR,   szFkTable,   DB_MAX_TABLE_NAME_LEN+1,  &cb);
             GetData( 8, SQL_C_CHAR,   szFkCol,     DB_MAX_COLUMN_NAME_LEN+1, &cb);
-            Temp0.Printf(wxT("%s[%s] "),Temp0.c_str(),szFkTable);  // [ ] in case there is a blank in the Table name
+            tempStr.Printf(wxT("%s[%s] "),tempStr.c_str(),szFkTable);  // [ ] in case there is a blank in the Table name
         }  // if
     }  // while
         }  // if
     }  // while
-    Temp0.Trim();     // Get rid of any unneeded blanks
-    if (Temp0 != wxT(""))
+
+    tempStr.Trim();     // Get rid of any unneeded blanks
+    if (!tempStr.IsEmpty())
     {
     {
-        for (i=0;i<noCols;i++)
+        for (i=0; i<noCols; i++)
         {   // Find the Column name
         {   // Find the Column name
-            if (!wxStrcmp(colInf[i].colName,szPkCol))           // We have found the Column, store the Information
-                wxStrcpy(colInf[i].PkTableName,Temp0.c_str());  // Name of the Tables where this Primary Key is used as a Foreign Key
+            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
         }
     }  // if
         }
     }  // if
+
     SQLFreeStmt(hstmt, SQL_CLOSE);  /* Close the cursor (the hstmt is still allocated). */
 
     /*---------------------------------------------------------------------*/
     /* Get all the foreign keys in the tablename table.                    */
     /*---------------------------------------------------------------------*/
     retcode = SQLForeignKeys(hstmt,
     SQLFreeStmt(hstmt, SQL_CLOSE);  /* Close the cursor (the hstmt is still allocated). */
 
     /*---------------------------------------------------------------------*/
     /* Get all the foreign keys in the tablename table.                    */
     /*---------------------------------------------------------------------*/
     retcode = SQLForeignKeys(hstmt,
-                             NULL, 0,                        /* Primary catalog   */
-                             NULL, 0,                        /* Primary schema    */
-                             NULL, 0,                        /* Primary table     */
-                             NULL, 0,                        /* Foreign catalog   */
-                             NULL, 0,                        /* Foreign schema    */
-                             (UCHAR *)tableName, SQL_NTS);   /* Foreign table     */
+                             NULL, 0,                             /* Primary catalog   */
+                             NULL, 0,                             /* Primary schema    */
+                             NULL, 0,                             /* Primary table     */
+                             NULL, 0,                             /* Foreign catalog   */
+                             NULL, 0,                             /* Foreign schema    */
+                             (SQLTCHAR *)tableName.c_str(), SQL_NTS);/* Foreign table     */
 
     /*---------------------------------------------------------------------*/
     /*  Fetch and display the result set. This will be all of the          */
     /*  primary keys in other tables that are referred to by foreign       */
     /*  keys in the tableName table.                                       */
     /*---------------------------------------------------------------------*/
 
     /*---------------------------------------------------------------------*/
     /*  Fetch and display the result set. This will be all of the          */
     /*  primary keys in other tables that are referred to by foreign       */
     /*  keys in the tableName table.                                       */
     /*---------------------------------------------------------------------*/
-    i = 0;
     while ((retcode == SQL_SUCCESS) || (retcode == SQL_SUCCESS_WITH_INFO))
     {
         retcode = SQLFetch(hstmt);
     while ((retcode == SQL_SUCCESS) || (retcode == SQL_SUCCESS_WITH_INFO))
     {
         retcode = SQLFetch(hstmt);
@@ -1818,7 +2316,7 @@ int wxDb::GetKeyFields(char *tableName, wxDbColInf* colInf, int noCols)
             GetData( 5, SQL_C_SSHORT, &iKeySeq,    0,                        &cb);
             GetData( 8, SQL_C_CHAR,   szFkCol,     DB_MAX_COLUMN_NAME_LEN+1, &cb);
             //-------
             GetData( 5, SQL_C_SSHORT, &iKeySeq,    0,                        &cb);
             GetData( 8, SQL_C_CHAR,   szFkCol,     DB_MAX_COLUMN_NAME_LEN+1, &cb);
             //-------
-            for (i=0;i<noCols;i++)                              // Find the Column name
+            for (i=0; i<noCols; i++)                            // Find the Column name
             {
                 if (!wxStrcmp(colInf[i].colName,szFkCol))       // We have found the (Foreign Key) Column
                 {
             {
                 if (!wxStrcmp(colInf[i].colName,szFkCol))       // We have found the (Foreign Key) Column
                 {
@@ -1837,7 +2335,7 @@ int wxDb::GetKeyFields(char *tableName, wxDbColInf* colInf, int noCols)
 
 #if OLD_GETCOLUMNS
 /********** wxDb::GetColumns() **********/
 
 #if OLD_GETCOLUMNS
 /********** wxDb::GetColumns() **********/
-wxDbColInf *wxDb::GetColumns(char *tableName[], const char *userID)
+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.
 /*
  *        1) The last array element of the tableName[] argument must be zero (null).
  *            This is how the end of the array is detected.
@@ -1865,34 +2363,17 @@ wxDbColInf *wxDb::GetColumns(char *tableName[], const char *userID)
  *       to avoid undesired unbinding of columns.
  */
 {
  *       to avoid undesired unbinding of columns.
  */
 {
-    int      noCols = 0;
-    int      colNo  = 0;
+    UWORD       noCols = 0;
+    UWORD       colNo  = 0;
     wxDbColInf *colInf = 0;
 
     RETCODE  retcode;
     SDWORD   cb;
 
     wxDbColInf *colInf = 0;
 
     RETCODE  retcode;
     SDWORD   cb;
 
-    wxString UserID;
     wxString TableName;
 
     wxString TableName;
 
-    if (userID)
-    {
-        if (!wxStrlen(userID))
-            UserID = uid;
-        else
-            UserID = userID;
-    }
-    else
-        UserID = "";
-
-    // dBase does not use user names, and some drivers fail if you try to pass one
-    if (Dbms() == dbmsDBASE)
-        UserID = "";
-
-    // Oracle and Interbase user names may only be in uppercase, so force
-    // the name to uppercase
-    if (Dbms() == dbmsORACLE)
-        UserID = UserID.Upper();
+    wxString UserID;
+    convertUserID(userID,UserID);
 
     // Pass 1 - Determine how many columns there are.
     // Pass 2 - Allocate the wxDbColInf array and fill in
 
     // Pass 1 - Determine how many columns there are.
     // Pass 2 - Allocate the wxDbColInf array and fill in
@@ -1909,8 +2390,8 @@ wxDbColInf *wxDb::GetColumns(char *tableName[], const char *userID)
             if (!colInf)
                 break;
             // Mark the end of the array
             if (!colInf)
                 break;
             // Mark the end of the array
-            wxStrcpy(colInf[noCols].tableName, wxT(""));
-            wxStrcpy(colInf[noCols].colName, wxT(""));
+            wxStrcpy(colInf[noCols].tableName,wxEmptyString);
+            wxStrcpy(colInf[noCols].colName,wxEmptyString);
             colInf[noCols].sqlDataType = 0;
         }
         // Loop through each table name
             colInf[noCols].sqlDataType = 0;
         }
         // Loop through each table name
@@ -1928,15 +2409,15 @@ wxDbColInf *wxDb::GetColumns(char *tableName[], const char *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 (wxStrcmp(UserID.c_str(),wxT("")) &&
-                 Dbms() != dbmsMY_SQL &&
-                 Dbms() != dbmsACCESS &&
-                 Dbms() != dbmsMS_SQL_SERVER)
+            if (!UserID.IsEmpty() &&
+                Dbms() != dbmsMY_SQL &&
+                Dbms() != dbmsACCESS &&
+                Dbms() != dbmsMS_SQL_SERVER)
             {
                 retcode = SQLColumns(hstmt,
                                      NULL, 0,                                // All qualifiers
             {
                 retcode = SQLColumns(hstmt,
                                      NULL, 0,                                // All qualifiers
-                                     (UCHAR *) UserID.c_str(), SQL_NTS,    // Owner
-                                     (UCHAR *) TableName.c_str(), SQL_NTS,
+                                     (SQLTCHAR *) UserID.c_str(), SQL_NTS,      // Owner
+                                     (SQLTCHAR *) TableName.c_str(), SQL_NTS,
                                      NULL, 0);                               // All columns
             }
             else
                                      NULL, 0);                               // All columns
             }
             else
@@ -1944,7 +2425,7 @@ wxDbColInf *wxDb::GetColumns(char *tableName[], const char *userID)
                 retcode = SQLColumns(hstmt,
                                      NULL, 0,                                // All qualifiers
                                      NULL, 0,                                // Owner
                 retcode = SQLColumns(hstmt,
                                      NULL, 0,                                // All qualifiers
                                      NULL, 0,                                // Owner
-                                     (UCHAR *) TableName.c_str(), SQL_NTS,
+                                     (SQLTCHAR *) TableName.c_str(), SQL_NTS,
                                      NULL, 0);                               // All columns
             }
             if (retcode != SQL_SUCCESS)
                                      NULL, 0);                               // All columns
             }
             if (retcode != SQL_SUCCESS)
@@ -1993,13 +2474,14 @@ wxDbColInf *wxDb::GetColumns(char *tableName[], const char *userID)
 #endif
                             colInf[colNo].dbDataType = DB_DATA_TYPE_VARCHAR;
                         }
 #endif
                             colInf[colNo].dbDataType = DB_DATA_TYPE_VARCHAR;
                         }
-                        else if (!wxStricmp(typeInfInteger.TypeName,colInf[colNo].typeName))
+                        else if (!wxStricmp(typeInfInteger.TypeName, colInf[colNo].typeName))
                             colInf[colNo].dbDataType = DB_DATA_TYPE_INTEGER;
                             colInf[colNo].dbDataType = DB_DATA_TYPE_INTEGER;
-                        else if (!wxStricmp(typeInfFloat.TypeName,colInf[colNo].typeName))
+                        else if (!wxStricmp(typeInfFloat.TypeName, colInf[colNo].typeName))
                             colInf[colNo].dbDataType = DB_DATA_TYPE_FLOAT;
                             colInf[colNo].dbDataType = DB_DATA_TYPE_FLOAT;
-                        else if (!wxStricmp(typeInfDate.TypeName,colInf[colNo].typeName))
+                        else if (!wxStricmp(typeInfDate.TypeName, colInf[colNo].typeName))
                             colInf[colNo].dbDataType = DB_DATA_TYPE_DATE;
                             colInf[colNo].dbDataType = DB_DATA_TYPE_DATE;
-
+                        else if (!wxStricmp(typeInfBlob.TypeName, colInf[colNo].typeName))
+                            colInf[colNo].dbDataType = DB_DATA_TYPE_BLOB;
                         colNo++;
                     }
                 }
                         colNo++;
                     }
                 }
@@ -2023,7 +2505,7 @@ wxDbColInf *wxDb::GetColumns(char *tableName[], const char *userID)
 
 /********** wxDb::GetColumns() **********/
 
 
 /********** wxDb::GetColumns() **********/
 
-wxDbColInf *wxDb::GetColumns(char *tableName, int *numCols, const char *userID)
+wxDbColInf *wxDb::GetColumns(const wxString &tableName, UWORD *numCols, const wxChar *userID)
 //
 // Same as the above GetColumns() function except this one gets columns
 // only for a single table, and if 'numCols' is not NULL, the number of
 //
 // Same as the above GetColumns() function except this one gets columns
 // only for a single table, and if 'numCols' is not NULL, the number of
@@ -2039,34 +2521,17 @@ wxDbColInf *wxDb::GetColumns(char *tableName, int *numCols, const char *userID)
 //       to avoid undesired unbinding of columns.
 
 {
 //       to avoid undesired unbinding of columns.
 
 {
-    int       noCols = 0;
-    int       colNo  = 0;
+    UWORD       noCols = 0;
+    UWORD       colNo  = 0;
     wxDbColInf *colInf = 0;
 
     RETCODE  retcode;
     SDWORD   cb;
 
     wxDbColInf *colInf = 0;
 
     RETCODE  retcode;
     SDWORD   cb;
 
-    wxString UserID;
     wxString TableName;
 
     wxString TableName;
 
-    if (userID)
-    {
-        if (!wxStrlen(userID))
-            UserID = uid;
-        else
-            UserID = userID;
-    }
-    else
-        UserID = "";
-
-    // dBase does not use user names, and some drivers fail if you try to pass one
-    if (Dbms() == dbmsDBASE)
-        UserID = "";
-
-    // Oracle user names may only be in uppercase, so force
-    // the name to uppercase
-    if (Dbms() == dbmsORACLE)
-        UserID = UserID.Upper();
+    wxString UserID;
+    convertUserID(userID,UserID);
 
     // Pass 1 - Determine how many columns there are.
     // Pass 2 - Allocate the wxDbColInf array and fill in
 
     // Pass 1 - Determine how many columns there are.
     // Pass 2 - Allocate the wxDbColInf array and fill in
@@ -2083,9 +2548,9 @@ wxDbColInf *wxDb::GetColumns(char *tableName, int *numCols, const char *userID)
             if (!colInf)
                 break;
             // Mark the end of the array
             if (!colInf)
                 break;
             // Mark the end of the array
-            wxStrcpy(colInf[noCols].tableName, wxT(""));
-            wxStrcpy(colInf[noCols].colName, wxT(""));
-            colInf[noCols].sqlDataType = 0;
+            wxStrcpy(colInf[noCols].tableName, wxEmptyString);
+            wxStrcpy(colInf[noCols].colName, wxEmptyString);
+            colInf[noCols].sqlDataType  = 0;
         }
 
         TableName = tableName;
         }
 
         TableName = tableName;
@@ -2099,15 +2564,15 @@ wxDbColInf *wxDb::GetColumns(char *tableName, int *numCols, const char *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 (wxStrcmp(UserID.c_str(),wxT("")) &&
-             Dbms() != dbmsMY_SQL &&
-             Dbms() != dbmsACCESS &&
-             Dbms() != dbmsMS_SQL_SERVER)
+        if (!UserID.IsEmpty() &&
+            Dbms() != dbmsMY_SQL &&
+            Dbms() != dbmsACCESS &&
+            Dbms() != dbmsMS_SQL_SERVER)
         {
             retcode = SQLColumns(hstmt,
                                  NULL, 0,                                // All qualifiers
         {
             retcode = SQLColumns(hstmt,
                                  NULL, 0,                                // All qualifiers
-                                 (UCHAR *) UserID.c_str(), SQL_NTS,    // Owner
-                                 (UCHAR *) TableName.c_str(), SQL_NTS,
+                                 (SQLTCHAR *) UserID.c_str(), SQL_NTS,    // Owner
+                                 (SQLTCHAR *) TableName.c_str(), SQL_NTS,
                                  NULL, 0);                               // All columns
         }
         else
                                  NULL, 0);                               // All columns
         }
         else
@@ -2115,7 +2580,7 @@ wxDbColInf *wxDb::GetColumns(char *tableName, int *numCols, const char *userID)
             retcode = SQLColumns(hstmt,
                                  NULL, 0,                                 // All qualifiers
                                  NULL, 0,                                 // Owner
             retcode = SQLColumns(hstmt,
                                  NULL, 0,                                 // All qualifiers
                                  NULL, 0,                                 // Owner
-                                 (UCHAR *) TableName.c_str(), SQL_NTS,
+                                 (SQLTCHAR *) TableName.c_str(), SQL_NTS,
                                  NULL, 0);                                // All columns
         }
         if (retcode != SQL_SUCCESS)
                                  NULL, 0);                                // All columns
         }
         if (retcode != SQL_SUCCESS)
@@ -2160,14 +2625,14 @@ wxDbColInf *wxDb::GetColumns(char *tableName, int *numCols, const char *userID)
                     // BJO 20000428 : Virtuoso returns type names with upper cases!
                     if (Dbms() == dbmsVIRTUOSO)
                     {
                     // BJO 20000428 : Virtuoso returns type names with upper cases!
                     if (Dbms() == dbmsVIRTUOSO)
                     {
-                        wxString s =  colInf[colNo].typeName;
+                        wxString s = colInf[colNo].typeName;
                         s = s.MakeLower();
                         wxStrcmp(colInf[colNo].typeName, s.c_str());
                     }
 
                     // Determine the wxDb data type that is used to represent the native data type of this data source
                     colInf[colNo].dbDataType = 0;
                         s = s.MakeLower();
                         wxStrcmp(colInf[colNo].typeName, s.c_str());
                     }
 
                     // Determine the wxDb data type that is used to represent the native data type of this data source
                     colInf[colNo].dbDataType = 0;
-                    if (!wxStricmp(typeInfVarchar.TypeName,colInf[colNo].typeName))
+                    if (!wxStricmp(typeInfVarchar.TypeName, colInf[colNo].typeName))
                     {
 #ifdef _IODBC_
                         // IODBC does not return a correct columnSize, so we set
                     {
 #ifdef _IODBC_
                         // IODBC does not return a correct columnSize, so we set
@@ -2181,12 +2646,14 @@ wxDbColInf *wxDb::GetColumns(char *tableName, int *numCols, const char *userID)
 
                         colInf[colNo].dbDataType = DB_DATA_TYPE_VARCHAR;
                     }
 
                         colInf[colNo].dbDataType = DB_DATA_TYPE_VARCHAR;
                     }
-                    else if (!wxStricmp(typeInfInteger.TypeName,colInf[colNo].typeName))
+                    else if (!wxStricmp(typeInfInteger.TypeName, colInf[colNo].typeName))
                         colInf[colNo].dbDataType = DB_DATA_TYPE_INTEGER;
                         colInf[colNo].dbDataType = DB_DATA_TYPE_INTEGER;
-                    else if (!wxStricmp(typeInfFloat.TypeName,colInf[colNo].typeName))
+                    else if (!wxStricmp(typeInfFloat.TypeName, colInf[colNo].typeName))
                         colInf[colNo].dbDataType = DB_DATA_TYPE_FLOAT;
                         colInf[colNo].dbDataType = DB_DATA_TYPE_FLOAT;
-                    else if (!wxStricmp(typeInfDate.TypeName,colInf[colNo].typeName))
+                    else if (!wxStricmp(typeInfDate.TypeName, colInf[colNo].typeName))
                         colInf[colNo].dbDataType = DB_DATA_TYPE_DATE;
                         colInf[colNo].dbDataType = DB_DATA_TYPE_DATE;
+                    else if (!wxStricmp(typeInfBlob.TypeName, colInf[colNo].typeName))
+                        colInf[colNo].dbDataType = DB_DATA_TYPE_BLOB;
 
                     colNo++;
                 }
 
                     colNo++;
                 }
@@ -2225,12 +2692,12 @@ wxDbColInf *wxDb::GetColumns(char *tableName, int *numCols, const char *userID)
     independant and which always returns the columns in the order they were
     created.
 
     independant and which always returns the columns in the order they were
     created.
 
-    - The first one (wxDbColInf *wxDb::GetColumns(char *tableName[], const
-      char* userID)) calls the second implementation for each separate table
+    - The first one (wxDbColInf *wxDb::GetColumns(wxChar *tableName[], const
+      wxChar* userID)) calls the second implementation for each separate table
       before merging the results. This makes the code easier to maintain as
       only one member (the second) makes the real work
       before merging the results. This makes the code easier to maintain as
       only one member (the second) makes the real work
-    - wxDbColInf *wxDb::GetColumns(char *tableName, int *numCols, const
-      char *userID) is a little bit improved
+    - wxDbColInf *wxDb::GetColumns(const wxString &tableName, int *numCols, const
+      wxChar *userID) is a little bit improved
     - It doesn't anymore rely on the type-name to find out which database-type
       each column has
     - It ends by sorting the columns, so that they are returned in the same
     - It doesn't anymore rely on the type-name to find out which database-type
       each column has
     - It ends by sorting the columns, so that they are returned in the same
@@ -2239,18 +2706,18 @@ wxDbColInf *wxDb::GetColumns(char *tableName, int *numCols, const char *userID)
 
 typedef struct
 {
 
 typedef struct
 {
-    int noCols;
+    UWORD noCols;
     wxDbColInf *colInf;
 } _TableColumns;
 
 
     wxDbColInf *colInf;
 } _TableColumns;
 
 
-wxDbColInf *wxDb::GetColumns(char *tableName[], const char* userID)
+wxDbColInf *wxDb::GetColumns(wxChar *tableName[], const wxChar *userID)
 {
     int i, j;
     // The last array element of the tableName[] argument must be zero (null).
     // This is how the end of the array is detected.
 
 {
     int i, j;
     // The last array element of the tableName[] argument must be zero (null).
     // This is how the end of the array is detected.
 
-    int noCols = 0;
+    UWORD noCols = 0;
 
     // How many tables ?
     int tbl;
 
     // How many tables ?
     int tbl;
@@ -2273,9 +2740,9 @@ wxDbColInf *wxDb::GetColumns(char *tableName[], const char* userID)
     wxDbColInf *colInf = new wxDbColInf[noCols+1];
 
     // Mark the end of the array
     wxDbColInf *colInf = new wxDbColInf[noCols+1];
 
     // Mark the end of the array
-    wxStrcpy(colInf[noCols].tableName, wxT(""));
-    wxStrcpy(colInf[noCols].colName, wxT(""));
-    colInf[noCols].sqlDataType = 0;
+    wxStrcpy(colInf[noCols].tableName, wxEmptyString);
+    wxStrcpy(colInf[noCols].colName, wxEmptyString);
+    colInf[noCols].sqlDataType  = 0;
 
     // Merge ...
     int offset = 0;
 
     // Merge ...
     int offset = 0;
@@ -2294,7 +2761,7 @@ wxDbColInf *wxDb::GetColumns(char *tableName[], const char* userID)
 }  // wxDb::GetColumns()  -- NEW
 
 
 }  // wxDb::GetColumns()  -- NEW
 
 
-wxDbColInf *wxDb::GetColumns(char *tableName, int *numCols, const char *userID)
+wxDbColInf *wxDb::GetColumns(const wxString &tableName, int *numCols, const wxChar *userID)
 //
 // Same as the above GetColumns() function except this one gets columns
 // only for a single table, and if 'numCols' is not NULL, the number of
 //
 // Same as the above GetColumns() function except this one gets columns
 // only for a single table, and if 'numCols' is not NULL, the number of
@@ -2309,34 +2776,17 @@ wxDbColInf *wxDb::GetColumns(char *tableName, int *numCols, const char *userID)
 //       by this function.  This function should use its own wxDb instance
 //       to avoid undesired unbinding of columns.
 {
 //       by this function.  This function should use its own wxDb instance
 //       to avoid undesired unbinding of columns.
 {
-    SWORD       noCols = 0;
-    int         colNo  = 0;
+    UWORD       noCols = 0;
+    UWORD       colNo  = 0;
     wxDbColInf *colInf = 0;
 
     RETCODE  retcode;
     SDWORD   cb;
 
     wxDbColInf *colInf = 0;
 
     RETCODE  retcode;
     SDWORD   cb;
 
-    wxString UserID;
     wxString TableName;
 
     wxString TableName;
 
-    if (userID)
-    {
-        if (!wxStrlen(userID))
-            UserID = uid;
-        else
-            UserID = userID;
-    }
-    else
-        UserID = "";
-
-    // dBase does not use user names, and some drivers fail if you try to pass one
-    if (Dbms() == dbmsDBASE)
-        UserID = "";
-
-    // Oracle user names may only be in uppercase, so force
-    // the name to uppercase
-    if (Dbms() == dbmsORACLE)
-        UserID = UserID.Upper();
+    wxString UserID;
+    convertUserID(userID,UserID);
 
     // Pass 1 - Determine how many columns there are.
     // Pass 2 - Allocate the wxDbColInf array and fill in
 
     // Pass 1 - Determine how many columns there are.
     // Pass 2 - Allocate the wxDbColInf array and fill in
@@ -2353,8 +2803,8 @@ wxDbColInf *wxDb::GetColumns(char *tableName, int *numCols, const char *userID)
             if (!colInf)
                 break;
             // Mark the end of the array
             if (!colInf)
                 break;
             // Mark the end of the array
-            wxStrcpy(colInf[noCols].tableName, wxT(""));
-            wxStrcpy(colInf[noCols].colName, wxT(""));
+            wxStrcpy(colInf[noCols].tableName, wxEmptyString);
+            wxStrcpy(colInf[noCols].colName, wxEmptyString);
             colInf[noCols].sqlDataType = 0;
         }
 
             colInf[noCols].sqlDataType = 0;
         }
 
@@ -2369,7 +2819,7 @@ wxDbColInf *wxDb::GetColumns(char *tableName, int *numCols, const char *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 (wxStrcmp(UserID.c_str(),wxT("")) &&
+        if (!UserID.IsEmpty() &&
             Dbms() != dbmsMY_SQL &&
             Dbms() != dbmsACCESS &&
             Dbms() != dbmsMS_SQL_SERVER)
             Dbms() != dbmsMY_SQL &&
             Dbms() != dbmsACCESS &&
             Dbms() != dbmsMS_SQL_SERVER)
@@ -2461,10 +2911,13 @@ wxDbColInf *wxDb::GetColumns(char *tableName, int *numCols, const char *userID)
                         case SQL_DATE:
                             colInf[colNo].dbDataType = DB_DATA_TYPE_DATE;
                             break;
                         case SQL_DATE:
                             colInf[colNo].dbDataType = DB_DATA_TYPE_DATE;
                             break;
+                        case SQL_BINARY:
+                            colInf[colNo].dbDataType = DB_DATA_TYPE_BLOB;
+                            break;
 #ifdef __WXDEBUG__
                         default:
                             wxString errMsg;
 #ifdef __WXDEBUG__
                         default:
                             wxString errMsg;
-                            errMsg.sprintf("SQL Data type %d currently not supported by wxWindows", colInf[colNo].sqlDataType);
+                            errMsg.Printf(wxT("SQL Data type %d currently not supported by wxWidgets"), colInf[colNo].sqlDataType);
                             wxLogDebug(errMsg,wxT("ODBC DEBUG MESSAGE"));
 #endif
                     }
                             wxLogDebug(errMsg,wxT("ODBC DEBUG MESSAGE"));
 #endif
                     }
@@ -2496,7 +2949,7 @@ wxDbColInf *wxDb::GetColumns(char *tableName, int *numCols, const char *userID)
     // Build a generic SELECT statement which returns 0 rows
     wxString Stmt;
 
     // Build a generic SELECT statement which returns 0 rows
     wxString Stmt;
 
-    Stmt.sprintf("select * from %s where 0=1", tableName);
+    Stmt.Printf(wxT("select * from \"%s\" where 0=1"), tableName);
 
     // Execute query
     if (SQLExecDirect(hstmt, (UCHAR FAR *) Stmt.c_str(), SQL_NTS) != SQL_SUCCESS)
 
     // Execute query
     if (SQLExecDirect(hstmt, (UCHAR FAR *) Stmt.c_str(), SQL_NTS) != SQL_SUCCESS)
@@ -2568,7 +3021,7 @@ wxDbColInf *wxDb::GetColumns(char *tableName, int *numCols, const char *userID)
 
 
 /********** wxDb::GetColumnCount() **********/
 
 
 /********** wxDb::GetColumnCount() **********/
-int wxDb::GetColumnCount(char *tableName, const char *userID)
+int wxDb::GetColumnCount(const wxString &tableName, const wxChar *userID)
 /*
  * Returns a count of how many columns are in a table.
  * If an error occurs in computing the number of columns
 /*
  * Returns a count of how many columns are in a table.
  * If an error occurs in computing the number of columns
@@ -2584,83 +3037,61 @@ int wxDb::GetColumnCount(char *tableName, const char *userID)
  *       to avoid undesired unbinding of columns.
  */
 {
  *       to avoid undesired unbinding of columns.
  */
 {
-    int      noCols = 0;
+    UWORD    noCols = 0;
 
     RETCODE  retcode;
 
 
     RETCODE  retcode;
 
-    wxString UserID;
     wxString TableName;
 
     wxString TableName;
 
-    if (userID)
+    wxString UserID;
+    convertUserID(userID,UserID);
+
+    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() == dbmsINTERBASE))
+        TableName = TableName.Upper();
+
+    SQLFreeStmt(hstmt, SQL_CLOSE);
+
+    // 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() &&
+        Dbms() != dbmsMY_SQL &&
+        Dbms() != dbmsACCESS &&
+        Dbms() != dbmsMS_SQL_SERVER)
     {
     {
-        if (!wxStrlen(userID))
-            UserID = uid;
-        else
-            UserID = userID;
+        retcode = SQLColumns(hstmt,
+                             NULL, 0,                                // All qualifiers
+                             (SQLTCHAR *) UserID.c_str(), SQL_NTS,      // Owner
+                             (SQLTCHAR *) TableName.c_str(), SQL_NTS,
+                             NULL, 0);                               // All columns
     }
     else
     }
     else
-        UserID = wxT("");
-
-    // dBase does not use user names, and some drivers fail if you try to pass one
-    if (Dbms() == dbmsDBASE)
-        UserID = wxT("");
-
-    // Oracle user names may only be in uppercase, so force
-    // the name to uppercase
-    if (Dbms() == dbmsORACLE)
-        UserID = UserID.Upper();
-
     {
     {
-        // Loop through each table name
-        {
-            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() == dbmsINTERBASE))
-                TableName = TableName.Upper();
-
-            SQLFreeStmt(hstmt, SQL_CLOSE);
-
-            // 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 (wxStrcmp(UserID.c_str(),wxT("")) &&
-                 Dbms() != dbmsMY_SQL &&
-                 Dbms() != dbmsACCESS &&
-                 Dbms() != dbmsMS_SQL_SERVER)
-            {
-                retcode = SQLColumns(hstmt,
-                                     NULL, 0,                                // All qualifiers
-                                     (UCHAR *) UserID.c_str(), SQL_NTS,      // Owner
-                                     (UCHAR *) TableName.c_str(), SQL_NTS,
-                                     NULL, 0);                               // All columns
-            }
-            else
-            {
-                retcode = SQLColumns(hstmt,
-                                     NULL, 0,                                // All qualifiers
-                                     NULL, 0,                                // Owner
-                                     (UCHAR *) TableName.c_str(), SQL_NTS,
-                                     NULL, 0);                               // All columns
-            }
-            if (retcode != SQL_SUCCESS)
-            {  // Error occured, abort
-                DispAllErrors(henv, hdbc, hstmt);
-                SQLFreeStmt(hstmt, SQL_CLOSE);
-                return(-1);
-            }
+        retcode = SQLColumns(hstmt,
+                             NULL, 0,                                // All qualifiers
+                             NULL, 0,                                // Owner
+                             (SQLTCHAR *) TableName.c_str(), SQL_NTS,
+                             NULL, 0);                               // All columns
+    }
+    if (retcode != SQL_SUCCESS)
+    {  // Error occured, abort
+        DispAllErrors(henv, hdbc, hstmt);
+        SQLFreeStmt(hstmt, SQL_CLOSE);
+        return(-1);
+    }
 
 
-            // Count the columns
-            while ((retcode = SQLFetch(hstmt)) == SQL_SUCCESS)
-                noCols++;
+    // Count the columns
+    while ((retcode = SQLFetch(hstmt)) == SQL_SUCCESS)
+        noCols++;
 
 
-            if (retcode != SQL_NO_DATA_FOUND)
-            {  // Error occured, abort
-                DispAllErrors(henv, hdbc, hstmt);
-                SQLFreeStmt(hstmt, SQL_CLOSE);
-                return(-1);
-            }
-        }
+    if (retcode != SQL_NO_DATA_FOUND)
+    {  // Error occured, abort
+        DispAllErrors(henv, hdbc, hstmt);
+        SQLFreeStmt(hstmt, SQL_CLOSE);
+        return(-1);
     }
 
     SQLFreeStmt(hstmt, SQL_CLOSE);
     }
 
     SQLFreeStmt(hstmt, SQL_CLOSE);
@@ -2670,7 +3101,7 @@ int wxDb::GetColumnCount(char *tableName, const char *userID)
 
 
 /********** wxDb::GetCatalog() *******/
 
 
 /********** wxDb::GetCatalog() *******/
-wxDbInf *wxDb::GetCatalog(char *userID)
+wxDbInf *wxDb::GetCatalog(const wxChar *userID)
 /*
  * ---------------------------------------------------------------------
  * -- 19991203 : mj10777 : Create                                 ------
 /*
  * ---------------------------------------------------------------------
  * -- 19991203 : mj10777 : Create                                 ------
@@ -2693,7 +3124,6 @@ wxDbInf *wxDb::GetCatalog(char *userID)
  *       to avoid undesired unbinding of columns.
  */
 {
  *       to avoid undesired unbinding of columns.
  */
 {
-    wxDbInf *pDbInf = NULL; // Array of catalog entries
     int      noTab = 0;     // Counter while filling table entries
     int      pass;
     RETCODE  retcode;
     int      noTab = 0;     // Counter while filling table entries
     int      pass;
     RETCODE  retcode;
@@ -2701,28 +3131,13 @@ wxDbInf *wxDb::GetCatalog(char *userID)
     wxString tblNameSave;
 
     wxString UserID;
     wxString tblNameSave;
 
     wxString UserID;
+    convertUserID(userID,UserID);
 
 
-    if (userID)
-    {
-        if (!wxStrlen(userID))
-            UserID = uid;
-        else
-            UserID = userID;
-    }
-    else
-        UserID = wxT("");
-
-    // dBase does not use user names, and some drivers fail if you try to pass one
-    if (Dbms() == dbmsDBASE)
-        UserID = wxT("");
+    //-------------------------------------------------------------
+    // Create the Database Array of catalog entries
 
 
-    // Oracle user names may only be in uppercase, so force
-    // the name to uppercase
-    if (Dbms() == dbmsORACLE)
-        UserID = UserID.Upper();
+    wxDbInf *pDbInf = new wxDbInf;
 
 
-    //-------------------------------------------------------------
-    pDbInf = new wxDbInf;          // Create the Database Arrray
     //-------------------------------------------------------------
     // Table Information
     // Pass 1 - Determine how many Tables there are.
     //-------------------------------------------------------------
     // Table Information
     // Pass 1 - Determine how many Tables there are.
@@ -2733,15 +3148,16 @@ wxDbInf *wxDb::GetCatalog(char *userID)
     for (pass = 1; pass <= 2; pass++)
     {
         SQLFreeStmt(hstmt, SQL_CLOSE);   // Close if Open
     for (pass = 1; pass <= 2; pass++)
     {
         SQLFreeStmt(hstmt, SQL_CLOSE);   // Close if Open
-        tblNameSave = wxT("");
+        tblNameSave.Empty();
 
 
-        if (wxStrcmp(UserID.c_str(),wxT("")) &&
+        if (!UserID.IsEmpty() &&
             Dbms() != dbmsMY_SQL &&
             Dbms() != dbmsMY_SQL &&
-            Dbms() != dbmsACCESS)
+            Dbms() != dbmsACCESS &&
+            Dbms() != dbmsMS_SQL_SERVER)
         {
             retcode = SQLTables(hstmt,
                                 NULL, 0,                             // All qualifiers
         {
             retcode = SQLTables(hstmt,
                                 NULL, 0,                             // All qualifiers
-                                (UCHAR *) UserID.c_str(), SQL_NTS,   // User specified
+                                (SQLTCHAR *) UserID.c_str(), SQL_NTS,   // User specified
                                 NULL, 0,                             // All tables
                                 NULL, 0);                            // All columns
         }
                                 NULL, 0,                             // All tables
                                 NULL, 0);                            // All columns
         }
@@ -2803,7 +3219,7 @@ wxDbInf *wxDb::GetCatalog(char *userID)
 
 
 /********** wxDb::Catalog() **********/
 
 
 /********** wxDb::Catalog() **********/
-bool wxDb::Catalog(const char *userID, const char *fileName)
+bool wxDb::Catalog(const wxChar *userID, const wxString &fileName)
 /*
  * Creates the text file specified in 'filename' which will contain
  * a minimal data dictionary of all tables accessible by the user specified
 /*
  * Creates the text file specified in 'filename' which will contain
  * a minimal data dictionary of all tables accessible by the user specified
@@ -2819,51 +3235,35 @@ bool wxDb::Catalog(const char *userID, const char *fileName)
  *       to avoid undesired unbinding of columns.
  */
 {
  *       to avoid undesired unbinding of columns.
  */
 {
-    assert(fileName && wxStrlen(fileName));
+    wxASSERT(fileName.Length());
 
     RETCODE   retcode;
     SDWORD    cb;
 
     RETCODE   retcode;
     SDWORD    cb;
-    char      tblName[DB_MAX_TABLE_NAME_LEN+1];
+    wxChar    tblName[DB_MAX_TABLE_NAME_LEN+1];
     wxString  tblNameSave;
     wxString  tblNameSave;
-    char      colName[DB_MAX_COLUMN_NAME_LEN+1];
+    wxChar    colName[DB_MAX_COLUMN_NAME_LEN+1];
     SWORD     sqlDataType;
     SWORD     sqlDataType;
-    char      typeName[30+1];
-    SWORD     precision, length;
-
-    wxString UserID;
+    wxChar    typeName[30+1];
+    SDWORD    precision, length;
 
 
-    FILE *fp = fopen(fileName,"wt");
+    FILE *fp = wxFopen(fileName.c_str(),wxT("wt"));
     if (fp == NULL)
         return(FALSE);
 
     SQLFreeStmt(hstmt, SQL_CLOSE);
 
     if (fp == NULL)
         return(FALSE);
 
     SQLFreeStmt(hstmt, SQL_CLOSE);
 
-    if (userID)
-    {
-        if (!wxStrlen(userID))
-            UserID = uid;
-        else
-            UserID = userID;
-    }
-    else
-        UserID = wxT("");
-
-    // dBase does not use user names, and some drivers fail if you try to pass one
-    if (Dbms() == dbmsDBASE)
-        UserID = wxT("");
-
-    // Oracle user names may only be in uppercase, so force
-    // the name to uppercase
-    if (Dbms() == dbmsORACLE)
-        UserID = UserID.Upper();
+    wxString UserID;
+    convertUserID(userID,UserID);
 
 
-    if (wxStrcmp(UserID.c_str(),wxT("")) &&
-         Dbms() != dbmsMY_SQL &&
-         Dbms() != dbmsACCESS)
+    if (!UserID.IsEmpty() &&
+        Dbms() != dbmsMY_SQL &&
+        Dbms() != dbmsACCESS &&
+        Dbms() != dbmsINTERBASE &&
+        Dbms() != dbmsMS_SQL_SERVER)
     {
         retcode = SQLColumns(hstmt,
                              NULL, 0,                                // All qualifiers
     {
         retcode = SQLColumns(hstmt,
                              NULL, 0,                                // All qualifiers
-                             (UCHAR *) UserID.c_str(), SQL_NTS,      // User specified
+                             (SQLTCHAR *) UserID.c_str(), SQL_NTS,      // User specified
                              NULL, 0,                                // All tables
                              NULL, 0);                               // All columns
     }
                              NULL, 0,                                // All tables
                              NULL, 0);                               // All columns
     }
@@ -2883,41 +3283,45 @@ bool wxDb::Catalog(const char *userID, const char *fileName)
     }
 
     wxString outStr;
     }
 
     wxString outStr;
-    tblNameSave = wxT("");
+    tblNameSave.Empty();
     int cnt = 0;
 
     int cnt = 0;
 
-    while ((retcode = SQLFetch(hstmt)) == SQL_SUCCESS)
+    while (TRUE)
     {
     {
-        if (wxStrcmp(tblName,tblNameSave.c_str()))
+        retcode = SQLFetch(hstmt);
+        if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
+            break;
+
+        GetData(3,SQL_C_CHAR,  (UCHAR *) tblName,     DB_MAX_TABLE_NAME_LEN+1, &cb);
+        GetData(4,SQL_C_CHAR,  (UCHAR *) colName,     DB_MAX_COLUMN_NAME_LEN+1,&cb);
+        GetData(5,SQL_C_SSHORT,(UCHAR *)&sqlDataType, 0,                       &cb);
+        GetData(6,SQL_C_CHAR,  (UCHAR *) typeName,    sizeof(typeName),        &cb);
+        GetData(7,SQL_C_SLONG, (UCHAR *)&precision,   0,                       &cb);
+        GetData(8,SQL_C_SLONG, (UCHAR *)&length,      0,                       &cb);
+
+        if (wxStrcmp(tblName, tblNameSave.c_str()))
         {
             if (cnt)
         {
             if (cnt)
-                fputs("\n", fp);
-            fputs("================================ ", fp);
-            fputs("================================ ", fp);
-            fputs("===================== ", fp);
-            fputs("========= ", fp);
-            fputs("=========\n", fp);
-            outStr.sprintf(wxT("%-32s %-32s %-21s %9s %9s\n"),
+                wxFputs(wxT("\n"), fp);
+            wxFputs(wxT("================================ "), fp);
+            wxFputs(wxT("================================ "), fp);
+            wxFputs(wxT("===================== "), fp);
+            wxFputs(wxT("========= "), fp);
+            wxFputs(wxT("=========\n"), fp);
+            outStr.Printf(wxT("%-32s %-32s %-21s %9s %9s\n"),
                 wxT("TABLE NAME"), wxT("COLUMN NAME"), wxT("DATA TYPE"), wxT("PRECISION"), wxT("LENGTH"));
                 wxT("TABLE NAME"), wxT("COLUMN NAME"), wxT("DATA TYPE"), wxT("PRECISION"), wxT("LENGTH"));
-            fputs(outStr.c_str(), fp);
-            fputs("================================ ", fp);
-            fputs("================================ ", fp);
-            fputs("===================== ", fp);
-            fputs("========= ", fp);
-            fputs("=========\n", fp);
+            wxFputs(outStr.c_str(), fp);
+            wxFputs(wxT("================================ "), fp);
+            wxFputs(wxT("================================ "), fp);
+            wxFputs(wxT("===================== "), fp);
+            wxFputs(wxT("========= "), fp);
+            wxFputs(wxT("=========\n"), fp);
             tblNameSave = tblName;
         }
 
             tblNameSave = tblName;
         }
 
-      GetData(3,SQL_C_CHAR,  (UCHAR *)tblName,     DB_MAX_TABLE_NAME_LEN+1, &cb);
-      GetData(4,SQL_C_CHAR,  (UCHAR *)colName,     DB_MAX_COLUMN_NAME_LEN+1,&cb);
-      GetData(5,SQL_C_SSHORT,(UCHAR *)&sqlDataType,0,                       &cb);
-      GetData(6,SQL_C_CHAR,  (UCHAR *)typeName,    sizeof(typeName),        &cb);
-      GetData(7,SQL_C_SSHORT,(UCHAR *)&precision,  0,                       &cb);
-      GetData(8,SQL_C_SSHORT,(UCHAR *)&length,     0,                       &cb);
-
-        outStr.sprintf("%-32s %-32s (%04d)%-15s %9d %9d\n",
+        outStr.Printf(wxT("%-32s %-32s (%04d)%-15s %9ld %9ld\n"),
             tblName, colName, sqlDataType, typeName, precision, length);
             tblName, colName, sqlDataType, typeName, precision, length);
-        if (fputs(outStr.c_str(), fp) == EOF)
+        if (wxFputs(outStr.c_str(), fp) == EOF)
         {
             SQLFreeStmt(hstmt, SQL_CLOSE);
             fclose(fp);
         {
             SQLFreeStmt(hstmt, SQL_CLOSE);
             fclose(fp);
@@ -2937,9 +3341,9 @@ bool wxDb::Catalog(const char *userID, const char *fileName)
 }  // wxDb::Catalog()
 
 
 }  // wxDb::Catalog()
 
 
-bool wxDb::TableExists(const char *tableName, const char *userID, const char *tablePath)
+bool wxDb::TableExists(const wxString &tableName, const wxChar *userID, const wxString &tablePath)
 /*
 /*
- * Table name can refer to a table, view, alias or synonym.  Returns true
+ * Table name can refer to a table, view, alias or synonym.  Returns TRUE
  * if the object exists in the database.  This function does not indicate
  * whether or not the user has privleges to query or perform other functions
  * on the table.
  * if the object exists in the database.  This function does not indicate
  * whether or not the user has privleges to query or perform other functions
  * on the table.
@@ -2950,38 +3354,25 @@ bool wxDb::TableExists(const char *tableName, const char *userID, const char *ta
  *        userID != ""    ... UserID set equal to 'userID'
  */
 {
  *        userID != ""    ... UserID set equal to 'userID'
  */
 {
-    wxString UserID;
-    wxString TableName;
+    wxASSERT(tableName.Length());
 
 
-    assert(tableName && wxStrlen(tableName));
+    wxString TableName;
 
     if (Dbms() == dbmsDBASE)
     {
         wxString dbName;
 
     if (Dbms() == dbmsDBASE)
     {
         wxString dbName;
-        if (tablePath && wxStrlen(tablePath))
-            dbName.sprintf("%s\\%s.dbf",tablePath,tableName);
+        if (tablePath.Length())
+            dbName.Printf(wxT("%s/%s.dbf"), tablePath.c_str(), tableName.c_str());
         else
         else
-            dbName.sprintf("%s.dbf",tableName);
+            dbName.Printf(wxT("%s.dbf"), tableName.c_str());
 
         bool exists;
 
         bool exists;
-        exists = wxFileExists(dbName.c_str());
+        exists = wxFileExists(dbName);
         return exists;
     }
 
         return exists;
     }
 
-    if (userID)
-    {
-        if (!wxStrlen(userID))
-            UserID = uid;
-        else
-            UserID = userID;
-    }
-    else
-        UserID = "";
-
-    // Oracle user names may only be in uppercase, so force
-    // the name to uppercase
-    if (Dbms() == dbmsORACLE)
-        UserID = UserID.Upper();
+    wxString UserID;
+    convertUserID(userID,UserID);
 
     TableName = tableName;
     // Oracle and Interbase table names are uppercase only, so force
 
     TableName = tableName;
     // Oracle and Interbase table names are uppercase only, so force
@@ -2995,15 +3386,18 @@ bool wxDb::TableExists(const char *tableName, const char *userID, const char *ta
 
     // 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 (wxStrcmp(UserID,"") &&
+    if (!UserID.IsEmpty() &&
         Dbms() != dbmsMY_SQL &&
         Dbms() != dbmsACCESS &&
         Dbms() != dbmsMY_SQL &&
         Dbms() != dbmsACCESS &&
-        Dbms() != dbmsMS_SQL_SERVER)
+        Dbms() != dbmsMS_SQL_SERVER &&
+        Dbms() != dbmsDB2 &&
+        Dbms() != dbmsINTERBASE &&
+        Dbms() != dbmsPERVASIVE_SQL)
     {
         retcode = SQLTables(hstmt,
                             NULL, 0,                                  // All qualifiers
     {
         retcode = SQLTables(hstmt,
                             NULL, 0,                                  // All qualifiers
-                            (UCHAR *) UserID.c_str(), SQL_NTS,        // Only tables owned by this user
-                            (UCHAR FAR *)TableName.c_str(), SQL_NTS,
+                            (SQLTCHAR *) UserID.c_str(), SQL_NTS,        // Only tables owned by this user
+                            (SQLTCHAR FAR *)TableName.c_str(), SQL_NTS,
                             NULL, 0);                                 // All table types
     }
     else
                             NULL, 0);                                 // All table types
     }
     else
@@ -3011,7 +3405,7 @@ bool wxDb::TableExists(const char *tableName, const char *userID, const char *ta
         retcode = SQLTables(hstmt,
                             NULL, 0,                                  // All qualifiers
                             NULL, 0,                                  // All owners
         retcode = SQLTables(hstmt,
                             NULL, 0,                                  // All qualifiers
                             NULL, 0,                                  // All owners
-                            (UCHAR FAR *)TableName.c_str(), SQL_NTS,
+                            (SQLTCHAR FAR *)TableName.c_str(), SQL_NTS,
                             NULL, 0);                                 // All table types
     }
     if (retcode != SQL_SUCCESS)
                             NULL, 0);                                 // All table types
     }
     if (retcode != SQL_SUCCESS)
@@ -3032,38 +3426,24 @@ bool wxDb::TableExists(const char *tableName, const char *userID, const char *ta
 
 
 /********** wxDb::TablePrivileges() **********/
 
 
 /********** wxDb::TablePrivileges() **********/
-bool wxDb::TablePrivileges(const char *tableName, const char* priv, const char *userID,
-                            const char *schema, const char *tablePath)
+bool wxDb::TablePrivileges(const wxString &tableName, const wxString &priv, const wxChar *userID,
+                            const wxChar *schema, const wxString &WXUNUSED(tablePath))
 {
 {
+    wxASSERT(tableName.Length());
+
     wxDbTablePrivilegeInfo  result;
     SDWORD  cbRetVal;
     RETCODE retcode;
 
     wxDbTablePrivilegeInfo  result;
     SDWORD  cbRetVal;
     RETCODE retcode;
 
-    //We probably need to be able to dynamically set this based on
-    //the driver type, and state.
-    char curRole[]="public";
+    // We probably need to be able to dynamically set this based on
+    // the driver type, and state.
+    wxChar curRole[]=wxT("public");
 
 
-    //Prologue here similar to db::TableExists()
-    wxString UserID;
     wxString TableName;
 
     wxString TableName;
 
-    assert(userID);
-    assert(tableName && wxStrlen(tableName));
-
-    if (userID)
-    {
-        if (!wxStrlen(userID))
-            UserID = uid;
-        else
-            UserID = userID;
-    }
-    else
-        UserID = "";
-
-    // Oracle user names may only be in uppercase, so force
-    // the name to uppercase
-    if (Dbms() == dbmsORACLE)
-        UserID = UserID.Upper();
+    wxString UserID,Schema;
+    convertUserID(userID,UserID);
+    convertUserID(schema,Schema);
 
     TableName = tableName;
     // Oracle and Interbase table names are uppercase only, so force
 
     TableName = tableName;
     // Oracle and Interbase table names are uppercase only, so force
@@ -3074,54 +3454,64 @@ bool wxDb::TablePrivileges(const char *tableName, const char* priv, const char *
 
     SQLFreeStmt(hstmt, SQL_CLOSE);
 
 
     SQLFreeStmt(hstmt, SQL_CLOSE);
 
-    if (!schema)
+    // Some databases cannot accept a user name when looking up table names,
+    // so we use the call below that leaves out the user name
+    if (!Schema.IsEmpty() &&
+        Dbms() != dbmsMY_SQL &&
+        Dbms() != dbmsACCESS &&
+        Dbms() != dbmsMS_SQL_SERVER)
     {
         retcode = SQLTablePrivileges(hstmt,
                                      NULL, 0,                                    // Catalog
     {
         retcode = SQLTablePrivileges(hstmt,
                                      NULL, 0,                                    // Catalog
-                                     NULL, 0,                                    // Schema
-                                     (UCHAR FAR *)TableName.c_str(), SQL_NTS);
+                                     (SQLTCHAR FAR *)Schema.c_str(), SQL_NTS,               // Schema
+                                     (SQLTCHAR FAR *)TableName.c_str(), SQL_NTS);
     }
     else
     {
         retcode = SQLTablePrivileges(hstmt,
                                      NULL, 0,                                    // Catalog
     }
     else
     {
         retcode = SQLTablePrivileges(hstmt,
                                      NULL, 0,                                    // Catalog
-                                     (UCHAR FAR *)schema, SQL_NTS,               // Schema
-                                     (UCHAR FAR *)TableName.c_str(), SQL_NTS);
+                                     NULL, 0,                                    // Schema
+                                     (SQLTCHAR FAR *)TableName.c_str(), SQL_NTS);
     }
 
 #ifdef DBDEBUG_CONSOLE
     }
 
 #ifdef DBDEBUG_CONSOLE
-    fprintf(stderr ,"SQLTablePrivileges() returned %i \n",retcode);
+    wxFprintf(stderr ,wxT("SQLTablePrivileges() returned %i \n"),retcode);
 #endif
 
     if ((retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO))
         return(DispAllErrors(henv, hdbc, hstmt));
 
 #endif
 
     if ((retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO))
         return(DispAllErrors(henv, hdbc, hstmt));
 
+    bool failed = FALSE;
     retcode = SQLFetch(hstmt);
     while (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
     {
         if (SQLGetData(hstmt, 1, SQL_C_CHAR, (UCHAR*) result.tableQual, sizeof(result.tableQual), &cbRetVal) != SQL_SUCCESS)
     retcode = SQLFetch(hstmt);
     while (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
     {
         if (SQLGetData(hstmt, 1, SQL_C_CHAR, (UCHAR*) result.tableQual, sizeof(result.tableQual), &cbRetVal) != SQL_SUCCESS)
-            return(DispAllErrors(henv, hdbc, hstmt));
+            failed = TRUE;
 
 
-        if (SQLGetData(hstmt, 2, SQL_C_CHAR, (UCHAR*) result.tableOwner, sizeof(result.tableOwner), &cbRetVal) != SQL_SUCCESS)
-            return(DispAllErrors(henv, hdbc, hstmt));
+        if (!failed && SQLGetData(hstmt, 2, SQL_C_CHAR, (UCHAR*) result.tableOwner, sizeof(result.tableOwner), &cbRetVal) != SQL_SUCCESS)
+            failed = TRUE;
 
 
-        if (SQLGetData(hstmt, 3, SQL_C_CHAR, (UCHAR*) result.tableName, sizeof(result.tableName), &cbRetVal) != SQL_SUCCESS)
-            return(DispAllErrors(henv, hdbc, hstmt));
+        if (!failed && SQLGetData(hstmt, 3, SQL_C_CHAR, (UCHAR*) result.tableName, sizeof(result.tableName), &cbRetVal) != SQL_SUCCESS)
+            failed = TRUE;
 
 
-        if (SQLGetData(hstmt, 4, SQL_C_CHAR, (UCHAR*) result.grantor, sizeof(result.grantor), &cbRetVal) != SQL_SUCCESS)
-            return(DispAllErrors(henv, hdbc, hstmt));
+        if (!failed && SQLGetData(hstmt, 4, SQL_C_CHAR, (UCHAR*) result.grantor, sizeof(result.grantor), &cbRetVal) != SQL_SUCCESS)
+            failed = TRUE;
 
 
-        if (SQLGetData(hstmt, 5, SQL_C_CHAR, (UCHAR*) result.grantee, sizeof(result.grantee), &cbRetVal) != SQL_SUCCESS)
-            return(DispAllErrors(henv, hdbc, hstmt));
+        if (!failed && SQLGetData(hstmt, 5, SQL_C_CHAR, (UCHAR*) result.grantee, sizeof(result.grantee), &cbRetVal) != SQL_SUCCESS)
+            failed = TRUE;
 
 
-        if (SQLGetData(hstmt, 6, SQL_C_CHAR, (UCHAR*) result.privilege, sizeof(result.privilege), &cbRetVal) != SQL_SUCCESS)
-            return(DispAllErrors(henv, hdbc, hstmt));
+        if (!failed && SQLGetData(hstmt, 6, SQL_C_CHAR, (UCHAR*) result.privilege, sizeof(result.privilege), &cbRetVal) != SQL_SUCCESS)
+            failed = TRUE;
 
 
-        if (SQLGetData(hstmt, 7, SQL_C_CHAR, (UCHAR*) result.grantable, sizeof(result.grantable), &cbRetVal) != SQL_SUCCESS)
-            return(DispAllErrors(henv, hdbc, hstmt));
+        if (!failed && SQLGetData(hstmt, 7, SQL_C_CHAR, (UCHAR*) result.grantable, sizeof(result.grantable), &cbRetVal) != SQL_SUCCESS)
+            failed = TRUE;
 
 
+        if (failed)
+        {
+            return(DispAllErrors(henv, hdbc, hstmt));
+        }
 #ifdef DBDEBUG_CONSOLE
 #ifdef DBDEBUG_CONSOLE
-        fprintf(stderr,"Scanning %s privilege on table %s.%s granted by %s to %s\n",
+        wxFprintf(stderr,wxT("Scanning %s privilege on table %s.%s granted by %s to %s\n"),
                 result.privilege,result.tableOwner,result.tableName,
                 result.grantor, result.grantee);
 #endif
                 result.privilege,result.tableOwner,result.tableName,
                 result.grantor, result.grantee);
 #endif
@@ -3155,17 +3545,45 @@ bool wxDb::TablePrivileges(const char *tableName, const char* priv, const char *
 }  // wxDb::TablePrivileges
 
 
 }  // wxDb::TablePrivileges
 
 
+const wxString wxDb::SQLTableName(const wxChar *tableName)
+{
+    wxString TableName;
+
+    if (Dbms() == dbmsACCESS)
+        TableName = _T("\"");
+    TableName += tableName;
+    if (Dbms() == dbmsACCESS)
+        TableName += _T("\"");
+
+    return TableName;
+}  // wxDb::SQLTableName()
+
+
+const wxString wxDb::SQLColumnName(const wxChar *colName)
+{
+    wxString ColName;
+
+    if (Dbms() == dbmsACCESS)
+        ColName = _T("\"");
+    ColName += colName;
+    if (Dbms() == dbmsACCESS)
+        ColName += _T("\"");
+
+    return ColName;
+}  // wxDb::SQLColumnName()
+
+
 /********** wxDb::SetSqlLogging() **********/
 /********** wxDb::SetSqlLogging() **********/
-bool wxDb::SetSqlLogging(wxDbSqlLogState state, const char *filename, bool append)
+bool wxDb::SetSqlLogging(wxDbSqlLogState state, const wxString &filename, bool append)
 {
 {
-    assert(state == sqlLogON  || state == sqlLogOFF);
-    assert(state == sqlLogOFF || filename);
+    wxASSERT(state == sqlLogON  || state == sqlLogOFF);
+    wxASSERT(state == sqlLogOFF || filename.Length());
 
     if (state == sqlLogON)
     {
         if (fpSqlLog == 0)
         {
 
     if (state == sqlLogON)
     {
         if (fpSqlLog == 0)
         {
-            fpSqlLog = fopen(filename, (append ? "at" : "wt"));
+            fpSqlLog = wxFopen(filename, (append ? wxT("at") : wxT("wt")));
             if (fpSqlLog == NULL)
                 return(FALSE);
         }
             if (fpSqlLog == NULL)
                 return(FALSE);
         }
@@ -3187,16 +3605,19 @@ bool wxDb::SetSqlLogging(wxDbSqlLogState state, const char *filename, bool appen
 
 
 /********** wxDb::WriteSqlLog() **********/
 
 
 /********** wxDb::WriteSqlLog() **********/
-bool wxDb::WriteSqlLog(const wxChar *logMsg)
+bool wxDb::WriteSqlLog(const wxString &logMsg)
 {
 {
-    assert(logMsg);
+    wxASSERT(logMsg.Length());
 
     if (fpSqlLog == 0 || sqlLogState == sqlLogOFF)
         return(FALSE);
 
 
     if (fpSqlLog == 0 || sqlLogState == sqlLogOFF)
         return(FALSE);
 
-    if (fputs("\n",   fpSqlLog) == EOF) return(FALSE);
-    if (fputs(logMsg, fpSqlLog) == EOF) return(FALSE);
-    if (fputs("\n",   fpSqlLog) == EOF) return(FALSE);
+    if (wxFputs(wxT("\n"),   fpSqlLog) == EOF)
+        return(FALSE);
+    if (wxFputs(logMsg, fpSqlLog) == EOF)
+        return(FALSE);
+    if (wxFputs(wxT("\n"),   fpSqlLog) == EOF)
+        return(FALSE);
 
     return(TRUE);
 
 
     return(TRUE);
 
@@ -3254,7 +3675,16 @@ wxDBMS wxDb::Dbms(void)
  *
  * DB2
  *        - Primary keys must be declared as NOT NULL
  *
  * DB2
  *        - Primary keys must be declared as NOT NULL
+ *        - Table and index names must not be longer than 13 characters in length (technically
+ *          table names can be up to 18 characters, but the primary index is created using the
+ *          base table name plus "_PIDX", so the limit if the table has a primary index is 13.
  *
  *
+ * PERVASIVE SQL
+ *
+ * INTERBASE
+ *        - Columns that are part of primary keys must be defined as being NOT NULL
+ *          when they are created.  Some code is added in ::CreateIndex to try to adjust the
+ *          column definition if it is not defined correctly, but it is experimental
  */
 {
     // Should only need to do this once for each new database connection
  */
 {
     // Should only need to do this once for each new database connection
@@ -3269,56 +3699,62 @@ wxDBMS wxDb::Dbms(void)
 
     // RGG 20001025 : add support for Interbase
     // GT : Integrated to base classes on 20001121
 
     // RGG 20001025 : add support for Interbase
     // GT : Integrated to base classes on 20001121
-    if (!wxStricmp(dbInf.dbmsName,"Interbase"))
+    if (!wxStricmp(dbInf.dbmsName,wxT("Interbase")))
         return((wxDBMS)(dbmsType = dbmsINTERBASE));
 
     // BJO 20000428 : add support for Virtuoso
         return((wxDBMS)(dbmsType = dbmsINTERBASE));
 
     // BJO 20000428 : add support for Virtuoso
-    if (!wxStricmp(dbInf.dbmsName,"OpenLink Virtuoso VDBMS"))
+    if (!wxStricmp(dbInf.dbmsName,wxT("OpenLink Virtuoso VDBMS")))
       return((wxDBMS)(dbmsType = dbmsVIRTUOSO));
 
       return((wxDBMS)(dbmsType = dbmsVIRTUOSO));
 
-    if (!wxStricmp(dbInf.dbmsName,"Adaptive Server Anywhere"))
+    if (!wxStricmp(dbInf.dbmsName,wxT("Adaptive Server Anywhere")))
         return((wxDBMS)(dbmsType = dbmsSYBASE_ASA));
 
     // BJO 20000427 : The "SQL Server" string is also returned by SQLServer when
     // connected through an OpenLink driver.
     // Is it also returned by Sybase Adapatitve server?
     // OpenLink driver name is OLOD3032.DLL for msw and oplodbc.so for unix
         return((wxDBMS)(dbmsType = dbmsSYBASE_ASA));
 
     // BJO 20000427 : The "SQL Server" string is also returned by SQLServer when
     // connected through an OpenLink driver.
     // Is it also returned by Sybase Adapatitve server?
     // OpenLink driver name is OLOD3032.DLL for msw and oplodbc.so for unix
-    if (!wxStricmp(dbInf.dbmsName,"SQL Server"))
+    if (!wxStricmp(dbInf.dbmsName,wxT("SQL Server")))
     {
     {
-      if (!wxStrncmp(dbInf.driverName, "oplodbc", 7) ||
-          !wxStrncmp(dbInf.driverName, "OLOD", 4))
-                       return ((wxDBMS)(dbmsMS_SQL_SERVER));
-               else
-                       return ((wxDBMS)(dbmsType = dbmsSYBASE_ASE));
+      if (!wxStrncmp(dbInf.driverName, wxT("oplodbc"), 7) ||
+          !wxStrncmp(dbInf.driverName, wxT("OLOD"), 4))
+            return ((wxDBMS)(dbmsMS_SQL_SERVER));
+        else
+            return ((wxDBMS)(dbmsType = dbmsSYBASE_ASE));
     }
 
     }
 
-    if (!wxStricmp(dbInf.dbmsName,"Microsoft SQL Server"))
+    if (!wxStricmp(dbInf.dbmsName,wxT("Microsoft SQL Server")))
         return((wxDBMS)(dbmsType = dbmsMS_SQL_SERVER));
         return((wxDBMS)(dbmsType = dbmsMS_SQL_SERVER));
-    if (!wxStricmp(dbInf.dbmsName,"MySQL"))
-        return((wxDBMS)(dbmsType = dbmsMY_SQL));
-    if (!wxStricmp(dbInf.dbmsName,"PostgreSQL"))  // v6.5.0
+
+    baseName[10] = 0;
+    if (!wxStricmp(baseName,wxT("PostgreSQL")))  // v6.5.0
         return((wxDBMS)(dbmsType = dbmsPOSTGRES));
 
         return((wxDBMS)(dbmsType = dbmsPOSTGRES));
 
+    baseName[9] = 0;
+    if (!wxStricmp(baseName,wxT("Pervasive")))
+        return((wxDBMS)(dbmsType = dbmsPERVASIVE_SQL));
+
     baseName[8] = 0;
     baseName[8] = 0;
-    if (!wxStricmp(baseName,"Informix"))
+    if (!wxStricmp(baseName,wxT("Informix")))
         return((wxDBMS)(dbmsType = dbmsINFORMIX));
 
     baseName[6] = 0;
         return((wxDBMS)(dbmsType = dbmsINFORMIX));
 
     baseName[6] = 0;
-    if (!wxStricmp(baseName,"Oracle"))
+    if (!wxStricmp(baseName,wxT("Oracle")))
         return((wxDBMS)(dbmsType = dbmsORACLE));
         return((wxDBMS)(dbmsType = dbmsORACLE));
-    if (!wxStricmp(dbInf.dbmsName,"ACCESS"))
+    if (!wxStricmp(baseName,wxT("ACCESS")))
         return((wxDBMS)(dbmsType = dbmsACCESS));
         return((wxDBMS)(dbmsType = dbmsACCESS));
-    if (!wxStricmp(dbInf.dbmsName,"MySQL"))
-        return((wxDBMS)(dbmsType = dbmsMY_SQL));
-    if (!wxStricmp(baseName,"Sybase"))
+    if (!wxStricmp(baseName,wxT("Sybase")))
       return((wxDBMS)(dbmsType = dbmsSYBASE_ASE));
 
     baseName[5] = 0;
       return((wxDBMS)(dbmsType = dbmsSYBASE_ASE));
 
     baseName[5] = 0;
-    if (!wxStricmp(baseName,"DBASE"))
+    if (!wxStricmp(baseName,wxT("DBASE")))
         return((wxDBMS)(dbmsType = dbmsDBASE));
         return((wxDBMS)(dbmsType = dbmsDBASE));
+    if (!wxStricmp(baseName,wxT("xBase")))
+        return((wxDBMS)(dbmsType = dbmsXBASE_SEQUITER));
+    if (!wxStricmp(baseName,wxT("MySQL")))
+        return((wxDBMS)(dbmsType = dbmsMY_SQL));
 
     baseName[3] = 0;
 
     baseName[3] = 0;
-    if (!wxStricmp(baseName,"DB2"))
+    if (!wxStricmp(baseName,wxT("DB2")))
         return((wxDBMS)(dbmsType = dbmsDBASE));
 
     return((wxDBMS)(dbmsType = dbmsUNIDENTIFIED));
         return((wxDBMS)(dbmsType = dbmsDBASE));
 
     return((wxDBMS)(dbmsType = dbmsUNIDENTIFIED));
@@ -3326,8 +3762,102 @@ wxDBMS wxDb::Dbms(void)
 }  // wxDb::Dbms()
 
 
 }  // wxDb::Dbms()
 
 
+bool wxDb::ModifyColumn(const wxString &tableName, const wxString &columnName,
+                        int dataType, ULONG columnLength,
+                        const wxString &optionalParam)
+{
+    wxASSERT(tableName.Length());
+    wxASSERT(columnName.Length());
+    wxASSERT((dataType == DB_DATA_TYPE_VARCHAR && columnLength > 0) ||
+             dataType != DB_DATA_TYPE_VARCHAR);
+
+    // Must specify a columnLength if modifying a VARCHAR type column
+    if (dataType == DB_DATA_TYPE_VARCHAR && !columnLength)
+        return FALSE;
+
+    wxString dataTypeName;
+    wxString sqlStmt;
+    wxString alterSlashModify;
+
+    switch(dataType)
+    {
+        case DB_DATA_TYPE_VARCHAR :
+            dataTypeName = typeInfVarchar.TypeName;
+            break;
+        case DB_DATA_TYPE_INTEGER :
+            dataTypeName = typeInfInteger.TypeName;
+            break;
+        case DB_DATA_TYPE_FLOAT :
+            dataTypeName = typeInfFloat.TypeName;
+            break;
+        case DB_DATA_TYPE_DATE :
+            dataTypeName = typeInfDate.TypeName;
+            break;
+        case DB_DATA_TYPE_BLOB :
+            dataTypeName = typeInfBlob.TypeName;
+            break;
+        default:
+            return FALSE;
+    }
+
+    // Set the modify or alter syntax depending on the type of database connected to
+    switch (Dbms())
+    {
+        case dbmsORACLE :
+            alterSlashModify = _T("MODIFY");
+            break;
+        case dbmsMS_SQL_SERVER :
+            alterSlashModify = _T("ALTER COLUMN");
+            break;
+        case dbmsUNIDENTIFIED :
+            return FALSE;
+        case dbmsSYBASE_ASA :
+        case dbmsSYBASE_ASE :
+        case dbmsMY_SQL :
+        case dbmsPOSTGRES :
+        case dbmsACCESS :
+        case dbmsDBASE :
+        case dbmsXBASE_SEQUITER :
+        default :
+            alterSlashModify = _T("MODIFY");
+            break;
+    }
+
+    // create the SQL statement
+    if ( Dbms() == dbmsMY_SQL )
+    {
+        sqlStmt.Printf(wxT("ALTER TABLE %s %s %s %s"), tableName.c_str(), alterSlashModify.c_str(),
+              columnName.c_str(), dataTypeName.c_str());
+    }
+    else
+    {
+        sqlStmt.Printf(wxT("ALTER TABLE \"%s\" \"%s\" \"%s\" %s"), tableName.c_str(), alterSlashModify.c_str(),
+              columnName.c_str(), dataTypeName.c_str());
+    }
+
+    // For varchars only, append the size of the column
+    if (dataType == DB_DATA_TYPE_VARCHAR &&
+        (Dbms() != dbmsMY_SQL || dataTypeName != _T("text")))
+    {
+        wxString s;
+        s.Printf(wxT("(%lu)"), columnLength);
+        sqlStmt += s;
+    }
+
+    // for passing things like "NOT NULL"
+    if (optionalParam.Length())
+    {
+        sqlStmt += wxT(" ");
+        sqlStmt += optionalParam;
+    }
+
+    return ExecSql(sqlStmt);
+
+} // wxDb::ModifyColumn()
+
+
 /********** wxDbGetConnection() **********/
 /********** wxDbGetConnection() **********/
-wxDb WXDLLEXPORT *wxDbGetConnection(wxDbConnectInf *pDbConfig, bool FwdOnlyCursors)
+wxDb WXDLLIMPEXP_ODBC *wxDbGetConnection(wxDbConnectInf *pDbConfig, bool FwdOnlyCursors)
 {
     wxDbList *pList;
 
 {
     wxDbList *pList;
 
@@ -3345,17 +3875,42 @@ wxDb WXDLLEXPORT *wxDbGetConnection(wxDbConnectInf *pDbConfig, bool FwdOnlyCurso
         // The database connection must be for the same datasource
         // name and must currently not be in use.
         if (pList->Free &&
         // The database connection must be for the same datasource
         // name and must currently not be in use.
         if (pList->Free &&
-            (pList->PtrDb->FwdOnlyCursors() == FwdOnlyCursors) &&
-            (!wxStrcmp(pDbConfig->Dsn, pList->Dsn)))  // Found a free connection
+            (pList->PtrDb->FwdOnlyCursors() == FwdOnlyCursors))
         {
         {
-            pList->Free = FALSE;
-            return(pList->PtrDb);
+            if (pDbConfig->UseConnectionStr())
+            {
+                if (pList->PtrDb->OpenedWithConnectionString() && 
+                     (!wxStrcmp(pDbConfig->GetConnectionStr(), pList->ConnectionStr)))
+                {
+                    // Found a free connection
+                    pList->Free = FALSE;
+                    return(pList->PtrDb);
+                }
+            }
+            else
+            {
+                if (!pList->PtrDb->OpenedWithConnectionString() &&
+                     (!wxStrcmp(pDbConfig->GetDsn(), pList->Dsn)))
+                {
+                    // Found a free connection
+                    pList->Free = FALSE;
+                    return(pList->PtrDb);
+                }
+            }
         }
 
         }
 
-        if (!wxStrcmp(pDbConfig->Dsn, pList->Dsn) &&
-            !wxStrcmp(pDbConfig->Uid, pList->Uid) &&
-            !wxStrcmp(pDbConfig->AuthStr, pList->AuthStr))
-            matchingDbConnection = pList->PtrDb;
+        if (pDbConfig->UseConnectionStr())
+        {
+            if (!wxStrcmp(pDbConfig->GetConnectionStr(), pList->ConnectionStr))
+                matchingDbConnection = pList->PtrDb;
+        }
+        else
+        {
+            if (!wxStrcmp(pDbConfig->GetDsn(), pList->Dsn) &&
+                !wxStrcmp(pDbConfig->GetUserID(), pList->Uid) &&
+                !wxStrcmp(pDbConfig->GetPassword(), pList->AuthStr))
+                matchingDbConnection = pList->PtrDb;
+        }
     }
 
     // No available connections.  A new connection must be made and
     }
 
     // No available connections.  A new connection must be made and
@@ -3377,25 +3932,36 @@ wxDb WXDLLEXPORT *wxDbGetConnection(wxDbConnectInf *pDbConfig, bool FwdOnlyCurso
     }
 
     // Initialize new node in the linked list
     }
 
     // Initialize new node in the linked list
-    pList->PtrNext = 0;
-    pList->Free = FALSE;
-    wxStrcpy(pList->Dsn, pDbConfig->Dsn);
-    wxStrcpy(pList->Uid, pDbConfig->Uid);
-    wxStrcpy(pList->AuthStr, pDbConfig->AuthStr);
+    pList->PtrNext          = 0;
+    pList->Free             = FALSE;
+    pList->Dsn              = pDbConfig->GetDsn();
+    pList->Uid              = pDbConfig->GetUserID();
+    pList->AuthStr          = pDbConfig->GetPassword();
+    pList->ConnectionStr    = pDbConfig->GetConnectionStr();
 
 
-    pList->PtrDb = new wxDb(pDbConfig->Henv,FwdOnlyCursors);
+    pList->PtrDb = new wxDb(pDbConfig->GetHenv(), FwdOnlyCursors);
 
 
-    bool opened = FALSE;
+    bool opened;
 
     if (!matchingDbConnection)
 
     if (!matchingDbConnection)
-        opened = pList->PtrDb->Open(pDbConfig->Dsn, pDbConfig->Uid, pDbConfig->AuthStr);
+    {
+        if (pDbConfig->UseConnectionStr())
+        {
+            opened = pList->PtrDb->Open(pDbConfig->GetConnectionStr());
+        }
+        else
+        {
+            opened = pList->PtrDb->Open(pDbConfig->GetDsn(), pDbConfig->GetUserID(), pDbConfig->GetPassword());
+        }
+    }
     else
         opened = pList->PtrDb->Open(matchingDbConnection);
 
     // Connect to the datasource
     if (opened)
     {
     else
         opened = pList->PtrDb->Open(matchingDbConnection);
 
     // Connect to the datasource
     if (opened)
     {
-        pList->PtrDb->SetSqlLogging(SQLLOGstate,SQLLOGfn,TRUE);
+        pList->PtrDb->setCached(TRUE);  // Prevent a user from deleting a cached connection
+        pList->PtrDb->SetSqlLogging(SQLLOGstate, SQLLOGfn, TRUE);
         return(pList->PtrDb);
     }
     else  // Unable to connect, destroy list item
         return(pList->PtrDb);
     }
     else  // Unable to connect, destroy list item
@@ -3403,11 +3969,12 @@ wxDb WXDLLEXPORT *wxDbGetConnection(wxDbConnectInf *pDbConfig, bool FwdOnlyCurso
         if (pList->PtrPrev)
             pList->PtrPrev->PtrNext = 0;
         else
         if (pList->PtrPrev)
             pList->PtrPrev->PtrNext = 0;
         else
-            PtrBegDbList = 0;                // Empty list again
-        pList->PtrDb->CommitTrans();    // Commit any open transactions on wxDb object
-        pList->PtrDb->Close();            // Close the wxDb object
-        delete pList->PtrDb;                // Deletes the wxDb object
-        delete pList;                        // Deletes the linked list object
+            PtrBegDbList = 0;        // Empty list again
+
+        pList->PtrDb->CommitTrans(); // Commit any open transactions on wxDb object
+        pList->PtrDb->Close();       // Close the wxDb object
+        delete pList->PtrDb;         // Deletes the wxDb object
+        delete pList;                // Deletes the linked list object
         return(0);
     }
 
         return(0);
     }
 
@@ -3415,7 +3982,7 @@ wxDb WXDLLEXPORT *wxDbGetConnection(wxDbConnectInf *pDbConfig, bool FwdOnlyCurso
 
 
 /********** wxDbFreeConnection() **********/
 
 
 /********** wxDbFreeConnection() **********/
-bool WXDLLEXPORT wxDbFreeConnection(wxDb *pDb)
+bool WXDLLIMPEXP_ODBC wxDbFreeConnection(wxDb *pDb)
 {
     wxDbList *pList;
 
 {
     wxDbList *pList;
 
@@ -3433,7 +4000,7 @@ bool WXDLLEXPORT wxDbFreeConnection(wxDb *pDb)
 
 
 /********** wxDbCloseConnections() **********/
 
 
 /********** wxDbCloseConnections() **********/
-void WXDLLEXPORT wxDbCloseConnections(void)
+void WXDLLIMPEXP_ODBC wxDbCloseConnections(void)
 {
     wxDbList *pList, *pNext;
 
 {
     wxDbList *pList, *pNext;
 
@@ -3443,6 +4010,7 @@ void WXDLLEXPORT wxDbCloseConnections(void)
         pNext = pList->PtrNext;       // Save the pointer to next
         pList->PtrDb->CommitTrans();  // Commit any open transactions on wxDb object
         pList->PtrDb->Close();        // Close the wxDb object
         pNext = pList->PtrNext;       // Save the pointer to next
         pList->PtrDb->CommitTrans();  // Commit any open transactions on wxDb object
         pList->PtrDb->Close();        // Close the wxDb object
+        pList->PtrDb->setCached(FALSE);  // Allows deletion of the wxDb instance
         delete pList->PtrDb;          // Deletes the wxDb object
         delete pList;                 // Deletes the linked list object
     }
         delete pList->PtrDb;          // Deletes the wxDb object
         delete pList;                 // Deletes the linked list object
     }
@@ -3454,7 +4022,7 @@ void WXDLLEXPORT wxDbCloseConnections(void)
 
 
 /********** wxDbConnectionsInUse() **********/
 
 
 /********** wxDbConnectionsInUse() **********/
-int WXDLLEXPORT wxDbConnectionsInUse(void)
+int WXDLLIMPEXP_ODBC wxDbConnectionsInUse(void)
 {
     wxDbList *pList;
     int cnt = 0;
 {
     wxDbList *pList;
     int cnt = 0;
@@ -3471,6 +4039,54 @@ int WXDLLEXPORT wxDbConnectionsInUse(void)
 }  // wxDbConnectionsInUse()
 
 
 }  // wxDbConnectionsInUse()
 
 
+
+/********** wxDbLogExtendedErrorMsg() **********/
+// DEBUG ONLY function
+const wxChar WXDLLIMPEXP_ODBC *wxDbLogExtendedErrorMsg(const wxChar *userText,
+                                                  wxDb *pDb,
+                                                  const wxChar *ErrFile,
+                                                  int ErrLine)
+{
+    static wxString msg;
+    msg = userText;
+
+    wxString tStr;
+
+    if (ErrFile || ErrLine)
+    {
+        msg += wxT("File: ");
+        msg += ErrFile;
+        msg += wxT("   Line: ");
+        tStr.Printf(wxT("%d"),ErrLine);
+        msg += tStr.c_str();
+        msg += wxT("\n");
+    }
+
+    msg.Append (wxT("\nODBC errors:\n"));
+    msg += wxT("\n");
+
+    // Display errors for this connection
+    int i;
+    for (i = 0; i < DB_MAX_ERROR_HISTORY; i++)
+    {
+        if (pDb->errorList[i])
+        {
+            msg.Append(pDb->errorList[i]);
+            if (wxStrcmp(pDb->errorList[i],wxT("")) != 0)
+                msg.Append(wxT("\n"));
+            // Clear the errmsg buffer so the next error will not
+            // end up showing the previous error that have occurred
+            wxStrcpy(pDb->errorList[i],wxT(""));
+        }
+    }
+    msg += wxT("\n");
+
+    wxLogDebug(msg.c_str());
+
+    return msg.c_str();
+}  // wxDbLogExtendedErrorMsg()
+
+
 /********** wxDbSqlLog() **********/
 bool wxDbSqlLog(wxDbSqlLogState state, const wxChar *filename)
 {
 /********** wxDbSqlLog() **********/
 bool wxDbSqlLog(wxDbSqlLogState state, const wxChar *filename)
 {
@@ -3494,8 +4110,8 @@ bool wxDbSqlLog(wxDbSqlLogState state, const wxChar *filename)
 
 #if 0
 /********** wxDbCreateDataSource() **********/
 
 #if 0
 /********** wxDbCreateDataSource() **********/
-int wxDbCreateDataSource(const char *driverName, const char *dsn, const char *description,
-                         bool sysDSN, const char *defDir, wxWindow *parent)
+int wxDbCreateDataSource(const wxString &driverName, const wxString &dsn, const wxString &description,
+                         bool sysDSN, const wxString &defDir, wxWindow *parent)
 /*
  * !!!! ONLY FUNCTIONAL UNDER MSW with VC6 !!!!
  * Very rudimentary creation of an ODBC data source.
 /*
  * !!!! ONLY FUNCTIONAL UNDER MSW with VC6 !!!!
  * Very rudimentary creation of an ODBC data source.
@@ -3518,7 +4134,7 @@ int wxDbCreateDataSource(const char *driverName, const char *dsn, const char *de
     // NOTE: The decimal 2 is an invalid character in all keyword pairs
     // so that is why I used it, as wxString does not deal well with
     // embedded nulls in strings
     // NOTE: The decimal 2 is an invalid character in all keyword pairs
     // so that is why I used it, as wxString does not deal well with
     // embedded nulls in strings
-    setupStr.sprintf("DSN=%s%cDescription=%s%cDefaultDir=%s%c",dsn,2,description,2,defDir,2);
+    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
     // by the SQLConfigDataSource() function
 
     // Replace the separator from above with the '\0' seperator needed
     // by the SQLConfigDataSource() function
@@ -3527,7 +4143,7 @@ int wxDbCreateDataSource(const char *driverName, const char *dsn, const char *de
     {
         k = setupStr.Find((wxChar)2,TRUE);
         if (k != wxNOT_FOUND)
     {
         k = setupStr.Find((wxChar)2,TRUE);
         if (k != wxNOT_FOUND)
-            setupStr[(UINT)k] = '\0';
+            setupStr[(UINT)k] = wxT('\0');
     }
     while (k != wxNOT_FOUND);
 
     }
     while (k != wxNOT_FOUND);
 
@@ -3540,7 +4156,7 @@ int wxDbCreateDataSource(const char *driverName, const char *dsn, const char *de
         DWORD retcode = 0;
         WORD cb;
         wxChar errMsg[SQL_MAX_MESSAGE_LENGTH];
         DWORD retcode = 0;
         WORD cb;
         wxChar errMsg[SQL_MAX_MESSAGE_LENGTH];
-        errMsg[0] = '\0';
+        errMsg[0] = wxT('\0');
 
         // This function is only supported in ODBC drivers v3.0 compliant and above
         SQLInstallerError(1,&retcode,errMsg,SQL_MAX_MESSAGE_LENGTH-1,&cb);
 
         // This function is only supported in ODBC drivers v3.0 compliant and above
         SQLInstallerError(1,&retcode,errMsg,SQL_MAX_MESSAGE_LENGTH-1,&cb);
@@ -3564,7 +4180,7 @@ int wxDbCreateDataSource(const char *driverName, const char *dsn, const char *de
     // Using iODBC/unixODBC or some other compiler which does not support the APIs
     // necessary to use this function, so this function is not supported
 #ifdef __WXDEBUG__
     // Using iODBC/unixODBC or some other compiler which does not support the APIs
     // necessary to use this function, so this function is not supported
 #ifdef __WXDEBUG__
-    wxLogDebug("wxDbCreateDataSource() not available except under VC++/MSW",wxT("ODBC DEBUG MESSAGE"));
+    wxLogDebug(wxT("wxDbCreateDataSource() not available except under VC++/MSW"),wxT("ODBC DEBUG MESSAGE"));
 #endif
     result = FALSE;
 #endif  // __VISUALC__
 #endif
     result = FALSE;
 #endif  // __VISUALC__
@@ -3576,8 +4192,8 @@ int wxDbCreateDataSource(const char *driverName, const char *dsn, const char *de
 
 
 /********** wxDbGetDataSource() **********/
 
 
 /********** wxDbGetDataSource() **********/
-bool wxDbGetDataSource(HENV henv, char *Dsn, SWORD DsnMax, char *DsDesc, SWORD DsDescMax,
-                         UWORD direction)
+bool wxDbGetDataSource(HENV henv, wxChar *Dsn, SWORD DsnMax, wxChar *DsDesc,
+                       SWORD DsDescMax, UWORD direction)
 /*
  * Dsn and DsDesc will contain the data source name and data source
  * description upon return
 /*
  * Dsn and DsDesc will contain the data source name and data source
  * description upon return
@@ -3585,8 +4201,8 @@ bool wxDbGetDataSource(HENV henv, char *Dsn, SWORD DsnMax, char *DsDesc, SWORD D
 {
     SWORD cb1,cb2;
 
 {
     SWORD cb1,cb2;
 
-    if (SQLDataSources(henv, direction, (UCHAR FAR *) Dsn, DsnMax, &cb1,
-                             (UCHAR FAR *) DsDesc, DsDescMax, &cb2) == SQL_SUCCESS)
+    if (SQLDataSources(henv, direction, (SQLTCHAR FAR *) Dsn, DsnMax, &cb1,
+                             (SQLTCHAR FAR *) DsDesc, DsDescMax, &cb2) == SQL_SUCCESS)
         return(TRUE);
     else
         return(FALSE);
         return(TRUE);
     else
         return(FALSE);
@@ -3615,22 +4231,22 @@ bool GetDataSource(HENV henv, char *Dsn, SWORD DsnMax, char *DsDesc, SWORD DsDes
     return wxDbGetDataSource(henv, Dsn, DsnMax, DsDesc, DsDescMax, direction);
 }
 /***** DEPRECATED: use wxDbGetConnection() *****/
     return wxDbGetDataSource(henv, Dsn, DsnMax, DsDesc, DsDescMax, direction);
 }
 /***** DEPRECATED: use wxDbGetConnection() *****/
-wxDb WXDLLEXPORT *GetDbConnection(DbStuff *pDbStuff, bool FwdOnlyCursors)
+wxDb WXDLLIMPEXP_ODBC *GetDbConnection(DbStuff *pDbStuff, bool FwdOnlyCursors)
 {
     return wxDbGetConnection((wxDbConnectInf *)pDbStuff, FwdOnlyCursors);
 }
 /***** DEPRECATED: use wxDbFreeConnection() *****/
 {
     return wxDbGetConnection((wxDbConnectInf *)pDbStuff, FwdOnlyCursors);
 }
 /***** DEPRECATED: use wxDbFreeConnection() *****/
-bool WXDLLEXPORT FreeDbConnection(wxDb *pDb)
+bool WXDLLIMPEXP_ODBC FreeDbConnection(wxDb *pDb)
 {
     return wxDbFreeConnection(pDb);
 }
 /***** DEPRECATED: use wxDbCloseConnections() *****/
 {
     return wxDbFreeConnection(pDb);
 }
 /***** DEPRECATED: use wxDbCloseConnections() *****/
-void WXDLLEXPORT CloseDbConnections(void)
+void WXDLLIMPEXP_ODBC CloseDbConnections(void)
 {
     wxDbCloseConnections();
 }
 /***** DEPRECATED: use wxDbConnectionsInUse() *****/
 {
     wxDbCloseConnections();
 }
 /***** DEPRECATED: use wxDbConnectionsInUse() *****/
-int WXDLLEXPORT NumberDbConnectionsInUse(void)
+int WXDLLIMPEXP_ODBC NumberDbConnectionsInUse(void)
 {
     return wxDbConnectionsInUse();
 }
 {
     return wxDbConnectionsInUse();
 }