Qt 6.x
The Qt SDK
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 "qdebug.h"
7#include "qcoreapplication.h"
8#include "qreadwritelock.h"
9#include "qsqldriver.h"
10#include "qsqldriverplugin.h"
11#include "qsqlindex.h"
12#include "QtCore/qapplicationstatic.h"
13#include "private/qfactoryloader_p.h"
14#include "private/qsqlnulldriver_p.h"
15#include "qhash.h"
16#include "qthread.h"
17
19
20using namespace Qt::StringLiterals;
21
23 (QSqlDriverFactoryInterface_iid, "/sqldrivers"_L1))
24
25const char *QSqlDatabase::defaultConnection = "qt_sql_default_connection";
26
27class QConnectionDict: public QHash<QString, QSqlDatabase>
28{
29public:
31 {
32 QReadLocker locker(&lock);
33 return value(key);
34 }
35 bool contains_ts(const QString &key) const
36 {
37 QReadLocker locker(&lock);
38 return contains(key);
39 }
41 {
42 QReadLocker locker(&lock);
43 return keys();
44 }
45
47};
49
50namespace {
51 struct DriverDict : public QHash<QString, QSqlDriverCreatorBase*>
52 {
53 ~DriverDict();
54 };
55}
56Q_APPLICATION_STATIC(DriverDict, qtDriverDict)
57
59{
60public:
62 ref(1),
63 driver(dr),
64 port(-1)
65 {
66 precisionPolicy = QSql::LowPrecisionDouble;
67 }
70 void init(const QString& type);
71 void copy(const QSqlDatabasePrivate *other);
72 void disable();
73
81 int port;
85
86 static QSqlDatabasePrivate *shared_null();
87 static QSqlDatabase database(const QString& name, bool open);
88 static void addDatabase(const QSqlDatabase &db, const QString & name);
89 static void removeDatabase(const QString& name);
90 static void invalidateDb(const QSqlDatabase &db, const QString &name, bool doWarn = true);
91 static DriverDict &driverDict();
92 static void cleanConnections();
93};
94
96{
97 dbname = other.dbname;
98 uname = other.uname;
99 pword = other.pword;
100 hname = other.hname;
101 drvName = other.drvName;
102 port = other.port;
103 connOptions = other.connOptions;
104 driver = other.driver;
105 precisionPolicy = other.precisionPolicy;
106 if (driver)
107 driver->setNumericalPrecisionPolicy(other.driver->numericalPrecisionPolicy());
108}
109
111{
112 if (driver != shared_null()->driver)
113 delete driver;
114}
115
117{
118 QConnectionDict *dict = dbDict();
119 Q_ASSERT(dict);
120 QWriteLocker locker(&dict->lock);
121
123 while (it != dict->end()) {
124 invalidateDb(it.value(), it.key(), false);
125 ++it;
126 }
127 dict->clear();
128}
129
130DriverDict::~DriverDict()
131{
132 qDeleteAll(*this);
134}
135
137{
138 return *qtDriverDict();
139}
140
142{
143 static QSqlNullDriver dr;
144 static QSqlDatabasePrivate n(&dr);
145 return &n;
146}
147
149{
150 if (db.d->ref.loadRelaxed() != 1 && doWarn) {
151 qWarning("QSqlDatabasePrivate::removeDatabase: connection '%s' is still in use, "
152 "all queries will cease to work.", name.toLocal8Bit().constData());
153 db.d->disable();
154 db.d->connName.clear();
155 }
156}
157
159{
160 QConnectionDict *dict = dbDict();
161 Q_ASSERT(dict);
162 QWriteLocker locker(&dict->lock);
163
164 if (!dict->contains(name))
165 return;
166
167 invalidateDb(dict->take(name), name);
168}
169
171{
172 QConnectionDict *dict = dbDict();
173 Q_ASSERT(dict);
174 QWriteLocker locker(&dict->lock);
175
176 if (dict->contains(name)) {
177 invalidateDb(dict->take(name), name);
178 qWarning("QSqlDatabasePrivate::addDatabase: duplicate connection name '%s', old "
179 "connection removed.", name.toLocal8Bit().data());
180 }
181 dict->insert(name, db);
182 db.d->connName = name;
183}
184
188{
189 const QConnectionDict *dict = dbDict();
190 Q_ASSERT(dict);
191
192 QSqlDatabase db = dict->value_ts(name);
193 if (!db.isValid())
194 return db;
195 if (db.driver()->thread() != QThread::currentThread()) {
196 qWarning("QSqlDatabasePrivate::database: requested database does not belong to the calling thread.");
197 return QSqlDatabase();
198 }
199
200 if (open && !db.isOpen()) {
201 if (!db.open())
202 qWarning() << "QSqlDatabasePrivate::database: unable to open database:" << db.lastError().text();
203
204 }
205 return db;
206}
207
208
213{
214 dbname = other->dbname;
215 uname = other->uname;
216 pword = other->pword;
217 hname = other->hname;
218 drvName = other->drvName;
219 port = other->port;
220 connOptions = other->connOptions;
221 precisionPolicy = other->precisionPolicy;
222 if (driver)
223 driver->setNumericalPrecisionPolicy(other->driver->numericalPrecisionPolicy());
224}
225
227{
228 if (driver != shared_null()->driver) {
229 delete driver;
231 }
232}
233
428{
431 return db;
432}
433
449{
451}
452
480void QSqlDatabase::removeDatabase(const QString& connectionName)
481{
483}
484
492{
494
495 if (QFactoryLoader *fl = loader()) {
496 typedef QMultiMap<int, QString> PluginKeyMap;
497
498 const PluginKeyMap keyMap = fl->keyMap();
499 for (const QString &val : keyMap) {
500 if (!list.contains(val))
501 list << val;
502 }
503 }
504
505 QReadLocker locker(&dbDict()->lock);
506 const DriverDict &dict = QSqlDatabasePrivate::driverDict();
507 for (const auto &[k, _] : dict.asKeyValueRange()) {
508 if (!list.contains(k))
509 list << k;
510 }
511
512 return list;
513}
514
529{
530 QWriteLocker locker(&dbDict()->lock);
532 if (creator)
534}
535
545bool QSqlDatabase::contains(const QString& connectionName)
546{
547 return dbDict()->contains_ts(connectionName);
548}
549
558{
559 return dbDict()->keys_ts();
560}
561
591{
592 d->init(type);
593}
594
602 : d(new QSqlDatabasePrivate(driver))
603{
604}
605
612 : d(QSqlDatabasePrivate::shared_null())
613{
614 d->ref.ref();
615}
616
621{
622 d = other.d;
623 d->ref.ref();
624}
625
630{
631 qAtomicAssign(d, other.d);
632 return *this;
633}
634
642{
643 drvName = type;
644
645 if (!driver) {
646 QReadLocker locker(&dbDict()->lock);
647 const DriverDict &dict = QSqlDatabasePrivate::driverDict();
648 for (DriverDict::const_iterator it = dict.constBegin();
649 it != dict.constEnd() && !driver; ++it) {
650 if (type == it.key()) {
651 driver = ((QSqlDriverCreatorBase*)(*it))->createObject();
652 }
653 }
654 }
655
656 if (!driver && loader())
657 driver = qLoadPlugin<QSqlDriver, QSqlDriverPlugin>(loader(), type);
658
659 if (!driver) {
660 qWarning("QSqlDatabase: %s driver not loaded", type.toLatin1().data());
661 qWarning("QSqlDatabase: available drivers: %s",
662 QSqlDatabase::drivers().join(u' ').toLatin1().data());
663 if (QCoreApplication::instance() == nullptr)
664 qWarning("QSqlDatabase: an instance of QCoreApplication is required for loading driver plugins");
666 }
667}
668
679{
680 if (!d->ref.deref()) {
681 close();
682 delete d;
683 }
684}
685
695#if QT_DEPRECATED_SINCE(6, 6)
696QSqlQuery QSqlDatabase::exec(const QString & query) const
697{
699 if (!query.isEmpty()) {
700 r.exec(query);
701 d->driver->setLastError(r.lastError());
702 }
703 return r;
704}
705#endif
706
717{
718 return d->driver->open(d->dbname, d->uname, d->pword, d->hname,
719 d->port, d->connOptions);
720}
721
736bool QSqlDatabase::open(const QString& user, const QString& password)
737{
738 setUserName(user);
739 return d->driver->open(d->dbname, user, password, d->hname,
740 d->port, d->connOptions);
741}
742
754{
755 d->driver->close();
756}
757
764{
765 return d->driver->isOpen();
766}
767
775{
776 return d->driver->isOpenError();
777}
778
787{
789 return false;
790 return d->driver->beginTransaction();
791}
792
808{
810 return false;
811 return d->driver->commitTransaction();
812}
813
829{
831 return false;
832 return d->driver->rollbackTransaction();
833}
834
872{
873 if (isValid())
874 d->dbname = name;
875}
876
890{
891 if (isValid())
892 d->uname = name;
893}
894
912{
913 if (isValid())
914 d->pword = password;
915}
916
930{
931 if (isValid())
932 d->hname = host;
933}
934
948{
949 if (isValid())
950 d->port = port;
951}
952
960{
961 return d->dbname;
962}
963
970{
971 return d->uname;
972}
973
980{
981 return d->pword;
982}
983
990{
991 return d->hname;
992}
993
1000{
1001 return d->drvName;
1002}
1003
1011{
1012 return d->port;
1013}
1014
1023{
1024 return d->driver;
1025}
1026
1038{
1039 return d->driver->lastError();
1040}
1041
1042
1051{
1052 return d->driver->tables(type);
1053}
1054
1068{
1069 return d->driver->primaryIndex(tablename);
1070}
1071
1072
1086{
1087 return d->driver->record(tablename);
1088}
1089
1090
1112{
1113 if (isValid())
1114 d->connOptions = options;
1115}
1116
1124{
1125 return d->connOptions;
1126}
1127
1136{
1137 return drivers().contains(name);
1138}
1139
1231{
1234 return db;
1235}
1236
1244{
1245 return d->driver && d->driver != d->shared_null()->driver;
1246}
1247
1261{
1262 if (!other.isValid())
1263 return QSqlDatabase();
1264
1265 QSqlDatabase db(other.driverName());
1266 db.d->copy(other.d);
1268 return db;
1269}
1270
1289{
1290 const QConnectionDict *dict = dbDict();
1291 Q_ASSERT(dict);
1292
1294}
1295
1305{
1306 return d->connName;
1307}
1308
1327{
1328 if (driver())
1329 driver()->setNumericalPrecisionPolicy(precisionPolicy);
1330 d->precisionPolicy = precisionPolicy;
1331}
1332
1342{
1343 if (driver())
1344 return driver()->numericalPrecisionPolicy();
1345 else
1346 return d->precisionPolicy;
1347}
1348
1349
1350#ifndef QT_NO_DEBUG_STREAM
1352{
1353 QDebugStateSaver saver(dbg);
1354 dbg.nospace();
1355 dbg.noquote();
1356 if (!d.isValid()) {
1357 dbg << "QSqlDatabase(invalid)";
1358 return dbg;
1359 }
1360
1361 dbg << "QSqlDatabase(driver=\"" << d.driverName() << "\", database=\""
1362 << d.databaseName() << "\", host=\"" << d.hostName() << "\", port=" << d.port()
1363 << ", user=\"" << d.userName() << "\", open=" << d.isOpen() << ')';
1364 return dbg;
1365}
1366#endif
1367
\inmodule QtCore
Definition qatomic.h:112
bool ref() noexcept
bool deref() noexcept
QStringList keys_ts() const
bool contains_ts(const QString &key) const
QSqlDatabase value_ts(const QString &key) const
QReadWriteLock lock
static QCoreApplication * instance() noexcept
Returns a pointer to the application's QCoreApplication (or QGuiApplication/QApplication) instance.
\inmodule QtCore
\inmodule QtCore
\inmodule QtCore
Definition qhash.h:818
iterator begin()
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in the hash.
Definition qhash.h:1202
T take(const Key &key)
Removes the item with the key from the hash and returns the value associated with it.
Definition qhash.h:975
QList< QString > keys() const
Returns a list containing all the keys in the hash, in an arbitrary order.
Definition qhash.h:1076
bool contains(const QString &key) const noexcept
Returns true if the hash contains an item with the key; otherwise returns false.
Definition qhash.h:991
iterator end() noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last ...
Definition qhash.h:1206
void clear() noexcept(std::is_nothrow_destructible< Node >::value)
Removes all items from the hash and frees up all memory used by it.
Definition qhash.h:949
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1283
\inmodule QtCore
\inmodule QtCore
static QSqlDatabasePrivate * shared_null()
void init(const QString &type)
static DriverDict & driverDict()
QSqlDatabasePrivate(QSqlDriver *dr)
static QSqlDatabase database(const QString &name, bool open)
static void cleanConnections()
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
static QStringList connectionNames()
\threadsafe
QSql::NumericalPrecisionPolicy numericalPrecisionPolicy() const
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)
QString password() const
Returns the connection's password.
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
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.
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:25
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)
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.
QSql::NumericalPrecisionPolicy numericalPrecisionPolicy() const
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.
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:16
The QSqlQuery class provides a means of executing and manipulating SQL statements.
Definition qsqlquery.h:23
The QSqlRecord class encapsulates a database record.
Definition qsqlrecord.h:20
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static QThread * currentThread()
Definition qthread.cpp:966
\inmodule QtCore
qDeleteAll(list.begin(), list.end())
QSet< QString >::iterator it
NumericalPrecisionPolicy
Definition qtsqlglobal.h:44
@ LowPrecisionDouble
Definition qtsqlglobal.h:47
Combined button and popup list for selecting options.
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
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
EGLOutputPortEXT port
#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS)
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define qWarning
Definition qlogging.h:162
GLuint64 key
GLboolean r
[2]
GLenum type
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint ref
GLuint name
GLfloat n
GLenum query
GLuint GLfloat * val
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QDebug operator<<(QDebug dbg, const QSqlDatabase &d)
#define QSqlDriverFactoryInterface_iid
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
static const struct @437 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:44