]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/dbtable.cpp
reckognize cp125x charsets
[wxWidgets.git] / src / common / dbtable.cpp
index f85c5904f7d99a803d2c51398e097ea1f1b920d5..68b5fd652f13011950a74148df6920b203664ceb 100644 (file)
@@ -102,22 +102,47 @@ ULONG lastTableID = 0;
 #endif
 
 
-/********** wxDbTable::wxDbTable() **********/
-wxDbTable::wxDbTable(wxDb *pwxDb, const wxString &tblName, const int nCols,
+/********** wxDbColDef::wxDbColDef() Constructor **********/
+wxDbColDef::wxDbColDef()
+{
+    Initialize();
+}  // Constructor
+
+
+bool wxDbColDef::Initialize()
+{
+    ColName[0]      = 0;
+    DbDataType      = DB_DATA_TYPE_INTEGER;
+    SqlCtype        = SQL_C_LONG;
+    PtrDataObj      = NULL;
+    SzDataObj       = 0;
+    KeyField        = FALSE;
+    Updateable      = FALSE;
+    InsertAllowed   = FALSE;
+    DerivedCol      = FALSE;
+    CbValue         = 0;
+    Null = FALSE;
+
+    return TRUE;
+}  // wxDbColDef::Initialize()
+
+
+/********** wxDbTable::wxDbTable() Constructor **********/
+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()
 
@@ -129,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
@@ -145,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
@@ -177,7 +202,7 @@ bool wxDbTable::initialize(wxDb *pwxDb, const wxString &tblName, const int nCols
     
     wxString s;
     tableID = ++lastTableID;
-    s.Printf(wxT("wxDbTable constructor (%-20s) tableID:[%6lu] pDb:[%p]"), tblName,tableID,pDb);
+    s.Printf(wxT("wxDbTable constructor (%-20s) tableID:[%6lu] pDb:[%p]"), tblName.c_str(), tableID, pDb);
     
 #ifdef __WXDEBUG__
     wxTablesInUse *tableInUse;
@@ -300,7 +325,7 @@ void wxDbTable::cleanup()
     wxString s;
     if (pDb)
     {
-        s.Printf(wxT("wxDbTable destructor (%-20s) tableID:[%6lu] pDb:[%p]"), tableName,tableID,pDb);
+        s.Printf(wxT("wxDbTable destructor (%-20s) tableID:[%6lu] pDb:[%p]"), tableName.c_str(), tableID, pDb);
         pDb->WriteSqlLog(s);
     }
 
@@ -344,20 +369,41 @@ void wxDbTable::cleanup()
     if (!queryOnly)
     {
         if (hstmtInsert)
+        {
+/*
+ODBC 3.0 says to use this form
+            if (SQLFreeHandle(*hstmtDel, SQL_DROP) != SQL_SUCCESS)
+*/
             if (SQLFreeStmt(hstmtInsert, SQL_DROP) != SQL_SUCCESS)
                 pDb->DispAllErrors(henv, hdbc);
+        }
 
         if (hstmtDelete)
+        {
+/*
+ODBC 3.0 says to use this form
+            if (SQLFreeHandle(*hstmtDel, SQL_DROP) != SQL_SUCCESS)
+*/
             if (SQLFreeStmt(hstmtDelete, SQL_DROP) != SQL_SUCCESS)
+                pDb->DispAllErrors(henv, hdbc);
+        }
 
         if (hstmtUpdate)
+        {
+/*
+ODBC 3.0 says to use this form
+            if (SQLFreeHandle(*hstmtDel, SQL_DROP) != SQL_SUCCESS)
+*/
             if (SQLFreeStmt(hstmtUpdate, SQL_DROP) != SQL_SUCCESS)
                 pDb->DispAllErrors(henv, hdbc);
+        }
     }
 
     if (hstmtInternal)
+    {
         if (SQLFreeStmt(hstmtInternal, SQL_DROP) != SQL_SUCCESS)
             pDb->DispAllErrors(henv, hdbc);
+    }
 
     // Delete dynamically allocated cursors
     if (hstmtDefault)
@@ -384,7 +430,8 @@ bool wxDbTable::bindParams(bool forUpdate)
     
     // Bind each column of the table that should be bound
     // to a parameter marker
-    int i,colNo;
+    int i;
+        UWORD colNo;
     for (i = 0, colNo = 1; i < noCols; i++)
     {
         if (forUpdate)
@@ -441,6 +488,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)
         {
@@ -488,11 +544,10 @@ 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));
@@ -639,7 +694,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;   
@@ -650,7 +705,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'))
@@ -667,7 +722,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");
     }
 
@@ -676,9 +731,9 @@ bool wxDbTable::Open(bool checkPrivileges)
         wxString p;
 
         if (!tablePath.IsEmpty())
-            p.Printf(wxT("Error opening '%s/%s'.\n"),tablePath,tableName);
+            p.Printf(wxT("Error opening '%s/%s'.\n"),tablePath.c_str(),tableName.c_str());
         else
