QODBCResult Class Reference

#include <qsql_odbc.h>

Inheritance diagram for QODBCResult:

Inheritance graph
[legend]
Collaboration diagram for QODBCResult:

Collaboration graph
[legend]
List of all members.

Detailed Description

Definition at line 73 of file qsql_odbc.h.

Public Member Functions

 QODBCResult (const QODBCDriver *db, QODBCDriverPrivate *p)
virtual ~QODBCResult ()
bool prepare (const QString &query)
bool exec ()
QVariant handle () const

Protected Member Functions

bool fetchNext ()
bool fetchFirst ()
bool fetchLast ()
bool fetchPrior ()
bool fetch (int i)
bool reset (const QString &query)
QVariant data (int field)
bool isNull (int field)
int size ()
int numRowsAffected ()
QSqlRecord record () const

Private Attributes

QODBCPrivated


Constructor & Destructor Documentation

QODBCResult::QODBCResult ( const QODBCDriver db,
QODBCDriverPrivate p 
)

Definition at line 642 of file qsql_odbc.cpp.

References d, QODBCPrivate::hDbc, QODBCPrivate::hEnv, p, QODBCPrivate::sql_char_type, QODBCPrivate::sql_longvarchar_type, QODBCPrivate::sql_varchar_type, QODBCPrivate::unicode, and QODBCPrivate::useSchema.

00643 : QSqlResult(db)
00644 {
00645     d = new QODBCPrivate();
00646     d->hEnv = p->hEnv;
00647     d->hDbc = p->hDbc;
00648     d->unicode = p->unicode;
00649     d->useSchema = p->useSchema;
00650     d->sql_char_type = p->sql_char_type;
00651     d->sql_varchar_type = p->sql_varchar_type;
00652     d->sql_longvarchar_type = p->sql_longvarchar_type;
00653 }

QODBCResult::~QODBCResult (  )  [virtual]

Definition at line 655 of file qsql_odbc.cpp.

References d, QSqlResult::driver(), QODBCPrivate::hStmt, QString::number(), and qSqlWarning().

00656 {
00657     if (d->hStmt && driver()->isOpen()) {
00658         SQLRETURN r = SQLFreeHandle(SQL_HANDLE_STMT, d->hStmt);
00659         if (r != SQL_SUCCESS)
00660             qSqlWarning(QLatin1String("QODBCDriver: Unable to free statement handle ")
00661                          + QString::number(r), d);
00662     }
00663 
00664     delete d;
00665 }

Here is the call graph for this function:


Member Function Documentation

bool QODBCResult::prepare ( const QString query  )  [virtual]

Prepares the given query for execution; the query will normally use placeholders so that it can be executed repeatedly. Returns true if the query is prepared successfully; otherwise returns false.

See also:
exec()

Reimplemented from QSqlResult.

Definition at line 973 of file qsql_odbc.cpp.

References QSql::BeforeFirstRow, QSqlRecord::clear(), d, QODBCPrivate::hDbc, QODBCPrivate::hStmt, QSqlResult::isForwardOnly(), QString::length(), qMakeError(), qSqlWarning(), QODBCPrivate::rInf, QSqlResult::setActive(), QSqlResult::setAt(), QSqlResult::setLastError(), QSqlError::StatementError, QString::toLocal8Bit(), QCoreApplication::translate(), and QString::unicode().

00974 {
00975     setActive(false);
00976     setAt(QSql::BeforeFirstRow);
00977     SQLRETURN r;
00978 
00979     d->rInf.clear();
00980     if (d->hStmt) {
00981         r = SQLFreeHandle(SQL_HANDLE_STMT, d->hStmt);
00982         if (r != SQL_SUCCESS) {
00983             qSqlWarning(QLatin1String("QODBCResult::prepare: Unable to close statement"), d);
00984             return false;
00985         }
00986     }
00987     r  = SQLAllocHandle(SQL_HANDLE_STMT,
00988                          d->hDbc,
00989                          &d->hStmt);
00990     if (r != SQL_SUCCESS) {
00991         qSqlWarning(QLatin1String("QODBCResult::prepare: Unable to allocate statement handle"), d);
00992         return false;
00993     }
00994 
00995     if (isForwardOnly()) {
00996         r = SQLSetStmtAttr(d->hStmt,
00997                             SQL_ATTR_CURSOR_TYPE,
00998                             (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
00999                             SQL_IS_UINTEGER);
01000     } else {
01001         r = SQLSetStmtAttr(d->hStmt,
01002                             SQL_ATTR_CURSOR_TYPE,
01003                             (SQLPOINTER)SQL_CURSOR_STATIC,
01004                             SQL_IS_UINTEGER);
01005     }
01006     if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
01007         setLastError(qMakeError(QCoreApplication::translate("QODBCResult",
01008             "QODBCResult::reset: Unable to set 'SQL_CURSOR_STATIC' as statement attribute. "
01009             "Please check your ODBC driver configuration"), QSqlError::StatementError, d));
01010         return false;
01011     }
01012 
01013 #ifdef UNICODE
01014     r = SQLPrepare(d->hStmt,
01015                     (SQLWCHAR*) query.unicode(),
01016                     (SQLINTEGER) query.length());
01017 #else
01018     QByteArray query8 = query.toLocal8Bit();
01019     r = SQLPrepare(d->hStmt,
01020                     (SQLCHAR*) query8.constData(),
01021                     (SQLINTEGER) query8.length());
01022 #endif
01023 
01024     if (r != SQL_SUCCESS) {
01025         setLastError(qMakeError(QCoreApplication::translate("QODBCResult",
01026                      "Unable to prepare statement"), QSqlError::StatementError, d));
01027         return false;
01028     }
01029     return true;
01030 }

