X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/8907154c1a8a6882c6797d1f16393ddfb23e7f3a..d48687a0719620cc888072db31bb3814dea400ab:/src/common/dbtable.cpp diff --git a/src/common/dbtable.cpp b/src/common/dbtable.cpp index f32954f688..ac9981425e 100644 --- a/src/common/dbtable.cpp +++ b/src/common/dbtable.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Name: dbtable.cpp +// Name: src/common/dbtable.cpp // Purpose: Implementation of the wxDbTable class. // Author: Doug Card // Modified by: George Tasker @@ -11,36 +11,28 @@ // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// -/* -// SYNOPSIS START -// SYNOPSIS STOP -*/ - #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif -#ifdef DBDEBUG_CONSOLE -#if wxUSE_IOSTREAMH - #include -#else - #include -#endif - #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/crt.h" #endif -#include "wx/filefn.h" -#if wxUSE_ODBC +#ifdef DBDEBUG_CONSOLE + #include "wx/ioswrap.h" +#endif + +#include "wx/filefn.h" #include #include @@ -48,28 +40,27 @@ #include "wx/dbtable.h" -#ifdef __UNIX__ -// The HPUX preprocessor lines below were commented out on 8/20/97 -// because macros.h currently redefines DEBUG and is unneeded. -// # ifdef HPUX -// # include -// # endif -# ifdef LINUX -# include -# endif +// 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 ULONG lastTableID = 0; #ifdef __WXDEBUG__ + #include "wx/thread.h" + wxList TablesInUse; + wxCriticalSection csTablesInUse; #endif void csstrncpyt(wxChar *target, const wxChar *source, int n) { - while ( (*target++ = *source++) != '\0' && --n ) + while ( (*target++ = *source++) != '\0' && --n != 0 ) ; *target = '\0'; @@ -97,6 +88,7 @@ bool wxDbColDef::Initialize() DerivedCol = false; CbValue = 0; Null = false; + CbValueCol = 0; return true; } // wxDbColDef::Initialize() @@ -111,19 +103,6 @@ wxDbTable::wxDbTable(wxDb *pwxDb, const wxString &tblName, const UWORD numColumn } // wxDbTable::wxDbTable() -/***** DEPRECATED: use wxDbTable::wxDbTable() format above *****/ -#if WXWIN_COMPATIBILITY_2_4 -wxDbTable::wxDbTable(wxDb *pwxDb, const wxString &tblName, const UWORD numColumns, - const wxChar *qryTblName, bool qryOnly, const wxString &tblPath) -{ - wxString tempQryTblName; - tempQryTblName = qryTblName; - if (!initialize(pwxDb, tblName, numColumns, tempQryTblName, qryOnly, tblPath)) - cleanup(); -} // wxDbTable::wxDbTable() -#endif // WXWIN_COMPATIBILITY_2_4 - - /********** wxDbTable::~wxDbTable() **********/ wxDbTable::~wxDbTable() { @@ -159,7 +138,7 @@ bool wxDbTable::initialize(wxDb *pwxDb, const wxString &tblName, const UWORD num tableName.Empty(); queryTableName.Empty(); - wxASSERT(tblName.Length()); + wxASSERT(tblName.length()); wxASSERT(pDb); if (!pDb) @@ -171,12 +150,12 @@ bool wxDbTable::initialize(wxDb *pwxDb, const wxString &tblName, const UWORD num (pDb->Dbms() == dbmsINTERBASE)) tableName = tableName.Upper(); - if (tblPath.Length()) + if (tblPath.length()) tablePath = tblPath; // Table Path - used for dBase files else tablePath.Empty(); - if (qryTblName.Length()) // Name of the table/view to query + if (qryTblName.length()) // Name of the table/view to query queryTableName = qryTblName; else queryTableName = tblName; @@ -190,7 +169,8 @@ bool wxDbTable::initialize(wxDb *pwxDb, const wxString &tblName, const UWORD num wxString s; tableID = ++lastTableID; - s.Printf(wxT("wxDbTable constructor (%-20s) tableID:[%6lu] pDb:[%p]"), tblName.c_str(), tableID, pDb); + s.Printf(wxT("wxDbTable constructor (%-20s) tableID:[%6lu] pDb:[%p]"), + tblName.c_str(), tableID, wx_static_cast(void*, pDb)); #ifdef __WXDEBUG__ wxTablesInUse *tableInUse; @@ -198,7 +178,10 @@ bool wxDbTable::initialize(wxDb *pwxDb, const wxString &tblName, const UWORD num tableInUse->tableName = tblName; tableInUse->tableID = tableID; tableInUse->pDb = pDb; - TablesInUse.Append(tableInUse); + { + wxCriticalSectionLocker lock(csTablesInUse); + TablesInUse.Append(tableInUse); + } #endif pDb->WriteSqlLog(s); @@ -313,7 +296,8 @@ void wxDbTable::cleanup() wxString s; if (pDb) { - s.Printf(wxT("wxDbTable destructor (%-20s) tableID:[%6lu] pDb:[%p]"), tableName.c_str(), tableID, pDb); + s.Printf(wxT("wxDbTable destructor (%-20s) tableID:[%6lu] pDb:[%p]"), + tableName.c_str(), tableID, wx_static_cast(void*, pDb)); pDb->WriteSqlLog(s); } @@ -323,17 +307,20 @@ void wxDbTable::cleanup() bool found = false; wxList::compatibility_iterator pNode; - pNode = TablesInUse.GetFirst(); - while (pNode && !found) { - if (((wxTablesInUse *)pNode->GetData())->tableID == tableID) + wxCriticalSectionLocker lock(csTablesInUse); + pNode = TablesInUse.GetFirst(); + while (!found && pNode) { - found = true; - delete (wxTablesInUse *)pNode->GetData(); - TablesInUse.Erase(pNode); + if (((wxTablesInUse *)pNode->GetData())->tableID == tableID) + { + found = true; + delete (wxTablesInUse *)pNode->GetData(); + TablesInUse.Erase(pNode); + } + else + pNode = pNode->GetNext(); } - else - pNode = pNode->GetNext(); } if (!found) { @@ -413,6 +400,7 @@ void wxDbTable::setCbValueForColumn(int columnIndex) switch(colDefs[columnIndex].DbDataType) { case DB_DATA_TYPE_VARCHAR: + case DB_DATA_TYPE_MEMO: if (colDefs[columnIndex].Null) colDefs[columnIndex].CbValue = SQL_NULL_DATA; else @@ -484,6 +472,11 @@ bool wxDbTable::bindParams(bool forUpdate) precision = colDefs[i].SzDataObj; scale = 0; break; + case DB_DATA_TYPE_MEMO: + fSqlType = pDb->GetTypeInfMemo().FsqlType; + precision = colDefs[i].SzDataObj; + scale = 0; + break; case DB_DATA_TYPE_INTEGER: fSqlType = pDb->GetTypeInfInteger().FsqlType; precision = pDb->GetTypeInfInteger().Precision; @@ -556,21 +549,17 @@ bool wxDbTable::bindUpdateParams(void) /********** wxDbTable::bindCols() **********/ bool wxDbTable::bindCols(HSTMT cursor) { - static SQLLEN cb; - // Bind each column of the table to a memory address for fetching data UWORD i; for (i = 0; i < m_numCols; i++) { - cb = colDefs[i].CbValue; if (SQLBindCol(cursor, (UWORD)(i+1), colDefs[i].SqlCtype, (UCHAR*) colDefs[i].PtrDataObj, - colDefs[i].SzDataObj, &cb ) != SQL_SUCCESS) + colDefs[i].SzDataObj, &colDefs[i].CbValueCol ) != SQL_SUCCESS) return (pDb->DispAllErrors(henv, hdbc, cursor)); } // Completed successfully return true; - } // wxDbTable::bindCols() @@ -599,7 +588,7 @@ bool wxDbTable::getRec(UWORD fetchType) // of each column just read in. int i; for (i = 0; i < m_numCols; i++) - colDefs[i].Null = (colDefs[i].CbValue == SQL_NULL_DATA); + colDefs[i].Null = (colDefs[i].CbValueCol == SQL_NULL_DATA); } } else @@ -619,7 +608,7 @@ bool wxDbTable::getRec(UWORD fetchType) // of each column just read in. int i; for (i = 0; i < m_numCols; i++) - colDefs[i].Null = (colDefs[i].CbValue == SQL_NULL_DATA); + colDefs[i].Null = (colDefs[i].CbValueCol == SQL_NULL_DATA); } } @@ -635,7 +624,7 @@ bool wxDbTable::execDelete(const wxString &pSqlStmt) RETCODE retcode; // Execute the DELETE statement - retcode = SQLExecDirect(hstmtDelete, (SQLTCHAR FAR *) pSqlStmt.c_str(), SQL_NTS); + retcode = SQLExecDirect(hstmtDelete, WXSQLCAST(pSqlStmt), SQL_NTS); if (retcode == SQL_SUCCESS || retcode == SQL_NO_DATA_FOUND || @@ -657,7 +646,7 @@ bool wxDbTable::execUpdate(const wxString &pSqlStmt) RETCODE retcode; // Execute the UPDATE statement - retcode = SQLExecDirect(hstmtUpdate, (SQLTCHAR FAR *) pSqlStmt.c_str(), SQL_NTS); + retcode = SQLExecDirect(hstmtUpdate, WXSQLCAST(pSqlStmt), SQL_NTS); if (retcode == SQL_SUCCESS || retcode == SQL_NO_DATA_FOUND || @@ -729,7 +718,7 @@ bool wxDbTable::query(int queryType, bool forUpdate, bool distinct, const wxStri // Execute the SQL SELECT statement int retcode; - retcode = SQLExecDirect(hstmt, (SQLTCHAR FAR *) (queryType == DB_SELECT_STATEMENT ? pSqlStmt.c_str() : sqlStmt.c_str()), SQL_NTS); + retcode = SQLExecDirect(hstmt, (queryType == DB_SELECT_STATEMENT ? WXSQLCAST(pSqlStmt) : WXSQLCAST(sqlStmt)), SQL_NTS); if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) return(pDb->DispAllErrors(henv, hdbc, hstmt)); @@ -868,7 +857,7 @@ bool wxDbTable::Open(bool checkPrivileges, bool checkTableExists) // Prepare the insert statement for execution if (insertableCount) { - if (SQLPrepare(hstmtInsert, (SQLTCHAR FAR *) sqlStmt.c_str(), SQL_NTS) != SQL_SUCCESS) + if (SQLPrepare(hstmtInsert, WXSQLCAST(sqlStmt), SQL_NTS) != SQL_SUCCESS) return(pDb->DispAllErrors(henv, hdbc, hstmtInsert)); } else @@ -987,7 +976,7 @@ void wxDbTable::BuildDeleteStmt(wxString &pSqlStmt, int typeOfDel, const wxStrin // Handle the case of DeleteWhere() and the where clause is blank. It should // delete all records from the database in this case. - if (typeOfDel == DB_DEL_WHERE && (pWhereClause.Length() == 0)) + if (typeOfDel == DB_DEL_WHERE && (pWhereClause.length() == 0)) { pSqlStmt.Printf(wxT("DELETE FROM %s"), pDb->SQLTableName(tableName.c_str()).c_str()); @@ -1066,7 +1055,7 @@ void wxDbTable::BuildSelectStmt(wxString &pSqlStmt, int typeOfSelect, bool disti if (typeOfSelect == DB_SELECT_WHERE && from && wxStrlen(from)) appendFromClause = true; #else - if (typeOfSelect == DB_SELECT_WHERE && from.Length()) + if (typeOfSelect == DB_SELECT_WHERE && from.length()) appendFromClause = true; #endif @@ -1126,7 +1115,7 @@ void wxDbTable::BuildSelectStmt(wxString &pSqlStmt, int typeOfSelect, bool disti #if wxODBC_BACKWARD_COMPATABILITY if (where && wxStrlen(where)) // May not want a where clause!!! #else - if (where.Length()) // May not want a where clause!!! + if (where.length()) // May not want a where clause!!! #endif { pSqlStmt += wxT(" WHERE "); @@ -1135,7 +1124,7 @@ void wxDbTable::BuildSelectStmt(wxString &pSqlStmt, int typeOfSelect, bool disti break; case DB_SELECT_KEYFIELDS: BuildWhereClause(whereClause, DB_WHERE_KEYFIELDS); - if (whereClause.Length()) + if (whereClause.length()) { pSqlStmt += wxT(" WHERE "); pSqlStmt += whereClause; @@ -1143,7 +1132,7 @@ void wxDbTable::BuildSelectStmt(wxString &pSqlStmt, int typeOfSelect, bool disti break; case DB_SELECT_MATCHING: BuildWhereClause(whereClause, DB_WHERE_MATCHING); - if (whereClause.Length()) + if (whereClause.length()) { pSqlStmt += wxT(" WHERE "); pSqlStmt += whereClause; @@ -1155,7 +1144,7 @@ void wxDbTable::BuildSelectStmt(wxString &pSqlStmt, int typeOfSelect, bool disti #if wxODBC_BACKWARD_COMPATABILITY if (orderBy && wxStrlen(orderBy)) #else - if (orderBy.Length()) + if (orderBy.length()) #endif { pSqlStmt += wxT(" ORDER BY "); @@ -1289,7 +1278,7 @@ void wxDbTable::BuildWhereClause(wxString &pWhereClause, int typeOfWhere, // Concatenate where phrase for the column wxString tStr = colDefs[colNumber].ColName; - if (qualTableName.Length() && tStr.Find(wxT('.')) == wxNOT_FOUND) + if (qualTableName.length() && tStr.Find(wxT('.')) == wxNOT_FOUND) { pWhereClause += pDb->SQLTableName(qualTableName); pWhereClause += wxT("."); @@ -1308,7 +1297,7 @@ void wxDbTable::BuildWhereClause(wxString &pWhereClause, int typeOfWhere, case SQL_C_WCHAR: #endif //case SQL_C_WXCHAR: SQL_C_WXCHAR is covered by either SQL_C_CHAR or SQL_C_WCHAR - colValue.Printf(wxT("'%s'"), (UCHAR FAR *) colDefs[colNumber].PtrDataObj); + colValue.Printf(wxT("'%s'"), GetDb()->EscapeSqlChars((wxChar *)colDefs[colNumber].PtrDataObj).c_str()); break; case SQL_C_SHORT: case SQL_C_SSHORT: @@ -1414,6 +1403,9 @@ bool wxDbTable::CreateTable(bool attemptDrop) case DB_DATA_TYPE_VARCHAR: cout << pDb->GetTypeInfVarchar().TypeName << wxT("(") << (int)(colDefs[i].SzDataObj / sizeof(wxChar)) << wxT(")"); break; + case DB_DATA_TYPE_MEMO: + cout << pDb->GetTypeInfMemo().TypeName; + break; case DB_DATA_TYPE_INTEGER: cout << pDb->GetTypeInfInteger().TypeName; break; @@ -1455,6 +1447,9 @@ bool wxDbTable::CreateTable(bool attemptDrop) case DB_DATA_TYPE_VARCHAR: sqlStmt += pDb->GetTypeInfVarchar().TypeName; break; + case DB_DATA_TYPE_MEMO: + sqlStmt += pDb->GetTypeInfMemo().TypeName; + break; case DB_DATA_TYPE_INTEGER: sqlStmt += pDb->GetTypeInfInteger().TypeName; break; @@ -1524,7 +1519,7 @@ bool wxDbTable::CreateTable(bool attemptDrop) // DB2 is limited to 18 characters for index names if (pDb->Dbms() == dbmsDB2) { - wxASSERT_MSG((tableName && wxStrlen(tableName) <= 13), wxT("DB2 table/index names must be no longer than 13 characters in length.\n\nTruncating table name to 13 characters.")); + wxASSERT_MSG(!tableName.empty() && tableName.length() <= 13, wxT("DB2 table/index names must be no longer than 13 characters in length.\n\nTruncating table name to 13 characters.")); sqlStmt += pDb->SQLTableName(tableName.substr(0, 13).c_str()); // sqlStmt += tableName.substr(0, 13); } @@ -1577,7 +1572,7 @@ bool wxDbTable::CreateTable(bool attemptDrop) #endif // Execute the CREATE TABLE statement - RETCODE retcode = SQLExecDirect(hstmt, (SQLTCHAR FAR *) sqlStmt.c_str(), SQL_NTS); + RETCODE retcode = SQLExecDirect(hstmt, WXSQLCAST(sqlStmt), SQL_NTS); if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) { pDb->DispAllErrors(henv, hdbc, hstmt); @@ -1617,7 +1612,7 @@ bool wxDbTable::DropTable() cout << endl << sqlStmt.c_str() << endl; #endif - RETCODE retcode = SQLExecDirect(hstmt, (SQLTCHAR FAR *) sqlStmt.c_str(), SQL_NTS); + RETCODE retcode = SQLExecDirect(hstmt, WXSQLCAST(sqlStmt), SQL_NTS); if (retcode != SQL_SUCCESS) { // Check for "Base table not found" error and ignore @@ -1786,7 +1781,7 @@ bool wxDbTable::CreateIndex(const wxString &indexName, bool unique, UWORD numInd #endif // Execute the CREATE INDEX statement - RETCODE retcode = SQLExecDirect(hstmt, (SQLTCHAR FAR *) sqlStmt.c_str(), SQL_NTS); + RETCODE retcode = SQLExecDirect(hstmt, WXSQLCAST(sqlStmt), SQL_NTS); if (retcode != SQL_SUCCESS) { pDb->DispAllErrors(henv, hdbc, hstmt); @@ -1837,7 +1832,7 @@ bool wxDbTable::DropIndex(const wxString &indexName) #ifdef DBDEBUG_CONSOLE cout << endl << sqlStmt.c_str() << endl; #endif - RETCODE retcode = SQLExecDirect(hstmt, (SQLTCHAR FAR *) sqlStmt.c_str(), SQL_NTS); + RETCODE retcode = SQLExecDirect(hstmt, WXSQLCAST(sqlStmt), SQL_NTS); if (retcode != SQL_SUCCESS) { // Check for "Index not found" error and ignore @@ -2234,6 +2229,20 @@ void wxDbTable::ClearMemberVar(UWORD colNumber, bool setToNull) pDt->second = 0; pDt->fraction = 0; break; + case SQL_C_DATE: + DATE_STRUCT *pDtd; + pDtd = (DATE_STRUCT *) colDefs[colNumber].PtrDataObj; + pDtd->year = 0; + pDtd->month = 0; + pDtd->day = 0; + break; + case SQL_C_TIME: + TIME_STRUCT *pDtt; + pDtt = (TIME_STRUCT *) colDefs[colNumber].PtrDataObj; + pDtt->hour = 0; + pDtt->minute = 0; + pDtt->second = 0; + break; } if (setToNull) @@ -2289,7 +2298,7 @@ bool wxDbTable::SetColDefs(UWORD index, const wxString &fieldName, int dataType, if (!colDefs) // May happen if the database connection fails return false; - if (fieldName.Length() > (unsigned int) DB_MAX_COLUMN_NAME_LEN) + if (fieldName.length() > (unsigned int) DB_MAX_COLUMN_NAME_LEN) { wxStrncpy(colDefs[index].ColName, fieldName, DB_MAX_COLUMN_NAME_LEN); colDefs[index].ColName[DB_MAX_COLUMN_NAME_LEN] = 0; // Prevent buffer overrun @@ -2349,6 +2358,11 @@ wxDbColDataPtr* wxDbTable::SetColDefs(wxDbColInf *pColInfs, UWORD numCols) pColDataPtrs[index].SzDataObj = pColInfs[index].bufferSize+(1*sizeof(wxChar)); pColDataPtrs[index].SqlCtype = SQL_C_WXCHAR; break; + case DB_DATA_TYPE_MEMO: + pColDataPtrs[index].PtrDataObj = new wxChar[pColInfs[index].bufferSize+(1*sizeof(wxChar))]; + pColDataPtrs[index].SzDataObj = pColInfs[index].bufferSize+(1*sizeof(wxChar)); + pColDataPtrs[index].SqlCtype = SQL_C_WXCHAR; + break; case DB_DATA_TYPE_INTEGER: // Can be long or short if (pColInfs[index].bufferSize == sizeof(long)) @@ -2438,7 +2452,7 @@ ULONG wxDbTable::Count(const wxString &args) #if wxODBC_BACKWARD_COMPATABILITY if (from && wxStrlen(from)) #else - if (from.Length()) + if (from.length()) #endif sqlStmt += from; @@ -2446,7 +2460,7 @@ ULONG wxDbTable::Count(const wxString &args) #if wxODBC_BACKWARD_COMPATABILITY if (where && wxStrlen(where)) #else - if (where.Length()) + if (where.length()) #endif { sqlStmt += wxT(" WHERE "); @@ -2465,7 +2479,7 @@ ULONG wxDbTable::Count(const wxString &args) } // Execute the SQL statement - if (SQLExecDirect(*hstmtCount, (SQLTCHAR FAR *) sqlStmt.c_str(), SQL_NTS) != SQL_SUCCESS) + if (SQLExecDirect(*hstmtCount, WXSQLCAST(sqlStmt), SQL_NTS) != SQL_SUCCESS) { pDb->DispAllErrors(henv, hdbc, *hstmtCount); return(0); @@ -2904,4 +2918,3 @@ void wxDbTable::SetKey(const GenericKey& k) #endif // wxUSE_ODBC -