Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qsqldatabase.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
4#include "qsqldatabase.h"
5#include "qsqlquery.h"
6#include "qloggingcategory.h"
7#include "qcoreapplication.h"
8#include "qreadwritelock.h"
9#include "qsqldriver.h"
10#include "qsqldriver_p.h"
11#include "qsqldriverplugin.h"
12#include "qsqlindex.h"
13#include "QtCore/qapplicationstatic.h"
14#include "private/qfactoryloader_p.h"
15#include "private/qsqlnulldriver_p.h"
16#include "qhash.h"
17#include "qthread.h"
18
20
21static Q_LOGGING_CATEGORY(lcSqlDb, "qt.sql.qsqldatabase")
22
23using namespace Qt::StringLiterals;
24
25#define CHECK_QCOREAPPLICATION \
26 if (Q_UNLIKELY(!QCoreApplication::instance())) { \
27 qCWarning(lcSqlDb, "QSqlDatabase requires a QCoreApplication"); \
28 return; \
29 }
30#define CHECK_QCOREAPPLICATION_RETVAL \
31 if (Q_UNLIKELY(!QCoreApplication::instance())) { \
32 qCWarning(lcSqlDb, "QSqlDatabase requires a QCoreApplication"); \
33 return {}; \
34 }
35
37 (QSqlDriverFactoryInterface_iid, "/sqldrivers"_L1))
38
39const char *QSqlDatabase::defaultConnection = "qt_sql_default_connection";
40
41namespace {
43 {
46 {
47 QReadLocker locker(&lock);
48 return connections.value(key);
49 }
50 bool connectionExists(const QString &key) const
51 {
52 QReadLocker locker(&lock);
53 return connections.contains(key);
54 }
56 {
57 QReadLocker locker(&lock);
58 return connections.keys();
59 }
61 QHash<QString, QSqlDriverCreatorBase*> registeredDrivers;
62 QHash<QString, QSqlDatabase> connections;
63 };
64}
65Q_APPLICATION_STATIC(QtSqlGlobals, s_sqlGlobals)
66
68{
69public:
71 ref(1),
72 driver(dr),
73 port(-1)
74 {
75 precisionPolicy = QSql::LowPrecisionDouble;
76 }
79 void init(const QString& type);
80 void copy(const QSqlDatabasePrivate *other);
81 void disable();
82
90 int port;
94
95 static QSqlDatabasePrivate *shared_null();
96 static QSqlDatabase database(const QString& name, bool open);
97 static void addDatabase(const QSqlDatabase &db, const QString & name);
98 static void removeDatabase(const QString& name);
99 static void invalidateDb(const QSqlDatabase &db, const QString &name, bool doWarn = true);
100};
101
103{
104 dbname = other.dbname;
105 uname = other.uname;
106 pword = other.pword;
107 hname = other.hname;
108 drvName = other.drvName;
109 port = other.port;
110 connOptions = other.connOptions;
111 driver = other.driver;
112 precisionPolicy = other.precisionPolicy;
113 if (driver)
114 driver->setNumericalPrecisionPolicy(other.driver->numericalPrecisionPolicy());
115}
116
122
123QtSqlGlobals::~QtSqlGlobals()
124{
125 qDeleteAll(registeredDrivers);
126 for (const auto &[k, v] : std::as_const(connections).asKeyValueRange())
128}
129
131{
132 static QSqlNullDriver dr;
133 static QSqlDatabasePrivate n(&dr);
134 return &n;
135}
136
138{
139 if (db.d->ref.loadRelaxed() != 1 && doWarn) {
140 qCWarning(lcSqlDb, "QSqlDatabasePrivate::removeDatabase: connection '%ls' is still in use, "
141 "all queries will cease to work.", qUtf16Printable(name));
142 db.d->disable();
143 db.d->connName.clear();
144 }
145}
146
148{
150 QtSqlGlobals *sqlGlobals = s_sqlGlobals();
151 QWriteLocker locker(&sqlGlobals->lock);
152
153 if (!sqlGlobals->connections.contains(name))
154 return;
155
156 invalidateDb(sqlGlobals->connections.take(name), name);
157}
158
160{
162 QtSqlGlobals *sqlGlobals = s_sqlGlobals();
163 QWriteLocker locker(&sqlGlobals->lock);
164
165 if (sqlGlobals->connections.contains(name)) {
166 invalidateDb(sqlGlobals->connections.take(name), name);
167 qCWarning(lcSqlDb, "QSqlDatabasePrivate::addDatabase: duplicate connection name '%ls', old "
168 "connection removed.", qUtf16Printable(name));
169 }
170 sqlGlobals->connections.insert(name, db);
171 db.d->connName = name;
172}
173
177{
179 QSqlDatabase db = s_sqlGlobals()->connection(name);
180 if (!db.isValid())
181 return db;
182 if (db.driver()->thread() != QThread::currentThread()) {
183 qCWarning(lcSqlDb, "QSqlDatabasePrivate::database: requested database does not belong to the calling thread.");
184 return QSqlDatabase();
185 }
186
187 if (open && !db.isOpen()) {
188 if (!db.open())
189 qCWarning(lcSqlDb) << "QSqlDatabasePrivate::database: unable to open database:" << db.lastError().text();
190
191 }
192 return db;
193}
194
195
200{
201 dbname = other->dbname;
202 uname = other->uname;
203 pword = other->pword;
204 hname = other->hname;
205 drvName = other->drvName;
206 port = other->port;
207 connOptions = other->connOptions;
208 precisionPolicy = other->precisionPolicy;
209 if (driver)
210 driver->setNumericalPrecisionPolicy(other->driver->numericalPrecisionPolicy());
211}
212
214{
215 if (driver != shared_null()->driver) {
216 delete driver;
217 driver = shared_null()->driver;
218 }
219}
220
243 = default;
244
426
445
477
485{
488
489 if (QFactoryLoader *fl = loader()) {
490 typedef QMultiMap<int, QString> PluginKeyMap;
491
492 const PluginKeyMap keyMap = fl->keyMap();
493 for (const QString &val : keyMap) {
494 if (!list.contains(val))
495 list << val;
496 }
497 }
498
499 QtSqlGlobals *sqlGlobals = s_sqlGlobals();
500 QReadLocker locker(&sqlGlobals->lock);
501 const auto &dict = sqlGlobals->registeredDrivers;
502 for (const auto &[k, _] : dict.asKeyValueRange()) {
503 if (!list.contains(k))
504 list << k;
505 }
506
507 return list;
508}
509
524{
526 QtSqlGlobals *sqlGlobals = s_sqlGlobals();
527 QWriteLocker locker(&sqlGlobals->lock);
528 delete sqlGlobals->registeredDrivers.take(name);
529 if (creator)
530 sqlGlobals->registeredDrivers.insert(name, creator);
531}
532
542bool QSqlDatabase::contains(const QString& connectionName)
543{
545 return s_sqlGlobals()->connectionExists(connectionName);
546}
547
556{
558 return s_sqlGlobals()->connectionNames();
559}
560
593
601 : d(new QSqlDatabasePrivate(driver))
602{
603}
604
611 : d(QSqlDatabasePrivate::shared_null())
612{
613 d->ref.ref();
614}
615
620{
621 d = other.d;
622 d->ref.ref();
623}
624
629{
630 qAtomicAssign(d, other.d);
631 return *this;
632}
633
641{
643 drvName = type;
644
645 if (!driver) {
646 QtSqlGlobals *sqlGlobals = s_sqlGlobals();
647 QReadLocker locker(&sqlGlobals->lock);
648 const auto &dict = sqlGlobals->registeredDrivers;
649 auto it = dict.find(type);
650 if (it != dict.end())
651 driver = it.value()->createObject();
652 }
653
654 if (!driver && loader())
655 driver = qLoadPlugin<QSqlDriver, QSqlDriverPlugin>(loader(), type);
656
657 if (!driver) {
658 qCWarning(lcSqlDb, "QSqlDatabase: %ls driver not loaded", qUtf16Printable(type));
659 qCWarning(lcSqlDb, "QSqlDatabase: available drivers: %ls",
661 if (QCoreApplication::instance() == nullptr)
662 qCWarning(lcSqlDb, "QSqlDatabase: an instance of QCoreApplication is required for loading driver plugins");
663 driver = shared_null()->driver;
664 }
665}
666
677{
678 if (!d->ref.deref()) {
679 close();
680 delete d;
681 }
682}
683
693#if QT_DEPRECATED_SINCE(6, 6)
694QSqlQuery QSqlDatabase::exec(const QString & query) const
695{
697 if (!query.isEmpty()) {
698 r.exec(query);
699 d->driver->setLastError(r.lastError());
700 }
701 return r;
702}
703#endif
704
715{
716 return d->driver->open(d->dbname, d->uname, d->pword, d->hname,
717 d->port, d->connOptions);
718}
719
734bool QSqlDatabase::open(const QString& user, const QString& password)
735{
736 setUserName(user);
737 return d->driver->open(d->dbname, user, password, d->hname,
738 d->port, d->connOptions);
739}
740
752{
753 d->driver->close();
754}
755
762{
763 return d->driver->isOpen();
764}
765
773{
774 return d->driver->isOpenError();
775}
776
785{
787 return false;
788 return d->driver->beginTransaction();
789}
790
806{
808 return false;
809 return d->driver->commitTransaction();
810}
811
827{
829 return false;
830 return d->driver->rollbackTransaction();
831}
832
870{
871 if (isValid())
872 d->dbname = name;
873}
874
888{
889 if (isValid())
890 d->uname = name;
891}
892
910{
911 if (isValid())
912 d->pword = password;
913}
914
928{
929 if (isValid())
930 d->hname = host;
931}
932
946{
947 if (isValid())
948 d->port = port;
949}
950
958{
959 return d->dbname;
960}
961
968{
969 return d->uname;
970}
971
978{
979 return d->pword;
980}
981
988{
989 return d->hname;
990}
991
998{
999 return d->drvName;
1000}
1001
1009{
1010 return d->port;
1011}
1012
1021{
1022 return d->driver;
1023}
1024
1036{
1037 return d->driver->lastError();
1038}
1039
1040
1052
1066{
1067 return d->driver->primaryIndex(tablename);
1068}
1069
1070
1084{
1085 return d->driver->record(tablename);
1086}
1087
1088
1110{
1111 if (isValid())
1112 d->connOptions = options;
1113}
1114
1122{
1123 return d->connOptions;
1124}
1125
1134{
1135 return drivers().contains(name);
1136}
1137
1235
1243{
1244 return d->driver && d->driver != d->shared_null()->driver;
1245}
1246
1260{
1261 if (!other.isValid())
1262 return QSqlDatabase();
1263
1264 QSqlDatabase db(other.driverName());
1265 db.d->copy(other.d);
1267 return db;
1268}
1269
1288{
1290 return cloneDatabase(s_sqlGlobals()->connection(other), connectionName);
1291}
1292
1300{
1301 return d->connName;
1302}
1303
1326{
1327 if (driver())
1328 driver()->setNumericalPrecisionPolicy(precisionPolicy);
1329 d->precisionPolicy = precisionPolicy;
1330}
1331
1342
1360{
1361 if (auto drv = driver()) {
1363 // two instances are alive - the one here and the one in dbDict()
1364 if (d->ref.loadRelaxed() > 2) {
1365 qWarning("QSqlDatabasePrivate::moveToThread: connection '%ls' is still in use "
1366 "in the current thread.", qUtf16Printable(d->connName));
1367 return false;
1368 }
1369 return drv->moveToThread(targetThread);
1370 }
1371 }
1372 return false;
1373}
1374
1381{
1382 if (auto drv = driver())
1383 return drv->thread();
1384 return nullptr;
1385}
1386
1387
1388#ifndef QT_NO_DEBUG_STREAM
1390{
1391 QDebugStateSaver saver(dbg);
1392 dbg.nospace();
1393 dbg.noquote();
1394 if (!d.isValid()) {
1395 dbg << "QSqlDatabase(invalid)";
1396 return dbg;
1397 }
1398
1399 dbg << "QSqlDatabase(driver=\"" << d.driverName() << "\", database=\""
1400 << d.databaseName() << "\", host=\"" << d.hostName() << "\", port=" << d.port()
1401 << ", user=\"" << d.userName() << "\", open=" << d.isOpen() << ')';
1402 return dbg;
1403}
1404#endif
1405
1407
1408#include "moc_qsqldatabase.cpp"
\inmodule QtCore
Definition qatomic.h:112
bool ref() noexcept
bool deref() noexcept
T loadRelaxed() const noexcept
static QCoreApplication * instance() noexcept
Returns a pointer to the application's QCoreApplication (or QGuiApplication/QApplication) instance.
\inmodule QtCore
\inmodule QtCore
QThread * thread() const
Returns the thread in which the object lives.
Definition qobject.cpp:1598
bool moveToThread(QThread *thread QT6_DECL_NEW_OVERLOAD_TAIL)
Changes the thread affinity for this object and its children and returns true on success.
Definition qobject.cpp:1643
\inmodule QtCore
\inmodule QtCore
iterator end()
Definition qset.h:140
iterator find(const T &value)
Definition qset.h:159
static QSqlDatabasePrivate * shared_null()
void init(const QString &type)
QSqlDatabasePrivate(QSqlDriver *dr)
static QSqlDatabase database(const QString &name, bool open)
static void removeDatabase(const QString &name)
static void invalidateDb(const QSqlDatabase &db, const QString &name, bool doWarn=true)
QSql::NumericalPrecisionPolicy precisionPolicy
static void addDatabase(const QSqlDatabase &db, const QString &name)
void copy(const QSqlDatabasePrivate *other)
The QSqlDatabase class handles a connection to a database.
bool isValid() const
Returns true if the QSqlDatabase has a valid driver.
void close()
Closes the database connection, freeing any resources acquired, and invalidating any existing QSqlQue...
static bool contains(const QString &connectionName=QLatin1StringView(defaultConnection))
\threadsafe
QString driverName() const
Returns the connection's driver name.
int port() const
Returns the connection's port number.
bool open()
Executes a SQL statement on the database and returns a QSqlQuery object.
QSqlIndex primaryIndex(const QString &tablename) const
Returns the primary index for table tablename.
void setDatabaseName(const QString &name)
Sets the connection's database name to name.
QString connectionName() const
Returns the connection name, which may be empty.
static QStringList connectionNames()
\threadsafe
QSqlDriver * driver() const
Returns the database driver used to access the database connection.
QString hostName() const
Returns the connection's host name; it may be empty.
bool isOpen() const
Returns true if the database connection is currently open; otherwise returns false.
QString connectOptions() const
Returns the connection options string used for this connection.
bool transaction()
Begins a transaction on the database if the driver supports transactions.
static const char * defaultConnection
void setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy precisionPolicy)
Sets \l numericalPrecisionPolicy to precisionPolicy.
QString password() const
Returns the connection's password.
bool moveToThread(QThread *targetThread)
QSqlRecord record(const QString &tablename) const
Returns a QSqlRecord populated with the names of all the fields in the table (or view) called tablena...
static void removeDatabase(const QString &connectionName)
\threadsafe
QSqlDatabase & operator=(const QSqlDatabase &other)
Assigns other to this object.
static QSqlDatabase addDatabase(const QString &type, const QString &connectionName=QLatin1StringView(defaultConnection))
\threadsafe
QSql::NumericalPrecisionPolicy numericalPrecisionPolicy
void setPassword(const QString &password)
Sets the connection's password to password.
bool rollback()
Rolls back a transaction on the database, if the driver supports transactions and a transaction() has...
QStringList tables(QSql::TableType type=QSql::Tables) const
Returns a list of the database's tables, system tables and views, as specified by the parameter type.
bool isOpenError() const
Returns true if there was an error opening the database connection; otherwise returns false.
QSqlDatabase()
Creates an empty, invalid QSqlDatabase object.
static QSqlDatabase database(const QString &connectionName=QLatin1StringView(defaultConnection), bool open=true)
\threadsafe
bool commit()
Commits a transaction to the database if the driver supports transactions and a transaction() has bee...
static QSqlDatabase cloneDatabase(const QSqlDatabase &other, const QString &connectionName)
Clones the database connection other and stores it as connectionName.
void setUserName(const QString &name)
Sets the connection's user name to name.
QString userName() const
Returns the connection's user name; it may be empty.
static bool isDriverAvailable(const QString &name)
Returns true if a driver called name is available; otherwise returns false.
static void registerSqlDriver(const QString &name, QSqlDriverCreatorBase *creator)
[2]
void setConnectOptions(const QString &options=QString())
Sets database-specific options.
QString databaseName() const
Returns the connection's database name, which may be empty.
QThread * currentThread() const
QSqlError lastError() const
Returns information about the last error that occurred on the database.
void setHostName(const QString &host)
Sets the connection's host name to host.
void setPort(int p)
Sets the connection's port number to port.
static QStringList drivers()
Returns a list of all the available database drivers.
~QSqlDatabase()
Destroys the object and frees any allocated resources.
The QSqlDriverCreatorBase class is the base class for SQL driver factories.
virtual ~QSqlDriverCreatorBase()
Destroys the SQL driver creator object.
The QSqlDriver class is an abstract base class for accessing specific SQL databases.
Definition qsqldriver.h:26
virtual bool commitTransaction()
This function is called to commit a transaction.
virtual QSqlResult * createResult() const =0
Creates an empty SQL result on the database.
void setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy precisionPolicy)
Sets \l numericalPrecisionPolicy to precisionPolicy.
virtual QSqlIndex primaryIndex(const QString &tableName) const
Returns the primary index for table tableName.
virtual bool beginTransaction()
This function is called to begin a transaction.
QSqlError lastError() const
Returns a QSqlError object which contains information about the last error that occurred on the datab...
virtual QSqlRecord record(const QString &tableName) const
Returns a QSqlRecord populated with the names of the fields in table tableName.
virtual bool rollbackTransaction()
This function is called to rollback a transaction.
virtual void close()=0
Derived classes must reimplement this pure virtual function in order to close the database connection...
bool isOpenError() const
Returns true if the there was an error opening the database connection; otherwise returns false.
virtual void setLastError(const QSqlError &e)
This function is used to set the value of the last error, error, that occurred on the database.
virtual bool open(const QString &db, const QString &user=QString(), const QString &password=QString(), const QString &host=QString(), int port=-1, const QString &connOpts=QString())=0
Derived classes must reimplement this pure virtual function to open a database connection on database...
virtual bool isOpen() const
Returns true if the database connection is open; otherwise returns false.
QSql::NumericalPrecisionPolicy numericalPrecisionPolicy
Definition qsqldriver.h:58
virtual bool hasFeature(DriverFeature f) const =0
Returns true if the driver supports feature feature; otherwise returns false.
virtual QStringList tables(QSql::TableType tableType) const
Returns a list of the names of the tables in the database.
The QSqlError class provides SQL database error information.
Definition qsqlerror.h:17
The QSqlIndex class provides functions to manipulate and describe database indexes.
Definition qsqlindex.h:18
The QSqlQuery class provides a means of executing and manipulating SQL statements.
Definition qsqlquery.h:24
The QSqlRecord class encapsulates a database record.
Definition qsqlrecord.h:20
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QThread * currentThread()
Definition qthread.cpp:1039
\inmodule QtCore
qDeleteAll(list.begin(), list.end())
QSet< QString >::iterator it
NumericalPrecisionPolicy
Definition qtsqlglobal.h:43
@ LowPrecisionDouble
Definition qtsqlglobal.h:46
Combined button and popup list for selecting options.
Definition qcompare.h:63
static jboolean copy(JNIEnv *, jobject)
#define Q_APPLICATION_STATIC(TYPE, NAME,...)
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
DBusConnection * connection
EGLOutputPortEXT port
#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS)
#define qWarning
Definition qlogging.h:166
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
GLsizei const GLfloat * v
[13]
GLuint64 key
GLboolean r
[2]
GLenum type
GLint ref
GLuint name
GLfloat n
GLenum query
GLuint GLfloat * val
QDebug operator<<(QDebug dbg, const QSqlDatabase &d)
#define CHECK_QCOREAPPLICATION
#define CHECK_QCOREAPPLICATION_RETVAL
#define QSqlDriverFactoryInterface_iid
#define qUtf16Printable(string)
Definition qstring.h:1543
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
static const struct @450 keyMap[]
QList< int > list
[14]
file open(QIODevice::ReadOnly)
QObject::connect nullptr
QMimeDatabase db
[0]
QReadWriteLock lock
[0]
QSharedPointer< T > other(t)
[5]
QItemEditorCreatorBase * creator
void removeDatabase()
bool contains(const AT &t) const noexcept
Definition qlist.h:45
QHash< QString, QSqlDriverCreatorBase * > registeredDrivers
bool connectionExists(const QString &key) const
QHash< QString, QSqlDatabase > connections
QSqlDatabase connection(const QString &key) const