aboutsummaryrefslogtreecommitdiffstats
path: root/SQLiteStudio3/coreSQLiteStudio
diff options
context:
space:
mode:
Diffstat (limited to 'SQLiteStudio3/coreSQLiteStudio')
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/ChangeLog.txt62
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/TODO.txt21
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/common/bistrhash.cpp213
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/common/bistrhash.h213
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/common/sortedset.h64
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/common/strhash.h23
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/common/utils.cpp43
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/common/utils.h40
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/common/utils_sql.cpp62
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/common/utils_sql.h4
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/coreSQLiteStudio.pro10
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/csvserializer.cpp251
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/csvserializer.h7
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/abstractdb2.h4
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/abstractdb3.h23
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/chainexecutor.cpp59
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/chainexecutor.h13
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/db.cpp1
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/db.h3
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.cpp41
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.h5
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorcellsize.cpp35
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorcolumns.cpp13
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorexecute.cpp5
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/dbattacher.h11
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/dbobjectorganizer.cpp47
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/dbobjectorganizer.h1
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/dbversionconverter.cpp16
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/dbversionconverter.h16
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/exportworker.cpp7
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/impl/dbattacherimpl.cpp19
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/impl/dbattacherimpl.h2
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/importworker.cpp5
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/log.cpp28
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/log.h5
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateindex.cpp55
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateindex.h13
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetable.cpp22
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetable.h7
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetrigger.cpp10
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetrigger.h5
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateview.cpp29
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateview.h9
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteddlwithdbcontext.h16
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteexpr.cpp8
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteextendedindexedcolumn.h19
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteindexedcolumn.cpp27
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteindexedcolumn.h8
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteorderby.cpp82
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteorderby.h12
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitetablerelatedddl.h1
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitevacuum.cpp3
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/parser/lexer.cpp33
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/parser/lexer.h9
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/parser/sqlite3_parse.cpp969
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/parser/sqlite3_parse.y7
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/parser/statementtokenbuilder.cpp2
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/querygenerator.cpp275
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/querygenerator.h75
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/schemaresolver.cpp124
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/schemaresolver.h5
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/selectresolver.cpp61
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/selectresolver.h6
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/services/dbmanager.h6
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/services/impl/dbmanagerimpl.cpp42
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/services/impl/dbmanagerimpl.h7
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/services/impl/pluginmanagerimpl.cpp15
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/services/impl/pluginmanagerimpl.h8
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/sqlitestudio.cpp2
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/tablemodifier.cpp185
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/tablemodifier.h50
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_de.qmbin23 -> 45651 bytes
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_de.ts112
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_es.ts110
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_fr.ts168
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_it.qmbin0 -> 23 bytes
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_it.ts110
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_pl.ts114
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_pt_BR.ts110
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_ru.ts110
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_sk.qmbin4601 -> 6146 bytes
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_sk.ts108
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_zh_CN.qmbin16 -> 107 bytes
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_zh_CN.ts110
84 files changed, 3157 insertions, 1474 deletions
diff --git a/SQLiteStudio3/coreSQLiteStudio/ChangeLog.txt b/SQLiteStudio3/coreSQLiteStudio/ChangeLog.txt
index 38c2289..a477b8c 100644
--- a/SQLiteStudio3/coreSQLiteStudio/ChangeLog.txt
+++ b/SQLiteStudio3/coreSQLiteStudio/ChangeLog.txt
@@ -1,3 +1,65 @@
+[3.1.0]
+ * [ADDED]: SQLCipher plugin is now free, open source and distributed together with other standard plugins.
+ * [ADDED]: #2963 Indexed expressions for CREATE INDEX statements (introduced in SQLite 3.9) are now supported and can be edited in Index Dialog.
+ * [ADDED]: View window now supports explicit column names for the view (introduced in SQLite 3.9).
+ * [ADDED]: #3056 #3063 Implemented index column ordering in index dialog.
+ * [ADDED]: Added shortcut (Ctrl+/ by default) to toggle comment of current line or selected block of code (if any) in SQL editor.
+ * [ADDED]: #3040 Added new entry in context menu of data grid to generate SELECT/INSERT/UPDATE/DELETE statement together with WHERE clause containing IN conditions for selected cells.
+ * [ADDED]: Added new entry in context menu of database list to generate queries like in #3040 for selected table.
+ * [ADDED]: #2975 Information message after successful table/view change.
+ * [ADDED]: Introduced "loadByDefault" property for plugin descriptor files.
+ * [ADDED]: Added options to have "Data" tab placed as a first tab for Table windows and for View windows. By default option is disabled, so by default nothing changes.
+ * [ADDED]: Added option in configuration dialog to avoid reopening status panel for each message printed there.
+ * [ADDED]: Added option in configuration dialog to prevent displaying tooltips over data view when user holds mouse over it.
+ * [ADDED]: #3070 Added option in configuration dialog to have new databases marked as not permanent by default.
+ * [ADDED]: #3070 Added option in configuration dialog to bypass database dialog completely when dropping file from file manager onto database list.
+ * [ADDED]: #3013 When double clicking on empty space in list of indexes or tables (in table or view window) the action is not ignored, but a dialog opens for adding new item.
+ * [CHANGE]: DbAndroid plugin has now JAR file embedded and you can get it from Tools menu.
+ * [CHANGE]: SQLite version updated to 3.13.0.
+ * [CHANGE]: Qt version updated to 5.6.0. Should still compile with 5.3, but binary distributions on homepage will be made with 5.6.
+ * [CHANGE]: Foreign key dropdown (when editing FK cell) uses now more readable set of columns and column headers can be resized.
+ * [CHANGE]: Column dialog validates scale and precision fields (against INTEGER PRIMARY KEY and against each other).
+ * [CHANGE]: Structure tab in table window has now fully named headers in column list.
+ * [CHANGE]: Table and View window options moved from Look & Feel configuration page to Data Browsing page.
+ * [CHANGE]: All database list options moved to a separate Database List configuration page.
+ * [CHANGE]: Window list in main menu -> "View" -> "Window list" is not sorted alphabetically.
+ * [BUGFIX]: Not loading Android plugin by default (needs manual load from configuration dialog), which stops the "ADB" error for people not using the plugin.
+ * [BUGFIX]: #2927 Several critical bugs fixed and enhancements to table modification algorithm related to foreign keys.
+ * [BUGFIX]: #2954 #2803 #2937 Fixed incorrect recreation of foreign keys chain.
+ * [BUGFIX]: #3008 Editing foreign key cell with more than 10 000 possible values will now use simple text editor, not dropdown. It also loads values asynchronously.
+ * [BUGFIX]: Fixed importing from CSV with some of lines containing less fields than defined in header (or in first data row).
+ * [BUGFIX]: #2989 Fixed multiline value handling in CSV import plugin.
+ * [BUGFIX]: #2921 Fixed empty values as NULL handling in CSV import plugin.
+ * [BUGFIX]: #3034 Fixed handling empty string as value for DEFAULT constraint.
+ * [BUGFIX]: #3064 Fixed locking database executions when counting rows in huge tables.
+ * [BUGFIX]: DbAndroid plugin has fix for null pointer in the JAR when client has disconnected
+ * [BUGFIX]: Error message details were missing in some cases (when smart execution method failed at parsing stage). This is fixed now.
+ * [BUGFIX]: #3026 #3027 #3043 Fixed RAISE() function formatting in enterprise formatter (used to produce invalid SQL).
+ * [BUGFIX]: #3015 Fixed error with DEFAULT constraint containing datetime('now', 'localtime').
+ * [BUGFIX]: #3000 Fixed compilation errors for Qt >= 5.5.
+ * [BUGFIX]: #2956 Fixed unexpected data refresh when clicking in the right side of value filter field in table window.
+ * [BUGFIX]: #2991 #2928 #2929 #2941 #2960 Fixed executing "garbage" query, causing application crash.
+ * [BUGFIX]: #2920 Fixed removing several databases.
+ * [BUGFIX]: #3068 #3066 Fixed database removal confirmation dialog so the message asks about removing it from the list, not deleting it.
+ * [BUGFIX]: #3073 Fixed crash when unloading plugin with its own configuration subpage and saving config dialog.
+ * [BUGFIX]: #2931 #2962 Fixed incorrect results when executing 2-level queries with an expression and an alias combination as a result column definition.
+ * [BUGFIX]: #2942 Fixed deleting multiple tables/indexes/... when selected them and picked "Delete table/index/..." from context menu.
+ * [BUGFIX]: #2945 Fixed manual reordering of database objects with Drag&Drop.
+ * [BUGFIX]: #3055 Fixed crash when exporting on MacOS using plugin that requires column value length information (such as PDF export plugin).
+ * [BUGFIX]: #3047 Fixed copying/moving tables together with indexes or triggers with Drag&Drop across same SQLite version databases.
+ * [BUGFIX]: #3012 SQL simple formatter plugin does not load by default from now on. It is still available, but won't load until manually loaded.
+ * [BUGFIX]: Table window for new table (just created) will now properly close when that table gets deleted immediately by the user.
+ * [BUGFIX]: #2998 Fixed reading decimal values from database when using simple execution method (a fallback in case of some problems).
+ * [BUGFIX]: #2999 Fixed working on objects from database that on the list is named "main".
+ * [BUGFIX]: Fixed error detection when selecting column from incorrect table alias (http://forum.sqlitestudio.pl/viewtopic.php?f=11&t=1051).
+ * [BUGFIX]: #3046 Fixed scale & precision fields in column dialog so it's possible to delete their values from the column.
+ * [BUGFIX]: Vacuum invoked from context menu on database list is now executed in SQL editor and is asynchronous.
+ * [BUGFIX]: #3001 Order of objects exported by Export Dialog is now alphabetical (in object type groups).
+ * [BUGFIX]: #3022 Fixed parsing of some expressions, resulting in this particular bug report in being unable to browse view results.
+ * [BUGFIX]: Enhanced floating point numbers handling.
+ * [BUGFIX]: Fixed formatting of INSERT and UPDATE statements.
+ * [BUGFIX]: Enterprise formatter no longer puts new lines when formating list of elements in "IN" clause.
+
[3.0.7]
* [ADDED]: #2951 Implemented dropdown value picking for foreign key columns in grid view.
* [ADDED]: Context menu entry to go to row in referenced table by current foreign key cell value.
diff --git a/SQLiteStudio3/coreSQLiteStudio/TODO.txt b/SQLiteStudio3/coreSQLiteStudio/TODO.txt
index 5c0f35c..4faac9d 100644
--- a/SQLiteStudio3/coreSQLiteStudio/TODO.txt
+++ b/SQLiteStudio3/coreSQLiteStudio/TODO.txt
@@ -1,16 +1,11 @@
-Thread 5 Crashed:: Thread (pooled)
-0 libcoreSQLiteStudio.1.0.0.dylib 0x0000000101f24ba7 QHash<QString, QVariant>::value(QString const&) const + 23
-1 libcoreSQLiteStudio.1.0.0.dylib 0x0000000101f24ad4 QHash<QString, QVariant>::operator[](QString const&) const + 36
-2 libcoreSQLiteStudio.1.0.0.dylib 0x0000000101f24936 SqlResultsRow::value(QString const&) const + 54
-3 libcoreSQLiteStudio.1.0.0.dylib 0x0000000101f06c1a SchemaResolver::getAllObjects(QString const&) + 1178
-4 libcoreSQLiteStudio.1.0.0.dylib 0x0000000101f06746 SchemaResolver::getAllObjects() + 70
-5 libguiSQLiteStudio.1.0.0.dylib 0x000000010252f428 SqlEditor::refreshValidObjects()::$_0::operator()() const + 456 (sqleditor.cpp:529)
-6 libguiSQLiteStudio.1.0.0.dylib 0x000000010252f1ec QtConcurrent::StoredFunctorCall0<void, SqlEditor::refreshValidObjects()::$_0>::runFunctor() + 28 (qtconcurrentstoredfunctioncall.h:72)
-7 libguiSQLiteStudio.1.0.0.dylib 0x0000000102534ca1 QtConcurrent::RunFunctionTask<void>::run() + 81 (qtconcurrentrunbase.h:132)
-8 libguiSQLiteStudio.1.0.0.dylib 0x0000000102534dbc non-virtual thunk to QtConcurrent::RunFunctionTask<void>::run() + 28 (qtconcurrentrśunbase.h:141)
+cannot reproduce:
+2922 / 2926 / 2925
+2940
+3009 - db w emailu od goretux@gmail.com
+3052
+3062
-
-* Outstanding features for 3.1:
+* Outstanding features for 3.2:
- migrate updates engine to Qt Install Framework
- loadable extensions full support
- BLOB preview engine based on plugins
@@ -51,6 +46,8 @@ Thread 5 Crashed:: Thread (pooled)
- executing queries with bind parameters
- completer: when suggesting table in FROM clause, look at columns after SELECT to give related tables first.
- constraints tab in table window should have toolbar for adding/editing/deleting constraints
+- add menu mnemonics support (underlined shortcut letters)
+- per column filtering field when clicked on column header(?)
CLI:
- plugin management commands
diff --git a/SQLiteStudio3/coreSQLiteStudio/common/bistrhash.cpp b/SQLiteStudio3/coreSQLiteStudio/common/bistrhash.cpp
new file mode 100644
index 0000000..091121c
--- /dev/null
+++ b/SQLiteStudio3/coreSQLiteStudio/common/bistrhash.cpp
@@ -0,0 +1,213 @@
+#include "bistrhash.h"
+
+BiStrHash::BiStrHash(std::initializer_list<std::pair<QString, QString> > list)
+{
+ hash = QHash<QString,QString>(list);
+ initInvertedAndLower();
+}
+
+BiStrHash::BiStrHash(const QHash<QString, QString>& other)
+{
+ unite(other);
+}
+
+BiStrHash::BiStrHash(const BiStrHash& other) : hash(other.hash), inverted(other.inverted),
+ lowerHash(other.lowerHash), lowerInverted(other.lowerInverted)
+{
+}
+
+void BiStrHash::insert(const QString& left, const QString& right)
+{
+ if (lowerHash.contains(left.toLower()))
+ removeLeft(left, Qt::CaseInsensitive);
+
+ if (lowerInverted.contains(right.toLower()))
+ removeRight(right, Qt::CaseInsensitive);
+
+ inverted.insert(right, left);
+ hash.insert(left, right);
+ lowerHash.insert(left.toLower(), left);
+ lowerInverted.insert(right.toLower(), right);
+}
+
+bool BiStrHash::containsLeft(const QString& left, Qt::CaseSensitivity cs)
+{
+ if (cs == Qt::CaseSensitive)
+ return hash.contains(left);
+ else
+ return lowerHash.contains(left.toLower());
+}
+
+bool BiStrHash::containsRight(const QString& right, Qt::CaseSensitivity cs)
+{
+ if (cs == Qt::CaseSensitive)
+ return inverted.contains(right);
+ else
+ return lowerInverted.contains(right.toLower());
+}
+
+int BiStrHash::removeLeft(const QString& left, Qt::CaseSensitivity cs)
+{
+ if (cs == Qt::CaseSensitive)
+ {
+ if (!hash.contains(left))
+ return 0;
+
+ inverted.remove(hash.value(left));
+ hash.remove(left);
+
+ return 1;
+ }
+ else
+ {
+ QString lowerLeft = left.toLower();
+ if (!lowerHash.contains(lowerLeft))
+ return 0;
+
+ QString right = hash.value(lowerHash.value(lowerLeft));
+
+ hash.remove(inverted.value(right));
+ inverted.remove(right);
+ lowerHash.remove(lowerLeft);
+ lowerInverted.remove(right.toLower());
+
+ return 1;
+ }
+}
+
+int BiStrHash::removeRight(const QString& right, Qt::CaseSensitivity cs)
+{
+ if (cs == Qt::CaseSensitive)
+ {
+ if (!inverted.contains(right))
+ return 0;
+
+ hash.remove(inverted.value(right));
+ inverted.remove(right);
+
+ return 1;
+ }
+ else
+ {
+ QString lowerRight = right.toLower();
+ if (!lowerInverted.contains(lowerRight))
+ return 0;
+
+ QString left = inverted.value(lowerInverted.value(lowerRight));
+
+ inverted.remove(hash.value(left));
+ hash.remove(left);
+ lowerHash.remove(left.toLower());
+ lowerInverted.remove(lowerRight);
+
+ return 1;
+ }
+}
+
+QString BiStrHash::takeLeft(const QString& left, Qt::CaseSensitivity cs)
+{
+ if (cs == Qt::CaseSensitive)
+ {
+ QString right = hash.take(left);
+ inverted.remove(right);
+ return right;
+ }
+ else
+ {
+ QString right = hash.take(lowerHash.take(left.toLower()));
+ inverted.remove(lowerInverted.take(right.toLower()));
+ return right;
+ }
+}
+
+QString BiStrHash::takeRight(const QString& right, Qt::CaseSensitivity cs)
+{
+ if (cs == Qt::CaseSensitive)
+ {
+ QString left = inverted.take(right);
+ hash.remove(left);
+ return left;
+ }
+ else
+ {
+ QString left = inverted.take(lowerInverted.take(right.toLower()));
+ hash.remove(lowerHash.take(left.toLower()));
+ return left;
+ }
+}
+
+BiStrHash& BiStrHash::unite(const BiStrHash& other)
+{
+ unite(other.hash);
+ return *this;
+}
+
+BiStrHash& BiStrHash::unite(const QHash<QString, QString>& other)
+{
+ QHashIterator<QString, QString> it(other);
+ while (it.hasNext())
+ insert(it.next().key(), it.value());
+
+ return *this;
+}
+
+QString BiStrHash::valueByLeft(const QString& left, Qt::CaseSensitivity cs) const
+{
+ if (cs == Qt::CaseSensitive)
+ return hash.value(left);
+ else
+ return hash.value(lowerHash.value(left.toLower()));
+}
+
+QString BiStrHash::valueByRight(const QString& right, Qt::CaseSensitivity cs) const
+{
+ if (cs == Qt::CaseSensitive)
+ return inverted.value(right);
+ else
+ return inverted.value(lowerInverted.value(right.toLower()));
+}
+
+QStringList BiStrHash::leftValues() const
+{
+ return hash.keys();
+}
+
+QStringList BiStrHash::rightValues() const
+{
+ return inverted.keys();
+}
+
+QHashIterator<QString, QString> BiStrHash::iterator() const
+{
+ return QHashIterator<QString,QString>(hash);
+}
+
+void BiStrHash::clear()
+{
+ hash.clear();
+ inverted.clear();
+ lowerHash.clear();
+ lowerInverted.clear();
+}
+
+int BiStrHash::count() const
+{
+ return hash.count();
+}
+
+bool BiStrHash::isEmpty() const
+{
+ return hash.isEmpty();
+}
+
+void BiStrHash::initInvertedAndLower()
+{
+ QHashIterator<QString,QString> it(hash);
+ while (it.hasNext())
+ {
+ it.next();
+ inverted[it.value()] = it.key();
+ lowerHash[it.key().toLower()] = it.key();
+ lowerInverted[it.value().toLower()] = it.value();
+ }
+}
diff --git a/SQLiteStudio3/coreSQLiteStudio/common/bistrhash.h b/SQLiteStudio3/coreSQLiteStudio/common/bistrhash.h
index 65c907b..2089010 100644
--- a/SQLiteStudio3/coreSQLiteStudio/common/bistrhash.h
+++ b/SQLiteStudio3/coreSQLiteStudio/common/bistrhash.h
@@ -2,6 +2,7 @@
#define BISTRHASH_H
#include "bihash.h"
+#include "coreSQLiteStudio_global.h"
#include <QHash>
#include <QString>
@@ -14,7 +15,7 @@
*
* Just like BiHash, the BiStrHash doesn't provide operator[]. For more details see BiHash.
*/
-class BiStrHash
+class API_EXPORT BiStrHash
{
public:
/**
@@ -26,11 +27,7 @@ class BiStrHash
* @brief Creates pre-initialized hash.
* @param list C++11 style initializer list, like: <tt>{{"x"="y"}, {"a"="b"}}</tt>
*/
- BiStrHash(std::initializer_list<std::pair<QString, QString>> list)
- {
- hash = QHash<QString,QString>(list);
- initInvertedAndLower();
- }
+ BiStrHash(std::initializer_list<std::pair<QString, QString>> list);
/**
* @brief Creates BiStrHash basing on QHash.
@@ -39,17 +36,13 @@ class BiStrHash
* Any conflicting values from the \p other hash will overwrite
* current values in the hash.
*/
- BiStrHash(const QHash<QString, QString> & other)
- {
- unite(other);
- }
+ BiStrHash(const QHash<QString, QString> & other);
/**
* @brief Copy constructor.
* @param other Other hash to copy.
*/
- BiStrHash(const BiStrHash& other) : hash(other.hash), inverted(other.inverted),
- lowerHash(other.lowerHash), lowerInverted(other.lowerInverted) {}
+ BiStrHash(const BiStrHash& other);
/**
* @brief Inserts entry into the hash.
@@ -59,19 +52,7 @@ class BiStrHash
* Inserting to the hash is done in case-insensitive manner, hence any conflicting
* values matched with case insensitive method will be replaced with the new entry.
*/
- void insert(const QString& left, const QString& right)
- {
- if (lowerHash.contains(left.toLower()))
- removeLeft(left, Qt::CaseInsensitive);
-
- if (lowerInverted.contains(right.toLower()))
- removeRight(right, Qt::CaseInsensitive);
-
- inverted.insert(right, left);
- hash.insert(left, right);
- lowerHash.insert(left.toLower(), left);
- lowerInverted.insert(right.toLower(), right);
- }
+ void insert(const QString& left, const QString& right);
/**
* @brief Tests if given value is in the left values of the hash.
@@ -79,13 +60,7 @@ class BiStrHash
* @param cs Case sensitivity flag.
* @return true if the key was matched in left side values, or false otherwise.
*/
- bool containsLeft(const QString& left, Qt::CaseSensitivity cs = Qt::CaseSensitive)
- {
- if (cs == Qt::CaseSensitive)
- return hash.contains(left);
- else
- return lowerHash.contains(left.toLower());
- }
+ bool containsLeft(const QString& left, Qt::CaseSensitivity cs = Qt::CaseSensitive);
/**
* @brief Tests if given value is in the right values of the hash.
@@ -93,13 +68,7 @@ class BiStrHash
* @param cs Case sensitivity flag.
* @return true if the key was matched in right side values, or false otherwise.
*/
- bool containsRight(const QString& right, Qt::CaseSensitivity cs = Qt::CaseSensitive)
- {
- if (cs == Qt::CaseSensitive)
- return inverted.contains(right);
- else
- return lowerInverted.contains(right.toLower());
- }
+ bool containsRight(const QString& right, Qt::CaseSensitivity cs = Qt::CaseSensitive);
/**
* @brief Removes entry matching given value in left-side values.
@@ -107,34 +76,7 @@ class BiStrHash
* @param cs Case sensitivity flag.
* @return Number of entries removed.
*/
- int removeLeft(const QString& left, Qt::CaseSensitivity cs = Qt::CaseSensitive)
- {
- if (cs == Qt::CaseSensitive)
- {
- if (!hash.contains(left))
- return 0;
-
- inverted.remove(hash.value(left));
- hash.remove(left);
-
- return 1;
- }
- else
- {
- QString lowerLeft = left.toLower();
- if (!lowerHash.contains(lowerLeft))
- return 0;
-
- QString right = hash.value(lowerHash.value(lowerLeft));
-
- hash.remove(inverted.value(right));
- inverted.remove(right);
- lowerHash.remove(lowerLeft);
- lowerInverted.remove(right.toLower());
-
- return 1;
- }
- }
+ int removeLeft(const QString& left, Qt::CaseSensitivity cs = Qt::CaseSensitive);
/**
* @brief Removes entry matching given value in right-side values.
@@ -142,34 +84,7 @@ class BiStrHash
* @param cs Case sensitivity flag.
* @return Number of entries removed.
*/
- int removeRight(const QString& right, Qt::CaseSensitivity cs = Qt::CaseSensitive)
- {
- if (cs == Qt::CaseSensitive)
- {
- if (!inverted.contains(right))
- return 0;
-
- hash.remove(inverted.value(right));
- inverted.remove(right);
-
- return 1;
- }
- else
- {
- QString lowerRight = right.toLower();
- if (!lowerInverted.contains(lowerRight))
- return 0;
-
- QString left = inverted.value(lowerInverted.value(lowerRight));
-
- inverted.remove(hash.value(left));
- hash.remove(left);
- lowerHash.remove(left.toLower());
- lowerInverted.remove(lowerRight);
-
- return 1;
- }
- }
+ int removeRight(const QString& right, Qt::CaseSensitivity cs = Qt::CaseSensitive);
/**
* @brief Removes entry from hash and returns it.
@@ -177,21 +92,7 @@ class BiStrHash
* @param cs Case sensitivity flag.
* @return Right side value, or null string if the \p left was not matched.
*/
- QString takeLeft(const QString& left, Qt::CaseSensitivity cs = Qt::CaseSensitive)
- {
- if (cs == Qt::CaseSensitive)
- {
- QString right = hash.take(left);
- inverted.remove(right);
- return right;
- }
- else
- {
- QString right = hash.take(lowerHash.take(left.toLower()));
- inverted.remove(lowerInverted.take(right.toLower()));
- return right;
- }
- }
+ QString takeLeft(const QString& left, Qt::CaseSensitivity cs = Qt::CaseSensitive);
/**
* @brief Removes entry from hash and returns it.
@@ -199,44 +100,19 @@ class BiStrHash
* @param cs Case sensitivity flag.
* @return Left side value, or null string if the \p left was not matched.
*/
- QString takeRight(const QString& right, Qt::CaseSensitivity cs = Qt::CaseSensitive)
- {
- if (cs == Qt::CaseSensitive)
- {
- QString left = inverted.take(right);
- hash.remove(left);
- return left;
- }
- else
- {
- QString left = inverted.take(lowerInverted.take(right.toLower()));
- hash.remove(lowerHash.take(left.toLower()));
- return left;
- }
- }
+ QString takeRight(const QString& right, Qt::CaseSensitivity cs = Qt::CaseSensitive);
/**
* @brief Copies all entries from the other hash to this hash.
* @param other Other hash to copy values from.
* @return Reference to this hash, after update.
*/
- BiStrHash& unite(const BiStrHash& other)
- {
- unite(other.hash);
- return *this;
- }
+ BiStrHash& unite(const BiStrHash& other);
/**
* @overload
*/
- BiStrHash& unite(const QHash<QString,QString>& other)
- {
- QHashIterator<QString, QString> it(other);
- while (it.hasNext())
- insert(it.next().key(), it.value());
-
- return *this;
- }
+ BiStrHash& unite(const QHash<QString,QString>& other);
/**
* @brief Finds right-side value by matching the left-side value.
@@ -244,13 +120,7 @@ class BiStrHash
* @param cs Case sensitivity flag.
* @return Right-side value, or null string if left-side value was not matched.
*/
- QString valueByLeft(const QString& left, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
- {
- if (cs == Qt::CaseSensitive)
- return hash.value(left);
- else
- return hash.value(lowerHash.value(left.toLower()));
- }
+ QString valueByLeft(const QString& left, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
/**
* @brief Finds left-side value by matching the right-side value.
@@ -258,85 +128,48 @@ class BiStrHash
* @param cs Case sensitivity flag.
* @return Left-side value, or null string if right-side value was not matched.
*/
- QString valueByRight(const QString& right, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
- {
- if (cs == Qt::CaseSensitive)
- return inverted.value(right);
- else
- return inverted.value(lowerInverted.value(right.toLower()));
- }
+ QString valueByRight(const QString& right, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
/**
* @brief Gives all left-side values.
* @return List of values.
*/
- QStringList leftValues() const
- {
- return hash.keys();
- }
+ QStringList leftValues() const;
/**
* @brief Gives all right-side values.
* @return List of values.
*/
- QStringList rightValues() const
- {
- return inverted.keys();
- }
+ QStringList rightValues() const;
/**
* @brief Provides java-style iterator for this hash.
* @return Iterator object.
*/
- QHashIterator<QString,QString> iterator() const
- {
- return QHashIterator<QString,QString>(hash);
- }
+ QHashIterator<QString,QString> iterator() const;
/**
* @brief Removes all entries from the hash.
*/
- void clear()
- {
- hash.clear();
- inverted.clear();
- lowerHash.clear();
- lowerInverted.clear();
- }
+ void clear();
/**
* @brief Counts all entries in the hash.
* @return Number of entries in the hash.
*/
- int count() const
- {
- return hash.count();
- }
+ int count() const;
/**
* @brief Tests whether the hash is empty or not.
* @return true if the hash is empty, false otherwise.
*/
- bool isEmpty() const
- {
- return hash.isEmpty();
- }
+ bool isEmpty() const;
private:
/**
* @brief Fills inverted and lower internal hashes basing on the main hash class member.
*/
- void initInvertedAndLower()
- {
- QHashIterator<QString,QString> it(hash);
- while (it.hasNext())
- {
- it.next();
- inverted[it.value()] = it.key();
- lowerHash[it.key().toLower()] = it.key();
- lowerInverted[it.value().toLower()] = it.value();
- }
- }
+ void initInvertedAndLower();
/**
* @brief Standard mapping - left to right.
diff --git a/SQLiteStudio3/coreSQLiteStudio/common/sortedset.h b/SQLiteStudio3/coreSQLiteStudio/common/sortedset.h
new file mode 100644
index 0000000..266e409
--- /dev/null
+++ b/SQLiteStudio3/coreSQLiteStudio/common/sortedset.h
@@ -0,0 +1,64 @@
+#ifndef SORTEDSET_H
+#define SORTEDSET_H
+
+#include "common/sortedhash.h"
+
+template <class T>
+class SortedSet : private SortedHash<T, bool>
+{
+ public:
+ bool contains(const T &value) const
+ {
+ return QHash<T, bool>::containsKey(value);
+ }
+
+ int count() const
+ {
+ return size();
+ }
+
+ bool isEmpty() const
+ {
+ return SortedHash<T, bool>::isEmpty();
+ }
+
+ bool remove(const T& value)
+ {
+ return SortedHash<T, bool>::remove(value);
+ }
+
+ int size() const
+ {
+ return QHash<T, bool>::size();
+ }
+
+ void swap(SortedSet<T>& other)
+ {
+ return SortedHash<T, bool>::swap(other);
+ }
+
+ SortedSet<T>& operator+=(const T& value)
+ {
+ SortedHash<T, bool>::insert(value, true);
+ return *this;
+ }
+
+ SortedSet<T>& operator-=(const T& value)
+ {
+ SortedHash<T, bool>::remove(value);
+ return *this;
+ }
+
+ QSet<T>& operator<<(const T &value)
+ {
+ SortedHash<T, bool>::insert(value, true);
+ return *this;
+ }
+
+ QList<T> toList()
+ {
+ return SortedHash<T, bool>::keys();
+ }
+};
+
+#endif // SORTEDSET_H
diff --git a/SQLiteStudio3/coreSQLiteStudio/common/strhash.h b/SQLiteStudio3/coreSQLiteStudio/common/strhash.h
index 4fb7bb3..41b3d11 100644
--- a/SQLiteStudio3/coreSQLiteStudio/common/strhash.h
+++ b/SQLiteStudio3/coreSQLiteStudio/common/strhash.h
@@ -11,12 +11,12 @@ class StrHash
{
public:
StrHash() {}
- StrHash(std::initializer_list<std::pair<QString,T>> list) : hash(QHash<QString,T>(list))
+ StrHash(std::initializer_list<std::pair<QString, T>> list) : hash(QHash<QString, T>(list))
{
initLower();
}
- StrHash(const QHash<QString,T>& other) : hash(QHash<QString,T>(other))
+ StrHash(const QHash<QString, T>& other) : hash(QHash<QString, T>(other))
{
initLower();
}
@@ -87,9 +87,9 @@ class StrHash
return *this;
}
- StrHash<T>& unite(const QHash<QString,T>& other)
+ StrHash<T>& unite(const QHash<QString, T>& other)
{
- QHashIterator<QString,T> it(other);
+ QHashIterator<QString, T> it(other);
while (it.hasNext())
{
it.next();
@@ -117,9 +117,9 @@ class StrHash
return hash.keys();
}
- QHashIterator<QString,T> iterator() const
+ QHashIterator<QString, T> iterator() const
{
- return QHashIterator<QString,T>(hash);
+ return QHashIterator<QString, T>(hash);
}
void clear()
@@ -146,6 +146,11 @@ class StrHash
return hash.isEmpty();
}
+ QHash<QString, T> toQHash() const
+ {
+ return hash;
+ }
+
T& operator[](const QString& key)
{
if (lowerCaseHash.contains(key.toLower()) && !hash.contains(key))
@@ -167,7 +172,7 @@ class StrHash
private:
void initLower()
{
- QHashIterator<QString,T> it(hash);
+ QHashIterator<QString, T> it(hash);
while (it.hasNext())
{
it.next();
@@ -175,8 +180,8 @@ class StrHash
}
}
- QHash<QString,QString> lowerCaseHash;
- QHash<QString,T> hash;
+ QHash<QString, QString> lowerCaseHash;
+ QHash<QString, T> hash;
};
#endif // STRHASH_H
diff --git a/SQLiteStudio3/coreSQLiteStudio/common/utils.cpp b/SQLiteStudio3/coreSQLiteStudio/common/utils.cpp
index f2b3d1c..6cf1892 100644
--- a/SQLiteStudio3/coreSQLiteStudio/common/utils.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/common/utils.cpp
@@ -11,6 +11,8 @@
#include <QDebug>
#include <QRegularExpression>
#include <QDir>
+#include <QByteArray>
+#include <QDataStream>
#ifdef Q_OS_LINUX
#include <sys/utsname.h>
@@ -214,12 +216,12 @@ qint64 Range::length() const
return to - from + 1;
}
-QString generateUniqueName(const QString &baseName, const QStringList &existingNames)
+QString generateUniqueName(const QString& baseName, const QStringList& existingNames, Qt::CaseSensitivity cs)
{
QString name = baseName;
int i = 0;
- while (existingNames.contains(name))
- name = baseName+QString::number(i++);
+ while (existingNames.contains(name, cs))
+ name = baseName + QString::number(i++);
return name;
}
@@ -887,3 +889,38 @@ QString decryptRsa(const QString& input, const QString& modulus, const QString&
std::string result = RSA::Decrypt(inputStdStr, key);
return QString::fromStdString(result);
}
+
+QStringList concat(const QList<QStringList>& list)
+{
+ QStringList result;
+ for (const QStringList& item : list)
+ result.append(item);
+
+ return result;
+}
+
+QString doubleToString(double val)
+{
+ return QString::number(val, 'g', 16);
+}
+
+void sortWithReferenceList(QList<QString>& listToSort, const QList<QString>& referenceList, Qt::CaseSensitivity cs)
+{
+ qSort(listToSort.begin(), listToSort.end(), [referenceList, cs](const QString& s1, const QString& s2) -> bool
+ {
+ int idx1 = indexOf(referenceList, s1, cs);
+ int idx2 = indexOf(referenceList, s2, cs);
+ if (idx1 == -1 || idx2 == -1)
+ {
+ if (idx1 == -1 && idx2 == -1)
+ return false;
+
+ return (idx1 == -1);
+ }
+
+ if (idx1 == idx2)
+ return false;
+
+ return (idx1 > idx2);
+ });
+}
diff --git a/SQLiteStudio3/coreSQLiteStudio/common/utils.h b/SQLiteStudio3/coreSQLiteStudio/common/utils.h
index 90d2d62..934e70a 100644
--- a/SQLiteStudio3/coreSQLiteStudio/common/utils.h
+++ b/SQLiteStudio3/coreSQLiteStudio/common/utils.h
@@ -57,7 +57,7 @@ API_EXPORT QString randStr(int length, bool numChars = true, bool whiteSpaces =
API_EXPORT QString randStr(int length, const QString& charCollection);
API_EXPORT QString randBinStr(int length);
API_EXPORT QString randStrNotIn(int length, const QSet<QString> set, bool numChars = true, bool whiteSpaces = false);
-API_EXPORT QString generateUniqueName(const QString& prefix, const QStringList& existingNames);
+API_EXPORT QString generateUniqueName(const QString& prefix, const QStringList& existingNames, Qt::CaseSensitivity cs = Qt::CaseSensitive);
API_EXPORT bool isNumeric(const QVariant& value);
API_EXPORT QString rStrip(const QString& str);
API_EXPORT QStringList tokenizeArgs(const QString& str);
@@ -73,6 +73,20 @@ API_EXPORT QHash<QString,QVariant> bytesToHash(const QByteArray& bytes);
API_EXPORT int indexOf(const QStringList& list, const QString& value, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive);
API_EXPORT int indexOf(const QStringList& list, const QString& value, Qt::CaseSensitivity cs = Qt::CaseSensitive);
+template <class T>
+int indexOf(const QList<T>& list, std::function<bool(const T&)> predicate)
+{
+ int i = 0;
+ for (const T& item : list)
+ {
+ if (predicate(item))
+ return i;
+
+ ++i;
+ }
+ return -1;
+}
+
/**
* @brief Returns only those elements from the list, which passed the filter.
* @tparam T type for which the filter will be applied for. It should match the type in the list and in the function argument.
@@ -103,6 +117,18 @@ bool contains(const QList<T>& list, std::function<bool(const T& value)> testFunc
return false;
}
+template <class T>
+QList<T> concat(const QList<QList<T>>& list)
+{
+ QList<T> result;
+ for (const QList<T>& item : list)
+ result.append(item);
+
+ return result;
+}
+
+API_EXPORT QStringList concat(const QList<QStringList>& list);
+
/**
* @brief Appends or prepends characters to the string to make it of specified length.
* @param str Input string to work with.
@@ -205,6 +231,18 @@ API_EXPORT bool renameBetweenPartitions(const QString& src, const QString& dst);
API_EXPORT bool isWritableRecursively(const QString& dir);
API_EXPORT QString encryptRsa(const QString& input, const QString& modulus, const QString& exponent);
API_EXPORT QString decryptRsa(const QString& input, const QString& modulus, const QString& exponent);
+API_EXPORT QString doubleToString(double val);
+
+/**
+ * @brief Sorts string list using reference list for ordering.
+ * @param listToSort This list will be sorted.
+ * @param referenceList Should contain all elements from list to sort - it tells the order.
+ * @param cs Case sensitivity of the string comparision.
+ *
+ * Sorts \p listToSort using \p referenceList as a reference of what is the order.
+ * If any element from \p listToSort is not on the list of \p referenceList, then the element will be placed at the end.
+ */
+API_EXPORT void sortWithReferenceList(QList<QString>& listToSort, const QList<QString>& referenceList, Qt::CaseSensitivity cs = Qt::CaseSensitive);
enum class DistributionType
{
diff --git a/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.cpp b/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.cpp
index eba10fa..5c7e7e9 100644
--- a/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.cpp
@@ -77,6 +77,16 @@ QString wrapObjIfNeeded(const QString& obj, Dialect dialect, NameWrapper favWrap
return obj;
}
+QString wrapObjIfNeeded(const QString& obj, Dialect dialect, bool useDoubleQuoteForEmptyValue, NameWrapper favWrapper)
+{
+ return wrapObjIfNeeded(obj, dialect, ((useDoubleQuoteForEmptyValue && obj.isEmpty()) ? NameWrapper::DOUBLE_QUOTE : favWrapper));
+}
+
+QString wrapObjName(const QString& obj, Dialect dialect, bool useDoubleQuoteForEmptyValue, NameWrapper favWrapper)
+{
+ return wrapObjName(obj, dialect, ((useDoubleQuoteForEmptyValue && obj.isEmpty()) ? NameWrapper::DOUBLE_QUOTE : favWrapper));
+}
+
QString wrapObjName(const QString& obj, Dialect dialect, NameWrapper favWrapper)
{
QString result = obj;
@@ -573,6 +583,8 @@ QueryAccessMode getQueryAccessMode(const QString& query, Dialect dialect, bool*
TokenList tokens = Lexer::tokenize(query, dialect);
int keywordIdx = tokens.indexOf(Token::KEYWORD);
+ if (keywordIdx < 0)
+ return QueryAccessMode::WRITE;
int cmdIdx = readOnlyCommands.indexOf(tokens[keywordIdx]->value.toUpper());
if (keywordIdx > -1 && cmdIdx > -1)
@@ -632,3 +644,53 @@ QueryAccessMode getQueryAccessMode(const QString& query, Dialect dialect, bool*
return QueryAccessMode::WRITE;
}
+
+QStringList valueListToSqlList(const QVariantList& values, Dialect dialect)
+{
+ QStringList argList;
+ for (const QVariant& value : values)
+ {
+ if (!value.isValid() || value.isNull())
+ {
+ argList << "NULL";
+ continue;
+ }
+
+ switch (value.userType())
+ {
+ case QVariant::Int:
+ case QVariant::UInt:
+ case QVariant::LongLong:
+ case QVariant::ULongLong:
+ argList << value.toString();
+ break;
+ case QVariant::Double:
+ argList << doubleToString(value.toDouble());
+ break;
+ case QVariant::Bool:
+ argList << QString::number(value.toInt());
+ break;
+ case QVariant::ByteArray:
+ {
+ if (dialect == Dialect::Sqlite3) // version 2 will go to the regular string processing
+ {
+ argList << "X'" + value.toByteArray().toHex().toUpper() + "'";
+ break;
+ }
+ }
+ default:
+ argList << wrapString(escapeString(value.toString()));
+ break;
+ }
+ }
+ return argList;
+}
+
+QStringList wrapStrings(const QStringList& strList)
+{
+ QStringList list;
+ for (const QString& str : strList)
+ list << wrapString(str);
+
+ return list;
+}
diff --git a/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.h b/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.h
index 038c146..ceccea0 100644
--- a/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.h
+++ b/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.h
@@ -36,7 +36,9 @@ API_EXPORT bool isObjectWrapped(const QChar& c);
API_EXPORT bool doesStringNeedWrapping(const QString& str);
API_EXPORT bool isStringWrapped(const QString& str);
API_EXPORT QString wrapObjIfNeeded(const QString& obj, Dialect dialect, NameWrapper favWrapper = NameWrapper::null);
+API_EXPORT QString wrapObjIfNeeded(const QString& obj, Dialect dialect, bool useDoubleQuoteForEmptyValue, NameWrapper favWrapper = NameWrapper::null);
API_EXPORT QString wrapObjName(const QString& obj, Dialect dialect, NameWrapper favWrapper = NameWrapper::null);
+API_EXPORT QString wrapObjName(const QString& obj, Dialect dialect, bool useDoubleQuoteForEmptyValue, NameWrapper favWrapper = NameWrapper::null);
API_EXPORT QString wrapObjName(const QString& obj, NameWrapper wrapper);
API_EXPORT TokenPtr stripObjName(TokenPtr token, Dialect dialect);
API_EXPORT QString stripObjName(const QString &str, Dialect dialect);
@@ -45,6 +47,7 @@ API_EXPORT bool isObjWrapped(const QString& str, Dialect dialect);
API_EXPORT NameWrapper getObjWrapper(const QString& str, Dialect dialect);
API_EXPORT bool isWrapperChar(const QChar& c, Dialect dialect);
API_EXPORT QString wrapString(const QString& str);
+API_EXPORT QStringList wrapStrings(const QStringList& strList);
API_EXPORT QString wrapStringIfNeeded(const QString& str);
API_EXPORT QString escapeString(QString &str);
API_EXPORT QString escapeString(const QString& str);
@@ -75,6 +78,7 @@ API_EXPORT QString trimBindParamPrefix(const QString& param);
API_EXPORT QString commentAllSqlLines(const QString& sql);
API_EXPORT QString getBindTokenName(const TokenPtr& token);
API_EXPORT QueryAccessMode getQueryAccessMode(const QString& query, Dialect dialect, bool* isSelect = nullptr);
+API_EXPORT QStringList valueListToSqlList(const QList<QVariant>& values, Dialect dialect);
#endif // UTILS_SQL_H
diff --git a/SQLiteStudio3/coreSQLiteStudio/coreSQLiteStudio.pro b/SQLiteStudio3/coreSQLiteStudio/coreSQLiteStudio.pro
index 886678d..59da902 100644
--- a/SQLiteStudio3/coreSQLiteStudio/coreSQLiteStudio.pro
+++ b/SQLiteStudio3/coreSQLiteStudio/coreSQLiteStudio.pro
@@ -221,7 +221,9 @@ SOURCES += sqlitestudio.cpp \
common/signalwait.cpp \
common/blockingsocket.cpp \
common/threadwitheventloop.cpp \
- common/private/blockingsocketprivate.cpp
+ common/private/blockingsocketprivate.cpp \
+ querygenerator.cpp \
+ common/bistrhash.cpp
HEADERS += sqlitestudio.h\
coreSQLiteStudio_global.h \
@@ -413,7 +415,11 @@ HEADERS += sqlitestudio.h\
common/blockingsocket.h \
common/threadwitheventloop.h \
common/private/blockingsocketprivate.h \
- common/expiringcache.h
+ common/expiringcache.h \
+ parser/ast/sqliteddlwithdbcontext.h \
+ parser/ast/sqliteextendedindexedcolumn.h \
+ querygenerator.h \
+ common/sortedset.h
unix: {
target.path = $$LIBDIR
diff --git a/SQLiteStudio3/coreSQLiteStudio/csvserializer.cpp b/SQLiteStudio3/coreSQLiteStudio/csvserializer.cpp
index c89074f..15bf4e8 100644
--- a/SQLiteStudio3/coreSQLiteStudio/csvserializer.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/csvserializer.cpp
@@ -3,103 +3,85 @@
// TODO write unit tests for CsvSerializer
-QString CsvSerializer::serialize(const QList<QStringList>& data, const CsvFormat& format)
-{
- QStringList outputRows;
-
- foreach (const QStringList& dataRow, data)
- outputRows << serialize(dataRow, format);
-
- return outputRows.join(format.rowSeparator);
-}
-
-QString CsvSerializer::serialize(const QStringList& data, const CsvFormat& format)
-{
- QString value;
- bool hasQuote;
- QStringList outputCells;
- foreach (const QString& rowValue, data)
- {
- value = rowValue;
-
- hasQuote = value.contains("\"");
- if (hasQuote)
- value.replace("\"", "\"\"");
-
- if (hasQuote || value.contains(format.columnSeparator) || value.contains(format.rowSeparator))
- value = "\""+value+"\"";
-
- outputCells << value;
- }
-
- return outputCells.join(format.columnSeparator);
-}
-
-template <class T>
-bool isCsvColumnSeparator(const T& data, int pos, const CsvFormat& format)
+template <class C>
+bool isCsvColumnSeparator(QTextStream& data, const C& theChar, const CsvFormat& format)
{
- if (!format.strictColumnSeparator && format.columnSeparator.contains(data[pos]))
- return true;
+ if (!format.strictColumnSeparator)
+ return format.columnSeparator.contains(theChar);
+ // Strict checking (characters in defined order make a separator)
+ qint64 origPos = data.pos();
+ data.seek(origPos - 1);
+ C nextChar;
for (const QChar& c : format.columnSeparator)
{
- if (c != data[pos++])
+ data >> nextChar;
+ if (c != nextChar)
+ {
+ data.seek(origPos);
return false;
+ }
}
return true;
}
-template <class T>
-bool isCsvRowSeparator(const T& data, int& pos, const CsvFormat& format)
+template <class C>
+bool isCsvRowSeparator(QTextStream& data, const C& theChar, const CsvFormat& format)
{
- if (!format.strictRowSeparator && format.rowSeparator.contains(data[pos]))
- return true;
+ if (!format.strictRowSeparator)
+ return format.rowSeparator.contains(theChar);
- int localPos = pos;
+ // Strict checking (characters in defined order make a separator)
+ qint64 origPos = data.pos();
+ data.seek(origPos - 1);
+ C nextChar;
for (const QChar& c : format.rowSeparator)
{
- if (localPos >= data.size() || c != data[localPos++])
+ data >> nextChar;
+ if (data.atEnd() || c != nextChar)
+ {
+ data.seek(origPos);
return false;
+ }
}
- pos = localPos - 1;
return true;
}
-template <class T>
-QList<QList<T>> typedDeserialize(const T& data, const CsvFormat& format)
+template <class T, class C>
+QList<QList<T>> typedDeserialize(QTextStream& data, const CsvFormat& format, bool oneEntry)
{
QList<QList<T>> rows;
QList<T> cells;
- int pos = 0;
- int lgt = data.length();
bool quotes = false;
bool sepAsLast = false;
T field = "";
- QChar c;
+ C c0;
+ C c1;
- while (pos < lgt)
+ while (!data.atEnd())
{
- c = data[pos];
+ data >> c0;
sepAsLast = false;
- if (!quotes && c == '"' )
+ if (!quotes && c0 == '"' )
{
quotes = true;
}
- else if (quotes && c == '"' )
+ else if (quotes && c0 == '"' )
{
- if (pos + 1 < data.length())
+ if (!data.atEnd())
{
- if (data[pos+1] == '"' )
+ data >> c1;
+ if (c1 == '"' )
{
- field += c;
- pos++;
+ field += c0;
}
else
{
quotes = false;
+ data.seek(data.pos() - 1);
}
}
else
@@ -110,24 +92,32 @@ QList<QList<T>> typedDeserialize(const T& data, const CsvFormat& format)
quotes = false;
}
}
- else if (!quotes && isCsvColumnSeparator(data, pos, format))
+ else if (!quotes)
{
- cells << field;
- field.clear();
- sepAsLast = true;
- }
- else if (!quotes && isCsvRowSeparator(data, pos, format))
- {
- cells << field;
- rows << cells;
- cells.clear();
- field.clear();
+ if (isCsvColumnSeparator(data, c0, format))
+ {
+ cells << field;
+ field = "";
+ sepAsLast = true;
+ }
+ else if (isCsvRowSeparator(data, c0, format))
+ {
+ cells << field;
+ rows << cells;
+ cells.clear();
+ field = "";
+ if (oneEntry)
+ break;
+ }
+ else
+ {
+ field += c0;
+ }
}
else
{
- field += c;
+ field += c0;
}
- pos++;
}
if (field.size() > 0 || sepAsLast)
@@ -139,14 +129,61 @@ QList<QList<T>> typedDeserialize(const T& data, const CsvFormat& format)
return rows;
}
-QList<QList<QByteArray> > CsvSerializer::deserialize(const QByteArray& data, const CsvFormat& format)
+QString CsvSerializer::serialize(const QList<QStringList>& data, const CsvFormat& format)
{
- return typedDeserialize<QByteArray>(data, format);
+ QStringList outputRows;
+
+ foreach (const QStringList& dataRow, data)
+ outputRows << serialize(dataRow, format);
+
+ return outputRows.join(format.rowSeparator);
}
-QList<QStringList> CsvSerializer::deserialize(const QString& data, const CsvFormat& format)
+QString CsvSerializer::serialize(const QStringList& data, const CsvFormat& format)
+{
+ QString value;
+ bool hasQuote;
+ QStringList outputCells;
+ foreach (const QString& rowValue, data)
+ {
+ value = rowValue;
+
+ hasQuote = value.contains("\"");
+ if (hasQuote)
+ value.replace("\"", "\"\"");
+
+ if (hasQuote || value.contains(format.columnSeparator) || value.contains(format.rowSeparator))
+ value = "\""+value+"\"";
+
+ outputCells << value;
+ }
+
+ return outputCells.join(format.columnSeparator);
+}
+
+QStringList CsvSerializer::deserializeOneEntry(QTextStream& data, const CsvFormat& format)
+{
+ QList<QStringList> deserialized = CsvSerializer::deserialize(data, format, true);
+ if (deserialized.size() > 0)
+ return deserialized.first();
+
+ return QStringList();
+}
+
+QList<QStringList> CsvSerializer::deserialize(QTextStream& data, const CsvFormat& format)
+{
+ return CsvSerializer::deserialize(data, format, false);
+}
+
+QList<QList<QByteArray>> CsvSerializer::deserialize(const QByteArray& data, const CsvFormat& format)
{
- QList<QList<QString>> deserialized = typedDeserialize<QString>(data, format);
+ QTextStream stream(data, QIODevice::ReadWrite);
+ return typedDeserialize<QByteArray,char>(stream, format, false);
+}
+
+QList<QStringList> CsvSerializer::deserialize(QTextStream& data, const CsvFormat& format, bool oneEntry)
+{
+ QList<QList<QString>> deserialized = typedDeserialize<QString, QChar>(data, format, oneEntry);
QList<QStringList> finalList;
for (const QList<QString>& resPart : deserialized)
@@ -155,64 +192,10 @@ QList<QStringList> CsvSerializer::deserialize(const QString& data, const CsvForm
return finalList;
}
+QList<QStringList> CsvSerializer::deserialize(const QString& data, const CsvFormat& format)
+{
+ QString dataString = data;
+ QTextStream stream(&dataString, QIODevice::ReadWrite);
+ return deserialize(stream, format, false);
+}
-//QList<QStringList> CsvSerializer::deserialize(const QByteArray& data, const CsvFormat& format)
-//{
-// QList<QStringList> rows;
-// QStringList cells;
-
-// int pos = 0;
-// int lgt = data.length();
-// bool quotes = false;
-// bool sepAsLast = false;
-// QString field = "";
-// QChar c;
-
-// while (pos < lgt)
-// {
-// c = data[pos];
-// sepAsLast = false;
-// if (!quotes && c == '"' )
-// {
-// quotes = true;
-// }
-// else if (quotes && c == '"' )
-// {
-// if (pos + 1 < data.length() && data[pos+1] == '"' )
-// {
-// field += c;
-// pos++;
-// }
-// else
-// {
-// quotes = false;
-// }
-// }
-// else if (!quotes && format.columnSeparator.contains(c))
-// {
-// cells << field;
-// field.clear();
-// sepAsLast = true;
-// }
-// else if (!quotes && format.rowSeparator.contains(c))
-// {
-// cells << field;
-// rows << cells;
-// cells.clear();
-// field.clear();
-// }
-// else
-// {
-// field += c;
-// }
-// pos++;
-// }
-
-// if (field.size() > 0 || sepAsLast)
-// cells << field;
-
-// if (cells.size() > 0)
-// rows << cells;
-
-// return rows;
-//}
diff --git a/SQLiteStudio3/coreSQLiteStudio/csvserializer.h b/SQLiteStudio3/coreSQLiteStudio/csvserializer.h
index 1ff6ee9..0b7e095 100644
--- a/SQLiteStudio3/coreSQLiteStudio/csvserializer.h
+++ b/SQLiteStudio3/coreSQLiteStudio/csvserializer.h
@@ -4,6 +4,8 @@
#include "coreSQLiteStudio_global.h"
#include "csvformat.h"
+#include <QTextStream>
+
class API_EXPORT CsvSerializer
{
public:
@@ -11,6 +13,11 @@ class API_EXPORT CsvSerializer
static QString serialize(const QStringList& data, const CsvFormat& format);
static QList<QStringList> deserialize(const QString& data, const CsvFormat& format);
static QList<QList<QByteArray>> deserialize(const QByteArray& data, const CsvFormat& format);
+ static QList<QStringList> deserialize(QTextStream& data, const CsvFormat& format);
+ static QStringList deserializeOneEntry(QTextStream& data, const CsvFormat& format);
+
+ private:
+ static QList<QStringList> deserialize(QTextStream& data, const CsvFormat& format, bool oneEntry);
};
#endif // CSVSERIALIZER_H
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/abstractdb2.h b/SQLiteStudio3/coreSQLiteStudio/db/abstractdb2.h
index 5b95f61..7419f8c 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/abstractdb2.h
+++ b/SQLiteStudio3/coreSQLiteStudio/db/abstractdb2.h
@@ -600,7 +600,7 @@ bool AbstractDb2<T>::Query::execInternal(const QList<QVariant>& args)
}
bool ok = (fetchFirst() == SQLITE_OK);
- if (ok)
+ if (ok && !flags.testFlag(Db::Flag::SKIP_DROP_DETECTION))
db->checkForDroppedObject(query);
return ok;
@@ -643,7 +643,7 @@ bool AbstractDb2<T>::Query::execInternal(const QHash<QString, QVariant>& args)
}
bool ok = (fetchFirst() == SQLITE_OK);
- if (ok)
+ if (ok && !flags.testFlag(Db::Flag::SKIP_DROP_DETECTION))
db->checkForDroppedObject(query);
return ok;
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/abstractdb3.h b/SQLiteStudio3/coreSQLiteStudio/db/abstractdb3.h
index e7b0a4b..db9bc02 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/abstractdb3.h
+++ b/SQLiteStudio3/coreSQLiteStudio/db/abstractdb3.h
@@ -68,10 +68,10 @@ class AbstractDb3 : public AbstractDb
class Row : public SqlResultsRow
{
public:
- int init(const QStringList& columns, typename T::stmt* stmt);
+ int init(const QStringList& columns, typename T::stmt* stmt, Db::Flags flags);
private:
- int getValue(typename T::stmt* stmt, int col, QVariant& value);
+ int getValue(typename T::stmt* stmt, int col, QVariant& value, Db::Flags flags);
};
Query(AbstractDb3<T>* db, const QString& query);
@@ -888,7 +888,7 @@ bool AbstractDb3<T>::Query::execInternal(const QList<QVariant>& args)
}
bool ok = (fetchFirst() == T::OK);
- if (ok)
+ if (ok && !flags.testFlag(Db::Flag::SKIP_DROP_DETECTION))
db->checkForDroppedObject(query);
return ok;
@@ -942,7 +942,7 @@ bool AbstractDb3<T>::Query::execInternal(const QHash<QString, QVariant>& args)
}
bool ok = (fetchFirst() == T::OK);
- if (ok)
+ if (ok && !flags.testFlag(Db::Flag::SKIP_DROP_DETECTION))
db->checkForDroppedObject(query);
return ok;
@@ -1044,7 +1044,7 @@ template <class T>
SqlResultsRowPtr AbstractDb3<T>::Query::nextInternal()
{
Row* row = new Row;
- int res = row->init(colNames, stmt);
+ int res = row->init(colNames, stmt, flags);
if (res != T::OK)
{
delete row;
@@ -1131,13 +1131,13 @@ int AbstractDb3<T>::Query::fetchNext()
//------------------------------------------------------------------------------------
template <class T>
-int AbstractDb3<T>::Query::Row::init(const QStringList& columns, typename T::stmt* stmt)
+int AbstractDb3<T>::Query::Row::init(const QStringList& columns, typename T::stmt* stmt, Db::Flags flags)
{
int res = T::OK;
QVariant value;
for (int i = 0; i < columns.size(); i++)
{
- res = getValue(stmt, i, value);
+ res = getValue(stmt, i, value, flags);
if (res != T::OK)
return res;
@@ -1148,8 +1148,9 @@ int AbstractDb3<T>::Query::Row::init(const QStringList& columns, typename T::stm
}
template <class T>
-int AbstractDb3<T>::Query::Row::getValue(typename T::stmt* stmt, int col, QVariant& value)
+int AbstractDb3<T>::Query::Row::getValue(typename T::stmt* stmt, int col, QVariant& value, Db::Flags flags)
{
+ UNUSED(flags);
int dataType = T::column_type(stmt, col);
switch (dataType)
{
@@ -1162,12 +1163,12 @@ int AbstractDb3<T>::Query::Row::getValue(typename T::stmt* stmt, int col, QVaria
T::column_bytes(stmt, col)
);
break;
- case T::FLOAT:
- value = T::column_double(stmt, col);
- break;
case T::NULL_TYPE:
value = QVariant(QVariant::String);
break;
+ case T::FLOAT:
+ value = T::column_double(stmt, col);
+ break;
default:
value = QString(
reinterpret_cast<const QChar*>(T::column_text16(stmt, col)),
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/chainexecutor.cpp b/SQLiteStudio3/coreSQLiteStudio/db/chainexecutor.cpp
index f36a3bd..a35856b 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/chainexecutor.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/db/chainexecutor.cpp
@@ -42,6 +42,16 @@ void ChainExecutor::exec()
return;
}
+ if (disableForeignKeys && db->getDialect() == Dialect::Sqlite3)
+ {
+ SqlQueryPtr result = db->exec("PRAGMA foreign_keys = 0;");
+ if (result->isError())
+ {
+ emit failure(db->getErrorCode(), tr("Could not disable foreign keys in the database. Details: %1", "chain executor").arg(db->getErrorText()));
+ return;
+ }
+ }
+
if (transaction && !db->begin())
{
emit failure(db->getErrorCode(), tr("Could not start a database transaction. Details: %1", "chain executor").arg(db->getErrorText()));
@@ -75,7 +85,7 @@ void ChainExecutor::executeCurrentSql()
return;
}
- asyncId = db->asyncExec(sqls[currentSqlIndex], queryParams);
+ asyncId = db->asyncExec(sqls[currentSqlIndex], queryParams, getExecFlags());
}
QList<bool> ChainExecutor::getMandatoryQueries() const
@@ -122,6 +132,7 @@ void ChainExecutor::executionFailure(int errorCode, const QString& errorText)
if (transaction)
db->rollback();
+ restoreFk();
successfulExecution = false;
executionErrors << ExecutionError(errorCode, errorText);
emit failure(errorCode, errorText);
@@ -135,16 +146,18 @@ void ChainExecutor::executionSuccessful()
return;
}
+ restoreFk();
successfulExecution = true;
emit success();
}
void ChainExecutor::executeSync()
{
+ Db::Flags flags = getExecFlags();
SqlQueryPtr results;
- foreach (const QString& sql, sqls)
+ for (const QString& sql : sqls)
{
- results = db->exec(sql, queryParams);
+ results = db->exec(sql, queryParams, flags);
if (!handleResults(results))
return;
@@ -165,6 +178,46 @@ bool ChainExecutor::handleResults(SqlQueryPtr results)
}
return true;
}
+
+Db::Flags ChainExecutor::getExecFlags() const
+{
+ Db::Flags flags;
+ if (disableObjectDropsDetection)
+ flags |= Db::Flag::SKIP_DROP_DETECTION;
+
+ return flags;
+}
+
+void ChainExecutor::restoreFk()
+{
+ if (disableForeignKeys && db->getDialect() == Dialect::Sqlite3)
+ {
+ SqlQueryPtr result = db->exec("PRAGMA foreign_keys = 1;");
+ if (result->isError())
+ qCritical() << "Could not restore foreign keys in the database after chain execution. Details:" << db->getErrorText();
+ }
+}
+
+bool ChainExecutor::getDisableObjectDropsDetection() const
+{
+ return disableObjectDropsDetection;
+}
+
+void ChainExecutor::setDisableObjectDropsDetection(bool value)
+{
+ disableObjectDropsDetection = value;
+}
+
+bool ChainExecutor::getDisableForeignKeys() const
+{
+ return disableForeignKeys;
+}
+
+void ChainExecutor::setDisableForeignKeys(bool value)
+{
+ disableForeignKeys = value;
+}
+
bool ChainExecutor::getSuccessfulExecution() const
{
return successfulExecution;
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/chainexecutor.h b/SQLiteStudio3/coreSQLiteStudio/db/chainexecutor.h
index 2d3e3d3..0afbdb8 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/chainexecutor.h
+++ b/SQLiteStudio3/coreSQLiteStudio/db/chainexecutor.h
@@ -198,6 +198,12 @@ class API_EXPORT ChainExecutor : public QObject
*/
void setParam(const QString& paramName, const QVariant& value);
+ bool getDisableForeignKeys() const;
+ void setDisableForeignKeys(bool value);
+
+ bool getDisableObjectDropsDetection() const;
+ void setDisableObjectDropsDetection(bool value);
+
private:
/**
* @brief Executes query defines as the current one.
@@ -241,6 +247,10 @@ class API_EXPORT ChainExecutor : public QObject
*/
bool handleResults(SqlQueryPtr results);
+ Db::Flags getExecFlags() const;
+
+ void restoreFk();
+
/**
* @brief Database for execution.
*/
@@ -315,6 +325,9 @@ class API_EXPORT ChainExecutor : public QObject
*/
QHash<QString,QVariant> queryParams;
+ bool disableForeignKeys = false;
+ bool disableObjectDropsDetection = false;
+
public slots:
/**
* @brief Interrupts query execution.
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/db.cpp b/SQLiteStudio3/coreSQLiteStudio/db/db.cpp
index 7676f30..977812a 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/db.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/db/db.cpp
@@ -1,6 +1,7 @@
#include "db.h"
#include <QMetaEnum>
#include <QDebug>
+#include <QDataStream>
Db::Db()
{
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/db.h b/SQLiteStudio3/coreSQLiteStudio/db/db.h
index efadd41..4a9e80a 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/db.h
+++ b/SQLiteStudio3/coreSQLiteStudio/db/db.h
@@ -140,7 +140,7 @@ class API_EXPORT Db : public QObject, public Interruptable
{
NONE = 0x0, /**< No flags. This is default. */
PRELOAD = 0x1, /**< Preloads all execution results into the results object. Useful for asynchronous execution. */
- NO_LOCK = 0x2 /**<
+ NO_LOCK = 0x2, /**<
* Prevents SQLiteStudio from setting the lock for execution on this base (not the SQLite lock,
* just a Db internal lock for multi-threading access to the Db::exec()). This should be used
* only in justified circumstances. That is when the Db call has to be done from within the part
@@ -148,6 +148,7 @@ class API_EXPORT Db : public QObject, public Interruptable
* threads. Justified situation is when you implement Db::initialDbSetup() in the derived class,
* or when you implement SqlFunctionPlugin. Don't use it for the usual cases.
*/
+ SKIP_DROP_DETECTION = 0x4, /**< Query execution will not notify about any detected objects dropped by the query. */
};
Q_DECLARE_FLAGS(Flags, Flag)
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.cpp b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.cpp
index f8d7fd2..d2e7072 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.cpp
@@ -20,6 +20,7 @@
#include "queryexecutorsteps/queryexecutordetectschemaalter.h"
#include "queryexecutorsteps/queryexecutorvaluesmode.h"
#include "common/unused.h"
+#include "log.h"
#include <QMutexLocker>
#include <QDateTime>
#include <QThreadPool>
@@ -94,13 +95,16 @@ void QueryExecutor::executeChain()
bool result;
foreach (QueryExecutorStep* currentStep, executionChain)
{
- if (interrupted)
+ if (isInterrupted())
{
stepFailed(currentStep);
return;
}
+ logExecutorStep(currentStep);
result = currentStep->exec();
+ logExecutorAfterStep(context->processedQuery);
+
if (!result)
{
stepFailed(currentStep);
@@ -127,7 +131,7 @@ void QueryExecutor::stepFailed(QueryExecutorStep* currentStep)
clearChain();
- if (interrupted)
+ if (isInterrupted())
{
executionInProgress = false;
emit executionFailed(SqlErrorCode::INTERRUPTED, tr("Execution interrupted."));
@@ -240,6 +244,7 @@ void QueryExecutor::interrupt()
return;
}
+ QMutexLocker lock(&interruptionMutex);
interrupted = true;
db->asyncInterrupt();
}
@@ -255,11 +260,11 @@ bool QueryExecutor::countResults()
if (asyncMode)
{
// Start asynchronous results counting query
- resultsCountingAsyncId = db->asyncExec(context->countingQuery, context->queryParameters);
+ resultsCountingAsyncId = db->asyncExec(context->countingQuery, context->queryParameters, Db::Flag::NO_LOCK);
}
else
{
- SqlQueryPtr results = db->exec(context->countingQuery, context->queryParameters);
+ SqlQueryPtr results = db->exec(context->countingQuery, context->queryParameters, Db::Flag::NO_LOCK);
context->totalRowsReturned = results->getSingleCell().toLongLong();
context->totalPages = (int)qCeil(((double)(context->totalRowsReturned)) / ((double)getResultsPerPage()));
@@ -568,6 +573,11 @@ void QueryExecutor::setForceSimpleMode(bool value)
forceSimpleMode = value;
}
+bool QueryExecutor::isInterrupted() const
+{
+ QMutexLocker lock(&interruptionMutex);
+ return interrupted;
+}
const QStringList& QueryExecutor::getRequiredDbAttaches() const
{
@@ -586,24 +596,29 @@ void QueryExecutor::setNoMetaColumns(bool value)
void QueryExecutor::handleErrorsFromSmartAndSimpleMethods(SqlQueryPtr results)
{
- 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.
+ // The case when simple method error is more true than smart method error is very rare nowdays (but happens sometimes,
+ // therefore we need to check code from smart execution, before deciding which one to use).
// Just rename attach names in the message.
- QString msg = context->errorMessageFromSmartExecution;
+ bool useSmartError = context->errorCodeFromSmartExecution != 0;
+ QString msg = useSmartError ? context->errorMessageFromSmartExecution : results->getErrorText();
+ int code = useSmartError ? context->errorCodeFromSmartExecution : results->getErrorCode();
QString match;
QString replaceName;
Dialect dialect = db->getDialect();
- for (const QString& attachName : context->dbNameToAttach.rightValues())
+ if (useSmartError)
{
- match = attachName + ".";
- replaceName = wrapObjIfNeeded(context->dbNameToAttach.valueByRight(attachName), dialect) + ".";
- while (msg.contains(match))
- msg.replace(match, replaceName);
+ for (const QString& attachName : context->dbNameToAttach.rightValues())
+ {
+ match = attachName + ".";
+ replaceName = wrapObjIfNeeded(context->dbNameToAttach.valueByRight(attachName), dialect) + ".";
+ while (msg.contains(match))
+ msg.replace(match, replaceName);
+ }
}
- error(context->errorCodeFromSmartExecution, msg);
+ error(code, msg);
}
void QueryExecutor::releaseResultsAndCleanup()
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.h b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.h
index 95c6a0c..eddbe8c 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.h
+++ b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutor.h
@@ -1032,6 +1032,8 @@ class API_EXPORT QueryExecutor : public QObject, public QRunnable
bool getForceSimpleMode() const;
void setForceSimpleMode(bool value);
+ bool isInterrupted() const;
+
private:
/**
* @brief Executes query.
@@ -1161,7 +1163,8 @@ class API_EXPORT QueryExecutor : public QObject, public QRunnable
* The state of "execution in progress" is the only value synchronized between threads.
* It makes sure that single QueryExecutor will execute only one query at the time.
*/
- QMutex executionMutex;
+ mutable QMutex executionMutex;
+ mutable QMutex interruptionMutex;
/**
* @brief Query to execute as defined by the user.
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorcellsize.cpp b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorcellsize.cpp
index fceea3f..934a20d 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorcellsize.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorcellsize.cpp
@@ -57,8 +57,39 @@ bool QueryExecutorCellSize::applyDataLimit(SqliteSelect* select, SqliteSelect::C
TokenList QueryExecutorCellSize::getLimitTokens(const QueryExecutor::ResultColumnPtr& resCol)
{
+ // CASE WHEN typeof(alias) IN ('real', 'integer', 'numeric', 'null') THEN alias ELSE substr(alias, 1, limit) END
TokenList newTokens;
- newTokens << TokenPtr::create(Token::OTHER, "substr")
+ newTokens << TokenPtr::create(Token::KEYWORD, "CASE")
+ << TokenPtr::create(Token::SPACE, " ")
+ << TokenPtr::create(Token::KEYWORD, "WHEN")
+ << TokenPtr::create(Token::SPACE, " ")
+ << TokenPtr::create(Token::OTHER, "typeof")
+ << TokenPtr::create(Token::PAR_LEFT, "(")
+ << TokenPtr::create(Token::OTHER, resCol->queryExecutorAlias)
+ << TokenPtr::create(Token::PAR_RIGHT, ")")
+ << TokenPtr::create(Token::SPACE, " ")
+ << TokenPtr::create(Token::KEYWORD, "IN")
+ << TokenPtr::create(Token::SPACE, " ")
+ << TokenPtr::create(Token::PAR_LEFT, "(")
+ << TokenPtr::create(Token::STRING, "'real'")
+ << TokenPtr::create(Token::OPERATOR, ",")
+ << TokenPtr::create(Token::SPACE, " ")
+ << TokenPtr::create(Token::STRING, "'integer'")
+ << TokenPtr::create(Token::OPERATOR, ",")
+ << TokenPtr::create(Token::SPACE, " ")
+ << TokenPtr::create(Token::STRING, "'numeric'")
+ << TokenPtr::create(Token::OPERATOR, ",")
+ << TokenPtr::create(Token::SPACE, " ")
+ << TokenPtr::create(Token::STRING, "'null'")
+ << TokenPtr::create(Token::PAR_RIGHT, ")")
+ << TokenPtr::create(Token::SPACE, " ")
+ << TokenPtr::create(Token::KEYWORD, "THEN")
+ << TokenPtr::create(Token::SPACE, " ")
+ << TokenPtr::create(Token::OTHER, resCol->queryExecutorAlias)
+ << TokenPtr::create(Token::SPACE, " ")
+ << TokenPtr::create(Token::KEYWORD, "ELSE")
+ << TokenPtr::create(Token::SPACE, " ")
+ << TokenPtr::create(Token::OTHER, "substr")
<< TokenPtr::create(Token::PAR_LEFT, "(")
<< TokenPtr::create(Token::OTHER, resCol->queryExecutorAlias)
<< TokenPtr::create(Token::OPERATOR, ",")
@@ -69,6 +100,8 @@ TokenList QueryExecutorCellSize::getLimitTokens(const QueryExecutor::ResultColum
<< TokenPtr::create(Token::INTEGER, QString::number(queryExecutor->getDataLengthLimit()))
<< TokenPtr::create(Token::PAR_RIGHT, ")")
<< TokenPtr::create(Token::SPACE, " ")
+ << TokenPtr::create(Token::KEYWORD, "END")
+ << TokenPtr::create(Token::SPACE, " ")
<< TokenPtr::create(Token::KEYWORD, "AS")
<< TokenPtr::create(Token::SPACE, " ")
<< TokenPtr::create(Token::OTHER, resCol->queryExecutorAlias);
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorcolumns.cpp b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorcolumns.cpp
index 287a8ce..344f2e5 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorcolumns.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorcolumns.cpp
@@ -71,12 +71,13 @@ bool QueryExecutorColumns::exec()
i++;
}
+// qDebug() << "before: " << context->processedQuery;
// Update query
select->rebuildTokens();
wrapWithAliasedColumns(select.data());
updateQueries();
-// qDebug() << context->processedQuery;
+// qDebug() << "after: " << context->processedQuery;
return true;
}
@@ -130,6 +131,9 @@ SqliteSelect::Core::ResultColumn* QueryExecutorColumns::getResultColumnForSelect
SqliteSelect::Core::ResultColumn* selectResultColumn = new SqliteSelect::Core::ResultColumn();
QString colString = resultColumn->column;
+ if (col.aliasDefinedInSubQuery) // #2931
+ colString = col.alias;
+
if (!resultColumn->expression)
colString = wrapObjIfNeeded(colString, dialect);
@@ -167,16 +171,11 @@ SqliteSelect::Core::ResultColumn* QueryExecutorColumns::getResultColumnForSelect
}
}
+ selectResultColumn->asKw = true;
if (!col.alias.isNull())
- {
- selectResultColumn->asKw = true;
selectResultColumn->alias = col.alias;
- }
else
- {
- selectResultColumn->asKw = true;
selectResultColumn->alias = resultColumn->queryExecutorAlias;
- }
return selectResultColumn;
}
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorexecute.cpp b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorexecute.cpp
index a954da7..3036796 100644
--- a/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorexecute.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/db/queryexecutorsteps/queryexecutorexecute.cpp
@@ -41,11 +41,13 @@ bool QueryExecutorExecute::executeQueries()
if (context->preloadResults)
flags |= Db::Flag::PRELOAD;
+ QString queryStr;
int queryCount = context->parsedQueries.size();
for (const SqliteQueryPtr& query : context->parsedQueries)
{
+ queryStr = query->detokenize();
bindParamsForQuery = getBindParamsForQuery(query);
- results = db->prepare(query->detokenize());
+ results = db->prepare(queryStr);
results->setArgs(bindParamsForQuery);
results->setFlags(flags);
@@ -56,6 +58,7 @@ bool QueryExecutorExecute::executeQueries()
if (isBeginTransaction(query->queryType))
rowsAffectedBeforeTransaction.push(context->rowsAffected);
+// qDebug() << "Executing query:" << queryStr;
results->execute();
if (results->isError())
diff --git a/SQLiteStudio3/coreSQLiteStudio/dbattacher.h b/SQLiteStudio3/coreSQLiteStudio/dbattacher.h
index 5b94832..0e849a5 100644
--- a/SQLiteStudio3/coreSQLiteStudio/dbattacher.h
+++ b/SQLiteStudio3/coreSQLiteStudio/dbattacher.h
@@ -73,6 +73,17 @@ class API_EXPORT DbAttacher
* @return Query string.
*/
virtual QString getQuery() const = 0;
+
+ /**
+ * @brief Tells if "main" database name was used in the query and was ommited.
+ * @return true when "main" db token was in the query, or false otherwise.
+ *
+ * The "main" database will not be attached and this getter tells wheter such situation occured.
+ * This is to assert situation when user has database on the list which name is actually "main".
+ * Table window always uses "main." prefix when reading data and this caused attacher to step in,
+ * which then caused some execution error.
+ */
+ virtual bool getMainDbNameUsed() const = 0;
};
/**
diff --git a/SQLiteStudio3/coreSQLiteStudio/dbobjectorganizer.cpp b/SQLiteStudio3/coreSQLiteStudio/dbobjectorganizer.cpp
index f8c51dc..542668b 100644
--- a/SQLiteStudio3/coreSQLiteStudio/dbobjectorganizer.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/dbobjectorganizer.cpp
@@ -559,7 +559,21 @@ bool DbObjectOrganizer::copySimpleObjectToDb(const QString& name, const QString&
if (convertedDdl.trimmed() == ";") // empty query, result of ignored errors in UI
return true;
- SqlQueryPtr result = dstDb->exec(convertedDdl);
+ SqlQueryPtr result;
+
+ if (!attachName.isNull())
+ {
+ convertedDdl = prefixSimpleObjectWithAttachName(name, convertedDdl);
+ if (convertedDdl.isNull())
+ return false;
+
+ result = srcDb->exec(convertedDdl);
+ }
+ else
+ {
+ result = dstDb->exec(convertedDdl);
+ }
+
if (result->isError())
{
notifyError(errorMessage.arg(result->getErrorText()));
@@ -750,6 +764,37 @@ bool DbObjectOrganizer::execConfirmFunctionInMainThread(const QStringList& table
return res;
}
+QString DbObjectOrganizer::prefixSimpleObjectWithAttachName(const QString& objName, const QString& ddl)
+{
+ Parser parser(srcDb->getDialect());
+ if (!parser.parse(ddl))
+ {
+ qDebug() << "Parsing error while copying or moving object:" << objName << ", details:" << parser.getErrorString();
+ notifyError(tr("Could not parse object '%1' in order to move or copy it.").arg(objName));
+ return QString();
+ }
+
+ if (parser.getQueries().isEmpty())
+ {
+ qDebug() << "Empty queries from parser while copying or moving object:" << objName;
+ notifyError(tr("Could not parse object '%1' in order to move or copy it.").arg(objName));
+ return QString();
+ }
+
+ SqliteQueryPtr query = parser.getQueries().first();
+ SqliteDdlWithDbContextPtr ddlWithDb = query.dynamicCast<SqliteDdlWithDbContext>();
+ if (!ddlWithDb)
+ {
+ qDebug() << "Not instance of SqliteDdlWithDbContext while copying or moving object:" << objName << ", it's type is:" << (int)query->queryType;
+ notifyError(tr("Could not parse object '%1' in order to move or copy it.").arg(objName));
+ return QString();
+ }
+
+ ddlWithDb->setTargetDatabase(attachName);
+ query->rebuildTokens();
+ return query->tokens.detokenize();
+}
+
void DbObjectOrganizer::processPreparationFinished()
{
if (errorsToConfirm.size() > 0 && !conversionErrorsConfimFunction(errorsToConfirm))
diff --git a/SQLiteStudio3/coreSQLiteStudio/dbobjectorganizer.h b/SQLiteStudio3/coreSQLiteStudio/dbobjectorganizer.h
index 8a7e7a9..42b258a 100644
--- a/SQLiteStudio3/coreSQLiteStudio/dbobjectorganizer.h
+++ b/SQLiteStudio3/coreSQLiteStudio/dbobjectorganizer.h
@@ -109,6 +109,7 @@ class API_EXPORT DbObjectOrganizer : public QObject, public QRunnable, public In
bool rollback();
void emitFinished(bool success);
bool execConfirmFunctionInMainThread(const QStringList& tables);
+ QString prefixSimpleObjectWithAttachName(const QString& objName, const QString& ddl);
ReferencedTablesConfimFunction confirmFunction;
NameConflictResolveFunction nameConflictResolveFunction;
diff --git a/SQLiteStudio3/coreSQLiteStudio/dbversionconverter.cpp b/SQLiteStudio3/coreSQLiteStudio/dbversionconverter.cpp
index 676009a..9e4c664 100644
--- a/SQLiteStudio3/coreSQLiteStudio/dbversionconverter.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/dbversionconverter.cpp
@@ -793,20 +793,10 @@ bool DbVersionConverter::modifyAllIndexedColumnsForVersion2(SqliteStatement* stm
}
-bool DbVersionConverter::modifyAllIndexedColumnsForVersion2(const QList<SqliteIndexedColumn*> columns)
+bool DbVersionConverter::modifySingleIndexedColumnForVersion2(SqliteExtendedIndexedColumn* idxCol)
{
- for (SqliteIndexedColumn* idxCol : columns)
- {
- if (!modifySingleIndexedColumnForVersion2(idxCol))
- return false;
- }
- return true;
-}
-
-bool DbVersionConverter::modifySingleIndexedColumnForVersion2(SqliteIndexedColumn* idxCol)
-{
- if (!idxCol->collate.isNull())
- idxCol->collate = QString::null;
+ if (!idxCol->getCollation().isNull())
+ idxCol->clearCollation();
return true;
}
diff --git a/SQLiteStudio3/coreSQLiteStudio/dbversionconverter.h b/SQLiteStudio3/coreSQLiteStudio/dbversionconverter.h
index 8343c2f..9486f1b 100644
--- a/SQLiteStudio3/coreSQLiteStudio/dbversionconverter.h
+++ b/SQLiteStudio3/coreSQLiteStudio/dbversionconverter.h
@@ -2,6 +2,7 @@
#define DBVERSIONCONVERTER_H
#include "parser/ast/sqlitequery.h"
+#include "parser/ast/sqliteorderby.h"
#include <QList>
#include <QStringList>
#include <QPair>
@@ -85,8 +86,7 @@ class API_EXPORT DbVersionConverter : public QObject
bool modifyAllExprsForVersion2(SqliteStatement* stmt);
bool modifySingleExprForVersion2(SqliteExpr* expr);
bool modifyAllIndexedColumnsForVersion2(SqliteStatement* stmt);
- bool modifyAllIndexedColumnsForVersion2(const QList<SqliteIndexedColumn*> columns);
- bool modifySingleIndexedColumnForVersion2(SqliteIndexedColumn* idxCol);
+ bool modifySingleIndexedColumnForVersion2(SqliteExtendedIndexedColumn* idxCol);
bool modifyBeginTransForVersion3(SqliteBeginTrans* begin);
bool modifyCreateTableForVersion3(SqliteCreateTable* createTable);
QString getSqlForDiff(SqliteStatement* stmt);
@@ -100,6 +100,18 @@ class API_EXPORT DbVersionConverter : public QObject
void conversionInterrupted(Db* db, bool rollback);
template <class T>
+ bool modifyAllIndexedColumnsForVersion2(const QList<T*> columns)
+ {
+ for (T* idxCol : columns)
+ {
+ if (!modifySingleIndexedColumnForVersion2(idxCol))
+ return false;
+ }
+ return true;
+ }
+
+
+ template <class T>
QSharedPointer<T> copyQuery(SqliteQueryPtr query)
{
return QSharedPointer<T>::create(*(query.dynamicCast<T>().data()));
diff --git a/SQLiteStudio3/coreSQLiteStudio/exportworker.cpp b/SQLiteStudio3/coreSQLiteStudio/exportworker.cpp
index ffecd4d..6427138 100644
--- a/SQLiteStudio3/coreSQLiteStudio/exportworker.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/exportworker.cpp
@@ -4,6 +4,7 @@
#include "services/notifymanager.h"
#include "common/utils_sql.h"
#include "common/utils.h"
+#include "db/sqlresultsrow.h"
#include <QMutexLocker>
#include <QDebug>
@@ -590,6 +591,9 @@ QList<ExportManager::ExportObjectPtr> ExportWorker::collectDbObjects(QString* er
qSort(objectsToExport.begin(), objectsToExport.end(), [](ExportManager::ExportObjectPtr obj1, ExportManager::ExportObjectPtr obj2) -> bool
{
+ if (obj1->type == obj2->type)
+ return obj1->name.compare(obj2->name, Qt::CaseInsensitive) < 0;
+
return (obj1->type < obj2->type);
});
@@ -638,7 +642,8 @@ void ExportWorker::queryTableDataToExport(Db* db, const QString& table, SqlQuery
else
{
QList<int> colWidths;
- for (const QVariant& value : colLengthQuery->next()->valueList())
+ SqlResultsRowPtr row = colLengthQuery->next();
+ for (const QVariant& value : row->valueList())
colWidths << value.toInt();
providerData[ExportManager::DATA_LENGTHS] = QVariant::fromValue(colWidths);
diff --git a/SQLiteStudio3/coreSQLiteStudio/impl/dbattacherimpl.cpp b/SQLiteStudio3/coreSQLiteStudio/impl/dbattacherimpl.cpp
index 75d94eb..7d9c1ba 100644
--- a/SQLiteStudio3/coreSQLiteStudio/impl/dbattacherimpl.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/impl/dbattacherimpl.cpp
@@ -69,7 +69,7 @@ TokenList DbAttacherImpl::getDbTokens()
void DbAttacherImpl::detachAttached()
{
- foreach (const QString& dbName, dbNameToAttach.leftValues())
+ for (const QString& dbName : dbNameToAttach.leftValues())
db->detach(nameToDbMap[dbName]);
dbNameToAttach.clear();
@@ -87,7 +87,7 @@ QHash<QString, TokenList> DbAttacherImpl::groupDbTokens(const TokenList& dbToken
// Filter out tokens of unknown databases and group results by name
QHash<QString,TokenList> groupedDbTokens;
QString strippedName;
- foreach (TokenPtr token, dbTokens)
+ for (TokenPtr token : dbTokens)
{
strippedName = stripObjName(token->value, dialect);
if (!nameToDbMap.contains(strippedName, Qt::CaseInsensitive))
@@ -101,8 +101,14 @@ QHash<QString, TokenList> DbAttacherImpl::groupDbTokens(const TokenList& dbToken
bool DbAttacherImpl::attachAllDbs(const QHash<QString, TokenList>& groupedDbTokens)
{
QString attachName;
- foreach (const QString& dbName, groupedDbTokens.keys())
+ for (const QString& dbName : groupedDbTokens.keys())
{
+ if (dbName.toLower() == "main")
+ {
+ mainDbNameUsed = true;
+ continue;
+ }
+
attachName = db->attach(nameToDbMap[dbName]);
if (attachName.isNull())
{
@@ -121,7 +127,7 @@ QHash<TokenPtr, TokenPtr> DbAttacherImpl::getTokenMapping(const TokenList& dbTok
QHash<TokenPtr, TokenPtr> tokenMapping;
QString strippedName;
TokenPtr dstToken;
- foreach (TokenPtr srcToken, dbTokens)
+ for (TokenPtr srcToken : dbTokens)
{
strippedName = stripObjName(srcToken->value, dialect);
if (strippedName.compare("main", Qt::CaseInsensitive) == 0 ||
@@ -158,6 +164,11 @@ void DbAttacherImpl::replaceTokensInQueries(const QHash<TokenPtr, TokenPtr>& tok
}
}
+bool DbAttacherImpl::getMainDbNameUsed() const
+{
+ return mainDbNameUsed;
+}
+
BiStrHash DbAttacherImpl::getDbNameToAttach() const
{
return dbNameToAttach;
diff --git a/SQLiteStudio3/coreSQLiteStudio/impl/dbattacherimpl.h b/SQLiteStudio3/coreSQLiteStudio/impl/dbattacherimpl.h
index 49307c6..6fbe6c8 100644
--- a/SQLiteStudio3/coreSQLiteStudio/impl/dbattacherimpl.h
+++ b/SQLiteStudio3/coreSQLiteStudio/impl/dbattacherimpl.h
@@ -18,6 +18,7 @@ class DbAttacherImpl : public DbAttacher
void detachDatabases();
BiStrHash getDbNameToAttach() const;
QString getQuery() const;
+ bool getMainDbNameUsed() const;
private:
/**
@@ -83,6 +84,7 @@ class DbAttacherImpl : public DbAttacher
Dialect dialect;
BiStrHash dbNameToAttach;
StrHash<Db*> nameToDbMap;
+ bool mainDbNameUsed = false;
};
class DbAttacherDefaultFactory : public DbAttacherFactory
diff --git a/SQLiteStudio3/coreSQLiteStudio/importworker.cpp b/SQLiteStudio3/coreSQLiteStudio/importworker.cpp
index b8d5a5a..a8ca8f7 100644
--- a/SQLiteStudio3/coreSQLiteStudio/importworker.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/importworker.cpp
@@ -147,6 +147,11 @@ bool ImportWorker::importData()
QList<QVariant> row;
while ((row = plugin->next()).size() > 0)
{
+ // Fill up missing values in the line
+ for (int i = row.size(); i < colCount; i++)
+ row << QVariant(QVariant::String);
+
+ // Assign argument values
query->setArgs(row.mid(0, colCount));
if (!query->execute())
{
diff --git a/SQLiteStudio3/coreSQLiteStudio/log.cpp b/SQLiteStudio3/coreSQLiteStudio/log.cpp
index d54abdb..d45f1aa 100644
--- a/SQLiteStudio3/coreSQLiteStudio/log.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/log.cpp
@@ -1,9 +1,11 @@
#include "log.h"
+#include "db/queryexecutorsteps/queryexecutorstep.h"
#include <QTime>
#include <QDebug>
-bool SQL_DEBUG = false;
-QString SQL_DEBUG_FILTER = "";
+static bool SQL_DEBUG = false;
+static bool EXECUTOR_DEBUG = false;
+static QString SQL_DEBUG_FILTER = "";
void setSqlLoggingEnabled(bool enabled)
{
@@ -45,3 +47,25 @@ void logSql(Db* db, const QString& str, const QList<QVariant>& args, Db::Flags f
foreach (const QVariant& arg, args)
qDebug() << " SQL arg>" << i++ << "=" << arg;
}
+
+void setExecutorLoggingEnabled(bool enabled)
+{
+ EXECUTOR_DEBUG = enabled;
+}
+
+void logExecutorStep(QueryExecutorStep* step)
+{
+ if (!EXECUTOR_DEBUG)
+ return;
+
+ qDebug() << "Executing step:" << step->metaObject()->className() << step->objectName();
+}
+
+
+void logExecutorAfterStep(const QString& str)
+{
+ if (!EXECUTOR_DEBUG)
+ return;
+
+ qDebug() << str;
+}
diff --git a/SQLiteStudio3/coreSQLiteStudio/log.h b/SQLiteStudio3/coreSQLiteStudio/log.h
index dddb513..1cf8dc5 100644
--- a/SQLiteStudio3/coreSQLiteStudio/log.h
+++ b/SQLiteStudio3/coreSQLiteStudio/log.h
@@ -8,9 +8,14 @@
#include <QList>
#include <QVariant>
+class QueryExecutorStep;
+
API_EXPORT void logSql(Db* db, const QString& str, const QHash<QString,QVariant>& args, Db::Flags flags);
API_EXPORT void logSql(Db* db, const QString& str, const QList<QVariant>& args, Db::Flags flags);
+API_EXPORT void logExecutorStep(QueryExecutorStep* step);
+API_EXPORT void logExecutorAfterStep(const QString& str);
API_EXPORT void setSqlLoggingEnabled(bool enabled);
API_EXPORT void setSqlLoggingFilter(const QString& filter);
+API_EXPORT void setExecutorLoggingEnabled(bool enabled);
#endif // LOG_H
diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateindex.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateindex.cpp
index 16cec8f..fdbadf8 100644
--- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateindex.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateindex.cpp
@@ -14,11 +14,10 @@ SqliteCreateIndex::SqliteCreateIndex(const SqliteCreateIndex& other) :
SqliteQuery(other), uniqueKw(other.uniqueKw), ifNotExistsKw(other.ifNotExistsKw), database(other.database), index(other.index),
table(other.table)
{
- DEEP_COPY_COLLECTION(SqliteIndexedColumn, indexedColumns);
+ DEEP_COPY_COLLECTION(SqliteOrderBy, indexedColumns);
}
-SqliteCreateIndex::SqliteCreateIndex(bool unique, bool ifNotExists, const QString &name1, const QString &name2, const QString &name3,
- const QList<SqliteIndexedColumn *> &columns, SqliteConflictAlgo onConflict)
+SqliteCreateIndex::SqliteCreateIndex(bool unique, bool ifNotExists, const QString& name1, const QString& name2, const QString& name3, const QList<SqliteIndexedColumn*>& columns, SqliteConflictAlgo onConflict)
: SqliteCreateIndex()
{
// Constructor for SQLite 2
@@ -36,14 +35,11 @@ SqliteCreateIndex::SqliteCreateIndex(bool unique, bool ifNotExists, const QStrin
table = name2;
this->onConflict = onConflict;
- this->indexedColumns = columns;
-
- foreach (SqliteIndexedColumn* idxCol, columns)
- idxCol->setParent(this);
+ this->indexedColumns = toOrderColumns(columns);
}
SqliteCreateIndex::SqliteCreateIndex(bool unique, bool ifNotExists, const QString& name1, const QString& name2, const QString& name3,
- const QList<SqliteIndexedColumn*>& columns, SqliteExpr* where)
+ const QList<SqliteOrderBy*>& columns, SqliteExpr* where)
: SqliteCreateIndex()
{
// Constructor for SQLite 3
@@ -61,7 +57,7 @@ SqliteCreateIndex::SqliteCreateIndex(bool unique, bool ifNotExists, const QStrin
table = name3;
this->indexedColumns = columns;
- foreach (SqliteIndexedColumn* idxCol, columns)
+ foreach (SqliteOrderBy* idxCol, columns)
idxCol->setParent(this);
this->where = where;
@@ -189,3 +185,44 @@ TokenList SqliteCreateIndex::rebuildTokensFromContents()
return builder.build();
}
+
+QList<SqliteOrderBy*> SqliteCreateIndex::toOrderColumns(const QList<SqliteIndexedColumn*>& columns)
+{
+ QList<SqliteOrderBy*> result;
+ SqliteOrderBy* orderBy = nullptr;
+ SqliteExpr* expr = nullptr;
+ for (SqliteIndexedColumn* idxCol : columns)
+ {
+ orderBy = new SqliteOrderBy();
+ orderBy->setParent(this);
+ orderBy->expr = new SqliteExpr();
+ orderBy->expr->setParent(orderBy);
+
+ if (!idxCol->collate.isNull())
+ {
+ expr = new SqliteExpr();
+ expr->initId(idxCol->name);
+ expr->setParent(orderBy->expr);
+
+ orderBy->expr->initCollate(expr, idxCol->collate);
+ }
+ else
+ {
+ orderBy->expr->initId(idxCol->name);
+ }
+
+ result << orderBy;
+ delete idxCol;
+ }
+ return result;
+}
+
+QString SqliteCreateIndex::getTargetDatabase() const
+{
+ return database;
+}
+
+void SqliteCreateIndex::setTargetDatabase(const QString& database)
+{
+ this->database = database;
+}
diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateindex.h b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateindex.h
index 9251b18..033a663 100644
--- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateindex.h
+++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateindex.h
@@ -5,12 +5,14 @@
#include "sqlitetablerelatedddl.h"
#include "sqliteconflictalgo.h"
#include "sqliteexpr.h"
+#include "sqliteddlwithdbcontext.h"
+#include "sqliteorderby.h"
#include <QString>
#include <QList>
class SqliteIndexedColumn;
-class API_EXPORT SqliteCreateIndex : public SqliteQuery, public SqliteTableRelatedDdl
+class API_EXPORT SqliteCreateIndex : public SqliteQuery, public SqliteTableRelatedDdl, public SqliteDdlWithDbContext
{
public:
SqliteCreateIndex();
@@ -19,16 +21,18 @@ class API_EXPORT SqliteCreateIndex : public SqliteQuery, public SqliteTableRelat
const QString& name3, const QList<SqliteIndexedColumn*>& columns,
SqliteConflictAlgo onConflict = SqliteConflictAlgo::null);
SqliteCreateIndex(bool unique, bool ifNotExists, const QString& name1, const QString& name2,
- const QString& name3, const QList<SqliteIndexedColumn*>& columns,
+ const QString& name3, const QList<SqliteOrderBy*>& columns,
SqliteExpr* where);
~SqliteCreateIndex();
SqliteStatement* clone();
QString getTargetTable() const;
+ QString getTargetDatabase() const;
+ void setTargetDatabase(const QString& database);
bool uniqueKw = false;
bool ifNotExistsKw = false;
- QList<SqliteIndexedColumn*> indexedColumns;
+ QList<SqliteOrderBy*> indexedColumns;
// The database refers to index name in Sqlite3, but in Sqlite2 it refers to the table.
QString database = QString::null;
QString index = QString::null;
@@ -43,6 +47,9 @@ class API_EXPORT SqliteCreateIndex : public SqliteQuery, public SqliteTableRelat
TokenList getDatabaseTokensInStatement();
QList<FullObject> getFullObjectsInStatement();
TokenList rebuildTokensFromContents();
+
+ private:
+ QList<SqliteOrderBy*> toOrderColumns(const QList<SqliteIndexedColumn*>& columns);
};
typedef QSharedPointer<SqliteCreateIndex> SqliteCreateIndexPtr;
diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetable.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetable.cpp
index d21578e..2ac6c04 100644
--- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetable.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetable.cpp
@@ -669,13 +669,23 @@ bool SqliteCreateTable::Column::hasConstraint(SqliteCreateTable::Column::Constra
SqliteCreateTable::Column::Constraint* SqliteCreateTable::Column::getConstraint(SqliteCreateTable::Column::Constraint::Type type) const
{
- foreach (Constraint* constr, constraints)
+ for (Constraint* constr : constraints)
if (constr->type == type)
return constr;
return nullptr;
}
+QList<SqliteCreateTable::Column::Constraint*> SqliteCreateTable::Column::getConstraints(SqliteCreateTable::Column::Constraint::Type type) const
+{
+ QList<Constraint*> list;
+ for (Constraint* constr : constraints)
+ if (constr->type == type)
+ list << constr;
+
+ return list;
+}
+
QList<SqliteCreateTable::Column::Constraint*> SqliteCreateTable::Column::getForeignKeysByTable(const QString& foreignTable) const
{
QList<Constraint*> results;
@@ -768,3 +778,13 @@ TokenList SqliteCreateTable::Column::Constraint::rebuildTokensFromContents()
return builder.build();
}
+
+QString SqliteCreateTable::getTargetDatabase() const
+{
+ return database;
+}
+
+void SqliteCreateTable::setTargetDatabase(const QString& database)
+{
+ this->database = database;
+}
diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetable.h b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetable.h
index 877d0fa..74f4fce 100644
--- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetable.h
+++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetable.h
@@ -10,10 +10,11 @@
#include "sqlitecolumntype.h"
#include "sqlitesortorder.h"
#include "sqlitedeferrable.h"
+#include "sqliteddlwithdbcontext.h"
#include <QVariant>
#include <QList>
-class API_EXPORT SqliteCreateTable : public SqliteQuery
+class API_EXPORT SqliteCreateTable : public SqliteQuery, public SqliteDdlWithDbContext
{
public:
class API_EXPORT Column : public SqliteStatement
@@ -93,6 +94,7 @@ class API_EXPORT SqliteCreateTable : public SqliteQuery
bool hasConstraint(Constraint::Type type) const;
Constraint* getConstraint(Constraint::Type type) const;
+ QList<Constraint*> getConstraints(Constraint::Type type) const;
QList<Constraint*> getForeignKeysByTable(const QString& foreignTable) const;
QString name = QString::null;
@@ -181,6 +183,8 @@ class API_EXPORT SqliteCreateTable : public SqliteQuery
QList<Column::Constraint*> getColumnForeignKeysByTable(const QString& foreignTable) const;
QStringList getColumnNames() const;
QHash<QString,QString> getModifiedColumnsMap(bool lowercaseKeys = false, Qt::CaseSensitivity cs = Qt::CaseInsensitive) const;
+ QString getTargetDatabase() const;
+ void setTargetDatabase(const QString& database);
bool ifNotExistsKw = false;
bool tempKw = false;
@@ -202,7 +206,6 @@ class API_EXPORT SqliteCreateTable : public SqliteQuery
private:
void init(bool ifNotExistsKw, int temp, const QString& name1, const QString& name2);
-
};
typedef QSharedPointer<SqliteCreateTable> SqliteCreateTablePtr;
diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetrigger.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetrigger.cpp
index 8f67aea..e15ddd6 100644
--- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetrigger.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetrigger.cpp
@@ -379,3 +379,13 @@ TokenList SqliteCreateTrigger::rebuildTokensFromContents()
return builder.build();
}
+
+QString SqliteCreateTrigger::getTargetDatabase() const
+{
+ return database;
+}
+
+void SqliteCreateTrigger::setTargetDatabase(const QString& database)
+{
+ this->database = database;
+}
diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetrigger.h b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetrigger.h
index 2fb8ae4..2ccf876 100644
--- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetrigger.h
+++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreatetrigger.h
@@ -1,6 +1,7 @@
#ifndef SQLITECREATETRIGGER_H
#define SQLITECREATETRIGGER_H
+#include "sqliteddlwithdbcontext.h"
#include "sqlitequery.h"
#include "sqlitetablerelatedddl.h"
@@ -9,7 +10,7 @@
class SqliteExpr;
-class API_EXPORT SqliteCreateTrigger : public SqliteQuery, public SqliteTableRelatedDdl
+class API_EXPORT SqliteCreateTrigger : public SqliteQuery, public SqliteTableRelatedDdl, public SqliteDdlWithDbContext
{
public:
enum class Time
@@ -63,6 +64,8 @@ class API_EXPORT SqliteCreateTrigger : public SqliteQuery, public SqliteTableRel
SqliteStatement* clone();
QString getTargetTable() const;
+ QString getTargetDatabase() const;
+ void setTargetDatabase(const QString& database);
bool tempKw = false;
bool temporaryKw = false;
diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateview.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateview.cpp
index d1a8961..fe638db 100644
--- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateview.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateview.cpp
@@ -3,6 +3,7 @@
#include "sqlitequerytype.h"
#include "parser/statementtokenbuilder.h"
#include "common/global.h"
+#include "sqliteindexedcolumn.h"
SqliteCreateView::SqliteCreateView()
{
@@ -14,7 +15,7 @@ SqliteCreateView::SqliteCreateView(const SqliteCreateView& other) :
database(other.database), view(other.view)
{
DEEP_COPY_FIELD(SqliteSelect, select);
-
+ DEEP_COPY_COLLECTION(SqliteIndexedColumn, columns);
}
SqliteCreateView::SqliteCreateView(int temp, bool ifNotExists, const QString &name1, const QString &name2, SqliteSelect *select) :
@@ -41,6 +42,15 @@ SqliteCreateView::SqliteCreateView(int temp, bool ifNotExists, const QString &na
select->setParent(this);
}
+SqliteCreateView::SqliteCreateView(int temp, bool ifNotExists, const QString& name1, const QString& name2, SqliteSelect* select, const QList<SqliteIndexedColumn*>& columns)
+ : SqliteCreateView(temp, ifNotExists, name1, name2, select)
+{
+ this->columns = columns;
+
+ for (SqliteIndexedColumn* col : columns)
+ col->setParent(this);
+}
+
SqliteCreateView::~SqliteCreateView()
{
}
@@ -112,9 +122,24 @@ TokenList SqliteCreateView::rebuildTokensFromContents()
if (dialect == Dialect::Sqlite3 && !database.isNull())
builder.withOther(database, dialect).withOperator(".");
- builder.withOther(view, dialect).withSpace().withKeyword("AS").withStatement(select);
+ builder.withOther(view, dialect).withSpace();
+
+ if (columns.size() > 0)
+ builder.withParLeft().withStatementList<SqliteIndexedColumn>(columns).withParRight().withSpace();
+
+ builder.withKeyword("AS").withStatement(select);
builder.withOperator(";");
return builder.build();
}
+
+QString SqliteCreateView::getTargetDatabase() const
+{
+ return database;
+}
+
+void SqliteCreateView::setTargetDatabase(const QString& database)
+{
+ this->database = database;
+}
diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateview.h b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateview.h
index 4858227..1f46d5e 100644
--- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateview.h
+++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitecreateview.h
@@ -1,20 +1,26 @@
#ifndef SQLITECREATEVIEW_H
#define SQLITECREATEVIEW_H
+#include "sqliteddlwithdbcontext.h"
#include "sqlitequery.h"
+#include <QList>
#include <QString>
class SqliteSelect;
+class SqliteIndexedColumn;
-class API_EXPORT SqliteCreateView : public SqliteQuery
+class API_EXPORT SqliteCreateView : public SqliteQuery, public SqliteDdlWithDbContext
{
public:
SqliteCreateView();
SqliteCreateView(const SqliteCreateView& other);
SqliteCreateView(int temp, bool ifNotExists, const QString& name1, const QString& name2, SqliteSelect* select);
+ SqliteCreateView(int temp, bool ifNotExists, const QString& name1, const QString& name2, SqliteSelect* select, const QList<SqliteIndexedColumn*>& columns);
~SqliteCreateView();
SqliteStatement* clone();
+ QString getTargetDatabase() const;
+ void setTargetDatabase(const QString& database);
bool tempKw = false;
bool temporaryKw = false;
@@ -22,6 +28,7 @@ class API_EXPORT SqliteCreateView : public SqliteQuery
QString database = QString::null;
QString view = QString::null;
SqliteSelect* select = nullptr;
+ QList<SqliteIndexedColumn*> columns;
protected:
QStringList getDatabasesInStatement();
diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteddlwithdbcontext.h b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteddlwithdbcontext.h
new file mode 100644
index 0000000..cb64986
--- /dev/null
+++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteddlwithdbcontext.h
@@ -0,0 +1,16 @@
+#ifndef SQLITEDDLWITHDBCONTEXT_H
+#define SQLITEDDLWITHDBCONTEXT_H
+
+#include "coreSQLiteStudio_global.h"
+#include <QSharedPointer>
+
+class API_EXPORT SqliteDdlWithDbContext
+{
+ public:
+ virtual QString getTargetDatabase() const = 0;
+ virtual void setTargetDatabase(const QString& database) = 0;
+};
+
+typedef QSharedPointer<SqliteDdlWithDbContext> SqliteDdlWithDbContextPtr;
+
+#endif // SQLITEDDLWITHDBCONTEXT_H
diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteexpr.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteexpr.cpp
index b84a818..3009b4b 100644
--- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteexpr.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteexpr.cpp
@@ -91,7 +91,7 @@ QString SqliteExpr::notNullOp(SqliteExpr::NotNull value)
}
}
-SqliteStatement*SqliteExpr::clone()
+SqliteStatement* SqliteExpr::clone()
{
return new SqliteExpr(*this);
}
@@ -462,7 +462,11 @@ TokenList SqliteExpr::rebuildTokensFromContents()
if (distinctKw)
builder.withKeyword("DISTINCT");
- builder.withStatementList(exprList).withParRight();
+ if (star)
+ builder.withOperator("*").withParRight();
+ else
+ builder.withStatementList(exprList).withParRight();
+
break;
case SqliteExpr::Mode::SUB_EXPR:
builder.withParLeft().withStatement(expr1).withParRight();
diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteextendedindexedcolumn.h b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteextendedindexedcolumn.h
new file mode 100644
index 0000000..1ea6119
--- /dev/null
+++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteextendedindexedcolumn.h
@@ -0,0 +1,19 @@
+#ifndef SQLITEEXTENDEDINDEXEDCOLUMN_H
+#define SQLITEEXTENDEDINDEXEDCOLUMN_H
+
+#include "coreSQLiteStudio_global.h"
+#include <QSharedPointer>
+
+class API_EXPORT SqliteExtendedIndexedColumn
+{
+ public:
+ virtual QString getColumnName() const = 0;
+ virtual void setColumnName(const QString& name) = 0;
+ virtual QString getCollation() const = 0;
+ virtual void setCollation(const QString& name) = 0;
+ virtual void clearCollation() = 0;
+};
+
+typedef QSharedPointer<SqliteExtendedIndexedColumn> SqliteExtendedIndexedColumnPtr;
+
+#endif // SQLITEEXTENDEDINDEXEDCOLUMN_H
diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteindexedcolumn.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteindexedcolumn.cpp
index 5e65eab..142af06 100644
--- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteindexedcolumn.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteindexedcolumn.cpp
@@ -24,11 +24,26 @@ SqliteIndexedColumn::SqliteIndexedColumn(const QString& name)
this->name = name;
}
-SqliteStatement*SqliteIndexedColumn::clone()
+SqliteStatement* SqliteIndexedColumn::clone()
{
return new SqliteIndexedColumn(*this);
}
+QString SqliteIndexedColumn::getColumnName() const
+{
+ return name;
+}
+
+void SqliteIndexedColumn::setColumnName(const QString& name)
+{
+ this->name = name;
+}
+
+void SqliteIndexedColumn::setCollation(const QString& name)
+{
+ this->collate = name;
+}
+
QStringList SqliteIndexedColumn::getColumnsInStatement()
{
return getStrListFromValue(name);
@@ -50,3 +65,13 @@ TokenList SqliteIndexedColumn::rebuildTokensFromContents()
builder.withSortOrder(sortOrder);
return builder.build();
}
+
+QString SqliteIndexedColumn::getCollation() const
+{
+ return collate;
+}
+
+void SqliteIndexedColumn::clearCollation()
+{
+ collate.clear();
+}
diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteindexedcolumn.h b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteindexedcolumn.h
index c013d17..c0fe680 100644
--- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteindexedcolumn.h
+++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteindexedcolumn.h
@@ -3,9 +3,10 @@
#include "sqlitestatement.h"
#include "sqlitesortorder.h"
+#include "sqliteextendedindexedcolumn.h"
#include <QString>
-class API_EXPORT SqliteIndexedColumn : public SqliteStatement
+class API_EXPORT SqliteIndexedColumn : public SqliteStatement, public SqliteExtendedIndexedColumn
{
public:
SqliteIndexedColumn();
@@ -14,6 +15,11 @@ class API_EXPORT SqliteIndexedColumn : public SqliteStatement
explicit SqliteIndexedColumn(const QString& name);
SqliteStatement* clone();
+ QString getColumnName() const;
+ void setColumnName(const QString& name);
+ void setCollation(const QString& name);
+ QString getCollation() const;
+ void clearCollation();
QString name = QString::null;
SqliteSortOrder sortOrder = SqliteSortOrder::null;
diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteorderby.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteorderby.cpp
index 3bb1b44..8eb7b46 100644
--- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteorderby.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteorderby.cpp
@@ -30,6 +30,76 @@ SqliteStatement*SqliteOrderBy::clone()
return new SqliteOrderBy(*this);
}
+bool SqliteOrderBy::isSimpleColumn() const
+{
+ return !getColumnName().isEmpty();
+}
+
+QString SqliteOrderBy::getColumnName() const
+{
+ if (!expr)
+ return QString();
+
+ if (expr->mode == SqliteExpr::Mode::ID)
+ return expr->column;
+
+ if (expr->mode == SqliteExpr::Mode::COLLATE && expr->expr1 && expr->expr1->mode == SqliteExpr::Mode::ID)
+ return expr->expr1->literalValue.toString();
+
+ return QString();
+}
+
+QString SqliteOrderBy::getCollation() const
+{
+ if (expr->mode == SqliteExpr::Mode::COLLATE)
+ return expr->collation;
+
+ return QString();
+}
+
+QString SqliteOrderBy::getColumnString() const
+{
+ QString res = getColumnName();
+ if (res.isNull())
+ return expr->detokenize();
+
+ return res;
+}
+
+void SqliteOrderBy::setColumnName(const QString& name)
+{
+ if (expr && expr->mode == SqliteExpr::Mode::COLLATE)
+ {
+ safe_delete(expr->expr1);
+ expr->expr1 = new SqliteExpr();
+ expr->expr1->setParent(expr);
+ expr->expr1->initId(name);
+ }
+ else
+ {
+ safe_delete(expr);
+ expr = new SqliteExpr();
+ expr->setParent(this);
+ expr->initId(name);
+ }
+}
+
+void SqliteOrderBy::setCollation(const QString& name)
+{
+ if (expr && expr->mode == SqliteExpr::Mode::COLLATE)
+ {
+ expr->collation = name;
+ }
+ else
+ {
+ SqliteExpr* theExpr = expr;
+ SqliteExpr* collationExpr = new SqliteExpr();
+ collationExpr->initCollate(theExpr, name);
+ theExpr->setParent(collationExpr);
+ collationExpr->setParent(this);
+ }
+}
+
TokenList SqliteOrderBy::rebuildTokensFromContents()
{
StatementTokenBuilder builder;
@@ -39,3 +109,15 @@ TokenList SqliteOrderBy::rebuildTokensFromContents()
return builder.build();
}
+
+
+void SqliteOrderBy::clearCollation()
+{
+ if (expr->mode != SqliteExpr::Mode::COLLATE)
+ return;
+
+ SqliteExpr* tmpExpr = expr;
+ expr = tmpExpr->expr1;
+ expr->setParent(this);
+ delete tmpExpr;
+}
diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteorderby.h b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteorderby.h
index 598423d..4f75c78 100644
--- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteorderby.h
+++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqliteorderby.h
@@ -3,10 +3,11 @@
#include "sqlitestatement.h"
#include "sqlitesortorder.h"
+#include "sqliteextendedindexedcolumn.h"
class SqliteExpr;
-class API_EXPORT SqliteOrderBy : public SqliteStatement
+class API_EXPORT SqliteOrderBy : public SqliteStatement, public SqliteExtendedIndexedColumn
{
public:
SqliteOrderBy();
@@ -15,9 +16,16 @@ class API_EXPORT SqliteOrderBy : public SqliteStatement
~SqliteOrderBy();
SqliteStatement* clone();
+ bool isSimpleColumn() const;
+ QString getColumnName() const;
+ QString getCollation() const;
+ QString getColumnString() const;
+ void setColumnName(const QString& name);
+ void setCollation(const QString& name);
+ void clearCollation();
SqliteExpr* expr = nullptr;
- SqliteSortOrder order;
+ SqliteSortOrder order = SqliteSortOrder::null;
protected:
TokenList rebuildTokensFromContents();
diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitetablerelatedddl.h b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitetablerelatedddl.h
index 599849a..9de9be7 100644
--- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitetablerelatedddl.h
+++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitetablerelatedddl.h
@@ -2,6 +2,7 @@
#define SQLITETABLERELATEDDDL_H
#include "coreSQLiteStudio_global.h"
+#include <QSharedPointer>
class API_EXPORT SqliteTableRelatedDdl
{
diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitevacuum.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitevacuum.cpp
index 96ff7a4..9d595ed 100644
--- a/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitevacuum.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/parser/ast/sqlitevacuum.cpp
@@ -32,6 +32,9 @@ QStringList SqliteVacuum::getDatabasesInStatement()
TokenList SqliteVacuum::getDatabaseTokensInStatement()
{
+ if (!tokensMap.contains("nm"))
+ return TokenList();
+
return getTokenListFromNamedKey("nm");
}
diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/lexer.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/lexer.cpp
index c85b3ba..6be7528 100644
--- a/SQLiteStudio3/coreSQLiteStudio/parser/lexer.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/parser/lexer.cpp
@@ -3,6 +3,7 @@
#include "lexer_low_lev.h"
#include "sqlite2_parse.h"
#include "sqlite3_parse.h"
+#include "common/utils_sql.h"
#include <QString>
#include <QMultiHash>
#include <QDebug>
@@ -281,11 +282,41 @@ QString Lexer::detokenize(const TokenList& tokens)
QString str;
foreach (TokenPtr token, tokens)
- str += token->value;
+ str += detokenize(token);
return str;
}
+QString Lexer::detokenize(const TokenPtr& token)
+{
+ switch (token->type) {
+ case Token::OTHER:
+ case Token::CTX_ALIAS:
+ case Token::CTX_COLLATION:
+ case Token::CTX_COLUMN:
+ case Token::CTX_COLUMN_NEW:
+ case Token::CTX_COLUMN_TYPE:
+ case Token::CTX_CONSTRAINT:
+ case Token::CTX_DATABASE:
+ case Token::CTX_INDEX:
+ case Token::CTX_INDEX_NEW:
+ case Token::CTX_TABLE:
+ case Token::CTX_TABLE_NEW:
+ case Token::CTX_TRANSACTION:
+ case Token::CTX_TRIGGER:
+ case Token::CTX_TRIGGER_NEW:
+ case Token::CTX_VIEW:
+ case Token::CTX_VIEW_NEW:
+ return token->value.isEmpty() ? wrapObjName(token->value, Dialect::Sqlite3, NameWrapper::DOUBLE_QUOTE) : token->value;
+ case Token::CTX_ERROR_MESSAGE:
+ case Token::STRING:
+ return token->value.isEmpty() ? wrapString(token->value) : token->value;
+ default:
+ break;
+ }
+ return token->value;
+}
+
TokenList Lexer::tokenize(const QString& sql, Dialect dialect)
{
Lexer lexer(dialect);
diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/lexer.h b/SQLiteStudio3/coreSQLiteStudio/parser/lexer.h
index b21639e..8473844 100644
--- a/SQLiteStudio3/coreSQLiteStudio/parser/lexer.h
+++ b/SQLiteStudio3/coreSQLiteStudio/parser/lexer.h
@@ -129,6 +129,15 @@ class API_EXPORT Lexer
static QString detokenize(const TokenList& tokens);
/**
+ * @brief Translates token to string propert representation.
+ * @param token Token to translate.
+ * @return Translated string.
+ *
+ * This method applies wrappers where needed (for strings and ids).
+ */
+ static QString detokenize(const TokenPtr& token);
+
+ /**
* @brief Tokenizes given SQL query with given dialect.
* @param sql SQL query to tokenize.
* @param dialect SQLite dialect to use when tokenizing.
diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/sqlite3_parse.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/sqlite3_parse.cpp
index 9ff6487..43cc4a0 100644
--- a/SQLiteStudio3/coreSQLiteStudio/parser/sqlite3_parse.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/parser/sqlite3_parse.cpp
@@ -170,7 +170,7 @@ typedef union {
#define sqlite3_parseARG_PDECL ,ParserContext* parserContext
#define sqlite3_parseARG_FETCH ParserContext* parserContext = yypParser->parserContext
#define sqlite3_parseARG_STORE yypParser->parserContext = parserContext
-#define YYNSTATE 724
+#define YYNSTATE 725
#define YYNRULE 424
#define YYFALLBACK 1
#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
@@ -243,235 +243,237 @@ static const YYMINORTYPE yyzerominor = { 0 };
** shifting non-terminals after a reduce.
** yy_default[] Default action for each state.
*/
-#define YY_ACTTAB_COUNT (2263)
+#define YY_ACTTAB_COUNT (2285)
static const YYACTIONTYPE yy_action[] = {
- /* 0 */ 431, 48, 48, 47, 47, 47, 46, 216, 716, 339,
- /* 10 */ 643, 425, 51, 51, 51, 51, 44, 49, 49, 49,
- /* 20 */ 49, 48, 48, 47, 47, 47, 46, 216, 721, 1026,
- /* 30 */ 1026, 643, 131, 580, 51, 51, 51, 51, 411, 49,
- /* 40 */ 49, 49, 49, 48, 48, 47, 47, 47, 46, 216,
- /* 50 */ 579, 81, 58, 643, 157, 685, 301, 282, 1026, 1026,
- /* 60 */ 41, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026,
- /* 70 */ 1026, 1026, 563, 1026, 1026, 1026, 1026, 38, 39, 1026,
- /* 80 */ 1026, 1026, 1026, 1026, 40, 431, 528, 385, 716, 595,
- /* 90 */ 594, 280, 4, 377, 716, 630, 425, 642, 608, 422,
- /* 100 */ 12, 134, 687, 429, 562, 609, 483, 690, 331, 279,
- /* 110 */ 714, 713, 564, 565, 642, 689, 688, 687, 235, 506,
- /* 120 */ 60, 320, 610, 411, 47, 47, 47, 46, 216, 122,
- /* 130 */ 243, 213, 247, 59, 1142, 1142, 486, 609, 607, 603,
- /* 140 */ 685, 306, 485, 584, 716, 41, 507, 509, 642, 508,
- /* 150 */ 676, 9, 642, 144, 95, 281, 379, 276, 378, 132,
- /* 160 */ 297, 716, 38, 39, 601, 200, 199, 7, 355, 40,
- /* 170 */ 884, 307, 1134, 274, 249, 716, 17, 4, 884, 1134,
- /* 180 */ 56, 717, 642, 431, 422, 884, 329, 687, 429, 716,
- /* 190 */ 687, 643, 690, 687, 425, 690, 714, 713, 690, 642,
- /* 200 */ 689, 688, 687, 689, 688, 687, 689, 688, 687, 98,
- /* 210 */ 682, 240, 643, 218, 410, 884, 486, 884, 884, 483,
- /* 220 */ 716, 411, 239, 884, 303, 582, 512, 581, 884, 884,
- /* 230 */ 884, 884, 884, 642, 643, 676, 9, 642, 685, 217,
- /* 240 */ 245, 673, 102, 41, 287, 300, 714, 713, 67, 302,
- /* 250 */ 148, 307, 1133, 151, 306, 484, 81, 715, 97, 1133,
- /* 260 */ 38, 39, 551, 714, 713, 771, 130, 40, 946, 376,
- /* 270 */ 373, 372, 447, 46, 216, 4, 946, 714, 713, 334,
- /* 280 */ 642, 682, 422, 946, 606, 687, 429, 371, 448, 447,
- /* 290 */ 690, 714, 713, 304, 265, 146, 267, 642, 689, 688,
- /* 300 */ 687, 287, 68, 677, 691, 255, 362, 259, 359, 692,
- /* 310 */ 1027, 1027, 682, 946, 715, 946, 946, 447, 698, 234,
- /* 320 */ 386, 715, 714, 713, 773, 651, 946, 946, 946, 946,
- /* 330 */ 110, 642, 317, 676, 9, 642, 222, 677, 299, 52,
- /* 340 */ 53, 426, 289, 1027, 1027, 675, 675, 50, 50, 51,
- /* 350 */ 51, 51, 51, 716, 49, 49, 49, 49, 48, 48,
- /* 360 */ 47, 47, 47, 46, 216, 431, 428, 340, 716, 335,
- /* 370 */ 671, 670, 287, 283, 716, 138, 425, 209, 219, 430,
- /* 380 */ 268, 395, 651, 682, 336, 715, 715, 686, 187, 52,
- /* 390 */ 53, 426, 289, 715, 452, 675, 675, 50, 50, 51,
- /* 400 */ 51, 51, 51, 411, 49, 49, 49, 49, 48, 48,
- /* 410 */ 47, 47, 47, 46, 216, 91, 953, 716, 619, 712,
- /* 420 */ 685, 403, 382, 130, 710, 41, 376, 373, 372, 711,
- /* 430 */ 233, 953, 394, 311, 210, 593, 666, 384, 428, 16,
- /* 440 */ 316, 659, 38, 39, 371, 231, 230, 716, 89, 40,
- /* 450 */ 931, 430, 716, 658, 716, 714, 713, 4, 931, 686,
- /* 460 */ 92, 143, 642, 358, 422, 931, 674, 687, 429, 14,
- /* 470 */ 714, 713, 690, 131, 456, 551, 714, 713, 953, 642,
- /* 480 */ 689, 688, 687, 668, 667, 210, 593, 458, 384, 457,
- /* 490 */ 576, 88, 1027, 1027, 13, 931, 672, 931, 931, 54,
- /* 500 */ 575, 678, 42, 368, 37, 401, 35, 381, 931, 1,
- /* 510 */ 931, 931, 641, 642, 634, 676, 9, 642, 661, 714,
- /* 520 */ 713, 52, 53, 426, 289, 1027, 1027, 675, 675, 50,
- /* 530 */ 50, 51, 51, 51, 51, 660, 49, 49, 49, 49,
- /* 540 */ 48, 48, 47, 47, 47, 46, 216, 657, 648, 714,
- /* 550 */ 713, 496, 542, 569, 714, 713, 714, 713, 656, 691,
- /* 560 */ 543, 614, 320, 30, 692, 27, 716, 585, 274, 682,
- /* 570 */ 160, 1027, 1027, 426, 289, 693, 613, 675, 675, 50,
- /* 580 */ 50, 51, 51, 51, 51, 398, 49, 49, 49, 49,
- /* 590 */ 48, 48, 47, 47, 47, 46, 216, 1025, 1025, 81,
- /* 600 */ 52, 53, 426, 289, 1027, 1027, 675, 675, 50, 50,
- /* 610 */ 51, 51, 51, 51, 496, 49, 49, 49, 49, 48,
- /* 620 */ 48, 47, 47, 47, 46, 216, 1025, 1025, 1025, 1025,
- /* 630 */ 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025,
- /* 640 */ 716, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025,
- /* 650 */ 1025, 1025, 1027, 1027, 357, 49, 49, 49, 49, 48,
- /* 660 */ 48, 47, 47, 47, 46, 216, 288, 552, 714, 713,
- /* 670 */ 495, 682, 298, 662, 346, 153, 538, 69, 694, 715,
- /* 680 */ 715, 52, 53, 426, 289, 1027, 1027, 675, 675, 50,
- /* 690 */ 50, 51, 51, 51, 51, 1094, 49, 49, 49, 49,
- /* 700 */ 48, 48, 47, 47, 47, 46, 216, 52, 53, 426,
- /* 710 */ 289, 418, 511, 675, 675, 50, 50, 51, 51, 51,
- /* 720 */ 51, 159, 49, 49, 49, 49, 48, 48, 47, 47,
- /* 730 */ 47, 46, 216, 490, 954, 315, 482, 482, 663, 553,
- /* 740 */ 215, 650, 714, 713, 81, 52, 53, 426, 289, 954,
- /* 750 */ 414, 675, 675, 50, 50, 51, 51, 51, 51, 397,
- /* 760 */ 49, 49, 49, 49, 48, 48, 47, 47, 47, 46,
- /* 770 */ 216, 158, 1094, 21, 716, 627, 459, 716, 1079, 716,
- /* 780 */ 647, 1045, 140, 89, 716, 1149, 154, 435, 2, 715,
- /* 790 */ 424, 671, 670, 396, 460, 461, 954, 52, 53, 426,
- /* 800 */ 289, 573, 716, 675, 675, 50, 50, 51, 51, 51,
- /* 810 */ 51, 321, 49, 49, 49, 49, 48, 48, 47, 47,
- /* 820 */ 47, 46, 216, 431, 1108, 81, 206, 205, 204, 52,
- /* 830 */ 53, 426, 289, 716, 425, 675, 675, 50, 50, 51,
- /* 840 */ 51, 51, 51, 344, 49, 49, 49, 49, 48, 48,
- /* 850 */ 47, 47, 47, 46, 216, 597, 715, 666, 600, 462,
- /* 860 */ 666, 411, 31, 716, 657, 90, 12, 894, 720, 668,
- /* 870 */ 667, 609, 724, 434, 81, 656, 714, 713, 685, 714,
- /* 880 */ 713, 714, 713, 41, 528, 272, 714, 713, 610, 349,
- /* 890 */ 528, 450, 89, 677, 12, 633, 633, 338, 636, 609,
- /* 900 */ 38, 39, 649, 609, 714, 713, 716, 40, 1142, 1142,
- /* 910 */ 716, 524, 682, 581, 716, 4, 610, 468, 60, 450,
- /* 920 */ 642, 208, 422, 506, 60, 687, 429, 677, 32, 109,
- /* 930 */ 690, 609, 500, 501, 352, 714, 713, 642, 689, 688,
- /* 940 */ 687, 428, 900, 900, 467, 466, 552, 465, 421, 383,
- /* 950 */ 507, 509, 142, 508, 430, 440, 69, 1142, 1142, 715,
- /* 960 */ 444, 722, 686, 182, 646, 714, 713, 645, 231, 230,
- /* 970 */ 437, 642, 356, 676, 9, 642, 417, 444, 52, 53,
- /* 980 */ 426, 289, 91, 91, 675, 675, 50, 50, 51, 51,
- /* 990 */ 51, 51, 644, 49, 49, 49, 49, 48, 48, 47,
- /* 1000 */ 47, 47, 46, 216, 1034, 444, 668, 667, 714, 713,
- /* 1010 */ 91, 453, 714, 713, 682, 641, 714, 713, 324, 202,
- /* 1020 */ 52, 53, 426, 289, 446, 680, 675, 675, 50, 50,
- /* 1030 */ 51, 51, 51, 51, 639, 49, 49, 49, 49, 48,
- /* 1040 */ 48, 47, 47, 47, 46, 216, 605, 52, 53, 426,
- /* 1050 */ 289, 716, 446, 675, 675, 50, 50, 51, 51, 51,
- /* 1060 */ 51, 459, 49, 49, 49, 49, 48, 48, 47, 47,
- /* 1070 */ 47, 46, 216, 453, 715, 36, 663, 423, 215, 460,
- /* 1080 */ 341, 369, 592, 52, 53, 426, 289, 638, 89, 675,
- /* 1090 */ 675, 50, 50, 51, 51, 51, 51, 31, 49, 49,
- /* 1100 */ 49, 49, 48, 48, 47, 47, 47, 46, 216, 413,
- /* 1110 */ 723, 2, 11, 52, 53, 426, 289, 33, 588, 675,
- /* 1120 */ 675, 50, 50, 51, 51, 51, 51, 624, 49, 49,
- /* 1130 */ 49, 49, 48, 48, 47, 47, 47, 46, 216, 515,
- /* 1140 */ 715, 537, 29, 91, 342, 666, 140, 136, 571, 52,
- /* 1150 */ 53, 426, 289, 714, 713, 675, 675, 50, 50, 51,
- /* 1160 */ 51, 51, 51, 548, 49, 49, 49, 49, 48, 48,
- /* 1170 */ 47, 47, 47, 46, 216, 91, 716, 234, 386, 52,
- /* 1180 */ 53, 426, 289, 338, 271, 675, 675, 50, 50, 51,
- /* 1190 */ 51, 51, 51, 333, 49, 49, 49, 49, 48, 48,
- /* 1200 */ 47, 47, 47, 46, 216, 532, 8, 517, 696, 87,
- /* 1210 */ 137, 52, 53, 426, 289, 22, 557, 675, 675, 50,
- /* 1220 */ 50, 51, 51, 51, 51, 135, 49, 49, 49, 49,
- /* 1230 */ 48, 48, 47, 47, 47, 46, 216, 81, 1109, 91,
- /* 1240 */ 716, 91, 52, 53, 426, 289, 615, 722, 675, 675,
- /* 1250 */ 50, 50, 51, 51, 51, 51, 620, 49, 49, 49,
- /* 1260 */ 49, 48, 48, 47, 47, 47, 46, 216, 604, 1107,
- /* 1270 */ 99, 504, 390, 491, 52, 53, 426, 289, 714, 713,
- /* 1280 */ 675, 675, 50, 50, 51, 51, 51, 51, 682, 49,
- /* 1290 */ 49, 49, 49, 48, 48, 47, 47, 47, 46, 216,
- /* 1300 */ 226, 52, 57, 426, 289, 599, 388, 675, 675, 50,
- /* 1310 */ 50, 51, 51, 51, 51, 428, 49, 49, 49, 49,
- /* 1320 */ 48, 48, 47, 47, 47, 46, 216, 431, 430, 5,
- /* 1330 */ 10, 620, 620, 632, 491, 631, 686, 187, 425, 53,
- /* 1340 */ 426, 289, 714, 713, 675, 675, 50, 50, 51, 51,
- /* 1350 */ 51, 51, 716, 49, 49, 49, 49, 48, 48, 47,
- /* 1360 */ 47, 47, 46, 216, 552, 411, 598, 107, 464, 591,
- /* 1370 */ 403, 387, 428, 697, 69, 612, 611, 715, 428, 716,
- /* 1380 */ 404, 715, 685, 716, 209, 430, 209, 41, 625, 316,
- /* 1390 */ 682, 430, 596, 686, 187, 428, 223, 590, 539, 686,
- /* 1400 */ 187, 653, 287, 716, 38, 39, 589, 225, 430, 718,
- /* 1410 */ 431, 40, 620, 716, 91, 715, 686, 187, 252, 4,
- /* 1420 */ 570, 425, 715, 19, 642, 89, 422, 403, 405, 687,
- /* 1430 */ 429, 716, 624, 332, 690, 716, 428, 328, 716, 705,
- /* 1440 */ 716, 642, 689, 688, 687, 715, 316, 266, 411, 430,
- /* 1450 */ 561, 365, 316, 716, 714, 713, 602, 686, 187, 488,
- /* 1460 */ 715, 829, 716, 375, 65, 685, 308, 682, 540, 406,
- /* 1470 */ 41, 706, 285, 209, 273, 642, 475, 676, 9, 642,
- /* 1480 */ 530, 714, 713, 651, 715, 714, 713, 38, 39, 64,
- /* 1490 */ 18, 399, 370, 431, 40, 129, 716, 366, 326, 534,
- /* 1500 */ 534, 63, 4, 270, 425, 714, 713, 642, 475, 422,
- /* 1510 */ 316, 530, 687, 429, 716, 714, 713, 690, 279, 716,
- /* 1520 */ 533, 716, 156, 624, 642, 689, 688, 687, 525, 716,
- /* 1530 */ 125, 411, 519, 714, 713, 514, 715, 714, 713, 3,
- /* 1540 */ 714, 713, 714, 713, 79, 525, 682, 85, 685, 519,
- /* 1550 */ 479, 26, 514, 41, 25, 714, 713, 516, 642, 472,
- /* 1560 */ 676, 9, 642, 716, 714, 713, 407, 479, 716, 682,
- /* 1570 */ 38, 39, 353, 77, 286, 431, 510, 40, 283, 505,
- /* 1580 */ 555, 428, 616, 503, 83, 4, 425, 715, 140, 351,
- /* 1590 */ 642, 715, 422, 469, 430, 687, 429, 716, 714, 713,
- /* 1600 */ 690, 716, 686, 192, 472, 428, 703, 642, 689, 688,
- /* 1610 */ 687, 438, 428, 411, 497, 62, 714, 713, 430, 119,
- /* 1620 */ 254, 714, 713, 714, 713, 430, 686, 181, 438, 704,
- /* 1630 */ 685, 714, 713, 686, 163, 41, 251, 629, 311, 161,
- /* 1640 */ 138, 642, 715, 676, 9, 642, 455, 1035, 682, 531,
- /* 1650 */ 701, 702, 38, 39, 152, 641, 498, 469, 431, 40,
- /* 1660 */ 499, 478, 699, 428, 715, 714, 713, 4, 1037, 425,
- /* 1670 */ 714, 713, 642, 416, 422, 715, 430, 687, 429, 641,
- /* 1680 */ 428, 350, 690, 619, 686, 172, 641, 494, 454, 642,
- /* 1690 */ 689, 688, 687, 430, 111, 428, 411, 716, 72, 714,
- /* 1700 */ 713, 686, 190, 714, 713, 621, 287, 337, 430, 428,
- /* 1710 */ 436, 428, 96, 685, 209, 558, 686, 188, 41, 715,
- /* 1720 */ 567, 287, 430, 642, 430, 676, 9, 642, 716, 207,
- /* 1730 */ 686, 196, 686, 195, 715, 38, 39, 641, 716, 286,
- /* 1740 */ 431, 327, 40, 224, 86, 428, 695, 319, 203, 428,
- /* 1750 */ 4, 425, 715, 318, 641, 642, 325, 422, 430, 715,
- /* 1760 */ 687, 429, 430, 150, 261, 690, 686, 197, 221, 641,
- /* 1770 */ 686, 201, 642, 689, 688, 687, 428, 715, 411, 716,
- /* 1780 */ 719, 709, 708, 641, 433, 641, 707, 651, 258, 430,
- /* 1790 */ 428, 283, 220, 536, 428, 685, 149, 686, 232, 714,
- /* 1800 */ 713, 715, 651, 430, 715, 147, 642, 430, 676, 9,
- /* 1810 */ 642, 686, 290, 428, 82, 686, 191, 38, 39, 641,
- /* 1820 */ 679, 367, 432, 641, 40, 15, 430, 145, 700, 234,
- /* 1830 */ 714, 713, 4, 715, 686, 194, 408, 642, 420, 422,
- /* 1840 */ 714, 713, 687, 429, 716, 428, 684, 690, 637, 715,
- /* 1850 */ 641, 227, 428, 294, 642, 689, 688, 687, 430, 716,
- /* 1860 */ 293, 715, 428, 17, 641, 430, 686, 193, 641, 292,
- /* 1870 */ 400, 291, 402, 686, 185, 430, 521, 28, 683, 55,
- /* 1880 */ 428, 714, 713, 686, 189, 43, 428, 641, 642, 640,
- /* 1890 */ 676, 9, 642, 430, 216, 419, 428, 66, 529, 430,
- /* 1900 */ 428, 686, 314, 428, 229, 214, 228, 686, 313, 430,
- /* 1910 */ 428, 415, 34, 430, 141, 626, 430, 686, 312, 641,
- /* 1920 */ 428, 686, 184, 430, 686, 171, 641, 428, 715, 635,
- /* 1930 */ 139, 686, 170, 430, 108, 386, 641, 716, 463, 622,
- /* 1940 */ 430, 686, 183, 428, 617, 428, 714, 713, 686, 169,
- /* 1950 */ 428, 716, 715, 389, 641, 583, 430, 715, 430, 380,
- /* 1960 */ 641, 714, 713, 430, 686, 186, 686, 168, 428, 716,
- /* 1970 */ 641, 686, 167, 541, 641, 428, 578, 641, 716, 257,
- /* 1980 */ 133, 430, 577, 256, 641, 428, 474, 428, 430, 686,
- /* 1990 */ 93, 428, 715, 715, 641, 716, 686, 166, 430, 716,
- /* 2000 */ 430, 641, 330, 716, 430, 716, 686, 164, 686, 174,
- /* 2010 */ 428, 277, 686, 173, 393, 428, 275, 641, 716, 641,
- /* 2020 */ 716, 568, 574, 430, 641, 428, 573, 715, 430, 715,
- /* 2030 */ 428, 686, 175, 489, 715, 428, 686, 178, 430, 714,
- /* 2040 */ 713, 572, 641, 430, 716, 428, 686, 94, 430, 641,
- /* 2050 */ 310, 686, 177, 714, 713, 128, 686, 176, 430, 641,
- /* 2060 */ 554, 641, 549, 716, 428, 641, 686, 180, 716, 428,
- /* 2070 */ 716, 714, 713, 716, 392, 715, 547, 430, 546, 545,
- /* 2080 */ 714, 713, 430, 502, 641, 686, 179, 430, 544, 641,
- /* 2090 */ 686, 165, 527, 309, 80, 686, 70, 714, 713, 641,
- /* 2100 */ 535, 714, 713, 269, 641, 714, 713, 714, 713, 641,
- /* 2110 */ 127, 106, 471, 523, 248, 263, 715, 518, 481, 641,
- /* 2120 */ 714, 713, 714, 713, 476, 212, 246, 715, 715, 244,
- /* 2130 */ 477, 126, 492, 473, 480, 262, 242, 354, 641, 715,
- /* 2140 */ 470, 236, 715, 641, 360, 322, 714, 713, 641, 715,
- /* 2150 */ 347, 363, 24, 652, 715, 442, 427, 715, 443, 441,
- /* 2160 */ 124, 284, 526, 715, 648, 714, 713, 264, 715, 715,
- /* 2170 */ 714, 713, 714, 713, 715, 714, 713, 253, 78, 250,
- /* 2180 */ 715, 241, 237, 238, 105, 123, 121, 84, 104, 155,
- /* 2190 */ 715, 513, 715, 120, 715, 715, 715, 493, 348, 103,
- /* 2200 */ 118, 345, 76, 343, 117, 75, 116, 115, 114, 74,
- /* 2210 */ 73, 113, 23, 323, 451, 101, 20, 100, 623, 112,
- /* 2220 */ 61, 520, 449, 445, 439, 655, 628, 162, 278, 669,
- /* 2230 */ 665, 412, 569, 295, 681, 198, 374, 522, 618, 260,
- /* 2240 */ 361, 6, 305, 664, 654, 556, 364, 409, 566, 211,
- /* 2250 */ 296, 71, 560, 559, 487, 587, 586, 81, 550, 1150,
- /* 2260 */ 1150, 1150, 45,
+ /* 0 */ 432, 49, 49, 48, 48, 48, 47, 216, 717, 340,
+ /* 10 */ 644, 426, 52, 52, 52, 52, 45, 50, 50, 50,
+ /* 20 */ 50, 49, 49, 48, 48, 48, 47, 216, 722, 1027,
+ /* 30 */ 1027, 644, 131, 581, 52, 52, 52, 52, 412, 50,
+ /* 40 */ 50, 50, 50, 49, 49, 48, 48, 48, 47, 216,
+ /* 50 */ 580, 81, 59, 644, 157, 686, 302, 283, 1027, 1027,
+ /* 60 */ 42, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027,
+ /* 70 */ 1027, 1027, 564, 1027, 1027, 1027, 1027, 39, 40, 1027,
+ /* 80 */ 1027, 1027, 1027, 1027, 41, 432, 529, 386, 717, 596,
+ /* 90 */ 595, 281, 4, 378, 717, 631, 426, 643, 609, 423,
+ /* 100 */ 13, 134, 688, 430, 563, 610, 484, 691, 332, 280,
+ /* 110 */ 715, 714, 565, 566, 643, 690, 689, 688, 235, 507,
+ /* 120 */ 61, 321, 611, 412, 48, 48, 48, 47, 216, 122,
+ /* 130 */ 243, 213, 247, 60, 1143, 1143, 487, 610, 608, 604,
+ /* 140 */ 686, 307, 486, 585, 717, 42, 508, 510, 643, 509,
+ /* 150 */ 677, 9, 643, 144, 95, 282, 380, 277, 379, 132,
+ /* 160 */ 298, 717, 39, 40, 602, 200, 199, 7, 356, 41,
+ /* 170 */ 885, 308, 1135, 275, 249, 717, 18, 4, 885, 1135,
+ /* 180 */ 57, 718, 643, 432, 423, 885, 330, 688, 430, 717,
+ /* 190 */ 688, 644, 691, 688, 426, 691, 715, 714, 691, 643,
+ /* 200 */ 690, 689, 688, 690, 689, 688, 690, 689, 688, 98,
+ /* 210 */ 683, 240, 644, 218, 411, 885, 487, 885, 885, 484,
+ /* 220 */ 717, 412, 239, 885, 304, 583, 513, 582, 885, 885,
+ /* 230 */ 885, 885, 885, 643, 644, 677, 9, 643, 686, 217,
+ /* 240 */ 245, 674, 102, 42, 288, 301, 715, 714, 67, 303,
+ /* 250 */ 148, 308, 1134, 151, 307, 485, 81, 716, 97, 1134,
+ /* 260 */ 39, 40, 552, 715, 714, 772, 130, 41, 947, 377,
+ /* 270 */ 374, 373, 448, 47, 216, 4, 947, 715, 714, 335,
+ /* 280 */ 643, 683, 423, 947, 607, 688, 430, 372, 449, 448,
+ /* 290 */ 691, 715, 714, 305, 265, 146, 268, 643, 690, 689,
+ /* 300 */ 688, 288, 68, 678, 692, 255, 363, 259, 360, 693,
+ /* 310 */ 1028, 1028, 683, 947, 716, 947, 947, 448, 699, 234,
+ /* 320 */ 387, 716, 715, 714, 774, 652, 947, 947, 947, 947,
+ /* 330 */ 110, 643, 318, 677, 9, 643, 222, 678, 300, 53,
+ /* 340 */ 54, 427, 290, 1028, 1028, 676, 676, 51, 51, 52,
+ /* 350 */ 52, 52, 52, 717, 50, 50, 50, 50, 49, 49,
+ /* 360 */ 48, 48, 48, 47, 216, 432, 429, 341, 717, 336,
+ /* 370 */ 672, 671, 288, 284, 717, 138, 426, 209, 219, 431,
+ /* 380 */ 269, 396, 652, 683, 337, 716, 716, 687, 187, 53,
+ /* 390 */ 54, 427, 290, 716, 453, 676, 676, 51, 51, 52,
+ /* 400 */ 52, 52, 52, 412, 50, 50, 50, 50, 49, 49,
+ /* 410 */ 48, 48, 48, 47, 216, 91, 954, 717, 620, 713,
+ /* 420 */ 686, 404, 383, 130, 711, 42, 377, 374, 373, 712,
+ /* 430 */ 233, 954, 395, 312, 210, 594, 667, 385, 429, 17,
+ /* 440 */ 317, 660, 39, 40, 372, 231, 230, 717, 89, 41,
+ /* 450 */ 932, 431, 717, 659, 717, 715, 714, 4, 932, 687,
+ /* 460 */ 92, 143, 643, 359, 423, 932, 675, 688, 430, 15,
+ /* 470 */ 715, 714, 691, 131, 457, 552, 715, 714, 954, 643,
+ /* 480 */ 690, 689, 688, 669, 668, 210, 594, 459, 385, 458,
+ /* 490 */ 577, 88, 1028, 1028, 14, 932, 673, 932, 932, 55,
+ /* 500 */ 576, 679, 43, 369, 38, 402, 36, 382, 932, 1,
+ /* 510 */ 932, 932, 642, 643, 635, 677, 9, 643, 662, 715,
+ /* 520 */ 714, 53, 54, 427, 290, 1028, 1028, 676, 676, 51,
+ /* 530 */ 51, 52, 52, 52, 52, 661, 50, 50, 50, 50,
+ /* 540 */ 49, 49, 48, 48, 48, 47, 216, 658, 649, 715,
+ /* 550 */ 714, 497, 543, 570, 715, 714, 715, 714, 657, 692,
+ /* 560 */ 544, 615, 321, 31, 693, 28, 717, 586, 275, 683,
+ /* 570 */ 160, 1028, 1028, 427, 290, 694, 614, 676, 676, 51,
+ /* 580 */ 51, 52, 52, 52, 52, 399, 50, 50, 50, 50,
+ /* 590 */ 49, 49, 48, 48, 48, 47, 216, 1026, 1026, 81,
+ /* 600 */ 53, 54, 427, 290, 1028, 1028, 676, 676, 51, 51,
+ /* 610 */ 52, 52, 52, 52, 497, 50, 50, 50, 50, 49,
+ /* 620 */ 49, 48, 48, 48, 47, 216, 1026, 1026, 1026, 1026,
+ /* 630 */ 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026,
+ /* 640 */ 717, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026,
+ /* 650 */ 1026, 1026, 1028, 1028, 358, 50, 50, 50, 50, 49,
+ /* 660 */ 49, 48, 48, 48, 47, 216, 289, 553, 715, 714,
+ /* 670 */ 496, 683, 299, 663, 347, 153, 539, 69, 695, 716,
+ /* 680 */ 716, 53, 54, 427, 290, 1028, 1028, 676, 676, 51,
+ /* 690 */ 51, 52, 52, 52, 52, 1095, 50, 50, 50, 50,
+ /* 700 */ 49, 49, 48, 48, 48, 47, 216, 53, 54, 427,
+ /* 710 */ 290, 419, 512, 676, 676, 51, 51, 52, 52, 52,
+ /* 720 */ 52, 159, 50, 50, 50, 50, 49, 49, 48, 48,
+ /* 730 */ 48, 47, 216, 491, 955, 316, 483, 483, 664, 554,
+ /* 740 */ 215, 651, 715, 714, 81, 53, 54, 427, 290, 955,
+ /* 750 */ 415, 676, 676, 51, 51, 52, 52, 52, 52, 398,
+ /* 760 */ 50, 50, 50, 50, 49, 49, 48, 48, 48, 47,
+ /* 770 */ 216, 158, 1095, 22, 717, 628, 460, 717, 1080, 717,
+ /* 780 */ 648, 1046, 140, 89, 717, 1150, 154, 436, 2, 716,
+ /* 790 */ 425, 672, 671, 397, 461, 462, 955, 53, 54, 427,
+ /* 800 */ 290, 574, 717, 676, 676, 51, 51, 52, 52, 52,
+ /* 810 */ 52, 322, 50, 50, 50, 50, 49, 49, 48, 48,
+ /* 820 */ 48, 47, 216, 432, 1109, 81, 206, 205, 204, 53,
+ /* 830 */ 54, 427, 290, 717, 426, 676, 676, 51, 51, 52,
+ /* 840 */ 52, 52, 52, 345, 50, 50, 50, 50, 49, 49,
+ /* 850 */ 48, 48, 48, 47, 216, 598, 716, 667, 601, 463,
+ /* 860 */ 667, 412, 32, 717, 658, 90, 13, 895, 721, 669,
+ /* 870 */ 668, 610, 725, 435, 81, 657, 715, 714, 686, 715,
+ /* 880 */ 714, 715, 714, 42, 529, 273, 715, 714, 611, 350,
+ /* 890 */ 529, 451, 89, 678, 13, 634, 634, 339, 637, 610,
+ /* 900 */ 39, 40, 650, 610, 715, 714, 717, 41, 1143, 1143,
+ /* 910 */ 717, 525, 683, 582, 717, 4, 611, 469, 61, 451,
+ /* 920 */ 643, 208, 423, 507, 61, 688, 430, 678, 33, 109,
+ /* 930 */ 691, 610, 501, 502, 353, 715, 714, 643, 690, 689,
+ /* 940 */ 688, 429, 901, 901, 468, 467, 553, 466, 422, 384,
+ /* 950 */ 508, 510, 142, 509, 431, 441, 69, 1143, 1143, 716,
+ /* 960 */ 445, 723, 687, 182, 647, 715, 714, 646, 231, 230,
+ /* 970 */ 438, 643, 357, 677, 9, 643, 418, 445, 53, 54,
+ /* 980 */ 427, 290, 91, 91, 676, 676, 51, 51, 52, 52,
+ /* 990 */ 52, 52, 645, 50, 50, 50, 50, 49, 49, 48,
+ /* 1000 */ 48, 48, 47, 216, 1035, 445, 669, 668, 715, 714,
+ /* 1010 */ 91, 454, 715, 714, 683, 642, 715, 714, 325, 202,
+ /* 1020 */ 53, 54, 427, 290, 447, 681, 676, 676, 51, 51,
+ /* 1030 */ 52, 52, 52, 52, 640, 50, 50, 50, 50, 49,
+ /* 1040 */ 49, 48, 48, 48, 47, 216, 606, 53, 54, 427,
+ /* 1050 */ 290, 717, 447, 676, 676, 51, 51, 52, 52, 52,
+ /* 1060 */ 52, 460, 50, 50, 50, 50, 49, 49, 48, 48,
+ /* 1070 */ 48, 47, 216, 454, 716, 37, 664, 424, 215, 461,
+ /* 1080 */ 342, 370, 593, 53, 54, 427, 290, 639, 89, 676,
+ /* 1090 */ 676, 51, 51, 52, 52, 52, 52, 32, 50, 50,
+ /* 1100 */ 50, 50, 49, 49, 48, 48, 48, 47, 216, 414,
+ /* 1110 */ 724, 2, 12, 53, 54, 427, 290, 34, 589, 676,
+ /* 1120 */ 676, 51, 51, 52, 52, 52, 52, 625, 50, 50,
+ /* 1130 */ 50, 50, 49, 49, 48, 48, 48, 47, 216, 516,
+ /* 1140 */ 716, 538, 30, 91, 343, 667, 140, 136, 572, 53,
+ /* 1150 */ 54, 427, 290, 715, 714, 676, 676, 51, 51, 52,
+ /* 1160 */ 52, 52, 52, 549, 50, 50, 50, 50, 49, 49,
+ /* 1170 */ 48, 48, 48, 47, 216, 91, 717, 234, 387, 53,
+ /* 1180 */ 54, 427, 290, 339, 272, 676, 676, 51, 51, 52,
+ /* 1190 */ 52, 52, 52, 334, 50, 50, 50, 50, 49, 49,
+ /* 1200 */ 48, 48, 48, 47, 216, 533, 8, 518, 697, 87,
+ /* 1210 */ 137, 53, 54, 427, 290, 23, 558, 676, 676, 51,
+ /* 1220 */ 51, 52, 52, 52, 52, 135, 50, 50, 50, 50,
+ /* 1230 */ 49, 49, 48, 48, 48, 47, 216, 81, 1110, 91,
+ /* 1240 */ 717, 91, 53, 54, 427, 290, 616, 723, 676, 676,
+ /* 1250 */ 51, 51, 52, 52, 52, 52, 605, 50, 50, 50,
+ /* 1260 */ 50, 49, 49, 48, 48, 48, 47, 216, 99, 1108,
+ /* 1270 */ 391, 505, 389, 492, 53, 54, 427, 290, 715, 714,
+ /* 1280 */ 676, 676, 51, 51, 52, 52, 52, 52, 621, 50,
+ /* 1290 */ 50, 50, 50, 49, 49, 48, 48, 48, 47, 216,
+ /* 1300 */ 683, 53, 58, 427, 290, 683, 600, 676, 676, 51,
+ /* 1310 */ 51, 52, 52, 52, 52, 429, 50, 50, 50, 50,
+ /* 1320 */ 49, 49, 48, 48, 48, 47, 216, 432, 431, 717,
+ /* 1330 */ 5, 621, 226, 633, 492, 632, 687, 187, 426, 54,
+ /* 1340 */ 427, 290, 715, 714, 676, 676, 51, 51, 52, 52,
+ /* 1350 */ 52, 52, 717, 50, 50, 50, 50, 49, 49, 48,
+ /* 1360 */ 48, 48, 47, 216, 553, 412, 288, 599, 287, 717,
+ /* 1370 */ 404, 388, 429, 698, 69, 613, 252, 716, 429, 716,
+ /* 1380 */ 405, 716, 686, 30, 209, 431, 209, 42, 626, 317,
+ /* 1390 */ 489, 431, 597, 687, 187, 429, 223, 309, 540, 687,
+ /* 1400 */ 187, 329, 683, 717, 39, 40, 11, 683, 431, 287,
+ /* 1410 */ 432, 41, 621, 654, 91, 592, 687, 92, 556, 4,
+ /* 1420 */ 571, 426, 716, 625, 643, 537, 423, 404, 406, 688,
+ /* 1430 */ 430, 715, 714, 333, 691, 717, 716, 429, 717, 591,
+ /* 1440 */ 717, 643, 690, 689, 688, 107, 317, 652, 412, 531,
+ /* 1450 */ 431, 590, 317, 717, 715, 714, 612, 830, 687, 187,
+ /* 1460 */ 429, 225, 326, 717, 541, 686, 526, 417, 20, 642,
+ /* 1470 */ 42, 715, 714, 431, 683, 643, 717, 677, 9, 643,
+ /* 1480 */ 531, 687, 187, 526, 562, 717, 621, 39, 40, 327,
+ /* 1490 */ 376, 65, 64, 432, 41, 274, 19, 266, 371, 535,
+ /* 1500 */ 535, 267, 4, 271, 426, 715, 714, 643, 421, 423,
+ /* 1510 */ 716, 407, 688, 430, 286, 400, 717, 691, 717, 280,
+ /* 1520 */ 717, 63, 129, 429, 643, 690, 689, 688, 367, 717,
+ /* 1530 */ 603, 412, 520, 534, 317, 515, 431, 715, 714, 156,
+ /* 1540 */ 715, 714, 715, 714, 687, 192, 717, 209, 686, 520,
+ /* 1550 */ 480, 465, 515, 42, 717, 715, 714, 3, 643, 717,
+ /* 1560 */ 677, 9, 643, 717, 716, 715, 714, 480, 138, 125,
+ /* 1570 */ 39, 40, 85, 476, 79, 432, 683, 41, 715, 714,
+ /* 1580 */ 27, 429, 473, 511, 717, 4, 426, 715, 714, 517,
+ /* 1590 */ 643, 532, 423, 408, 431, 688, 430, 642, 26, 719,
+ /* 1600 */ 691, 717, 687, 181, 77, 476, 506, 643, 690, 689,
+ /* 1610 */ 688, 620, 716, 412, 354, 470, 706, 439, 715, 714,
+ /* 1620 */ 715, 714, 715, 714, 261, 288, 717, 473, 221, 504,
+ /* 1630 */ 686, 715, 714, 704, 439, 42, 717, 716, 716, 568,
+ /* 1640 */ 83, 643, 140, 677, 9, 643, 498, 1036, 715, 714,
+ /* 1650 */ 702, 284, 39, 40, 254, 642, 715, 714, 432, 41,
+ /* 1660 */ 328, 715, 714, 429, 716, 715, 714, 4, 1038, 426,
+ /* 1670 */ 119, 10, 643, 503, 423, 707, 431, 688, 430, 470,
+ /* 1680 */ 429, 161, 691, 251, 687, 163, 715, 714, 716, 643,
+ /* 1690 */ 690, 689, 688, 431, 717, 429, 412, 152, 479, 456,
+ /* 1700 */ 455, 687, 172, 715, 714, 72, 652, 705, 431, 429,
+ /* 1710 */ 630, 312, 111, 686, 530, 338, 687, 190, 42, 437,
+ /* 1720 */ 716, 622, 431, 643, 96, 677, 9, 643, 715, 714,
+ /* 1730 */ 687, 188, 209, 717, 207, 39, 40, 642, 715, 714,
+ /* 1740 */ 432, 224, 41, 617, 86, 429, 703, 717, 203, 429,
+ /* 1750 */ 4, 426, 320, 720, 642, 643, 150, 423, 431, 716,
+ /* 1760 */ 688, 430, 431, 700, 429, 691, 687, 196, 475, 642,
+ /* 1770 */ 687, 195, 643, 690, 689, 688, 716, 431, 412, 717,
+ /* 1780 */ 319, 710, 717, 642, 522, 687, 197, 709, 708, 258,
+ /* 1790 */ 499, 429, 434, 220, 500, 686, 715, 714, 625, 16,
+ /* 1800 */ 42, 717, 716, 257, 431, 717, 643, 256, 677, 9,
+ /* 1810 */ 643, 716, 687, 201, 717, 351, 716, 39, 40, 642,
+ /* 1820 */ 149, 248, 432, 642, 41, 482, 147, 246, 433, 442,
+ /* 1830 */ 368, 478, 4, 426, 716, 715, 714, 643, 642, 423,
+ /* 1840 */ 716, 717, 715, 430, 82, 701, 429, 691, 685, 715,
+ /* 1850 */ 714, 145, 495, 234, 643, 690, 689, 688, 429, 431,
+ /* 1860 */ 412, 559, 244, 284, 352, 642, 474, 687, 232, 18,
+ /* 1870 */ 242, 431, 401, 429, 471, 716, 716, 686, 295, 687,
+ /* 1880 */ 291, 715, 714, 716, 715, 714, 431, 294, 643, 696,
+ /* 1890 */ 677, 9, 643, 542, 687, 191, 528, 293, 680, 39,
+ /* 1900 */ 40, 717, 716, 715, 714, 429, 41, 715, 714, 429,
+ /* 1910 */ 490, 716, 292, 29, 4, 493, 715, 714, 431, 643,
+ /* 1920 */ 642, 423, 431, 227, 688, 430, 687, 194, 429, 691,
+ /* 1930 */ 687, 193, 642, 429, 477, 429, 643, 690, 689, 688,
+ /* 1940 */ 429, 431, 717, 715, 714, 429, 431, 642, 431, 687,
+ /* 1950 */ 185, 717, 403, 431, 687, 189, 687, 315, 431, 717,
+ /* 1960 */ 216, 687, 314, 429, 409, 684, 687, 313, 717, 429,
+ /* 1970 */ 643, 56, 677, 9, 643, 44, 431, 716, 717, 642,
+ /* 1980 */ 638, 627, 431, 642, 687, 184, 623, 420, 236, 653,
+ /* 1990 */ 687, 171, 323, 716, 716, 641, 229, 66, 214, 716,
+ /* 2000 */ 429, 716, 642, 715, 714, 618, 35, 642, 228, 642,
+ /* 2010 */ 429, 133, 394, 431, 642, 524, 276, 429, 716, 642,
+ /* 2020 */ 429, 687, 170, 431, 716, 716, 636, 569, 416, 716,
+ /* 2030 */ 431, 687, 183, 431, 429, 550, 429, 642, 687, 169,
+ /* 2040 */ 716, 687, 186, 642, 715, 714, 429, 431, 716, 431,
+ /* 2050 */ 141, 429, 108, 715, 714, 687, 168, 687, 167, 431,
+ /* 2060 */ 139, 715, 714, 270, 431, 519, 429, 687, 93, 390,
+ /* 2070 */ 715, 714, 687, 166, 642, 717, 716, 429, 584, 431,
+ /* 2080 */ 715, 714, 481, 429, 642, 717, 381, 687, 164, 717,
+ /* 2090 */ 431, 642, 444, 579, 642, 578, 431, 387, 687, 174,
+ /* 2100 */ 429, 263, 429, 472, 687, 173, 429, 331, 642, 278,
+ /* 2110 */ 642, 574, 575, 431, 716, 431, 429, 361, 464, 431,
+ /* 2120 */ 642, 687, 175, 687, 178, 642, 429, 687, 94, 431,
+ /* 2130 */ 716, 429, 573, 429, 555, 548, 348, 687, 177, 431,
+ /* 2140 */ 642, 547, 546, 545, 431, 429, 431, 687, 176, 716,
+ /* 2150 */ 393, 642, 687, 180, 687, 179, 443, 642, 431, 536,
+ /* 2160 */ 428, 128, 285, 431, 311, 310, 687, 165, 80, 716,
+ /* 2170 */ 264, 687, 70, 716, 642, 716, 642, 715, 714, 366,
+ /* 2180 */ 642, 649, 253, 716, 106, 250, 127, 715, 714, 241,
+ /* 2190 */ 642, 715, 714, 237, 126, 716, 238, 262, 716, 355,
+ /* 2200 */ 642, 212, 716, 25, 124, 642, 716, 642, 527, 716,
+ /* 2210 */ 364, 78, 105, 123, 121, 155, 84, 514, 104, 642,
+ /* 2220 */ 120, 349, 494, 624, 642, 346, 103, 118, 76, 344,
+ /* 2230 */ 117, 75, 116, 115, 74, 73, 114, 521, 324, 113,
+ /* 2240 */ 24, 452, 450, 21, 101, 100, 112, 446, 62, 440,
+ /* 2250 */ 162, 296, 670, 666, 656, 413, 279, 619, 570, 198,
+ /* 2260 */ 629, 375, 523, 260, 362, 306, 6, 71, 682, 665,
+ /* 2270 */ 655, 557, 211, 297, 410, 567, 365, 46, 551, 561,
+ /* 2280 */ 560, 488, 588, 81, 587,
};
static const YYCODETYPE yy_lookahead[] = {
/* 0 */ 4, 81, 82, 83, 84, 85, 86, 87, 4, 58,
@@ -599,271 +601,273 @@ static const YYCODETYPE yy_lookahead[] = {
/* 1220 */ 71, 72, 73, 74, 75, 97, 77, 78, 79, 80,
/* 1230 */ 81, 82, 83, 84, 85, 86, 87, 55, 89, 219,
/* 1240 */ 4, 219, 62, 63, 64, 65, 30, 89, 68, 69,
- /* 1250 */ 70, 71, 72, 73, 74, 75, 191, 77, 78, 79,
- /* 1260 */ 80, 81, 82, 83, 84, 85, 86, 87, 144, 89,
- /* 1270 */ 99, 89, 99, 101, 62, 63, 64, 65, 106, 107,
- /* 1280 */ 68, 69, 70, 71, 72, 73, 74, 75, 4, 77,
+ /* 1250 */ 70, 71, 72, 73, 74, 75, 144, 77, 78, 79,
+ /* 1260 */ 80, 81, 82, 83, 84, 85, 86, 87, 99, 89,
+ /* 1270 */ 99, 89, 104, 101, 62, 63, 64, 65, 106, 107,
+ /* 1280 */ 68, 69, 70, 71, 72, 73, 74, 75, 191, 77,
/* 1290 */ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
- /* 1300 */ 235, 62, 63, 64, 65, 83, 104, 68, 69, 70,
+ /* 1300 */ 4, 62, 63, 64, 65, 4, 83, 68, 69, 70,
/* 1310 */ 71, 72, 73, 74, 75, 177, 77, 78, 79, 80,
- /* 1320 */ 81, 82, 83, 84, 85, 86, 87, 4, 190, 96,
- /* 1330 */ 96, 191, 191, 201, 162, 201, 198, 199, 15, 63,
+ /* 1320 */ 81, 82, 83, 84, 85, 86, 87, 4, 190, 4,
+ /* 1330 */ 96, 191, 235, 201, 162, 201, 198, 199, 15, 63,
/* 1340 */ 64, 65, 106, 107, 68, 69, 70, 71, 72, 73,
/* 1350 */ 74, 75, 4, 77, 78, 79, 80, 81, 82, 83,
- /* 1360 */ 84, 85, 86, 87, 177, 42, 97, 17, 177, 97,
- /* 1370 */ 232, 233, 177, 186, 187, 235, 235, 190, 177, 4,
- /* 1380 */ 185, 190, 59, 4, 252, 190, 252, 64, 152, 251,
- /* 1390 */ 106, 190, 135, 198, 199, 177, 209, 97, 211, 198,
- /* 1400 */ 199, 117, 177, 4, 81, 82, 97, 38, 190, 177,
- /* 1410 */ 4, 88, 191, 4, 219, 190, 198, 199, 97, 96,
- /* 1420 */ 97, 15, 190, 96, 101, 104, 103, 232, 233, 106,
- /* 1430 */ 107, 4, 177, 232, 111, 4, 177, 212, 4, 91,
- /* 1440 */ 4, 118, 119, 120, 121, 190, 251, 177, 42, 190,
- /* 1450 */ 6, 181, 251, 4, 106, 107, 235, 198, 199, 97,
- /* 1460 */ 190, 97, 4, 38, 96, 59, 104, 4, 104, 251,
- /* 1470 */ 64, 177, 254, 252, 97, 152, 101, 154, 155, 156,
- /* 1480 */ 101, 106, 107, 258, 190, 106, 107, 81, 82, 96,
- /* 1490 */ 96, 232, 38, 4, 88, 115, 4, 64, 243, 100,
- /* 1500 */ 101, 96, 96, 97, 15, 106, 107, 101, 133, 103,
- /* 1510 */ 251, 132, 106, 107, 4, 106, 107, 111, 129, 4,
- /* 1520 */ 103, 4, 98, 177, 118, 119, 120, 121, 101, 4,
- /* 1530 */ 123, 42, 101, 106, 107, 101, 190, 106, 107, 12,
- /* 1540 */ 106, 107, 106, 107, 142, 118, 4, 128, 59, 118,
- /* 1550 */ 101, 71, 118, 64, 71, 106, 107, 139, 152, 101,
- /* 1560 */ 154, 155, 156, 4, 106, 107, 157, 118, 4, 106,
- /* 1570 */ 81, 82, 22, 153, 177, 4, 89, 88, 177, 89,
- /* 1580 */ 117, 177, 146, 47, 39, 96, 15, 190, 104, 243,
- /* 1590 */ 101, 190, 103, 101, 190, 106, 107, 4, 106, 107,
- /* 1600 */ 111, 4, 198, 199, 146, 177, 91, 118, 119, 120,
- /* 1610 */ 121, 101, 177, 42, 39, 96, 106, 107, 190, 123,
- /* 1620 */ 161, 106, 107, 106, 107, 190, 198, 199, 118, 177,
- /* 1630 */ 59, 106, 107, 198, 199, 64, 95, 236, 237, 96,
- /* 1640 */ 98, 152, 190, 154, 155, 156, 97, 158, 106, 132,
- /* 1650 */ 91, 177, 81, 82, 143, 251, 7, 165, 4, 88,
- /* 1660 */ 11, 103, 177, 177, 190, 106, 107, 96, 97, 15,
- /* 1670 */ 106, 107, 101, 276, 103, 190, 190, 106, 107, 251,
- /* 1680 */ 177, 32, 111, 141, 198, 199, 251, 162, 97, 118,
- /* 1690 */ 119, 120, 121, 190, 93, 177, 42, 4, 95, 106,
- /* 1700 */ 107, 198, 199, 106, 107, 141, 177, 37, 190, 177,
- /* 1710 */ 36, 177, 189, 59, 252, 118, 198, 199, 64, 190,
- /* 1720 */ 127, 177, 190, 152, 190, 154, 155, 156, 4, 238,
- /* 1730 */ 198, 199, 198, 199, 190, 81, 82, 251, 4, 177,
- /* 1740 */ 4, 212, 88, 204, 204, 177, 177, 275, 273, 177,
- /* 1750 */ 96, 15, 190, 275, 251, 101, 212, 103, 190, 190,
- /* 1760 */ 106, 107, 190, 90, 177, 111, 198, 199, 181, 251,
- /* 1770 */ 198, 199, 118, 119, 120, 121, 177, 190, 42, 4,
- /* 1780 */ 176, 176, 176, 251, 176, 251, 49, 258, 177, 190,
- /* 1790 */ 177, 177, 181, 100, 177, 59, 178, 198, 199, 106,
- /* 1800 */ 107, 190, 258, 190, 190, 178, 152, 190, 154, 155,
- /* 1810 */ 156, 198, 199, 177, 180, 198, 199, 81, 82, 251,
- /* 1820 */ 177, 60, 183, 251, 88, 104, 190, 56, 184, 138,
- /* 1830 */ 106, 107, 96, 190, 198, 199, 177, 101, 276, 103,
- /* 1840 */ 106, 107, 106, 107, 4, 177, 221, 111, 177, 190,
- /* 1850 */ 251, 237, 177, 227, 118, 119, 120, 121, 190, 4,
- /* 1860 */ 228, 190, 177, 151, 251, 190, 198, 199, 251, 229,
- /* 1870 */ 148, 230, 147, 198, 199, 190, 152, 149, 231, 150,
- /* 1880 */ 177, 106, 107, 198, 199, 252, 177, 251, 152, 64,
- /* 1890 */ 154, 155, 156, 190, 87, 203, 177, 96, 164, 190,
- /* 1900 */ 177, 198, 199, 177, 259, 87, 255, 198, 199, 190,
- /* 1910 */ 177, 203, 158, 190, 99, 177, 190, 198, 199, 251,
- /* 1920 */ 177, 198, 199, 190, 198, 199, 251, 177, 190, 241,
- /* 1930 */ 241, 198, 199, 190, 99, 139, 251, 4, 163, 177,
- /* 1940 */ 190, 198, 199, 177, 177, 177, 106, 107, 198, 199,
- /* 1950 */ 177, 4, 190, 223, 251, 200, 190, 190, 190, 123,
- /* 1960 */ 251, 106, 107, 190, 198, 199, 198, 199, 177, 4,
- /* 1970 */ 251, 198, 199, 118, 251, 177, 200, 251, 4, 177,
- /* 1980 */ 177, 190, 208, 181, 251, 177, 146, 177, 190, 198,
- /* 1990 */ 199, 177, 190, 190, 251, 4, 198, 199, 190, 4,
- /* 2000 */ 190, 251, 31, 4, 190, 4, 198, 199, 198, 199,
- /* 2010 */ 177, 200, 198, 199, 177, 177, 177, 251, 4, 251,
- /* 2020 */ 4, 177, 202, 190, 251, 177, 122, 190, 190, 190,
- /* 2030 */ 177, 198, 199, 100, 190, 177, 198, 199, 190, 106,
- /* 2040 */ 107, 200, 251, 190, 4, 177, 198, 199, 190, 251,
- /* 2050 */ 203, 198, 199, 106, 107, 99, 198, 199, 190, 251,
- /* 2060 */ 208, 251, 177, 4, 177, 251, 198, 199, 4, 177,
- /* 2070 */ 4, 106, 107, 4, 177, 190, 200, 190, 200, 200,
- /* 2080 */ 106, 107, 190, 118, 251, 198, 199, 190, 200, 251,
- /* 2090 */ 198, 199, 118, 203, 180, 198, 199, 106, 107, 251,
- /* 2100 */ 241, 106, 107, 177, 251, 106, 107, 106, 107, 251,
- /* 2110 */ 99, 180, 165, 118, 177, 177, 190, 118, 181, 251,
- /* 2120 */ 106, 107, 106, 107, 133, 241, 177, 190, 190, 177,
- /* 2130 */ 181, 99, 118, 181, 118, 264, 177, 27, 251, 190,
- /* 2140 */ 181, 177, 190, 251, 177, 181, 106, 107, 251, 190,
- /* 2150 */ 177, 265, 158, 152, 190, 177, 177, 190, 118, 100,
- /* 2160 */ 99, 177, 227, 190, 100, 106, 107, 177, 190, 190,
- /* 2170 */ 106, 107, 106, 107, 190, 106, 107, 177, 215, 177,
- /* 2180 */ 190, 177, 177, 177, 62, 99, 99, 96, 180, 250,
- /* 2190 */ 190, 215, 190, 99, 190, 190, 190, 227, 241, 180,
- /* 2200 */ 99, 241, 217, 60, 99, 217, 99, 99, 99, 217,
- /* 2210 */ 217, 99, 268, 241, 18, 99, 268, 99, 152, 99,
- /* 2220 */ 270, 152, 241, 241, 16, 201, 240, 224, 201, 261,
- /* 2230 */ 261, 256, 206, 226, 191, 210, 202, 227, 242, 242,
- /* 2240 */ 242, 224, 175, 191, 191, 191, 263, 216, 207, 262,
- /* 2250 */ 222, 239, 207, 207, 274, 198, 198, 55, 211, 277,
- /* 2260 */ 277, 277, 253,
+ /* 1360 */ 84, 85, 86, 87, 177, 42, 177, 97, 177, 4,
+ /* 1370 */ 232, 233, 177, 186, 187, 235, 97, 190, 177, 190,
+ /* 1380 */ 185, 190, 59, 104, 252, 190, 252, 64, 152, 251,
+ /* 1390 */ 97, 190, 135, 198, 199, 177, 209, 104, 211, 198,
+ /* 1400 */ 199, 212, 106, 4, 81, 82, 96, 106, 190, 177,
+ /* 1410 */ 4, 88, 191, 117, 219, 97, 198, 199, 117, 96,
+ /* 1420 */ 97, 15, 190, 177, 101, 100, 103, 232, 233, 106,
+ /* 1430 */ 107, 106, 107, 232, 111, 4, 190, 177, 4, 97,
+ /* 1440 */ 4, 118, 119, 120, 121, 17, 251, 258, 42, 101,
+ /* 1450 */ 190, 97, 251, 4, 106, 107, 235, 97, 198, 199,
+ /* 1460 */ 177, 38, 244, 4, 104, 59, 101, 276, 96, 251,
+ /* 1470 */ 64, 106, 107, 190, 4, 152, 4, 154, 155, 156,
+ /* 1480 */ 132, 198, 199, 118, 6, 4, 191, 81, 82, 243,
+ /* 1490 */ 38, 96, 96, 4, 88, 97, 96, 177, 38, 100,
+ /* 1500 */ 101, 181, 96, 97, 15, 106, 107, 101, 276, 103,
+ /* 1510 */ 190, 251, 106, 107, 254, 232, 4, 111, 4, 129,
+ /* 1520 */ 4, 96, 115, 177, 118, 119, 120, 121, 64, 4,
+ /* 1530 */ 235, 42, 101, 103, 251, 101, 190, 106, 107, 98,
+ /* 1540 */ 106, 107, 106, 107, 198, 199, 4, 252, 59, 118,
+ /* 1550 */ 101, 177, 118, 64, 4, 106, 107, 12, 152, 4,
+ /* 1560 */ 154, 155, 156, 4, 190, 106, 107, 118, 98, 123,
+ /* 1570 */ 81, 82, 128, 101, 142, 4, 106, 88, 106, 107,
+ /* 1580 */ 71, 177, 101, 89, 4, 96, 15, 106, 107, 139,
+ /* 1590 */ 101, 132, 103, 157, 190, 106, 107, 251, 71, 177,
+ /* 1600 */ 111, 4, 198, 199, 153, 133, 89, 118, 119, 120,
+ /* 1610 */ 121, 141, 190, 42, 22, 101, 91, 101, 106, 107,
+ /* 1620 */ 106, 107, 106, 107, 177, 177, 4, 146, 181, 47,
+ /* 1630 */ 59, 106, 107, 91, 118, 64, 4, 190, 190, 127,
+ /* 1640 */ 39, 152, 104, 154, 155, 156, 39, 158, 106, 107,
+ /* 1650 */ 91, 177, 81, 82, 161, 251, 106, 107, 4, 88,
+ /* 1660 */ 212, 106, 107, 177, 190, 106, 107, 96, 97, 15,
+ /* 1670 */ 123, 96, 101, 118, 103, 177, 190, 106, 107, 165,
+ /* 1680 */ 177, 96, 111, 95, 198, 199, 106, 107, 190, 118,
+ /* 1690 */ 119, 120, 121, 190, 4, 177, 42, 143, 103, 97,
+ /* 1700 */ 97, 198, 199, 106, 107, 95, 258, 177, 190, 177,
+ /* 1710 */ 236, 237, 93, 59, 164, 37, 198, 199, 64, 36,
+ /* 1720 */ 190, 141, 190, 152, 189, 154, 155, 156, 106, 107,
+ /* 1730 */ 198, 199, 252, 4, 238, 81, 82, 251, 106, 107,
+ /* 1740 */ 4, 204, 88, 146, 204, 177, 177, 4, 273, 177,
+ /* 1750 */ 96, 15, 275, 176, 251, 101, 90, 103, 190, 190,
+ /* 1760 */ 106, 107, 190, 177, 177, 111, 198, 199, 146, 251,
+ /* 1770 */ 198, 199, 118, 119, 120, 121, 190, 190, 42, 4,
+ /* 1780 */ 275, 176, 4, 251, 152, 198, 199, 176, 49, 177,
+ /* 1790 */ 7, 177, 176, 181, 11, 59, 106, 107, 177, 104,
+ /* 1800 */ 64, 4, 190, 177, 190, 4, 152, 181, 154, 155,
+ /* 1810 */ 156, 190, 198, 199, 4, 32, 190, 81, 82, 251,
+ /* 1820 */ 178, 177, 4, 251, 88, 181, 178, 177, 183, 100,
+ /* 1830 */ 60, 181, 96, 15, 190, 106, 107, 101, 251, 103,
+ /* 1840 */ 190, 4, 106, 107, 180, 184, 177, 111, 221, 106,
+ /* 1850 */ 107, 56, 162, 138, 118, 119, 120, 121, 177, 190,
+ /* 1860 */ 42, 118, 177, 177, 243, 251, 181, 198, 199, 151,
+ /* 1870 */ 177, 190, 148, 177, 181, 190, 190, 59, 227, 198,
+ /* 1880 */ 199, 106, 107, 190, 106, 107, 190, 228, 152, 177,
+ /* 1890 */ 154, 155, 156, 118, 198, 199, 118, 229, 177, 81,
+ /* 1900 */ 82, 4, 190, 106, 107, 177, 88, 106, 107, 177,
+ /* 1910 */ 100, 190, 230, 149, 96, 118, 106, 107, 190, 101,
+ /* 1920 */ 251, 103, 190, 237, 106, 107, 198, 199, 177, 111,
+ /* 1930 */ 198, 199, 251, 177, 133, 177, 118, 119, 120, 121,
+ /* 1940 */ 177, 190, 4, 106, 107, 177, 190, 251, 190, 198,
+ /* 1950 */ 199, 4, 147, 190, 198, 199, 198, 199, 190, 4,
+ /* 1960 */ 87, 198, 199, 177, 177, 231, 198, 199, 4, 177,
+ /* 1970 */ 152, 150, 154, 155, 156, 252, 190, 190, 4, 251,
+ /* 1980 */ 177, 177, 190, 251, 198, 199, 177, 203, 177, 152,
+ /* 1990 */ 198, 199, 181, 190, 190, 64, 259, 96, 87, 190,
+ /* 2000 */ 177, 190, 251, 106, 107, 177, 158, 251, 255, 251,
+ /* 2010 */ 177, 177, 177, 190, 251, 118, 177, 177, 190, 251,
+ /* 2020 */ 177, 198, 199, 190, 190, 190, 241, 177, 203, 190,
+ /* 2030 */ 190, 198, 199, 190, 177, 177, 177, 251, 198, 199,
+ /* 2040 */ 190, 198, 199, 251, 106, 107, 177, 190, 190, 190,
+ /* 2050 */ 99, 177, 99, 106, 107, 198, 199, 198, 199, 190,
+ /* 2060 */ 241, 106, 107, 177, 190, 118, 177, 198, 199, 223,
+ /* 2070 */ 106, 107, 198, 199, 251, 4, 190, 177, 200, 190,
+ /* 2080 */ 106, 107, 118, 177, 251, 4, 123, 198, 199, 4,
+ /* 2090 */ 190, 251, 118, 200, 251, 208, 190, 139, 198, 199,
+ /* 2100 */ 177, 177, 177, 165, 198, 199, 177, 31, 251, 200,
+ /* 2110 */ 251, 122, 202, 190, 190, 190, 177, 177, 163, 190,
+ /* 2120 */ 251, 198, 199, 198, 199, 251, 177, 198, 199, 190,
+ /* 2130 */ 190, 177, 200, 177, 208, 200, 177, 198, 199, 190,
+ /* 2140 */ 251, 200, 200, 200, 190, 177, 190, 198, 199, 190,
+ /* 2150 */ 177, 251, 198, 199, 198, 199, 177, 251, 190, 241,
+ /* 2160 */ 177, 99, 177, 190, 203, 203, 198, 199, 180, 190,
+ /* 2170 */ 177, 198, 199, 190, 251, 190, 251, 106, 107, 203,
+ /* 2180 */ 251, 100, 177, 190, 180, 177, 99, 106, 107, 177,
+ /* 2190 */ 251, 106, 107, 177, 99, 190, 177, 264, 190, 27,
+ /* 2200 */ 251, 241, 190, 158, 99, 251, 190, 251, 227, 190,
+ /* 2210 */ 265, 215, 62, 99, 99, 250, 96, 215, 180, 251,
+ /* 2220 */ 99, 241, 227, 152, 251, 241, 180, 99, 217, 60,
+ /* 2230 */ 99, 217, 99, 99, 217, 217, 99, 152, 241, 99,
+ /* 2240 */ 268, 18, 241, 268, 99, 99, 99, 241, 270, 16,
+ /* 2250 */ 224, 226, 261, 261, 201, 256, 201, 242, 206, 210,
+ /* 2260 */ 240, 202, 227, 242, 242, 175, 224, 239, 191, 191,
+ /* 2270 */ 191, 191, 262, 222, 216, 207, 263, 253, 211, 207,
+ /* 2280 */ 207, 274, 198, 55, 198,
};
#define YY_SHIFT_USE_DFLT (-81)
-#define YY_SHIFT_COUNT (434)
+#define YY_SHIFT_COUNT (435)
#define YY_SHIFT_MIN (-80)
-#define YY_SHIFT_MAX (2208)
+#define YY_SHIFT_MAX (2233)
static const short yy_shift_ofst[] = {
/* 0 */ 1158, -4, 201, 1182, 819, 1571, 1571, 689, 361, 1489,
- /* 10 */ 1654, 1654, 770, 364, 364, 157, 81, 179, 1406, 1323,
- /* 20 */ 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654,
+ /* 10 */ 1654, 1654, 1654, 770, 364, 364, 157, 81, 179, 1406,
+ /* 20 */ 1323, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654,
/* 30 */ 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654,
/* 40 */ 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1654,
- /* 50 */ 1654, 1654, 1654, 1654, 1654, 1654, 1654, 1736, 370, 798,
- /* 60 */ 181, 370, 2001, 2001, 2001, 2001, 2001, 887, 887, 565,
- /* 70 */ 277, 4, 1510, 1492, 1458, 1375, 1449, 1434, 1431, 1427,
- /* 80 */ 1379, 448, 1399, 2066, 2066, 2069, 439, 2066, 2064, 2001,
+ /* 50 */ 1654, 1654, 1654, 1654, 1654, 1654, 1736, 1654, 1818, 370,
+ /* 60 */ 798, 181, 370, 1837, 1837, 1837, 1837, 887, 887, 565,
+ /* 70 */ 277, 4, 1516, 1514, 1481, 1472, 1449, 1434, 1431, 1365,
+ /* 80 */ 1348, 448, 1399, 2071, 2071, 2085, 439, 2071, 2081, 1837,
/* 90 */ 565, 1039, 538, 538, 735, 84, 44, 171, 859, 775,
/* 100 */ 906, 773, 910, 636, 1172, 5, 450, 5, 443, 413,
- /* 110 */ 185, 2059, 2040, 1775, 1947, 1840, 1991, 2016, 1933, 2014,
- /* 120 */ 1525, 1999, 1724, 1995, 1974, 1965, 1734, 1517, 1693, 1855,
- /* 130 */ 1047, 1593, 1597, 902, 140, 1542, 1542, 1436, 1564, 1542,
- /* 140 */ 1236, 780, 1409, 349, 562, 216, 620, 1559, 1515, 1348,
- /* 150 */ 90, 829, 829, 829, 872, 544, 2202, 2202, 2202, 2202,
- /* 160 */ 2202, -81, -81, 459, 619, 619, 619, 619, 619, 619,
+ /* 110 */ 185, 1729, 1974, 1955, 1938, 1622, 1801, 1964, 1810, 1797,
+ /* 120 */ 1690, 1947, 1632, 1897, 1778, 1555, 1550, 1459, 1325, 1775,
+ /* 130 */ 1047, 1512, 1743, 902, 140, 1470, 1470, 1597, 1580, 1470,
+ /* 140 */ 1236, 780, 1436, 349, 562, 216, 620, 1559, 1542, 1525,
+ /* 150 */ 90, 829, 829, 829, 872, 544, 2228, 2228, 2228, 2228,
+ /* 160 */ 2228, -81, -81, 459, 619, 619, 619, 619, 619, 619,
/* 170 */ 619, 619, 619, 645, 327, 683, 1180, 1149, 1117, 1087,
/* 180 */ 1051, 1021, 985, 958, 916, 767, 1239, 1212, 1276, 509,
/* 190 */ 509, -60, -38, -38, -38, -38, 578, -80, 314, 87,
/* 200 */ 87, 41, 155, 75, 58, 58, 58, -6, 186, 862,
- /* 210 */ -47, 808, 1649, 1463, 1284, 206, 908, 424, 400, 25,
- /* 220 */ 729, 729, 679, 1364, -2, 855, 729, 442, 346, 855,
- /* 230 */ 750, 750, 187, -9, 169, 2208, 2120, 2118, 2116, 2196,
- /* 240 */ 2196, 2112, 2109, 2143, 2108, 2143, 2107, 2143, 2105, 2143,
- /* 250 */ 2101, 1761, 1712, 2094, 1761, 2122, 2091, 2087, 2086, 2122,
- /* 260 */ 1712, 2061, 1994, 2110, 2032, 1761, 2011, 1761, 1956, 1801,
- /* 270 */ 1836, 1836, 1836, 1836, 1971, 1801, 1836, 1904, 1836, 1971,
- /* 280 */ 1836, 1836, 1796, 1835, 1815, 1754, 1801, 1818, 1801, 1825,
- /* 290 */ 1807, 1729, 1725, 1728, 1722, 1712, 1691, 1771, 1721, 1761,
- /* 300 */ 1737, 1737, 1673, 1673, 1673, 1673, -81, -81, -81, -81,
- /* 310 */ -81, -81, -81, -81, -81, -81, 564, 79, 158, 45,
- /* 320 */ 702, 243, -49, 398, 1362, 1321, 1042, 984, 788, 2,
- /* 330 */ 471, -20, 758, 678, 344, 144, -44, 1674, 1670, 1601,
- /* 340 */ 1603, 1591, 1549, 1558, 1543, 1511, 1541, 1519, 1496, 1459,
- /* 350 */ 1575, 1484, 1545, 1536, 1550, 1490, 1487, 1418, 1420, 1483,
- /* 360 */ 1480, 1419, 1402, 1527, 1407, 1424, 1417, 1433, 1389, 1380,
- /* 370 */ 1405, 1454, 1394, 1393, 1377, 1368, 1425, 1444, 1327, 1369,
- /* 380 */ 1350, 1309, 1300, 1272, 1202, 1257, 1234, 1269, 1233, 1202,
- /* 390 */ 1222, 1173, 1171, 1124, 1128, 1050, 1216, 1197, 1113, 993,
- /* 400 */ 1193, 1038, 1099, 993, 990, 937, 846, 895, 870, 848,
- /* 410 */ 867, 825, 757, 805, 675, 652, 571, 644, 625, 613,
- /* 420 */ 571, 438, 474, 421, 399, 406, 355, 362, 231, 225,
- /* 430 */ 166, 143, 63, -37, -61,
+ /* 210 */ -47, 808, 1783, 1301, 1296, 206, 908, 424, 400, 25,
+ /* 220 */ 729, 729, 679, 1360, -2, 855, 729, 442, 346, 855,
+ /* 230 */ 750, 750, 187, -9, 169, 2233, 2147, 2146, 2145, 2223,
+ /* 240 */ 2223, 2140, 2137, 2169, 2134, 2169, 2133, 2169, 2131, 2169,
+ /* 250 */ 2128, 1770, 1718, 2121, 1770, 2150, 2120, 2115, 2114, 2150,
+ /* 260 */ 1718, 2105, 2045, 2172, 2095, 1770, 2087, 1901, 1770, 2062,
+ /* 270 */ 1901, 1963, 1963, 1963, 1963, 2076, 1901, 1963, 1989, 1963,
+ /* 280 */ 2076, 1963, 1963, 1958, 1953, 1951, 1848, 1901, 1911, 1901,
+ /* 290 */ 1931, 1873, 1821, 1805, 1764, 1724, 1718, 1715, 1795, 1695,
+ /* 300 */ 1770, 1739, 1739, 1666, 1666, 1666, 1666, -81, -81, -81,
+ /* 310 */ -81, -81, -81, -81, -81, -81, -81, 564, 79, 158,
+ /* 320 */ 45, 702, 243, -49, 398, 1293, 1279, 1042, 984, 788,
+ /* 330 */ 2, 471, -20, 758, 678, 344, 144, -44, 1683, 1678,
+ /* 340 */ 1619, 1610, 1603, 1602, 1595, 1585, 1554, 1588, 1575, 1547,
+ /* 350 */ 1493, 1607, 1538, 1601, 1582, 1592, 1517, 1494, 1450, 1451,
+ /* 360 */ 1527, 1509, 1444, 1432, 1545, 1446, 1441, 1430, 1464, 1390,
+ /* 370 */ 1407, 1425, 1460, 1400, 1396, 1398, 1395, 1452, 1478, 1372,
+ /* 380 */ 1423, 1428, 1354, 1342, 1318, 1168, 1257, 1310, 1270, 1234,
+ /* 390 */ 1168, 1223, 1171, 1169, 1112, 1128, 1050, 1216, 1197, 1113,
+ /* 400 */ 993, 1193, 1038, 1099, 993, 990, 937, 846, 895, 870,
+ /* 410 */ 848, 867, 825, 757, 805, 675, 652, 571, 644, 625,
+ /* 420 */ 613, 571, 438, 474, 421, 399, 406, 355, 362, 231,
+ /* 430 */ 225, 166, 143, 63, -37, -61,
};
#define YY_REDUCE_USE_DFLT (-100)
-#define YY_REDUCE_COUNT (315)
+#define YY_REDUCE_COUNT (316)
#define YY_REDUCE_MIN (-99)
-#define YY_REDUCE_MAX (2067)
+#define YY_REDUCE_MAX (2090)
static const short yy_reduce_ofst[] = {
- /* 0 */ 615, 1195, 699, -99, 764, 1138, 189, 705, 1259, 1218,
- /* 10 */ 1201, 261, 196, 884, 599, 1187, 1897, 1892, 1887, 1868,
- /* 20 */ 1858, 1853, 1848, 1838, 1833, 1814, 1810, 1808, 1798, 1791,
- /* 30 */ 1773, 1768, 1766, 1750, 1743, 1733, 1726, 1723, 1719, 1709,
- /* 40 */ 1703, 1685, 1675, 1668, 1636, 1617, 1613, 1599, 1572, 1568,
- /* 50 */ 1534, 1532, 1518, 1503, 1486, 1435, 1428, 1404, 490, 1401,
- /* 60 */ 214, 769, 1544, 1529, 1225, 124, 67, 596, 175, 547,
- /* 70 */ 1221, 1614, 1964, 1959, 1952, 1949, 1937, 1802, 1611, 1587,
- /* 80 */ 1270, 1562, 203, 1346, 1255, 131, 347, 950, 1397, 195,
- /* 90 */ 885, 265, 1134, 1132, 125, 377, 1011, 2006, 2005, 1979,
- /* 100 */ 1671, 1671, 2004, 2002, 2000, 697, 1990, 11, 1671, 1984,
- /* 110 */ 1979, 1978, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1973,
- /* 120 */ 1671, 1671, 1967, 1671, 1671, 1938, 1671, 1671, 1671, 1926,
- /* 130 */ 1885, 1844, 1839, 1837, 1803, 1141, 1140, 1767, 1762, 1065,
- /* 140 */ 1738, 1671, 1659, 1643, 1569, 1485, 632, 1474, 1452, 1294,
- /* 150 */ 1232, 1191, 666, 489, 938, 1022, 1020, 956, 924, 791,
- /* 160 */ 763, 746, 205, 1462, 1462, 1462, 1462, 1462, 1462, 1462,
- /* 170 */ 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462,
- /* 180 */ 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462,
- /* 190 */ 1462, 1462, 1462, 1462, 1462, 1462, 1462, 1462, 2047, 2058,
- /* 200 */ 2057, 1462, 1980, 1980, 2046, 2045, 2041, 2012, 2031, 2009,
- /* 210 */ 2028, 1983, 1987, 2054, 2053, 2052, 2043, 2017, 2067, 2010,
- /* 220 */ 1998, 1997, 2034, 2025, 2026, 2027, 1996, 1986, 1975, 2024,
- /* 230 */ 1969, 1968, 1462, 2007, 2003, 1950, 1859, 1982, 1981, 1948,
- /* 240 */ 1944, 1972, 1859, 1993, 1859, 1992, 1859, 1988, 1859, 1985,
- /* 250 */ 1960, 2019, 1970, 1957, 2008, 1976, 1939, 1859, 1859, 1963,
- /* 260 */ 1935, 1859, 1886, 1871, 1884, 1931, 1859, 1914, 1859, 1890,
- /* 270 */ 1888, 1879, 1878, 1876, 1852, 1847, 1841, 1820, 1811, 1774,
- /* 280 */ 1776, 1755, 1730, 1689, 1688, 1651, 1708, 1645, 1692, 1633,
- /* 290 */ 1462, 1647, 1641, 1640, 1632, 1626, 1625, 1644, 1639, 1634,
- /* 300 */ 1627, 1618, 1608, 1606, 1605, 1604, 1478, 1472, 1475, 1540,
- /* 310 */ 1539, 1491, 1462, 1462, 1462, 1523,
+ /* 0 */ 615, 1195, 699, -99, 764, 1138, 189, 705, 1283, 1260,
+ /* 10 */ 1218, 1201, 261, 196, 884, 599, 1187, 1973, 1968, 1956,
+ /* 20 */ 1954, 1949, 1939, 1929, 1925, 1923, 1906, 1900, 1889, 1874,
+ /* 30 */ 1869, 1859, 1857, 1843, 1840, 1833, 1823, 1792, 1786, 1768,
+ /* 40 */ 1763, 1758, 1756, 1751, 1732, 1728, 1696, 1681, 1669, 1614,
+ /* 50 */ 1587, 1572, 1568, 1532, 1518, 1503, 1486, 1404, 1346, 490,
+ /* 60 */ 1474, 214, 769, 1448, 1189, 124, 67, 596, 175, 547,
+ /* 70 */ 1295, 1686, 1811, 1693, 1685, 1650, 1644, 1626, 1612, 1447,
+ /* 80 */ 1320, 1232, 203, 1621, 1246, 131, 347, 950, 1191, 195,
+ /* 90 */ 885, 265, 1134, 1132, 125, 377, 1011, 2019, 2016, 1983,
+ /* 100 */ 1803, 1803, 2012, 2008, 2005, 697, 1993, 11, 1803, 1985,
+ /* 110 */ 1983, 1979, 1803, 1803, 1803, 1803, 1803, 1803, 1803, 1959,
+ /* 120 */ 1803, 1803, 1940, 1803, 1803, 1924, 1803, 1803, 1803, 1886,
+ /* 130 */ 1858, 1850, 1839, 1835, 1834, 1221, 1140, 1828, 1809, 1097,
+ /* 140 */ 1804, 1803, 1787, 1721, 1712, 1586, 632, 1569, 1530, 1498,
+ /* 150 */ 1422, 1374, 666, 489, 938, 1022, 1020, 956, 924, 791,
+ /* 160 */ 763, 746, 205, 1480, 1480, 1480, 1480, 1480, 1480, 1480,
+ /* 170 */ 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480,
+ /* 180 */ 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480,
+ /* 190 */ 1480, 1480, 1480, 1480, 1480, 1480, 1480, 1480, 2067, 2086,
+ /* 200 */ 2084, 1480, 2007, 2007, 2073, 2072, 2068, 2028, 2058, 2024,
+ /* 210 */ 2051, 2013, 2010, 2080, 2079, 2078, 2077, 2042, 2090, 2035,
+ /* 220 */ 2022, 2021, 2059, 2049, 2052, 2055, 2015, 2020, 1999, 2053,
+ /* 230 */ 1992, 1991, 1480, 2025, 2026, 1978, 1918, 2006, 2001, 1975,
+ /* 240 */ 1972, 1997, 1918, 2018, 1918, 2017, 1918, 2014, 1918, 2011,
+ /* 250 */ 1984, 2046, 1995, 1980, 2038, 2002, 1965, 1918, 1918, 1996,
+ /* 260 */ 1981, 1918, 1945, 1933, 1960, 2004, 1918, 1976, 1988, 1918,
+ /* 270 */ 1962, 1943, 1942, 1941, 1935, 1926, 1961, 1932, 1910, 1909,
+ /* 280 */ 1887, 1893, 1878, 1846, 1819, 1785, 1753, 1825, 1737, 1784,
+ /* 290 */ 1723, 1480, 1734, 1682, 1668, 1659, 1651, 1627, 1661, 1645,
+ /* 300 */ 1664, 1648, 1642, 1616, 1611, 1605, 1577, 1505, 1477, 1475,
+ /* 310 */ 1540, 1537, 1496, 1480, 1480, 1480, 1535,
};
static const YYACTIONTYPE yy_default[] = {
- /* 0 */ 729, 1037, 1142, 1142, 1026, 1026, 1026, 1142, 1026, 1026,
- /* 10 */ 1026, 1026, 900, 1148, 1148, 1148, 1026, 1026, 1026, 1026,
- /* 20 */ 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026,
- /* 30 */ 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026,
- /* 40 */ 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026,
- /* 50 */ 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1015, 1148, 894,
- /* 60 */ 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 774,
- /* 70 */ 890, 900, 1148, 1148, 1148, 1148, 1148, 962, 949, 940,
- /* 80 */ 1148, 1148, 1148, 972, 972, 955, 842, 972, 1148, 1148,
- /* 90 */ 1148, 1148, 928, 928, 1027, 1148, 766, 1112, 1117, 1013,
- /* 100 */ 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 901, 1148,
- /* 110 */ 1013, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148,
- /* 120 */ 1148, 963, 956, 950, 941, 1148, 1148, 1148, 1148, 1148,
- /* 130 */ 1148, 1148, 1148, 1148, 1148, 890, 890, 1148, 1148, 890,
- /* 140 */ 1148, 1148, 1148, 1014, 1148, 1148, 763, 1148, 1148, 1148,
- /* 150 */ 735, 1058, 1148, 1148, 729, 1142, 1142, 1142, 1142, 1142,
- /* 160 */ 1142, 1135, 880, 935, 906, 945, 933, 937, 1038, 1031,
- /* 170 */ 1032, 1030, 936, 1027, 1027, 1027, 1027, 1027, 1027, 1027,
- /* 180 */ 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 988, 1000,
- /* 190 */ 987, 995, 1004, 999, 996, 990, 989, 991, 1148, 1148,
- /* 200 */ 1148, 992, 1148, 1148, 1148, 1148, 1148, 893, 1148, 1148,
- /* 210 */ 864, 1148, 1086, 1148, 1148, 776, 1148, 878, 738, 944,
- /* 220 */ 918, 918, 809, 833, 798, 928, 918, 908, 1033, 928,
- /* 230 */ 1148, 1148, 993, 891, 878, 1126, 909, 909, 909, 1111,
- /* 240 */ 1111, 909, 909, 855, 909, 855, 909, 855, 909, 855,
- /* 250 */ 909, 760, 944, 909, 760, 846, 968, 909, 909, 846,
- /* 260 */ 944, 909, 1093, 1091, 909, 760, 909, 760, 909, 1046,
- /* 270 */ 844, 844, 844, 844, 825, 1046, 844, 809, 844, 825,
- /* 280 */ 844, 844, 1148, 909, 909, 1148, 1046, 1052, 1046, 1027,
- /* 290 */ 994, 934, 922, 932, 929, 944, 1148, 757, 828, 760,
- /* 300 */ 746, 746, 734, 734, 734, 734, 1139, 1139, 1135, 811,
- /* 310 */ 811, 896, 1003, 1002, 1001, 785, 1039, 1148, 1148, 1148,
- /* 320 */ 1148, 1148, 1148, 1060, 1148, 1148, 1148, 1148, 1148, 1148,
- /* 330 */ 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 730, 1148,
- /* 340 */ 1148, 1148, 1148, 1148, 1129, 1148, 1148, 1148, 1148, 1148,
- /* 350 */ 1148, 1090, 1089, 1148, 1148, 1148, 1148, 1148, 1148, 1148,
- /* 360 */ 1148, 1148, 1148, 1078, 1148, 1148, 1148, 1148, 1148, 1148,
- /* 370 */ 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148,
- /* 380 */ 1148, 1148, 1148, 1148, 867, 869, 1148, 1148, 1148, 868,
- /* 390 */ 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 930,
- /* 400 */ 1148, 923, 1148, 1036, 1148, 1017, 1025, 1148, 1148, 1148,
- /* 410 */ 1148, 1148, 1016, 1148, 1148, 1148, 1144, 1148, 1148, 1148,
- /* 420 */ 1143, 1148, 1148, 1148, 1148, 1148, 1028, 980, 1148, 979,
- /* 430 */ 978, 769, 1148, 744, 1148, 726, 731, 1128, 1125, 1127,
- /* 440 */ 1122, 1123, 1121, 1124, 1120, 1118, 1119, 1116, 1114, 1113,
- /* 450 */ 1115, 1110, 1106, 1066, 1064, 1062, 1071, 1070, 1069, 1068,
- /* 460 */ 1067, 1063, 1061, 1065, 1059, 959, 947, 938, 862, 1105,
- /* 470 */ 1103, 1104, 1057, 1055, 1056, 861, 860, 859, 854, 853,
- /* 480 */ 852, 851, 1132, 1141, 1140, 1138, 1137, 1136, 1130, 1131,
- /* 490 */ 1044, 1043, 1041, 1040, 1042, 762, 1082, 1085, 1084, 1083,
- /* 500 */ 1088, 1087, 1080, 1092, 1097, 1096, 1101, 1100, 1099, 1098,
- /* 510 */ 1095, 1077, 967, 966, 964, 969, 961, 960, 965, 952,
- /* 520 */ 958, 957, 948, 951, 847, 943, 939, 942, 863, 1081,
- /* 530 */ 858, 857, 856, 761, 756, 911, 755, 754, 765, 831,
- /* 540 */ 832, 840, 843, 838, 841, 837, 836, 835, 839, 834,
- /* 550 */ 830, 768, 767, 775, 824, 802, 800, 799, 803, 816,
- /* 560 */ 815, 822, 821, 820, 819, 818, 814, 817, 813, 812,
- /* 570 */ 804, 797, 796, 810, 795, 827, 826, 823, 794, 850,
- /* 580 */ 849, 848, 845, 793, 792, 791, 790, 789, 788, 986,
- /* 590 */ 985, 1006, 977, 865, 872, 871, 870, 874, 875, 885,
- /* 600 */ 883, 882, 881, 917, 916, 915, 914, 913, 912, 905,
- /* 610 */ 903, 899, 898, 904, 902, 920, 921, 919, 897, 889,
- /* 620 */ 887, 888, 886, 974, 971, 973, 970, 907, 895, 892,
- /* 630 */ 879, 925, 924, 1029, 1018, 1008, 1019, 910, 1007, 1005,
- /* 640 */ 1028, 1025, 1020, 1102, 1024, 1012, 1011, 1010, 1147, 1145,
- /* 650 */ 1146, 1049, 1051, 1054, 1053, 1050, 927, 926, 1048, 1047,
- /* 660 */ 1009, 984, 781, 779, 780, 1074, 1073, 1076, 1075, 1072,
- /* 670 */ 783, 782, 778, 777, 998, 997, 982, 1021, 1022, 981,
- /* 680 */ 1023, 983, 770, 873, 866, 976, 975, 808, 807, 806,
- /* 690 */ 805, 877, 876, 787, 801, 786, 784, 764, 759, 758,
- /* 700 */ 753, 751, 748, 750, 747, 752, 749, 745, 743, 742,
- /* 710 */ 741, 740, 739, 773, 772, 771, 769, 737, 736, 733,
- /* 720 */ 732, 728, 727, 725,
+ /* 0 */ 730, 1038, 1143, 1143, 1027, 1027, 1027, 1143, 1027, 1027,
+ /* 10 */ 1027, 1027, 1027, 901, 1149, 1149, 1149, 1027, 1027, 1027,
+ /* 20 */ 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027,
+ /* 30 */ 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027,
+ /* 40 */ 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027,
+ /* 50 */ 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1016, 1149,
+ /* 60 */ 895, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 775,
+ /* 70 */ 891, 901, 1149, 1149, 1149, 1149, 1149, 963, 950, 941,
+ /* 80 */ 1149, 1149, 1149, 973, 973, 956, 843, 973, 1149, 1149,
+ /* 90 */ 1149, 1149, 929, 929, 1028, 1149, 767, 1113, 1118, 1014,
+ /* 100 */ 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 902, 1149,
+ /* 110 */ 1014, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149,
+ /* 120 */ 1149, 964, 957, 951, 942, 1149, 1149, 1149, 1149, 1149,
+ /* 130 */ 1149, 1149, 1149, 1149, 1149, 891, 891, 1149, 1149, 891,
+ /* 140 */ 1149, 1149, 1149, 1015, 1149, 1149, 764, 1149, 1149, 1149,
+ /* 150 */ 736, 1059, 1149, 1149, 730, 1143, 1143, 1143, 1143, 1143,
+ /* 160 */ 1143, 1136, 881, 936, 907, 946, 934, 938, 1039, 1032,
+ /* 170 */ 1033, 1031, 937, 1028, 1028, 1028, 1028, 1028, 1028, 1028,
+ /* 180 */ 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 989, 1001,
+ /* 190 */ 988, 996, 1005, 1000, 997, 991, 990, 992, 1149, 1149,
+ /* 200 */ 1149, 993, 1149, 1149, 1149, 1149, 1149, 894, 1149, 1149,
+ /* 210 */ 865, 1149, 1087, 1149, 1149, 777, 1149, 879, 739, 945,
+ /* 220 */ 919, 919, 810, 834, 799, 929, 919, 909, 1034, 929,
+ /* 230 */ 1149, 1149, 994, 892, 879, 1127, 910, 910, 910, 1112,
+ /* 240 */ 1112, 910, 910, 856, 910, 856, 910, 856, 910, 856,
+ /* 250 */ 910, 761, 945, 910, 761, 847, 969, 910, 910, 847,
+ /* 260 */ 945, 910, 1094, 1092, 910, 761, 910, 1047, 761, 910,
+ /* 270 */ 1047, 845, 845, 845, 845, 826, 1047, 845, 810, 845,
+ /* 280 */ 826, 845, 845, 1149, 910, 910, 1149, 1047, 1053, 1047,
+ /* 290 */ 1028, 995, 935, 923, 933, 930, 945, 1149, 758, 829,
+ /* 300 */ 761, 747, 747, 735, 735, 735, 735, 1140, 1140, 1136,
+ /* 310 */ 812, 812, 897, 1004, 1003, 1002, 786, 1040, 1149, 1149,
+ /* 320 */ 1149, 1149, 1149, 1149, 1061, 1149, 1149, 1149, 1149, 1149,
+ /* 330 */ 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 731,
+ /* 340 */ 1149, 1149, 1149, 1149, 1149, 1130, 1149, 1149, 1149, 1149,
+ /* 350 */ 1149, 1149, 1091, 1090, 1149, 1149, 1149, 1149, 1149, 1149,
+ /* 360 */ 1149, 1149, 1149, 1149, 1079, 1149, 1149, 1149, 1149, 1149,
+ /* 370 */ 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149,
+ /* 380 */ 1149, 1149, 1149, 1149, 1149, 868, 870, 1149, 1149, 1149,
+ /* 390 */ 869, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149,
+ /* 400 */ 931, 1149, 924, 1149, 1037, 1149, 1018, 1026, 1149, 1149,
+ /* 410 */ 1149, 1149, 1149, 1017, 1149, 1149, 1149, 1145, 1149, 1149,
+ /* 420 */ 1149, 1144, 1149, 1149, 1149, 1149, 1149, 1029, 981, 1149,
+ /* 430 */ 980, 979, 770, 1149, 745, 1149, 727, 732, 1129, 1126,
+ /* 440 */ 1128, 1123, 1124, 1122, 1125, 1121, 1119, 1120, 1117, 1115,
+ /* 450 */ 1114, 1116, 1111, 1107, 1067, 1065, 1063, 1072, 1071, 1070,
+ /* 460 */ 1069, 1068, 1064, 1062, 1066, 1060, 960, 948, 939, 863,
+ /* 470 */ 1106, 1104, 1105, 1058, 1056, 1057, 862, 861, 860, 855,
+ /* 480 */ 854, 853, 852, 1133, 1142, 1141, 1139, 1138, 1137, 1131,
+ /* 490 */ 1132, 1045, 1044, 1042, 1041, 1043, 763, 1083, 1086, 1085,
+ /* 500 */ 1084, 1089, 1088, 1081, 1093, 1098, 1097, 1102, 1101, 1100,
+ /* 510 */ 1099, 1096, 1078, 968, 967, 965, 970, 962, 961, 966,
+ /* 520 */ 953, 959, 958, 949, 952, 848, 944, 940, 943, 864,
+ /* 530 */ 1082, 859, 858, 857, 762, 757, 912, 756, 755, 766,
+ /* 540 */ 832, 833, 841, 844, 839, 842, 838, 837, 836, 840,
+ /* 550 */ 835, 831, 769, 768, 776, 825, 803, 801, 800, 804,
+ /* 560 */ 817, 816, 823, 822, 821, 820, 819, 815, 818, 814,
+ /* 570 */ 813, 805, 798, 797, 811, 796, 828, 827, 824, 795,
+ /* 580 */ 851, 850, 849, 846, 794, 793, 792, 791, 790, 789,
+ /* 590 */ 987, 986, 1007, 978, 866, 873, 872, 871, 875, 876,
+ /* 600 */ 886, 884, 883, 882, 918, 917, 916, 915, 914, 913,
+ /* 610 */ 906, 904, 900, 899, 905, 903, 921, 922, 920, 898,
+ /* 620 */ 890, 888, 889, 887, 975, 972, 974, 971, 908, 896,
+ /* 630 */ 893, 880, 926, 925, 1030, 1019, 1009, 1020, 911, 1008,
+ /* 640 */ 1006, 1029, 1026, 1021, 1103, 1025, 1013, 1012, 1011, 1148,
+ /* 650 */ 1146, 1147, 1050, 1052, 1055, 1054, 1051, 928, 927, 1049,
+ /* 660 */ 1048, 1010, 985, 782, 780, 781, 1075, 1074, 1077, 1076,
+ /* 670 */ 1073, 784, 783, 779, 778, 999, 998, 983, 1022, 1023,
+ /* 680 */ 982, 1024, 984, 771, 874, 867, 977, 976, 809, 808,
+ /* 690 */ 807, 806, 878, 877, 788, 802, 787, 785, 765, 760,
+ /* 700 */ 759, 754, 752, 749, 751, 748, 753, 750, 746, 744,
+ /* 710 */ 743, 742, 741, 740, 774, 773, 772, 770, 738, 737,
+ /* 720 */ 734, 733, 729, 728, 726,
};
/* The next table maps tokens into fallback tokens. If a construct
@@ -1297,7 +1301,7 @@ static const char *const yyRuleName[] = {
/* 129 */ "cmd ::= DROP TABLE ifexists ID_DB|ID_TAB",
/* 130 */ "ifexists ::= IF EXISTS",
/* 131 */ "ifexists ::=",
- /* 132 */ "cmd ::= CREATE temp VIEW ifnotexists fullname AS select",
+ /* 132 */ "cmd ::= CREATE temp VIEW ifnotexists fullname idxlist_opt AS select",
/* 133 */ "cmd ::= CREATE temp VIEW ifnotexists nm DOT ID_VIEW_NEW",
/* 134 */ "cmd ::= CREATE temp VIEW ifnotexists ID_DB|ID_VIEW_NEW",
/* 135 */ "cmd ::= DROP VIEW ifexists fullname",
@@ -1481,7 +1485,7 @@ static const char *const yyRuleName[] = {
/* 313 */ "exprlist ::=",
/* 314 */ "nexprlist ::= nexprlist COMMA expr",
/* 315 */ "nexprlist ::= exprx",
- /* 316 */ "cmd ::= CREATE uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP where_opt",
+ /* 316 */ "cmd ::= CREATE uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt",
/* 317 */ "cmd ::= CREATE uniqueflag INDEX ifnotexists nm dbnm ON ID_TAB",
/* 318 */ "cmd ::= CREATE uniqueflag INDEX ifnotexists nm DOT ID_IDX_NEW",
/* 319 */ "cmd ::= CREATE uniqueflag INDEX ifnotexists ID_DB|ID_IDX_NEW",
@@ -2354,7 +2358,7 @@ static const struct {
{ 169, 4 },
{ 217, 2 },
{ 217, 0 },
- { 169, 7 },
+ { 169, 8 },
{ 169, 7 },
{ 169, 5 },
{ 169, 4 },
@@ -3398,12 +3402,13 @@ static void yy_reduce(
{ yy_destructor(yypParser,177,&yymsp[-2].minor);
}
break;
- case 132: /* cmd ::= CREATE temp VIEW ifnotexists fullname AS select */
+ case 132: /* cmd ::= CREATE temp VIEW ifnotexists fullname idxlist_opt AS select */
{
- yygotominor.yy399 = new SqliteCreateView(*(yymsp[-5].minor.yy376), *(yymsp[-3].minor.yy237), yymsp[-2].minor.yy66->name1, yymsp[-2].minor.yy66->name2, yymsp[0].minor.yy123);
- delete yymsp[-5].minor.yy376;
- delete yymsp[-3].minor.yy237;
- delete yymsp[-2].minor.yy66;
+ yygotominor.yy399 = new SqliteCreateView(*(yymsp[-6].minor.yy376), *(yymsp[-4].minor.yy237), yymsp[-3].minor.yy66->name1, yymsp[-3].minor.yy66->name2, yymsp[0].minor.yy123, *(yymsp[-2].minor.yy139));
+ delete yymsp[-6].minor.yy376;
+ delete yymsp[-4].minor.yy237;
+ delete yymsp[-3].minor.yy66;
+ delete yymsp[-2].minor.yy139;
objectForTokens = yygotominor.yy399;
}
break;
@@ -4463,7 +4468,7 @@ static void yy_reduce(
yygotominor.yy13->append(yymsp[0].minor.yy490);
}
break;
- case 316: /* cmd ::= CREATE uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP where_opt */
+ case 316: /* cmd ::= CREATE uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
{
yygotominor.yy399 = new SqliteCreateIndex(
*(yymsp[-10].minor.yy237),
@@ -4471,7 +4476,7 @@ static void yy_reduce(
*(yymsp[-7].minor.yy211),
*(yymsp[-6].minor.yy211),
*(yymsp[-4].minor.yy211),
- *(yymsp[-2].minor.yy139),
+ *(yymsp[-2].minor.yy495),
yymsp[0].minor.yy490
);
delete yymsp[-8].minor.yy237;
@@ -4479,7 +4484,7 @@ static void yy_reduce(
delete yymsp[-7].minor.yy211;
delete yymsp[-6].minor.yy211;
delete yymsp[-4].minor.yy211;
- delete yymsp[-2].minor.yy139;
+ delete yymsp[-2].minor.yy495;
objectForTokens = yygotominor.yy399;
}
break;
diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/sqlite3_parse.y b/SQLiteStudio3/coreSQLiteStudio/parser/sqlite3_parse.y
index 0bab877..932e965 100644
--- a/SQLiteStudio3/coreSQLiteStudio/parser/sqlite3_parse.y
+++ b/SQLiteStudio3/coreSQLiteStudio/parser/sqlite3_parse.y
@@ -737,11 +737,12 @@ ifexists(X) ::= . {X = new bool(false);}
cmd(X) ::= CREATE temp(T) VIEW
ifnotexists(E) fullname(N)
- AS select(S). {
- X = new SqliteCreateView(*(T), *(E), N->name1, N->name2, S);
+ idxlist_opt(C) AS select(S). {
+ X = new SqliteCreateView(*(T), *(E), N->name1, N->name2, S, *(C));
delete T;
delete E;
delete N;
+ delete C;
objectForTokens = X;
}
@@ -1824,7 +1825,7 @@ nexprlist(X) ::= exprx(E). {
cmd(X) ::= CREATE uniqueflag(U) INDEX
ifnotexists(E) nm(N1) dbnm(N2)
- ON nm(N3) LP idxlist(L) RP
+ ON nm(N3) LP sortlist(L) RP
where_opt(W). {
X = new SqliteCreateIndex(
*(U),
diff --git a/SQLiteStudio3/coreSQLiteStudio/parser/statementtokenbuilder.cpp b/SQLiteStudio3/coreSQLiteStudio/parser/statementtokenbuilder.cpp
index ba2ea37..a97b765 100644
--- a/SQLiteStudio3/coreSQLiteStudio/parser/statementtokenbuilder.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/parser/statementtokenbuilder.cpp
@@ -74,7 +74,7 @@ StatementTokenBuilder& StatementTokenBuilder::withComment(const QString& value)
StatementTokenBuilder& StatementTokenBuilder::withFloat(double value)
{
- return with(Token::FLOAT, QString::number(value));
+ return with(Token::FLOAT, doubleToString(value));
}
StatementTokenBuilder& StatementTokenBuilder::withInteger(qint64 value)
diff --git a/SQLiteStudio3/coreSQLiteStudio/querygenerator.cpp b/SQLiteStudio3/coreSQLiteStudio/querygenerator.cpp
new file mode 100644
index 0000000..4e2d9b6
--- /dev/null
+++ b/SQLiteStudio3/coreSQLiteStudio/querygenerator.cpp
@@ -0,0 +1,275 @@
+#include "querygenerator.h"
+#include "common/global.h"
+#include "common/utils_sql.h"
+#include "db/db.h"
+
+QueryGenerator::QueryGenerator()
+{
+
+}
+
+QString QueryGenerator::generateSelectFromTable(Db* db, const QString& table, const StrHash<QVariantList> values)
+{
+ return generateSelectFromTable(db, QString(), table, values);
+}
+
+QString QueryGenerator::generateSelectFromTable(Db* db, const QString& database, const QString& table, const StrHash<QVariantList> values)
+{
+ SchemaResolver resolver(db);
+ QStringList columns = resolver.getTableColumns(database, table);
+ return generateSelectFromTableOrView(db, database, table, columns, values);
+}
+
+QString QueryGenerator::generateInsertToTable(Db* db, const QString& table, const StrHash<QVariantList> values)
+{
+ return generateInsertToTable(db, QString(), table, values);
+}
+
+QString QueryGenerator::generateInsertToTable(Db* db, const QString& database, const QString& table, StrHash<QVariantList> values)
+{
+ static_qstring(tpl, "INSERT INTO %1 (%2) VALUES %3");
+ static_qstring(rowTpl, "(%1)");
+
+ Dialect dialect = db->getDialect();
+ QString target = toFullObjectName(database, table, dialect);
+
+ // Get all table's columns
+ SchemaResolver resolver(db);
+ QStringList tableCols = resolver.getTableColumns(database, table);
+
+ // If no values were given, then column names will serve as values for insertion
+ if (values.isEmpty())
+ {
+ QStringList valueList = wrapStrings(tableCols);
+ QList<QString> wrappedCols = wrapObjNamesIfNeeded(tableCols, dialect);
+ return tpl.arg(target, wrappedCols.join(", "), rowTpl.arg(valueList.join(", ")));
+ }
+
+ // Values were given. Sort given columns in order they are defined in table
+ QStringList valueCols = values.keys();
+ sortWithReferenceList(valueCols, tableCols);
+
+ // Group values into rows
+ QStringList valueSets = toValueSets(valueCols, values, dialect);
+ QString valueStr = rowTpl.arg(valueSets.join("), ("));
+
+ // Wrap given column names
+ QList<QString> wrappedCols = wrapObjNamesIfNeeded(valueCols, dialect);
+
+ return tpl.arg(target, wrappedCols.join(", "), valueStr);
+}
+
+QString QueryGenerator::generateUpdateOfTable(Db* db, const QString& table, const StrHash<QVariantList> values)
+{
+ return generateUpdateOfTable(db, QString(), table, values);
+}
+
+QString QueryGenerator::generateUpdateOfTable(Db* db, const QString& database, const QString& table, StrHash<QVariantList> values)
+{
+ static_qstring(tpl, "UPDATE %1 SET %2%3");
+ static_qstring(tplWithWhere, "UPDATE %1 SET %2 WHERE %3");
+ static_qstring(updateColTpl, "%1 = %2");
+
+ Dialect dialect = db->getDialect();
+ QString target = toFullObjectName(database, table, dialect);
+
+ // Get all columns of the table
+ SchemaResolver resolver(db);
+ QStringList tableCols = resolver.getTableColumns(database, table);
+
+ // Create list of "column = 'column'"
+ QStringList commonUpdateCols;
+ for (const QString& col : tableCols)
+ commonUpdateCols << updateColTpl.arg(wrapObjIfNeeded(col, dialect), wrapString(col));
+
+ // Put it to comma spearated string
+ QString commonColumnStr = commonUpdateCols.join(", ");
+
+ // If no values were given, we simply use column names as values everywhere
+ if (values.isEmpty())
+ return tplWithWhere.arg(target, commonColumnStr, commonColumnStr);
+
+ // If values were given, then they will be used in WHERE clause
+ QStringList valueCols = values.keys();
+ sortWithReferenceList(valueCols, tableCols);
+
+ // Conditions for WHERE clause
+ QString conditionStr = valuesToConditionStr(values, dialect);
+
+ return tpl.arg(target, commonColumnStr, conditionStr);
+}
+
+QString QueryGenerator::generateDeleteFromTable(Db* db, const QString& table, const StrHash<QVariantList> values)
+{
+ return generateDeleteFromTable(db, QString(), table, values);
+}
+
+QString QueryGenerator::generateDeleteFromTable(Db* db, const QString& database, const QString& table, StrHash<QVariantList> values)
+{
+ static_qstring(tpl, "DELETE FROM %1%2");
+ static_qstring(tplWithWhere, "DELETE FROM %1 WHERE %2");
+ static_qstring(conditionColTpl, "%1 = %2");
+
+ Dialect dialect = db->getDialect();
+ QString target = toFullObjectName(database, table, dialect);
+
+ // Get all columns of the table
+ SchemaResolver resolver(db);
+ QStringList tableCols = resolver.getTableColumns(database, table);
+
+ // If no values were given, we simply use column names as values everywhere
+ if (values.isEmpty())
+ {
+ // Create list of "column = 'column'"
+ QStringList conditionCols;
+ for (const QString& col : tableCols)
+ conditionCols << conditionColTpl.arg(wrapObjIfNeeded(col, dialect), wrapString(col));
+
+ // Put it to comma spearated string
+ QString conditionStr = conditionCols.join(", ");
+
+ return tplWithWhere.arg(target, conditionStr);
+ }
+
+ // If values were given, then they will be used in WHERE clause
+ QStringList valueCols = values.keys();
+ sortWithReferenceList(valueCols, tableCols);
+
+ // Conditions for WHERE clause
+ QString conditionStr = valuesToConditionStr(values, dialect);
+
+ return tpl.arg(target, conditionStr);
+}
+
+QString QueryGenerator::generateSelectFromView(Db* db, const QString& view, const StrHash<QVariantList> values)
+{
+ return generateSelectFromView(db, QString(), view, values);
+}
+
+QString QueryGenerator::generateSelectFromView(Db* db, const QString& database, const QString& view, const StrHash<QVariantList> values)
+{
+ SchemaResolver resolver(db);
+ QStringList columns = resolver.getViewColumns(database, view);
+ return generateSelectFromTableOrView(db, database, view, columns, values);
+}
+
+QString QueryGenerator::generateSelectFromSelect(Db* db, const QString& initialSelect, const StrHash<QVariantList> values, const BiStrHash& dbNameToAttach)
+{
+ static_qstring(tpl, "SELECT %1 FROM (%2)%3");
+
+ Dialect dialect = db->getDialect();
+
+ // Resolve all columns of the select
+ SelectResolver resolver(db, initialSelect, dbNameToAttach);
+ QList<SelectResolver::Column> columns = resolver.resolveColumnsFromFirstCore();
+
+ // Generate result columns
+ QStringList resCols;
+ for (const SelectResolver::Column& col : columns)
+ resCols << toResultColumnString(col, dialect);
+
+ // Generate conditions for WHERE clause
+ QString conditionStr = valuesToConditionStr(values, dialect);
+
+ return tpl.arg(resCols.join(", "), initialSelect, conditionStr);
+}
+
+QString QueryGenerator::generateSelectFromTableOrView(Db* db, const QString& database, const QString& tableOrView, const QStringList& columns, const StrHash<QVariantList> values)
+{
+ static_qstring(tpl, "SELECT %1 FROM %2%3");
+
+ Dialect dialect = db->getDialect();
+
+ QString target = toFullObjectName(database, tableOrView, dialect);
+ QString conditionStr = valuesToConditionStr(values, dialect);
+
+ return tpl.arg(columns.join(", "), target, conditionStr);
+}
+
+QString QueryGenerator::getAlias(const QString& name, QSet<QString>& usedAliases)
+{
+ static_qstring(tpl, "%2%1");
+
+ QString letter;
+ if (name.length() == 0)
+ letter = "t";
+ else
+ letter = name[0];
+
+ QString alias = letter + "1";
+ int i = 2;
+ while (usedAliases.contains(alias))
+ alias = tpl.arg(i++).arg(letter);
+
+ usedAliases << alias;
+ return alias;
+}
+
+QStringList QueryGenerator::valuesToConditionList(const StrHash<QVariantList>& values, Dialect dialect)
+{
+ static_qstring(conditionTpl1, "%1 = %2");
+ static_qstring(conditionTpl2, "%1 IN (%2)");
+
+ QStringList conditions;
+ QStringList conditionValues;
+ for (const QString& col : values.keys())
+ {
+ conditionValues = valueListToSqlList(values[col], dialect);
+ conditionValues.removeDuplicates();
+ if (conditionValues.size() == 1)
+ conditions << conditionTpl1.arg(wrapObjIfNeeded(col, dialect), conditionValues.first());
+ else
+ conditions << conditionTpl2.arg(wrapObjIfNeeded(col, dialect), conditionValues.join(", "));
+ }
+ return conditions;
+}
+
+QString QueryGenerator::valuesToConditionStr(const StrHash<QVariantList>& values, Dialect dialect)
+{
+ static_qstring(condTpl, " WHERE %1");
+
+ QStringList conditions = valuesToConditionList(values, dialect);
+ QString conditionStr = "";
+ if (conditions.size() > 0)
+ conditionStr = condTpl.arg(conditions.join(" AND "));
+
+ return conditionStr;
+}
+
+QString QueryGenerator::toResultColumnString(const SelectResolver::Column& column, Dialect dialect)
+{
+ return wrapObjIfNeeded(column.displayName, dialect);
+}
+
+QString QueryGenerator::toFullObjectName(const QString& database, const QString& object, Dialect dialect)
+{
+ static_qstring(tpl, "%1%2");
+
+ QString dbName = "";
+ if (!database.isEmpty() && dbName.toLower() != "main")
+ dbName = wrapObjIfNeeded(database, dialect);
+
+ if (!dbName.isEmpty())
+ dbName.append(".");
+
+ return tpl.arg(dbName, wrapObjIfNeeded(object, dialect));
+}
+
+QStringList QueryGenerator::toValueSets(const QStringList& columns, const StrHash<QVariantList> values, Dialect dialect)
+{
+ QStringList rows;
+ QVariantList rowValues;
+ QStringList valueList;
+
+ for (int total = values.values().first().size(), i = 0; i < total; i++)
+ {
+ rowValues.clear();
+ for (const QString& col : columns)
+ rowValues << values[col][i];
+
+ valueList = valueListToSqlList(rowValues, dialect);
+ rows << valueList.join(", ");
+ }
+
+ return rows;
+}
diff --git a/SQLiteStudio3/coreSQLiteStudio/querygenerator.h b/SQLiteStudio3/coreSQLiteStudio/querygenerator.h
new file mode 100644
index 0000000..3f7df9c
--- /dev/null
+++ b/SQLiteStudio3/coreSQLiteStudio/querygenerator.h
@@ -0,0 +1,75 @@
+#ifndef QUERYGENERATOR_H
+#define QUERYGENERATOR_H
+
+#include "common/column.h"
+#include "dialect.h"
+#include "common/bistrhash.h"
+#include "schemaresolver.h"
+#include "common/strhash.h"
+#include <QString>
+#include <QVariant>
+
+class Db;
+
+class API_EXPORT QueryGenerator
+{
+ public:
+ QueryGenerator();
+
+ /**
+ * @brief Generates select of all column from the \p table having given column values matched.
+ * @overload
+ */
+ QString generateSelectFromTable(Db* db, const QString& table, const StrHash<QVariantList> values = StrHash<QVariantList>());
+
+ /**
+ * @brief Generates SELECT of all column from the \p table having given column values matched.
+ * @param db Database where the \p table exists.
+ * @param database Attach name of the database (such as "main" or "temp", or any other used for ATTACH).
+ * @param table Table to generate select for.
+ * @param values Values to comply with.
+ * @return SELECT statement string.
+ *
+ * Generates SELECT for given table, listing all result columns explicitly and adding WHERE clause (if \p values is not empty) with columns included in \p values
+ * having any of values specified for those columns in that parameter.
+ *
+ * If \p values is ommited, then no WHERE clause is added.
+ */
+ QString generateSelectFromTable(Db* db, const QString& database, const QString& table, const StrHash<QVariantList> values = StrHash<QVariantList>());
+
+ QString generateInsertToTable(Db* db, const QString& table, const StrHash<QVariantList> values = StrHash<QVariantList>());
+ QString generateInsertToTable(Db* db, const QString& database, const QString& table, StrHash<QVariantList> values = StrHash<QVariantList>());
+
+ QString generateUpdateOfTable(Db* db, const QString& table, const StrHash<QVariantList> values = StrHash<QVariantList>());
+ QString generateUpdateOfTable(Db* db, const QString& database, const QString& table, StrHash<QVariantList> values = StrHash<QVariantList>());
+
+ QString generateDeleteFromTable(Db* db, const QString& table, const StrHash<QVariantList> values = StrHash<QVariantList>());
+ QString generateDeleteFromTable(Db* db, const QString& database, const QString& table, StrHash<QVariantList> values = StrHash<QVariantList>());
+
+ QString generateSelectFromView(Db* db, const QString& view, const StrHash<QVariantList> values = StrHash<QVariantList>());
+ QString generateSelectFromView(Db* db, const QString& database, const QString& view, const StrHash<QVariantList> values = StrHash<QVariantList>());
+
+ /**
+ * @brief Generates SELECT for all columns from the \p initialSelect having values matched.
+ * @param db Database that will be used to resolve tables used in the \p initialSelect
+ * @param initialSelect The SELECT statement that will be used as a base for generating new query.
+ * @param values Map of column names and values for them, so the WHERE clause is generated for them.
+ * @param dbNameToAttach If the \p initialSelect uses attached databases, they should be provided in this parameter, so their symbolic names can be resolved to real attach name.
+ * @return Generated SELECT statement string.
+ *
+ * Generates SELECT using \p initialSelect as a base. Lists all columns from \p initialSelect result columns explicitly (no star operator).
+ * If there are \p values given, then the WHERE clause is added for them to match columns.
+ */
+ QString generateSelectFromSelect(Db* db, const QString& initialSelect, const StrHash<QVariantList> values = StrHash<QVariantList>(), const BiStrHash& dbNameToAttach = BiStrHash());
+
+ private:
+ QString generateSelectFromTableOrView(Db* db, const QString& database, const QString& tableOrView, const QStringList& columns, const StrHash<QVariantList> values = StrHash<QVariantList>());
+ QString getAlias(const QString& name, QSet<QString>& usedAliases);
+ QStringList valuesToConditionList(const StrHash<QVariantList>& values, Dialect dialect);
+ QString valuesToConditionStr(const StrHash<QVariantList>& values, Dialect dialect);
+ QString toResultColumnString(const SelectResolver::Column& column, Dialect dialect);
+ QString toFullObjectName(const QString& database, const QString& object, Dialect dialect);
+ QStringList toValueSets(const QStringList& columns, const StrHash<QVariantList> values, Dialect dialect);
+};
+
+#endif // QUERYGENERATOR_H
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;
diff --git a/SQLiteStudio3/coreSQLiteStudio/schemaresolver.h b/SQLiteStudio3/coreSQLiteStudio/schemaresolver.h
index 5d325d8..336b0f2 100644
--- a/SQLiteStudio3/coreSQLiteStudio/schemaresolver.h
+++ b/SQLiteStudio3/coreSQLiteStudio/schemaresolver.h
@@ -141,6 +141,11 @@ class API_EXPORT SchemaResolver
QString getObjectDdl(const QString& name, ObjectType type);
QString getObjectDdl(const QString& database, const QString& name, ObjectType type);
+ QStringList getColumnsFromDdlUsingPragma(const QString& ddl);
+ QStringList getColumnsUsingPragma(const QString& tableOrView);
+ QStringList getColumnsUsingPragma(SqliteCreateTable* createTable);
+ QStringList getColumnsUsingPragma(SqliteCreateView* createView);
+
/**
* @brief Parses given object's DDL.
* @param name Name of the object in the database.
diff --git a/SQLiteStudio3/coreSQLiteStudio/selectresolver.cpp b/SQLiteStudio3/coreSQLiteStudio/selectresolver.cpp
index 8107b94..02489ee 100644
--- a/SQLiteStudio3/coreSQLiteStudio/selectresolver.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/selectresolver.cpp
@@ -28,13 +28,29 @@ SelectResolver::~SelectResolver()
safe_delete(schemaResolver);
}
+QList<SelectResolver::Column> SelectResolver::resolveColumnsFromFirstCore()
+{
+ if (!parseOriginalQuery())
+ return QList<SelectResolver::Column>();
+
+ return resolve(originalQueryParsed->coreSelects.first());
+}
+
+QList<QList<SelectResolver::Column>> SelectResolver::resolveColumns()
+{
+ if (!parseOriginalQuery())
+ return QList<QList<SelectResolver::Column>>();
+
+ return resolve(originalQueryParsed.data());
+}
+
QList<SelectResolver::Column> SelectResolver::resolve(SqliteSelect::Core *selectCore)
{
errors.clear();
return resolveCore(selectCore);
}
-QList<QList<SelectResolver::Column> > SelectResolver::resolve(SqliteSelect *select)
+QList<QList<SelectResolver::Column>> SelectResolver::resolve(SqliteSelect *select)
{
errors.clear();
QList<QList<SelectResolver::Column> > results;
@@ -377,10 +393,16 @@ void SelectResolver::resolveDbAndTable(SqliteSelect::Core::ResultColumn *resCol)
col.tableAlias = matched.tableAlias;
col.flags = matched.flags;
}
+ else if (matched.type == Column::OTHER)
+ {
+ col.type = Column::OTHER;
+ }
else if (!ignoreInvalidNames)
{
- qDebug() << "Source table for column '" << expr->detokenize()
+ QString colStr = expr->detokenize();
+ qDebug() << "Source table for column '" << colStr
<< "' not matched while resolving select: " << query;
+ errors << QObject::tr("Could not resolve table for column '%1'.").arg(colStr);
}
currentCoreResults << col;
@@ -473,7 +495,7 @@ TokenList SelectResolver::getResColTokensWithoutAlias(SqliteSelect::Core::Result
{
depth--;
}
- else if (token->type == Token::KEYWORD && token->value.compare("AS", Qt::CaseInsensitive) && depth <= 0)
+ else if (token->type == Token::KEYWORD && token->value.compare("AS", Qt::CaseInsensitive) == 0 && depth <= 0)
{
idx = idxCandidate;
break;
@@ -534,6 +556,16 @@ QList<SelectResolver::Column> SelectResolver::resolveSingleSourceSubSelect(Sqlit
{
QList<Column> columnSources = resolveSubSelect(joinSrc->select);
applySubSelectAlias(columnSources, joinSrc->alias);
+
+ QMutableListIterator<Column> it(columnSources);
+ while (it.hasNext())
+ {
+ if (it.next().alias.isEmpty())
+ continue;
+
+ it.value().aliasDefinedInSubQuery = true;
+ }
+
return columnSources;
}
@@ -640,6 +672,29 @@ QString SelectResolver::resolveDatabase(const QString& database)
return database;
}
+bool SelectResolver::parseOriginalQuery()
+{
+ if (originalQueryParsed)
+ return true;
+
+ Parser parser(db->getDialect());
+ if (!parser.parse(query) || parser.getQueries().isEmpty())
+ {
+ qWarning() << "Could not parse query in SelectResolver:" << query;
+ return false;
+ }
+
+ SqliteQueryPtr theQuery = parser.getQueries().first();
+ if (theQuery.dynamicCast<SqliteSelect>().isNull())
+ {
+ qWarning() << "Parsed query is not SELECT as expected in SelectResolver::parseOriginalQuery():" << query;
+ return false;
+ }
+
+ originalQueryParsed = theQuery.dynamicCast<SqliteSelect>();
+ return true;
+}
+
int SelectResolver::Table::operator ==(const SelectResolver::Table &other)
{
return table == other.table && database == other.database && alias == other.alias;
diff --git a/SQLiteStudio3/coreSQLiteStudio/selectresolver.h b/SQLiteStudio3/coreSQLiteStudio/selectresolver.h
index 4213d73..1edfcb9 100644
--- a/SQLiteStudio3/coreSQLiteStudio/selectresolver.h
+++ b/SQLiteStudio3/coreSQLiteStudio/selectresolver.h
@@ -109,6 +109,7 @@ class API_EXPORT SelectResolver
QString alias;
QString tableAlias;
QString displayName;
+ bool aliasDefinedInSubQuery = false;
int flags = 0;
SqliteSelect::Core::ResultColumn* originalColumn = nullptr;
@@ -120,6 +121,9 @@ class API_EXPORT SelectResolver
SelectResolver(Db* db, const QString &originalQuery, const BiStrHash& dbNameToAttach);
~SelectResolver();
+ QList<Column> resolveColumnsFromFirstCore();
+ QList<QList<Column> > resolveColumns();
+
QList<Column> resolve(SqliteSelect::Core* selectCore);
QList<QList<Column> > resolve(SqliteSelect* select);
@@ -212,6 +216,7 @@ class API_EXPORT SelectResolver
QStringList getTableColumns(const QString& database, const QString& table, const QString &alias);
void applySubSelectAlias(QList<Column>& columns, const QString& alias);
QString resolveDatabase(const QString& database);
+ bool parseOriginalQuery();
void markDistinctColumns();
void markCompoundColumns();
@@ -224,6 +229,7 @@ class API_EXPORT SelectResolver
Db* db = nullptr;
QString query;
+ SqliteSelectPtr originalQueryParsed;
/**
* @brief Database name to attach name map.
diff --git a/SQLiteStudio3/coreSQLiteStudio/services/dbmanager.h b/SQLiteStudio3/coreSQLiteStudio/services/dbmanager.h
index 66bbf08..52746e4 100644
--- a/SQLiteStudio3/coreSQLiteStudio/services/dbmanager.h
+++ b/SQLiteStudio3/coreSQLiteStudio/services/dbmanager.h
@@ -131,7 +131,7 @@ class API_EXPORT DbManager : public QObject
*
* This method is fast, as it uses hash table lookup.
*/
- virtual Db* getByName(const QString& name, Qt::CaseSensitivity cs = Qt::CaseSensitive) = 0;
+ virtual Db* getByName(const QString& name, Qt::CaseSensitivity cs = Qt::CaseInsensitive) = 0;
/**
* @brief Gives database object by its file path.
@@ -162,6 +162,10 @@ class API_EXPORT DbManager : public QObject
*/
virtual bool isTemporary(Db* db) = 0;
+ virtual DbPlugin* getPluginForDbFile(const QString& filePath) = 0;
+ virtual QString generateUniqueDbName(const QString& filePath) = 0;
+ virtual QString generateUniqueDbName(DbPlugin* plugin, const QString& filePath) = 0;
+
/**
* @brief Generates database name.
* @param filePath Database file path.
diff --git a/SQLiteStudio3/coreSQLiteStudio/services/impl/dbmanagerimpl.cpp b/SQLiteStudio3/coreSQLiteStudio/services/impl/dbmanagerimpl.cpp
index cbdc921..74f482f 100644
--- a/SQLiteStudio3/coreSQLiteStudio/services/impl/dbmanagerimpl.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/services/impl/dbmanagerimpl.cpp
@@ -99,7 +99,7 @@ bool DbManagerImpl::updateDb(Db* db, const QString &name, const QString &path, c
db->setPath(normalizedPath);
db->setConnectionOptions(options);
- bool result = false;
+ bool result = true;
if (permanent)
{
if (CFG->isDbInConfig(oldName))
@@ -284,6 +284,44 @@ QString DbManagerImpl::quickAddDb(const QString& path, const QHash<QString, QVar
return newName;
}
+DbPlugin* DbManagerImpl::getPluginForDbFile(const QString& filePath)
+{
+ QFileInfo file(filePath);
+ if (!file.exists() || file.isDir())
+ return nullptr;
+
+ QHash<QString,QVariant> options;
+ Db* probeDb = nullptr;
+ for (DbPlugin* plugin : dbPlugins)
+ {
+ probeDb = plugin->getInstance("", filePath, options);
+ if (probeDb)
+ {
+ delete probeDb;
+ probeDb = nullptr;
+ return plugin;
+ }
+ }
+
+ return nullptr;
+}
+
+QString DbManagerImpl::generateUniqueDbName(const QString& filePath)
+{
+ DbPlugin* plugin = getPluginForDbFile(filePath);
+ if (!plugin)
+ return QString();
+
+ return generateUniqueDbName(plugin, filePath);
+}
+
+QString DbManagerImpl::generateUniqueDbName(DbPlugin* plugin, const QString& filePath)
+{
+ QString name = plugin->generateDbName(filePath);
+ name = generateUniqueName(name, getDbNames(), Qt::CaseInsensitive);
+ return name;
+}
+
void DbManagerImpl::setInMemDbCreatorPlugin(DbPlugin* plugin)
{
inMemDbCreatorPlugin = plugin;
@@ -543,6 +581,7 @@ void DbManagerImpl::aboutToUnload(Plugin* plugin, PluginType* type)
InvalidDb* invalidDb = nullptr;
DbPlugin* dbPlugin = dynamic_cast<DbPlugin*>(plugin);
+ dbPlugins.removeOne(dbPlugin);
QList<Db*> toRemove;
for (Db* db : dbList)
{
@@ -577,5 +616,6 @@ void DbManagerImpl::loaded(Plugin* plugin, PluginType* type)
return;
DbPlugin* dbPlugin = dynamic_cast<DbPlugin*>(plugin);
+ dbPlugins << dbPlugin;
rescanInvalidDatabasesForPlugin(dbPlugin);
}
diff --git a/SQLiteStudio3/coreSQLiteStudio/services/impl/dbmanagerimpl.h b/SQLiteStudio3/coreSQLiteStudio/services/impl/dbmanagerimpl.h
index 67a1335..2e3630a 100644
--- a/SQLiteStudio3/coreSQLiteStudio/services/impl/dbmanagerimpl.h
+++ b/SQLiteStudio3/coreSQLiteStudio/services/impl/dbmanagerimpl.h
@@ -40,11 +40,14 @@ class API_EXPORT DbManagerImpl : public DbManager
QList<Db*> getValidDbList();
QList<Db*> getConnectedDbList();
QStringList getDbNames();
- Db* getByName(const QString& name, Qt::CaseSensitivity cs = Qt::CaseSensitive);
+ Db* getByName(const QString& name, Qt::CaseSensitivity cs = Qt::CaseInsensitive);
Db* getByPath(const QString& path);
Db* createInMemDb();
bool isTemporary(Db* db);
QString quickAddDb(const QString &path, const QHash<QString, QVariant> &options);
+ DbPlugin* getPluginForDbFile(const QString& filePath);
+ QString generateUniqueDbName(const QString& filePath);
+ QString generateUniqueDbName(DbPlugin* plugin, const QString& filePath);
/**
* @brief Defines database plugin used for creating in-memory databases.
@@ -138,6 +141,8 @@ class API_EXPORT DbManagerImpl : public DbManager
*/
DbPlugin* inMemDbCreatorPlugin = nullptr;
+ QList<DbPlugin*> dbPlugins;
+
private slots:
/**
* @brief Slot called when connected to db.
diff --git a/SQLiteStudio3/coreSQLiteStudio/services/impl/pluginmanagerimpl.cpp b/SQLiteStudio3/coreSQLiteStudio/services/impl/pluginmanagerimpl.cpp
index 017d260..9fe21de 100644
--- a/SQLiteStudio3/coreSQLiteStudio/services/impl/pluginmanagerimpl.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/services/impl/pluginmanagerimpl.cpp
@@ -341,7 +341,7 @@ bool PluginManagerImpl::shouldAutoLoad(const QString& pluginName)
{
QStringList loadedPlugins = CFG_CORE.General.LoadedPlugins.get().split(",", QString::SkipEmptyParts);
QStringList pair;
- foreach (const QString& loadedPlugin, loadedPlugins)
+ for (const QString& loadedPlugin : loadedPlugins)
{
pair = loadedPlugin.split("=");
if (pair.size() != 2)
@@ -354,7 +354,7 @@ bool PluginManagerImpl::shouldAutoLoad(const QString& pluginName)
return (bool)pair[1].toInt();
}
- return true;
+ return pluginContainer[pluginName]->loadByDefault;
}
QStringList PluginManagerImpl::getAllPluginNames(PluginType* type) const
@@ -626,6 +626,7 @@ bool PluginManagerImpl::readMetaData(PluginManagerImpl::PluginContainer* contain
container->author = metaData["author"].toString();
container->description = metaData["description"].toString();
container->title = metaData["title"].toString();
+ container->loadByDefault = metaData.contains("loadByDefault") ? metaData["loadByDefault"].toBool() : true;
}
else if (container->plugin)
{
@@ -635,6 +636,7 @@ bool PluginManagerImpl::readMetaData(PluginManagerImpl::PluginContainer* contain
container->author = container->plugin->getAuthor();
container->description = container->plugin->getDescription();
container->title = container->plugin->getTitle();
+ container->loadByDefault = true;
}
else
{
@@ -706,12 +708,9 @@ QHash<QString, QVariant> PluginManagerImpl::readMetaData(const QJsonObject& meta
results["name"] = metaData.value("className").toString();
QJsonObject root = metaData.value("MetaData").toObject();
- results["type"] = root.value("type").toString();
- results["title"] = root.value("title").toString();
- results["description"] = root.value("description").toString();
- results["author"] = root.value("author").toString();
- results["version"] = root.value("version").toInt();
- results["ui"] = root.value("ui").toString();
+ for (const QString& k : root.keys()) {
+ results[k] = root.value(k).toVariant();
+ }
return results;
}
diff --git a/SQLiteStudio3/coreSQLiteStudio/services/impl/pluginmanagerimpl.h b/SQLiteStudio3/coreSQLiteStudio/services/impl/pluginmanagerimpl.h
index 6968cab..c9d56aa 100644
--- a/SQLiteStudio3/coreSQLiteStudio/services/impl/pluginmanagerimpl.h
+++ b/SQLiteStudio3/coreSQLiteStudio/services/impl/pluginmanagerimpl.h
@@ -140,6 +140,14 @@ class API_EXPORT PluginManagerImpl : public PluginManager
bool builtIn = false;
/**
+ * @brief Flag indicating that plugin should be loaded, unless user unloaded it manually.
+ *
+ * If this flag is set to false, then the plugin will not be loaded, even it was not manually unloaded.
+ * This flag can be defined in plugin's json file using property named 'loadByDefault'.
+ */
+ bool loadByDefault = true;
+
+ /**
* @brief Names of plugnis that this plugin depends on.
*/
QList<PluginDependency> dependencies;
diff --git a/SQLiteStudio3/coreSQLiteStudio/sqlitestudio.cpp b/SQLiteStudio3/coreSQLiteStudio/sqlitestudio.cpp
index 46486e8..efb5bb4 100644
--- a/SQLiteStudio3/coreSQLiteStudio/sqlitestudio.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/sqlitestudio.cpp
@@ -39,7 +39,7 @@
DEFINE_SINGLETON(SQLiteStudio)
-static const int sqlitestudioVersion = 30007;
+static const int sqlitestudioVersion = 30100;
SQLiteStudio::SQLiteStudio()
{
diff --git a/SQLiteStudio3/coreSQLiteStudio/tablemodifier.cpp b/SQLiteStudio3/coreSQLiteStudio/tablemodifier.cpp
index 3e23239..a0f6262 100644
--- a/SQLiteStudio3/coreSQLiteStudio/tablemodifier.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/tablemodifier.cpp
@@ -36,6 +36,11 @@ void TableModifier::alterTable(SqliteCreateTablePtr newCreateTable)
existingColumns = newCreateTable->getColumnNames();
newName = newCreateTable->table;
+ if (db->getDialect() == Dialect::Sqlite3)
+ sqls << "PRAGMA foreign_keys = 0;";
+
+ handleFkConstrains(newCreateTable.data(), createTable->table, newName);
+
QString tempTableName;
if (table.compare(newName, Qt::CaseInsensitive) == 0)
tempTableName = renameToTemp();
@@ -44,7 +49,7 @@ void TableModifier::alterTable(SqliteCreateTablePtr newCreateTable)
sqls << newCreateTable->detokenize();
copyDataTo(newCreateTable);
- handleFks(tempTableName);
+ handleFks();
// If temp table was created, it means that table name hasn't changed. In that case we need to cleanup temp table (drop it).
// Otherwise, the table name has changed, therefor there still remains the old table which we copied data from - we need to drop it here.
@@ -53,6 +58,9 @@ void TableModifier::alterTable(SqliteCreateTablePtr newCreateTable)
handleIndexes();
handleTriggers();
handleViews();
+
+ if (db->getDialect() == Dialect::Sqlite3)
+ sqls << "PRAGMA foreign_keys = 1;";
}
void TableModifier::renameTo(const QString& newName)
@@ -60,15 +68,10 @@ void TableModifier::renameTo(const QString& newName)
if (!createTable)
return;
- if (dialect == Dialect::Sqlite3)
- {
- sqls << QString("ALTER TABLE %1 RENAME TO %2;").arg(wrapObjIfNeeded(table, dialect), wrapObjIfNeeded(newName, dialect));
- }
- else
- {
- sqls << QString("CREATE TABLE %1 AS SELECT * FROM %2;").arg(wrapObjIfNeeded(newName, dialect), wrapObjIfNeeded(table, dialect))
- << QString("DROP TABLE %1;").arg(wrapObjIfNeeded(table, dialect));
- }
+ // Using ALTER TABLE RENAME TO is not a good solution here, because it automatically renames all occurrences in REFERENCES,
+ // which we don't want, because we rename a lot to temporary tables and drop them.
+ sqls << QString("CREATE TABLE %1 AS SELECT * FROM %2;").arg(wrapObjIfNeeded(newName, dialect), wrapObjIfNeeded(table, dialect))
+ << QString("DROP TABLE %1;").arg(wrapObjIfNeeded(table, dialect));
table = newName;
createTable->table = newName;
@@ -93,14 +96,19 @@ void TableModifier::copyDataTo(const QString& targetTable)
copyDataTo(targetTable, colsToCopy, colsToCopy);
}
-void TableModifier::handleFks(const QString& tempTableName)
+void TableModifier::handleFks()
{
+ tablesHandledForFk << originalTable;
+
SchemaResolver resolver(db);
QStringList fkTables = resolver.getFkReferencingTables(originalTable);
- foreach (const QString& fkTable, fkTables)
+ for (const QString& fkTable : fkTables)
{
+ if (tablesHandledForFk.contains(fkTable, Qt::CaseInsensitive))
+ continue; // Avoid recurrent FK handling
+
TableModifier subModifier(db, fkTable);
if (!subModifier.isValid())
{
@@ -109,15 +117,22 @@ void TableModifier::handleFks(const QString& tempTableName)
continue;
}
+ // Those were removed when fixing #2954. Seem to be useless for subHandleFks(). Unless there's some bug report for it,
+ // they should be removed in near future:
+
subModifier.usedTempTableNames = usedTempTableNames;
- subModifier.tableColMap = tableColMap;
subModifier.triggerNameToDdlMap = triggerNameToDdlMap;
- subModifier.existingColumns = existingColumns;
- subModifier.newName = newName;
- subModifier.subHandleFks(originalTable, tempTableName);
+ subModifier.existingColumns = existingColumns; // for identifying removed columns
+ subModifier.tableColMap = tableColMap; // for identifying renamed columns
+ subModifier.newName = fkTable;
+ subModifier.tablesHandledForFk = tablesHandledForFk;
+ subModifier.handleFks(originalTable, newName);
sqls += subModifier.generateSqls();
modifiedTables << fkTable;
+
triggerNameToDdlMap = subModifier.triggerNameToDdlMap;
+ tablesHandledForFk = subModifier.tablesHandledForFk;
+ usedTempTableNames = subModifier.usedTempTableNames;
modifiedTables += subModifier.getModifiedTables();
modifiedIndexes += subModifier.getModifiedIndexes();
@@ -129,22 +144,9 @@ void TableModifier::handleFks(const QString& tempTableName)
}
}
-void TableModifier::subHandleFks(const QString& oldName, const QString& oldTempName)
+void TableModifier::handleFks(const QString& oldName, const QString& theNewName)
{
- bool modified = false;
- foreach (SqliteCreateTable::Constraint* fk, createTable->getForeignKeysByTable(oldName))
- {
- if (subHandleFks(fk->foreignKey, oldName, oldTempName))
- modified = true;
- }
-
- foreach (SqliteCreateTable::Column::Constraint* fk, createTable->getColumnForeignKeysByTable(oldName))
- {
- if (subHandleFks(fk->foreignKey, oldName, oldTempName))
- modified = true;
- }
-
- if (!modified)
+ if (!handleFkConstrains(createTable.data(), oldName, theNewName))
return;
QString tempName = renameToTemp();
@@ -155,7 +157,7 @@ void TableModifier::subHandleFks(const QString& oldName, const QString& oldTempN
copyDataTo(originalTable);
- handleFks(tempName);
+ handleFks();
sqls << QString("DROP TABLE %1;").arg(wrapObjIfNeeded(tempName, dialect));
@@ -163,21 +165,15 @@ void TableModifier::subHandleFks(const QString& oldName, const QString& oldTempN
simpleHandleTriggers();
}
-bool TableModifier::subHandleFks(SqliteForeignKey* fk, const QString& oldName, const QString& oldTempName)
+bool TableModifier::handleFks(SqliteForeignKey* fk, const QString& oldName, const QString& theNewName)
{
// If table was not renamed (but uses temp table name), we will rename temp name into target name.
// If table was renamed, we will rename old name to new name.
bool modified = false;
// Table
- if (handleName(oldName, fk->foreignTable))
- modified = true;
- else if (!oldTempName.isNull() && fk->foreignTable.compare(oldName, Qt::CaseInsensitive) == 0)
- {
- // This is the case when main table was not renamed - we will stay with the original name, but we need to mark it as modified,
- // so the table gets recreated (the temp table is changed to the original table name in this FK).
+ if (handleName(oldName, theNewName, fk->foreignTable))
modified = true;
- }
// Columns
if (handleIndexedColumns(fk->indexedColumns))
@@ -186,45 +182,59 @@ bool TableModifier::subHandleFks(SqliteForeignKey* fk, const QString& oldName, c
return modified;
}
+bool TableModifier::handleFkConstrains(SqliteCreateTable* stmt, const QString& oldName, const QString& theNewName)
+{
+ bool modified = false;
+ for (SqliteCreateTable::Constraint* fk : stmt->getForeignKeysByTable(oldName))
+ {
+ if (handleFks(fk->foreignKey, oldName, theNewName))
+ modified = true;
+ }
+
+ for (SqliteCreateTable::Column::Constraint* fk : stmt->getColumnForeignKeysByTable(oldName))
+ {
+ if (handleFks(fk->foreignKey, oldName, theNewName))
+ modified = true;
+ }
+ return modified;
+}
+
bool TableModifier::handleName(const QString& oldName, QString& valueToUpdate)
{
- if (newName.compare(oldName, Qt::CaseInsensitive) == 0)
+ return handleName(oldName, newName, valueToUpdate);
+}
+
+bool TableModifier::handleName(const QString& oldName, const QString& theNewName, QString& valueToUpdate)
+{
+ if (theNewName.compare(oldName, Qt::CaseInsensitive) == 0)
return false;
if (valueToUpdate.compare(oldName, Qt::CaseInsensitive) == 0)
{
- valueToUpdate = newName;
+ valueToUpdate = theNewName;
return true;
}
return false;
}
-bool TableModifier::handleIndexedColumns(QList<SqliteIndexedColumn*>& columnsToUpdate)
+bool TableModifier::handleIndexedColumnsInitial(SqliteOrderBy* col, bool& modified)
{
- bool modified = false;
- QString lowerName;
- QMutableListIterator<SqliteIndexedColumn*> it(columnsToUpdate);
- while (it.hasNext())
- {
- SqliteIndexedColumn* idxCol = it.next();
+ if (col->isSimpleColumn())
+ return false;
- // If column was modified, assign new name
- lowerName = idxCol->name.toLower();
- if (tableColMap.contains(lowerName))
- {
- idxCol->name = tableColMap[lowerName];
- modified = true;
- continue;
- }
+ QString oldExpr = col->expr->tokens.detokenize();
+ if (!handleExpr(col->expr))
+ qWarning() << "Handling column change in multi-level expression of CREATE INDEX column failed. The change will most probably be skipped in the final update DDL.";
- // It wasn't modified, but it's not on existing columns list? Remove it.
- if (indexOf(existingColumns, idxCol->name, Qt::CaseInsensitive) == -1)
- {
- it.remove();
- modified = true;
- }
- }
- return modified;
+ modified = (col->expr->tokens.detokenize() != oldExpr);
+ return true;
+}
+
+bool TableModifier::handleIndexedColumnsInitial(SqliteIndexedColumn* col, bool& modified)
+{
+ UNUSED(col);
+ UNUSED(modified);
+ return false;
}
bool TableModifier::handleColumnNames(QStringList& columnsToUpdate)
@@ -783,6 +793,51 @@ bool TableModifier::handleExprWithTrigTable(SqliteExpr* expr)
return true;
}
+bool TableModifier::handleExpr(SqliteExpr* expr)
+{
+ // Handle subqueries
+ QList<SqliteExpr*> exprList;
+ exprList << expr->expr1;
+ exprList << expr->expr2;
+ exprList << expr->expr3;
+ exprList.append(expr->exprList);
+ exprList.removeAll(nullptr);
+ if (!exprList.isEmpty())
+ {
+ bool res = true;
+ for (SqliteExpr* e : exprList)
+ {
+ res &= handleExpr(e);
+ if (!res)
+ break;
+ }
+ return res;
+ }
+
+ // No need to handle subselect. Currently handleExpr() is used only in context of expr index column (in CREATE INDEX),
+ // which does not allow subselects. If the method comes to use with subselects supported, then this has to be implemented.
+
+ // Handle specific column
+ if (expr->mode != SqliteExpr::Mode::ID)
+ return true;
+
+ if (!expr->database.isNull())
+ return true;
+
+ QStringList columns = QStringList({expr->column});
+ if (!handleColumnNames(columns))
+ return true;
+
+ if (columns.isEmpty())
+ {
+ qDebug() << "Column in the expression is no longer present in the table. Cannot update the expression automatically.";
+ return false;
+ }
+
+ expr->column = columns.first();
+ return true;
+}
+
void TableModifier::simpleHandleIndexes()
{
SchemaResolver resolver(db);
diff --git a/SQLiteStudio3/coreSQLiteStudio/tablemodifier.h b/SQLiteStudio3/coreSQLiteStudio/tablemodifier.h
index 675202d..cba27ed 100644
--- a/SQLiteStudio3/coreSQLiteStudio/tablemodifier.h
+++ b/SQLiteStudio3/coreSQLiteStudio/tablemodifier.h
@@ -59,6 +59,7 @@ class API_EXPORT TableModifier
bool handleAllExprWithTrigTable(SqliteStatement* stmt, const QString& contextTable);
bool handleExprListWithTrigTable(const QList<SqliteExpr*>& exprList);
bool handleExprWithTrigTable(SqliteExpr* expr);
+ bool handleExpr(SqliteExpr* expr);
void simpleHandleIndexes();
void simpleHandleTriggers(const QString& view = QString::null);
SqliteQueryPtr parseQuery(const QString& ddl);
@@ -68,16 +69,55 @@ class API_EXPORT TableModifier
* @param newCreateTable
* Finds all tables referencing currently modified table and updates their referenced table name and columns.
*/
- void handleFks(const QString& tempTableName);
- void subHandleFks(const QString& oldName, const QString& oldTempName);
- bool subHandleFks(SqliteForeignKey* fk, const QString& oldName, const QString& oldTempName);
+ void handleFks();
+ void handleFks(const QString& oldName, const QString& theNewName);
+ bool handleFks(SqliteForeignKey* fk, const QString& oldName, const QString& theNewName);
+ bool handleFkConstrains(SqliteCreateTable* stmt, const QString& oldName, const QString& theNewName);
bool handleName(const QString& oldName, QString& valueToUpdate);
- bool handleIndexedColumns(QList<SqliteIndexedColumn*>& columnsToUpdate);
+ static bool handleName(const QString& oldName, const QString& theNewName, QString& valueToUpdate);
+ bool handleIndexedColumns(const QList<SqliteOrderBy*>& columnsToUpdate);
+ bool handleIndexedColumnsInitial(SqliteOrderBy* col, bool& modified);
+ bool handleIndexedColumnsInitial(SqliteIndexedColumn* col, bool& modified);
bool handleColumnNames(QStringList& columnsToUpdate);
bool handleColumnTokens(TokenList& columnsToUpdate);
bool handleUpdateColumns(SqliteUpdate* update);
+
+ template <class T>
+ bool handleIndexedColumns(QList<T*>& columnsToUpdate)
+ {
+ bool modified = false;
+ QString lowerName;
+ QString colName;
+ QMutableListIterator<T*> it(columnsToUpdate);
+ while (it.hasNext())
+ {
+ T* idxCol = it.next();
+ if (handleIndexedColumnsInitial(idxCol, modified))
+ continue;
+
+ colName = idxCol->getColumnName();
+
+ // If column was modified, assign new name
+ lowerName = colName.toLower();
+ if (tableColMap.contains(lowerName))
+ {
+ idxCol->setColumnName(tableColMap[lowerName]);
+ modified = true;
+ continue;
+ }
+
+ // It wasn't modified, but it's not on existing columns list? Remove it.
+ if (indexOf(existingColumns, colName, Qt::CaseInsensitive) == -1)
+ {
+ it.remove();
+ modified = true;
+ }
+ }
+ return modified;
+ }
+
Db* db = nullptr;
Dialect dialect;
@@ -114,6 +154,7 @@ class API_EXPORT TableModifier
QStringList existingColumns;
QHash<QString, QString> tableColMap;
QHash<QString, QString> triggerNameToDdlMap;
+ QStringList tablesHandledForFk;
QStringList modifiedTables;
QStringList modifiedIndexes;
QStringList modifiedTriggers;
@@ -121,4 +162,5 @@ class API_EXPORT TableModifier
QStringList usedTempTableNames;
};
+
#endif // TABLEMODIFIER_H
diff --git a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_de.qm b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_de.qm
index 9dad8df..2c10fb5 100644
--- a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_de.qm
+++ b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_de.qm
Binary files differ
diff --git a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_de.ts b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_de.ts
index 51b496d..0c60582 100644
--- a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_de.ts
+++ b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_de.ts
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
-<TS version="2.1" language="de_DE">
+<TS version="2.0" language="de_DE">
<context>
<name>AbstractDb</name>
<message>
@@ -38,19 +38,25 @@
<translation>Die Datenbank ist zur Ausführung von Abfragen nicht geöffnet worden.</translation>
</message>
<message>
- <location filename="../db/chainexecutor.cpp" line="47"/>
+ <location filename="../db/chainexecutor.cpp" line="50"/>
+ <source>Could not disable foreign keys in the database. Details: %1</source>
+ <comment>chain executor</comment>
+ <translation>Fremdschlüssel konnten nicht deaktiviert werden für die Datenbank. Details: %1</translation>
+ </message>
+ <message>
+ <location filename="../db/chainexecutor.cpp" line="57"/>
<source>Could not start a database transaction. Details: %1</source>
<comment>chain executor</comment>
<translation>Es kann keine Datenbanktransaktion gestartet werden. Details: %1</translation>
</message>
<message>
- <location filename="../db/chainexecutor.cpp" line="74"/>
+ <location filename="../db/chainexecutor.cpp" line="84"/>
<source>Interrupted</source>
<comment>chain executor</comment>
<translation>Abgebrochen</translation>
</message>
<message>
- <location filename="../db/chainexecutor.cpp" line="134"/>
+ <location filename="../db/chainexecutor.cpp" line="145"/>
<source>Could not commit a database transaction. Details: %1</source>
<comment>chain executor</comment>
<translation>Die Datenbanktransaktion kann nicht &apos;committet&apos; werden. Details: %1</translation>
@@ -153,25 +159,25 @@
<translation>Die Datenbank %1 kann nicht aktualisiert werden. Grund: %2</translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="312"/>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="341"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="350"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="379"/>
<source>Database file doesn&apos;t exist.</source>
<translation>Die Datenbankdatei existiert nicht.</translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="314"/>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="343"/>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="565"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="352"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="381"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="604"/>
<source>No supporting plugin loaded.</source>
<translation>Es wurde kein passendes plugin geladen.</translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="484"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="522"/>
<source>Database could not be initialized.</source>
<translation>Die Datenbank kann nicht initialisiert werden.</translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="494"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="532"/>
<source>No suitable database driver plugin found.</source>
<translation>Es wurde kein passender Datenbanktreiber (plugin) gefunden.</translation>
</message>
@@ -228,21 +234,28 @@ Tabellen, Indizes, Trigger und Views die in Datenbank %3 kopiert wurden, werden
<source>Error while creating trigger in target database: %1</source>
<translation>Fehler beim Erstellen eines Triggers in der Zieldatenbank %1</translation>
</message>
+ <message>
+ <location filename="../dbobjectorganizer.cpp" line="773"/>
+ <location filename="../dbobjectorganizer.cpp" line="780"/>
+ <location filename="../dbobjectorganizer.cpp" line="789"/>
+ <source>Could not parse object &apos;%1&apos; in order to move or copy it.</source>
+ <translation>Objekt &apos;%1&apos; konnte analysieren, um es zu verschieben oder kopieren zu können.</translation>
+ </message>
</context>
<context>
<name>DbVersionConverter</name>
<message>
- <location filename="../dbversionconverter.cpp" line="923"/>
+ <location filename="../dbversionconverter.cpp" line="913"/>
<source>Target file exists, but could not be overwritten.</source>
<translation>Die Zieldatei existiert zwar, konnte aber nicht überschrieben werden.</translation>
</message>
<message>
- <location filename="../dbversionconverter.cpp" line="942"/>
+ <location filename="../dbversionconverter.cpp" line="932"/>
<source>Could not find proper database plugin to create target database.</source>
<translation>Es konnte kein geeignetes Datenbankplugin gefunden werden, um die Zieldatenbank zu erzeugen.</translation>
</message>
<message>
- <location filename="../dbversionconverter.cpp" line="1176"/>
+ <location filename="../dbversionconverter.cpp" line="1166"/>
<source>Error while converting database: %1</source>
<translation>Fehler beim Konvertieren der Datenbank: %1</translation>
</message>
@@ -320,33 +333,33 @@ Tabellen, Indizes, Trigger und Views die in Datenbank %3 kopiert wurden, werden
<context>
<name>ExportWorker</name>
<message>
- <location filename="../exportworker.cpp" line="121"/>
+ <location filename="../exportworker.cpp" line="122"/>
<source>Error while exporting query results: %1</source>
<translation>Fehler beim Exportieren der Abfrageergebnisse: %1</translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="201"/>
+ <location filename="../exportworker.cpp" line="202"/>
<source>Error while counting data column width to export from query results: %1</source>
<translation>Fehler beim Ermitteln der Spaltenbreite für den Export der Abfrageergebnisse: %1</translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="353"/>
- <location filename="../exportworker.cpp" line="411"/>
+ <location filename="../exportworker.cpp" line="354"/>
+ <location filename="../exportworker.cpp" line="412"/>
<source>Could not parse %1 in order to export it. It will be excluded from the export output.</source>
<translation>%1 konnte zum Exportieren nicht korrekt verarbeitet werden. Diese Daten werden nicht exportiert.</translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="612"/>
+ <location filename="../exportworker.cpp" line="616"/>
<source>Error while reading data to export from table %1: %2</source>
<translation>Fehler beim Lesen der zu exportierenden Daten aus der Tabelle %1: %2</translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="620"/>
+ <location filename="../exportworker.cpp" line="624"/>
<source>Error while counting data to export from table %1: %2</source>
<translation>Fehler beim Ermitteln der zu exportierenden Daten aus der Tabelle %1: %2</translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="636"/>
+ <location filename="../exportworker.cpp" line="640"/>
<source>Error while counting data column width to export from table %1: %2</source>
<translation>Fehler beim Ermitteln der Spaltenbreite für den Export aus Tabelle %1: %2</translation>
</message>
@@ -446,20 +459,20 @@ Tabellen, Indizes, Trigger und Views die in Datenbank %3 kopiert wurden, werden
</message>
<message>
<location filename="../importworker.cpp" line="126"/>
- <location filename="../importworker.cpp" line="163"/>
- <location filename="../importworker.cpp" line="170"/>
+ <location filename="../importworker.cpp" line="168"/>
+ <location filename="../importworker.cpp" line="175"/>
<source>Error while importing data: %1</source>
<translation>Fehler beim Import der Daten: %1</translation>
</message>
<message>
<location filename="../importworker.cpp" line="126"/>
- <location filename="../importworker.cpp" line="170"/>
+ <location filename="../importworker.cpp" line="175"/>
<source>Interrupted.</source>
<comment>import process status update</comment>
<translation>Abgebrochen.</translation>
</message>
<message>
- <location filename="../importworker.cpp" line="158"/>
+ <location filename="../importworker.cpp" line="163"/>
<source>Could not import data row number %1. The row was ignored. Problem details: %2</source>
<translation>Datenzeile %1 konnte nicht importiert werden. Die Zeile wurde ignoriert. Problembeschreibung: %2</translation>
</message>
@@ -487,13 +500,13 @@ Tabellen, Indizes, Trigger und Views die in Datenbank %3 kopiert wurden, werden
<translation>Plugin %1 konnte wegen eines Fehlers bei der Initialisierung nicht geladen werden.</translation>
</message>
<message>
- <location filename="../services/impl/pluginmanagerimpl.cpp" line="732"/>
+ <location filename="../services/impl/pluginmanagerimpl.cpp" line="731"/>
<source>min: %1</source>
<comment>plugin dependency version</comment>
<translation>Min: %1</translation>
</message>
<message>
- <location filename="../services/impl/pluginmanagerimpl.cpp" line="733"/>
+ <location filename="../services/impl/pluginmanagerimpl.cpp" line="732"/>
<source>max: %1</source>
<comment>plugin dependency version</comment>
<translation>Max: %1</translation>
@@ -833,7 +846,7 @@ Problembeschreibung: %2</translation>
<translation>SQLite %1 unterstützt keine &apos;%2&apos; Klausel Ausdrücken.</translation>
</message>
<message>
- <location filename="../impl/dbattacherimpl.cpp" line="109"/>
+ <location filename="../impl/dbattacherimpl.cpp" line="115"/>
<source>Could not attach database %1: %2</source>
<translatorcomment>Generell muss in den Übersetzungen das &apos;attached&apos; genauer analysiert werden.</translatorcomment>
<translation>Die Datenbank %1 kann nicht angefügt werden: %2</translation>
@@ -846,13 +859,13 @@ Problembeschreibung: %2</translation>
</message>
<message>
<location filename="../parser/sqlite2_parse.cpp" line="1904"/>
- <location filename="../parser/sqlite3_parse.cpp" line="2167"/>
+ <location filename="../parser/sqlite3_parse.cpp" line="2171"/>
<source>Parser stack overflow</source>
<translation>Stacküberlauf bei Verarbeitung</translation>
</message>
<message>
<location filename="../parser/sqlite2_parse.cpp" line="4465"/>
- <location filename="../parser/sqlite3_parse.cpp" line="5084"/>
+ <location filename="../parser/sqlite3_parse.cpp" line="5089"/>
<source>Syntax error</source>
<translation>Syntaxfehler</translation>
</message>
@@ -907,11 +920,16 @@ Problembeschreibung: %2</translation>
<translation>Der Implementationscode darf nicht leer sein.</translation>
</message>
<message>
- <location filename="../selectresolver.cpp" line="317"/>
+ <location filename="../selectresolver.cpp" line="333"/>
<source>Could not resolve data source for column: %1</source>
<translation>Die Datenquelle für Spalte %1 kann nicht aufgelöst werden.</translation>
</message>
<message>
+ <location filename="../selectresolver.cpp" line="405"/>
+ <source>Could not resolve table for column &apos;%1&apos;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location filename="../services/impl/configimpl.cpp" line="612"/>
<source>Could not initialize configuration file. Any configuration changes and queries history will be lost after application restart. Tried to initialize the file at following localizations: %1.</source>
<translatorcomment>Ich hoffe, dass ich &quot;to initialize&quot; hier richtig mit &quot;erstellt&quot; übersetzt habe.</translatorcomment>
@@ -960,39 +978,39 @@ Problembeschreibung: %2</translation>
<translation>Tabellen füllen</translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="107"/>
+ <location filename="../tablemodifier.cpp" line="115"/>
<source>Table %1 is referencing table %2, but the foreign key definition will not be updated for new table definition due to problems while parsing DDL of the table %3.</source>
<translation>Tabelle %1 referenziert Tabelle %2, jedoch wird die &apos;foreign key&apos;-Definition für die neue Tabellendefinition nicht aktualisiert, da es Probleme bei der DDL-Analyse von Tabelle %3 gibt.</translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="379"/>
+ <location filename="../tablemodifier.cpp" line="389"/>
<source>All columns indexed by the index %1 are gone. The index will not be recreated after table modification.</source>
<translation>Alle Spalten, die von Index %1 indiziert wurden, sind verloren. Der Index wird nach der Tabellenmodifikation nicht neu erstellt.</translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="418"/>
+ <location filename="../tablemodifier.cpp" line="428"/>
<source>There is problem with proper processing trigger %1. It may be not fully updated afterwards and will need your attention.</source>
<translation>Es ist ein Problem bei der korrekten Verarbeitung des Triggers %1 aufgetreten. Er wird möglicherweise nicht vollständig aktualisert werden und sollte geprüft werden.</translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="465"/>
+ <location filename="../tablemodifier.cpp" line="475"/>
<source>Cannot not update trigger %1 according to table %2 modification.</source>
<translation>Die Aktualisierung des Triggers %1, resultierend aus der Änderung der Tabelle %2, kann nicht ausgeführt werden.</translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="645"/>
- <location filename="../tablemodifier.cpp" line="669"/>
- <location filename="../tablemodifier.cpp" line="688"/>
+ <location filename="../tablemodifier.cpp" line="655"/>
+ <location filename="../tablemodifier.cpp" line="679"/>
+ <location filename="../tablemodifier.cpp" line="698"/>
<source>There is a problem with updating an %1 statement within %2 trigger. One of the %1 substatements which might be referring to table %3 cannot be properly modified. Manual update of the trigger may be necessary.</source>
<translation>Es ist ein Problem beim Aktualisieren einer %1 Abfrage innerhalb eines %2 Triggers aufgetreten. Eine der %1 Unterabfragen, welche möglicherweise die Tabelle %3 referenziert, kann nicht geändert werden. Eine manuelle Anpassung des Triggers wird nötig sein.</translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="433"/>
+ <location filename="../tablemodifier.cpp" line="443"/>
<source>All columns covered by the trigger %1 are gone. The trigger will not be recreated after table modification.</source>
<translation>Alle Spalten, die durch den Trigger %1 abgedeckt wurden, sind verloren. Der Trigger wird nach der Änderung nicht wiederhergestellt.</translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="483"/>
+ <location filename="../tablemodifier.cpp" line="493"/>
<source>Cannot not update view %1 according to table %2 modifications.
The view will remain as it is.</source>
<translation>Die Aktualisierung des Views %1, resultierend aus der Änderung der Tabelle %2, kann nicht ausgeführt werden. Der View wird daher nicht geändert.</translation>
@@ -1016,29 +1034,29 @@ The view will remain as it is.</source>
<context>
<name>QueryExecutor</name>
<message>
- <location filename="../db/queryexecutor.cpp" line="133"/>
+ <location filename="../db/queryexecutor.cpp" line="137"/>
<source>Execution interrupted.</source>
<translation>Ausführung abgebrochen.</translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="174"/>
+ <location filename="../db/queryexecutor.cpp" line="178"/>
<source>Database is not open.</source>
<translation>Die Datenbank ist nicht geöffnet.</translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="182"/>
+ <location filename="../db/queryexecutor.cpp" line="186"/>
<source>Only one query can be executed simultaneously.</source>
<translation>Es kann nur eine Abfrage gleichzeitig ausgeführt werden.</translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="264"/>
- <location filename="../db/queryexecutor.cpp" line="548"/>
+ <location filename="../db/queryexecutor.cpp" line="275"/>
+ <location filename="../db/queryexecutor.cpp" line="560"/>
<source>An error occured while executing the count(*) query, thus data paging will be disabled. Error details from the database: %1</source>
<translatorcomment>Hier muss ggf. noch das &apos;data paging&apos; korrekt übersetzt werden.</translatorcomment>
<translation>Beim Ausführen der count(*) Abfrage ist ein Fehler aufgetreten, daher wird das data paging abgeschaltet. Problemdetails der Datenbank: %1</translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="459"/>
+ <location filename="../db/queryexecutor.cpp" line="471"/>
<source>SQLiteStudio was unable to extract metadata from the query. Results won&apos;t be editable.</source>
<translation>SQLiteStudio konnte keine Metadaten aus der Abfrage extrahieren. Die Ergebnismenge kann daher nicht editiert werden.</translation>
</message>
@@ -1094,7 +1112,7 @@ The view will remain as it is.</source>
<message>
<location filename="../services/updatemanager.cpp" line="131"/>
<source>An error occurred while checking for updates: %1.</source>
- <translation>Beim Prüfen auf Updates trat folgender Fehler auf: %1</translation>
+ <translation>Beim Prüfen auf Updates trat folgender Fehler auf: %1.</translation>
</message>
<message>
<location filename="../services/updatemanager.cpp" line="144"/>
diff --git a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_es.ts b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_es.ts
index 8131da9..6cab7b8 100644
--- a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_es.ts
+++ b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_es.ts
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
-<TS version="2.1" language="es_ES">
+<TS version="2.0" language="es_ES">
<context>
<name>AbstractDb</name>
<message>
@@ -38,19 +38,25 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/chainexecutor.cpp" line="47"/>
+ <location filename="../db/chainexecutor.cpp" line="50"/>
+ <source>Could not disable foreign keys in the database. Details: %1</source>
+ <comment>chain executor</comment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../db/chainexecutor.cpp" line="57"/>
<source>Could not start a database transaction. Details: %1</source>
<comment>chain executor</comment>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/chainexecutor.cpp" line="74"/>
+ <location filename="../db/chainexecutor.cpp" line="84"/>
<source>Interrupted</source>
<comment>chain executor</comment>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/chainexecutor.cpp" line="134"/>
+ <location filename="../db/chainexecutor.cpp" line="145"/>
<source>Could not commit a database transaction. Details: %1</source>
<comment>chain executor</comment>
<translation type="unfinished"></translation>
@@ -152,25 +158,25 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="312"/>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="341"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="350"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="379"/>
<source>Database file doesn&apos;t exist.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="314"/>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="343"/>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="565"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="352"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="381"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="604"/>
<source>No supporting plugin loaded.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="484"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="522"/>
<source>Database could not be initialized.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="494"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="532"/>
<source>No suitable database driver plugin found.</source>
<translation type="unfinished"></translation>
</message>
@@ -226,21 +232,28 @@ Tables, indexes, triggers and views copied to database %3 will remain.</source>
<source>Error while creating trigger in target database: %1</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../dbobjectorganizer.cpp" line="773"/>
+ <location filename="../dbobjectorganizer.cpp" line="780"/>
+ <location filename="../dbobjectorganizer.cpp" line="789"/>
+ <source>Could not parse object &apos;%1&apos; in order to move or copy it.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>DbVersionConverter</name>
<message>
- <location filename="../dbversionconverter.cpp" line="923"/>
+ <location filename="../dbversionconverter.cpp" line="913"/>
<source>Target file exists, but could not be overwritten.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../dbversionconverter.cpp" line="942"/>
+ <location filename="../dbversionconverter.cpp" line="932"/>
<source>Could not find proper database plugin to create target database.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../dbversionconverter.cpp" line="1176"/>
+ <location filename="../dbversionconverter.cpp" line="1166"/>
<source>Error while converting database: %1</source>
<translation type="unfinished"></translation>
</message>
@@ -318,33 +331,33 @@ Tables, indexes, triggers and views copied to database %3 will remain.</source>
<context>
<name>ExportWorker</name>
<message>
- <location filename="../exportworker.cpp" line="121"/>
+ <location filename="../exportworker.cpp" line="122"/>
<source>Error while exporting query results: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="201"/>
+ <location filename="../exportworker.cpp" line="202"/>
<source>Error while counting data column width to export from query results: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="353"/>
- <location filename="../exportworker.cpp" line="411"/>
+ <location filename="../exportworker.cpp" line="354"/>
+ <location filename="../exportworker.cpp" line="412"/>
<source>Could not parse %1 in order to export it. It will be excluded from the export output.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="612"/>
+ <location filename="../exportworker.cpp" line="616"/>
<source>Error while reading data to export from table %1: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="620"/>
+ <location filename="../exportworker.cpp" line="624"/>
<source>Error while counting data to export from table %1: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="636"/>
+ <location filename="../exportworker.cpp" line="640"/>
<source>Error while counting data column width to export from table %1: %2</source>
<translation type="unfinished"></translation>
</message>
@@ -443,20 +456,20 @@ Tables, indexes, triggers and views copied to database %3 will remain.</source>
</message>
<message>
<location filename="../importworker.cpp" line="126"/>
- <location filename="../importworker.cpp" line="163"/>
- <location filename="../importworker.cpp" line="170"/>
+ <location filename="../importworker.cpp" line="168"/>
+ <location filename="../importworker.cpp" line="175"/>
<source>Error while importing data: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../importworker.cpp" line="126"/>
- <location filename="../importworker.cpp" line="170"/>
+ <location filename="../importworker.cpp" line="175"/>
<source>Interrupted.</source>
<comment>import process status update</comment>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../importworker.cpp" line="158"/>
+ <location filename="../importworker.cpp" line="163"/>
<source>Could not import data row number %1. The row was ignored. Problem details: %2</source>
<translation type="unfinished"></translation>
</message>
@@ -484,13 +497,13 @@ Tables, indexes, triggers and views copied to database %3 will remain.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/pluginmanagerimpl.cpp" line="732"/>
+ <location filename="../services/impl/pluginmanagerimpl.cpp" line="731"/>
<source>min: %1</source>
<comment>plugin dependency version</comment>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/pluginmanagerimpl.cpp" line="733"/>
+ <location filename="../services/impl/pluginmanagerimpl.cpp" line="732"/>
<source>max: %1</source>
<comment>plugin dependency version</comment>
<translation type="unfinished"></translation>
@@ -827,7 +840,7 @@ Error details: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../impl/dbattacherimpl.cpp" line="109"/>
+ <location filename="../impl/dbattacherimpl.cpp" line="115"/>
<source>Could not attach database %1: %2</source>
<translation type="unfinished"></translation>
</message>
@@ -839,13 +852,13 @@ Error details: %2</source>
</message>
<message>
<location filename="../parser/sqlite2_parse.cpp" line="1904"/>
- <location filename="../parser/sqlite3_parse.cpp" line="2167"/>
+ <location filename="../parser/sqlite3_parse.cpp" line="2171"/>
<source>Parser stack overflow</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../parser/sqlite2_parse.cpp" line="4465"/>
- <location filename="../parser/sqlite3_parse.cpp" line="5084"/>
+ <location filename="../parser/sqlite3_parse.cpp" line="5089"/>
<source>Syntax error</source>
<translation type="unfinished"></translation>
</message>
@@ -900,11 +913,16 @@ Error details: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../selectresolver.cpp" line="317"/>
+ <location filename="../selectresolver.cpp" line="333"/>
<source>Could not resolve data source for column: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
+ <location filename="../selectresolver.cpp" line="405"/>
+ <source>Could not resolve table for column &apos;%1&apos;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location filename="../services/impl/configimpl.cpp" line="612"/>
<source>Could not initialize configuration file. Any configuration changes and queries history will be lost after application restart. Tried to initialize the file at following localizations: %1.</source>
<translation type="unfinished"></translation>
@@ -952,39 +970,39 @@ Error details: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="107"/>
+ <location filename="../tablemodifier.cpp" line="115"/>
<source>Table %1 is referencing table %2, but the foreign key definition will not be updated for new table definition due to problems while parsing DDL of the table %3.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="379"/>
+ <location filename="../tablemodifier.cpp" line="389"/>
<source>All columns indexed by the index %1 are gone. The index will not be recreated after table modification.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="418"/>
+ <location filename="../tablemodifier.cpp" line="428"/>
<source>There is problem with proper processing trigger %1. It may be not fully updated afterwards and will need your attention.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="465"/>
+ <location filename="../tablemodifier.cpp" line="475"/>
<source>Cannot not update trigger %1 according to table %2 modification.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="645"/>
- <location filename="../tablemodifier.cpp" line="669"/>
- <location filename="../tablemodifier.cpp" line="688"/>
+ <location filename="../tablemodifier.cpp" line="655"/>
+ <location filename="../tablemodifier.cpp" line="679"/>
+ <location filename="../tablemodifier.cpp" line="698"/>
<source>There is a problem with updating an %1 statement within %2 trigger. One of the %1 substatements which might be referring to table %3 cannot be properly modified. Manual update of the trigger may be necessary.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="433"/>
+ <location filename="../tablemodifier.cpp" line="443"/>
<source>All columns covered by the trigger %1 are gone. The trigger will not be recreated after table modification.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="483"/>
+ <location filename="../tablemodifier.cpp" line="493"/>
<source>Cannot not update view %1 according to table %2 modifications.
The view will remain as it is.</source>
<translation type="unfinished"></translation>
@@ -1008,28 +1026,28 @@ The view will remain as it is.</source>
<context>
<name>QueryExecutor</name>
<message>
- <location filename="../db/queryexecutor.cpp" line="133"/>
+ <location filename="../db/queryexecutor.cpp" line="137"/>
<source>Execution interrupted.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="174"/>
+ <location filename="../db/queryexecutor.cpp" line="178"/>
<source>Database is not open.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="182"/>
+ <location filename="../db/queryexecutor.cpp" line="186"/>
<source>Only one query can be executed simultaneously.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="264"/>
- <location filename="../db/queryexecutor.cpp" line="548"/>
+ <location filename="../db/queryexecutor.cpp" line="275"/>
+ <location filename="../db/queryexecutor.cpp" line="560"/>
<source>An error occured while executing the count(*) query, thus data paging will be disabled. Error details from the database: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="459"/>
+ <location filename="../db/queryexecutor.cpp" line="471"/>
<source>SQLiteStudio was unable to extract metadata from the query. Results won&apos;t be editable.</source>
<translation type="unfinished"></translation>
</message>
diff --git a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_fr.ts b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_fr.ts
index 5d6090c..6f86594 100644
--- a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_fr.ts
+++ b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_fr.ts
@@ -7,7 +7,7 @@
<location filename="../db/abstractdb.cpp" line="306"/>
<location filename="../db/abstractdb.cpp" line="323"/>
<source>Cannot execute query on closed database.</source>
- <translation>Impossible d&apos;exécuter la requête sur une base de données fermée.</translation>
+ <translation>Impossible d&rsquo;exécuter la requête sur une base de données fermée.</translation>
</message>
<message>
<location filename="../db/abstractdb.cpp" line="603"/>
@@ -29,19 +29,19 @@
<location filename="../db/chainexecutor.cpp" line="35"/>
<source>The database for executing queries was not defined.</source>
<comment>chain executor</comment>
- <translation>La base de données pour exécuter des requêtes n&apos;était pas définie.</translation>
+ <translation>La base de données pour exécuter des requêtes n&rsquo;était pas définie.</translation>
</message>
<message>
<location filename="../db/chainexecutor.cpp" line="41"/>
<source>The database for executing queries was not open.</source>
<comment>chain executor</comment>
- <translation>La base de données pour exécuter des requêtes n&apos;est pas ouverte.</translation>
+ <translation>La base de données pour exécuter des requêtes n&rsquo;est pas ouverte.</translation>
</message>
<message>
<location filename="../db/chainexecutor.cpp" line="47"/>
<source>Could not start a database transaction. Details: %1</source>
<comment>chain executor</comment>
- <translation>Impossible d&apos;initialiser une transaction de la base de données:%1</translation>
+ <translation>Impossible d&rsquo;initialiser une transaction de la base de données:%1</translation>
</message>
<message>
<location filename="../db/chainexecutor.cpp" line="74"/>
@@ -53,7 +53,7 @@
<location filename="../db/chainexecutor.cpp" line="134"/>
<source>Could not commit a database transaction. Details: %1</source>
<comment>chain executor</comment>
- <translation>Impossible d&apos;enregistrer la transaction de la base de données:%1</translation>
+ <translation>Impossible d&rsquo;enregistrer la transaction de la base de données:%1</translation>
</message>
</context>
<context>
@@ -76,7 +76,7 @@
<message>
<location filename="../completionhelper.cpp" line="211"/>
<source>New index name</source>
- <translation>Nouveau nom d&apos;index</translation>
+ <translation>Nouveau nom d&rsquo;index</translation>
</message>
<message>
<location filename="../completionhelper.cpp" line="214"/>
@@ -116,7 +116,7 @@
<message>
<location filename="../completionhelper.cpp" line="245"/>
<source>Error message</source>
- <translation>Message d&apos;erreur</translation>
+ <translation>Message d&rsquo;erreur</translation>
</message>
<message>
<location filename="../completionhelper.cpp" line="289"/>
@@ -126,7 +126,7 @@
<message>
<location filename="../completionhelper.cpp" line="304"/>
<source>Any word</source>
- <translation>N&apos;importe quel mot</translation>
+ <translation>N&rsquo;importe quel mot</translation>
</message>
<message>
<location filename="../completionhelper.cpp" line="485"/>
@@ -144,18 +144,18 @@
<message>
<location filename="../services/impl/dbmanagerimpl.cpp" line="63"/>
<source>Could not add database %1: %2</source>
- <translation>Impossible d&apos;ajouter une base de données %1: %2</translation>
+ <translation>Impossible d&rsquo;ajouter une base de données %1: %2</translation>
</message>
<message>
<location filename="../services/impl/dbmanagerimpl.cpp" line="138"/>
<source>Database %1 could not be updated, because of an error: %2</source>
- <translation>La base de données %1 ne peut ëtre mise à jour à cause de l&apos;erreur: %2</translation>
+ <translation>La base de données %1 ne peut ëtre mise à jour à cause de l&rsquo;erreur: %2</translation>
</message>
<message>
<location filename="../services/impl/dbmanagerimpl.cpp" line="312"/>
<location filename="../services/impl/dbmanagerimpl.cpp" line="341"/>
<source>Database file doesn&apos;t exist.</source>
- <translation>Le fichier de la base de données n&apos;existe pas.</translation>
+ <translation>Le fichier de la base de données n&rsquo;existe pas.</translation>
</message>
<message>
<location filename="../services/impl/dbmanagerimpl.cpp" line="314"/>
@@ -186,7 +186,7 @@
<message>
<location filename="../dbobjectorganizer.cpp" line="380"/>
<source>Could not parse table.</source>
- <translation>Impossible d&apos;analyser la table.</translation>
+ <translation>Impossible d&rsquo;analyser la table.</translation>
</message>
<message>
<location filename="../dbobjectorganizer.cpp" line="426"/>
@@ -220,7 +220,7 @@ Tables, index, déclencheurs et vues copiés de la base de données %3 seront ma
<message>
<location filename="../dbobjectorganizer.cpp" line="547"/>
<source>Error while creating index in target database: %1</source>
- <translation>Erreur lors de la création de l&apos;index de la base de données:%1</translation>
+ <translation>Erreur lors de la création de l&rsquo;index de la base de données:%1</translation>
</message>
<message>
<location filename="../dbobjectorganizer.cpp" line="552"/>
@@ -264,7 +264,7 @@ Tables, index, déclencheurs et vues copiés de la base de données %3 seront ma
<location filename="../ddlhistorymodel.cpp" line="69"/>
<source>Date of execution</source>
<comment>ddl history header</comment>
- <translation>Date d&apos;exécution</translation>
+ <translation>Date d&rsquo;exécution</translation>
</message>
<message>
<location filename="../ddlhistorymodel.cpp" line="71"/>
@@ -278,22 +278,22 @@ Tables, index, déclencheurs et vues copiés de la base de données %3 seront ma
<message>
<location filename="../services/exportmanager.cpp" line="72"/>
<source>Export plugin %1 doesn&apos;t support exporing query results.</source>
- <translation>Plugin d&apos;export %1 ne supporte pas l&apos;exportation de la requête.</translation>
+ <translation>Plugin d&rsquo;export %1 ne supporte pas l&rsquo;exportation de la requête.</translation>
</message>
<message>
<location filename="../services/exportmanager.cpp" line="98"/>
<source>Export plugin %1 doesn&apos;t support exporing tables.</source>
- <translation>Plugin d&apos;export %1 ne supporte pas l&apos;exportation de la table.</translation>
+ <translation>Plugin d&rsquo;export %1 ne supporte pas l&rsquo;exportation de la table.</translation>
</message>
<message>
<location filename="../services/exportmanager.cpp" line="122"/>
<source>Export plugin %1 doesn&apos;t support exporing databases.</source>
- <translation>Plugin d&apos;export %1 ne supporte pas l&apos;exportation de la base de données.</translation>
+ <translation>Plugin d&rsquo;export %1 ne supporte pas l&rsquo;exportation de la base de données.</translation>
</message>
<message>
<location filename="../services/exportmanager.cpp" line="155"/>
<source>Export format &apos;%1&apos; is not supported. Supported formats are: %2.</source>
- <translation>Format d&apos;export %1 n&apos;est pas supporté. Les formats supportés sont: %2.</translation>
+ <translation>Format d&rsquo;export «&nbsp;%1&nbsp;» n&rsquo;est pas supporté. Les formats supportés sont: %2.</translation>
</message>
<message>
<location filename="../services/exportmanager.cpp" line="218"/>
@@ -303,7 +303,7 @@ Tables, index, déclencheurs et vues copiés de la base de données %3 seront ma
<message>
<location filename="../services/exportmanager.cpp" line="222"/>
<source>Export to the file &apos;%1&apos; was successful.</source>
- <translation>Export vers le fichier &apos;%1&apos; avec succès.</translation>
+ <translation>Export vers le fichier &rsquo;%1&rsquo; avec succès.</translation>
</message>
<message>
<location filename="../services/exportmanager.cpp" line="224"/>
@@ -313,7 +313,7 @@ Tables, index, déclencheurs et vues copiés de la base de données %3 seront ma
<message>
<location filename="../services/exportmanager.cpp" line="266"/>
<source>Could not export to file %1. File cannot be open for writting.</source>
- <translation>Impossible d&apos;exporter vers le fichier &apos;%1&apos;. Le fichier ne peut être ouvert en écriture.</translation>
+ <translation>Impossible d&rsquo;exporter vers le fichier %1. Le fichier ne peut être ouvert en écriture.</translation>
</message>
</context>
<context>
@@ -321,7 +321,7 @@ Tables, index, déclencheurs et vues copiés de la base de données %3 seront ma
<message>
<location filename="../exportworker.cpp" line="121"/>
<source>Error while exporting query results: %1</source>
- <translation>Erreur lors de l&apos;exportation des résultats de la requête:%1</translation>
+ <translation>Erreur lors de l&rsquo;exportation des résultats de la requête:%1</translation>
</message>
<message>
<location filename="../exportworker.cpp" line="201"/>
@@ -332,7 +332,7 @@ Tables, index, déclencheurs et vues copiés de la base de données %3 seront ma
<location filename="../exportworker.cpp" line="353"/>
<location filename="../exportworker.cpp" line="411"/>
<source>Could not parse %1 in order to export it. It will be excluded from the export output.</source>
- <translation>Impossible d&apos;analyser %1 afin de l&apos;exporter. Celle-ci sera excluse de l&apos;exportation.</translation>
+ <translation>Impossible d&rsquo;analyser %1 afin de l&rsquo;exporter. Celle-ci sera excluse de l&rsquo;exportation.</translation>
</message>
<message>
<location filename="../exportworker.cpp" line="612"/>
@@ -355,7 +355,7 @@ Tables, index, déclencheurs et vues copiés de la base de données %3 seront ma
<message>
<location filename="../services/impl/functionmanagerimpl.cpp" line="232"/>
<source>Invalid number of arguments to function &apos;%1&apos;. Expected %2, but got %3.</source>
- <translation>Nombre de paramètres invalide de la fonction%1. Attendu %2, obtenu %3.</translation>
+ <translation>Nombre de paramètres invalide de la fonction %1. Attendu %2, obtenu %3.</translation>
</message>
<message>
<location filename="../services/impl/functionmanagerimpl.cpp" line="341"/>
@@ -365,7 +365,7 @@ Tables, index, déclencheurs et vues copiés de la base de données %3 seront ma
<message>
<location filename="../services/impl/functionmanagerimpl.cpp" line="347"/>
<source>Function %1(%2) was registered with language %3, but the plugin supporting that language is not currently loaded.</source>
- <translation>La fonction %1(%2) est référencée avec le langage %3, mais le plugin supportant ce langage n&apos;est actuellement pas chargé.</translation>
+ <translation>La fonction %1(%2) est référencée avec le langage %3, mais le plugin supportant ce langage n&rsquo;est actuellement pas chargé.</translation>
</message>
<message>
<location filename="../services/impl/functionmanagerimpl.cpp" line="365"/>
@@ -376,17 +376,17 @@ Tables, index, déclencheurs et vues copiés de la base de données %3 seront ma
<location filename="../services/impl/functionmanagerimpl.cpp" line="384"/>
<location filename="../services/impl/functionmanagerimpl.cpp" line="417"/>
<source>Could not open file %1 for reading: %2</source>
- <translation>Impossible d&apos;ouvrir en lecture le ficher %1:%2</translation>
+ <translation>Impossible d&rsquo;ouvrir en lecture le ficher %1:%2</translation>
</message>
<message>
<location filename="../services/impl/functionmanagerimpl.cpp" line="439"/>
<source>Could not open file %1 for writting: %2</source>
- <translation>Impossible d&apos;ouvrir en écriture le ficher %1:%2</translation>
+ <translation>Impossible d&rsquo;ouvrir en écriture le ficher %1:%2</translation>
</message>
<message>
<location filename="../services/impl/functionmanagerimpl.cpp" line="459"/>
<source>Error while writting to file %1: %2</source>
- <translation>Erreur lors de l&apos;écriture du fichier %1:%2</translation>
+ <translation>Erreur lors de l&rsquo;écriture du fichier %1:%2</translation>
</message>
<message>
<location filename="../services/impl/functionmanagerimpl.cpp" line="477"/>
@@ -399,7 +399,7 @@ Tables, index, déclencheurs et vues copiés de la base de données %3 seront ma
<message>
<location filename="../plugins/genericexportplugin.cpp" line="20"/>
<source>Could not initialize text codec for exporting. Using default codec: %1</source>
- <translation>Impossible d&apos;initialiser le paramètre texte por l&apos;export. Utulisation du paramètre par défaut: %1</translation>
+ <translation>Impossible d&rsquo;initialiser le paramètre texte por l&rsquo;export. Utulisation du paramètre par défaut: %1</translation>
</message>
</context>
<context>
@@ -407,7 +407,7 @@ Tables, index, déclencheurs et vues copiés de la base de données %3 seront ma
<message>
<location filename="../services/importmanager.cpp" line="93"/>
<source>Imported data to the table &apos;%1&apos; successfully.</source>
- <translation>Importation des données de la table &apos;%1&apos; réussie.</translation>
+ <translation>Importation des données de la table «&nbsp;%1&nbsp;» réussie.</translation>
</message>
</context>
<context>
@@ -415,39 +415,39 @@ Tables, index, déclencheurs et vues copiés de la base de données %3 seront ma
<message>
<location filename="../importworker.cpp" line="24"/>
<source>No columns provided by the import plugin.</source>
- <translation>Aucune colonne fournie par le plugin d&apos;importation.</translation>
+ <translation>Aucune colonne fournie par le plugin d&rsquo;importation.</translation>
</message>
<message>
<location filename="../importworker.cpp" line="30"/>
<source>Could not start transaction in order to import a data: %1</source>
- <translation>Impossible d&apos;initialiser la transaction d&apos;import de données: %1</translation>
+ <translation>Impossible d&rsquo;initialiser la transaction d&rsquo;import de données: %1</translation>
</message>
<message>
<location filename="../importworker.cpp" line="48"/>
<source>Could not commit transaction for imported data: %1</source>
- <translation>Impossible d&apos;enregistrer la transaction d&apos;import de données: %1</translation>
+ <translation>Impossible d&rsquo;enregistrer la transaction d&rsquo;import de données: %1</translation>
</message>
<message>
<location filename="../importworker.cpp" line="94"/>
<source>Table &apos;%1&apos; has less columns than there are columns in the data to be imported. Excessive data columns will be ignored.</source>
- <translation>La table %1 a moins de colonnes que de données à importer. Les colonnes supplèmentaires seront ignorées.</translation>
+ <translation>La table «&nbsp;%1&nbsp;» a moins de colonnes que de données à importer. Les colonnes supplèmentaires seront ignorées.</translation>
</message>
<message>
<location filename="../importworker.cpp" line="99"/>
<source>Table &apos;%1&apos; has more columns than there are columns in the data to be imported. Some columns in the table will be left empty.</source>
- <translation>La table %1 a plus de colonnes que de colonnes de données à importer. Certaines colonnes de la table seront vides.</translation>
+ <translation>La table «&nbsp;%1&nbsp;» a plus de colonnes que de colonnes de données à importer. Certaines colonnes de la table seront vides.</translation>
</message>
<message>
<location filename="../importworker.cpp" line="117"/>
<source>Could not create table to import to: %1</source>
- <translation>Impossible de créer la table d&apos;import: %1</translation>
+ <translation>Impossible de créer la table d&rsquo;import: %1</translation>
</message>
<message>
<location filename="../importworker.cpp" line="126"/>
<location filename="../importworker.cpp" line="163"/>
<location filename="../importworker.cpp" line="170"/>
<source>Error while importing data: %1</source>
- <translation>Erreur lors de l&apos;import des données: %1</translation>
+ <translation>Erreur lors de l&rsquo;import des données: %1</translation>
</message>
<message>
<location filename="../importworker.cpp" line="126"/>
@@ -472,12 +472,12 @@ Tables, index, déclencheurs et vues copiés de la base de données %3 seront ma
<message>
<location filename="../services/impl/pluginmanagerimpl.cpp" line="554"/>
<source>Cannot load plugin %1, because its dependency was not loaded: %2.</source>
- <translation>Chargement impossible du plugin %1, les dépendances n&apos;ont pa été chargées: %2.</translation>
+ <translation>Chargement impossible du plugin %1, les dépendances n&rsquo;ont pa été chargées: %2.</translation>
</message>
<message>
<location filename="../services/impl/pluginmanagerimpl.cpp" line="563"/>
<source>Cannot load plugin %1. Error details: %2</source>
- <translation>Chargement impossible du plugin %1, Détails de l&apos;erreur: %2</translation>
+ <translation>Chargement impossible du plugin %1, Détails de l&rsquo;erreur: %2</translation>
</message>
<message>
<location filename="../services/impl/pluginmanagerimpl.cpp" line="579"/>
@@ -553,7 +553,7 @@ Tables, index, déclencheurs et vues copiés de la base de données %3 seront ma
<message>
<location filename="../plugins/populatedictionary.ui" line="74"/>
<source>Method of using words</source>
- <translation>Méthode d&apos;utilisation des mots</translation>
+ <translation>Méthode d&rsquo;utilisation des mots</translation>
</message>
<message>
<location filename="../plugins/populatedictionary.ui" line="80"/>
@@ -571,7 +571,7 @@ Tables, index, déclencheurs et vues copiés de la base de données %3 seront ma
<message>
<location filename="../services/populatemanager.cpp" line="89"/>
<source>Table &apos;%1&apos; populated successfully.</source>
- <translation>Table &apos;%1&apos; remplie avec succès.</translation>
+ <translation>Table «&nbsp;%1&nbsp;» remplie avec succès.</translation>
</message>
</context>
<context>
@@ -704,7 +704,7 @@ Tables, index, déclencheurs et vues copiés de la base de données %3 seront ma
<message>
<location filename="../plugins/populatescript.ui" line="26"/>
<source>Initialization code (optional)</source>
- <translation>Code d&apos;initialisation (optionel)</translation>
+ <translation>Code d&rsquo;initialisation (optionel)</translation>
</message>
<message>
<location filename="../plugins/populatescript.ui" line="45"/>
@@ -748,7 +748,7 @@ Tables, index, déclencheurs et vues copiés de la base de données %3 seront ma
<message>
<location filename="../populateworker.cpp" line="23"/>
<source>Could not start transaction in order to perform table populating. Error details: %1</source>
- <translation>Impossible d&apos;initialiser la transaction pour remplir la table.Détails de l&apos;erreur %1</translation>
+ <translation>Impossible d&rsquo;initialiser la transaction pour remplir la table.Détails de l&rsquo;erreur %1</translation>
</message>
<message>
<location filename="../populateworker.cpp" line="63"/>
@@ -758,7 +758,7 @@ Tables, index, déclencheurs et vues copiés de la base de données %3 seront ma
<message>
<location filename="../populateworker.cpp" line="74"/>
<source>Could not commit transaction after table populating. Error details: %1</source>
- <translation>Impossible d&apos;enregistrer la transaction après le remplissage de la table. Erreur %1</translation>
+ <translation>Impossible d&rsquo;enregistrer la transaction après le remplissage de la table. Erreur %1</translation>
</message>
</context>
<context>
@@ -767,7 +767,7 @@ Tables, index, déclencheurs et vues copiés de la base de données %3 seront ma
<location filename="../db/abstractdb2.h" line="199"/>
<location filename="../db/abstractdb3.h" line="356"/>
<source>Could not open database: %1</source>
- <translation>Impossible d&apos;ouvrir la base de données: %1</translation>
+ <translation>Impossible d&rsquo;ouvrir la base de données: %1</translation>
</message>
<message>
<location filename="../db/abstractdb2.h" line="805"/>
@@ -789,18 +789,18 @@ Tables, index, déclencheurs et vues copiés de la base de données %3 seront ma
<location filename="../dbversionconverter.cpp" line="253"/>
<location filename="../dbversionconverter.cpp" line="331"/>
<source>SQLite %1 does not support &apos;%2&apos; statement.</source>
- <translation>SQLite %1 ne supporte pas l&apos;instruction &apos;%2&apos;.</translation>
+ <translation>SQLite %1 ne supporte pas l&rsquo;instruction «&nbsp;%2&nbsp;».</translation>
</message>
<message>
<location filename="../dbversionconverter.cpp" line="201"/>
<source>SQLite %1 does not support &apos;%2&apos; statement, but the regular table can be created instead if you proceed.</source>
- <translation>SQLite %1 ne supporte pas l&apos;instruction &apos;%2&apos;, mais la table normale peut être créée à la place si vous confirmez.</translation>
+ <translation>SQLite %1 ne supporte pas l&rsquo;instruction «&nbsp;%2&nbsp;», mais la table normale peut être créée à la place si vous confirmez.</translation>
</message>
<message>
<location filename="../dbversionconverter.cpp" line="424"/>
<source>Could not parse statement: %1
Error details: %2</source>
- <translation>Impossible d&apos;analyser l&apos;instruction: %1
+ <translation>Impossible d&rsquo;analyser l&rsquo;instruction: %1
Détails erreur: %2</translation>
</message>
<message>
@@ -809,29 +809,29 @@ Détails erreur: %2</translation>
<location filename="../dbversionconverter.cpp" line="482"/>
<location filename="../dbversionconverter.cpp" line="515"/>
<source>SQLite %1 does not support the &apos;%2&apos; clause. Cannot convert &apos;%3&apos; statement with that clause.</source>
- <translation>SQLite %1 ne supporte pas la clause &apos;%2&apos;. Impossible de convertir l&apos;instruction &apos;%3&apos; avec cette clause.</translation>
+ <translation>SQLite %1 ne supporte pas la clause «&nbsp;%2&nbsp;». Impossible de convertir l&rsquo;instruction «&nbsp;%3&nbsp;» avec cette clause.</translation>
</message>
<message>
<location filename="../dbversionconverter.cpp" line="488"/>
<source>SQLite %1 does not support the &apos;%2&apos; clause in the &apos;%3&apos; statement.</source>
- <translation>SQLite %1 ne supporte pas la clause &apos;%2&apos; de l&apos;instruction &apos;%3&apos;.</translation>
+ <translation>SQLite %1 ne supporte pas la clause «&nbsp;%2&nbsp;» de l&rsquo;instruction «&nbsp;%3&nbsp;».</translation>
</message>
<message>
<location filename="../dbversionconverter.cpp" line="756"/>
<source>SQLite %1 does not support current date or time clauses in expressions.</source>
- <translation>SQLite %1 ne supporte pas la clause date ou l&apos;heure actuelle dans l&apos;expression.</translation>
+ <translation>SQLite %1 ne supporte pas la clause date ou l&rsquo;heure actuelle dans l&rsquo;expression.</translation>
</message>
<message>
<location filename="../dbversionconverter.cpp" line="767"/>
<location filename="../dbversionconverter.cpp" line="770"/>
<location filename="../dbversionconverter.cpp" line="781"/>
<source>SQLite %1 does not support &apos;%2&apos; clause in expressions.</source>
- <translation>SQLite %1 ne supporte pas la clause &apos;%2&apos; dans l&apos;expression.</translation>
+ <translation>SQLite %1 ne supporte pas la clause «&nbsp;%2&nbsp;» dans l&rsquo;expression.</translation>
</message>
<message>
<location filename="../impl/dbattacherimpl.cpp" line="109"/>
<source>Could not attach database %1: %2</source>
- <translation>Impossible d&apos;attacher la base de données %1: %2</translation>
+ <translation>Impossible d&rsquo;attacher la base de données %1: %2</translation>
</message>
<message>
<location filename="../parser/parsercontext.cpp" line="108"/>
@@ -849,12 +849,12 @@ Détails erreur: %2</translation>
<location filename="../parser/sqlite2_parse.cpp" line="4465"/>
<location filename="../parser/sqlite3_parse.cpp" line="5084"/>
<source>Syntax error</source>
- <translation>Erreur de syntaxe </translation>
+ <translation>Erreur de syntaxe</translation>
</message>
<message>
<location filename="../plugins/populatedictionary.cpp" line="30"/>
<source>Could not open dictionary file %1 for reading.</source>
- <translation>Impossible d&apos;ouvrir en lecture le fichier dictionnaire %1.</translation>
+ <translation>Impossible d&rsquo;ouvrir en lecture le fichier dictionnaire %1.</translation>
</message>
<message>
<location filename="../plugins/populatedictionary.cpp" line="91"/>
@@ -884,22 +884,22 @@ Détails erreur: %2</translation>
<message>
<location filename="../plugins/populatescript.cpp" line="58"/>
<source>Error while executing populating initial code: %1</source>
- <translation>Erreur à l&apos;initialisation du code de remplissage: %1</translation>
+ <translation>Erreur à l&rsquo;initialisation du code de remplissage: %1</translation>
</message>
<message>
<location filename="../plugins/populatescript.cpp" line="80"/>
<source>Error while executing populating code: %1</source>
- <translation>Erreur à l&apos;exécution du code de remplissage: %1</translation>
+ <translation>Erreur à l&rsquo;exécution du code de remplissage: %1</translation>
</message>
<message>
<location filename="../plugins/populatescript.cpp" line="112"/>
<source>Select implementation language.</source>
- <translation>Sélectionnez l&apos;application langage.</translation>
+ <translation>Sélectionnez l&rsquo;application langage.</translation>
</message>
<message>
<location filename="../plugins/populatescript.cpp" line="113"/>
<source>Implementation code cannot be empty.</source>
- <translation>L&apos;application de code ne peut être vide.</translation>
+ <translation>L&rsquo;application de code ne peut être vide.</translation>
</message>
<message>
<location filename="../selectresolver.cpp" line="317"/>
@@ -909,7 +909,9 @@ Détails erreur: %2</translation>
<message>
<location filename="../services/impl/configimpl.cpp" line="612"/>
<source>Could not initialize configuration file. Any configuration changes and queries history will be lost after application restart. Tried to initialize the file at following localizations: %1.</source>
- <translation>Impossible d&apos;initialiser le fichier de configuration. Aucune modification et les requêtes seront perdues après redémarrage. Essayez d&apos;initialiser le fichier avec cette localisation: %1.</translation>
+ <translation>Impossible d&rsquo;initialiser le fichier de configuration.
+ Aucune modification et les requêtes seront perdues après redémarrage.
+ Essayez d&rsquo;initialiser le fichier avec cette localisation: %1.</translation>
</message>
<message>
<location filename="../sqlitestudio.cpp" line="291"/>
@@ -956,12 +958,12 @@ Détails erreur: %2</translation>
<message>
<location filename="../tablemodifier.cpp" line="107"/>
<source>Table %1 is referencing table %2, but the foreign key definition will not be updated for new table definition due to problems while parsing DDL of the table %3.</source>
- <translation>La table %1 référence la table %2, mais la clé étrangère ne pourra être mise à jour pour la nouvelle table à cause de problèmes lors de l&apos;analyse DDL de la table %3.</translation>
+ <translation>La table %1 référence la table %2, mais la clé étrangère ne pourra être mise à jour pour la nouvelle table à cause de problèmes lors de l&rsquo;analyse DDL de la table %3.</translation>
</message>
<message>
<location filename="../tablemodifier.cpp" line="379"/>
<source>All columns indexed by the index %1 are gone. The index will not be recreated after table modification.</source>
- <translation>Toutes les colonnes indéxées par l&apos;indexe %1 sont faites. L&apos;indexe ne sera pas recréé après la modification de la table.</translation>
+ <translation>Toutes les colonnes indéxées par l&rsquo;indexe %1 sont faites. L&rsquo;indexe ne sera pas recréé après la modification de la table.</translation>
</message>
<message>
<location filename="../tablemodifier.cpp" line="418"/>
@@ -994,22 +996,22 @@ La vue restera telque.</translation>
</message>
<message>
<source>There is a problem with updating an %1 statement within %2 trigger. One of the SELECT substatements which might be referring to table %3 cannot be properly modified. Manual update of the trigger may be necessary.</source>
- <translation type="obsolete">Il y a un problème à la mise à jour l&apos;instruction %1 avec le déclencheur %2. Une partie de l&apos;instruction SELECT référençant la table %3 ne ppermet pas sa modification. La mise à jour manuelle du déclencheur est nécessaire.</translation>
+ <translation type="obsolete">Il y a un problème à la mise à jour l&rsquo;instruction %1 avec le déclencheur %2. Une partie de l&rsquo;instruction SELECT référençant la table %3 ne ppermet pas sa modification. La mise à jour manuelle du déclencheur est nécessaire.</translation>
</message>
<message>
<location filename="../viewmodifier.cpp" line="25"/>
<source>Could not parse DDL of the view to be created. Details: %1</source>
- <translation>Impossible d&apos;analyser le DDL de création de vue. Détails: %1</translation>
+ <translation>Impossible d&rsquo;analyser le DDL de création de vue. Détails: %1</translation>
</message>
<message>
<location filename="../viewmodifier.cpp" line="34"/>
<source>Parsed query is not CREATE VIEW. It&apos;s: %1</source>
- <translation>L&apos;expression CREATE VIEW est fausse. C&apos;est: %1</translation>
+ <translation>L&rsquo;expression CREATE VIEW est fausse. C&rsquo;est: %1</translation>
</message>
<message>
<location filename="../viewmodifier.cpp" line="82"/>
<source>SQLiteStudio was unable to resolve columns returned by the new view, therefore it won&apos;t be able to tell which triggers might fail during the recreation process.</source>
- <translation>SQLiteStudio ne peut résoudre les colonnes résultant de la nouvelle vue, d&apos;où le déclencheur en cause ne pourra être indiqué pendant le process.</translation>
+ <translation>SQLiteStudio ne peut résoudre les colonnes résultant de la nouvelle vue, d&rsquo;où le déclencheur en cause ne pourra être indiqué pendant le process.</translation>
</message>
</context>
<context>
@@ -1022,7 +1024,7 @@ La vue restera telque.</translation>
<message>
<location filename="../db/queryexecutor.cpp" line="174"/>
<source>Database is not open.</source>
- <translation>La base de données n&apos;est ouverte.</translation>
+ <translation>La base de données n&rsquo;est ouverte.</translation>
</message>
<message>
<location filename="../db/queryexecutor.cpp" line="182"/>
@@ -1033,12 +1035,12 @@ La vue restera telque.</translation>
<location filename="../db/queryexecutor.cpp" line="264"/>
<location filename="../db/queryexecutor.cpp" line="548"/>
<source>An error occured while executing the count(*) query, thus data paging will be disabled. Error details from the database: %1</source>
- <translation>Une erreur s&apos;est produite à l&apos;exécution de la requête count(*), la recherche des données est arrêtée. Erreur de la base de données:%1</translation>
+ <translation>Une erreur s&rsquo;est produite à l&rsquo;exécution de la requête count(*), la recherche des données est arrêtée. Erreur de la base de données:%1</translation>
</message>
<message>
<location filename="../db/queryexecutor.cpp" line="459"/>
<source>SQLiteStudio was unable to extract metadata from the query. Results won&apos;t be editable.</source>
- <translation>SQLiteStudio ne peut extraire des métadonnées d&apos;une requête. Les résultats ne peut être affichés.</translation>
+ <translation>SQLiteStudio ne peut extraire des métadonnées d&rsquo;une requête. Les résultats ne peut être affichés.</translation>
</message>
</context>
<context>
@@ -1066,7 +1068,7 @@ La vue restera telque.</translation>
<location filename="../sqlhistorymodel.cpp" line="32"/>
<source>Execution date</source>
<comment>sql history header</comment>
- <translation>Date d&apos;exécution</translation>
+ <translation>Date d&rsquo;exécution</translation>
</message>
<message>
<location filename="../sqlhistorymodel.cpp" line="34"/>
@@ -1098,7 +1100,7 @@ La vue restera telque.</translation>
<message>
<location filename="../services/updatemanager.cpp" line="144"/>
<source>Could not check available updates, because server responded with invalid message format. It is safe to ignore this warning.</source>
- <translation>Impossible de vérifier la mise à jour, car le serveur a répondu avec un message invalide. Il est possible d&apos;ignorer le warning.</translation>
+ <translation>Impossible de vérifier la mise à jour, car le serveur a répondu avec un message invalide. Il est possible d&rsquo;ignorer le warning.</translation>
</message>
<message>
<location filename="../services/updatemanager.cpp" line="175"/>
@@ -1108,7 +1110,7 @@ La vue restera telque.</translation>
<message>
<location filename="../services/updatemanager.cpp" line="188"/>
<source>Could not download updates, because server responded with invalid message format. You can try again later or download and install updates manually. See &lt;a href=&quot;%1&quot;&gt;User Manual&lt;/a&gt; for details.</source>
- <translation>Impossibles de télécharger les mises à jour, car le serveur répond avec un format de message invalide. Vous pover essayer plus tard ou télécharger et mettre à jour manuellement. Voir &lt;a href=&quot;%1&quot;&gt;User Manual&lt;/a&gt; for details.</translation>
+ <translation>Impossibles de télécharger les mises à jour, car le serveur répond avec un format de message invalide. Vous pover essayer plus tard ou télécharger et mettre à jour manuellement. Voir &lt;a href=&quot;%1&quot;&gt;User Manual&lt;/a&gt; for details.</translation>
</message>
<message>
<location filename="../services/updatemanager.cpp" line="195"/>
@@ -1118,7 +1120,7 @@ La vue restera telque.</translation>
<message>
<location filename="../services/updatemanager.cpp" line="206"/>
<source>There was no updates to download. Updating aborted.</source>
- <translation>Il n&apos;y a aucune mise à jour à télécharger. Mise à jour abandonnée.</translation>
+ <translation>Il n&rsquo;y a aucune mise à jour à télécharger. Mise à jour abandonnée.</translation>
</message>
<message>
<location filename="../services/updatemanager.cpp" line="241"/>
@@ -1133,7 +1135,7 @@ La vue restera telque.</translation>
<message>
<location filename="../services/updatemanager.cpp" line="255"/>
<source>Failed to open file &apos;%1&apos; for writting: %2. Updating aborted.</source>
- <translation>Erreur à l&apos;ouverture du fichier %1 pour l&apos;écriture: %2. Mise à jour abandonnée.</translation>
+ <translation>Erreur à l&rsquo;ouverture du fichier «&nbsp;%1&nbsp;» pour l&rsquo;écriture: %2. Mise à jour abandonnée.</translation>
</message>
<message>
<location filename="../services/updatemanager.cpp" line="276"/>
@@ -1143,7 +1145,7 @@ La vue restera telque.</translation>
<message>
<location filename="../services/updatemanager.cpp" line="287"/>
<source>Could not copy current application directory into %1 directory.</source>
- <translation>Impossible de copier le répertoire de l&apos;application courante dans %1.</translation>
+ <translation>Impossible de copier le répertoire de l&rsquo;application courante dans %1.</translation>
</message>
<message>
<location filename="../services/updatemanager.cpp" line="340"/>
@@ -1165,7 +1167,7 @@ Details: %3</source>
<message>
<location filename="../services/updatemanager.cpp" line="360"/>
<source>Could not move directory %1 to %2 and also failed to restore original directory, so the original SQLiteStudio directory is now located at: %3</source>
- <translation>Impossible de déplacer le répertoire %1 vers %2 d&apos;où l&apos;impossibilité de restaurer le répertoire original. SQLiteStudio est maintenant localisé: %3</translation>
+ <translation>Impossible de déplacer le répertoire %1 vers %2 d&rsquo;où l&rsquo;impossibilité de restaurer le répertoire original. SQLiteStudio est maintenant localisé: %3</translation>
</message>
<message>
<location filename="../services/updatemanager.cpp" line="365"/>
@@ -1175,12 +1177,12 @@ Details: %3</source>
<message>
<location filename="../services/updatemanager.cpp" line="444"/>
<source>Could not unpack component %1 into %2 directory.</source>
- <translation>Impossible d&apos;extraire le composant %1 dans le répertoire %2.</translation>
+ <translation>Impossible d&rsquo;extraire le composant %1 dans le répertoire %2.</translation>
</message>
<message>
<location filename="../services/updatemanager.cpp" line="555"/>
<source>Could not find permissions elevator application to run update as a root. Looked for: %1</source>
- <translation>Impossible d&apos;élever les autorisations pour lancer la mise à jour en tantque root. Bloqué: %1</translation>
+ <translation>Impossible d&rsquo;élever les autorisations pour lancer la mise à jour en tantque root. Bloqué: %1</translation>
</message>
<message>
<location filename="../services/updatemanager.cpp" line="562"/>
@@ -1213,17 +1215,17 @@ Details: %3</source>
<message>
<location filename="../services/updatemanager.cpp" line="661"/>
<source>Could not execute final updating steps as administrator.</source>
- <translation>Impossible de finaliser la mis à jour en tant qu&apos;administrateur.</translation>
+ <translation>Impossible de finaliser la mis à jour en tant qu&rsquo;administrateur.</translation>
</message>
<message>
<location filename="../services/updatemanager.cpp" line="673"/>
<source>Could not execute final updating steps as administrator. Updater startup timed out.</source>
- <translation>Impossible de finaliser la mis à jour en tant qu&apos;administrateur. Délai d&apos;attente de lancement dépassé.</translation>
+ <translation>Impossible de finaliser la mis à jour en tant qu&rsquo;administrateur. Délai d&rsquo;attente de lancement dépassé.</translation>
</message>
<message>
<location filename="../services/updatemanager.cpp" line="679"/>
<source>Could not execute final updating steps as administrator. Updater operation timed out.</source>
- <translation>Impossible de finaliser la mis à jour en tant qu&apos;administrateur. Délai d&apos;attente d&apos;opération dépassé.</translation>
+ <translation>Impossible de finaliser la mis à jour en tant qu&rsquo;administrateur. Délai d&rsquo;attente d&rsquo;opération dépassé.</translation>
</message>
<message>
<location filename="../services/updatemanager.cpp" line="696"/>
@@ -1238,7 +1240,7 @@ Details: %3</source>
<message>
<location filename="../services/updatemanager.cpp" line="817"/>
<source>Package not in tar.gz format, cannot install: %1</source>
- <translation>Installation impossible un paquet n&apos;est pas au format tar.zg: %1</translation>
+ <translation>Installation impossible un paquet n&rsquo;est pas au format tar.zg: %1</translation>
</message>
<message>
<location filename="../services/updatemanager.cpp" line="824"/>
@@ -1280,8 +1282,8 @@ Details: %3</source>
<location filename="../services/updatemanager.cpp" line="961"/>
<source>Error executing update command: %1
Error message: %2</source>
- <translation>Erreur d&apos;exécution de la commande de mise à jour: %1
-Message d&apos;erreur: %2</translation>
+ <translation>Erreur d&rsquo;exécution de la commande de mise à jour: %1
+Message d&rsquo;erreur: %2</translation>
</message>
<message>
<location filename="../services/updatemanager.cpp" line="1028"/>
diff --git a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_it.qm b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_it.qm
new file mode 100644
index 0000000..9dad8df
--- /dev/null
+++ b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_it.qm
Binary files differ
diff --git a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_it.ts b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_it.ts
index 27d4349..9b031de 100644
--- a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_it.ts
+++ b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_it.ts
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
-<TS version="2.1" language="it_IT">
+<TS version="2.0" language="it_IT">
<context>
<name>AbstractDb</name>
<message>
@@ -38,19 +38,25 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/chainexecutor.cpp" line="47"/>
+ <location filename="../db/chainexecutor.cpp" line="50"/>
+ <source>Could not disable foreign keys in the database. Details: %1</source>
+ <comment>chain executor</comment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../db/chainexecutor.cpp" line="57"/>
<source>Could not start a database transaction. Details: %1</source>
<comment>chain executor</comment>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/chainexecutor.cpp" line="74"/>
+ <location filename="../db/chainexecutor.cpp" line="84"/>
<source>Interrupted</source>
<comment>chain executor</comment>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/chainexecutor.cpp" line="134"/>
+ <location filename="../db/chainexecutor.cpp" line="145"/>
<source>Could not commit a database transaction. Details: %1</source>
<comment>chain executor</comment>
<translation type="unfinished"></translation>
@@ -152,25 +158,25 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="312"/>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="341"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="350"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="379"/>
<source>Database file doesn&apos;t exist.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="314"/>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="343"/>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="565"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="352"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="381"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="604"/>
<source>No supporting plugin loaded.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="484"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="522"/>
<source>Database could not be initialized.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="494"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="532"/>
<source>No suitable database driver plugin found.</source>
<translation type="unfinished"></translation>
</message>
@@ -226,21 +232,28 @@ Tables, indexes, triggers and views copied to database %3 will remain.</source>
<source>Error while creating trigger in target database: %1</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../dbobjectorganizer.cpp" line="773"/>
+ <location filename="../dbobjectorganizer.cpp" line="780"/>
+ <location filename="../dbobjectorganizer.cpp" line="789"/>
+ <source>Could not parse object &apos;%1&apos; in order to move or copy it.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>DbVersionConverter</name>
<message>
- <location filename="../dbversionconverter.cpp" line="923"/>
+ <location filename="../dbversionconverter.cpp" line="913"/>
<source>Target file exists, but could not be overwritten.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../dbversionconverter.cpp" line="942"/>
+ <location filename="../dbversionconverter.cpp" line="932"/>
<source>Could not find proper database plugin to create target database.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../dbversionconverter.cpp" line="1176"/>
+ <location filename="../dbversionconverter.cpp" line="1166"/>
<source>Error while converting database: %1</source>
<translation type="unfinished"></translation>
</message>
@@ -318,33 +331,33 @@ Tables, indexes, triggers and views copied to database %3 will remain.</source>
<context>
<name>ExportWorker</name>
<message>
- <location filename="../exportworker.cpp" line="121"/>
+ <location filename="../exportworker.cpp" line="122"/>
<source>Error while exporting query results: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="201"/>
+ <location filename="../exportworker.cpp" line="202"/>
<source>Error while counting data column width to export from query results: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="353"/>
- <location filename="../exportworker.cpp" line="411"/>
+ <location filename="../exportworker.cpp" line="354"/>
+ <location filename="../exportworker.cpp" line="412"/>
<source>Could not parse %1 in order to export it. It will be excluded from the export output.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="612"/>
+ <location filename="../exportworker.cpp" line="616"/>
<source>Error while reading data to export from table %1: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="620"/>
+ <location filename="../exportworker.cpp" line="624"/>
<source>Error while counting data to export from table %1: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="636"/>
+ <location filename="../exportworker.cpp" line="640"/>
<source>Error while counting data column width to export from table %1: %2</source>
<translation type="unfinished"></translation>
</message>
@@ -443,20 +456,20 @@ Tables, indexes, triggers and views copied to database %3 will remain.</source>
</message>
<message>
<location filename="../importworker.cpp" line="126"/>
- <location filename="../importworker.cpp" line="163"/>
- <location filename="../importworker.cpp" line="170"/>
+ <location filename="../importworker.cpp" line="168"/>
+ <location filename="../importworker.cpp" line="175"/>
<source>Error while importing data: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../importworker.cpp" line="126"/>
- <location filename="../importworker.cpp" line="170"/>
+ <location filename="../importworker.cpp" line="175"/>
<source>Interrupted.</source>
<comment>import process status update</comment>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../importworker.cpp" line="158"/>
+ <location filename="../importworker.cpp" line="163"/>
<source>Could not import data row number %1. The row was ignored. Problem details: %2</source>
<translation type="unfinished"></translation>
</message>
@@ -484,13 +497,13 @@ Tables, indexes, triggers and views copied to database %3 will remain.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/pluginmanagerimpl.cpp" line="732"/>
+ <location filename="../services/impl/pluginmanagerimpl.cpp" line="731"/>
<source>min: %1</source>
<comment>plugin dependency version</comment>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/pluginmanagerimpl.cpp" line="733"/>
+ <location filename="../services/impl/pluginmanagerimpl.cpp" line="732"/>
<source>max: %1</source>
<comment>plugin dependency version</comment>
<translation type="unfinished"></translation>
@@ -827,7 +840,7 @@ Error details: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../impl/dbattacherimpl.cpp" line="109"/>
+ <location filename="../impl/dbattacherimpl.cpp" line="115"/>
<source>Could not attach database %1: %2</source>
<translation type="unfinished"></translation>
</message>
@@ -839,13 +852,13 @@ Error details: %2</source>
</message>
<message>
<location filename="../parser/sqlite2_parse.cpp" line="1904"/>
- <location filename="../parser/sqlite3_parse.cpp" line="2167"/>
+ <location filename="../parser/sqlite3_parse.cpp" line="2171"/>
<source>Parser stack overflow</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../parser/sqlite2_parse.cpp" line="4465"/>
- <location filename="../parser/sqlite3_parse.cpp" line="5084"/>
+ <location filename="../parser/sqlite3_parse.cpp" line="5089"/>
<source>Syntax error</source>
<translation type="unfinished"></translation>
</message>
@@ -900,11 +913,16 @@ Error details: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../selectresolver.cpp" line="317"/>
+ <location filename="../selectresolver.cpp" line="333"/>
<source>Could not resolve data source for column: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
+ <location filename="../selectresolver.cpp" line="405"/>
+ <source>Could not resolve table for column &apos;%1&apos;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location filename="../services/impl/configimpl.cpp" line="612"/>
<source>Could not initialize configuration file. Any configuration changes and queries history will be lost after application restart. Tried to initialize the file at following localizations: %1.</source>
<translation type="unfinished"></translation>
@@ -952,40 +970,40 @@ Error details: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="107"/>
+ <location filename="../tablemodifier.cpp" line="115"/>
<source>Table %1 is referencing table %2, but the foreign key definition will not be updated for new table definition due to problems while parsing DDL of the table %3.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="379"/>
+ <location filename="../tablemodifier.cpp" line="389"/>
<source>All columns indexed by the index %1 are gone. The index will not be recreated after table modification.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="418"/>
+ <location filename="../tablemodifier.cpp" line="428"/>
<source>There is problem with proper processing trigger %1. It may be not fully updated afterwards and will need your attention.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="433"/>
+ <location filename="../tablemodifier.cpp" line="443"/>
<source>All columns covered by the trigger %1 are gone. The trigger will not be recreated after table modification.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="465"/>
+ <location filename="../tablemodifier.cpp" line="475"/>
<source>Cannot not update trigger %1 according to table %2 modification.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="483"/>
+ <location filename="../tablemodifier.cpp" line="493"/>
<source>Cannot not update view %1 according to table %2 modifications.
The view will remain as it is.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="645"/>
- <location filename="../tablemodifier.cpp" line="669"/>
- <location filename="../tablemodifier.cpp" line="688"/>
+ <location filename="../tablemodifier.cpp" line="655"/>
+ <location filename="../tablemodifier.cpp" line="679"/>
+ <location filename="../tablemodifier.cpp" line="698"/>
<source>There is a problem with updating an %1 statement within %2 trigger. One of the %1 substatements which might be referring to table %3 cannot be properly modified. Manual update of the trigger may be necessary.</source>
<translation type="unfinished"></translation>
</message>
@@ -1008,28 +1026,28 @@ The view will remain as it is.</source>
<context>
<name>QueryExecutor</name>
<message>
- <location filename="../db/queryexecutor.cpp" line="133"/>
+ <location filename="../db/queryexecutor.cpp" line="137"/>
<source>Execution interrupted.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="174"/>
+ <location filename="../db/queryexecutor.cpp" line="178"/>
<source>Database is not open.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="182"/>
+ <location filename="../db/queryexecutor.cpp" line="186"/>
<source>Only one query can be executed simultaneously.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="264"/>
- <location filename="../db/queryexecutor.cpp" line="548"/>
+ <location filename="../db/queryexecutor.cpp" line="275"/>
+ <location filename="../db/queryexecutor.cpp" line="560"/>
<source>An error occured while executing the count(*) query, thus data paging will be disabled. Error details from the database: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="459"/>
+ <location filename="../db/queryexecutor.cpp" line="471"/>
<source>SQLiteStudio was unable to extract metadata from the query. Results won&apos;t be editable.</source>
<translation type="unfinished"></translation>
</message>
diff --git a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_pl.ts b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_pl.ts
index a89ea4d..c3e000c 100644
--- a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_pl.ts
+++ b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_pl.ts
@@ -38,19 +38,25 @@
<translation>Baza danych do wykonywania zapytań nie jest otwarta.</translation>
</message>
<message>
- <location filename="../db/chainexecutor.cpp" line="47"/>
+ <location filename="../db/chainexecutor.cpp" line="50"/>
+ <source>Could not disable foreign keys in the database. Details: %1</source>
+ <comment>chain executor</comment>
+ <translation>Nie udało się wyłączyć kluczy obcych w bazie. Szczegóły: %1</translation>
+ </message>
+ <message>
+ <location filename="../db/chainexecutor.cpp" line="57"/>
<source>Could not start a database transaction. Details: %1</source>
<comment>chain executor</comment>
<translation>Nie udało się rozpocząć transakcji bazy danych. Szczegóły: %1</translation>
</message>
<message>
- <location filename="../db/chainexecutor.cpp" line="74"/>
+ <location filename="../db/chainexecutor.cpp" line="84"/>
<source>Interrupted</source>
<comment>chain executor</comment>
<translation>Przerwane</translation>
</message>
<message>
- <location filename="../db/chainexecutor.cpp" line="134"/>
+ <location filename="../db/chainexecutor.cpp" line="145"/>
<source>Could not commit a database transaction. Details: %1</source>
<comment>chain executor</comment>
<translation>Nie udało się zatwierdzić transakcji bazy danych. Szczegóły: %1</translation>
@@ -152,25 +158,25 @@
<translation>Nie udało się zaktualizować baza danych %1 z powodu błędu: %2</translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="312"/>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="341"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="350"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="379"/>
<source>Database file doesn&apos;t exist.</source>
<translation>Plik bazy danych nie istnieje.</translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="314"/>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="343"/>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="565"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="352"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="381"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="604"/>
<source>No supporting plugin loaded.</source>
<translation>Nie załadowano obsługującej wtyczki.</translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="484"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="522"/>
<source>Database could not be initialized.</source>
<translation>Nie udało się zainicjalizować bazy danych.</translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="494"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="532"/>
<source>No suitable database driver plugin found.</source>
<translation>Nie znaleziono odpowiedniej wtyczki sterownika.</translation>
</message>
@@ -227,21 +233,28 @@ Tabele, indeksy, wyzwalacze i widoki skopiowane do bazy danych %3 pozostaną na
<source>Error while creating trigger in target database: %1</source>
<translation>Błąd podczas tworzenia wyzwalacza w docelowej bazie danych: %1</translation>
</message>
+ <message>
+ <location filename="../dbobjectorganizer.cpp" line="773"/>
+ <location filename="../dbobjectorganizer.cpp" line="780"/>
+ <location filename="../dbobjectorganizer.cpp" line="789"/>
+ <source>Could not parse object &apos;%1&apos; in order to move or copy it.</source>
+ <translation>Nie można zanalizować obiektu &apos;%1&apos; w celu przeniesienia lub skopiowania go.</translation>
+ </message>
</context>
<context>
<name>DbVersionConverter</name>
<message>
- <location filename="../dbversionconverter.cpp" line="923"/>
+ <location filename="../dbversionconverter.cpp" line="913"/>
<source>Target file exists, but could not be overwritten.</source>
<translation>Plik docelowy istnieje, ale nie może być nadpisany.</translation>
</message>
<message>
- <location filename="../dbversionconverter.cpp" line="942"/>
+ <location filename="../dbversionconverter.cpp" line="932"/>
<source>Could not find proper database plugin to create target database.</source>
<translation>Nie znaleziono odpowiedniej wtyczki bazy danych, aby utworzyć docelową bazę danych.</translation>
</message>
<message>
- <location filename="../dbversionconverter.cpp" line="1176"/>
+ <location filename="../dbversionconverter.cpp" line="1166"/>
<source>Error while converting database: %1</source>
<translation>Błąd podczas konwersji bazy danych: %1</translation>
</message>
@@ -323,7 +336,7 @@ Tabele, indeksy, wyzwalacze i widoki skopiowane do bazy danych %3 pozostaną na
<context>
<name>ExportWorker</name>
<message>
- <location filename="../exportworker.cpp" line="121"/>
+ <location filename="../exportworker.cpp" line="122"/>
<source>Error while exporting query results: %1</source>
<translation>Błąd podczas eksportowania wyników zapytania: %1</translation>
</message>
@@ -332,28 +345,28 @@ Tabele, indeksy, wyzwalacze i widoki skopiowane do bazy danych %3 pozostaną na
<translation type="obsolete">Błąd podczas liczenia szerokości kolumn danych do eksportu wyników zapytania: %2</translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="201"/>
+ <location filename="../exportworker.cpp" line="202"/>
<source>Error while counting data column width to export from query results: %1</source>
<translation>Błąd podczas liczenia szerokości kolumn danych do eksportu wyników zapytania: %1</translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="353"/>
- <location filename="../exportworker.cpp" line="411"/>
+ <location filename="../exportworker.cpp" line="354"/>
+ <location filename="../exportworker.cpp" line="412"/>
<source>Could not parse %1 in order to export it. It will be excluded from the export output.</source>
<translation>Nie udało się przeanalizować %1 w celu wyeksportowania. Element ten zostanie pominięty w wynikach eksportu.</translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="612"/>
+ <location filename="../exportworker.cpp" line="616"/>
<source>Error while reading data to export from table %1: %2</source>
<translation>Błąd podczas odczytu danych do eksportu z tabeli %1: %2</translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="620"/>
+ <location filename="../exportworker.cpp" line="624"/>
<source>Error while counting data to export from table %1: %2</source>
<translation>Błąd podczas liczenia danych do eksportu z tabeli %1: %2</translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="636"/>
+ <location filename="../exportworker.cpp" line="640"/>
<source>Error while counting data column width to export from table %1: %2</source>
<translation>Błąd podczas obliczania szerokości kolumn danych do eksportu z tabeli %1: %2</translation>
</message>
@@ -452,20 +465,20 @@ Tabele, indeksy, wyzwalacze i widoki skopiowane do bazy danych %3 pozostaną na
</message>
<message>
<location filename="../importworker.cpp" line="126"/>
- <location filename="../importworker.cpp" line="163"/>
- <location filename="../importworker.cpp" line="170"/>
+ <location filename="../importworker.cpp" line="168"/>
+ <location filename="../importworker.cpp" line="175"/>
<source>Error while importing data: %1</source>
<translation>Błąd podczas importowania danych: %1</translation>
</message>
<message>
<location filename="../importworker.cpp" line="126"/>
- <location filename="../importworker.cpp" line="170"/>
+ <location filename="../importworker.cpp" line="175"/>
<source>Interrupted.</source>
<comment>import process status update</comment>
<translation>Przerwano.</translation>
</message>
<message>
- <location filename="../importworker.cpp" line="158"/>
+ <location filename="../importworker.cpp" line="163"/>
<source>Could not import data row number %1. The row was ignored. Problem details: %2</source>
<translation>Nie udało się zaimportować wiersza danych numer %1. Wiersz ten został zignorowany. Szczegóły problemu: %2</translation>
</message>
@@ -493,13 +506,13 @@ Tabele, indeksy, wyzwalacze i widoki skopiowane do bazy danych %3 pozostaną na
<translation>Nie udało się załadować wtyczki %1 (błąd podczas inicjalizacji wtyczki).</translation>
</message>
<message>
- <location filename="../services/impl/pluginmanagerimpl.cpp" line="732"/>
+ <location filename="../services/impl/pluginmanagerimpl.cpp" line="731"/>
<source>min: %1</source>
<comment>plugin dependency version</comment>
<translation>min: %1</translation>
</message>
<message>
- <location filename="../services/impl/pluginmanagerimpl.cpp" line="733"/>
+ <location filename="../services/impl/pluginmanagerimpl.cpp" line="732"/>
<source>max: %1</source>
<comment>plugin dependency version</comment>
<translation>maks: %1</translation>
@@ -824,7 +837,7 @@ Szczegóły błędu: %2</translation>
<translation>SQLite %1 nie obsługuje klauzuli &apos;%2&apos; w wyrażeniach.</translation>
</message>
<message>
- <location filename="../impl/dbattacherimpl.cpp" line="109"/>
+ <location filename="../impl/dbattacherimpl.cpp" line="115"/>
<source>Could not attach database %1: %2</source>
<translation>Nie udało się dołączyć bazy danych %1: %2</translation>
</message>
@@ -836,13 +849,13 @@ Szczegóły błędu: %2</translation>
</message>
<message>
<location filename="../parser/sqlite2_parse.cpp" line="1904"/>
- <location filename="../parser/sqlite3_parse.cpp" line="2167"/>
+ <location filename="../parser/sqlite3_parse.cpp" line="2171"/>
<source>Parser stack overflow</source>
<translation>Przeciążenie stosu analizatora.</translation>
</message>
<message>
- <location filename="../parser/sqlite2_parse.cpp" line="4461"/>
- <location filename="../parser/sqlite3_parse.cpp" line="5080"/>
+ <location filename="../parser/sqlite2_parse.cpp" line="4465"/>
+ <location filename="../parser/sqlite3_parse.cpp" line="5089"/>
<source>Syntax error</source>
<translation>Błąd składni</translation>
</message>
@@ -897,12 +910,17 @@ Szczegóły błędu: %2</translation>
<translation>Kod implementacji nie może być pusty.</translation>
</message>
<message>
- <location filename="../selectresolver.cpp" line="307"/>
+ <location filename="../selectresolver.cpp" line="333"/>
<source>Could not resolve data source for column: %1</source>
<translation>Nie znaleziono źródła danych dla kolumny: %1</translation>
</message>
<message>
- <location filename="../services/impl/configimpl.cpp" line="617"/>
+ <location filename="../selectresolver.cpp" line="405"/>
+ <source>Could not resolve table for column &apos;%1&apos;.</source>
+ <translation>Nie można ustalić tabeli lub kolumny &apos;%1&apos;.</translation>
+ </message>
+ <message>
+ <location filename="../services/impl/configimpl.cpp" line="612"/>
<source>Could not initialize configuration file. Any configuration changes and queries history will be lost after application restart. Tried to initialize the file at following localizations: %1.</source>
<translation>Nie udało się zainicjalizować pliku konfiguracyjnego. Jakiekolwiek zmiany w konfiguracji i historia zapytań będą utracone po zrestartowaniu aplikacji. Próbowano zainicjalizować plik konfiguracyjny w następujących lokalizacjach: %1.</translation>
</message>
@@ -949,39 +967,39 @@ Szczegóły błędu: %2</translation>
<translation>Zaludnianie tabel</translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="108"/>
+ <location filename="../tablemodifier.cpp" line="115"/>
<source>Table %1 is referencing table %2, but the foreign key definition will not be updated for new table definition due to problems while parsing DDL of the table %3.</source>
<translation>Tabela %1 odwołuje się do tabeli %2, ale definicja klucza obcego nie zostanie zaktualizowane dla definicji nowej tabeli w związku z problemami przy analizowaniu DDL tabeli %3.</translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="380"/>
+ <location filename="../tablemodifier.cpp" line="389"/>
<source>All columns indexed by the index %1 are gone. The index will not be recreated after table modification.</source>
<translation>Wszystkie kolumny indeksowane przez indeks %1 już nie istnieją. Indeks ten nie będzie odtworzony po modyfikacji tabeli.</translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="419"/>
+ <location filename="../tablemodifier.cpp" line="428"/>
<source>There is problem with proper processing trigger %1. It may be not fully updated afterwards and will need your attention.</source>
<translation>Wystąpił problem z poprawnym przetworzeniem wyzwalacza %1. Może on zostać zaktualizowany tylko częściowo i będzie wymagał twojej uwagi.</translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="466"/>
+ <location filename="../tablemodifier.cpp" line="475"/>
<source>Cannot not update trigger %1 according to table %2 modification.</source>
<translation>Nie można zaktualizować wyzwalacza %1 zgodnie z modyfikacjami tabeli %2.</translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="587"/>
- <location filename="../tablemodifier.cpp" line="611"/>
- <location filename="../tablemodifier.cpp" line="630"/>
+ <location filename="../tablemodifier.cpp" line="655"/>
+ <location filename="../tablemodifier.cpp" line="679"/>
+ <location filename="../tablemodifier.cpp" line="698"/>
<source>There is a problem with updating an %1 statement within %2 trigger. One of the %1 substatements which might be referring to table %3 cannot be properly modified. Manual update of the trigger may be necessary.</source>
<translation>Jest problem ze zaktualizowaniem zapytania %1 w wyzwalaczu %2. Jedeno z podzapytań %1, które może odwoływać się do tabeli %3 nie może być poprawnie zmodyfikowane. Ręczna aktualizacja tego wyzwalacza może być niezbędna.</translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="434"/>
+ <location filename="../tablemodifier.cpp" line="443"/>
<source>All columns covered by the trigger %1 are gone. The trigger will not be recreated after table modification.</source>
<translation>Wszystkie kolumny obsługiwane przez wyzwalacz %1 już nie istnieją. Wyzwalacz ten nie będzie odtworzony po modyfikacji tabeli.</translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="484"/>
+ <location filename="../tablemodifier.cpp" line="493"/>
<source>Cannot not update view %1 according to table %2 modifications.
The view will remain as it is.</source>
<translation>Nie można zaktualizować widoku %1 w związku z modyfikacjami tabeli %2.
@@ -1018,7 +1036,7 @@ Widok pozostanie nienaruszony.</translation>
<translation>Nie udało się zamknąć bazy danych: %1</translation>
</message>
<message>
- <location filename="../db/abstractdb2.h" line="803"/>
+ <location filename="../db/abstractdb2.h" line="805"/>
<location filename="../db/abstractdb3.h" line="1100"/>
<source>Result set expired or no row available.</source>
<translation>Wyniki zapytania są nieaktualne, lub nie ma dostępnych wierszy.</translation>
@@ -1034,28 +1052,28 @@ Widok pozostanie nienaruszony.</translation>
<context>
<name>QueryExecutor</name>
<message>
- <location filename="../db/queryexecutor.cpp" line="133"/>
+ <location filename="../db/queryexecutor.cpp" line="137"/>
<source>Execution interrupted.</source>
<translation>Wykonywanie przerwane.</translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="174"/>
+ <location filename="../db/queryexecutor.cpp" line="178"/>
<source>Database is not open.</source>
<translation>Baza danych nie jest otwarta.</translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="182"/>
+ <location filename="../db/queryexecutor.cpp" line="186"/>
<source>Only one query can be executed simultaneously.</source>
<translation>Tylko jedno zapytanie może być wykonywane w danym momencie.</translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="264"/>
- <location filename="../db/queryexecutor.cpp" line="538"/>
+ <location filename="../db/queryexecutor.cpp" line="275"/>
+ <location filename="../db/queryexecutor.cpp" line="560"/>
<source>An error occured while executing the count(*) query, thus data paging will be disabled. Error details from the database: %1</source>
<translation>Wystąpił błąd podczas wykonywania zapytania count(*), przez co stronicowanie danych będzie wyłączone. Szczegóły błędy z bazy danych: %1</translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="449"/>
+ <location filename="../db/queryexecutor.cpp" line="471"/>
<source>SQLiteStudio was unable to extract metadata from the query. Results won&apos;t be editable.</source>
<translation>SQLiteStudio nie mogło uzyskać metadanych z zapytania. Nie będzie można edytować wyników zapytania.</translation>
</message>
diff --git a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_pt_BR.ts b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_pt_BR.ts
index bb040e6..8637f5e 100644
--- a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_pt_BR.ts
+++ b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_pt_BR.ts
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
-<TS version="2.1" language="pt_BR">
+<TS version="2.0" language="pt_BR">
<context>
<name>AbstractDb</name>
<message>
@@ -38,19 +38,25 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/chainexecutor.cpp" line="47"/>
+ <location filename="../db/chainexecutor.cpp" line="50"/>
+ <source>Could not disable foreign keys in the database. Details: %1</source>
+ <comment>chain executor</comment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../db/chainexecutor.cpp" line="57"/>
<source>Could not start a database transaction. Details: %1</source>
<comment>chain executor</comment>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/chainexecutor.cpp" line="74"/>
+ <location filename="../db/chainexecutor.cpp" line="84"/>
<source>Interrupted</source>
<comment>chain executor</comment>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/chainexecutor.cpp" line="134"/>
+ <location filename="../db/chainexecutor.cpp" line="145"/>
<source>Could not commit a database transaction. Details: %1</source>
<comment>chain executor</comment>
<translation type="unfinished"></translation>
@@ -152,25 +158,25 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="312"/>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="341"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="350"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="379"/>
<source>Database file doesn&apos;t exist.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="314"/>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="343"/>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="565"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="352"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="381"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="604"/>
<source>No supporting plugin loaded.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="484"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="522"/>
<source>Database could not be initialized.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="494"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="532"/>
<source>No suitable database driver plugin found.</source>
<translation type="unfinished"></translation>
</message>
@@ -226,21 +232,28 @@ Tables, indexes, triggers and views copied to database %3 will remain.</source>
<source>Error while creating trigger in target database: %1</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../dbobjectorganizer.cpp" line="773"/>
+ <location filename="../dbobjectorganizer.cpp" line="780"/>
+ <location filename="../dbobjectorganizer.cpp" line="789"/>
+ <source>Could not parse object &apos;%1&apos; in order to move or copy it.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>DbVersionConverter</name>
<message>
- <location filename="../dbversionconverter.cpp" line="923"/>
+ <location filename="../dbversionconverter.cpp" line="913"/>
<source>Target file exists, but could not be overwritten.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../dbversionconverter.cpp" line="942"/>
+ <location filename="../dbversionconverter.cpp" line="932"/>
<source>Could not find proper database plugin to create target database.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../dbversionconverter.cpp" line="1176"/>
+ <location filename="../dbversionconverter.cpp" line="1166"/>
<source>Error while converting database: %1</source>
<translation type="unfinished"></translation>
</message>
@@ -318,33 +331,33 @@ Tables, indexes, triggers and views copied to database %3 will remain.</source>
<context>
<name>ExportWorker</name>
<message>
- <location filename="../exportworker.cpp" line="121"/>
+ <location filename="../exportworker.cpp" line="122"/>
<source>Error while exporting query results: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="201"/>
+ <location filename="../exportworker.cpp" line="202"/>
<source>Error while counting data column width to export from query results: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="353"/>
- <location filename="../exportworker.cpp" line="411"/>
+ <location filename="../exportworker.cpp" line="354"/>
+ <location filename="../exportworker.cpp" line="412"/>
<source>Could not parse %1 in order to export it. It will be excluded from the export output.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="612"/>
+ <location filename="../exportworker.cpp" line="616"/>
<source>Error while reading data to export from table %1: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="620"/>
+ <location filename="../exportworker.cpp" line="624"/>
<source>Error while counting data to export from table %1: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="636"/>
+ <location filename="../exportworker.cpp" line="640"/>
<source>Error while counting data column width to export from table %1: %2</source>
<translation type="unfinished"></translation>
</message>
@@ -443,20 +456,20 @@ Tables, indexes, triggers and views copied to database %3 will remain.</source>
</message>
<message>
<location filename="../importworker.cpp" line="126"/>
- <location filename="../importworker.cpp" line="163"/>
- <location filename="../importworker.cpp" line="170"/>
+ <location filename="../importworker.cpp" line="168"/>
+ <location filename="../importworker.cpp" line="175"/>
<source>Error while importing data: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../importworker.cpp" line="126"/>
- <location filename="../importworker.cpp" line="170"/>
+ <location filename="../importworker.cpp" line="175"/>
<source>Interrupted.</source>
<comment>import process status update</comment>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../importworker.cpp" line="158"/>
+ <location filename="../importworker.cpp" line="163"/>
<source>Could not import data row number %1. The row was ignored. Problem details: %2</source>
<translation type="unfinished"></translation>
</message>
@@ -484,13 +497,13 @@ Tables, indexes, triggers and views copied to database %3 will remain.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/pluginmanagerimpl.cpp" line="732"/>
+ <location filename="../services/impl/pluginmanagerimpl.cpp" line="731"/>
<source>min: %1</source>
<comment>plugin dependency version</comment>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/pluginmanagerimpl.cpp" line="733"/>
+ <location filename="../services/impl/pluginmanagerimpl.cpp" line="732"/>
<source>max: %1</source>
<comment>plugin dependency version</comment>
<translation type="unfinished"></translation>
@@ -827,7 +840,7 @@ Error details: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../impl/dbattacherimpl.cpp" line="109"/>
+ <location filename="../impl/dbattacherimpl.cpp" line="115"/>
<source>Could not attach database %1: %2</source>
<translation type="unfinished"></translation>
</message>
@@ -839,13 +852,13 @@ Error details: %2</source>
</message>
<message>
<location filename="../parser/sqlite2_parse.cpp" line="1904"/>
- <location filename="../parser/sqlite3_parse.cpp" line="2167"/>
+ <location filename="../parser/sqlite3_parse.cpp" line="2171"/>
<source>Parser stack overflow</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../parser/sqlite2_parse.cpp" line="4465"/>
- <location filename="../parser/sqlite3_parse.cpp" line="5084"/>
+ <location filename="../parser/sqlite3_parse.cpp" line="5089"/>
<source>Syntax error</source>
<translation type="unfinished"></translation>
</message>
@@ -900,11 +913,16 @@ Error details: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../selectresolver.cpp" line="317"/>
+ <location filename="../selectresolver.cpp" line="333"/>
<source>Could not resolve data source for column: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
+ <location filename="../selectresolver.cpp" line="405"/>
+ <source>Could not resolve table for column &apos;%1&apos;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location filename="../services/impl/configimpl.cpp" line="612"/>
<source>Could not initialize configuration file. Any configuration changes and queries history will be lost after application restart. Tried to initialize the file at following localizations: %1.</source>
<translation type="unfinished"></translation>
@@ -952,39 +970,39 @@ Error details: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="107"/>
+ <location filename="../tablemodifier.cpp" line="115"/>
<source>Table %1 is referencing table %2, but the foreign key definition will not be updated for new table definition due to problems while parsing DDL of the table %3.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="379"/>
+ <location filename="../tablemodifier.cpp" line="389"/>
<source>All columns indexed by the index %1 are gone. The index will not be recreated after table modification.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="418"/>
+ <location filename="../tablemodifier.cpp" line="428"/>
<source>There is problem with proper processing trigger %1. It may be not fully updated afterwards and will need your attention.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="465"/>
+ <location filename="../tablemodifier.cpp" line="475"/>
<source>Cannot not update trigger %1 according to table %2 modification.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="645"/>
- <location filename="../tablemodifier.cpp" line="669"/>
- <location filename="../tablemodifier.cpp" line="688"/>
+ <location filename="../tablemodifier.cpp" line="655"/>
+ <location filename="../tablemodifier.cpp" line="679"/>
+ <location filename="../tablemodifier.cpp" line="698"/>
<source>There is a problem with updating an %1 statement within %2 trigger. One of the %1 substatements which might be referring to table %3 cannot be properly modified. Manual update of the trigger may be necessary.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="433"/>
+ <location filename="../tablemodifier.cpp" line="443"/>
<source>All columns covered by the trigger %1 are gone. The trigger will not be recreated after table modification.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="483"/>
+ <location filename="../tablemodifier.cpp" line="493"/>
<source>Cannot not update view %1 according to table %2 modifications.
The view will remain as it is.</source>
<translation type="unfinished"></translation>
@@ -1008,28 +1026,28 @@ The view will remain as it is.</source>
<context>
<name>QueryExecutor</name>
<message>
- <location filename="../db/queryexecutor.cpp" line="133"/>
+ <location filename="../db/queryexecutor.cpp" line="137"/>
<source>Execution interrupted.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="174"/>
+ <location filename="../db/queryexecutor.cpp" line="178"/>
<source>Database is not open.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="182"/>
+ <location filename="../db/queryexecutor.cpp" line="186"/>
<source>Only one query can be executed simultaneously.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="264"/>
- <location filename="../db/queryexecutor.cpp" line="548"/>
+ <location filename="../db/queryexecutor.cpp" line="275"/>
+ <location filename="../db/queryexecutor.cpp" line="560"/>
<source>An error occured while executing the count(*) query, thus data paging will be disabled. Error details from the database: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="459"/>
+ <location filename="../db/queryexecutor.cpp" line="471"/>
<source>SQLiteStudio was unable to extract metadata from the query. Results won&apos;t be editable.</source>
<translation type="unfinished"></translation>
</message>
diff --git a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_ru.ts b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_ru.ts
index 83ba986..7e8bb9d 100644
--- a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_ru.ts
+++ b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_ru.ts
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
-<TS version="2.1" language="ru_RU">
+<TS version="2.0" language="ru_RU">
<context>
<name>AbstractDb</name>
<message>
@@ -38,19 +38,25 @@
<translation>Не открыта база данных для выполнения запросов.</translation>
</message>
<message>
- <location filename="../db/chainexecutor.cpp" line="47"/>
+ <location filename="../db/chainexecutor.cpp" line="50"/>
+ <source>Could not disable foreign keys in the database. Details: %1</source>
+ <comment>chain executor</comment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../db/chainexecutor.cpp" line="57"/>
<source>Could not start a database transaction. Details: %1</source>
<comment>chain executor</comment>
<translation>Невозможно начать транзакцию. Подробности: %1</translation>
</message>
<message>
- <location filename="../db/chainexecutor.cpp" line="74"/>
+ <location filename="../db/chainexecutor.cpp" line="84"/>
<source>Interrupted</source>
<comment>chain executor</comment>
<translation>Прервано</translation>
</message>
<message>
- <location filename="../db/chainexecutor.cpp" line="134"/>
+ <location filename="../db/chainexecutor.cpp" line="145"/>
<source>Could not commit a database transaction. Details: %1</source>
<comment>chain executor</comment>
<translation>Невозможно завершить транзакцию. Подробности: %1</translation>
@@ -152,26 +158,26 @@
<translation>Невозможно обновить базу данных %1 из-за ошибки: %2</translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="312"/>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="341"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="350"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="379"/>
<source>Database file doesn&apos;t exist.</source>
<translation>Файл базы данных не существует.</translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="314"/>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="343"/>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="565"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="352"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="381"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="604"/>
<source>No supporting plugin loaded.</source>
<translatorcomment>Unclear error string. Checking the source didn&apos;t help.</translatorcomment>
<translation>Модуль поддержки не загружен.</translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="484"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="522"/>
<source>Database could not be initialized.</source>
<translation>Невозможно инициализировать базу данных.</translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="494"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="532"/>
<source>No suitable database driver plugin found.</source>
<translation>Не найден подходящий драйвер базы данных.</translation>
</message>
@@ -228,21 +234,28 @@ Tables, indexes, triggers and views copied to database %3 will remain.</source>
<source>Error while creating trigger in target database: %1</source>
<translation>Ошибка при создании триггера в целевой базе данных: %1</translation>
</message>
+ <message>
+ <location filename="../dbobjectorganizer.cpp" line="773"/>
+ <location filename="../dbobjectorganizer.cpp" line="780"/>
+ <location filename="../dbobjectorganizer.cpp" line="789"/>
+ <source>Could not parse object &apos;%1&apos; in order to move or copy it.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>DbVersionConverter</name>
<message>
- <location filename="../dbversionconverter.cpp" line="923"/>
+ <location filename="../dbversionconverter.cpp" line="913"/>
<source>Target file exists, but could not be overwritten.</source>
<translation>Целевой файл существует, но не может быть перезаписан.</translation>
</message>
<message>
- <location filename="../dbversionconverter.cpp" line="942"/>
+ <location filename="../dbversionconverter.cpp" line="932"/>
<source>Could not find proper database plugin to create target database.</source>
<translation>Невозможно найти подходящий модуль для создания целевой базы данных.</translation>
</message>
<message>
- <location filename="../dbversionconverter.cpp" line="1176"/>
+ <location filename="../dbversionconverter.cpp" line="1166"/>
<source>Error while converting database: %1</source>
<translation>Ошибка при конвертации базы данных: %1</translation>
</message>
@@ -320,33 +333,33 @@ Tables, indexes, triggers and views copied to database %3 will remain.</source>
<context>
<name>ExportWorker</name>
<message>
- <location filename="../exportworker.cpp" line="121"/>
+ <location filename="../exportworker.cpp" line="122"/>
<source>Error while exporting query results: %1</source>
<translation>Ошибка при экспорте результатов запроса: %1</translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="201"/>
+ <location filename="../exportworker.cpp" line="202"/>
<source>Error while counting data column width to export from query results: %1</source>
<translation>Ошибка при подсчёте ширины столбца данных для экспорта результатов запроса: %1</translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="353"/>
- <location filename="../exportworker.cpp" line="411"/>
+ <location filename="../exportworker.cpp" line="354"/>
+ <location filename="../exportworker.cpp" line="412"/>
<source>Could not parse %1 in order to export it. It will be excluded from the export output.</source>
<translation>Невозможно проанализировать структуру %1. Данный объект будет исключён при выполнении экспорта.</translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="612"/>
+ <location filename="../exportworker.cpp" line="616"/>
<source>Error while reading data to export from table %1: %2</source>
<translation>Ошибка при считывании данных для экспорта из таблицы %1: %2</translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="620"/>
+ <location filename="../exportworker.cpp" line="624"/>
<source>Error while counting data to export from table %1: %2</source>
<translation>Ошибка при подсчёте количества данных для экспорта из таблицы %1: %2</translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="636"/>
+ <location filename="../exportworker.cpp" line="640"/>
<source>Error while counting data column width to export from table %1: %2</source>
<translation>Ошибка при подсчёте ширины столбца данных для экспорта из таблицы %1: %2</translation>
</message>
@@ -445,20 +458,20 @@ Tables, indexes, triggers and views copied to database %3 will remain.</source>
</message>
<message>
<location filename="../importworker.cpp" line="126"/>
- <location filename="../importworker.cpp" line="163"/>
- <location filename="../importworker.cpp" line="170"/>
+ <location filename="../importworker.cpp" line="168"/>
+ <location filename="../importworker.cpp" line="175"/>
<source>Error while importing data: %1</source>
<translation>Ошибка при импорте данных: %1</translation>
</message>
<message>
<location filename="../importworker.cpp" line="126"/>
- <location filename="../importworker.cpp" line="170"/>
+ <location filename="../importworker.cpp" line="175"/>
<source>Interrupted.</source>
<comment>import process status update</comment>
<translation>Прервано.</translation>
</message>
<message>
- <location filename="../importworker.cpp" line="158"/>
+ <location filename="../importworker.cpp" line="163"/>
<source>Could not import data row number %1. The row was ignored. Problem details: %2</source>
<translation>Невозможно импортировать строку данных № %1. Строка пропущена. Подробности проблемы: %2</translation>
</message>
@@ -486,13 +499,13 @@ Tables, indexes, triggers and views copied to database %3 will remain.</source>
<translation>Невозможно загрузить модуль %1 (ошибка при инициализации модуля).</translation>
</message>
<message>
- <location filename="../services/impl/pluginmanagerimpl.cpp" line="732"/>
+ <location filename="../services/impl/pluginmanagerimpl.cpp" line="731"/>
<source>min: %1</source>
<comment>plugin dependency version</comment>
<translation>минимальная: %1</translation>
</message>
<message>
- <location filename="../services/impl/pluginmanagerimpl.cpp" line="733"/>
+ <location filename="../services/impl/pluginmanagerimpl.cpp" line="732"/>
<source>max: %1</source>
<comment>plugin dependency version</comment>
<translation>максимальная: %1</translation>
@@ -829,7 +842,7 @@ Error details: %2</source>
<translation>SQLite %1 не поддерживает оператор &apos;%2&apos; в выражениях.</translation>
</message>
<message>
- <location filename="../impl/dbattacherimpl.cpp" line="109"/>
+ <location filename="../impl/dbattacherimpl.cpp" line="115"/>
<source>Could not attach database %1: %2</source>
<translation>Не удалось присоединить базу данных %1: %2</translation>
</message>
@@ -841,13 +854,13 @@ Error details: %2</source>
</message>
<message>
<location filename="../parser/sqlite2_parse.cpp" line="1904"/>
- <location filename="../parser/sqlite3_parse.cpp" line="2167"/>
+ <location filename="../parser/sqlite3_parse.cpp" line="2171"/>
<source>Parser stack overflow</source>
<translation>Переполнение стека анализатора</translation>
</message>
<message>
<location filename="../parser/sqlite2_parse.cpp" line="4465"/>
- <location filename="../parser/sqlite3_parse.cpp" line="5084"/>
+ <location filename="../parser/sqlite3_parse.cpp" line="5089"/>
<source>Syntax error</source>
<translation>Синтаксическая ошибка</translation>
</message>
@@ -902,11 +915,16 @@ Error details: %2</source>
<translation>Заполняющий код не может быть пустым.</translation>
</message>
<message>
- <location filename="../selectresolver.cpp" line="317"/>
+ <location filename="../selectresolver.cpp" line="333"/>
<source>Could not resolve data source for column: %1</source>
<translation>Невозможно определить источник данных для столбца: %1</translation>
</message>
<message>
+ <location filename="../selectresolver.cpp" line="405"/>
+ <source>Could not resolve table for column &apos;%1&apos;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location filename="../services/impl/configimpl.cpp" line="612"/>
<source>Could not initialize configuration file. Any configuration changes and queries history will be lost after application restart. Tried to initialize the file at following localizations: %1.</source>
<translation>Невозможно инициализировать файл конфигурации. Любые изменения конфигурации и история запросов будут утеряны после перезапуска приложения. Попытки инициализации файла предпринимались в следующих местах: %1.</translation>
@@ -954,39 +972,39 @@ Error details: %2</source>
<translation>Заполнение таблиц</translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="107"/>
+ <location filename="../tablemodifier.cpp" line="115"/>
<source>Table %1 is referencing table %2, but the foreign key definition will not be updated for new table definition due to problems while parsing DDL of the table %3.</source>
<translation>Таблица %1 ссылается на таблицу %2, но описание внешнего ключа не будет обновлено для описания новой таблицы из-за проблем с анализом DDL таблицы %3.</translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="379"/>
+ <location filename="../tablemodifier.cpp" line="389"/>
<source>All columns indexed by the index %1 are gone. The index will not be recreated after table modification.</source>
<translation>Все столбцы, проиндексированные индексом %1, удалены. Индекс не будет воссоздан после модификации таблицы.</translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="418"/>
+ <location filename="../tablemodifier.cpp" line="428"/>
<source>There is problem with proper processing trigger %1. It may be not fully updated afterwards and will need your attention.</source>
<translation>Возникла проблема при обработке триггера %1. Впоследствии он не будет полностью обновлён и потребует вашего внимания.</translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="465"/>
+ <location filename="../tablemodifier.cpp" line="475"/>
<source>Cannot not update trigger %1 according to table %2 modification.</source>
<translation>Невозможно обновить триггер %1 в соответствии с модификацией таблицы %2.</translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="645"/>
- <location filename="../tablemodifier.cpp" line="669"/>
- <location filename="../tablemodifier.cpp" line="688"/>
+ <location filename="../tablemodifier.cpp" line="655"/>
+ <location filename="../tablemodifier.cpp" line="679"/>
+ <location filename="../tablemodifier.cpp" line="698"/>
<source>There is a problem with updating an %1 statement within %2 trigger. One of the %1 substatements which might be referring to table %3 cannot be properly modified. Manual update of the trigger may be necessary.</source>
<translation>Возникла проблема при обновлении конструкции %1 внутри триггера %2. Одна из вложенных конструкций %1, которая возможно ссылается на таблицу %3, не может быть корректно модифицирована. Возможно необходима ручная правка триггера.</translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="433"/>
+ <location filename="../tablemodifier.cpp" line="443"/>
<source>All columns covered by the trigger %1 are gone. The trigger will not be recreated after table modification.</source>
<translation>Все столбцы, затронутые в триггере %1, удалены. Триггер не будет воссоздан после модификации таблицы.</translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="483"/>
+ <location filename="../tablemodifier.cpp" line="493"/>
<source>Cannot not update view %1 according to table %2 modifications.
The view will remain as it is.</source>
<translation>Невозможно обновить представление %1 в соответствии с модификациями таблицы %2.
@@ -1015,28 +1033,28 @@ The view will remain as it is.</source>
<context>
<name>QueryExecutor</name>
<message>
- <location filename="../db/queryexecutor.cpp" line="133"/>
+ <location filename="../db/queryexecutor.cpp" line="137"/>
<source>Execution interrupted.</source>
<translation>Выполнение прервано.</translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="174"/>
+ <location filename="../db/queryexecutor.cpp" line="178"/>
<source>Database is not open.</source>
<translation>База данных не открыта.</translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="182"/>
+ <location filename="../db/queryexecutor.cpp" line="186"/>
<source>Only one query can be executed simultaneously.</source>
<translation>Одновременно может быть выполнен только один запрос.</translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="264"/>
- <location filename="../db/queryexecutor.cpp" line="548"/>
+ <location filename="../db/queryexecutor.cpp" line="275"/>
+ <location filename="../db/queryexecutor.cpp" line="560"/>
<source>An error occured while executing the count(*) query, thus data paging will be disabled. Error details from the database: %1</source>
<translation>Возникла ошибка при выполнении запроса count(*), поэтому разбивка данных по страницам отключена. Детали ошибки из базы данных: %1</translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="459"/>
+ <location filename="../db/queryexecutor.cpp" line="471"/>
<source>SQLiteStudio was unable to extract metadata from the query. Results won&apos;t be editable.</source>
<translation>SQLiteStudio не удалось извлечь метаданные из запроса. Результаты нельзя будет редактировать.</translation>
</message>
diff --git a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_sk.qm b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_sk.qm
index 6dae38a..eb79951 100644
--- a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_sk.qm
+++ b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_sk.qm
Binary files differ
diff --git a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_sk.ts b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_sk.ts
index 1c29a80..4a617e4 100644
--- a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_sk.ts
+++ b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_sk.ts
@@ -38,19 +38,25 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/chainexecutor.cpp" line="47"/>
+ <location filename="../db/chainexecutor.cpp" line="50"/>
+ <source>Could not disable foreign keys in the database. Details: %1</source>
+ <comment>chain executor</comment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../db/chainexecutor.cpp" line="57"/>
<source>Could not start a database transaction. Details: %1</source>
<comment>chain executor</comment>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/chainexecutor.cpp" line="74"/>
+ <location filename="../db/chainexecutor.cpp" line="84"/>
<source>Interrupted</source>
<comment>chain executor</comment>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/chainexecutor.cpp" line="134"/>
+ <location filename="../db/chainexecutor.cpp" line="145"/>
<source>Could not commit a database transaction. Details: %1</source>
<comment>chain executor</comment>
<translation type="unfinished"></translation>
@@ -152,25 +158,25 @@
<translation>Databáza %1 nemôže byť aktualizovaná kvôli chybe: %2</translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="312"/>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="341"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="350"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="379"/>
<source>Database file doesn&apos;t exist.</source>
<translation>Databázový súbor neexistuje.</translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="314"/>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="343"/>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="565"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="352"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="381"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="604"/>
<source>No supporting plugin loaded.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="484"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="522"/>
<source>Database could not be initialized.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="494"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="532"/>
<source>No suitable database driver plugin found.</source>
<translation type="unfinished"></translation>
</message>
@@ -226,21 +232,28 @@ Tables, indexes, triggers and views copied to database %3 will remain.</source>
<source>Error while creating trigger in target database: %1</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../dbobjectorganizer.cpp" line="773"/>
+ <location filename="../dbobjectorganizer.cpp" line="780"/>
+ <location filename="../dbobjectorganizer.cpp" line="789"/>
+ <source>Could not parse object &apos;%1&apos; in order to move or copy it.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>DbVersionConverter</name>
<message>
- <location filename="../dbversionconverter.cpp" line="923"/>
+ <location filename="../dbversionconverter.cpp" line="913"/>
<source>Target file exists, but could not be overwritten.</source>
<translation>Cieľový súbor existuje ale nemôže byť prepísaný.</translation>
</message>
<message>
- <location filename="../dbversionconverter.cpp" line="942"/>
+ <location filename="../dbversionconverter.cpp" line="932"/>
<source>Could not find proper database plugin to create target database.</source>
<translation>Nieje možné nájsť správny databázový plugin pre vytvorenie cieľovej databázy.</translation>
</message>
<message>
- <location filename="../dbversionconverter.cpp" line="1176"/>
+ <location filename="../dbversionconverter.cpp" line="1166"/>
<source>Error while converting database: %1</source>
<translation>Vyskytla sa chyba počas konvertovania databázy: %1</translation>
</message>
@@ -318,33 +331,33 @@ Tables, indexes, triggers and views copied to database %3 will remain.</source>
<context>
<name>ExportWorker</name>
<message>
- <location filename="../exportworker.cpp" line="121"/>
+ <location filename="../exportworker.cpp" line="122"/>
<source>Error while exporting query results: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="201"/>
+ <location filename="../exportworker.cpp" line="202"/>
<source>Error while counting data column width to export from query results: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="353"/>
- <location filename="../exportworker.cpp" line="411"/>
+ <location filename="../exportworker.cpp" line="354"/>
+ <location filename="../exportworker.cpp" line="412"/>
<source>Could not parse %1 in order to export it. It will be excluded from the export output.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="612"/>
+ <location filename="../exportworker.cpp" line="616"/>
<source>Error while reading data to export from table %1: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="620"/>
+ <location filename="../exportworker.cpp" line="624"/>
<source>Error while counting data to export from table %1: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="636"/>
+ <location filename="../exportworker.cpp" line="640"/>
<source>Error while counting data column width to export from table %1: %2</source>
<translation type="unfinished"></translation>
</message>
@@ -443,20 +456,20 @@ Tables, indexes, triggers and views copied to database %3 will remain.</source>
</message>
<message>
<location filename="../importworker.cpp" line="126"/>
- <location filename="../importworker.cpp" line="163"/>
- <location filename="../importworker.cpp" line="170"/>
+ <location filename="../importworker.cpp" line="168"/>
+ <location filename="../importworker.cpp" line="175"/>
<source>Error while importing data: %1</source>
<translation>Vyskytla sa chyba počas importu dát: %1</translation>
</message>
<message>
<location filename="../importworker.cpp" line="126"/>
- <location filename="../importworker.cpp" line="170"/>
+ <location filename="../importworker.cpp" line="175"/>
<source>Interrupted.</source>
<comment>import process status update</comment>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../importworker.cpp" line="158"/>
+ <location filename="../importworker.cpp" line="163"/>
<source>Could not import data row number %1. The row was ignored. Problem details: %2</source>
<translation type="unfinished"></translation>
</message>
@@ -484,13 +497,13 @@ Tables, indexes, triggers and views copied to database %3 will remain.</source>
<translation>Nemôžem načítať plugin %1 (nastala chyba pri jeho inicializácii).</translation>
</message>
<message>
- <location filename="../services/impl/pluginmanagerimpl.cpp" line="732"/>
+ <location filename="../services/impl/pluginmanagerimpl.cpp" line="731"/>
<source>min: %1</source>
<comment>plugin dependency version</comment>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/pluginmanagerimpl.cpp" line="733"/>
+ <location filename="../services/impl/pluginmanagerimpl.cpp" line="732"/>
<source>max: %1</source>
<comment>plugin dependency version</comment>
<translation type="unfinished"></translation>
@@ -827,7 +840,7 @@ Error details: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../impl/dbattacherimpl.cpp" line="109"/>
+ <location filename="../impl/dbattacherimpl.cpp" line="115"/>
<source>Could not attach database %1: %2</source>
<translation type="unfinished"></translation>
</message>
@@ -839,13 +852,13 @@ Error details: %2</source>
</message>
<message>
<location filename="../parser/sqlite2_parse.cpp" line="1904"/>
- <location filename="../parser/sqlite3_parse.cpp" line="2167"/>
+ <location filename="../parser/sqlite3_parse.cpp" line="2171"/>
<source>Parser stack overflow</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../parser/sqlite2_parse.cpp" line="4465"/>
- <location filename="../parser/sqlite3_parse.cpp" line="5084"/>
+ <location filename="../parser/sqlite3_parse.cpp" line="5089"/>
<source>Syntax error</source>
<translation>Chyba syntaxe</translation>
</message>
@@ -900,11 +913,16 @@ Error details: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../selectresolver.cpp" line="317"/>
+ <location filename="../selectresolver.cpp" line="333"/>
<source>Could not resolve data source for column: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
+ <location filename="../selectresolver.cpp" line="405"/>
+ <source>Could not resolve table for column &apos;%1&apos;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location filename="../services/impl/configimpl.cpp" line="612"/>
<source>Could not initialize configuration file. Any configuration changes and queries history will be lost after application restart. Tried to initialize the file at following localizations: %1.</source>
<translation type="unfinished"></translation>
@@ -952,39 +970,39 @@ Error details: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="107"/>
+ <location filename="../tablemodifier.cpp" line="115"/>
<source>Table %1 is referencing table %2, but the foreign key definition will not be updated for new table definition due to problems while parsing DDL of the table %3.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="379"/>
+ <location filename="../tablemodifier.cpp" line="389"/>
<source>All columns indexed by the index %1 are gone. The index will not be recreated after table modification.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="418"/>
+ <location filename="../tablemodifier.cpp" line="428"/>
<source>There is problem with proper processing trigger %1. It may be not fully updated afterwards and will need your attention.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="465"/>
+ <location filename="../tablemodifier.cpp" line="475"/>
<source>Cannot not update trigger %1 according to table %2 modification.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="645"/>
- <location filename="../tablemodifier.cpp" line="669"/>
- <location filename="../tablemodifier.cpp" line="688"/>
+ <location filename="../tablemodifier.cpp" line="655"/>
+ <location filename="../tablemodifier.cpp" line="679"/>
+ <location filename="../tablemodifier.cpp" line="698"/>
<source>There is a problem with updating an %1 statement within %2 trigger. One of the %1 substatements which might be referring to table %3 cannot be properly modified. Manual update of the trigger may be necessary.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="433"/>
+ <location filename="../tablemodifier.cpp" line="443"/>
<source>All columns covered by the trigger %1 are gone. The trigger will not be recreated after table modification.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="483"/>
+ <location filename="../tablemodifier.cpp" line="493"/>
<source>Cannot not update view %1 according to table %2 modifications.
The view will remain as it is.</source>
<translation type="unfinished"></translation>
@@ -1008,28 +1026,28 @@ The view will remain as it is.</source>
<context>
<name>QueryExecutor</name>
<message>
- <location filename="../db/queryexecutor.cpp" line="133"/>
+ <location filename="../db/queryexecutor.cpp" line="137"/>
<source>Execution interrupted.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="174"/>
+ <location filename="../db/queryexecutor.cpp" line="178"/>
<source>Database is not open.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="182"/>
+ <location filename="../db/queryexecutor.cpp" line="186"/>
<source>Only one query can be executed simultaneously.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="264"/>
- <location filename="../db/queryexecutor.cpp" line="548"/>
+ <location filename="../db/queryexecutor.cpp" line="275"/>
+ <location filename="../db/queryexecutor.cpp" line="560"/>
<source>An error occured while executing the count(*) query, thus data paging will be disabled. Error details from the database: %1</source>
<translation>Vyskytla sa chyba počas vykonávania dotazu count(*), dôsledkom čoho bolo zablokované stránkovanie. Detail chyby: %1</translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="459"/>
+ <location filename="../db/queryexecutor.cpp" line="471"/>
<source>SQLiteStudio was unable to extract metadata from the query. Results won&apos;t be editable.</source>
<translation type="unfinished"></translation>
</message>
diff --git a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_zh_CN.qm b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_zh_CN.qm
index be651ee..3c6eeb3 100644
--- a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_zh_CN.qm
+++ b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_zh_CN.qm
Binary files differ
diff --git a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_zh_CN.ts b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_zh_CN.ts
index 448558d..3410fa0 100644
--- a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_zh_CN.ts
+++ b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_zh_CN.ts
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
-<TS version="2.1" language="zh_CN">
+<TS version="2.0" language="zh_CN">
<context>
<name>AbstractDb</name>
<message>
@@ -38,19 +38,25 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/chainexecutor.cpp" line="47"/>
+ <location filename="../db/chainexecutor.cpp" line="50"/>
+ <source>Could not disable foreign keys in the database. Details: %1</source>
+ <comment>chain executor</comment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../db/chainexecutor.cpp" line="57"/>
<source>Could not start a database transaction. Details: %1</source>
<comment>chain executor</comment>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/chainexecutor.cpp" line="74"/>
+ <location filename="../db/chainexecutor.cpp" line="84"/>
<source>Interrupted</source>
<comment>chain executor</comment>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/chainexecutor.cpp" line="134"/>
+ <location filename="../db/chainexecutor.cpp" line="145"/>
<source>Could not commit a database transaction. Details: %1</source>
<comment>chain executor</comment>
<translation type="unfinished"></translation>
@@ -152,25 +158,25 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="312"/>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="341"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="350"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="379"/>
<source>Database file doesn&apos;t exist.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="314"/>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="343"/>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="565"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="352"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="381"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="604"/>
<source>No supporting plugin loaded.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="484"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="522"/>
<source>Database could not be initialized.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/dbmanagerimpl.cpp" line="494"/>
+ <location filename="../services/impl/dbmanagerimpl.cpp" line="532"/>
<source>No suitable database driver plugin found.</source>
<translation type="unfinished"></translation>
</message>
@@ -226,21 +232,28 @@ Tables, indexes, triggers and views copied to database %3 will remain.</source>
<source>Error while creating trigger in target database: %1</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../dbobjectorganizer.cpp" line="773"/>
+ <location filename="../dbobjectorganizer.cpp" line="780"/>
+ <location filename="../dbobjectorganizer.cpp" line="789"/>
+ <source>Could not parse object &apos;%1&apos; in order to move or copy it.</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>DbVersionConverter</name>
<message>
- <location filename="../dbversionconverter.cpp" line="923"/>
+ <location filename="../dbversionconverter.cpp" line="913"/>
<source>Target file exists, but could not be overwritten.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../dbversionconverter.cpp" line="942"/>
+ <location filename="../dbversionconverter.cpp" line="932"/>
<source>Could not find proper database plugin to create target database.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../dbversionconverter.cpp" line="1176"/>
+ <location filename="../dbversionconverter.cpp" line="1166"/>
<source>Error while converting database: %1</source>
<translation type="unfinished"></translation>
</message>
@@ -318,33 +331,33 @@ Tables, indexes, triggers and views copied to database %3 will remain.</source>
<context>
<name>ExportWorker</name>
<message>
- <location filename="../exportworker.cpp" line="121"/>
+ <location filename="../exportworker.cpp" line="122"/>
<source>Error while exporting query results: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="201"/>
+ <location filename="../exportworker.cpp" line="202"/>
<source>Error while counting data column width to export from query results: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="353"/>
- <location filename="../exportworker.cpp" line="411"/>
+ <location filename="../exportworker.cpp" line="354"/>
+ <location filename="../exportworker.cpp" line="412"/>
<source>Could not parse %1 in order to export it. It will be excluded from the export output.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="612"/>
+ <location filename="../exportworker.cpp" line="616"/>
<source>Error while reading data to export from table %1: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="620"/>
+ <location filename="../exportworker.cpp" line="624"/>
<source>Error while counting data to export from table %1: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../exportworker.cpp" line="636"/>
+ <location filename="../exportworker.cpp" line="640"/>
<source>Error while counting data column width to export from table %1: %2</source>
<translation type="unfinished"></translation>
</message>
@@ -443,20 +456,20 @@ Tables, indexes, triggers and views copied to database %3 will remain.</source>
</message>
<message>
<location filename="../importworker.cpp" line="126"/>
- <location filename="../importworker.cpp" line="163"/>
- <location filename="../importworker.cpp" line="170"/>
+ <location filename="../importworker.cpp" line="168"/>
+ <location filename="../importworker.cpp" line="175"/>
<source>Error while importing data: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../importworker.cpp" line="126"/>
- <location filename="../importworker.cpp" line="170"/>
+ <location filename="../importworker.cpp" line="175"/>
<source>Interrupted.</source>
<comment>import process status update</comment>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../importworker.cpp" line="158"/>
+ <location filename="../importworker.cpp" line="163"/>
<source>Could not import data row number %1. The row was ignored. Problem details: %2</source>
<translation type="unfinished"></translation>
</message>
@@ -484,13 +497,13 @@ Tables, indexes, triggers and views copied to database %3 will remain.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/pluginmanagerimpl.cpp" line="732"/>
+ <location filename="../services/impl/pluginmanagerimpl.cpp" line="731"/>
<source>min: %1</source>
<comment>plugin dependency version</comment>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../services/impl/pluginmanagerimpl.cpp" line="733"/>
+ <location filename="../services/impl/pluginmanagerimpl.cpp" line="732"/>
<source>max: %1</source>
<comment>plugin dependency version</comment>
<translation type="unfinished"></translation>
@@ -827,7 +840,7 @@ Error details: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../impl/dbattacherimpl.cpp" line="109"/>
+ <location filename="../impl/dbattacherimpl.cpp" line="115"/>
<source>Could not attach database %1: %2</source>
<translation type="unfinished"></translation>
</message>
@@ -839,13 +852,13 @@ Error details: %2</source>
</message>
<message>
<location filename="../parser/sqlite2_parse.cpp" line="1904"/>
- <location filename="../parser/sqlite3_parse.cpp" line="2167"/>
+ <location filename="../parser/sqlite3_parse.cpp" line="2171"/>
<source>Parser stack overflow</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../parser/sqlite2_parse.cpp" line="4465"/>
- <location filename="../parser/sqlite3_parse.cpp" line="5084"/>
+ <location filename="../parser/sqlite3_parse.cpp" line="5089"/>
<source>Syntax error</source>
<translation type="unfinished"></translation>
</message>
@@ -900,11 +913,16 @@ Error details: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../selectresolver.cpp" line="317"/>
+ <location filename="../selectresolver.cpp" line="333"/>
<source>Could not resolve data source for column: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
+ <location filename="../selectresolver.cpp" line="405"/>
+ <source>Could not resolve table for column &apos;%1&apos;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location filename="../services/impl/configimpl.cpp" line="612"/>
<source>Could not initialize configuration file. Any configuration changes and queries history will be lost after application restart. Tried to initialize the file at following localizations: %1.</source>
<translation type="unfinished"></translation>
@@ -952,39 +970,39 @@ Error details: %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="107"/>
+ <location filename="../tablemodifier.cpp" line="115"/>
<source>Table %1 is referencing table %2, but the foreign key definition will not be updated for new table definition due to problems while parsing DDL of the table %3.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="379"/>
+ <location filename="../tablemodifier.cpp" line="389"/>
<source>All columns indexed by the index %1 are gone. The index will not be recreated after table modification.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="418"/>
+ <location filename="../tablemodifier.cpp" line="428"/>
<source>There is problem with proper processing trigger %1. It may be not fully updated afterwards and will need your attention.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="465"/>
+ <location filename="../tablemodifier.cpp" line="475"/>
<source>Cannot not update trigger %1 according to table %2 modification.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="645"/>
- <location filename="../tablemodifier.cpp" line="669"/>
- <location filename="../tablemodifier.cpp" line="688"/>
+ <location filename="../tablemodifier.cpp" line="655"/>
+ <location filename="../tablemodifier.cpp" line="679"/>
+ <location filename="../tablemodifier.cpp" line="698"/>
<source>There is a problem with updating an %1 statement within %2 trigger. One of the %1 substatements which might be referring to table %3 cannot be properly modified. Manual update of the trigger may be necessary.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="433"/>
+ <location filename="../tablemodifier.cpp" line="443"/>
<source>All columns covered by the trigger %1 are gone. The trigger will not be recreated after table modification.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../tablemodifier.cpp" line="483"/>
+ <location filename="../tablemodifier.cpp" line="493"/>
<source>Cannot not update view %1 according to table %2 modifications.
The view will remain as it is.</source>
<translation type="unfinished"></translation>
@@ -1008,28 +1026,28 @@ The view will remain as it is.</source>
<context>
<name>QueryExecutor</name>
<message>
- <location filename="../db/queryexecutor.cpp" line="133"/>
+ <location filename="../db/queryexecutor.cpp" line="137"/>
<source>Execution interrupted.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="174"/>
+ <location filename="../db/queryexecutor.cpp" line="178"/>
<source>Database is not open.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="182"/>
+ <location filename="../db/queryexecutor.cpp" line="186"/>
<source>Only one query can be executed simultaneously.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="264"/>
- <location filename="../db/queryexecutor.cpp" line="548"/>
+ <location filename="../db/queryexecutor.cpp" line="275"/>
+ <location filename="../db/queryexecutor.cpp" line="560"/>
<source>An error occured while executing the count(*) query, thus data paging will be disabled. Error details from the database: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../db/queryexecutor.cpp" line="459"/>
+ <location filename="../db/queryexecutor.cpp" line="471"/>
<source>SQLiteStudio was unable to extract metadata from the query. Results won&apos;t be editable.</source>
<translation type="unfinished"></translation>
</message>