summaryrefslogtreecommitdiffstats
path: root/SQLiteStudio3/Tests
diff options
context:
space:
mode:
Diffstat (limited to 'SQLiteStudio3/Tests')
-rw-r--r--SQLiteStudio3/Tests/CompletionHelperTest/tst_completionhelpertest.cpp12
-rw-r--r--SQLiteStudio3/Tests/DsvFormatsTest/tst_dsvformatstesttest.cpp29
-rw-r--r--SQLiteStudio3/Tests/LexerTest/LexerTest.pro32
-rw-r--r--SQLiteStudio3/Tests/LexerTest/tst_lexertest.cpp66
-rw-r--r--SQLiteStudio3/Tests/ParserTest/tst_parsertest.cpp104
-rw-r--r--SQLiteStudio3/Tests/SelectResolverTest/tst_selectresolvertest.cpp43
-rw-r--r--SQLiteStudio3/Tests/TableModifierTest/tst_tablemodifiertest.cpp132
-rw-r--r--SQLiteStudio3/Tests/TestUtils/TestUtils.pro6
-rw-r--r--SQLiteStudio3/Tests/TestUtils/configmock.cpp40
-rw-r--r--SQLiteStudio3/Tests/TestUtils/configmock.h9
-rw-r--r--SQLiteStudio3/Tests/TestUtils/dbmanagermock.cpp2
-rw-r--r--SQLiteStudio3/Tests/TestUtils/dbmanagermock.h6
-rw-r--r--SQLiteStudio3/Tests/TestUtils/extensionmanagermock.cpp19
-rw-r--r--SQLiteStudio3/Tests/TestUtils/extensionmanagermock.h17
-rw-r--r--SQLiteStudio3/Tests/TestUtils/mocks.cpp2
-rw-r--r--SQLiteStudio3/Tests/Tests.pro3
-rw-r--r--SQLiteStudio3/Tests/UtilsTest/tst_utilssqltest.cpp11
17 files changed, 466 insertions, 67 deletions
diff --git a/SQLiteStudio3/Tests/CompletionHelperTest/tst_completionhelpertest.cpp b/SQLiteStudio3/Tests/CompletionHelperTest/tst_completionhelpertest.cpp
index fc21a55..fd5611a 100644
--- a/SQLiteStudio3/Tests/CompletionHelperTest/tst_completionhelpertest.cpp
+++ b/SQLiteStudio3/Tests/CompletionHelperTest/tst_completionhelpertest.cpp
@@ -63,7 +63,7 @@ CompletionHelperTest::CompletionHelperTest()
QList<ExpectedToken *> CompletionHelperTest::getEntryList(QList<ExpectedTokenPtr> tokens)
{
QList<ExpectedToken*> entries;
- foreach (ExpectedTokenPtr expectedToken, tokens)
+ for (ExpectedTokenPtr expectedToken : tokens)
entries += expectedToken.data();
return entries;
@@ -72,7 +72,7 @@ QList<ExpectedToken *> CompletionHelperTest::getEntryList(QList<ExpectedTokenPtr
QSet<ExpectedToken::Type> CompletionHelperTest::getTypeList(QList<ExpectedTokenPtr> tokens)
{
QSet<ExpectedToken::Type> entries;
- foreach (ExpectedTokenPtr expectedToken, tokens)
+ for (ExpectedTokenPtr expectedToken : tokens)
entries += expectedToken->type;
return entries;
@@ -101,7 +101,7 @@ bool CompletionHelperTest::contains(const QList<ExpectedTokenPtr> &tokens, Expec
int CompletionHelperTest::find(const QList<ExpectedTokenPtr> &tokens, ExpectedToken::Type type)
{
int i = 0;
- foreach (ExpectedTokenPtr token, tokens)
+ for (ExpectedTokenPtr token : tokens)
{
if (token->type == type)
return i;
@@ -114,7 +114,7 @@ int CompletionHelperTest::find(const QList<ExpectedTokenPtr> &tokens, ExpectedTo
int CompletionHelperTest::find(const QList<ExpectedTokenPtr> &tokens, ExpectedToken::Type type, const QString &value)
{
int i = -1;
- foreach (ExpectedTokenPtr token, tokens)
+ for (ExpectedTokenPtr token : tokens)
{
i++;
if (token->type != type)
@@ -129,7 +129,7 @@ int CompletionHelperTest::find(const QList<ExpectedTokenPtr> &tokens, ExpectedTo
int CompletionHelperTest::find(const QList<ExpectedTokenPtr> &tokens, ExpectedToken::Type type, const QString &value, const QString &prefix)
{
int i = -1;
- foreach (ExpectedTokenPtr token, tokens)
+ for (ExpectedTokenPtr token : tokens)
{
i++;
if (token->type != type)
@@ -147,7 +147,7 @@ int CompletionHelperTest::find(const QList<ExpectedTokenPtr> &tokens, ExpectedTo
int CompletionHelperTest::find(const QList<ExpectedTokenPtr> &tokens, ExpectedToken::Type type, const QString &value, const QString &prefix, const QString &contextInfo)
{
int i = -1;
- foreach (ExpectedTokenPtr token, tokens)
+ for (ExpectedTokenPtr token : tokens)
{
i++;
if (token->type != type)
diff --git a/SQLiteStudio3/Tests/DsvFormatsTest/tst_dsvformatstesttest.cpp b/SQLiteStudio3/Tests/DsvFormatsTest/tst_dsvformatstesttest.cpp
index bd55d53..903e6f6 100644
--- a/SQLiteStudio3/Tests/DsvFormatsTest/tst_dsvformatstesttest.cpp
+++ b/SQLiteStudio3/Tests/DsvFormatsTest/tst_dsvformatstesttest.cpp
@@ -14,7 +14,7 @@ class DsvFormatsTestTest : public QObject
public:
DsvFormatsTestTest();
- private:
+private:
QString toString(const QList<QStringList>& input);
QList<QStringList> sampleData;
@@ -27,6 +27,7 @@ class DsvFormatsTestTest : public QObject
void testTsv1();
void testTsv2();
void testCsv1();
+ void testCsvPerformance();
};
DsvFormatsTestTest::DsvFormatsTestTest()
@@ -79,7 +80,7 @@ void DsvFormatsTestTest::testTsv1()
QString result = TsvSerializer::serialize(sampleData);
QString common = "";
- int i;
+ int i = 0;
if (result != sampleTsv)
{
int lgt = qMax(result.length(), sampleTsv.length());
@@ -105,6 +106,30 @@ void DsvFormatsTestTest::testCsv1()
QVERIFY(result.first().size() == 2);
}
+void DsvFormatsTestTest::testCsvPerformance()
+{
+ QString input;
+ for (int i = 0; i < 10000; i++)
+ input += "abc,d,g,\"jkl\nh\",mno\r\n";
+
+ QTemporaryFile theFile;
+ theFile.open();
+ theFile.write(input.toLatin1());
+ theFile.seek(0);
+ QTextStream stream(&theFile);
+
+ QTime timer;
+ timer.start();
+ QList<QStringList> result = CsvSerializer::deserialize(stream, CsvFormat::DEFAULT);
+ int time = timer.elapsed();
+
+ QVERIFY(result.size() == 10000);
+ QVERIFY(result.first().size() == 5);
+ QVERIFY(result.last().size() == 5);
+
+ qDebug() << "Deserialization time:" << time;
+}
+
QTEST_APPLESS_MAIN(DsvFormatsTestTest)
#include "tst_dsvformatstesttest.moc"
diff --git a/SQLiteStudio3/Tests/LexerTest/LexerTest.pro b/SQLiteStudio3/Tests/LexerTest/LexerTest.pro
new file mode 100644
index 0000000..a4f2630
--- /dev/null
+++ b/SQLiteStudio3/Tests/LexerTest/LexerTest.pro
@@ -0,0 +1,32 @@
+#-------------------------------------------------
+#
+# Project created by QtCreator 2018-07-15T23:45:16
+#
+#-------------------------------------------------
+
+include($$PWD/../TestUtils/test_common.pri)
+
+QT += testlib
+
+QT -= gui
+
+TARGET = tst_lexertest
+CONFIG += console
+CONFIG -= app_bundle
+
+TEMPLATE = app
+
+# The following define makes your compiler emit warnings if you use
+# any feature of Qt which has been marked as deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if you use deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+
+SOURCES += \
+ tst_lexertest.cpp
diff --git a/SQLiteStudio3/Tests/LexerTest/tst_lexertest.cpp b/SQLiteStudio3/Tests/LexerTest/tst_lexertest.cpp
new file mode 100644
index 0000000..deac898
--- /dev/null
+++ b/SQLiteStudio3/Tests/LexerTest/tst_lexertest.cpp
@@ -0,0 +1,66 @@
+#include "parser/lexer.h"
+#include <QString>
+#include <QtTest>
+
+class LexerTest : public QObject
+{
+ Q_OBJECT
+
+ public:
+ LexerTest();
+
+ private Q_SLOTS:
+ void testStringCase1();
+ void testFloat();
+ void testHex1();
+ void testHex2();
+};
+
+LexerTest::LexerTest()
+{
+}
+
+void LexerTest::testStringCase1()
+{
+ QString sql = "INSERT INTO tab VALUES (1, 2, :val); /* test";
+
+ Lexer lex(Dialect::Sqlite3);
+ TokenList tokens = lex.tokenize(sql);
+ QVERIFY(tokens.size() == 20);
+}
+
+void LexerTest::testFloat()
+{
+ QString sql = "SELECT .2";
+
+ Lexer lex(Dialect::Sqlite3);
+ TokenList tokens = lex.tokenize(sql);
+ QVERIFY(tokens.size() == 3);
+ QVERIFY(tokens[2]->type == Token::FLOAT);
+}
+
+void LexerTest::testHex1()
+{
+ QString sql = "SELECT 0x";
+
+ Lexer lex(Dialect::Sqlite3);
+ TokenList tokens = lex.tokenize(sql);
+ QVERIFY(tokens.size() == 3);
+ QVERIFY(tokens[2]->type == Token::INVALID);
+}
+
+void LexerTest::testHex2()
+{
+ QString sql = "SELECT 0x5zzz";
+
+ Lexer lex(Dialect::Sqlite3);
+ TokenList tokens = lex.tokenize(sql);
+ QVERIFY(tokens.size() == 4);
+ QVERIFY(tokens[2]->type == Token::INTEGER);
+ QVERIFY(tokens[3]->type == Token::OTHER);
+ QVERIFY(tokens[3]->value == "zzz");
+}
+
+QTEST_APPLESS_MAIN(LexerTest)
+
+#include "tst_lexertest.moc"
diff --git a/SQLiteStudio3/Tests/ParserTest/tst_parsertest.cpp b/SQLiteStudio3/Tests/ParserTest/tst_parsertest.cpp
index 7355616..eb2a76f 100644
--- a/SQLiteStudio3/Tests/ParserTest/tst_parsertest.cpp
+++ b/SQLiteStudio3/Tests/ParserTest/tst_parsertest.cpp
@@ -1,12 +1,15 @@
#include "parser/parser.h"
#include "parser/ast/sqliteselect.h"
#include "parser/ast/sqlitecreatetable.h"
+#include "parser/ast/sqliteinsert.h"
+#include "parser/ast/sqlitewith.h"
+#include "parser/ast/sqliteupdate.h"
#include "parser/keywords.h"
#include "parser/lexer.h"
#include "parser/parsererror.h"
+#include "common/utils_sql.h"
#include <QString>
#include <QtTest>
-#include <parser/ast/sqliteinsert.h>
class ParserTest : public QObject
{
@@ -40,6 +43,12 @@ class ParserTest : public QObject
void testCommentBeginMultiline();
void testBetween();
void testBigNum();
+ void testSelectWith();
+ void testInsertWithDoubleQuoteValues();
+ void testParseAndRebuildAlias();
+ void testRebuildTokensUpdate();
+ void testRebuildTokensInsertUpsert();
+ void testGetColumnTokensFromInsertUpsert();
void initTestCase();
void cleanupTestCase();
};
@@ -134,7 +143,7 @@ void ParserTest::testGetFullObjects()
QList<SqliteStatement::FullObject> fullObjects = query->getContextFullObjects();
QVERIFY(fullObjects.size() == 2);
- foreach (const SqliteStatement::FullObject& fullObj, fullObjects)
+ for (const SqliteStatement::FullObject& fullObj : fullObjects)
{
switch (fullObj.type)
{
@@ -162,7 +171,7 @@ void ParserTest::testGetFullObjects2()
QList<SqliteStatement::FullObject> fullObjects = query->getContextFullObjects();
QVERIFY(fullObjects.size() == 5);
- foreach (const SqliteStatement::FullObject& fullObj, fullObjects)
+ for (const SqliteStatement::FullObject& fullObj : fullObjects)
{
switch (fullObj.type)
{
@@ -401,10 +410,99 @@ void ParserTest::testUniqConflict()
QVERIFY(tokens[16]->type == Token::Type::PAR_RIGHT);
}
+void ParserTest::testSelectWith()
+{
+ QString sql = "WITH m (c1, c2) AS (VALUES (1, 'a'), (2, 'b')) SELECT * FROM m;";
+ bool res = parser3->parse(sql);
+ QVERIFY(res);
+ QVERIFY(parser3->getErrors().isEmpty());
+
+ const SqliteQueryPtr query = parser3->getQueries().first();
+ query->rebuildTokens();
+ QString detokenized = query->detokenize().replace(" ", "");
+ QVERIFY(sql.replace(" ", "") == detokenized);
+}
+
+void ParserTest::testInsertWithDoubleQuoteValues()
+{
+ QString sql = "REPLACE INTO _Variables (Name, TextValue) VALUES (\"varNowTime\", strftime(\"%Y-%m-%dT%H:%M:%S\", \"now\", \"localtime\"));";
+ bool res = parser3->parse(sql);
+ QVERIFY(res);
+ QVERIFY(parser3->getErrors().isEmpty());
+
+ const SqliteInsertPtr insert = parser3->getQueries().first().dynamicCast<SqliteInsert>();
+ insert->rebuildTokens();
+ QString detokenized = insert->detokenize().replace(" ", "");
+ QVERIFY(sql.replace(" ", "") == detokenized);
+}
+
+void ParserTest::testParseAndRebuildAlias()
+{
+ QString sql = "SELECT x AS [\"abc\".\"def\"];";
+ bool res = parser3->parse(sql);
+ QVERIFY(res);
+ QVERIFY(parser3->getErrors().isEmpty());
+
+ SqliteQueryPtr query = parser3->getQueries().first();
+ query->rebuildTokens();
+ QString newSql = query->detokenize();
+ QVERIFY(sql == newSql);
+}
+
+void ParserTest::testRebuildTokensUpdate()
+{
+ QString sql = "UPDATE tab SET col1 = 1, (col2, col3) = 2 WHERE x = 3;";
+ bool res = parser3->parse(sql);
+ QVERIFY(res);
+ QVERIFY(parser3->getErrors().isEmpty());
+
+ SqliteUpdatePtr update = parser3->getQueries().first().dynamicCast<SqliteUpdate>();
+ QVERIFY(update->keyValueMap.size() == 2);
+ QVERIFY(update->keyValueMap[1].first.type() == QVariant::StringList);
+ QStringList set2List = update->keyValueMap[1].first.toStringList();
+ QVERIFY(set2List[0] == "col2");
+ QVERIFY(set2List[1] == "col3");
+ QVERIFY(update->where);
+ QVERIFY(!update->table.isNull());
+ QVERIFY(update->where);
+ update->rebuildTokens();
+ QVERIFY(update->tokens.detokenize() == sql);
+}
+
+void ParserTest::testRebuildTokensInsertUpsert()
+{
+ QString sql = "INSERT INTO tab (a1, a2) VALUES (123, 456) ON CONFLICT (b1, b2, b3) DO UPDATE SET col1 = 1, (col2, col3) = 2 WHERE x = 3;";
+ bool res = parser3->parse(sql);
+ QVERIFY(res);
+ QVERIFY(parser3->getErrors().isEmpty());
+
+ SqliteInsertPtr insert = parser3->getQueries().first().dynamicCast<SqliteInsert>();
+ QVERIFY(insert->upsert);
+
+ insert->rebuildTokens();
+ QVERIFY(insert->tokens.detokenize() == sql);
+}
+
+void ParserTest::testGetColumnTokensFromInsertUpsert()
+{
+ QString sql = "INSERT INTO tab (a1, a2) VALUES (123, 456) ON CONFLICT (b1, b2, b3) DO UPDATE SET col1 = 1, (col2, col3) = 2 WHERE x = 3;";
+ bool res = parser3->parse(sql);
+ QVERIFY(res);
+ QVERIFY(parser3->getErrors().isEmpty());
+
+ SqliteInsertPtr insert = parser3->getQueries().first().dynamicCast<SqliteInsert>();
+ QVERIFY(insert->upsert);
+
+ TokenList tk = insert->getContextColumnTokens();
+ qSort(tk.begin(), tk.end(), [](const TokenPtr& t1, const TokenPtr& t2) {return t1->start < t2->start;});
+ QVERIFY(tk.toValueList().join(" ") == "a1 a2 b1 b2 b3 col1 col2 col3 x");
+}
+
void ParserTest::initTestCase()
{
initKeywords();
Lexer::staticInit();
+ initUtilsSql();
parser2 = new Parser(Dialect::Sqlite2);
parser3 = new Parser(Dialect::Sqlite3);
}
diff --git a/SQLiteStudio3/Tests/SelectResolverTest/tst_selectresolvertest.cpp b/SQLiteStudio3/Tests/SelectResolverTest/tst_selectresolvertest.cpp
index 2d6762e..13a30a9 100644
--- a/SQLiteStudio3/Tests/SelectResolverTest/tst_selectresolvertest.cpp
+++ b/SQLiteStudio3/Tests/SelectResolverTest/tst_selectresolvertest.cpp
@@ -27,7 +27,9 @@ class SelectResolverTest : public QObject
void testTableHash();
void testColumnHash();
void testWithCommonTableExpression();
+ void testWithCte2();
void testStarWithJoinAndError();
+ void testTableFunction();
void test1();
void testSubselectWithAlias();
};
@@ -196,6 +198,26 @@ void SelectResolverTest::testWithCommonTableExpression()
QVERIFY(coreColumns[0].flags & SelectResolver::Flag::FROM_CTE_SELECT);
}
+void SelectResolverTest::testWithCte2()
+{
+ QString sql = "with m(c1, c2) as ("
+ " values (1, 'a'), (2, 'b'), (3, 'c')"
+ ")"
+ "select * from m";
+
+ SelectResolver resolver(db, sql);
+ Parser parser(db->getDialect());
+ QVERIFY(parser.parse(sql));
+
+ QList<QList<SelectResolver::Column>> columns = resolver.resolve(parser.getQueries().first().dynamicCast<SqliteSelect>().data());
+ QList<SelectResolver::Column> coreColumns = columns.first();
+ QVERIFY(coreColumns.size() == 2);
+ QVERIFY(coreColumns[0].type == SelectResolver::Column::COLUMN);
+ QVERIFY(coreColumns[0].flags & SelectResolver::Flag::FROM_CTE_SELECT);
+ QVERIFY(coreColumns[1].type == SelectResolver::Column::COLUMN);
+ QVERIFY(coreColumns[1].flags & SelectResolver::Flag::FROM_CTE_SELECT);
+}
+
void SelectResolverTest::testStarWithJoinAndError()
{
QString sql = "SELECT t1.*, t2.* FROM test t1 JOIN test2 USING (col1)";
@@ -208,6 +230,27 @@ void SelectResolverTest::testStarWithJoinAndError()
QVERIFY(resolver.hasErrors());
}
+void SelectResolverTest::testTableFunction()
+{
+ QString sql = "select * from json_tree(json_array(1, 2, 3))";
+ SelectResolver resolver(db, sql);
+ Parser parser(db->getDialect());
+ QVERIFY(parser.parse(sql));
+
+ SqlQueryPtr versionResult = db->exec("select sqlite_version()");
+ qDebug() << "SQLite3 version:" << versionResult->getSingleCell().toString();
+
+ SqliteSelectPtr select = parser.getQueries().first().dynamicCast<SqliteSelect>();
+ QList<QList<SelectResolver::Column> > columns = resolver.resolve(select.data());
+ if (resolver.hasErrors()) {
+ for (const QString& err : resolver.getErrors())
+ qWarning() << err;
+ }
+ QVERIFY(!resolver.hasErrors());
+ QVERIFY(columns.first().size() == 8);
+ QVERIFY(columns.first().first().type == SelectResolver::Column::OTHER);
+}
+
void SelectResolverTest::test1()
{
QString sql = "SELECT * FROM (SELECT count(col1), col2 FROM test)";
diff --git a/SQLiteStudio3/Tests/TableModifierTest/tst_tablemodifiertest.cpp b/SQLiteStudio3/Tests/TableModifierTest/tst_tablemodifiertest.cpp
index 2630f36..7bb8c0e 100644
--- a/SQLiteStudio3/Tests/TableModifierTest/tst_tablemodifiertest.cpp
+++ b/SQLiteStudio3/Tests/TableModifierTest/tst_tablemodifiertest.cpp
@@ -55,23 +55,29 @@ void TableModifierTest::testCase1()
QStringList sqls = mod.generateSqls();
/*
+ * 1. Disable FK.
* 1. Create new (with new name)
* 2. Copy data to new
- * 3. Drop old table.
- * 4. Rename referencing table to temp name.
- * 5. Create new referencing table.
- * 6. Copy data to new referencing table.
- * 7. Drop temp table.
+ * 4. Rename referencing table to temp name in 2 steps.
+ * 5. Second step of renaming - drop old table.
+ * 6. Create new referencing table.
+ * 7. Copy data to new referencing table.
+ * 8. Drop temp table.
+ * 9. Drop old table.
+ * 10. Re-enable FK.
*/
- QVERIFY(sqls.size() == 7);
+ QVERIFY(sqls.size() == 10);
int i = 0;
+ verifyRe("PRAGMA foreign_keys = 0;", sqls[i++]);
verifyRe("CREATE TABLE test2 .*", sqls[i++]);
verifyRe("INSERT INTO test2.*SELECT.*FROM test;", sqls[i++]);
- verifyRe("DROP TABLE test;", sqls[i++]);
- verifyRe("ALTER TABLE abc RENAME TO sqlitestudio_temp_table.*", sqls[i++]);
+ verifyRe("CREATE TABLE sqlitestudio_temp_table.*AS SELECT.*FROM abc.*", sqls[i++]);
+ verifyRe("DROP TABLE abc;", sqls[i++]);
verifyRe("CREATE TABLE abc .*", sqls[i++]);
verifyRe("INSERT INTO abc.*SELECT.*FROM sqlitestudio_temp_table.*", sqls[i++]);
verifyRe("DROP TABLE sqlitestudio_temp_table.*", sqls[i++]);
+ verifyRe("DROP TABLE test;", sqls[i++]);
+ verifyRe("PRAGMA foreign_keys = 1;", sqls[i++]);
}
void TableModifierTest::testCase2()
@@ -84,25 +90,33 @@ void TableModifierTest::testCase2()
QStringList sqls = mod.generateSqls();
/*
- * 1. Rename to temp.
- * 2. Create new.
- * 3. Copy data from temp to new one.
- * 4. Drop temp table.
- * 5. Rename referencing table to temp name.
- * 6. Create new referencing table.
- * 7. Copy data to new referencing table.
- * 8. Drop temp table.
+ * 1. Disable FK.
+ * 2. Rename to temp in 2 steps.
+ * 3. Second step of renaming (drop).
+ * 4. Create new.
+ * 5. Copy data from temp to new one.
+ * 6. Rename referencing table to temp name in 2 steps.
+ * 7. Second step of renaming (drop).
+ * 8. Create new referencing table.
+ * 9. Copy data to new referencing table.
+ * 10. Drop first temp table.
+ * 11. Drop second temp table.
+ * 12. Enable FK.
*/
- QVERIFY(sqls.size() == 8);
+ QVERIFY(sqls.size() == 12);
int i = 0;
- verifyRe("ALTER TABLE test RENAME TO sqlitestudio_temp_table.*", sqls[i++]);
+ verifyRe("PRAGMA foreign_keys = 0;", sqls[i++]);
+ verifyRe("CREATE TABLE sqlitestudio_temp_table.*AS SELECT.*FROM test.*", sqls[i++]);
+ verifyRe("DROP TABLE test;", sqls[i++]);
verifyRe("CREATE TABLE test .*newCol.*", sqls[i++]);
verifyRe("INSERT INTO test.*SELECT.*FROM sqlitestudio_temp_table.*", sqls[i++]);
- verifyRe("DROP TABLE sqlitestudio_temp_table.*", sqls[i++]);
- verifyRe("ALTER TABLE abc RENAME TO sqlitestudio_temp_table.*", sqls[i++]);
+ verifyRe("CREATE TABLE sqlitestudio_temp_table.*AS SELECT.*FROM abc.*", sqls[i++]);
+ verifyRe("DROP TABLE abc;", sqls[i++]);
verifyRe("CREATE TABLE abc .*xyz text REFERENCES test \\(newCol\\).*", sqls[i++]);
verifyRe("INSERT INTO abc.*SELECT.*FROM sqlitestudio_temp_table.*", sqls[i++]);
verifyRe("DROP TABLE sqlitestudio_temp_table.*", sqls[i++]);
+ verifyRe("DROP TABLE sqlitestudio_temp_table.*", sqls[i++]);
+ verifyRe("PRAGMA foreign_keys = 1;", sqls[i++]);
}
void TableModifierTest::testCase3()
@@ -118,27 +132,33 @@ void TableModifierTest::testCase3()
QStringList sqls = mod.generateSqls();
/*
- * 1. Create new (with new name)
- * 2. Copy data to new
- * 3. Drop old table.
- * 4. Rename referencing table to temp name.
- * 5. Create new referencing table.
- * 6. Copy data to new referencing table.
- * 7. Drop temp table.
- * 8. Re-create index i2.
- * 9. Re-create index i1 with new table name and column name.
+ * 1. Disable FK.
+ * 2. Create new (with new name)
+ * 3. Copy data to new
+ * 4. Drop old table.
+ * 5. Rename referencing table to temp name in two steps.
+ * 6. Second step of renaming (drop).
+ * 7. Create new referencing table.
+ * 8. Copy data to new referencing table.
+ * 9. Drop temp table.
+ * 10. Re-create index i2.
+ * 11. Re-create index i1 with new table name and column name.
+ * 12. Disable FK.
*/
- QVERIFY(sqls.size() == 9);
+ QVERIFY(sqls.size() == 12);
int i = 0;
+ verifyRe("PRAGMA foreign_keys = 0;", sqls[i++]);
verifyRe("CREATE TABLE newTable .*", sqls[i++]);
verifyRe("INSERT INTO newTable.*SELECT.*FROM test;", sqls[i++]);
- verifyRe("DROP TABLE test;", sqls[i++]);
- verifyRe("ALTER TABLE abc RENAME TO sqlitestudio_temp_table.*", sqls[i++]);
+ verifyRe("CREATE TABLE sqlitestudio_temp_table.*AS SELECT.*FROM abc.*", sqls[i++]);
+ verifyRe("DROP TABLE abc;", sqls[i++]);
verifyRe("CREATE TABLE abc .*xyz text REFERENCES newTable \\(newCol\\).*", sqls[i++]);
verifyRe("INSERT INTO abc.*SELECT.*FROM sqlitestudio_temp_table.*", sqls[i++]);
verifyRe("DROP TABLE sqlitestudio_temp_table.*", sqls[i++]);
verifyRe("CREATE INDEX i2 ON abc \\(id\\);", sqls[i++]);
+ verifyRe("DROP TABLE test;", sqls[i++]);
verifyRe("CREATE INDEX i1 ON newTable \\(newCol\\);", sqls[i++]);
+ verifyRe("PRAGMA foreign_keys = 1;", sqls[i++]);
}
void TableModifierTest::testCase4()
@@ -156,13 +176,16 @@ void TableModifierTest::testCase4()
QStringList sqls = mod.generateSqls();
/*
- * 1. Create new (with new name)
- * 2. Copy data to new
- * 3. Drop old table.
- * 4. Recreate trigger with all subqueries updated.
+ * 1. Disable FK.
+ * 2. Create new (with new name)
+ * 3. Copy data to new
+ * 4. Drop old table.
+ * 5. Recreate trigger with all subqueries updated.
+ * 6. Enable FK.
*/
- QVERIFY(sqls.size() == 4);
+ QVERIFY(sqls.size() == 6);
int i = 0;
+ verifyRe("PRAGMA foreign_keys = 0;", sqls[i++]);
verifyRe("CREATE TABLE newTable .*", sqls[i++]);
verifyRe("INSERT INTO newTable.*SELECT.*FROM test;", sqls[i++]);
verifyRe("DROP TABLE test;", sqls[i++]);
@@ -172,6 +195,7 @@ void TableModifierTest::testCase4()
"UPDATE newTable SET newCol = (SELECT newCol FROM newTable) WHERE x = (SELECT newCol FROM newTable); "
"INSERT INTO newTable (newCol) VALUES (1); "
"END;" == sqls[i++], "Trigger DDL incorrect.");
+ verifyRe("PRAGMA foreign_keys = 1;", sqls[i++]);
}
void TableModifierTest::testCase5()
@@ -188,21 +212,25 @@ void TableModifierTest::testCase5()
QStringList sqls = mod.generateSqls();
/*
- * 1. Create new (with new name)
- * 2. Copy data to new
- * 3. Drop old table.
- * 4. Drop old view.
- * 5. Recreate view with new column and table.
- * 6. Recreate trigger with all subqueries updated.
+ * 1. Disable FK.
+ * 2. Create new (with new name)
+ * 3. Copy data to new
+ * 4. Drop old table.
+ * 5. Drop old view.
+ * 6. Recreate view with new column and table.
+ * 7. Recreate trigger with all subqueries updated.
+ * 8. Enable FK.
*/
- QVERIFY(sqls.size() == 6);
+ QVERIFY(sqls.size() == 8);
int i = 0;
+ verifyRe("PRAGMA foreign_keys = 0;", sqls[i++]);
verifyRe("CREATE TABLE newTable .*", sqls[i++]);
verifyRe("INSERT INTO newTable.*SELECT.*FROM test;", sqls[i++]);
verifyRe("DROP TABLE test;", sqls[i++]);
verifyRe("DROP VIEW v1;", sqls[i++]);
verifyRe("CREATE VIEW v1 AS SELECT \\* FROM \\(SELECT newCol FROM newTable\\);", sqls[i++]);
verifyRe("CREATE TRIGGER t1 INSTEAD OF INSERT ON v1 BEGIN SELECT 1; END;", sqls[i++]);
+ verifyRe("PRAGMA foreign_keys = 1;", sqls[i++]);
}
void TableModifierTest::testCase6()
@@ -217,19 +245,25 @@ void TableModifierTest::testCase6()
QStringList sqls = mod.generateSqls();
/*
- * 1. Create new (with new name)
- * 2. Copy data to new
- * 3. Drop old table.
- * 4. Recreate trigger with all subqueries updated.
+ * 1. Disable FK.
+ * 2. Create new (with new name)
+ * 3. Copy data to new
+ * 4. Drop old table.
+ * 5. Recreate trigger with all subqueries updated.
+ * 6. Drop view.
+ * 7. Recreate view with new table referenced.
+ * 8. Enable FK.
*/
- QVERIFY(sqls.size() == 6);
+ QVERIFY(sqls.size() == 8);
int i = 0;
+ verifyRe("PRAGMA foreign_keys = 0;", sqls[i++]);
verifyRe("CREATE TABLE newTable \\(id int, val2 text\\);", sqls[i++]);
verifyRe("INSERT INTO newTable \\(id, val2\\) SELECT id, val2 FROM test;", sqls[i++]);
verifyRe("DROP TABLE test;", sqls[i++]);
verifyRe("CREATE TRIGGER t2 AFTER UPDATE OF Id ON newTable BEGIN SELECT NULL, Val2 FROM newTable; END;", sqls[i++]);
verifyRe("DROP VIEW v1;", sqls[i++]);
verifyRe("CREATE VIEW v1 AS SELECT \\* FROM \\(SELECT Id, NULL FROM newTable\\);", sqls[i++]);
+ verifyRe("PRAGMA foreign_keys = 1;", sqls[i++]);
}
void TableModifierTest::initTestCase()
diff --git a/SQLiteStudio3/Tests/TestUtils/TestUtils.pro b/SQLiteStudio3/Tests/TestUtils/TestUtils.pro
index f448ccb..77e0b19 100644
--- a/SQLiteStudio3/Tests/TestUtils/TestUtils.pro
+++ b/SQLiteStudio3/Tests/TestUtils/TestUtils.pro
@@ -23,7 +23,8 @@ SOURCES += \
mocks.cpp \
dbattachermock.cpp \
dbmanagermock.cpp \
- collationmanagermock.cpp
+ collationmanagermock.cpp \
+ extensionmanagermock.cpp
HEADERS +=\
testutils_global.h \
@@ -35,7 +36,8 @@ HEADERS +=\
mocks.h \
dbattachermock.h \
dbmanagermock.h \
- collationmanagermock.h
+ collationmanagermock.h \
+ extensionmanagermock.h
unix:!symbian {
maemo5 {
diff --git a/SQLiteStudio3/Tests/TestUtils/configmock.cpp b/SQLiteStudio3/Tests/TestUtils/configmock.cpp
index 9bf3863..5a9169a 100644
--- a/SQLiteStudio3/Tests/TestUtils/configmock.cpp
+++ b/SQLiteStudio3/Tests/TestUtils/configmock.cpp
@@ -35,6 +35,11 @@ QVariant ConfigMock::get(const QString&, const QString&)
return QVariant();
}
+QVariant ConfigMock::get(const QString &, const QString &, const QVariant &)
+{
+ return QVariant();
+}
+
QHash<QString, QVariant> ConfigMock::getAll()
{
return QHash<QString, QVariant>();
@@ -102,6 +107,10 @@ void ConfigMock::clearSqlHistory()
{
}
+void ConfigMock::deleteSqlHistory(const QList<qint64>&)
+{
+}
+
QAbstractItemModel* ConfigMock::getSqlHistoryModel()
{
return nullptr;
@@ -124,6 +133,37 @@ QStringList ConfigMock::getCliHistory() const
return QStringList();
}
+void ConfigMock::addBindParamHistory(const QVector<QPair<QString, QVariant> >&)
+{
+}
+
+void ConfigMock::applyBindParamHistoryLimit()
+{
+}
+
+QVector<QPair<QString, QVariant> > ConfigMock::getBindParamHistory(const QStringList&) const
+{
+ return QVector<QPair<QString, QVariant>>();
+}
+
+void ConfigMock::addPopulateHistory(const QString&, const QString&, int, const QHash<QString, QPair<QString, QVariant> >&)
+{
+}
+
+void ConfigMock::applyPopulateHistoryLimit()
+{
+}
+
+QHash<QString, QPair<QString, QVariant>> ConfigMock::getPopulateHistory(const QString&, const QString&, int&) const
+{
+ return QHash<QString, QPair<QString, QVariant>>();
+}
+
+QVariant ConfigMock::getPopulateHistory(const QString&) const
+{
+ return QVariant();
+}
+
void ConfigMock::addDdlHistory(const QString&, const QString&, const QString&)
{
}
diff --git a/SQLiteStudio3/Tests/TestUtils/configmock.h b/SQLiteStudio3/Tests/TestUtils/configmock.h
index 89c870e..7f04e98 100644
--- a/SQLiteStudio3/Tests/TestUtils/configmock.h
+++ b/SQLiteStudio3/Tests/TestUtils/configmock.h
@@ -16,6 +16,7 @@ class ConfigMock : public Config
void rollbackMassSave();
void set(const QString&, const QString&, const QVariant&);
QVariant get(const QString&, const QString&);
+ QVariant get(const QString&, const QString&, const QVariant&);
QHash<QString, QVariant> getAll();
bool addDb(const QString&, const QString&, const QHash<QString, QVariant>&);
bool updateDb(const QString&, const QString&, const QString&, const QHash<QString, QVariant>&);
@@ -30,11 +31,19 @@ class ConfigMock : public Config
qint64 addSqlHistory(const QString&, const QString&, int, int);
void updateSqlHistory(qint64, const QString&, const QString&, int, int);
void clearSqlHistory();
+ void deleteSqlHistory(const QList<qint64>&);
QAbstractItemModel*getSqlHistoryModel();
void addCliHistory(const QString&);
void applyCliHistoryLimit();
void clearCliHistory();
QStringList getCliHistory() const;
+ void addBindParamHistory(const QVector<QPair<QString, QVariant>>&);
+ void applyBindParamHistoryLimit();
+ QVector<QPair<QString, QVariant>> getBindParamHistory(const QStringList&) const;
+ void addPopulateHistory(const QString&, const QString&, int, const QHash<QString, QPair<QString, QVariant>>&);
+ void applyPopulateHistoryLimit();
+ QHash<QString, QPair<QString, QVariant>> getPopulateHistory(const QString&, const QString&, int&) const;
+ QVariant getPopulateHistory(const QString&) const;
void addDdlHistory(const QString&, const QString&, const QString&);
QList<DdlHistoryEntryPtr> getDdlHistoryFor(const QString&, const QString&, const QDate&);
DdlHistoryModel* getDdlHistoryModel();
diff --git a/SQLiteStudio3/Tests/TestUtils/dbmanagermock.cpp b/SQLiteStudio3/Tests/TestUtils/dbmanagermock.cpp
index 926e57b..10caed4 100644
--- a/SQLiteStudio3/Tests/TestUtils/dbmanagermock.cpp
+++ b/SQLiteStudio3/Tests/TestUtils/dbmanagermock.cpp
@@ -57,7 +57,7 @@ Db* DbManagerMock::getByPath(const QString&)
return nullptr;
}
-Db*DbManagerMock::createInMemDb()
+Db*DbManagerMock::createInMemDb(bool)
{
return nullptr;
}
diff --git a/SQLiteStudio3/Tests/TestUtils/dbmanagermock.h b/SQLiteStudio3/Tests/TestUtils/dbmanagermock.h
index ce7eb51..ee69fa1 100644
--- a/SQLiteStudio3/Tests/TestUtils/dbmanagermock.h
+++ b/SQLiteStudio3/Tests/TestUtils/dbmanagermock.h
@@ -16,9 +16,9 @@ class DbManagerMock : public DbManager
QList<Db*> getValidDbList();
QList<Db*> getConnectedDbList();
QStringList getDbNames();
- Db*getByName(const QString&, Qt::CaseSensitivity);
- Db*getByPath(const QString&);
- Db*createInMemDb();
+ Db* getByName(const QString&, Qt::CaseSensitivity);
+ Db* getByPath(const QString&);
+ Db* createInMemDb(bool = false);
bool isTemporary(Db*);
QString quickAddDb(const QString &path, const QHash<QString, QVariant> &);
DbPlugin* getPluginForDbFile(const QString&);
diff --git a/SQLiteStudio3/Tests/TestUtils/extensionmanagermock.cpp b/SQLiteStudio3/Tests/TestUtils/extensionmanagermock.cpp
new file mode 100644
index 0000000..dc4669b
--- /dev/null
+++ b/SQLiteStudio3/Tests/TestUtils/extensionmanagermock.cpp
@@ -0,0 +1,19 @@
+#include "extensionmanagermock.h"
+
+ExtensionManagerMock::ExtensionManagerMock()
+{
+}
+
+void ExtensionManagerMock::setExtensions(const QList<SqliteExtensionManager::ExtensionPtr>&)
+{
+}
+
+QList<SqliteExtensionManager::ExtensionPtr> ExtensionManagerMock::getAllExtensions() const
+{
+ return QList<SqliteExtensionManager::ExtensionPtr>();
+}
+
+QList<SqliteExtensionManager::ExtensionPtr> ExtensionManagerMock::getExtensionForDatabase(const QString&) const
+{
+ return QList<SqliteExtensionManager::ExtensionPtr>();
+}
diff --git a/SQLiteStudio3/Tests/TestUtils/extensionmanagermock.h b/SQLiteStudio3/Tests/TestUtils/extensionmanagermock.h
new file mode 100644
index 0000000..7a7a1f4
--- /dev/null
+++ b/SQLiteStudio3/Tests/TestUtils/extensionmanagermock.h
@@ -0,0 +1,17 @@
+#ifndef EXTENSIONMANAGERMOCK_H
+#define EXTENSIONMANAGERMOCK_H
+
+#include "services/sqliteextensionmanager.h"
+
+class ExtensionManagerMock : public SqliteExtensionManager
+{
+ public:
+ ExtensionManagerMock();
+
+ public:
+ void setExtensions(const QList<ExtensionPtr>&);
+ QList<ExtensionPtr> getAllExtensions() const;
+ QList<ExtensionPtr> getExtensionForDatabase(const QString&) const;
+};
+
+#endif // EXTENSIONMANAGERMOCK_H
diff --git a/SQLiteStudio3/Tests/TestUtils/mocks.cpp b/SQLiteStudio3/Tests/TestUtils/mocks.cpp
index dee3bfd..bb1a226 100644
--- a/SQLiteStudio3/Tests/TestUtils/mocks.cpp
+++ b/SQLiteStudio3/Tests/TestUtils/mocks.cpp
@@ -7,6 +7,7 @@
#include "collationmanagermock.h"
#include "dbattachermock.h"
#include "dbmanagermock.h"
+#include "extensionmanagermock.h"
MockRepository* mockRepository = nullptr;
@@ -34,4 +35,5 @@ void initMocks()
SQLITESTUDIO->setDbAttacherFactory(new DbAttacherFactoryMock());
SQLITESTUDIO->setDbManager(new DbManagerMock());
SQLITESTUDIO->setCollationManager(new CollationManagerMock());
+ SQLITESTUDIO->setSqliteExtensionManager(new ExtensionManagerMock());
}
diff --git a/SQLiteStudio3/Tests/Tests.pro b/SQLiteStudio3/Tests/Tests.pro
index 2690494..b48ea8d 100644
--- a/SQLiteStudio3/Tests/Tests.pro
+++ b/SQLiteStudio3/Tests/Tests.pro
@@ -32,4 +32,5 @@ SUBDIRS += \
hash_tables \
db_ver_conv \
dsv \
- UtilsTest
+ UtilsTest \
+ LexerTest
diff --git a/SQLiteStudio3/Tests/UtilsTest/tst_utilssqltest.cpp b/SQLiteStudio3/Tests/UtilsTest/tst_utilssqltest.cpp
index 97c9234..2719ae4 100644
--- a/SQLiteStudio3/Tests/UtilsTest/tst_utilssqltest.cpp
+++ b/SQLiteStudio3/Tests/UtilsTest/tst_utilssqltest.cpp
@@ -14,6 +14,7 @@ private Q_SLOTS:
void testRemoveEmpties();
void testRemoveComments();
void testRemoveCommentsAndEmpties();
+ void testDoubleToString();
};
UtilsSqlTest::UtilsSqlTest()
@@ -70,6 +71,16 @@ void UtilsSqlTest::testRemoveCommentsAndEmpties()
QVERIFY2(sp[0] == "select 'dfgh ;sdg /*''*/ dfga' from aa;", failure.arg(sp[0]).toLatin1().data());
}
+void UtilsSqlTest::testDoubleToString()
+{
+ QVERIFY(doubleToString(QVariant(5.001)) == "5.001");
+ QVERIFY(doubleToString(QVariant(5.0000001)) == "5.0000001");
+ QVERIFY(doubleToString(QVariant(5.000000000000000000000000001)) == "5.0"); // too big, considered as round 5
+ QVERIFY(doubleToString(QVariant(0.0000001)) == "0.0000001");
+ QVERIFY(doubleToString(QVariant(9.99999999999998)) == "9.99999999999998");
+ QVERIFY(doubleToString(QVariant(0.1 + 0.1 + 0.1)) == "0.3");
+}
+
QTEST_APPLESS_MAIN(UtilsSqlTest)
#include "tst_utilssqltest.moc"