summaryrefslogtreecommitdiffstats
path: root/SQLiteStudio3/coreSQLiteStudio/dbversionconverter.cpp
diff options
context:
space:
mode:
authorLibravatarUnit 193 <unit193@unit193.net>2021-12-17 07:06:30 -0500
committerLibravatarUnit 193 <unit193@unit193.net>2021-12-17 07:06:30 -0500
commit1fdc150116cad39aae5c5da407c3312b47a59e3a (patch)
tree123c79a4d7ad2d45781ba03ce939f7539fb428d8 /SQLiteStudio3/coreSQLiteStudio/dbversionconverter.cpp
parentfeda8a7db8d1d7c5439aa8f8feef7cc0dd2b59a0 (diff)
New upstream version 3.3.3+dfsg1.upstream/3.3.3+dfsg1
Diffstat (limited to 'SQLiteStudio3/coreSQLiteStudio/dbversionconverter.cpp')
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/dbversionconverter.cpp1263
1 files changed, 0 insertions, 1263 deletions
diff --git a/SQLiteStudio3/coreSQLiteStudio/dbversionconverter.cpp b/SQLiteStudio3/coreSQLiteStudio/dbversionconverter.cpp
deleted file mode 100644
index 0ef924d..0000000
--- a/SQLiteStudio3/coreSQLiteStudio/dbversionconverter.cpp
+++ /dev/null
@@ -1,1263 +0,0 @@
-#include "dbversionconverter.h"
-#include "schemaresolver.h"
-#include "common/global.h"
-#include "parser/ast/sqlitealtertable.h"
-#include "parser/ast/sqliteanalyze.h"
-#include "parser/ast/sqliteattach.h"
-#include "parser/ast/sqlitebegintrans.h"
-#include "parser/ast/sqlitecommittrans.h"
-#include "parser/ast/sqlitecopy.h"
-#include "parser/ast/sqlitecreatevirtualtable.h"
-#include "parser/ast/sqlitedelete.h"
-#include "parser/ast/sqlitedetach.h"
-#include "parser/ast/sqlitedropindex.h"
-#include "parser/ast/sqlitedroptable.h"
-#include "parser/ast/sqlitedroptrigger.h"
-#include "parser/ast/sqlitedropview.h"
-#include "parser/ast/sqliteemptyquery.h"
-#include "parser/ast/sqliteinsert.h"
-#include "parser/ast/sqlitepragma.h"
-#include "parser/ast/sqlitereindex.h"
-#include "parser/ast/sqliterelease.h"
-#include "parser/ast/sqliterollback.h"
-#include "parser/ast/sqlitesavepoint.h"
-#include "parser/ast/sqliteupdate.h"
-#include "parser/ast/sqlitevacuum.h"
-#include "parser/ast/sqliteupsert.h"
-#include "services/pluginmanager.h"
-#include "plugins/dbplugin.h"
-#include "services/dbmanager.h"
-#include <QDebug>
-#include <QDir>
-#include <QFile>
-#include <QtConcurrent/QtConcurrentRun>
-
-DbVersionConverter::DbVersionConverter()
-{
- connect(this, SIGNAL(askUserForConfirmation()), this, SLOT(confirmConversion()));
- connect(this, SIGNAL(conversionSuccessful()), this, SLOT(registerDbAfterSuccessfulConversion()));
-}
-
-DbVersionConverter::~DbVersionConverter()
-{
- safe_delete(fullConversionConfig);
- safe_delete(resolver);
-}
-
-void DbVersionConverter::convert(Dialect from, Dialect to, Db* srcDb, const QString& targetFile, const QString& targetName, ConversionConfimFunction confirmFunc,
- ConversionErrorsConfimFunction errorsConfirmFunc)
-{
- safe_delete(fullConversionConfig);
- fullConversionConfig = new FullConversionConfig;
- fullConversionConfig->from = from;
- fullConversionConfig->to = to;
- fullConversionConfig->srcDb = srcDb;
- fullConversionConfig->confirmFunc = confirmFunc;
- fullConversionConfig->errorsConfirmFunc = errorsConfirmFunc;
- fullConversionConfig->targetFile = targetFile;
- fullConversionConfig->targetName = targetName;
- QtConcurrent::run(this, &DbVersionConverter::fullConvertStep1);
-}
-
-void DbVersionConverter::convert(Dialect from, Dialect to, Db* db)
-{
- if (from == Dialect::Sqlite2 && to == Dialect::Sqlite3)
- convert2To3(db);
- else if (from == Dialect::Sqlite3 && to == Dialect::Sqlite2)
- convert3To2(db);
- else
- qCritical() << "Unsupported db conversion combination.";
-}
-
-void DbVersionConverter::convert3To2(Db* db)
-{
- reset();
- this->db = db;
- targetDialect = Dialect::Sqlite2;
- convertDb();
-}
-
-void DbVersionConverter::convert2To3(Db* db)
-{
- reset();
- this->db = db;
- targetDialect = Dialect::Sqlite3;
- convertDb();
-}
-
-QString DbVersionConverter::convert(Dialect from, Dialect to, const QString& sql)
-{
- if (from == Dialect::Sqlite2 && to == Dialect::Sqlite3)
- return convert2To3(sql);
- else if (from == Dialect::Sqlite3 && to == Dialect::Sqlite2)
- return convert3To2(sql);
- else
- {
- qCritical() << "Unsupported db conversion combination.";
- return QString();
- }
-}
-
-QString DbVersionConverter::convert3To2(const QString& sql)
-{
- QStringList result;
- for (SqliteQueryPtr query : parse(sql, Dialect::Sqlite3))
- result << convert3To2(query)->detokenize();
-
- return result.join("\n");
-}
-
-QString DbVersionConverter::convert2To3(const QString& sql)
-{
- QStringList result;
- for (SqliteQueryPtr query : parse(sql, Dialect::Sqlite2))
- result << convert2To3(query)->detokenize();
-
- return result.join("\n");
-}
-
-SqliteQueryPtr DbVersionConverter::convert(Dialect from, Dialect to, SqliteQueryPtr query)
-{
- if (from == Dialect::Sqlite2 && to == Dialect::Sqlite3)
- return convert2To3(query);
- else if (from == Dialect::Sqlite3 && to == Dialect::Sqlite2)
- return convert3To2(query);
- else
- {
- qCritical() << "Unsupported db conversion combination.";
- return SqliteQueryPtr();
- }
-}
-
-SqliteQueryPtr DbVersionConverter::convert3To2(SqliteQueryPtr query)
-{
- SqliteQueryPtr newQuery;
- switch (query->queryType)
- {
- case SqliteQueryType::AlterTable:
- errors << QObject::tr("SQLite %1 does not support '%2' statement.").arg("2", "ALTER TABLE");
- newQuery = SqliteEmptyQueryPtr::create();
- storeErrorDiff(query.data());
- break;
- case SqliteQueryType::Analyze:
- errors << QObject::tr("SQLite %1 does not support '%2' statement.").arg("2", "ANAYLZE");
- newQuery = SqliteEmptyQueryPtr::create();
- storeErrorDiff(query.data());
- break;
- case SqliteQueryType::Attach:
- newQuery = copyQuery<SqliteAttach>(query);
- break;
- case SqliteQueryType::BeginTrans:
- newQuery = copyQuery<SqliteBeginTrans>(query);
- break;
- case SqliteQueryType::CommitTrans:
- newQuery = copyQuery<SqliteCommitTrans>(query);
- break;
- case SqliteQueryType::Copy:
- qWarning() << "COPY query passed to DbVersionConverter::convertToVersion2(). SQLite3 query should not have COPY statement.";
- newQuery = copyQuery<SqliteCopy>(query);
- break;
- case SqliteQueryType::CreateIndex:
- newQuery = copyQuery<SqliteCreateIndex>(query);
- if (!modifyCreateIndexForVersion2(newQuery.dynamicCast<SqliteCreateIndex>().data()))
- {
- newQuery = SqliteEmptyQueryPtr::create();
- storeErrorDiff(query.data());
- }
- break;
- case SqliteQueryType::CreateTable:
- newQuery = copyQuery<SqliteCreateTable>(query);
- if (!modifyCreateTableForVersion2(newQuery.dynamicCast<SqliteCreateTable>().data()))
- {
- newQuery = SqliteEmptyQueryPtr::create();
- storeErrorDiff(query.data());
- }
- break;
- case SqliteQueryType::CreateTrigger:
- newQuery = copyQuery<SqliteCreateTrigger>(query);
- if (!modifyCreateTriggerForVersion2(newQuery.dynamicCast<SqliteCreateTrigger>().data()))
- {
- newQuery = SqliteEmptyQueryPtr::create();
- storeErrorDiff(query.data());
- }
- break;
- case SqliteQueryType::CreateView:
- newQuery = copyQuery<SqliteCreateView>(query);
- if (!modifyCreateViewForVersion2(newQuery.dynamicCast<SqliteCreateView>().data()))
- {
- newQuery = SqliteEmptyQueryPtr::create();
- storeErrorDiff(query.data());
- }
- break;
- case SqliteQueryType::CreateVirtualTable:
- newQuery = copyQuery<SqliteCreateVirtualTable>(query);
- if (!modifyVirtualTableForVesion2(newQuery, newQuery.dynamicCast<SqliteCreateVirtualTable>().data()))
- {
- errors << QObject::tr("SQLite %1 does not support '%2' statement.").arg("2", "CREATE VIRTUAL TABLE");
- newQuery = SqliteEmptyQueryPtr::create();
- storeErrorDiff(query.data());
- }
- else
- {
- errors << QObject::tr("SQLite %1 does not support '%2' statement, but the regular table can be created instead if you proceed.")
- .arg("2", "CREATE VIRTUAL TABLE");
- }
- break;
- case SqliteQueryType::Delete:
- newQuery = copyQuery<SqliteDelete>(query);
- if (!modifyDeleteForVersion2(newQuery.dynamicCast<SqliteDelete>().data()))
- {
- newQuery = SqliteEmptyQueryPtr::create();
- if (diffsForNonDDL)
- storeErrorDiff(query.data());
- }
- break;
- case SqliteQueryType::Detach:
- newQuery = copyQuery<SqliteDetach>(query);
- break;
- case SqliteQueryType::DropIndex:
- newQuery = copyQuery<SqliteDropIndex>(query);
- break;
- case SqliteQueryType::DropTable:
- newQuery = copyQuery<SqliteDropTable>(query);
- break;
- case SqliteQueryType::DropTrigger:
- newQuery = copyQuery<SqliteDropTrigger>(query);
- break;
- case SqliteQueryType::DropView:
- newQuery = copyQuery<SqliteDropView>(query);
- break;
- case SqliteQueryType::Insert:
- newQuery = copyQuery<SqliteInsert>(query);
- if (!modifyInsertForVersion2(newQuery.dynamicCast<SqliteInsert>().data()))
- {
- newQuery = SqliteEmptyQueryPtr::create();
- if (diffsForNonDDL)
- storeErrorDiff(query.data());
- }
- break;
- case SqliteQueryType::Pragma:
- newQuery = copyQuery<SqlitePragma>(query);
- break;
- case SqliteQueryType::Reindex:
- errors << QObject::tr("SQLite %1 does not support '%2' statement.").arg("2", "REINDEX");
- newQuery = SqliteEmptyQueryPtr::create();
- storeErrorDiff(query.data());
- break;
- case SqliteQueryType::Release:
- errors << QObject::tr("SQLite %1 does not support '%2' statement.").arg("2", "RELEASE");
- newQuery = SqliteEmptyQueryPtr::create();
- storeErrorDiff(query.data());
- break;
- case SqliteQueryType::Rollback:
- newQuery = copyQuery<SqliteRollback>(query);
- break;
- case SqliteQueryType::Savepoint:
- errors << QObject::tr("SQLite %1 does not support '%2' statement.").arg("2", "SAVEPOINT");
- newQuery = SqliteEmptyQueryPtr::create();
- storeErrorDiff(query.data());
- break;
- case SqliteQueryType::Select:
- {
- newQuery = copyQuery<SqliteSelect>(query);
- if (!modifySelectForVersion2(newQuery.dynamicCast<SqliteSelect>().data()))
- {
- newQuery = SqliteEmptyQueryPtr::create();
- if (diffsForNonDDL)
- storeErrorDiff(query.data());
- }
- break;
- }
- case SqliteQueryType::Update:
- newQuery = copyQuery<SqliteUpdate>(query);
- if (!modifyUpdateForVersion2(newQuery.dynamicCast<SqliteUpdate>().data()))
- {
- newQuery = SqliteEmptyQueryPtr::create();
- if (diffsForNonDDL)
- storeErrorDiff(query.data());
- }
- break;
- case SqliteQueryType::Vacuum:
- newQuery = copyQuery<SqliteVacuum>(query);
- break;
- case SqliteQueryType::UNDEFINED:
- qWarning() << "UNDEFINED query type passed to DbVersionConverter::convertToVersion2().";
- newQuery = SqliteEmptyQueryPtr::create();
- break;
- case SqliteQueryType::EMPTY:
- newQuery = copyQuery<SqliteEmptyQuery>(query);
- break;
- }
-
- if (!newQuery)
- {
- qCritical() << "Query type not matched in DbVersionConverter::convertToVersion2():" << static_cast<int>(query->queryType);
- return SqliteQueryPtr();
- }
-
- if (newQuery->queryType != SqliteQueryType::EMPTY)
- {
- newQuery->setSqliteDialect(Dialect::Sqlite2);
- newQueries << newQuery;
- }
-
- newQuery->rebuildTokens();
- return newQuery;
-}
-
-SqliteQueryPtr DbVersionConverter::convert2To3(SqliteQueryPtr query)
-{
- SqliteQueryPtr newQuery;
- switch (query->queryType)
- {
- case SqliteQueryType::AlterTable:
- newQuery = copyQuery<SqliteAlterTable>(query);
- qWarning() << "ALTER TABLE query passed to DbVersionConverter::convertToVersion3(). SQLite2 query should not have ALTER TABLE statement.";
- break;
- case SqliteQueryType::Analyze:
- newQuery = copyQuery<SqliteAnalyze>(query);
- qWarning() << "ANALYZE query passed to DbVersionConverter::convertToVersion3(). SQLite2 query should not have ANALYZE statement.";
- break;
- case SqliteQueryType::Attach:
- newQuery = copyQuery<SqliteAttach>(query);
- break;
- case SqliteQueryType::BeginTrans:
- newQuery = copyQuery<SqliteBeginTrans>(query);
- if (!modifyBeginTransForVersion3(newQuery.dynamicCast<SqliteBeginTrans>().data()))
- {
- newQuery = SqliteEmptyQueryPtr::create();
- storeErrorDiff(query.data());
- }
- break;
- case SqliteQueryType::CommitTrans:
- newQuery = copyQuery<SqliteCommitTrans>(query);
- break;
- case SqliteQueryType::Copy:
- errors << QObject::tr("SQLite %1 does not support '%2' statement.").arg("3", "COPY");
- newQuery = SqliteEmptyQueryPtr::create();
- storeErrorDiff(query.data());
- break;
- case SqliteQueryType::CreateIndex:
- newQuery = copyQuery<SqliteCreateIndex>(query);
- break;
- case SqliteQueryType::CreateTable:
- newQuery = copyQuery<SqliteCreateTable>(query);
- break;
- case SqliteQueryType::CreateTrigger:
- newQuery = copyQuery<SqliteCreateTrigger>(query);
- break;
- case SqliteQueryType::CreateView:
- newQuery = copyQuery<SqliteCreateView>(query);
- break;
- case SqliteQueryType::CreateVirtualTable:
- newQuery = copyQuery<SqliteCreateVirtualTable>(query);
- break;
- case SqliteQueryType::Delete:
- newQuery = copyQuery<SqliteDelete>(query);
- break;
- case SqliteQueryType::Detach:
- newQuery = copyQuery<SqliteDetach>(query);
- break;
- case SqliteQueryType::DropIndex:
- newQuery = copyQuery<SqliteDropIndex>(query);
- break;
- case SqliteQueryType::DropTable:
- newQuery = copyQuery<SqliteDropTable>(query);
- break;
- case SqliteQueryType::DropTrigger:
- newQuery = copyQuery<SqliteDropTrigger>(query);
- break;
- case SqliteQueryType::DropView:
- newQuery = copyQuery<SqliteDropView>(query);
- break;
- case SqliteQueryType::Insert:
- newQuery = copyQuery<SqliteInsert>(query);
- break;
- case SqliteQueryType::Pragma:
- newQuery = copyQuery<SqlitePragma>(query);
- break;
- case SqliteQueryType::Reindex:
- newQuery = copyQuery<SqliteReindex>(query);
- qWarning() << "REINDEX query passed to DbVersionConverter::convertToVersion3(). SQLite2 query should not have REINDEX statement.";
- break;
- case SqliteQueryType::Release:
- newQuery = copyQuery<SqliteRelease>(query);
- qWarning() << "RELEASE query passed to DbVersionConverter::convertToVersion3(). SQLite2 query should not have RELEASE statement.";
- break;
- case SqliteQueryType::Rollback:
- newQuery = copyQuery<SqliteRollback>(query);
- break;
- case SqliteQueryType::Savepoint:
- newQuery = copyQuery<SqliteSavepoint>(query);
- qWarning() << "SAVEPOINT query passed to DbVersionConverter::convertToVersion3(). SQLite2 query should not have SAVEPOINT statement.";
- break;
- case SqliteQueryType::Select:
- newQuery = copyQuery<SqliteSelect>(query);
- break;
- case SqliteQueryType::Update:
- newQuery = copyQuery<SqliteUpdate>(query);
- break;
- case SqliteQueryType::Vacuum:
- newQuery = copyQuery<SqliteVacuum>(query);
- break;
- case SqliteQueryType::UNDEFINED:
- qWarning() << "UNDEFINED query type passed to DbVersionConverter::convertToVersion3().";
- case SqliteQueryType::EMPTY:
- newQuery = copyQuery<SqliteEmptyQuery>(query);
- break;
- }
-
- if (!newQuery)
- {
- qCritical() << "Query type not matched in DbVersionConverter::convertToVersion3():" << static_cast<int>(query->queryType);
- return SqliteQueryPtr();
- }
-
- if (newQuery->queryType != SqliteQueryType::EMPTY)
- {
- newQuery->setSqliteDialect(Dialect::Sqlite2);
- newQueries << newQuery;
- }
- return newQuery;
-}
-
-QList<SqliteQueryPtr> DbVersionConverter::parse(const QString& sql, Dialect dialect)
-{
- Parser parser(dialect);
- if (!parser.parse(sql))
- {
- errors << QObject::tr("Could not parse statement: %1\nError details: %2").arg(sql, parser.getErrorString());
- return QList<SqliteQueryPtr>();
- }
-
- return parser.getQueries();
-}
-
-bool DbVersionConverter::modifySelectForVersion2(SqliteSelect* select)
-{
- if (select->with)
- {
- errors << QObject::tr("SQLite %1 does not support the '%2' clause. Cannot convert '%3' statement with that clause.").arg("2", "WITH", "SELECT");
- return false;
- }
-
- QString sql1 = getSqlForDiff(select);
-
- for (SqliteSelect::Core* core : select->coreSelects)
- {
- if (core->valuesMode)
- core->valuesMode = false;
- }
-
- if (!modifyAllIndexedColumnsForVersion2(select))
- return false;
-
- if (!modifyAllExprsForVersion2(select))
- return false;
-
- if (diffsForNonDDL)
- storeDiff(sql1, select);
-
- return true;
-}
-
-bool DbVersionConverter::modifyDeleteForVersion2(SqliteDelete* del)
-{
- if (del->with)
- {
- errors << QObject::tr("SQLite %1 does not support the '%2' clause. Cannot convert '%3' statement with that clause.").arg("2", "WITH", "DELETE");
- return false;
- }
-
- QString sql1 = getSqlForDiff(del);
-
- del->indexedBy = QString::null;
- del->indexedByKw = false;
- del->notIndexedKw = false;
-
- if (!modifyAllExprsForVersion2(del))
- return false;
-
- if (diffsForNonDDL)
- storeDiff(sql1, del);
-
- return true;
-}
-
-bool DbVersionConverter::modifyInsertForVersion2(SqliteInsert* insert)
-{
- if (insert->with)
- {
- errors << QObject::tr("SQLite %1 does not support the '%2' clause. Cannot convert '%3' statement with that clause.").arg("2", "WITH", "INSERT");
- return false;
- }
-
- if (insert->defaultValuesKw)
- {
- errors << QObject::tr("SQLite %1 does not support the '%2' clause in the '%3' statement.").arg("2", "DEFAULT VALUES", "INSERT");
- return false;
- }
-
- if (!insert->select)
- {
- qCritical() << "No SELECT substatement in INSERT when converting from SQLite 3 to 2.";
- return false;
- }
-
- QString sql1 = getSqlForDiff(insert);
-
- if (insert->upsert)
- safe_delete(insert->upsert);
-
- // Modifying SELECT deals with "VALUES" completely.
- if (!modifySelectForVersion2(insert->select))
- return false;
-
- if (!modifyAllExprsForVersion2(insert))
- return false;
-
- if (diffsForNonDDL)
- storeDiff(sql1, insert);
-
- return true;
-}
-
-bool DbVersionConverter::modifyUpdateForVersion2(SqliteUpdate* update)
-{
- if (update->with)
- {
- errors << QObject::tr("SQLite %1 does not support the '%2' clause. Cannot convert '%3' statement with that clause.").arg("2", "WITH", "UPDATE");
- return false;
- }
-
- QString sql1 = getSqlForDiff(update);
-
- if (!modifyAllExprsForVersion2(update))
- return false;
-
- update->indexedBy = QString::null;
- update->indexedByKw = false;
- update->notIndexedKw = false;
-
- if (diffsForNonDDL)
- storeDiff(sql1, update);
-
- return true;
-}
-
-bool DbVersionConverter::modifyCreateTableForVersion2(SqliteCreateTable* createTable)
-{
- QString sql1 = getSqlForDiff(createTable);
-
- if (!createTable->database.isNull())
- createTable->database = QString::null;
-
- // Subselect
- if (createTable->select)
- {
- if (!modifySelectForVersion2(createTable->select))
- return false;
- }
-
- // Table constraints
- QMutableListIterator<SqliteCreateTable::Constraint*> tableConstrIt(createTable->constraints);
- while (tableConstrIt.hasNext())
- {
- tableConstrIt.next();
- if (tableConstrIt.value()->type == SqliteCreateTable::Constraint::PRIMARY_KEY)
- tableConstrIt.value()->autoincrKw = false;
- }
-
- // Column constraints
- QMutableListIterator<SqliteCreateTable::Column*> tableColIt(createTable->columns);
- while (tableColIt.hasNext())
- {
- tableColIt.next();
- QMutableListIterator<SqliteCreateTable::Column::Constraint*> tableColConstrIt(tableColIt.value()->constraints);
- while (tableColConstrIt.hasNext())
- {
- tableColConstrIt.next();
- switch (tableColConstrIt.value()->type)
- {
- case SqliteCreateTable::Column::Constraint::COLLATE: // theoretically supported by SQLite2, but it raises error from SQLite2 when used
- case SqliteCreateTable::Column::Constraint::NAME_ONLY:
- {
- delete tableColConstrIt.value();
- tableColConstrIt.remove();
- break;
- }
- case SqliteCreateTable::Column::Constraint::DEFAULT:
- {
- if (!tableColConstrIt.value()->ctime.isNull())
- {
- delete tableColConstrIt.value();
- tableColConstrIt.remove();
- }
- else
- tableColConstrIt.value()->name = QString::null;
-
- break;
- }
- case SqliteCreateTable::Column::Constraint::PRIMARY_KEY:
- {
- tableColConstrIt.value()->autoincrKw = false;
- break;
- }
- case SqliteCreateTable::Column::Constraint::FOREIGN_KEY:
- {
- QMutableListIterator<SqliteForeignKey::Condition*> condIt(tableColConstrIt.value()->foreignKey->conditions);
- while (condIt.hasNext())
- {
- condIt.next();
- if (condIt.value()->reaction == SqliteForeignKey::Condition::NO_ACTION
- && condIt.value()->action != SqliteForeignKey::Condition::MATCH) // SQLite 2 has no "NO ACTION"
- {
- condIt.remove();
- }
- }
- break;
- }
- case SqliteCreateTable::Column::Constraint::NOT_NULL:
- case SqliteCreateTable::Column::Constraint::UNIQUE:
- case SqliteCreateTable::Column::Constraint::CHECK:
- case SqliteCreateTable::Column::Constraint::NULL_:
- case SqliteCreateTable::Column::Constraint::DEFERRABLE_ONLY:
- break;
- }
- }
- }
-
- if (!modifyAllIndexedColumnsForVersion2(createTable))
- return false;
-
- // WITHOUT ROWID
- if (!createTable->withOutRowId.isNull())
- createTable->withOutRowId = QString::null;
-
- storeDiff(sql1, createTable);
- return true;
-}
-
-bool DbVersionConverter::modifyCreateTriggerForVersion2(SqliteCreateTrigger* createTrigger)
-{
- QString sql = getSqlForDiff(createTrigger);
-
- if (!createTrigger->database.isNull())
- createTrigger->database = QString::null;
-
- for (SqliteQuery* query : createTrigger->queries)
- {
- switch (query->queryType)
- {
- case SqliteQueryType::Delete:
- {
- if (!modifyDeleteForVersion2(dynamic_cast<SqliteDelete*>(query)))
- return false;
-
- break;
- }
- case SqliteQueryType::Update:
- {
- if (!modifyUpdateForVersion2(dynamic_cast<SqliteUpdate*>(query)))
- return false;
-
- break;
- }
- case SqliteQueryType::Insert:
- {
- if (!modifyInsertForVersion2(dynamic_cast<SqliteInsert*>(query)))
- return false;
-
- break;
- }
- case SqliteQueryType::Select:
- {
- if (!modifySelectForVersion2(dynamic_cast<SqliteSelect*>(query)))
- return false;
-
- break;
- }
- default:
- qWarning() << "Unexpected query type in trigger:" << sqliteQueryTypeToString(query->queryType);
- break;
- }
- }
-
- storeDiff(sql, createTrigger);
- return true;
-}
-
-bool DbVersionConverter::modifyCreateIndexForVersion2(SqliteCreateIndex* createIndex)
-{
- QString sql1 = getSqlForDiff(createIndex);
-
- if (!createIndex->database.isNull())
- createIndex->database = QString::null;
-
- if (createIndex->where)
- {
- delete createIndex->where;
- createIndex->where = nullptr;
- }
-
- if (!modifyAllIndexedColumnsForVersion2(createIndex->indexedColumns))
- return false;
-
- storeDiff(sql1, createIndex);
- return true;
-}
-
-bool DbVersionConverter::modifyCreateViewForVersion2(SqliteCreateView* createView)
-{
- QString sql1 = getSqlForDiff(createView);
-
- if (!createView->database.isNull())
- createView->database = QString::null;
-
- if (!modifySelectForVersion2(createView->select))
- return false;
-
- storeDiff(sql1, createView);
- return true;
-}
-
-bool DbVersionConverter::modifyVirtualTableForVesion2(SqliteQueryPtr& query, SqliteCreateVirtualTable* createVirtualTable)
-{
- if (!resolver)
- return false;
-
- SqliteCreateTablePtr createTable = resolver->resolveVirtualTableAsRegularTable(createVirtualTable->database, createVirtualTable->table);
- if (!createTable)
- return false;
-
- QString sql = getSqlForDiff(createVirtualTable);
- storeDiff(sql, createTable.data());
-
- query = createTable.dynamicCast<SqliteQuery>();
- return true;
-}
-
-bool DbVersionConverter::modifyAllExprsForVersion2(SqliteStatement* stmt)
-{
- QList<SqliteExpr*> allExprs = stmt->getAllTypedStatements<SqliteExpr>();
- for (SqliteExpr* expr : allExprs)
- {
- if (!modifySingleExprForVersion2(expr))
- return false;
- }
- return true;
-}
-
-bool DbVersionConverter::modifySingleExprForVersion2(SqliteExpr* expr)
-{
- switch (expr->mode)
- {
- case SqliteExpr::Mode::null:
- case SqliteExpr::Mode::LITERAL_VALUE:
- case SqliteExpr::Mode::BIND_PARAM:
- case SqliteExpr::Mode::ID:
- case SqliteExpr::Mode::UNARY_OP:
- case SqliteExpr::Mode::BINARY_OP:
- case SqliteExpr::Mode::FUNCTION:
- case SqliteExpr::Mode::SUB_EXPR:
- case SqliteExpr::Mode::LIKE:
- case SqliteExpr::Mode::NULL_:
- case SqliteExpr::Mode::NOTNULL:
- case SqliteExpr::Mode::IS:
- case SqliteExpr::Mode::BETWEEN:
- case SqliteExpr::Mode::CASE:
- case SqliteExpr::Mode::RAISE:
- break;
- case SqliteExpr::Mode::CTIME:
- errors << QObject::tr("SQLite %1 does not support current date or time clauses in expressions.").arg("2");
- return false;
- case SqliteExpr::Mode::ROW_VALUE:
- errors << QObject::tr("SQLite %1 does not support row value clauses in expressions.").arg("2");
- return false;
- case SqliteExpr::Mode::IN:
- case SqliteExpr::Mode::SUB_SELECT:
- {
- if (!modifySelectForVersion2(expr->select))
- return false;
-
- break;
- }
- case SqliteExpr::Mode::CAST:
- errors << QObject::tr("SQLite %1 does not support '%2' clause in expressions.").arg("2", "CAST");
- return false;
- case SqliteExpr::Mode::EXISTS:
- errors << QObject::tr("SQLite %1 does not support '%2' clause in expressions.").arg("2", "EXISTS");
- return false;
- case SqliteExpr::Mode::COLLATE:
- {
- if (dynamic_cast<SqliteOrderBy*>(expr->parentStatement()))
- {
- // This is the only case when SQLite2 parser puts this mode into expression, that is for sortorder
- break;
- }
- else
- {
- errors << QObject::tr("SQLite %1 does not support '%2' clause in expressions.").arg("2", "COLLATE");
- return false;
- }
- }
- }
- return true;
-}
-
-bool DbVersionConverter::modifyAllIndexedColumnsForVersion2(SqliteStatement* stmt)
-{
- QList<SqliteIndexedColumn*> columns = stmt->getAllTypedStatements<SqliteIndexedColumn>();
- return modifyAllIndexedColumnsForVersion2(columns);
-
-}
-
-bool DbVersionConverter::modifySingleIndexedColumnForVersion2(SqliteExtendedIndexedColumn* idxCol)
-{
- if (!idxCol->getCollation().isNull())
- idxCol->clearCollation();
-
- return true;
-}
-
-bool DbVersionConverter::modifyBeginTransForVersion3(SqliteBeginTrans* begin)
-{
- QString sql1 = getSqlForDiff(begin);
- begin->onConflict = SqliteConflictAlgo::null;
- storeDiff(sql1, begin);
- return true;
-}
-
-bool DbVersionConverter::modifyCreateTableForVersion3(SqliteCreateTable* createTable)
-{
- QString sql1 = getSqlForDiff(createTable);
-
- // Column constraints
- QMutableListIterator<SqliteCreateTable::Column*> tableColIt(createTable->columns);
- while (tableColIt.hasNext())
- {
- tableColIt.next();
- QMutableListIterator<SqliteCreateTable::Column::Constraint*> tableColConstrIt(tableColIt.value()->constraints);
- while (tableColConstrIt.hasNext())
- {
- tableColConstrIt.next();
- switch (tableColConstrIt.value()->type)
- {
- case SqliteCreateTable::Column::Constraint::CHECK:
- {
- tableColConstrIt.value()->onConflict = SqliteConflictAlgo::null;
- break;
- }
- case SqliteCreateTable::Column::Constraint::NAME_ONLY:
- case SqliteCreateTable::Column::Constraint::DEFAULT:
- case SqliteCreateTable::Column::Constraint::PRIMARY_KEY:
- case SqliteCreateTable::Column::Constraint::NOT_NULL:
- case SqliteCreateTable::Column::Constraint::UNIQUE:
- case SqliteCreateTable::Column::Constraint::COLLATE:
- case SqliteCreateTable::Column::Constraint::FOREIGN_KEY:
- case SqliteCreateTable::Column::Constraint::NULL_:
- case SqliteCreateTable::Column::Constraint::DEFERRABLE_ONLY:
- break;
- }
- }
- }
-
- storeDiff(sql1, createTable);
- return true;
-}
-
-QString DbVersionConverter::getSqlForDiff(SqliteStatement* stmt)
-{
- stmt->rebuildTokens();
- return stmt->detokenize();
-}
-
-void DbVersionConverter::storeDiff(const QString& sql1, SqliteStatement* stmt)
-{
- stmt->rebuildTokens();
- QString sql2 = stmt->detokenize();
- if (sql1 != sql2)
- diffList << QPair<QString,QString>(sql1, sql2);
-}
-
-void DbVersionConverter::storeErrorDiff(SqliteStatement* stmt)
-{
- stmt->rebuildTokens();
- diffList << QPair<QString,QString>(stmt->detokenize(), "");
-}
-
-void DbVersionConverter::reset()
-{
- db = nullptr;
- targetDialect = Dialect::Sqlite3;
- diffList.clear();
- newQueries.clear();
- errors.clear();
- safe_delete(resolver);
-}
-
-QList<Dialect> DbVersionConverter::getSupportedVersions() const
-{
- QList<Dialect> versions;
- for (Db* db : getAllPossibleDbInstances())
- {
- versions << db->getDialect();
- delete db;
- }
- return versions;
-}
-
-QStringList DbVersionConverter::getSupportedVersionNames() const
-{
- QStringList versions;
- for (Db* db : getAllPossibleDbInstances())
- {
- versions << db->getTypeLabel();
- delete db;
- }
- return versions;
-}
-
-void DbVersionConverter::fullConvertStep1()
-{
- convert(fullConversionConfig->from, fullConversionConfig->to, fullConversionConfig->srcDb);
- emit askUserForConfirmation();
-}
-
-void DbVersionConverter::fullConvertStep2()
-{
- QFile outputFile(fullConversionConfig->targetFile);
- if (outputFile.exists() && !outputFile.remove())
- {
- emit conversionFailed(tr("Target file exists, but could not be overwritten."));
- return;
- }
-
- Db* db = nullptr;
- Db* tmpDb = nullptr;
- for (DbPlugin* plugin : PLUGINS->getLoadedPlugins<DbPlugin>())
- {
- tmpDb = plugin->getInstance("", ":memory:", QHash<QString,QVariant>());
- if (tmpDb && tmpDb->initAfterCreated() && tmpDb->getDialect() == fullConversionConfig->to)
- db = plugin->getInstance(fullConversionConfig->targetName, fullConversionConfig->targetFile, QHash<QString,QVariant>());
-
- safe_delete(tmpDb);
- if (db)
- break;
- }
-
- if (!db)
- {
- emit conversionFailed(tr("Could not find proper database plugin to create target database."));
- return;
- }
-
- if (checkForInterrupted(db, false))
- return;
-
- if (!db->open())
- {
- emit conversionFailed(db->getErrorText());
- return;
- }
-
- if (!db->begin())
- {
- conversionError(db, db->getErrorText());
- return;
- }
-
- QStringList tables;
- if (!fullConvertCreateObjectsStep1(db, tables))
- return; // error handled inside
-
- if (checkForInterrupted(db, true))
- return;
-
- if (!fullConvertCopyData(db, tables))
- return; // error handled inside
-
- if (checkForInterrupted(db, true))
- return;
-
- if (!fullConvertCreateObjectsStep2(db))
- return; // error handled inside
-
- if (checkForInterrupted(db, true))
- return;
-
- if (!db->commit())
- {
- conversionError(db, db->getErrorText());
- return;
- }
- emit conversionSuccessful();
-}
-
-bool DbVersionConverter::fullConvertCreateObjectsStep1(Db* db, QStringList& tables)
-{
- SqlQueryPtr result;
- SqliteCreateTablePtr createTable;
- for (const SqliteQueryPtr& query : getConverted())
- {
- // Triggers and indexes are created in step2, after data was copied, to avoid invoking triggers
- // and speed up copying data.
- if (query->queryType == SqliteQueryType::CreateTrigger || query->queryType == SqliteQueryType::CreateIndex)
- continue;
-
- createTable = query.dynamicCast<SqliteCreateTable>();
- if (!createTable.isNull())
- tables << createTable->table;
-
- result = db->exec(query->detokenize());
- if (result->isError())
- {
- conversionError(db, result->getErrorText());
- return false;
- }
- }
- return true;
-}
-
-bool DbVersionConverter::fullConvertCreateObjectsStep2(Db* db)
-{
- SqlQueryPtr result;
- for (const SqliteQueryPtr& query : getConverted())
- {
- // Creating only triggers and indexes
- if (query->queryType != SqliteQueryType::CreateTrigger && query->queryType != SqliteQueryType::CreateIndex)
- continue;
-
- result = db->exec(query->detokenize());
- if (result->isError())
- {
- conversionError(db, result->getErrorText());
- return false;
- }
-
- if (checkForInterrupted(db, true))
- return false;
- }
- return true;
-}
-
-bool DbVersionConverter::fullConvertCopyData(Db* db, const QStringList& tables)
-{
- static const QString selectSql = QStringLiteral("SELECT * FROM %1;");
- static const QString insertSql = QStringLiteral("INSERT INTO %1 VALUES (%2);");
-
- Dialect srcDialect = fullConversionConfig->srcDb->getDialect();
- Dialect trgDialect = db->getDialect();
- QString srcTable;
- QString trgTable;
- SqlQueryPtr result;
- SqlQueryPtr dataResult;
- SqlResultsRowPtr resultsRow;
- int i = 1;
- for (const QString& table : tables)
- {
- // Select data
- srcTable = wrapObjIfNeeded(table, srcDialect);
- trgTable = wrapObjIfNeeded(table, trgDialect);
- dataResult = fullConversionConfig->srcDb->exec(selectSql.arg(srcTable));
- if (dataResult->isError())
- {
- conversionError(db, dataResult->getErrorText());
- return false;
- }
-
- if (checkForInterrupted(db, true))
- return false;
-
- // Copy row by row
- i = 1;
- while (dataResult->hasNext())
- {
- // Get row
- resultsRow = dataResult->next();
- if (dataResult->isError())
- {
- conversionError(db, dataResult->getErrorText());
- return false;
- }
-
- // Insert row
- result = db->exec(insertSql.arg(trgTable, generateQueryPlaceholders(resultsRow->valueList().size())), resultsRow->valueList());
- if (result->isError())
- {
- conversionError(db, result->getErrorText());
- return false;
- }
-
- if (i++ % 100 == 0 && checkForInterrupted(db, true))
- return false;
- }
- }
-
- return true;
-}
-
-bool DbVersionConverter::checkForInterrupted(Db* db, bool rollback)
-{
- if (isInterrupted())
- {
- conversionInterrupted(db, rollback);
- return true;
- }
- return false;
-}
-
-QList<Db*> DbVersionConverter::getAllPossibleDbInstances() const
-{
- QList<Db*> dbList;
- Db* db = nullptr;
- for (DbPlugin* plugin : PLUGINS->getLoadedPlugins<DbPlugin>())
- {
- db = plugin->getInstance("", ":memory:", QHash<QString,QVariant>());
- if (!db || !db->initAfterCreated())
- continue;
-
- dbList << db;
- }
- return dbList;
-}
-
-QString DbVersionConverter::generateQueryPlaceholders(int argCount)
-{
- QStringList args;
- for (int i = 0; i < argCount; i++)
- args << "?";
-
- return args.join(", ");
-}
-
-void DbVersionConverter::sortConverted()
-{
- qSort(newQueries.begin(), newQueries.end(), [](const SqliteQueryPtr& q1, const SqliteQueryPtr& q2) -> bool
- {
- if (!q1 || !q2)
- {
- if (!q1)
- return false;
- else
- return true;
- }
- if (q1->queryType == q2->queryType)
- return false;
-
- if (q1->queryType == SqliteQueryType::CreateTable)
- return true;
-
- if (q1->queryType == SqliteQueryType::CreateView && q2->queryType != SqliteQueryType::CreateTable)
- return true;
-
- return false;
- });
-}
-
-void DbVersionConverter::setInterrupted(bool value)
-{
- QMutexLocker locker(&interruptMutex);
- interrupted = value;
-}
-
-bool DbVersionConverter::isInterrupted()
-{
- QMutexLocker locker(&interruptMutex);
- return interrupted;
-}
-
-void DbVersionConverter::conversionInterrupted(Db* db, bool rollback)
-{
- emit conversionAborted();
- if (rollback)
- db->rollback();
-
- db->close();
-
- QFile file(fullConversionConfig->targetFile);
- if (file.exists())
- file.remove();
-}
-
-void DbVersionConverter::conversionError(Db* db, const QString& errMsg)
-{
- emit conversionFailed(tr("Error while converting database: %1").arg(errMsg));
- db->rollback();
- db->close();
-
- QFile file(fullConversionConfig->targetFile);
- if (file.exists())
- file.remove();
-}
-
-void DbVersionConverter::confirmConversion()
-{
- if (!errors.isEmpty() && !fullConversionConfig->errorsConfirmFunc(errors))
- {
- emit conversionAborted();
- return;
- }
-
- if (!diffList.isEmpty() && !fullConversionConfig->confirmFunc(diffList))
- {
- emit conversionAborted();
- return;
- }
-
- QtConcurrent::run(this, &DbVersionConverter::fullConvertStep2);
-}
-
-void DbVersionConverter::registerDbAfterSuccessfulConversion()
-{
- DBLIST->addDb(fullConversionConfig->targetName, fullConversionConfig->targetFile);
-}
-
-void DbVersionConverter::interrupt()
-{
- setInterrupted(true);
-}
-
-const QList<QPair<QString, QString> >& DbVersionConverter::getDiffList() const
-{
- return diffList;
-}
-
-const QSet<QString>& DbVersionConverter::getErrors() const
-{
- return errors;
-}
-
-const QList<SqliteQueryPtr>&DbVersionConverter::getConverted() const
-{
- return newQueries;
-}
-
-QStringList DbVersionConverter::getConvertedSqls() const
-{
- QStringList sqls;
- for (SqliteQueryPtr query : newQueries)
- sqls << query->detokenize();
-
- return sqls;
-}
-
-void DbVersionConverter::convertDb()
-{
- resolver = new SchemaResolver(db);
- resolver->setIgnoreSystemObjects(true);
- StrHash<SqliteQueryPtr> parsedObjects = resolver->getAllParsedObjects();
- for (SqliteQueryPtr query : parsedObjects.values())
- {
- switch (targetDialect)
- {
- case Dialect::Sqlite2:
- convert3To2(query);
- break;
- case Dialect::Sqlite3:
- convert2To3(query);
- break;
- }
- }
- sortConverted();
-}