///////////////////////////////////////////////////////////////////////////////
-// Name: db.cpp
+// Name: src/common/db.cpp
// Purpose: Implementation of the wxDb class. The wxDb class represents a connection
// to an ODBC data source. The wxDb class allows operations on the data
// source such as opening and closing the data source.
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
-/*
-// SYNOPSIS START
-// SYNOPSIS STOP
-*/
-#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
- #pragma implementation "db.h"
-#endif
-
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
-#ifdef DBDEBUG_CONSOLE
- #include "wx/ioswrap.h"
-#endif
+#if wxUSE_ODBC
#ifndef WX_PRECOMP
- #include "wx/string.h"
#include "wx/object.h"
#include "wx/list.h"
+ #include "wx/string.h"
#include "wx/utils.h"
#include "wx/log.h"
+ #include "wx/app.h"
+#endif
+
+#ifdef DBDEBUG_CONSOLE
+ #include "wx/ioswrap.h"
#endif
+
#include "wx/filefn.h"
#include "wx/wxchar.h"
-#if wxUSE_ODBC
-
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "wx/db.h"
+// FIXME-UTF8: get rid of this after switching to Unicode-only builds:
+#if wxUSE_UNICODE
+ #define WXSQLCAST(s) ((SQLTCHAR FAR *)(wchar_t*)(s).wchar_str())
+#else
+ #define WXSQLCAST(s) ((SQLTCHAR FAR *)(char*)(s).char_str())
+#endif
+
// DLL options compatibility check:
-#include "wx/app.h"
WX_CHECK_BUILD_OPTIONS("wxODBC")
WXDLLIMPEXP_DATA_ODBC(wxDbList*) PtrBegDbList = 0;
wxChar const *SQL_CATALOG_FILENAME = wxT("catalog.txt");
#ifdef __WXDEBUG__
+ #include "wx/thread.h"
+
extern wxList TablesInUse;
+ extern wxCriticalSection csTablesInUse;
#endif
// SQL Log defaults to be used by GetDbConnection
// Initialize the ODBC Environment for Database Operations
if (SQLAllocEnv(&Henv) != SQL_SUCCESS)
{
- wxLogDebug(wxT("A problem occured while trying to get a connection to the data source"));
+ wxLogDebug(wxT("A problem occurred while trying to get a connection to the data source"));
return false;
}
void wxDbConnectInf::SetDsn(const wxString &dsn)
{
- wxASSERT(dsn.Length() < sizeof(Dsn));
+ wxASSERT(dsn.length() < WXSIZEOF(Dsn));
- wxStrncpy(Dsn, dsn, sizeof(Dsn)-1);
- Dsn[sizeof(Dsn)-1] = 0; // Prevent buffer overrun
+ wxStrncpy(Dsn, dsn, WXSIZEOF(Dsn)-1);
+ Dsn[WXSIZEOF(Dsn)-1] = 0; // Prevent buffer overrun
} // wxDbConnectInf::SetDsn()
void wxDbConnectInf::SetUserID(const wxString &uid)
{
- wxASSERT(uid.Length() < sizeof(Uid));
- wxStrncpy(Uid, uid, sizeof(Uid)-1);
- Uid[sizeof(Uid)-1] = 0; // Prevent buffer overrun
+ wxASSERT(uid.length() < WXSIZEOF(Uid));
+ wxStrncpy(Uid, uid, WXSIZEOF(Uid)-1);
+ Uid[WXSIZEOF(Uid)-1] = 0; // Prevent buffer overrun
} // wxDbConnectInf::SetUserID()
void wxDbConnectInf::SetPassword(const wxString &password)
{
- wxASSERT(password.Length() < sizeof(AuthStr));
+ wxASSERT(password.length() < WXSIZEOF(AuthStr));
- wxStrncpy(AuthStr, password, sizeof(AuthStr)-1);
- AuthStr[sizeof(AuthStr)-1] = 0; // Prevent buffer overrun
+ wxStrncpy(AuthStr, password, WXSIZEOF(AuthStr)-1);
+ AuthStr[WXSIZEOF(AuthStr)-1] = 0; // Prevent buffer overrun
} // wxDbConnectInf::SetPassword()
void wxDbConnectInf::SetConnectionStr(const wxString &connectStr)
{
- wxASSERT(connectStr.Length() < sizeof(ConnectionStr));
+ wxASSERT(connectStr.length() < WXSIZEOF(ConnectionStr));
useConnectionStr = wxStrlen(connectStr) > 0;
- wxStrncpy(ConnectionStr, connectStr, sizeof(ConnectionStr)-1);
- ConnectionStr[sizeof(ConnectionStr)-1] = 0; // Prevent buffer overrun
+ wxStrncpy(ConnectionStr, connectStr, WXSIZEOF(ConnectionStr)-1);
+ ConnectionStr[WXSIZEOF(ConnectionStr)-1] = 0; // Prevent buffer overrun
} // wxDbConnectInf::SetConnectionStr()
if ((i_sqlDataType == SQL_VARCHAR)
#if wxUSE_UNICODE
#if defined(SQL_WCHAR)
- || (i_sqlDataType == SQL_WCHAR)
+ || (i_sqlDataType == SQL_WCHAR)
#endif
#if defined(SQL_WVARCHAR)
|| (i_sqlDataType == SQL_WVARCHAR)
case DB_DATA_TYPE_FLOAT:
if (decimalDigits == 0)
decimalDigits = 2;
- tempStr = wxT("%");
- tempStr.Printf(wxT("%s%d.%d"), tempStr.c_str(),columnLength, decimalDigits);
+ tempStr.Printf(wxT("%%%d.%d"), columnLength, decimalDigits);
s_Field.Printf(wxT("%sf"), tempStr.c_str());
break;
case DB_DATA_TYPE_DATE:
typeInfBlob.CaseSensitive = 0;
typeInfBlob.MaximumScale = 0;
+ typeInfMemo.TypeName.Empty();
+ typeInfMemo.FsqlType = 0;
+ typeInfMemo.Precision = 0;
+ typeInfMemo.CaseSensitive = 0;
+ typeInfMemo.MaximumScale = 0;
+
// Error reporting is turned OFF by default
silent = true;
// immediately, as the value is not good after
// this function has left scope.
//
-const wxChar *wxDb::convertUserID(const wxChar *userID, wxString &UserID)
+void wxDb::convertUserID(const wxChar *userID, wxString &UserID)
{
if (userID)
{
|| Dbms() == dbmsXBASE_SEQUITER )
UserID.Empty();
- // Oracle user names may only be in uppercase, so force
- // the name to uppercase
- if (Dbms() == dbmsORACLE)
+ // Some databases require user names to be specified in uppercase,
+ // so force the name to uppercase
+ if ((Dbms() == dbmsORACLE) ||
+ (Dbms() == dbmsMAXDB))
UserID = UserID.Upper();
-
- return UserID.c_str();
} // wxDb::convertUserID()
SQL_VARBINARY
};
+ // These are the possible SQL types we check for use agains the datasource we are connected
+ // to for the purpose of determining which data type to use for the MEMO column types
+ // (a type which allow to store large strings; like VARCHAR just with a bigger precision)
+ //
+ // NOTE: The first type in this enumeration that is determined to be supported by the
+ // datasource/driver is the one that will be used.
+ SWORD PossibleSqlMemoTypes[] = {
+ SQL_LONGVARCHAR,
+ };
+
// Query the data source regarding data type information
else if (failOnDataTypeUnsupported)
return false;
+ // --------------- MEMO ---------------
+ for (iIndex = 0; iIndex < WXSIZEOF(PossibleSqlMemoTypes) &&
+ !getDataTypeInfo(PossibleSqlMemoTypes[iIndex], typeInfMemo); ++iIndex)
+ {}
+
+ if (iIndex < WXSIZEOF(PossibleSqlMemoTypes))
+ typeInfMemo.FsqlType = PossibleSqlMemoTypes[iIndex];
+ else if (failOnDataTypeUnsupported)
+ return false;
+
return true;
} // wxDb::determineDataTypes
cout << wxT("FLOAT DATA TYPE: ") << typeInfFloat.TypeName << endl;
cout << wxT("DATE DATA TYPE: ") << typeInfDate.TypeName << endl;
cout << wxT("BLOB DATA TYPE: ") << typeInfBlob.TypeName << endl;
+ cout << wxT("MEMO DATA TYPE: ") << typeInfMemo.TypeName << endl;
cout << endl;
#endif
bool wxDb::Open(const wxString& inConnectStr, bool failOnDataTypeUnsupported)
{
- wxASSERT(inConnectStr.Length());
- dsn = wxT("");
- uid = wxT("");
- authStr = wxT("");
+ wxASSERT(inConnectStr.length());
+ return Open(inConnectStr, NULL, failOnDataTypeUnsupported);
+}
+
+bool wxDb::Open(const wxString& inConnectStr, SQLHWND parentWnd, bool failOnDataTypeUnsupported)
+{
+ dsn = wxEmptyString;
+ uid = wxEmptyString;
+ authStr = wxEmptyString;
RETCODE retcode;
inConnectionStr = inConnectStr;
- retcode = SQLDriverConnect(hdbc, NULL, (SQLTCHAR FAR *)inConnectionStr.c_str(),
- (SWORD)inConnectionStr.Length(), (SQLTCHAR FAR *)outConnectBuffer,
- sizeof(outConnectBuffer), &outConnectBufferLen, SQL_DRIVER_COMPLETE );
+ retcode = SQLDriverConnect(hdbc, parentWnd, WXSQLCAST(inConnectionStr),
+ (SWORD)inConnectionStr.length(), (SQLTCHAR FAR *)outConnectBuffer,
+ WXSIZEOF(outConnectBuffer), &outConnectBufferLen, SQL_DRIVER_COMPLETE );
if ((retcode != SQL_SUCCESS) &&
(retcode != SQL_SUCCESS_WITH_INFO))
/********** wxDb::Open() **********/
bool wxDb::Open(const wxString &Dsn, const wxString &Uid, const wxString &AuthStr, bool failOnDataTypeUnsupported)
{
- wxASSERT(Dsn.Length());
+ wxASSERT(!Dsn.empty());
dsn = Dsn;
uid = Uid;
authStr = AuthStr;
- inConnectionStr = wxT("");
- outConnectionStr = wxT("");
+ inConnectionStr = wxEmptyString;
+ outConnectionStr = wxEmptyString;
RETCODE retcode;
}
// Connect to the data source
- retcode = SQLConnect(hdbc, (SQLTCHAR FAR *) dsn.c_str(), SQL_NTS,
- (SQLTCHAR FAR *) uid.c_str(), SQL_NTS,
- (SQLTCHAR FAR *) authStr.c_str(), SQL_NTS);
+ retcode = SQLConnect(hdbc,
+ WXSQLCAST(dsn), SQL_NTS,
+ WXSQLCAST(uid), SQL_NTS,
+ WXSQLCAST(authStr), SQL_NTS);
if ((retcode != SQL_SUCCESS) &&
(retcode != SQL_SUCCESS_WITH_INFO))
// Use the connection string if one is present
if (dbConnectInf->UseConnectionStr())
- return Open(GetConnectionInStr(), failOnDataTypeUnsupported);
+ return Open(dbConnectInf->GetConnectionStr(), failOnDataTypeUnsupported);
else
return Open(dbConnectInf->GetDsn(), dbConnectInf->GetUserID(),
dbConnectInf->GetPassword(), failOnDataTypeUnsupported);
inConnectionStr = copyDb->GetConnectionInStr();
- retcode = SQLDriverConnect(hdbc, NULL, (SQLTCHAR FAR *)inConnectionStr.c_str(),
- (SWORD)inConnectionStr.Length(), (SQLTCHAR FAR *)outConnectBuffer,
- sizeof(outConnectBuffer), &outConnectBufferLen, SQL_DRIVER_COMPLETE);
+ retcode = SQLDriverConnect(hdbc, NULL, WXSQLCAST(inConnectionStr),
+ (SWORD)inConnectionStr.length(), (SQLTCHAR FAR *)outConnectBuffer,
+ WXSIZEOF(outConnectBuffer), &outConnectBufferLen, SQL_DRIVER_COMPLETE);
if ((retcode != SQL_SUCCESS) &&
(retcode != SQL_SUCCESS_WITH_INFO))
else
{
// Connect to the data source
- retcode = SQLConnect(hdbc, (SQLTCHAR FAR *) dsn.c_str(), SQL_NTS,
- (SQLTCHAR FAR *) uid.c_str(), SQL_NTS,
- (SQLTCHAR FAR *) authStr.c_str(), SQL_NTS);
+ retcode = SQLConnect(hdbc,
+ WXSQLCAST(dsn), SQL_NTS,
+ WXSQLCAST(uid), SQL_NTS,
+ WXSQLCAST(authStr), SQL_NTS);
}
if ((retcode != SQL_SUCCESS) &&
typeInfBlob.CaseSensitive = copyDb->typeInfBlob.CaseSensitive;
typeInfBlob.MaximumScale = copyDb->typeInfBlob.MaximumScale;
+ // Memo
+ typeInfMemo.FsqlType = copyDb->typeInfMemo.FsqlType;
+ typeInfMemo.TypeName = copyDb->typeInfMemo.TypeName;
+ typeInfMemo.Precision = copyDb->typeInfMemo.Precision;
+ typeInfMemo.CaseSensitive = copyDb->typeInfMemo.CaseSensitive;
+ typeInfMemo.MaximumScale = copyDb->typeInfMemo.MaximumScale;
+
#ifdef DBDEBUG_CONSOLE
cout << wxT("VARCHAR DATA TYPE: ") << typeInfVarchar.TypeName << endl;
cout << wxT("INTEGER DATA TYPE: ") << typeInfInteger.TypeName << endl;
cout << wxT("FLOAT DATA TYPE: ") << typeInfFloat.TypeName << endl;
cout << wxT("DATE DATA TYPE: ") << typeInfDate.TypeName << endl;
cout << wxT("BLOB DATA TYPE: ") << typeInfBlob.TypeName << endl;
+ cout << wxT("MEMO DATA TYPE: ") << typeInfMemo.TypeName << endl;
cout << endl;
#endif
* wxDbSqlTypeInfo is a structure that is filled in with data type information,
*/
RETCODE retcode;
- SDWORD cbRet;
+ SQLLEN cbRet;
// Get information about the data type specified
if (SQLGetTypeInfo(hstmt, fSqlType) != SQL_SUCCESS)
wxASSERT(nTables == 0);
#ifdef __WXDEBUG__
- wxTablesInUse *tiu;
- wxList::compatibility_iterator pNode;
- pNode = TablesInUse.GetFirst();
- wxString s,s2;
- while (pNode)
{
- tiu = (wxTablesInUse *)pNode->GetData();
- if (tiu->pDb == this)
+ wxCriticalSectionLocker lock(csTablesInUse);
+ wxTablesInUse *tiu;
+ wxList::compatibility_iterator pNode;
+ pNode = TablesInUse.GetFirst();
+ wxString s,s2;
+ while (pNode)
{
- s.Printf(wxT("(%-20s) tableID:[%6lu] pDb:[%p]"), tiu->tableName,tiu->tableID,tiu->pDb);
- s2.Printf(wxT("Orphaned table found using pDb:[%p]"),this);
- wxLogDebug(s.c_str(),s2.c_str());
+ tiu = (wxTablesInUse *)pNode->GetData();
+ if (tiu->pDb == this)
+ {
+ s.Printf(wxT("(%-20s) tableID:[%6lu] pDb:[%p]"),
+ tiu->tableName, tiu->tableID, wx_static_cast(void*, tiu->pDb));
+ s2.Printf(wxT("Orphaned table found using pDb:[%p]"), wx_static_cast(void*, this));
+ wxLogDebug(s.c_str(),s2.c_str());
+ }
+ pNode = pNode->GetNext();
}
- pNode = pNode->GetNext();
}
#endif
/*
* This function is called internally whenever an error condition prevents the user's
* request from being executed. This function will query the datasource as to the
- * actual error(s) that just occured on the previous request of the datasource.
+ * actual error(s) that just occurred on the previous request of the datasource.
*
* The function will retrieve each error condition from the datasource and
* Printf the codes/text values into a string which it then logs via logError().
* If in DBDEBUG_CONSOLE mode, the constructed string will be displayed in the console
* window and program execution will be paused until the user presses a key.
*
- * This function always returns a false, so that functions which call this function
+ * This function always returns false, so that functions which call this function
* can have a line like "return (DispAllErrors(henv, hdbc));" to indicate the failure
- * of the users request, so that the calling code can then process the error msg log
+ * of the user's request, so that the calling code can then process the error message log.
*/
{
wxString odbcErrMsg;
-#ifdef __VMS
- while (SQLError(aHenv, aHdbc, aHstmt, (SQLTCHAR FAR *) sqlState, (SQLINTEGER *) &nativeError, (SQLTCHAR FAR *) errorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &cbErrorMsg) == SQL_SUCCESS)
-#else
- while (SQLError(aHenv, aHdbc, aHstmt, (SQLTCHAR FAR *) sqlState, (long*) &nativeError, (SQLTCHAR FAR *) errorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &cbErrorMsg) == SQL_SUCCESS)
-#endif
+ while (SQLError(aHenv, aHdbc, aHstmt, (SQLTCHAR FAR *) sqlState, &nativeError, (SQLTCHAR FAR *) errorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &cbErrorMsg) == SQL_SUCCESS)
{
- odbcErrMsg.Printf(wxT("SQL State = %s\nNative Error Code = %li\nError Message = %s\n"), sqlState, nativeError, errorMsg);
+ odbcErrMsg.Printf(wxT("SQL State = %s\nNative Error Code = %li\nError Message = %s\n"),
+ sqlState, (long)nativeError, errorMsg);
logError(odbcErrMsg, sqlState);
if (!silent)
{
/********** wxDb::GetNextError() **********/
bool wxDb::GetNextError(HENV aHenv, HDBC aHdbc, HSTMT aHstmt)
{
-#ifdef __VMS
- if (SQLError(aHenv, aHdbc, aHstmt, (SQLTCHAR FAR *) sqlState, (SQLINTEGER *) &nativeError, (SQLTCHAR FAR *) errorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &cbErrorMsg) == SQL_SUCCESS)
-#else
- if (SQLError(aHenv, aHdbc, aHstmt, (SQLTCHAR FAR *) sqlState, (long*) &nativeError, (SQLTCHAR FAR *) errorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &cbErrorMsg) == SQL_SUCCESS)
-#endif
+ if (SQLError(aHenv, aHdbc, aHstmt, (SQLTCHAR FAR *) sqlState, &nativeError, (SQLTCHAR FAR *) errorMsg, SQL_MAX_MESSAGE_LENGTH - 1, &cbErrorMsg) == SQL_SUCCESS)
return true;
else
return false;
{
wxString odbcErrMsg;
- odbcErrMsg.Printf(wxT("SQL State = %s\nNative Error Code = %li\nError Message = %s\n"), sqlState, nativeError, errorMsg);
+ odbcErrMsg.Printf(wxT("SQL State = %s\nNative Error Code = %li\nError Message = %s\n"),
+ sqlState, (long)nativeError, errorMsg);
logError(odbcErrMsg, sqlState);
if (silent)
/********** wxDb::logError() **********/
void wxDb::logError(const wxString &errMsg, const wxString &SQLState)
{
- wxASSERT(errMsg.Length());
+ wxASSERT(errMsg.length());
static int pLast = -1;
int dbStatus;
wxStrncpy(errorList[pLast], errMsg, DB_MAX_ERROR_MSG_LEN);
errorList[pLast][DB_MAX_ERROR_MSG_LEN] = 0;
- if (SQLState.Length())
+ if (SQLState.length())
if ((dbStatus = TranslateSqlState(SQLState)) != DB_ERR_FUNCTION_SEQUENCE_ERROR)
DB_STATUS = dbStatus;
sqlStmt = wxT("CREATE VIEW ");
sqlStmt += viewName;
- if (colList.Length())
+ if (colList.length())
{
sqlStmt += wxT(" (");
sqlStmt += colList;
cout << endl << sqlStmt.c_str() << endl;
#endif
- if (SQLExecDirect(hstmt, (SQLTCHAR FAR *) sqlStmt.c_str(), SQL_NTS) != SQL_SUCCESS)
+ if (SQLExecDirect(hstmt, WXSQLCAST(sqlStmt), SQL_NTS) != SQL_SUCCESS)
{
// Check for "Base table not found" error and ignore
GetNextError(henv, hdbc, hstmt);
SQLFreeStmt(hstmt, SQL_CLOSE);
- retcode = SQLExecDirect(hstmt, (SQLTCHAR FAR *) pSqlStmt.c_str(), SQL_NTS);
+ retcode = SQLExecDirect(hstmt, WXSQLCAST(pSqlStmt), SQL_NTS);
if (retcode == SQL_SUCCESS ||
(Dbms() == dbmsDB2 && (retcode == SQL_SUCCESS_WITH_INFO || retcode == SQL_NO_DATA_FOUND)))
{
short colNum;
wxChar name[DB_MAX_COLUMN_NAME_LEN+1];
SWORD Sword;
- SDWORD Sdword;
+ SQLLEN Sqllen;
wxDbColInf* pColInf = new wxDbColInf[noCols];
// Fill in column information (name, datatype)
{
if (SQLColAttributes(hstmt, (UWORD)(colNum+1), SQL_COLUMN_NAME,
name, sizeof(name),
- &Sword, &Sdword) != SQL_SUCCESS)
+ &Sword, &Sqllen) != SQL_SUCCESS)
{
DispAllErrors(henv, hdbc, hstmt);
delete[] pColInf;
pColInf[colNum].colName[DB_MAX_COLUMN_NAME_LEN] = 0; // Prevent buffer overrun
if (SQLColAttributes(hstmt, (UWORD)(colNum+1), SQL_COLUMN_TYPE,
- NULL, 0, &Sword, &Sdword) != SQL_SUCCESS)
+ NULL, 0, &Sword, &Sqllen) != SQL_SUCCESS)
{
DispAllErrors(henv, hdbc, hstmt);
delete[] pColInf;
return false;
}
- switch (Sdword)
+ switch (Sqllen)
{
#if wxUSE_UNICODE
#if defined(SQL_WCHAR)
case SQL_CHAR:
pColInf[colNum].dbDataType = DB_DATA_TYPE_VARCHAR;
break;
+ case SQL_LONGVARCHAR:
+ pColInf[colNum].dbDataType = DB_DATA_TYPE_MEMO;
+ break;
case SQL_TINYINT:
case SQL_SMALLINT:
case SQL_INTEGER:
#ifdef __WXDEBUG__
default:
wxString errMsg;
- errMsg.Printf(wxT("SQL Data type %ld currently not supported by wxWidgets"), (long)Sdword);
+ errMsg.Printf(wxT("SQL Data type %ld currently not supported by wxWidgets"), (long)Sqllen);
wxLogDebug(errMsg,wxT("ODBC DEBUG MESSAGE"));
#endif
}
/********** wxDb::GetData() **********/
-bool wxDb::GetData(UWORD colNo, SWORD cType, PTR pData, SDWORD maxLen, SDWORD FAR *cbReturned)
+bool wxDb::GetData(UWORD colNo, SWORD cType, PTR pData, SDWORD maxLen, SQLLEN FAR *cbReturned)
{
wxASSERT(pData);
wxASSERT(cbReturned);
wxChar szPkCol[DB_MAX_COLUMN_NAME_LEN+1]; /* Primary key column */
wxChar szFkCol[DB_MAX_COLUMN_NAME_LEN+1]; /* Foreign key column */
SQLRETURN retcode;
- SDWORD cb;
+ SQLLEN cb;
SWORD i;
wxString tempStr;
/*
retcode = SQLPrimaryKeys(hstmt,
NULL, 0, /* Catalog name */
NULL, 0, /* Schema name */
- (SQLTCHAR FAR *) tableName.c_str(), SQL_NTS); /* Table name */
+ WXSQLCAST(tableName), SQL_NTS); /* Table name */
/*---------------------------------------------------------------------*/
/* Fetch and display the result set. This will be a list of the */
retcode = SQLForeignKeys(hstmt,
NULL, 0, /* Primary catalog */
NULL, 0, /* Primary schema */
- (SQLTCHAR FAR *)tableName.c_str(), SQL_NTS,/* Primary table */
+ WXSQLCAST(tableName), SQL_NTS,/* Primary table */
NULL, 0, /* Foreign catalog */
NULL, 0, /* Foreign schema */
NULL, 0); /* Foreign table */
GetData( 5, SQL_C_SSHORT, &iKeySeq, 0, &cb);
GetData( 7, SQL_C_WXCHAR, szFkTable, DB_MAX_TABLE_NAME_LEN+1, &cb);
GetData( 8, SQL_C_WXCHAR, szFkCol, DB_MAX_COLUMN_NAME_LEN+1, &cb);
- tempStr.Printf(wxT("%s[%s] "),tempStr.c_str(),szFkTable); // [ ] in case there is a blank in the Table name
+ tempStr << _T('[') << szFkTable << _T(']'); // [ ] in case there is a blank in the Table name
} // if
} // while
NULL, 0, /* Primary table */
NULL, 0, /* Foreign catalog */
NULL, 0, /* Foreign schema */
- (SQLTCHAR *)tableName.c_str(), SQL_NTS);/* Foreign table */
+ WXSQLCAST(tableName), SQL_NTS);/* Foreign table */
/*---------------------------------------------------------------------*/
/* Fetch and display the result set. This will be all of the */
* 1) The last array element of the tableName[] argument must be zero (null).
* This is how the end of the array is detected.
* 2) This function returns an array of wxDbColInf structures. If no columns
- * were found, or an error occured, this pointer will be zero (null). THE
+ * were found, or an error occurred, this pointer will be zero (null). THE
* CALLING FUNCTION IS RESPONSIBLE FOR DELETING THE MEMORY RETURNED WHEN IT
* IS FINISHED WITH IT. i.e.
*
wxDbColInf *colInf = 0;
RETCODE retcode;
- SDWORD cb;
+ SQLLEN cb;
wxString TableName;
{
retcode = SQLColumns(hstmt,
NULL, 0, // All qualifiers
- (SQLTCHAR *) UserID.c_str(), SQL_NTS, // Owner
- (SQLTCHAR *) TableName.c_str(), SQL_NTS,
+ WXSQLCAST(UserID), SQL_NTS, // Owner
+ WXSQLCAST(TableName), SQL_NTS,
NULL, 0); // All columns
}
else
retcode = SQLColumns(hstmt,
NULL, 0, // All qualifiers
NULL, 0, // Owner
- (SQLTCHAR *) TableName.c_str(), SQL_NTS,
+ WXSQLCAST(TableName), SQL_NTS,
NULL, 0); // All columns
}
if (retcode != SQL_SUCCESS)
- { // Error occured, abort
+ { // Error occurred, abort
DispAllErrors(henv, hdbc, hstmt);
if (colInf)
delete [] colInf;
}
}
if (retcode != SQL_NO_DATA_FOUND)
- { // Error occured, abort
+ { // Error occurred, abort
DispAllErrors(henv, hdbc, hstmt);
if (colInf)
delete [] colInf;
wxDbColInf *colInf = 0;
RETCODE retcode;
- SDWORD cb;
+ SQLLEN cb;
wxString TableName;
{
retcode = SQLColumns(hstmt,
NULL, 0, // All qualifiers
- (SQLTCHAR *) UserID.c_str(), SQL_NTS, // Owner
- (SQLTCHAR *) TableName.c_str(), SQL_NTS,
+ WXSQLCAST(UserID), SQL_NTS, // Owner
+ WXSQLCAST(TableName), SQL_NTS,
NULL, 0); // All columns
}
else
retcode = SQLColumns(hstmt,
NULL, 0, // All qualifiers
NULL, 0, // Owner
- (SQLTCHAR *) TableName.c_str(), SQL_NTS,
+ WXSQLCAST(TableName), SQL_NTS,
NULL, 0); // All columns
}
if (retcode != SQL_SUCCESS)
- { // Error occured, abort
+ { // Error occurred, abort
DispAllErrors(henv, hdbc, hstmt);
if (colInf)
delete [] colInf;
}
}
if (retcode != SQL_NO_DATA_FOUND)
- { // Error occured, abort
+ { // Error occurred, abort
DispAllErrors(henv, hdbc, hstmt);
if (colInf)
delete [] colInf;
/*
BJO 20000503
These are tentative new GetColumns members which should be more database
- independant and which always returns the columns in the order they were
+ independent and which always returns the columns in the order they were
created.
- The first one (wxDbColInf *wxDb::GetColumns(wxChar *tableName[], const
NULL, 0); // All columns
}
if (retcode != SQL_SUCCESS)
- { // Error occured, abort
+ { // Error occurred, abort
DispAllErrors(henv, hdbc, hstmt);
if (colInf)
delete [] colInf;
case SQL_CHAR:
colInf[colNo].dbDataType = DB_DATA_TYPE_VARCHAR;
break;
+ case SQL_LONGVARCHAR:
+ colInf[colNo].dbDataType = DB_DATA_TYPE_MEMO;
+ break;
case SQL_TINYINT:
case SQL_SMALLINT:
case SQL_INTEGER:
}
}
if (retcode != SQL_NO_DATA_FOUND)
- { // Error occured, abort
+ { // Error occurred, abort
DispAllErrors(henv, hdbc, hstmt);
if (colInf)
delete [] colInf;
{
retcode = SQLColumns(hstmt,
NULL, 0, // All qualifiers
- (SQLTCHAR *) UserID.c_str(), SQL_NTS, // Owner
- (SQLTCHAR *) TableName.c_str(), SQL_NTS,
+ WXSQLCAST(UserID), SQL_NTS, // Owner
+ WXSQLCAST(TableName), SQL_NTS,
NULL, 0); // All columns
}
else
retcode = SQLColumns(hstmt,
NULL, 0, // All qualifiers
NULL, 0, // Owner
- (SQLTCHAR *) TableName.c_str(), SQL_NTS,
+ WXSQLCAST(TableName), SQL_NTS,
NULL, 0); // All columns
}
if (retcode != SQL_SUCCESS)
- { // Error occured, abort
+ { // Error occurred, abort
DispAllErrors(henv, hdbc, hstmt);
SQLFreeStmt(hstmt, SQL_CLOSE);
return(-1);
noCols++;
if (retcode != SQL_NO_DATA_FOUND)
- { // Error occured, abort
+ { // Error occurred, abort
DispAllErrors(henv, hdbc, hstmt);
SQLFreeStmt(hstmt, SQL_CLOSE);
return(-1);
* -- : uses SQLTables and fills pTableInf; ------
* -- : pColInf is set to NULL and numCols to 0; ------
* -- : returns pDbInf (wxDbInf) ------
- * -- - if unsuccesfull (pDbInf == NULL) ------
+ * -- - if unsuccessful (pDbInf == NULL) ------
* -- : pColInf can be filled with GetColumns(..); ------
* -- : numCols can be filled with GetColumnCount(..); ------
* ---------------------------------------------------------------------
int noTab = 0; // Counter while filling table entries
int pass;
RETCODE retcode;
- SDWORD cb;
+ SQLLEN cb;
wxString tblNameSave;
wxString UserID;
{
retcode = SQLTables(hstmt,
NULL, 0, // All qualifiers
- (SQLTCHAR *) UserID.c_str(), SQL_NTS, // User specified
+ WXSQLCAST(UserID), SQL_NTS, // User specified
NULL, 0, // All tables
NULL, 0); // All columns
}
* to avoid undesired unbinding of columns.
*/
{
- wxASSERT(fileName.Length());
+ wxASSERT(fileName.length());
RETCODE retcode;
- SDWORD cb;
+ SQLLEN cb;
wxChar tblName[DB_MAX_TABLE_NAME_LEN+1];
wxString tblNameSave;
wxChar colName[DB_MAX_COLUMN_NAME_LEN+1];
{
retcode = SQLColumns(hstmt,
NULL, 0, // All qualifiers
- (SQLTCHAR *) UserID.c_str(), SQL_NTS, // User specified
+ WXSQLCAST(UserID), SQL_NTS, // User specified
NULL, 0, // All tables
NULL, 0); // All columns
}
* userID != "" ... UserID set equal to 'userID'
*/
{
- wxASSERT(tableName.Length());
+ wxASSERT(tableName.length());
wxString TableName;
if (Dbms() == dbmsDBASE)
{
wxString dbName;
- if (tablePath.Length())
+ if (tablePath.length())
dbName.Printf(wxT("%s/%s.dbf"), tablePath.c_str(), tableName.c_str());
else
dbName.Printf(wxT("%s.dbf"), tableName.c_str());
{
retcode = SQLTables(hstmt,
NULL, 0, // All qualifiers
- (SQLTCHAR *) UserID.c_str(), SQL_NTS, // Only tables owned by this user
- (SQLTCHAR FAR *)TableName.c_str(), SQL_NTS,
+ WXSQLCAST(UserID), SQL_NTS, // Only tables owned by this user
+ WXSQLCAST(TableName), SQL_NTS,
NULL, 0); // All table types
}
else
retcode = SQLTables(hstmt,
NULL, 0, // All qualifiers
NULL, 0, // All owners
- (SQLTCHAR FAR *)TableName.c_str(), SQL_NTS,
+ WXSQLCAST(TableName), SQL_NTS,
NULL, 0); // All table types
}
if (retcode != SQL_SUCCESS)
bool wxDb::TablePrivileges(const wxString &tableName, const wxString &priv, const wxChar *userID,
const wxChar *schema, const wxString &WXUNUSED(tablePath))
{
- wxASSERT(tableName.Length());
+ wxASSERT(tableName.length());
wxDbTablePrivilegeInfo result;
- SDWORD cbRetVal;
+ SQLLEN cbRetVal;
RETCODE retcode;
// We probably need to be able to dynamically set this based on
{
retcode = SQLTablePrivileges(hstmt,
NULL, 0, // Catalog
- (SQLTCHAR FAR *)Schema.c_str(), SQL_NTS, // Schema
- (SQLTCHAR FAR *)TableName.c_str(), SQL_NTS);
+ WXSQLCAST(Schema), SQL_NTS, // Schema
+ WXSQLCAST(TableName), SQL_NTS);
}
else
{
retcode = SQLTablePrivileges(hstmt,
NULL, 0, // Catalog
NULL, 0, // Schema
- (SQLTCHAR FAR *)TableName.c_str(), SQL_NTS);
+ WXSQLCAST(TableName), SQL_NTS);
}
#ifdef DBDEBUG_CONSOLE
bool wxDb::SetSqlLogging(wxDbSqlLogState state, const wxString &filename, bool append)
{
wxASSERT(state == sqlLogON || state == sqlLogOFF);
- wxASSERT(state == sqlLogOFF || filename.Length());
+ wxASSERT(state == sqlLogOFF || filename.length());
if (state == sqlLogON)
{
/********** wxDb::WriteSqlLog() **********/
bool wxDb::WriteSqlLog(const wxString &logMsg)
{
- wxASSERT(logMsg.Length());
+ wxASSERT(logMsg.length());
if (fpSqlLog == 0 || sqlLogState == sqlLogOFF)
return false;
return((wxDBMS)(dbmsType = dbmsXBASE_SEQUITER));
if (!wxStricmp(baseName,wxT("MySQL")))
return((wxDBMS)(dbmsType = dbmsMY_SQL));
+ if (!wxStricmp(baseName,wxT("MaxDB")))
+ return((wxDBMS)(dbmsType = dbmsMAXDB));
baseName[3] = 0;
if (!wxStricmp(baseName,wxT("DB2")))
- return((wxDBMS)(dbmsType = dbmsDBASE));
+ return((wxDBMS)(dbmsType = dbmsDB2));
return((wxDBMS)(dbmsType = dbmsUNIDENTIFIED));
int dataType, ULONG columnLength,
const wxString &optionalParam)
{
- wxASSERT(tableName.Length());
- wxASSERT(columnName.Length());
+ wxASSERT(tableName.length());
+ wxASSERT(columnName.length());
wxASSERT((dataType == DB_DATA_TYPE_VARCHAR && columnLength > 0) ||
dataType != DB_DATA_TYPE_VARCHAR);
}
// for passing things like "NOT NULL"
- if (optionalParam.Length())
+ if (optionalParam.length())
{
sqlStmt += wxT(" ");
sqlStmt += optionalParam;
} // wxDb::ModifyColumn()
+/********** wxDb::EscapeSqlChars() **********/
+wxString wxDb::EscapeSqlChars(const wxString& valueOrig)
+{
+ wxString value(valueOrig);
+ switch (Dbms())
+ {
+ case dbmsACCESS:
+ // Access doesn't seem to care about backslashes, so only escape single quotes.
+ value.Replace(wxT("'"), wxT("''"));
+ break;
+
+ default:
+ // All the others are supposed to be the same for now, add special
+ // handling for them if necessary
+ value.Replace(wxT("\\"), wxT("\\\\"));
+ value.Replace(wxT("'"), wxT("\\'"));
+ break;
+ }
+
+ return value;
+} // wxDb::EscapeSqlChars()
+
/********** wxDbGetConnection() **********/
wxDb WXDLLIMPEXP_ODBC *wxDbGetConnection(wxDbConnectInf *pDbConfig, bool FwdOnlyCursors)
// embedded nulls in strings
setupStr.Printf(wxT("DSN=%s%cDescription=%s%cDefaultDir=%s%c"),dsn,2,description,2,defDir,2);
- // Replace the separator from above with the '\0' seperator needed
+ // Replace the separator from above with the '\0' separator needed
// by the SQLConfigDataSource() function
int k;
do
********************************************************************
*
* The following functions are all DEPRECATED and are included for
- * backward compatability reasons only
+ * backward compatibility reasons only
*
********************************************************************
********************************************************************/