Skip to content

Commit c077ff7

Browse files
committed
Import MySQL completion candidates from pygments
Since the pygments library is already required, why not use its list of reserved words for completions? This fixes #767 and should keep us up-to-date. It's really great to have the JSON_* functions. Obsoletes #925. Compared to the previous code, this PR * removes LEN and TOP, which are not MySQL reserved words * preserves extra completion candidates containing space, such as "ORDER BY" Downsides and bugs: * pygments.lexers._mysql_builtins does contain a leading underscore, so we should be aware that the library reserves the right to break this usage. The library version has been more tightly defined to remediate issues here. * Similarly, certain tests might become more brittle with regard to library updates. * Certain reserved words are duplicated with special commands, so if the first word of a command-line is any of the following, duplicated completions will show, as both upper- and lower-case: exit, help, source, status, system, use. This is fixable, but should we prefer the upper- or lower-case flavor? * There are _many_ more completion candidates now, which may inspire us to do further work soon on prioritizing which completions are seen at the top.
1 parent d94ca37 commit c077ff7

File tree

5 files changed

+197
-168
lines changed

5 files changed

+197
-168
lines changed

changelog.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
TBD
2+
==============
3+
4+
Features
5+
--------
6+
* More complete and up-to-date set of MySQL reserved words for completions.
7+
8+
19
1.44.2 (2026/01/13)
210
==============
311

mycli/sqlcompleter.py

Lines changed: 21 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from prompt_toolkit.completion import CompleteEvent, Completer, Completion
99
from prompt_toolkit.completion.base import Document
10+
from pygments.lexers._mysql_builtins import MYSQL_DATATYPES, MYSQL_FUNCTIONS, MYSQL_KEYWORDS
1011

1112
from mycli.packages.completion_engine import suggest_type
1213
from mycli.packages.filepaths import complete_path, parse_path, suggest_path
@@ -18,141 +19,27 @@
1819

1920

2021
class SQLCompleter(Completer):
22+
favorite_keywords = [
23+
'SELECT',
24+
'FROM',
25+
'WHERE',
26+
'UPDATE',
27+
'DELETE FROM',
28+
'GROUP BY',
29+
'ORDER BY',
30+
'JOIN',
31+
'INSERT INTO',
32+
'LIKE',
33+
'LIMIT',
34+
]
2135
keywords = [
22-
"SELECT",
23-
"FROM",
24-
"WHERE",
25-
"UPDATE",
26-
"DELETE FROM",
27-
"GROUP BY",
28-
"JOIN",
29-
"INSERT INTO",
30-
"LIKE",
31-
"LIMIT",
32-
"ACCESS",
33-
"ADD",
34-
"ALL",
35-
"ALTER TABLE",
36-
"AND",
37-
"ANY",
38-
"AS",
39-
"ASC",
40-
"AUTO_INCREMENT",
41-
"BEFORE",
42-
"BEGIN",
43-
"BETWEEN",
44-
"BIGINT",
45-
"BINARY",
46-
"BY",
47-
"CASE",
48-
"CHANGE MASTER TO",
49-
"CHAR",
50-
"CHARACTER SET",
51-
"CHECK",
52-
"COLLATE",
53-
"COLUMN",
54-
"COMMENT",
55-
"COMMIT",
56-
"CONSTRAINT",
57-
"CREATE",
58-
"CURRENT",
59-
"CURRENT_TIMESTAMP",
60-
"DATABASE",
61-
"DATE",
62-
"DECIMAL",
63-
"DEFAULT",
64-
"DESC",
65-
"DESCRIBE",
66-
"DROP",
67-
"ELSE",
68-
"END",
69-
"ENGINE",
70-
"ESCAPE",
71-
"EXISTS",
72-
"FILE",
73-
"FLOAT",
74-
"FOR",
75-
"FOREIGN KEY",
76-
"FORMAT",
77-
"FULL",
78-
"FUNCTION",
79-
"GRANT",
80-
"HAVING",
81-
"HOST",
82-
"IDENTIFIED",
83-
"IN",
84-
"INCREMENT",
85-
"INDEX",
86-
"INT",
87-
"INTEGER",
88-
"INTERVAL",
89-
"INTO",
90-
"IS",
91-
"KEY",
92-
"LEFT",
93-
"LEVEL",
94-
"LOCK",
95-
"LOGS",
96-
"LONG",
97-
"MASTER",
98-
"MEDIUMINT",
99-
"MODE",
100-
"MODIFY",
101-
"NOT",
102-
"NULL",
103-
"NUMBER",
104-
"OFFSET",
105-
"ON",
106-
"OPTION",
107-
"OR",
108-
"ORDER BY",
109-
"OUTER",
110-
"OWNER",
111-
"PASSWORD",
112-
"PORT",
113-
"PRIMARY",
114-
"PRIVILEGES",
115-
"PROCESSLIST",
116-
"PURGE",
117-
"REFERENCES",
118-
"REGEXP",
119-
"RENAME",
120-
"REPAIR",
121-
"RESET",
122-
"REVOKE",
123-
"RIGHT",
124-
"ROLLBACK",
125-
"ROW",
126-
"ROWS",
127-
"ROW_FORMAT",
128-
"SAVEPOINT",
129-
"SESSION",
130-
"SET",
131-
"SHARE",
132-
"SHOW",
133-
"SLAVE",
134-
"SMALLINT",
135-
"START",
136-
"STOP",
137-
"TABLE",
138-
"THEN",
139-
"TINYINT",
140-
"TO",
141-
"TRANSACTION",
142-
"TRIGGER",
143-
"TRUNCATE",
144-
"UNION",
145-
"UNIQUE",
146-
"UNSIGNED",
147-
"USE",
148-
"USER",
149-
"USING",
150-
"VALUES",
151-
"VARCHAR",
152-
"VIEW",
153-
"WHEN",
154-
"WITH",
36+
x.upper()
37+
for x in favorite_keywords
38+
+ list(MYSQL_DATATYPES)
39+
+ list(MYSQL_KEYWORDS)
40+
+ ['ALTER TABLE', 'CHANGE MASTER TO', 'CHARACTER SET', 'FOREIGN KEY']
15541
]
42+
keywords = list(dict.fromkeys(keywords))
15643

15744
tidb_keywords = [
15845
"SELECT",
@@ -838,27 +725,7 @@ class SQLCompleter(Completer):
838725
"ZEROFILL",
839726
]
840727

841-
functions = [
842-
"AVG",
843-
"CONCAT",
844-
"COUNT",
845-
"DISTINCT",
846-
"FIRST",
847-
"FORMAT",
848-
"FROM_UNIXTIME",
849-
"LAST",
850-
"LCASE",
851-
"LEN",
852-
"MAX",
853-
"MID",
854-
"MIN",
855-
"NOW",
856-
"ROUND",
857-
"SUM",
858-
"TOP",
859-
"UCASE",
860-
"UNIX_TIMESTAMP",
861-
]
728+
functions = [x.upper() for x in MYSQL_FUNCTIONS]
862729

863730
# https://docs.pingcap.com/tidb/dev/tidb-functions
864731
tidb_functions = [

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ urls = { homepage = "http://mycli.net" }
1111
dependencies = [
1212
"click >= 8.3.1",
1313
"cryptography >= 1.0.0",
14-
"Pygments>=1.6",
14+
"Pygments ~= 2.19.2",
1515
"prompt_toolkit>=3.0.6,<4.0.0",
1616
"PyMySQL >= 0.9.2",
1717
"sqlparse>=0.3.0,<0.6.0",

test/test_naive_completion.py

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,48 @@ def test_function_name_completion(completer, complete_event):
3737
text = "SELECT MA"
3838
position = len("SELECT MA")
3939
result = list(completer.get_completions(Document(text=text, cursor_position=position), complete_event))
40-
assert sorted(x.text for x in result) == ["MASTER", "MAX"]
40+
assert sorted(x.text for x in result) == [
41+
'MAKEDATE',
42+
'MAKETIME',
43+
'MAKE_SET',
44+
'MASTER',
45+
'MASTER_AUTO_POSITION',
46+
'MASTER_BIND',
47+
'MASTER_COMPRESSION_ALGORITHMS',
48+
'MASTER_CONNECT_RETRY',
49+
'MASTER_DELAY',
50+
'MASTER_HEARTBEAT_PERIOD',
51+
'MASTER_HOST',
52+
'MASTER_LOG_FILE',
53+
'MASTER_LOG_POS',
54+
'MASTER_PASSWORD',
55+
'MASTER_PORT',
56+
'MASTER_POS_WAIT',
57+
'MASTER_PUBLIC_KEY_PATH',
58+
'MASTER_RETRY_COUNT',
59+
'MASTER_SSL',
60+
'MASTER_SSL_CA',
61+
'MASTER_SSL_CAPATH',
62+
'MASTER_SSL_CERT',
63+
'MASTER_SSL_CIPHER',
64+
'MASTER_SSL_CRL',
65+
'MASTER_SSL_CRLPATH',
66+
'MASTER_SSL_KEY',
67+
'MASTER_SSL_VERIFY_SERVER_CERT',
68+
'MASTER_TLS_CIPHERSUITES',
69+
'MASTER_TLS_VERSION',
70+
'MASTER_USER',
71+
'MASTER_ZSTD_COMPRESSION_LEVEL',
72+
'MATCH',
73+
'MAX',
74+
'MAXVALUE',
75+
'MAX_CONNECTIONS_PER_HOUR',
76+
'MAX_QUERIES_PER_HOUR',
77+
'MAX_ROWS',
78+
'MAX_SIZE',
79+
'MAX_UPDATES_PER_HOUR',
80+
'MAX_USER_CONNECTIONS',
81+
]
4182

4283

4384
def test_column_name_completion(completer, complete_event):

0 commit comments

Comments
 (0)