source: trunk/src/sql/kernel/qsqldatabase.cpp@ 1016

Last change on this file since 1016 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 42.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtSql module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qsqldatabase.h"
43#include "qsqlquery.h"
44
45#ifdef Q_OS_WIN32
46// Conflicting declarations of LPCBYTE in sqlfront.h and winscard.h
47#define _WINSCARD_H_
48#endif
49
50#ifdef QT_SQL_PSQL
51#include "../drivers/psql/qsql_psql.h"
52#endif
53#ifdef QT_SQL_MYSQL
54#include "../drivers/mysql/qsql_mysql.h"
55#endif
56#ifdef QT_SQL_ODBC
57#include "../drivers/odbc/qsql_odbc.h"
58#endif
59#ifdef QT_SQL_OCI
60#include "../drivers/oci/qsql_oci.h"
61#endif
62#ifdef QT_SQL_TDS
63// conflicting RETCODE typedef between odbc and freetds
64#define RETCODE DBRETCODE
65#include "../drivers/tds/qsql_tds.h"
66#undef RETCODE
67#endif
68#ifdef QT_SQL_DB2
69#include "../drivers/db2/qsql_db2.h"
70#endif
71#ifdef QT_SQL_SQLITE
72#include "../drivers/sqlite/qsql_sqlite.h"
73#endif
74#ifdef QT_SQL_SQLITE2
75#include "../drivers/sqlite2/qsql_sqlite2.h"
76#endif
77#ifdef QT_SQL_IBASE
78#undef SQL_FLOAT // avoid clash with ODBC
79#undef SQL_DOUBLE
80#undef SQL_TIMESTAMP
81#undef SQL_TYPE_TIME
82#undef SQL_TYPE_DATE
83#undef SQL_DATE
84#define SCHAR IBASE_SCHAR // avoid clash with ODBC (older versions of ibase.h with Firebird)
85#include "../drivers/ibase/qsql_ibase.h"
86#undef SCHAR
87#endif
88
89#include "qdebug.h"
90#include "qcoreapplication.h"
91#include "qreadwritelock.h"
92#include "qsqlresult.h"
93#include "qsqldriver.h"
94#include "qsqldriverplugin.h"
95#include "qsqlindex.h"
96#include "private/qfactoryloader_p.h"
97#include "private/qsqlnulldriver_p.h"
98#include "qmutex.h"
99#include "qhash.h"
100#include <stdlib.h>
101
102QT_BEGIN_NAMESPACE
103
104#ifndef QT_NO_LIBRARY
105Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
106 (QSqlDriverFactoryInterface_iid,
107 QLatin1String("/sqldrivers")))
108#endif
109
110QT_STATIC_CONST_IMPL char *QSqlDatabase::defaultConnection = "qt_sql_default_connection";
111
112typedef QHash<QString, QSqlDriverCreatorBase*> DriverDict;
113
114class QConnectionDict: public QHash<QString, QSqlDatabase>
115{
116public:
117 inline bool contains_ts(const QString &key)
118 {
119 QReadLocker locker(&lock);
120 return contains(key);
121 }
122 inline QStringList keys_ts() const
123 {
124 QReadLocker locker(&lock);
125 return keys();
126 }
127
128 mutable QReadWriteLock lock;
129};
130Q_GLOBAL_STATIC(QConnectionDict, dbDict)
131
132class QSqlDatabasePrivate
133{
134public:
135 QSqlDatabasePrivate(QSqlDatabase *d, QSqlDriver *dr = 0):
136 q(d),
137 driver(dr),
138 port(-1)
139 {
140 ref = 1;
141 if(driver)
142 precisionPolicy = driver->numericalPrecisionPolicy();
143 else
144 precisionPolicy= QSql::LowPrecisionDouble;
145 }
146 QSqlDatabasePrivate(const QSqlDatabasePrivate &other);
147 ~QSqlDatabasePrivate();
148 void init(const QString& type);
149 void copy(const QSqlDatabasePrivate *other);
150 void disable();
151
152 QAtomicInt ref;
153 QSqlDatabase *q;
154 QSqlDriver* driver;
155 QString dbname;
156 QString uname;
157 QString pword;
158 QString hname;
159 QString drvName;
160 int port;
161 QString connOptions;
162 QString connName;
163 QSql::NumericalPrecisionPolicy precisionPolicy;
164
165 static QSqlDatabasePrivate *shared_null();
166 static QSqlDatabase database(const QString& name, bool open);
167 static void addDatabase(const QSqlDatabase &db, const QString & name);
168 static void removeDatabase(const QString& name);
169 static void invalidateDb(const QSqlDatabase &db, const QString &name);
170 static DriverDict &driverDict();
171 static void cleanConnections();
172};
173
174QSqlDatabasePrivate::QSqlDatabasePrivate(const QSqlDatabasePrivate &other)
175{
176 ref = 1;
177 q = other.q;
178 dbname = other.dbname;
179 uname = other.uname;
180 pword = other.pword;
181 hname = other.hname;
182 drvName = other.drvName;
183 port = other.port;
184 connOptions = other.connOptions;
185 driver = other.driver;
186 precisionPolicy = other.precisionPolicy;
187}
188
189QSqlDatabasePrivate::~QSqlDatabasePrivate()
190{
191 if (driver != shared_null()->driver)
192 delete driver;
193}
194
195void QSqlDatabasePrivate::cleanConnections()
196{
197 QConnectionDict *dict = dbDict();
198 Q_ASSERT(dict);
199 QWriteLocker locker(&dict->lock);
200
201 QConnectionDict::iterator it = dict->begin();
202 while (it != dict->end()) {
203 invalidateDb(it.value(), it.key());
204 ++it;
205 }
206 dict->clear();
207}
208
209static bool qDriverDictInit = false;
210static void cleanDriverDict()
211{
212 qDeleteAll(QSqlDatabasePrivate::driverDict());
213 QSqlDatabasePrivate::driverDict().clear();
214 QSqlDatabasePrivate::cleanConnections();
215 qDriverDictInit = false;
216}
217
218DriverDict &QSqlDatabasePrivate::driverDict()
219{
220 static DriverDict dict;
221 if (!qDriverDictInit) {
222 qDriverDictInit = true;
223 qAddPostRoutine(cleanDriverDict);
224 }
225 return dict;
226}
227
228QSqlDatabasePrivate *QSqlDatabasePrivate::shared_null()
229{
230 static QSqlNullDriver dr;
231 static QSqlDatabasePrivate n(NULL, &dr);
232 return &n;
233}
234
235void QSqlDatabasePrivate::invalidateDb(const QSqlDatabase &db, const QString &name)
236{
237 if (db.d->ref != 1) {
238 qWarning("QSqlDatabasePrivate::removeDatabase: connection '%s' is still in use, "
239 "all queries will cease to work.", name.toLocal8Bit().constData());
240 db.d->disable();
241 db.d->connName.clear();
242 }
243}
244
245void QSqlDatabasePrivate::removeDatabase(const QString &name)
246{
247 QConnectionDict *dict = dbDict();
248 Q_ASSERT(dict);
249 QWriteLocker locker(&dict->lock);
250
251 if (!dict->contains(name))
252 return;
253
254 invalidateDb(dict->take(name), name);
255}
256
257void QSqlDatabasePrivate::addDatabase(const QSqlDatabase &db, const QString &name)
258{
259 QConnectionDict *dict = dbDict();
260 Q_ASSERT(dict);
261 QWriteLocker locker(&dict->lock);
262
263 if (dict->contains(name)) {
264 invalidateDb(dict->take(name), name);
265 qWarning("QSqlDatabasePrivate::addDatabase: duplicate connection name '%s', old "
266 "connection removed.", name.toLocal8Bit().data());
267 }
268 dict->insert(name, db);
269 db.d->connName = name;
270}
271
272/*! \internal
273*/
274QSqlDatabase QSqlDatabasePrivate::database(const QString& name, bool open)
275{
276 const QConnectionDict *dict = dbDict();
277 Q_ASSERT(dict);
278
279 dict->lock.lockForRead();
280 QSqlDatabase db = dict->value(name);
281 dict->lock.unlock();
282 if (db.isValid() && !db.isOpen() && open) {
283 if (!db.open())
284 qWarning() << "QSqlDatabasePrivate::database: unable to open database:" << db.lastError().text();
285
286 }
287 return db;
288}
289
290
291/*! \internal
292 Copies the connection data from \a other.
293*/
294void QSqlDatabasePrivate::copy(const QSqlDatabasePrivate *other)
295{
296 q = other->q;
297 dbname = other->dbname;
298 uname = other->uname;
299 pword = other->pword;
300 hname = other->hname;
301 drvName = other->drvName;
302 port = other->port;
303 connOptions = other->connOptions;
304 precisionPolicy = other->precisionPolicy;
305}
306
307void QSqlDatabasePrivate::disable()
308{
309 if (driver != shared_null()->driver) {
310 delete driver;
311 driver = shared_null()->driver;
312 }
313}
314
315/*!
316 \class QSqlDriverCreatorBase
317 \brief The QSqlDriverCreatorBase class is the base class for
318 SQL driver factories.
319
320 \ingroup database
321 \inmodule QtSql
322
323 Reimplement createObject() to return an instance of the specific
324 QSqlDriver subclass that you want to provide.
325
326 See QSqlDatabase::registerSqlDriver() for details.
327
328 \sa QSqlDriverCreator
329*/
330
331/*!
332 \fn QSqlDriverCreatorBase::~QSqlDriverCreatorBase()
333
334 Destroys the SQL driver creator object.
335*/
336
337/*!
338 \fn QSqlDriver *QSqlDriverCreatorBase::createObject() const
339
340 Reimplement this function to returns a new instance of a
341 QSqlDriver subclass.
342*/
343
344/*!
345 \class QSqlDriverCreator
346 \brief The QSqlDriverCreator class is a template class that
347 provides a SQL driver factory for a specific driver type.
348
349 \ingroup database
350 \inmodule QtSql
351
352 QSqlDriverCreator<T> instantiates objects of type T, where T is a
353 QSqlDriver subclass.
354
355 See QSqlDatabase::registerSqlDriver() for details.
356*/
357
358/*!
359 \fn QSqlDriver *QSqlDriverCreator::createObject() const
360 \reimp
361*/
362
363/*!
364 \class QSqlDatabase
365 \brief The QSqlDatabase class represents a connection to
366 a database.
367
368 \ingroup database
369
370 \inmodule QtSql
371
372 The QSqlDatabase class provides an interface for accessing a
373 database through a connection. An instance of QSqlDatabase
374 represents the connection. The connection provides access to the
375 database via one of the \l{SQL Database Drivers#Supported
376 Databases} {supported database drivers}, which are derived from
377 QSqlDriver. Alternatively, you can subclass your own database
378 driver from QSqlDriver. See \l{How to Write Your Own Database
379 Driver} for more information.
380
381 Create a connection (i.e., an instance of QSqlDatabase) by calling
382 one of the static addDatabase() functions, where you specify
383 \l{SQL Database Drivers#Supported Databases} {the driver or type
384 of driver} to use (i.e., what kind of database will you access?)
385 and a connection name. A connection is known by its own name,
386 \e{not} by the name of the database it connects to. You can have
387 multiple connections to one database. QSqlDatabase also supports
388 the concept of a \e{default} connection, which is the unnamed
389 connection. To create the default connection, don't pass the
390 connection name argument when you call addDatabase().
391 Subsequently, when you call any static member function that takes
392 the connection name argument, if you don't pass the connection
393 name argument, the default connection is assumed. The following
394 snippet shows how to create and open a default connection to a
395 PostgreSQL database:
396
397 \snippet doc/src/snippets/sqldatabase/sqldatabase.cpp 0
398
399 Once the QSqlDatabase object has been created, set the connection
400 parameters with setDatabaseName(), setUserName(), setPassword(),
401 setHostName(), setPort(), and setConnectOptions(). Then call
402 open() to activate the physical connection to the database. The
403 connection is not usable until you open it.
404
405 The connection defined above will be the \e{default} connection,
406 because we didn't give a connection name to \l{QSqlDatabase::}
407 {addDatabase()}. Subsequently, you can get the default connection
408 by calling database() without the connection name argument:
409
410 \snippet doc/src/snippets/sqldatabase/sqldatabase.cpp 1
411
412 QSqlDatabase is a value class. Changes made to a database
413 connection via one instance of QSqlDatabase will affect other
414 instances of QSqlDatabase that represent the same connection. Use
415 cloneDatabase() to create an independent database connection based
416 on an existing one.
417
418 If you create multiple database connections, specify a unique
419 connection name for each one, when you call addDatabase(). Use
420 database() with a connection name to get that connection. Use
421 removeDatabase() with a connection name to remove a connection.
422 QSqlDatabase outputs a warning if you try to remove a connection
423 referenced by other QSqlDatabase objects. Use contains() to see if
424 a given connection name is in the list of connections.
425
426 Once a connection is established, you can call tables() to get the
427 list of tables in the database, call primaryIndex() to get a
428 table's primary index, and call record() to get meta-information
429 about a table's fields (e.g., field names).
430
431 \note QSqlDatabase::exec() is deprecated. Use QSqlQuery::exec()
432 instead.
433
434 If the driver supports transactions, use transaction() to start a
435 transaction, and commit() or rollback() to complete it. Use
436 \l{QSqlDriver::} {hasFeature()} to ask if the driver supports
437 transactions. \note When using transactions, you must start the
438 transaction before you create your query.
439
440 If an error occurrs, lastError() will return information about it.
441
442 Get the names of the available SQL drivers with drivers(). Check
443 for the presence of a particular driver with isDriverAvailable().
444 If you have created your own custom driver, you must register it
445 with registerSqlDriver().
446
447 \sa QSqlDriver, QSqlQuery, {QtSql Module}, {Threads and the SQL Module}
448*/
449
450/*! \fn QSqlDatabase QSqlDatabase::addDatabase(const QString &type, const QString &connectionName)
451 \threadsafe
452
453 Adds a database to the list of database connections using the
454 driver \a type and the connection name \a connectionName. If
455 there already exists a database connection called \a
456 connectionName, that connection is removed.
457
458 The database connection is referred to by \a connectionName. The
459 newly added database connection is returned.
460
461 If \a type is not available or could not be loaded, isValid() returns false.
462
463 If \a connectionName is not specified, the new connection becomes
464 the default connection for the application, and subsequent calls
465 to database() without the connection name argument will return the
466 default connection. If a \a connectionName is provided here, use
467 database(\a connectionName) to retrieve the connection.
468
469 \warning If you add a connection with the same name as an existing
470 connection, the new connection replaces the old one. If you call
471 this function more than once without specifying \a connectionName,
472 the default connection will be the one replaced.
473
474 Before using the connection, it must be initialized. e.g., call
475 some or all of setDatabaseName(), setUserName(), setPassword(),
476 setHostName(), setPort(), and setConnectOptions(), and, finally,
477 open().
478
479 \sa database() removeDatabase() {Threads and the SQL Module}
480*/
481QSqlDatabase QSqlDatabase::addDatabase(const QString &type, const QString &connectionName)
482{
483 QSqlDatabase db(type);
484 QSqlDatabasePrivate::addDatabase(db, connectionName);
485 return db;
486}
487
488/*!
489 \threadsafe
490
491 Returns the database connection called \a connectionName. The
492 database connection must have been previously added with
493 addDatabase(). If \a open is true (the default) and the database
494 connection is not already open it is opened now. If no \a
495 connectionName is specified the default connection is used. If \a
496 connectionName does not exist in the list of databases, an invalid
497 connection is returned.
498
499 \sa isOpen() {Threads and the SQL Module}
500*/
501
502QSqlDatabase QSqlDatabase::database(const QString& connectionName, bool open)
503{
504 return QSqlDatabasePrivate::database(connectionName, open);
505}
506
507/*!
508 \threadsafe
509
510 Removes the database connection \a connectionName from the list of
511 database connections.
512
513 \warning There should be no open queries on the database
514 connection when this function is called, otherwise a resource leak
515 will occur.
516
517 Example:
518
519 \snippet doc/src/snippets/code/src_sql_kernel_qsqldatabase.cpp 0
520
521 The correct way to do it:
522
523 \snippet doc/src/snippets/code/src_sql_kernel_qsqldatabase.cpp 1
524
525 To remove the default connection, which may have been created with a
526 call to addDatabase() not specifying a connection name, you can
527 retrieve the default connection name by calling connectionName() on
528 the database returned by database(). Note that if a default database
529 hasn't been created an invalid database will be returned.
530
531 \sa database() connectionName() {Threads and the SQL Module}
532*/
533
534void QSqlDatabase::removeDatabase(const QString& connectionName)
535{
536 QSqlDatabasePrivate::removeDatabase(connectionName);
537}
538
539/*!
540 Returns a list of all the available database drivers.
541
542 \sa registerSqlDriver()
543*/
544
545QStringList QSqlDatabase::drivers()
546{
547 QStringList list;
548
549#ifdef QT_SQL_PSQL
550 list << QLatin1String("QPSQL7");
551 list << QLatin1String("QPSQL");
552#endif
553#ifdef QT_SQL_MYSQL
554 list << QLatin1String("QMYSQL3");
555 list << QLatin1String("QMYSQL");
556#endif
557#ifdef QT_SQL_ODBC
558 list << QLatin1String("QODBC3");
559 list << QLatin1String("QODBC");
560#endif
561#ifdef QT_SQL_OCI
562 list << QLatin1String("QOCI8");
563 list << QLatin1String("QOCI");
564#endif
565#ifdef QT_SQL_TDS
566 list << QLatin1String("QTDS7");
567 list << QLatin1String("QTDS");
568#endif
569#ifdef QT_SQL_DB2
570 list << QLatin1String("QDB2");
571#endif
572#ifdef QT_SQL_SQLITE
573 list << QLatin1String("QSQLITE");
574#endif
575#ifdef QT_SQL_SQLITE2
576 list << QLatin1String("QSQLITE2");
577#endif
578#ifdef QT_SQL_IBASE
579 list << QLatin1String("QIBASE");
580#endif
581
582#ifndef QT_NO_LIBRARY
583 if (QFactoryLoader *fl = loader()) {
584 QStringList keys = fl->keys();
585 for (QStringList::const_iterator i = keys.constBegin(); i != keys.constEnd(); ++i) {
586 if (!list.contains(*i))
587 list << *i;
588 }
589 }
590#endif
591
592 DriverDict dict = QSqlDatabasePrivate::driverDict();
593 for (DriverDict::const_iterator i = dict.constBegin(); i != dict.constEnd(); ++i) {
594 if (!list.contains(i.key()))
595 list << i.key();
596 }
597
598 return list;
599}
600
601/*!
602 This function registers a new SQL driver called \a name, within
603 the SQL framework. This is useful if you have a custom SQL driver
604 and don't want to compile it as a plugin.
605
606 Example:
607 \snippet doc/src/snippets/code/src_sql_kernel_qsqldatabase.cpp 2
608
609 QSqlDatabase takes ownership of the \a creator pointer, so you
610 mustn't delete it yourself.
611
612 \sa drivers()
613*/
614void QSqlDatabase::registerSqlDriver(const QString& name, QSqlDriverCreatorBase *creator)
615{
616 delete QSqlDatabasePrivate::driverDict().take(name);
617 if (creator)
618 QSqlDatabasePrivate::driverDict().insert(name, creator);
619}
620
621/*!
622 \threadsafe
623
624 Returns true if the list of database connections contains \a
625 connectionName; otherwise returns false.
626
627 \sa connectionNames(), database(), {Threads and the SQL Module}
628*/
629
630bool QSqlDatabase::contains(const QString& connectionName)
631{
632 return dbDict()->contains_ts(connectionName);
633}
634
635/*!
636 \threadsafe
637
638 Returns a list containing the names of all connections.
639
640 \sa contains(), database(), {Threads and the SQL Module}
641*/
642QStringList QSqlDatabase::connectionNames()
643{
644 return dbDict()->keys_ts();
645}
646
647/*!
648 \overload
649
650 Creates a QSqlDatabase connection that uses the driver referred
651 to by \a type. If the \a type is not recognized, the database
652 connection will have no functionality.
653
654 The currently available driver types are:
655
656 \table
657 \header \i Driver Type \i Description
658 \row \i QDB2 \i IBM DB2
659 \row \i QIBASE \i Borland InterBase Driver
660 \row \i QMYSQL \i MySQL Driver
661 \row \i QOCI \i Oracle Call Interface Driver
662 \row \i QODBC \i ODBC Driver (includes Microsoft SQL Server)
663 \row \i QPSQL \i PostgreSQL Driver
664 \row \i QSQLITE \i SQLite version 3 or above
665 \row \i QSQLITE2 \i SQLite version 2
666 \row \i QTDS \i Sybase Adaptive Server
667 \endtable
668
669 Additional third party drivers, including your own custom
670 drivers, can be loaded dynamically.
671
672 \sa {SQL Database Drivers}, registerSqlDriver(), drivers()
673*/
674
675QSqlDatabase::QSqlDatabase(const QString &type)
676{
677 d = new QSqlDatabasePrivate(this);
678 d->init(type);
679}
680
681/*!
682 \overload
683
684 Creates a database connection using the given \a driver.
685*/
686
687QSqlDatabase::QSqlDatabase(QSqlDriver *driver)
688{
689 d = new QSqlDatabasePrivate(this, driver);
690}
691
692/*!
693 Creates an empty, invalid QSqlDatabase object. Use addDatabase(),
694 removeDatabase(), and database() to get valid QSqlDatabase
695 objects.
696*/
697QSqlDatabase::QSqlDatabase()
698{
699 d = QSqlDatabasePrivate::shared_null();
700 d->ref.ref();
701}
702
703/*!
704 Creates a copy of \a other.
705*/
706QSqlDatabase::QSqlDatabase(const QSqlDatabase &other)
707{
708 d = other.d;
709 d->ref.ref();
710}
711
712/*!
713 Assigns \a other to this object.
714*/
715QSqlDatabase &QSqlDatabase::operator=(const QSqlDatabase &other)
716{
717 qAtomicAssign(d, other.d);
718 return *this;
719}
720
721/*!
722 \internal
723
724 Create the actual driver instance \a type.
725*/
726
727void QSqlDatabasePrivate::init(const QString &type)
728{
729 drvName = type;
730
731 if (!driver) {
732#ifdef QT_SQL_PSQL
733 if (type == QLatin1String("QPSQL") || type == QLatin1String("QPSQL7"))
734 driver = new QPSQLDriver();
735#endif
736#ifdef QT_SQL_MYSQL
737 if (type == QLatin1String("QMYSQL") || type == QLatin1String("QMYSQL3"))
738 driver = new QMYSQLDriver();
739#endif
740#ifdef QT_SQL_ODBC
741 if (type == QLatin1String("QODBC") || type == QLatin1String("QODBC3"))
742 driver = new QODBCDriver();
743#endif
744#ifdef QT_SQL_OCI
745 if (type == QLatin1String("QOCI") || type == QLatin1String("QOCI8"))
746 driver = new QOCIDriver();
747#endif
748#ifdef QT_SQL_TDS
749 if (type == QLatin1String("QTDS") || type == QLatin1String("QTDS7"))
750 driver = new QTDSDriver();
751#endif
752#ifdef QT_SQL_DB2
753 if (type == QLatin1String("QDB2"))
754 driver = new QDB2Driver();
755#endif
756#ifdef QT_SQL_SQLITE
757 if (type == QLatin1String("QSQLITE"))
758 driver = new QSQLiteDriver();
759#endif
760#ifdef QT_SQL_SQLITE2
761 if (type == QLatin1String("QSQLITE2"))
762 driver = new QSQLite2Driver();
763#endif
764#ifdef QT_SQL_IBASE
765 if (type == QLatin1String("QIBASE"))
766 driver = new QIBaseDriver();
767#endif
768 }
769
770 if (!driver) {
771 DriverDict dict = QSqlDatabasePrivate::driverDict();
772 for (DriverDict::const_iterator it = dict.constBegin();
773 it != dict.constEnd() && !driver; ++it) {
774 if (type == it.key()) {
775 driver = ((QSqlDriverCreatorBase*)(*it))->createObject();
776 }
777 }
778 }
779
780#ifndef QT_NO_LIBRARY
781 if (!driver && loader()) {
782 if (QSqlDriverFactoryInterface *factory = qobject_cast<QSqlDriverFactoryInterface*>(loader()->instance(type)))
783 driver = factory->create(type);
784 }
785#endif // QT_NO_LIBRARY
786
787 if (!driver) {
788 qWarning("QSqlDatabase: %s driver not loaded", type.toLatin1().data());
789 qWarning("QSqlDatabase: available drivers: %s",
790 QSqlDatabase::drivers().join(QLatin1String(" ")).toLatin1().data());
791 if (QCoreApplication::instance() == 0)
792 qWarning("QSqlDatabase: an instance of QCoreApplication is required for loading driver plugins");
793 driver = shared_null()->driver;
794 }
795}
796
797/*!
798 Destroys the object and frees any allocated resources.
799
800 If this is the last QSqlDatabase object that uses a certain
801 database connection, the is automatically closed.
802
803 \sa close()
804*/
805
806QSqlDatabase::~QSqlDatabase()
807{
808 if (!d->ref.deref()) {
809 close();
810 delete d;
811 }
812}
813
814/*!
815 Executes a SQL statement on the database and returns a QSqlQuery
816 object. Use lastError() to retrieve error information. If \a
817 query is empty, an empty, invalid query is returned and
818 lastError() is not affected.
819
820 \sa QSqlQuery, lastError()
821*/
822
823QSqlQuery QSqlDatabase::exec(const QString & query) const
824{
825 QSqlQuery r(d->driver->createResult());
826 if (!query.isEmpty()) {
827 r.exec(query);
828 d->driver->setLastError(r.lastError());
829 }
830 return r;
831}
832
833/*!
834 Opens the database connection using the current connection
835 values. Returns true on success; otherwise returns false. Error
836 information can be retrieved using lastError().
837
838 \sa lastError() setDatabaseName() setUserName() setPassword()
839 \sa setHostName() setPort() setConnectOptions()
840*/
841
842bool QSqlDatabase::open()
843{
844 return d->driver->open(d->dbname, d->uname, d->pword, d->hname,
845 d->port, d->connOptions);
846}
847
848/*!
849 \overload
850
851 Opens the database connection using the given \a user name and \a
852 password. Returns true on success; otherwise returns false. Error
853 information can be retrieved using the lastError() function.
854
855 This function does not store the password it is given. Instead,
856 the password is passed directly to the driver for opening the
857 connection and it is then discarded.
858
859 \sa lastError()
860*/
861
862bool QSqlDatabase::open(const QString& user, const QString& password)
863{
864 setUserName(user);
865 return d->driver->open(d->dbname, user, password, d->hname,
866 d->port, d->connOptions);
867}
868
869/*!
870 Closes the database connection, freeing any resources acquired, and
871 invalidating any existing QSqlQuery objects that are used with the
872 database.
873
874 This will also affect copies of this QSqlDatabase object.
875
876 \sa removeDatabase()
877*/
878
879void QSqlDatabase::close()
880{
881 d->driver->close();
882}
883
884/*!
885 Returns true if the database connection is currently open;
886 otherwise returns false.
887*/
888
889bool QSqlDatabase::isOpen() const
890{
891 return d->driver->isOpen();
892}
893
894/*!
895 Returns true if there was an error opening the database
896 connection; otherwise returns false. Error information can be
897 retrieved using the lastError() function.
898*/
899
900bool QSqlDatabase::isOpenError() const
901{
902 return d->driver->isOpenError();
903}
904
905/*!
906 Begins a transaction on the database if the driver supports
907 transactions. Returns \c{true} if the operation succeeded.
908 Otherwise it returns \c{false}.
909
910 \sa QSqlDriver::hasFeature(), commit(), rollback()
911*/
912bool QSqlDatabase::transaction()
913{
914 if (!d->driver->hasFeature(QSqlDriver::Transactions))
915 return false;
916 return d->driver->beginTransaction();
917}
918
919/*!
920 Commits a transaction to the database if the driver supports
921 transactions and a transaction() has been started. Returns \c{true}
922 if the operation succeeded. Otherwise it returns \c{false}.
923
924 \note For some databases, the commit will fail and return \c{false}
925 if there is an \l{QSqlQuery::isActive()} {active query} using the
926 database for a \c{SELECT}. Make the query \l{QSqlQuery::isActive()}
927 {inactive} before doing the commit.
928
929 Call lastError() to get information about errors.
930
931 \sa QSqlQuery::isActive() QSqlDriver::hasFeature() rollback()
932*/
933bool QSqlDatabase::commit()
934{
935 if (!d->driver->hasFeature(QSqlDriver::Transactions))
936 return false;
937 return d->driver->commitTransaction();
938}
939
940/*!
941 Rolls back a transaction on the database, if the driver supports
942 transactions and a transaction() has been started. Returns \c{true}
943 if the operation succeeded. Otherwise it returns \c{false}.
944
945 \note For some databases, the rollback will fail and return
946 \c{false} if there is an \l{QSqlQuery::isActive()} {active query}
947 using the database for a \c{SELECT}. Make the query
948 \l{QSqlQuery::isActive()} {inactive} before doing the rollback.
949
950 Call lastError() to get information about errors.
951
952 \sa QSqlQuery::isActive() QSqlDriver::hasFeature() commit()
953*/
954bool QSqlDatabase::rollback()
955{
956 if (!d->driver->hasFeature(QSqlDriver::Transactions))
957 return false;
958 return d->driver->rollbackTransaction();
959}
960
961/*!
962 Sets the connection's database name to \a name. To have effect,
963 the database name must be set \e{before} the connection is
964 \l{open()} {opened}. Alternatively, you can close() the
965 connection, set the database name, and call open() again. \note
966 The \e{database name} is not the \e{connection name}. The
967 connection name must be passed to addDatabase() at connection
968 object create time.
969
970 For the QOCI (Oracle) driver, the database name is the TNS
971 Service Name.
972
973 For the QODBC driver, the \a name can either be a DSN, a DSN
974 filename (in which case the file must have a \c .dsn extension),
975 or a connection string.
976
977 For example, Microsoft Access users can use the following
978 connection string to open an \c .mdb file directly, instead of
979 having to create a DSN entry in the ODBC manager:
980
981 \snippet doc/src/snippets/code/src_sql_kernel_qsqldatabase.cpp 3
982
983 There is no default value.
984
985 \sa databaseName() setUserName() setPassword() setHostName()
986 \sa setPort() setConnectOptions() open()
987*/
988
989void QSqlDatabase::setDatabaseName(const QString& name)
990{
991 if (isValid())
992 d->dbname = name;
993}
994
995/*!
996 Sets the connection's user name to \a name. To have effect, the
997 user name must be set \e{before} the connection is \l{open()}
998 {opened}. Alternatively, you can close() the connection, set the
999 user name, and call open() again.
1000
1001 There is no default value.
1002
1003 \sa userName() setDatabaseName() setPassword() setHostName()
1004 \sa setPort() setConnectOptions() open()
1005*/
1006
1007void QSqlDatabase::setUserName(const QString& name)
1008{
1009 if (isValid())
1010 d->uname = name;
1011}
1012
1013/*!
1014 Sets the connection's password to \a password. To have effect, the
1015 password must be set \e{before} the connection is \l{open()}
1016 {opened}. Alternatively, you can close() the connection, set the
1017 password, and call open() again.
1018
1019 There is no default value.
1020
1021 \warning This function stores the password in plain text within
1022 Qt. Use the open() call that takes a password as parameter to
1023 avoid this behavior.
1024
1025 \sa password() setUserName() setDatabaseName() setHostName()
1026 \sa setPort() setConnectOptions() open()
1027*/
1028
1029void QSqlDatabase::setPassword(const QString& password)
1030{
1031 if (isValid())
1032 d->pword = password;
1033}
1034
1035/*!
1036 Sets the connection's host name to \a host. To have effect, the
1037 host name must be set \e{before} the connection is \l{open()}
1038 {opened}. Alternatively, you can close() the connection, set the
1039 host name, and call open() again.
1040
1041 There is no default value.
1042
1043 \sa hostName() setUserName() setPassword() setDatabaseName()
1044 \sa setPort() setConnectOptions() open()
1045*/
1046
1047void QSqlDatabase::setHostName(const QString& host)
1048{
1049 if (isValid())
1050 d->hname = host;
1051}
1052
1053/*!
1054 Sets the connection's port number to \a port. To have effect, the
1055 port number must be set \e{before} the connection is \l{open()}
1056 {opened}. Alternatively, you can close() the connection, set the
1057 port number, and call open() again..
1058
1059 There is no default value.
1060
1061 \sa port() setUserName() setPassword() setHostName()
1062 \sa setDatabaseName() setConnectOptions() open()
1063*/
1064
1065void QSqlDatabase::setPort(int port)
1066{
1067 if (isValid())
1068 d->port = port;
1069}
1070
1071/*!
1072 Returns the connection's database name, which may be empty.
1073 \note The database name is not the connection name.
1074
1075 \sa setDatabaseName()
1076*/
1077QString QSqlDatabase::databaseName() const
1078{
1079 return d->dbname;
1080}
1081
1082/*!
1083 Returns the connection's user name; it may be empty.
1084
1085 \sa setUserName()
1086*/
1087QString QSqlDatabase::userName() const
1088{
1089 return d->uname;
1090}
1091
1092/*!
1093 Returns the connection's password. If the password was not set
1094 with setPassword(), and if the password was given in the open()
1095 call, or if no password was used, an empty string is returned.
1096*/
1097QString QSqlDatabase::password() const
1098{
1099 return d->pword;
1100}
1101
1102/*!
1103 Returns the connection's host name; it may be empty.
1104
1105 \sa setHostName()
1106*/
1107QString QSqlDatabase::hostName() const
1108{
1109 return d->hname;
1110}
1111
1112/*!
1113 Returns the connection's driver name.
1114
1115 \sa addDatabase(), driver()
1116*/
1117QString QSqlDatabase::driverName() const
1118{
1119 return d->drvName;
1120}
1121
1122/*!
1123 Returns the connection's port number. The value is undefined if
1124 the port number has not been set.
1125
1126 \sa setPort()
1127*/
1128int QSqlDatabase::port() const
1129{
1130 return d->port;
1131}
1132
1133/*!
1134 Returns the database driver used to access the database
1135 connection.
1136
1137 \sa addDatabase() drivers()
1138*/
1139
1140QSqlDriver* QSqlDatabase::driver() const
1141{
1142 return d->driver;
1143}
1144
1145/*!
1146 Returns information about the last error that occurred on the
1147 database.
1148
1149 Failures that occur in conjunction with an individual query are
1150 reported by QSqlQuery::lastError().
1151
1152 \sa QSqlError, QSqlQuery::lastError()
1153*/
1154
1155QSqlError QSqlDatabase::lastError() const
1156{
1157 return d->driver->lastError();
1158}
1159
1160
1161/*!
1162 Returns a list of the database's tables, system tables and views,
1163 as specified by the parameter \a type.
1164
1165 \sa primaryIndex(), record()
1166*/
1167
1168QStringList QSqlDatabase::tables(QSql::TableType type) const
1169{
1170 return d->driver->tables(type);
1171}
1172
1173/*!
1174 Returns the primary index for table \a tablename. If no primary
1175 index exists an empty QSqlIndex is returned.
1176
1177 \sa tables(), record()
1178*/
1179
1180QSqlIndex QSqlDatabase::primaryIndex(const QString& tablename) const
1181{
1182 return d->driver->primaryIndex(tablename);
1183}
1184
1185
1186/*!
1187 Returns a QSqlRecord populated with the names of all the fields in
1188 the table (or view) called \a tablename. The order in which the
1189 fields appear in the record is undefined. If no such table (or
1190 view) exists, an empty record is returned.
1191*/
1192
1193QSqlRecord QSqlDatabase::record(const QString& tablename) const
1194{
1195 return d->driver->record(tablename);
1196}
1197
1198
1199/*!
1200 Sets database-specific \a options. This must be done before the
1201 connection is opened or it has no effect (or you can close() the
1202 connection, call this function and open() the connection again).
1203
1204 The format of the \a options string is a semicolon separated list
1205 of option names or option=value pairs. The options depend on the
1206 database client used:
1207
1208 \table
1209 \header \i ODBC \i MySQL \i PostgreSQL
1210 \row
1211
1212 \i
1213 \list
1214 \i SQL_ATTR_ACCESS_MODE
1215 \i SQL_ATTR_LOGIN_TIMEOUT
1216 \i SQL_ATTR_CONNECTION_TIMEOUT
1217 \i SQL_ATTR_CURRENT_CATALOG
1218 \i SQL_ATTR_METADATA_ID
1219 \i SQL_ATTR_PACKET_SIZE
1220 \i SQL_ATTR_TRACEFILE
1221 \i SQL_ATTR_TRACE
1222 \i SQL_ATTR_CONNECTION_POOLING
1223 \i SQL_ATTR_ODBC_VERSION
1224 \endlist
1225
1226 \i
1227 \list
1228 \i CLIENT_COMPRESS
1229 \i CLIENT_FOUND_ROWS
1230 \i CLIENT_IGNORE_SPACE
1231 \i CLIENT_SSL
1232 \i CLIENT_ODBC
1233 \i CLIENT_NO_SCHEMA
1234 \i CLIENT_INTERACTIVE
1235 \i UNIX_SOCKET
1236 \i MYSQL_OPT_RECONNECT
1237 \endlist
1238
1239 \i
1240 \list
1241 \i connect_timeout
1242 \i options
1243 \i tty
1244 \i requiressl
1245 \i service
1246 \endlist
1247
1248 \header \i DB2 \i OCI \i TDS
1249 \row
1250
1251 \i
1252 \list
1253 \i SQL_ATTR_ACCESS_MODE
1254 \i SQL_ATTR_LOGIN_TIMEOUT
1255 \endlist
1256
1257 \i
1258 \list
1259 \i OCI_ATTR_PREFETCH_ROWS
1260 \i OCI_ATTR_PREFETCH_MEMORY
1261 \endlist
1262
1263 \i
1264 \e none
1265
1266 \header \i SQLite \i Interbase
1267 \row
1268
1269 \i
1270 \list
1271 \i QSQLITE_BUSY_TIMEOUT
1272 \i QSQLITE_OPEN_READONLY
1273 \i QSQLITE_ENABLE_SHARED_CACHE
1274 \endlist
1275
1276 \i
1277 \list
1278 \i ISC_DPB_LC_CTYPE
1279 \i ISC_DPB_SQL_ROLE_NAME
1280 \endlist
1281
1282 \endtable
1283
1284 Examples:
1285 \snippet doc/src/snippets/code/src_sql_kernel_qsqldatabase.cpp 4
1286
1287 Refer to the client library documentation for more information
1288 about the different options.
1289
1290 \sa connectOptions()
1291*/
1292
1293void QSqlDatabase::setConnectOptions(const QString &options)
1294{
1295 if (isValid())
1296 d->connOptions = options;
1297}
1298
1299/*!
1300 Returns the connection options string used for this connection.
1301 The string may be empty.
1302
1303 \sa setConnectOptions()
1304 */
1305QString QSqlDatabase::connectOptions() const
1306{
1307 return d->connOptions;
1308}
1309
1310/*!
1311 Returns true if a driver called \a name is available; otherwise
1312 returns false.
1313
1314 \sa drivers()
1315*/
1316
1317bool QSqlDatabase::isDriverAvailable(const QString& name)
1318{
1319 return drivers().contains(name);
1320}
1321
1322/*! \fn QSqlDatabase QSqlDatabase::addDatabase(QSqlDriver* driver, const QString& connectionName)
1323
1324 This overload is useful when you want to create a database
1325 connection with a \l{QSqlDriver} {driver} you instantiated
1326 yourself. It might be your own database driver, or you might just
1327 need to instantiate one of the Qt drivers yourself. If you do
1328 this, it is recommended that you include the driver code in your
1329 application. For example, you can create a PostgreSQL connection
1330 with your own QPSQL driver like this:
1331
1332 \snippet doc/src/snippets/code/src_sql_kernel_qsqldatabase.cpp 5
1333 \codeline
1334 \snippet doc/src/snippets/code/src_sql_kernel_qsqldatabase.cpp 6
1335
1336 The above code sets up a PostgreSQL connection and instantiates a
1337 QPSQLDriver object. Next, addDatabase() is called to add the
1338 connection to the known connections so that it can be used by the
1339 Qt SQL classes. When a driver is instantiated with a connection
1340 handle (or set of handles), Qt assumes that you have already
1341 opened the database connection.
1342
1343 \note We assume that \c qtdir is the directory where Qt is
1344 installed. This will pull in the code that is needed to use the
1345 PostgreSQL client library and to instantiate a QPSQLDriver object,
1346 assuming that you have the PostgreSQL headers somewhere in your
1347 include search path.
1348
1349 Remember that you must link your application against the database
1350 client library. Make sure the client library is in your linker's
1351 search path, and add lines like these to your \c{.pro} file:
1352
1353 \snippet doc/src/snippets/code/src_sql_kernel_qsqldatabase.cpp 7
1354
1355 The method described works for all the supplied drivers. The only
1356 difference will be in the driver constructor arguments. Here is a
1357 table of the drivers included with Qt, their source code files,
1358 and their constructor arguments:
1359
1360 \table
1361 \header \i Driver \i Class name \i Constructor arguments \i File to include
1362 \row
1363 \i QPSQL
1364 \i QPSQLDriver
1365 \i PGconn *connection
1366 \i \c qsql_psql.cpp
1367 \row
1368 \i QMYSQL
1369 \i QMYSQLDriver
1370 \i MYSQL *connection
1371 \i \c qsql_mysql.cpp
1372 \row
1373 \i QOCI
1374 \i QOCIDriver
1375 \i OCIEnv *environment, OCISvcCtx *serviceContext
1376 \i \c qsql_oci.cpp
1377 \row
1378 \i QODBC
1379 \i QODBCDriver
1380 \i SQLHANDLE environment, SQLHANDLE connection
1381 \i \c qsql_odbc.cpp
1382 \row
1383 \i QDB2
1384 \i QDB2
1385 \i SQLHANDLE environment, SQLHANDLE connection
1386 \i \c qsql_db2.cpp
1387 \row
1388 \i QTDS
1389 \i QTDSDriver
1390 \i LOGINREC *loginRecord, DBPROCESS *dbProcess, const QString &hostName
1391 \i \c qsql_tds.cpp
1392 \row
1393 \i QSQLITE
1394 \i QSQLiteDriver
1395 \i sqlite *connection
1396 \i \c qsql_sqlite.cpp
1397 \row
1398 \i QIBASE
1399 \i QIBaseDriver
1400 \i isc_db_handle connection
1401 \i \c qsql_ibase.cpp
1402 \endtable
1403
1404 The host name (or service name) is needed when constructing the
1405 QTDSDriver for creating new connections for internal queries. This
1406 is to prevent blocking when several QSqlQuery objects are used
1407 simultaneously.
1408
1409 \warning Adding a database connection with the same connection
1410 name as an existing connection, causes the existing connection to
1411 be replaced by the new one.
1412
1413 \warning The SQL framework takes ownership of the \a driver. It
1414 must not be deleted. To remove the connection, use
1415 removeDatabase().
1416
1417 \sa drivers()
1418*/
1419QSqlDatabase QSqlDatabase::addDatabase(QSqlDriver* driver, const QString& connectionName)
1420{
1421 QSqlDatabase db(driver);
1422 QSqlDatabasePrivate::addDatabase(db, connectionName);
1423 return db;
1424}
1425
1426/*!
1427 Returns true if the QSqlDatabase has a valid driver.
1428
1429 Example:
1430 \snippet doc/src/snippets/code/src_sql_kernel_qsqldatabase.cpp 8
1431*/
1432bool QSqlDatabase::isValid() const
1433{
1434 return d->driver && d->driver != d->shared_null()->driver;
1435}
1436
1437#ifdef QT3_SUPPORT
1438/*!
1439 Use query.record() instead.
1440*/
1441QSqlRecord QSqlDatabase::record(const QSqlQuery& query) const
1442{ return query.record(); }
1443
1444/*!
1445 Use query.record() instead.
1446*/
1447QSqlRecord QSqlDatabase::recordInfo(const QSqlQuery& query) const
1448{ return query.record(); }
1449
1450/*!
1451 \fn QSqlRecord QSqlDatabase::recordInfo(const QString& tablename) const
1452
1453 Use record() instead.
1454*/
1455#endif
1456
1457/*!
1458 Clones the database connection \a other and and stores it as \a
1459 connectionName. All the settings from the original database, e.g.
1460 databaseName(), hostName(), etc., are copied across. Does nothing
1461 if \a other is an invalid database. Returns the newly created
1462 database connection.
1463
1464 \note The new connection has not been opened. Before using the new
1465 connection, you must call open().
1466*/
1467QSqlDatabase QSqlDatabase::cloneDatabase(const QSqlDatabase &other, const QString &connectionName)
1468{
1469 if (!other.isValid())
1470 return QSqlDatabase();
1471
1472 QSqlDatabase db(other.driverName());
1473 db.d->copy(other.d);
1474 QSqlDatabasePrivate::addDatabase(db, connectionName);
1475 return db;
1476}
1477
1478/*!
1479 \since 4.4
1480
1481 Returns the connection name, which may be empty. \note The
1482 connection name is not the \l{databaseName()} {database name}.
1483
1484 \sa addDatabase()
1485*/
1486QString QSqlDatabase::connectionName() const
1487{
1488 return d->connName;
1489}
1490
1491/*!
1492 \since 4.6
1493
1494 Sets the default numerical precision policy used by queries created
1495 on this database connection to \a precisionPolicy.
1496
1497 Note: Drivers that don't support fetching numerical values with low
1498 precision will ignore the precision policy. You can use
1499 QSqlDriver::hasFeature() to find out whether a driver supports this
1500 feature.
1501
1502 Note: Setting the default precision policy to \a precisionPolicy
1503 doesn't affect any currently active queries.
1504
1505 \sa QSql::NumericalPrecisionPolicy, numericalPrecisionPolicy(),
1506 QSqlQuery::setNumericalPrecisionPolicy(), QSqlQuery::numericalPrecisionPolicy()
1507*/
1508void QSqlDatabase::setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy precisionPolicy)
1509{
1510 if(driver())
1511 driver()->setNumericalPrecisionPolicy(precisionPolicy);
1512 d->precisionPolicy = precisionPolicy;
1513}
1514
1515/*!
1516 \since 4.6
1517
1518 Returns the current default precision policy for the database connection.
1519
1520 \sa QSql::NumericalPrecisionPolicy, setNumericalPrecisionPolicy(),
1521 QSqlQuery::numericalPrecisionPolicy(), QSqlQuery::setNumericalPrecisionPolicy()
1522*/
1523QSql::NumericalPrecisionPolicy QSqlDatabase::numericalPrecisionPolicy() const
1524{
1525 if(driver())
1526 return driver()->numericalPrecisionPolicy();
1527 else
1528 return d->precisionPolicy;
1529}
1530
1531
1532#ifndef QT_NO_DEBUG_STREAM
1533QDebug operator<<(QDebug dbg, const QSqlDatabase &d)
1534{
1535 if (!d.isValid()) {
1536 dbg.nospace() << "QSqlDatabase(invalid)";
1537 return dbg.space();
1538 }
1539
1540 dbg.nospace() << "QSqlDatabase(driver=\"" << d.driverName() << "\", database=\""
1541 << d.databaseName() << "\", host=\"" << d.hostName() << "\", port=" << d.port()
1542 << ", user=\"" << d.userName() << "\", open=" << d.isOpen() << ")";
1543 return dbg.space();
1544}
1545#endif
1546
1547QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.