aboutsummaryrefslogtreecommitdiffstats
path: root/SQLiteStudio3/coreSQLiteStudio/common
diff options
context:
space:
mode:
Diffstat (limited to 'SQLiteStudio3/coreSQLiteStudio/common')
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/common/table.cpp30
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/common/table.h18
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/common/utils.cpp21
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/common/utils.h13
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/common/utils_sql.cpp147
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/common/utils_sql.h6
6 files changed, 223 insertions, 12 deletions
diff --git a/SQLiteStudio3/coreSQLiteStudio/common/table.cpp b/SQLiteStudio3/coreSQLiteStudio/common/table.cpp
index a9b0f16..20a9864 100644
--- a/SQLiteStudio3/coreSQLiteStudio/common/table.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/common/table.cpp
@@ -90,3 +90,33 @@ int qHash(AliasedTable table)
{
return qHash(table.getDatabase() + "." + table.getTable() + " " + table.getTableAlias());
}
+
+DbAndTable::DbAndTable() :
+ Table()
+{
+}
+
+DbAndTable::DbAndTable(Db *db, const QString &database, const QString &table) :
+ Table(database, table), db(db)
+{
+}
+
+DbAndTable::DbAndTable(const DbAndTable &other) :
+ Table(other), db(other.db)
+{
+}
+
+int DbAndTable::operator ==(const DbAndTable &other) const
+{
+ return other.database == this->database && other.table == this->table && other.db == this->db;
+}
+
+Db *DbAndTable::getDb() const
+{
+ return db;
+}
+
+void DbAndTable::setDb(Db *value)
+{
+ db = value;
+}
diff --git a/SQLiteStudio3/coreSQLiteStudio/common/table.h b/SQLiteStudio3/coreSQLiteStudio/common/table.h
index 5cc4570..5460148 100644
--- a/SQLiteStudio3/coreSQLiteStudio/common/table.h
+++ b/SQLiteStudio3/coreSQLiteStudio/common/table.h
@@ -4,6 +4,8 @@
#include "coreSQLiteStudio_global.h"
#include <QString>
+class Db;
+
class API_EXPORT Table
{
public:
@@ -25,6 +27,22 @@ class API_EXPORT Table
QString table;
};
+class API_EXPORT DbAndTable : public Table
+{
+public:
+ DbAndTable();
+ DbAndTable(Db* db, const QString& database, const QString& table);
+ DbAndTable(const DbAndTable& other);
+
+ int operator ==(const DbAndTable& other) const;
+
+ Db *getDb() const;
+ void setDb(Db *value);
+
+protected:
+ Db* db = nullptr;
+};
+
class API_EXPORT AliasedTable : public Table
{
public:
diff --git a/SQLiteStudio3/coreSQLiteStudio/common/utils.cpp b/SQLiteStudio3/coreSQLiteStudio/common/utils.cpp
index 6cf1892..e3d2e47 100644
--- a/SQLiteStudio3/coreSQLiteStudio/common/utils.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/common/utils.cpp
@@ -694,6 +694,9 @@ QString getOsString()
case QSysInfo::WV_WINDOWS8_1:
os += " 8.1";
break;
+ case QSysInfo::WV_WINDOWS10:
+ os += " 10";
+ break;
case QSysInfo::WV_32s:
case QSysInfo::WV_95:
case QSysInfo::WV_98:
@@ -707,6 +710,7 @@ QString getOsString()
case QSysInfo::WV_CE_5:
case QSysInfo::WV_CE_6:
case QSysInfo::WV_CE_based:
+ case QSysInfo::WV_None:
break;
}
#elif defined(Q_OS_LINUX)
@@ -742,6 +746,12 @@ QString getOsString()
case QSysInfo::MV_10_9:
os += " 10.9 Mavericks";
break;
+ case QSysInfo::MV_10_10:
+ os += " 10.10 Yosemite";
+ break;
+ case QSysInfo::MV_10_11:
+ os += " 10.11 El Capitan";
+ break;
case QSysInfo::MV_9:
case QSysInfo::MV_10_0:
case QSysInfo::MV_10_1:
@@ -755,6 +765,13 @@ QString getOsString()
case QSysInfo::MV_IOS_6_1:
case QSysInfo::MV_IOS_7_0:
case QSysInfo::MV_IOS_7_1:
+ case QSysInfo::MV_IOS_8_0:
+ case QSysInfo::MV_IOS_8_1:
+ case QSysInfo::MV_IOS_8_2:
+ case QSysInfo::MV_IOS_8_3:
+ case QSysInfo::MV_IOS_8_4:
+ case QSysInfo::MV_IOS_9_0:
+ case QSysInfo::MV_None:
case QSysInfo::MV_Unknown:
break;
}
@@ -899,9 +916,9 @@ QStringList concat(const QList<QStringList>& list)
return result;
}
-QString doubleToString(double val)
+QString doubleToString(const QVariant& val)
{
- return QString::number(val, 'g', 16);
+ return val.toString();
}
void sortWithReferenceList(QList<QString>& listToSort, const QList<QString>& referenceList, Qt::CaseSensitivity cs)
diff --git a/SQLiteStudio3/coreSQLiteStudio/common/utils.h b/SQLiteStudio3/coreSQLiteStudio/common/utils.h
index 934e70a..c56a4db 100644
--- a/SQLiteStudio3/coreSQLiteStudio/common/utils.h
+++ b/SQLiteStudio3/coreSQLiteStudio/common/utils.h
@@ -87,6 +87,17 @@ int indexOf(const QList<T>& list, std::function<bool(const T&)> predicate)
return -1;
}
+template <class T>
+T* findFirst(const QList<T*>& list, std::function<bool(T*)> predicate)
+{
+ for (T* item : list)
+ {
+ if (predicate(item))
+ return item;
+ }
+ return nullptr;
+}
+
/**
* @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.
@@ -231,7 +242,7 @@ 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);
+API_EXPORT QString doubleToString(const QVariant& val);
/**
* @brief Sorts string list using reference list for ordering.
diff --git a/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.cpp b/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.cpp
index 5c7e7e9..ad37ff0 100644
--- a/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.cpp
@@ -4,6 +4,7 @@
#include "parser/token.h"
#include "parser/lexer.h"
#include "parser/keywords.h"
+#include "log.h"
#include <QHash>
#include <QPair>
#include <QString>
@@ -368,11 +369,23 @@ QString removeComments(const QString& value)
return tokens.detokenize();
}
+void splitQueriesUpdateCaseWhenDepth(Token::Type type, const QString& value, int& caseWhenDepth)
+{
+ if (type != Token::KEYWORD)
+ return;
+
+ if (value == "CASE")
+ caseWhenDepth++;
+ else if (value == "END" && caseWhenDepth > 0)
+ caseWhenDepth--;
+}
+
QList<TokenList> splitQueries(const TokenList& tokenizedQuery, bool* complete)
{
QList<TokenList> queries;
TokenList currentQueryTokens;
QString value;
+ int caseWhenDepth = 0;
int createTriggerMeter = 0;
bool insideTrigger = false;
bool completeQuery = false;
@@ -384,16 +397,19 @@ QList<TokenList> splitQueries(const TokenList& tokenizedQuery, bool* complete)
if (insideTrigger)
{
- if (token->type == Token::KEYWORD && value == "END")
+ if (token->type == Token::KEYWORD && value == "END" && caseWhenDepth <= 0 && caseWhenDepth == 0)
{
insideTrigger = false;
completeQuery = true;
}
currentQueryTokens << token;
+ splitQueriesUpdateCaseWhenDepth(token->type, value, caseWhenDepth);
continue;
}
+ splitQueriesUpdateCaseWhenDepth(token->type, value, caseWhenDepth);
+
if (token->type == Token::KEYWORD)
{
if (value == "CREATE" || value == "TRIGGER" || value == "BEGIN")
@@ -407,6 +423,7 @@ QList<TokenList> splitQueries(const TokenList& tokenizedQuery, bool* complete)
else if (token->type == Token::OPERATOR && value == ";")
{
createTriggerMeter = 0;
+ caseWhenDepth = 0;
currentQueryTokens << token;
queries << currentQueryTokens;
currentQueryTokens.clear();
@@ -427,9 +444,114 @@ QList<TokenList> splitQueries(const TokenList& tokenizedQuery, bool* complete)
return queries;
}
-QStringList splitQueries(const QString& sql, Dialect dialect, bool keepEmptyQueries, bool* complete)
+QStringList quickSplitQueries(const QString& sql, bool keepEmptyQueries, bool removeComments)
+{
+ QChar c;
+ bool inString = false;
+ bool inMultiLineComment = false;
+ bool inSingleLineComment = false;
+ QStringList queries;
+ QString query;
+ QString trimmed;
+ for (int i = 0, total = sql.size(); i < total; ++i)
+ {
+ c = sql[i];
+
+ // String
+ if (inString)
+ {
+ query += c;
+ if (c == '\'')
+ {
+ inString = false;
+ }
+ continue;
+ }
+
+ // One-line comment
+ if (inSingleLineComment)
+ {
+ if (!removeComments)
+ query += c;
+
+ if (c == '\r' && (i + 1) < total && sql[i+1] == '\n')
+ {
+ if (!removeComments)
+ query += '\n';
+
+ i++;
+ inSingleLineComment = false;
+ }
+ else if (c == '\n' || c == '\r')
+ inSingleLineComment = false;
+
+ continue;
+ }
+
+ // Multi-line comment
+ if (inMultiLineComment)
+ {
+ if (!removeComments)
+ query += c;
+
+ if (c == '*' && (i + 1) < total && sql[i+1] == '/')
+ {
+ if (!removeComments)
+ query += '/';
+
+ i++;
+ inMultiLineComment = false;
+ }
+
+ continue;
+ }
+
+ // Everything rest
+ if (c == '\'')
+ {
+ query += c;
+ inString = true;
+ }
+ else if (c == '-' && (i + 1) < total && sql[i+1] == '-')
+ {
+ inSingleLineComment = true;
+ i++;
+ if (!removeComments)
+ query += "--";
+ }
+ else if (c == '/' && (i + 1) < total && sql[i+1] == '*')
+ {
+ inMultiLineComment = true;
+ i++;
+ if (!removeComments)
+ query += "/*";
+ }
+ else if (c == ';')
+ {
+ query += c;
+ if (keepEmptyQueries || (!(trimmed = query.trimmed()).isEmpty() && trimmed != ";"))
+ queries << query;
+
+ query.clear();
+ }
+ else
+ {
+ query += c;
+ }
+ }
+
+ if (!query.isNull() && (!(trimmed = query.trimmed()).isEmpty() && trimmed != ";"))
+ queries << query;
+
+ return queries;
+}
+
+QStringList splitQueries(const QString& sql, Dialect dialect, bool keepEmptyQueries, bool removeComments, bool* complete)
{
TokenList tokens = Lexer::tokenize(sql, dialect);
+ if (removeComments)
+ tokens = tokens.filterOut(Token::COMMENT);
+
QList<TokenList> tokenizedQueries = splitQueries(tokens, complete);
QString query;
@@ -437,7 +559,7 @@ QStringList splitQueries(const QString& sql, Dialect dialect, bool keepEmptyQuer
foreach (const TokenList& queryTokens, tokenizedQueries)
{
query = queryTokens.detokenize();
- if (keepEmptyQueries || !query.trimmed().isEmpty())
+ if (keepEmptyQueries || (!query.trimmed().isEmpty() && query.trimmed() != ";"))
queries << query;
}
@@ -452,7 +574,7 @@ QString getQueryWithPosition(const QStringList& queries, int position, int* star
if (startPos)
*startPos = 0;
- foreach (const QString& query, queries)
+ for (const QString& query : queries)
{
length = query.length();
if (position >= currentPos && position < currentPos+length)
@@ -479,9 +601,9 @@ QString getQueryWithPosition(const QStringList& queries, int position, int* star
return QString::null;
}
-QString getQueryWithPosition(const QString& queries, int position, Dialect dialect, int* startPos)
+QString getQueryWithPosition(const QString& queries, int position, int* startPos)
{
- QStringList queryList = splitQueries(queries, dialect);
+ QStringList queryList = quickSplitQueries(queries);
return getQueryWithPosition(queryList, position, startPos);
}
@@ -665,7 +787,7 @@ QStringList valueListToSqlList(const QVariantList& values, Dialect dialect)
argList << value.toString();
break;
case QVariant::Double:
- argList << doubleToString(value.toDouble());
+ argList << doubleToString(value);
break;
case QVariant::Bool:
argList << QString::number(value.toInt());
@@ -694,3 +816,14 @@ QStringList wrapStrings(const QStringList& strList)
return list;
}
+
+QString trimQueryEnd(const QString &query)
+{
+ QString q = query.trimmed();
+ while (q.endsWith(";"))
+ {
+ q.chop(1);
+ q = q.trimmed();
+ }
+ return q;
+}
diff --git a/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.h b/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.h
index ceccea0..1da3108 100644
--- a/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.h
+++ b/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.h
@@ -67,9 +67,10 @@ API_EXPORT bool isSystemTable(const QString& name);
API_EXPORT bool isSystemIndex(const QString& name, Dialect dialect);
API_EXPORT QString removeComments(const QString& value);
API_EXPORT QList<TokenList> splitQueries(const TokenList& tokenizedQueries, bool* complete = nullptr);
-API_EXPORT QStringList splitQueries(const QString& sql, Dialect dialect, bool keepEmptyQueries = true, bool* complete = nullptr);
+API_EXPORT QStringList splitQueries(const QString& sql, Dialect dialect, bool keepEmptyQueries = true, bool removeComments = false, bool* complete = nullptr);
+API_EXPORT QStringList quickSplitQueries(const QString& sql, bool keepEmptyQueries = true, bool removeComments = false);
API_EXPORT QString getQueryWithPosition(const QStringList& queries, int position, int* startPos = nullptr);
-API_EXPORT QString getQueryWithPosition(const QString& queries, int position, Dialect dialect, int* startPos = nullptr);
+API_EXPORT QString getQueryWithPosition(const QString& queries, int position, int* startPos = nullptr);
API_EXPORT QList<QueryWithParamNames> getQueriesWithParamNames(const QString& query, Dialect dialect);
API_EXPORT QList<QueryWithParamCount> getQueriesWithParamCount(const QString& query, Dialect dialect);
API_EXPORT QueryWithParamNames getQueryWithParamNames(const QString& query, Dialect dialect);
@@ -79,6 +80,7 @@ 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);
+API_EXPORT QString trimQueryEnd(const QString& query);
#endif // UTILS_SQL_H