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