src/sql/kernel/qsqlresult.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 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::fromUtf16(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     \sa isForwardOnly(), fetchNext(), QSqlQuery::setForwardOnly()
       
   568 */
       
   569 void QSqlResult::setForwardOnly(bool forward)
       
   570 {
       
   571     d->forwardOnly = forward;
       
   572 }
       
   573 
       
   574 /*!
       
   575     Prepares the given \a query, using the underlying database
       
   576     functionality where possible. Returns true if the query is
       
   577     prepared successfully; otherwise returns false.
       
   578 
       
   579     \sa prepare()
       
   580 */
       
   581 bool QSqlResult::savePrepare(const QString& query)
       
   582 {
       
   583     if (!driver())
       
   584         return false;
       
   585     d->clear();
       
   586     d->sql = query;
       
   587     if (!driver()->hasFeature(QSqlDriver::PreparedQueries))
       
   588         return prepare(query);
       
   589 
       
   590     if (driver()->hasFeature(QSqlDriver::NamedPlaceholders)) {
       
   591         // parse the query to memorize parameter location
       
   592         d->namedToPositionalBinding();
       
   593         d->executedQuery = d->positionalToNamedBinding();
       
   594     } else {
       
   595         d->executedQuery = d->namedToPositionalBinding();
       
   596     }
       
   597     return prepare(d->executedQuery);
       
   598 }
       
   599 
       
   600 /*!
       
   601     Prepares the given \a query for execution; the query will normally
       
   602     use placeholders so that it can be executed repeatedly. Returns
       
   603     true if the query is prepared successfully; otherwise returns false.
       
   604 
       
   605     \sa exec()
       
   606 */
       
   607 bool QSqlResult::prepare(const QString& query)
       
   608 {
       
   609     int n = query.size();
       
   610 
       
   611     bool inQuote = false;
       
   612     int i = 0;
       
   613 
       
   614     while (i < n) {
       
   615         QChar ch = query.at(i);
       
   616         if (ch == QLatin1Char(':') && !inQuote
       
   617                 && (i == 0 || query.at(i - 1) != QLatin1Char(':'))
       
   618                 && (i < n - 1 && qIsAlnum(query.at(i + 1)))) {
       
   619             int pos = i + 2;
       
   620             while (pos < n && qIsAlnum(query.at(pos)))
       
   621                 ++pos;
       
   622 
       
   623             d->holders.append(QHolder(query.mid(i, pos - i), i));
       
   624             i = pos;
       
   625         } else {
       
   626             if (ch == QLatin1Char('\''))
       
   627                 inQuote = !inQuote;
       
   628             ++i;
       
   629         }
       
   630     }
       
   631     d->sql = query;
       
   632     return true; // fake prepares should always succeed
       
   633 }
       
   634 
       
   635 /*!
       
   636     Executes the query, returning true if successful; otherwise returns
       
   637     false.
       
   638 
       
   639     \sa prepare()
       
   640 */
       
   641 bool QSqlResult::exec()
       
   642 {
       
   643     bool ret;
       
   644     // fake preparation - just replace the placeholders..
       
   645     QString query = lastQuery();
       
   646     if (d->binds == NamedBinding) {
       
   647         int i;
       
   648         QVariant val;
       
   649         QString holder;
       
   650         for (i = d->holders.count() - 1; i >= 0; --i) {
       
   651             holder = d->holders.at(i).holderName;
       
   652             val = d->values.value(d->indexes.value(holder));
       
   653             QSqlField f(QLatin1String(""), val.type());
       
   654             f.setValue(val);
       
   655             query = query.replace(d->holders.at(i).holderPos,
       
   656                                    holder.length(), driver()->formatValue(f));
       
   657         }
       
   658     } else {
       
   659         QString val;
       
   660         int i = 0;
       
   661         int idx = 0;
       
   662         for (idx = 0; idx < d->values.count(); ++idx) {
       
   663             i = query.indexOf(QLatin1Char('?'), i);
       
   664             if (i == -1)
       
   665                 continue;
       
   666             QVariant var = d->values.value(idx);
       
   667             QSqlField f(QLatin1String(""), var.type());
       
   668             if (var.isNull())
       
   669                 f.clear();
       
   670             else
       
   671                 f.setValue(var);
       
   672             val = driver()->formatValue(f);
       
   673             query = query.replace(i, 1, driver()->formatValue(f));
       
   674             i += val.length();
       
   675         }
       
   676     }
       
   677 
       
   678     // have to retain the original query with placeholders
       
   679     QString orig = lastQuery();
       
   680     ret = reset(query);
       
   681     d->executedQuery = query;
       
   682     setQuery(orig);
       
   683     d->resetBindCount();
       
   684     return ret;
       
   685 }
       
   686 
       
   687 /*!
       
   688     Binds the value \a val of parameter type \a paramType to position \a index
       
   689     in the current record (row).
       
   690 
       
   691     \sa addBindValue()
       
   692 */
       
   693 void QSqlResult::bindValue(int index, const QVariant& val, QSql::ParamType paramType)
       
   694 {
       
   695     d->binds = PositionalBinding;
       
   696     d->indexes[qFieldSerial(index)] = index;
       
   697     if (d->values.count() <= index)
       
   698         d->values.resize(index + 1);
       
   699     d->values[index] = val;
       
   700     if (paramType != QSql::In || !d->types.isEmpty())
       
   701         d->types[index] = paramType;
       
   702 }
       
   703 
       
   704 /*!
       
   705     \overload
       
   706 
       
   707     Binds the value \a val of parameter type \a paramType to the \a
       
   708     placeholder name in the current record (row).
       
   709 
       
   710     Note that binding an undefined placeholder will result in undefined behavior.
       
   711 */
       
   712 void QSqlResult::bindValue(const QString& placeholder, const QVariant& val,
       
   713                            QSql::ParamType paramType)
       
   714 {
       
   715     d->binds = NamedBinding;
       
   716     // if the index has already been set when doing emulated named
       
   717     // bindings - don't reset it
       
   718     int idx = d->indexes.value(placeholder, -1);
       
   719     if (idx >= 0) {
       
   720         if (d->values.count() <= idx)
       
   721             d->values.resize(idx + 1);
       
   722         d->values[idx] = val;
       
   723     } else {
       
   724         d->values.append(val);
       
   725         idx = d->values.count() - 1;
       
   726         d->indexes[placeholder] = idx;
       
   727     }
       
   728 
       
   729     if (paramType != QSql::In || !d->types.isEmpty())
       
   730         d->types[idx] = paramType;
       
   731 }
       
   732 
       
   733 /*!
       
   734     Binds the value \a val of parameter type \a paramType to the next
       
   735     available position in the current record (row).
       
   736 
       
   737     \sa bindValue()
       
   738 */
       
   739 void QSqlResult::addBindValue(const QVariant& val, QSql::ParamType paramType)
       
   740 {
       
   741     d->binds = PositionalBinding;
       
   742     bindValue(d->bindCount, val, paramType);
       
   743     ++d->bindCount;
       
   744 }
       
   745 
       
   746 /*!
       
   747     Returns the value bound at position \a index in the current record
       
   748     (row).
       
   749 
       
   750     \sa bindValue(), boundValues()
       
   751 */
       
   752 QVariant QSqlResult::boundValue(int index) const
       
   753 {
       
   754     return d->values.value(index);
       
   755 }
       
   756 
       
   757 /*!
       
   758     \overload
       
   759 
       
   760     Returns the value bound by the given \a placeholder name in the
       
   761     current record (row).
       
   762 
       
   763     \sa bindValueType()
       
   764 */
       
   765 QVariant QSqlResult::boundValue(const QString& placeholder) const
       
   766 {
       
   767     int idx = d->indexes.value(placeholder, -1);
       
   768     return d->values.value(idx);
       
   769 }
       
   770 
       
   771 /*!
       
   772     Returns the parameter type for the value bound at position \a index.
       
   773 
       
   774     \sa boundValue()
       
   775 */
       
   776 QSql::ParamType QSqlResult::bindValueType(int index) const
       
   777 {
       
   778     return d->types.value(index, QSql::In);
       
   779 }
       
   780 
       
   781 /*!
       
   782     \overload
       
   783 
       
   784     Returns the parameter type for the value bound with the given \a
       
   785     placeholder name.
       
   786 */
       
   787 QSql::ParamType QSqlResult::bindValueType(const QString& placeholder) const
       
   788 {
       
   789     return d->types.value(d->indexes.value(placeholder, -1), QSql::In);
       
   790 }
       
   791 
       
   792 /*!
       
   793     Returns the number of bound values in the result.
       
   794 
       
   795     \sa boundValues()
       
   796 */
       
   797 int QSqlResult::boundValueCount() const
       
   798 {
       
   799     return d->values.count();
       
   800 }
       
   801 
       
   802 /*!
       
   803     Returns a vector of the result's bound values for the current
       
   804     record (row).
       
   805 
       
   806     \sa boundValueCount()
       
   807 */
       
   808 QVector<QVariant>& QSqlResult::boundValues() const
       
   809 {
       
   810     return d->values;
       
   811 }
       
   812 
       
   813 /*!
       
   814     Returns the binding syntax used by prepared queries.
       
   815 */
       
   816 QSqlResult::BindingSyntax QSqlResult::bindingSyntax() const
       
   817 {
       
   818     return d->binds;
       
   819 }
       
   820 
       
   821 /*!
       
   822     Clears the entire result set and releases any associated
       
   823     resources.
       
   824 */
       
   825 void QSqlResult::clear()
       
   826 {
       
   827     d->clear();
       
   828 }
       
   829 
       
   830 /*!
       
   831     Returns the query that was actually executed. This may differ from
       
   832     the query that was passed, for example if bound values were used
       
   833     with a prepared query and the underlying database doesn't support
       
   834     prepared queries.
       
   835 
       
   836     \sa exec(), setQuery()
       
   837 */
       
   838 QString QSqlResult::executedQuery() const
       
   839 {
       
   840     return d->executedQuery;
       
   841 }
       
   842 
       
   843 void QSqlResult::resetBindCount()
       
   844 {
       
   845     d->resetBindCount();
       
   846 }
       
   847 
       
   848 /*!
       
   849     Returns the name of the bound value at position \a index in the
       
   850     current record (row).
       
   851 
       
   852     \sa boundValue()
       
   853 */
       
   854 QString QSqlResult::boundValueName(int index) const
       
   855 {
       
   856     return d->holderAt(index);
       
   857 }
       
   858 
       
   859 /*!
       
   860     Returns true if at least one of the query's bound values is a \c
       
   861     QSql::Out or a QSql::InOut; otherwise returns false.
       
   862 
       
   863     \sa bindValueType()
       
   864 */
       
   865 bool QSqlResult::hasOutValues() const
       
   866 {
       
   867     if (d->types.isEmpty())
       
   868         return false;
       
   869     QHash<int, QSql::ParamType>::ConstIterator it;
       
   870     for (it = d->types.constBegin(); it != d->types.constEnd(); ++it) {
       
   871         if (it.value() != QSql::In)
       
   872             return true;
       
   873     }
       
   874     return false;
       
   875 }
       
   876 
       
   877 /*!
       
   878     Returns the current record if the query is active; otherwise
       
   879     returns an empty QSqlRecord.
       
   880 
       
   881     The default implementation always returns an empty QSqlRecord.
       
   882 
       
   883     \sa isActive()
       
   884 */
       
   885 QSqlRecord QSqlResult::record() const
       
   886 {
       
   887     return QSqlRecord();
       
   888 }
       
   889 
       
   890 /*!
       
   891     Returns the object ID of the most recent inserted row if the
       
   892     database supports it.
       
   893     An invalid QVariant will be returned if the query did not
       
   894     insert any value or if the database does not report the id back.
       
   895     If more than one row was touched by the insert, the behavior is
       
   896     undefined.
       
   897 
       
   898     Note that for Oracle databases the row's ROWID will be returned,
       
   899     while for MySQL databases the row's auto-increment field will
       
   900     be returned.
       
   901 
       
   902     \sa QSqlDriver::hasFeature()
       
   903 */
       
   904 QVariant QSqlResult::lastInsertId() const
       
   905 {
       
   906     return QVariant();
       
   907 }
       
   908 
       
   909 /*! \internal
       
   910 */
       
   911 void QSqlResult::virtual_hook(int, void *)
       
   912 {
       
   913 }
       
   914 
       
   915 /*! \internal
       
   916     \since 4.2
       
   917 
       
   918     Executes a prepared query in batch mode if the driver supports it,
       
   919     otherwise emulates a batch execution using bindValue() and exec().
       
   920     QSqlDriver::hasFeature() can be used to find out whether a driver
       
   921     supports batch execution.
       
   922 
       
   923     Batch execution can be faster for large amounts of data since it
       
   924     reduces network roundtrips.
       
   925 
       
   926     For batch executions, bound values have to be provided as lists
       
   927     of variants (QVariantList).
       
   928 
       
   929     Each list must contain values of the same type. All lists must
       
   930     contain equal amount of values (rows).
       
   931 
       
   932     NULL values are passed in as typed QVariants, for example
       
   933     \c {QVariant(QVariant::Int)} for an integer NULL value.
       
   934 
       
   935     Example:
       
   936 
       
   937     \snippet doc/src/snippets/code/src_sql_kernel_qsqlresult.cpp 0
       
   938 
       
   939     Here, we insert two rows into a SQL table, with each row containing three values.
       
   940 
       
   941     \sa exec(), QSqlDriver::hasFeature()
       
   942 */
       
   943 bool QSqlResult::execBatch(bool arrayBind)
       
   944 {
       
   945     if (driver()->hasFeature(QSqlDriver::BatchOperations)) {
       
   946         virtual_hook(BatchOperation, &arrayBind);
       
   947         d->resetBindCount();
       
   948         return d->error.type() == QSqlError::NoError;
       
   949     } else {
       
   950         QVector<QVariant> values = d->values;
       
   951         if (values.count() == 0)
       
   952             return false;
       
   953         for (int i = 0; i < values.at(0).toList().count(); ++i) {
       
   954             for (int j = 0; j < values.count(); ++j)
       
   955                 bindValue(j, values.at(j).toList().at(i), QSql::In);
       
   956             if (!exec())
       
   957                 return false;
       
   958         }
       
   959         return true;
       
   960     }
       
   961     return false;
       
   962 }
       
   963 
       
   964 /*! \internal
       
   965  */
       
   966 void QSqlResult::detachFromResultSet()
       
   967 {
       
   968     if (driver()->hasFeature(QSqlDriver::FinishQuery) 
       
   969             || driver()->hasFeature(QSqlDriver::SimpleLocking))
       
   970         virtual_hook(DetachFromResultSet, 0);
       
   971 }
       
   972 
       
   973 /*! \internal
       
   974  */
       
   975 void QSqlResult::setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy policy)
       
   976 {
       
   977     d->precisionPolicy = policy;
       
   978     virtual_hook(SetNumericalPrecision, &policy);
       
   979 }
       
   980 
       
   981 /*! \internal
       
   982  */
       
   983 QSql::NumericalPrecisionPolicy QSqlResult::numericalPrecisionPolicy() const
       
   984 {
       
   985     return d->precisionPolicy;
       
   986 }
       
   987 
       
   988 /*! \internal
       
   989 */
       
   990 bool QSqlResult::nextResult()
       
   991 {
       
   992     if (driver()->hasFeature(QSqlDriver::MultipleResultSets)) {
       
   993         bool result = false;
       
   994         virtual_hook(NextResult, &result);
       
   995         return result;
       
   996     }
       
   997     return false;
       
   998 }
       
   999 
       
  1000 /*!
       
  1001     Returns the low-level database handle for this result set
       
  1002     wrapped in a QVariant or an invalid QVariant if there is no handle.
       
  1003 
       
  1004     \warning Use this with uttermost care and only if you know what you're doing.
       
  1005 
       
  1006     \warning The handle returned here can become a stale pointer if the result
       
  1007     is modified (for example, if you clear it).
       
  1008 
       
  1009     \warning The handle can be NULL if the result was not executed yet.
       
  1010 
       
  1011     The handle returned here is database-dependent, you should query the type
       
  1012     name of the variant before accessing it.
       
  1013 
       
  1014     This example retrieves the handle for a sqlite result:
       
  1015 
       
  1016     \snippet doc/src/snippets/code/src_sql_kernel_qsqlresult.cpp 1
       
  1017 
       
  1018     This snippet returns the handle for PostgreSQL or MySQL:
       
  1019 
       
  1020     \snippet doc/src/snippets/code/src_sql_kernel_qsqlresult.cpp 2
       
  1021 
       
  1022     \sa QSqlDriver::handle()
       
  1023 */
       
  1024 QVariant QSqlResult::handle() const
       
  1025 {
       
  1026     return QVariant();
       
  1027 }
       
  1028 
       
  1029 QT_END_NAMESPACE