Skip to content

Commit 4bca62a

Browse files
committed
#5216 Fixed Query Executor to use Smart Execution Method when there is a Virtual Table mentioned in the query, therefore enabling all advanced features of the Query Executor.
1 parent 39f98ab commit 4bca62a

File tree

5 files changed

+62
-66
lines changed

5 files changed

+62
-66
lines changed

ChangeLog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
### 3.4.15
44
- BUGFIX: #5218 Fixed Drag&Drop of items in the database list - a bug that was introduced in 3.4.14.
5+
- BUGFIX: #5216 Fixed Query Executor to use Smart Execution Method when there is a Virtual Table mentioned in the query, therefore enabling all advanced features of the Query Executor.
56

67
### 3.4.14
78
- ADDED: #5190 Added support for optional ORDER BY and LIMIT clauses in UPDATE and DELETE statements.

SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutoraddrowids.cpp

Lines changed: 7 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "parser/ast/sqliteselect.h"
33
#include "selectresolver.h"
44
#include "parser/ast/sqlitecreatetable.h"
5+
#include "parser/ast/sqlitecreatevirtualtable.h"
56
#include "schemaresolver.h"
67
#include "common/compatibility.h"
78
#include <QDebug>
@@ -112,48 +113,15 @@ QList<SqliteSelect*> QueryExecutorAddRowIds::getSubSelects(SqliteSelect::Core* c
112113

113114
QHash<QString,QString> QueryExecutorAddRowIds::getNextColNames(const SelectResolver::Table& table)
114115
{
115-
QHash<QString,QString> colNames;
116-
117116
SchemaResolver resolver(db);
118-
SqliteQueryPtr query = resolver.getParsedObject(table.database, table.table, SchemaResolver::TABLE);
119-
SqliteCreateTablePtr createTable = query.dynamicCast<SqliteCreateTable>();
120-
if (!createTable)
121-
{
122-
qCritical() << "No CREATE TABLE object after parsing and casting in QueryExecutorAddRowIds::getNextColNames(). Cannot provide ROWID columns.";
123-
return colNames;
124-
}
117+
QStringList rowIdCols = table.database.isNull() ?
118+
resolver.getRowIdTableColumns(table.table) :
119+
resolver.getRowIdTableColumns(table.database, table.table);
125120

126-
if (!createTable->withOutRowId)
127-
{
128-
// It's a regular ROWID table
129-
colNames[getNextColName()] = "ROWID";
130-
return colNames;
131-
}
132-
133-
SqliteStatement* primaryKey = createTable->getPrimaryKey();
134-
if (!primaryKey)
135-
{
136-
qCritical() << "WITHOUT ROWID table, but could not find // Co PRIMARY KEY in QueryExecutorAddRowIds::getNextColNames().";
137-
return colNames;
138-
}
139-
140-
SqliteCreateTable::Column::Constraint* columnConstr = dynamic_cast<SqliteCreateTable::Column::Constraint*>(primaryKey);
141-
if (columnConstr)
142-
{
143-
colNames[getNextColName()] = dynamic_cast<SqliteCreateTable::Column*>(columnConstr->parentStatement())->name;
144-
return colNames;
145-
}
146-
147-
SqliteCreateTable::Constraint* tableConstr = dynamic_cast<SqliteCreateTable::Constraint*>(primaryKey);
148-
if (tableConstr)
149-
{
150-
for (SqliteIndexedColumn*& idxCol : tableConstr->indexedColumns)
151-
colNames[getNextColName()] = idxCol->name;
152-
153-
return colNames;
154-
}
121+
QHash<QString,QString> colNames;
122+
for (const QString& colName : rowIdCols)
123+
colNames[getNextColName()] = colName;
155124

156-
qCritical() << "PRIMARY KEY that is neither table or column constraint. Should never happen (QueryExecutorAddRowIds::getNextColNames()).";
157125
return colNames;
158126
}
159127

SQLiteStudio3/coreSQLiteStudio/schemaresolver.cpp

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1418,27 +1418,51 @@ SqliteCreateTablePtr SchemaResolver::resolveVirtualTableAsRegularTable(const QSt
14181418
return virtualTableAsRegularTable(database, table);
14191419
}
14201420

1421-
QStringList SchemaResolver::getWithoutRowIdTableColumns(const QString& table)
1421+
QStringList SchemaResolver::getRowIdTableColumns(const QString& table)
14221422
{
1423-
return getWithoutRowIdTableColumns("main", table);
1423+
return getRowIdTableColumns("main", table);
14241424
}
14251425

1426-
QStringList SchemaResolver::getWithoutRowIdTableColumns(const QString& database, const QString& table)
1426+
QStringList SchemaResolver::getRowIdTableColumns(const QString& database, const QString& table)
14271427
{
1428-
QStringList columns;
1428+
SqlQueryPtr results = db->exec(QString("PRAGMA %1.table_list(%2);")
1429+
.arg(database, wrapObjIfNeeded(table)));
1430+
if (results->isError())
1431+
{
1432+
qWarning() << "Could not get rowId column list using PRAGMA for db.table:" << database << "." << table << " (step 1), error was:" << results->getErrorText();
1433+
return QStringList();
1434+
}
14291435

1430-
SqliteQueryPtr query = getParsedObject(database, table, TABLE);
1431-
if (!query)
1432-
return columns;
1436+
if (!results->hasNext())
1437+
{
1438+
qWarning() << "Could not get rowId column list using PRAGMA for db.table:" << database << "." << table << " (step 1), no row was returned.";
1439+
return QStringList();
1440+
}
14331441

1434-
SqliteCreateTablePtr createTable = query.dynamicCast<SqliteCreateTable>();
1435-
if (!createTable)
1436-
return columns;
1442+
SqlResultsRowPtr row = results->next();
1443+
int withoutRowId = row->value("wr").toInt();
1444+
if (!withoutRowId)
1445+
return QStringList{"ROWID"};
1446+
1447+
// WITHOUT ROWID table
1448+
results = db->exec(QString("PRAGMA %1.table_info(%2);")
1449+
.arg(database, wrapObjIfNeeded(table)));
14371450

1438-
if (!createTable->withOutRowId)
1439-
return columns; // it's not WITHOUT ROWID table
1451+
if (results->isError())
1452+
{
1453+
qWarning() << "Could not get rowId column list using PRAGMA for db.table:" << database << "." << table << " (step 2), error was:" << results->getErrorText();
1454+
return QStringList();
1455+
}
14401456

1441-
return createTable->getPrimaryKeyColumns();
1457+
QStringList columns;
1458+
while (results->hasNext())
1459+
{
1460+
row = results->next();
1461+
int pk = row->value("pk").toInt();
1462+
if (pk)
1463+
columns << row->value("name").toString();
1464+
}
1465+
return columns;
14421466
}
14431467

14441468
QString SchemaResolver::getSqliteMasterDdl(bool temp)

SQLiteStudio3/coreSQLiteStudio/schemaresolver.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,8 @@ class API_EXPORT SchemaResolver
132132
SqliteCreateTablePtr resolveVirtualTableAsRegularTable(const QString& table);
133133
SqliteCreateTablePtr resolveVirtualTableAsRegularTable(const QString& database, const QString& table);
134134

135-
QStringList getWithoutRowIdTableColumns(const QString& table);
136-
QStringList getWithoutRowIdTableColumns(const QString& database, const QString& table);
135+
QStringList getRowIdTableColumns(const QString& table);
136+
QStringList getRowIdTableColumns(const QString& database, const QString& table);
137137

138138
/**
139139
* @brief getTableColumns Get column names for a table.

SQLiteStudio3/guiSQLiteStudio/datagrid/sqlquerymodel.cpp

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,29 +1321,32 @@ void SqlQueryModel::readColumnDetails()
13211321
QHash<AliasedTable, SqlQueryModel::TableDetails> SqlQueryModel::readTableDetails()
13221322
{
13231323
QHash<AliasedTable, TableDetails> results;
1324-
SqliteQueryPtr query;
1325-
SqliteCreateTablePtr createTable;
13261324
SchemaResolver resolver(getDb());
1327-
QString database;
1328-
AliasedTable table;
1329-
QString columnName;
1330-
13311325
for (const QueryExecutor::SourceTablePtr& srcTable : queryExecutor->getSourceTables())
13321326
{
1333-
database = srcTable->database.isEmpty() ? "main" : srcTable->database;
1327+
QString database = srcTable->database.isEmpty() ? "main" : srcTable->database;
13341328

1335-
query = resolver.getParsedObject(database, srcTable->table, SchemaResolver::TABLE);
1336-
if (!query || !query.dynamicCast<SqliteCreateTable>())
1329+
SqliteQueryPtr query = resolver.getParsedObject(database, srcTable->table, SchemaResolver::TABLE);
1330+
if (!query)
13371331
{
13381332
qWarning() << "Could not get parsed table while reading table details in SqlQueryModel. Queried table was:"
13391333
<< database + "." + srcTable->table;
13401334
continue;
13411335
}
1342-
createTable = query.dynamicCast<SqliteCreateTable>();
1336+
SqliteCreateTablePtr createTable = query.dynamicCast<SqliteCreateTable>();
1337+
if (!createTable && resolver.isVirtualTable(database, srcTable->table))
1338+
createTable = resolver.resolveVirtualTableAsRegularTable(database, srcTable->table);
1339+
1340+
if (!createTable)
1341+
{
1342+
qWarning() << "Could not get parsed table while reading table details in SqlQueryModel. Neither as regular nor virtual table. Queried table was:"
1343+
<< database + "." + srcTable->table;
1344+
continue;
1345+
}
13431346

13441347
// Table details
13451348
TableDetails tableDetails;
1346-
table = {database, srcTable->table, srcTable->alias};
1349+
AliasedTable table = {database, srcTable->table, srcTable->alias};
13471350

13481351
// Table constraints
13491352
for (SqliteCreateTable::Constraint* tableConstr : createTable->constraints)
@@ -1354,7 +1357,7 @@ QHash<AliasedTable, SqlQueryModel::TableDetails> SqlQueryModel::readTableDetails
13541357
{
13551358
// Column details
13561359
TableDetails::ColumnDetails columnDetails;
1357-
columnName = stripObjName(columnStmt->name);
1360+
QString columnName = stripObjName(columnStmt->name);
13581361

13591362
// Column type
13601363
if (columnStmt->type)

0 commit comments

Comments
 (0)