diff options
Diffstat (limited to 'src/sql/drivers')
27 files changed, 353 insertions, 273 deletions
diff --git a/src/sql/drivers/db2/qsql_db2.cpp b/src/sql/drivers/db2/qsql_db2.cpp index 9406861d4c..50a9af23bc 100644 --- a/src/sql/drivers/db2/qsql_db2.cpp +++ b/src/sql/drivers/db2/qsql_db2.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include "qsql_db2.h" +#include "qsql_db2_p.h" #include <qcoreapplication.h> #include <qdatetime.h> #include <qsqlfield.h> diff --git a/src/sql/drivers/db2/qsql_db2.pri b/src/sql/drivers/db2/qsql_db2.pri index 963732aaee..c9e65e2c2e 100644 --- a/src/sql/drivers/db2/qsql_db2.pri +++ b/src/sql/drivers/db2/qsql_db2.pri @@ -1,4 +1,4 @@ -HEADERS += $$PWD/qsql_db2.h +HEADERS += $$PWD/qsql_db2_p.h SOURCES += $$PWD/qsql_db2.cpp unix { diff --git a/src/sql/drivers/db2/qsql_db2.h b/src/sql/drivers/db2/qsql_db2_p.h index 4e25c317eb..6a5363740b 100644 --- a/src/sql/drivers/db2/qsql_db2.h +++ b/src/sql/drivers/db2/qsql_db2_p.h @@ -42,6 +42,17 @@ #ifndef QSQL_DB2_H #define QSQL_DB2_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #ifdef QT_PLUGIN #define Q_EXPORT_SQLDRIVER_DB2 #else @@ -51,15 +62,8 @@ #include <QtSql/qsqlresult.h> #include <QtSql/qsqldriver.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE -#if 0 -#pragma qt_no_master_include -#pragma qt_sync_stop_processing -#endif - class QDB2Driver; class QDB2DriverPrivate; class QDB2ResultPrivate; @@ -126,6 +130,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif // QSQL_DB2_H diff --git a/src/sql/drivers/ibase/qsql_ibase.cpp b/src/sql/drivers/ibase/qsql_ibase.cpp index 5fd07318ec..abf6a74c3e 100644 --- a/src/sql/drivers/ibase/qsql_ibase.cpp +++ b/src/sql/drivers/ibase/qsql_ibase.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include "qsql_ibase.h" +#include "qsql_ibase_p.h" #include <qcoreapplication.h> #include <qdatetime.h> #include <qvariant.h> @@ -47,6 +47,7 @@ #include <qsqlfield.h> #include <qsqlindex.h> #include <qsqlquery.h> +#include <QtSql/private/qsqlcachedresult_p.h> #include <qlist.h> #include <qvector.h> #include <qtextcodec.h> @@ -346,6 +347,31 @@ static void qFreeEventBuffer(QIBaseEventBuffer* eBuffer) delete eBuffer; } +class QIBaseResultPrivate; + +class QIBaseResult : public QSqlCachedResult +{ + friend class QIBaseResultPrivate; + +public: + explicit QIBaseResult(const QIBaseDriver* db); + virtual ~QIBaseResult(); + + bool prepare(const QString& query); + bool exec(); + QVariant handle() const; + +protected: + bool gotoNext(QSqlCachedResult::ValueCache& row, int rowIdx); + bool reset (const QString& query); + int size(); + int numRowsAffected(); + QSqlRecord record() const; + +private: + QIBaseResultPrivate* d; +}; + class QIBaseResultPrivate { public: diff --git a/src/sql/drivers/ibase/qsql_ibase.pri b/src/sql/drivers/ibase/qsql_ibase.pri index 26017e8727..ef3b68d34e 100644 --- a/src/sql/drivers/ibase/qsql_ibase.pri +++ b/src/sql/drivers/ibase/qsql_ibase.pri @@ -1,4 +1,4 @@ -HEADERS += $$PWD/qsql_ibase.h +HEADERS += $$PWD/qsql_ibase_p.h SOURCES += $$PWD/qsql_ibase.cpp unix { diff --git a/src/sql/drivers/ibase/qsql_ibase.h b/src/sql/drivers/ibase/qsql_ibase_p.h index 2ce20966c6..b2560ca17c 100644 --- a/src/sql/drivers/ibase/qsql_ibase.h +++ b/src/sql/drivers/ibase/qsql_ibase_p.h @@ -42,47 +42,26 @@ #ifndef QSQL_IBASE_H #define QSQL_IBASE_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtSql/qsqlresult.h> #include <QtSql/qsqldriver.h> -#include <QtSql/private/qsqlcachedresult_p.h> #include <ibase.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE -#if 0 -#pragma qt_no_master_include -#pragma qt_sync_stop_processing -#endif - class QIBaseDriverPrivate; -class QIBaseResultPrivate; class QIBaseDriver; -class QIBaseResult : public QSqlCachedResult -{ - friend class QIBaseResultPrivate; - -public: - explicit QIBaseResult(const QIBaseDriver* db); - virtual ~QIBaseResult(); - - bool prepare(const QString& query); - bool exec(); - QVariant handle() const; - -protected: - bool gotoNext(QSqlCachedResult::ValueCache& row, int rowIdx); - bool reset (const QString& query); - int size(); - int numRowsAffected(); - QSqlRecord record() const; - -private: - QIBaseResultPrivate* d; -}; - class QIBaseDriver : public QSqlDriver { Q_OBJECT @@ -132,5 +111,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER #endif // QSQL_IBASE_H diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp index b4aa5cd4cc..04ba450d46 100644 --- a/src/sql/drivers/mysql/qsql_mysql.cpp +++ b/src/sql/drivers/mysql/qsql_mysql.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include "qsql_mysql.h" +#include "qsql_mysql_p.h" #include <qcoreapplication.h> #include <qvariant.h> diff --git a/src/sql/drivers/mysql/qsql_mysql.pri b/src/sql/drivers/mysql/qsql_mysql.pri index 0423eb4ed9..50f49ca548 100644 --- a/src/sql/drivers/mysql/qsql_mysql.pri +++ b/src/sql/drivers/mysql/qsql_mysql.pri @@ -1,4 +1,4 @@ -HEADERS += $$PWD/qsql_mysql.h +HEADERS += $$PWD/qsql_mysql_p.h SOURCES += $$PWD/qsql_mysql.cpp !isEmpty(MYSQL_PATH) { diff --git a/src/sql/drivers/mysql/qsql_mysql.h b/src/sql/drivers/mysql/qsql_mysql_p.h index 37e18c8fb1..c23bcd92d7 100644 --- a/src/sql/drivers/mysql/qsql_mysql.h +++ b/src/sql/drivers/mysql/qsql_mysql_p.h @@ -42,6 +42,17 @@ #ifndef QSQL_MYSQL_H #define QSQL_MYSQL_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtSql/qsqldriver.h> #include <QtSql/qsqlresult.h> @@ -57,15 +68,8 @@ #define Q_EXPORT_SQLDRIVER_MYSQL Q_SQL_EXPORT #endif -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE -#if 0 -#pragma qt_no_master_include -#pragma qt_sync_stop_processing -#endif - class QMYSQLDriverPrivate; class QMYSQLResultPrivate; class QMYSQLDriver; @@ -142,6 +146,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif // QSQL_MYSQL_H diff --git a/src/sql/drivers/oci/qsql_oci.cpp b/src/sql/drivers/oci/qsql_oci.cpp index e2bb9a4eaf..8a6161d816 100644 --- a/src/sql/drivers/oci/qsql_oci.cpp +++ b/src/sql/drivers/oci/qsql_oci.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include "qsql_oci.h" +#include "qsql_oci_p.h" #include <qcoreapplication.h> #include <qvariant.h> @@ -51,6 +51,7 @@ #include <qsqlfield.h> #include <qsqlindex.h> #include <qsqlquery.h> +#include <QtSql/private/qsqlcachedresult_p.h> #include <qstringlist.h> #include <qvarlengtharray.h> #include <qvector.h> @@ -162,6 +163,33 @@ Q_DECLARE_METATYPE(QOCIRowIdPointer) QT_END_INCLUDE_NAMESPACE class QOCICols; +struct QOCIResultPrivate; + +class Q_EXPORT_SQLDRIVER_OCI QOCIResult : public QSqlCachedResult +{ + friend class QOCIDriver; + friend struct QOCIResultPrivate; + friend class QOCICols; +public: + QOCIResult(const QOCIDriver * db, const QOCIDriverPrivate* p); + ~QOCIResult(); + bool prepare(const QString& query); + bool exec(); + QVariant handle() const; + +protected: + bool gotoNext(ValueCache &values, int index); + bool reset (const QString& query); + int size(); + int numRowsAffected(); + QSqlRecord record() const; + QVariant lastInsertId() const; + bool execBatch(bool arrayBind = false); + void virtual_hook(int id, void *data); + +private: + QOCIResultPrivate *d; +}; struct QOCIResultPrivate { diff --git a/src/sql/drivers/oci/qsql_oci.pri b/src/sql/drivers/oci/qsql_oci.pri index 60ccc4c227..66ccdb1abb 100644 --- a/src/sql/drivers/oci/qsql_oci.pri +++ b/src/sql/drivers/oci/qsql_oci.pri @@ -1,4 +1,4 @@ -HEADERS += $$PWD/qsql_oci.h +HEADERS += $$PWD/qsql_oci_p.h SOURCES += $$PWD/qsql_oci.cpp unix { @@ -6,4 +6,4 @@ unix { } else { LIBS *= -loci } -macx:QMAKE_LFLAGS += -Wl,-flat_namespace,-U,_environ +mac:QMAKE_LFLAGS += -Wl,-flat_namespace,-U,_environ diff --git a/src/sql/drivers/oci/qsql_oci.h b/src/sql/drivers/oci/qsql_oci_p.h index 2488e696d2..fecc828434 100644 --- a/src/sql/drivers/oci/qsql_oci.h +++ b/src/sql/drivers/oci/qsql_oci_p.h @@ -42,9 +42,19 @@ #ifndef QSQL_OCI_H #define QSQL_OCI_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtSql/qsqlresult.h> #include <QtSql/qsqldriver.h> -#include <QtSql/private/qsqlcachedresult_p.h> #ifdef QT_PLUGIN #define Q_EXPORT_SQLDRIVER_OCI @@ -52,48 +62,14 @@ #define Q_EXPORT_SQLDRIVER_OCI Q_SQL_EXPORT #endif -QT_BEGIN_HEADER - typedef struct OCIEnv OCIEnv; typedef struct OCISvcCtx OCISvcCtx; QT_BEGIN_NAMESPACE -#if 0 -#pragma qt_no_master_include -#pragma qt_sync_stop_processing -#endif - class QOCIDriver; class QOCICols; struct QOCIDriverPrivate; -struct QOCIResultPrivate; - -class Q_EXPORT_SQLDRIVER_OCI QOCIResult : public QSqlCachedResult -{ - friend class QOCIDriver; - friend struct QOCIResultPrivate; - friend class QOCICols; -public: - QOCIResult(const QOCIDriver * db, const QOCIDriverPrivate* p); - ~QOCIResult(); - bool prepare(const QString& query); - bool exec(); - QVariant handle() const; - -protected: - bool gotoNext(ValueCache &values, int index); - bool reset (const QString& query); - int size(); - int numRowsAffected(); - QSqlRecord record() const; - QVariant lastInsertId() const; - bool execBatch(bool arrayBind = false); - void virtual_hook(int id, void *data); - -private: - QOCIResultPrivate *d; -}; class Q_EXPORT_SQLDRIVER_OCI QOCIDriver : public QSqlDriver { @@ -131,6 +107,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif // QSQL_OCI_H diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp index 9517d95fc4..a7f583c3b8 100644 --- a/src/sql/drivers/odbc/qsql_odbc.cpp +++ b/src/sql/drivers/odbc/qsql_odbc.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include "qsql_odbc.h" +#include "qsql_odbc_p.h" #include <qsqlrecord.h> #if defined (Q_OS_WIN32) @@ -115,9 +115,10 @@ class QODBCDriverPrivate { public: enum DefaultCase{Lower, Mixed, Upper, Sensitive}; + enum DBMSType {UnknownDB, MSSqlServer, MySqlServer, PostgreSQL, Oracle, Sybase}; QODBCDriverPrivate() - : hEnv(0), hDbc(0), unicode(false), useSchema(false), disconnectCount(0), datetime_precision(19), isMySqlServer(false), - isMSSqlServer(false), isFreeTDSDriver(false), hasSQLFetchScroll(true), + : hEnv(0), hDbc(0), unicode(false), useSchema(false), disconnectCount(0), datetime_precision(19), + dbmsType(UnknownDB), isFreeTDSDriver(false), hasSQLFetchScroll(true), hasMultiResultSets(false), isQuoteInitialized(false), quote(QLatin1Char('"')) { } @@ -129,15 +130,14 @@ public: bool useSchema; int disconnectCount; int datetime_precision; - bool isMySqlServer; - bool isMSSqlServer; + DBMSType dbmsType; bool isFreeTDSDriver; bool hasSQLFetchScroll; bool hasMultiResultSets; bool checkDriver() const; void checkUnicode(); - void checkSqlServer(); + void checkDBMS(); void checkHasSQLFetchScroll(); void checkHasMultiResults(); void checkSchemaUsage(); @@ -1677,6 +1677,38 @@ QSqlRecord QODBCResult::record() const return d->rInf; } +QVariant QODBCResult::lastInsertId() const +{ + QString sql; + + switch (d->driverPrivate->dbmsType) { + case QODBCDriverPrivate::MSSqlServer: + case QODBCDriverPrivate::Sybase: + sql = QLatin1String("SELECT @@IDENTITY;"); + break; + case QODBCDriverPrivate::MySqlServer: + sql = QLatin1String("SELECT LAST_INSERT_ID();"); + break; + case QODBCDriverPrivate::PostgreSQL: + sql = QLatin1String("SELECT lastval();"); + break; + default: + break; + } + + if (!sql.isEmpty()) { + QSqlQuery qry(driver()->createResult()); + if (qry.exec(sql) && qry.next()) + return qry.value(0); + + qSqlWarning(QLatin1String("QODBCResult::lastInsertId: Unable to get lastInsertId"), d); + } else { + qSqlWarning(QLatin1String("QODBCResult::lastInsertId: not implemented for this DBMS"), d); + } + + return QVariant(); +} + QVariant QODBCResult::handle() const { return QVariant(qRegisterMetaType<SQLHANDLE>("SQLHANDLE"), &d->hStmt); @@ -1797,16 +1829,20 @@ bool QODBCDriver::hasFeature(DriverFeature f) const return true; case QuerySize: case NamedPlaceholders: - case LastInsertId: case BatchOperations: case SimpleLocking: case EventNotifications: case CancelQuery: return false; + case LastInsertId: + return (d->dbmsType == QODBCDriverPrivate::MSSqlServer) + || (d->dbmsType == QODBCDriverPrivate::Sybase) + || (d->dbmsType == QODBCDriverPrivate::MySqlServer) + || (d->dbmsType == QODBCDriverPrivate::PostgreSQL); case MultipleResultSets: return d->hasMultiResultSets; case BLOB: { - if(d->isMySqlServer) + if (d->dbmsType == QODBCDriverPrivate::MySqlServer) return true; else return false; @@ -1896,13 +1932,13 @@ bool QODBCDriver::open(const QString & db, d->checkUnicode(); d->checkSchemaUsage(); - d->checkSqlServer(); + d->checkDBMS(); d->checkHasSQLFetchScroll(); d->checkHasMultiResults(); d->checkDateTimePrecision(); setOpen(true); setOpenError(false); - if(d->isMSSqlServer) { + if (d->dbmsType == QODBCDriverPrivate::MSSqlServer) { QSqlQuery i(createResult()); i.exec(QLatin1String("SET QUOTED_IDENTIFIER ON")); } @@ -2069,7 +2105,7 @@ void QODBCDriverPrivate::checkSchemaUsage() useSchema = (val != 0); } -void QODBCDriverPrivate::checkSqlServer() +void QODBCDriverPrivate::checkDBMS() { SQLRETURN r; QVarLengthArray<SQLTCHAR> serverString(200); @@ -2088,8 +2124,16 @@ void QODBCDriverPrivate::checkSqlServer() #else serverType = QString::fromUtf8((const char *)serverString.constData(), t); #endif - isMySqlServer = serverType.contains(QLatin1String("mysql"), Qt::CaseInsensitive); - isMSSqlServer = serverType.contains(QLatin1String("Microsoft SQL Server"), Qt::CaseInsensitive); + if (serverType.contains(QLatin1String("PostgreSQL"), Qt::CaseInsensitive)) + dbmsType = PostgreSQL; + else if (serverType.contains(QLatin1String("Oracle"), Qt::CaseInsensitive)) + dbmsType = Oracle; + else if (serverType.contains(QLatin1String("MySql"), Qt::CaseInsensitive)) + dbmsType = MySqlServer; + else if (serverType.contains(QLatin1String("Microsoft SQL Server"), Qt::CaseInsensitive)) + dbmsType = MSSqlServer; + else if (serverType.contains(QLatin1String("Sybase"), Qt::CaseInsensitive)) + dbmsType = Sybase; } r = SQLGetInfo(hDbc, SQL_DRIVER_NAME, diff --git a/src/sql/drivers/odbc/qsql_odbc.pri b/src/sql/drivers/odbc/qsql_odbc.pri index 19ff784a04..b206df37c3 100644 --- a/src/sql/drivers/odbc/qsql_odbc.pri +++ b/src/sql/drivers/odbc/qsql_odbc.pri @@ -1,4 +1,4 @@ -HEADERS += $$PWD/qsql_odbc.h +HEADERS += $$PWD/qsql_odbc_p.h SOURCES += $$PWD/qsql_odbc.cpp unix { diff --git a/src/sql/drivers/odbc/qsql_odbc.h b/src/sql/drivers/odbc/qsql_odbc_p.h index 4fba49b9c5..191f64f072 100644 --- a/src/sql/drivers/odbc/qsql_odbc.h +++ b/src/sql/drivers/odbc/qsql_odbc_p.h @@ -42,6 +42,17 @@ #ifndef QSQL_ODBC_H #define QSQL_ODBC_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtSql/qsqldriver.h> #include <QtSql/qsqlresult.h> @@ -70,15 +81,8 @@ #include <sqlext.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE -#if 0 -#pragma qt_no_master_include -#pragma qt_sync_stop_processing -#endif - class QODBCPrivate; class QODBCDriverPrivate; class QODBCDriver; @@ -93,6 +97,7 @@ public: bool prepare(const QString& query); bool exec(); + QVariant lastInsertId() const; QVariant handle() const; virtual void setForwardOnly(bool forward); @@ -158,6 +163,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif // QSQL_ODBC_H diff --git a/src/sql/drivers/psql/qsql_psql.cpp b/src/sql/drivers/psql/qsql_psql.cpp index 0eadceb1d1..7d844fa1bd 100644 --- a/src/sql/drivers/psql/qsql_psql.cpp +++ b/src/sql/drivers/psql/qsql_psql.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include "qsql_psql.h" +#include "qsql_psql_p.h" #include <qcoreapplication.h> #include <qvariant.h> @@ -183,11 +183,12 @@ PGresult * QPSQLDriverPrivate::exec(const QString & stmt) const class QPSQLResultPrivate { public: - QPSQLResultPrivate(QPSQLResult *qq): q(qq), driver(0), result(0), currentSize(-1), preparedQueriesEnabled(false) {} + QPSQLResultPrivate(QPSQLResult *qq): q(qq), privDriver(0), result(0), currentSize(-1), preparedQueriesEnabled(false) {} static QString fieldSerial(int i) { return QLatin1Char('$') + QString::number(i + 1); } + void deallocatePreparedStmt(); QPSQLResult *q; - const QPSQLDriverPrivate *driver; + const QPSQLDriverPrivate *privDriver; PGresult *result; int currentSize; bool preparedQueriesEnabled; @@ -226,7 +227,7 @@ bool QPSQLResultPrivate::processResults() return true; } q->setLastError(qMakeError(QCoreApplication::translate("QPSQLResult", - "Unable to create query"), QSqlError::StatementError, driver, result)); + "Unable to create query"), QSqlError::StatementError, privDriver, result)); return false; } @@ -276,22 +277,22 @@ static QVariant::Type qDecodePSQLType(int t) return type; } -static void qDeallocatePreparedStmt(QPSQLResultPrivate *d) +void QPSQLResultPrivate::deallocatePreparedStmt() { - const QString stmt = QLatin1String("DEALLOCATE ") + d->preparedStmtId; - PGresult *result = d->driver->exec(stmt); + const QString stmt = QLatin1String("DEALLOCATE ") + preparedStmtId; + PGresult *result = privDriver->exec(stmt); if (PQresultStatus(result) != PGRES_COMMAND_OK) - qWarning("Unable to free statement: %s", PQerrorMessage(d->driver->connection)); + qWarning("Unable to free statement: %s", PQerrorMessage(privDriver->connection)); PQclear(result); - d->preparedStmtId.clear(); + preparedStmtId.clear(); } QPSQLResult::QPSQLResult(const QPSQLDriver* db, const QPSQLDriverPrivate* p) : QSqlResult(db) { d = new QPSQLResultPrivate(this); - d->driver = p; + d->privDriver = p; d->preparedQueriesEnabled = db->hasFeature(QSqlDriver::PreparedQueries); } @@ -300,7 +301,7 @@ QPSQLResult::~QPSQLResult() cleanup(); if (d->preparedQueriesEnabled && !d->preparedStmtId.isNull()) - qDeallocatePreparedStmt(d); + d->deallocatePreparedStmt(); delete d; } @@ -359,7 +360,7 @@ QVariant QPSQLResult::data(int i) case QVariant::Bool: return QVariant((bool)(val[0] == 't')); case QVariant::String: - return d->driver->isUtf8 ? QString::fromUtf8(val) : QString::fromLatin1(val); + return d->privDriver->isUtf8 ? QString::fromUtf8(val) : QString::fromLatin1(val); case QVariant::LongLong: if (val[0] == '-') return QString::fromLatin1(val).toLongLong(); @@ -457,7 +458,7 @@ bool QPSQLResult::reset (const QString& query) return false; if (!driver()->isOpen() || driver()->isOpenError()) return false; - d->result = d->driver->exec(query); + d->result = d->privDriver->exec(query); return d->processResults(); } @@ -473,7 +474,12 @@ int QPSQLResult::numRowsAffected() QVariant QPSQLResult::lastInsertId() const { - if (isActive()) { + if (d->privDriver->pro >= QPSQLDriver::Version81) { + QSqlQuery qry(driver()->createResult()); + // Most recent sequence value obtained from nextval + if (qry.exec(QLatin1String("SELECT lastval();")) && qry.next()) + return qry.value(0); + } else if (isActive()) { Oid id = PQoidValue(d->result); if (id != InvalidOid) return QVariant(id); @@ -490,7 +496,7 @@ QSqlRecord QPSQLResult::record() const int count = PQnfields(d->result); for (int i = 0; i < count; ++i) { QSqlField f; - if (d->driver->isUtf8) + if (d->privDriver->isUtf8) f.setName(QString::fromUtf8(PQfname(d->result, i))); else f.setName(QString::fromLocal8Bit(PQfname(d->result, i))); @@ -557,16 +563,16 @@ bool QPSQLResult::prepare(const QString &query) cleanup(); if (!d->preparedStmtId.isEmpty()) - qDeallocatePreparedStmt(d); + d->deallocatePreparedStmt(); const QString stmtId = qMakePreparedStmtId(); const QString stmt = QString::fromLatin1("PREPARE %1 AS ").arg(stmtId).append(QSqlResultPrivate::positionalToNamedBinding(query, QPSQLResultPrivate::fieldSerial)); - PGresult *result = d->driver->exec(stmt); + PGresult *result = d->privDriver->exec(stmt); if (PQresultStatus(result) != PGRES_COMMAND_OK) { setLastError(qMakeError(QCoreApplication::translate("QPSQLResult", - "Unable to prepare statement"), QSqlError::StatementError, d->driver, result)); + "Unable to prepare statement"), QSqlError::StatementError, d->privDriver, result)); PQclear(result); d->preparedStmtId.clear(); return false; @@ -585,13 +591,13 @@ bool QPSQLResult::exec() cleanup(); QString stmt; - const QString params = qCreateParamString(boundValues(), d->q->driver()); + const QString params = qCreateParamString(boundValues(), driver()); if (params.isEmpty()) stmt = QString::fromLatin1("EXECUTE %1").arg(d->preparedStmtId); else stmt = QString::fromLatin1("EXECUTE %1 (%2)").arg(d->preparedStmtId).arg(params); - d->result = d->driver->exec(stmt); + d->result = d->privDriver->exec(stmt); return d->processResults(); } diff --git a/src/sql/drivers/psql/qsql_psql.pri b/src/sql/drivers/psql/qsql_psql.pri index 9b647d8200..d0ded5e625 100644 --- a/src/sql/drivers/psql/qsql_psql.pri +++ b/src/sql/drivers/psql/qsql_psql.pri @@ -1,4 +1,4 @@ -HEADERS += $$PWD/qsql_psql.h +HEADERS += $$PWD/qsql_psql_p.h SOURCES += $$PWD/qsql_psql.cpp unix|win32-g++* { diff --git a/src/sql/drivers/psql/qsql_psql.h b/src/sql/drivers/psql/qsql_psql_p.h index 444ef1bccc..6f60a2a34f 100644 --- a/src/sql/drivers/psql/qsql_psql.h +++ b/src/sql/drivers/psql/qsql_psql_p.h @@ -42,6 +42,17 @@ #ifndef QSQL_PSQL_H #define QSQL_PSQL_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtSql/qsqlresult.h> #include <QtSql/qsqldriver.h> @@ -51,18 +62,11 @@ #define Q_EXPORT_SQLDRIVER_PSQL Q_SQL_EXPORT #endif -QT_BEGIN_HEADER - typedef struct pg_conn PGconn; typedef struct pg_result PGresult; QT_BEGIN_NAMESPACE -#if 0 -#pragma qt_no_master_include -#pragma qt_sync_stop_processing -#endif - class QPSQLResultPrivate; class QPSQLDriverPrivate; class QPSQLDriver; @@ -158,6 +162,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif // QSQL_PSQL_H diff --git a/src/sql/drivers/sqlite/qsql_sqlite.cpp b/src/sql/drivers/sqlite/qsql_sqlite.cpp index f11279f262..483c640b43 100644 --- a/src/sql/drivers/sqlite/qsql_sqlite.cpp +++ b/src/sql/drivers/sqlite/qsql_sqlite.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include "qsql_sqlite.h" +#include "qsql_sqlite_p.h" #include <qcoreapplication.h> #include <qvariant.h> @@ -47,6 +47,7 @@ #include <qsqlfield.h> #include <qsqlindex.h> #include <qsqlquery.h> +#include <QtSql/private/qsqlcachedresult_p.h> #include <qstringlist.h> #include <qvector.h> #include <qdebug.h> @@ -106,6 +107,33 @@ static QSqlError qMakeError(sqlite3 *access, const QString &descr, QSqlError::Er type, errorCode); } +class QSQLiteResultPrivate; + +class QSQLiteResult : public QSqlCachedResult +{ + friend class QSQLiteDriver; + friend class QSQLiteResultPrivate; +public: + explicit QSQLiteResult(const QSQLiteDriver* db); + ~QSQLiteResult(); + QVariant handle() const; + +protected: + bool gotoNext(QSqlCachedResult::ValueCache& row, int idx); + bool reset(const QString &query); + bool prepare(const QString &query); + bool exec(); + int size(); + int numRowsAffected(); + QVariant lastInsertId() const; + QSqlRecord record() const; + void detachFromResultSet(); + void virtual_hook(int id, void *data); + +private: + QSQLiteResultPrivate* d; +}; + class QSQLiteDriverPrivate { public: diff --git a/src/sql/drivers/sqlite/qsql_sqlite.pri b/src/sql/drivers/sqlite/qsql_sqlite.pri index a2e80d4c74..e323f2eba5 100644 --- a/src/sql/drivers/sqlite/qsql_sqlite.pri +++ b/src/sql/drivers/sqlite/qsql_sqlite.pri @@ -1,4 +1,4 @@ -HEADERS += $$PWD/qsql_sqlite.h +HEADERS += $$PWD/qsql_sqlite_p.h SOURCES += $$PWD/qsql_sqlite.cpp !system-sqlite:!contains(LIBS, .*sqlite3.*) { diff --git a/src/sql/drivers/sqlite/qsql_sqlite.h b/src/sql/drivers/sqlite/qsql_sqlite_p.h index 0fdcd4e240..548d1da97c 100644 --- a/src/sql/drivers/sqlite/qsql_sqlite.h +++ b/src/sql/drivers/sqlite/qsql_sqlite_p.h @@ -42,9 +42,19 @@ #ifndef QSQL_SQLITE_H #define QSQL_SQLITE_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtSql/qsqldriver.h> #include <QtSql/qsqlresult.h> -#include <QtSql/private/qsqlcachedresult_p.h> struct sqlite3; @@ -54,44 +64,11 @@ struct sqlite3; #define Q_EXPORT_SQLDRIVER_SQLITE Q_SQL_EXPORT #endif -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE -#if 0 -#pragma qt_no_master_include -#pragma qt_sync_stop_processing -#endif - class QSQLiteDriverPrivate; -class QSQLiteResultPrivate; class QSQLiteDriver; -class QSQLiteResult : public QSqlCachedResult -{ - friend class QSQLiteDriver; - friend class QSQLiteResultPrivate; -public: - explicit QSQLiteResult(const QSQLiteDriver* db); - ~QSQLiteResult(); - QVariant handle() const; - -protected: - bool gotoNext(QSqlCachedResult::ValueCache& row, int idx); - bool reset(const QString &query); - bool prepare(const QString &query); - bool exec(); - int size(); - int numRowsAffected(); - QVariant lastInsertId() const; - QSqlRecord record() const; - void detachFromResultSet(); - void virtual_hook(int id, void *data); - -private: - QSQLiteResultPrivate* d; -}; - class Q_EXPORT_SQLDRIVER_SQLITE QSQLiteDriver : public QSqlDriver { Q_OBJECT @@ -125,6 +102,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif // QSQL_SQLITE_H diff --git a/src/sql/drivers/sqlite2/qsql_sqlite2.cpp b/src/sql/drivers/sqlite2/qsql_sqlite2.cpp index 02e4004901..a85a120973 100644 --- a/src/sql/drivers/sqlite2/qsql_sqlite2.cpp +++ b/src/sql/drivers/sqlite2/qsql_sqlite2.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include "qsql_sqlite2.h" +#include "qsql_sqlite2_p.h" #include <qcoreapplication.h> #include <qvariant.h> @@ -50,6 +50,7 @@ #include <qsqlfield.h> #include <qsqlindex.h> #include <qsqlquery.h> +#include <QtSql/private/qsqlcachedresult_p.h> #include <qstringlist.h> #include <qvector.h> @@ -94,6 +95,30 @@ QSQLite2DriverPrivate::QSQLite2DriverPrivate() : access(0) utf8 = (qstrcmp(sqlite_encoding, "UTF-8") == 0); } +class QSQLite2ResultPrivate; + +class QSQLite2Result : public QSqlCachedResult +{ + friend class QSQLite2Driver; + friend class QSQLite2ResultPrivate; +public: + explicit QSQLite2Result(const QSQLite2Driver* db); + ~QSQLite2Result(); + QVariant handle() const; + +protected: + bool gotoNext(QSqlCachedResult::ValueCache& row, int idx); + bool reset (const QString& query); + int size(); + int numRowsAffected(); + QSqlRecord record() const; + void detachFromResultSet(); + void virtual_hook(int id, void *data); + +private: + QSQLite2ResultPrivate* d; +}; + class QSQLite2ResultPrivate { public: diff --git a/src/sql/drivers/sqlite2/qsql_sqlite2.pri b/src/sql/drivers/sqlite2/qsql_sqlite2.pri index 9a9f6cdf9e..5baba30db0 100644 --- a/src/sql/drivers/sqlite2/qsql_sqlite2.pri +++ b/src/sql/drivers/sqlite2/qsql_sqlite2.pri @@ -1,4 +1,4 @@ -HEADERS += $$PWD/qsql_sqlite2.h +HEADERS += $$PWD/qsql_sqlite2_p.h SOURCES += $$PWD/qsql_sqlite2.cpp !contains(LIBS, .*sqlite.*):LIBS += -lsqlite diff --git a/src/sql/drivers/sqlite2/qsql_sqlite2.h b/src/sql/drivers/sqlite2/qsql_sqlite2_p.h index f141ad1cc2..7a075210ae 100644 --- a/src/sql/drivers/sqlite2/qsql_sqlite2.h +++ b/src/sql/drivers/sqlite2/qsql_sqlite2_p.h @@ -42,11 +42,21 @@ #ifndef QSQL_SQLITE2_H #define QSQL_SQLITE2_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtSql/qsqldriver.h> #include <QtSql/qsqlresult.h> #include <QtSql/qsqlrecord.h> #include <QtSql/qsqlindex.h> -#include <QtSql/private/qsqlcachedresult_p.h> #if defined (Q_OS_WIN32) # include <QtCore/qt_windows.h> @@ -54,41 +64,11 @@ struct sqlite; -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE -#if 0 -#pragma qt_no_master_include -#pragma qt_sync_stop_processing -#endif - class QSQLite2DriverPrivate; -class QSQLite2ResultPrivate; class QSQLite2Driver; -class QSQLite2Result : public QSqlCachedResult -{ - friend class QSQLite2Driver; - friend class QSQLite2ResultPrivate; -public: - explicit QSQLite2Result(const QSQLite2Driver* db); - ~QSQLite2Result(); - QVariant handle() const; - -protected: - bool gotoNext(QSqlCachedResult::ValueCache& row, int idx); - bool reset (const QString& query); - int size(); - int numRowsAffected(); - QSqlRecord record() const; - void detachFromResultSet(); - void virtual_hook(int id, void *data); - -private: - QSQLite2ResultPrivate* d; -}; - class QSQLite2Driver : public QSqlDriver { Q_OBJECT @@ -127,6 +107,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif // QSQL_SQLITE2_H diff --git a/src/sql/drivers/tds/qsql_tds.cpp b/src/sql/drivers/tds/qsql_tds.cpp index 45bba42ca7..996a1bdd1a 100644 --- a/src/sql/drivers/tds/qsql_tds.cpp +++ b/src/sql/drivers/tds/qsql_tds.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include "qsql_tds.h" +#include "qsql_tds_p.h" #include <qglobal.h> #ifdef Q_OS_WIN32 // We assume that MS SQL Server is used. Set Q_USE_SYBASE to force Sybase. @@ -58,6 +58,7 @@ #include <qsqlfield.h> #include <qsqlindex.h> #include <qsqlquery.h> +#include <QtSql/private/qsqlcachedresult_p.h> #include <qstringlist.h> #include <qvector.h> @@ -145,6 +146,33 @@ public: bool initialized; }; +struct QTDSColumnData +{ + void *data; + DBINT nullbind; +}; +Q_DECLARE_TYPEINFO(QTDSColumnData, Q_MOVABLE_TYPE); + +class QTDSResultPrivate; + +class QTDSResult : public QSqlCachedResult +{ +public: + explicit QTDSResult(const QTDSDriver* db); + ~QTDSResult(); + QVariant handle() const; + +protected: + void cleanup(); + bool reset (const QString& query); + int size(); + int numRowsAffected(); + bool gotoNext(QSqlCachedResult::ValueCache &values, int index); + QSqlRecord record() const; + +private: + QTDSResultPrivate* d; +}; class QTDSResultPrivate { @@ -156,7 +184,7 @@ public: void addErrorMsg(QString& errMsg) { errorMsgs.append(errMsg); } QString getErrorMsgs() { return errorMsgs.join(QLatin1String("\n")); } void clearErrorMsgs() { errorMsgs.clear(); } - QVector<void *> buffer; + QVector<QTDSColumnData> buffer; QSqlRecord rec; private: @@ -325,8 +353,8 @@ void QTDSResult::cleanup() { d->clearErrorMsgs(); d->rec.clear(); - for (int i = 0; i < d->buffer.size() / 2; ++i) - free(d->buffer.at(i * 2)); + for (int i = 0; i < d->buffer.size(); ++i) + free(d->buffer.at(i * 2).data); d->buffer.clear(); // "can" stands for "cancel"... very clever. dbcanquery(d->dbproc); @@ -340,9 +368,9 @@ QVariant QTDSResult::handle() const return QVariant(qRegisterMetaType<DBPROCESS *>("DBPROCESS*"), &d->dbproc); } -static inline bool qIsNull(const void *ind) +static inline bool qIsNull(const QTDSColumnData &p) { - return *reinterpret_cast<const DBINT *>(&ind) == -1; + return p.nullbind == -1; } bool QTDSResult::gotoNext(QSqlCachedResult::ValueCache &values, int index) @@ -364,33 +392,33 @@ bool QTDSResult::gotoNext(QSqlCachedResult::ValueCache &values, int index) int idx = index + i; switch (d->rec.field(i).type()) { case QVariant::DateTime: - if (qIsNull(d->buffer.at(i * 2 + 1))) { + if (qIsNull(d->buffer.at(i))) { values[idx] = QVariant(QVariant::DateTime); } else { - DBDATETIME *bdt = (DBDATETIME*) d->buffer.at(i * 2); + DBDATETIME *bdt = (DBDATETIME*) d->buffer.at(i).data; QDate date = QDate::fromString(QLatin1String("1900-01-01"), Qt::ISODate); QTime time = QTime::fromString(QLatin1String("00:00:00"), Qt::ISODate); values[idx] = QDateTime(date.addDays(bdt->dtdays), time.addMSecs(int(bdt->dttime / 0.3))); } break; case QVariant::Int: - if (qIsNull(d->buffer.at(i * 2 + 1))) + if (qIsNull(d->buffer.at(i))) values[idx] = QVariant(QVariant::Int); else - values[idx] = *((int*)d->buffer.at(i * 2)); + values[idx] = *((int*)d->buffer.at(i).data); break; case QVariant::Double: case QVariant::String: - if (qIsNull(d->buffer.at(i * 2 + 1))) + if (qIsNull(d->buffer.at(i))) values[idx] = QVariant(QVariant::String); else - values[idx] = QString::fromLocal8Bit((const char*)d->buffer.at(i * 2)).trimmed(); + values[idx] = QString::fromLocal8Bit((const char*)d->buffer.at(i).data).trimmed(); break; case QVariant::ByteArray: { - if (qIsNull(d->buffer.at(i * 2 + 1))) + if (qIsNull(d->buffer.at(i))) values[idx] = QVariant(QVariant::ByteArray); else - values[idx] = QByteArray((const char*)d->buffer.at(i * 2)); + values[idx] = QByteArray((const char*)d->buffer.at(i).data); break; } default: @@ -430,7 +458,7 @@ bool QTDSResult::reset (const QString& query) setSelect((DBCMDROW(d->dbproc) == SUCCEED)); // decide whether or not we are dealing with a SELECT query int numCols = dbnumcols(d->dbproc); if (numCols > 0) { - d->buffer.resize(numCols * 2); + d->buffer.resize(numCols); init(numCols); } for (int i = 0; i < numCols; ++i) { @@ -470,11 +498,11 @@ bool QTDSResult::reset (const QString& query) break; } if (ret == SUCCEED) { - d->buffer[i * 2] = p; - ret = dbnullbind(d->dbproc, i+1, (DBINT*)(&d->buffer[i * 2 + 1])); + d->buffer[i].data = p; + ret = dbnullbind(d->dbproc, i+1, &d->buffer[i].nullbind); } else { - d->buffer[i * 2] = 0; - d->buffer[i * 2 + 1] = 0; + d->buffer[i].data = 0; + d->buffer[i].nullbind = 0; free(p); } if ((ret != SUCCEED) && (ret != -1)) { diff --git a/src/sql/drivers/tds/qsql_tds.pri b/src/sql/drivers/tds/qsql_tds.pri index 38aab2f3e4..67d037aa6b 100644 --- a/src/sql/drivers/tds/qsql_tds.pri +++ b/src/sql/drivers/tds/qsql_tds.pri @@ -1,4 +1,4 @@ -HEADERS += $$PWD/qsql_tds.h +HEADERS += $$PWD/qsql_tds_p.h SOURCES += $$PWD/qsql_tds.cpp unix|win32-g++*: { diff --git a/src/sql/drivers/tds/qsql_tds.h b/src/sql/drivers/tds/qsql_tds_p.h index 38cb2dc42e..5336f183ef 100644 --- a/src/sql/drivers/tds/qsql_tds.h +++ b/src/sql/drivers/tds/qsql_tds_p.h @@ -42,9 +42,19 @@ #ifndef QSQL_TDS_H #define QSQL_TDS_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtSql/qsqlresult.h> #include <QtSql/qsqldriver.h> -#include <QtSql/private/qsqlcachedresult_p.h> #ifdef Q_OS_WIN32 #define WIN32_LEAN_AND_MEAN @@ -67,38 +77,11 @@ #define Q_EXPORT_SQLDRIVER_TDS Q_SQL_EXPORT #endif -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE -#if 0 -#pragma qt_no_master_include -#pragma qt_sync_stop_processing -#endif - class QTDSDriverPrivate; -class QTDSResultPrivate; class QTDSDriver; -class QTDSResult : public QSqlCachedResult -{ -public: - explicit QTDSResult(const QTDSDriver* db); - ~QTDSResult(); - QVariant handle() const; - -protected: - void cleanup(); - bool reset (const QString& query); - int size(); - int numRowsAffected(); - bool gotoNext(QSqlCachedResult::ValueCache &values, int index); - QSqlRecord record() const; - -private: - QTDSResultPrivate* d; -}; - class Q_EXPORT_SQLDRIVER_TDS QTDSDriver : public QSqlDriver { Q_OBJECT @@ -137,6 +120,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif // QSQL_TDS_H |