Here is the call graph for this function:

bool QODBCResult::exec (  )  [virtual]

Executes the query, returning true if successful; otherwise returns false.

See also:
prepare()

Reimplemented from QSqlResult.

Definition at line 1032 of file qsql_odbc.cpp.

References QSqlRecord::append(), QList< T >::append(), QSql::BeforeFirstRow, QSqlResult::bindValueType(), QSqlResult::boundValues(), QVariant::ByteArray, QString::capacity(), QSqlRecord::clear(), constData(), QString::constData(), QByteArray::constData(), d, QVarLengthArray< T, Prealloc >::data(), QVariant::Date, QDateTime::date(), QVariant::DateTime, QDate::day(), QVariant::Double, QODBCPrivate::fieldCache, QODBCPrivate::fieldCacheIdx, QString::fromAscii(), QString::fromUtf16(), QSqlResult::hasOutValues(), QTime::hour(), QODBCPrivate::hStmt, i, QSql::InOut, QVariant::Int, QSqlResult::isSelect(), QString::length(), QByteArray::length(), QTime::minute(), QDate::month(), QTime::msec(), NULL, QSql::Out, qMakeError(), qMakeFieldInfo(), qODBCWarn(), qParamType, QSQLLEN, qSqlWarning(), qWarning(), QByteArray::resize(), QVector< T >::resize(), QODBCPrivate::rInf, QTime::second(), QSqlResult::setActive(), QSqlResult::setAt(), QSqlResult::setLastError(), QSqlResult::setSelect(), QVarLengthArray< T, Prealloc >::size(), QByteArray::size(), QSqlError::StatementError, QVariant::String, QList< T >::takeFirst(), QDateTime::time(), QVariant::Time, QCoreApplication::translate(), type, QODBCPrivate::unicode, QString::utf16(), val, values, and QDate::year().

