diff options
| author | 2016-06-13 18:42:42 -0400 | |
|---|---|---|
| committer | 2016-06-13 18:42:42 -0400 | |
| commit | 5d9314f134ddd3dc4c853e398ac90ba247fb2e4f (patch) | |
| tree | 5c457fc188036988d7abd29a3eb09931e406510f /SQLiteStudio3/coreSQLiteStudio | |
| parent | 8e640722c62692818ab840d50b3758f89a41a54e (diff) | |
Imported Upstream version 3.1.0upstream/3.1.0
Diffstat (limited to 'SQLiteStudio3/coreSQLiteStudio')
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 Binary files differindex 9dad8df..2c10fb5 100644 --- a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_de.qm +++ b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_de.qm 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 'committet' 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'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 '%1' in order to move or copy it.</source> + <translation>Objekt '%1' 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 '%2' 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 'attached' 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 '%1'.</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 "to initialize" hier richtig mit "erstellt" ü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 'foreign key'-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 'data paging' 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'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'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 '%1' 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 '%1'.</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'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'exécuter la requête sur une base de données fermée.</translation> + <translation>Impossible d’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'était pas définie.</translation> + <translation>La base de données pour exécuter des requêtes n’é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'est pas ouverte.</translation> + <translation>La base de données pour exécuter des requêtes n’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'initialiser une transaction de la base de données:%1</translation> + <translation>Impossible d’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'enregistrer la transaction de la base de données:%1</translation> + <translation>Impossible d’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'index</translation> + <translation>Nouveau nom d’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'erreur</translation> + <translation>Message d’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'importe quel mot</translation> + <translation>N’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'ajouter une base de données %1: %2</translation> + <translation>Impossible d’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'erreur: %2</translation> + <translation>La base de données %1 ne peut ëtre mise à jour à cause de l’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't exist.</source> - <translation>Le fichier de la base de données n'existe pas.</translation> + <translation>Le fichier de la base de données n’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'analyser la table.</translation> + <translation>Impossible d’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'index de la base de données:%1</translation> + <translation>Erreur lors de la création de l’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'exécution</translation> + <translation>Date d’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't support exporing query results.</source> - <translation>Plugin d'export %1 ne supporte pas l'exportation de la requête.</translation> + <translation>Plugin d’export %1 ne supporte pas l’exportation de la requête.</translation> </message> <message> <location filename="../services/exportmanager.cpp" line="98"/> <source>Export plugin %1 doesn't support exporing tables.</source> - <translation>Plugin d'export %1 ne supporte pas l'exportation de la table.</translation> + <translation>Plugin d’export %1 ne supporte pas l’exportation de la table.</translation> </message> <message> <location filename="../services/exportmanager.cpp" line="122"/> <source>Export plugin %1 doesn't support exporing databases.</source> - <translation>Plugin d'export %1 ne supporte pas l'exportation de la base de données.</translation> + <translation>Plugin d’export %1 ne supporte pas l’exportation de la base de données.</translation> </message> <message> <location filename="../services/exportmanager.cpp" line="155"/> <source>Export format '%1' is not supported. Supported formats are: %2.</source> - <translation>Format d'export %1 n'est pas supporté. Les formats supportés sont: %2.</translation> + <translation>Format d’export « %1 » n’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 '%1' was successful.</source> - <translation>Export vers le fichier '%1' avec succès.</translation> + <translation>Export vers le fichier ’%1’ 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'exporter vers le fichier '%1'. Le fichier ne peut être ouvert en écriture.</translation> + <translation>Impossible d’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'exportation des résultats de la requête:%1</translation> + <translation>Erreur lors de l’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'analyser %1 afin de l'exporter. Celle-ci sera excluse de l'exportation.</translation> + <translation>Impossible d’analyser %1 afin de l’exporter. Celle-ci sera excluse de l’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 '%1'. 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'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’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'ouvrir en lecture le ficher %1:%2</translation> + <translation>Impossible d’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'ouvrir en écriture le ficher %1:%2</translation> + <translation>Impossible d’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'écriture du fichier %1:%2</translation> + <translation>Erreur lors de l’é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'initialiser le paramètre texte por l'export. Utulisation du paramètre par défaut: %1</translation> + <translation>Impossible d’initialiser le paramètre texte por l’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 '%1' successfully.</source> - <translation>Importation des données de la table '%1' réussie.</translation> + <translation>Importation des données de la table « %1 » 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'importation.</translation> + <translation>Aucune colonne fournie par le plugin d’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'initialiser la transaction d'import de données: %1</translation> + <translation>Impossible d’initialiser la transaction d’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'enregistrer la transaction d'import de données: %1</translation> + <translation>Impossible d’enregistrer la transaction d’import de données: %1</translation> </message> <message> <location filename="../importworker.cpp" line="94"/> <source>Table '%1' 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 « %1 » 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 '%1' 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 « %1 » 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'import: %1</translation> + <translation>Impossible de créer la table d’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'import des données: %1</translation> + <translation>Erreur lors de l’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'ont pa été chargées: %2.</translation> + <translation>Chargement impossible du plugin %1, les dépendances n’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'erreur: %2</translation> + <translation>Chargement impossible du plugin %1, Détails de l’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'utilisation des mots</translation> + <translation>Méthode d’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 '%1' populated successfully.</source> - <translation>Table '%1' remplie avec succès.</translation> + <translation>Table « %1 » 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'initialisation (optionel)</translation> + <translation>Code d’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'initialiser la transaction pour remplir la table.Détails de l'erreur %1</translation> + <translation>Impossible d’initialiser la transaction pour remplir la table.Détails de l’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'enregistrer la transaction après le remplissage de la table. Erreur %1</translation> + <translation>Impossible d’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'ouvrir la base de données: %1</translation> + <translation>Impossible d’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 '%2' statement.</source> - <translation>SQLite %1 ne supporte pas l'instruction '%2'.</translation> + <translation>SQLite %1 ne supporte pas l’instruction « %2 ».</translation> </message> <message> <location filename="../dbversionconverter.cpp" line="201"/> <source>SQLite %1 does not support '%2' statement, but the regular table can be created instead if you proceed.</source> - <translation>SQLite %1 ne supporte pas l'instruction '%2', mais la table normale peut être créée à la place si vous confirmez.</translation> + <translation>SQLite %1 ne supporte pas l’instruction « %2 », 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'analyser l'instruction: %1 + <translation>Impossible d’analyser l’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 '%2' clause. Cannot convert '%3' statement with that clause.</source> - <translation>SQLite %1 ne supporte pas la clause '%2'. Impossible de convertir l'instruction '%3' avec cette clause.</translation> + <translation>SQLite %1 ne supporte pas la clause « %2 ». Impossible de convertir l’instruction « %3 » avec cette clause.</translation> </message> <message> <location filename="../dbversionconverter.cpp" line="488"/> <source>SQLite %1 does not support the '%2' clause in the '%3' statement.</source> - <translation>SQLite %1 ne supporte pas la clause '%2' de l'instruction '%3'.</translation> + <translation>SQLite %1 ne supporte pas la clause « %2 » de l’instruction « %3 ».</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'heure actuelle dans l'expression.</translation> + <translation>SQLite %1 ne supporte pas la clause date ou l’heure actuelle dans l’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 '%2' clause in expressions.</source> - <translation>SQLite %1 ne supporte pas la clause '%2' dans l'expression.</translation> + <translation>SQLite %1 ne supporte pas la clause « %2 » dans l’expression.</translation> </message> <message> <location filename="../impl/dbattacherimpl.cpp" line="109"/> <source>Could not attach database %1: %2</source> - <translation>Impossible d'attacher la base de données %1: %2</translation> + <translation>Impossible d’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'ouvrir en lecture le fichier dictionnaire %1.</translation> + <translation>Impossible d’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'initialisation du code de remplissage: %1</translation> + <translation>Erreur à l’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'exécution du code de remplissage: %1</translation> + <translation>Erreur à l’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'application langage.</translation> + <translation>Sélectionnez l’application langage.</translation> </message> <message> <location filename="../plugins/populatescript.cpp" line="113"/> <source>Implementation code cannot be empty.</source> - <translation>L'application de code ne peut être vide.</translation> + <translation>L’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'initialiser le fichier de configuration. Aucune modification et les requêtes seront perdues après redémarrage. Essayez d'initialiser le fichier avec cette localisation: %1.</translation> + <translation>Impossible d’initialiser le fichier de configuration. + Aucune modification et les requêtes seront perdues après redémarrage. + Essayez d’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'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’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'indexe %1 sont faites. L'indexe ne sera pas recréé après la modification de la table.</translation> + <translation>Toutes les colonnes indéxées par l’indexe %1 sont faites. L’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'instruction %1 avec le déclencheur %2. Une partie de l'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’instruction %1 avec le déclencheur %2. Une partie de l’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'analyser le DDL de création de vue. Détails: %1</translation> + <translation>Impossible d’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's: %1</source> - <translation>L'expression CREATE VIEW est fausse. C'est: %1</translation> + <translation>L’expression CREATE VIEW est fausse. C’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'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'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’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'est ouverte.</translation> + <translation>La base de données n’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'est produite à l'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’est produite à l’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't be editable.</source> - <translation>SQLiteStudio ne peut extraire des métadonnées d'une requête. Les résultats ne peut être affichés.</translation> + <translation>SQLiteStudio ne peut extraire des métadonnées d’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'exécution</translation> + <translation>Date d’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'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’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 <a href="%1">User Manual</a> 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 <a href="%1">User Manual</a> 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 <a href="%1">User Manual</a> 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'y a aucune mise à jour à télécharger. Mise à jour abandonnée.</translation> + <translation>Il n’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 '%1' for writting: %2. Updating aborted.</source> - <translation>Erreur à l'ouverture du fichier %1 pour l'écriture: %2. Mise à jour abandonnée.</translation> + <translation>Erreur à l’ouverture du fichier « %1 » pour l’é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'application courante dans %1.</translation> + <translation>Impossible de copier le répertoire de l’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'où l'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’où l’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'extraire le composant %1 dans le répertoire %2.</translation> + <translation>Impossible d’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'élever les autorisations pour lancer la mise à jour en tantque root. Bloqué: %1</translation> + <translation>Impossible d’é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'administrateur.</translation> + <translation>Impossible de finaliser la mis à jour en tant qu’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'administrateur. Délai d'attente de lancement dépassé.</translation> + <translation>Impossible de finaliser la mis à jour en tant qu’administrateur. Délai d’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'administrateur. Délai d'attente d'opération dépassé.</translation> + <translation>Impossible de finaliser la mis à jour en tant qu’administrateur. Délai d’attente d’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'est pas au format tar.zg: %1</translation> + <translation>Installation impossible un paquet n’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'exécution de la commande de mise à jour: %1 -Message d'erreur: %2</translation> + <translation>Erreur d’exécution de la commande de mise à jour: %1 +Message d’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 Binary files differnew file mode 100644 index 0000000..9dad8df --- /dev/null +++ b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_it.qm 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'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 '%1' 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 '%1'.</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'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'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 '%1' in order to move or copy it.</source> + <translation>Nie można zanalizować obiektu '%1' 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 '%2' 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 '%1'.</source> + <translation>Nie można ustalić tabeli lub kolumny '%1'.</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'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'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 '%1' 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 '%1'.</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'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'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'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 '%1' 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 не поддерживает оператор '%2' в выражениях.</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 '%1'.</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't be editable.</source> <translation>SQLiteStudio не удалось извлечь метаданные из запроса. Результаты нельзя будет редактировать.</translation> </message> diff --git a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_sk.qm b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_sk.qm Binary files differindex 6dae38a..eb79951 100644 --- a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_sk.qm +++ b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_sk.qm 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'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 '%1' 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 '%1'.</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'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 Binary files differindex be651ee..3c6eeb3 100644 --- a/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_zh_CN.qm +++ b/SQLiteStudio3/coreSQLiteStudio/translations/coreSQLiteStudio_zh_CN.qm 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'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 '%1' 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 '%1'.</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't be editable.</source> <translation type="unfinished"></translation> </message> |