-            p.Printf(wxT("Error opening '%s'.\n"), tableName);
+            p.Printf(wxT("Error opening '%s'.\n"), tableName.c_str());
 
         p += s;
         pDb->LogError(p.GetData());
@@ -711,7 +766,7 @@ bool wxDbTable::Open(bool checkPrivileges)
     if (!queryOnly && noCols > 0)
     {
         bool needComma = FALSE;
-        sqlStmt.Printf(wxT("INSERT INTO %s ("), tableName);
+        sqlStmt.Printf(wxT("INSERT INTO %s ("), tableName.c_str());
         for (i = 0; i < noCols; i++)
         {
             if (! colDefs[i].InsertAllowed)
@@ -862,11 +917,11 @@ 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);
+        pSqlStmt.Printf(wxT("DELETE FROM %s"), tableName.c_str());
         return;
     }
 
-    pSqlStmt.Printf(wxT("DELETE FROM %s WHERE "), tableName);
+    pSqlStmt.Printf(wxT("DELETE FROM %s WHERE "), tableName.c_str());
 
     // Append the WHERE clause to the SQL DELETE statement
     switch(typeOfDel)
@@ -883,7 +938,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;
@@ -1060,7 +1115,7 @@ void wxDbTable::BuildUpdateStmt(wxString &pSqlStmt, int typeOfUpd, const wxStrin
 
     bool firstColumn = TRUE;
 
-    pSqlStmt.Printf(wxT("UPDATE %s SET "), tableName);
+    pSqlStmt.Printf(wxT("UPDATE %s SET "), tableName.c_str());
 
     // Append a list of columns to be updated
     int i;
@@ -1094,7 +1149,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;
@@ -1269,6 +1324,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;
     }
@@ -1276,7 +1334,7 @@ bool wxDbTable::CreateTable(bool attemptDrop)
 
     // Build a CREATE TABLE string from the colDefs structure.
     bool needComma = FALSE;
-    sqlStmt.Printf(wxT("CREATE TABLE %s ("), tableName);
+    sqlStmt.Printf(wxT("CREATE TABLE %s ("), tableName.c_str());
 
     for (i = 0; i < noCols; i++)
     {
@@ -1304,9 +1362,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);
@@ -1402,7 +1464,7 @@ bool wxDbTable::DropTable()
 
     wxString sqlStmt;
 
-    sqlStmt.Printf(wxT("DROP TABLE %s"), tableName);
+    sqlStmt.Printf(wxT("DROP TABLE %s"), tableName.c_str());
 
     pDb->WriteSqlLog(sqlStmt);
 
@@ -1576,12 +1638,12 @@ bool wxDbTable::DropIndex(const wxString &idxName)
     wxString sqlStmt;
 
     if (pDb->Dbms() == dbmsACCESS || pDb->Dbms() == dbmsMY_SQL)
-        sqlStmt.Printf(wxT("DROP INDEX %s ON %s"),idxName,tableName);
+        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))
-        sqlStmt.Printf(wxT("DROP INDEX %s.%s"),tableName,idxName);
+        sqlStmt.Printf(wxT("DROP INDEX %s.%s"),tableName.c_str(), idxName.c_str());
     else
-        sqlStmt.Printf(wxT("DROP INDEX %s"),idxName);
+        sqlStmt.Printf(wxT("DROP INDEX %s"),idxName.c_str());
 
     pDb->WriteSqlLog(sqlStmt);
 
@@ -1624,9 +1686,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;
@@ -1817,7 +1879,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
@@ -1880,12 +1942,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()
 
 
@@ -1902,7 +1964,7 @@ bool wxDbTable::IsCursorClosedOnCommit(void)
 
 
 /********** wxDbTable::ClearMemberVar() **********/
-void wxDbTable::ClearMemberVar(int colNo, bool setToNull)
+void wxDbTable::ClearMemberVar(UWORD colNo, bool setToNull)
 {
     wxASSERT(colNo < noCols);
 
@@ -1979,7 +2041,7 @@ 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,
+                           SWORD cType, int size, bool keyField, bool upd,
                            bool insAllow, bool derivedCol)
 {
     if (!colDefs)  // May happen if the database connection fails
@@ -2073,8 +2135,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);
         }
     }
 
@@ -2150,7 +2230,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);
@@ -2195,7 +2275,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 = '");
@@ -2233,8 +2313,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)
     {
@@ -2249,7 +2329,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;
@@ -2319,6 +2399,11 @@ bool wxDbTable::DeleteCursor(HSTMT *hstmtDel)
     if (!hstmtDel)  // Cursor already deleted
         return(result);
 
+/*
+ODBC 3.0 says to use this form
+    if (SQLFreeHandle(*hstmtDel, SQL_DROP) != SQL_SUCCESS)
+    
+*/
     if (SQLFreeStmt(*hstmtDel, SQL_DROP) != SQL_SUCCESS)
     {
         pDb->DispAllErrors(henv, hdbc);