01033 {
01034     SQLRETURN r;
01035     QList<QByteArray> tmpStorage; // holds temporary buffers
01036     QVarLengthArray<QSQLLEN, 32> indicators(boundValues().count());
01037 
01038     memset(indicators.data(), 0, indicators.size() * sizeof(QSQLLEN));
01039     setActive(false);
01040     setAt(QSql::BeforeFirstRow);
01041     d->rInf.clear();
01042     d->fieldCacheIdx = 0;
01043 
01044     if (!d->hStmt) {
01045         qSqlWarning(QLatin1String("QODBCResult::exec: No statement handle available"), d);
01046         return false;
01047     }
01048     if (isSelect())
01049         SQLCloseCursor(d->hStmt);
01050 
01051     // bind parameters - only positional binding allowed
01052     QVector<QVariant>& values = boundValues();
01053     int i;
01054     for (i = 0; i < values.count(); ++i) {
01055         if (bindValueType(i) & QSql::Out)
01056             values[i].detach();
01057         const QVariant &val = values.at(i);
01058         QSQLLEN *ind = &indicators[i];
01059         if (val.isNull())
01060             *ind = SQL_NULL_DATA;
01061         switch (val.type()) {
01062             case QVariant::Date: {
01063                 QByteArray ba;
01064                 ba.resize(sizeof(DATE_STRUCT));
01065                 DATE_STRUCT *dt = (DATE_STRUCT *)ba.constData();
01066                 QDate qdt = val.toDate();
01067                 dt->year = qdt.year();
01068                 dt->month = qdt.month();
01069                 dt->day = qdt.day();
01070                 r = SQLBindParameter(d->hStmt,
01071                                       i + 1,
01072                                       qParamType[(QFlag)(bindValueType(i)) & QSql::InOut],
01073                                       SQL_C_DATE,
01074                                       SQL_DATE,
01075                                       0,
01076                                       0,
01077                                       (void *) dt,
01078                                       0,
01079                                       *ind == SQL_NULL_DATA ? ind : NULL);
01080                 tmpStorage.append(ba);
01081                 break; }
01082             case QVariant::Time: {
01083                 QByteArray ba;
01084                 ba.resize(sizeof(TIME_STRUCT));
01085                 TIME_STRUCT *dt = (TIME_STRUCT *)ba.constData();
01086                 QTime qdt = val.toTime();
01087                 dt->hour = qdt.hour();
01088                 dt->minute = qdt.minute();
01089                 dt->second = qdt.second();
01090                 r = SQLBindParameter(d->hStmt,
01091                                       i + 1,
01092                                       qParamType[(QFlag)(bindValueType(i)) & QSql::InOut],
01093                                       SQL_C_TIME,
01094                                       SQL_TIME,
01095                                       0,
01096                                       0,
01097                                       (void *) dt,
01098                                       0,
01099                                       *ind == SQL_NULL_DATA ? ind : NULL);
01100                 tmpStorage.append(ba);
01101                 break; }
01102             case QVariant::DateTime: {
01103                 QByteArray ba;
01104                 ba.resize(sizeof(TIMESTAMP_STRUCT));
01105                 TIMESTAMP_STRUCT * dt = (TIMESTAMP_STRUCT *)ba.constData();
01106                 QDateTime qdt = val.toDateTime();
01107                 dt->year = qdt.date().year();
01108                 dt->month = qdt.date().month();
01109                 dt->day = qdt.date().day();
01110                 dt->hour = qdt.time().hour();
01111                 dt->minute = qdt.time().minute();
01112                 dt->second = qdt.time().second();
01113                 dt->fraction = qdt.time().msec() * 1000000;
01114                 r = SQLBindParameter(d->hStmt,
01115                                       i + 1,
01116                                       qParamType[(QFlag)(bindValueType(i)) & QSql::InOut],
01117                                       SQL_C_TIMESTAMP,
01118                                       SQL_TIMESTAMP,
01119                                       19,
01120                                       0,
01121                                       (void *) dt,
01122                                       0,
01123                                       *ind == SQL_NULL_DATA ? ind : NULL);
01124                 tmpStorage.append(ba);
01125                 break; }
01126             case QVariant::Int:
01127                 r = SQLBindParameter(d->hStmt,
01128                                       i + 1,
01129                                       qParamType[(QFlag)(bindValueType(i)) & QSql::InOut],
01130                                       SQL_C_SLONG,
01131                                       SQL_INTEGER,
01132                                       0,
01133                                       0,
01134                                       (void *) val.constData(),
01135                                       0,
01136                                       *ind == SQL_NULL_DATA ? ind : NULL);
01137                 break;
01138             case QVariant::Double:
01139                 r = SQLBindParameter(d->hStmt,
01140                                       i + 1,
01141                                       qParamType[(QFlag)(bindValueType(i)) & QSql::InOut],
01142                                       SQL_C_DOUBLE,
01143                                       SQL_DOUBLE,
01144                                       0,
01145                                       0,
01146                                       (void *) val.constData(),
01147                                       0,
01148                                       *ind == SQL_NULL_DATA ? ind : NULL);
01149                 break;
01150             case QVariant::ByteArray:
01151                 if (*ind != SQL_NULL_DATA) {
01152                     *ind = val.toByteArray().size();
01153                 }
01154                 r = SQLBindParameter(d->hStmt,
01155                                       i + 1,
01156                                       qParamType[(QFlag)(bindValueType(i)) & QSql::InOut],
01157                                       SQL_C_BINARY,
01158                                       SQL_LONGVARBINARY,
01159                                       val.toByteArray().size(),
01160                                       0,
01161                                       (void *) val.toByteArray().constData(),
01162                                       val.toByteArray().size(),
01163                                       ind);
01164                 break;
01165 #ifndef Q_ODBC_VERSION_2
01166             case QVariant::String:
01167                 if (d->unicode) {
01168                     QString str = val.toString();
01169                     str.utf16();
01170                     if (*ind != SQL_NULL_DATA)
01171                         *ind = str.length() * sizeof(QChar);
01172                     if (bindValueType(i) & QSql::Out) {
01173                         QByteArray ba((char*)str.constData(), str.capacity() * sizeof(QChar));
01174                         r = SQLBindParameter(d->hStmt,
01175                                             i + 1,
01176                                             qParamType[(QFlag)(bindValueType(i)) & QSql::InOut],
01177                                             SQL_C_WCHAR,
01178                                             str.length() > 4000 ? SQL_WLONGVARCHAR : SQL_WVARCHAR,
01179                                             0, // god knows... don't change this!
01180                                             0,
01181                                             (void *)ba.constData(),
01182                                             ba.size(),
01183                                             ind);
01184                         tmpStorage.append(ba);
01185                         break;
01186                     }
01187 
01188                     r = SQLBindParameter(d->hStmt,
01189                                           i + 1,
01190                                           qParamType[(QFlag)(bindValueType(i)) & QSql::InOut],
01191                                           SQL_C_WCHAR,
01192                                           str.length() > 4000 ? SQL_WLONGVARCHAR : SQL_WVARCHAR,
01193                                           str.length() * sizeof(QChar),
01194                                           0,
01195                                           (void *)str.constData(),
01196                                           str.length() * sizeof(QChar),
01197                                           ind);
01198                     break;
01199                 }
01200 #endif
01201             // fall through
01202             default: {
01203                 QByteArray ba = val.toString().toAscii();
01204                 if (*ind != SQL_NULL_DATA)
01205                     *ind = ba.size();
01206                 r = SQLBindParameter(d->hStmt,
01207                                       i + 1,
01208                                       qParamType[(QFlag)(bindValueType(i)) & QSql::InOut],
01209                                       SQL_C_CHAR,
01210                                       ba.length() > 4000 ? SQL_LONGVARCHAR : SQL_VARCHAR,
01211                                       ba.length() + 1,
01212                                       0,
01213                                       (void *) ba.constData(),
01214                                       ba.length() + 1,
01215                                       ind);
01216                 tmpStorage.append(ba);
01217                 break; }
01218         }
01219         if (r != SQL_SUCCESS) {
01220             qWarning("QODBCResult::exec: unable to bind variable: %s",
01221                      qODBCWarn(d).toLocal8Bit().constData());
01222             setLastError(qMakeError(QCoreApplication::translate("QODBCResult",
01223                          "Unable to bind variable"), QSqlError::StatementError, d));
01224             return false;
01225         }
01226     }
01227     r = SQLExecute(d->hStmt);
01228     if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
01229         qWarning("QODBCResult::exec: Unable to execute statement: %s",
01230                  qODBCWarn(d).toLocal8Bit().constData());
01231         setLastError(qMakeError(QCoreApplication::translate("QODBCResult",
01232                      "Unable to execute statement"), QSqlError::StatementError, d));
01233         return false;
01234     }
01235     SQLSMALLINT count;
01236     r = SQLNumResultCols(d->hStmt, &count);
01237     if (count) {
01238         setSelect(true);
01239         for (int i = 0; i < count; ++i) {
01240             d->rInf.append(qMakeFieldInfo(d, i));
01241         }
01242   d->fieldCache.resize(count);
01243     } else {
01244         setSelect(false);
01245     }
01246     setActive(true);
01247 
01248     //get out parameters
01249     if (!hasOutValues())
01250         return true;
01251 
01252     for (i = 0; i < values.count(); ++i) {
01253         switch (values.at(i).type()) {
01254             case QVariant::Date: {
01255                 DATE_STRUCT ds = *((DATE_STRUCT *)tmpStorage.takeFirst().constData());
01256                 values[i] = QVariant(QDate(ds.year, ds.month, ds.day));
01257                 break; }
01258             case QVariant::Time: {
01259                 TIME_STRUCT dt = *((TIME_STRUCT *)tmpStorage.takeFirst().constData());
01260                 values[i] = QVariant(QTime(dt.hour, dt.minute, dt.second));
01261                 break; }
01262             case QVariant::DateTime: {
01263                 TIMESTAMP_STRUCT dt = *((TIMESTAMP_STRUCT*)
01264                                         tmpStorage.takeFirst().constData());
01265                 values[i] = QVariant(QDateTime(QDate(dt.year, dt.month, dt.day),
01266                                QTime(dt.hour, dt.minute, dt.second, dt.fraction / 1000000)));
01267                 break; }
01268             case QVariant::Int:
01269             case QVariant::Double:
01270             case QVariant::ByteArray:
01271                 //nothing to do
01272                 break;
01273             case QVariant::String:
01274                 if (d->unicode) {
01275                     if (bindValueType(i) & QSql::Out)
01276                         values[i] = QString::fromUtf16((ushort*)tmpStorage.takeFirst().constData());
01277                     break;
01278                 }
01279                 // fall through
01280             default: {
01281                 QByteArray ba = tmpStorage.takeFirst();
01282                 if (bindValueType(i) & QSql::Out)
01283                     values[i] = QString::fromAscii(tmpStorage.takeFirst().constData());
01284                 break; }
01285         }
01286         if (indicators[i] == SQL_NULL_DATA)
01287             values[i] = QVariant(values[i].type());
01288     }
01289     return true;
01290 }

