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