summaryrefslogtreecommitdiffstats
path: root/SQLiteStudio3/coreSQLiteStudio/db
diff options
context:
space:
mode:
Diffstat (limited to 'SQLiteStudio3/coreSQLiteStudio/db')
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/abstractdb2.h3
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/abstractdb3.h4
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.cpp18
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.h2
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutoraddrowids.cpp40
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutoraddrowids.h4
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorexecute.cpp28
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorexecute.h3
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorreplaceviews.cpp7
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/stdsqlite3driver.h1
10 files changed, 87 insertions, 23 deletions
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/abstractdb2.h b/SQLiteStudio3/coreSQLiteStudio/db/abstractdb2.h
index 0620a7d..5b95f61 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/abstractdb2.h
+++ b/SQLiteStudio3/coreSQLiteStudio/db/abstractdb2.h
@@ -109,7 +109,6 @@ class AbstractDb2 : public AbstractDb
int colCount = -1;
QStringList colNames;
QList<QVariant> nextRowValues;
- int affected = 0;
bool rowAvailable = false;
};
@@ -725,6 +724,8 @@ SqlResultsRowPtr AbstractDb2<T>::Query::nextInternal()
if (!rowAvailable || db.isNull())
return SqlResultsRowPtr();
+ ReadWriteLocker locker(&(db->dbOperLock), query, Dialect::Sqlite2, flags.testFlag(Db::Flag::NO_LOCK));
+
Row* row = new Row;
row->init(colNames, nextRowValues);
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/abstractdb3.h b/SQLiteStudio3/coreSQLiteStudio/db/abstractdb3.h
index fe37d5e..e7b0a4b 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/abstractdb3.h
+++ b/SQLiteStudio3/coreSQLiteStudio/db/abstractdb3.h
@@ -107,7 +107,6 @@ class AbstractDb3 : public AbstractDb
QString errorMessage;
int colCount = 0;
QStringList colNames;
- int affected = 0;
bool rowAvailable = false;
};
@@ -1076,13 +1075,14 @@ int AbstractDb3<T>::Query::fetchFirst()
for (int i = 0; i < colCount; i++)
colNames << QString::fromUtf8(T::column_name(stmt, i));
+ int changesBefore = T::total_changes(db->dbHandle);
rowAvailable = true;
int res = fetchNext();
affected = 0;
if (res == T::OK)
{
- affected = T::changes(db->dbHandle);
+ affected = T::total_changes(db->dbHandle) - changesBefore;
insertRowId["ROWID"] = T::last_insert_rowid(db->dbHandle);
}
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.cpp b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.cpp
index 9fc49df..b790ffa 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.cpp
@@ -40,7 +40,8 @@ QueryExecutor::QueryExecutor(Db* db, const QString& query, QObject *parent) :
setAutoDelete(false);
connect(this, SIGNAL(executionFailed(int,QString)), this, SLOT(cleanupAfterExecFailed(int,QString)));
- connect(DBLIST, SIGNAL(dbAboutToBeUnloaded(Db*, DbPlugin*)), this, SLOT(cleanupBeforeDbDestroy(Db*, DbPlugin*)));
+ connect(DBLIST, SIGNAL(dbAboutToBeUnloaded(Db*, DbPlugin*)), this, SLOT(cleanupBeforeDbDestroy(Db*)));
+ connect(DBLIST, SIGNAL(dbRemoved(Db*)), this, SLOT(cleanupBeforeDbDestroy(Db*)));
}
QueryExecutor::~QueryExecutor()
@@ -146,9 +147,8 @@ void QueryExecutor::cleanupAfterExecFailed(int code, QString errorMessage)
cleanup();
}
-void QueryExecutor::cleanupBeforeDbDestroy(Db* dbToBeUnloaded, DbPlugin* plugin)
+void QueryExecutor::cleanupBeforeDbDestroy(Db* dbToBeUnloaded)
{
- UNUSED(plugin);
if (!dbToBeUnloaded || dbToBeUnloaded != db)
return;
@@ -404,7 +404,16 @@ void QueryExecutor::executeSimpleMethod()
simpleExecution = true;
context->editionForbiddenReasons << EditionForbiddenReason::SMART_EXECUTION_FAILED;
simpleExecutionStartTime = QDateTime::currentMSecsSinceEpoch();
- asyncId = db->asyncExec(originalQuery, context->queryParameters, Db::Flag::PRELOAD);
+
+ if (asyncMode)
+ {
+ asyncId = db->asyncExec(originalQuery, context->queryParameters, Db::Flag::PRELOAD);
+ }
+ else
+ {
+ SqlQueryPtr results = db->exec(originalQuery, context->queryParameters, Db::Flag::PRELOAD);
+ simpleExecutionFinished(results);
+ }
}
void QueryExecutor::simpleExecutionFinished(SqlQueryPtr results)
@@ -435,6 +444,7 @@ void QueryExecutor::simpleExecutionFinished(SqlQueryPtr results)
context->executionTime = QDateTime::currentMSecsSinceEpoch() - simpleExecutionStartTime;
context->rowsAffected = results->rowsAffected();
context->totalRowsReturned = 0;
+ context->executionResults = results;
requiredDbAttaches = context->dbNameToAttach.leftValues();
executionMutex.lock();
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.h b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.h
index c6d7701..83d0436 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.h
+++ b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.h
@@ -1407,7 +1407,7 @@ class API_EXPORT QueryExecutor : public QObject, public QRunnable
* from deleted Db. Keeping results is dangerous, becuase the Db driver (plugin) is most likely to
* be unloaded soon and we won't be able to call results destructor.
*/
- void cleanupBeforeDbDestroy(Db* dbToBeUnloaded, DbPlugin* plugin);
+ void cleanupBeforeDbDestroy(Db* dbToBeUnloaded);
};
int qHash(QueryExecutor::EditionForbiddenReason reason);
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutoraddrowids.cpp b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutoraddrowids.cpp
index 9307d13..ea42baf 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutoraddrowids.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutoraddrowids.cpp
@@ -59,6 +59,16 @@ QHash<SelectResolver::Table,QHash<QString,QString>> QueryExecutorAddRowIds::addR
return rowIdColsMap;
}
+ bool hasStar = false;
+ for (SqliteSelect::Core::ResultColumn* resCol : core->resultColumns)
+ {
+ if (resCol->star)
+ {
+ hasStar = true;
+ break;
+ }
+ }
+
// Getting all tables we need to get ROWID for
SelectResolver resolver(db, select->tokens.detokenize(), context->dbNameToAttach);
resolver.resolveMultiCore = false; // multicore subselects result in not editable columns, skip them
@@ -69,7 +79,7 @@ QHash<SelectResolver::Table,QHash<QString,QString>> QueryExecutorAddRowIds::addR
if (table.flags & (SelectResolver::FROM_COMPOUND_SELECT | SelectResolver::FROM_DISTINCT_SELECT | SelectResolver::FROM_GROUPED_SELECT))
continue; // we don't get ROWID from compound, distinct or aggregated subselects
- if (!addResultColumns(core, table, rowIdColsMap, isTopSelect))
+ if (!addResultColumns(core, table, rowIdColsMap, isTopSelect, hasStar))
{
ok = false;
return rowIdColsMap;
@@ -146,12 +156,14 @@ QHash<QString,QString> QueryExecutorAddRowIds::getNextColNames(const SelectResol
}
bool QueryExecutorAddRowIds::addResultColumns(SqliteSelect::Core* core, const SelectResolver::Table& table,
- QHash<SelectResolver::Table,QHash<QString,QString>>& rowIdColsMap, bool isTopSelect)
+ QHash<SelectResolver::Table,QHash<QString,QString>>& rowIdColsMap, bool isTopSelect, bool hasStar)
{
QHash<QString, QString> executorToRealColumns;
+ bool aliasOnlyAsSelectColumn = false;
if (rowIdColsMap.contains(table))
{
executorToRealColumns = rowIdColsMap[table]; // we already have resCol names from subselect
+ aliasOnlyAsSelectColumn = true;
}
else
{
@@ -169,7 +181,7 @@ bool QueryExecutorAddRowIds::addResultColumns(SqliteSelect::Core* core, const Se
while (it.hasNext())
{
it.next();
- if (!addResultColumns(core, table, it.key(), it.value()))
+ if (!addResultColumns(core, table, it.key(), it.value(), aliasOnlyAsSelectColumn))
return false;
}
@@ -189,7 +201,7 @@ bool QueryExecutorAddRowIds::addResultColumns(SqliteSelect::Core* core, const Se
}
bool QueryExecutorAddRowIds::addResultColumns(SqliteSelect::Core* core, const SelectResolver::Table& table, const QString& queryExecutorColumn,
- const QString& realColumn)
+ const QString& realColumn, bool aliasOnlyAsSelectColumn)
{
SqliteSelect::Core::ResultColumn* resCol = new SqliteSelect::Core::ResultColumn();
resCol->setParent(core);
@@ -197,17 +209,25 @@ bool QueryExecutorAddRowIds::addResultColumns(SqliteSelect::Core* core, const Se
resCol->expr = new SqliteExpr();
resCol->expr->setParent(resCol);
- resCol->expr->initId(realColumn);
- if (!table.alias.isNull())
+ if (aliasOnlyAsSelectColumn)
{
- resCol->expr->table = table.alias;
+ // We are re-querying this column from subselect, we already have it as an alias
+ resCol->expr->initId(queryExecutorColumn);
}
else
{
- if (!table.database.isNull())
- resCol->expr->database = table.database;
+ resCol->expr->initId(realColumn);
+ if (!table.alias.isNull())
+ {
+ resCol->expr->table = table.alias;
+ }
+ else
+ {
+ if (!table.database.isNull())
+ resCol->expr->database = table.database;
- resCol->expr->table = table.table;
+ resCol->expr->table = table.table;
+ }
}
resCol->asKw = true;
resCol->alias = queryExecutorColumn;
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutoraddrowids.h b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutoraddrowids.h
index a5431fa..fa2167f 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutoraddrowids.h
+++ b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutoraddrowids.h
@@ -31,7 +31,7 @@ class QueryExecutorAddRowIds : public QueryExecutorStep
* Finds columns representing ROWID for the \p table and adds them to result columns and to the context.
*/
bool addResultColumns(SqliteSelect::Core* core, const SelectResolver::Table& table,
- QHash<SelectResolver::Table, QHash<QString, QString> >& rowIdColsMap, bool isTopSelect);
+ QHash<SelectResolver::Table, QHash<QString, QString> >& rowIdColsMap, bool isTopSelect, bool hasStar);
/**
* @brief Adds the column to result columns list.
@@ -44,7 +44,7 @@ class QueryExecutorAddRowIds : public QueryExecutorStep
* Adds given column to the result column list in the SELECT statement.
*/
bool addResultColumns(SqliteSelect::Core* core, const SelectResolver::Table& table, const QString& queryExecutorColumn,
- const QString& realColumn);
+ const QString& realColumn, bool aliasOnlyAsSelectColumn);
/**
* @brief Adds all necessary ROWID columns to result columns.
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorexecute.cpp b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorexecute.cpp
index df2ed68..a954da7 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorexecute.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorexecute.cpp
@@ -7,6 +7,7 @@
#include "datatype.h"
#include <QDateTime>
#include <QDebug>
+#include <QStack>
#include <schemaresolver.h>
#include <common/table.h>
@@ -34,6 +35,7 @@ bool QueryExecutorExecute::executeQueries()
QHash<QString, QVariant> bindParamsForQuery;
SqlQueryPtr results;
context->rowsAffected = 0;
+ QStack<int> rowsAffectedBeforeTransaction;
Db::Flags flags;
if (context->preloadResults)
@@ -51,6 +53,9 @@ bool QueryExecutorExecute::executeQueries()
if (queryCount == 0) // last query?
setupSqlite2ColumnDataTypes(results);
+ if (isBeginTransaction(query->queryType))
+ rowsAffectedBeforeTransaction.push(context->rowsAffected);
+
results->execute();
if (results->isError())
@@ -60,6 +65,14 @@ bool QueryExecutorExecute::executeQueries()
}
context->rowsAffected += results->rowsAffected();
+
+ if (rowsAffectedBeforeTransaction.size() > 0)
+ {
+ if (isCommitTransaction(query->queryType))
+ rowsAffectedBeforeTransaction.pop();
+ else if (isRollbackTransaction(query->queryType))
+ context->rowsAffected = rowsAffectedBeforeTransaction.pop();
+ }
}
handleSuccessfulResult(results);
return true;
@@ -152,3 +165,18 @@ void QueryExecutorExecute::setupSqlite2ColumnDataTypes(SqlQueryPtr results)
sqlite2Helper->setBinaryType(idx);
}
}
+
+bool QueryExecutorExecute::isBeginTransaction(SqliteQueryType queryType)
+{
+ return (queryType == SqliteQueryType::BeginTrans || queryType == SqliteQueryType::Savepoint);
+}
+
+bool QueryExecutorExecute::isCommitTransaction(SqliteQueryType queryType)
+{
+ return (queryType == SqliteQueryType::CommitTrans || queryType == SqliteQueryType::Release);
+}
+
+bool QueryExecutorExecute::isRollbackTransaction(SqliteQueryType queryType)
+{
+ return queryType == SqliteQueryType::Rollback;
+}
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorexecute.h b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorexecute.h
index a88bf56..ea6fed2 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorexecute.h
+++ b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorexecute.h
@@ -80,6 +80,9 @@ class QueryExecutorExecute : public QueryExecutorStep
qint64 startTime;
void setupSqlite2ColumnDataTypes(SqlQueryPtr results);
+ bool isBeginTransaction(SqliteQueryType queryType);
+ bool isCommitTransaction(SqliteQueryType queryType);
+ bool isRollbackTransaction(SqliteQueryType queryType);
};
#endif // QUERYEXECUTOREXECUTE_H
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorreplaceviews.cpp b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorreplaceviews.cpp
index 94300a0..1f2e736 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorreplaceviews.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorreplaceviews.cpp
@@ -25,6 +25,7 @@ bool QueryExecutorReplaceViews::exec()
return true;
replaceViews(select.data());
+ select->rebuildTokens();
updateQueries();
return true;
@@ -72,7 +73,7 @@ void QueryExecutorReplaceViews::replaceViews(SqliteSelect* select)
SqliteCreateViewPtr view;
QList<SqliteSelect::Core::SingleSource*> sources = core->getAllTypedStatements<SqliteSelect::Core::SingleSource>();
- foreach (SqliteSelect::Core::SingleSource* src, sources)
+ for (SqliteSelect::Core::SingleSource* src : sources)
{
if (src->table.isNull())
continue;
@@ -92,9 +93,9 @@ void QueryExecutorReplaceViews::replaceViews(SqliteSelect* select)
src->select = view->select;
src->database = QString::null;
src->table = QString::null;
- }
- select->rebuildTokens();
+ replaceViews(src->select);
+ }
}
uint qHash(const QueryExecutorReplaceViews::View& view)
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/stdsqlite3driver.h b/SQLiteStudio3/coreSQLiteStudio/db/stdsqlite3driver.h
index 2f26aaf..6b0c422 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/stdsqlite3driver.h
+++ b/SQLiteStudio3/coreSQLiteStudio/db/stdsqlite3driver.h
@@ -64,6 +64,7 @@
static int column_type(stmt* arg1, int arg2) {return Prefix##sqlite3_column_type(arg1, arg2);} \
static int column_count(stmt* arg1) {return Prefix##sqlite3_column_count(arg1);} \
static int changes(handle* arg) {return Prefix##sqlite3_changes(arg);} \
+ static int total_changes(handle* arg) {return Prefix##sqlite3_total_changes(arg);} \
static int last_insert_rowid(handle* arg) {return Prefix##sqlite3_last_insert_rowid(arg);} \
static int step(stmt* arg) {return Prefix##sqlite3_step(arg);} \
static int reset(stmt* arg) {return Prefix##sqlite3_reset(arg);} \