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