aboutsummaryrefslogtreecommitdiffstats
path: root/SQLiteStudio3/coreSQLiteStudio/schemaresolver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'SQLiteStudio3/coreSQLiteStudio/schemaresolver.cpp')
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/schemaresolver.cpp124
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;