diff options
Diffstat (limited to 'SQLiteStudio3/coreSQLiteStudio/schemaresolver.cpp')
| -rw-r--r-- | SQLiteStudio3/coreSQLiteStudio/schemaresolver.cpp | 124 |
1 files changed, 113 insertions, 11 deletions
diff --git a/SQLiteStudio3/coreSQLiteStudio/schemaresolver.cpp b/SQLiteStudio3/coreSQLiteStudio/schemaresolver.cpp index 7988748..0044c3e 100644 --- a/SQLiteStudio3/coreSQLiteStudio/schemaresolver.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/schemaresolver.cpp @@ -250,8 +250,10 @@ SqliteCreateTablePtr SchemaResolver::virtualTableAsRegularTable(const QString &d // Create temp table to see columns. QString newTable = db->getUniqueNewObjectName(strippedName); - QString origTable = wrapObjName(strippedName, dialect); - db->exec(QString("CREATE TEMP TABLE %1 AS SELECT * FROM %2.%3 LIMIT 0;").arg(newTable, dbName, origTable), dbFlags); + QString origTable = wrapObjIfNeeded(strippedName, dialect); + 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(); // Get parsed DDL of the temp table. SqliteQueryPtr query = getParsedObject("temp", newTable, TABLE); @@ -288,6 +290,11 @@ QString SchemaResolver::getObjectDdl(const QString &database, const QString &nam // Prepare db prefix. QString dbName = getPrefixDb(database, dialect); + // Standalone or temp table? + QString targetTable = "sqlite_master"; + if (database.toLower() == "temp") + targetTable = "sqlite_temp_master"; + // Cache QString typeStr = objectTypeToString(type); bool useCache = usesCache(); @@ -297,29 +304,32 @@ QString SchemaResolver::getObjectDdl(const QString &database, const QString &nam // Get the DDL QVariant results; + SqlQueryPtr queryResults; if (type != ANY) { - results = db->exec(QString( - "SELECT sql FROM %1.sqlite_master WHERE lower(name) = '%2' AND type = '%3';").arg(dbName, escapeString(lowerName), typeStr), + queryResults = db->exec(QString( + "SELECT sql FROM %1.%4 WHERE lower(name) = '%2' AND type = '%3';").arg(dbName, escapeString(lowerName), typeStr, targetTable), dbFlags - )->getSingleCell(); + ); + } else { - results = db->exec(QString( - "SELECT sql FROM %1.sqlite_master WHERE lower(name) = '%2';").arg(dbName, escapeString(lowerName)), + queryResults = db->exec(QString( + "SELECT sql FROM %1.%3 WHERE lower(name) = '%2';").arg(dbName, escapeString(lowerName), targetTable), dbFlags - )->getSingleCell(); + ); } // Validate query results - if (!results.isValid() || results.isNull()) + if (queryResults->isError()) { - qDebug() << "Could not get object's DDL:" << dbName << "." << name; + qDebug() << "Could not get object's DDL:" << dbName << "." << name << ", details:" << queryResults->getErrorText(); return QString::null; } // The DDL string + results = queryResults->getSingleCell(); QString resStr = results.toString(); // If the DDL doesn't have semicolon at the end (usually the case), add it. @@ -333,6 +343,95 @@ QString SchemaResolver::getObjectDdl(const QString &database, const QString &nam return resStr; } +QStringList SchemaResolver::getColumnsFromDdlUsingPragma(const QString& ddl) +{ + Parser parser(db->getDialect()); + if (!parser.parse(ddl) || parser.getQueries().isEmpty()) + { + qWarning() << "Could not parse DDL for determinating columns using PRAGMA. The DDL was:\n" << ddl; + return QStringList(); + } + + SqliteQueryPtr query = parser.getQueries().first(); + if (query->queryType == SqliteQueryType::CreateTable) + return getColumnsUsingPragma(query.dynamicCast<SqliteCreateTable>().data()); + + if (query->queryType == SqliteQueryType::CreateView) + return getColumnsUsingPragma(query.dynamicCast<SqliteCreateView>().data()); + + qWarning() << "Tried to get columns of DDL using pragma for statement other than table or view:" << sqliteQueryTypeToString(query->queryType) << "for DDL:\n" << ddl; + return QStringList(); +} + +QStringList SchemaResolver::getColumnsUsingPragma(const QString& tableOrView) +{ + static_qstring(query, "PRAGMA table_info(%1)"); + SqlQueryPtr results = db->exec(query.arg(wrapObjIfNeeded(tableOrView, db->getDialect()))); + if (results->isError()) + { + qWarning() << "Could not get column list using PRAGMA for table or view:" << tableOrView << ", error was:" << results->getErrorText(); + return QStringList(); + } + + QStringList cols; + for (const SqlResultsRowPtr& row : results->getAll()) + cols << row->value("name").toString(); + + return cols; +} + +QStringList SchemaResolver::getColumnsUsingPragma(SqliteCreateTable* createTable) +{ + QString name = getUniqueName(); + SqliteCreateTable* stmt = dynamic_cast<SqliteCreateTable*>(createTable->clone()); + stmt->tempKw = true; + stmt->table = name; + stmt->database = QString(); + stmt->rebuildTokens(); + QString ddl = stmt->tokens.detokenize(); + delete stmt; + + SqlQueryPtr result = db->exec(ddl); + if (result->isError()) + { + qWarning() << "Could not create table for finding its columns using PRAGMA. Error was:" << result->getErrorText(); + return QStringList(); + } + + QStringList columns = getColumnsUsingPragma(name); + + static_qstring(dropSql, "DROP TABLE %1"); + db->exec(dropSql.arg(wrapObjIfNeeded(name, db->getDialect()))); + + return columns; +} + +QStringList SchemaResolver::getColumnsUsingPragma(SqliteCreateView* createView) +{ + QString name = getUniqueName(); + SqliteCreateView* stmt = dynamic_cast<SqliteCreateView*>(createView->clone()); + stmt->tempKw = true; + stmt->view = name; + stmt->database = QString(); + stmt->rebuildTokens(); + QString ddl = stmt->tokens.detokenize(); + delete stmt; + + SqlQueryPtr result = db->exec(ddl); + if (result->isError()) + { + qWarning() << "Could not create view for finding its columns using PRAGMA. Error was:" << result->getErrorText(); + return QStringList(); + } + + QStringList columns = getColumnsUsingPragma(name); + + static_qstring(dropSql, "DROP VIEW %1"); + db->exec(dropSql.arg(wrapObjIfNeeded(name, db->getDialect()))); + + return columns; +} + SqliteQueryPtr SchemaResolver::getParsedObject(const QString &name, ObjectType type) { return getParsedObject("main", name, type); @@ -679,8 +778,11 @@ QList<SqliteCreateIndexPtr> SchemaResolver::getParsedIndexesForTable(const QStri QStringList indexes = getIndexes(database); SqliteQueryPtr query; SqliteCreateIndexPtr createIndex; - foreach (const QString& index, indexes) + for (const QString& index : indexes) { + if (index.startsWith("sqlite_", Qt::CaseInsensitive)) + continue; + query = getParsedObject(database, index, INDEX); if (!query) continue; |
