diff --git a/src/common/db.cpp b/src/common/db.cpp index 29de4dba2b..cc27d8ac0e 100644 --- a/src/common/db.cpp +++ b/src/common/db.cpp @@ -388,6 +388,7 @@ bool wxDb::Open(char *Dsn, char *Uid, char *AuthStr) // Float if (! getDataTypeInfo(SQL_DOUBLE, typeInfFloat)) + if (! getDataTypeInfo(SQL_REAL, typeInfFloat)) if (! getDataTypeInfo(SQL_FLOAT, typeInfFloat)) if (! getDataTypeInfo(SQL_DECIMAL, typeInfFloat)) @@ -404,6 +405,7 @@ bool wxDb::Open(char *Dsn, char *Uid, char *AuthStr) else typeInfFloat.FsqlType = SQL_DOUBLE; + // Integer if (! getDataTypeInfo(SQL_INTEGER, typeInfInteger)) // If SQL_INTEGER is not supported, use the floating point @@ -837,6 +839,11 @@ bool wxDb::getDataTypeInfo(SWORD fSqlType, wxDbSqlTypeInfo &structSQLTypeInfo) if (!wxStrcmp(structSQLTypeInfo.TypeName, "varchar")) wxStrcpy(structSQLTypeInfo.TypeName, "char"); } +// BJO 20000427 : OpenLink driver (at least for unix) +#ifdef _IODBC_ + 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)); if (SQLGetData(hstmt, 8, SQL_C_SHORT, (UCHAR*) &structSQLTypeInfo.CaseSensitive, 0, &cbRet) != SQL_SUCCESS) @@ -1682,7 +1689,7 @@ wxDbColInf *wxDb::GetColumns(char *tableName[], const char *userID) GetData(10, SQL_C_SSHORT, (UCHAR*) &colInf[colNo].numPrecRadix, 0, &cb); GetData(11, SQL_C_SSHORT, (UCHAR*) &colInf[colNo].nullable, 0, &cb); GetData(12, SQL_C_CHAR, (UCHAR*) colInf[colNo].remarks, 254+1, &cb); - + // Determine the wxDb data type that is used to represent the native data type of this data source colInf[colNo].dbDataType = 0; if (!wxStricmp(typeInfVarchar.TypeName,colInf[colNo].typeName)) @@ -1856,39 +1863,41 @@ wxDbColInf *wxDb::GetColumns(char *tableName, int *numCols, const char *userID) colInf[colNo].FkCol = 0; // Foreign key column 0=No; 1= First Key, 2 = Second Key etc. colInf[colNo].FkTableName[0] = 0; // Foreign key table name - // Determine the wxDb data type that is used to represent the native data type of this data source - colInf[colNo].dbDataType = 0; - if (!wxStricmp(typeInfVarchar.TypeName,colInf[colNo].typeName)) - { - if (colInf[colNo].columnSize < 1) - { - // IODBC does not return a correct columnSize, so we set - // columnSize = bufferLength if no column size was returned - colInf[colNo].columnSize = colInf[colNo].bufferLength; - } - colInf[colNo].dbDataType = DB_DATA_TYPE_VARCHAR; - } - else if (!wxStricmp(typeInfInteger.TypeName,colInf[colNo].typeName)) - colInf[colNo].dbDataType = DB_DATA_TYPE_INTEGER; - else if (!wxStricmp(typeInfFloat.TypeName,colInf[colNo].typeName)) - colInf[colNo].dbDataType = DB_DATA_TYPE_FLOAT; - else if (!wxStricmp(typeInfDate.TypeName,colInf[colNo].typeName)) - colInf[colNo].dbDataType = DB_DATA_TYPE_DATE; - + + + // Determine the wxDb data type that is used to represent the native data type of this data source + colInf[colNo].dbDataType = 0; + if (!wxStricmp(typeInfVarchar.TypeName,colInf[colNo].typeName)) + { + if (colInf[colNo].columnSize < 1) + { + // IODBC does not return a correct columnSize, so we set + // columnSize = bufferLength if no column size was returned + colInf[colNo].columnSize = colInf[colNo].bufferLength; + } + colInf[colNo].dbDataType = DB_DATA_TYPE_VARCHAR; + } + else if (!wxStricmp(typeInfInteger.TypeName,colInf[colNo].typeName)) + colInf[colNo].dbDataType = DB_DATA_TYPE_INTEGER; + else if (!wxStricmp(typeInfFloat.TypeName,colInf[colNo].typeName)) + colInf[colNo].dbDataType = DB_DATA_TYPE_FLOAT; + else if (!wxStricmp(typeInfDate.TypeName,colInf[colNo].typeName)) + colInf[colNo].dbDataType = DB_DATA_TYPE_DATE; + colNo++; } } } if (retcode != SQL_NO_DATA_FOUND) - { // Error occured, abort + { // Error occured, abort DispAllErrors(henv, hdbc, hstmt); if (colInf) - delete [] colInf; + delete [] colInf; SQLFreeStmt(hstmt, SQL_CLOSE); if (numCols) - *numCols = 0; + *numCols = 0; return(0); - } + } } SQLFreeStmt(hstmt, SQL_CLOSE); @@ -2068,6 +2077,8 @@ wxDbInf *wxDb::GetCatalog(char *userID) // Pass 2 - Create the Table array and fill it // - Create the Cols array = NULL //------------------------------------------------------------- + + for (pass = 1; pass <= 2; pass++) { SQLFreeStmt(hstmt, SQL_CLOSE); // Close if Open @@ -2077,6 +2088,7 @@ wxDbInf *wxDb::GetCatalog(char *userID) Dbms() != dbmsMY_SQL && Dbms() != dbmsACCESS) { + retcode = SQLTables(hstmt, NULL, 0, // All qualifiers (UCHAR *) UserID.c_str(), SQL_NTS, // User specified @@ -2085,22 +2097,26 @@ wxDbInf *wxDb::GetCatalog(char *userID) } else { + retcode = SQLTables(hstmt, NULL, 0, // All qualifiers NULL, 0, // User specified NULL, 0, // All tables NULL, 0); // All columns } + if (retcode != SQL_SUCCESS) { + DispAllErrors(henv, hdbc, hstmt); pDbInf = NULL; SQLFreeStmt(hstmt, SQL_CLOSE); return pDbInf; } - + while ((retcode = SQLFetch(hstmt)) == SQL_SUCCESS) // Table Information { + if (pass == 1) // First pass, just count the Tables { if (pDbInf->numTables == 0) @@ -2124,10 +2140,12 @@ wxDbInf *wxDb::GetCatalog(char *userID) (pDbInf->pTableInf+noTab)->pColInf = NULL; } noTab = 0; - } // if (pDbInf->pTableInf == NULL) // Has the Table Array been created + } // if (pDbInf->pTableInf == NULL) // Has the Table Array been created + GetData( 3, SQL_C_CHAR, (UCHAR*) (pDbInf->pTableInf+noTab)->tableName, DB_MAX_TABLE_NAME_LEN+1, &cb); GetData( 4, SQL_C_CHAR, (UCHAR*) (pDbInf->pTableInf+noTab)->tableType, 30+1, &cb); GetData( 5, SQL_C_CHAR, (UCHAR*) (pDbInf->pTableInf+noTab)->tableRemarks, 254+1, &cb); + noTab++; } // if (pass == 2) We now know the amount of Tables } // while ((retcode = SQLFetch(hstmt)) == SQL_SUCCESS) @@ -2465,11 +2483,17 @@ wxDBMS wxDb::Dbms(void) { wxChar baseName[25+1]; wxStrncpy(baseName,dbInf.dbmsName,25); - + + if (!wxStricmp(dbInf.dbmsName,"Adaptive Server Anywhere")) return(dbmsSYBASE_ASA); - if (!wxStricmp(dbInf.dbmsName,"SQL Server")) // Sybase Adaptive Server - return(dbmsSYBASE_ASE); + + // BJO 20000427 : The "SQL Server" string is also returned by SQLServer when connected trough an OpenLink driver. + // Is it also returned by Sybase? + if (!wxStricmp(dbInf.dbmsName,"SQL Server")) + if (!wxStricmp(dbInf.driverName, "oplodbc.so")) return dbmsMS_SQL_SERVER; else return dbmsSYBASE_ASE; + + if (!wxStricmp(dbInf.dbmsName,"Microsoft SQL Server")) return(dbmsMS_SQL_SERVER); if (!wxStricmp(dbInf.dbmsName,"MySQL")) diff --git a/src/common/dbtable.cpp b/src/common/dbtable.cpp index 85e86cf91a..59093b0a2c 100644 --- a/src/common/dbtable.cpp +++ b/src/common/dbtable.cpp @@ -71,6 +71,7 @@ # define wxUSE_ODBC 1 #endif + #if wxUSE_ODBC #include @@ -184,7 +185,7 @@ wxDbTable::wxDbTable(wxDb *pwxDb, const char *tblName, const int nCols, // Set the cursor type for the statement handles cursorType = SQL_CURSOR_STATIC; - //cursorType = SQL_CURSOR_FORWARD_ONLY; + if (SQLSetStmtOption(hstmtInternal, SQL_CURSOR_TYPE, cursorType) != SQL_SUCCESS) { // Check to see if cursor type is supported @@ -358,8 +359,9 @@ bool wxDbTable::bindInsertParams(void) continue; switch(colDefs[i].DbDataType) { + case DB_DATA_TYPE_VARCHAR: - fSqlType = pDb->GetTypeInfVarchar().FsqlType; + fSqlType = pDb->GetTypeInfVarchar().FsqlType; precision = colDefs[i].SzDataObj; scale = 0; colDefs[i].CbValue = SQL_NTS; @@ -394,10 +396,11 @@ bool wxDbTable::bindInsertParams(void) colDefs[i].CbValue = SQL_NULL_DATA; colDefs[i].Null = FALSE; } - if (SQLBindParameter(hstmtInsert, colNo++, SQL_PARAM_INPUT, colDefs[i].SqlCtype, - fSqlType, precision, scale, (UCHAR*) colDefs[i].PtrDataObj, - precision+1,&colDefs[i].CbValue) != SQL_SUCCESS) - return(pDb->DispAllErrors(henv, hdbc, hstmtInsert)); + + if (SQLBindParameter(hstmtInsert, colNo++, SQL_PARAM_INPUT, colDefs[i].SqlCtype, + fSqlType, precision, scale, (UCHAR*) colDefs[i].PtrDataObj, + precision+1,&colDefs[i].CbValue) != SQL_SUCCESS) + return(pDb->DispAllErrors(henv, hdbc, hstmtInsert)); } // Completed successfully @@ -440,7 +443,7 @@ bool wxDbTable::bindUpdateParams(void) 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. @@ -455,10 +458,11 @@ bool wxDbTable::bindUpdateParams(void) colDefs[i].CbValue = 0; break; } - if (SQLBindParameter(hstmtUpdate, colNo++, SQL_PARAM_INPUT, colDefs[i].SqlCtype, - fSqlType, precision, scale, (UCHAR*) colDefs[i].PtrDataObj, - precision+1, &colDefs[i].CbValue) != SQL_SUCCESS) - return(pDb->DispAllErrors(henv, hdbc, hstmtUpdate)); + + if (SQLBindParameter(hstmtUpdate, colNo++, SQL_PARAM_INPUT, colDefs[i].SqlCtype, + fSqlType, precision, scale, (UCHAR*) colDefs[i].PtrDataObj, + precision+1, &colDefs[i].CbValue) != SQL_SUCCESS) + return(pDb->DispAllErrors(henv, hdbc, hstmtUpdate)); } // Completed successfully @@ -475,11 +479,11 @@ bool wxDbTable::bindCols(HSTMT cursor) // Bind each column of the table to a memory address for fetching data int i; for (i = 0; i < noCols; i++) - { - if (SQLBindCol(cursor, i+1, colDefs[i].SqlCtype, (UCHAR*) colDefs[i].PtrDataObj, - colDefs[i].SzDataObj, &cb) != SQL_SUCCESS) - return(pDb->DispAllErrors(henv, hdbc, cursor)); - } + { + if (SQLBindCol(cursor, i+1, colDefs[i].SqlCtype, (UCHAR*) colDefs[i].PtrDataObj, + colDefs[i].SzDataObj, &cb) != SQL_SUCCESS) + return (pDb->DispAllErrors(henv, hdbc, cursor)); + } // Completed successfully return(TRUE); @@ -615,10 +619,10 @@ bool wxDbTable::query(int queryType, bool forUpdate, bool distinct, const char * bool wxDbTable::Open(void) { if (!pDb) - return FALSE; - + return FALSE; int i; wxString sqlStmt; + // Verify that the table exists in the database if (!pDb->TableExists(tableName,pDb->GetUsername(),tablePath)) @@ -640,15 +644,21 @@ bool wxDbTable::Open(void) // the wxDbTable object and the ODBC record. if (!queryOnly) { + if (!bindInsertParams()) // Inserts return(FALSE); + if (!bindUpdateParams()) // Updates return(FALSE); + } if (!bindCols(*hstmtDefault)) // Selects return(FALSE); + if (!bindCols(hstmtInternal)) // Internal use only return(FALSE); + + /* * Do NOT bind the hstmtCount cursor!!! */ @@ -1115,13 +1125,14 @@ 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")) // "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() == dbmsMY_SQL && !wxStrcmp(pDb->sqlState,"S1000")) || // untested - (pDb->Dbms() == dbmsPOSTGRES && !wxStrcmp(pDb->sqlState,"08S01")))) // untested + 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() == dbmsPOSTGRES && !wxStrcmp(pDb->sqlState,"08S01")))) { pDb->DispNextError(); pDb->DispAllErrors(henv, hdbc, hstmt); @@ -1241,10 +1252,13 @@ bool wxDbTable::DropIndex(const char * idxName) if (wxStrcmp(pDb->sqlState,"S0012")) // "Index not found" { // Check for product specific error codes - if (!((pDb->Dbms() == dbmsSYBASE_ASA && !wxStrcmp(pDb->sqlState,"42000")) || // v5.x (and lower?) - (pDb->Dbms() == dbmsSYBASE_ASE && !wxStrcmp(pDb->sqlState,"S0002")) || // Base table not found - (pDb->Dbms() == dbmsMY_SQL && !wxStrcmp(pDb->sqlState,"42S02")) // untested - )) + if (!((pDb->Dbms() == dbmsSYBASE_ASA && !wxStrcmp(pDb->sqlState,"42000")) || // v5.x (and lower?) + (pDb->Dbms() == dbmsSYBASE_ASE && !wxStrcmp(pDb->sqlState,"37000")) || + (pDb->Dbms() == dbmsMS_SQL_SERVER && !wxStrcmp(pDb->sqlState,"S1000")) || + (pDb->Dbms() == dbmsSYBASE_ASE && !wxStrcmp(pDb->sqlState,"S0002")) || // Base table not found + (pDb->Dbms() == dbmsMY_SQL && !wxStrcmp(pDb->sqlState,"42S02")) || // untested + (pDb->Dbms() == dbmsPOSTGRES && !wxStrcmp(pDb->sqlState,"08S01")) + )) { pDb->DispNextError(); pDb->DispAllErrors(henv, hdbc, hstmt);