+ retcode = SQLGetInfo(hdbc, SQL_OUTER_JOINS, (UCHAR*) dbInf.outerJoins, 2, &cb);
+ if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+ {
+ DispAllErrors(henv, hdbc);
+ if (failOnDataTypeUnsupported)
+ return FALSE;
+ }
+
+ retcode = SQLGetInfo(hdbc, SQL_PROCEDURES, (UCHAR*) dbInf.procedureSupport, 2, &cb);
+ if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+ {
+ DispAllErrors(henv, hdbc);
+ if (failOnDataTypeUnsupported)
+ return FALSE;
+ }
+
+ retcode = SQLGetInfo(hdbc, SQL_ACCESSIBLE_TABLES, (UCHAR*) dbInf.accessibleTables, 2, &cb);
+ if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+ {
+ DispAllErrors(henv, hdbc);
+ if (failOnDataTypeUnsupported)
+ return FALSE;
+ }
+
+ retcode = SQLGetInfo(hdbc, SQL_CURSOR_COMMIT_BEHAVIOR, (UCHAR*) &dbInf.cursorCommitBehavior, sizeof(dbInf.cursorCommitBehavior), &cb);
+ if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+ {
+ DispAllErrors(henv, hdbc);
+ if (failOnDataTypeUnsupported)
+ return FALSE;
+ }
+
+ retcode = SQLGetInfo(hdbc, SQL_CURSOR_ROLLBACK_BEHAVIOR, (UCHAR*) &dbInf.cursorRollbackBehavior, sizeof(dbInf.cursorRollbackBehavior), &cb);
+ if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+ {
+ DispAllErrors(henv, hdbc);
+ if (failOnDataTypeUnsupported)
+ return FALSE;
+ }
+
+ retcode = SQLGetInfo(hdbc, SQL_NON_NULLABLE_COLUMNS, (UCHAR*) &dbInf.supportNotNullClause, sizeof(dbInf.supportNotNullClause), &cb);
+ if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+ {
+ DispAllErrors(henv, hdbc);
+ if (failOnDataTypeUnsupported)
+ return FALSE;
+ }
+
+ retcode = SQLGetInfo(hdbc, SQL_ODBC_SQL_OPT_IEF, (UCHAR*) dbInf.supportIEF, 2, &cb);
+ if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+ {
+ DispAllErrors(henv, hdbc);
+ if (failOnDataTypeUnsupported)
+ return FALSE;
+ }
+
+ retcode = SQLGetInfo(hdbc, SQL_DEFAULT_TXN_ISOLATION, (UCHAR*) &dbInf.txnIsolation, sizeof(dbInf.txnIsolation), &cb);
+ if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+ {
+ DispAllErrors(henv, hdbc);
+ if (failOnDataTypeUnsupported)
+ return FALSE;
+ }
+
+ retcode = SQLGetInfo(hdbc, SQL_TXN_ISOLATION_OPTION, (UCHAR*) &dbInf.txnIsolationOptions, sizeof(dbInf.txnIsolationOptions), &cb);
+ if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+ {
+ DispAllErrors(henv, hdbc);
+ if (failOnDataTypeUnsupported)
+ return FALSE;
+ }
+
+ retcode = SQLGetInfo(hdbc, SQL_FETCH_DIRECTION, (UCHAR*) &dbInf.fetchDirections, sizeof(dbInf.fetchDirections), &cb);
+ if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+ {
+ DispAllErrors(henv, hdbc);
+ if (failOnDataTypeUnsupported)
+ return FALSE;
+ }
+
+ retcode = SQLGetInfo(hdbc, SQL_LOCK_TYPES, (UCHAR*) &dbInf.lockTypes, sizeof(dbInf.lockTypes), &cb);
+ if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+ {
+ DispAllErrors(henv, hdbc);
+ if (failOnDataTypeUnsupported)
+ return FALSE;
+ }
+
+ retcode = SQLGetInfo(hdbc, SQL_POS_OPERATIONS, (UCHAR*) &dbInf.posOperations, sizeof(dbInf.posOperations), &cb);
+ if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+ {
+ DispAllErrors(henv, hdbc);
+ if (failOnDataTypeUnsupported)
+ return FALSE;
+ }
+
+ retcode = SQLGetInfo(hdbc, SQL_POSITIONED_STATEMENTS, (UCHAR*) &dbInf.posStmts, sizeof(dbInf.posStmts), &cb);
+ if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+ {
+ DispAllErrors(henv, hdbc);
+ if (failOnDataTypeUnsupported)
+ return FALSE;
+ }
+
+ retcode = SQLGetInfo(hdbc, SQL_SCROLL_CONCURRENCY, (UCHAR*) &dbInf.scrollConcurrency, sizeof(dbInf.scrollConcurrency), &cb);
+ if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+ {
+ DispAllErrors(henv, hdbc);
+ if (failOnDataTypeUnsupported)
+ return FALSE;
+ }
+
+ retcode = SQLGetInfo(hdbc, SQL_SCROLL_OPTIONS, (UCHAR*) &dbInf.scrollOptions, sizeof(dbInf.scrollOptions), &cb);
+ if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+ {
+ DispAllErrors(henv, hdbc);
+ if (failOnDataTypeUnsupported)
+ return FALSE;
+ }
+
+ retcode = SQLGetInfo(hdbc, SQL_STATIC_SENSITIVITY, (UCHAR*) &dbInf.staticSensitivity, sizeof(dbInf.staticSensitivity), &cb);
+ if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+ {
+ DispAllErrors(henv, hdbc);
+ if (failOnDataTypeUnsupported)
+ return FALSE;
+ }
+
+ retcode = SQLGetInfo(hdbc, SQL_TXN_CAPABLE, (UCHAR*) &dbInf.txnCapable, sizeof(dbInf.txnCapable), &cb);
+ if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+ {
+ DispAllErrors(henv, hdbc);
+ if (failOnDataTypeUnsupported)
+ return FALSE;
+ }
+
+ retcode = SQLGetInfo(hdbc, SQL_LOGIN_TIMEOUT, (UCHAR*) &dbInf.loginTimeout, sizeof(dbInf.loginTimeout), &cb);
+ if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO )
+ {
+ DispAllErrors(henv, hdbc);
+ if (failOnDataTypeUnsupported)
+ return FALSE;
+ }
+
+#ifdef DBDEBUG_CONSOLE
+ cout << wxT("***** DATA SOURCE INFORMATION *****") << endl;
+ cout << wxT(wxT("SERVER Name: ") << dbInf.serverName << endl;
+ cout << wxT("DBMS Name: ") << dbInf.dbmsName << wxT("; DBMS Version: ") << dbInf.dbmsVer << endl;
+ cout << wxT("ODBC Version: ") << dbInf.odbcVer << wxT("; Driver Version: ") << dbInf.driverVer << endl;
+
+ cout << wxT("API Conf. Level: ");
+ switch(dbInf.apiConfLvl)
+ {
+ case SQL_OAC_NONE: cout << wxT("None"); break;
+ case SQL_OAC_LEVEL1: cout << wxT("Level 1"); break;
+ case SQL_OAC_LEVEL2: cout << wxT("Level 2"); break;
+ }
+ cout << endl;
+
+ cout << wxT("SAG CLI Conf. Level: ");
+ switch(dbInf.cliConfLvl)
+ {
+ case SQL_OSCC_NOT_COMPLIANT: cout << wxT("Not Compliant"); break;
+ case SQL_OSCC_COMPLIANT: cout << wxT("Compliant"); break;
+ }
+ cout << endl;
+
+ cout << wxT("SQL Conf. Level: ");
+ switch(dbInf.sqlConfLvl)
+ {
+ case SQL_OSC_MINIMUM: cout << wxT("Minimum Grammar"); break;
+ case SQL_OSC_CORE: cout << wxT("Core Grammar"); break;
+ case SQL_OSC_EXTENDED: cout << wxT("Extended Grammar"); break;
+ }
+ cout << endl;
+
+ cout << wxT("Max. Connections: ") << dbInf.maxConnections << endl;
+ cout << wxT("Outer Joins: ") << dbInf.outerJoins << endl;
+ cout << wxT("Support for Procedures: ") << dbInf.procedureSupport << endl;
+ cout << wxT("All tables accessible : ") << dbInf.accessibleTables << endl;
+ cout << wxT("Cursor COMMIT Behavior: ");
+ switch(dbInf.cursorCommitBehavior)
+ {
+ case SQL_CB_DELETE: cout << wxT("Delete cursors"); break;
+ case SQL_CB_CLOSE: cout << wxT("Close cursors"); break;
+ case SQL_CB_PRESERVE: cout << wxT("Preserve cursors"); break;
+ }
+ cout << endl;
+
+ cout << wxT("Cursor ROLLBACK Behavior: ");
+ switch(dbInf.cursorRollbackBehavior)
+ {
+ case SQL_CB_DELETE: cout << wxT("Delete cursors"); break;
+ case SQL_CB_CLOSE: cout << wxT("Close cursors"); break;
+ case SQL_CB_PRESERVE: cout << wxT("Preserve cursors"); break;
+ }
+ cout << endl;
+
+ cout << wxT("Support NOT NULL clause: ");
+ switch(dbInf.supportNotNullClause)
+ {
+ case SQL_NNC_NULL: cout << wxT("No"); break;
+ case SQL_NNC_NON_NULL: cout << wxT("Yes"); break;
+ }
+ cout << endl;
+
+ cout << wxT("Support IEF (Ref. Integrity): ") << dbInf.supportIEF << endl;
+ cout << wxT("Login Timeout: ") << dbInf.loginTimeout << endl;
+
+ cout << endl << endl << wxT("more ...") << endl;
+ getchar();
+
+ cout << wxT("Default Transaction Isolation: ";
+ switch(dbInf.txnIsolation)
+ {
+ case SQL_TXN_READ_UNCOMMITTED: cout << wxT("Read Uncommitted"); break;
+ case SQL_TXN_READ_COMMITTED: cout << wxT("Read Committed"); break;
+ case SQL_TXN_REPEATABLE_READ: cout << wxT("Repeatable Read"); break;
+ case SQL_TXN_SERIALIZABLE: cout << wxT("Serializable"); break;
+#ifdef ODBC_V20
+ case SQL_TXN_VERSIONING: cout << wxT("Versioning"); break;
+#endif
+ }
+ cout << endl;
+
+ cout << wxT("Transaction Isolation Options: ");
+ if (dbInf.txnIsolationOptions & SQL_TXN_READ_UNCOMMITTED)
+ cout << wxT("Read Uncommitted, ");
+ if (dbInf.txnIsolationOptions & SQL_TXN_READ_COMMITTED)
+ cout << wxT("Read Committed, ");
+ if (dbInf.txnIsolationOptions & SQL_TXN_REPEATABLE_READ)
+ cout << wxT("Repeatable Read, ");
+ if (dbInf.txnIsolationOptions & SQL_TXN_SERIALIZABLE)
+ cout << wxT("Serializable, ");
+#ifdef ODBC_V20
+ if (dbInf.txnIsolationOptions & SQL_TXN_VERSIONING)
+ cout << wxT("Versioning");
+#endif
+ cout << endl;
+
+ cout << wxT("Fetch Directions Supported:") << endl << wxT(" ");
+ if (dbInf.fetchDirections & SQL_FD_FETCH_NEXT)
+ cout << wxT("Next, ");
+ if (dbInf.fetchDirections & SQL_FD_FETCH_PRIOR)
+ cout << wxT("Prev, ");
+ if (dbInf.fetchDirections & SQL_FD_FETCH_FIRST)
+ cout << wxT("First, ");
+ if (dbInf.fetchDirections & SQL_FD_FETCH_LAST)
+ cout << wxT("Last, ");
+ if (dbInf.fetchDirections & SQL_FD_FETCH_ABSOLUTE)
+ cout << wxT("Absolute, ");
+ if (dbInf.fetchDirections & SQL_FD_FETCH_RELATIVE)
+ cout << wxT("Relative, ");
+#ifdef ODBC_V20
+ if (dbInf.fetchDirections & SQL_FD_FETCH_RESUME)
+ cout << wxT("Resume, ");
+#endif
+ if (dbInf.fetchDirections & SQL_FD_FETCH_BOOKMARK)
+ cout << wxT("Bookmark");
+ cout << endl;
+
+ cout << wxT("Lock Types Supported (SQLSetPos): ");
+ if (dbInf.lockTypes & SQL_LCK_NO_CHANGE)
+ cout << wxT("No Change, ");
+ if (dbInf.lockTypes & SQL_LCK_EXCLUSIVE)
+ cout << wxT("Exclusive, ");
+ if (dbInf.lockTypes & SQL_LCK_UNLOCK)
+ cout << wxT("UnLock");
+ cout << endl;
+
+ cout << wxT("Position Operations Supported (SQLSetPos): ");
+ if (dbInf.posOperations & SQL_POS_POSITION)
+ cout << wxT("Position, ");
+ if (dbInf.posOperations & SQL_POS_REFRESH)
+ cout << wxT("Refresh, ");
+ if (dbInf.posOperations & SQL_POS_UPDATE)
+ cout << wxT("Upd, "));
+ if (dbInf.posOperations & SQL_POS_DELETE)
+ cout << wxT("Del, ");
+ if (dbInf.posOperations & SQL_POS_ADD)
+ cout << wxT("Add");
+ cout << endl;
+
+ cout << wxT("Positioned Statements Supported: ");
+ if (dbInf.posStmts & SQL_PS_POSITIONED_DELETE)
+ cout << wxT("Pos delete, ");
+ if (dbInf.posStmts & SQL_PS_POSITIONED_UPDATE)
+ cout << wxT("Pos update, ");
+ if (dbInf.posStmts & SQL_PS_SELECT_FOR_UPDATE)
+ cout << wxT("Select for update");
+ cout << endl;
+
+ cout << wxT("Scroll Concurrency: ");
+ if (dbInf.scrollConcurrency & SQL_SCCO_READ_ONLY)
+ cout << wxT("Read Only, ");
+ if (dbInf.scrollConcurrency & SQL_SCCO_LOCK)
+ cout << wxT("Lock, ");
+ if (dbInf.scrollConcurrency & SQL_SCCO_OPT_ROWVER)
+ cout << wxT("Opt. Rowver, ");
+ if (dbInf.scrollConcurrency & SQL_SCCO_OPT_VALUES)
+ cout << wxT("Opt. Values");
+ cout << endl;
+
+ cout << wxT("Scroll Options: ");
+ if (dbInf.scrollOptions & SQL_SO_FORWARD_ONLY)
+ cout << wxT("Fwd Only, ");
+ if (dbInf.scrollOptions & SQL_SO_STATIC)
+ cout << wxT("Static, ");
+ if (dbInf.scrollOptions & SQL_SO_KEYSET_DRIVEN)
+ cout << wxT("Keyset Driven, ");
+ if (dbInf.scrollOptions & SQL_SO_DYNAMIC)
+ cout << wxT("Dynamic, ");
+ if (dbInf.scrollOptions & SQL_SO_MIXED)
+ cout << wxT("Mixed");
+ cout << endl;
+
+ cout << wxT("Static Sensitivity: ");
+ if (dbInf.staticSensitivity & SQL_SS_ADDITIONS)
+ cout << wxT("Additions, ");
+ if (dbInf.staticSensitivity & SQL_SS_DELETIONS)
+ cout << wxT("Deletions, ");
+ if (dbInf.staticSensitivity & SQL_SS_UPDATES)
+ cout << wxT("Updates");
+ cout << endl;
+
+ cout << wxT("Transaction Capable?: ");
+ switch(dbInf.txnCapable)
+ {
+ case SQL_TC_NONE: cout << wxT("No"); break;
+ case SQL_TC_DML: cout << wxT("DML Only"); break;
+ case SQL_TC_DDL_COMMIT: cout << wxT("DDL Commit"); break;
+ case SQL_TC_DDL_IGNORE: cout << wxT("DDL Ignore"); break;
+ case SQL_TC_ALL: cout << wxT("DDL & DML"); break;
+ }
+ cout << endl;
+
+ cout << endl;
+#endif
+
+ // Completed Successfully
+ return(TRUE);
+
+} // wxDb::getDbInfo()
+
+
+/********** wxDb::getDataTypeInfo() **********/
+bool wxDb::getDataTypeInfo(SWORD fSqlType, wxDbSqlTypeInfo &structSQLTypeInfo)
+{
+/*
+ * fSqlType will be something like SQL_VARCHAR. This parameter determines
+ * the data type inf. is gathered for.
+ *
+ * wxDbSqlTypeInfo is a structure that is filled in with data type information,
+ */
+ RETCODE retcode;
+ SDWORD cbRet;
+
+ // Get information about the data type specified
+ if (SQLGetTypeInfo(hstmt, fSqlType) != SQL_SUCCESS)
+ return(DispAllErrors(henv, hdbc, hstmt));
+
+ // Fetch the record
+ retcode = SQLFetch(hstmt);
+ if (retcode != SQL_SUCCESS)
+ {
+#ifdef DBDEBUG_CONSOLE
+ if (retcode == SQL_NO_DATA_FOUND)
+ cout << wxT("SQL_NO_DATA_FOUND fetching inf. about data type.") << endl;
+#endif
+ DispAllErrors(henv, hdbc, hstmt);
+ SQLFreeStmt(hstmt, SQL_CLOSE);
+ return(FALSE);
+ }
+
+ wxChar typeName[DB_TYPE_NAME_LEN+1];
+
+ // Obtain columns from the record
+ if (SQLGetData(hstmt, 1, SQL_C_CHAR, (UCHAR*) typeName, DB_TYPE_NAME_LEN, &cbRet) != SQL_SUCCESS)
+ return(DispAllErrors(henv, hdbc, hstmt));
+
+ structSQLTypeInfo.TypeName = typeName;
+
+ // BJO 20000503: no more needed with new GetColumns...
+#if OLD_GETCOLUMNS
+ // BJO 991209
+ if (Dbms() == dbmsMY_SQL)
+ {
+ if (structSQLTypeInfo.TypeName == wxT("middleint"))
+ structSQLTypeInfo.TypeName = wxT("mediumint");
+ else if (structSQLTypeInfo.TypeName == wxT("middleint unsigned"))
+ structSQLTypeInfo.TypeName = wxT("mediumint unsigned");
+ else if (structSQLTypeInfo.TypeName == wxT("integer"))
+ structSQLTypeInfo.TypeName = wxT("int");
+ else if (structSQLTypeInfo.TypeName == wxT("integer unsigned"))
+ structSQLTypeInfo.TypeName = wxT("int unsigned");
+ else if (structSQLTypeInfo.TypeName == wxT("middleint"))
+ structSQLTypeInfo.TypeName = wxT("mediumint");
+ else if (structSQLTypeInfo.TypeName == wxT("varchar"))
+ structSQLTypeInfo.TypeName = wxT("char");
+ }
+
+ // BJO 20000427 : OpenLink driver
+ if (!wxStrncmp(dbInf.driverName, wxT("oplodbc"), 7) ||
+ !wxStrncmp(dbInf.driverName, wxT("OLOD"), 4))
+ {
+ if (structSQLTypeInfo.TypeName == wxT("double precision"))
+ structSQLTypeInfo.TypeName = wxT("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)
+ return(DispAllErrors(henv, hdbc, hstmt));
+// if (SQLGetData(hstmt, 14, SQL_C_SHORT, (UCHAR*) &structSQLTypeInfo.MinimumScale, 0, &cbRet) != SQL_SUCCESS)
+// return(DispAllErrors(henv, hdbc, hstmt));
+
+ if (SQLGetData(hstmt, 15, SQL_C_SHORT,(UCHAR*) &structSQLTypeInfo.MaximumScale, 0, &cbRet) != SQL_SUCCESS)
+ return(DispAllErrors(henv, hdbc, hstmt));
+
+ if (structSQLTypeInfo.MaximumScale < 0)
+ structSQLTypeInfo.MaximumScale = 0;
+
+ // Close the statement handle which closes open cursors
+ if (SQLFreeStmt(hstmt, SQL_CLOSE) != SQL_SUCCESS)
+ return(DispAllErrors(henv, hdbc, hstmt));
+
+ // Completed Successfully
+ return(TRUE);
+
+} // wxDb::getDataTypeInfo()
+
+
+/********** wxDb::Close() **********/
+void wxDb::Close(void)
+{
+ // Close the Sql Log file
+ if (fpSqlLog)
+ {
+ fclose(fpSqlLog);
+ fpSqlLog = 0;
+ }
+
+ // Free statement handle
+ if (dbIsOpen)
+ {
+ if (SQLFreeStmt(hstmt, SQL_DROP) != SQL_SUCCESS)
+ DispAllErrors(henv, hdbc);
+ }
+
+ // Disconnect from the datasource
+ if (SQLDisconnect(hdbc) != SQL_SUCCESS)
+ DispAllErrors(henv, hdbc);
+
+ // Free the connection to the datasource
+ if (SQLFreeConnect(hdbc) != SQL_SUCCESS)
+ DispAllErrors(henv, hdbc);
+
+ // There should be zero Ctable objects still connected to this db object
+ wxASSERT(nTables == 0);
+
+#ifdef __WXDEBUG__
+ wxTablesInUse *tiu;
+ wxList::compatibility_iterator pNode;
+ pNode = TablesInUse.GetFirst();
+ wxString s,s2;
+ while (pNode)
+ {
+ tiu = (wxTablesInUse *)pNode->GetData();
+ if (tiu->pDb == this)
+ {
+ s.Printf(wxT("(%-20s) tableID:[%6lu] pDb:[%p]"), tiu->tableName,tiu->tableID,tiu->pDb);
+ s2.Printf(wxT("Orphaned table found using pDb:[%p]"),this);
+ wxLogDebug(s.c_str(),s2.c_str());
+ }
+ pNode = pNode->GetNext();
+ }
+#endif
+
+ // Copy the error messages to a global variable
+ int i;
+ for (i = 0; i < DB_MAX_ERROR_HISTORY; i++)
+ wxStrcpy(DBerrorList[i], errorList[i]);
+
+ dbmsType = dbmsUNIDENTIFIED;
+ dbIsOpen = FALSE;
+
+} // wxDb::Close()