From d55da698a82122d80f8b82d936b4fe748b0275a6 Mon Sep 17 00:00:00 2001 From: "Bart A.M. Jourquin" Date: Thu, 4 May 2000 12:19:28 +0000 Subject: [PATCH] new GetColumns() members git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_2_BRANCH@7344 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/db.h | 12 ++- src/common/db.cpp | 216 +++++++++++++++++++++++++++++++++++++---- src/common/dbtable.cpp | 8 +- 3 files changed, 212 insertions(+), 24 deletions(-) diff --git a/include/wx/db.h b/include/wx/db.h index c4af471402..3fc3bee800 100644 --- a/include/wx/db.h +++ b/include/wx/db.h @@ -38,6 +38,12 @@ #ifndef DB_DOT_H #define DB_DOT_H + +// BJO 20000503: introduce new GetColumns members which are database independant and +// return columns in the order they were created +#define OLD_GETCOLUMNS 1 + + // Use this line for wxWindows v1.x //#include "wx_ver.h" // Use this line for wxWindows v2.x @@ -300,6 +306,8 @@ public: }; + + class WXDLLEXPORT wxDbTableInf // Description of a Table { public: @@ -486,8 +494,10 @@ public: wxDbInf *GetCatalog(char *userID); bool Catalog(const char *userID=NULL, const char *fileName = SQL_CATALOG_FILENAME); int GetKeyFields(char *tableName, wxDbColInf* colInf, int nocols); + wxDbColInf *GetColumns(char *tableName[], const char *userID=NULL); - wxDbColInf *GetColumns(char *tableName, int *numCols, const char *userID=NULL); + wxDbColInf *GetColumns(char *tableName, int *numCols, const char *userID=NULL); + int GetColumnCount(char *tableName, const char *userID=NULL); char *GetDatabaseName(void) {return dbInf.dbmsName;} char *GetDataSource(void) {return dsn;} diff --git a/src/common/db.cpp b/src/common/db.cpp index 06e47140f4..2213024ec0 100644 --- a/src/common/db.cpp +++ b/src/common/db.cpp @@ -51,6 +51,7 @@ #include "wx/ioswrap.h" #endif + #ifdef __BORLANDC__ #pragma hdrstop #endif //__BORLANDC__ @@ -830,22 +831,25 @@ bool wxDb::getDataTypeInfo(SWORD fSqlType, wxDbSqlTypeInfo &structSQLTypeInfo) if (SQLGetData(hstmt, 1, SQL_C_CHAR, (UCHAR*) structSQLTypeInfo.TypeName, DB_TYPE_NAME_LEN, &cbRet) != SQL_SUCCESS) return(DispAllErrors(henv, hdbc, hstmt)); + + // BJO 20000503: no more needed with new GetColumns... +#if OLD_GETCOLUMNS // BJO 991209 if (Dbms() == dbmsMY_SQL) - { + { if (!wxStrcmp(structSQLTypeInfo.TypeName, "middleint")) wxStrcpy(structSQLTypeInfo.TypeName, "mediumint"); if (!wxStrcmp(structSQLTypeInfo.TypeName, "middleint unsigned")) wxStrcpy(structSQLTypeInfo.TypeName, "mediumint unsigned"); if (!wxStrcmp(structSQLTypeInfo.TypeName, "integer")) wxStrcpy(structSQLTypeInfo.TypeName, "int"); if (!wxStrcmp(structSQLTypeInfo.TypeName, "integer unsigned")) wxStrcpy(structSQLTypeInfo.TypeName, "int unsigned"); if (!wxStrcmp(structSQLTypeInfo.TypeName, "middleint")) wxStrcpy(structSQLTypeInfo.TypeName, "mediumint"); if (!wxStrcmp(structSQLTypeInfo.TypeName, "varchar")) wxStrcpy(structSQLTypeInfo.TypeName, "char"); - } - + } + // BJO 20000427 : OpenLink driver if (!wxStrncmp(dbInf.driverName, "oplodbc", 7) || !wxStrncmp(dbInf.driverName, "OLOD", 4)) if (!wxStrcmp(structSQLTypeInfo.TypeName, "double precision")) wxStrcpy(structSQLTypeInfo.TypeName, "real"); - +#endif if (SQLGetData(hstmt, 3, SQL_C_LONG, (UCHAR*) &structSQLTypeInfo.Precision, 0, &cbRet) != SQL_SUCCESS) return(DispAllErrors(henv, hdbc, hstmt)); @@ -1553,6 +1557,7 @@ int wxDb::GetKeyFields(char *tableName, wxDbColInf* colInf, int noCols) } // wxDb::GetKeyFields() +#if OLD_GETCOLUMNS /********** wxDb::GetColumns() **********/ wxDbColInf *wxDb::GetColumns(char *tableName[], const char *userID) /* @@ -1734,21 +1739,22 @@ wxDbColInf *wxDb::GetColumns(char *tableName[], const char *userID) /********** wxDb::GetColumns() **********/ + wxDbColInf *wxDb::GetColumns(char *tableName, int *numCols, const char *userID) -/* - * Same as the above GetColumns() function except this one gets columns - * only for a single table, and if 'numCols' is not NULL, the number of - * columns stored in the returned wxDbColInf is set in '*numCols' - * - * userID is evaluated in the following manner: - * userID == NULL ... UserID is ignored - * userID == "" ... UserID set equal to 'this->uid' - * userID != "" ... UserID set equal to 'userID' - * - * NOTE: ALL column bindings associated with this wxDb instance are unbound - * by this function. This function should use its own wxDb instance - * to avoid undesired unbinding of columns. - */ +// +// Same as the above GetColumns() function except this one gets columns +// only for a single table, and if 'numCols' is not NULL, the number of +// columns stored in the returned wxDbColInf is set in '*numCols' +// +// userID is evaluated in the following manner: +// userID == NULL ... UserID is ignored +// userID == "" ... UserID set equal to 'this->uid' +// userID != "" ... UserID set equal to 'userID' +// +// NOTE: ALL column bindings associated with this wxDb instance are unbound +// by this function. This function should use its own wxDb instance +// to avoid undesired unbinding of columns. + { int noCols = 0; int colNo = 0; @@ -1920,6 +1926,180 @@ wxDbColInf *wxDb::GetColumns(char *tableName, int *numCols, const char *userID) } // wxDb::GetColumns() +#else // New GetColumns + + + +/* + +BJO 20000503 + +These are tentative new GetColumns members which should be more database independant and +which always returns the columns in the order they were created. + +*/ + +typedef struct _TableColumns +{ + int noCols; + wxDbColInf *colInf; +}; + +wxDbColInf *wxDb::GetColumns(char *tableName[], const char* WXUNUSED(userID)) +{ + // The last array element of the tableName[] argument must be zero (null). + // This is how the end of the array is detected. + + int noCols = 0; + + // How many tables ? + int tbl; + for (tbl = 0 ; tableName[tbl]; tbl++); + + // Create a table to maintain the columns for each separate table + _TableColumns *TableColumns = new _TableColumns[tbl]; + + // Fill the table + for (int i = 0 ; i < tbl ; i++) + { + TableColumns[i].colInf = GetColumns(tableName[i], &TableColumns[i].noCols); + if (TableColumns[i].colInf == NULL) return NULL; + noCols += TableColumns[i].noCols; + } + + // Now merge all the separate table infos + wxDbColInf *colInf = new wxDbColInf[noCols+1]; + + // Mark the end of the array + wxStrcpy(colInf[noCols].tableName, wxT("")); + wxStrcpy(colInf[noCols].colName, wxT("")); + colInf[noCols].sqlDataType = 0; + + // Merge ... + int offset = 0; + for (int i = 0 ; i < tbl ; i++) + { + for (int j = 0 ; j < TableColumns[i].noCols ; j++) + { + colInf[offset++] = TableColumns[i].colInf[j]; + } + } + delete [] TableColumns; + + return colInf; +} + + +/********** wxDb::GetColumns() **********/ +wxDbColInf *wxDb::GetColumns(char *tableName, int *numCols, const char* WXUNUSED(userID)) +{ + + wxDbColInf *colInf = 0; + short noCols; + + // Build a generic SELECT statement which returns 0 rows + wxString Stmt; + + Stmt.sprintf("select * from %s where 0=1", tableName); + + // Execute query + if (SQLExecDirect(hstmt, (UCHAR FAR *) Stmt.c_str(), SQL_NTS) != SQL_SUCCESS) + { + DispAllErrors(henv, hdbc, hstmt); + return NULL; + } + + // Get the number of result columns + if (SQLNumResultCols (hstmt, &noCols) != SQL_SUCCESS) + { + DispAllErrors(henv, hdbc, hstmt); + return NULL; + } + + + if (noCols == 0) // Probably a bogus table name + return NULL; + + // Allocate noCols wxDbColInf objects to hold the column information + colInf = new wxDbColInf[noCols+1]; + if (!colInf) return NULL; + + // Mark the end of the array + wxStrcpy(colInf[noCols].tableName, wxT("")); + wxStrcpy(colInf[noCols].colName, wxT("")); + colInf[noCols].sqlDataType = 0; + + + // Get the name and other type information + for (short colNum = 0; colNum < noCols; colNum++) + { + + if (SQLDescribeCol (hstmt, + colNum+1, + (UCHAR*) colInf[colNum].colName,DB_MAX_COLUMN_NAME_LEN+1, + &colInf[colNum].bufferLength, + &colInf[colNum].sqlDataType, + (UDWORD*) &colInf[colNum].columnSize, + &colInf[colNum].decimalDigits, + &colInf[colNum].nullable) != SQL_SUCCESS) + { + DispAllErrors(henv, hdbc, hstmt); + return NULL; + } + + + wxStrcpy(colInf[colNum].tableName, tableName); + + // Get the intern datatype + switch (colInf[colNum].sqlDataType) + { + case SQL_VARCHAR: + case SQL_CHAR: + colInf[colNum].dbDataType = DB_DATA_TYPE_VARCHAR; + wxStrcpy(colInf[colNum].typeName, typeInfVarchar.TypeName); + break; + + case SQL_TINYINT: + case SQL_SMALLINT: + case SQL_INTEGER: + colInf[colNum].dbDataType = DB_DATA_TYPE_INTEGER; + wxStrcpy(colInf[colNum].typeName, typeInfInteger.TypeName); + break; + case SQL_DOUBLE: + case SQL_DECIMAL: + case SQL_NUMERIC: + case SQL_FLOAT: + case SQL_REAL: + colInf[colNum].dbDataType = DB_DATA_TYPE_FLOAT; + wxStrcpy(colInf[colNum].typeName, typeInfFloat.TypeName); + break; + case SQL_DATE: + colInf[colNum].dbDataType = DB_DATA_TYPE_DATE; + wxStrcpy(colInf[colNum].typeName, typeInfDate.TypeName); + break; + + default: + wxString s; + s.sprintf("SQL Data type %d bot supported by wxWindows", colInf[colNum].sqlDataType); + wxMessageBox(wxT(s)); + return NULL; + } + } + + + SQLFreeStmt(hstmt, SQL_CLOSE); + + // Store Primary and Foreign Keys + GetKeyFields(tableName,colInf,noCols); + + *numCols = (int) noCols; + + return colInf; + +} // wxDb::GetColumns() + +#endif + /********** wxDb::GetColumnCount() **********/ int wxDb::GetColumnCount(char *tableName, const char *userID) diff --git a/src/common/dbtable.cpp b/src/common/dbtable.cpp index 87107a0c3b..e1c631deee 100644 --- a/src/common/dbtable.cpp +++ b/src/common/dbtable.cpp @@ -586,7 +586,7 @@ bool wxDbTable::query(int queryType, bool forUpdate, bool distinct, const char * { // so generate a select statement. BuildSelectStmt(sqlStmt, queryType, distinct); pDb->WriteSqlLog(sqlStmt); - } + } else wxStrcpy(sqlStmt, pSqlStmt); SQLFreeStmt(hstmt, SQL_CLOSE); if (SQLExecDirect(hstmt, (UCHAR FAR *) sqlStmt, SQL_NTS) == SQL_SUCCESS) @@ -1126,13 +1126,11 @@ bool wxDbTable::DropTable() { // Check for "Base table not found" error and ignore pDb->GetNextError(henv, hdbc, hstmt); - if (wxStrcmp(pDb->sqlState,"S0002")) // "Base table not found" + if (wxStrcmp(pDb->sqlState,"S0002") && wxStrcmp(pDb->sqlState, "S1000")) // "Base table not found" { // Check for product specific error codes if (!((pDb->Dbms() == dbmsSYBASE_ASA && !wxStrcmp(pDb->sqlState,"42000")) || // 5.x (and lower?) - (pDb->Dbms() == dbmsSYBASE_ASE && !wxStrcmp(pDb->sqlState,"37000")) || - (pDb->Dbms() == dbmsMS_SQL_SERVER && !wxStrcmp(pDb->sqlState,"S1000")) || // BJO20000427 with OpenLinkDriver - (pDb->Dbms() == dbmsMY_SQL && !wxStrcmp(pDb->sqlState,"S1000")) || + (pDb->Dbms() == dbmsSYBASE_ASE && !wxStrcmp(pDb->sqlState,"37000")) || (pDb->Dbms() == dbmsPOSTGRES && !wxStrcmp(pDb->sqlState,"08S01")))) { pDb->DispNextError();