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
54QT_BEGIN_NAMESPACE
55
56QString QSqlResultPrivate::holderAt(int index) const
57{
58 return holders.size() > index ? holders.at(i: index).holderName : fieldSerial(index);
59}
60
61// return a unique id for bound names
62QString 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, size: int(end - ptr));
78}
79
80static 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
87QString QSqlResultPrivate::positionalToNamedBinding(const QString &query) const
88{
89 int n = query.size();
90
91 QString result;
92 result.reserve(asize: 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: 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(i: 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
127QString 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(s: QLatin1String("EXECUTE BLOCK"), cs: Qt::CaseInsensitive))
134 return query;
135
136 int n = query.size();
137
138 QString result;
139 result.reserve(asize: 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: 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: i - 1) != QLatin1Char(':'))
163 && (i + 1 < n && qIsAlnum(ch: query.at(i: i + 1)))) {
164 int pos = i + 2;
165 while (pos < n && qIsAlnum(ch: query.at(i: pos)))
166 ++pos;
167 QString holder(query.mid(position: i, n: pos - i));
168 indexes[holder].append(t: count++);
169 holders.append(t: 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(asize: 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
231QSqlResult::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*/
241QSqlResult::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
253QSqlResult::~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
266void 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
279QString 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*/
292int 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
307bool 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
325bool 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
338void 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
354void 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
367bool 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
378const 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
392void 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
408void 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
419QSqlError 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
527bool QSqlResult::fetchNext()
528{
529 return fetch(i: 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
543bool QSqlResult::fetchPrevious()
544{
545 return fetch(i: 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*/
554bool 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*/
584void 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*/
599bool 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(f: 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(f: QSqlDriver::NamedPlaceholders))
613 d->executedQuery = d->positionalToNamedBinding(query);
614
615 return prepare(query: 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*/
625bool 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*/
642bool 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(i: d->indexes.value(akey: holder).value(i: 0,defaultValue: -1));
655 QSqlField f(QLatin1String(""), QVariant::Type(val.userType()));
656 f.setValue(val);
657 query = query.replace(i: d->holders.at(i).holderPos,
658 len: holder.length(), after: driver()->formatValue(field: 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(c: QLatin1Char('?'), from: i);
666 if (i == -1)
667 continue;
668 QVariant var = d->values.value(i: 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(field: f);
675 query = query.replace(i, len: 1, after: driver()->formatValue(field: f));
676 i += val.length();
677 }
678 }
679
680 // have to retain the original query with placeholders
681 QString orig = lastQuery();
682 ret = reset(sqlquery: 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*/
695void 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(i: index)];
700 if (!indexes.contains(t: index))
701 indexes.append(t: index);
702 if (d->values.count() <= index)
703 d->values.resize(asize: 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*/
719void 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(akey: placeholder);
727 for (int idx : indexes) {
728 if (d->values.count() <= idx)
729 d->values.resize(asize: 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*/
742void QSqlResult::addBindValue(const QVariant& val, QSql::ParamType paramType)
743{
744 Q_D(QSqlResult);
745 d->binds = PositionalBinding;
746 bindValue(index: 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*/
756QVariant QSqlResult::boundValue(int index) const
757{
758 Q_D(const QSqlResult);
759 return d->values.value(i: 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*/
770QVariant QSqlResult::boundValue(const QString& placeholder) const
771{
772 Q_D(const QSqlResult);
773 const QVector<int> indexes = d->indexes.value(akey: placeholder);
774 return d->values.value(i: indexes.value(i: 0,defaultValue: -1));
775}
776
777/*!
778 Returns the parameter type for the value bound at position \a index.
779
780 \sa boundValue()
781*/
782QSql::ParamType QSqlResult::bindValueType(int index) const
783{
784 Q_D(const QSqlResult);
785 return d->types.value(akey: index, adefaultValue: 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*/
794QSql::ParamType QSqlResult::bindValueType(const QString& placeholder) const
795{
796 Q_D(const QSqlResult);
797 return d->types.value(akey: d->indexes.value(akey: placeholder).value(i: 0,defaultValue: -1), adefaultValue: QSql::In);
798}
799
800/*!
801 Returns the number of bound values in the result.
802
803 \sa boundValues()
804*/
805int 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*/
817QVector<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*/
826QSqlResult::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*/
836void 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*/
850QString QSqlResult::executedQuery() const
851{
852 Q_D(const QSqlResult);
853 return d->executedQuery;
854}
855
856/*!
857 Resets the number of bind parameters.
858*/
859void 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*/
871QString 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*/
883bool 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*/
904QSqlRecord 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*/
923QVariant QSqlResult::lastInsertId() const
924{
925 return QVariant();
926}
927
928/*! \internal
929*/
930void 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*/
962bool 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(i: 0).toList().count(); ++i) {
971 for (int j = 0; j < values.count(); ++j)
972 bindValue(index: j, val: values.at(i: j).toList().at(i), paramType: QSql::In);
973 if (!exec())
974 return false;
975 }
976 return true;
977}
978
979/*! \internal
980 */
981void QSqlResult::detachFromResultSet()
982{
983}
984
985/*! \internal
986 */
987void QSqlResult::setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy policy)
988{
989 Q_D(QSqlResult);
990 d->precisionPolicy = policy;
991}
992
993/*! \internal
994 */
995QSql::NumericalPrecisionPolicy QSqlResult::numericalPrecisionPolicy() const
996{
997 Q_D(const QSqlResult);
998 return d->precisionPolicy;
999}
1000
1001/*! \internal
1002*/
1003bool 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*/
1036QVariant QSqlResult::handle() const
1037{
1038 return QVariant();
1039}
1040
1041QT_END_NAMESPACE
1042

source code of qtbase/src/sql/kernel/qsqlresult.cpp