diff options
Diffstat (limited to 'tests/auto/sql/kernel/qsqldatabase/tst_databases.h')
-rw-r--r-- | tests/auto/sql/kernel/qsqldatabase/tst_databases.h | 458 |
1 files changed, 209 insertions, 249 deletions
diff --git a/tests/auto/sql/kernel/qsqldatabase/tst_databases.h b/tests/auto/sql/kernel/qsqldatabase/tst_databases.h index d17c47879d..5a10bde814 100644 --- a/tests/auto/sql/kernel/qsqldatabase/tst_databases.h +++ b/tests/auto/sql/kernel/qsqldatabase/tst_databases.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only /* possible connection parameters */ #ifndef TST_DATABASES_H @@ -34,6 +9,7 @@ #include <QSqlDriver> #include <QSqlError> #include <QSqlQuery> +#include <QSqlRecord> #include <QRegularExpression> #include <QRegularExpressionMatch> #include <QDir> @@ -41,8 +17,15 @@ #include <QVariant> #include <QDebug> #include <QSqlTableModel> +#include <QJsonArray> +#include <QJsonObject> +#include <QJsonDocument> +#include <QSysInfo> +#include <QVersionNumber> #include <QtSql/private/qsqldriver_p.h> -#include <QtTest/QtTest> +#include <QTest> + +using namespace Qt::StringLiterals; #define CHECK_DATABASE( db ) \ if ( !db.isValid() ) { qFatal( "db is Invalid" ); } @@ -53,88 +36,26 @@ #define DBMS_SPECIFIC(db, driver) \ if (!db.driverName().startsWith(driver)) { QSKIP(driver " specific test"); } -// ### use QSystem::hostName if it is integrated in qtest/main -static QString qGetHostName() -{ - static QString hostname; - - if (hostname.isEmpty()) { - hostname = QSysInfo::machineHostName(); - hostname.replace(QLatin1Char( '.' ), QLatin1Char( '_' )); - hostname.replace(QLatin1Char( '-' ), QLatin1Char( '_' )); - } - - return hostname; -} - -inline QString fixupTableName(const QString &tableName, QSqlDatabase db) -{ - QString tbName = tableName; - // On Oracle we are limited to 30 character tablenames - QSqlDriverPrivate *d = static_cast<QSqlDriverPrivate *>(QObjectPrivate::get(db.driver())); - if (d && d->dbmsType == QSqlDriver::Oracle) - tbName.truncate(30); - // On Interbase we are limited to 31 character tablenames - if (d && d->dbmsType == QSqlDriver::Interbase) - tbName.truncate(31); - return tbName; -} - // to prevent nameclashes on our database server, each machine // will use its own set of table names. Call this function to get // "tablename_hostname" inline static QString qTableName(const QString &prefix, const char *sourceFileName, QSqlDatabase db, bool escape = true) { - const auto tableStr = fixupTableName(QString(QLatin1String("dbtst") + db.driverName() + "_" + - prefix + QString::number(qHash(QLatin1String(sourceFileName) + - "_" + qGetHostName().replace("-", "_")), 16)), db); + const auto hash = qHash(QLatin1String(sourceFileName) + '_' + + QSysInfo::machineHostName().replace('-', '_')); + auto tableStr = QLatin1String("dbtst") + db.driverName() + '_' + prefix + + QString::number(hash, 16); + // Oracle & Interbase/Firebird have a limit on the tablename length + QSqlDriver *drv = db.driver(); + if (drv) + tableStr.truncate(drv->maximumIdentifierLength(QSqlDriver::TableName)); return escape ? db.driver()->escapeIdentifier(tableStr, QSqlDriver::TableName) : tableStr; } -inline static QString qTableName(const QString& prefix, QSqlDatabase db) -{ - QString tableStr; - if (db.driverName().toLower().contains("ODBC")) - tableStr += QLatin1String("_odbc"); - return fixupTableName(QString(db.driver()->escapeIdentifier(prefix + tableStr + QLatin1Char('_') + - qGetHostName(), QSqlDriver::TableName)),db); -} - -inline static bool testWhiteSpaceNames( const QString &name ) -{ -/* return name.startsWith( "QPSQL" ) - || name.startsWith( "QODBC" ) - || name.startsWith( "QSQLITE" ) - || name.startsWith( "QMYSQL" );*/ - return name != QLatin1String("QSQLITE2"); -} - -inline static QString toHex( const QString& binary ) -{ - QString str; - static char const hexchars[] = "0123456789ABCDEF"; - - for ( int i = 0; i < binary.size(); i++ ) { - ushort code = binary.at(i).unicode(); - str += (QChar)(hexchars[ (code >> 12) & 0x0F ]); - str += (QChar)(hexchars[ (code >> 8) & 0x0F ]); - str += (QChar)(hexchars[ (code >> 4) & 0x0F ]); - str += (QChar)(hexchars[ code & 0x0F ]); - } - - return str; -} - - class tst_Databases { - public: - tst_Databases(): counter( 0 ) - { - } - ~tst_Databases() { close(); @@ -142,83 +63,84 @@ public: // returns a testtable consisting of the names of all database connections if // driverPrefix is empty, otherwise only those that start with driverPrefix. - int fillTestTable( const QString& driverPrefix = QString() ) const + int fillTestTable(const QString &driverPrefix = QString()) const { - QTest::addColumn<QString>( "dbName" ); + QTest::addColumn<QString>("dbName"); int count = 0; - for ( int i = 0; i < dbNames.count(); ++i ) { - QSqlDatabase db = QSqlDatabase::database( dbNames.at( i ) ); - - if ( !db.isValid() ) + for (const auto &dbName : std::as_const(dbNames)) { + QSqlDatabase db = QSqlDatabase::database(dbName); + if (!db.isValid()) continue; - - if ( driverPrefix.isEmpty() || db.driverName().startsWith( driverPrefix ) ) { - QTest::newRow( dbNames.at( i ).toLatin1() ) << dbNames.at( i ); + if (driverPrefix.isEmpty() || db.driverName().startsWith(driverPrefix)) { + QTest::newRow(dbName.toLatin1()) << dbName; ++count; } } - return count; } - int fillTestTableWithStrategies( const QString& driverPrefix = QString() ) const + int fillTestTableWithStrategies(const QString &driverPrefix = QString()) const { - QTest::addColumn<QString>( "dbName" ); - QTest::addColumn<int>("submitpolicy_i"); + QTest::addColumn<QString>("dbName"); + QTest::addColumn<QSqlTableModel::EditStrategy>("submitpolicy"); int count = 0; - for ( int i = 0; i < dbNames.count(); ++i ) { - QSqlDatabase db = QSqlDatabase::database( dbNames.at( i ) ); - - if ( !db.isValid() ) + for (const auto &dbName : std::as_const(dbNames)) { + QSqlDatabase db = QSqlDatabase::database(dbName); + if (!db.isValid()) continue; if ( driverPrefix.isEmpty() || db.driverName().startsWith( driverPrefix ) ) { - QTest::newRow( QString("%1 [field]").arg(dbNames.at( i )).toLatin1() ) << dbNames.at( i ) << (int)QSqlTableModel::OnFieldChange; - QTest::newRow( QString("%1 [row]").arg(dbNames.at( i )).toLatin1() ) << dbNames.at( i ) << (int)QSqlTableModel::OnRowChange; - QTest::newRow( QString("%1 [manual]").arg(dbNames.at( i )).toLatin1() ) << dbNames.at( i ) << (int)QSqlTableModel::OnManualSubmit; + QTest::newRow(QString("%1 [field]").arg(dbName).toLatin1() ) << dbName << QSqlTableModel::OnFieldChange; + QTest::newRow(QString("%1 [row]").arg(dbName).toLatin1() ) << dbName << QSqlTableModel::OnRowChange; + QTest::newRow(QString("%1 [manual]").arg(dbName).toLatin1() ) << dbName << QSqlTableModel::OnManualSubmit; ++count; } } - return count; } - void addDb( const QString& driver, const QString& dbName, - const QString& user = QString(), const QString& passwd = QString(), - const QString& host = QString(), int port = -1, const QString params = QString() ) + void addDb(const QString &driver, const QString &dbName, + const QString &user = QString(), const QString &passwd = QString(), + const QString &host = QString(), int port = -1, const QString ¶ms = QString()) { - QSqlDatabase db; - - if ( !QSqlDatabase::drivers().contains( driver ) ) { + if (!QSqlDatabase::drivers().contains(driver)) { qWarning() << "Driver" << driver << "is not installed"; return; } // construct a stupid unique name - QString cName = QString::number( counter++ ) + QLatin1Char('_') + driver + QLatin1Char('@'); + QString cName = QString::number(counter++) + QLatin1Char('_') + driver + QLatin1Char('@'); cName += host.isEmpty() ? dbName : host; - if ( port > 0 ) - cName += QLatin1Char(':') + QString::number( port ); - - db = QSqlDatabase::addDatabase( driver, cName ); + if (port > 0) + cName += QLatin1Char(':') + QString::number(port); + + QString opts = params; + if (driver == "QSQLITE") { + // Since the database for sqlite is generated at runtime it's always + // available, but we use QTempDir so it's always in a different + // location. Thus, let's ignore the path completely. + cName = "SQLite"; + qInfo("SQLite will use the database located at %ls", qUtf16Printable(dbName)); + opts += QStringLiteral(";QSQLITE_ENABLE_NON_ASCII_CASE_FOLDING"); + } - if ( !db.isValid() ) { + auto db = QSqlDatabase::addDatabase(driver, cName); + if (!db.isValid()) { qWarning( "Could not create database object" ); return; } - db.setDatabaseName( dbName ); - - db.setUserName( user ); - db.setPassword( passwd ); - db.setHostName( host ); - db.setPort( port ); - db.setConnectOptions( params ); - dbNames.append( cName ); + db.setDatabaseName(dbName); + db.setUserName(user); + db.setPassword(passwd); + db.setHostName(host); + db.setPort(port); + db.setConnectOptions(opts); + dbNames.append(cName); } bool addDbs() @@ -253,10 +175,9 @@ public: qWarning() << "No entries in " + f.fileName(); } else { const QJsonArray entriesA = entriesV.toArray(); - QJsonArray::const_iterator it = entriesA.constBegin(); - while (it != entriesA.constEnd()) { - if ((*it).isObject()) { - const QJsonObject object = (*it).toObject(); + for (const auto &elem : entriesA) { + if (elem.isObject()) { + const QJsonObject object = elem.toObject(); addDb(object.value(QStringLiteral("driver")).toString(), object.value(QStringLiteral("name")).toString(), object.value(QStringLiteral("username")).toString(), @@ -266,13 +187,12 @@ public: object.value(QStringLiteral("parameters")).toString()); added = true; } - ++it; } } } QTemporaryDir *sqLiteDir = dbDir(); if (sqLiteDir) { - addDb(QStringLiteral("QSQLITE"), QDir::toNativeSeparators(sqLiteDir->path() + QStringLiteral("/foo.db"))); + addDb(QStringLiteral("QSQLITE"), QDir::toNativeSeparators(sqLiteDir->path() + QStringLiteral("/sqlite.db"))); added = true; } return added; @@ -284,17 +204,18 @@ public: if (!addDbs()) return false; - QStringList::Iterator it = dbNames.begin(); + auto it = dbNames.begin(); + while (it != dbNames.end()) { + const auto &dbName = *it; + QSqlDatabase db = QSqlDatabase::database(dbName, false ); + qDebug() << "Opening:" << dbName; - while ( it != dbNames.end() ) { - QSqlDatabase db = QSqlDatabase::database(( *it ), false ); - qDebug() << "Opening:" << (*it); - - if ( db.isValid() && !db.isOpen() ) { - if ( !db.open() ) { - qWarning( "tst_Databases: Unable to open %s on %s:\n%s", qPrintable( db.driverName() ), qPrintable( *it ), qPrintable( db.lastError().databaseText() ) ); + if (db.isValid() && !db.isOpen()) { + if (!db.open()) { + qWarning("tst_Databases: Unable to open %s on %s:\n%s", qPrintable(db.driverName()), + qPrintable(dbName), qPrintable(db.lastError().databaseText())); // well... opening failed, so we just ignore the server, maybe it is not running - it = dbNames.erase( it ); + it = dbNames.erase(it); } else { ++it; } @@ -305,57 +226,51 @@ public: void close() { - for ( QStringList::Iterator it = dbNames.begin(); it != dbNames.end(); ++it ) { + for (const auto &dbName : std::as_const(dbNames)) { { - QSqlDatabase db = QSqlDatabase::database(( *it ), false ); - - if ( db.isValid() && db.isOpen() ) + QSqlDatabase db = QSqlDatabase::database(dbName, false); + if (db.isValid() && db.isOpen()) db.close(); } - - QSqlDatabase::removeDatabase(( *it ) ); + QSqlDatabase::removeDatabase(dbName); } - dbNames.clear(); } // for debugging only: outputs the connection as string - static QString dbToString( const QSqlDatabase db ) + static QString dbToString(const QSqlDatabase &db) { QString res = db.driverName() + QLatin1Char('@'); - if ( db.driverName().startsWith( "QODBC" ) || db.driverName().startsWith( "QOCI" ) ) { + if (db.driverName().startsWith("QODBC") || db.driverName().startsWith("QOCI")) res += db.databaseName(); - } else { + else res += db.hostName(); - } - if ( db.port() > 0 ) { - res += QLatin1Char(':') + QString::number( db.port() ); - } + if (db.port() > 0) + res += QLatin1Char(':') + QString::number(db.port()); return res; } // drop a table only if it exists to prevent warnings - static void safeDropTables( QSqlDatabase db, const QStringList& tableNames ) + static void safeDropTables(const QSqlDatabase &db, const QStringList &tableNames) { - bool wasDropped; - QSqlQuery q( db ); - QStringList dbtables=db.tables(); + QSqlQuery q(db); + QStringList dbtables = db.tables(); QSqlDriver::DbmsType dbType = getDatabaseType(db); - foreach(const QString &tableName, tableNames) + for (const QString &tableName : tableNames) { - wasDropped = true; - QString table=tableName; - if ( db.driver()->isIdentifierEscaped(table, QSqlDriver::TableName)) + bool wasDropped = true; + QString table = tableName; + if (db.driver()->isIdentifierEscaped(table, QSqlDriver::TableName)) table = db.driver()->stripDelimiters(table, QSqlDriver::TableName); - if ( dbtables.contains( table, Qt::CaseInsensitive ) ) { - foreach(const QString &table2, dbtables.filter(table, Qt::CaseInsensitive)) { - if(table2.compare(table.section('.', -1, -1), Qt::CaseInsensitive) == 0) { - table=db.driver()->escapeIdentifier(table2, QSqlDriver::TableName); - if (dbType == QSqlDriver::PostgreSQL) + if (dbtables.contains(table, Qt::CaseInsensitive)) { + for (const QString &table2 : dbtables.filter(table, Qt::CaseInsensitive)) { + if (table2.compare(table.section('.', -1, -1), Qt::CaseInsensitive) == 0) { + table = db.driver()->escapeIdentifier(table2, QSqlDriver::TableName); + if (dbType == QSqlDriver::PostgreSQL || dbType == QSqlDriver::MimerSQL) wasDropped = q.exec( "drop table " + table + " cascade"); else wasDropped = q.exec( "drop table " + table); @@ -363,7 +278,7 @@ public: } } } - if ( !wasDropped ) { + if (!wasDropped) { qWarning() << dbToString(db) << "unable to drop table" << tableName << ':' << q.lastError(); // qWarning() << "last query:" << q.lastQuery(); // qWarning() << "dbtables:" << dbtables; @@ -372,38 +287,31 @@ public: } } - static void safeDropTable( QSqlDatabase db, const QString& tableName ) + static void safeDropViews(const QSqlDatabase &db, const QStringList &viewNames) { - safeDropTables(db, QStringList() << tableName); - } + if (isMSAccess(db)) // Access is sooo stupid. + safeDropTables(db, viewNames); - static void safeDropViews( QSqlDatabase db, const QStringList &viewNames ) - { - if ( isMSAccess( db ) ) // Access is sooo stupid. - safeDropTables( db, viewNames ); - - bool wasDropped; - QSqlQuery q( db ); - QStringList dbtables=db.tables(QSql::Views); - - foreach(QString viewName, viewNames) + QSqlQuery q(db); + QStringList dbtables = db.tables(QSql::Views); + for (const QString &viewName : viewNames) { - wasDropped = true; - QString view=viewName; - if ( db.driver()->isIdentifierEscaped(view, QSqlDriver::TableName)) + bool wasDropped = true; + QString view = viewName; + if (db.driver()->isIdentifierEscaped(view, QSqlDriver::TableName)) view = db.driver()->stripDelimiters(view, QSqlDriver::TableName); - if ( dbtables.contains( view, Qt::CaseInsensitive ) ) { - foreach(const QString &view2, dbtables.filter(view, Qt::CaseInsensitive)) { - if(view2.compare(view.section('.', -1, -1), Qt::CaseInsensitive) == 0) { - view=db.driver()->escapeIdentifier(view2, QSqlDriver::TableName); - wasDropped = q.exec( "drop view " + view); + if (dbtables.contains(view, Qt::CaseInsensitive)) { + for (const QString &view2 : dbtables.filter(view, Qt::CaseInsensitive)) { + if (view2.compare(view.section('.', -1, -1), Qt::CaseInsensitive) == 0) { + view = db.driver()->escapeIdentifier(view2, QSqlDriver::TableName); + wasDropped = q.exec("drop view " + view); dbtables.removeAll(view); } } } - if ( !wasDropped ) + if (!wasDropped) qWarning() << dbToString(db) << "unable to drop view" << viewName << ':' << q.lastError(); // << "\nlast query:" << q.lastQuery() // << "\ndbtables:" << dbtables @@ -411,14 +319,9 @@ public: } } - static void safeDropView( QSqlDatabase db, const QString& tableName ) - { - safeDropViews(db, QStringList() << tableName); - } - // returns the type name of the blob datatype for the database db. // blobSize is only used if the db doesn't have a generic blob type - static QString blobTypeName( QSqlDatabase db, int blobSize = 10000 ) + static QString blobTypeName(const QSqlDatabase &db, int blobSize = 10000) { const QSqlDriver::DbmsType dbType = getDatabaseType(db); if (dbType == QSqlDriver::MySqlServer) @@ -447,19 +350,35 @@ public: return "blob"; } - static QString dateTimeTypeName(QSqlDatabase db) + static QString dateTimeTypeName(const QSqlDatabase &db) { const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db); if (dbType == QSqlDriver::PostgreSQL) return QLatin1String("timestamptz"); if (dbType == QSqlDriver::Oracle && getOraVersion(db) >= 9) return QLatin1String("timestamp(0)"); - if (dbType == QSqlDriver::Interbase) + if (dbType == QSqlDriver::Interbase || dbType == QSqlDriver::MimerSQL) return QLatin1String("timestamp"); return QLatin1String("datetime"); } - static QString autoFieldName( QSqlDatabase db ) + static QString timeTypeName(const QSqlDatabase &db) + { + const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db); + if (dbType == QSqlDriver::Oracle && getOraVersion(db) >= 9) + return QLatin1String("timestamp(0)"); + return QLatin1String("time"); + } + + static QString dateTypeName(const QSqlDatabase &db) + { + const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db); + if (dbType == QSqlDriver::Oracle && getOraVersion(db) >= 9) + return QLatin1String("timestamp(0)"); + return QLatin1String("date"); + } + + static QString autoFieldName(const QSqlDatabase &db) { const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db); if (dbType == QSqlDriver::MySqlServer) @@ -474,43 +393,35 @@ public: return QString(); } - static QByteArray printError( const QSqlError& err ) + static QByteArray printError(const QSqlError &err) { QString result; if (!err.nativeErrorCode().isEmpty()) - result += '(' + err.nativeErrorCode() + ") "; - result += '\''; - if(!err.driverText().isEmpty()) + result += u'(' + err.nativeErrorCode() + ") "; + result += u'\''; + if (!err.driverText().isEmpty()) result += err.driverText() + "' || '"; - result += err.databaseText() + QLatin1Char('\''); + result += err.databaseText() + u'\''; return result.toLocal8Bit(); } - static QByteArray printError( const QSqlError& err, const QSqlDatabase& db ) + static QByteArray printError(const QSqlError &err, const QSqlDatabase &db) { - QString result(dbToString(db) + ": "); - if (!err.nativeErrorCode().isEmpty()) - result += '(' + err.nativeErrorCode() + ") "; - result += '\''; - if(!err.driverText().isEmpty()) - result += err.driverText() + "' || '"; - result += err.databaseText() + QLatin1Char('\''); - return result.toLocal8Bit(); + return dbToString(db).toLocal8Bit() + ": " + printError(err); } - static QSqlDriver::DbmsType getDatabaseType(QSqlDatabase db) + static QSqlDriver::DbmsType getDatabaseType(const QSqlDatabase &db) { - QSqlDriverPrivate *d = static_cast<QSqlDriverPrivate *>(QObjectPrivate::get(db.driver())); - return d->dbmsType; + return db.driver()->dbmsType(); } - static bool isMSAccess( QSqlDatabase db ) + static bool isMSAccess(const QSqlDatabase &db) { return db.databaseName().contains( "Access Driver", Qt::CaseInsensitive ); } // -1 on fail, else Oracle version - static int getOraVersion( QSqlDatabase db ) + static int getOraVersion(const QSqlDatabase &db) { int ver = -1; QSqlQuery q( "SELECT banner FROM v$version", db ); @@ -529,28 +440,18 @@ public: return ver; } - static QString getMySqlVersion( const QSqlDatabase &db ) + static QVersionNumber getIbaseEngineVersion(const QSqlDatabase &db) { QSqlQuery q(db); - q.exec( "select version()" ); - if(q.next()) - return q.value( 0 ).toString(); - else - return QString(); - } - - static QString getPSQLVersion( const QSqlDatabase &db ) - { - QSqlQuery q(db); - q.exec( "select version()" ); - if(q.next()) - return q.value( 0 ).toString(); - else - return QString(); + q.exec("SELECT rdb$get_context('SYSTEM', 'ENGINE_VERSION') as version from rdb$database;"_L1); + q.next(); + auto record = q.record(); + auto version = QVersionNumber::fromString(record.value(0).toString()); + return version; } QStringList dbNames; - int counter; + int counter = 0; private: QTemporaryDir *dbDir() @@ -568,5 +469,64 @@ private: QScopedPointer<QTemporaryDir> m_dbDir; }; +class TableScope +{ +public: + TableScope(const QSqlDatabase &db, const QString &fullTableName) + : m_db(db) + , m_tableName(fullTableName) + { + tst_Databases::safeDropTables(m_db, {m_tableName}); + } + TableScope(const QSqlDatabase &db, const char *tableName, const char *file, bool escape = true) + : TableScope(db, qTableName(tableName, file, db, escape)) + { + } + + ~TableScope() + { + tst_Databases::safeDropTables(m_db, {m_tableName}); + } + + QString tableName() const + { + return m_tableName; + } +private: + QSqlDatabase m_db; + QString m_tableName; +}; + +class ProcScope +{ +public: + ProcScope(const QSqlDatabase &db, const char *procName, const char *file) + : m_db(db), + m_procName(qTableName(procName, file, db)) + { + cleanup(); + } + ~ProcScope() + { + cleanup(); + } + QString name() const + { + return m_procName; + } +protected: + void cleanup() + { + QSqlQuery q(m_db); + if (m_db.driverName() == "QIBASE") + q.exec("DROP PROCEDURE " + m_procName); + else + q.exec("DROP PROCEDURE IF EXISTS " + m_procName); + } +private: + QSqlDatabase m_db; + const QString m_procName; +}; + #endif |