From 7167ce41b61d2ba2cdb526777a4233eb84a3b66a Mon Sep 17 00:00:00 2001 From: Unit 193 Date: Sat, 6 Dec 2014 17:33:25 -0500 Subject: Imported Upstream version 2.99.6 --- SQLiteStudio3/coreSQLiteStudio/completionhelper.h | 264 ++++++++++++++++++++++ 1 file changed, 264 insertions(+) create mode 100644 SQLiteStudio3/coreSQLiteStudio/completionhelper.h (limited to 'SQLiteStudio3/coreSQLiteStudio/completionhelper.h') diff --git a/SQLiteStudio3/coreSQLiteStudio/completionhelper.h b/SQLiteStudio3/coreSQLiteStudio/completionhelper.h new file mode 100644 index 0000000..63b7225 --- /dev/null +++ b/SQLiteStudio3/coreSQLiteStudio/completionhelper.h @@ -0,0 +1,264 @@ +#ifndef COMPLETIONHELPER_H +#define COMPLETIONHELPER_H + +#include "expectedtoken.h" +#include "schemaresolver.h" +#include "selectresolver.h" +#include "dialect.h" +#include "completioncomparer.h" +#include "parser/ast/sqliteselect.h" +#include "parser/token.h" +#include "db/db.h" +#include "common/strhash.h" +#include "common/table.h" +#include +#include + +class DbAttacher; + +class API_EXPORT CompletionHelper : public QObject +{ + friend class CompletionComparer; + + public: + struct API_EXPORT Results + { + QList filtered(); + + QList expectedTokens; + QString partialToken; + bool wrappedToken = false; + }; + + CompletionHelper(const QString& sql, Db* db); + CompletionHelper(const QString& sql, quint32 cursorPos, Db* db); + ~CompletionHelper(); + + static void applyFilter(QList &results, const QString &filter); + static void init(); + + Results getExpectedTokens(); + + DbAttacher* getDbAttacher() const; + void setDbAttacher(DbAttacher* value); + + static bool enableLemonDebug; + + QString getCreateTriggerTable() const; + void setCreateTriggerTable(const QString& value); + + private: + enum class Context + { + NONE, + SELECT_RESULT_COLUMN, + SELECT_FROM, + SELECT_WHERE, + SELECT_GROUP_BY, + SELECT_HAVING, + SELECT_ORDER_BY, + SELECT_LIMIT, + UPDATE_COLUMN, + UPDATE_WHERE, + DELETE_WHERE, + CREATE_TABLE, + CREATE_TRIGGER, + EXPR + }; + + QList getExpectedTokens(TokenPtr token); + ExpectedTokenPtr getExpectedToken(ExpectedToken::Type type); + ExpectedTokenPtr getExpectedToken(ExpectedToken::Type type, const QString& value); + ExpectedTokenPtr getExpectedToken(ExpectedToken::Type type, const QString& value, + int priority); + ExpectedTokenPtr getExpectedToken(ExpectedToken::Type type, const QString& value, + const QString& contextInfo); + ExpectedTokenPtr getExpectedToken(ExpectedToken::Type type, const QString& value, + const QString& contextInfo, int priority); + ExpectedTokenPtr getExpectedToken(ExpectedToken::Type type, const QString &value, + const QString &contextInfo, const QString &label); + ExpectedTokenPtr getExpectedToken(ExpectedToken::Type type, const QString &value, + const QString &contextInfo, const QString &label, + int priority); + ExpectedTokenPtr getExpectedToken(ExpectedToken::Type type, const QString &value, + const QString &contextInfo, const QString &label, + const QString &prefix); + ExpectedTokenPtr getExpectedToken(ExpectedToken::Type type, const QString &value, + const QString &contextInfo, const QString &label, + const QString &prefix, int priority); + bool validatePreviousIdForGetObjects(QString* dbName = nullptr); + QList getTables(); + QList getIndexes(); + QList getTriggers(); + QList getViews(); + QList getDatabases(); + QList getObjects(ExpectedToken::Type type); + QList getObjects(ExpectedToken::Type type, const QString& database); + QList getColumns(); + QList getColumnsNoPrefix(); + QList getColumnsNoPrefix(const QString &column, const QStringList &tables); + QList getColumns(const QString& prefixTable); + QList getColumns(const QString& prefixDb, const QString& prefixTable); + QList getFavoredColumns(const QList& resultsSoFar); + + QList getPragmas(Dialect dialect); + QList getFunctions(Db* db); + QList getCollations(); + TokenPtr getPreviousDbOrTable(const TokenList& parsedTokens); + void attachDatabases(); + void detachDatabases(); + QString translateDatabase(const QString& dbName); + QString translateDatabaseBack(const QString& dbName); + void collectOtherDatabases(); + QString removeStartedToken(const QString& adjustedSql, QString &finalFilter, bool& wrappedFilter); + void filterContextKeywords(QList &results, const TokenList& tokens); + void filterOtherId(QList &results, const TokenList& tokens); + void filterDuplicates(QList &results); + bool isFilterType(Token::Type type); + void parseFullSql(); + void sort(QList &results); + void extractPreviousIdTokens(const TokenList& parsedTokens); + void extractQueryAdditionalInfo(); + void extractSelectAvailableColumnsAndTables(); + bool extractSelectCore(); + SqliteSelect::Core* extractSelectCore(SqliteQueryPtr query); + void extractTableAliasMap(); + void extractCreateTableColumns(); + void detectSelectContext(); + bool isInUpdateColumn(); + bool isInUpdateWhere(); + bool isInDeleteWhere(); + bool isInCreateTable(); + bool isInCreateTrigger(); + bool isIn(SqliteQueryType queryType, const QString& tokenMapKey, const QString &prefixKeyword); + bool isInExpr(); + bool testQueryToken(int tokenPosition, Token::Type type, const QString& value, Qt::CaseSensitivity cs = Qt::CaseInsensitive); + bool cursorAfterTokenMaps(SqliteStatement* stmt, const QStringList& mapNames); + bool cursorBeforeTokenMaps(SqliteStatement* stmt, const QStringList& mapNames); + + template + bool cursorFitsInCollection(const QList& collection) + { + if (collection.size() == 0) + return false; + + T* firstStmt = collection.first(); + T* lastStmt = collection.last(); + + int startIdx = -1; + int endIdx = -1; + if (firstStmt && firstStmt->tokens.size() > 0) + startIdx = firstStmt->tokens.first()->start; + + if (lastStmt && lastStmt->tokens.size() > 0) + endIdx = lastStmt->tokens.last()->end; + + if (startIdx < 0 || endIdx < 0) + return false; + + return (cursorPosition >= startIdx && cursorPosition <= endIdx); + } + + template + bool cursorFitsInStatement(T* stmt) + { + if (!stmt || stmt->tokens.size() == 0) + return false; + + int startIdx = stmt->tokens.first()->start; + int endIdx = stmt->tokens.last()->end; + + return (cursorPosition >= startIdx && cursorPosition <= endIdx); + } + + + Context context = Context::NONE; + Db* db = nullptr; + qint64 cursorPosition; + QString fullSql; + TokenPtr previousId; + TokenPtr twoIdsBack; + TokenList queryTokens; + SqliteQueryPtr parsedQuery; + SqliteQueryPtr originalParsedQuery; + SchemaResolver* schemaResolver = nullptr; + SelectResolver* selectResolver = nullptr; + DbAttacher* dbAttacher = nullptr; + QString createTriggerTable; + + /** + * @brief tableToAlias + * This map maps real table name to its alias. Every table can be typed multiple times + * with different aliases, therefore this map has a list on the right side. + */ + QHash tableToAlias; + + /** + * @brief aliasToTable + * Maps table alias to table's real name. + */ + //QHash aliasToTable; + StrHash aliasToTable; + + /** + * @brief currentSelectCore + * The SqliteSelect::Core object that contains current cursor position. + */ + SqliteSelect::Core* currentSelectCore = nullptr; + + /** + * @brief originalCurrentSelectCore + * + * The same as currentSelectCore, but relates to originalParsedQuery, not just parsedQuery. + */ + SqliteSelect::Core* originalCurrentSelectCore = nullptr; + + /** + * @brief selectAvailableColumns + * Available columns are columns that can be selected basing on what tables are mentioned in FROM clause. + */ + QList selectAvailableColumns; + + /** + * @brief selectAvailableTables + * Availble tables are tables mentioned in FROM clause. + */ + QSet selectAvailableTables; + + /** + * @brief parentSelectCores + * List of all parent select core objects in order: from direct parent, to the oldest parent. + */ + QList parentSelectCores; + + /** + * @brief parentSelectAvailableColumns + * List of all columns available in all tables mentioned in all parent select cores. + */ + QList parentSelectAvailableColumns; + + /** + * @brief parentSelectAvailableTables + * Same as parentSelectAvailableColumns, but for tables in FROM clauses. + */ + QSet parentSelectAvailableTables; + + /** + * @brief favoredColumnNames + * For some contexts there are favored column names, like for example CREATE TABLE + * will favour column names specified so far in its definition. + * Such columns will be added to completion results even they weren't result + * of regular computation. + */ + QStringList favoredColumnNames; + + /** + * @brief Context databases to look for objects in. + * + * If the query uses some other databases (not the currentone), then user might be interested + * also in objects from those databases. This list contains those databases. + */ + QStringList otherDatabasesToLookupFor; +}; + +#endif // COMPLETIONHELPER_H -- cgit v1.2.3