qt 6.6.0 clean

This commit is contained in:
kleuter
2023-11-01 22:23:55 +01:00
parent 7b5ada15e7
commit 5d8194efa7
1449 changed files with 134276 additions and 31391 deletions

View File

@ -5,6 +5,7 @@ add_subdirectory(qsqlfield)
add_subdirectory(qsqldatabase)
add_subdirectory(qsqlerror)
add_subdirectory(qsqldriver)
add_subdirectory(qsqlindex)
add_subdirectory(qsqlquery)
add_subdirectory(qsqlrecord)
add_subdirectory(qsqlthread)

View File

@ -19,11 +19,6 @@ class tst_QSql : public QObject
{
Q_OBJECT
public:
tst_QSql();
virtual ~tst_QSql();
public slots:
void initTestCase();
void cleanupTestCase();
@ -41,15 +36,6 @@ private slots:
};
/****************** General Qt SQL Module tests *****************/
tst_QSql::tst_QSql()
{
}
tst_QSql::~tst_QSql()
{
}
void tst_QSql::initTestCase()
{
}
@ -80,7 +66,7 @@ void tst_QSql::basicDriverTest()
tst_Databases dbs;
QVERIFY(dbs.open());
foreach (const QString& dbName, dbs.dbNames) {
for (const QString &dbName : std::as_const(dbs.dbNames)) {
QSqlDatabase db = QSqlDatabase::database(dbName);
QVERIFY_SQL(db, isValid());
@ -154,7 +140,7 @@ void tst_QSql::concurrentAccess()
tst_Databases dbs;
QVERIFY(dbs.open());
foreach (const QString& dbName, dbs.dbNames) {
for (const QString &dbName : std::as_const(dbs.dbNames)) {
QSqlDatabase db = QSqlDatabase::database(dbName);
QVERIFY(db.isValid());
if (tst_Databases::isMSAccess(db))
@ -186,7 +172,7 @@ void tst_QSql::openErrorRecovery()
QVERIFY(dbs.addDbs());
if (dbs.dbNames.isEmpty())
QSKIP("No database drivers installed");
foreach (const QString& dbName, dbs.dbNames) {
for (const QString &dbName : std::as_const(dbs.dbNames)) {
QSqlDatabase db = QSqlDatabase::database(dbName, false);
CHECK_DATABASE(db);

View File

@ -9,6 +9,7 @@
#include <QSqlDriver>
#include <QSqlError>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QRegularExpression>
#include <QRegularExpressionMatch>
#include <QDir>
@ -19,9 +20,13 @@
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonDocument>
#include <QSysInfo>
#include <QVersionNumber>
#include <QtSql/private/qsqldriver_p.h>
#include <QTest>
using namespace Qt::StringLiterals;
#define CHECK_DATABASE( db ) \
if ( !db.isValid() ) { qFatal( "db is Invalid" ); }
@ -31,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();
@ -120,67 +63,60 @@ 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.size(); ++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.size(); ++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 &params = 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 );
if (port > 0)
cName += QLatin1Char(':') + QString::number(port);
if (driver == "QSQLITE") {
// Since the database for sqlite is generated at runtime it's always
@ -190,21 +126,19 @@ public:
qInfo("SQLite will use the database located at %ls", qUtf16Printable(dbName));
}
db = QSqlDatabase::addDatabase( driver, cName );
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(params);
dbNames.append(cName);
}
bool addDbs()
@ -239,10 +173,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(),
@ -252,7 +185,6 @@ public:
object.value(QStringLiteral("parameters")).toString());
added = true;
}
++it;
}
}
}
@ -270,17 +202,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;
}
@ -291,57 +224,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);
@ -349,7 +276,7 @@ public:
}
}
}
if ( !wasDropped ) {
if (!wasDropped) {
qWarning() << dbToString(db) << "unable to drop table" << tableName << ':' << q.lastError();
// qWarning() << "last query:" << q.lastQuery();
// qWarning() << "dbtables:" << dbtables;
@ -358,38 +285,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
@ -397,14 +317,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)
@ -433,19 +348,19 @@ 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 timeTypeName(QSqlDatabase db)
static QString timeTypeName(const QSqlDatabase &db)
{
const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
if (dbType == QSqlDriver::Oracle && getOraVersion(db) >= 9)
@ -453,7 +368,7 @@ public:
return QLatin1String("time");
}
static QString dateTypeName(QSqlDatabase db)
static QString dateTypeName(const QSqlDatabase &db)
{
const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
if (dbType == QSqlDriver::Oracle && getOraVersion(db) >= 9)
@ -461,7 +376,7 @@ public:
return QLatin1String("date");
}
static QString autoFieldName( QSqlDatabase db )
static QString autoFieldName(const QSqlDatabase &db)
{
const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
if (dbType == QSqlDriver::MySqlServer)
@ -476,43 +391,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 );
@ -531,28 +438,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()
@ -570,5 +467,61 @@ 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);
q.exec("DROP PROCEDURE IF EXISTS " + m_procName);
}
private:
QSqlDatabase m_db;
const QString m_procName;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -52,47 +52,48 @@ void tst_QSqlDriver::initTestCase_data()
void tst_QSqlDriver::recreateTestTables(QSqlDatabase db)
{
QSqlQuery q(db);
const QString relTEST1(qTableName("relTEST1", __FILE__, db));
const QString tableName(qTableName("relTEST1", __FILE__, db));
tst_Databases::safeDropTables(db, {tableName});
QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
if (dbType == QSqlDriver::PostgreSQL)
QVERIFY_SQL( q, exec("set client_min_messages='warning'"));
tst_Databases::safeDropTable( db, relTEST1 );
QString doubleField;
if (dbType == QSqlDriver::SQLite)
doubleField = "more_data double";
else if (dbType == QSqlDriver::Oracle)
doubleField = "more_data number(8,7)";
else if (dbType == QSqlDriver::PostgreSQL)
else if (dbType == QSqlDriver::PostgreSQL || dbType == QSqlDriver::MimerSQL)
doubleField = "more_data double precision";
else if (dbType == QSqlDriver::Interbase)
doubleField = "more_data numeric(8,7)";
else
doubleField = "more_data double(8,7)";
const QString defValue(driverSupportsDefaultValues(dbType) ? QStringLiteral("DEFAULT 'defaultVal'") : QString());
QVERIFY_SQL( q, exec("create table " + relTEST1 +
QVERIFY_SQL( q, exec("create table " + tableName +
" (id int not null primary key, name varchar(20) " + defValue + ", title_key int, another_title_key int, " + doubleField + QLatin1Char(')')));
QVERIFY_SQL( q, exec("insert into " + relTEST1 + " values(1, 'harry', 1, 2, 1.234567)"));
QVERIFY_SQL( q, exec("insert into " + relTEST1 + " values(2, 'trond', 2, 1, 8.901234)"));
QVERIFY_SQL( q, exec("insert into " + relTEST1 + " values(3, 'vohi', 1, 2, 5.678901)"));
QVERIFY_SQL( q, exec("insert into " + relTEST1 + " values(4, 'boris', 2, 2, 2.345678)"));
QVERIFY_SQL( q, exec("insert into " + tableName + " values(1, 'harry', 1, 2, 1.234567)"));
QVERIFY_SQL( q, exec("insert into " + tableName + " values(2, 'trond', 2, 1, 8.901234)"));
QVERIFY_SQL( q, exec("insert into " + tableName + " values(3, 'vohi', 1, 2, 5.678901)"));
QVERIFY_SQL( q, exec("insert into " + tableName + " values(4, 'boris', 2, 2, 2.345678)"));
}
void tst_QSqlDriver::initTestCase()
{
foreach (const QString &dbname, dbs.dbNames)
for (const QString &dbname : std::as_const(dbs.dbNames))
recreateTestTables(QSqlDatabase::database(dbname));
}
void tst_QSqlDriver::cleanupTestCase()
{
foreach (const QString &dbName, dbs.dbNames) {
for (const QString &dbName : std::as_const(dbs.dbNames)) {
QSqlDatabase db = QSqlDatabase::database(dbName);
tst_Databases::safeDropTable(db, qTableName("relTEST1", __FILE__, db));
QStringList tables = {qTableName("relTEST1", __FILE__, db)};
const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
if (dbType == QSqlDriver::Oracle)
tst_Databases::safeDropTable(db, qTableName("clobTable", __FILE__, db));
tables.push_back(qTableName("clobTable", __FILE__, db));
tst_Databases::safeDropTables(db, tables);
}
dbs.close();
}
@ -111,7 +112,7 @@ void tst_QSqlDriver::record()
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
QString tablename(qTableName("relTEST1", __FILE__, db));
QString tablename(qTableName("relTEST1", __FILE__, db, false));
QStringList fields;
fields << "id" << "name" << "title_key" << "another_title_key" << "more_data";
@ -155,8 +156,9 @@ void tst_QSqlDriver::record()
//check that we can't get records using incorrect tablename casing that's been quoted
rec = db.driver()->record(db.driver()->escapeIdentifier(tablename,QSqlDriver::TableName));
if (dbType == QSqlDriver::MySqlServer || dbType == QSqlDriver::SQLite || dbType == QSqlDriver::Sybase
|| dbType == QSqlDriver::MSSqlServer || tst_Databases::isMSAccess(db))
if (dbType == QSqlDriver::MySqlServer || dbType == QSqlDriver::SQLite
|| dbType == QSqlDriver::Sybase || dbType == QSqlDriver::MSSqlServer
|| tst_Databases::isMSAccess(db) || dbType == QSqlDriver::MimerSQL)
QCOMPARE(rec.count(), 5); //mysql, sqlite and tds will match
else
QCOMPARE(rec.count(), 0);
@ -169,7 +171,7 @@ void tst_QSqlDriver::primaryIndex()
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
QString tablename(qTableName("relTEST1", __FILE__, db));
QString tablename(qTableName("relTEST1", __FILE__, db, false));
//check that we can get primary index using unquoted mixed case table name
QSqlIndex index = db.driver()->primaryIndex(tablename);
QCOMPARE(index.count(), 1);
@ -205,22 +207,23 @@ void tst_QSqlDriver::primaryIndex()
tablename = tablename.toUpper();
index = db.driver()->primaryIndex(db.driver()->escapeIdentifier(tablename, QSqlDriver::TableName));
if (dbType == QSqlDriver::MySqlServer || dbType == QSqlDriver::SQLite || dbType == QSqlDriver::Sybase
|| dbType == QSqlDriver::MSSqlServer || tst_Databases::isMSAccess(db))
if (dbType == QSqlDriver::MySqlServer || dbType == QSqlDriver::SQLite
|| dbType == QSqlDriver::Sybase || dbType == QSqlDriver::MSSqlServer
|| tst_Databases::isMSAccess(db) || dbType == QSqlDriver::MimerSQL)
QCOMPARE(index.count(), 1); //mysql will always find the table name regardless of casing
else
QCOMPARE(index.count(), 0);
// Test getting a primary index for a table with a clob in it - QTBUG-64427
if (dbType == QSqlDriver::Oracle) {
const QString clobTable(qTableName("clobTable", __FILE__, db));
TableScope ts(db, "clobTable", __FILE__);
QSqlQuery qry(db);
QVERIFY_SQL(qry, exec("CREATE TABLE " + clobTable + " (id INTEGER, clobField CLOB)"));
QVERIFY_SQL(qry, exec("CREATE UNIQUE INDEX " + clobTable + "IDX ON " + clobTable + " (id)"));
QVERIFY_SQL(qry, exec("ALTER TABLE " + clobTable + " ADD CONSTRAINT " + clobTable +
QVERIFY_SQL(qry, exec("CREATE TABLE " + ts.tableName() + " (id INTEGER, clobField CLOB)"));
QVERIFY_SQL(qry, exec("CREATE UNIQUE INDEX " + ts.tableName() + "IDX ON " + ts.tableName() + " (id)"));
QVERIFY_SQL(qry, exec("ALTER TABLE " + ts.tableName() + " ADD CONSTRAINT " + ts.tableName() +
"PK PRIMARY KEY(id)"));
QVERIFY_SQL(qry, exec("ALTER TABLE " + clobTable + " MODIFY (id NOT NULL ENABLE)"));
const QSqlIndex primaryIndex = db.driver()->primaryIndex(clobTable);
QVERIFY_SQL(qry, exec("ALTER TABLE " + ts.tableName() + " MODIFY (id NOT NULL ENABLE)"));
const QSqlIndex primaryIndex = db.driver()->primaryIndex(ts.tableName());
QCOMPARE(primaryIndex.count(), 1);
QCOMPARE(primaryIndex.fieldName(0), QStringLiteral("ID"));
}

View File

@ -108,12 +108,16 @@ void tst_QSqlError::moveOperator()
void tst_QSqlError::operators()
{
QSqlError error1(QString(), QString(), QSqlError::NoError);
QSqlError error2(QString(), QString(), QSqlError::NoError);
QSqlError error3(QString(), QString(), QSqlError::UnknownError);
QSqlError error1(QStringLiteral("a"), QStringLiteral("b"), QSqlError::NoError, QStringLiteral("ec1"));
QSqlError error2(QStringLiteral("c"), QStringLiteral("d"), QSqlError::NoError, QStringLiteral("ec1"));
QSqlError error3(QString(), QString(), QSqlError::UnknownError, QStringLiteral("ec1"));
QSqlError error4(QString(), QString(), QSqlError::NoError, QStringLiteral("ec2"));
QSqlError error5(QString(), QString(), QSqlError::UnknownError, QStringLiteral("ec2"));
QCOMPARE(error1, error2);
QVERIFY(error1 != error3);
QVERIFY(error1 != error4);
QVERIFY(error4 != error5);
}
void tst_QSqlError::qtbug_74575()

View File

@ -39,6 +39,7 @@ private slots:
void clear();
void setTableName_data();
void setTableName();
void moveSemantics();
};
// Testing get/set functions
@ -344,5 +345,24 @@ void tst_QSqlField::setTableName()
QCOMPARE(field.tableName(), tableName);
}
void tst_QSqlField::moveSemantics()
{
QSqlField field("test", QMetaType(QMetaType::QString), "testTable");
QSqlField empty;
field.setValue("string");
auto moved = std::move(field);
// `field` is now partially-formed
// moving transfers state:
QCOMPARE(moved.value().toString(), QLatin1String("string"));
// moved-from objects can be assigned-to:
field = empty;
QVERIFY(field.value().isNull());
// moved-from object can be destroyed:
moved = std::move(field);
}
QTEST_MAIN(tst_QSqlField)
#include "tst_qsqlfield.moc"

View File

@ -0,0 +1,15 @@
# Copyright (C) 2023 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## tst_qsqlindex Test:
#####################################################################
qt_internal_add_test(tst_qsqlindex
SOURCES
tst_qsqlindex.cpp
LIBRARIES
Qt::CorePrivate
Qt::Sql
Qt::SqlPrivate
)

View File

@ -0,0 +1,126 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <QTest>
#include <QtSql/QtSql>
#include <QtCore/QDateTime>
#include <QtCore/QTimeZone>
#include <numeric>
#include "../qsqldatabase/tst_databases.h"
using namespace Qt::StringLiterals;
QString qtest;
class tst_QSqlIndex : public QObject
{
Q_OBJECT
public:
tst_QSqlIndex();
private slots:
void construction_data();
void construction();
void assignment_data();
void assignment();
void basicFunctions();
};
tst_QSqlIndex::tst_QSqlIndex()
{
}
void tst_QSqlIndex::construction_data()
{
QTest::addColumn<QSqlIndex>("sqlIndex");
QTest::addColumn<QString>("cursorName");
QTest::addColumn<QString>("name");
const QString cursorName("cusorName"_L1);
const QString name("name"_L1);
QSqlIndex sqlIndex(cursorName, name);
QTest::newRow("ctor1") << QSqlIndex() << QString() << QString();
QTest::newRow("ctor2") << sqlIndex << cursorName << name;
QTest::newRow("copy ctor") << QSqlIndex(sqlIndex) << cursorName << name;
QTest::newRow("move ctor") << QSqlIndex(std::move(sqlIndex)) << cursorName << name;
}
void tst_QSqlIndex::construction()
{
QFETCH(QSqlIndex, sqlIndex);
QFETCH(QString, cursorName);
QFETCH(QString, name);
QCOMPARE(sqlIndex.cursorName(), cursorName);
QCOMPARE(sqlIndex.name(), name);
QCOMPARE(sqlIndex.isDescending(0), false);
QCOMPARE(sqlIndex.count(), 0);
}
void tst_QSqlIndex::assignment_data()
{
QTest::addColumn<QSqlIndex>("sqlIndex");
QTest::addColumn<QString>("cursorName");
QTest::addColumn<QString>("name");
const QString cursorName("cusorName"_L1);
const QString name("name"_L1);
QSqlIndex sqlIndex(cursorName, name);
QSqlIndex sqlIndex1 = sqlIndex;
QSqlIndex sqlIndex2 = std::move(sqlIndex);
sqlIndex = std::move(sqlIndex2);
QTest::newRow("copy assignment") << sqlIndex1 << cursorName << name;
QTest::newRow("move assignment") << sqlIndex << cursorName << name;
}
void tst_QSqlIndex::assignment()
{
QFETCH(QSqlIndex, sqlIndex);
QFETCH(QString, cursorName);
QFETCH(QString, name);
QCOMPARE(sqlIndex.cursorName(), cursorName);
QCOMPARE(sqlIndex.name(), name);
QCOMPARE(sqlIndex.isDescending(0), false);
QCOMPARE(sqlIndex.count(), 0);
}
void tst_QSqlIndex::basicFunctions()
{
QSqlIndex sqlIndex("cursorName"_L1, "name"_L1);
const QSqlField f1("field1"_L1, QMetaType(QMetaType::UInt), "table1"_L1);
const QSqlField f2("field2"_L1, QMetaType(QMetaType::Double), "table2"_L1);
QCOMPARE(sqlIndex.cursorName(), "cursorName"_L1);
sqlIndex.setCursorName("updatedCursorName"_L1);
QCOMPARE(sqlIndex.name(), "name"_L1);
sqlIndex.setName("updatedName"_L1);
QCOMPARE(sqlIndex.cursorName(), "updatedCursorName"_L1);
QCOMPARE(sqlIndex.name(), "updatedName"_L1);
sqlIndex.append(f1);
QCOMPARE(sqlIndex.count(), 1);
QCOMPARE(sqlIndex.isDescending(0), false);
sqlIndex.append(f2, true);
QCOMPARE(sqlIndex.count(), 2);
QCOMPARE(sqlIndex.isDescending(0), false);
QCOMPARE(sqlIndex.isDescending(1), true);
sqlIndex.setDescending(0, true);
sqlIndex.setDescending(1, false);
sqlIndex.setDescending(2, true);
QCOMPARE(sqlIndex.count(), 2);
QCOMPARE(sqlIndex.isDescending(0), true);
QCOMPARE(sqlIndex.isDescending(1), false);
QCOMPARE(sqlIndex.field(0), f1);
QCOMPARE(sqlIndex.field(1), f2);
}
QTEST_MAIN(tst_QSqlIndex)
#include "tst_qsqlindex.moc"

File diff suppressed because it is too large Load Diff

View File

@ -40,6 +40,7 @@ private slots:
void clearValues();
void clear();
void append();
void moveSemantics();
private:
std::unique_ptr<QSqlRecord> rec;
@ -449,5 +450,24 @@ void tst_QSqlRecord::value()
QCOMPARE(rec2.value("string").toString(), QLatin1String("Harry"));
}
void tst_QSqlRecord::moveSemantics()
{
QSqlRecord rec, empty;
rec.append(QSqlField("string", QMetaType(QMetaType::QString)));
rec.setValue("string", "Harry");
auto moved = std::move(rec);
// `rec` is not partially-formed
// moving transfers state:
QCOMPARE(moved.value("string").toString(), QLatin1String("Harry"));
// moved-from objects can be assigned-to:
rec = empty;
QVERIFY(rec.value("string").isNull());
// moved-from object can be destroyed:
moved = std::move(rec);
}
QTEST_MAIN(tst_QSqlRecord)
#include "tst_qsqlrecord.moc"

View File

@ -258,18 +258,16 @@ void tst_QSqlThread::generic_data(const QString& engine)
void tst_QSqlThread::dropTestTables()
{
for (int i = 0; i < dbs.dbNames.size(); ++i) {
QSqlDatabase db = QSqlDatabase::database(dbs.dbNames.at(i));
QSqlQuery q(db);
tst_Databases::safeDropTables(db, QStringList() << qtest << qTableName("qtest2", __FILE__, db) << qTableName("emptytable", __FILE__, db));
for (const auto &dbName : dbs.dbNames) {
QSqlDatabase db = QSqlDatabase::database(dbName);
tst_Databases::safeDropTables(db, { qtest, qTableName("qtest2", __FILE__, db), qTableName("emptytable", __FILE__, db) });
}
}
void tst_QSqlThread::createTestTables()
{
for (int i = 0; i < dbs.dbNames.size(); ++i) {
QSqlDatabase db = QSqlDatabase::database(dbs.dbNames.at(i));
for (const auto &dbName : dbs.dbNames) {
QSqlDatabase db = QSqlDatabase::database(dbName);
QSqlQuery q(db);
QVERIFY_SQL(q, exec("create table " + qtest
@ -285,8 +283,8 @@ void tst_QSqlThread::createTestTables()
void tst_QSqlThread::repopulateTestTables()
{
for (int i = 0; i < dbs.dbNames.size(); ++i) {
QSqlDatabase db = QSqlDatabase::database(dbs.dbNames.at(i));
for (const auto &dbName : dbs.dbNames) {
QSqlDatabase db = QSqlDatabase::database(dbName);
QSqlQuery q(db);
QVERIFY_SQL(q, exec("delete from " + qtest));

View File

@ -62,9 +62,9 @@ private slots:
void task_QTBUG_4963_setHeaderDataWithProxyModel();
private:
void generic_data(const QString &engine=QString());
void dropTestTables(QSqlDatabase db);
void createTestTables(QSqlDatabase db);
void generic_data(const QString &engine = QString());
void dropTestTables(const QSqlDatabase &db);
void createTestTables(const QSqlDatabase &db);
void populateTestTables(QSqlDatabase db);
tst_Databases dbs;
};
@ -73,8 +73,8 @@ private:
class DBTestModel: public QSqlQueryModel
{
public:
DBTestModel(QObject *parent = nullptr): QSqlQueryModel(parent) {}
QModelIndex indexInQuery(const QModelIndex &item) const override { return QSqlQueryModel::indexInQuery(item); }
using QSqlQueryModel::QSqlQueryModel;
using QSqlQueryModel::indexInQuery;
};
tst_QSqlQueryModel::tst_QSqlQueryModel()
@ -88,8 +88,8 @@ tst_QSqlQueryModel::~tst_QSqlQueryModel()
void tst_QSqlQueryModel::initTestCase()
{
QVERIFY(dbs.open());
for (QStringList::ConstIterator it = dbs.dbNames.begin(); it != dbs.dbNames.end(); ++it) {
QSqlDatabase db = QSqlDatabase::database((*it));
for (const auto &dbName : std::as_const(dbs.dbNames)) {
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
dropTestTables(db); //in case of leftovers
createTestTables(db);
@ -99,15 +99,15 @@ void tst_QSqlQueryModel::initTestCase()
void tst_QSqlQueryModel::cleanupTestCase()
{
for (QStringList::ConstIterator it = dbs.dbNames.begin(); it != dbs.dbNames.end(); ++it) {
QSqlDatabase db = QSqlDatabase::database((*it));
for (const auto &dbName : std::as_const(dbs.dbNames)) {
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
dropTestTables(db);
}
dbs.close();
}
void tst_QSqlQueryModel::dropTestTables(QSqlDatabase db)
void tst_QSqlQueryModel::dropTestTables(const QSqlDatabase &db)
{
QStringList tableNames;
tableNames << qTableName("test", __FILE__, db)
@ -117,7 +117,7 @@ void tst_QSqlQueryModel::dropTestTables(QSqlDatabase db)
tst_Databases::safeDropTables(db, tableNames);
}
void tst_QSqlQueryModel::createTestTables(QSqlDatabase db)
void tst_QSqlQueryModel::createTestTables(const QSqlDatabase &db)
{
dropTestTables(db);
QSqlQuery q(db);

View File

@ -77,16 +77,17 @@ void tst_QSqlRelationalDelegate::recreateTestTables(QSqlDatabase db)
void tst_QSqlRelationalDelegate::initTestCase()
{
foreach (const QString &dbname, dbs.dbNames) {
QSqlDatabase db=QSqlDatabase::database(dbname);
for (const QString &dbName : std::as_const(dbs.dbNames)) {
QSqlDatabase db = QSqlDatabase::database(dbName);
QSqlQuery q(db);
QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
if (dbType == QSqlDriver::Interbase) {
db.exec("SET DIALECT 3");
q.exec("SET DIALECT 3");
} else if (dbType == QSqlDriver::MSSqlServer) {
db.exec("SET ANSI_DEFAULTS ON");
db.exec("SET IMPLICIT_TRANSACTIONS OFF");
q.exec("SET ANSI_DEFAULTS ON");
q.exec("SET IMPLICIT_TRANSACTIONS OFF");
} else if (dbType == QSqlDriver::PostgreSQL) {
db.exec("set client_min_messages='warning'");
q.exec("set client_min_messages='warning'");
}
recreateTestTables(db);
}
@ -94,7 +95,7 @@ void tst_QSqlRelationalDelegate::initTestCase()
void tst_QSqlRelationalDelegate::cleanupTestCase()
{
foreach (const QString &dbName, dbs.dbNames) {
for (const QString &dbName : std::as_const(dbs.dbNames)) {
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
dropTestTables(QSqlDatabase::database(dbName));

View File

@ -7,21 +7,12 @@
#include "../../kernel/qsqldatabase/tst_databases.h"
QString reltest1;
QString reltest2;
QString reltest3;
QString reltest4;
QString reltest5;
class tst_QSqlRelationalTableModel : public QObject
{
Q_OBJECT
public:
void recreateTestTables(QSqlDatabase);
tst_QSqlRelationalTableModel();
tst_Databases dbs;
using QObject::QObject;
public slots:
void initTestCase_data();
@ -56,25 +47,43 @@ private slots:
void setRelation();
private:
void dropTestTables( QSqlDatabase db );
void fixupTableNamesForDb(const QSqlDatabase &db);
void recreateTestTables(const QSqlDatabase &db);
void dropTestTables(const QSqlDatabase &db);
static QString escapeTableName(const QSqlDatabase &db, const QString &name)
{
QString _name = name;
const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
if (dbType == QSqlDriver::Oracle ||
dbType == QSqlDriver::DB2)
_name = name.toUpper();
return db.driver()->escapeIdentifier(_name, QSqlDriver::TableName);
}
static QString escapeFieldName(const QSqlDatabase &db, const QString &name)
{
QString _name = name;
const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
if (dbType == QSqlDriver::Interbase ||
dbType == QSqlDriver::Oracle ||
dbType == QSqlDriver::DB2)
_name = name.toUpper();
return db.driver()->escapeIdentifier(_name, QSqlDriver::FieldName);
}
QString reltest1;
QString reltest2;
QString reltest3;
QString reltest4;
QString reltest5;
tst_Databases dbs;
};
tst_QSqlRelationalTableModel::tst_QSqlRelationalTableModel()
void tst_QSqlRelationalTableModel::fixupTableNamesForDb(const QSqlDatabase &db)
{
static QSqlDatabase static_qtest_db_1 = QSqlDatabase();
reltest1 = qTableName("reltest1", __FILE__, static_qtest_db_1);
static QSqlDatabase static_qtest_db_2 = QSqlDatabase();
reltest2 = qTableName("reltest2", __FILE__, static_qtest_db_2);
static QSqlDatabase static_qtest_db_3 = QSqlDatabase();
reltest3 = qTableName("reltest3", __FILE__, static_qtest_db_3);
static QSqlDatabase static_qtest_db_4 = QSqlDatabase();
reltest4 = qTableName("reltest4", __FILE__, static_qtest_db_4);
static QSqlDatabase static_qtest_db_5 = QSqlDatabase();
reltest5 = qTableName("reltest5", __FILE__, static_qtest_db_5);
reltest1 = qTableName("reltest1", __FILE__, db);
reltest2 = qTableName("reltest2", __FILE__, db);
reltest3 = qTableName("reltest3", __FILE__, db);
reltest4 = qTableName("reltest4", __FILE__, db);
reltest5 = qTableName("reltest5", __FILE__, db);
}
void tst_QSqlRelationalTableModel::initTestCase_data()
@ -84,7 +93,7 @@ void tst_QSqlRelationalTableModel::initTestCase_data()
QSKIP("No database drivers are available in this Qt configuration");
}
void tst_QSqlRelationalTableModel::recreateTestTables(QSqlDatabase db)
void tst_QSqlRelationalTableModel::recreateTestTables(const QSqlDatabase &db)
{
dropTestTables(db);
@ -114,32 +123,36 @@ void tst_QSqlRelationalTableModel::recreateTestTables(QSqlDatabase db)
QVERIFY_SQL( q, exec("insert into " + reltest5 + " values('herr', 'Hr')"));
QVERIFY_SQL( q, exec("insert into " + reltest5 + " values('mister', 'Mr')"));
if (testWhiteSpaceNames(db.driverName())) {
const auto reltest6 = qTableName("rel test6", __FILE__, db);
QVERIFY_SQL( q, exec("create table " + reltest6 + " (id int not null primary key, " + db.driver()->escapeIdentifier("city key", QSqlDriver::FieldName) +
" int, " + db.driver()->escapeIdentifier("extra field", QSqlDriver::FieldName) + " int)"));
QVERIFY_SQL( q, exec("insert into " + reltest6 + " values(1, 1,9)"));
QVERIFY_SQL( q, exec("insert into " + reltest6 + " values(2, 2,8)"));
const auto reltest6 = qTableName("rel test6", __FILE__, db);
const auto cityKeyStr = db.driver()->escapeIdentifier("city key", QSqlDriver::FieldName);
const auto extraFieldStr = db.driver()->escapeIdentifier("extra field", QSqlDriver::FieldName);
QVERIFY_SQL( q, exec("create table " + reltest6 + " (id int not null primary key, " + cityKeyStr +
" int, " + extraFieldStr + " int)"));
QVERIFY_SQL( q, exec("insert into " + reltest6 + " values(1, 1,9)"));
QVERIFY_SQL( q, exec("insert into " + reltest6 + " values(2, 2,8)"));
const auto reltest7 = qTableName("rel test7", __FILE__, db);
QVERIFY_SQL( q, exec("create table " + reltest7 + " (" + db.driver()->escapeIdentifier("city id", QSqlDriver::TableName) + " int not null primary key, " + db.driver()->escapeIdentifier("city name", QSqlDriver::FieldName) + " varchar(20))"));
QVERIFY_SQL( q, exec("insert into " + reltest7 + " values(1, 'New York')"));
QVERIFY_SQL( q, exec("insert into " + reltest7 + " values(2, 'Washington')"));
}
const auto reltest7 = qTableName("rel test7", __FILE__, db);
const auto cityIdStr = db.driver()->escapeIdentifier("city id", QSqlDriver::TableName);
const auto cityNameStr = db.driver()->escapeIdentifier("city name", QSqlDriver::FieldName);
QVERIFY_SQL( q, exec("create table " + reltest7 + " (" + cityIdStr + " int not null primary key, " +
cityNameStr + " varchar(20))"));
QVERIFY_SQL( q, exec("insert into " + reltest7 + " values(1, 'New York')"));
QVERIFY_SQL( q, exec("insert into " + reltest7 + " values(2, 'Washington')"));
}
void tst_QSqlRelationalTableModel::initTestCase()
{
foreach (const QString &dbname, dbs.dbNames) {
QSqlDatabase db=QSqlDatabase::database(dbname);
for (const QString &dbName : std::as_const(dbs.dbNames)) {
QSqlDatabase db = QSqlDatabase::database(dbName);
QSqlQuery q(db);
QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
if (dbType == QSqlDriver::Interbase) {
db.exec("SET DIALECT 3");
q.exec("SET DIALECT 3");
} else if (dbType == QSqlDriver::MSSqlServer) {
db.exec("SET ANSI_DEFAULTS ON");
db.exec("SET IMPLICIT_TRANSACTIONS OFF");
q.exec("SET ANSI_DEFAULTS ON");
q.exec("SET IMPLICIT_TRANSACTIONS OFF");
} else if (dbType == QSqlDriver::PostgreSQL) {
db.exec("set client_min_messages='warning'");
q.exec("set client_min_messages='warning'");
}
recreateTestTables(db);
}
@ -147,30 +160,27 @@ void tst_QSqlRelationalTableModel::initTestCase()
void tst_QSqlRelationalTableModel::cleanupTestCase()
{
foreach (const QString &dbName, dbs.dbNames) {
for (const QString &dbName : std::as_const(dbs.dbNames)) {
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE( db );
dropTestTables( QSqlDatabase::database(dbName) );
CHECK_DATABASE(db);
dropTestTables(db);
}
dbs.close();
}
void tst_QSqlRelationalTableModel::dropTestTables( QSqlDatabase db )
void tst_QSqlRelationalTableModel::dropTestTables(const QSqlDatabase &db)
{
QStringList tableNames;
tableNames << reltest1
<< reltest2
<< reltest3
<< reltest4
<< reltest5
<< qTableName("rel test6", __FILE__, db)
<< qTableName("rel test7", __FILE__, db)
<< qTableName("CASETEST1", db)
<< qTableName("casetest1", db);
fixupTableNamesForDb(db);
QStringList tableNames{reltest1, reltest2, reltest3, reltest4, reltest5,
qTableName("rel test6", __FILE__, db),
qTableName("rel test7", __FILE__, db),
qTableName("CASETEST1", __FILE__, db),
qTableName("casetest1", __FILE__, db)};
tst_Databases::safeDropTables( db, tableNames );
db.exec("DROP SCHEMA " + qTableName("QTBUG_5373", __FILE__, db) + " CASCADE");
db.exec("DROP SCHEMA " + qTableName("QTBUG_5373_s2", __FILE__, db) + " CASCADE");
QSqlQuery q(db);
q.exec("DROP SCHEMA " + qTableName("QTBUG_5373", __FILE__, db) + " CASCADE");
q.exec("DROP SCHEMA " + qTableName("QTBUG_5373_s2", __FILE__, db) + " CASCADE");
}
void tst_QSqlRelationalTableModel::init()
@ -186,6 +196,7 @@ void tst_QSqlRelationalTableModel::data()
QFETCH_GLOBAL(QString, dbName);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
fixupTableNamesForDb(db);
QSqlRelationalTableModel model(0, db);
@ -227,6 +238,7 @@ void tst_QSqlRelationalTableModel::setData()
QFETCH_GLOBAL(QString, dbName);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
fixupTableNamesForDb(db);
const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
// set the values using OnRowChange Strategy
@ -434,6 +446,7 @@ void tst_QSqlRelationalTableModel::insertRecord()
QFETCH_GLOBAL(QString, dbName);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
fixupTableNamesForDb(db);
QSqlRelationalTableModel model(0, db);
@ -544,6 +557,7 @@ void tst_QSqlRelationalTableModel::insertWithStrategies()
QFETCH_GLOBAL(QString, dbName);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
fixupTableNamesForDb(db);
const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
QSqlRelationalTableModel model(0, db);
@ -652,56 +666,33 @@ void tst_QSqlRelationalTableModel::removeColumn()
QFETCH_GLOBAL(QString, dbName);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
recreateTestTables(db);
QSqlRelationalTableModel model(0, db);
for (const auto mode : {QSqlRelationalTableModel::InnerJoin, QSqlRelationalTableModel::LeftJoin}) {
recreateTestTables(db);
model.setTable(reltest1);
model.setRelation(2, QSqlRelation(reltest2, "id", "title"));
QVERIFY_SQL(model, select());
QSqlRelationalTableModel model(0, db);
QVERIFY_SQL(model, removeColumn(3));
QVERIFY_SQL(model, select());
model.setTable(reltest1);
model.setRelation(2, QSqlRelation(reltest2, "id", "title"));
model.setJoinMode(mode);
QVERIFY_SQL(model, select());
QCOMPARE(model.columnCount(), 3);
QVERIFY_SQL(model, removeColumn(3));
QVERIFY_SQL(model, select());
QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
QCOMPARE(model.data(model.index(0, 3)), QVariant());
QCOMPARE(model.columnCount(), 3);
// try removing more than one column
QVERIFY_SQL(model, removeColumns(1, 2));
QCOMPARE(model.columnCount(), 1);
QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
QCOMPARE(model.data(model.index(0, 1)), QVariant());
QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
QCOMPARE(model.data(model.index(0, 3)), QVariant());
// try in LeftJoin mode the same tests
CHECK_DATABASE(db);
recreateTestTables(db);
QSqlRelationalTableModel lmodel(0, db);
lmodel.setTable(reltest1);
lmodel.setRelation(2, QSqlRelation(reltest2, "id", "title"));
lmodel.setJoinMode(QSqlRelationalTableModel::LeftJoin);
QVERIFY_SQL(lmodel, select());
QVERIFY_SQL(lmodel, removeColumn(3));
QVERIFY_SQL(lmodel, select());
QCOMPARE(lmodel.columnCount(), 3);
QCOMPARE(lmodel.data(lmodel.index(0, 0)).toInt(), 1);
QCOMPARE(lmodel.data(lmodel.index(0, 1)).toString(), QString("harry"));
QCOMPARE(lmodel.data(lmodel.index(0, 2)).toString(), QString("herr"));
QCOMPARE(lmodel.data(lmodel.index(0, 3)), QVariant());
// try removing more than one column
QVERIFY_SQL(lmodel, removeColumns(1, 2));
QCOMPARE(lmodel.columnCount(), 1);
QCOMPARE(lmodel.data(lmodel.index(0, 0)).toInt(), 1);
QCOMPARE(lmodel.data(lmodel.index(0, 1)), QVariant());
// try removing more than one column
QVERIFY_SQL(model, removeColumns(1, 2));
QCOMPARE(model.columnCount(), 1);
QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
QCOMPARE(model.data(model.index(0, 1)), QVariant());
}
}
void tst_QSqlRelationalTableModel::filter()
@ -736,6 +727,7 @@ void tst_QSqlRelationalTableModel::sort()
QFETCH_GLOBAL(QString, dbName);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
fixupTableNamesForDb(db);
const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
QSqlRelationalTableModel model(0, db);
@ -781,7 +773,7 @@ void tst_QSqlRelationalTableModel::sort()
QStringList stringsInDatabaseOrder;
// PostgreSQL puts the null ones (from the table with the original value) first in descending order
// which translate to empty strings in the related table
if (dbType == QSqlDriver::PostgreSQL)
if (dbType == QSqlDriver::PostgreSQL || dbType == QSqlDriver::MimerSQL)
stringsInDatabaseOrder << "" << "" << "mister" << "mister" << "herr" << "herr";
else
stringsInDatabaseOrder << "mister" << "mister" << "herr" << "herr" << "" << "";
@ -794,7 +786,7 @@ void tst_QSqlRelationalTableModel::sort()
// PostgreSQL puts the null ones (from the table with the original value) first in descending order
// which translate to empty strings in the related table
stringsInDatabaseOrder.clear();
if (dbType == QSqlDriver::PostgreSQL)
if (dbType == QSqlDriver::PostgreSQL || dbType == QSqlDriver::MimerSQL)
stringsInDatabaseOrder << "herr" << "mister" << "mister" << "mister" << "mister" << "";
else if (dbType != QSqlDriver::Sybase)
stringsInDatabaseOrder << "" << "herr" << "mister" << "mister" << "mister" << "mister";
@ -873,6 +865,7 @@ void tst_QSqlRelationalTableModel::revert()
QFETCH_GLOBAL(QString, dbName);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
fixupTableNamesForDb(db);
QSqlRelationalTableModel model(0, db);
@ -910,6 +903,7 @@ void tst_QSqlRelationalTableModel::clearDisplayValuesCache()
QFETCH_GLOBAL(QString, dbName);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
fixupTableNamesForDb(db);
const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
QSqlRelationalTableModel model(0, db);
@ -964,6 +958,7 @@ void tst_QSqlRelationalTableModel::insertRecordDuplicateFieldNames()
QFETCH_GLOBAL(QString, dbName);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
fixupTableNamesForDb(db);
const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
QSqlRelationalTableModel model(0, db);
@ -975,13 +970,12 @@ void tst_QSqlRelationalTableModel::insertRecordDuplicateFieldNames()
model.setRelation(2, QSqlRelation(reltest4, "id", "name"));
QVERIFY_SQL(model, select());
if (dbType == QSqlDriver::Interbase || dbType == QSqlDriver::Oracle || dbType == QSqlDriver::DB2) {
QCOMPARE(model.record(1).value((reltest4+QLatin1String("_name_2")).toUpper()).toString(),
QString("Trondheim"));
} else {
QCOMPARE(model.record(1).value((reltest4+QLatin1String("_name_2"))).toString(),
QString("Trondheim"));
}
QString reltest4Unescaped = qTableName("reltest4", __FILE__, db, false);
QString fieldName = reltest4Unescaped + QLatin1String("_name_2");
if (dbType == QSqlDriver::Oracle || dbType == QSqlDriver::DB2)
fieldName = fieldName.toUpper();
fieldName.truncate(db.driver()->maximumIdentifierLength(QSqlDriver::TableName));
QCOMPARE(model.record(1).value(fieldName).toString(), QLatin1String("Trondheim"));
QSqlRecord rec = model.record();
rec.setValue(0, 3);
@ -997,10 +991,7 @@ void tst_QSqlRelationalTableModel::insertRecordDuplicateFieldNames()
}
// The duplicate field names is aliased because it's comes from the relation's display column.
if (dbType == QSqlDriver::Interbase || dbType == QSqlDriver::Oracle || dbType == QSqlDriver::DB2)
QCOMPARE(rec.fieldName(2), (reltest4+QLatin1String("_name_2")).toUpper());
else
QCOMPARE(rec.fieldName(2), reltest4+QLatin1String("_name_2"));
QCOMPARE(rec.fieldName(2), fieldName);
QVERIFY(model.insertRecord(-1, rec));
QCOMPARE(model.data(model.index(2, 2)).toString(), QString("Oslo"));
@ -1013,6 +1004,7 @@ void tst_QSqlRelationalTableModel::invalidData()
QFETCH_GLOBAL(QString, dbName);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
fixupTableNamesForDb(db);
QSqlRelationalTableModel model(0, db);
model.setTable(reltest1);
@ -1043,6 +1035,7 @@ void tst_QSqlRelationalTableModel::relationModel()
QFETCH_GLOBAL(QString, dbName);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
fixupTableNamesForDb(db);
QSqlRelationalTableModel model(0, db);
model.setTable(reltest1);
@ -1086,60 +1079,64 @@ void tst_QSqlRelationalTableModel::casing()
QFETCH_GLOBAL(QString, dbName);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
fixupTableNamesForDb(db);
const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
if (dbType == QSqlDriver::Interbase || dbType == QSqlDriver::SQLite || dbType == QSqlDriver::MSSqlServer)
if (dbType == QSqlDriver::SQLite || dbType == QSqlDriver::MSSqlServer)
QSKIP("The casing test for this database is irrelevant since this database does not treat different cases as separate entities");
QSqlQuery q(db);
QVERIFY_SQL( q, exec("create table " + qTableName("CASETEST1", db).toUpper() +
const QString caseTestUpper = qTableName("CASETEST1", __FILE__, db).toUpper();
const QString caseTestLower = qTableName("casetest1", __FILE__, db);
tst_Databases::safeDropTables(db, {caseTestUpper, caseTestLower});
QVERIFY_SQL( q, exec("create table " + caseTestUpper +
" (id int not null primary key, name varchar(20), title_key int, another_title_key int)"));
if (!q.exec("create table " + qTableName("casetest1", db) +
if (!q.exec("create table " + caseTestLower +
" (ident int not null primary key, name varchar(20), title_key int)"))
QSKIP("The casing test for this database is irrelevant since this database does not treat different cases as separate entities");
QVERIFY_SQL( q, exec("insert into " + qTableName("CASETEST1", db).toUpper() + " values(1, 'harry', 1, 2)"));
QVERIFY_SQL( q, exec("insert into " + qTableName("CASETEST1", db).toUpper() + " values(2, 'trond', 2, 1)"));
QVERIFY_SQL( q, exec("insert into " + qTableName("CASETEST1", db).toUpper() + " values(3, 'vohi', 1, 2)"));
QVERIFY_SQL( q, exec("insert into " + qTableName("CASETEST1", db).toUpper() + " values(4, 'boris', 2, 2)"));
QVERIFY_SQL( q, exec("insert into " + qTableName("casetest1", db) + " values(1, 'jerry', 1)"));
QVERIFY_SQL( q, exec("insert into " + qTableName("casetest1", db) + " values(2, 'george', 2)"));
QVERIFY_SQL( q, exec("insert into " + qTableName("casetest1", db) + " values(4, 'kramer', 2)"));
QVERIFY_SQL( q, exec("insert into " + caseTestUpper + " values(1, 'harry', 1, 2)"));
QVERIFY_SQL( q, exec("insert into " + caseTestUpper + " values(2, 'trond', 2, 1)"));
QVERIFY_SQL( q, exec("insert into " + caseTestUpper + " values(3, 'vohi', 1, 2)"));
QVERIFY_SQL( q, exec("insert into " + caseTestUpper + " values(4, 'boris', 2, 2)"));
QVERIFY_SQL( q, exec("insert into " + caseTestLower + " values(1, 'jerry', 1)"));
QVERIFY_SQL( q, exec("insert into " + caseTestLower + " values(2, 'george', 2)"));
QVERIFY_SQL( q, exec("insert into " + caseTestLower + " values(4, 'kramer', 2)"));
if (dbType == QSqlDriver::Oracle) {
//try an owner that doesn't exist
QSqlRecord rec = db.driver()->record("doug." + qTableName("CASETEST1", db).toUpper());
QSqlRecord rec = db.driver()->record("doug." + caseTestUpper);
QCOMPARE( rec.count(), 0);
//try an owner that does exist
rec = db.driver()->record(db.userName() + QLatin1Char('.') + qTableName("CASETEST1", db).toUpper());
rec = db.driver()->record(db.userName() + QLatin1Char('.') + caseTestUpper);
QCOMPARE( rec.count(), 4);
}
QSqlRecord rec = db.driver()->record(qTableName("CASETEST1", db).toUpper());
QSqlRecord rec = db.driver()->record(caseTestUpper);
QCOMPARE( rec.count(), 4);
rec = db.driver()->record(qTableName("casetest1", db));
rec = db.driver()->record(caseTestLower);
QCOMPARE( rec.count(), 3);
QSqlTableModel upperCaseModel(0, db);
upperCaseModel.setTable(qTableName("CASETEST1", db).toUpper());
upperCaseModel.setTable(caseTestUpper);
QCOMPARE(upperCaseModel.tableName(), qTableName("CASETEST1", db).toUpper());
QCOMPARE(upperCaseModel.tableName(), caseTestUpper);
QVERIFY_SQL(upperCaseModel, select());
QCOMPARE(upperCaseModel.rowCount(), 4);
QSqlTableModel lowerCaseModel(0, db);
lowerCaseModel.setTable(qTableName("casetest1", db));
QCOMPARE(lowerCaseModel.tableName(), qTableName("casetest1", db));
lowerCaseModel.setTable(caseTestLower);
QCOMPARE(lowerCaseModel.tableName(), caseTestLower);
QVERIFY_SQL(lowerCaseModel, select());
QCOMPARE(lowerCaseModel.rowCount(), 3);
QSqlRelationalTableModel model(0, db);
model.setTable(qTableName("CASETEST1", db).toUpper());
model.setTable(caseTestUpper);
model.setRelation(2, QSqlRelation(reltest2, "id", "title"));
QVERIFY_SQL(model, select());
@ -1153,7 +1150,7 @@ void tst_QSqlRelationalTableModel::escapedRelations()
QFETCH_GLOBAL(QString, dbName);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
fixupTableNamesForDb(db);
recreateTestTables(db);
@ -1161,16 +1158,7 @@ void tst_QSqlRelationalTableModel::escapedRelations()
model.setTable(reltest1);
//try with relation table name quoted
if (dbType == QSqlDriver::Interbase || dbType == QSqlDriver::Oracle || dbType == QSqlDriver::DB2) {
model.setRelation(2, QSqlRelation(db.driver()->escapeIdentifier(reltest2.toUpper(),QSqlDriver::TableName),
"id",
"title"));
} else {
model.setRelation(2, QSqlRelation(db.driver()->escapeIdentifier(reltest2,QSqlDriver::TableName),
"id",
"title"));
}
model.setRelation(2, QSqlRelation(escapeTableName(db, reltest2), "id", "title"));
QVERIFY_SQL(model, select());
QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
@ -1185,16 +1173,8 @@ void tst_QSqlRelationalTableModel::escapedRelations()
QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
//try with index column quoted
model.setRelation(2, QSqlRelation(reltest2, escapeFieldName(db, "id"), "title"));
model.setJoinMode(QSqlRelationalTableModel::InnerJoin);
if (dbType == QSqlDriver::Interbase || dbType == QSqlDriver::Oracle || dbType == QSqlDriver::DB2) {
model.setRelation(2, QSqlRelation(reltest2,
db.driver()->escapeIdentifier("id", QSqlDriver::FieldName).toUpper(),
"title"));
} else {
model.setRelation(2, QSqlRelation(reltest2,
db.driver()->escapeIdentifier("id", QSqlDriver::FieldName),
"title"));
}
QVERIFY_SQL(model, select());
QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
@ -1209,18 +1189,8 @@ void tst_QSqlRelationalTableModel::escapedRelations()
QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
//try with display column quoted
model.setRelation(2, QSqlRelation(reltest2, "id", escapeFieldName(db, "title")));
model.setJoinMode(QSqlRelationalTableModel::InnerJoin);
if (dbType == QSqlDriver::Interbase || dbType == QSqlDriver::Oracle || dbType == QSqlDriver::DB2) {
model.setRelation(2, QSqlRelation(reltest2,
"id",
db.driver()->escapeIdentifier("title", QSqlDriver::FieldName).toUpper()));
} else {
model.setRelation(2, QSqlRelation(reltest2,
"id",
db.driver()->escapeIdentifier("title", QSqlDriver::FieldName)));
}
QVERIFY_SQL(model, select());
QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
@ -1235,16 +1205,10 @@ void tst_QSqlRelationalTableModel::escapedRelations()
QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
//try with tablename and index and display columns quoted in the relation
model.setRelation(2, QSqlRelation(escapeTableName(db, reltest2),
escapeFieldName(db, "id"),
escapeFieldName(db, "title")));
model.setJoinMode(QSqlRelationalTableModel::InnerJoin);
if (dbType == QSqlDriver::Interbase || dbType == QSqlDriver::Oracle || dbType == QSqlDriver::DB2) {
model.setRelation(2, QSqlRelation(reltest2,
"id",
db.driver()->escapeIdentifier("title", QSqlDriver::FieldName).toUpper()));
} else {
model.setRelation(2, QSqlRelation(reltest2,
"id",
db.driver()->escapeIdentifier("title", QSqlDriver::FieldName)));
}
QVERIFY_SQL(model, select());
QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
@ -1264,17 +1228,13 @@ void tst_QSqlRelationalTableModel::escapedTableName()
QFETCH_GLOBAL(QString, dbName);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
fixupTableNamesForDb(db);
// set the values using OnRowChange Strategy with an escaped tablename
{
QSqlRelationalTableModel model(0, db);
if (dbType == QSqlDriver::Interbase || dbType == QSqlDriver::Oracle || dbType == QSqlDriver::DB2) {
model.setTable(db.driver()->escapeIdentifier(reltest1.toUpper(), QSqlDriver::TableName));
} else {
model.setTable(db.driver()->escapeIdentifier(reltest1, QSqlDriver::TableName));
}
model.setTable(escapeTableName(db, reltest1));
model.setSort(0, Qt::AscendingOrder);
model.setRelation(2, QSqlRelation(reltest2, "id", "title"));
QVERIFY_SQL(model, select());
@ -1317,11 +1277,7 @@ void tst_QSqlRelationalTableModel::escapedTableName()
{
QSqlRelationalTableModel model(0, db);
if (dbType == QSqlDriver::Interbase || dbType == QSqlDriver::Oracle || dbType == QSqlDriver::DB2) {
model.setTable(db.driver()->escapeIdentifier(reltest1.toUpper(), QSqlDriver::TableName));
} else {
model.setTable(db.driver()->escapeIdentifier(reltest1, QSqlDriver::TableName));
}
model.setTable(escapeTableName(db, reltest1));
model.setSort(0, Qt::AscendingOrder);
model.setRelation(2, QSqlRelation(reltest2, "id", "title"));
model.setJoinMode(QSqlRelationalTableModel::LeftJoin);
@ -1368,9 +1324,8 @@ void tst_QSqlRelationalTableModel::whiteSpaceInIdentifiers()
QFETCH_GLOBAL(QString, dbName);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
fixupTableNamesForDb(db);
if (!testWhiteSpaceNames(db.driverName()))
QSKIP("White space test irrelevant for driver");
QSqlRelationalTableModel model(0, db);
model.setTable(qTableName("rel test6", __FILE__, db));
model.setSort(0, Qt::DescendingOrder);
@ -1453,6 +1408,7 @@ void tst_QSqlRelationalTableModel::psqlSchemaTest()
QFETCH_GLOBAL(QString, dbName);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
fixupTableNamesForDb(db);
QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
if (dbType != QSqlDriver::PostgreSQL)
@ -1480,6 +1436,7 @@ void tst_QSqlRelationalTableModel::selectAfterUpdate()
QFETCH_GLOBAL(QString, dbName);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
fixupTableNamesForDb(db);
QSqlRelationalTableModel model(0, db);
model.setTable(reltest1);
@ -1505,6 +1462,7 @@ void tst_QSqlRelationalTableModel::relationOnFirstColumn()
QFETCH_GLOBAL(QString, dbName);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
fixupTableNamesForDb(db);
QString testTable1 = qTableName("QTBUG_20038_test1", __FILE__, db);
QString testTable2 = qTableName("QTBUG_20038_test2", __FILE__, db);
@ -1519,7 +1477,14 @@ void tst_QSqlRelationalTableModel::relationOnFirstColumn()
QVERIFY_SQL(q, exec("INSERT INTO " + testTable1 + " (id1, val1) VALUES(3, 30);"));
//prepare test2 table
QVERIFY_SQL(q, exec("CREATE TABLE " + testTable2 + " (id INTEGER PRIMARY KEY, name TEXT);"));
if (tst_Databases::getDatabaseType(db) == QSqlDriver::MimerSQL) {
QVERIFY_SQL(q,
exec("CREATE TABLE " + testTable2
+ " (id INTEGER PRIMARY KEY, name NVARCHAR(100));"));
} else {
QVERIFY_SQL(q,
exec("CREATE TABLE " + testTable2 + " (id INTEGER PRIMARY KEY, name VARCHAR(100));"));
}
QVERIFY_SQL(q, exec("DELETE FROM " + testTable2 + QLatin1Char(';')));
QVERIFY_SQL(q, exec("INSERT INTO " + testTable2 + " (id, name) VALUES (10, 'Hervanta');"));
QVERIFY_SQL(q, exec("INSERT INTO " + testTable2 + " (id, name) VALUES (20, 'Keskusta');"));

View File

@ -155,18 +155,15 @@ void tst_QSqlTableModel::dropTestTables()
if (dbType == QSqlDriver::PostgreSQL)
QVERIFY_SQL( q, exec("set client_min_messages='warning'"));
QStringList tableNames;
tableNames << qTableName("test1", __FILE__, db)
<< qTableName("test2", __FILE__, db)
<< qTableName("test3", __FILE__, db)
<< qTableName("test4", __FILE__, db)
<< qTableName("emptytable", __FILE__, db)
<< qTableName("bigtable", __FILE__, db)
<< qTableName("foo", __FILE__, db)
<< qTableName("pktest", __FILE__, db);
if (testWhiteSpaceNames(db.driverName()))
tableNames << qTableName("qtestw hitespace", db);
QStringList tableNames{qTableName("test1", __FILE__, db),
qTableName("test2", __FILE__, db),
qTableName("test3", __FILE__, db),
qTableName("test4", __FILE__, db),
qTableName("emptytable", __FILE__, db),
qTableName("bigtable", __FILE__, db),
qTableName("foo", __FILE__, db),
qTableName("pktest", __FILE__, db),
qTableName("qtestw hitespace", __FILE__, db)};
tst_Databases::safeDropTables(db, tableNames);
if (db.driverName().startsWith("QPSQL")) {
@ -196,10 +193,8 @@ void tst_QSqlTableModel::createTestTables()
QVERIFY_SQL(q, exec("create table " + qTableName("emptytable", __FILE__, db) + "(id int)"));
if (testWhiteSpaceNames(db.driverName())) {
QString qry = "create table " + qTableName("qtestw hitespace", db) + " ("+ db.driver()->escapeIdentifier("a field", QSqlDriver::FieldName) + " int)";
QVERIFY_SQL( q, exec(qry));
}
const auto fieldStr = db.driver()->escapeIdentifier("a field", QSqlDriver::FieldName);
QVERIFY_SQL(q, exec("create table " + qTableName("qtestw hitespace", __FILE__, db) + " ("+ fieldStr + " int)"));
QVERIFY_SQL(q, exec("create table " + qTableName("pktest", __FILE__, db) + "(id int not null primary key, a varchar(20))"));
}
@ -430,8 +425,7 @@ void tst_QSqlTableModel::insertColumns()
{
// Just like the select test, with extra stuff
QFETCH(QString, dbName);
QFETCH(int, submitpolicy_i);
QSqlTableModel::EditStrategy submitpolicy = (QSqlTableModel::EditStrategy) submitpolicy_i;
QFETCH(QSqlTableModel::EditStrategy, submitpolicy);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
const auto test = qTableName("test1", __FILE__, db);
@ -581,13 +575,13 @@ void tst_QSqlTableModel::setRecord()
CHECK_DATABASE(db);
const auto test3 = qTableName("test3", __FILE__, db);
QList<QSqlTableModel::EditStrategy> policies = QList<QSqlTableModel::EditStrategy>() << QSqlTableModel::OnFieldChange << QSqlTableModel::OnRowChange << QSqlTableModel::OnManualSubmit;
const auto policies = { QSqlTableModel::OnFieldChange, QSqlTableModel::OnRowChange, QSqlTableModel::OnManualSubmit };
QString Xsuffix;
foreach( QSqlTableModel::EditStrategy submitpolicy, policies) {
for (QSqlTableModel::EditStrategy submitpolicy : policies) {
QSqlTableModel model(0, db);
model.setEditStrategy((QSqlTableModel::EditStrategy)submitpolicy);
model.setEditStrategy(submitpolicy);
model.setTable(test3);
model.setSort(0, Qt::AscendingOrder);
QVERIFY_SQL(model, select());
@ -601,7 +595,7 @@ void tst_QSqlTableModel::setRecord()
QVERIFY(model.setRecord(i, rec));
// dataChanged() emitted by setData() for each *changed* column
if ((QSqlTableModel::EditStrategy)submitpolicy == QSqlTableModel::OnManualSubmit) {
if (submitpolicy == QSqlTableModel::OnManualSubmit) {
QCOMPARE(spy.size(), 2);
QCOMPARE(spy.at(0).size(), 2);
QCOMPARE(qvariant_cast<QModelIndex>(spy.at(0).at(0)), model.index(i, 1));
@ -609,10 +603,10 @@ void tst_QSqlTableModel::setRecord()
QCOMPARE(qvariant_cast<QModelIndex>(spy.at(1).at(0)), model.index(i, 2));
QCOMPARE(qvariant_cast<QModelIndex>(spy.at(1).at(1)), model.index(i, 2));
QVERIFY(model.submitAll());
} else if ((QSqlTableModel::EditStrategy)submitpolicy == QSqlTableModel::OnRowChange && i == model.rowCount() -1)
} else if (submitpolicy == QSqlTableModel::OnRowChange && i == model.rowCount() -1)
model.submit();
else {
if ((QSqlTableModel::EditStrategy)submitpolicy != QSqlTableModel::OnManualSubmit)
if (submitpolicy != QSqlTableModel::OnManualSubmit)
// dataChanged() also emitted by selectRow()
QCOMPARE(spy.size(), 3);
else
@ -714,8 +708,7 @@ void tst_QSqlTableModel::recordReimpl()
void tst_QSqlTableModel::insertRow()
{
QFETCH(QString, dbName);
QFETCH(int, submitpolicy_i);
QSqlTableModel::EditStrategy submitpolicy = (QSqlTableModel::EditStrategy) submitpolicy_i;
QFETCH(QSqlTableModel::EditStrategy, submitpolicy);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
const auto test = qTableName("test1", __FILE__, db);
@ -824,8 +817,7 @@ void tst_QSqlTableModel::insertRowFailure()
{
QFETCH(QString, dbName);
QSqlDatabase db = QSqlDatabase::database(dbName);
QFETCH(int, submitpolicy_i);
QSqlTableModel::EditStrategy submitpolicy = (QSqlTableModel::EditStrategy) submitpolicy_i;
QFETCH(QSqlTableModel::EditStrategy, submitpolicy);
CHECK_DATABASE(db);
QSqlTableModel model(0, db);
@ -974,8 +966,7 @@ void tst_QSqlTableModel::insertMultiRecords()
void tst_QSqlTableModel::insertWithAutoColumn()
{
QFETCH(QString, dbName);
QFETCH(int, submitpolicy_i);
QSqlTableModel::EditStrategy submitpolicy = (QSqlTableModel::EditStrategy) submitpolicy_i;
QFETCH(QSqlTableModel::EditStrategy, submitpolicy);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
@ -1197,8 +1188,7 @@ void tst_QSqlTableModel::removeRows()
void tst_QSqlTableModel::removeInsertedRow()
{
QFETCH(QString, dbName);
QFETCH(int, submitpolicy_i);
QSqlTableModel::EditStrategy submitpolicy = (QSqlTableModel::EditStrategy) submitpolicy_i;
QFETCH(QSqlTableModel::EditStrategy, submitpolicy);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
const auto test = qTableName("test1", __FILE__, db);
@ -1382,8 +1372,7 @@ void tst_QSqlTableModel::removeInsertedRows()
void tst_QSqlTableModel::revert()
{
QFETCH(QString, dbName);
QFETCH(int, submitpolicy_i);
QSqlTableModel::EditStrategy submitpolicy = (QSqlTableModel::EditStrategy) submitpolicy_i;
QFETCH(QSqlTableModel::EditStrategy, submitpolicy);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
@ -1459,8 +1448,7 @@ void tst_QSqlTableModel::revert()
void tst_QSqlTableModel::isDirty()
{
QFETCH(QString, dbName);
QFETCH(int, submitpolicy_i);
QSqlTableModel::EditStrategy submitpolicy = (QSqlTableModel::EditStrategy) submitpolicy_i;
QFETCH(QSqlTableModel::EditStrategy, submitpolicy);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
const auto test = qTableName("test1", __FILE__, db);
@ -1665,11 +1653,11 @@ void tst_QSqlTableModel::emptyTable()
QCOMPARE(model.columnCount(), 1);
// QTBUG-29108: check correct horizontal header for empty query with pending insert
QCOMPARE(model.headerData(0, Qt::Horizontal).toString(), QString("id"));
QCOMPARE(model.headerData(0, Qt::Horizontal).toString().toLower(), QString("id"));
model.setEditStrategy(QSqlTableModel::OnManualSubmit);
model.insertRow(0);
QCOMPARE(model.rowCount(), 1);
QCOMPARE(model.headerData(0, Qt::Horizontal).toString(), QString("id"));
QCOMPARE(model.headerData(0, Qt::Horizontal).toString().toLower(), QString("id"));
model.revertAll();
}
@ -1700,10 +1688,7 @@ void tst_QSqlTableModel::whitespaceInIdentifiers()
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
if (!testWhiteSpaceNames(db.driverName()))
QSKIP("DBMS doesn't support whitespaces in identifiers");
QString tableName = qTableName("qtestw hitespace", db);
QString tableName = qTableName("qtestw hitespace", __FILE__, db);
QSqlTableModel model(0, db);
model.setTable(tableName);
@ -1947,14 +1932,16 @@ void tst_QSqlTableModel::sqlite_attachedDatabase()
attachedDb.setDatabaseName(db.databaseName()+QLatin1String("attached.dat"));
QVERIFY_SQL(attachedDb, open());
QSqlQuery q(attachedDb);
tst_Databases::safeDropTables(attachedDb, QStringList() << "atest" << "atest2");
TableScope ts(db, "atest", __FILE__);
TableScope tsAttached(attachedDb, "atest", __FILE__);
TableScope tsAttached2(attachedDb, "atest2", __FILE__);
QVERIFY_SQL( q, exec("CREATE TABLE atest(id int, text varchar(20))"));
QVERIFY_SQL( q, exec("CREATE TABLE atest2(id int, text varchar(20))"));
QVERIFY_SQL( q, exec("INSERT INTO atest VALUES(1, 'attached-atest')"));
QVERIFY_SQL( q, exec("INSERT INTO atest2 VALUES(2, 'attached-atest2')"));
QSqlQuery q2(db);
tst_Databases::safeDropTable(db, "atest");
QVERIFY_SQL(q2, exec("CREATE TABLE atest(id int, text varchar(20))"));
QVERIFY_SQL(q2, exec("INSERT INTO atest VALUES(3, 'main')"));
QVERIFY_SQL(q2, exec("ATTACH DATABASE \""+attachedDb.databaseName()+"\" as adb"));
@ -2145,29 +2132,27 @@ void tst_QSqlTableModel::sqlite_selectFromIdentifierWithDot()
{
QFETCH(QString, dbName);
QSqlDatabase db = QSqlDatabase::database(dbName);
TableScope fieldDot(db, "fieldDot", __FILE__);
TableScope tableDot(db, u'[' + qTableName("table.dot", __FILE__, db) + u']');
CHECK_DATABASE(db);
{
const auto fieldDot = qTableName("fieldDot", __FILE__, db);
tst_Databases::safeDropTable(db, fieldDot);
QSqlQuery qry(db);
QVERIFY_SQL(qry, exec("create table " + fieldDot + " (id int primary key, "
QVERIFY_SQL(qry, exec("create table " + fieldDot.tableName() + " (id int primary key, "
"\"person.firstname\" varchar(20))"));
QVERIFY_SQL(qry, exec("insert into " + fieldDot + " values(1, 'Andy')"));
QVERIFY_SQL(qry, exec("insert into " + fieldDot.tableName() + " values(1, 'Andy')"));
QSqlTableModel model(0, db);
model.setTable(fieldDot);
model.setTable(fieldDot.tableName());
QVERIFY_SQL(model, select());
QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
QCOMPARE(model.data(model.index(0, 1)).toString(), QString("Andy"));
}
const auto tableDot = QLatin1Char('[') + qTableName("table.dot", __FILE__, db) + QLatin1Char(']');
{
tst_Databases::safeDropTable(db, tableDot);
QSqlQuery qry(db);
QVERIFY_SQL(qry, exec("create table " + tableDot + " (id int primary key, "
QVERIFY_SQL(qry, exec("create table " + tableDot.tableName() + " (id int primary key, "
"\"person.firstname\" varchar(20))"));
QVERIFY_SQL(qry, exec("insert into " + tableDot + " values(1, 'Andy')"));
QVERIFY_SQL(qry, exec("insert into " + tableDot.tableName() + " values(1, 'Andy')"));
QSqlTableModel model(0, db);
model.setTable(tableDot);
model.setTable(tableDot.tableName());
QVERIFY_SQL(model, select());
QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
QCOMPARE(model.data(model.index(0, 1)).toString(), QString("Andy"));
@ -2179,7 +2164,7 @@ void tst_QSqlTableModel::sqlite_selectFromIdentifierWithDot()
QSqlQuery qry(attachedDb);
QVERIFY_SQL(qry, exec(QString("attach '%1' AS 'attached'").arg(db.databaseName())));
QSqlTableModel model(0, attachedDb);
model.setTable(QString("attached.%1").arg(tableDot));
model.setTable(QString("attached.%1").arg(tableDot.tableName()));
QVERIFY_SQL(model, select());
QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
QCOMPARE(model.data(model.index(0, 1)).toString(), QString("Andy"));