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
424
443
475
483{
486
487 if (QFactoryLoader *fl = loader()) {
488 typedef QMultiMap<int, QString> PluginKeyMap;
489
490 const PluginKeyMap keyMap = fl->keyMap();
491 for (const QString &val : keyMap) {
492 if (!list.contains(val))
493 list << val;
494 }
495 }
496
497 QtSqlGlobals *sqlGlobals = s_sqlGlobals();
498 QReadLocker locker(&sqlGlobals->lock);
499 const auto &dict = sqlGlobals->registeredDrivers;
500 for (const auto &[k, _] : dict.asKeyValueRange()) {
501 if (!list.contains(k))
502 list << k;
503 }
504
505 return list;
506}
507
522{
524 QtSqlGlobals *sqlGlobals = s_sqlGlobals();
525 QWriteLocker locker(&sqlGlobals->lock);
526 delete sqlGlobals->registeredDrivers.take(name);
527 if (creator)
528 sqlGlobals->registeredDrivers.insert(name, creator);
529}
530
540bool QSqlDatabase::contains(const QString& connectionName)
541{
543 return s_sqlGlobals()->connectionExists(connectionName);
544}
545
554{
556 return s_sqlGlobals()->connectionNames();
557}
558
591
599 : d(new QSqlDatabasePrivate(driver))
600{
601}
602
609 : d(QSqlDatabasePrivate::shared_null())
610{
611 d->ref.ref();
612}
613
618{
619 d = other.d;
620 d->ref.ref();
621}
622
627{
628 qAtomicAssign(d, other.d);
629 return *this;
630}
631
639{
641 drvName = type;
642
643 if (!driver) {
644 QtSqlGlobals *sqlGlobals = s_sqlGlobals();
645 QReadLocker locker(&sqlGlobals->lock);
646 const auto &dict = sqlGlobals->registeredDrivers;
647 auto it = dict.find(type);
648 if (it != dict.end())
649 driver = it.value()->createObject();
650 }
651
652 if (!driver && loader())
653 driver = qLoadPlugin<QSqlDriver, QSqlDriverPlugin>(loader(), type);
654
655 if (!driver) {
656 qCWarning(lcSqlDb, "QSqlDatabase: %ls driver not loaded", qUtf16Printable(type));
657 qCWarning(lcSqlDb, "QSqlDatabase: available drivers: %ls",
659 if (QCoreApplication::instance() == nullptr)
660 qCWarning(lcSqlDb, "QSqlDatabase: an instance of QCoreApplication is required for loading driver plugins");
661 driver = shared_null()->driver;
662 }
663}
664
675{
676 if (!d->ref.deref()) {
677 close();
678 delete d;
679 }
680}
681
691#if QT_DEPRECATED_SINCE(6, 6)
692QSqlQuery QSqlDatabase::exec(const QString & query) const
693{
695 if (!query.isEmpty()) {
696 r.exec(query);
697 d->driver->setLastError(r.lastError());
698 }
699 return r;
700}
701#endif
702
713{
714 return d->driver->open(d->dbname, d->uname, d->pword, d->hname,
715 d->port, d->connOptions);
716}
717
732bool QSqlDatabase::open(const QString& user, const QString& password)
733{
734 setUserName(user);
735 return d->driver->open(d->dbname, user, password, d->hname,
736 d->port, d->connOptions);
737}
738
750{
751 d->driver->close();
752}
753
760{
761 return d->driver->isOpen();
762}
763
771{
772 return d->driver->isOpenError();
773}
774
783{
785 return false;
786 return d->driver->beginTransaction();
787}
788
804{
806 return false;
807 return d->driver->commitTransaction();
808}
809
825{
827 return false;
828 return d->driver->rollbackTransaction();
829}
830
868{
869 if (isValid())
870 d->dbname = name;
871}
872
886{
887 if (isValid())
888 d->uname = name;
889}
890
908{
909 if (isValid())
910 d->pword = password;
911}
912
926{
927 if (isValid())
928 d->hname = host;
929}
930
944{
945 if (isValid())
946 d->port = port;
947}
948
956{
957 return d->dbname;
958}
959
966{
967 return d->uname;
968}
969
976{
977 return d->pword;
978}
979
986{
987 return d->hname;
988}
989
996{
997 return d->drvName;
998}
999
1007{
1008 return d->port;
1009}
1010
1019{
1020 return d->driver;
1021}
1022
1034{
1035 return d->driver->lastError();
1036}
1037
1038
1050
1064{
1065 return d->driver->primaryIndex(tablename);
1066}
1067
1068
1082{
1083 return d->driver->record(tablename);
1084}
1085
1086
1108{
1109 if (isValid())
1110 d->connOptions = options;
1111}
1112
1120{
1121 return d->connOptions;
1122}
1123
1132{
1133 return drivers().contains(name);
1134}
1135
1233
1241{
1242 return d->driver && d->driver != d->shared_null()->driver;
1243}
1244
1258{
1259 if (!other.isValid())
1260 return QSqlDatabase();
1261
1262 QSqlDatabase db(other.driverName());
1263 db.d->copy(other.d);
1265 return db;
1266}
1267
1286{
1288 return cloneDatabase(s_sqlGlobals()->connection(other), connectionName);
1289}
1290
1298{
1299 return d->connName;
1300}
1301
1324{
1325 if (driver())
1326 driver()->setNumericalPrecisionPolicy(precisionPolicy);
1327 d->precisionPolicy = precisionPolicy;
1328}
1329
1340
1358{
1359 if (auto drv = driver()) {
1361 // two instances are alive - the one here and the one in dbDict()
1362 if (d->ref.loadRelaxed() > 2) {
1363 qWarning("QSqlDatabasePrivate::moveToThread: connection '%ls' is still in use "
1364 "in the current thread.", qUtf16Printable(d->connName));
1365 return false;
1366 }
1367 return drv->moveToThread(targetThread);
1368 }
1369 }
1370 return false;
1371}
1372
1379{
1380 if (auto drv = driver())
1381 return drv->thread();
1382 return nullptr;
1383}
1384
1385
1386#ifndef QT_NO_DEBUG_STREAM
1388{
1389 QDebugStateSaver saver(dbg);
1390 dbg.nospace();
1391 dbg.noquote();
1392 if (!d.isValid()) {
1393 dbg << "QSqlDatabase(invalid)";
1394 return dbg;
1395 }
1396
1397 dbg << "QSqlDatabase(driver=\"" << d.driverName() << "\", database=\""
1398 << d.databaseName() << "\", host=\"" << d.hostName() << "\", port=" << d.port()
1399 << ", user=\"" << d.userName() << "\", open=" << d.isOpen() << ')';
1400 return dbg;
1401}
1402#endif
1403
1405
1406#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.
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