X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a144affed28cbd6828dfbe8c17b4cac989e7a6b3..e0c5c96f67eaf13ccbd378616bdf98c8dba01e78:/src/common/dbtable.cpp diff --git a/src/common/dbtable.cpp b/src/common/dbtable.cpp index 234c9c72a5..c5482f8a69 100644 --- a/src/common/dbtable.cpp +++ b/src/common/dbtable.cpp @@ -24,7 +24,8 @@ // SYNOPSIS START // SYNOPSIS STOP */ -#ifdef __GNUG__ + +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "dbtable.h" #endif @@ -35,7 +36,11 @@ #endif #ifdef DBDEBUG_CONSOLE - #include "iostream.h" +#if wxUSE_IOSTREAMH + #include +#else + #include +#endif #include "wx/ioswrap.h" #endif @@ -44,7 +49,6 @@ #include "wx/object.h" #include "wx/list.h" #include "wx/utils.h" - #include "wx/msgdlg.h" #include "wx/log.h" #endif #include "wx/filefn.h" @@ -54,7 +58,6 @@ #include #include #include -//#include #include "wx/dbtable.h" @@ -77,6 +80,16 @@ ULONG lastTableID = 0; #endif +void csstrncpyt(wxChar *target, const wxChar *source, int n) +{ + while ( (*target++ = *source++) != '\0' && --n ) + ; + + *target = '\0'; +} + + + /********** wxDbColDef::wxDbColDef() Constructor **********/ wxDbColDef::wxDbColDef() { @@ -168,14 +181,14 @@ bool wxDbTable::initialize(wxDb *pwxDb, const wxString &tblName, const UWORD num tablePath = tblPath; // Table Path - used for dBase files else tablePath.Empty(); - + if (qryTblName.Length()) // Name of the table/view to query queryTableName = qryTblName; else queryTableName = tblName; - + pDb->incrementTableCount(); - + wxString s; tableID = ++lastTableID; s.Printf(wxT("wxDbTable constructor (%-20s) tableID:[%6lu] pDb:[%p]"), tblName.c_str(), tableID, pDb); @@ -188,17 +201,17 @@ bool wxDbTable::initialize(wxDb *pwxDb, const wxString &tblName, const UWORD num tableInUse->pDb = pDb; TablesInUse.Append(tableInUse); #endif - + pDb->WriteSqlLog(s); - + // Grab the HENV and HDBC from the wxDb object henv = pDb->GetHENV(); hdbc = pDb->GetHDBC(); - + // Allocate space for column definitions if (noCols) colDefs = new wxDbColDef[noCols]; // Points to the first column definition - + // Allocate statement handles for the table if (!queryOnly) { @@ -215,12 +228,12 @@ bool wxDbTable::initialize(wxDb *pwxDb, const wxString &tblName, const UWORD num // Allocate a separate statement handle for internal use if (SQLAllocStmt(hdbc, &hstmtInternal) != SQL_SUCCESS) pDb->DispAllErrors(henv, hdbc); - + // Set the cursor type for the statement handles cursorType = SQL_CURSOR_STATIC; - + if (SQLSetStmtOption(hstmtInternal, SQL_CURSOR_TYPE, cursorType) != SQL_SUCCESS) - { + { // Check to see if cursor type is supported pDb->GetNextError(henv, hdbc, hstmtInternal); if (! wxStrcmp(pDb->sqlState, wxT("01S02"))) // Option Value Changed @@ -272,7 +285,7 @@ bool wxDbTable::initialize(wxDb *pwxDb, const wxString &tblName, const UWORD num else cout << wxT("Cursor Type set to STATIC") << endl << endl; #endif - + if (!queryOnly) { // Set the cursor type for the INSERT statement handle @@ -285,7 +298,7 @@ bool wxDbTable::initialize(wxDb *pwxDb, const wxString &tblName, const UWORD num if (SQLSetStmtOption(hstmtUpdate, SQL_CURSOR_TYPE, SQL_CURSOR_FORWARD_ONLY) != SQL_SUCCESS) pDb->DispAllErrors(henv, hdbc, hstmtUpdate); } - + // Make the default cursor the active cursor hstmtDefault = GetNewCursor(FALSE,FALSE); wxASSERT(hstmtDefault); @@ -312,17 +325,17 @@ void wxDbTable::cleanup() bool found = FALSE; wxNode *pNode; - pNode = TablesInUse.First(); + pNode = TablesInUse.GetFirst(); while (pNode && !found) { - if (((wxTablesInUse *)pNode->Data())->tableID == tableID) + if (((wxTablesInUse *)pNode->GetData())->tableID == tableID) { found = TRUE; if (!TablesInUse.DeleteNode(pNode)) wxLogDebug (s,wxT("Unable to delete node!")); } else - pNode = pNode->Next(); + pNode = pNode->GetNext(); } if (!found) { @@ -403,11 +416,11 @@ bool wxDbTable::bindParams(bool forUpdate) wxASSERT(!queryOnly); if (queryOnly) return(FALSE); - + SWORD fSqlType = 0; - UDWORD precision = 0; + SDWORD precision = 0; SWORD scale = 0; - + // Bind each column of the table that should be bound // to a parameter marker int i; @@ -449,7 +462,7 @@ bool wxDbTable::bindParams(bool forUpdate) case DB_DATA_TYPE_FLOAT: fSqlType = pDb->GetTypeInfFloat().FsqlType; precision = pDb->GetTypeInfFloat().Precision; - scale = pDb->GetTypeInfFloat().MaximumScale; + scale = pDb->GetTypeInfFloat().MaximumScale; // SQL Sybase Anywhere v5.5 returned a negative number for the // MaxScale. This caused ODBC to kick out an error on ibscale. // I check for this here and set the scale = precision. @@ -471,7 +484,7 @@ bool wxDbTable::bindParams(bool forUpdate) break; case DB_DATA_TYPE_BLOB: fSqlType = pDb->GetTypeInfBlob().FsqlType; - precision = 50000; + precision = -1; scale = 0; if (colDefs[i].Null) colDefs[i].CbValue = SQL_NULL_DATA; @@ -482,7 +495,7 @@ bool wxDbTable::bindParams(bool forUpdate) if (forUpdate) { if (SQLBindParameter(hstmtUpdate, colNo++, SQL_PARAM_INPUT, colDefs[i].SqlCtype, - fSqlType, precision, scale, (UCHAR*) colDefs[i].PtrDataObj, + fSqlType, precision, scale, (UCHAR*) colDefs[i].PtrDataObj, precision+1, &colDefs[i].CbValue) != SQL_SUCCESS) { return(pDb->DispAllErrors(henv, hdbc, hstmtUpdate)); @@ -491,14 +504,14 @@ bool wxDbTable::bindParams(bool forUpdate) else { if (SQLBindParameter(hstmtInsert, colNo++, SQL_PARAM_INPUT, colDefs[i].SqlCtype, - fSqlType, precision, scale, (UCHAR*) colDefs[i].PtrDataObj, + fSqlType, precision, scale, (UCHAR*) colDefs[i].PtrDataObj, precision+1,&colDefs[i].CbValue) != SQL_SUCCESS) { return(pDb->DispAllErrors(henv, hdbc, hstmtInsert)); } } } - + // Completed successfully return(TRUE); @@ -522,15 +535,16 @@ bool wxDbTable::bindUpdateParams(void) /********** wxDbTable::bindCols() **********/ bool wxDbTable::bindCols(HSTMT cursor) { + static SDWORD cb; + // Bind each column of the table to a memory address for fetching data UWORD i; for (i = 0; i < noCols; i++) { + cb = colDefs[i].CbValue; if (SQLBindCol(cursor, (UWORD)(i+1), colDefs[i].SqlCtype, (UCHAR*) colDefs[i].PtrDataObj, - colDefs[i].SzDataObj, &colDefs[i].CbValue ) != SQL_SUCCESS) - { + colDefs[i].SzDataObj, &cb ) != SQL_SUCCESS) return (pDb->DispAllErrors(henv, hdbc, cursor)); - } } // Completed successfully @@ -600,7 +614,7 @@ bool wxDbTable::execDelete(const wxString &pSqlStmt) RETCODE retcode; // Execute the DELETE statement - retcode = SQLExecDirect(hstmtDelete, (UCHAR FAR *) pSqlStmt.c_str(), SQL_NTS); + retcode = SQLExecDirect(hstmtDelete, (SQLTCHAR FAR *) pSqlStmt.c_str(), SQL_NTS); if (retcode == SQL_SUCCESS || retcode == SQL_NO_DATA_FOUND || @@ -622,7 +636,7 @@ bool wxDbTable::execUpdate(const wxString &pSqlStmt) RETCODE retcode; // Execute the UPDATE statement - retcode = SQLExecDirect(hstmtUpdate, (UCHAR FAR *) pSqlStmt.c_str(), SQL_NTS); + retcode = SQLExecDirect(hstmtUpdate, (SQLTCHAR FAR *) pSqlStmt.c_str(), SQL_NTS); if (retcode == SQL_SUCCESS || retcode == SQL_NO_DATA_FOUND || @@ -631,6 +645,37 @@ bool wxDbTable::execUpdate(const wxString &pSqlStmt) // Record updated successfully return(TRUE); } + else if (retcode == SQL_NEED_DATA) + { + PTR pParmID; + retcode = SQLParamData(hstmtUpdate, &pParmID); + while (retcode == SQL_NEED_DATA) + { + // Find the parameter + int i; + for (i=0; i < noCols; i++) + { + if (colDefs[i].PtrDataObj == pParmID) + { + // We found it. Store the parameter. + retcode = SQLPutData(hstmtUpdate, pParmID, colDefs[i].SzDataObj); + if (retcode != SQL_SUCCESS) + { + pDb->DispNextError(); + return pDb->DispAllErrors(henv, hdbc, hstmtUpdate); + } + break; + } + } + } + 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)); @@ -661,8 +706,8 @@ bool wxDbTable::query(int queryType, bool forUpdate, bool distinct, const wxStri return(FALSE); // Execute the SQL SELECT statement - int retcode; - retcode = SQLExecDirect(hstmt, (UCHAR FAR *) (queryType == DB_SELECT_STATEMENT ? pSqlStmt.c_str() : sqlStmt.c_str()), SQL_NTS); + int retcode; + retcode = SQLExecDirect(hstmt, (SQLTCHAR FAR *) (queryType == DB_SELECT_STATEMENT ? pSqlStmt.c_str() : sqlStmt.c_str()), SQL_NTS); if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) return(pDb->DispAllErrors(henv, hdbc, hstmt)); @@ -679,7 +724,7 @@ bool wxDbTable::query(int queryType, bool forUpdate, bool distinct, const wxStri bool wxDbTable::Open(bool checkPrivileges, bool checkTableExists) { if (!pDb) - return FALSE; + return FALSE; int i; wxString sqlStmt; @@ -711,12 +756,12 @@ bool wxDbTable::Open(bool checkPrivileges, bool checkTableExists) else if (checkPrivileges) { // Verify the user has rights to access the table. - // Shortcut boolean evaluation to optimize out call to + // Shortcut boolean evaluation to optimize out call to // TablePrivileges // // Unfortunately this optimization doesn't seem to be // reliable! - if (// *(pDb->dbInf.accessibleTables) == 'N' && + if (// *(pDb->dbInf.accessibleTables) == 'N' && !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"); } @@ -742,14 +787,14 @@ bool wxDbTable::Open(bool checkPrivileges, bool checkTableExists) { if (!bindInsertParams()) // Inserts return(FALSE); - + if (!bindUpdateParams()) // Updates return(FALSE); } if (!bindCols(*hstmtDefault)) // Selects return(FALSE); - + if (!bindCols(hstmtInternal)) // Internal use only return(FALSE); @@ -761,14 +806,16 @@ bool wxDbTable::Open(bool checkPrivileges, bool checkTableExists) if (!queryOnly && noCols > 0) { bool needComma = FALSE; - sqlStmt.Printf(wxT("INSERT INTO %s ("), tableName.c_str()); + sqlStmt.Printf(wxT("INSERT INTO %s ("), + pDb->SQLTableName(tableName.c_str()).c_str()); for (i = 0; i < noCols; i++) { if (! colDefs[i].InsertAllowed) continue; if (needComma) sqlStmt += wxT(","); - sqlStmt += colDefs[i].ColName; + sqlStmt += pDb->SQLColumnName(colDefs[i].ColName); +// sqlStmt += colDefs[i].ColName; needComma = TRUE; } needComma = FALSE; @@ -787,17 +834,17 @@ bool wxDbTable::Open(bool checkPrivileges, bool checkTableExists) insertableCount++; } sqlStmt += wxT(")"); - + // Prepare the insert statement for execution - if (insertableCount) + if (insertableCount) { - if (SQLPrepare(hstmtInsert, (UCHAR FAR *) sqlStmt.c_str(), SQL_NTS) != SQL_SUCCESS) + if (SQLPrepare(hstmtInsert, (SQLTCHAR FAR *) sqlStmt.c_str(), SQL_NTS) != SQL_SUCCESS) return(pDb->DispAllErrors(henv, hdbc, hstmtInsert)); } - else + else insertable= FALSE; } - + // Completed successfully return(TRUE); @@ -891,7 +938,7 @@ bool wxDbTable::GetLast(void) wxFAIL_MSG(wxT("GetLast()::Backward scrolling cursors are not enabled for this instance of wxDbTable")); return FALSE; } - else + else return(getRec(SQL_FETCH_LAST)); } // wxDbTable::GetLast() @@ -912,11 +959,13 @@ void wxDbTable::BuildDeleteStmt(wxString &pSqlStmt, int typeOfDel, const wxStrin // delete all records from the database in this case. if (typeOfDel == DB_DEL_WHERE && (pWhereClause.Length() == 0)) { - pSqlStmt.Printf(wxT("DELETE FROM %s"), tableName.c_str()); + pSqlStmt.Printf(wxT("DELETE FROM %s"), + pDb->SQLTableName(tableName.c_str()).c_str()); return; } - pSqlStmt.Printf(wxT("DELETE FROM %s WHERE "), tableName.c_str()); + pSqlStmt.Printf(wxT("DELETE FROM %s WHERE "), + pDb->SQLTableName(tableName.c_str()).c_str()); // Append the WHERE clause to the SQL DELETE statement switch(typeOfDel) @@ -993,15 +1042,17 @@ void wxDbTable::BuildSelectStmt(wxString &pSqlStmt, int typeOfSelect, bool disti // Add the column list int i; + wxString tStr; for (i = 0; i < noCols; i++) { + tStr = colDefs[i].ColName; // If joining tables, the base table column names must be qualified to avoid ambiguity - if (appendFromClause || pDb->Dbms() == dbmsACCESS) + if ((appendFromClause || pDb->Dbms() == dbmsACCESS) && !tStr.Find(wxT('.'))) { - pSqlStmt += queryTableName; + pSqlStmt += pDb->SQLTableName(queryTableName.c_str()); pSqlStmt += wxT("."); } - pSqlStmt += colDefs[i].ColName; + pSqlStmt += pDb->SQLColumnName(colDefs[i].ColName); if (i + 1 < noCols) pSqlStmt += wxT(","); } @@ -1014,7 +1065,8 @@ void wxDbTable::BuildSelectStmt(wxString &pSqlStmt, int typeOfSelect, bool disti if (appendFromClause || pDb->Dbms() == dbmsACCESS) { pSqlStmt += wxT(","); - pSqlStmt += queryTableName; + pSqlStmt += pDb->SQLTableName(queryTableName); +// pSqlStmt += queryTableName; pSqlStmt += wxT(".ROWID"); } else @@ -1023,7 +1075,8 @@ void wxDbTable::BuildSelectStmt(wxString &pSqlStmt, int typeOfSelect, bool disti // Append the FROM tablename portion pSqlStmt += wxT(" FROM "); - pSqlStmt += queryTableName; + pSqlStmt += pDb->SQLTableName(queryTableName); +// pSqlStmt += queryTableName; // Sybase uses the HOLDLOCK keyword to lock a record during query. // The HOLDLOCK keyword follows the table name in the from clause. @@ -1110,7 +1163,8 @@ void wxDbTable::BuildUpdateStmt(wxString &pSqlStmt, int typeOfUpd, const wxStrin bool firstColumn = TRUE; - pSqlStmt.Printf(wxT("UPDATE %s SET "), tableName.Upper().c_str()); + pSqlStmt.Printf(wxT("UPDATE %s SET "), + pDb->SQLTableName(tableName.c_str()).c_str()); // Append a list of columns to be updated int i; @@ -1123,7 +1177,9 @@ void wxDbTable::BuildUpdateStmt(wxString &pSqlStmt, int typeOfUpd, const wxStrin pSqlStmt += wxT(","); else firstColumn = FALSE; - pSqlStmt += colDefs[i].ColName; + + pSqlStmt += pDb->SQLColumnName(colDefs[i].ColName); +// pSqlStmt += colDefs[i].ColName; pSqlStmt += wxT(" = ?"); } } @@ -1185,54 +1241,59 @@ void wxDbTable::BuildWhereClause(wxString &pWhereClause, int typeOfWhere, wxString colValue; // Loop through the columns building a where clause as you go - int i; - for (i = 0; i < noCols; i++) + int colNo; + for (colNo = 0; colNo < noCols; colNo++) { // Determine if this column should be included in the WHERE clause - if ((typeOfWhere == DB_WHERE_KEYFIELDS && colDefs[i].KeyField) || - (typeOfWhere == DB_WHERE_MATCHING && (!IsColNull(i)))) + if ((typeOfWhere == DB_WHERE_KEYFIELDS && colDefs[colNo].KeyField) || + (typeOfWhere == DB_WHERE_MATCHING && (!IsColNull(colNo)))) { // Skip over timestamp columns - if (colDefs[i].SqlCtype == SQL_C_TIMESTAMP) + if (colDefs[colNo].SqlCtype == SQL_C_TIMESTAMP) continue; // If there is more than 1 column, join them with the keyword "AND" if (moreThanOneColumn) pWhereClause += wxT(" AND "); else moreThanOneColumn = TRUE; + // Concatenate where phrase for the column - if (qualTableName.Length()) + wxString tStr = colDefs[colNo].ColName; + + if (qualTableName.Length() && !tStr.Find(wxT('.'))) { - pWhereClause += qualTableName; + pWhereClause += pDb->SQLTableName(qualTableName); pWhereClause += wxT("."); } - pWhereClause += colDefs[i].ColName; - if (useLikeComparison && (colDefs[i].SqlCtype == SQL_C_CHAR)) + pWhereClause += pDb->SQLColumnName(colDefs[colNo].ColName); + + if (useLikeComparison && (colDefs[colNo].SqlCtype == SQL_C_CHAR)) pWhereClause += wxT(" LIKE "); else pWhereClause += wxT(" = "); - switch(colDefs[i].SqlCtype) + + switch(colDefs[colNo].SqlCtype) { case SQL_C_CHAR: - colValue.Printf(wxT("'%s'"), (UCHAR FAR *) colDefs[i].PtrDataObj); + colValue.Printf(wxT("'%s'"), (UCHAR FAR *) colDefs[colNo].PtrDataObj); break; case SQL_C_SSHORT: - colValue.Printf(wxT("%hi"), *((SWORD *) colDefs[i].PtrDataObj)); + colValue.Printf(wxT("%hi"), *((SWORD *) colDefs[colNo].PtrDataObj)); break; case SQL_C_USHORT: - colValue.Printf(wxT("%hu"), *((UWORD *) colDefs[i].PtrDataObj)); + colValue.Printf(wxT("%hu"), *((UWORD *) colDefs[colNo].PtrDataObj)); break; case SQL_C_SLONG: - colValue.Printf(wxT("%li"), *((SDWORD *) colDefs[i].PtrDataObj)); + colValue.Printf(wxT("%li"), *((SDWORD *) colDefs[colNo].PtrDataObj)); break; case SQL_C_ULONG: - colValue.Printf(wxT("%lu"), *((UDWORD *) colDefs[i].PtrDataObj)); + colValue.Printf(wxT("%lu"), *((UDWORD *) colDefs[colNo].PtrDataObj)); break; case SQL_C_FLOAT: - colValue.Printf(wxT("%.6f"), *((SFLOAT *) colDefs[i].PtrDataObj)); + colValue.Printf(wxT("%.6f"), *((SFLOAT *) colDefs[colNo].PtrDataObj)); break; case SQL_C_DOUBLE: - colValue.Printf(wxT("%.6f"), *((SDOUBLE *) colDefs[i].PtrDataObj)); + colValue.Printf(wxT("%.6f"), *((SDOUBLE *) colDefs[colNo].PtrDataObj)); break; } pWhereClause += colValue; @@ -1329,7 +1390,9 @@ bool wxDbTable::CreateTable(bool attemptDrop) // Build a CREATE TABLE string from the colDefs structure. bool needComma = FALSE; - sqlStmt.Printf(wxT("CREATE TABLE %s ("), tableName.c_str()); + + sqlStmt.Printf(wxT("CREATE TABLE %s ("), + pDb->SQLTableName(tableName.c_str()).c_str()); for (i = 0; i < noCols; i++) { @@ -1340,7 +1403,8 @@ bool wxDbTable::CreateTable(bool attemptDrop) if (needComma) sqlStmt += wxT(","); // Column Name - sqlStmt += colDefs[i].ColName; + sqlStmt += pDb->SQLColumnName(colDefs[i].ColName); +// sqlStmt += colDefs[i].ColName; sqlStmt += wxT(" "); // Column Type switch(colDefs[i].DbDataType) @@ -1362,7 +1426,8 @@ bool wxDbTable::CreateTable(bool attemptDrop) 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 && + (pDb->Dbms() != dbmsMY_SQL || pDb->GetTypeInfVarchar().TypeName != _T("text")))// || // colDefs[i].DbDataType == DB_DATA_TYPE_BLOB) { wxString s; @@ -1381,7 +1446,7 @@ bool wxDbTable::CreateTable(bool attemptDrop) sqlStmt += wxT(" NOT NULL"); } } - + needComma = TRUE; } // If there is a primary key defined, include it in the create statement @@ -1393,10 +1458,12 @@ bool wxDbTable::CreateTable(bool attemptDrop) break; } } - if (j && pDb->Dbms() != dbmsDBASE) // Found a keyfield + if ( j && (pDb->Dbms() != dbmsDBASE) + && (pDb->Dbms() != dbmsXBASE_SEQUITER) ) // Found a keyfield { switch (pDb->Dbms()) { + case dbmsACCESS: case dbmsINFORMIX: case dbmsSYBASE_ASA: case dbmsSYBASE_ASE: @@ -1413,10 +1480,12 @@ bool wxDbTable::CreateTable(bool attemptDrop) 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); + sqlStmt += pDb->SQLTableName(tableName.substr(0, 13).c_str()); +// sqlStmt += tableName.substr(0, 13); } else - sqlStmt += tableName; + sqlStmt += pDb->SQLTableName(tableName.c_str()); +// sqlStmt += tableName; sqlStmt += wxT("_PIDX PRIMARY KEY ("); break; @@ -1430,7 +1499,15 @@ bool wxDbTable::CreateTable(bool attemptDrop) { if (j++) // Multi part key, comma separate names sqlStmt += wxT(","); - sqlStmt += colDefs[i].ColName; + sqlStmt += pDb->SQLColumnName(colDefs[i].ColName); + + if (pDb->Dbms() == dbmsMY_SQL && + colDefs[i].DbDataType == DB_DATA_TYPE_VARCHAR) + { + wxString s; + s.Printf(wxT("(%d)"), colDefs[i].SzDataObj); + sqlStmt += s; + } } } sqlStmt += wxT(")"); @@ -1440,7 +1517,8 @@ bool wxDbTable::CreateTable(bool attemptDrop) pDb->Dbms() == dbmsSYBASE_ASE) { sqlStmt += wxT(" CONSTRAINT "); - sqlStmt += tableName; + sqlStmt += pDb->SQLTableName(tableName); +// sqlStmt += tableName; sqlStmt += wxT("_PIDX"); } } @@ -1454,7 +1532,7 @@ bool wxDbTable::CreateTable(bool attemptDrop) #endif // Execute the CREATE TABLE statement - RETCODE retcode = SQLExecDirect(hstmt, (UCHAR FAR *) sqlStmt.c_str(), SQL_NTS); + RETCODE retcode = SQLExecDirect(hstmt, (SQLTCHAR FAR *) sqlStmt.c_str(), SQL_NTS); if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) { pDb->DispAllErrors(henv, hdbc, hstmt); @@ -1485,7 +1563,8 @@ bool wxDbTable::DropTable() wxString sqlStmt; - sqlStmt.Printf(wxT("DROP TABLE %s"), tableName.c_str()); + sqlStmt.Printf(wxT("DROP TABLE %s"), + pDb->SQLTableName(tableName.c_str()).c_str()); pDb->WriteSqlLog(sqlStmt); @@ -1493,22 +1572,19 @@ bool wxDbTable::DropTable() cout << endl << sqlStmt.c_str() << endl; #endif - - - - RETCODE retcode = SQLExecDirect(hstmt, (UCHAR FAR *) sqlStmt.c_str(), SQL_NTS); + RETCODE retcode = SQLExecDirect(hstmt, (SQLTCHAR FAR *) sqlStmt.c_str(), SQL_NTS); if (retcode != SQL_SUCCESS) { // Check for "Base table not found" error and ignore - pDb->GetNextError(henv, hdbc, hstmt); + pDb->GetNextError(henv, hdbc, hstmt); if (wxStrcmp(pDb->sqlState, wxT("S0002")) /*&& - wxStrcmp(pDb->sqlState, wxT("S1000"))*/) // "Base table not found" + 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() == 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->Dbms() == dbmsPOSTGRES && !wxStrcmp(pDb->sqlState,wxT("08S01"))))) { pDb->DispNextError(); pDb->DispAllErrors(henv, hdbc, hstmt); @@ -1567,7 +1643,7 @@ bool wxDbTable::CreateIndex(const wxString &idxName, bool unique, UWORD noIdxCol if (!found) j++; } - + if (found) { ok = pDb->ModifyColumn(tableName, pIdxDefs[i].ColName, @@ -1576,11 +1652,14 @@ bool wxDbTable::CreateIndex(const wxString &idxName, bool unique, UWORD noIdxCol if (!ok) { + #if 0 + // retcode is not used wxODBC_ERRORS retcode; // Oracle returns a DB_ERR_GENERAL_ERROR if the column is already // defined to be NOT NULL, but reportedly MySQL doesn't mind. // This line is just here for debug checking of the value retcode = (wxODBC_ERRORS)pDb->DB_STATUS; + #endif } } else @@ -1594,26 +1673,49 @@ bool wxDbTable::CreateIndex(const wxString &idxName, bool unique, UWORD noIdxCol return(FALSE); } } - + // Build a CREATE INDEX statement sqlStmt = wxT("CREATE "); if (unique) sqlStmt += wxT("UNIQUE "); - + sqlStmt += wxT("INDEX "); - sqlStmt += idxName; + sqlStmt += pDb->SQLTableName(idxName); sqlStmt += wxT(" ON "); - sqlStmt += tableName; + + sqlStmt += pDb->SQLTableName(tableName); +// sqlStmt += tableName; sqlStmt += wxT(" ("); - + // Append list of columns making up index int i; for (i = 0; i < noIdxCols; i++) { - sqlStmt += pIdxDefs[i].ColName; + sqlStmt += pDb->SQLColumnName(pIdxDefs[i].ColName); +// sqlStmt += pIdxDefs[i].ColName; + // MySQL requires a key length on VARCHAR keys + if ( pDb->Dbms() == dbmsMY_SQL ) + { + // Find the details on this column + int j; + for ( j = 0; j < noCols; ++j ) + { + if ( wxStrcmp( pIdxDefs[i].ColName, colDefs[j].ColName ) == 0 ) + { + break; + } + } + if ( colDefs[j].DbDataType == DB_DATA_TYPE_VARCHAR) + { + wxString s; + s.Printf(wxT("(%d)"), colDefs[i].SzDataObj); + sqlStmt += s; + } + } + // 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)) && + if (!((pDb->Dbms() == dbmsMS_SQL_SERVER) && (wxStrncmp(pDb->dbInf.dbmsVer,_T("07"),2)==0)) && !(pDb->Dbms() == dbmsPOSTGRES)) { if (pIdxDefs[i].Ascending) @@ -1622,12 +1724,12 @@ bool wxDbTable::CreateIndex(const wxString &idxName, bool unique, UWORD noIdxCol sqlStmt += wxT(" DESC"); } else - wxASSERT_MSG(pIdxDefs[i].Ascending, "Datasource does not support DESCending index columns"); + wxASSERT_MSG(pIdxDefs[i].Ascending, _T("Datasource does not support DESCending index columns")); if ((i + 1) < noIdxCols) sqlStmt += wxT(","); } - + // Append closing parentheses sqlStmt += wxT(")"); @@ -1638,7 +1740,7 @@ bool wxDbTable::CreateIndex(const wxString &idxName, bool unique, UWORD noIdxCol #endif // Execute the CREATE INDEX statement - if (SQLExecDirect(hstmt, (UCHAR FAR *) sqlStmt.c_str(), SQL_NTS) != SQL_SUCCESS) + if (SQLExecDirect(hstmt, (SQLTCHAR FAR *) sqlStmt.c_str(), SQL_NTS) != SQL_SUCCESS) { pDb->DispAllErrors(henv, hdbc, hstmt); pDb->RollbackTrans(); @@ -1670,12 +1772,18 @@ bool wxDbTable::DropIndex(const wxString &idxName) 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()); + sqlStmt.Printf(wxT("DROP INDEX %s ON %s"), + pDb->SQLTableName(idxName.c_str()).c_str(), + pDb->SQLTableName(tableName.c_str()).c_str()); else if ((pDb->Dbms() == dbmsMS_SQL_SERVER) || - (pDb->Dbms() == dbmsSYBASE_ASE)) - sqlStmt.Printf(wxT("DROP INDEX %s.%s"),tableName.c_str(), idxName.c_str()); + (pDb->Dbms() == dbmsSYBASE_ASE) || + (pDb->Dbms() == dbmsXBASE_SEQUITER)) + sqlStmt.Printf(wxT("DROP INDEX %s.%s"), + pDb->SQLTableName(tableName.c_str()).c_str(), + pDb->SQLTableName(idxName.c_str()).c_str()); else - sqlStmt.Printf(wxT("DROP INDEX %s"),idxName.c_str()); + sqlStmt.Printf(wxT("DROP INDEX %s"), + pDb->SQLTableName(idxName.c_str()).c_str()); pDb->WriteSqlLog(sqlStmt); @@ -1683,7 +1791,7 @@ bool wxDbTable::DropIndex(const wxString &idxName) cout << endl << sqlStmt.c_str() << endl; #endif - if (SQLExecDirect(hstmt, (UCHAR FAR *) sqlStmt.c_str(), SQL_NTS) != SQL_SUCCESS) + if (SQLExecDirect(hstmt, (SQLTCHAR FAR *) sqlStmt.c_str(), SQL_NTS) != SQL_SUCCESS) { // Check for "Index not found" error and ignore pDb->GetNextError(henv, hdbc, hstmt); @@ -1766,7 +1874,8 @@ int wxDbTable::Insert(void) // Insert the record by executing the already prepared insert statement RETCODE retcode; retcode=SQLExecute(hstmtInsert); - if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO && + retcode != SQL_NEED_DATA) { // Check to see if integrity constraint was violated pDb->GetNextError(henv, hdbc, hstmtInsert); @@ -1779,6 +1888,31 @@ int wxDbTable::Insert(void) return(DB_FAILURE); } } + if (retcode == SQL_NEED_DATA) + { + PTR pParmID; + retcode = SQLParamData(hstmtInsert, &pParmID); + while (retcode == SQL_NEED_DATA) + { + // Find the parameter + int i; + for (i=0; i < noCols; i++) + { + if (colDefs[i].PtrDataObj == pParmID) + { + // We found it. Store the parameter. + retcode = SQLPutData(hstmtInsert, pParmID, colDefs[i].SzDataObj); + if (retcode != SQL_SUCCESS) + { + pDb->DispNextError(); + pDb->DispAllErrors(henv, hdbc, hstmtInsert); + return(DB_FAILURE); + } + break; + } + } + } + } // Record inserted into the datasource successfully return(DB_SUCCESS); @@ -2077,17 +2211,23 @@ void wxDbTable::SetColDefs(UWORD index, const wxString &fieldName, int dataType, SWORD cType, int size, bool keyField, bool upd, bool insAllow, bool derivedCol) { + wxASSERT_MSG( index < noCols, + _T("Specified column index exceeds the maximum number of columns for this table.") ); + if (!colDefs) // May happen if the database connection fails return; if (fieldName.Length() > (unsigned int) 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; + +#ifdef __WXDEBUG__ 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()); + tmpMsg.Printf(_T("Column name '%s' is too long. Truncated to '%s'."), + fieldName.c_str(),colDefs[index].ColName); + wxFAIL_MSG(tmpMsg); +#endif // __WXDEBUG__ } else wxStrcpy(colDefs[index].ColName, fieldName); @@ -2111,7 +2251,7 @@ void wxDbTable::SetColDefs(UWORD index, const wxString &fieldName, int dataType, } colDefs[index].Null = FALSE; - + } // wxDbTable::SetColDefs() @@ -2124,7 +2264,7 @@ wxDbColDataPtr* wxDbTable::SetColDefs(wxDbColInf *pColInfs, UWORD numCols) if (pColInfs) { UWORD index; - + pColDataPtrs = new wxDbColDataPtr[numCols+1]; for (index = 0; index < numCols; index++) @@ -2165,7 +2305,7 @@ wxDbColDataPtr* wxDbTable::SetColDefs(wxDbColInf *pColInfs, UWORD numCols) pColDataPtrs[index].PtrDataObj = new double; pColDataPtrs[index].SzDataObj = sizeof(double); pColDataPtrs[index].SqlCtype = SQL_C_DOUBLE; - } + } break; case DB_DATA_TYPE_DATE: pColDataPtrs[index].PtrDataObj = new TIMESTAMP_STRUCT; @@ -2173,8 +2313,7 @@ wxDbColDataPtr* wxDbTable::SetColDefs(wxDbColInf *pColInfs, UWORD numCols) 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")); + wxFAIL_MSG(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; @@ -2184,7 +2323,7 @@ wxDbColDataPtr* wxDbTable::SetColDefs(wxDbColInf *pColInfs, UWORD numCols) 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 + // 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 @@ -2222,7 +2361,8 @@ ULONG wxDbTable::Count(const wxString &args) sqlStmt = wxT("SELECT COUNT("); sqlStmt += args; sqlStmt += wxT(") FROM "); - sqlStmt += queryTableName; + sqlStmt += pDb->SQLTableName(queryTableName); +// sqlStmt += queryTableName; #if wxODBC_BACKWARD_COMPATABILITY if (from && wxStrlen(from)) #else @@ -2253,7 +2393,7 @@ ULONG wxDbTable::Count(const wxString &args) } // Execute the SQL statement - if (SQLExecDirect(*hstmtCount, (UCHAR FAR *) sqlStmt.c_str(), SQL_NTS) != SQL_SUCCESS) + if (SQLExecDirect(*hstmtCount, (SQLTCHAR FAR *) sqlStmt.c_str(), SQL_NTS) != SQL_SUCCESS) { pDb->DispAllErrors(henv, hdbc, *hstmtCount); return(0); @@ -2293,8 +2433,8 @@ bool wxDbTable::Refresh(void) hstmt = hstmtInternal; #if wxODBC_BACKWARD_COMPATABILITY // Save the where and order by clauses - char *saveWhere = where; - char *saveOrderBy = orderBy; + wxChar *saveWhere = where; + wxChar *saveOrderBy = orderBy; #else wxString saveWhere = where; wxString saveOrderBy = orderBy; @@ -2314,7 +2454,8 @@ bool wxDbTable::Refresh(void) // based on the key fields. if (SQLGetData(hstmt, (UWORD)(noCols+1), SQL_C_CHAR, (UCHAR*) rowid, wxDB_ROWID_LEN, &cb) == SQL_SUCCESS) { - whereClause += queryTableName; + whereClause += pDb->SQLTableName(queryTableName); +// whereClause += queryTableName; whereClause += wxT(".ROWID = '"); whereClause += rowid; whereClause += wxT("'"); @@ -2357,7 +2498,10 @@ bool wxDbTable::SetColNull(UWORD colNo, bool set) { colDefs[colNo].Null = set; if (set) // Blank out the values in the member variable - ClearMemberVar(colNo,FALSE); // Must call with FALSE, or infinite recursion will happen + { + colDefs[colNo].CbValue = SQL_NULL_DATA; // SF PATCH#766404 + ClearMemberVar(colNo,FALSE); // Must call with FALSE, or infinite recursion will happen + } return(TRUE); } else @@ -2369,18 +2513,21 @@ bool wxDbTable::SetColNull(UWORD colNo, bool set) /********** wxDbTable::SetColNull() **********/ bool wxDbTable::SetColNull(const wxString &colName, bool set) { - int i; - for (i = 0; i < noCols; i++) + int colNo; + for (colNo = 0; colNo < noCols; colNo++) { - if (!wxStricmp(colName, colDefs[i].ColName)) + if (!wxStricmp(colName, colDefs[colNo].ColName)) break; } - if (i < noCols) + if (colNo < noCols) { - colDefs[i].Null = set; + colDefs[colNo].Null = set; if (set) // Blank out the values in the member variable - ClearMemberVar(i,FALSE); // Must call with FALSE, or infinite recursion will happen + { + colDefs[colNo].CbValue = SQL_NULL_DATA; // SF PATCH#766404 + ClearMemberVar(colNo,FALSE); // Must call with FALSE, or infinite recursion will happen + } return(TRUE); } else @@ -2439,7 +2586,7 @@ bool wxDbTable::DeleteCursor(HSTMT *hstmtDel) /* ODBC 3.0 says to use this form if (SQLFreeHandle(*hstmtDel, SQL_DROP) != SQL_SUCCESS) - + */ if (SQLFreeStmt(*hstmtDel, SQL_DROP) != SQL_SUCCESS) { @@ -2476,53 +2623,53 @@ void wxDbTable::SetRowMode(const rowmode_t rowmode) SetCursor(hstmtDefault); break; default: - assert(0); + wxASSERT(0); } } // wxDbTable::SetRowMode() -wxVariant wxDbTable::GetCol(const int col) const +wxVariant wxDbTable::GetCol(const int colNo) const { wxVariant val; - if ((col < noCols) && (!IsColNull(col))) + if ((colNo < noCols) && (!IsColNull(colNo))) { - switch (colDefs[col].SqlCtype) + switch (colDefs[colNo].SqlCtype) { case SQL_CHAR: case SQL_VARCHAR: - val = (char *)(colDefs[col].PtrDataObj); + val = (wxChar *)(colDefs[colNo].PtrDataObj); break; case SQL_C_LONG: case SQL_C_SLONG: - val = *(long *)(colDefs[col].PtrDataObj); + val = *(long *)(colDefs[colNo].PtrDataObj); break; case SQL_C_SHORT: case SQL_C_SSHORT: - val = (long int )(*(short *)(colDefs[col].PtrDataObj)); + val = (long int )(*(short *)(colDefs[colNo].PtrDataObj)); break; case SQL_C_ULONG: - val = (long)(*(unsigned long *)(colDefs[col].PtrDataObj)); + val = (long)(*(unsigned long *)(colDefs[colNo].PtrDataObj)); break; case SQL_C_TINYINT: - val = (long)(*(char *)(colDefs[col].PtrDataObj)); + val = (long)(*(wxChar *)(colDefs[colNo].PtrDataObj)); break; case SQL_C_UTINYINT: - val = (long)(*(unsigned char *)(colDefs[col].PtrDataObj)); + val = (long)(*(wxChar *)(colDefs[colNo].PtrDataObj)); break; case SQL_C_USHORT: - val = (long)(*(UWORD *)(colDefs[col].PtrDataObj)); + val = (long)(*(UWORD *)(colDefs[colNo].PtrDataObj)); break; case SQL_C_DATE: - val = (DATE_STRUCT *)(colDefs[col].PtrDataObj); + val = (DATE_STRUCT *)(colDefs[colNo].PtrDataObj); break; case SQL_C_TIME: - val = (TIME_STRUCT *)(colDefs[col].PtrDataObj); + val = (TIME_STRUCT *)(colDefs[colNo].PtrDataObj); break; case SQL_C_TIMESTAMP: - val = (TIMESTAMP_STRUCT *)(colDefs[col].PtrDataObj); + val = (TIMESTAMP_STRUCT *)(colDefs[colNo].PtrDataObj); break; case SQL_C_DOUBLE: - val = *(double *)(colDefs[col].PtrDataObj); + val = *(double *)(colDefs[colNo].PtrDataObj); break; default: assert(0); @@ -2532,66 +2679,58 @@ wxVariant wxDbTable::GetCol(const int col) const } // wxDbTable::GetCol() -void csstrncpyt(char *s, const char *t, int n) -{ - while ((*s++ = *t++) && --n) - {}; - - *s = '\0'; -} - -void wxDbTable::SetCol(const int col, const wxVariant val) +void wxDbTable::SetCol(const int colNo, const wxVariant val) { //FIXME: Add proper wxDateTime support to wxVariant.. wxDateTime dateval; - SetColNull(col, val.IsNull()); + SetColNull(colNo, val.IsNull()); if (!val.IsNull()) { - if ((colDefs[col].SqlCtype == SQL_C_DATE) - || (colDefs[col].SqlCtype == SQL_C_TIME) - || (colDefs[col].SqlCtype == SQL_C_TIMESTAMP)) + if ((colDefs[colNo].SqlCtype == SQL_C_DATE) + || (colDefs[colNo].SqlCtype == SQL_C_TIME) + || (colDefs[colNo].SqlCtype == SQL_C_TIMESTAMP)) { //Returns null if invalid! if (!dateval.ParseDate(val.GetString())) - SetColNull(col,TRUE); - } + SetColNull(colNo, TRUE); + } - switch (colDefs[col].SqlCtype) + switch (colDefs[colNo].SqlCtype) { case SQL_CHAR: case SQL_VARCHAR: - csstrncpyt((char *)(colDefs[col].PtrDataObj), - val.GetString().c_str(), - colDefs[col].SzDataObj-1); + csstrncpyt((wxChar *)(colDefs[colNo].PtrDataObj), + val.GetString().c_str(), + colDefs[colNo].SzDataObj-1); break; case SQL_C_LONG: case SQL_C_SLONG: - *(long *)(colDefs[col].PtrDataObj) = val; + *(long *)(colDefs[colNo].PtrDataObj) = val; break; case SQL_C_SHORT: case SQL_C_SSHORT: - *(short *)(colDefs[col].PtrDataObj) = val.GetLong(); + *(short *)(colDefs[colNo].PtrDataObj) = val.GetLong(); break; case SQL_C_ULONG: - *(unsigned long *)(colDefs[col].PtrDataObj) = val.GetLong(); + *(unsigned long *)(colDefs[colNo].PtrDataObj) = val.GetLong(); break; case SQL_C_TINYINT: - *(char *)(colDefs[col].PtrDataObj) = val.GetChar(); + *(wxChar *)(colDefs[colNo].PtrDataObj) = val.GetChar(); break; case SQL_C_UTINYINT: - *(unsigned char *)(colDefs[col].PtrDataObj) = val.GetChar(); + *(wxChar *)(colDefs[colNo].PtrDataObj) = val.GetChar(); break; case SQL_C_USHORT: - *(unsigned short *)(colDefs[col].PtrDataObj) = val.GetLong(); + *(unsigned short *)(colDefs[colNo].PtrDataObj) = val.GetLong(); break; //FIXME: Add proper wxDateTime support to wxVariant.. case SQL_C_DATE: { DATE_STRUCT *dataptr = - (DATE_STRUCT *)colDefs[col].PtrDataObj; - + (DATE_STRUCT *)colDefs[colNo].PtrDataObj; + dataptr->year = dateval.GetYear(); dataptr->month = dateval.GetMonth()+1; dataptr->day = dateval.GetDay(); @@ -2600,8 +2739,8 @@ void wxDbTable::SetCol(const int col, const wxVariant val) case SQL_C_TIME: { TIME_STRUCT *dataptr = - (TIME_STRUCT *)colDefs[col].PtrDataObj; - + (TIME_STRUCT *)colDefs[colNo].PtrDataObj; + dataptr->hour = dateval.GetHour(); dataptr->minute = dateval.GetMinute(); dataptr->second = dateval.GetSecond(); @@ -2610,18 +2749,18 @@ void wxDbTable::SetCol(const int col, const wxVariant val) case SQL_C_TIMESTAMP: { TIMESTAMP_STRUCT *dataptr = - (TIMESTAMP_STRUCT *)colDefs[col].PtrDataObj; + (TIMESTAMP_STRUCT *)colDefs[colNo].PtrDataObj; dataptr->year = dateval.GetYear(); dataptr->month = dateval.GetMonth()+1; dataptr->day = dateval.GetDay(); - + dataptr->hour = dateval.GetHour(); dataptr->minute = dateval.GetMinute(); dataptr->second = dateval.GetSecond(); } break; case SQL_C_DOUBLE: - *(double *)(colDefs[col].PtrDataObj) = val; + *(double *)(colDefs[colNo].PtrDataObj) = val; break; default: assert(0); @@ -2633,11 +2772,11 @@ void wxDbTable::SetCol(const int col, const wxVariant val) GenericKey wxDbTable::GetKey() { void *blk; - char *blkptr; - + wxChar *blkptr; + blk = malloc(m_keysize); - blkptr = (char *) blk; - + blkptr = (wxChar *) blk; + int i; for (i=0; i < noCols; i++) { @@ -2657,11 +2796,11 @@ GenericKey wxDbTable::GetKey() void wxDbTable::SetKey(const GenericKey& k) { - void *blk; - char *blkptr; - + void *blk; + wxChar *blkptr; + blk = k.GetBlk(); - blkptr = (char *)blk; + blkptr = (wxChar *)blk; int i; for (i=0; i < noCols; i++)