// SYNOPSIS START
// SYNOPSIS STOP
*/
+#ifdef __GNUG__
+ #pragma implementation "db.h"
+#endif
#include "wx/wxprec.h"
-
-// Use this line for wxWindows v1.x
-//#include "wx_ver.h"
-// Use this line for wxWindows v2.x
-#include "wx/version.h"
-
-#if wxMAJOR_VERSION == 2
- #ifdef __GNUG__
- #pragma implementation "db.h"
- #endif
+#ifdef __BORLANDC__
+ #pragma hdrstop
#endif
#ifdef DBDEBUG_CONSOLE
#include "wx/ioswrap.h"
#endif
-#ifdef __BORLANDC__
- #pragma hdrstop
-#endif //__BORLANDC__
-
-#if wxMAJOR_VERSION == 2
- #ifndef WX_PRECOMP
- #include "wx/string.h"
- #include "wx/object.h"
- #include "wx/list.h"
- #include "wx/utils.h"
+#ifndef WX_PRECOMP
+ #include "wx/string.h"
+ #include "wx/object.h"
+ #include "wx/list.h"
+ #include "wx/utils.h"
+ #if wxUSE_GUI
#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
+ #include "wx/log.h"
#endif
+#include "wx/filefn.h"
+#include "wx/wxchar.h"
#if wxUSE_ODBC
#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;
// connection
wxChar DBerrorList[DB_MAX_ERROR_HISTORY][DB_MAX_ERROR_MSG_LEN];
+
// This type defines the return row-struct form
// SQLTablePrivileges, and is used by wxDB::TablePrivileges.
typedef struct
} wxDbTablePrivilegeInfo;
-/********** wxDbColFor Constructor **********/
-wxDbColFor::wxDbColFor()
+/********** wxDbConnectInf Constructor - form 1 **********/
+wxDbConnectInf::wxDbConnectInf()
{
- s_Field.Empty();
- 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].Empty();
- s_Amount[i].Empty();
- 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;
+ Description.Empty();
+ FileType.Empty();
+ DefaultDir.Empty();
+
+ 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;
+ }
-wxDbColInf::~wxDbColInf()
+ freeHenvOnDestroy = TRUE;
+
+ 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()
+
+
+/********** wxDbColFor Constructor **********/
+wxDbColFor::wxDbColFor()
{
- if (pTableInf)
- delete [] pTableInf;
- pTableInf = NULL;
-} // wxDbInf::~wxDbInf()
+ 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()
+/********** wxDbColFor::Format() **********/
int wxDbColFor::Format(int Nation, int dbDataType, SWORD sqlDataType,
short columnSize, short decimalDigits)
{
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))
s_Field = wxT("%02d/%02d/%04d %02d:%02d:%02d.%03d");
}
break;
+ case DB_DATA_TYPE_BLOB:
+ s_Field.Printf(wxT("Unable to format(%d)-SQL(%d)"),dbDataType,sqlDataType); //
+ break;
default:
s_Field.Printf(wxT("Unknown Format(%d)-SQL(%d)"),dbDataType,sqlDataType); //
break;
} // 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;
+
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
nTables = 0;
dbmsType = dbmsUNIDENTIFIED;
- wxStrcpy(sqlState,wxT(""));
- wxStrcpy(errorMsg,wxT(""));
+ wxStrcpy(sqlState,wxEmptyString);
+ wxStrcpy(errorMsg,wxEmptyString);
nativeError = cbErrorMsg = 0;
for (i = 0; i < DB_MAX_ERROR_HISTORY; i++)
- wxStrcpy(errorList[i], wxT(""));
+ wxStrcpy(errorList[i], wxEmptyString);
// Init typeInf structures
typeInfVarchar.TypeName.Empty();
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;
// Mark database as not open as of yet
dbIsOpen = FALSE;
+ dbIsCached = FALSE;
} // wxDb::initialize()
-/********** PRIVATE! wxDb::initialize PRIVATE! **********/
+/********** PRIVATE! wxDb::convertUserID PRIVATE! **********/
//
// NOTE: Return value from this function MUST be copied
// immediately, as the value is not good after
(UCHAR FAR *) uid.c_str(), SQL_NTS,
(UCHAR FAR *) authStr.c_str(), SQL_NTS);
-/*
- if (retcode == SQL_SUCCESS_WITH_INFO)
- DispAllErrors(henv, hdbc);
- else if (retcode != SQL_SUCCESS)
- return(DispAllErrors(henv, hdbc));
-
- if (retcode == SQL_ERROR)
- return(DispAllErrors(henv, hdbc));
-*/
- if ((retcode != SQL_SUCCESS) &&
+ if ((retcode != SQL_SUCCESS) &&
(retcode != SQL_SUCCESS_WITH_INFO))
- return(DispAllErrors(henv, hdbc));
+ return(DispAllErrors(henv, hdbc));
/*
If using Intersolv branded ODBC drivers, this is the place where you would substitute
your branded driver license information
- SQLSetConnectOption(hdbc, 1041, (UDWORD) wxT(""));
- SQLSetConnectOption(hdbc, 1042, (UDWORD) wxT(""));
+ SQLSetConnectOption(hdbc, 1041, (UDWORD) wxEmptyString);
+ SQLSetConnectOption(hdbc, 1042, (UDWORD) wxEmptyString);
*/
// Mark database as open
// 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
// Float
if (!getDataTypeInfo(SQL_DOUBLE,typeInfFloat))
-
if (!getDataTypeInfo(SQL_REAL,typeInfFloat))
if (!getDataTypeInfo(SQL_FLOAT,typeInfFloat))
if (!getDataTypeInfo(SQL_DECIMAL,typeInfFloat))
// Date/Time
if (Dbms() != dbmsDBASE)
{
- if (! getDataTypeInfo(SQL_TIMESTAMP,typeInfDate))
+ if (!getDataTypeInfo(SQL_TIMESTAMP,typeInfDate))
return(FALSE);
else
typeInfDate.FsqlType = SQL_TIMESTAMP;
typeInfDate.FsqlType = SQL_DATE;
}
+ if (!getDataTypeInfo(SQL_LONGVARBINARY, typeInfBlob))
+ {
+ if (!getDataTypeInfo(SQL_VARBINARY,typeInfBlob))
+ return(FALSE);
+ else
+ typeInfBlob.FsqlType = SQL_VARBINARY;
+ }
+ else
+ typeInfBlob.FsqlType = SQL_LONGVARBINARY;
+
+//typeInfBlob.TypeName = "BLOB";
+
#ifdef DBDEBUG_CONSOLE
cout << wxT("VARCHAR DATA TYPE: ") << typeInfVarchar.TypeName << endl;
cout << wxT("INTEGER DATA TYPE: ") << typeInfInteger.TypeName << endl;
cout << wxT("FLOAT DATA TYPE: ") << typeInfFloat.TypeName << endl;
cout << wxT("DATE DATA TYPE: ") << typeInfDate.TypeName << endl;
+ cout << wxT("BLOB DATA TYPE: ") << typeInfBlob.TypeName << endl;
cout << endl;
#endif
} // wxDb::Open()
+bool wxDb::Open(wxDbConnectInf *dbConnectInf)
+{
+ return Open(dbConnectInf->GetDsn(), dbConnectInf->GetUserID(),
+ dbConnectInf->GetPassword());
+} // wxDb::Open()
+
+
bool wxDb::Open(wxDb *copyDb)
{
dsn = copyDb->GetDatasourceName();
(UCHAR FAR *) uid.c_str(), SQL_NTS,
(UCHAR FAR *) authStr.c_str(), SQL_NTS);
- if (retcode == SQL_ERROR)
- return(DispAllErrors(henv, hdbc));
+ if (retcode == SQL_ERROR)
+ return(DispAllErrors(henv, hdbc));
/*
If using Intersolv branded ODBC drivers, this is the place where you would substitute
your branded driver license information
- SQLSetConnectOption(hdbc, 1041, (UDWORD) wxT(""));
- SQLSetConnectOption(hdbc, 1042, (UDWORD) wxT(""));
+ SQLSetConnectOption(hdbc, 1041, (UDWORD) wxEmptyString);
+ SQLSetConnectOption(hdbc, 1042, (UDWORD) wxEmptyString);
*/
// Mark database as open
typeInfDate.CaseSensitive = copyDb->typeInfDate.CaseSensitive;
typeInfDate.MaximumScale = copyDb->typeInfDate.MaximumScale;
+ // Blob
+ typeInfBlob.FsqlType = copyDb->typeInfBlob.FsqlType;
+ typeInfBlob.TypeName = copyDb->typeInfBlob.TypeName;
+ typeInfBlob.Precision = copyDb->typeInfBlob.Precision;
+ typeInfBlob.CaseSensitive = copyDb->typeInfBlob.CaseSensitive;
+ typeInfBlob.MaximumScale = copyDb->typeInfBlob.MaximumScale;
+
#ifdef DBDEBUG_CONSOLE
cout << wxT("VARCHAR DATA TYPE: ") << typeInfVarchar.TypeName << endl;
cout << wxT("INTEGER DATA TYPE: ") << typeInfInteger.TypeName << endl;
cout << wxT("FLOAT DATA TYPE: ") << typeInfFloat.TypeName << endl;
cout << wxT("DATE DATA TYPE: ") << typeInfDate.TypeName << endl;
+ cout << wxT("BLOB DATA TYPE: ") << typeInfBlob.TypeName << endl;
cout << endl;
#endif
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
{
s.Printf(wxT("(%-20s) tableID:[%6lu] pDb:[%p]"), tiu->tableName,tiu->tableID,tiu->pDb);
s2.Printf(wxT("Orphaned found using pDb:[%p]"),this);
- wxLogDebug (s,s2);
+ wxLogDebug (s.c_str(),s2.c_str());
}
pNode = pNode->Next();
}
// 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()
}
}
- return(FALSE); // This function always returns false.
+ return(FALSE); // This function always returns FALSE.
} // wxDb::DispAllErrors()
}
sqlStmt += wxT(" ON ");
- sqlStmt += tableName;
+ sqlStmt += SQLTableName(tableName);
sqlStmt += wxT(" TO ");
sqlStmt += userList;
*/
wxString sqlStmt;
- sqlStmt.Printf(wxT("DROP VIEW %s"), viewName);
+ sqlStmt.Printf(wxT("DROP VIEW %s"), viewName.c_str());
WriteSqlLog(sqlStmt);
}
// Commit the transaction
- if (! CommitTrans())
+ if (!CommitTrans())
return(FALSE);
return TRUE;
/********** wxDb::ExecSql() **********/
bool wxDb::ExecSql(const wxString &pSqlStmt)
{
+ RETCODE retcode;
+
SQLFreeStmt(hstmt, SQL_CLOSE);
- if (SQLExecDirect(hstmt, (UCHAR FAR *) pSqlStmt.c_str(), SQL_NTS) == SQL_SUCCESS)
+
+ retcode = SQLExecDirect(hstmt, (UCHAR FAR *) pSqlStmt.c_str(), SQL_NTS);
+ if (retcode == SQL_SUCCESS ||
+ (Dbms() == dbmsDB2 && (retcode == SQL_SUCCESS_WITH_INFO || retcode == SQL_NO_DATA_FOUND)))
+ {
return(TRUE);
+ }
else
{
DispAllErrors(henv, hdbc, hstmt);
/********** wxDb::GetKeyFields() **********/
-int wxDb::GetKeyFields(const wxString &tableName, wxDbColInf* colInf, int noCols)
+int wxDb::GetKeyFields(const wxString &tableName, wxDbColInf* colInf, UWORD noCols)
{
wxChar szPkTable[DB_MAX_TABLE_NAME_LEN+1]; /* Primary key table name */
wxChar szFkTable[DB_MAX_TABLE_NAME_LEN+1]; /* Foreign key table name */
wxChar szFkCol[DB_MAX_COLUMN_NAME_LEN+1]; /* Foreign key column */
SQLRETURN retcode;
SDWORD cb;
- int i;
+ SWORD i;
wxString tempStr;
/*
* -----------------------------------------------------------------------
* to avoid undesired unbinding of columns.
*/
{
- int noCols = 0;
- int colNo = 0;
+ UWORD noCols = 0;
+ UWORD colNo = 0;
wxDbColInf *colInf = 0;
RETCODE retcode;
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
#endif
colInf[colNo].dbDataType = DB_DATA_TYPE_VARCHAR;
}
- else if (!wxStricmp(typeInfInteger.TypeName,colInf[colNo].typeName))
+ else if (!wxStricmp(typeInfInteger.TypeName, colInf[colNo].typeName))
colInf[colNo].dbDataType = DB_DATA_TYPE_INTEGER;
- else if (!wxStricmp(typeInfFloat.TypeName,colInf[colNo].typeName))
+ else if (!wxStricmp(typeInfFloat.TypeName, colInf[colNo].typeName))
colInf[colNo].dbDataType = DB_DATA_TYPE_FLOAT;
- else if (!wxStricmp(typeInfDate.TypeName,colInf[colNo].typeName))
+ else if (!wxStricmp(typeInfDate.TypeName, colInf[colNo].typeName))
colInf[colNo].dbDataType = DB_DATA_TYPE_DATE;
-
+ else if (!wxStricmp(typeInfBlob.TypeName, colInf[colNo].typeName))
+ colInf[colNo].dbDataType = DB_DATA_TYPE_BLOB;
colNo++;
}
}
/********** wxDb::GetColumns() **********/
-wxDbColInf *wxDb::GetColumns(const wxString &tableName, int *numCols, const wxChar *userID)
+wxDbColInf *wxDb::GetColumns(const wxString &tableName, UWORD *numCols, const wxChar *userID)
//
// Same as the above GetColumns() function except this one gets columns
// only for a single table, and if 'numCols' is not NULL, the number of
// to avoid undesired unbinding of columns.
{
- int noCols = 0;
- int colNo = 0;
+ UWORD noCols = 0;
+ UWORD colNo = 0;
wxDbColInf *colInf = 0;
RETCODE retcode;
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;
}
// 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
colInf[colNo].dbDataType = DB_DATA_TYPE_VARCHAR;
}
- else if (!wxStricmp(typeInfInteger.TypeName,colInf[colNo].typeName))
+ else if (!wxStricmp(typeInfInteger.TypeName, colInf[colNo].typeName))
colInf[colNo].dbDataType = DB_DATA_TYPE_INTEGER;
- else if (!wxStricmp(typeInfFloat.TypeName,colInf[colNo].typeName))
+ else if (!wxStricmp(typeInfFloat.TypeName, colInf[colNo].typeName))
colInf[colNo].dbDataType = DB_DATA_TYPE_FLOAT;
- else if (!wxStricmp(typeInfDate.TypeName,colInf[colNo].typeName))
+ else if (!wxStricmp(typeInfDate.TypeName, colInf[colNo].typeName))
colInf[colNo].dbDataType = DB_DATA_TYPE_DATE;
+ else if (!wxStricmp(typeInfBlob.TypeName, colInf[colNo].typeName))
+ colInf[colNo].dbDataType = DB_DATA_TYPE_BLOB;
colNo++;
}
typedef struct
{
- int noCols;
+ UWORD noCols;
wxDbColInf *colInf;
} _TableColumns;
// 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;
wxDbColInf *colInf = new wxDbColInf[noCols+1];
// Mark the end of the array
- wxStrcpy(colInf[noCols].tableName, wxT(""));
- wxStrcpy(colInf[noCols].colName, wxT(""));
+ wxStrcpy(colInf[noCols].tableName, wxEmptyString);
+ wxStrcpy(colInf[noCols].colName, wxEmptyString);
colInf[noCols].sqlDataType = 0;
// Merge ...
// 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;
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;
}
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;
// Build a generic SELECT statement which returns 0 rows
wxString Stmt;
- Stmt.Printf(wxT("select * from %s where 0=1"), tableName);
+ Stmt.Printf(wxT("select * from \"%s\" where 0=1"), tableName);
// Execute query
if (SQLExecDirect(hstmt, (UCHAR FAR *) Stmt.c_str(), SQL_NTS) != SQL_SUCCESS)
* to avoid undesired unbinding of columns.
*/
{
- int noCols = 0;
+ UWORD noCols = 0;
RETCODE retcode;
wxChar colName[DB_MAX_COLUMN_NAME_LEN+1];
SWORD sqlDataType;
wxChar typeName[30+1];
- SWORD precision, length;
+ SDWORD precision, length;
FILE *fp = fopen(fileName.c_str(),wxT("wt"));
if (fp == NULL)
if (!UserID.IsEmpty() &&
Dbms() != dbmsMY_SQL &&
Dbms() != dbmsACCESS &&
+ Dbms() != dbmsINTERBASE &&
Dbms() != dbmsMS_SQL_SERVER)
{
retcode = SQLColumns(hstmt,
tblNameSave.Empty();
int cnt = 0;
- while ((retcode = SQLFetch(hstmt)) == SQL_SUCCESS)
+ while (TRUE)
{
+ retcode = SQLFetch(hstmt);
+ if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
+ break;
+
if (wxStrcmp(tblName, tblNameSave.c_str()))
{
if (cnt)
tblNameSave = tblName;
}
- GetData(3,SQL_C_CHAR, (UCHAR *)tblName, DB_MAX_TABLE_NAME_LEN+1, &cb);
- GetData(4,SQL_C_CHAR, (UCHAR *)colName, DB_MAX_COLUMN_NAME_LEN+1,&cb);
- GetData(5,SQL_C_SSHORT,(UCHAR *)&sqlDataType,0, &cb);
- GetData(6,SQL_C_CHAR, (UCHAR *)typeName, sizeof(typeName), &cb);
- GetData(7,SQL_C_SSHORT,(UCHAR *)&precision, 0, &cb);
- GetData(8,SQL_C_SSHORT,(UCHAR *)&length, 0, &cb);
+ GetData(3,SQL_C_CHAR, (UCHAR *) tblName, DB_MAX_TABLE_NAME_LEN+1, &cb);
+ GetData(4,SQL_C_CHAR, (UCHAR *) colName, DB_MAX_COLUMN_NAME_LEN+1,&cb);
+ GetData(5,SQL_C_SSHORT,(UCHAR *)&sqlDataType, 0, &cb);
+ GetData(6,SQL_C_CHAR, (UCHAR *) typeName, sizeof(typeName), &cb);
+ GetData(7,SQL_C_SLONG, (UCHAR *)&precision, 0, &cb);
+ GetData(8,SQL_C_SLONG, (UCHAR *)&length, 0, &cb);
outStr.Printf(wxT("%-32s %-32s (%04d)%-15s %9d %9d\n"),
tblName, colName, sqlDataType, typeName, precision, length);
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.
{
wxString dbName;
if (tablePath.Length())
- dbName.Printf(wxT("%s/%s.dbf"),tablePath,tableName);
+ dbName.Printf(wxT("%s/%s.dbf"), tablePath.c_str(), tableName.c_str());
else
- dbName.Printf(wxT("%s.dbf"),tableName);
+ dbName.Printf(wxT("%s.dbf"), tableName.c_str());
bool exists;
exists = wxFileExists(dbName);
if (!UserID.IsEmpty() &&
Dbms() != dbmsMY_SQL &&
Dbms() != dbmsACCESS &&
- Dbms() != dbmsMS_SQL_SERVER)
+ Dbms() != dbmsMS_SQL_SERVER &&
+ Dbms() != dbmsDB2 &&
+ Dbms() != dbmsINTERBASE &&
+ Dbms() != dbmsPERVASIVE_SQL)
{
retcode = SQLTables(hstmt,
NULL, 0, // All qualifiers
wxString TableName;
- wxString UserID;
+ wxString UserID,Schema;
convertUserID(userID,UserID);
+ convertUserID(schema,Schema);
TableName = tableName;
// Oracle and Interbase table names are uppercase only, so force
SQLFreeStmt(hstmt, SQL_CLOSE);
- if (!schema)
+ // Some databases cannot accept a user name when looking up table names,
+ // so we use the call below that leaves out the user name
+ if (!Schema.IsEmpty() &&
+ Dbms() != dbmsMY_SQL &&
+ Dbms() != dbmsACCESS &&
+ Dbms() != dbmsMS_SQL_SERVER)
{
retcode = SQLTablePrivileges(hstmt,
NULL, 0, // Catalog
- NULL, 0, // Schema
+ (UCHAR FAR *)Schema.c_str(), SQL_NTS, // Schema
(UCHAR FAR *)TableName.c_str(), SQL_NTS);
}
else
{
retcode = SQLTablePrivileges(hstmt,
NULL, 0, // Catalog
- (UCHAR FAR *)schema, SQL_NTS, // Schema
+ NULL, 0, // Schema
(UCHAR FAR *)TableName.c_str(), SQL_NTS);
}
if ((retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO))
return(DispAllErrors(henv, hdbc, hstmt));
+ bool failed = FALSE;
retcode = SQLFetch(hstmt);
while (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
if (SQLGetData(hstmt, 1, SQL_C_CHAR, (UCHAR*) result.tableQual, sizeof(result.tableQual), &cbRetVal) != SQL_SUCCESS)
- return(DispAllErrors(henv, hdbc, hstmt));
+ failed = TRUE;
- if (SQLGetData(hstmt, 2, SQL_C_CHAR, (UCHAR*) result.tableOwner, sizeof(result.tableOwner), &cbRetVal) != SQL_SUCCESS)
- return(DispAllErrors(henv, hdbc, hstmt));
+ if (!failed && SQLGetData(hstmt, 2, SQL_C_CHAR, (UCHAR*) result.tableOwner, sizeof(result.tableOwner), &cbRetVal) != SQL_SUCCESS)
+ failed = TRUE;
- if (SQLGetData(hstmt, 3, SQL_C_CHAR, (UCHAR*) result.tableName, sizeof(result.tableName), &cbRetVal) != SQL_SUCCESS)
- return(DispAllErrors(henv, hdbc, hstmt));
+ if (!failed && SQLGetData(hstmt, 3, SQL_C_CHAR, (UCHAR*) result.tableName, sizeof(result.tableName), &cbRetVal) != SQL_SUCCESS)
+ failed = TRUE;
- if (SQLGetData(hstmt, 4, SQL_C_CHAR, (UCHAR*) result.grantor, sizeof(result.grantor), &cbRetVal) != SQL_SUCCESS)
- return(DispAllErrors(henv, hdbc, hstmt));
+ if (!failed && SQLGetData(hstmt, 4, SQL_C_CHAR, (UCHAR*) result.grantor, sizeof(result.grantor), &cbRetVal) != SQL_SUCCESS)
+ failed = TRUE;
- if (SQLGetData(hstmt, 5, SQL_C_CHAR, (UCHAR*) result.grantee, sizeof(result.grantee), &cbRetVal) != SQL_SUCCESS)
- return(DispAllErrors(henv, hdbc, hstmt));
+ if (!failed && SQLGetData(hstmt, 5, SQL_C_CHAR, (UCHAR*) result.grantee, sizeof(result.grantee), &cbRetVal) != SQL_SUCCESS)
+ failed = TRUE;
- if (SQLGetData(hstmt, 6, SQL_C_CHAR, (UCHAR*) result.privilege, sizeof(result.privilege), &cbRetVal) != SQL_SUCCESS)
- return(DispAllErrors(henv, hdbc, hstmt));
+ if (!failed && SQLGetData(hstmt, 6, SQL_C_CHAR, (UCHAR*) result.privilege, sizeof(result.privilege), &cbRetVal) != SQL_SUCCESS)
+ failed = TRUE;
- if (SQLGetData(hstmt, 7, SQL_C_CHAR, (UCHAR*) result.grantable, sizeof(result.grantable), &cbRetVal) != SQL_SUCCESS)
- return(DispAllErrors(henv, hdbc, hstmt));
+ if (!failed && SQLGetData(hstmt, 7, SQL_C_CHAR, (UCHAR*) result.grantable, sizeof(result.grantable), &cbRetVal) != SQL_SUCCESS)
+ failed = TRUE;
+ if (failed)
+ {
+ return(DispAllErrors(henv, hdbc, hstmt));
+ }
#ifdef DBDEBUG_CONSOLE
fprintf(stderr,wxT("Scanning %s privilege on table %s.%s granted by %s to %s\n"),
result.privilege,result.tableOwner,result.tableName,
} // wxDb::TablePrivileges
+const wxString wxDb::SQLTableName(const wxChar *tableName)
+{
+ wxString TableName;
+
+ if (Dbms() == dbmsACCESS)
+ TableName = '"';
+ TableName += tableName;
+ if (Dbms() == dbmsACCESS)
+ TableName += '"';
+
+ return TableName;
+} // wxDb::SQLTableName()
+
+
+const wxString wxDb::SQLColumnName(const wxChar *colName)
+{
+ wxString ColName;
+
+ if (Dbms() == dbmsACCESS)
+ ColName = '"';
+ ColName += colName;
+ if (Dbms() == dbmsACCESS)
+ ColName += '"';
+
+ return ColName;
+} // wxDb::SQLColumnName()
+
+
/********** wxDb::SetSqlLogging() **********/
bool wxDb::SetSqlLogging(wxDbSqlLogState state, const wxString &filename, bool append)
{
*
* 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
{
if (!wxStrncmp(dbInf.driverName, wxT("oplodbc"), 7) ||
!wxStrncmp(dbInf.driverName, wxT("OLOD"), 4))
- return ((wxDBMS)(dbmsMS_SQL_SERVER));
- else
- return ((wxDBMS)(dbmsType = dbmsSYBASE_ASE));
+ return ((wxDBMS)(dbmsMS_SQL_SERVER));
+ else
+ return ((wxDBMS)(dbmsType = dbmsSYBASE_ASE));
}
if (!wxStricmp(dbInf.dbmsName,wxT("Microsoft SQL Server")))
if (!wxStricmp(dbInf.dbmsName,wxT("PostgreSQL"))) // v6.5.0
return((wxDBMS)(dbmsType = dbmsPOSTGRES));
+ baseName[9] = 0;
+ if (!wxStricmp(dbInf.dbmsName,wxT("Pervasive")))
+ return((wxDBMS)(dbmsType = dbmsPERVASIVE_SQL));
+
baseName[8] = 0;
if (!wxStricmp(baseName,wxT("Informix")))
return((wxDBMS)(dbmsType = dbmsINFORMIX));
// Must specify a columnLength if modifying a VARCHAR type column
if (dataType == DB_DATA_TYPE_VARCHAR && !columnLength)
return FALSE;
-
+
wxString dataTypeName;
- wxString sqlStmt;
+ wxString sqlStmt;
wxString alterSlashModify;
- switch(dataType)
- {
- case DB_DATA_TYPE_VARCHAR :
- dataTypeName = typeInfVarchar.TypeName;
- break;
- case DB_DATA_TYPE_INTEGER :
- dataTypeName = typeInfInteger.TypeName;
- break;
- case DB_DATA_TYPE_FLOAT :
- dataTypeName = typeInfFloat.TypeName;
- break;
- case DB_DATA_TYPE_DATE :
- dataTypeName = typeInfDate.TypeName;
- break;
- default:
- return FALSE;
- }
-
- // Set the modify or alter syntax depending on the type of database connected to
- switch (Dbms())
- {
- case dbmsORACLE :
- alterSlashModify = "MODIFY";
- break;
- case dbmsMS_SQL_SERVER :
- alterSlashModify = "ALTER COLUMN";
- break;
- case dbmsUNIDENTIFIED :
+ switch(dataType)
+ {
+ case DB_DATA_TYPE_VARCHAR :
+ dataTypeName = typeInfVarchar.TypeName;
+ break;
+ case DB_DATA_TYPE_INTEGER :
+ dataTypeName = typeInfInteger.TypeName;
+ break;
+ case DB_DATA_TYPE_FLOAT :
+ dataTypeName = typeInfFloat.TypeName;
+ break;
+ case DB_DATA_TYPE_DATE :
+ dataTypeName = typeInfDate.TypeName;
+ break;
+ case DB_DATA_TYPE_BLOB :
+ dataTypeName = typeInfBlob.TypeName;
+ break;
+ default:
+ return FALSE;
+ }
+
+ // Set the modify or alter syntax depending on the type of database connected to
+ switch (Dbms())
+ {
+ case dbmsORACLE :
+ alterSlashModify = "MODIFY";
+ break;
+ case dbmsMS_SQL_SERVER :
+ alterSlashModify = "ALTER COLUMN";
+ break;
+ case dbmsUNIDENTIFIED :
return FALSE;
- case dbmsSYBASE_ASA :
- case dbmsSYBASE_ASE :
- case dbmsMY_SQL :
- case dbmsPOSTGRES :
- case dbmsACCESS :
- case dbmsDBASE :
- default :
- alterSlashModify = "MODIFY";
- break;
- }
-
- // create the SQL statement
- sqlStmt.Printf(wxT("ALTER TABLE %s %s %s %s"), tableName, alterSlashModify,
- columnName, dataTypeName);
+ case dbmsSYBASE_ASA :
+ case dbmsSYBASE_ASE :
+ case dbmsMY_SQL :
+ case dbmsPOSTGRES :
+ case dbmsACCESS :
+ case dbmsDBASE :
+ default :
+ alterSlashModify = "MODIFY";
+ break;
+ }
+
+ // create the SQL statement
+ sqlStmt.Printf(wxT("ALTER TABLE \"%s\" \"%s\" \"%s\" %s"), tableName.c_str(), alterSlashModify.c_str(),
+ columnName.c_str(), dataTypeName.c_str());
// For varchars only, append the size of the column
if (dataType == DB_DATA_TYPE_VARCHAR)
sqlStmt += optionalParam;
}
- return ExecSql(sqlStmt);
+ return ExecSql(sqlStmt);
} // wxDb::ModifyColumn()
// name and must currently not be in use.
if (pList->Free &&
(pList->PtrDb->FwdOnlyCursors() == FwdOnlyCursors) &&
- (!wxStrcmp(pDbConfig->Dsn, pList->Dsn))) // Found a free connection
+ (!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))
+ if (!wxStrcmp(pDbConfig->GetDsn(), pList->Dsn) &&
+ !wxStrcmp(pDbConfig->GetUserID(), pList->Uid) &&
+ !wxStrcmp(pDbConfig->GetPassword(), pList->AuthStr))
matchingDbConnection = pList->PtrDb;
}
// Initialize new node in the linked list
pList->PtrNext = 0;
pList->Free = FALSE;
- pList->Dsn = pDbConfig->Dsn;
- pList->Uid = pDbConfig->Uid;
- pList->AuthStr = pDbConfig->AuthStr;
+ pList->Dsn = pDbConfig->GetDsn();
+ pList->Uid = pDbConfig->GetUserID();
+ pList->AuthStr = pDbConfig->GetPassword();
- pList->PtrDb = new wxDb(pDbConfig->Henv,FwdOnlyCursors);
+ pList->PtrDb = new wxDb(pDbConfig->GetHenv(), FwdOnlyCursors);
bool opened = FALSE;
if (!matchingDbConnection)
- opened = pList->PtrDb->Open(pDbConfig->Dsn, pDbConfig->Uid, pDbConfig->AuthStr);
+ opened = pList->PtrDb->Open(pDbConfig->GetDsn(), pDbConfig->GetUserID(), pDbConfig->GetPassword());
else
opened = pList->PtrDb->Open(matchingDbConnection);
// Connect to the datasource
if (opened)
{
+ pList->PtrDb->setCached(TRUE); // Prevent a user from deleting a cached connection
pList->PtrDb->SetSqlLogging(SQLLOGstate,SQLLOGfn,TRUE);
return(pList->PtrDb);
}
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
}
} // wxDbConnectionsInUse()
+
+/********** wxDbLogExtendedErrorMsg() **********/
+// DEBUG ONLY function
+const wxChar WXDLLEXPORT *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)
{