X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/da99271dcbfc8ab3da4ad18393e6b7b57b7428bf..804c69d3d193d0d821aea227524f8f5d96ecc309:/src/common/dbtable.cpp?ds=inline diff --git a/src/common/dbtable.cpp b/src/common/dbtable.cpp index 2a64883a0b..0df9c08bc4 100644 --- a/src/common/dbtable.cpp +++ b/src/common/dbtable.cpp @@ -128,21 +128,21 @@ bool wxDbColDef::Initialize() /********** wxDbTable::wxDbTable() Constructor **********/ -wxDbTable::wxDbTable(wxDb *pwxDb, const wxString &tblName, const int nCols, +wxDbTable::wxDbTable(wxDb *pwxDb, const wxString &tblName, const UWORD numColumns, const wxString &qryTblName, bool qryOnly, const wxString &tblPath) { - if (!initialize(pwxDb, tblName, nCols, qryTblName, qryOnly, tblPath)) + if (!initialize(pwxDb, tblName, numColumns, qryTblName, qryOnly, tblPath)) cleanup(); } // wxDbTable::wxDbTable() /***** DEPRECATED: use wxDbTable::wxDbTable() format above *****/ -wxDbTable::wxDbTable(wxDb *pwxDb, const wxString &tblName, const int nCols, +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, nCols, tempQryTblName, qryOnly, tblPath)) + if (!initialize(pwxDb, tblName, numColumns, tempQryTblName, qryOnly, tblPath)) cleanup(); } // wxDbTable::wxDbTable() @@ -154,7 +154,7 @@ wxDbTable::~wxDbTable() } // wxDbTable::~wxDbTable() -bool wxDbTable::initialize(wxDb *pwxDb, const wxString &tblName, const int nCols, +bool wxDbTable::initialize(wxDb *pwxDb, const wxString &tblName, const UWORD numColumns, const wxString &qryTblName, bool qryOnly, const wxString &tblPath) { // Initializing member variables @@ -170,7 +170,7 @@ bool wxDbTable::initialize(wxDb *pwxDb, const wxString &tblName, const int nCols hstmtInternal = 0; colDefs = 0; tableID = 0; - noCols = nCols; // No. of cols in the table + noCols = numColumns; // Number of cols in the table where.Empty(); // Where clause orderBy.Empty(); // Order By clause from.Empty(); // From clause @@ -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); @@ -430,17 +430,19 @@ bool wxDbTable::bindParams(bool forUpdate) // Bind each column of the table that should be bound // to a parameter marker - int i,colNo; - for (i = 0, colNo = 1; i < noCols; i++) + int 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; } @@ -487,6 +489,15 @@ bool wxDbTable::bindParams(bool forUpdate) else colDefs[i].CbValue = 0; break; + case DB_DATA_TYPE_BLOB: + fSqlType = pDb->GetTypeInfBlob().FsqlType; + precision = 50000; + scale = 0; + if (colDefs[i].Null) + colDefs[i].CbValue = SQL_NULL_DATA; + else + colDefs[i].CbValue = SQL_LEN_DATA_AT_EXEC(colDefs[i].SzDataObj); + break; } if (forUpdate) { @@ -531,14 +542,11 @@ 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 - int i; + UWORD i; for (i = 0; i < noCols; i++) { - if (SQLBindCol(cursor, i+1, colDefs[i].SqlCtype, (UCHAR*) colDefs[i].PtrDataObj, -//RG-NULL colDefs[i].SzDataObj, &cb) != SQL_SUCCESS) + if (SQLBindCol(cursor, (UWORD)(i+1), colDefs[i].SqlCtype, (UCHAR*) colDefs[i].PtrDataObj, colDefs[i].SzDataObj, &colDefs[i].CbValue ) != SQL_SUCCESS) { return (pDb->DispAllErrors(henv, hdbc, cursor)); @@ -563,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); @@ -609,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() @@ -622,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() @@ -685,7 +711,7 @@ bool wxDbTable::query(int queryType, bool forUpdate, bool distinct, const wxStri /********** wxDbTable::Open() **********/ -bool wxDbTable::Open(bool checkPrivileges) +bool wxDbTable::Open(bool checkPrivileges, bool checkTableExists) { if (!pDb) return FALSE; @@ -696,7 +722,7 @@ bool wxDbTable::Open(bool checkPrivileges) s.Empty(); // Verify that the table exists in the database - if (!pDb->TableExists(tableName,/*pDb->GetUsername()*/NULL,tablePath)) + if (checkTableExists && !pDb->TableExists(tableName, pDb->GetUsername(), tablePath)) { s = wxT("Table/view does not exist in the database"); if ( *(pDb->dbInf.accessibleTables) == wxT('Y')) @@ -713,7 +739,7 @@ bool wxDbTable::Open(bool checkPrivileges) // Unfortunately this optimization doesn't seem to be // reliable! if (// *(pDb->dbInf.accessibleTables) == 'N' && - !pDb->TablePrivileges(tableName,wxT("SELECT"),NULL,pDb->GetUsername(),tablePath)) + !pDb->TablePrivileges(tableName,wxT("SELECT"), pDb->GetUsername(), pDb->GetUsername(), tablePath)) s = wxT("Current logged in user does not have sufficient privileges to access this table.\n"); } @@ -929,7 +955,7 @@ void wxDbTable::BuildDeleteStmt(wxString &pSqlStmt, int typeOfDel, const wxStrin // Get the ROWID value. If not successful retreiving the ROWID, // simply fall down through the code and build the WHERE clause // based on the key fields. - if (SQLGetData(hstmt, noCols+1, SQL_C_CHAR, (UCHAR*) rowid, wxDB_ROWID_LEN, &cb) == SQL_SUCCESS) + if (SQLGetData(hstmt, (UWORD)(noCols+1), SQL_C_CHAR, (UCHAR*) rowid, wxDB_ROWID_LEN, &cb) == SQL_SUCCESS) { pSqlStmt += wxT("ROWID = '"); pSqlStmt += rowid; @@ -992,7 +1018,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("."); @@ -1007,7 +1033,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; @@ -1106,7 +1132,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; @@ -1140,7 +1166,7 @@ void wxDbTable::BuildUpdateStmt(wxString &pSqlStmt, int typeOfUpd, const wxStrin // Get the ROWID value. If not successful retreiving the ROWID, // simply fall down through the code and build the WHERE clause // based on the key fields. - if (SQLGetData(hstmt, noCols+1, SQL_C_CHAR, (UCHAR*) rowid, wxDB_ROWID_LEN, &cb) == SQL_SUCCESS) + if (SQLGetData(hstmt, (UWORD)(noCols+1), SQL_C_CHAR, (UCHAR*) rowid, wxDB_ROWID_LEN, &cb) == SQL_SUCCESS) { pSqlStmt += wxT("ROWID = '"); pSqlStmt += rowid; @@ -1315,6 +1341,9 @@ bool wxDbTable::CreateTable(bool attemptDrop) case DB_DATA_TYPE_DATE: cout << pDb->typeInfDate.TypeName; break; + case DB_DATA_TYPE_BLOB: + cout << pDb->typeInfBlob.TypeName; + break; } cout << endl; } @@ -1350,9 +1379,13 @@ bool wxDbTable::CreateTable(bool attemptDrop) case DB_DATA_TYPE_DATE: sqlStmt += pDb->GetTypeInfDate().TypeName; break; + case DB_DATA_TYPE_BLOB: + sqlStmt += pDb->GetTypeInfBlob().TypeName; + break; } // For varchars, append the size of the string - if (colDefs[i].DbDataType == DB_DATA_TYPE_VARCHAR) + if (colDefs[i].DbDataType == DB_DATA_TYPE_VARCHAR)// || +// colDefs[i].DbDataType == DB_DATA_TYPE_BLOB) { wxString s; s.Printf(wxT("(%d)"), colDefs[i].SzDataObj); @@ -1383,16 +1416,31 @@ bool wxDbTable::CreateTable(bool attemptDrop) } if (j && pDb->Dbms() != dbmsDBASE) // Found a keyfield { - if (pDb->Dbms() != dbmsMY_SQL) + switch (pDb->Dbms()) { - sqlStmt += wxT(",CONSTRAINT "); - sqlStmt += tableName; - sqlStmt += wxT("_PIDX PRIMARY KEY ("); - } - else - { - /* MySQL goes out on this one. We also declare the relevant key NON NULL above */ - sqlStmt += wxT(", PRIMARY KEY ("); + 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 @@ -1405,7 +1453,15 @@ bool wxDbTable::CreateTable(bool attemptDrop) sqlStmt += colDefs[i].ColName; } } - sqlStmt += wxT(")"); + sqlStmt += wxT(")"); + + if (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(")"); @@ -1456,22 +1512,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); } } @@ -1488,7 +1549,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; @@ -1616,12 +1678,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)) @@ -1670,9 +1733,9 @@ bool wxDbTable::DropIndex(const wxString &idxName) /********** wxDbTable::SetOrderByColNums() **********/ -bool wxDbTable::SetOrderByColNums(int first, ... ) +bool wxDbTable::SetOrderByColNums(UWORD first, ... ) { - int colNo = first; + int colNo = first; // using 'int' to be able to look for wxDB_NO_MORE_COLUN_NUMBERS va_list argptr; bool abort = FALSE; @@ -1863,7 +1926,7 @@ bool wxDbTable::DeleteMatching(void) /********** wxDbTable::IsColNull() **********/ -bool wxDbTable::IsColNull(int colNo) +bool wxDbTable::IsColNull(UWORD colNo) { /* This logic is just not right. It would indicate TRUE @@ -1926,12 +1989,12 @@ bool wxDbTable::CanUpdByROWID(void) * as the ROWID is not getting updated correctly */ return FALSE; - +/* if (pDb->Dbms() == dbmsORACLE) return(TRUE); else return(FALSE); - +*/ } // wxDbTable::CanUpdByROWID() @@ -1948,7 +2011,7 @@ bool wxDbTable::IsCursorClosedOnCommit(void) /********** wxDbTable::ClearMemberVar() **********/ -void wxDbTable::ClearMemberVar(int colNo, bool setToNull) +void wxDbTable::ClearMemberVar(UWORD colNo, bool setToNull) { wxASSERT(colNo < noCols); @@ -2024,8 +2087,8 @@ bool wxDbTable::SetQueryTimeout(UDWORD nSeconds) /********** wxDbTable::SetColDefs() **********/ -void wxDbTable::SetColDefs(int index, const wxString &fieldName, int dataType, void *pData, - int cType, int size, bool keyField, bool upd, +void wxDbTable::SetColDefs(UWORD index, const wxString &fieldName, int dataType, void *pData, + SWORD cType, int size, bool keyField, bool upd, bool insAllow, bool derivedCol) { if (!colDefs) // May happen if the database connection fails @@ -2063,14 +2126,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]; @@ -2119,8 +2182,26 @@ wxDbColDataPtr* wxDbTable::SetColDefs(wxDbColInf *pColInfs, ULONG numCols) pColDataPtrs[index].SzDataObj = sizeof(TIMESTAMP_STRUCT); pColDataPtrs[index].SqlCtype = SQL_C_TIMESTAMP; break; + case DB_DATA_TYPE_BLOB: + 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 *); + pColDataPtrs[index].SqlCtype = SQL_VARBINARY; + break; + } + if (pColDataPtrs[index].PtrDataObj != NULL) + SetColDefs (index,pColInfs[index].colName,pColInfs[index].dbDataType, pColDataPtrs[index].PtrDataObj, pColDataPtrs[index].SqlCtype, pColDataPtrs[index].SzDataObj); + else + { + // Unable to build all the column definitions, as either one of + // the calls to "new" failed above, or there was a BLOB field + // to have a column definition for. If BLOBs are to be used, + // the other form of ::SetColDefs() must be used, as it is impossible + // to know the maximum size to create the PtrDataObj to be. + delete [] pColDataPtrs; + return NULL; } - SetColDefs (index,pColInfs[index].colName,pColInfs[index].dbDataType, pColDataPtrs[index].PtrDataObj, pColDataPtrs[index].SqlCtype, pColDataPtrs[index].SzDataObj); } } @@ -2196,7 +2277,7 @@ ULONG wxDbTable::Count(const wxString &args) } // Obtain the result - if (SQLGetData(*hstmtCount, 1, SQL_C_ULONG, &count, sizeof(count), &cb) != SQL_SUCCESS) + if (SQLGetData(*hstmtCount, (UWORD)1, SQL_C_ULONG, &count, sizeof(count), &cb) != SQL_SUCCESS) { pDb->DispAllErrors(henv, hdbc, *hstmtCount); return(0); @@ -2241,7 +2322,7 @@ bool wxDbTable::Refresh(void) // Get the ROWID value. If not successful retreiving the ROWID, // simply fall down through the code and build the WHERE clause // based on the key fields. - if (SQLGetData(hstmt, noCols+1, SQL_C_CHAR, (UCHAR*) rowid, wxDB_ROWID_LEN, &cb) == SQL_SUCCESS) + if (SQLGetData(hstmt, (UWORD)(noCols+1), SQL_C_CHAR, (UCHAR*) rowid, wxDB_ROWID_LEN, &cb) == SQL_SUCCESS) { whereClause += queryTableName; whereClause += wxT(".ROWID = '"); @@ -2279,8 +2360,8 @@ bool wxDbTable::Refresh(void) } // wxDbTable::Refresh() -/********** wxDbTable::SetColNull(int colNo, bool set) **********/ -bool wxDbTable::SetColNull(int colNo, bool set) +/********** wxDbTable::SetColNull() **********/ +bool wxDbTable::SetColNull(UWORD colNo, bool set) { if (colNo < noCols) { @@ -2295,7 +2376,7 @@ bool wxDbTable::SetColNull(int colNo, bool set) } // wxDbTable::SetColNull() -/********** wxDbTable::SetColNull(const wxString &colName, bool set) **********/ +/********** wxDbTable::SetColNull() **********/ bool wxDbTable::SetColNull(const wxString &colName, bool set) { int i;