Here is the call graph for this function:

QVariant QODBCResult::handle (  )  const [virtual]

Returns the low-level database handle for this result set wrapped in a QVariant or an invalid QVariant if there is no handle.

Warning:
Use this with uttermost care and only if you know what you're doing.

The handle returned here can become a stale pointer if the result is modified (for example, if you clear it).

The handle can be NULL if the result was not executed yet.

The handle returned here is database-dependent, you should query the type name of the variant before accessing it.

This example retrieves the handle for a sqlite result:

    QSqlQuery query = ...
    QVariant v = query.result()->handle();
    if (v.isValid() && v.typeName() == "sqlite3_stmt*") {
        // v.data() returns a pointer to the handle
        sqlite3_stmt *handle = *static_cast<sqlite3_stmt **>(v.data());
        if (handle != 0) { // check that it is not NULL
            ...
        }
    }

This snippet returns the handle for PostgreSQL or MySQL:

    if (v.typeName() == "PGresult*") {
        PGresult *handle = *static_cast<PGresult **>(v.data());
        if (handle != 0) ...
    }

    if (v.typeName() == "MYSQL_STMT*") {
        MYSQL_STMT *handle = *static_cast<MYSQL_STMT **>(v.data());
        if (handle != 0) ...
    }

See also:
QSqlDriver::handle()

