From 3565aad630864ecdbe53fdaa501ea708555b3c7c Mon Sep 17 00:00:00 2001 From: Unit 193 Date: Sun, 30 Apr 2023 18:30:36 -0400 Subject: New upstream version 3.4.4+dfsg. --- SQLiteStudio3/coreSQLiteStudio/schemaresolver.cpp | 106 +++++++++++++++++++--- 1 file changed, 92 insertions(+), 14 deletions(-) (limited to 'SQLiteStudio3/coreSQLiteStudio/schemaresolver.cpp') diff --git a/SQLiteStudio3/coreSQLiteStudio/schemaresolver.cpp b/SQLiteStudio3/coreSQLiteStudio/schemaresolver.cpp index 4d65461..129bb43 100644 --- a/SQLiteStudio3/coreSQLiteStudio/schemaresolver.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/schemaresolver.cpp @@ -98,14 +98,15 @@ StrHash SchemaResolver::getGroupedTriggers(const QString &database) StrHash SchemaResolver::getGroupedObjects(const QString &database, const QStringList &inputList, SqliteQueryType type) { QString strType = sqliteQueryTypeToString(type); + ObjectType objectType = objectTypeFromQueryType(type); StrHash groupedObjects; SqliteQueryPtr parsedQuery; SqliteTableRelatedDdlPtr tableRelatedDdl; - for (QString object : inputList) + for (const QString& object : inputList) { - parsedQuery = getParsedObject(database, object, ANY); + parsedQuery = getParsedObject(database, object, objectType); if (!parsedQuery) { qWarning() << "Could not get parsed object for " << strType << ":" << object; @@ -116,7 +117,8 @@ StrHash SchemaResolver::getGroupedObjects(const QString &database, if (!tableRelatedDdl) { qWarning() << "Parsed object is not of expected type. Expected" << strType - << ", but got" << sqliteQueryTypeToString(parsedQuery->queryType); + << ", but got" << sqliteQueryTypeToString(parsedQuery->queryType) + << "; Object db and name:" << database << object; continue; } @@ -145,12 +147,12 @@ QSet SchemaResolver::getDatabases() return db->getAllAttaches(); } -QStringList SchemaResolver::getTableColumns(const QString& table) +QStringList SchemaResolver::getTableColumns(const QString& table, bool onlyReal) { - return getTableColumns("main", table); + return getTableColumns("main", table, onlyReal); } -QStringList SchemaResolver::getTableColumns(const QString &database, const QString &table) +QStringList SchemaResolver::getTableColumns(const QString &database, const QString &table, bool onlyReal) { QStringList columns; // result @@ -178,7 +180,12 @@ QStringList SchemaResolver::getTableColumns(const QString &database, const QStri // Now we have a regular table, let's extract columns. for (SqliteCreateTable::Column* column : createTable->columns) + { + if (onlyReal && column->hasConstraint(SqliteCreateTable::Column::Constraint::GENERATED)) + continue; + columns << column->name; + } return columns; } @@ -272,12 +279,14 @@ QList SchemaResolver::getViewColumnObjects(const QString SqliteCreateTablePtr SchemaResolver::virtualTableAsRegularTable(const QString &database, const QString &table) { - QString strippedName = stripObjName(table); + // The "table" name here used to be stripped with stripObjName(), but actually [abc] is a proper table name, + // that should not be stripped. Any names passed to SchemaResolver cannot be wrapped. + QString dbName = getPrefixDb(database); // Create temp table to see columns. - QString newTable = db->getUniqueNewObjectName(strippedName); - QString origTable = wrapObjIfNeeded(strippedName); + QString newTable = db->getUniqueNewObjectName(table); + QString origTable = wrapObjIfNeeded(table); SqlQueryPtr tempTableRes = db->exec(QString("CREATE TEMP TABLE %1 AS SELECT * FROM %2.%3 LIMIT 0;").arg(newTable, dbName, origTable), dbFlags); if (tempTableRes->isError()) qWarning() << "Could not create temp table to identify virtual table columns of virtual table " << origTable << ". Error details:" << tempTableRes->getErrorText(); @@ -303,6 +312,9 @@ QString SchemaResolver::getObjectDdl(const QString& name, ObjectType type) QString SchemaResolver::getObjectDdl(const QString &database, const QString &name, ObjectType type) { + // The "name" here used to be stripped with stripObjName(), but actually [abc] is a proper object name, + // that should not be stripped. Any names passed to SchemaResolver cannot be wrapped. + if (name.isNull()) return QString(); @@ -310,13 +322,13 @@ QString SchemaResolver::getObjectDdl(const QString &database, const QString &nam QString dbName = getPrefixDb(database); // In case of sqlite_master or sqlite_temp_master we have static definitions - QString lowerName = stripObjName(name).toLower(); + QString lowerName = name.toLower(); if (lowerName == "sqlite_master") return getSqliteMasterDdl(false); else if (lowerName == "sqlite_temp_master") return getSqliteMasterDdl(true); else if (lowerName.startsWith("sqlite_autoindex_")) - return getSqliteAutoIndexDdl(dbName, stripObjName(name)); + return getSqliteAutoIndexDdl(dbName, name); // Standalone or temp table? QString targetTable = "sqlite_master"; @@ -648,7 +660,7 @@ QString SchemaResolver::getSqliteAutoIndexDdl(const QString& database, const QSt } // Check the unique flag of the index - static_qstring(idxUniqueQueryTpl, "SELECT unique FROM %1.pragma_index_list(%2) WHERE name = ?"); + static_qstring(idxUniqueQueryTpl, "SELECT [unique] FROM %1.pragma_index_list(%2) WHERE name = ?"); SqlQueryPtr uniqRes = db->exec(idxUniqueQueryTpl.arg(dbName, wrapString(table)), {index}, dbFlags); bool unique = uniqRes->getSingleCell().toInt() > 0; @@ -846,6 +858,47 @@ QStringList SchemaResolver::getFkReferencingTables(const QString& table, const Q return tables; } +SchemaResolver::ObjectType SchemaResolver::objectTypeFromQueryType(const SqliteQueryType& queryType) +{ + switch (queryType) + { + case SqliteQueryType::CreateIndex: + return INDEX; + case SqliteQueryType::CreateTrigger: + return TRIGGER; + case SqliteQueryType::CreateView: + return VIEW; + case SqliteQueryType::CreateTable: + case SqliteQueryType::CreateVirtualTable: + return TABLE; + case SqliteQueryType::Select: + case SqliteQueryType::Pragma: + case SqliteQueryType::UNDEFINED: + case SqliteQueryType::EMPTY: + case SqliteQueryType::AlterTable: + case SqliteQueryType::Analyze: + case SqliteQueryType::Attach: + case SqliteQueryType::BeginTrans: + case SqliteQueryType::CommitTrans: + case SqliteQueryType::Copy: + case SqliteQueryType::Delete: + case SqliteQueryType::Detach: + case SqliteQueryType::DropIndex: + case SqliteQueryType::DropTable: + case SqliteQueryType::DropTrigger: + case SqliteQueryType::DropView: + case SqliteQueryType::Insert: + case SqliteQueryType::Reindex: + case SqliteQueryType::Release: + case SqliteQueryType::Rollback: + case SqliteQueryType::Savepoint: + case SqliteQueryType::Update: + case SqliteQueryType::Vacuum: + return ANY; + } + return ANY; +} + QStringList SchemaResolver::getIndexesForTable(const QString& database, const QString& table) { static_qstring(idxForTableTpl, "SELECT name FROM %1.pragma_index_list(%2)"); @@ -1150,7 +1203,7 @@ bool SchemaResolver::isWithoutRowIdTable(const QString& database, const QString& if (!createTable) return false; - return !createTable->withOutRowId.isNull(); + return createTable->withOutRowId; } bool SchemaResolver::isVirtualTable(const QString& database, const QString& table) @@ -1195,7 +1248,7 @@ QStringList SchemaResolver::getWithoutRowIdTableColumns(const QString& database, if (!createTable) return columns; - if (createTable->withOutRowId.isNull()) + if (!createTable->withOutRowId) return columns; // it's not WITHOUT ROWID table return createTable->getPrimaryKeyColumns(); @@ -1252,6 +1305,31 @@ void SchemaResolver::setNoDbLocking(bool value) dbFlags ^= Db::Flag::NO_LOCK; } +QString SchemaResolver::normalizeCaseObjectName(const QString& name) +{ + static_qstring(sql, "SELECT name FROM main.sqlite_master WHERE lower(name) = lower(?);"); + return normalizeCaseObjectNameByQuery(sql, name); +} + +QString SchemaResolver::normalizeCaseObjectName(const QString& database, const QString& name) +{ + static_qstring(sql, "SELECT name FROM %1.sqlite_master WHERE lower(name) = lower(?);"); + QString query = sql.arg(wrapObjIfNeeded(database)); + return normalizeCaseObjectNameByQuery(query, name); +} + +QString SchemaResolver::normalizeCaseObjectNameByQuery(const QString& query, const QString& name) +{ + SqlQueryPtr results = db->exec(query, {name}); + if (results->isError()) + { + qCritical() << "Could not get object name normalized case. Object name:" << name << ", error:" + << results->getErrorText(); + return name; + } + + return results->getSingleCell().toString(); +} SchemaResolver::ObjectCacheKey::ObjectCacheKey(Type type, Db* db, const QString& value1, const QString& value2, const QString& value3) : type(type), db(db), value1(value1), value2(value2), value3(value3) -- cgit v1.2.3