diff --git a/changelog.md b/changelog.md index 84545e80..a0c711e3 100644 --- a/changelog.md +++ b/changelog.md @@ -3,6 +3,7 @@ TBD Features -------- +* More complete and up-to-date set of MySQL reserved words for completions. * Allow history file location to be configured. diff --git a/mycli/sqlcompleter.py b/mycli/sqlcompleter.py index 1ed62068..5590ce21 100644 --- a/mycli/sqlcompleter.py +++ b/mycli/sqlcompleter.py @@ -7,6 +7,7 @@ from prompt_toolkit.completion import CompleteEvent, Completer, Completion from prompt_toolkit.completion.base import Document +from pygments.lexers._mysql_builtins import MYSQL_DATATYPES, MYSQL_FUNCTIONS, MYSQL_KEYWORDS from mycli.packages.completion_engine import suggest_type from mycli.packages.filepaths import complete_path, parse_path, suggest_path @@ -18,141 +19,27 @@ class SQLCompleter(Completer): + favorite_keywords = [ + 'SELECT', + 'FROM', + 'WHERE', + 'UPDATE', + 'DELETE FROM', + 'GROUP BY', + 'ORDER BY', + 'JOIN', + 'INSERT INTO', + 'LIKE', + 'LIMIT', + ] keywords = [ - "SELECT", - "FROM", - "WHERE", - "UPDATE", - "DELETE FROM", - "GROUP BY", - "JOIN", - "INSERT INTO", - "LIKE", - "LIMIT", - "ACCESS", - "ADD", - "ALL", - "ALTER TABLE", - "AND", - "ANY", - "AS", - "ASC", - "AUTO_INCREMENT", - "BEFORE", - "BEGIN", - "BETWEEN", - "BIGINT", - "BINARY", - "BY", - "CASE", - "CHANGE MASTER TO", - "CHAR", - "CHARACTER SET", - "CHECK", - "COLLATE", - "COLUMN", - "COMMENT", - "COMMIT", - "CONSTRAINT", - "CREATE", - "CURRENT", - "CURRENT_TIMESTAMP", - "DATABASE", - "DATE", - "DECIMAL", - "DEFAULT", - "DESC", - "DESCRIBE", - "DROP", - "ELSE", - "END", - "ENGINE", - "ESCAPE", - "EXISTS", - "FILE", - "FLOAT", - "FOR", - "FOREIGN KEY", - "FORMAT", - "FULL", - "FUNCTION", - "GRANT", - "HAVING", - "HOST", - "IDENTIFIED", - "IN", - "INCREMENT", - "INDEX", - "INT", - "INTEGER", - "INTERVAL", - "INTO", - "IS", - "KEY", - "LEFT", - "LEVEL", - "LOCK", - "LOGS", - "LONG", - "MASTER", - "MEDIUMINT", - "MODE", - "MODIFY", - "NOT", - "NULL", - "NUMBER", - "OFFSET", - "ON", - "OPTION", - "OR", - "ORDER BY", - "OUTER", - "OWNER", - "PASSWORD", - "PORT", - "PRIMARY", - "PRIVILEGES", - "PROCESSLIST", - "PURGE", - "REFERENCES", - "REGEXP", - "RENAME", - "REPAIR", - "RESET", - "REVOKE", - "RIGHT", - "ROLLBACK", - "ROW", - "ROWS", - "ROW_FORMAT", - "SAVEPOINT", - "SESSION", - "SET", - "SHARE", - "SHOW", - "SLAVE", - "SMALLINT", - "START", - "STOP", - "TABLE", - "THEN", - "TINYINT", - "TO", - "TRANSACTION", - "TRIGGER", - "TRUNCATE", - "UNION", - "UNIQUE", - "UNSIGNED", - "USE", - "USER", - "USING", - "VALUES", - "VARCHAR", - "VIEW", - "WHEN", - "WITH", + x.upper() + for x in favorite_keywords + + list(MYSQL_DATATYPES) + + list(MYSQL_KEYWORDS) + + ['ALTER TABLE', 'CHANGE MASTER TO', 'CHARACTER SET', 'FOREIGN KEY'] ] + keywords = list(dict.fromkeys(keywords)) tidb_keywords = [ "SELECT", @@ -838,27 +725,7 @@ class SQLCompleter(Completer): "ZEROFILL", ] - functions = [ - "AVG", - "CONCAT", - "COUNT", - "DISTINCT", - "FIRST", - "FORMAT", - "FROM_UNIXTIME", - "LAST", - "LCASE", - "LEN", - "MAX", - "MID", - "MIN", - "NOW", - "ROUND", - "SUM", - "TOP", - "UCASE", - "UNIX_TIMESTAMP", - ] + functions = [x.upper() for x in MYSQL_FUNCTIONS] # https://docs.pingcap.com/tidb/dev/tidb-functions tidb_functions = [ diff --git a/pyproject.toml b/pyproject.toml index f6d13cff..675f88b1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ urls = { homepage = "http://mycli.net" } dependencies = [ "click >= 8.3.1", "cryptography >= 1.0.0", - "Pygments>=1.6", + "Pygments ~= 2.19.2", "prompt_toolkit>=3.0.6,<4.0.0", "PyMySQL >= 0.9.2", "sqlparse>=0.3.0,<0.6.0", diff --git a/test/test_naive_completion.py b/test/test_naive_completion.py index 2ba9c6fe..fd4be76b 100644 --- a/test/test_naive_completion.py +++ b/test/test_naive_completion.py @@ -37,7 +37,48 @@ def test_function_name_completion(completer, complete_event): text = "SELECT MA" position = len("SELECT MA") result = list(completer.get_completions(Document(text=text, cursor_position=position), complete_event)) - assert sorted(x.text for x in result) == ["MASTER", "MAX"] + assert sorted(x.text for x in result) == [ + 'MAKEDATE', + 'MAKETIME', + 'MAKE_SET', + 'MASTER', + 'MASTER_AUTO_POSITION', + 'MASTER_BIND', + 'MASTER_COMPRESSION_ALGORITHMS', + 'MASTER_CONNECT_RETRY', + 'MASTER_DELAY', + 'MASTER_HEARTBEAT_PERIOD', + 'MASTER_HOST', + 'MASTER_LOG_FILE', + 'MASTER_LOG_POS', + 'MASTER_PASSWORD', + 'MASTER_PORT', + 'MASTER_POS_WAIT', + 'MASTER_PUBLIC_KEY_PATH', + 'MASTER_RETRY_COUNT', + 'MASTER_SSL', + 'MASTER_SSL_CA', + 'MASTER_SSL_CAPATH', + 'MASTER_SSL_CERT', + 'MASTER_SSL_CIPHER', + 'MASTER_SSL_CRL', + 'MASTER_SSL_CRLPATH', + 'MASTER_SSL_KEY', + 'MASTER_SSL_VERIFY_SERVER_CERT', + 'MASTER_TLS_CIPHERSUITES', + 'MASTER_TLS_VERSION', + 'MASTER_USER', + 'MASTER_ZSTD_COMPRESSION_LEVEL', + 'MATCH', + 'MAX', + 'MAXVALUE', + 'MAX_CONNECTIONS_PER_HOUR', + 'MAX_QUERIES_PER_HOUR', + 'MAX_ROWS', + 'MAX_SIZE', + 'MAX_UPDATES_PER_HOUR', + 'MAX_USER_CONNECTIONS', + ] def test_column_name_completion(completer, complete_event): diff --git a/test/test_smart_completion_public_schema_only.py b/test/test_smart_completion_public_schema_only.py index f65f7c7d..7efe10ef 100644 --- a/test/test_smart_completion_public_schema_only.py +++ b/test/test_smart_completion_public_schema_only.py @@ -63,7 +63,55 @@ def test_select_keyword_completion(completer, complete_event): text = "SEL" position = len("SEL") result = completer.get_completions(Document(text=text, cursor_position=position), complete_event) - assert list(result) == [Completion(text="SELECT", start_position=-3)] + assert list(result) == [ + Completion(text='SELECT', start_position=-3), + Completion(text='SERIAL', start_position=-3), + Completion(text='GET_MASTER_PUBLIC_KEY', start_position=-3), + Completion(text='GET_SOURCE_PUBLIC_KEY', start_position=-3), + Completion(text='MASTER_COMPRESSION_ALGORITHMS', start_position=-3), + Completion(text='MASTER_DELAY', start_position=-3), + Completion(text='MASTER_LOG_FILE', start_position=-3), + Completion(text='MASTER_LOG_POS', start_position=-3), + Completion(text='MASTER_PUBLIC_KEY_PATH', start_position=-3), + Completion(text='MASTER_SSL', start_position=-3), + Completion(text='MASTER_SSL_CA', start_position=-3), + Completion(text='MASTER_SSL_CAPATH', start_position=-3), + Completion(text='MASTER_SSL_CERT', start_position=-3), + Completion(text='MASTER_SSL_CIPHER', start_position=-3), + Completion(text='MASTER_SSL_CRL', start_position=-3), + Completion(text='MASTER_SSL_CRLPATH', start_position=-3), + Completion(text='MASTER_SSL_KEY', start_position=-3), + Completion(text='MASTER_SSL_VERIFY_SERVER_CERT', start_position=-3), + Completion(text='MASTER_TLS_CIPHERSUITES', start_position=-3), + Completion(text='MASTER_TLS_VERSION', start_position=-3), + Completion(text='MASTER_ZSTD_COMPRESSION_LEVEL', start_position=-3), + Completion(text='SCHEDULE', start_position=-3), + Completion(text='SECONDARY_LOAD', start_position=-3), + Completion(text='SECONDARY_UNLOAD', start_position=-3), + Completion(text='SERIALIZABLE', start_position=-3), + Completion(text='SOURCE_COMPRESSION_ALGORITHMS', start_position=-3), + Completion(text='SOURCE_CONNECTION_AUTO_FAILOVER', start_position=-3), + Completion(text='SOURCE_DELAY', start_position=-3), + Completion(text='SOURCE_LOG_FILE', start_position=-3), + Completion(text='SOURCE_LOG_POS', start_position=-3), + Completion(text='SOURCE_PUBLIC_KEY_PATH', start_position=-3), + Completion(text='SOURCE_SSL', start_position=-3), + Completion(text='SOURCE_SSL_CA', start_position=-3), + Completion(text='SOURCE_SSL_CAPATH', start_position=-3), + Completion(text='SOURCE_SSL_CERT', start_position=-3), + Completion(text='SOURCE_SSL_CIPHER', start_position=-3), + Completion(text='SOURCE_SSL_CRL', start_position=-3), + Completion(text='SOURCE_SSL_CRLPATH', start_position=-3), + Completion(text='SOURCE_SSL_KEY', start_position=-3), + Completion(text='SOURCE_SSL_VERIFY_SERVER_CERT', start_position=-3), + Completion(text='SOURCE_TLS_CIPHERSUITES', start_position=-3), + Completion(text='SOURCE_TLS_VERSION', start_position=-3), + Completion(text='SOURCE_ZSTD_COMPRESSION_LEVEL', start_position=-3), + Completion(text='SQL_BIG_RESULT', start_position=-3), + Completion(text='SQL_BUFFER_RESULT', start_position=-3), + Completion(text='SQL_SMALL_RESULT', start_position=-3), + Completion(text='STATS_AUTO_RECALC', start_position=-3), + ] def test_select_star(completer, complete_event): @@ -100,15 +148,80 @@ def test_function_name_completion(completer, complete_event): position = len("SELECT MA") result = completer.get_completions(Document(text=text, cursor_position=position), complete_event) assert list(result) == [ - Completion(text="MAX", start_position=-2), - Completion(text="CHANGE MASTER TO", start_position=-2), - Completion(text="CURRENT_TIMESTAMP", start_position=-2), - Completion(text="DECIMAL", start_position=-2), - Completion(text="FORMAT", start_position=-2), - Completion(text="MASTER", start_position=-2), - Completion(text="PRIMARY", start_position=-2), - Completion(text="ROW_FORMAT", start_position=-2), - Completion(text="SMALLINT", start_position=-2), + Completion(text='MAKE_SET', start_position=-2), + Completion(text='MAKEDATE', start_position=-2), + Completion(text='MAKETIME', start_position=-2), + Completion(text='MASTER_POS_WAIT', start_position=-2), + Completion(text='MAX', start_position=-2), + Completion(text='DECIMAL', start_position=-2), + Completion(text='SMALLINT', start_position=-2), + Completion(text='TIMESTAMP', start_position=-2), + Completion(text='ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS', start_position=-2), + Completion(text='COLUMN_FORMAT', start_position=-2), + Completion(text='COLUMN_NAME', start_position=-2), + Completion(text='COMPACT', start_position=-2), + Completion(text='CONSTRAINT_SCHEMA', start_position=-2), + Completion(text='CURRENT_TIMESTAMP', start_position=-2), + Completion(text='FORMAT', start_position=-2), + Completion(text='GET_FORMAT', start_position=-2), + Completion(text='GET_MASTER_PUBLIC_KEY', start_position=-2), + Completion(text='LOCALTIMESTAMP', start_position=-2), + Completion(text='MASTER', start_position=-2), + Completion(text='MASTER_AUTO_POSITION', start_position=-2), + Completion(text='MASTER_BIND', start_position=-2), + Completion(text='MASTER_COMPRESSION_ALGORITHMS', start_position=-2), + Completion(text='MASTER_CONNECT_RETRY', start_position=-2), + Completion(text='MASTER_DELAY', start_position=-2), + Completion(text='MASTER_HEARTBEAT_PERIOD', start_position=-2), + Completion(text='MASTER_HOST', start_position=-2), + Completion(text='MASTER_LOG_FILE', start_position=-2), + Completion(text='MASTER_LOG_POS', start_position=-2), + Completion(text='MASTER_PASSWORD', start_position=-2), + Completion(text='MASTER_PORT', start_position=-2), + Completion(text='MASTER_PUBLIC_KEY_PATH', start_position=-2), + Completion(text='MASTER_RETRY_COUNT', start_position=-2), + Completion(text='MASTER_SSL', start_position=-2), + Completion(text='MASTER_SSL_CA', start_position=-2), + Completion(text='MASTER_SSL_CAPATH', start_position=-2), + Completion(text='MASTER_SSL_CERT', start_position=-2), + Completion(text='MASTER_SSL_CIPHER', start_position=-2), + Completion(text='MASTER_SSL_CRL', start_position=-2), + Completion(text='MASTER_SSL_CRLPATH', start_position=-2), + Completion(text='MASTER_SSL_KEY', start_position=-2), + Completion(text='MASTER_SSL_VERIFY_SERVER_CERT', start_position=-2), + Completion(text='MASTER_TLS_CIPHERSUITES', start_position=-2), + Completion(text='MASTER_TLS_VERSION', start_position=-2), + Completion(text='MASTER_USER', start_position=-2), + Completion(text='MASTER_ZSTD_COMPRESSION_LEVEL', start_position=-2), + Completion(text='MATCH', start_position=-2), + Completion(text='MAX_CONNECTIONS_PER_HOUR', start_position=-2), + Completion(text='MAX_QUERIES_PER_HOUR', start_position=-2), + Completion(text='MAX_ROWS', start_position=-2), + Completion(text='MAX_SIZE', start_position=-2), + Completion(text='MAX_UPDATES_PER_HOUR', start_position=-2), + Completion(text='MAX_USER_CONNECTIONS', start_position=-2), + Completion(text='MAXVALUE', start_position=-2), + Completion(text='MESSAGE_TEXT', start_position=-2), + Completion(text='MIGRATE', start_position=-2), + Completion(text='NETWORK_NAMESPACE', start_position=-2), + Completion(text='PRIMARY', start_position=-2), + Completion(text='REQUIRE_ROW_FORMAT', start_position=-2), + Completion(text='REQUIRE_TABLE_PRIMARY_KEY_CHECK', start_position=-2), + Completion(text='ROW_FORMAT', start_position=-2), + Completion(text='SCHEMA', start_position=-2), + Completion(text='SCHEMA_NAME', start_position=-2), + Completion(text='SCHEMAS', start_position=-2), + Completion(text='SOURCE_COMPRESSION_ALGORITHMS', start_position=-2), + Completion(text='SQL_AFTER_MTS_GAPS', start_position=-2), + Completion(text='SQL_SMALL_RESULT', start_position=-2), + Completion(text='STATS_SAMPLE_PAGES', start_position=-2), + Completion(text='TEMPORARY', start_position=-2), + Completion(text='TEMPTABLE', start_position=-2), + Completion(text='TERMINATED', start_position=-2), + Completion(text='TIMESTAMPADD', start_position=-2), + Completion(text='TIMESTAMPDIFF', start_position=-2), + Completion(text='UTC_TIMESTAMP', start_position=-2), + Completion(text='CHANGE MASTER TO', start_position=-2), ]