Reimplemented from QSqlResult.

Definition at line 1299 of file qsql_odbc.cpp.

References d, and QODBCPrivate::hStmt.

01300 {
01301     return QVariant(qRegisterMetaType<SQLHANDLE>("SQLHANDLE"), &d->hStmt);
01302 }

bool QODBCResult::fetchNext (  )  [protected, virtual]

Positions the result to the next available record (row) in the result.

This function is only called if the result is in an active state. The default implementation calls fetch() with the next index. Derived classes can reimplement this function and position the result to the next record in some other way, and call setAt() with an appropriate value. Return true to indicate success, or false to signify failure.

See also:
fetch(), fetchPrevious()

Reimplemented from QSqlResult.

Definition at line 771 of file qsql_odbc.cpp.

References QSqlResult::at(), QODBCPrivate::clearValues(), QSqlError::ConnectionError, d, QODBCPrivate::hStmt, qMakeError(), QSqlResult::setAt(), QSqlResult::setLastError(), and QCoreApplication::translate().

Referenced by fetch(), fetchFirst(), and fetchLast().

00772 {
00773     SQLRETURN r;
00774     d->clearValues();
00775     r = SQLFetchScroll(d->hStmt,
00776                        SQL_FETCH_NEXT,
00777                        0);
00778     if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
00779         if (r != SQL_NO_DATA)
00780             setLastError(qMakeError(QCoreApplication::translate("QODBCResult",
00781                 "Unable to fetch next"), QSqlError::ConnectionError, d));
00782         return false;
00783     }
00784     setAt(at() + 1);
00785     return true;
00786 }

Here is the call graph for this function:

bool QODBCResult::fetchFirst (  )  [protected, virtual]

Positions the result to the first record (row 0) in the result.

This function is only called if the result is in an active state. Derived classes must reimplement this function and position the result to the first record, and call setAt() with an appropriate value. Return true to indicate success, or false to signify failure.

See also:
fetch(), fetchLast()

Implements QSqlResult.

Definition at line 788 of file qsql_odbc.cpp.

References QSqlResult::at(), QSql::BeforeFirstRow, QODBCPrivate::clearValues(), d, fetchNext(), QODBCPrivate::hStmt, QSqlResult::isForwardOnly(), and QSqlResult::setAt().

00789 {
00790     if (isForwardOnly() && at() != QSql::BeforeFirstRow)
00791         return false;
00792     SQLRETURN r;
00793     d->clearValues();
00794     if (isForwardOnly()) {
00795         return fetchNext();
00796     }
00797     r = SQLFetchScroll(d->hStmt,
00798                        SQL_FETCH_FIRST,
00799                        0);
00800     if (r != SQL_SUCCESS)
00801         return false;
00802     setAt(0);
00803     return true;
00804 }

Here is the call graph for this function:

bool QODBCResult::fetchLast (  )  [protected, virtual]

Positions the result to the last record (last row) in the result.

This function is only called if the result is in an active state. Derived classes must reimplement this function and position the result to the last record, and call setAt() with an appropriate value. Return true to indicate success, or false to signify failure.

See also:
fetch(), fetchFirst()

Implements QSqlResult.

Definition at line 821 of file qsql_odbc.cpp.

References QSql::AfterLastRow, QSqlResult::at(), QSql::BeforeFirstRow, QODBCPrivate::clearValues(), d, fetchNext(), QODBCPrivate::hStmt, i, QSqlResult::isForwardOnly(), and QSqlResult::setAt().

00822 {
00823     SQLRETURN r;
00824     d->clearValues();
00825 
00826     if (isForwardOnly()) {
00827         // cannot seek to last row in forwardOnly mode, so we have to use brute force
00828         int i = at();
00829         if (i == QSql::AfterLastRow)
00830             return false;
00831         if (i == QSql::BeforeFirstRow)
00832             i = 0;
00833         while (fetchNext())
00834             ++i;
00835         setAt(i);
00836         return true;
00837     }
00838 
00839     r = SQLFetchScroll(d->hStmt,
00840                        SQL_FETCH_LAST,
00841                        0);
00842     if (r != SQL_SUCCESS) {
00843         return false;
00844     }
00845     SQLINTEGER currRow;
00846     r = SQLGetStmtAttr(d->hStmt,
00847                         SQL_ROW_NUMBER,
00848                         &currRow,
00849                         SQL_IS_INTEGER,
00850                         0);
00851     if (r != SQL_SUCCESS)
00852         return false;
00853     setAt(currRow-1);
00854     return true;
00855 }

