diff options
Diffstat (limited to 'SQLiteStudio3/coreSQLiteStudio/common')
| -rw-r--r-- | SQLiteStudio3/coreSQLiteStudio/common/bistrhash.cpp | 213 | ||||
| -rw-r--r-- | SQLiteStudio3/coreSQLiteStudio/common/bistrhash.h | 213 | ||||
| -rw-r--r-- | SQLiteStudio3/coreSQLiteStudio/common/sortedset.h | 64 | ||||
| -rw-r--r-- | SQLiteStudio3/coreSQLiteStudio/common/strhash.h | 23 | ||||
| -rw-r--r-- | SQLiteStudio3/coreSQLiteStudio/common/utils.cpp | 43 | ||||
| -rw-r--r-- | SQLiteStudio3/coreSQLiteStudio/common/utils.h | 40 | ||||
| -rw-r--r-- | SQLiteStudio3/coreSQLiteStudio/common/utils_sql.cpp | 62 | ||||
| -rw-r--r-- | SQLiteStudio3/coreSQLiteStudio/common/utils_sql.h | 4 |
8 files changed, 459 insertions, 203 deletions
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 |
