aboutsummaryrefslogtreecommitdiffstats
path: root/SQLiteStudio3/coreSQLiteStudio/db
diff options
context:
space:
mode:
authorLibravatarUnit 193 <unit193@ubuntu.com>2015-02-22 14:06:29 -0500
committerLibravatarUnit 193 <unit193@ubuntu.com>2015-02-22 14:06:29 -0500
commit306d6d3ca9c9ad774d19135681a7f9805f77035f (patch)
treea3e36ac2cc769162c30a1bcc33e126f7a4f4ccea /SQLiteStudio3/coreSQLiteStudio/db
parent016003905ca0e8e459e3dc33e786beda8ec92f45 (diff)
Imported Upstream version 3.0.3upstream/3.0.3
Diffstat (limited to 'SQLiteStudio3/coreSQLiteStudio/db')
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/abstractdb2.h2
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/db.h6
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.cpp47
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.h21
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutoraddrowids.cpp3
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorcolumns.cpp6
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutordatasources.cpp2
7 files changed, 56 insertions, 31 deletions
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/abstractdb2.h b/SQLiteStudio3/coreSQLiteStudio/db/abstractdb2.h
index c521bfa..9b27dc3 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/abstractdb2.h
+++ b/SQLiteStudio3/coreSQLiteStudio/db/abstractdb2.h
@@ -352,7 +352,7 @@ void AbstractDb2<T>::storeResult(sqlite_func* func, const QVariant& result, bool
case QVariant::UInt:
case QVariant::LongLong:
{
- sqlite_set_result_int(func, result.toInt());
+ sqlite_set_result_int(func, result.toLongLong());
break;
}
case QVariant::Double:
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/db.h b/SQLiteStudio3/coreSQLiteStudio/db/db.h
index 7d10a05..e11a844 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/db.h
+++ b/SQLiteStudio3/coreSQLiteStudio/db/db.h
@@ -501,7 +501,8 @@ class API_EXPORT Db : public QObject, public Interruptable
* @brief Attaches given database to this database.
* @param otherDb Other registered database object.
* @param silent If true, no errors or warnings will be reported to the NotifyManager (they will still appear in logs).
- * @return Name of the attached database (it's not the symbolic name of the other database, it's a name you would use in <tt>ATTACH 'name'</tt> statement).
+ * @return Name of the attached database (it's not the symbolic name of the other database, it's a name you would use in <tt>ATTACH 'name'</tt> statement),
+ * or null string if error occurred.
*
* This is convinent method to attach other registered databases to this database. It generates attached database name, so it doesn't conflict
* with other - already attached - database names, attaches the database with that name and returns that name to you, so you can refer to it in queries.
@@ -583,7 +584,8 @@ class API_EXPORT Db : public QObject, public Interruptable
* @return Database type label.
*
* The database type label is used on UI to tell user what database it is (SQLite 3, SQLite 2, Encrypted SQLite 3, etc).
- * This is defined by DbPlugin.
+ * This is usually the same as DbPlugin::getTitle(), but getTitle() is used in list of plugins in configuration dialog,
+ * while getTypeLabel() is used on databases list.
*/
virtual QString getTypeLabel() = 0;
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.cpp b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.cpp
index 97b3f1d..9fc49df 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.cpp
@@ -107,6 +107,8 @@ void QueryExecutor::executeChain()
}
}
+ requiredDbAttaches = context->dbNameToAttach.leftValues();
+
// We're done.
clearChain();
@@ -433,6 +435,7 @@ void QueryExecutor::simpleExecutionFinished(SqlQueryPtr results)
context->executionTime = QDateTime::currentMSecsSinceEpoch() - simpleExecutionStartTime;
context->rowsAffected = results->rowsAffected();
context->totalRowsReturned = 0;
+ requiredDbAttaches = context->dbNameToAttach.leftValues();
executionMutex.lock();
executionInProgress = false;
@@ -538,6 +541,12 @@ bool QueryExecutor::handleRowCountingResults(quint32 asyncId, SqlQueryPtr result
return true;
}
+
+const QStringList& QueryExecutor::getRequiredDbAttaches() const
+{
+ return requiredDbAttaches;
+}
+
bool QueryExecutor::getNoMetaColumns() const
{
return noMetaColumns;
@@ -550,32 +559,24 @@ void QueryExecutor::setNoMetaColumns(bool value)
void QueryExecutor::handleErrorsFromSmartAndSimpleMethods(SqlQueryPtr results)
{
- QString simpleText = results->getErrorText();
-
- // Smart text may contain messages from steps before the actual execution, but they will have negative error code.
- // Positive error code means that the error came directly from SQLite.
- QString smartText = context->errorCodeFromSmartExecution > 0 ? context->errorMessageFromSmartExecution : QString();
-
- if (simpleText.contains("no such") && smartText.contains("no such"))
- {
- // This happens if user refers to invalid column in attached database.
- // Smart execution will tell "no such column: xxx", while simple method will tell:
- // "no such table: attach.table". In that case we're more interested in smart method message.
- // This also applies to views.
- error(context->errorCodeFromSmartExecution, smartText);
- return;
- }
-
- if (simpleText.contains("no such") && smartText.contains("ambiguous"))
+ UNUSED(results);
+ // It turns out that currently smart execution error has more sense to be displayed to user than the simple execution error,
+ // so we're ignoring error from simple method, because it's usually misleading.
+ // The case when simple method error is more true than smart method error is very rare nowdays.
+ // Just rename attach names in the message.
+ QString msg = context->errorMessageFromSmartExecution;
+ QString match;
+ QString replaceName;
+ Dialect dialect = db->getDialect();
+ for (const QString& attachName : context->dbNameToAttach.rightValues())
{
- // This happens when smart execution raised "amigous column name" or something like that,
- // but simple method failed to work because of transparent database attaching. We prefer smart method error.
- error(context->errorCodeFromSmartExecution, smartText);
- return;
+ match = attachName + ".";
+ replaceName = wrapObjIfNeeded(context->dbNameToAttach.valueByRight(attachName), dialect) + ".";
+ while (msg.contains(match))
+ msg.replace(match, replaceName);
}
- // No special case, use simple method error
- error(results->getErrorCode(), simpleText);
+ error(context->errorCodeFromSmartExecution, msg);
}
void QueryExecutor::releaseResultsAndCleanup()
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.h b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.h
index 72c7fed..c6d7701 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.h
+++ b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.h
@@ -344,10 +344,19 @@ class API_EXPORT QueryExecutor : public QObject, public QRunnable
{
/**
* @brief Database name that the table with this row ID is in.
+ *
+ * It's the actual database name as SQLite sees it. That means it is a "main", or any attach name.
*/
QString database;
/**
+ * @brief Symbolic database name as listed in databases list.
+ *
+ * It can be empty if database was not explicitly passed in the query.
+ */
+ QString dbName;
+
+ /**
* @brief Table name that the row ID is for.
*/
QString table;
@@ -1018,6 +1027,8 @@ class API_EXPORT QueryExecutor : public QObject, public QRunnable
*/
void releaseResultsAndCleanup();
+ const QStringList& getRequiredDbAttaches() const;
+
private:
/**
* @brief Executes query.
@@ -1280,6 +1291,16 @@ class API_EXPORT QueryExecutor : public QObject, public QRunnable
bool noMetaColumns = false;
/**
+ * @brief List of required databases to attach.
+ *
+ * List of database names (symbolic names, as they appear on the list) that needs to be
+ * attached to access all columns returned by the most recent successful execution.
+ *
+ * This is set after every successful execution.
+ */
+ QStringList requiredDbAttaches;
+
+ /**
* @brief Chain of executor steps.
*
* Executor step list is set up by setupExecutionChain() and cleaned up after
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutoraddrowids.cpp b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutoraddrowids.cpp
index 55203e4..9307d13 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutoraddrowids.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutoraddrowids.cpp
@@ -60,7 +60,7 @@ QHash<SelectResolver::Table,QHash<QString,QString>> QueryExecutorAddRowIds::addR
}
// Getting all tables we need to get ROWID for
- SelectResolver resolver(db, select->tokens.detokenize());
+ SelectResolver resolver(db, select->tokens.detokenize(), context->dbNameToAttach);
resolver.resolveMultiCore = false; // multicore subselects result in not editable columns, skip them
QSet<SelectResolver::Table> tables = resolver.resolveTables(core);
@@ -177,6 +177,7 @@ bool QueryExecutorAddRowIds::addResultColumns(SqliteSelect::Core* core, const Se
{
// Query executor result column description
QueryExecutor::ResultRowIdColumnPtr queryExecutorResCol = QueryExecutor::ResultRowIdColumnPtr::create();
+ queryExecutorResCol->dbName = table.originalDatabase;
queryExecutorResCol->database = table.database;
queryExecutorResCol->table = table.table;
queryExecutorResCol->tableAlias = table.alias;
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorcolumns.cpp b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorcolumns.cpp
index bce1304..6acfb6f 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorcolumns.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorcolumns.cpp
@@ -289,10 +289,10 @@ QString QueryExecutorColumns::getAliasedColumnNameForSqlite2(const QueryExecutor
if (context->dbNameToAttach.containsLeft(resCol->database, Qt::CaseInsensitive))
colNameParts << context->dbNameToAttach.valueByLeft(resCol->database, Qt::CaseInsensitive);
else
- colNameParts << resCol->database;
+ colNameParts << wrapObjIfNeeded(resCol->database, dialect);
}
- colNameParts << resCol->table;
+ colNameParts << wrapObjIfNeeded(resCol->table, dialect);
}
- colNameParts << resCol->column;
+ colNameParts << wrapObjIfNeeded(resCol->column, dialect);
return colNameParts.join(".");
}
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutordatasources.cpp b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutordatasources.cpp
index 9a5c1c2..31cda9e 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutordatasources.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutordatasources.cpp
@@ -14,7 +14,7 @@ bool QueryExecutorDataSources::exec()
if (select->coreSelects.first()->valuesMode)
return true;
- SelectResolver resolver(db, select->tokens.detokenize());
+ SelectResolver resolver(db, select->tokens.detokenize(), context->dbNameToAttach);
resolver.resolveMultiCore = false; // multicore subselects result in not editable columns, skip them
SqliteSelect::Core* core = select->coreSelects.first();