Here is the call graph for this function:

bool QODBCResult::fetchPrior (  )  [protected]

Definition at line 806 of file qsql_odbc.cpp.

References QSqlResult::at(), QODBCPrivate::clearValues(), d, QODBCPrivate::hStmt, QSqlResult::isForwardOnly(), and QSqlResult::setAt().

00807 {
00808     if (isForwardOnly())
00809         return false;
00810     SQLRETURN r;
00811     d->clearValues();
00812     r = SQLFetchScroll(d->hStmt,
00813                        SQL_FETCH_PRIOR,
00814                        0);
00815     if (r != SQL_SUCCESS)
00816         return false;
00817     setAt(at() - 1);
00818     return true;
00819 }

Here is the call graph for this function:

bool QODBCResult::fetch ( int  i  )  [protected, virtual]

Positions the result to an arbitrary (zero-based) row index.

This function is only called if the result is in an active state. Derived classes must reimplement this function and position the result to the row index, and call setAt() with an appropriate value. Return true to indicate success, or false to signify failure.

See also:
isActive(), fetchFirst(), fetchLast(), fetchNext(), fetchPrevious()

Implements QSqlResult.

Definition at line 741 of file qsql_odbc.cpp.

References QSqlResult::at(), QSql::BeforeFirstRow, QODBCPrivate::clearValues(), d, fetchNext(), QODBCPrivate::hStmt, QSqlResult::isForwardOnly(), and QSqlResult::setAt().

00742 {
00743     if (isForwardOnly() && i < at())
00744         return false;
00745     if (i == at())
00746         return true;
00747     d->clearValues();
00748     int actualIdx = i + 1;
00749     if (actualIdx <= 0) {
00750         setAt(QSql::BeforeFirstRow);
00751         return false;
00752     }
00753     SQLRETURN r;
00754     if (isForwardOnly()) {
00755         bool ok = true;
00756         while (ok && i > at())
00757             ok = fetchNext();
00758         return ok;
00759     } else {
00760         r = SQLFetchScroll(d->hStmt,
00761                             SQL_FETCH_ABSOLUTE,
00762                             actualIdx);
00763     }
00764     if (r != SQL_SUCCESS){
00765         return false;
00766     }
00767     setAt(i);
00768     return true;
00769 }

Here is the call graph for this function:

bool QODBCResult::reset ( const QString query  )  [protected, virtual]

Sets the result to use the SQL statement query for subsequent data retrieval.

Derived classes must reimplement this function and apply the query to the database. This function is only called after the result is set to an inactive state and is positioned before the first record of the new result. Derived classes should return true if the query was successful and ready to be used, or false otherwise.

See also:
setQuery()

Implements QSqlResult.

Definition at line 667 of file qsql_odbc.cpp.

References QSqlRecord::append(), QSql::BeforeFirstRow, QSqlRecord::clear(), QVector< T >::clear(), d, QODBCPrivate::fieldCache, QODBCPrivate::fieldCacheIdx, QODBCPrivate::hDbc, QODBCPrivate::hStmt, i, QSqlResult::isForwardOnly(), QString::length(), qMakeError(), qMakeFieldInfo(), qSqlWarning(), QVector< T >::resize(), QODBCPrivate::rInf, QSqlResult::setActive(), QSqlResult::setAt(), QSqlResult::setLastError(), QSqlResult::setSelect(), QSqlError::StatementError, QString::toLocal8Bit(), QCoreApplication::translate(), and QString::unicode().

