util/src/sql/kernel/qsqlresult.cpp
changeset 7 f7bc934e204c
equal deleted inserted replaced
3:41300fa6a67c 7:f7bc934e204c
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtSql module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qvariant.h"
       
    43 #include "qhash.h"
       
    44 #include "qregexp.h"
       
    45 #include "qsqlerror.h"
       
    46 #include "qsqlfield.h"
       
    47 #include "qsqlrecord.h"
       
    48 #include "qsqlresult.h"
       
    49 #include "qvector.h"
       
    50 #include "qsqldriver.h"
       
    51 #include <QDebug>
       
    52 
       
    53 QT_BEGIN_NAMESPACE
       
    54 
       
    55 struct QHolder {
       
    56     QHolder(const QString& hldr = QString(), int index = -1): holderName(hldr), holderPos(index) {}
       
    57     bool operator==(const QHolder& h) const { return h.holderPos == holderPos && h.holderName == holderName; }
       
    58     bool operator!=(const QHolder& h) const { return h.holderPos != holderPos || h.holderName != holderName; }
       
    59     QString holderName;
       
    60     int holderPos;
       
    61 };
       
    62 
       
    63 class QSqlResultPrivate
       
    64 {
       
    65 public:
       
    66     QSqlResultPrivate(QSqlResult* d)
       
    67     : q(d), sqldriver(0), idx(QSql::BeforeFirstRow), active(false),
       
    68       isSel(false), forwardOnly(false), precisionPolicy(QSql::LowPrecisionDouble), bindCount(0), binds(QSqlResult::PositionalBinding)
       
    69     {}
       
    70 
       
    71     void clearValues()
       
    72     {
       
    73         values.clear();
       
    74         bindCount = 0;
       
    75     }
       
    76 
       
    77     void resetBindCount()
       
    78     {
       
    79         bindCount = 0;
       
    80     }
       
    81 
       
    82     void clearIndex()
       
    83     {
       
    84         indexes.clear();
       
    85         holders.clear();
       
    86         types.clear();
       
    87     }
       
    88 
       
    89     void clear()
       
    90     {
       
    91         clearValues();
       
    92         clearIndex();;
       
    93     }
       
    94 
       
    95     QString positionalToNamedBinding();
       
    96     QString namedToPositionalBinding();
       
    97     QString holderAt(int index) const;
       
    98 
       
    99 public:
       
   100     QSqlResult* q;
       
   101     const QSqlDriver* sqldriver;
       
   102     int idx;
       
   103     QString sql;
       
   104     bool active;
       
   105     bool isSel;
       
   106     QSqlError error;
       
   107     bool forwardOnly;
       
   108     QSql::NumericalPrecisionPolicy precisionPolicy;
       
   109 
       
   110     int bindCount;
       
   111     QSqlResult::BindingSyntax binds;
       
   112 
       
   113     QString executedQuery;
       
   114     QHash<int, QSql::ParamType> types;
       
   115     QVector<QVariant> values;
       
   116     typedef QHash<QString, int> IndexMap;
       
   117     IndexMap indexes;
       
   118 
       
   119     typedef QVector<QHolder> QHolderVector;
       
   120     QHolderVector holders;
       
   121 };
       
   122 
       
   123 QString QSqlResultPrivate::holderAt(int index) const
       
   124 {
       
   125     return indexes.key(index);
       
   126 }
       
   127 
       
   128 // return a unique id for bound names
       
   129 static QString qFieldSerial(int i)
       
   130 {
       
   131     ushort arr[] = { ':', 'f', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
       
   132     ushort *ptr = &arr[1];
       
   133 
       
   134     while (i > 0) {
       
   135         *(++ptr) = 'a' + i % 16;
       
   136         i >>= 4;
       
   137     }
       
   138 
       
   139     return QString(reinterpret_cast<const QChar *>(arr), int(ptr - arr) + 1);
       
   140 }
       
   141 
       
   142 static bool qIsAlnum(QChar ch)
       
   143 {
       
   144     uint u = uint(ch.unicode());
       
   145     // matches [a-zA-Z0-9_]
       
   146     return u - 'a' < 26 || u - 'A' < 26 || u - '0' < 10 || u == '_';
       
   147 }
       
   148 
       
   149 QString QSqlResultPrivate::positionalToNamedBinding()
       
   150 {
       
   151     int n = sql.size();
       
   152 
       
   153     QString result;
       
   154     result.reserve(n * 5 / 4);
       
   155     bool inQuote = false;
       
   156     int count = 0;
       
   157 
       
   158     for (int i = 0; i < n; ++i) {
       
   159         QChar ch = sql.at(i);
       
   160         if (ch == QLatin1Char('?') && !inQuote) {
       
   161             result += qFieldSerial(count++);
       
   162         } else {
       
   163             if (ch == QLatin1Char('\''))
       
   164                 inQuote = !inQuote;
       
   165             result += ch;
       
   166         }
       
   167     }
       
   168     result.squeeze();
       
   169     return result;
       
   170 }
       
   171 
       
   172 QString QSqlResultPrivate::namedToPositionalBinding()
       
   173 {
       
   174     int n = sql.size();
       
   175 
       
   176     QString result;
       
   177     result.reserve(n);
       
   178     bool inQuote = false;
       
   179     int count = 0;
       
   180     int i = 0;
       
   181 
       
   182     while (i < n) {
       
   183         QChar ch = sql.at(i);
       
   184         if (ch == QLatin1Char(':') && !inQuote
       
   185                 && (i == 0 || sql.at(i - 1) != QLatin1Char(':'))
       
   186                 && (i < n - 1 && qIsAlnum(sql.at(i + 1)))) {
       
   187             int pos = i + 2;
       
   188             while (pos < n && qIsAlnum(sql.at(pos)))
       
   189                 ++pos;
       
   190             indexes[sql.mid(i, pos - i)] = count++;
       
   191             result += QLatin1Char('?');
       
   192             i = pos;
       
   193         } else {
       
   194             if (ch == QLatin1Char('\''))
       
   195                 inQuote = !inQuote;
       
   196             result += ch;
       
   197             ++i;
       
   198         }
       
   199     }
       
   200     result.squeeze();
       
   201     return result;
       
   202 }
       
   203 
       
   204 /*!
       
   205     \class QSqlResult
       
   206     \brief The QSqlResult class provides an abstract interface for
       
   207     accessing data from specific SQL databases.
       
   208 
       
   209     \ingroup database
       
   210     \inmodule QtSql
       
   211 
       
   212     Normally, you would use QSqlQuery instead of QSqlResult, since
       
   213     QSqlQuery provides a generic wrapper for database-specific
       
   214     implementations of QSqlResult.
       
   215 
       
   216     If you are implementing your own SQL driver (by subclassing
       
   217     QSqlDriver), you will need to provide your own QSqlResult
       
   218     subclass that implements all the pure virtual functions and other
       
   219     virtual functions that you need.
       
   220 
       
   221     \sa QSqlDriver
       
   222 */
       
   223 
       
   224 /*!
       
   225     \enum QSqlResult::BindingSyntax
       
   226 
       
   227     This enum type specifies the different syntaxes for specifying
       
   228     placeholders in prepared queries.
       
   229 
       
   230     \value PositionalBinding Use the ODBC-style positional syntax, with "?" as placeholders.
       
   231     \value NamedBinding Use the Oracle-style syntax with named placeholders (e.g., ":id")
       
   232     \omitvalue BindByPosition
       
   233     \omitvalue BindByName
       
   234 
       
   235     \sa bindingSyntax()
       
   236 */
       
   237 
       
   238 /*!
       
   239     \enum QSqlResult::VirtualHookOperation
       
   240     \internal
       
   241 */
       
   242 
       
   243 /*!
       
   244     Creates a QSqlResult using database driver \a db. The object is
       
   245     initialized to an inactive state.
       
   246 
       
   247     \sa isActive(), driver()
       
   248 */
       
   249 
       
   250 QSqlResult::QSqlResult(const QSqlDriver *db)
       
   251 {
       
   252     d = new QSqlResultPrivate(this);
       
   253     d->sqldriver = db;
       
   254     if(db) {
       
   255         setNumericalPrecisionPolicy(db->numericalPrecisionPolicy());
       
   256     }
       
   257 }
       
   258 
       
   259 /*!
       
   260     Destroys the object and frees any allocated resources.
       
   261 */
       
   262 
       
   263 QSqlResult::~QSqlResult()
       
   264 {
       
   265     delete d;
       
   266 }
       
   267 
       
   268 /*!
       
   269     Sets the current query for the result to \a query. You must call
       
   270     reset() to execute the query on the database.
       
   271 
       
   272     \sa reset(), lastQuery()
       
   273 */
       
   274 
       
   275 void QSqlResult::setQuery(const QString& query)
       
   276 {
       
   277     d->sql = query;
       
   278 }
       
   279 
       
   280 /*!
       
   281     Returns the current SQL query text, or an empty string if there
       
   282     isn't one.
       
   283 
       
   284     \sa setQuery()
       
   285 */
       
   286 
       
   287 QString QSqlResult::lastQuery() const
       
   288 {
       
   289     return d->sql;
       
   290 }
       
   291 
       
   292 /*!
       
   293     Returns the current (zero-based) row position of the result. May
       
   294     return the special values QSql::BeforeFirstRow or
       
   295     QSql::AfterLastRow.
       
   296 
       
   297     \sa setAt(), isValid()
       
   298 */
       
   299 int QSqlResult::at() const
       
   300 {
       
   301     return d->idx;
       
   302 }
       
   303 
       
   304 
       
   305 /*!
       
   306     Returns true if the result is positioned on a valid record (that
       
   307     is, the result is not positioned before the first or after the
       
   308     last record); otherwise returns false.
       
   309 
       
   310     \sa at()
       
   311 */
       
   312 
       
   313 bool QSqlResult::isValid() const
       
   314 {
       
   315     return d->idx != QSql::BeforeFirstRow && d->idx != QSql::AfterLastRow;
       
   316 }
       
   317 
       
   318 /*!
       
   319     \fn bool QSqlResult::isNull(int index)
       
   320 
       
   321     Returns true if the field at position \a index in the current row
       
   322     is null; otherwise returns false.
       
   323 */
       
   324 
       
   325 /*!
       
   326     Returns true if the result has records to be retrieved; otherwise
       
   327     returns false.
       
   328 */
       
   329 
       
   330 bool QSqlResult::isActive() const
       
   331 {
       
   332     return d->active;
       
   333 }
       
   334 
       
   335 /*!
       
   336     This function is provided for derived classes to set the
       
   337     internal (zero-based) row position to \a index.
       
   338 
       
   339     \sa at()
       
   340 */
       
   341 
       
   342 void QSqlResult::setAt(int index)
       
   343 {
       
   344     d->idx = index;
       
   345 }
       
   346 
       
   347 
       
   348 /*!
       
   349     This function is provided for derived classes to indicate whether
       
   350     or not the current statement is a SQL \c SELECT statement. The \a
       
   351     select parameter should be true if the statement is a \c SELECT
       
   352     statement; otherwise it should be false.
       
   353 
       
   354     \sa isSelect()
       
   355 */
       
   356 
       
   357 void QSqlResult::setSelect(bool select)
       
   358 {
       
   359     d->isSel = select;
       
   360 }
       
   361 
       
   362 /*!
       
   363     Returns true if the current result is from a \c SELECT statement;
       
   364     otherwise returns false.
       
   365 
       
   366     \sa setSelect()
       
   367 */
       
   368 
       
   369 bool QSqlResult::isSelect() const
       
   370 {
       
   371     return d->isSel;
       
   372 }
       
   373 
       
   374 /*!
       
   375     Returns the driver associated with the result. This is the object
       
   376     that was passed to the constructor.
       
   377 */
       
   378 
       
   379 const QSqlDriver *QSqlResult::driver() const
       
   380 {
       
   381     return d->sqldriver;
       
   382 }
       
   383 
       
   384 
       
   385 /*!
       
   386     This function is provided for derived classes to set the internal
       
   387     active state to \a active.
       
   388 
       
   389     \sa isActive()
       
   390 */
       
   391 
       
   392 void QSqlResult::setActive(bool active)
       
   393 {
       
   394     if (active && d->executedQuery.isEmpty())
       
   395         d->executedQuery = d->sql;
       
   396 
       
   397     d->active = active;
       
   398 }
       
   399 
       
   400 /*!
       
   401     This function is provided for derived classes to set the last
       
   402     error to \a error.
       
   403 
       
   404     \sa lastError()
       
   405 */
       
   406 
       
   407 void QSqlResult::setLastError(const QSqlError &error)
       
   408 {
       
   409     d->error = error;
       
   410 }
       
   411 
       
   412 
       
   413 /*!
       
   414     Returns the last error associated with the result.
       
   415 */
       
   416 
       
   417 QSqlError QSqlResult::lastError() const
       
   418 {
       
   419     return d->error;
       
   420 }
       
   421 
       
   422 /*!
       
   423     \fn int QSqlResult::size()
       
   424 
       
   425     Returns the size of the \c SELECT result, or -1 if it cannot be
       
   426     determined or if the query is not a \c SELECT statement.
       
   427 
       
   428     \sa numRowsAffected()
       
   429 */
       
   430 
       
   431 /*!
       
   432     \fn int QSqlResult::numRowsAffected()
       
   433 
       
   434     Returns the number of rows affected by the last query executed, or
       
   435     -1 if it cannot be determined or if the query is a \c SELECT
       
   436     statement.
       
   437 
       
   438     \sa size()
       
   439 */
       
   440 
       
   441 /*!
       
   442     \fn QVariant QSqlResult::data(int index)
       
   443 
       
   444     Returns the data for field \a index in the current row as
       
   445     a QVariant. This function is only called if the result is in
       
   446     an active state and is positioned on a valid record and \a index is
       
   447     non-negative. Derived classes must reimplement this function and
       
   448     return the value of field \a index, or QVariant() if it cannot be
       
   449     determined.
       
   450 */
       
   451 
       
   452 /*!
       
   453     \fn  bool QSqlResult::reset(const QString &query)
       
   454 
       
   455     Sets the result to use the SQL statement \a query for subsequent
       
   456     data retrieval.
       
   457 
       
   458     Derived classes must reimplement this function and apply the \a
       
   459     query to the database. This function is only called after the
       
   460     result is set to an inactive state and is positioned before the
       
   461     first record of the new result. Derived classes should return
       
   462     true if the query was successful and ready to be used, or false
       
   463     otherwise.
       
   464 
       
   465     \sa setQuery()
       
   466 */
       
   467 
       
   468 /*!
       
   469     \fn bool QSqlResult::fetch(int index)
       
   470 
       
   471     Positions the result to an arbitrary (zero-based) row \a index.
       
   472 
       
   473     This function is only called if the result is in an active state.
       
   474     Derived classes must reimplement this function and position the
       
   475     result to the row \a index, and call setAt() with an appropriate
       
   476     value. Return true to indicate success, or false to signify
       
   477     failure.
       
   478 
       
   479     \sa isActive(), fetchFirst(), fetchLast(), fetchNext(), fetchPrevious()
       
   480 */
       
   481 
       
   482 /*!
       
   483     \fn bool QSqlResult::fetchFirst()
       
   484 
       
   485     Positions the result to the first record (row 0) in the result.
       
   486 
       
   487     This function is only called if the result is in an active state.
       
   488     Derived classes must reimplement this function and position the
       
   489     result to the first record, and call setAt() with an appropriate
       
   490     value. Return true to indicate success, or false to signify
       
   491     failure.
       
   492 
       
   493     \sa fetch(), fetchLast()
       
   494 */
       
   495 
       
   496 /*!
       
   497     \fn bool QSqlResult::fetchLast()
       
   498 
       
   499     Positions the result to the last record (last row) in the result.
       
   500 
       
   501     This function is only called if the result is in an active state.
       
   502     Derived classes must reimplement this function and position the
       
   503     result to the last record, and call setAt() with an appropriate
       
   504     value. Return true to indicate success, or false to signify
       
   505     failure.
       
   506 
       
   507     \sa fetch(), fetchFirst()
       
   508 */
       
   509 
       
   510 /*!
       
   511     Positions the result to the next available record (row) in the
       
   512     result.
       
   513 
       
   514     This function is only called if the result is in an active
       
   515     state. The default implementation calls fetch() with the next
       
   516     index. Derived classes can reimplement this function and position
       
   517     the result to the next record in some other way, and call setAt()
       
   518     with an appropriate value. Return true to indicate success, or
       
   519     false to signify failure.
       
   520 
       
   521     \sa fetch(), fetchPrevious()
       
   522 */
       
   523 
       
   524 bool QSqlResult::fetchNext()
       
   525 {
       
   526     return fetch(at() + 1);
       
   527 }
       
   528 
       
   529 /*!
       
   530     Positions the result to the previous record (row) in the result.
       
   531 
       
   532     This function is only called if the result is in an active state.
       
   533     The default implementation calls fetch() with the previous index.
       
   534     Derived classes can reimplement this function and position the
       
   535     result to the next record in some other way, and call setAt()
       
   536     with an appropriate value. Return true to indicate success, or
       
   537     false to signify failure.
       
   538 */
       
   539 
       
   540 bool QSqlResult::fetchPrevious()
       
   541 {
       
   542     return fetch(at() - 1);
       
   543 }
       
   544 
       
   545 /*!
       
   546     Returns true if you can only scroll forward through the result
       
   547     set; otherwise returns false.
       
   548 
       
   549     \sa setForwardOnly()
       
   550 */
       
   551 bool QSqlResult::isForwardOnly() const
       
   552 {
       
   553     return d->forwardOnly;
       
   554 }
       
   555 
       
   556 /*!
       
   557     Sets forward only mode to \a forward. If \a forward is true, only
       
   558     fetchNext() is allowed for navigating the results. Forward only
       
   559     mode needs much less memory since results do not have to be
       
   560     cached. By default, this feature is disabled.
       
   561 
       
   562     Setting forward only to false is a suggestion to the database engine,
       
   563     which has the final say on whether a result set is forward only or
       
   564     scrollable. isForwardOnly() will always return the correct status of
       
   565     the result set.
       
   566 
       
   567     \note Calling setForwardOnly after execution of the query will result
       
   568     in unexpected results at best, and crashes at worst.
       
   569 
       
   570     \sa isForwardOnly(), fetchNext(), QSqlQuery::setForwardOnly()
       
   571 */
       
   572 void QSqlResult::setForwardOnly(bool forward)
       
   573 {
       
   574     d->forwardOnly = forward;
       
   575 }
       
   576 
       
   577 /*!
       
   578     Prepares the given \a query, using the underlying database
       
   579     functionality where possible. Returns true if the query is
       
   580     prepared successfully; otherwise returns false.
       
   581 
       
   582     \sa prepare()
       
   583 */
       
   584 bool QSqlResult::savePrepare(const QString& query)
       
   585 {
       
   586     if (!driver())
       
   587         return false;
       
   588     d->clear();
       
   589     d->sql = query;
       
   590     if (!driver()->hasFeature(QSqlDriver::PreparedQueries))
       
   591         return prepare(query);
       
   592 
       
   593     if (driver()->hasFeature(QSqlDriver::NamedPlaceholders)) {
       
   594         // parse the query to memorize parameter location
       
   595         d->namedToPositionalBinding();
       
   596         d->executedQuery = d->positionalToNamedBinding();
       
   597     } else {
       
   598         d->executedQuery = d->namedToPositionalBinding();
       
   599     }
       
   600     return prepare(d->executedQuery);
       
   601 }
       
   602 
       
   603 /*!
       
   604     Prepares the given \a query for execution; the query will normally
       
   605     use placeholders so that it can be executed repeatedly. Returns
       
   606     true if the query is prepared successfully; otherwise returns false.
       
   607 
       
   608     \sa exec()
       
   609 */
       
   610 bool QSqlResult::prepare(const QString& query)
       
   611 {
       
   612     int n = query.size();
       
   613 
       
   614     bool inQuote = false;
       
   615     int i = 0;
       
   616 
       
   617     while (i < n) {
       
   618         QChar ch = query.at(i);
       
   619         if (ch == QLatin1Char(':') && !inQuote
       
   620                 && (i == 0 || query.at(i - 1) != QLatin1Char(':'))
       
   621                 && (i < n - 1 && qIsAlnum(query.at(i + 1)))) {
       
   622             int pos = i + 2;
       
   623             while (pos < n && qIsAlnum(query.at(pos)))
       
   624                 ++pos;
       
   625 
       
   626             d->holders.append(QHolder(query.mid(i, pos - i), i));
       
   627             i = pos;
       
   628         } else {
       
   629             if (ch == QLatin1Char('\''))
       
   630                 inQuote = !inQuote;
       
   631             ++i;
       
   632         }
       
   633     }
       
   634     d->sql = query;
       
   635     return true; // fake prepares should always succeed
       
   636 }
       
   637 
       
   638 /*!
       
   639     Executes the query, returning true if successful; otherwise returns
       
   640     false.
       
   641 
       
   642     \sa prepare()
       
   643 */
       
   644 bool QSqlResult::exec()
       
   645 {
       
   646     bool ret;
       
   647     // fake preparation - just replace the placeholders..
       
   648     QString query = lastQuery();
       
   649     if (d->binds == NamedBinding) {
       
   650         int i;
       
   651         QVariant val;
       
   652         QString holder;
       
   653         for (i = d->holders.count() - 1; i >= 0; --i) {
       
   654             holder = d->holders.at(i).holderName;
       
   655             val = d->values.value(d->indexes.value(holder));
       
   656             QSqlField f(QLatin1String(""), val.type());
       
   657             f.setValue(val);
       
   658             query = query.replace(d->holders.at(i).holderPos,
       
   659                                    holder.length(), driver()->formatValue(f));
       
   660         }
       
   661     } else {
       
   662         QString val;
       
   663         int i = 0;
       
   664         int idx = 0;
       
   665         for (idx = 0; idx < d->values.count(); ++idx) {
       
   666             i = query.indexOf(QLatin1Char('?'), i);
       
   667             if (i == -1)
       
   668                 continue;
       
   669             QVariant var = d->values.value(idx);
       
   670             QSqlField f(QLatin1String(""), var.type());
       
   671             if (var.isNull())
       
   672                 f.clear();
       
   673             else
       
   674                 f.setValue(var);
       
   675             val = driver()->formatValue(f);
       
   676             query = query.replace(i, 1, driver()->formatValue(f));
       
   677             i += val.length();
       
   678         }
       
   679     }
       
   680 
       
   681     // have to retain the original query with placeholders
       
   682     QString orig = lastQuery();
       
   683     ret = reset(query);
       
   684     d->executedQuery = query;
       
   685     setQuery(orig);
       
   686     d->resetBindCount();
       
   687     return ret;
       
   688 }
       
   689 
       
   690 /*!
       
   691     Binds the value \a val of parameter type \a paramType to position \a index
       
   692     in the current record (row).
       
   693 
       
   694     \sa addBindValue()
       
   695 */
       
   696 void QSqlResult::bindValue(int index, const QVariant& val, QSql::ParamType paramType)
       
   697 {
       
   698     d->binds = PositionalBinding;
       
   699     d->indexes[qFieldSerial(index)] = index;
       
   700     if (d->values.count() <= index)
       
   701         d->values.resize(index + 1);
       
   702     d->values[index] = val;
       
   703     if (paramType != QSql::In || !d->types.isEmpty())
       
   704         d->types[index] = paramType;
       
   705 }
       
   706 
       
   707 /*!
       
   708     \overload
       
   709 
       
   710     Binds the value \a val of parameter type \a paramType to the \a
       
   711     placeholder name in the current record (row).
       
   712 
       
   713    Values cannot be bound to multiple locations in the query, eg:
       
   714    \code
       
   715    INSERT INTO testtable (id, name, samename) VALUES (:id, :name, :name)
       
   716    \endcode
       
   717    Binding to name will bind to the first :name, but not the second.
       
   718 
       
   719     \note Binding an undefined placeholder will result in undefined behavior.
       
   720 
       
   721     \sa QSqlQuery::bindValue()
       
   722 */
       
   723 void QSqlResult::bindValue(const QString& placeholder, const QVariant& val,
       
   724                            QSql::ParamType paramType)
       
   725 {
       
   726     d->binds = NamedBinding;
       
   727     // if the index has already been set when doing emulated named
       
   728     // bindings - don't reset it
       
   729     int idx = d->indexes.value(placeholder, -1);
       
   730     if (idx >= 0) {
       
   731         if (d->values.count() <= idx)
       
   732             d->values.resize(idx + 1);
       
   733         d->values[idx] = val;
       
   734     } else {
       
   735         d->values.append(val);
       
   736         idx = d->values.count() - 1;
       
   737         d->indexes[placeholder] = idx;
       
   738     }
       
   739 
       
   740     if (paramType != QSql::In || !d->types.isEmpty())
       
   741         d->types[idx] = paramType;
       
   742 }
       
   743 
       
   744 /*!
       
   745     Binds the value \a val of parameter type \a paramType to the next
       
   746     available position in the current record (row).
       
   747 
       
   748     \sa bindValue()
       
   749 */
       
   750 void QSqlResult::addBindValue(const QVariant& val, QSql::ParamType paramType)
       
   751 {
       
   752     d->binds = PositionalBinding;
       
   753     bindValue(d->bindCount, val, paramType);
       
   754     ++d->bindCount;
       
   755 }
       
   756 
       
   757 /*!
       
   758     Returns the value bound at position \a index in the current record
       
   759     (row).
       
   760 
       
   761     \sa bindValue(), boundValues()
       
   762 */
       
   763 QVariant QSqlResult::boundValue(int index) const
       
   764 {
       
   765     return d->values.value(index);
       
   766 }
       
   767 
       
   768 /*!
       
   769     \overload
       
   770 
       
   771     Returns the value bound by the given \a placeholder name in the
       
   772     current record (row).
       
   773 
       
   774     \sa bindValueType()
       
   775 */
       
   776 QVariant QSqlResult::boundValue(const QString& placeholder) const
       
   777 {
       
   778     int idx = d->indexes.value(placeholder, -1);
       
   779     return d->values.value(idx);
       
   780 }
       
   781 
       
   782 /*!
       
   783     Returns the parameter type for the value bound at position \a index.
       
   784 
       
   785     \sa boundValue()
       
   786 */
       
   787 QSql::ParamType QSqlResult::bindValueType(int index) const
       
   788 {
       
   789     return d->types.value(index, QSql::In);
       
   790 }
       
   791 
       
   792 /*!
       
   793     \overload
       
   794 
       
   795     Returns the parameter type for the value bound with the given \a
       
   796     placeholder name.
       
   797 */
       
   798 QSql::ParamType QSqlResult::bindValueType(const QString& placeholder) const
       
   799 {
       
   800     return d->types.value(d->indexes.value(placeholder, -1), QSql::In);
       
   801 }
       
   802 
       
   803 /*!
       
   804     Returns the number of bound values in the result.
       
   805 
       
   806     \sa boundValues()
       
   807 */
       
   808 int QSqlResult::boundValueCount() const
       
   809 {
       
   810     return d->values.count();
       
   811 }
       
   812 
       
   813 /*!
       
   814     Returns a vector of the result's bound values for the current
       
   815     record (row).
       
   816 
       
   817     \sa boundValueCount()
       
   818 */
       
   819 QVector<QVariant>& QSqlResult::boundValues() const
       
   820 {
       
   821     return d->values;
       
   822 }
       
   823 
       
   824 /*!
       
   825     Returns the binding syntax used by prepared queries.
       
   826 */
       
   827 QSqlResult::BindingSyntax QSqlResult::bindingSyntax() const
       
   828 {
       
   829     return d->binds;
       
   830 }
       
   831 
       
   832 /*!
       
   833     Clears the entire result set and releases any associated
       
   834     resources.
       
   835 */
       
   836 void QSqlResult::clear()
       
   837 {
       
   838     d->clear();
       
   839 }
       
   840 
       
   841 /*!
       
   842     Returns the query that was actually executed. This may differ from
       
   843     the query that was passed, for example if bound values were used
       
   844     with a prepared query and the underlying database doesn't support
       
   845     prepared queries.
       
   846 
       
   847     \sa exec(), setQuery()
       
   848 */
       
   849 QString QSqlResult::executedQuery() const
       
   850 {
       
   851     return d->executedQuery;
       
   852 }
       
   853 
       
   854 void QSqlResult::resetBindCount()
       
   855 {
       
   856     d->resetBindCount();
       
   857 }
       
   858 
       
   859 /*!
       
   860     Returns the name of the bound value at position \a index in the
       
   861     current record (row).
       
   862 
       
   863     \sa boundValue()
       
   864 */
       
   865 QString QSqlResult::boundValueName(int index) const
       
   866 {
       
   867     return d->holderAt(index);
       
   868 }
       
   869 
       
   870 /*!
       
   871     Returns true if at least one of the query's bound values is a \c
       
   872     QSql::Out or a QSql::InOut; otherwise returns false.
       
   873 
       
   874     \sa bindValueType()
       
   875 */
       
   876 bool QSqlResult::hasOutValues() const
       
   877 {
       
   878     if (d->types.isEmpty())
       
   879         return false;
       
   880     QHash<int, QSql::ParamType>::ConstIterator it;
       
   881     for (it = d->types.constBegin(); it != d->types.constEnd(); ++it) {
       
   882         if (it.value() != QSql::In)
       
   883             return true;
       
   884     }
       
   885     return false;
       
   886 }
       
   887 
       
   888 /*!
       
   889     Returns the current record if the query is active; otherwise
       
   890     returns an empty QSqlRecord.
       
   891 
       
   892     The default implementation always returns an empty QSqlRecord.
       
   893 
       
   894     \sa isActive()
       
   895 */
       
   896 QSqlRecord QSqlResult::record() const
       
   897 {
       
   898     return QSqlRecord();
       
   899 }
       
   900 
       
   901 /*!
       
   902     Returns the object ID of the most recent inserted row if the
       
   903     database supports it.
       
   904     An invalid QVariant will be returned if the query did not
       
   905     insert any value or if the database does not report the id back.
       
   906     If more than one row was touched by the insert, the behavior is
       
   907     undefined.
       
   908 
       
   909     Note that for Oracle databases the row's ROWID will be returned,
       
   910     while for MySQL databases the row's auto-increment field will
       
   911     be returned.
       
   912 
       
   913     \sa QSqlDriver::hasFeature()
       
   914 */
       
   915 QVariant QSqlResult::lastInsertId() const
       
   916 {
       
   917     return QVariant();
       
   918 }
       
   919 
       
   920 /*! \internal
       
   921 */
       
   922 void QSqlResult::virtual_hook(int, void *)
       
   923 {
       
   924 }
       
   925 
       
   926 /*! \internal
       
   927     \since 4.2
       
   928 
       
   929     Executes a prepared query in batch mode if the driver supports it,
       
   930     otherwise emulates a batch execution using bindValue() and exec().
       
   931     QSqlDriver::hasFeature() can be used to find out whether a driver
       
   932     supports batch execution.
       
   933 
       
   934     Batch execution can be faster for large amounts of data since it
       
   935     reduces network roundtrips.
       
   936 
       
   937     For batch executions, bound values have to be provided as lists
       
   938     of variants (QVariantList).
       
   939 
       
   940     Each list must contain values of the same type. All lists must
       
   941     contain equal amount of values (rows).
       
   942 
       
   943     NULL values are passed in as typed QVariants, for example
       
   944     \c {QVariant(QVariant::Int)} for an integer NULL value.
       
   945 
       
   946     Example:
       
   947 
       
   948     \snippet doc/src/snippets/code/src_sql_kernel_qsqlresult.cpp 0
       
   949 
       
   950     Here, we insert two rows into a SQL table, with each row containing three values.
       
   951 
       
   952     \sa exec(), QSqlDriver::hasFeature()
       
   953 */
       
   954 bool QSqlResult::execBatch(bool arrayBind)
       
   955 {
       
   956     if (driver()->hasFeature(QSqlDriver::BatchOperations)) {
       
   957         virtual_hook(BatchOperation, &arrayBind);
       
   958         d->resetBindCount();
       
   959         return d->error.type() == QSqlError::NoError;
       
   960     } else {
       
   961         QVector<QVariant> values = d->values;
       
   962         if (values.count() == 0)
       
   963             return false;
       
   964         for (int i = 0; i < values.at(0).toList().count(); ++i) {
       
   965             for (int j = 0; j < values.count(); ++j)
       
   966                 bindValue(j, values.at(j).toList().at(i), QSql::In);
       
   967             if (!exec())
       
   968                 return false;
       
   969         }
       
   970         return true;
       
   971     }
       
   972     return false;
       
   973 }
       
   974 
       
   975 /*! \internal
       
   976  */
       
   977 void QSqlResult::detachFromResultSet()
       
   978 {
       
   979     if (driver()->hasFeature(QSqlDriver::FinishQuery) 
       
   980             || driver()->hasFeature(QSqlDriver::SimpleLocking))
       
   981         virtual_hook(DetachFromResultSet, 0);
       
   982 }
       
   983 
       
   984 /*! \internal
       
   985  */
       
   986 void QSqlResult::setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy policy)
       
   987 {
       
   988     d->precisionPolicy = policy;
       
   989     virtual_hook(SetNumericalPrecision, &policy);
       
   990 }
       
   991 
       
   992 /*! \internal
       
   993  */
       
   994 QSql::NumericalPrecisionPolicy QSqlResult::numericalPrecisionPolicy() const
       
   995 {
       
   996     return d->precisionPolicy;
       
   997 }
       
   998 
       
   999 /*! \internal
       
  1000 */
       
  1001 bool QSqlResult::nextResult()
       
  1002 {
       
  1003     if (driver()->hasFeature(QSqlDriver::MultipleResultSets)) {
       
  1004         bool result = false;
       
  1005         virtual_hook(NextResult, &result);
       
  1006         return result;
       
  1007     }
       
  1008     return false;
       
  1009 }
       
  1010 
       
  1011 /*!
       
  1012     Returns the low-level database handle for this result set
       
  1013     wrapped in a QVariant or an invalid QVariant if there is no handle.
       
  1014 
       
  1015     \warning Use this with uttermost care and only if you know what you're doing.
       
  1016 
       
  1017     \warning The handle returned here can become a stale pointer if the result
       
  1018     is modified (for example, if you clear it).
       
  1019 
       
  1020     \warning The handle can be NULL if the result was not executed yet.
       
  1021 
       
  1022     The handle returned here is database-dependent, you should query the type
       
  1023     name of the variant before accessing it.
       
  1024 
       
  1025     This example retrieves the handle for a sqlite result:
       
  1026 
       
  1027     \snippet doc/src/snippets/code/src_sql_kernel_qsqlresult.cpp 1
       
  1028 
       
  1029     This snippet returns the handle for PostgreSQL or MySQL:
       
  1030 
       
  1031     \snippet doc/src/snippets/code/src_sql_kernel_qsqlresult.cpp 2
       
  1032 
       
  1033     \sa QSqlDriver::handle()
       
  1034 */
       
  1035 QVariant QSqlResult::handle() const
       
  1036 {
       
  1037     return QVariant();
       
  1038 }
       
  1039 
       
  1040 QT_END_NAMESPACE