+ if (pDb->FwdOnlyCursors())
+ {
+ wxFAIL_MSG(wxT("GetPrev()::Backward scrolling cursors are not enabled for this instance of wxDbTable"));
+ return FALSE;
+ }
+ else
+ return(getRec(SQL_FETCH_PRIOR));
+} // wxDbTable::GetPrev()
+
+
+/********** wxDbTable::operator-- **********/
+bool wxDbTable::operator--(int)
+{
+ if (pDb->FwdOnlyCursors())
+ {
+ wxFAIL_MSG(wxT("operator--:Backward scrolling cursors are not enabled for this instance of wxDbTable"));
+ return FALSE;
+ }
+ else
+ return(getRec(SQL_FETCH_PRIOR));
+} // wxDbTable::operator--
+
+
+/********** wxDbTable::GetFirst() **********/
+bool wxDbTable::GetFirst(void)
+{
+ if (pDb->FwdOnlyCursors())
+ {
+ wxFAIL_MSG(wxT("GetFirst():Backward scrolling cursors are not enabled for this instance of wxDbTable"));
+ return FALSE;
+ }
+ else
+ return(getRec(SQL_FETCH_FIRST));
+} // wxDbTable::GetFirst()
+
+
+/********** wxDbTable::GetLast() **********/
+bool wxDbTable::GetLast(void)
+{
+ if (pDb->FwdOnlyCursors())
+ {
+ wxFAIL_MSG(wxT("GetLast()::Backward scrolling cursors are not enabled for this instance of wxDbTable"));
+ return FALSE;
+ }
+ else
+ return(getRec(SQL_FETCH_LAST));
+} // wxDbTable::GetLast()
+
+
+/********** wxDbTable::BuildSelectStmt() **********/
+void wxDbTable::BuildSelectStmt(char *pSqlStmt, int typeOfSelect, bool distinct)
+{
+ char whereClause[DB_MAX_WHERE_CLAUSE_LEN];
+
+ whereClause[0] = 0;
+
+ // Build a select statement to query the database
+ wxStrcpy(pSqlStmt, "SELECT ");
+
+ // SELECT DISTINCT values only?
+ if (distinct)
+ wxStrcat(pSqlStmt, "DISTINCT ");
+
+ // Was a FROM clause specified to join tables to the base table?
+ // Available for ::Query() only!!!
+ bool appendFromClause = FALSE;
+#if wxODBC_BACKWARD_COMPATABILITY
+ if (typeOfSelect == DB_SELECT_WHERE && from && wxStrlen(from))
+ appendFromClause = TRUE;
+#else
+ if (typeOfSelect == DB_SELECT_WHERE && from.Length())
+ appendFromClause = TRUE;
+#endif
+
+ // Add the column list
+ int i;
+ for (i = 0; i < noCols; i++)
+ {
+ // If joining tables, the base table column names must be qualified to avoid ambiguity
+ if (appendFromClause)
+ {
+ wxStrcat(pSqlStmt, queryTableName);
+ wxStrcat(pSqlStmt, ".");
+ }
+ wxStrcat(pSqlStmt, colDefs[i].ColName);
+ if (i + 1 < noCols)
+ wxStrcat(pSqlStmt, ",");
+ }
+
+ // If the datasource supports ROWID, get this column as well. Exception: Don't retrieve
+ // the ROWID if querying distinct records. The rowid will always be unique.
+ if (!distinct && CanUpdByROWID())
+ {
+ // If joining tables, the base table column names must be qualified to avoid ambiguity
+ if (appendFromClause)
+ {
+ wxStrcat(pSqlStmt, ",");
+ wxStrcat(pSqlStmt, queryTableName);
+ wxStrcat(pSqlStmt, ".ROWID");
+ }
+ else
+ wxStrcat(pSqlStmt, ",ROWID");
+ }
+
+ // Append the FROM tablename portion
+ wxStrcat(pSqlStmt, " FROM ");
+ wxStrcat(pSqlStmt, queryTableName);
+
+ // Sybase uses the HOLDLOCK keyword to lock a record during query.
+ // The HOLDLOCK keyword follows the table name in the from clause.
+ // Each table in the from clause must specify HOLDLOCK or
+ // NOHOLDLOCK (the default). Note: The "FOR UPDATE" clause
+ // is parsed but ignored in SYBASE Transact-SQL.
+ if (selectForUpdate && (pDb->Dbms() == dbmsSYBASE_ASA || pDb->Dbms() == dbmsSYBASE_ASE))
+ wxStrcat(pSqlStmt, " HOLDLOCK");
+
+ if (appendFromClause)
+ wxStrcat(pSqlStmt, from);
+
+ // Append the WHERE clause. Either append the where clause for the class
+ // or build a where clause. The typeOfSelect determines this.
+ switch(typeOfSelect)
+ {
+ case DB_SELECT_WHERE:
+#if wxODBC_BACKWARD_COMPATABILITY
+ if (where && wxStrlen(where)) // May not want a where clause!!!
+#else
+ if (where.Length()) // May not want a where clause!!!
+#endif
+ {
+ wxStrcat(pSqlStmt, " WHERE ");
+ wxStrcat(pSqlStmt, where);
+ }
+ break;
+ case DB_SELECT_KEYFIELDS:
+ BuildWhereClause(whereClause, DB_WHERE_KEYFIELDS);
+ if (wxStrlen(whereClause))
+ {
+ wxStrcat(pSqlStmt, " WHERE ");
+ wxStrcat(pSqlStmt, whereClause);
+ }
+ break;
+ case DB_SELECT_MATCHING:
+ BuildWhereClause(whereClause, DB_WHERE_MATCHING);
+ if (wxStrlen(whereClause))
+ {
+ wxStrcat(pSqlStmt, " WHERE ");
+ wxStrcat(pSqlStmt, whereClause);
+ }
+ break;
+ }
+
+ // Append the ORDER BY clause
+#if wxODBC_BACKWARD_COMPATABILITY
+ if (orderBy && wxStrlen(orderBy))
+#else
+ if (orderBy.Length())
+#endif
+ {
+ wxStrcat(pSqlStmt, " ORDER BY ");
+ wxStrcat(pSqlStmt, orderBy);
+ }
+
+ // SELECT FOR UPDATE if told to do so and the datasource is capable. Sybase
+ // parses the FOR UPDATE clause but ignores it. See the comment above on the
+ // HOLDLOCK for Sybase.
+ if (selectForUpdate && CanSelectForUpdate())
+ wxStrcat(pSqlStmt, " FOR UPDATE");
+
+} // wxDbTable::BuildSelectStmt()
+
+
+/********** wxDbTable::GetRowNum() **********/
+UWORD wxDbTable::GetRowNum(void)
+{
+ UDWORD rowNum;
+
+ if (SQLGetStmtOption(hstmt, SQL_ROW_NUMBER, (UCHAR*) &rowNum) != SQL_SUCCESS)
+ {
+ pDb->DispAllErrors(henv, hdbc, hstmt);
+ return(0);
+ }
+
+ // Completed successfully
+ return((UWORD) rowNum);
+
+} // wxDbTable::GetRowNum()
+
+
+/********** wxDbTable::CloseCursor() **********/
+bool wxDbTable::CloseCursor(HSTMT cursor)