00668 {
00669     setActive(false);
00670     setAt(QSql::BeforeFirstRow);
00671     SQLRETURN r;
00672 
00673     d->rInf.clear();
00674     d->fieldCache.clear();
00675     d->fieldCacheIdx = 0;
00676     // Always reallocate the statement handle - the statement attributes
00677     // are not reset if SQLFreeStmt() is called which causes some problems.
00678     if (d->hStmt) {
00679         r = SQLFreeHandle(SQL_HANDLE_STMT, d->hStmt);
00680         if (r != SQL_SUCCESS) {
00681             qSqlWarning(QLatin1String("QODBCResult::reset: Unable to free statement handle"), d);
00682             return false;
00683         }
00684     }
00685     r  = SQLAllocHandle(SQL_HANDLE_STMT,
00686                          d->hDbc,
00687                          &d->hStmt);
00688     if (r != SQL_SUCCESS) {
00689         qSqlWarning(QLatin1String("QODBCResult::reset: Unable to allocate statement handle"), d);
00690         return false;
00691     }
00692 
00693     if (isForwardOnly()) {
00694         r = SQLSetStmtAttr(d->hStmt,
00695                             SQL_ATTR_CURSOR_TYPE,
00696                             (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
00697                             SQL_IS_UINTEGER);
00698     } else {
00699         r = SQLSetStmtAttr(d->hStmt,
00700                             SQL_ATTR_CURSOR_TYPE,
00701                             (SQLPOINTER)SQL_CURSOR_STATIC,
00702                             SQL_IS_UINTEGER);
00703     }
00704     if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
00705         setLastError(qMakeError(QCoreApplication::translate("QODBCResult",
00706             "QODBCResult::reset: Unable to set 'SQL_CURSOR_STATIC' as statement attribute. "
00707             "Please check your ODBC driver configuration"), QSqlError::StatementError, d));
00708         return false;
00709     }
00710 
00711 #ifdef UNICODE
00712     r = SQLExecDirect(d->hStmt,
00713                        (SQLWCHAR*) query.unicode(),
00714                        (SQLINTEGER) query.length());
00715 #else
00716     QByteArray query8 = query.toLocal8Bit();
00717     r = SQLExecDirect(d->hStmt,
00718                        (SQLCHAR*) query8.constData(),
00719                        (SQLINTEGER) query8.length());
00720 #endif
00721     if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
00722         setLastError(qMakeError(QCoreApplication::translate("QODBCResult",
00723                      "Unable to execute statement"), QSqlError::StatementError, d));
00724         return false;
00725     }
00726     SQLSMALLINT count;
00727     r = SQLNumResultCols(d->hStmt, &count);
00728     if (count) {
00729         setSelect(true);
00730         for (int i = 0; i < count; ++i) {
00731             d->rInf.append(qMakeFieldInfo(d, i));
00732         }
00733         d->fieldCache.resize(count);
00734     } else {
00735         setSelect(false);
00736     }
00737     setActive(true);
00738     return true;
00739 }

Here is the call graph for this function:

QVariant QODBCResult::data ( int  field  )  [protected, virtual]

Returns the data for field index in the current row as a QVariant. This function is only called if the result is in an active state and is positioned on a valid record and index is non-negative. Derived classes must reimplement this function and return the value of field index, or QVariant() if it cannot be determined.

Implements QSqlResult.

Definition at line 857 of file qsql_odbc.cpp.

References QVector< T >::at(), QVariant::ByteArray, QSqlRecord::count(), d, QVariant::Date, QVariant::DateTime, QVariant::Double, QSqlRecord::field(), QODBCPrivate::fieldCache, QODBCPrivate::fieldCacheIdx, QODBCPrivate::hStmt, i, info, QVariant::Int, QVariant::LongLong, qGetBigIntData(), qGetBinaryData(), qGetDoubleData(), qGetIntData(), qGetStringData(), QSQLLEN, qWarning(), QODBCPrivate::rInf, QVariant::String, and QVariant::Time.

Referenced by isNull().

00858 {
00859     if (field >= d->rInf.count() || field < 0) {
00860         qWarning("QODBCResult::data: column %d out of range", field);
00861         return QVariant();
00862     }
00863     if (field < d->fieldCacheIdx)
00864         return d->fieldCache.at(field);
00865 
00866     SQLRETURN r(0);
00867     QSQLLEN lengthIndicator = 0;
00868 
00869     for (int i = d->fieldCacheIdx; i <= field; ++i) {
00870         // some servers do not support fetching column n after we already
00871         // fetched column n+1, so cache all previous columns here
00872         const QSqlField info = d->rInf.field(i);
00873         switch (info.type()) {
00874         case QVariant::LongLong:
00875             d->fieldCache[i] = qGetBigIntData(d->hStmt, i);
00876         break;
00877         case QVariant::Int:
00878             d->fieldCache[i] = qGetIntData(d->hStmt, i);
00879         break;
00880         case QVariant::Date:
00881             DATE_STRUCT dbuf;
00882             r = SQLGetData(d->hStmt,
00883                             i + 1,
00884                             SQL_C_DATE,
00885                             (SQLPOINTER)&dbuf,
00886                             0,
00887                             &lengthIndicator);
00888             if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (lengthIndicator != SQL_NULL_DATA))
00889                 d->fieldCache[i] = QVariant(QDate(dbuf.year, dbuf.month, dbuf.day));
00890             else
00891                 d->fieldCache[i] = QVariant(QVariant::Date);
00892         break;
00893         case QVariant::Time:
00894             TIME_STRUCT tbuf;
00895             r = SQLGetData(d->hStmt,
00896                             i + 1,
00897                             SQL_C_TIME,
00898                             (SQLPOINTER)&tbuf,
00899                             0,
00900                             &lengthIndicator);
00901             if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (lengthIndicator != SQL_NULL_DATA))
00902                 d->fieldCache[i] = QVariant(QTime(tbuf.hour, tbuf.minute, tbuf.second));
00903             else
00904                 d->fieldCache[i] = QVariant(QVariant::Time);
00905         break;
00906         case QVariant::DateTime:
00907             TIMESTAMP_STRUCT dtbuf;
00908             r = SQLGetData(d->hStmt,
00909                             i + 1,
00910                             SQL_C_TIMESTAMP,
00911                             (SQLPOINTER)&dtbuf,
00912                             0,
00913                             &lengthIndicator);
00914             if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (lengthIndicator != SQL_NULL_DATA))
00915                 d->fieldCache[i] = QVariant(QDateTime(QDate(dtbuf.year, dtbuf.month, dtbuf.day),
00916                        QTime(dtbuf.hour, dtbuf.minute, dtbuf.second, dtbuf.fraction / 1000000)));
00917             else
00918                 d->fieldCache[i] = QVariant(QVariant::DateTime);
00919             break;
00920         case QVariant::ByteArray:
00921             d->fieldCache[i] = qGetBinaryData(d->hStmt, i);
00922             break;
00923         case QVariant::String:
00924             d->fieldCache[i] = qGetStringData(d->hStmt, i, info.length(), true);
00925             break;
00926         case QVariant::Double:
00927             if (info.typeID() == SQL_DECIMAL || info.typeID() == SQL_NUMERIC)
00928                 // bind Double values as string to prevent loss of precision
00929                 d->fieldCache[i] = qGetStringData(d->hStmt, i,
00930                                        info.length() + 1, false); // length + 1 for the comma
00931             else
00932                 d->fieldCache[i] = qGetDoubleData(d->hStmt, i);
00933             break;
00934         default:
00935             d->fieldCache[i] = QVariant(qGetStringData(d->hStmt, i,
00936                                                            info.length(), false));
00937             break;
00938         }
00939         d->fieldCacheIdx = field + 1;
00940     }
00941     return d->fieldCache[field];
00942 }

