add support for SQL Server with OpenLink driver for Unix

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_2_BRANCH@7283 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Bart A.M. Jourquin
2000-04-27 11:37:47 +00:00
parent 4aba0fc00a
commit a99c0d5331
2 changed files with 95 additions and 57 deletions

View File

@@ -388,6 +388,7 @@ bool wxDb::Open(char *Dsn, char *Uid, char *AuthStr)
// Float // Float
if (! getDataTypeInfo(SQL_DOUBLE, typeInfFloat)) if (! getDataTypeInfo(SQL_DOUBLE, typeInfFloat))
if (! getDataTypeInfo(SQL_REAL, typeInfFloat)) if (! getDataTypeInfo(SQL_REAL, typeInfFloat))
if (! getDataTypeInfo(SQL_FLOAT, typeInfFloat)) if (! getDataTypeInfo(SQL_FLOAT, typeInfFloat))
if (! getDataTypeInfo(SQL_DECIMAL, typeInfFloat)) if (! getDataTypeInfo(SQL_DECIMAL, typeInfFloat))
@@ -404,6 +405,7 @@ bool wxDb::Open(char *Dsn, char *Uid, char *AuthStr)
else else
typeInfFloat.FsqlType = SQL_DOUBLE; typeInfFloat.FsqlType = SQL_DOUBLE;
// Integer // Integer
if (! getDataTypeInfo(SQL_INTEGER, typeInfInteger)) if (! getDataTypeInfo(SQL_INTEGER, typeInfInteger))
// If SQL_INTEGER is not supported, use the floating point // 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"); 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) if (SQLGetData(hstmt, 3, SQL_C_LONG, (UCHAR*) &structSQLTypeInfo.Precision, 0, &cbRet) != SQL_SUCCESS)
return(DispAllErrors(henv, hdbc, hstmt)); return(DispAllErrors(henv, hdbc, hstmt));
if (SQLGetData(hstmt, 8, SQL_C_SHORT, (UCHAR*) &structSQLTypeInfo.CaseSensitive, 0, &cbRet) != SQL_SUCCESS) 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(10, SQL_C_SSHORT, (UCHAR*) &colInf[colNo].numPrecRadix, 0, &cb);
GetData(11, SQL_C_SSHORT, (UCHAR*) &colInf[colNo].nullable, 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); 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 // Determine the wxDb data type that is used to represent the native data type of this data source
colInf[colNo].dbDataType = 0; colInf[colNo].dbDataType = 0;
if (!wxStricmp(typeInfVarchar.TypeName,colInf[colNo].typeName)) 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].FkCol = 0; // Foreign key column 0=No; 1= First Key, 2 = Second Key etc.
colInf[colNo].FkTableName[0] = 0; // Foreign key table name 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)) // Determine the wxDb data type that is used to represent the native data type of this data source
{ colInf[colNo].dbDataType = 0;
if (colInf[colNo].columnSize < 1) if (!wxStricmp(typeInfVarchar.TypeName,colInf[colNo].typeName))
{ {
// IODBC does not return a correct columnSize, so we set if (colInf[colNo].columnSize < 1)
// columnSize = bufferLength if no column size was returned {
colInf[colNo].columnSize = colInf[colNo].bufferLength; // IODBC does not return a correct columnSize, so we set
} // columnSize = bufferLength if no column size was returned
colInf[colNo].dbDataType = DB_DATA_TYPE_VARCHAR; colInf[colNo].columnSize = colInf[colNo].bufferLength;
} }
else if (!wxStricmp(typeInfInteger.TypeName,colInf[colNo].typeName)) colInf[colNo].dbDataType = DB_DATA_TYPE_VARCHAR;
colInf[colNo].dbDataType = DB_DATA_TYPE_INTEGER; }
else if (!wxStricmp(typeInfFloat.TypeName,colInf[colNo].typeName)) else if (!wxStricmp(typeInfInteger.TypeName,colInf[colNo].typeName))
colInf[colNo].dbDataType = DB_DATA_TYPE_FLOAT; colInf[colNo].dbDataType = DB_DATA_TYPE_INTEGER;
else if (!wxStricmp(typeInfDate.TypeName,colInf[colNo].typeName)) else if (!wxStricmp(typeInfFloat.TypeName,colInf[colNo].typeName))
colInf[colNo].dbDataType = DB_DATA_TYPE_DATE; colInf[colNo].dbDataType = DB_DATA_TYPE_FLOAT;
else if (!wxStricmp(typeInfDate.TypeName,colInf[colNo].typeName))
colInf[colNo].dbDataType = DB_DATA_TYPE_DATE;
colNo++; colNo++;
} }
} }
} }
if (retcode != SQL_NO_DATA_FOUND) if (retcode != SQL_NO_DATA_FOUND)
{ // Error occured, abort { // Error occured, abort
DispAllErrors(henv, hdbc, hstmt); DispAllErrors(henv, hdbc, hstmt);
if (colInf) if (colInf)
delete [] colInf; delete [] colInf;
SQLFreeStmt(hstmt, SQL_CLOSE); SQLFreeStmt(hstmt, SQL_CLOSE);
if (numCols) if (numCols)
*numCols = 0; *numCols = 0;
return(0); return(0);
} }
} }
SQLFreeStmt(hstmt, SQL_CLOSE); SQLFreeStmt(hstmt, SQL_CLOSE);
@@ -2068,6 +2077,8 @@ wxDbInf *wxDb::GetCatalog(char *userID)
// Pass 2 - Create the Table array and fill it // Pass 2 - Create the Table array and fill it
// - Create the Cols array = NULL // - Create the Cols array = NULL
//------------------------------------------------------------- //-------------------------------------------------------------
for (pass = 1; pass <= 2; pass++) for (pass = 1; pass <= 2; pass++)
{ {
SQLFreeStmt(hstmt, SQL_CLOSE); // Close if Open SQLFreeStmt(hstmt, SQL_CLOSE); // Close if Open
@@ -2077,6 +2088,7 @@ wxDbInf *wxDb::GetCatalog(char *userID)
Dbms() != dbmsMY_SQL && Dbms() != dbmsMY_SQL &&
Dbms() != dbmsACCESS) Dbms() != dbmsACCESS)
{ {
retcode = SQLTables(hstmt, retcode = SQLTables(hstmt,
NULL, 0, // All qualifiers NULL, 0, // All qualifiers
(UCHAR *) UserID.c_str(), SQL_NTS, // User specified (UCHAR *) UserID.c_str(), SQL_NTS, // User specified
@@ -2085,22 +2097,26 @@ wxDbInf *wxDb::GetCatalog(char *userID)
} }
else else
{ {
retcode = SQLTables(hstmt, retcode = SQLTables(hstmt,
NULL, 0, // All qualifiers NULL, 0, // All qualifiers
NULL, 0, // User specified NULL, 0, // User specified
NULL, 0, // All tables NULL, 0, // All tables
NULL, 0); // All columns NULL, 0); // All columns
} }
if (retcode != SQL_SUCCESS) if (retcode != SQL_SUCCESS)
{ {
DispAllErrors(henv, hdbc, hstmt); DispAllErrors(henv, hdbc, hstmt);
pDbInf = NULL; pDbInf = NULL;
SQLFreeStmt(hstmt, SQL_CLOSE); SQLFreeStmt(hstmt, SQL_CLOSE);
return pDbInf; return pDbInf;
} }
while ((retcode = SQLFetch(hstmt)) == SQL_SUCCESS) // Table Information while ((retcode = SQLFetch(hstmt)) == SQL_SUCCESS) // Table Information
{ {
if (pass == 1) // First pass, just count the Tables if (pass == 1) // First pass, just count the Tables
{ {
if (pDbInf->numTables == 0) if (pDbInf->numTables == 0)
@@ -2124,10 +2140,12 @@ wxDbInf *wxDb::GetCatalog(char *userID)
(pDbInf->pTableInf+noTab)->pColInf = NULL; (pDbInf->pTableInf+noTab)->pColInf = NULL;
} }
noTab = 0; 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( 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( 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); GetData( 5, SQL_C_CHAR, (UCHAR*) (pDbInf->pTableInf+noTab)->tableRemarks, 254+1, &cb);
noTab++; noTab++;
} // if (pass == 2) We now know the amount of Tables } // if (pass == 2) We now know the amount of Tables
} // while ((retcode = SQLFetch(hstmt)) == SQL_SUCCESS) } // while ((retcode = SQLFetch(hstmt)) == SQL_SUCCESS)
@@ -2465,11 +2483,17 @@ wxDBMS wxDb::Dbms(void)
{ {
wxChar baseName[25+1]; wxChar baseName[25+1];
wxStrncpy(baseName,dbInf.dbmsName,25); wxStrncpy(baseName,dbInf.dbmsName,25);
if (!wxStricmp(dbInf.dbmsName,"Adaptive Server Anywhere")) if (!wxStricmp(dbInf.dbmsName,"Adaptive Server Anywhere"))
return(dbmsSYBASE_ASA); 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")) if (!wxStricmp(dbInf.dbmsName,"Microsoft SQL Server"))
return(dbmsMS_SQL_SERVER); return(dbmsMS_SQL_SERVER);
if (!wxStricmp(dbInf.dbmsName,"MySQL")) if (!wxStricmp(dbInf.dbmsName,"MySQL"))

View File

@@ -71,6 +71,7 @@
# define wxUSE_ODBC 1 # define wxUSE_ODBC 1
#endif #endif
#if wxUSE_ODBC #if wxUSE_ODBC
#include <stdio.h> #include <stdio.h>
@@ -184,7 +185,7 @@ wxDbTable::wxDbTable(wxDb *pwxDb, const char *tblName, const int nCols,
// Set the cursor type for the statement handles // Set the cursor type for the statement handles
cursorType = SQL_CURSOR_STATIC; cursorType = SQL_CURSOR_STATIC;
//cursorType = SQL_CURSOR_FORWARD_ONLY;
if (SQLSetStmtOption(hstmtInternal, SQL_CURSOR_TYPE, cursorType) != SQL_SUCCESS) if (SQLSetStmtOption(hstmtInternal, SQL_CURSOR_TYPE, cursorType) != SQL_SUCCESS)
{ {
// Check to see if cursor type is supported // Check to see if cursor type is supported
@@ -358,8 +359,9 @@ bool wxDbTable::bindInsertParams(void)
continue; continue;
switch(colDefs[i].DbDataType) switch(colDefs[i].DbDataType)
{ {
case DB_DATA_TYPE_VARCHAR: case DB_DATA_TYPE_VARCHAR:
fSqlType = pDb->GetTypeInfVarchar().FsqlType; fSqlType = pDb->GetTypeInfVarchar().FsqlType;
precision = colDefs[i].SzDataObj; precision = colDefs[i].SzDataObj;
scale = 0; scale = 0;
colDefs[i].CbValue = SQL_NTS; colDefs[i].CbValue = SQL_NTS;
@@ -394,10 +396,11 @@ bool wxDbTable::bindInsertParams(void)
colDefs[i].CbValue = SQL_NULL_DATA; colDefs[i].CbValue = SQL_NULL_DATA;
colDefs[i].Null = FALSE; colDefs[i].Null = FALSE;
} }
if (SQLBindParameter(hstmtInsert, colNo++, SQL_PARAM_INPUT, colDefs[i].SqlCtype,
fSqlType, precision, scale, (UCHAR*) colDefs[i].PtrDataObj, if (SQLBindParameter(hstmtInsert, colNo++, SQL_PARAM_INPUT, colDefs[i].SqlCtype,
precision+1,&colDefs[i].CbValue) != SQL_SUCCESS) fSqlType, precision, scale, (UCHAR*) colDefs[i].PtrDataObj,
return(pDb->DispAllErrors(henv, hdbc, hstmtInsert)); precision+1,&colDefs[i].CbValue) != SQL_SUCCESS)
return(pDb->DispAllErrors(henv, hdbc, hstmtInsert));
} }
// Completed successfully // Completed successfully
@@ -440,7 +443,7 @@ bool wxDbTable::bindUpdateParams(void)
case DB_DATA_TYPE_FLOAT: case DB_DATA_TYPE_FLOAT:
fSqlType = pDb->GetTypeInfFloat().FsqlType; fSqlType = pDb->GetTypeInfFloat().FsqlType;
precision = pDb->GetTypeInfFloat().Precision; precision = pDb->GetTypeInfFloat().Precision;
scale = pDb->GetTypeInfFloat().MaximumScale; scale = pDb->GetTypeInfFloat().MaximumScale;
// SQL Sybase Anywhere v5.5 returned a negative number for the // SQL Sybase Anywhere v5.5 returned a negative number for the
// MaxScale. This caused ODBC to kick out an error on ibscale. // MaxScale. This caused ODBC to kick out an error on ibscale.
// I check for this here and set the scale = precision. // I check for this here and set the scale = precision.
@@ -455,10 +458,11 @@ bool wxDbTable::bindUpdateParams(void)
colDefs[i].CbValue = 0; colDefs[i].CbValue = 0;
break; break;
} }
if (SQLBindParameter(hstmtUpdate, colNo++, SQL_PARAM_INPUT, colDefs[i].SqlCtype,
fSqlType, precision, scale, (UCHAR*) colDefs[i].PtrDataObj, if (SQLBindParameter(hstmtUpdate, colNo++, SQL_PARAM_INPUT, colDefs[i].SqlCtype,
precision+1, &colDefs[i].CbValue) != SQL_SUCCESS) fSqlType, precision, scale, (UCHAR*) colDefs[i].PtrDataObj,
return(pDb->DispAllErrors(henv, hdbc, hstmtUpdate)); precision+1, &colDefs[i].CbValue) != SQL_SUCCESS)
return(pDb->DispAllErrors(henv, hdbc, hstmtUpdate));
} }
// Completed successfully // Completed successfully
@@ -475,11 +479,11 @@ bool wxDbTable::bindCols(HSTMT cursor)
// Bind each column of the table to a memory address for fetching data // Bind each column of the table to a memory address for fetching data
int i; int i;
for (i = 0; i < noCols; i++) for (i = 0; i < noCols; i++)
{ {
if (SQLBindCol(cursor, i+1, colDefs[i].SqlCtype, (UCHAR*) colDefs[i].PtrDataObj, if (SQLBindCol(cursor, i+1, colDefs[i].SqlCtype, (UCHAR*) colDefs[i].PtrDataObj,
colDefs[i].SzDataObj, &cb) != SQL_SUCCESS) colDefs[i].SzDataObj, &cb) != SQL_SUCCESS)
return(pDb->DispAllErrors(henv, hdbc, cursor)); return (pDb->DispAllErrors(henv, hdbc, cursor));
} }
// Completed successfully // Completed successfully
return(TRUE); return(TRUE);
@@ -615,10 +619,10 @@ bool wxDbTable::query(int queryType, bool forUpdate, bool distinct, const char *
bool wxDbTable::Open(void) bool wxDbTable::Open(void)
{ {
if (!pDb) if (!pDb)
return FALSE; return FALSE;
int i; int i;
wxString sqlStmt; wxString sqlStmt;
// Verify that the table exists in the database // Verify that the table exists in the database
if (!pDb->TableExists(tableName,pDb->GetUsername(),tablePath)) if (!pDb->TableExists(tableName,pDb->GetUsername(),tablePath))
@@ -640,15 +644,21 @@ bool wxDbTable::Open(void)
// the wxDbTable object and the ODBC record. // the wxDbTable object and the ODBC record.
if (!queryOnly) if (!queryOnly)
{ {
if (!bindInsertParams()) // Inserts if (!bindInsertParams()) // Inserts
return(FALSE); return(FALSE);
if (!bindUpdateParams()) // Updates if (!bindUpdateParams()) // Updates
return(FALSE); return(FALSE);
} }
if (!bindCols(*hstmtDefault)) // Selects if (!bindCols(*hstmtDefault)) // Selects
return(FALSE); return(FALSE);
if (!bindCols(hstmtInternal)) // Internal use only if (!bindCols(hstmtInternal)) // Internal use only
return(FALSE); return(FALSE);
/* /*
* Do NOT bind the hstmtCount cursor!!! * Do NOT bind the hstmtCount cursor!!!
*/ */
@@ -1115,13 +1125,14 @@ bool wxDbTable::DropTable()
{ {
// Check for "Base table not found" error and ignore // Check for "Base table not found" error and ignore
pDb->GetNextError(henv, hdbc, hstmt); 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 // Check for product specific error codes
if (!((pDb->Dbms() == dbmsSYBASE_ASA && !wxStrcmp(pDb->sqlState,"42000")) || // 5.x (and lower?) if (!((pDb->Dbms() == dbmsSYBASE_ASA && !wxStrcmp(pDb->sqlState,"42000")) || // 5.x (and lower?)
(pDb->Dbms() == dbmsSYBASE_ASE && !wxStrcmp(pDb->sqlState,"37000")) || (pDb->Dbms() == dbmsSYBASE_ASE && !wxStrcmp(pDb->sqlState,"37000")) ||
(pDb->Dbms() == dbmsMY_SQL && !wxStrcmp(pDb->sqlState,"S1000")) || // untested (pDb->Dbms() == dbmsMS_SQL_SERVER && !wxStrcmp(pDb->sqlState,"S1000")) || // BJO20000427 with OpenLinkDriver
(pDb->Dbms() == dbmsPOSTGRES && !wxStrcmp(pDb->sqlState,"08S01")))) // untested (pDb->Dbms() == dbmsMY_SQL && !wxStrcmp(pDb->sqlState,"S1000")) ||
(pDb->Dbms() == dbmsPOSTGRES && !wxStrcmp(pDb->sqlState,"08S01"))))
{ {
pDb->DispNextError(); pDb->DispNextError();
pDb->DispAllErrors(henv, hdbc, hstmt); pDb->DispAllErrors(henv, hdbc, hstmt);
@@ -1241,10 +1252,13 @@ bool wxDbTable::DropIndex(const char * idxName)
if (wxStrcmp(pDb->sqlState,"S0012")) // "Index not found" if (wxStrcmp(pDb->sqlState,"S0012")) // "Index not found"
{ {
// Check for product specific error codes // Check for product specific error codes
if (!((pDb->Dbms() == dbmsSYBASE_ASA && !wxStrcmp(pDb->sqlState,"42000")) || // v5.x (and lower?) 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() == dbmsSYBASE_ASE && !wxStrcmp(pDb->sqlState,"37000")) ||
(pDb->Dbms() == dbmsMY_SQL && !wxStrcmp(pDb->sqlState,"42S02")) // untested (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->DispNextError();
pDb->DispAllErrors(henv, hdbc, hstmt); pDb->DispAllErrors(henv, hdbc, hstmt);