X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e938ff5e2013d1181d2eb740f1c9836fc0dc7575..ed582841a275d236b9bac7651a0f3e7c91be868d:/src/common/dbtable.cpp diff --git a/src/common/dbtable.cpp b/src/common/dbtable.cpp index 68b5fd652f..e5e5fa368d 100644 --- a/src/common/dbtable.cpp +++ b/src/common/dbtable.cpp @@ -203,7 +203,7 @@ 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); - + #ifdef __WXDEBUG__ wxTablesInUse *tableInUse; tableInUse = new wxTablesInUse(); @@ -351,7 +351,7 @@ void wxDbTable::cleanup() if (!found) { wxString msg; - msg.Printf(wxT("Unable to find the tableID in the linked\nlist of tables in use.\n\n%s"),s); + msg.Printf(wxT("Unable to find the tableID in the linked\nlist of tables in use.\n\n%s"),s.c_str()); wxLogDebug (msg,wxT("NOTICE...")); } } @@ -417,7 +417,7 @@ ODBC 3.0 says to use this form /***************************** PRIVATE FUNCTIONS *****************************/ -/********** wxDbTable::bindUpdateParams() **********/ +/********** wxDbTable::bindParams() **********/ bool wxDbTable::bindParams(bool forUpdate) { wxASSERT(!queryOnly); @@ -431,17 +431,18 @@ bool wxDbTable::bindParams(bool forUpdate) // Bind each column of the table that should be bound // to a parameter marker int i; - UWORD colNo; - for (i = 0, colNo = 1; i < noCols; i++) + UWORD colNo; + + for (i=0, colNo=1; i < noCols; i++) { if (forUpdate) { - if (! colDefs[i].Updateable) + if (!colDefs[i].Updateable) continue; } else { - if (! colDefs[i].InsertAllowed) + if (!colDefs[i].InsertAllowed) continue; } @@ -541,8 +542,6 @@ bool wxDbTable::bindUpdateParams(void) /********** wxDbTable::bindCols() **********/ bool wxDbTable::bindCols(HSTMT cursor) { -//RG-NULL static SDWORD cb; - // Bind each column of the table to a memory address for fetching data UWORD i; for (i = 0; i < noCols; i++) @@ -572,7 +571,7 @@ bool wxDbTable::getRec(UWORD fetchType) UWORD rowStatus; retcode = SQLExtendedFetch(hstmt, fetchType, 0, &cRowsFetched, &rowStatus); - if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) { if (retcode == SQL_NO_DATA_FOUND) return(FALSE); @@ -618,12 +617,21 @@ bool wxDbTable::getRec(UWORD fetchType) /********** wxDbTable::execDelete() **********/ bool wxDbTable::execDelete(const wxString &pSqlStmt) { + RETCODE retcode; + // Execute the DELETE statement - if (SQLExecDirect(hstmtDelete, (UCHAR FAR *) pSqlStmt.c_str(), SQL_NTS) != SQL_SUCCESS) - return(pDb->DispAllErrors(henv, hdbc, hstmtDelete)); + retcode = SQLExecDirect(hstmtDelete, (UCHAR FAR *) pSqlStmt.c_str(), SQL_NTS); - // Record deleted successfully - return(TRUE); + if (retcode == SQL_SUCCESS || + retcode == SQL_NO_DATA_FOUND || + retcode == SQL_SUCCESS_WITH_INFO) + { + // Record deleted successfully + return(TRUE); + } + + // Problem deleting record + return(pDb->DispAllErrors(henv, hdbc, hstmtDelete)); } // wxDbTable::execDelete() @@ -631,12 +639,21 @@ bool wxDbTable::execDelete(const wxString &pSqlStmt) /********** wxDbTable::execUpdate() **********/ bool wxDbTable::execUpdate(const wxString &pSqlStmt) { + RETCODE retcode; + // Execute the UPDATE statement - if (SQLExecDirect(hstmtUpdate, (UCHAR FAR *) pSqlStmt.c_str(), SQL_NTS) != SQL_SUCCESS) - return(pDb->DispAllErrors(henv, hdbc, hstmtUpdate)); + retcode = SQLExecDirect(hstmtUpdate, (UCHAR FAR *) pSqlStmt.c_str(), SQL_NTS); - // Record deleted successfully - return(TRUE); + if (retcode == SQL_SUCCESS || + retcode == SQL_NO_DATA_FOUND || + retcode == SQL_SUCCESS_WITH_INFO) + { + // Record updated successfully + return(TRUE); + } + + // Problem updating record + return(pDb->DispAllErrors(henv, hdbc, hstmtUpdate)); } // wxDbTable::execUpdate() @@ -658,22 +675,7 @@ bool wxDbTable::query(int queryType, bool forUpdate, bool distinct, const wxStri BuildSelectStmt(sqlStmt, queryType, distinct); pDb->WriteSqlLog(sqlStmt); } -/* - This is the block of code that got added during the 2.2.1 merge with - the 2.2 main branch that somehow got added here when it should not have. - gt - else - wxStrcpy(sqlStmt, pSqlStmt); - - SQLFreeStmt(hstmt, SQL_CLOSE); - if (SQLExecDirect(hstmt, (UCHAR FAR *) sqlStmt, SQL_NTS) == SQL_SUCCESS) - return(TRUE); - else - { - pDb->DispAllErrors(henv, hdbc, hstmt); - return(FALSE); - } -*/ // Make sure the cursor is closed first if (!CloseCursor(hstmt)) return(FALSE); @@ -1001,7 +1003,7 @@ void wxDbTable::BuildSelectStmt(wxString &pSqlStmt, int typeOfSelect, bool disti for (i = 0; i < noCols; i++) { // If joining tables, the base table column names must be qualified to avoid ambiguity - if (appendFromClause) + if (appendFromClause || pDb->Dbms() == dbmsACCESS) { pSqlStmt += queryTableName; pSqlStmt += wxT("."); @@ -1016,7 +1018,7 @@ void wxDbTable::BuildSelectStmt(wxString &pSqlStmt, int typeOfSelect, bool disti if (!distinct && CanUpdByROWID()) { // If joining tables, the base table column names must be qualified to avoid ambiguity - if (appendFromClause) + if (appendFromClause || pDb->Dbms() == dbmsACCESS) { pSqlStmt += wxT(","); pSqlStmt += queryTableName; @@ -1115,7 +1117,7 @@ void wxDbTable::BuildUpdateStmt(wxString &pSqlStmt, int typeOfUpd, const wxStrin bool firstColumn = TRUE; - pSqlStmt.Printf(wxT("UPDATE %s SET "), tableName.c_str()); + pSqlStmt.Printf(wxT("UPDATE %s SET "), tableName.Upper().c_str()); // Append a list of columns to be updated int i; @@ -1124,7 +1126,7 @@ void wxDbTable::BuildUpdateStmt(wxString &pSqlStmt, int typeOfUpd, const wxStrin // Only append Updateable columns if (colDefs[i].Updateable) { - if (! firstColumn) + if (!firstColumn) pSqlStmt += wxT(","); else firstColumn = FALSE; @@ -1378,6 +1380,7 @@ bool wxDbTable::CreateTable(bool attemptDrop) if (pDb->Dbms() == dbmsDB2 || pDb->Dbms() == dbmsMY_SQL || pDb->Dbms() == dbmsSYBASE_ASE || + pDb->Dbms() == dbmsINTERBASE || pDb->Dbms() == dbmsMS_SQL_SERVER) { if (colDefs[i].KeyField) @@ -1399,16 +1402,32 @@ bool wxDbTable::CreateTable(bool attemptDrop) } if (j && pDb->Dbms() != dbmsDBASE) // Found a keyfield { - if (pDb->Dbms() != dbmsMY_SQL) - { - sqlStmt += wxT(",CONSTRAINT "); - sqlStmt += tableName; - sqlStmt += wxT("_PIDX PRIMARY KEY ("); - } - else + switch (pDb->Dbms()) { - /* MySQL goes out on this one. We also declare the relevant key NON NULL above */ - sqlStmt += wxT(", PRIMARY KEY ("); + case dbmsINFORMIX: + case dbmsSYBASE_ASA: + case dbmsSYBASE_ASE: + case dbmsMY_SQL: + { + // MySQL goes out on this one. We also declare the relevant key NON NULL above + sqlStmt += wxT(",PRIMARY KEY ("); + break; + } + default: + { + sqlStmt += wxT(",CONSTRAINT "); + // 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.")); + sqlStmt += tableName.substr(0, 13); + } + else + sqlStmt += tableName; + + sqlStmt += wxT("_PIDX PRIMARY KEY ("); + break; + } } // List column name(s) of column(s) comprising the primary key @@ -1421,7 +1440,16 @@ bool wxDbTable::CreateTable(bool attemptDrop) sqlStmt += colDefs[i].ColName; } } - sqlStmt += wxT(")"); + sqlStmt += wxT(")"); + + if (pDb->Dbms() == dbmsINFORMIX || + pDb->Dbms() == dbmsSYBASE_ASA || + pDb->Dbms() == dbmsSYBASE_ASE) + { + sqlStmt += wxT(" CONSTRAINT "); + sqlStmt += tableName; + sqlStmt += wxT("_PIDX"); + } } // Append the closing parentheses for the create table statement sqlStmt += wxT(")"); @@ -1472,22 +1500,27 @@ bool wxDbTable::DropTable() cout << endl << sqlStmt.c_str() << endl; #endif - if (SQLExecDirect(hstmt, (UCHAR FAR *) sqlStmt.c_str(), SQL_NTS) != SQL_SUCCESS) + + + + RETCODE retcode = SQLExecDirect(hstmt, (UCHAR FAR *) sqlStmt.c_str(), SQL_NTS); + if (retcode != SQL_SUCCESS) { // Check for "Base table not found" error and ignore pDb->GetNextError(henv, hdbc, hstmt); - if (wxStrcmp(pDb->sqlState, wxT("S0002")) && - wxStrcmp(pDb->sqlState, wxT("S1000"))) // "Base table not found" - { + if (wxStrcmp(pDb->sqlState, wxT("S0002")) /*&& + wxStrcmp(pDb->sqlState, wxT("S1000"))*/) // "Base table not found" + { // Check for product specific error codes - if (!((pDb->Dbms() == dbmsSYBASE_ASA && !wxStrcmp(pDb->sqlState,wxT("42000"))) || // 5.x (and lower?) - (pDb->Dbms() == dbmsSYBASE_ASE && !wxStrcmp(pDb->sqlState,wxT("37000"))) || - (pDb->Dbms() == dbmsPOSTGRES && !wxStrcmp(pDb->sqlState,wxT("08S01"))))) + if (!((pDb->Dbms() == dbmsSYBASE_ASA && !wxStrcmp(pDb->sqlState,wxT("42000"))) || // 5.x (and lower?) + (pDb->Dbms() == dbmsSYBASE_ASE && !wxStrcmp(pDb->sqlState,wxT("37000"))) || + (pDb->Dbms() == dbmsPERVASIVE_SQL && !wxStrcmp(pDb->sqlState,wxT("S1000"))) || // Returns an S1000 then an S0002 + (pDb->Dbms() == dbmsPOSTGRES && !wxStrcmp(pDb->sqlState,wxT("08S01"))))) { pDb->DispNextError(); pDb->DispAllErrors(henv, hdbc, hstmt); pDb->RollbackTrans(); - CloseCursor(hstmt); +// CloseCursor(hstmt); return(FALSE); } } @@ -1504,7 +1537,8 @@ bool wxDbTable::DropTable() /********** wxDbTable::CreateIndex() **********/ -bool wxDbTable::CreateIndex(const wxString &idxName, bool unique, int noIdxCols, wxDbIdxDef *pIdxDefs, bool attemptDrop) +bool wxDbTable::CreateIndex(const wxString &idxName, bool unique, UWORD noIdxCols, + wxDbIdxDef *pIdxDefs, bool attemptDrop) { wxString sqlStmt; @@ -1584,14 +1618,18 @@ bool wxDbTable::CreateIndex(const wxString &idxName, bool unique, int noIdxCols, for (i = 0; i < noIdxCols; i++) { sqlStmt += pIdxDefs[i].ColName; - /* Postgres doesn't cope with ASC */ - if (pDb->Dbms() != dbmsPOSTGRES) + + // Postgres and SQL Server 7 do not support the ASC/DESC keywords for index columns + if (!((pDb->Dbms() == dbmsMS_SQL_SERVER) && (strncmp(pDb->dbInf.dbmsVer,"07",2)==0)) && + !(pDb->Dbms() == dbmsPOSTGRES)) { if (pIdxDefs[i].Ascending) sqlStmt += wxT(" ASC"); else sqlStmt += wxT(" DESC"); } + else + wxASSERT_MSG(!pIdxDefs[i].Ascending, "Datasource does not support DESCending index columns"); if ((i + 1) < noIdxCols) sqlStmt += wxT(","); @@ -1632,12 +1670,13 @@ bool wxDbTable::DropIndex(const wxString &idxName) { // NOTE: This function returns TRUE if the Index does not exist, but // only for identified databases. Code will need to be added - // below for any other databases when those databases are defined + // below for any other databases when those databases are defined // to handle this situation consistently wxString sqlStmt; - if (pDb->Dbms() == dbmsACCESS || pDb->Dbms() == dbmsMY_SQL) + if (pDb->Dbms() == dbmsACCESS || pDb->Dbms() == dbmsMY_SQL || + pDb->Dbms() == dbmsDBASE /*|| Paradox needs this syntax too when we add support*/) sqlStmt.Printf(wxT("DROP INDEX %s ON %s"),idxName.c_str(), tableName.c_str()); else if ((pDb->Dbms() == dbmsMS_SQL_SERVER) || (pDb->Dbms() == dbmsSYBASE_ASE)) @@ -1661,6 +1700,7 @@ bool wxDbTable::DropIndex(const wxString &idxName) if (!((pDb->Dbms() == dbmsSYBASE_ASA && !wxStrcmp(pDb->sqlState,wxT("42000"))) || // v5.x (and lower?) (pDb->Dbms() == dbmsSYBASE_ASE && !wxStrcmp(pDb->sqlState,wxT("37000"))) || (pDb->Dbms() == dbmsMS_SQL_SERVER && !wxStrcmp(pDb->sqlState,wxT("S1000"))) || + (pDb->Dbms() == dbmsINTERBASE && !wxStrcmp(pDb->sqlState,wxT("S1000"))) || (pDb->Dbms() == dbmsSYBASE_ASE && !wxStrcmp(pDb->sqlState,wxT("S0002"))) || // Base table not found (pDb->Dbms() == dbmsMY_SQL && !wxStrcmp(pDb->sqlState,wxT("42S12"))) || // tested by Christopher Ludwik Marino-Cebulski using v3.23.21beta (pDb->Dbms() == dbmsPOSTGRES && !wxStrcmp(pDb->sqlState,wxT("08S01"))) @@ -1688,7 +1728,7 @@ bool wxDbTable::DropIndex(const wxString &idxName) /********** wxDbTable::SetOrderByColNums() **********/ bool wxDbTable::SetOrderByColNums(UWORD first, ... ) { - int colNo = first; // using 'int' to be able to look for wxDB_NO_MORE_COLUN_NUMBERS + int colNo = first; // using 'int' to be able to look for wxDB_NO_MORE_COLUN_NUMBERS va_list argptr; bool abort = FALSE; @@ -2040,7 +2080,7 @@ bool wxDbTable::SetQueryTimeout(UDWORD nSeconds) /********** wxDbTable::SetColDefs() **********/ -void wxDbTable::SetColDefs(int index, const wxString &fieldName, int dataType, void *pData, +void wxDbTable::SetColDefs(UWORD index, const wxString &fieldName, int dataType, void *pData, SWORD cType, int size, bool keyField, bool upd, bool insAllow, bool derivedCol) { @@ -2049,8 +2089,12 @@ void wxDbTable::SetColDefs(int index, const wxString &fieldName, int dataType, v if (fieldName.Length() > (unsigned int) DB_MAX_COLUMN_NAME_LEN) { - wxStrncpy (colDefs[index].ColName, fieldName, DB_MAX_COLUMN_NAME_LEN); + int assertColumnNameTooLong = 0; + wxStrncpy(colDefs[index].ColName, fieldName, DB_MAX_COLUMN_NAME_LEN); colDefs[index].ColName[DB_MAX_COLUMN_NAME_LEN] = 0; + wxString tmpMsg; + tmpMsg.Printf("Column name '%s' is too long. Truncated to '%s'.",fieldName.c_str(),colDefs[index].ColName); + wxASSERT_MSG(assertColumnNameTooLong,tmpMsg.c_str()); } else wxStrcpy(colDefs[index].ColName, fieldName); @@ -2079,14 +2123,14 @@ void wxDbTable::SetColDefs(int index, const wxString &fieldName, int dataType, v /********** wxDbTable::SetColDefs() **********/ -wxDbColDataPtr* wxDbTable::SetColDefs(wxDbColInf *pColInfs, ULONG numCols) +wxDbColDataPtr* wxDbTable::SetColDefs(wxDbColInf *pColInfs, UWORD numCols) { wxASSERT(pColInfs); wxDbColDataPtr *pColDataPtrs = NULL; if (pColInfs) { - ULONG index; + UWORD index; pColDataPtrs = new wxDbColDataPtr[numCols+1]; @@ -2136,7 +2180,7 @@ wxDbColDataPtr* wxDbTable::SetColDefs(wxDbColInf *pColInfs, ULONG numCols) pColDataPtrs[index].SqlCtype = SQL_C_TIMESTAMP; break; case DB_DATA_TYPE_BLOB: - int notSupportedYet = 0; + int notSupportedYet = 0; wxASSERT_MSG(notSupportedYet, wxT("This form of ::SetColDefs() cannot be used with BLOB columns")); pColDataPtrs[index].PtrDataObj = /*BLOB ADDITION NEEDED*/NULL; pColDataPtrs[index].SzDataObj = /*BLOB ADDITION NEEDED*/sizeof(void *);