Qt 6.x
The Qt SDK
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
qsqlquery.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 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
4#include "qsqlquery.h"
5
6//#define QT_DEBUG_SQL
7
8#include "qatomic.h"
9#include "qdebug.h"
10#include "qsqlrecord.h"
11#include "qsqlresult.h"
12#include "qsqldriver.h"
13#include "qsqldatabase.h"
14#include "private/qsqlnulldriver_p.h"
15
16#ifdef QT_DEBUG_SQL
17#include "qelapsedtimer.h"
18#endif
19
21
23{
24public:
29
31};
32
33Q_GLOBAL_STATIC_WITH_ARGS(QSqlQueryPrivate, nullQueryPrivate, (nullptr))
35Q_GLOBAL_STATIC_WITH_ARGS(QSqlNullResult, nullResult, (nullDriver()))
36
38{
39 QSqlQueryPrivate *null = nullQueryPrivate();
40 null->ref.ref();
41 return null;
42}
43
48 : ref(1), sqlResult(result)
49{
50 if (!sqlResult)
51 sqlResult = nullResult();
52}
53
55{
56 QSqlResult *nr = nullResult();
57 if (!nr || sqlResult == nr)
58 return;
59 delete sqlResult;
60}
61
202{
203 d = new QSqlQueryPrivate(result);
204}
205
211{
212 if (d && !d->ref.deref())
213 delete d;
214}
215
216#if QT_DEPRECATED_SINCE(6, 2)
227{
228 d = other.d;
229 d->ref.ref();
230}
231
242{
243 qAtomicAssign(d, other.d);
244 return *this;
245}
246#endif
247
270static void qInit(QSqlQuery *q, const QString& query, const QSqlDatabase &db)
271{
272 QSqlDatabase database = db;
273 if (!database.isValid()) {
274 database =
276 }
277 if (database.isValid())
278 *q = QSqlQuery(database.driver()->createResult());
279
280 if (!query.isEmpty())
281 q->exec(query);
282}
283
293{
295 qInit(this, query, db);
296}
297
306{
308 qInit(this, QString(), db);
309}
310
321bool QSqlQuery::isNull(int field) const
322{
323 return !d->sqlResult->isActive()
324 || !d->sqlResult->isValid()
325 || d->sqlResult->isNull(field);
326}
327
338{
340 if (index > -1)
341 return isNull(index);
342 qWarning("QSqlQuery::isNull: unknown field name '%s'", qPrintable(name));
343 return true;
344}
345
372{
373#ifdef QT_DEBUG_SQL
375 t.start();
376#endif
377 if (!driver()) {
378 qWarning("QSqlQuery::exec: called before driver has been set up");
379 return false;
380 }
381 if (d->ref.loadRelaxed() != 1) {
382 bool fo = isForwardOnly();
383 *this = QSqlQuery(driver()->createResult());
385 setForwardOnly(fo);
386 } else {
387 d->sqlResult->clear();
388 d->sqlResult->setActive(false);
392 }
393 d->sqlResult->setQuery(query.trimmed());
394 if (!driver()->isOpen() || driver()->isOpenError()) {
395 qWarning("QSqlQuery::exec: database not open");
396 return false;
397 }
398 if (query.isEmpty()) {
399 qWarning("QSqlQuery::exec: empty query");
400 return false;
401 }
402
403 bool retval = d->sqlResult->reset(query);
404#ifdef QT_DEBUG_SQL
405 qDebug().nospace() << "Executed query (" << t.elapsed() << "ms, " << d->sqlResult->size()
406 << " results, " << d->sqlResult->numRowsAffected()
407 << " affected): " << d->sqlResult->lastQuery();
408#endif
409 return retval;
410}
411
432{
433 if (isActive() && isValid() && (index > -1))
434 return d->sqlResult->data(index);
435 qWarning("QSqlQuery::value: not positioned on a valid record");
436 return QVariant();
437}
438
449{
451 if (index > -1)
452 return value(index);
453 qWarning("QSqlQuery::value: unknown field name '%s'", qPrintable(name));
454 return QVariant();
455}
456
466int QSqlQuery::at() const
467{
468 return d->sqlResult->at();
469}
470
479{
480 return d->sqlResult->lastQuery();
481}
482
488{
489 return d->sqlResult->driver();
490}
491
497{
498 return d->sqlResult;
499}
500
560bool QSqlQuery::seek(int index, bool relative)
561{
562 if (!isSelect() || !isActive())
563 return false;
564 int actualIdx;
565 if (!relative) { // arbitrary seek
566 if (index < 0) {
568 return false;
569 }
570 actualIdx = index;
571 } else {
572 switch (at()) { // relative seek
574 if (index > 0)
575 actualIdx = index - 1;
576 else {
577 return false;
578 }
579 break;
581 if (index < 0) {
582 d->sqlResult->fetchLast();
583 actualIdx = at() + index + 1;
584 } else {
585 return false;
586 }
587 break;
588 default:
589 if ((at() + index) < 0) {
591 return false;
592 }
593 actualIdx = at() + index;
594 break;
595 }
596 }
597 // let drivers optimize
598 if (isForwardOnly() && actualIdx < at()) {
599 qWarning("QSqlQuery::seek: cannot seek backwards in a forward only query");
600 return false;
601 }
602 if (actualIdx == (at() + 1) && at() != QSql::BeforeFirstRow) {
603 if (!d->sqlResult->fetchNext()) {
605 return false;
606 }
607 return true;
608 }
609 if (actualIdx == (at() - 1)) {
610 if (!d->sqlResult->fetchPrevious()) {
612 return false;
613 }
614 return true;
615 }
616 if (!d->sqlResult->fetch(actualIdx)) {
618 return false;
619 }
620 return true;
621}
622
653{
654 if (!isSelect() || !isActive())
655 return false;
656
657 switch (at()) {
659 return d->sqlResult->fetchFirst();
661 return false;
662 default:
663 if (!d->sqlResult->fetchNext()) {
665 return false;
666 }
667 return true;
668 }
669}
670
701{
702 if (!isSelect() || !isActive())
703 return false;
704 if (isForwardOnly()) {
705 qWarning("QSqlQuery::seek: cannot seek backwards in a forward only query");
706 return false;
707 }
708
709 switch (at()) {
711 return false;
713 return d->sqlResult->fetchLast();
714 default:
715 if (!d->sqlResult->fetchPrevious()) {
717 return false;
718 }
719 return true;
720 }
721}
722
734{
735 if (!isSelect() || !isActive())
736 return false;
738 qWarning("QSqlQuery::seek: cannot seek backwards in a forward only query");
739 return false;
740 }
741 return d->sqlResult->fetchFirst();
742}
743
757{
758 if (!isSelect() || !isActive())
759 return false;
760 return d->sqlResult->fetchLast();
761}
762
776{
778 return d->sqlResult->size();
779 return -1;
780}
781
792{
793 if (isActive())
794 return d->sqlResult->numRowsAffected();
795 return -1;
796}
797
806{
807 return d->sqlResult->lastError();
808}
809
816{
817 return d->sqlResult->isValid();
818}
819
838{
839 return d->sqlResult->isActive();
840}
841
848{
849 return d->sqlResult->isSelect();
850}
851
859{
860 return d->sqlResult->isForwardOnly();
861}
862
896{
897 d->sqlResult->setForwardOnly(forward);
898}
899
919{
920 QSqlRecord rec = d->sqlResult->record();
921
922 if (isValid()) {
923 for (qsizetype i = 0; i < rec.count(); ++i)
924 rec.setValue(i, value(i));
925 }
926 return rec;
927}
928
935{
936 *this = QSqlQuery(driver()->createResult());
937}
938
966{
967 if (d->ref.loadRelaxed() != 1) {
968 bool fo = isForwardOnly();
969 *this = QSqlQuery(driver()->createResult());
970 setForwardOnly(fo);
972 } else {
973 d->sqlResult->setActive(false);
977 }
978 if (!driver()) {
979 qWarning("QSqlQuery::prepare: no driver");
980 return false;
981 }
982 if (!driver()->isOpen() || driver()->isOpenError()) {
983 qWarning("QSqlQuery::prepare: database not open");
984 return false;
985 }
986 if (query.isEmpty()) {
987 qWarning("QSqlQuery::prepare: empty query");
988 return false;
989 }
990#ifdef QT_DEBUG_SQL
991 qDebug("\n QSqlQuery::prepare: %s", query.toLocal8Bit().constData());
992#endif
993 return d->sqlResult->savePrepare(query);
994}
995
1006{
1007#ifdef QT_DEBUG_SQL
1009 t.start();
1010#endif
1012
1013 if (d->sqlResult->lastError().isValid())
1015
1016 bool retval = d->sqlResult->exec();
1017#ifdef QT_DEBUG_SQL
1018 qDebug().nospace() << "Executed prepared query (" << t.elapsed() << "ms, "
1019 << d->sqlResult->size() << " results, " << d->sqlResult->numRowsAffected()
1020 << " affected): " << d->sqlResult->lastQuery();
1021#endif
1022 return retval;
1023}
1024
1075{
1077 return d->sqlResult->execBatch(mode == ValuesAsColumns);
1078}
1079
1094void QSqlQuery::bindValue(const QString& placeholder, const QVariant& val,
1095 QSql::ParamType paramType
1096)
1097{
1098 d->sqlResult->bindValue(placeholder, val, paramType);
1099}
1100
1107void QSqlQuery::bindValue(int pos, const QVariant& val, QSql::ParamType paramType)
1108{
1109 d->sqlResult->bindValue(pos, val, paramType);
1110}
1111
1124void QSqlQuery::addBindValue(const QVariant& val, QSql::ParamType paramType)
1125{
1126 d->sqlResult->addBindValue(val, paramType);
1127}
1128
1134QVariant QSqlQuery::boundValue(const QString& placeholder) const
1135{
1136 return d->sqlResult->boundValue(placeholder);
1137}
1138
1144{
1145 return d->sqlResult->boundValue(pos);
1146}
1147
1164{
1166 return values;
1167}
1168
1180{
1181 return d->sqlResult->boundValueNames();
1182}
1183
1195{
1196 return d->sqlResult->boundValueName(pos);
1197}
1198
1212{
1213 return d->sqlResult->executedQuery();
1214}
1215
1232{
1233 return d->sqlResult->lastInsertId();
1234}
1235
1258{
1259 d->sqlResult->setNumericalPrecisionPolicy(precisionPolicy);
1260}
1261
1268{
1270}
1271
1286{
1287 if (isActive()) {
1291 d->sqlResult->setActive(false);
1292 }
1293}
1294
1327{
1328 if (isActive())
1329 return d->sqlResult->nextResult();
1330 return false;
1331}
1332
bool isActive
\inmodule QtCore
Definition qatomic.h:112
bool ref() noexcept
bool deref() noexcept
T loadRelaxed() const noexcept
\inmodule QtCore
The QSqlDatabase class handles a connection to a database.
bool isValid() const
Returns true if the QSqlDatabase has a valid driver.
QSqlDriver * driver() const
Returns the database driver used to access the database connection.
static const char * defaultConnection
static QSqlDatabase database(const QString &connectionName=QLatin1StringView(defaultConnection), bool open=true)
\threadsafe
The QSqlDriver class is an abstract base class for accessing specific SQL databases.
Definition qsqldriver.h:25
virtual QSqlResult * createResult() const =0
Creates an empty SQL result on the database.
virtual bool hasFeature(DriverFeature f) const =0
Returns true if the driver supports feature feature; otherwise returns false.
The QSqlError class provides SQL database error information.
Definition qsqlerror.h:17
bool isValid() const
Returns true if an error is set, otherwise false.
QSqlQueryPrivate(QSqlResult *result)
Definition qsqlquery.cpp:47
QAtomicInt ref
Definition qsqlquery.cpp:27
QSqlResult * sqlResult
Definition qsqlquery.cpp:28
static QSqlQueryPrivate * shared_null()
The QSqlQuery class provides a means of executing and manipulating SQL statements.
Definition qsqlquery.h:23
QSqlQuery & operator=(const QSqlQuery &other)=delete
bool next()
Retrieves the next record in the result, if available, and positions the query on the retrieved recor...
bool last()
Retrieves the last record in the result, if available, and positions the query on the retrieved recor...
const QSqlDriver * driver() const
Returns the database driver associated with the query.
bool previous()
Retrieves the previous record in the result, if available, and positions the query on the retrieved r...
QStringList boundValueNames() const
void finish()
bool prepare(const QString &query)
Prepares the SQL query query for execution.
QVariant value(int i) const
Returns the value of field index in the current record.
int size() const
Returns the size of the result (number of rows returned), or -1 if the size cannot be determined or i...
int numRowsAffected() const
Returns the number of rows affected by the result's SQL statement, or -1 if it cannot be determined.
const QSqlResult * result() const
Returns the result associated with the query.
bool nextResult()
QSql::NumericalPrecisionPolicy numericalPrecisionPolicy() const
Returns the current precision policy.
bool first()
Retrieves the first record in the result, if available, and positions the query on the retrieved reco...
QVariant boundValue(const QString &placeholder) const
Returns the value for the placeholder.
void setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy precisionPolicy)
Instruct the database driver to return numerical values with a precision specified by precisionPolicy...
bool isForwardOnly() const
Returns true if you can only scroll forward through a result set; otherwise returns false.
QString boundValueName(int pos) const
void clear()
Clears the result set and releases any resources held by the query.
QSqlError lastError() const
Returns error information about the last error (if any) that occurred with this query.
BatchExecutionMode
\value ValuesAsRows - Updates multiple rows.
Definition qsqlquery.h:82
@ ValuesAsColumns
Definition qsqlquery.h:82
QSqlRecord record() const
Returns a QSqlRecord containing the field information for the current query.
QString lastQuery() const
Returns the text of the current query being used, or an empty string if there is no current query tex...
bool isActive() const
Returns true if the query is {active}.
QVariant lastInsertId() const
Returns the object ID of the most recent inserted row if the database supports it.
void setForwardOnly(bool forward)
Sets forward only mode to forward.
int at() const
Returns the current internal position of the query.
bool exec()
Executes a previously prepared SQL query.
void bindValue(const QString &placeholder, const QVariant &val, QSql::ParamType type=QSql::In)
Set the placeholder placeholder to be bound to value val in the prepared statement.
QVariantList boundValues() const
bool isSelect() const
Returns true if the current query is a SELECT statement; otherwise returns false.
QSqlQuery(QSqlResult *r)
Constructs a QSqlQuery object which uses the QSqlResult result to communicate with a database.
void addBindValue(const QVariant &val, QSql::ParamType type=QSql::In)
Adds the value val to the list of values when using positional value binding.
bool isNull(int field) const
Returns true if the query is not \l{isActive()}{active}, the query is not positioned on a valid recor...
~QSqlQuery()
Destroys the object and frees any allocated resources.
bool isValid() const
Returns true if the query is currently positioned on a valid record; otherwise returns false.
bool execBatch(BatchExecutionMode mode=ValuesAsRows)
bool seek(int i, bool relative=false)
Retrieves the record at position index, if available, and positions the query on the retrieved record...
QString executedQuery() const
Returns the last query that was successfully executed.
The QSqlRecord class encapsulates a database record.
Definition qsqlrecord.h:20
int count() const
Returns the number of fields in the record.
void setValue(int i, const QVariant &val)
Sets the value of the field at position index to val.
int indexOf(const QString &name) const
Returns the position of the field called name within the record, or -1 if it cannot be found.
The QSqlResult class provides an abstract interface for accessing data from specific SQL databases.
Definition qsqlresult.h:25
bool isForwardOnly() const
Returns true if you can only scroll forward through the result set; otherwise returns false.
virtual QVariant lastInsertId() const
Returns the object ID of the most recent inserted row if the database supports it.
virtual bool isNull(int i)=0
Returns true if the field at position index in the current row is null; otherwise returns false.
QString executedQuery() const
Returns the query that was actually executed.
void clear()
Clears the entire result set and releases any associated resources.
virtual bool execBatch(bool arrayBind=false)
virtual QVariant data(int i)=0
Returns the data for field index in the current row as a QVariant.
virtual void setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy policy)
virtual void detachFromResultSet()
int at() const
Returns the current (zero-based) row position of the result.
QVariant boundValue(const QString &placeholder) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
virtual bool exec()
Executes the query, returning true if successful; otherwise returns false.
void addBindValue(const QVariant &val, QSql::ParamType type)
Binds the value val of parameter type paramType to the next available position in the current record ...
bool isSelect() const
Returns true if the current result is from a SELECT statement; otherwise returns false.
virtual void setAt(int at)
This function is provided for derived classes to set the internal (zero-based) row position to index.
virtual bool fetchLast()=0
Positions the result to the last record (last row) in the result.
QString lastQuery() const
Returns the current SQL query text, or an empty string if there isn't one.
virtual void setActive(bool a)
This function is provided for derived classes to set the internal active state to active.
virtual bool fetchPrevious()
Positions the result to the previous record (row) in the result.
virtual bool nextResult()
virtual bool fetch(int i)=0
Positions the result to an arbitrary (zero-based) row index.
QVariantList & boundValues(QT6_DECL_NEW_OVERLOAD)
virtual bool fetchNext()
Positions the result to the next available record (row) in the result.
void resetBindCount()
Resets the number of bind parameters.
virtual bool savePrepare(const QString &sqlquery)
Prepares the given query, using the underlying database functionality where possible.
QSqlError lastError() const
Returns the last error associated with the result.
QSql::NumericalPrecisionPolicy numericalPrecisionPolicy() const
virtual int size()=0
Returns the size of the SELECT result, or -1 if it cannot be determined or if the query is not a SELE...
virtual bool fetchFirst()=0
Positions the result to the first record (row 0) in the result.
virtual void setLastError(const QSqlError &e)
This function is provided for derived classes to set the last error to error.
virtual int numRowsAffected()=0
Returns the number of rows affected by the last query executed, or -1 if it cannot be determined or i...
virtual QSqlRecord record() const
Returns the current record if the query is active; otherwise returns an empty QSqlRecord.
virtual void setQuery(const QString &query)
Sets the current query for the result to query.
const QSqlDriver * driver() const
Returns the driver associated with the result.
QString boundValueName(int pos) const
Returns the name of the bound value at position index in the current record (row).
bool isValid() const
Returns true if the result is positioned on a valid record (that is, the result is not positioned bef...
QStringList boundValueNames() const
Returns the names of all bound values.
virtual void setForwardOnly(bool forward)
Sets forward only mode to forward.
virtual void bindValue(int pos, const QVariant &val, QSql::ParamType type)
Binds the value val of parameter type paramType to position index in the current record (row).
bool isActive() const
Returns true if the result has records to be retrieved; otherwise returns false.
virtual bool reset(const QString &sqlquery)=0
Sets the result to use the SQL statement query for subsequent data retrieval.
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
\inmodule QtCore
Definition qvariant.h:64
@ AfterLastRow
Definition qtsqlglobal.h:23
@ BeforeFirstRow
Definition qtsqlglobal.h:22
NumericalPrecisionPolicy
Definition qtsqlglobal.h:44
Combined button and popup list for selecting options.
QT_WARNING_POP void qAtomicAssign(T *&d, T *x)
This is a helper for the assignment operators of implicitly shared classes.
Definition qatomic.h:180
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS)
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define qDebug
[1]
Definition qlogging.h:160
#define qWarning
Definition qlogging.h:162
GLenum GLsizei GLsizei GLint * values
[15]
GLenum mode
GLuint index
[2]
GLint ref
GLuint name
GLenum query
GLuint GLfloat * val
GLdouble GLdouble t
Definition qopenglext.h:243
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLuint64EXT * result
[6]
static void qInit(QSqlQuery *q, const QString &query, const QSqlDatabase &db)
#define qPrintable(string)
Definition qstring.h:1391
ptrdiff_t qsizetype
Definition qtypes.h:70
QMimeDatabase db
[0]
QSharedPointer< T > other(t)
[5]