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