Here is the call graph for this function:

bool QODBCResult::isNull ( int  field  )  [protected, virtual]

Returns true if the field at position index in the current row is null; otherwise returns false.

Implements QSqlResult.

Definition at line 944 of file qsql_odbc.cpp.

References QVector< T >::at(), d, data(), QODBCPrivate::fieldCache, QVariant::isNull(), and QVector< T >::size().

00945 {
00946     if (field < 0 || field > d->fieldCache.size())
00947         return true;
00948     if (field <= d->fieldCacheIdx) {
00949         // since there is no good way to find out whether the value is NULL
00950         // without fetching the field we'll fetch it here.
00951         // (data() also sets the NULL flag)
00952         data(field);
00953     }
00954     return d->fieldCache.at(field).isNull();
00955 }

Here is the call graph for this function:

int QODBCResult::size (  )  [protected, virtual]

Returns the size of the SELECT result, or -1 if it cannot be determined or if the query is not a SELECT statement.

See also:
numRowsAffected()

Implements QSqlResult.

Definition at line 957 of file qsql_odbc.cpp.

00958 {
00959     return -1;
00960 }

int QODBCResult::numRowsAffected (  )  [protected, virtual]

Returns the number of rows affected by the last query executed, or -1 if it cannot be determined or if the query is a SELECT statement.

See also:
size()

Implements QSqlResult.

Definition at line 962 of file qsql_odbc.cpp.

References d, QODBCPrivate::hStmt, QSQLLEN, and qSqlWarning().

00963 {
00964     QSQLLEN affectedRowCount = 0;
00965     SQLRETURN r = SQLRowCount(d->hStmt, &affectedRowCount);
00966     if (r == SQL_SUCCESS)
00967         return affectedRowCount;
00968     else
00969         qSqlWarning(QLatin1String("QODBCResult::numRowsAffected: Unable to count affected rows"), d);
00970     return -1;
00971 }

Here is the call graph for this function:

QSqlRecord QODBCResult::record (  )  const [protected, virtual]

Returns the current record if the query is active; otherwise returns an empty QSqlRecord.

The default implementation always returns an empty QSqlRecord.

See also:
isActive()

Reimplemented from QSqlResult.

Definition at line 1292 of file qsql_odbc.cpp.

References d, QSqlResult::isActive(), QSqlResult::isSelect(), and QODBCPrivate::rInf.

01293 {
01294     if (!isActive() || !isSelect())
01295         return QSqlRecord();
01296     return d->rInf;
01297 }

Here is the call graph for this function:


Member Data Documentation

QODBCPrivate* QODBCResult::d [private]

Reimplemented from QSqlResult.

Definition at line 98 of file qsql_odbc.h.

Referenced by data(), exec(), fetch(), fetchFirst(), fetchLast(), fetchNext(), fetchPrior(), handle(), isNull(), numRowsAffected(), prepare(), QODBCResult(), record(), reset(), and ~QODBCResult().


The documentation for this class was generated from the following files:
Generated on Thu Mar 15 18:32:50 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1