mycli 2.6.1__tar.gz → 2.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mycli-2.6.1/mycli.egg-info → mycli-2.7.0}/PKG-INFO +13 -21
- {mycli-2.6.1 → mycli-2.7.0}/changelog.md +39 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/TIPS +10 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/client.py +5 -1
- {mycli-2.6.1 → mycli-2.7.0}/mycli/client_commands.py +1 -1
- {mycli-2.6.1 → mycli-2.7.0}/mycli/client_query.py +1 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/clistyle.py +1 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/completion_refresher.py +5 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/main_modes/checkup.py +34 -21
- {mycli-2.6.1 → mycli-2.7.0}/mycli/main_modes/repl.py +1 -1
- {mycli-2.6.1 → mycli-2.7.0}/mycli/myclirc +7 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/completion_engine.py +25 -5
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/special/iocommands.py +4 -4
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/special/main.py +11 -11
- {mycli-2.6.1 → mycli-2.7.0}/mycli/schema_prefetcher.py +8 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/sqlcompleter.py +63 -7
- {mycli-2.6.1 → mycli-2.7.0}/mycli/sqlexecute.py +19 -0
- {mycli-2.6.1 → mycli-2.7.0/mycli.egg-info}/PKG-INFO +13 -21
- {mycli-2.6.1 → mycli-2.7.0}/mycli.egg-info/requires.txt +12 -20
- mycli-2.7.0/mycli.egg-info/scm_version.json +8 -0
- {mycli-2.6.1 → mycli-2.7.0}/pyproject.toml +19 -23
- {mycli-2.6.1 → mycli-2.7.0}/test/myclirc +7 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_checkup.py +18 -10
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_client.py +30 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_client_query.py +12 -2
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_clistyle.py +12 -1
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_completer_use_switch.py +3 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_completion_engine.py +33 -4
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_completion_refresher.py +4 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_main_modes_repl.py +17 -3
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_naive_completion.py +13 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_schema_prefetcher.py +11 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_smart_completion_public_schema_only.py +113 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_special_main.py +3 -3
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_sqlcompleter.py +39 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_sqlexecute.py +39 -0
- mycli-2.6.1/mycli.egg-info/scm_version.json +0 -8
- {mycli-2.6.1 → mycli-2.7.0}/.git-blame-ignore-revs +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/.github/dependabot.yml +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/.github/workflows/ci.yml +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/.github/workflows/lint.yml +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/.github/workflows/publish.yml +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/.github/workflows/typecheck.yml +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/.gitignore +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/AGENTS.md +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/AUTHORS.rst +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/CONTRIBUTING.md +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/LICENSE.txt +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/MANIFEST.in +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/README.md +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/SPONSORS.rst +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/doc/key_bindings.rst +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/doc/llm.md +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/doc/screenshots/main.gif +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/doc/screenshots/tables.png +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/doc/screenshots/total_histogram.png +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/doc/transforms.md +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/AUTHORS +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/SPONSORS +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/__init__.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/app_state.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/cli_runner.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/clibuffer.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/client_connection.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/clitoolbar.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/compat.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/config.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/constants.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/key_bindings.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/lexer.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/main.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/main_modes/batch.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/main_modes/execute.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/main_modes/list_dsn.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/output.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/__init__.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/batch_utils.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/cli_utils.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/filepaths.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/hybrid_redirection.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/interactive_utils.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/key_binding_utils.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/polars_transform.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/ptoolkit/__init__.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/ptoolkit/fzf.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/ptoolkit/history.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/ptoolkit/utils.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/special/__init__.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/special/dbcommands.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/special/delimitercommand.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/special/dsn_aliases.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/special/favoritequeries.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/special/llm.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/special/utils.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/sql_utils.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/sqlresult.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/string_utils.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/tabular_output/__init__.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/packages/tabular_output/sql_format.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/password_sources.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/ssh_tunnel.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/types.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli/vault.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli.egg-info/SOURCES.txt +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli.egg-info/dependency_links.txt +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli.egg-info/entry_points.txt +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli.egg-info/scm_file_list.json +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/mycli.egg-info/top_level.txt +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/setup.cfg +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/__init__.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/__init__.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/auto_vertical.feature +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/basic_commands.feature +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/connection.feature +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/crud_database.feature +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/crud_table.feature +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/db_utils.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/environment.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/fixture_data/help_commands.txt +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/fixture_utils.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/iocommands.feature +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/named_queries.feature +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/specials.feature +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/steps/__init__.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/steps/auto_vertical.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/steps/basic_commands.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/steps/connection.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/steps/crud_database.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/steps/crud_table.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/steps/iocommands.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/steps/named_queries.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/steps/specials.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/steps/utils.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/steps/wrappers.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/features/wrappager.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/mylogin.cnf +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/conftest.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_app_state.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_batch_utils.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_cli_runner.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_cli_utils.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_clibuffer.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_client_commands.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_client_connection.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_clitoolbar.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_config.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_delimitercommand.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_dsn_aliases.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_favoritequeries.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_filepaths.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_hybrid_redirection.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_interactive_utils.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_key_binding_utils.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_key_bindings.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_lexer.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_main.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_main_modes_batch.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_main_modes_execute.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_main_modes_list_dsn.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_output.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_password_sources.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_polars_transform.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_ptoolkit_fzf.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_ptoolkit_history.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_ptoolkit_utils.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_special_dbcommands.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_special_init.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_special_iocommands.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_special_llm.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_special_utils.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_sql_utils.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_sqlresult.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_ssh_tunnel.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_string_utils.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_tabular_output.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/pytests/test_vault.py +0 -0
- {mycli-2.6.1 → mycli-2.7.0}/test/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mycli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.7.0
|
|
4
4
|
Summary: CLI for MySQL Database. With auto-completion and syntax highlighting.
|
|
5
5
|
Author: Mycli Core Team
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -13,18 +13,18 @@ Requires-Python: >=3.10
|
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE.txt
|
|
15
15
|
License-File: AUTHORS.rst
|
|
16
|
-
Requires-Dist: click~=8.
|
|
16
|
+
Requires-Dist: click~=8.4.2
|
|
17
17
|
Requires-Dist: clickdc~=0.1.1
|
|
18
|
-
Requires-Dist: cryptography~=
|
|
19
|
-
Requires-Dist: Pygments~=2.
|
|
18
|
+
Requires-Dist: cryptography~=49.0.0
|
|
19
|
+
Requires-Dist: Pygments~=2.20.0
|
|
20
20
|
Requires-Dist: prompt_toolkit<4.0.0,>=3.0.41
|
|
21
21
|
Requires-Dist: PyMySQL~=1.1.2
|
|
22
22
|
Requires-Dist: sqlparse<0.6.0,>=0.3.0
|
|
23
|
-
Requires-Dist: sqlglot~=30.
|
|
24
|
-
Requires-Dist: sqlglotc~=30.
|
|
23
|
+
Requires-Dist: sqlglot~=30.12.0
|
|
24
|
+
Requires-Dist: sqlglotc~=30.12.0
|
|
25
25
|
Requires-Dist: configobj~=5.0.9
|
|
26
|
-
Requires-Dist: cli_helpers[styles]~=2.15.
|
|
27
|
-
Requires-Dist: wcwidth~=0.
|
|
26
|
+
Requires-Dist: cli_helpers[styles]~=2.15.1
|
|
27
|
+
Requires-Dist: wcwidth~=0.8.2
|
|
28
28
|
Requires-Dist: pyperclip~=1.11.0
|
|
29
29
|
Requires-Dist: pycryptodomex~=3.23.0
|
|
30
30
|
Requires-Dist: pyfzf~=0.3.1
|
|
@@ -32,10 +32,9 @@ Requires-Dist: rapidfuzz~=3.14.3
|
|
|
32
32
|
Requires-Dist: keyring~=25.7.0
|
|
33
33
|
Requires-Dist: yaspin~=3.4.0
|
|
34
34
|
Provides-Extra: llm
|
|
35
|
-
Requires-Dist: llm~=0.
|
|
36
|
-
Requires-Dist:
|
|
37
|
-
Requires-Dist:
|
|
38
|
-
Requires-Dist: pip==26.*; extra == "llm"
|
|
35
|
+
Requires-Dist: llm~=0.31.1; extra == "llm"
|
|
36
|
+
Requires-Dist: setuptools==83.*; extra == "llm"
|
|
37
|
+
Requires-Dist: pip~=26.1.2; extra == "llm"
|
|
39
38
|
Provides-Extra: dataframe
|
|
40
39
|
Requires-Dist: polars~=1.42.1; extra == "dataframe"
|
|
41
40
|
Requires-Dist: altair~=6.2.2; extra == "dataframe"
|
|
@@ -45,21 +44,14 @@ Requires-Dist: mycli[dataframe,llm]; extra == "all"
|
|
|
45
44
|
Provides-Extra: dev
|
|
46
45
|
Requires-Dist: behave~=1.3.3; extra == "dev"
|
|
47
46
|
Requires-Dist: coverage~=7.13.4; extra == "dev"
|
|
48
|
-
Requires-Dist: mypy~=
|
|
47
|
+
Requires-Dist: mypy~=2.3.0; extra == "dev"
|
|
49
48
|
Requires-Dist: pexpect~=4.9.0; extra == "dev"
|
|
50
|
-
Requires-Dist: pytest~=9.
|
|
49
|
+
Requires-Dist: pytest~=9.1.1; extra == "dev"
|
|
51
50
|
Requires-Dist: pytest-cov~=7.0.0; extra == "dev"
|
|
52
51
|
Requires-Dist: pytest-random-order~=1.2.0; extra == "dev"
|
|
53
52
|
Requires-Dist: tox~=4.35.0; extra == "dev"
|
|
54
53
|
Requires-Dist: pdbpp~=0.11.7; extra == "dev"
|
|
55
|
-
Requires-Dist: llm~=0.30.0; extra == "dev"
|
|
56
|
-
Requires-Dist: pydantic_core~=2.41.5; extra == "dev"
|
|
57
|
-
Requires-Dist: setuptools==82.*; extra == "dev"
|
|
58
|
-
Requires-Dist: pip==26.*; extra == "dev"
|
|
59
54
|
Requires-Dist: ruff~=0.15.0; extra == "dev"
|
|
60
|
-
Requires-Dist: polars~=1.42.1; extra == "dev"
|
|
61
|
-
Requires-Dist: altair~=6.2.2; extra == "dev"
|
|
62
|
-
Requires-Dist: vl-convert-python~=1.9.0; extra == "dev"
|
|
63
55
|
Dynamic: license-file
|
|
64
56
|
|
|
65
57
|
# mycli
|
|
@@ -1,3 +1,42 @@
|
|
|
1
|
+
2.7.0 (2026/07/25)
|
|
2
|
+
==============
|
|
3
|
+
|
|
4
|
+
Features
|
|
5
|
+
---------
|
|
6
|
+
* Show purpose in tabular `--checkup` output.
|
|
7
|
+
* Add optional dependencies to `--checkup`.
|
|
8
|
+
* Improve completions for `/command`s.
|
|
9
|
+
* Highlight indexed columns in completions with a suffix and/or a text style.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
Bugfixes
|
|
13
|
+
---------
|
|
14
|
+
* Ignoring `min_completion_trigger` only applies to first token after `/`.
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
Documentation
|
|
18
|
+
---------
|
|
19
|
+
* Add `.|` and `.>` to TIPS.
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
Internal
|
|
23
|
+
---------
|
|
24
|
+
* Update `cli_helpers` dependency to v2.15.1
|
|
25
|
+
* Update `click` to v8.4.2
|
|
26
|
+
* Update `cryptography` to v49.0.0
|
|
27
|
+
* Update `pygments` to v2.20.0
|
|
28
|
+
* Update `llm` to v0.31.1
|
|
29
|
+
* Update `setuptools` to v83.x
|
|
30
|
+
* Update `pip` to v26.1.2
|
|
31
|
+
* Update `pytest` to v9.1.1
|
|
32
|
+
* Add dependency cooldown period
|
|
33
|
+
* Exclude `cli_helpers` and `openai` from cooldown
|
|
34
|
+
* Update `sqlglot`/`sqlglotc` to v30.12.0
|
|
35
|
+
* Update `wcwidth` to v0.8.2
|
|
36
|
+
* Remove duplication in dev dependencies.
|
|
37
|
+
* Update `mypy` to v2.3.0.
|
|
38
|
+
|
|
39
|
+
|
|
1
40
|
2.6.1 (2026/07/24)
|
|
2
41
|
==============
|
|
3
42
|
|
|
@@ -144,6 +144,8 @@ display output in an interactive explorer \x at the end of a query!
|
|
|
144
144
|
|
|
145
145
|
run SQL scripts in batch mode using the standard input!
|
|
146
146
|
|
|
147
|
+
indexed columns are tagged with a "*" in completion menus!
|
|
148
|
+
|
|
147
149
|
###
|
|
148
150
|
### keystrokes
|
|
149
151
|
###
|
|
@@ -301,3 +303,11 @@ redirect query output to a CSV file with "$> <filename>"!
|
|
|
301
303
|
append query output to a CSV file with "$>> <filename>"!
|
|
302
304
|
|
|
303
305
|
run a command after shell redirects with "post_redirect_command" in ~/.myclirc!
|
|
306
|
+
|
|
307
|
+
###
|
|
308
|
+
### transforms
|
|
309
|
+
###
|
|
310
|
+
|
|
311
|
+
transform or plot query output with a dataframe using ".| df"!
|
|
312
|
+
|
|
313
|
+
save query output to a Parquet file with ".> output.parquet"!
|
|
@@ -183,6 +183,7 @@ class MyCli(AppStateMixin, OutputMixin, ClientCommandsMixin, ClientConnectionMix
|
|
|
183
183
|
self.initialize_logging()
|
|
184
184
|
|
|
185
185
|
keyword_casing = c["main"].get("keyword_casing", "auto")
|
|
186
|
+
indexed_column_suffix = c['main'].get('indexed_column_suffix', '')
|
|
186
187
|
|
|
187
188
|
self.highlight_preview = c['search'].as_bool('highlight_preview')
|
|
188
189
|
|
|
@@ -191,7 +192,10 @@ class MyCli(AppStateMixin, OutputMixin, ClientCommandsMixin, ClientConnectionMix
|
|
|
191
192
|
# Initialize completer.
|
|
192
193
|
self.smart_completion = c["main"].as_bool("smart_completion")
|
|
193
194
|
self.completer = SQLCompleter(
|
|
194
|
-
self.smart_completion,
|
|
195
|
+
self.smart_completion,
|
|
196
|
+
supported_formats=self.main_formatter.supported_formats,
|
|
197
|
+
keyword_casing=keyword_casing,
|
|
198
|
+
indexed_column_suffix=indexed_column_suffix,
|
|
195
199
|
)
|
|
196
200
|
self._completer_lock = threading.Lock()
|
|
197
201
|
|
|
@@ -52,6 +52,7 @@ class ClientQueryMixin:
|
|
|
52
52
|
"smart_completion": self.smart_completion,
|
|
53
53
|
"supported_formats": self.main_formatter.supported_formats,
|
|
54
54
|
"keyword_casing": self.completer.keyword_casing,
|
|
55
|
+
"indexed_column_suffix": self.completer.indexed_column_suffix,
|
|
55
56
|
},
|
|
56
57
|
)
|
|
57
58
|
|
|
@@ -15,6 +15,7 @@ logger = logging.getLogger(__name__)
|
|
|
15
15
|
TOKEN_TO_PROMPT_STYLE: dict[Token, str] = {
|
|
16
16
|
Token.Menu.Completions.Completion.Current: "completion-menu.completion.current",
|
|
17
17
|
Token.Menu.Completions.Completion: "completion-menu.completion",
|
|
18
|
+
Token.Menu.Completions.Completion.Indexed: "completion-menu.completion.indexed",
|
|
18
19
|
Token.Menu.Completions.Meta.Current: "completion-menu.meta.completion.current",
|
|
19
20
|
Token.Menu.Completions.Meta: "completion-menu.meta.completion",
|
|
20
21
|
Token.Menu.Completions.MultiColumnMeta: "completion-menu.multi-column-meta",
|
|
@@ -167,6 +167,11 @@ def refresh_tables(completer: SQLCompleter, executor: SQLExecute) -> None:
|
|
|
167
167
|
completer.extend_columns(table_columns_dbresult, kind="tables")
|
|
168
168
|
|
|
169
169
|
|
|
170
|
+
@refresher("indexed_columns")
|
|
171
|
+
def refresh_indexed_columns(completer: SQLCompleter, executor: SQLExecute) -> None:
|
|
172
|
+
completer.extend_indexed_columns(executor.indexed_columns())
|
|
173
|
+
|
|
174
|
+
|
|
170
175
|
@refresher("foreign_keys")
|
|
171
176
|
def refresh_foreign_keys(completer: SQLCompleter, executor: SQLExecute) -> None:
|
|
172
177
|
completer.extend_foreign_keys(executor.foreign_keys())
|
|
@@ -6,6 +6,8 @@ import sys
|
|
|
6
6
|
import urllib.error
|
|
7
7
|
import urllib.request
|
|
8
8
|
|
|
9
|
+
from tabulate import tabulate
|
|
10
|
+
|
|
9
11
|
from mycli.constants import REPO_URL
|
|
10
12
|
|
|
11
13
|
PYPI_API_BASE = 'https://pypi.org/pypi'
|
|
@@ -24,15 +26,20 @@ def pypi_api_fetch(fragment: str) -> dict:
|
|
|
24
26
|
|
|
25
27
|
def _dependencies_checkup() -> None:
|
|
26
28
|
print('\n### Key Python dependencies:\n')
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
'
|
|
30
|
-
'
|
|
31
|
-
'
|
|
32
|
-
'
|
|
33
|
-
'
|
|
34
|
-
'
|
|
35
|
-
'
|
|
29
|
+
table = []
|
|
30
|
+
for dependency, purpose in [
|
|
31
|
+
('cli_helpers', 'required'),
|
|
32
|
+
('click', 'required'),
|
|
33
|
+
('prompt_toolkit', 'required'),
|
|
34
|
+
('pygments', 'required'),
|
|
35
|
+
('pymysql', 'required'),
|
|
36
|
+
('sqlglot', 'required'),
|
|
37
|
+
('sqlglotc', 'required'),
|
|
38
|
+
('tabulate', 'required'),
|
|
39
|
+
('llm', 'optional for /llm command'),
|
|
40
|
+
('polars', 'optional for .| operator'),
|
|
41
|
+
('altair', 'optional for .| operator'),
|
|
42
|
+
('vl-convert-python', 'optional for .| operator'),
|
|
36
43
|
]:
|
|
37
44
|
try:
|
|
38
45
|
installed_version = importlib.metadata.version(dependency)
|
|
@@ -40,32 +47,38 @@ def _dependencies_checkup() -> None:
|
|
|
40
47
|
installed_version = None
|
|
41
48
|
pypi_profile = pypi_api_fetch(f'/{dependency}/json')
|
|
42
49
|
latest_version = pypi_profile.get('info', {}).get('version', None)
|
|
43
|
-
|
|
50
|
+
table.append([dependency, installed_version, latest_version, purpose])
|
|
51
|
+
print(tabulate(table, headers=['library', 'version', 'latest', 'purpose']))
|
|
44
52
|
|
|
45
53
|
|
|
46
54
|
def _executables_checkup() -> None:
|
|
47
55
|
print('\n### External executables:\n')
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
'
|
|
51
|
-
'
|
|
56
|
+
table = []
|
|
57
|
+
for executable, purpose in [
|
|
58
|
+
('less', 'required for paging'),
|
|
59
|
+
('fzf', r'optional for history search and \x'),
|
|
60
|
+
('pygmentize', 'optional for history search'),
|
|
52
61
|
]:
|
|
62
|
+
# executable, purpose = external
|
|
53
63
|
if shutil.which(executable):
|
|
54
|
-
|
|
64
|
+
table.append([executable, 'found', purpose])
|
|
55
65
|
else:
|
|
56
|
-
|
|
66
|
+
table.append([executable, 'MISSING', purpose])
|
|
67
|
+
print(tabulate(table, headers=['executable', 'status', 'purpose']))
|
|
57
68
|
|
|
58
69
|
|
|
59
70
|
def _environment_checkup() -> None:
|
|
60
71
|
print('\n### Environment variables:\n')
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
'
|
|
72
|
+
table = []
|
|
73
|
+
for variable, purpose in [
|
|
74
|
+
('EDITOR', r'optional for \edit and C-x C-e'),
|
|
75
|
+
('VISUAL', r'optional for \edit and C-x C-e'),
|
|
64
76
|
]:
|
|
65
77
|
if value := os.environ.get(variable):
|
|
66
|
-
|
|
78
|
+
table.append([f'${variable}', value, purpose])
|
|
67
79
|
else:
|
|
68
|
-
|
|
80
|
+
table.append([f'${variable}', 'UNSET', purpose])
|
|
81
|
+
print(tabulate(table, headers=['variable', 'setting', 'purpose']))
|
|
69
82
|
|
|
70
83
|
|
|
71
84
|
def _configuration_checkup(mycli) -> None:
|
|
@@ -112,7 +112,7 @@ def complete_while_typing_filter() -> bool:
|
|
|
112
112
|
return True
|
|
113
113
|
app = get_app()
|
|
114
114
|
text = app.current_buffer.text.lstrip()
|
|
115
|
-
if text.startswith('/') and not text.startswith('/*'):
|
|
115
|
+
if text.startswith('/') and not text.startswith('/*') and ' ' not in text:
|
|
116
116
|
return True
|
|
117
117
|
text_len = len(text)
|
|
118
118
|
if text_len < MIN_COMPLETION_TRIGGER:
|
|
@@ -9,6 +9,12 @@ show_warnings = False
|
|
|
9
9
|
# possible completions will be listed.
|
|
10
10
|
smart_completion = True
|
|
11
11
|
|
|
12
|
+
# Text appended to indexed column names in the completion menu. This text is
|
|
13
|
+
# not inserted into the query. Leave empty to disable the marker. Quote values
|
|
14
|
+
# containing spaces, commas, or comment characters.
|
|
15
|
+
# Alternative: ' [indexed]'
|
|
16
|
+
indexed_column_suffix = *
|
|
17
|
+
|
|
12
18
|
# Minimum characters typed before offering completion suggestions. Forward
|
|
13
19
|
# slash for a command is an exception which always offers completions.
|
|
14
20
|
# Suggestion: 3.
|
|
@@ -411,6 +417,7 @@ default_username_field = username
|
|
|
411
417
|
# Completion menus
|
|
412
418
|
completion-menu.completion.current = 'bg:#ffffff #000000'
|
|
413
419
|
completion-menu.completion = 'bg:#008888 #ffffff'
|
|
420
|
+
completion-menu.completion.indexed = 'bg:#008888 #ffffff'
|
|
414
421
|
completion-menu.meta.completion.current = 'bg:#44aaaa #000000'
|
|
415
422
|
completion-menu.meta.completion = 'bg:#448888 #ffffff'
|
|
416
423
|
completion-menu.multi-column-meta = 'bg:#aaffff #000000'
|
|
@@ -71,6 +71,10 @@ def _keyword_suggestions() -> list[Suggestion]:
|
|
|
71
71
|
return [{'type': 'keyword'}]
|
|
72
72
|
|
|
73
73
|
|
|
74
|
+
def _special_suggestions() -> list[Suggestion]:
|
|
75
|
+
return [{'type': 'special'}]
|
|
76
|
+
|
|
77
|
+
|
|
74
78
|
def _keyword_and_special_suggestions() -> list[Suggestion]:
|
|
75
79
|
return [{'type': 'keyword'}, {'type': 'special'}]
|
|
76
80
|
|
|
@@ -144,8 +148,11 @@ def _emit_none_token(_ctx: SuggestContext) -> list[Suggestion]:
|
|
|
144
148
|
return _keyword_suggestions()
|
|
145
149
|
|
|
146
150
|
|
|
147
|
-
def _emit_blank_token(
|
|
148
|
-
|
|
151
|
+
def _emit_blank_token(ctx: SuggestContext) -> list[Suggestion]:
|
|
152
|
+
if ctx.text_before_cursor.startswith('/'):
|
|
153
|
+
return _special_suggestions()
|
|
154
|
+
else:
|
|
155
|
+
return _keyword_and_special_suggestions()
|
|
149
156
|
|
|
150
157
|
|
|
151
158
|
def _emit_star(_ctx: SuggestContext) -> list[Suggestion]:
|
|
@@ -793,7 +800,8 @@ def suggest_special(text: str) -> list[dict[str, Any]]:
|
|
|
793
800
|
{"type": "view", "schema": []},
|
|
794
801
|
{"type": "schema"},
|
|
795
802
|
]
|
|
796
|
-
|
|
803
|
+
|
|
804
|
+
if cmd.lower() in [
|
|
797
805
|
r'\.',
|
|
798
806
|
r'/.',
|
|
799
807
|
'source',
|
|
@@ -806,14 +814,16 @@ def suggest_special(text: str) -> list[dict[str, Any]]:
|
|
|
806
814
|
'/tee',
|
|
807
815
|
]:
|
|
808
816
|
return [{"type": "file_name"}]
|
|
817
|
+
|
|
809
818
|
# todo: why is \edit case-sensitive?
|
|
810
|
-
|
|
819
|
+
if cmd in [
|
|
811
820
|
r'\e',
|
|
812
821
|
'/e',
|
|
813
822
|
r'\edit',
|
|
814
823
|
'/edit',
|
|
815
824
|
]:
|
|
816
825
|
return [{"type": "file_name"}]
|
|
826
|
+
|
|
817
827
|
if cmd in ["\\llm", "/llm", "\\ai", "/ai"]:
|
|
818
828
|
return [{"type": "llm"}]
|
|
819
829
|
|
|
@@ -828,7 +838,17 @@ def suggest_special(text: str) -> list[dict[str, Any]]:
|
|
|
828
838
|
return []
|
|
829
839
|
return [{'type': 'special_subcommand', 'subcommands': list(DSN_SUBCOMMANDS)}]
|
|
830
840
|
|
|
831
|
-
|
|
841
|
+
if cmd.lower() in [
|
|
842
|
+
'help',
|
|
843
|
+
'/help',
|
|
844
|
+
r'\help',
|
|
845
|
+
'?',
|
|
846
|
+
'/?',
|
|
847
|
+
r'\?',
|
|
848
|
+
]:
|
|
849
|
+
return [{"type": "keyword"}, {"type": "special"}]
|
|
850
|
+
|
|
851
|
+
return []
|
|
832
852
|
|
|
833
853
|
|
|
834
854
|
def suggest_based_on_last_token(
|
|
@@ -98,7 +98,7 @@ def is_show_warnings_enabled() -> bool:
|
|
|
98
98
|
'warnings',
|
|
99
99
|
'/warnings',
|
|
100
100
|
'Enable automatic warnings display.',
|
|
101
|
-
arg_type=ArgType.
|
|
101
|
+
arg_type=ArgType.NO_ARGUMENT,
|
|
102
102
|
case_sensitive=True,
|
|
103
103
|
aliases=[SpecialCommandAlias('\\W', case_sensitive=True)],
|
|
104
104
|
)
|
|
@@ -113,7 +113,7 @@ def enable_show_warnings() -> Generator[SQLResult, None, None]:
|
|
|
113
113
|
'nowarnings',
|
|
114
114
|
'/nowarnings',
|
|
115
115
|
'Disable automatic warnings display.',
|
|
116
|
-
arg_type=ArgType.
|
|
116
|
+
arg_type=ArgType.NO_ARGUMENT,
|
|
117
117
|
case_sensitive=True,
|
|
118
118
|
aliases=[SpecialCommandAlias('\\w', case_sensitive=True)],
|
|
119
119
|
)
|
|
@@ -152,7 +152,7 @@ def set_pager(arg: str, **_) -> list[SQLResult]:
|
|
|
152
152
|
"nopager",
|
|
153
153
|
"/nopager",
|
|
154
154
|
"Disable pager; print to stdout.",
|
|
155
|
-
arg_type=ArgType.
|
|
155
|
+
arg_type=ArgType.NO_ARGUMENT,
|
|
156
156
|
case_sensitive=True,
|
|
157
157
|
aliases=[SpecialCommandAlias("\\n", case_sensitive=True)],
|
|
158
158
|
)
|
|
@@ -165,7 +165,7 @@ def disable_pager() -> list[SQLResult]:
|
|
|
165
165
|
"\\timing",
|
|
166
166
|
"/timing",
|
|
167
167
|
"Toggle timing of queries.",
|
|
168
|
-
arg_type=ArgType.
|
|
168
|
+
arg_type=ArgType.NO_ARGUMENT,
|
|
169
169
|
case_sensitive=True,
|
|
170
170
|
aliases=[SpecialCommandAlias("\\t", case_sensitive=True)],
|
|
171
171
|
)
|
|
@@ -27,7 +27,7 @@ CASE_INSENSITIVE_COMMANDS: set[str] = set()
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
class ArgType(Enum):
|
|
30
|
-
|
|
30
|
+
NO_ARGUMENT = 0
|
|
31
31
|
PARSED_QUERY = 1
|
|
32
32
|
RAW_QUERY = 2
|
|
33
33
|
|
|
@@ -205,7 +205,7 @@ def execute(cur: Cursor, sql: str) -> list[SQLResult]:
|
|
|
205
205
|
if command.lower().startswith(("help", "/help", "\\?", "/?", "?")) and arg:
|
|
206
206
|
return show_keyword_help(cur=cur, arg=arg)
|
|
207
207
|
|
|
208
|
-
if special_cmd.arg_type == ArgType.
|
|
208
|
+
if special_cmd.arg_type == ArgType.NO_ARGUMENT:
|
|
209
209
|
return special_cmd.handler()
|
|
210
210
|
elif special_cmd.arg_type == ArgType.PARSED_QUERY:
|
|
211
211
|
return special_cmd.handler(cur=cur, arg=arg, command_verbosity=(command_verbosity == CommandVerbosity.VERBOSE))
|
|
@@ -219,7 +219,7 @@ def execute(cur: Cursor, sql: str) -> list[SQLResult]:
|
|
|
219
219
|
"help",
|
|
220
220
|
"/help [term]",
|
|
221
221
|
"Show this table, or search for help on a term.",
|
|
222
|
-
arg_type=ArgType.
|
|
222
|
+
arg_type=ArgType.NO_ARGUMENT,
|
|
223
223
|
aliases=[SpecialCommandAlias("\\?", case_sensitive=False), SpecialCommandAlias("?", case_sensitive=False)],
|
|
224
224
|
)
|
|
225
225
|
def show_help(*_args) -> list[SQLResult]:
|
|
@@ -283,7 +283,7 @@ def show_keyword_help(cur: Cursor, arg: str) -> list[SQLResult]:
|
|
|
283
283
|
return _show_mysql_help(cur, keyword)
|
|
284
284
|
|
|
285
285
|
|
|
286
|
-
@special_command('\\bug', '/bug', 'File a bug on GitHub.', arg_type=ArgType.
|
|
286
|
+
@special_command('\\bug', '/bug', 'File a bug on GitHub.', arg_type=ArgType.NO_ARGUMENT)
|
|
287
287
|
def file_bug(*_args) -> list[SQLResult]:
|
|
288
288
|
webbrowser.open_new_tab(ISSUES_URL)
|
|
289
289
|
return [SQLResult(status=f'{ISSUES_URL} — press "New Issue"')]
|
|
@@ -293,14 +293,14 @@ def file_bug(*_args) -> list[SQLResult]:
|
|
|
293
293
|
"exit",
|
|
294
294
|
"/exit",
|
|
295
295
|
"Exit.",
|
|
296
|
-
arg_type=ArgType.
|
|
296
|
+
arg_type=ArgType.NO_ARGUMENT,
|
|
297
297
|
aliases=[SpecialCommandAlias("\\q", case_sensitive=False)],
|
|
298
298
|
)
|
|
299
299
|
@special_command(
|
|
300
300
|
"quit",
|
|
301
301
|
"/quit",
|
|
302
302
|
"Quit.",
|
|
303
|
-
arg_type=ArgType.
|
|
303
|
+
arg_type=ArgType.NO_ARGUMENT,
|
|
304
304
|
aliases=[SpecialCommandAlias("\\q", case_sensitive=False)],
|
|
305
305
|
)
|
|
306
306
|
def quit_(*_args):
|
|
@@ -311,7 +311,7 @@ def quit_(*_args):
|
|
|
311
311
|
"\\edit",
|
|
312
312
|
"/edit <filename> | <query>\\edit",
|
|
313
313
|
"Edit query with editor (uses $VISUAL or $EDITOR).",
|
|
314
|
-
arg_type=ArgType.
|
|
314
|
+
arg_type=ArgType.NO_ARGUMENT,
|
|
315
315
|
case_sensitive=True,
|
|
316
316
|
aliases=[SpecialCommandAlias("\\e", case_sensitive=True)],
|
|
317
317
|
)
|
|
@@ -319,14 +319,14 @@ def quit_(*_args):
|
|
|
319
319
|
"\\clip",
|
|
320
320
|
"/clip | <query>\\clip",
|
|
321
321
|
"Copy query to the system clipboard.",
|
|
322
|
-
arg_type=ArgType.
|
|
322
|
+
arg_type=ArgType.NO_ARGUMENT,
|
|
323
323
|
case_sensitive=True,
|
|
324
324
|
)
|
|
325
325
|
@special_command(
|
|
326
326
|
"\\G",
|
|
327
327
|
"<query>\\G",
|
|
328
328
|
"Display query results vertically.",
|
|
329
|
-
arg_type=ArgType.
|
|
329
|
+
arg_type=ArgType.NO_ARGUMENT,
|
|
330
330
|
case_sensitive=True,
|
|
331
331
|
backslash_only=True,
|
|
332
332
|
)
|
|
@@ -334,7 +334,7 @@ def quit_(*_args):
|
|
|
334
334
|
"\\g",
|
|
335
335
|
"<query>\\g",
|
|
336
336
|
"Display query results (mnemonic: go).",
|
|
337
|
-
arg_type=ArgType.
|
|
337
|
+
arg_type=ArgType.NO_ARGUMENT,
|
|
338
338
|
case_sensitive=True,
|
|
339
339
|
backslash_only=True,
|
|
340
340
|
)
|
|
@@ -342,7 +342,7 @@ def quit_(*_args):
|
|
|
342
342
|
"\\x",
|
|
343
343
|
"<query>\\x",
|
|
344
344
|
"Display query results in an explorer rather than a pager.",
|
|
345
|
-
arg_type=ArgType.
|
|
345
|
+
arg_type=ArgType.NO_ARGUMENT,
|
|
346
346
|
case_sensitive=True,
|
|
347
347
|
backslash_only=True,
|
|
348
348
|
)
|
|
@@ -174,6 +174,7 @@ class SchemaPrefetcher:
|
|
|
174
174
|
def _prefetch_one(self, executor: SQLExecute, schema: str) -> None:
|
|
175
175
|
_logger.debug('prefetching schema %r', schema)
|
|
176
176
|
table_rows = list(executor.table_columns(schema=schema))
|
|
177
|
+
indexed_rows = list(executor.indexed_columns(schema=schema))
|
|
177
178
|
fk_rows = list(executor.foreign_keys(schema=schema))
|
|
178
179
|
enum_rows = list(executor.enum_values(schema=schema))
|
|
179
180
|
func_rows = list(executor.functions(schema=schema))
|
|
@@ -189,6 +190,12 @@ class SchemaPrefetcher:
|
|
|
189
190
|
cols = table_columns.setdefault(esc_table, ['*'])
|
|
190
191
|
cols.append(esc_col)
|
|
191
192
|
|
|
193
|
+
indexed_columns: dict[str, set[str]] = {}
|
|
194
|
+
for table, column in indexed_rows:
|
|
195
|
+
esc_table = completer.escape_name(table)
|
|
196
|
+
esc_col = completer.escape_name(column)
|
|
197
|
+
indexed_columns.setdefault(esc_table, set()).add(esc_col)
|
|
198
|
+
|
|
192
199
|
fk_tables: dict[str, set[str]] = {}
|
|
193
200
|
fk_relations: list[tuple[str, str, str, str]] = []
|
|
194
201
|
for table, col, ref_table, ref_col in fk_rows:
|
|
@@ -224,6 +231,7 @@ class SchemaPrefetcher:
|
|
|
224
231
|
live_completer.load_schema_metadata(
|
|
225
232
|
schema=schema,
|
|
226
233
|
table_columns=table_columns,
|
|
234
|
+
indexed_columns=indexed_columns,
|
|
227
235
|
foreign_keys=fk_payload,
|
|
228
236
|
enum_values=enum_values,
|
|
229
237
|
functions=functions,
|