X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/5a226de06289ba03a767f6643ff62042ba348e68..d3211838bf578eb8ada5a608b66626a6bde6846a:/src/common/dbtable.cpp diff --git a/src/common/dbtable.cpp b/src/common/dbtable.cpp index 0df9c08bc4..234c9c72a5 100644 --- a/src/common/dbtable.cpp +++ b/src/common/dbtable.cpp @@ -24,51 +24,30 @@ // SYNOPSIS START // SYNOPSIS STOP */ +#ifdef __GNUG__ + #pragma implementation "dbtable.h" +#endif -// Use this line for wxWindows v1.x -//#include "wx_ver.h" -// Use this line for wxWindows v2.x #include "wx/wxprec.h" -#include "wx/version.h" -#if wxMAJOR_VERSION == 2 - #ifdef __GNUG__ - #pragma implementation "dbtable.h" - #endif +#ifdef __BORLANDC__ + #pragma hdrstop #endif #ifdef DBDEBUG_CONSOLE + #include "iostream.h" #include "wx/ioswrap.h" #endif - -#ifdef __BORLANDC__ - #pragma hdrstop -#endif //__BORLANDC__ - -#if wxMAJOR_VERSION == 2 - #ifndef WX_PRECOMP - #include "wx/string.h" - #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" -#endif - -#if wxMAJOR_VERSION == 1 -# if defined(wx_msw) || defined(wx_x) -# ifdef WX_PRECOMP -# include "wx_prec.h" -# else -# include "wx.h" -# endif -# endif -# define wxUSE_ODBC 1 +#ifndef WX_PRECOMP + #include "wx/string.h" + #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" #if wxUSE_ODBC @@ -77,11 +56,7 @@ #include //#include -#if wxMAJOR_VERSION == 1 - #include "table.h" -#elif wxMAJOR_VERSION == 2 - #include "wx/dbtable.h" -#endif +#include "wx/dbtable.h" #ifdef __UNIX__ // The HPUX preprocessor lines below were commented out on 8/20/97 @@ -162,6 +137,7 @@ bool wxDbTable::initialize(wxDb *pwxDb, const wxString &tblName, const UWORD num henv = 0; hdbc = 0; hstmt = 0; + m_hstmtGridQuery = 0; hstmtDefault = 0; // Initialized below hstmtCount = 0; // Initialized first time it is needed hstmtInsert = 0; @@ -203,7 +179,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 +327,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...")); } } @@ -411,6 +387,10 @@ ODBC 3.0 says to use this form if (hstmtCount) DeleteCursor(hstmtCount); + + if (m_hstmtGridQuery) + DeleteCursor(m_hstmtGridQuery); + } // wxDbTable::cleanup() @@ -675,22 +655,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); @@ -719,6 +684,19 @@ bool wxDbTable::Open(bool checkPrivileges, bool checkTableExists) int i; wxString sqlStmt; wxString s; +// int NumKeyCols=0; + + // Calculate the maximum size of the concatenated + // keys for use with wxDbGrid + m_keysize = 0; + for (i=0; i < noCols; i++) + { + if (colDefs[i].KeyField) + { +// NumKeyCols++; + m_keysize += colDefs[i].SzDataObj; + } + } s.Empty(); // Verify that the table exists in the database @@ -1141,7 +1119,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; @@ -1330,19 +1308,19 @@ bool wxDbTable::CreateTable(bool attemptDrop) switch(colDefs[i].DbDataType) { case DB_DATA_TYPE_VARCHAR: - cout << pDb->typeInfVarchar.TypeName << wxT("(") << colDefs[i].SzDataObj << wxT(")"); + cout << pDb->GetTypeInfVarchar().TypeName << wxT("(") << colDefs[i].SzDataObj << wxT(")"); break; case DB_DATA_TYPE_INTEGER: - cout << pDb->typeInfInteger.TypeName; + cout << pDb->GetTypeInfInteger().TypeName; break; case DB_DATA_TYPE_FLOAT: - cout << pDb->typeInfFloat.TypeName; + cout << pDb->GetTypeInfFloat().TypeName; break; case DB_DATA_TYPE_DATE: - cout << pDb->typeInfDate.TypeName; + cout << pDb->GetTypeInfDate().TypeName; break; case DB_DATA_TYPE_BLOB: - cout << pDb->typeInfBlob.TypeName; + cout << pDb->GetTypeInfBlob().TypeName; break; } cout << endl; @@ -1395,6 +1373,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) @@ -1418,6 +1397,7 @@ bool wxDbTable::CreateTable(bool attemptDrop) { switch (pDb->Dbms()) { + case dbmsINFORMIX: case dbmsSYBASE_ASA: case dbmsSYBASE_ASE: case dbmsMY_SQL: @@ -1455,7 +1435,8 @@ bool wxDbTable::CreateTable(bool attemptDrop) } sqlStmt += wxT(")"); - if (pDb->Dbms() == dbmsSYBASE_ASA || + if (pDb->Dbms() == dbmsINFORMIX || + pDb->Dbms() == dbmsSYBASE_ASA || pDb->Dbms() == dbmsSYBASE_ASE) { sqlStmt += wxT(" CONSTRAINT "); @@ -1630,14 +1611,18 @@ bool wxDbTable::CreateIndex(const wxString &idxName, bool unique, UWORD noIdxCol 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(","); @@ -1708,6 +1693,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"))) @@ -1926,7 +1912,7 @@ bool wxDbTable::DeleteMatching(void) /********** wxDbTable::IsColNull() **********/ -bool wxDbTable::IsColNull(UWORD colNo) +bool wxDbTable::IsColNull(UWORD colNo) const { /* This logic is just not right. It would indicate TRUE @@ -2096,8 +2082,12 @@ void wxDbTable::SetColDefs(UWORD index, const wxString &fieldName, int dataType, 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); @@ -2423,7 +2413,7 @@ HSTMT *wxDbTable::GetNewCursor(bool setCursor, bool bindColumns) if (bindColumns) { - if(!bindCols(*newHSTMT)) + if (!bindCols(*newHSTMT)) { delete newHSTMT; return(0); @@ -2463,5 +2453,228 @@ ODBC 3.0 says to use this form } // wxDbTable::DeleteCursor() +////////////////////////////////////////////////////////////// +// wxDbGrid support functions +////////////////////////////////////////////////////////////// + +void wxDbTable::SetRowMode(const rowmode_t rowmode) +{ + if (!m_hstmtGridQuery) + { + m_hstmtGridQuery = GetNewCursor(FALSE,FALSE); + if (!bindCols(*m_hstmtGridQuery)) + return; + } + + m_rowmode = rowmode; + switch (m_rowmode) + { + case WX_ROW_MODE_QUERY: + SetCursor(m_hstmtGridQuery); + break; + case WX_ROW_MODE_INDIVIDUAL: + SetCursor(hstmtDefault); + break; + default: + assert(0); + } +} // wxDbTable::SetRowMode() + + +wxVariant wxDbTable::GetCol(const int col) const +{ + wxVariant val; + if ((col < noCols) && (!IsColNull(col))) + { + switch (colDefs[col].SqlCtype) + { + case SQL_CHAR: + case SQL_VARCHAR: + val = (char *)(colDefs[col].PtrDataObj); + break; + case SQL_C_LONG: + case SQL_C_SLONG: + val = *(long *)(colDefs[col].PtrDataObj); + break; + case SQL_C_SHORT: + case SQL_C_SSHORT: + val = (long int )(*(short *)(colDefs[col].PtrDataObj)); + break; + case SQL_C_ULONG: + val = (long)(*(unsigned long *)(colDefs[col].PtrDataObj)); + break; + case SQL_C_TINYINT: + val = (long)(*(char *)(colDefs[col].PtrDataObj)); + break; + case SQL_C_UTINYINT: + val = (long)(*(unsigned char *)(colDefs[col].PtrDataObj)); + break; + case SQL_C_USHORT: + val = (long)(*(UWORD *)(colDefs[col].PtrDataObj)); + break; + case SQL_C_DATE: + val = (DATE_STRUCT *)(colDefs[col].PtrDataObj); + break; + case SQL_C_TIME: + val = (TIME_STRUCT *)(colDefs[col].PtrDataObj); + break; + case SQL_C_TIMESTAMP: + val = (TIMESTAMP_STRUCT *)(colDefs[col].PtrDataObj); + break; + case SQL_C_DOUBLE: + val = *(double *)(colDefs[col].PtrDataObj); + break; + default: + assert(0); + } + } + return val; +} // 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) +{ + //FIXME: Add proper wxDateTime support to wxVariant.. + wxDateTime dateval; + + SetColNull(col, val.IsNull()); + + if (!val.IsNull()) + { + if ((colDefs[col].SqlCtype == SQL_C_DATE) + || (colDefs[col].SqlCtype == SQL_C_TIME) + || (colDefs[col].SqlCtype == SQL_C_TIMESTAMP)) + { + //Returns null if invalid! + if (!dateval.ParseDate(val.GetString())) + SetColNull(col,TRUE); + } + + switch (colDefs[col].SqlCtype) + { + case SQL_CHAR: + case SQL_VARCHAR: + csstrncpyt((char *)(colDefs[col].PtrDataObj), + val.GetString().c_str(), + colDefs[col].SzDataObj-1); + break; + case SQL_C_LONG: + case SQL_C_SLONG: + *(long *)(colDefs[col].PtrDataObj) = val; + break; + case SQL_C_SHORT: + case SQL_C_SSHORT: + *(short *)(colDefs[col].PtrDataObj) = val.GetLong(); + break; + case SQL_C_ULONG: + *(unsigned long *)(colDefs[col].PtrDataObj) = val.GetLong(); + break; + case SQL_C_TINYINT: + *(char *)(colDefs[col].PtrDataObj) = val.GetChar(); + break; + case SQL_C_UTINYINT: + *(unsigned char *)(colDefs[col].PtrDataObj) = val.GetChar(); + break; + case SQL_C_USHORT: + *(unsigned short *)(colDefs[col].PtrDataObj) = val.GetLong(); + break; + //FIXME: Add proper wxDateTime support to wxVariant.. + case SQL_C_DATE: + { + DATE_STRUCT *dataptr = + (DATE_STRUCT *)colDefs[col].PtrDataObj; + + dataptr->year = dateval.GetYear(); + dataptr->month = dateval.GetMonth()+1; + dataptr->day = dateval.GetDay(); + } + break; + case SQL_C_TIME: + { + TIME_STRUCT *dataptr = + (TIME_STRUCT *)colDefs[col].PtrDataObj; + + dataptr->hour = dateval.GetHour(); + dataptr->minute = dateval.GetMinute(); + dataptr->second = dateval.GetSecond(); + } + break; + case SQL_C_TIMESTAMP: + { + TIMESTAMP_STRUCT *dataptr = + (TIMESTAMP_STRUCT *)colDefs[col].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; + break; + default: + assert(0); + } // switch + } // if (!val.IsNull()) +} // wxDbTable::SetCol() + + +GenericKey wxDbTable::GetKey() +{ + void *blk; + char *blkptr; + + blk = malloc(m_keysize); + blkptr = (char *) blk; + + int i; + for (i=0; i < noCols; i++) + { + if (colDefs[i].KeyField) + { + memcpy(blkptr,colDefs[i].PtrDataObj, colDefs[i].SzDataObj); + blkptr += colDefs[i].SzDataObj; + } + } + + GenericKey k = GenericKey(blk, m_keysize); + free(blk); + + return k; +} // wxDbTable::GetKey() + + +void wxDbTable::SetKey(const GenericKey& k) +{ + void *blk; + char *blkptr; + + blk = k.GetBlk(); + blkptr = (char *)blk; + + int i; + for (i=0; i < noCols; i++) + { + if (colDefs[i].KeyField) + { + SetColNull(i, FALSE); + memcpy(colDefs[i].PtrDataObj, blkptr, colDefs[i].SzDataObj); + blkptr += colDefs[i].SzDataObj; + } + } +} // wxDbTable::SetKey() + + #endif // wxUSE_ODBC