?? qsqldatabase.cpp
字號:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the QtSql module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qsqldatabase.h"#include "qsqlquery.h"#ifdef Q_OS_WIN32// Conflicting declarations of LPCBYTE in sqlfront.h and winscard.h#define _WINSCARD_H_#endif#ifdef QT_SQL_PSQL#include "../drivers/psql/qsql_psql.h"#endif#ifdef QT_SQL_MYSQL#include "../drivers/mysql/qsql_mysql.h"#endif#ifdef QT_SQL_ODBC#include "../drivers/odbc/qsql_odbc.h"#endif#ifdef QT_SQL_OCI#include "../drivers/oci/qsql_oci.h"#endif#ifdef QT_SQL_TDS#include "../drivers/tds/qsql_tds.h"#endif#ifdef QT_SQL_DB2#include "../drivers/db2/qsql_db2.h"#endif#ifdef QT_SQL_SQLITE#include "../drivers/sqlite/qsql_sqlite.h"#endif#ifdef QT_SQL_SQLITE2#include "../drivers/sqlite2/qsql_sqlite2.h"#endif#ifdef QT_SQL_IBASE#include "../drivers/ibase/qsql_ibase.h"#endif#include "qdebug.h"#include "qcoreapplication.h"#include "qreadwritelock.h"#include "qsqlresult.h"#include "qsqldriver.h"#include "qsqldriverplugin.h"#include "qsqlindex.h"#include "private/qfactoryloader_p.h"#include "private/qsqlnulldriver_p.h"#include "qmutex.h"#include "qhash.h"#include <stdlib.h>#ifndef QT_NO_LIBRARYQ_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, (QSqlDriverFactoryInterface_iid, QCoreApplication::libraryPaths(), QLatin1String("/sqldrivers")))#endifQT_STATIC_CONST_IMPL char *QSqlDatabase::defaultConnection = "qt_sql_default_connection";typedef QHash<QString, QSqlDriverCreatorBase*> DriverDict;class QConnectionDict: public QHash<QString, QSqlDatabase>{public: inline bool contains_ts(const QString &key) { QReadLocker locker(&lock); return contains(key); } inline QStringList keys_ts() const { QReadLocker locker(&lock); return keys(); } mutable QReadWriteLock lock;};class QSqlDatabasePrivate{public: QSqlDatabasePrivate(QSqlDriver *dr = 0): driver(dr), port(-1) { ref = 1; } QSqlDatabasePrivate(const QSqlDatabasePrivate &other); ~QSqlDatabasePrivate(); void init(const QString& type); void copy(const QSqlDatabasePrivate *other); void disable(); QAtomic ref; QSqlDriver* driver; QString dbname; QString uname; QString pword; QString hname; QString drvName; int port; QString connOptions; static QSqlDatabasePrivate *shared_null(); static QSqlDatabase database(const QString& name, bool open); static void addDatabase(const QSqlDatabase &db, const QString & name); static void removeDatabase(const QString& name); static void invalidateDb(const QSqlDatabase &db, const QString &name); static DriverDict &driverDict(); Q_GLOBAL_STATIC(QConnectionDict, dbDict) static void cleanConnections();};QSqlDatabasePrivate::QSqlDatabasePrivate(const QSqlDatabasePrivate &other){ ref = 1; dbname = other.dbname; uname = other.uname; pword = other.pword; hname = other.hname; drvName = other.drvName; port = other.port; connOptions = other.connOptions; driver = other.driver;}QSqlDatabasePrivate::~QSqlDatabasePrivate(){ if (driver != shared_null()->driver) delete driver;}void QSqlDatabasePrivate::cleanConnections(){ QConnectionDict *dict = dbDict(); Q_ASSERT(dict); QWriteLocker locker(&dict->lock); QConnectionDict::iterator it = dict->begin(); while (it != dict->end()) { invalidateDb(it.value(), it.key()); ++it; } dict->clear();}static bool qDriverDictInit = false;static void cleanDriverDict(){ qDeleteAll(QSqlDatabasePrivate::driverDict()); QSqlDatabasePrivate::driverDict().clear(); QSqlDatabasePrivate::cleanConnections(); qDriverDictInit = false;}DriverDict &QSqlDatabasePrivate::driverDict(){ static DriverDict dict; if (!qDriverDictInit) { qDriverDictInit = true; qAddPostRoutine(cleanDriverDict); } return dict;}QSqlDatabasePrivate *QSqlDatabasePrivate::shared_null(){ static QSqlNullDriver dr; static QSqlDatabasePrivate n(&dr); return &n;}void QSqlDatabasePrivate::invalidateDb(const QSqlDatabase &db, const QString &name){ if (db.d->ref != 1) { qWarning("QSqlDatabasePrivate::removeDatabase: connection '%s' is still in use, " "all queries will cease to work.", name.toLocal8Bit().constData()); db.d->disable(); }}void QSqlDatabasePrivate::removeDatabase(const QString &name){ QConnectionDict *dict = dbDict(); Q_ASSERT(dict); QWriteLocker locker(&dict->lock); if (!dict->contains(name)) return; invalidateDb(dict->take(name), name);}void QSqlDatabasePrivate::addDatabase(const QSqlDatabase &db, const QString &name){ QConnectionDict *dict = dbDict(); Q_ASSERT(dict); QWriteLocker locker(&dict->lock); if (dict->contains(name)) { invalidateDb(dict->take(name), name); qWarning("QSqlDatabasePrivate::addDatabase: duplicate connection name '%s', old " "connection removed.", name.toLocal8Bit().data()); } dict->insert(name, db);}/*! \internal*/QSqlDatabase QSqlDatabasePrivate::database(const QString& name, bool open){ const QConnectionDict *dict = dbDict(); Q_ASSERT(dict); dict->lock.lockForRead(); QSqlDatabase db = dict->value(name); dict->lock.unlock(); if (db.isValid() && !db.isOpen() && open) { db.open(); if (!db.isOpen()) qWarning("QSqlDatabasePrivate::database: unable to open database: %s", db.lastError().text().toLocal8Bit().data()); } return db;}/*! \internal Copies the connection data from \a other.*/void QSqlDatabasePrivate::copy(const QSqlDatabasePrivate *other){ dbname = other->dbname; uname = other->uname; pword = other->pword; hname = other->hname; drvName = other->drvName; port = other->port; connOptions = other->connOptions;}void QSqlDatabasePrivate::disable(){ if (driver != shared_null()->driver) { delete driver; driver = shared_null()->driver; }}/*! \class QSqlDriverCreatorBase \brief The QSqlDriverCreatorBase class is the base class for SQL driver factories. \ingroup database \module sql Reimplement createObject() to return an instance of the specific QSqlDriver subclass that you want to provide. See QSqlDatabase::registerSqlDriver() for details. \sa QSqlDriverCreator*//*! \fn QSqlDriverCreatorBase::~QSqlDriverCreatorBase() Destroys the SQL driver creator object.*//*! \fn QSqlDriver *QSqlDriverCreatorBase::createObject() const Reimplement this function to returns a new instance of a QSqlDriver subclass.*//*! \class QSqlDriverCreator \brief The QSqlDriverCreator class is a template class that provides a SQL driver factory for a specific driver type. \ingroup database \module sql QSqlDriverCreator<T> instantiates objects of type T, where T is a QSqlDriver subclass. See QSqlDatabase::registerSqlDriver() for details.*//*! \fn QSqlDriver *QSqlDriverCreator::createObject() const \reimp*//*! \class QSqlDatabase \brief The QSqlDatabase class represents a connection to a database. \ingroup database \mainclass \module sql The QSqlDatabase class provides an abstract interface for accessing database backends. It relies on database-specific \l{QSqlDriver}s to actually access and manipulate data. The following code shows how to initialize a connection: \quotefromfile snippets/sqldatabase/sqldatabase.cpp \skipto QSqlDatabase_snippet \skipto QSqlDatabase db = \printuntil db.open() Once a QSqlDatabase object has been created you can set the connection parameters with setDatabaseName(), setUserName(), setPassword(), setHostName(), setPort(), and setConnectOptions(). Once the parameters have been set up you can call open() to open the connection. The connection defined above is a nameless connection. If is the default connection and can be accessed using database() later on: \skipto QSqlDatabase db = \printline QSqlDatabase db = To make programming more convenient, QSqlDatabase is a value class. Any changes done to a database connection through one QSqlDatabase object will affect other QSqlDatabase objects representing the same connection. Call cloneDatabase() if you want to create an independent database connection based on an existing one. If you need multiple database connections simultaneously, specify an arbitrary name to addDatabase() and database(). Call removeDatabase() to remove connections. QSqlDatabase will output a warning if you try to remove a connection referenced by other QSqlDatabase objects. Use contains() to see if a given connection name is in the list of connections. Once a connection is established you can see what tables the database offers with tables(), find the primary index for a table with primaryIndex(), get meta-information about a table's fields (e.g., their names) with record(), and execute a query with exec(). If transactions are supported, you can use transaction() to start a transaction, and then commit() or rollback() to complete it. You can find out whether transactions are supported using QSqlDriver::hasFeature(). If an error occurred, it is given by lastError(). The names of the underlying SQL drivers are available from drivers(); you can check for a particular driver with isDriverAvailable(). If you have created your own custom driver, you can register it with registerSqlDriver(). \sa QSqlDriver, QSqlQuery, {QtSql Module}*//*! \threadsafe Adds a database to the list of database connections using the driver \a type and the connection name \a connectionName. If there already exists a database connection called \a connectionName, that connection is removed. The database connection is referred to by \a connectionName. The newly added database connection is returned. If \a connectionName is not specified, the newly added database connection becomes the default database connection for the application, and subsequent calls to database() without a database name parameter will return a reference to it. If \a connectionName is given, use database(\a connectionName) to retrieve a pointer to the database connection. \warning If you add a database with the same name as an existing database, the new database will replace the old one. This will happen automatically if you call this function more than once without specifying \a connectionName. To make use of the connection, you will need to set it up, for example by calling some or all of setDatabaseName(), setUserName(), setPassword(), setHostName(), setPort(), and setConnectOptions(), and then you'll need to open() the connection. \sa database() removeDatabase()*/QSqlDatabase QSqlDatabase::addDatabase(const QString &type, const QString &connectionName){ QSqlDatabase db(type); QSqlDatabasePrivate::addDatabase(db, connectionName); return db;}/*! \threadsafe Returns the database connection called \a connectionName. The database connection must have been previously added with addDatabase(). If \a open is true (the default) and the database connection is not already open it is opened now. If no \a connectionName is specified the default connection is used. If \a connectionName does not exist in the list of databases, an invalid connection is returned. \sa isOpen()*/QSqlDatabase QSqlDatabase::database(const QString& connectionName, bool open){ return QSqlDatabasePrivate::database(connectionName, open);}/*! \threadsafe Removes the database connection \a connectionName from the list of database connections. \warning There should be no open queries on the database connection when this function is called, otherwise a resource leak will occur. Example: \code // WRONG QSqlDatabase db = QSqlDatabase::database("sales"); QSqlQuery query("SELECT NAME, DOB FROM EMPLOYEES", db); QSqlDatabase::removeDatabase("sales"); // will output a warning // "db" is now a dangling invalid database connection, // "query" contains an invalid result set \endcode The correct way to do it: \code { QSqlDatabase db = QSqlDatabase::database("sales"); QSqlQuery query("SELECT NAME, DOB FROM EMPLOYEES", db); } // Both "db" and "query" are destroyed because they are out of scope QSqlDatabase::removeDatabase("sales"); // correct \endcode \sa database()*/void QSqlDatabase::removeDatabase(const QString& connectionName){ QSqlDatabasePrivate::removeDatabase(connectionName);}/*! Returns a list of all the available database drivers. \sa registerSqlDriver()*/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -