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 | |
19 | QT_BEGIN_NAMESPACE |
20 | |
21 | static Q_LOGGING_CATEGORY(lcSqlDb, "qt.sql.qsqldatabase") |
22 | |
23 | using 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 | |
36 | Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, |
37 | (QSqlDriverFactoryInterface_iid, "/sqldrivers"_L1)) |
38 | |
39 | const char *QSqlDatabase::defaultConnection = "qt_sql_default_connection"; |
40 | |
41 | namespace { |
42 | struct QtSqlGlobals |
43 | { |
44 | ~QtSqlGlobals(); |
45 | QSqlDatabase connection(const QString &key) const |
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 | } |
55 | QStringList connectionNames() const |
56 | { |
57 | QReadLocker locker(&lock); |
58 | return connections.keys(); |
59 | } |
60 | mutable QReadWriteLock lock; |
61 | QHash<QString, QSqlDriverCreatorBase*> registeredDrivers; |
62 | QHash<QString, QSqlDatabase> connections; |
63 | }; |
64 | } |
65 | Q_APPLICATION_STATIC(QtSqlGlobals, s_sqlGlobals) |
66 | |
67 | class QSqlDatabasePrivate |
68 | { |
69 | public: |
70 | QSqlDatabasePrivate(QSqlDriver *dr): |
71 | ref(1), |
72 | driver(dr), |
73 | port(-1) |
74 | { |
75 | precisionPolicy = QSql::LowPrecisionDouble; |
76 | } |
77 | QSqlDatabasePrivate(const QSqlDatabasePrivate &other); |
78 | ~QSqlDatabasePrivate(); |
79 | void init(const QString& type); |
80 | void copy(const QSqlDatabasePrivate *other); |
81 | void disable(); |
82 | |
83 | QAtomicInt ref; |
84 | QSqlDriver* driver; |
85 | QString dbname; |
86 | QString uname; |
87 | QString pword; |
88 | QString hname; |
89 | QString drvName; |
90 | int port; |
91 | QString connOptions; |
92 | QString connName; |
93 | QSql::NumericalPrecisionPolicy precisionPolicy; |
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 | |
102 | QSqlDatabasePrivate::QSqlDatabasePrivate(const QSqlDatabasePrivate &other) : ref(1) |
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 | |
117 | QSqlDatabasePrivate::~QSqlDatabasePrivate() |
118 | { |
119 | if (driver != shared_null()->driver) |
120 | delete driver; |
121 | } |
122 | |
123 | QtSqlGlobals::~QtSqlGlobals() |
124 | { |
125 | qDeleteAll(c: registeredDrivers); |
126 | for (const auto &[k, v] : std::as_const(t&: connections).asKeyValueRange()) |
127 | QSqlDatabasePrivate::invalidateDb(db: v, name: k, doWarn: false); |
128 | } |
129 | |
130 | QSqlDatabasePrivate *QSqlDatabasePrivate::shared_null() |
131 | { |
132 | static QSqlNullDriver dr; |
133 | static QSqlDatabasePrivate n(&dr); |
134 | return &n; |
135 | } |
136 | |
137 | void QSqlDatabasePrivate::invalidateDb(const QSqlDatabase &db, const QString &name, bool doWarn) |
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 | |
147 | void QSqlDatabasePrivate::removeDatabase(const QString &name) |
148 | { |
149 | CHECK_QCOREAPPLICATION |
150 | QtSqlGlobals *sqlGlobals = s_sqlGlobals(); |
151 | QWriteLocker locker(&sqlGlobals->lock); |
152 | |
153 | if (!sqlGlobals->connections.contains(key: name)) |
154 | return; |
155 | |
156 | invalidateDb(db: sqlGlobals->connections.take(key: name), name); |
157 | } |
158 | |
159 | void QSqlDatabasePrivate::addDatabase(const QSqlDatabase &db, const QString &name) |
160 | { |
161 | CHECK_QCOREAPPLICATION |
162 | QtSqlGlobals *sqlGlobals = s_sqlGlobals(); |
163 | QWriteLocker locker(&sqlGlobals->lock); |
164 | |
165 | if (sqlGlobals->connections.contains(key: name)) { |
166 | invalidateDb(db: sqlGlobals->connections.take(key: name), name); |
167 | qCWarning(lcSqlDb, "QSqlDatabasePrivate::addDatabase: duplicate connection name '%ls', old " |
168 | "connection removed.", qUtf16Printable(name)); |
169 | } |
170 | sqlGlobals->connections.insert(key: name, value: db); |
171 | db.d->connName = name; |
172 | } |
173 | |
174 | /*! \internal |
175 | */ |
176 | QSqlDatabase QSqlDatabasePrivate::database(const QString& name, bool open) |
177 | { |
178 | CHECK_QCOREAPPLICATION_RETVAL |
179 | QSqlDatabase db = s_sqlGlobals()->connection(key: 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 | |
196 | /*! \internal |
197 | Copies the connection data from \a other. |
198 | */ |
199 | void QSqlDatabasePrivate::copy(const QSqlDatabasePrivate *other) |
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 | |
213 | void QSqlDatabasePrivate::disable() |
214 | { |
215 | if (driver != shared_null()->driver) { |
216 | delete driver; |
217 | driver = shared_null()->driver; |
218 | } |
219 | } |
220 | |
221 | /*! |
222 | \class QSqlDriverCreatorBase |
223 | \brief The QSqlDriverCreatorBase class is the base class for |
224 | SQL driver factories. |
225 | |
226 | \ingroup database |
227 | \inmodule QtSql |
228 | |
229 | Reimplement createObject() to return an instance of the specific |
230 | QSqlDriver subclass that you want to provide. |
231 | |
232 | See QSqlDatabase::registerSqlDriver() for details. |
233 | |
234 | \sa QSqlDriverCreator |
235 | */ |
236 | |
237 | /*! |
238 | \fn QSqlDriverCreatorBase::~QSqlDriverCreatorBase() |
239 | |
240 | Destroys the SQL driver creator object. |
241 | */ |
242 | QSqlDriverCreatorBase::~QSqlDriverCreatorBase() |
243 | = default; |
244 | |
245 | /*! |
246 | \fn QSqlDriver *QSqlDriverCreatorBase::createObject() const |
247 | |
248 | Reimplement this function to returns a new instance of a |
249 | QSqlDriver subclass. |
250 | */ |
251 | |
252 | /*! |
253 | \class QSqlDriverCreator |
254 | \brief The QSqlDriverCreator class is a template class that |
255 | provides a SQL driver factory for a specific driver type. |
256 | |
257 | \ingroup database |
258 | \inmodule QtSql |
259 | |
260 | QSqlDriverCreator<T> instantiates objects of type T, where T is a |
261 | QSqlDriver subclass. |
262 | |
263 | See QSqlDatabase::registerSqlDriver() for details. |
264 | */ |
265 | |
266 | /*! |
267 | \fn template <class T> QSqlDriver *QSqlDriverCreator<T>::createObject() const |
268 | \reimp |
269 | */ |
270 | |
271 | /*! |
272 | \class QSqlDatabase |
273 | \brief The QSqlDatabase class handles a connection to |
274 | a database. |
275 | |
276 | \ingroup database |
277 | |
278 | \inmodule QtSql |
279 | |
280 | The QSqlDatabase class provides an interface for accessing a |
281 | database through a connection. An instance of QSqlDatabase |
282 | represents the connection. The connection provides access to the |
283 | database via one of the \l{SQL Database Drivers#Supported |
284 | Databases} {supported database drivers}, which are derived from |
285 | QSqlDriver. Alternatively, you can subclass your own database |
286 | driver from QSqlDriver. See \l{How to Write Your Own Database |
287 | Driver} for more information. |
288 | A QSqlDatabase instance must only be accessed by the thread it |
289 | was created in. Therefore you have to make sure to create them |
290 | in the correct context. Alternatively you can change the context |
291 | with QSqlDatabase::moveToThread(). |
292 | |
293 | Create a connection (i.e., an instance of QSqlDatabase) by calling |
294 | one of the static addDatabase() functions, where you specify |
295 | \l{SQL Database Drivers#Supported Databases} {the driver or type |
296 | of driver} to use (depending on the type of database) |
297 | and a connection name. A connection is known by its own name, |
298 | \e{not} by the name of the database it connects to. You can have |
299 | multiple connections to one database. QSqlDatabase also supports |
300 | the concept of a \e{default} connection, which is the unnamed |
301 | connection. To create the default connection, don't pass the |
302 | connection name argument when you call addDatabase(). |
303 | Subsequently, the default connection will be assumed if you call |
304 | any static member function without specifying the connection name. |
305 | The following snippet shows how to create and open a default connection |
306 | to a PostgreSQL database: |
307 | |
308 | \snippet sqldatabase/sqldatabase.cpp 0 |
309 | |
310 | Once the QSqlDatabase object has been created, set the connection |
311 | parameters with setDatabaseName(), setUserName(), setPassword(), |
312 | setHostName(), setPort(), and setConnectOptions(). Then call |
313 | open() to activate the physical connection to the database. The |
314 | connection is not usable until you open it. |
315 | |
316 | The connection defined above will be the \e{default} connection, |
317 | because we didn't give a connection name to \l{QSqlDatabase::} |
318 | {addDatabase()}. Subsequently, you can get the default connection |
319 | by calling database() without the connection name argument: |
320 | |
321 | \snippet sqldatabase/sqldatabase.cpp 1 |
322 | |
323 | QSqlDatabase is a value class. Changes made to a database |
324 | connection via one instance of QSqlDatabase will affect other |
325 | instances of QSqlDatabase that represent the same connection. Use |
326 | cloneDatabase() to create an independent database connection based |
327 | on an existing one. |
328 | |
329 | \warning It is highly recommended that you do not keep a copy of the |
330 | QSqlDatabase around as a member of a class, as this will prevent the |
331 | instance from being correctly cleaned up on shutdown. If you need to |
332 | access an existing QSqlDatabase, it should be accessed with database(). |
333 | If you chose to have a QSqlDatabase member variable, this needs to be |
334 | deleted before the QCoreApplication instance is deleted, otherwise it |
335 | may lead to undefined behavior. |
336 | |
337 | If you create multiple database connections, specify a unique |
338 | connection name for each one, when you call addDatabase(). Use |
339 | database() with a connection name to get that connection. Use |
340 | removeDatabase() with a connection name to remove a connection. |
341 | QSqlDatabase outputs a warning if you try to remove a connection |
342 | referenced by other QSqlDatabase objects. Use contains() to see if |
343 | a given connection name is in the list of connections. |
344 | |
345 | \table |
346 | \header |
347 | \li {2,1}Some utility methods: |
348 | \row |
349 | \li tables() |
350 | \li returns the list of tables |
351 | \row |
352 | \li primaryIndex() |
353 | \li returns a table's primary index |
354 | \row |
355 | \li record() |
356 | \li returns meta-information about a table's fields |
357 | \row |
358 | \li transaction() |
359 | \li starts a transaction |
360 | \row |
361 | \li commit() |
362 | \li saves and completes a transaction |
363 | \row |
364 | \li rollback() |
365 | \li cancels a transaction |
366 | \row |
367 | \li hasFeature() |
368 | \li checks if a driver supports transactions |
369 | \row |
370 | \li lastError() |
371 | \li returns information about the last error |
372 | \row |
373 | \li drivers() |
374 | \li returns the names of the available SQL drivers |
375 | \row |
376 | \li isDriverAvailable() |
377 | \li checks if a particular driver is available |
378 | \row |
379 | \li registerSqlDriver() |
380 | \li registers a custom-made driver |
381 | \endtable |
382 | |
383 | \note When using transactions, you must start the |
384 | transaction before you create your query. |
385 | |
386 | \sa QSqlDriver, QSqlQuery, {Qt SQL}, {Threads and the SQL Module} |
387 | */ |
388 | |
389 | /*! \fn QSqlDatabase QSqlDatabase::addDatabase(const QString &type, const QString &connectionName) |
390 | \threadsafe |
391 | |
392 | Adds a database to the list of database connections using the |
393 | driver \a type and the connection name \a connectionName. If |
394 | there already exists a database connection called \a |
395 | connectionName, that connection is removed. |
396 | |
397 | The database connection is referred to by \a connectionName. The |
398 | newly added database connection is returned. |
399 | |
400 | If \a type is not available or could not be loaded, isValid() returns \c false. |
401 | |
402 | If \a connectionName is not specified, the new connection becomes |
403 | the default connection for the application, and subsequent calls |
404 | to database() without the connection name argument will return the |
405 | default connection. If a \a connectionName is provided here, use |
406 | database(\a connectionName) to retrieve the connection. |
407 | |
408 | \warning If you add a connection with the same name as an existing |
409 | connection, the new connection replaces the old one. If you call |
410 | this function more than once without specifying \a connectionName, |
411 | the default connection will be the one replaced. |
412 | |
413 | Before using the connection, it must be initialized. e.g., call |
414 | some or all of setDatabaseName(), setUserName(), setPassword(), |
415 | setHostName(), setPort(), and setConnectOptions(), and, finally, |
416 | open(). |
417 | |
418 | \sa database(), removeDatabase(), {Threads and the SQL Module} |
419 | */ |
420 | QSqlDatabase QSqlDatabase::addDatabase(const QString &type, const QString &connectionName) |
421 | { |
422 | QSqlDatabase db(type); |
423 | QSqlDatabasePrivate::addDatabase(db, name: connectionName); |
424 | return db; |
425 | } |
426 | |
427 | /*! |
428 | \threadsafe |
429 | |
430 | Returns the database connection called \a connectionName. The |
431 | database connection must have been previously added with |
432 | addDatabase(). If \a open is true (the default) and the database |
433 | connection is not already open it is opened now. If no \a |
434 | connectionName is specified the default connection is used. If \a |
435 | connectionName does not exist in the list of databases, an invalid |
436 | connection is returned. |
437 | |
438 | \sa isOpen(), {Threads and the SQL Module} |
439 | */ |
440 | |
441 | QSqlDatabase QSqlDatabase::database(const QString& connectionName, bool open) |
442 | { |
443 | return QSqlDatabasePrivate::database(name: connectionName, open); |
444 | } |
445 | |
446 | /*! |
447 | \threadsafe |
448 | |
449 | Removes the database connection \a connectionName from the list of |
450 | database connections. |
451 | |
452 | \warning There should be no open queries on the database |
453 | connection when this function is called, otherwise a resource leak |
454 | will occur. |
455 | |
456 | Example: |
457 | |
458 | \snippet code/src_sql_kernel_qsqldatabase.cpp 0 |
459 | |
460 | The correct way to do it: |
461 | |
462 | \snippet code/src_sql_kernel_qsqldatabase.cpp 1 |
463 | |
464 | To remove the default connection, which may have been created with a |
465 | call to addDatabase() not specifying a connection name, you can |
466 | retrieve the default connection name by calling connectionName() on |
467 | the database returned by database(). Note that if a default database |
468 | hasn't been created an invalid database will be returned. |
469 | |
470 | \sa database(), connectionName(), {Threads and the SQL Module} |
471 | */ |
472 | |
473 | void QSqlDatabase::removeDatabase(const QString& connectionName) |
474 | { |
475 | QSqlDatabasePrivate::removeDatabase(name: connectionName); |
476 | } |
477 | |
478 | /*! |
479 | Returns a list of all the available database drivers. |
480 | |
481 | \sa registerSqlDriver() |
482 | */ |
483 | |
484 | QStringList QSqlDatabase::drivers() |
485 | { |
486 | CHECK_QCOREAPPLICATION_RETVAL |
487 | QStringList list; |
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(str: 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(str: k)) |
504 | list << k; |
505 | } |
506 | |
507 | return list; |
508 | } |
509 | |
510 | /*! |
511 | This function registers a new SQL driver called \a name, within |
512 | the SQL framework. This is useful if you have a custom SQL driver |
513 | and don't want to compile it as a plugin. |
514 | |
515 | Example: |
516 | \snippet code/src_sql_kernel_qsqldatabase_snippet.cpp 2 |
517 | |
518 | QSqlDatabase takes ownership of the \a creator pointer, so you |
519 | mustn't delete it yourself. |
520 | |
521 | \sa drivers() |
522 | */ |
523 | void QSqlDatabase::registerSqlDriver(const QString& name, QSqlDriverCreatorBase *creator) |
524 | { |
525 | CHECK_QCOREAPPLICATION |
526 | QtSqlGlobals *sqlGlobals = s_sqlGlobals(); |
527 | QWriteLocker locker(&sqlGlobals->lock); |
528 | delete sqlGlobals->registeredDrivers.take(key: name); |
529 | if (creator) |
530 | sqlGlobals->registeredDrivers.insert(key: name, value: creator); |
531 | } |
532 | |
533 | /*! |
534 | \threadsafe |
535 | |
536 | Returns \c true if the list of database connections contains \a |
537 | connectionName; otherwise returns \c false. |
538 | |
539 | \sa connectionNames(), database(), {Threads and the SQL Module} |
540 | */ |
541 | |
542 | bool QSqlDatabase::contains(const QString& connectionName) |
543 | { |
544 | CHECK_QCOREAPPLICATION_RETVAL |
545 | return s_sqlGlobals()->connectionExists(key: connectionName); |
546 | } |
547 | |
548 | /*! |
549 | \threadsafe |
550 | |
551 | Returns a list containing the names of all connections. |
552 | |
553 | \sa contains(), database(), {Threads and the SQL Module} |
554 | */ |
555 | QStringList QSqlDatabase::connectionNames() |
556 | { |
557 | CHECK_QCOREAPPLICATION_RETVAL |
558 | return s_sqlGlobals()->connectionNames(); |
559 | } |
560 | |
561 | /*! |
562 | \overload |
563 | |
564 | Creates a QSqlDatabase connection that uses the driver referred |
565 | to by \a type. If the \a type is not recognized, the database |
566 | connection will have no functionality. |
567 | |
568 | The currently available driver types are: |
569 | |
570 | \table |
571 | \header \li Driver Type \li Description |
572 | \row \li QDB2 \li IBM DB2 |
573 | \row \li QIBASE \li Borland InterBase Driver |
574 | \row \li QMYSQL \li MySQL Driver |
575 | \row \li QOCI \li Oracle Call Interface Driver |
576 | \row \li QODBC \li ODBC Driver (includes Microsoft SQL Server) |
577 | \row \li QPSQL \li PostgreSQL Driver |
578 | \row \li QSQLITE \li SQLite version 3 or above |
579 | \row \li QMIMER \li Mimer SQL 11 or above |
580 | \endtable |
581 | |
582 | Additional third party drivers, including your own custom |
583 | drivers, can be loaded dynamically. |
584 | |
585 | \sa {SQL Database Drivers}, registerSqlDriver(), drivers() |
586 | */ |
587 | |
588 | QSqlDatabase::QSqlDatabase(const QString &type) |
589 | : d(new QSqlDatabasePrivate(nullptr)) |
590 | { |
591 | d->init(type); |
592 | } |
593 | |
594 | /*! |
595 | \overload |
596 | |
597 | Creates a database connection using the given \a driver. |
598 | */ |
599 | |
600 | QSqlDatabase::QSqlDatabase(QSqlDriver *driver) |
601 | : d(new QSqlDatabasePrivate(driver)) |
602 | { |
603 | } |
604 | |
605 | /*! |
606 | Creates an empty, invalid QSqlDatabase object. Use addDatabase(), |
607 | removeDatabase(), and database() to get valid QSqlDatabase |
608 | objects. |
609 | */ |
610 | QSqlDatabase::QSqlDatabase() |
611 | : d(QSqlDatabasePrivate::shared_null()) |
612 | { |
613 | d->ref.ref(); |
614 | } |
615 | |
616 | /*! |
617 | Creates a copy of \a other. |
618 | */ |
619 | QSqlDatabase::QSqlDatabase(const QSqlDatabase &other) |
620 | { |
621 | d = other.d; |
622 | d->ref.ref(); |
623 | } |
624 | |
625 | /*! |
626 | Assigns \a other to this object. |
627 | */ |
628 | QSqlDatabase &QSqlDatabase::operator=(const QSqlDatabase &other) |
629 | { |
630 | qAtomicAssign(d, x: other.d); |
631 | return *this; |
632 | } |
633 | |
634 | /*! |
635 | \internal |
636 | |
637 | Create the actual driver instance \a type. |
638 | */ |
639 | |
640 | void QSqlDatabasePrivate::init(const QString &type) |
641 | { |
642 | CHECK_QCOREAPPLICATION |
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(key: type); |
650 | if (it != dict.end()) |
651 | driver = it.value()->createObject(); |
652 | } |
653 | |
654 | if (!driver && loader()) |
655 | driver = qLoadPlugin<QSqlDriver, QSqlDriverPlugin>(loader: loader(), key: type); |
656 | |
657 | if (!driver) { |
658 | qCWarning(lcSqlDb, "QSqlDatabase: %ls driver not loaded", qUtf16Printable(type)); |
659 | qCWarning(lcSqlDb, "QSqlDatabase: available drivers: %ls", |
660 | qUtf16Printable(QSqlDatabase::drivers().join(u' '))); |
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 | |
667 | /*! |
668 | Destroys the object and frees any allocated resources. |
669 | |
670 | \note When the last connection is destroyed, the destructor |
671 | implicitly calls close() to release the database connection. |
672 | |
673 | \sa close() |
674 | */ |
675 | |
676 | QSqlDatabase::~QSqlDatabase() |
677 | { |
678 | if (!d->ref.deref()) { |
679 | close(); |
680 | delete d; |
681 | } |
682 | } |
683 | |
684 | /*! |
685 | Executes a SQL statement on the database and returns a QSqlQuery |
686 | object. Use lastError() to retrieve error information. If \a |
687 | query is empty, an empty, invalid query is returned and |
688 | lastError() is not affected. |
689 | |
690 | \sa QSqlQuery, lastError() |
691 | \deprecated [6.6] Use QSqlQuery::exec() instead. |
692 | */ |
693 | #if QT_DEPRECATED_SINCE(6, 6) |
694 | QSqlQuery QSqlDatabase::exec(const QString & query) const |
695 | { |
696 | QSqlQuery r(d->driver->createResult()); |
697 | if (!query.isEmpty()) { |
698 | r.exec(query); |
699 | d->driver->setLastError(r.lastError()); |
700 | } |
701 | return r; |
702 | } |
703 | #endif |
704 | |
705 | /*! |
706 | Opens the database connection using the current connection |
707 | values. Returns \c true on success; otherwise returns \c false. Error |
708 | information can be retrieved using lastError(). |
709 | |
710 | \sa lastError(), setDatabaseName(), setUserName(), setPassword(), |
711 | setHostName(), setPort(), setConnectOptions() |
712 | */ |
713 | |
714 | bool QSqlDatabase::open() |
715 | { |
716 | return d->driver->open(db: d->dbname, user: d->uname, password: d->pword, host: d->hname, |
717 | port: d->port, connOpts: d->connOptions); |
718 | } |
719 | |
720 | /*! |
721 | \overload |
722 | |
723 | Opens the database connection using the given \a user name and \a |
724 | password. Returns \c true on success; otherwise returns \c false. Error |
725 | information can be retrieved using the lastError() function. |
726 | |
727 | This function does not store the password it is given. Instead, |
728 | the password is passed directly to the driver for opening the |
729 | connection and it is then discarded. |
730 | |
731 | \sa lastError() |
732 | */ |
733 | |
734 | bool QSqlDatabase::open(const QString& user, const QString& password) |
735 | { |
736 | setUserName(user); |
737 | return d->driver->open(db: d->dbname, user, password, host: d->hname, |
738 | port: d->port, connOpts: d->connOptions); |
739 | } |
740 | |
741 | /*! |
742 | Closes the database connection, freeing any resources acquired, and |
743 | invalidating any existing QSqlQuery objects that are used with the |
744 | database. |
745 | |
746 | This will also affect copies of this QSqlDatabase object. |
747 | |
748 | \sa removeDatabase() |
749 | */ |
750 | |
751 | void QSqlDatabase::close() |
752 | { |
753 | d->driver->close(); |
754 | } |
755 | |
756 | /*! |
757 | Returns \c true if the database connection is currently open; |
758 | otherwise returns \c false. |
759 | */ |
760 | |
761 | bool QSqlDatabase::isOpen() const |
762 | { |
763 | return d->driver->isOpen(); |
764 | } |
765 | |
766 | /*! |
767 | Returns \c true if there was an error opening the database |
768 | connection; otherwise returns \c false. Error information can be |
769 | retrieved using the lastError() function. |
770 | */ |
771 | |
772 | bool QSqlDatabase::isOpenError() const |
773 | { |
774 | return d->driver->isOpenError(); |
775 | } |
776 | |
777 | /*! |
778 | Begins a transaction on the database if the driver supports |
779 | transactions. Returns \c{true} if the operation succeeded. |
780 | Otherwise it returns \c{false}. |
781 | |
782 | \sa QSqlDriver::hasFeature(), commit(), rollback() |
783 | */ |
784 | bool QSqlDatabase::transaction() |
785 | { |
786 | if (!d->driver->hasFeature(f: QSqlDriver::Transactions)) |
787 | return false; |
788 | return d->driver->beginTransaction(); |
789 | } |
790 | |
791 | /*! |
792 | Commits a transaction to the database if the driver supports |
793 | transactions and a transaction() has been started. Returns \c{true} |
794 | if the operation succeeded. Otherwise it returns \c{false}. |
795 | |
796 | \note For some databases, the commit will fail and return \c{false} |
797 | if there is an \l{QSqlQuery::isActive()} {active query} using the |
798 | database for a \c{SELECT}. Make the query \l{QSqlQuery::isActive()} |
799 | {inactive} before doing the commit. |
800 | |
801 | Call lastError() to get information about errors. |
802 | |
803 | \sa QSqlQuery::isActive(), QSqlDriver::hasFeature(), rollback() |
804 | */ |
805 | bool QSqlDatabase::commit() |
806 | { |
807 | if (!d->driver->hasFeature(f: QSqlDriver::Transactions)) |
808 | return false; |
809 | return d->driver->commitTransaction(); |
810 | } |
811 | |
812 | /*! |
813 | Rolls back a transaction on the database, if the driver supports |
814 | transactions and a transaction() has been started. Returns \c{true} |
815 | if the operation succeeded. Otherwise it returns \c{false}. |
816 | |
817 | \note For some databases, the rollback will fail and return |
818 | \c{false} if there is an \l{QSqlQuery::isActive()} {active query} |
819 | using the database for a \c{SELECT}. Make the query |
820 | \l{QSqlQuery::isActive()} {inactive} before doing the rollback. |
821 | |
822 | Call lastError() to get information about errors. |
823 | |
824 | \sa QSqlQuery::isActive(), QSqlDriver::hasFeature(), commit() |
825 | */ |
826 | bool QSqlDatabase::rollback() |
827 | { |
828 | if (!d->driver->hasFeature(f: QSqlDriver::Transactions)) |
829 | return false; |
830 | return d->driver->rollbackTransaction(); |
831 | } |
832 | |
833 | /*! |
834 | Sets the connection's database name to \a name. To have effect, |
835 | the database name must be set \e{before} the connection is |
836 | \l{open()} {opened}. Alternatively, you can close() the |
837 | connection, set the database name, and call open() again. \note |
838 | The \e{database name} is not the \e{connection name}. The |
839 | connection name must be passed to addDatabase() at connection |
840 | object create time. |
841 | |
842 | For the QSQLITE driver, if the database name specified does not |
843 | exist, then it will create the file for you unless the |
844 | QSQLITE_OPEN_READONLY option is set. |
845 | |
846 | Additionally, \a name can be set to \c ":memory:" which will |
847 | create a temporary database which is only available for the |
848 | lifetime of the application. |
849 | |
850 | For the QOCI (Oracle) driver, the database name is the TNS |
851 | Service Name. |
852 | |
853 | For the QODBC driver, the \a name can either be a DSN, a DSN |
854 | filename (in which case the file must have a \c .dsn extension), |
855 | or a connection string. |
856 | |
857 | For example, Microsoft Access users can use the following |
858 | connection string to open an \c .mdb file directly, instead of |
859 | having to create a DSN entry in the ODBC manager: |
860 | |
861 | \snippet code/src_sql_kernel_qsqldatabase.cpp 3 |
862 | |
863 | There is no default value. |
864 | |
865 | \sa databaseName(), setUserName(), setPassword(), setHostName(), |
866 | setPort(), setConnectOptions(), open() |
867 | */ |
868 | |
869 | void QSqlDatabase::setDatabaseName(const QString& name) |
870 | { |
871 | if (isValid()) |
872 | d->dbname = name; |
873 | } |
874 | |
875 | /*! |
876 | Sets the connection's user name to \a name. To have effect, the |
877 | user name must be set \e{before} the connection is \l{open()} |
878 | {opened}. Alternatively, you can close() the connection, set the |
879 | user name, and call open() again. |
880 | |
881 | There is no default value. |
882 | |
883 | \sa userName(), setDatabaseName(), setPassword(), setHostName(), |
884 | setPort(), setConnectOptions(), open() |
885 | */ |
886 | |
887 | void QSqlDatabase::setUserName(const QString& name) |
888 | { |
889 | if (isValid()) |
890 | d->uname = name; |
891 | } |
892 | |
893 | /*! |
894 | Sets the connection's password to \a password. To have effect, the |
895 | password must be set \e{before} the connection is \l{open()} |
896 | {opened}. Alternatively, you can close() the connection, set the |
897 | password, and call open() again. |
898 | |
899 | There is no default value. |
900 | |
901 | \warning This function stores the password in plain text within |
902 | Qt. Use the open() call that takes a password as parameter to |
903 | avoid this behavior. |
904 | |
905 | \sa password(), setUserName(), setDatabaseName(), setHostName(), |
906 | setPort(), setConnectOptions(), open() |
907 | */ |
908 | |
909 | void QSqlDatabase::setPassword(const QString& password) |
910 | { |
911 | if (isValid()) |
912 | d->pword = password; |
913 | } |
914 | |
915 | /*! |
916 | Sets the connection's host name to \a host. To have effect, the |
917 | host name must be set \e{before} the connection is \l{open()} |
918 | {opened}. Alternatively, you can close() the connection, set the |
919 | host name, and call open() again. |
920 | |
921 | There is no default value. |
922 | |
923 | \sa hostName(), setUserName(), setPassword(), setDatabaseName(), |
924 | setPort(), setConnectOptions(), open() |
925 | */ |
926 | |
927 | void QSqlDatabase::setHostName(const QString& host) |
928 | { |
929 | if (isValid()) |
930 | d->hname = host; |
931 | } |
932 | |
933 | /*! |
934 | Sets the connection's port number to \a port. To have effect, the |
935 | port number must be set \e{before} the connection is \l{open()} |
936 | {opened}. Alternatively, you can close() the connection, set the |
937 | port number, and call open() again.. |
938 | |
939 | There is no default value. |
940 | |
941 | \sa port(), setUserName(), setPassword(), setHostName(), |
942 | setDatabaseName(), setConnectOptions(), open() |
943 | */ |
944 | |
945 | void QSqlDatabase::setPort(int port) |
946 | { |
947 | if (isValid()) |
948 | d->port = port; |
949 | } |
950 | |
951 | /*! |
952 | Returns the connection's database name, which may be empty. |
953 | \note The database name is not the connection name. |
954 | |
955 | \sa setDatabaseName() |
956 | */ |
957 | QString QSqlDatabase::databaseName() const |
958 | { |
959 | return d->dbname; |
960 | } |
961 | |
962 | /*! |
963 | Returns the connection's user name; it may be empty. |
964 | |
965 | \sa setUserName() |
966 | */ |
967 | QString QSqlDatabase::userName() const |
968 | { |
969 | return d->uname; |
970 | } |
971 | |
972 | /*! |
973 | Returns the connection's password. An empty string will be returned |
974 | if the password was not set with setPassword(), and if the password |
975 | was given in the open() call, or if no password was used. |
976 | */ |
977 | QString QSqlDatabase::password() const |
978 | { |
979 | return d->pword; |
980 | } |
981 | |
982 | /*! |
983 | Returns the connection's host name; it may be empty. |
984 | |
985 | \sa setHostName() |
986 | */ |
987 | QString QSqlDatabase::hostName() const |
988 | { |
989 | return d->hname; |
990 | } |
991 | |
992 | /*! |
993 | Returns the connection's driver name. |
994 | |
995 | \sa addDatabase(), driver() |
996 | */ |
997 | QString QSqlDatabase::driverName() const |
998 | { |
999 | return d->drvName; |
1000 | } |
1001 | |
1002 | /*! |
1003 | Returns the connection's port number. The value is undefined if |
1004 | the port number has not been set. |
1005 | |
1006 | \sa setPort() |
1007 | */ |
1008 | int QSqlDatabase::port() const |
1009 | { |
1010 | return d->port; |
1011 | } |
1012 | |
1013 | /*! |
1014 | Returns the database driver used to access the database |
1015 | connection. |
1016 | |
1017 | \sa addDatabase(), drivers() |
1018 | */ |
1019 | |
1020 | QSqlDriver* QSqlDatabase::driver() const |
1021 | { |
1022 | return d->driver; |
1023 | } |
1024 | |
1025 | /*! |
1026 | Returns information about the last error that occurred on the |
1027 | database. |
1028 | |
1029 | Failures that occur in conjunction with an individual query are |
1030 | reported by QSqlQuery::lastError(). |
1031 | |
1032 | \sa QSqlError, QSqlQuery::lastError() |
1033 | */ |
1034 | |
1035 | QSqlError QSqlDatabase::lastError() const |
1036 | { |
1037 | return d->driver->lastError(); |
1038 | } |
1039 | |
1040 | |
1041 | /*! |
1042 | Returns a list of the database's tables, system tables and views, |
1043 | as specified by the parameter \a type. |
1044 | |
1045 | \sa primaryIndex(), record() |
1046 | */ |
1047 | |
1048 | QStringList QSqlDatabase::tables(QSql::TableType type) const |
1049 | { |
1050 | return d->driver->tables(tableType: type); |
1051 | } |
1052 | |
1053 | /*! |
1054 | Returns the primary index for table \a tablename. If no primary |
1055 | index exists, an empty QSqlIndex is returned. |
1056 | |
1057 | \note Some drivers, such as the \l {QPSQL Case Sensitivity}{QPSQL} |
1058 | driver, may may require you to pass \a tablename in lower case if |
1059 | the table was not quoted when created. See the |
1060 | \l{sql-driver.html}{Qt SQL driver} documentation for more information. |
1061 | |
1062 | \sa tables(), record() |
1063 | */ |
1064 | |
1065 | QSqlIndex QSqlDatabase::primaryIndex(const QString& tablename) const |
1066 | { |
1067 | return d->driver->primaryIndex(tableName: tablename); |
1068 | } |
1069 | |
1070 | |
1071 | /*! |
1072 | Returns a QSqlRecord populated with the names of all the fields in |
1073 | the table (or view) called \a tablename. The order in which the |
1074 | fields appear in the record is undefined. If no such table (or |
1075 | view) exists, an empty record is returned. |
1076 | |
1077 | \note Some drivers, such as the \l {QPSQL Case Sensitivity}{QPSQL} |
1078 | driver, may may require you to pass \a tablename in lower case if |
1079 | the table was not quoted when created. See the |
1080 | \l{sql-driver.html}{Qt SQL driver} documentation for more information. |
1081 | */ |
1082 | |
1083 | QSqlRecord QSqlDatabase::record(const QString& tablename) const |
1084 | { |
1085 | return d->driver->record(tableName: tablename); |
1086 | } |
1087 | |
1088 | |
1089 | /*! |
1090 | Sets database-specific \a options. This must be done before the |
1091 | connection is opened, otherwise it has no effect. Another possibility |
1092 | is to close the connection, call QSqlDatabase::setConnectOptions(), |
1093 | and open() the connection again. |
1094 | |
1095 | The format of the \a options string is a semicolon separated list |
1096 | of option names or option=value pairs. The options depend on the |
1097 | database client used and are described for each plugin in the |
1098 | \l{sql-driver.html}{SQL Database Drivers} page. |
1099 | |
1100 | Examples: |
1101 | \snippet code/src_sql_kernel_qsqldatabase.cpp 4 |
1102 | |
1103 | Refer to the client library documentation for more information |
1104 | about the different options. |
1105 | |
1106 | \sa connectOptions() |
1107 | */ |
1108 | |
1109 | void QSqlDatabase::setConnectOptions(const QString &options) |
1110 | { |
1111 | if (isValid()) |
1112 | d->connOptions = options; |
1113 | } |
1114 | |
1115 | /*! |
1116 | Returns the connection options string used for this connection. |
1117 | The string may be empty. |
1118 | |
1119 | \sa setConnectOptions() |
1120 | */ |
1121 | QString QSqlDatabase::connectOptions() const |
1122 | { |
1123 | return d->connOptions; |
1124 | } |
1125 | |
1126 | /*! |
1127 | Returns \c true if a driver called \a name is available; otherwise |
1128 | returns \c false. |
1129 | |
1130 | \sa drivers() |
1131 | */ |
1132 | |
1133 | bool QSqlDatabase::isDriverAvailable(const QString& name) |
1134 | { |
1135 | return drivers().contains(str: name); |
1136 | } |
1137 | |
1138 | /*! \fn QSqlDatabase QSqlDatabase::addDatabase(QSqlDriver* driver, const QString& connectionName) |
1139 | \overload |
1140 | |
1141 | This overload is useful when you want to create a database |
1142 | connection with a \l{QSqlDriver} {driver} you instantiated |
1143 | yourself. It might be your own database driver, or you might just |
1144 | need to instantiate one of the Qt drivers yourself. If you do |
1145 | this, it is recommended that you include the driver code in your |
1146 | application. For example, you can create a PostgreSQL connection |
1147 | with your own QPSQL driver like this: |
1148 | |
1149 | \snippet code/src_sql_kernel_qsqldatabase_snippet.cpp 6 |
1150 | |
1151 | The above code sets up a PostgreSQL connection and instantiates a |
1152 | QPSQLDriver object. Next, addDatabase() is called to add the |
1153 | connection to the known connections so that it can be used by the |
1154 | Qt SQL classes. When a driver is instantiated with a connection |
1155 | handle (or set of handles), Qt assumes that you have already |
1156 | opened the database connection. |
1157 | |
1158 | \note We assume that \c qtdir is the directory where Qt is |
1159 | installed. This will pull in the code that is needed to use the |
1160 | PostgreSQL client library and to instantiate a QPSQLDriver object, |
1161 | assuming that you have the PostgreSQL headers somewhere in your |
1162 | include search path. |
1163 | |
1164 | Remember that you must link your application against the database |
1165 | client library. Make sure the client library is in your linker's |
1166 | search path, and add lines like these to your \c{.pro} file: |
1167 | |
1168 | \snippet code/src_sql_kernel_qsqldatabase_snippet.cpp 7 |
1169 | |
1170 | The method described works for all the supplied drivers. The only |
1171 | difference will be in the driver constructor arguments. Here is a |
1172 | table of the drivers included with Qt, their source code files, |
1173 | and their constructor arguments: |
1174 | |
1175 | \table |
1176 | \header \li Driver \li Class name \li Constructor arguments \li File to include |
1177 | \row |
1178 | \li QPSQL |
1179 | \li QPSQLDriver |
1180 | \li PGconn *connection |
1181 | \li \c qsql_psql.cpp |
1182 | \row |
1183 | \li QMYSQL |
1184 | \li QMYSQLDriver |
1185 | \li MYSQL *connection |
1186 | \li \c qsql_mysql.cpp |
1187 | \row |
1188 | \li QOCI |
1189 | \li QOCIDriver |
1190 | \li OCIEnv *environment, OCISvcCtx *serviceContext |
1191 | \li \c qsql_oci.cpp |
1192 | \row |
1193 | \li QODBC |
1194 | \li QODBCDriver |
1195 | \li SQLHANDLE environment, SQLHANDLE connection |
1196 | \li \c qsql_odbc.cpp |
1197 | \row |
1198 | \li QDB2 |
1199 | \li QDB2 |
1200 | \li SQLHANDLE environment, SQLHANDLE connection |
1201 | \li \c qsql_db2.cpp |
1202 | \row |
1203 | \li QSQLITE |
1204 | \li QSQLiteDriver |
1205 | \li sqlite *connection |
1206 | \li \c qsql_sqlite.cpp |
1207 | \row |
1208 | \li QMIMER |
1209 | \li QMimerSQLDriver |
1210 | \li MimerSession *connection |
1211 | \li \c qsql_mimer.cpp |
1212 | \row |
1213 | \li QIBASE |
1214 | \li QIBaseDriver |
1215 | \li isc_db_handle connection |
1216 | \li \c qsql_ibase.cpp |
1217 | \endtable |
1218 | |
1219 | \warning Adding a database connection with the same connection |
1220 | name as an existing connection, causes the existing connection to |
1221 | be replaced by the new one. |
1222 | |
1223 | \warning The SQL framework takes ownership of the \a driver. It |
1224 | must not be deleted. To remove the connection, use |
1225 | removeDatabase(). |
1226 | |
1227 | \sa drivers() |
1228 | */ |
1229 | QSqlDatabase QSqlDatabase::addDatabase(QSqlDriver* driver, const QString& connectionName) |
1230 | { |
1231 | QSqlDatabase db(driver); |
1232 | QSqlDatabasePrivate::addDatabase(db, name: connectionName); |
1233 | return db; |
1234 | } |
1235 | |
1236 | /*! |
1237 | Returns \c true if the QSqlDatabase has a valid driver. |
1238 | |
1239 | Example: |
1240 | \snippet code/src_sql_kernel_qsqldatabase.cpp 8 |
1241 | */ |
1242 | bool QSqlDatabase::isValid() const |
1243 | { |
1244 | return d->driver && d->driver != d->shared_null()->driver; |
1245 | } |
1246 | |
1247 | /*! |
1248 | Clones the database connection \a other and stores it as \a |
1249 | connectionName. All the settings from the original database, e.g. |
1250 | databaseName(), hostName(), etc., are copied across. Does nothing |
1251 | if \a other is an invalid database. Returns the newly created |
1252 | database connection. |
1253 | |
1254 | \note The new connection has not been opened. Before using the new |
1255 | connection, you must call open(). |
1256 | |
1257 | \reentrant |
1258 | */ |
1259 | QSqlDatabase QSqlDatabase::cloneDatabase(const QSqlDatabase &other, const QString &connectionName) |
1260 | { |
1261 | if (!other.isValid()) |
1262 | return QSqlDatabase(); |
1263 | |
1264 | QSqlDatabase db(other.driverName()); |
1265 | db.d->copy(other: other.d); |
1266 | QSqlDatabasePrivate::addDatabase(db, name: connectionName); |
1267 | return db; |
1268 | } |
1269 | |
1270 | /*! |
1271 | \since 5.13 |
1272 | \overload |
1273 | |
1274 | Clones the database connection \a other and stores it as \a |
1275 | connectionName. All the settings from the original database, e.g. |
1276 | databaseName(), hostName(), etc., are copied across. Does nothing |
1277 | if \a other is an invalid database. Returns the newly created |
1278 | database connection. |
1279 | |
1280 | \note The new connection has not been opened. Before using the new |
1281 | connection, you must call open(). |
1282 | |
1283 | This overload is useful when cloning the database in another thread to the |
1284 | one that is used by the database represented by \a other. |
1285 | */ |
1286 | |
1287 | QSqlDatabase QSqlDatabase::cloneDatabase(const QString &other, const QString &connectionName) |
1288 | { |
1289 | CHECK_QCOREAPPLICATION_RETVAL |
1290 | return cloneDatabase(other: s_sqlGlobals()->connection(key: other), connectionName); |
1291 | } |
1292 | |
1293 | /*! |
1294 | Returns the connection name, which may be empty. \note The |
1295 | connection name is not the \l{databaseName()} {database name}. |
1296 | |
1297 | \sa addDatabase() |
1298 | */ |
1299 | QString QSqlDatabase::connectionName() const |
1300 | { |
1301 | return d->connName; |
1302 | } |
1303 | |
1304 | /*! |
1305 | \property QSqlDatabase::numericalPrecisionPolicy |
1306 | \since 6.8 |
1307 | |
1308 | This property holds the default numerical precision policy used by |
1309 | queries created on this database connection. |
1310 | |
1311 | Note: Drivers that don't support fetching numerical values with low |
1312 | precision will ignore the precision policy. You can use |
1313 | QSqlDriver::hasFeature() to find out whether a driver supports this |
1314 | feature. |
1315 | |
1316 | Note: Setting the default precision policy to \a precisionPolicy |
1317 | doesn't affect any currently active queries. |
1318 | |
1319 | \sa QSql::NumericalPrecisionPolicy, QSqlQuery::numericalPrecisionPolicy, |
1320 | QSqlDriver::numericalPrecisionPolicy |
1321 | */ |
1322 | /*! |
1323 | Sets \l numericalPrecisionPolicy to \a precisionPolicy. |
1324 | */ |
1325 | void QSqlDatabase::setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy precisionPolicy) |
1326 | { |
1327 | if (driver()) |
1328 | driver()->setNumericalPrecisionPolicy(precisionPolicy); |
1329 | d->precisionPolicy = precisionPolicy; |
1330 | } |
1331 | |
1332 | /*! |
1333 | Returns the \l numericalPrecisionPolicy. |
1334 | */ |
1335 | QSql::NumericalPrecisionPolicy QSqlDatabase::numericalPrecisionPolicy() const |
1336 | { |
1337 | if (driver()) |
1338 | return driver()->numericalPrecisionPolicy(); |
1339 | else |
1340 | return d->precisionPolicy; |
1341 | } |
1342 | |
1343 | /*! |
1344 | \since 6.8 |
1345 | |
1346 | Changes the thread affinity for QSqlDatabase and its associated driver. |
1347 | This function returns \c true when the function succeeds. Event processing |
1348 | will continue in the \a targetThread. |
1349 | |
1350 | During this operation you have to make sure that there is no QSqlQuery |
1351 | bound to this instance otherwise the QSqlDatabase will not be moved to |
1352 | the given thread and the function returns \c false. |
1353 | |
1354 | Since the associated driver is derived from QObject, all constraints for |
1355 | moving a QObject to another thread also apply to this function. |
1356 | |
1357 | \sa QObject::moveToThread(), {Threads and the SQL Module} |
1358 | */ |
1359 | bool QSqlDatabase::moveToThread(QThread *targetThread) |
1360 | { |
1361 | if (auto drv = driver()) { |
1362 | if (drv != QSqlDatabasePrivate::shared_null()->driver) { |
1363 | // two instances are alive - the one here and the one in dbDict() |
1364 | if (d->ref.loadRelaxed() > 2) { |
1365 | qWarning(msg: "QSqlDatabasePrivate::moveToThread: connection '%ls' is still in use " |
1366 | "in the current thread.", qUtf16Printable(d->connName)); |
1367 | return false; |
1368 | } |
1369 | return drv->moveToThread(thread: targetThread); |
1370 | } |
1371 | } |
1372 | return false; |
1373 | } |
1374 | |
1375 | /*! |
1376 | \since 6.8 |
1377 | |
1378 | Returns a pointer to the associated QThread instance. |
1379 | */ |
1380 | QThread *QSqlDatabase::thread() const |
1381 | { |
1382 | if (auto drv = driver()) |
1383 | return drv->thread(); |
1384 | return nullptr; |
1385 | } |
1386 | |
1387 | |
1388 | #ifndef QT_NO_DEBUG_STREAM |
1389 | QDebug operator<<(QDebug dbg, const QSqlDatabase &d) |
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 | |
1406 | QT_END_NAMESPACE |
1407 | |
1408 | #include "moc_qsqldatabase.cpp" |
1409 |
Definitions
- lcSqlDb
- loader
- defaultConnection
- QtSqlGlobals
- connection
- connectionExists
- connectionNames
- s_sqlGlobals
- QSqlDatabasePrivate
- QSqlDatabasePrivate
- QSqlDatabasePrivate
- ~QSqlDatabasePrivate
- ~QtSqlGlobals
- shared_null
- invalidateDb
- removeDatabase
- addDatabase
- database
- copy
- disable
- ~QSqlDriverCreatorBase
- addDatabase
- database
- removeDatabase
- drivers
- registerSqlDriver
- contains
- connectionNames
- QSqlDatabase
- QSqlDatabase
- QSqlDatabase
- QSqlDatabase
- operator=
- init
- ~QSqlDatabase
- exec
- open
- open
- close
- isOpen
- isOpenError
- transaction
- commit
- rollback
- setDatabaseName
- setUserName
- setPassword
- setHostName
- setPort
- databaseName
- userName
- password
- hostName
- driverName
- port
- driver
- lastError
- tables
- primaryIndex
- record
- setConnectOptions
- connectOptions
- isDriverAvailable
- addDatabase
- isValid
- cloneDatabase
- cloneDatabase
- connectionName
- setNumericalPrecisionPolicy
- numericalPrecisionPolicy
- moveToThread
- thread
Learn Advanced QML with KDAB
Find out more