execsql2 2.29.0__tar.gz → 2.30.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.
- execsql2-2.30.0/.github/ISSUE_TEMPLATE/bug_report.yml +57 -0
- execsql2-2.30.0/.github/ISSUE_TEMPLATE/feature_request.yml +28 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/.github/workflows/ci-cd.yml +3 -21
- {execsql2-2.29.0 → execsql2-2.30.0}/CHANGELOG.md +30 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/PKG-INFO +2 -4
- {execsql2-2.29.0 → execsql2-2.30.0}/README.md +1 -1
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/about/divergence.md +11 -11
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/api/index.md +1 -1
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/dev/architecture.md +73 -36
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/getting-started/syntax.md +3 -3
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/guides/editors.md +57 -9
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/guides/examples.md +20 -10
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/guides/formatter.md +2 -2
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/guides/sql_syntax.md +4 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/guides/usage.md +2 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/reference/configuration.md +6 -2
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/reference/lint.md +3 -1
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/reference/metacommands.md +36 -15
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/reference/security.md +4 -2
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/reference/substitution_vars.md +4 -1
- {execsql2-2.29.0 → execsql2-2.30.0}/extras/vscode-execsql/README.md +14 -10
- {execsql2-2.29.0 → execsql2-2.30.0}/extras/vscode-execsql/extension.js +71 -25
- {execsql2-2.29.0 → execsql2-2.30.0}/extras/vscode-execsql/package.json +22 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/extras/vscode-execsql/syntaxes/execsql.tmLanguage.json +1 -1
- {execsql2-2.29.0 → execsql2-2.30.0}/justfile +2 -2
- {execsql2-2.29.0 → execsql2-2.30.0}/pyproject.toml +2 -4
- {execsql2-2.29.0 → execsql2-2.30.0}/scripts/generate_vscode_grammar.py +1 -26
- execsql2-2.30.0/src/execsql/__main__.py +12 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/api.py +5 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/cli/__init__.py +3 -14
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/cli/application.py +5 -3
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/cli/commands/lint.py +4 -1
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/cli/commands/lsp.py +42 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/cli/dsn.py +3 -1
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/cli/lint.py +14 -6
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/cli/run.py +17 -9
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/config.py +32 -6
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/db/duckdb.py +96 -14
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/gui/__init__.py +3 -31
- execsql2-2.30.0/src/execsql/lsp/_util.py +21 -0
- execsql2-2.30.0/src/execsql/lsp/cache.py +73 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/lsp/code_actions.py +10 -14
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/lsp/completion.py +8 -15
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/lsp/diagnostics.py +14 -2
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/lsp/document.py +139 -41
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/lsp/hover.py +5 -13
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/lsp/navigation.py +7 -10
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/lsp/server.py +111 -29
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/manifest.py +29 -9
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/metacommands/__init__.py +0 -2
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/metacommands/io_fileops.py +5 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/script/executor.py +2 -21
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/state.py +6 -3
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/state.pyi +2 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/utils/errors.py +19 -36
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/utils/fileio.py +44 -48
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/utils/regex.py +0 -5
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/cli/test_cli.py +13 -18
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/cli/test_cli_e2e.py +0 -33
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/cli/test_cli_run.py +0 -27
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/cli/test_cli_surface.py +1 -1
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/cli/test_commands.py +3 -1
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/cli/test_dispatch.py +20 -2
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/cli/test_lint.py +20 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/cli/test_manifest.py +23 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_duckdb.py +65 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_transactions.py +0 -1
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/conftest.py +0 -9
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_exporters.py +1 -1
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_ods_export.py +1 -1
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_roundtrip_values.py +0 -5
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_xlsx.py +1 -1
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/gui/test_backends.py +0 -64
- execsql2-2.30.0/tests/lsp/test_cache.py +130 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/lsp/test_document.py +7 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/lsp/test_server.py +264 -15
- execsql2-2.30.0/tests/metacommands/conftest.py +22 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/metacommands/test_metacommands.py +6 -46
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/metacommands/test_metacommands_extended.py +0 -7
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/metacommands/test_metacommands_script_ext.py +0 -4
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/metacommands/test_row_count.py +3 -31
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/security/test_env_detection.py +2 -2
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/security/test_log_redaction.py +1 -1
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/security/test_log_secrets.py +48 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_api_isolation.py +28 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_config_data.py +50 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_executor_inprocess.py +0 -8
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_reference.py +1 -1
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_registry.py +5 -5
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_state.py +1 -1
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_tooling_versions.py +10 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/utils/test_errors.py +21 -36
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/utils/test_errors_extra.py +17 -15
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/utils/test_fileio.py +0 -20
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/utils/test_fileio_extra.py +1 -9
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/utils/test_regex.py +0 -25
- {execsql2-2.29.0 → execsql2-2.30.0}/uv.lock +1 -140
- execsql2-2.29.0/.github/ISSUE_TEMPLATE/bug_report.md +0 -40
- execsql2-2.29.0/.github/ISSUE_TEMPLATE/feature_request.md +0 -19
- execsql2-2.29.0/docs/images/connect.b64 +0 -1
- execsql2-2.29.0/docs/images/create_conf.png +0 -0
- execsql2-2.29.0/docs/images/entry_form.png +0 -0
- execsql2-2.29.0/docs/images/execsql_console.png +0 -0
- execsql2-2.29.0/docs/images/logo_small.png +0 -0
- execsql2-2.29.0/docs/images/pause_terminal.png +0 -0
- execsql2-2.29.0/docs/images/pause_terminal_sm.b64 +0 -1
- execsql2-2.29.0/docs/images/prompt_compare.png +0 -0
- execsql2-2.29.0/docs/images/unit_conversions.b64 +0 -1
- execsql2-2.29.0/src/execsql/__main__.py +0 -13
- {execsql2-2.29.0 → execsql2-2.30.0}/.github/dependabot.yml +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/.gitignore +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/.pre-commit-config.yaml +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/.pre-commit-hooks.yaml +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/.python-version +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/.readthedocs.yaml +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/CONTRIBUTING.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/LICENSE.txt +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/NOTICE +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/SECURITY.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/about/contributors.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/about/copyright.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/api/cli.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/api/db.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/api/exporters.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/api/importers.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/api/metacommands.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/dev/adding_db_adapters.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/dev/adding_exporters.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/dev/adding_importers.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/dev/adding_metacommands.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/dev/releasing.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/getting-started/installation.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/getting-started/requirements.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/guides/debugging.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/guides/documentation.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/guides/encoding.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/guides/logging.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/guides/using_scripts.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/images/Compare_planets.png +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/images/actions.png +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/images/actions2.png +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/images/checkboxes.png +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/images/connect.png +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/images/data_error1_screenshot.jpg +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/images/execsql_logo_01.png +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/images/fatals.png +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/images/pause_terminal_sm.png +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/images/set_build_commands.jpg +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/images/unit_conversions_029.png +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/images/unmatched.png +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/images/vim_execsql_highlight.png +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/docs/index.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/extras/plugin-template/README.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/extras/plugin-template/pyproject.toml +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/extras/plugin-template/src/execsql_plugin_YOURNAME/__init__.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/extras/plugin-template/tests/test_plugin.py.example +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/extras/vscode-execsql/.vscodeignore +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/extras/vscode-execsql/LICENSE.txt +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/extras/vscode-execsql/icon.png +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/extras/vscode-execsql/package-lock.json +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/scripts/benchmarks/README.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/scripts/benchmarks/results/.gitignore +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/scripts/benchmarks/run_benchmarks.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/__init__.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/cli/commands/__init__.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/cli/commands/config.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/cli/commands/format.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/cli/commands/init.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/cli/commands/listing.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/cli/commands/run.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/cli/dispatch.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/cli/help.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/cli/options.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/config_validation.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/data/__init__.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/data/execsql.conf.template +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/data/script_header.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/db/__init__.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/db/access.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/db/base.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/db/dsn.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/db/factory.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/db/firebird.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/db/mysql.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/db/oracle.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/db/postgres.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/db/sqlite.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/db/sqlserver.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/db/tiers.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/debug/__init__.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/debug/repl.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/exceptions.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/exporters/__init__.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/exporters/base.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/exporters/delimited.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/exporters/duckdb.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/exporters/feather.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/exporters/html.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/exporters/json.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/exporters/latex.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/exporters/markdown.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/exporters/ods.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/exporters/parquet.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/exporters/pretty.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/exporters/protocol.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/exporters/raw.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/exporters/sqlite.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/exporters/templates.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/exporters/values.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/exporters/xls.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/exporters/xlsx.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/exporters/xml.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/exporters/yaml.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/exporters/zip.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/format.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/gui/base.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/gui/console.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/gui/desktop.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/gui/tui.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/importers/__init__.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/importers/base.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/importers/csv.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/importers/feather.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/importers/json.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/importers/ods.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/importers/xls.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/interactive.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/lsp/__init__.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/lsp/folding.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/lsp/formatting.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/lsp/rename.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/metacommands/conditions.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/metacommands/connect.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/metacommands/control.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/metacommands/data.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/metacommands/debug.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/metacommands/dispatch.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/metacommands/effects.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/metacommands/io.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/metacommands/io_export.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/metacommands/io_import.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/metacommands/io_write.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/metacommands/prompt.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/metacommands/reference.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/metacommands/script_ext.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/metacommands/system.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/metacommands/upsert.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/models.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/parser.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/plugins.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/py.typed +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/script/__init__.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/script/ast.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/script/control.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/script/engine.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/script/parser.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/script/variables.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/types.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/utils/__init__.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/utils/auth.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/utils/color.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/utils/crypto.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/utils/datetime.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/utils/gui.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/utils/mail.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/utils/numeric.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/utils/strings.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/src/execsql/utils/timer.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/templates/README.md +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/templates/config_settings.sqlite +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/templates/example_config_prompt.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/templates/make_config_db.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/templates/md_compare.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/templates/md_glossary.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/templates/md_upsert.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/templates/pg_compare.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/templates/pg_glossary.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/templates/pg_upsert.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/templates/script_template.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/templates/ss_compare.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/templates/ss_glossary.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/templates/ss_upsert.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/__init__.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/cli/__init__.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/cli/test_config_validate.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/cli/test_error_location.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/cli/test_init.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/cli/test_lint_fixtures.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/cli/test_log_exit_record.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/cli/test_ping.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/cli/test_profile.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/cli/test_sigterm.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/cli/test_undeclared_imports.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/conftest.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/data/formatter_shapes/comment_anchoring.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/data/formatter_shapes/escapes_and_literals.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/data/formatter_shapes/substitution_and_metacommands.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/data/formatter_shapes/unparsable_sql.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/data/lint/conditions_and_blocks.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/data/lint/does_not_parse.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/data/lint/every_metacommand.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/data/lint/invalid.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/__init__.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_access_windows.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_base.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_copy_new.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_db_adapters_mocked.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_db_adapters_mocked_extra.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_dsn.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_factory.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_factory_postgres_encoding.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_import_atomic.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_import_replacement_quoted.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_import_short_rows.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_import_timezones.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_mysql_case_folding.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_mysql_inprocess.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_new_table_checks.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_oracle_driver.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_postgres.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_postgres_inprocess.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_quoted_substitution_roundtrip.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_roundtrip_adapters.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_sqlite.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_sqlite_extra.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_sqlserver_inprocess.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/db/test_tiers.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/__init__.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_base.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_db.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_delimited.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_duckdb_exporter.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_feather.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_html_extended.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_html_latex.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_json.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_json_extended.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_latex_extended.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_markdown.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_ods.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_parquet.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_pretty_extended.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_raw_extended.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_roundtrip_columnar.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_roundtrip_dbfile.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_roundtrip_delimited.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_roundtrip_json.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_roundtrip_latex_xml.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_roundtrip_markup.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_roundtrip_ods.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_roundtrip_pretty_raw.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_roundtrip_template.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_roundtrip_xlsx.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_sqlite_exporter.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_templates.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_templates_extended.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_values_extended.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_xls_xlsx.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_xml.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_yaml.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/exporters/test_zip.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/gui/__init__.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/gui/test_backends_extended.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/gui/test_compare_stats.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/gui/test_compute_row_diffs.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/gui/test_desktop_dialogs.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/gui/test_format_table.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/gui/test_tui_pilot.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/gui/test_tui_pilot_complex.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/gui/test_utils_gui_extended.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/importers/__init__.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/importers/conftest.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/importers/test_base_extended.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/importers/test_csv_blank_lines.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/importers/test_csv_edge_cases.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/importers/test_csv_importer.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/importers/test_feather_importer.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/importers/test_json_importer.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/importers/test_ods_importer.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/importers/test_roundtrip_csv.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/importers/test_xls_importer.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/integration/__init__.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/integration/conftest.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/integration/test_dsn.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/integration/test_duckdb.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/integration/test_mysql.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/integration/test_postgres.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/integration/test_sqlite.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/live_db.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/lsp/__init__.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/lsp/test_code_actions.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/lsp/test_completion.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/lsp/test_diagnostics.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/lsp/test_folding.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/lsp/test_formatting.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/lsp/test_hover.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/lsp/test_lsp_command.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/lsp/test_navigation.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/lsp/test_rename.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/metacommands/__init__.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/metacommands/test_assert.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/metacommands/test_breakpoint.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/metacommands/test_conditions_extra.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/metacommands/test_connect.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/metacommands/test_io_export.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/metacommands/test_io_import.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/metacommands/test_metacommands_connect.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/metacommands/test_metacommands_data.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/metacommands/test_metacommands_fileops_extra.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/metacommands/test_metacommands_io.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/metacommands/test_metacommands_io_write_extra.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/metacommands/test_metacommands_system.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/metacommands/test_metacommands_system_extra.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/metacommands/test_pg_upsert.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/metacommands/test_prompt.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/metacommands/test_show_scripts.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/__init__.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/audit_lint_bad.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/audit_smoke/sample.json +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/audit_smoke/sample.jsonl +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/audit_smoke.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/config_runtime.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/control_flow.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/counters_and_locals.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/error_handling.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/import_options/has_comments.csv +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/import_options.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/includes/helper.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/includes.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/io_formats.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/io_roundtrip.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/multi_db.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/parquet_feather_roundtrip.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/parse_only/parse_tree.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/predicates.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/scripts.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/smoke.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/subroutine_loops.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/subvars_advanced.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/template_export/greeting.tmpl +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/template_export.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/timer.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/transactions.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/write_create_table.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/fixtures/xlsx_ods_roundtrip.sql +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/scripts/test_sql_scripts.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/security/__init__.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/security/test_expansion_bomb.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/security/test_import_regex_hardening.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/security/test_odbc_injection.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/security/test_path_containment.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/security/test_substitution_injection.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/security/test_zip_bomb.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_api.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_api_errors.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_api_extended.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_api_filewriter.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_api_subprocess.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_ast.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_ast_parser.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_bundled_templates.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_config.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_config_extended.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_date_inference.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_debug_repl.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_engine.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_error_messages.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_exceptions.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_executor.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_format.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_interactive.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_mail.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_models.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_package.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_parser.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_parser_params.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_plugins.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_script.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/test_types.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/utils/__init__.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/utils/test_auth.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/utils/test_auth_extra.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/utils/test_crypto.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/utils/test_datetime.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/utils/test_encodedfile_context.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/utils/test_keyring_rules.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/utils/test_mail_tls.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/utils/test_numeric.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/utils/test_strings.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/utils/test_timer.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/tests/utils/test_timer_extra.py +0 -0
- {execsql2-2.29.0 → execsql2-2.30.0}/zensical.toml +0 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Something execsql does wrong, from the command line, the library, or an editor.
|
|
3
|
+
labels: [bug]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: what
|
|
7
|
+
attributes:
|
|
8
|
+
label: What happened
|
|
9
|
+
description: What you ran, what you expected, and what happened instead.
|
|
10
|
+
placeholder: |
|
|
11
|
+
`execsql run load.sql prod.db -t l` stopped at line 12 with ...
|
|
12
|
+
I expected ...
|
|
13
|
+
validations:
|
|
14
|
+
required: true
|
|
15
|
+
- type: textarea
|
|
16
|
+
id: script
|
|
17
|
+
attributes:
|
|
18
|
+
label: A script that shows it
|
|
19
|
+
description: The smallest script that reproduces the problem, if you can share one. Leave out data and credentials.
|
|
20
|
+
render: sql
|
|
21
|
+
- type: textarea
|
|
22
|
+
id: output
|
|
23
|
+
attributes:
|
|
24
|
+
label: Error output
|
|
25
|
+
description: The full message or traceback, and the end of `execsql.log` if the run wrote one.
|
|
26
|
+
render: text
|
|
27
|
+
- type: input
|
|
28
|
+
id: version
|
|
29
|
+
attributes:
|
|
30
|
+
label: execsql version
|
|
31
|
+
description: The output of `execsql --version`.
|
|
32
|
+
placeholder: execsql 2.30.0
|
|
33
|
+
validations:
|
|
34
|
+
required: true
|
|
35
|
+
- type: input
|
|
36
|
+
id: install
|
|
37
|
+
attributes:
|
|
38
|
+
label: How execsql is installed
|
|
39
|
+
description: The command, with its extras.
|
|
40
|
+
placeholder: uv tool install "execsql2[postgres,lsp]"
|
|
41
|
+
validations:
|
|
42
|
+
required: true
|
|
43
|
+
- type: input
|
|
44
|
+
id: environment
|
|
45
|
+
attributes:
|
|
46
|
+
label: Operating system, Python and database
|
|
47
|
+
placeholder: macOS 15, Python 3.12, PostgreSQL 16
|
|
48
|
+
validations:
|
|
49
|
+
required: true
|
|
50
|
+
- type: textarea
|
|
51
|
+
id: editor
|
|
52
|
+
attributes:
|
|
53
|
+
label: Editor and language server (only for a problem in an editor)
|
|
54
|
+
description: |
|
|
55
|
+
The editor and the execsql extension's version, the output of `execsql lsp --check`, and the server's log
|
|
56
|
+
at `info` (VS Code: View → Output → execsql). See https://execsql2.readthedocs.io/en/latest/guides/editors/#troubleshooting
|
|
57
|
+
render: text
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: A new feature, metacommand or option, or a change to how something works.
|
|
3
|
+
labels: [enhancement]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: problem
|
|
7
|
+
attributes:
|
|
8
|
+
label: The problem
|
|
9
|
+
description: What you are trying to do, and what gets in the way today.
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: proposal
|
|
14
|
+
attributes:
|
|
15
|
+
label: What you would like
|
|
16
|
+
description: For a new metacommand or CLI option, the syntax you would expect.
|
|
17
|
+
placeholder: "-- !x! NEW_METACOMMAND ..."
|
|
18
|
+
validations:
|
|
19
|
+
required: true
|
|
20
|
+
- type: textarea
|
|
21
|
+
id: alternatives
|
|
22
|
+
attributes:
|
|
23
|
+
label: Alternatives and workarounds
|
|
24
|
+
description: What you tried instead, if anything.
|
|
25
|
+
- type: textarea
|
|
26
|
+
id: context
|
|
27
|
+
attributes:
|
|
28
|
+
label: Anything else
|
|
@@ -51,25 +51,6 @@ jobs:
|
|
|
51
51
|
- run: uv sync --locked --all-extras
|
|
52
52
|
- run: uv run --no-sync mypy src/execsql/
|
|
53
53
|
|
|
54
|
-
formatter-corpus:
|
|
55
|
-
name: formatter-corpus
|
|
56
|
-
runs-on: ubuntu-latest
|
|
57
|
-
permissions:
|
|
58
|
-
contents: read
|
|
59
|
-
steps:
|
|
60
|
-
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
61
|
-
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
62
|
-
with:
|
|
63
|
-
python-version: "3.13"
|
|
64
|
-
cache: "pip"
|
|
65
|
-
- run: python -m pip install --upgrade pip
|
|
66
|
-
- run: python -m pip install ".[dev]"
|
|
67
|
-
# Every formatter bug to date came from real SQL containing a
|
|
68
|
-
# construct the project's own scripts lack. This gate runs those
|
|
69
|
-
# checks under their own name so a corpus failure is legible
|
|
70
|
-
# without reading a 6,000-test log.
|
|
71
|
-
- run: pytest tests/test_format.py -k corpus --no-cov -q
|
|
72
|
-
|
|
73
54
|
typer-floor:
|
|
74
55
|
name: typer-floor
|
|
75
56
|
runs-on: ubuntu-latest
|
|
@@ -155,7 +136,8 @@ jobs:
|
|
|
155
136
|
- run: python -m pip install --upgrade pip
|
|
156
137
|
- run: python -m pip install ".[dev]"
|
|
157
138
|
- run: cp CHANGELOG.md docs/about/change_log.md
|
|
158
|
-
|
|
139
|
+
# --strict: a warning, such as a link to an #anchor that does not exist, fails the job.
|
|
140
|
+
- run: zensical build --strict
|
|
159
141
|
|
|
160
142
|
tests:
|
|
161
143
|
strategy:
|
|
@@ -369,7 +351,7 @@ jobs:
|
|
|
369
351
|
build:
|
|
370
352
|
name: Build distribution 📦
|
|
371
353
|
runs-on: ubuntu-latest
|
|
372
|
-
needs: [ lint, typecheck, pre-commit,
|
|
354
|
+
needs: [ lint, typecheck, pre-commit, typer-floor, docs, tests, integration-tests, vscode-extension ]
|
|
373
355
|
# Deliberately NOT gated on tags: packaging breaks must surface on a PR,
|
|
374
356
|
# not at release time. Only publish/generate-release below are tag-gated.
|
|
375
357
|
permissions:
|
|
@@ -13,6 +13,36 @@ ______________________________________________________________________
|
|
|
13
13
|
|
|
14
14
|
______________________________________________________________________
|
|
15
15
|
|
|
16
|
+
## [2.30.0] - 2026-10-14
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- **`execsql lsp --log-level` and `--log-file`** (or `EXECSQL_LSP_LOG_LEVEL`): at `info` the server logs its version, the Python running it, whether the formatter is installed, the workspace folders and the config files each folder read; `debug` adds every protocol message. See [Troubleshooting](https://execsql2.readthedocs.io/en/latest/guides/editors/#troubleshooting) for what to include in a bug report.
|
|
21
|
+
- **VS Code extension:** the **execsql** Output channel shows the server's log (setting `execsql.server.logLevel`, default `info`) and why the server did not start; `execsql.trace.server` traces the protocol there.
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- **`execsql lint` checks every file** when one has an `INCLUDE` path the operating system rejects (such as a name too long for it): that file gets an I001 finding instead of the whole run stopping with "Uncaught exception", and a script lint cannot check at all is reported as one P001 error.
|
|
26
|
+
- **The language server shows "execsql could not check this script"** when checking a script fails unexpectedly, instead of keeping its old findings; hover, completion and navigation keep working for a script with such an `INCLUDE`.
|
|
27
|
+
- **The language server answers quickly in a script with many or large `INCLUDE`s:** completion, hover, go-to-definition and the other features no longer reread and reparse every included file on each request (50 included 3,000-line files: about 0.55 s per keystroke before, under 20 ms now). A changed included file is read again.
|
|
28
|
+
- **The language server lints less after a save:** saving a script, or a change to a `.sql` file on disk, lints again only the open scripts that `INCLUDE` that file, once, instead of every open script two or three times.
|
|
29
|
+
- **`execsql --help` shows each command's whole summary**, wrapped to the terminal, instead of cutting it off with `...` on a narrow one.
|
|
30
|
+
- **DuckDB temporary tables last for the whole run:** a table created with `CREATE TEMPORARY TABLE` is visible to the statements and metacommands after it (`INSERT`, `EXPORT`, `COPY`, conditions); before, it was gone by the next statement.
|
|
31
|
+
- **A `--dsn` / `dsn=` value without a scheme** (`//user:password@host/db`) is reported with its password as `***` instead of in full.
|
|
32
|
+
- **`--manifest` masks passwords and tokens:** a password, `SUB_DECRYPT` result or token (a URL's password, `password=...`, an API key) that reaches a file path, connection target or error message is written as `***`. `-a` and `--var` values are still written where a path uses them.
|
|
33
|
+
- **A registered secret no longer reaches `execsql.log` through a `HALT MESSAGE`** (the `exit` record of a halted run), an exported file name (`action` records) or a connection name (`connect` records); these now show `***` like every other log record.
|
|
34
|
+
- **`execsql.run()` returns the caller to their working directory** after a script that ran `CD`, including when the script fails; before, the caller was left in the script's last directory.
|
|
35
|
+
- **Language server settings for a workspace folder added after the first folder was deleted** are read; before, every later settings reload failed and the folder linted with stale rules. An unsaved script's relative `INCLUDE` resolves against the workspace root.
|
|
36
|
+
- **VS Code extension:** after `CONFIG`, only options `CONFIG` accepts are highlighted; config-file-only keys such as `DB_FILE`, `CONSOLE_HEIGHT` or `CSS_FILE` (which `CONFIG` rejects) no longer look valid.
|
|
37
|
+
- **VS Code extension:** turning `execsql.server.enabled` on or off, or changing `execsql.server.path`, takes effect without reloading the window; **execsql: Restart Language Server** works (and says so) when the server is off, and two quick restarts no longer leave a second server running.
|
|
38
|
+
|
|
39
|
+
### Removed
|
|
40
|
+
|
|
41
|
+
- **Unused helpers:** `execsql.gui.get_backend()` (the GUI picks its backend in `enable_gui()`), `ins_quoted_rx()` (re-exported from `execsql.metacommands`; nothing built a metacommand with it) `execsql.utils.errors.exception_info()` (use `exception_desc()`), and the `execsql.cli.main` re-export (the run command's own module, `execsql.cli.commands.run`, keeps it).
|
|
42
|
+
- **`execsql.utils.fileio`:** `filewriter_closeall()`, `filewriter_shutdown()` and `list_encodings()`, which nothing called; use `filewriter_end()` to stop a writer and `execsql list encodings` for the encodings. `FileWriter.ping()` is gone too.
|
|
43
|
+
|
|
44
|
+
______________________________________________________________________
|
|
45
|
+
|
|
16
46
|
## [2.29.0] - 2026-10-13
|
|
17
47
|
|
|
18
48
|
### Changed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: execsql2
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.30.0
|
|
4
4
|
Summary: Runs a SQL script against a PostgreSQL, SQLite, MariaDB/MySQL, DuckDB, Firebird, MS-Access, MS-SQL-Server, or Oracle database, or an ODBC DSN. Provides metacommands to import and export data, copy data between databases, conditionally execute SQL and metacommands, and dynamically alter SQL and metacommands with substitution variables.
|
|
5
5
|
Project-URL: Homepage, https://execsql2.readthedocs.io
|
|
6
6
|
Project-URL: Repository, https://github.com/geocoug/execsql
|
|
@@ -83,7 +83,6 @@ Provides-Extra: auth-plaintext
|
|
|
83
83
|
Requires-Dist: keyring>=25.0; extra == 'auth-plaintext'
|
|
84
84
|
Requires-Dist: keyrings-alt>=5.0; extra == 'auth-plaintext'
|
|
85
85
|
Provides-Extra: dev
|
|
86
|
-
Requires-Dist: build>=1.2.2.post1; extra == 'dev'
|
|
87
86
|
Requires-Dist: bump-my-version>=1.2.7; extra == 'dev'
|
|
88
87
|
Requires-Dist: defusedxml>=0.7; extra == 'dev'
|
|
89
88
|
Requires-Dist: jinja2>=3.1; extra == 'dev'
|
|
@@ -104,7 +103,6 @@ Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
|
104
103
|
Requires-Dist: sqlglot<30.22,>=30.21.0; extra == 'dev'
|
|
105
104
|
Requires-Dist: tables>=3.10; extra == 'dev'
|
|
106
105
|
Requires-Dist: tox-uv>=1.13.1; extra == 'dev'
|
|
107
|
-
Requires-Dist: twine>=6.1.0; extra == 'dev'
|
|
108
106
|
Requires-Dist: xlrd>=2.0; extra == 'dev'
|
|
109
107
|
Requires-Dist: zensical==0.0.67; extra == 'dev'
|
|
110
108
|
Provides-Extra: duckdb
|
|
@@ -466,7 +464,7 @@ execsql format --no-sql --in-place scripts/
|
|
|
466
464
|
```yaml
|
|
467
465
|
repos:
|
|
468
466
|
- repo: https://github.com/geocoug/execsql
|
|
469
|
-
rev: v2.
|
|
467
|
+
rev: v2.30.0
|
|
470
468
|
hooks:
|
|
471
469
|
- id: execsql-format
|
|
472
470
|
- id: execsql-lint
|
|
@@ -28,7 +28,7 @@ ______________________________________________________________________
|
|
|
28
28
|
| `--dry-run` | Parse the script and print the full command list without connecting to a database or executing anything. Substitution variables already populated at parse time (env vars, `--assign-arg` values, built-in start-time vars) are expanded in the output; execution-time variables (`$DB_NAME`, `$CURRENT_TIME`, etc.) remain unexpanded. |
|
|
29
29
|
| `--profile` | Record wall-clock time for each SQL and metacommand statement. After the script completes, print a summary table sorted by elapsed time (descending), showing time, percentage of total, source location, command type, and a command preview. |
|
|
30
30
|
| `--profile-limit N` | Number of top statements to display in the `--profile` summary (default: 20). Remaining statements are counted and noted in the output footer. |
|
|
31
|
-
| `--manifest FILE` | Write a JSON record of the run when it ends, even on failure: script, database, statement counts, files read, written and deleted (paths after substitution), connections, errors. Variable values
|
|
31
|
+
| `--manifest FILE` | Write a JSON record of the run when it ends, even on failure: script, database, statement counts, files read, written and deleted (paths after substitution), connections, errors. Variable values are never listed; passwords, decrypted values and token shapes are masked as `***` wherever they appear. |
|
|
32
32
|
| `--ping` | Test database connectivity and exit. Connects using the supplied connection parameters, queries for the server version, and prints a one-line success message (exit 0) or the error (exit 1). No script file argument is required. |
|
|
33
33
|
| `--lint` | Removed. Replaced by `execsql lint`, which takes files and directories and adds rule selection and JSON output. `execsql run --lint` now exits 2 with `run --lint was removed; use execsql lint` and never runs the script. |
|
|
34
34
|
| `--parse-tree` | Parse the script into an Abstract Syntax Tree and print a visual tree showing block nesting (IF/LOOP/BATCH/SCRIPT), source line ranges, compound conditions (ANDIF/ORIF), and all metacommands. Does not connect to a database or execute anything. Useful for understanding script structure and verifying the parser handles a script correctly. |
|
|
@@ -205,7 +205,7 @@ result = run(
|
|
|
205
205
|
result.raise_on_error()
|
|
206
206
|
```
|
|
207
207
|
|
|
208
|
-
Accepts `dsn=` or a pre-built `connection=` `Database` object. Each call runs in its own thread-local `RuntimeContext` with its own file-writer thread, so concurrent calls from different threads are safe and a halt in one does not stop another's file output. `halt_on_error=False` collects errors instead of raising.
|
|
208
|
+
Accepts `dsn=` or a pre-built `connection=` `Database` object. Each call runs in its own thread-local `RuntimeContext` with its own file-writer thread, so concurrent calls from different threads are safe and a halt in one does not stop another's file output. `halt_on_error=False` collects errors instead of raising. A script's `CD` lasts until `run()` returns, which then changes back to the caller's directory.
|
|
209
209
|
|
|
210
210
|
______________________________________________________________________
|
|
211
211
|
|
|
@@ -267,7 +267,8 @@ All 33 mutable runtime globals in `state.py` have been consolidated into a `Runt
|
|
|
267
267
|
- **DuckDB temporal types** — `TIMESTAMPTZ`, `TIMESTAMP`, `DATE`, `TIME` now map to native DuckDB types instead of `TEXT`.
|
|
268
268
|
- **SQLite `DT_Long` mapping** — `DT_Long` maps to `"hugeint"` in the SQLite type table. SQLite does not have a native `HUGEINT` type; the value receives `TEXT` affinity. In practice this is harmless because SQLite's type affinity system handles large integers transparently, but the mapping name differs from upstream.
|
|
269
269
|
- **`Database.auto_commits_ddl()` not provided** — 2.18.0 shipped this capability hook on the base `Database` class with `True` overrides on Oracle, MySQL, SQL Server, and MS Access. No call site ever consumed the hook, so 2.19.0 removed it. Its replacement is `Database.implicit_commit_rx`: MySQL and Oracle name the statements their server commits on its own (DDL), and a warning is written when one runs while `AUTOCOMMIT` is `OFF` or a batch is open. SQL Server holds DDL in a transaction like any other statement. (The companion hook `Database.needs_explicit_commit_after_ddl()`, used by the Firebird import path, remains.)
|
|
270
|
-
- **Statements are held until commit on every adapter** — while `AUTOCOMMIT` is `OFF` or a batch is open, `Database.before_statement()` makes sure each statement is inside a transaction. Most drivers already opened one; SQLite's (Python's `sqlite3`) opened one only before `INSERT`/`UPDATE`/`DELETE`/`REPLACE`, and DuckDB's never did, so upstream committed SQLite DDL, and every DuckDB statement, at once. SQLite now begins a transaction before other statements (except `VACUUM`, `ATTACH`, `DETACH`, `PRAGMA`); DuckDB begins one itself
|
|
270
|
+
- **Statements are held until commit on every adapter** — while `AUTOCOMMIT` is `OFF` or a batch is open, `Database.before_statement()` makes sure each statement is inside a transaction. Most drivers already opened one; SQLite's (Python's `sqlite3`) opened one only before `INSERT`/`UPDATE`/`DELETE`/`REPLACE`, and DuckDB's never did, so upstream committed SQLite DDL, and every DuckDB statement, at once. SQLite now begins a transaction before other statements (except `VACUUM`, `ATTACH`, `DETACH`, `PRAGMA`); DuckDB begins one itself and tracks it.
|
|
271
|
+
- **DuckDB statements share one connection** — a DuckDB cursor is a separate connection with its own transaction and its own temporary tables, and upstream ran each statement on a new cursor, so a `CREATE TEMPORARY TABLE` was gone by the next statement and a held transaction did not cover them. Every statement now runs on the database's one connection. That connection holds one result at a time, so when a statement runs while another query's rows are still being read (`COPY` scans its source while reading it), the unread rows are fetched into memory first; an `EXPORT` still streams.
|
|
271
272
|
- **DuckDB `$LAST_ROWCOUNT`** — the duckdb driver's `rowcount` is always `-1`; DuckDB answers an `INSERT`, `UPDATE` or `DELETE` with a one-column `Count` result instead. The DuckDB adapter reads that result, so `$LAST_ROWCOUNT` holds the rows changed, as on the other adapters. Upstream set it to `-1`.
|
|
272
273
|
|
|
273
274
|
### Execution Engine
|
|
@@ -279,7 +280,6 @@ The legacy flat command-list engine (`_parse_script_lines` / `runscripts` / `Com
|
|
|
279
280
|
- **BREAK outside LOOP is an error** — `BREAK` outside a loop block now raises an error (exit 1) instead of being silently ignored. This catches script bugs that upstream would not report.
|
|
280
281
|
- **File writer is a thread, one per run** — `WRITE`, `TEE` and the other text-file metacommands hand their output to a background thread owned by the run's `RuntimeContext`, which `execsql.run()` stops before returning. Upstream uses one `multiprocessing` subprocess for the whole program; under the `spawn` start method (macOS, Windows) that re-imported the calling program, so a library caller without an `if __name__ == "__main__":` guard ran its script twice.
|
|
281
282
|
- **Instance-scoped script registry** — Named SCRIPT blocks are stored on the `RuntimeContext` instance instead of a module-level dict, preventing cross-execution contamination.
|
|
282
|
-
- **Script source directory resolution** — `ScriptCmd` resolves `source_dir` at construction time (when the command is parsed) rather than per-statement at execution time. This is functionally equivalent for all normal usage since the script file does not move between parse and execution.
|
|
283
283
|
|
|
284
284
|
### Error Handling
|
|
285
285
|
|
|
@@ -322,13 +322,13 @@ These are behavioral changes driven by security or correctness issues in the ups
|
|
|
322
322
|
|
|
323
323
|
### Credential and Logging Safety
|
|
324
324
|
|
|
325
|
-
| Area | Fix
|
|
326
|
-
| ----------------------------- |
|
|
327
|
-
| ODBC password redaction | Connection strings in log output have `Pwd=***` substituted before logging.
|
|
328
|
-
| `enc_password` documentation | Prominent warnings that XOR encryption is obfuscation only — keys are hardcoded in source.
|
|
329
|
-
| Env-var secret denylist | Extended `_SENSITIVE_SUBSTRINGS` to cover mainstream cloud / payment / observability / VCS conventions (`*_KEY`, `APIKEY`, `API_KEY`, `DSN`, `WEBHOOK`). `-a` positional assignment log lines now redact unconditionally (`{***}` instead of the raw value).
|
|
330
|
-
| Secrets registered at source | The `run` record lists a count of `-a` values instead of the values (upstream wrote them in clear). DSN and SMTP passwords, prompted and keyring database passwords, `PROMPT ENTER_SUB ... PASSWORD` and `PROMPT CREDENTIALS` values, and `SUB_DECRYPT` results are registered for redaction, so SQL logged with `LOG_SQL ON`, `SYSTEM_CMD` echoes
|
|
331
|
-
| SMTP certificate verification | `EMAIL` over `use_ssl` or `use_tls` verifies the server certificate (upstream accepted any certificate, so the SMTP password could go to an impostor). New `[email]` settings: `ca_file` to trust an internal CA, `verify_certificate = No` to turn the check off.
|
|
325
|
+
| Area | Fix |
|
|
326
|
+
| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
327
|
+
| ODBC password redaction | Connection strings in log output have `Pwd=***` substituted before logging. |
|
|
328
|
+
| `enc_password` documentation | Prominent warnings that XOR encryption is obfuscation only — keys are hardcoded in source. |
|
|
329
|
+
| Env-var secret denylist | Extended `_SENSITIVE_SUBSTRINGS` to cover mainstream cloud / payment / observability / VCS conventions (`*_KEY`, `APIKEY`, `API_KEY`, `DSN`, `WEBHOOK`). `-a` positional assignment log lines now redact unconditionally (`{***}` instead of the raw value). |
|
|
330
|
+
| Secrets registered at source | The `run` record lists a count of `-a` values instead of the values (upstream wrote them in clear). DSN and SMTP passwords, prompted and keyring database passwords, `PROMPT ENTER_SUB ... PASSWORD` and `PROMPT CREDENTIALS` values, and `SUB_DECRYPT` results are registered for redaction, so SQL logged with `LOG_SQL ON`, `SYSTEM_CMD` echoes, error messages, the `exit` record (including a `HALT MESSAGE`), `action` export records and `connect` records show `***`. |
|
|
331
|
+
| SMTP certificate verification | `EMAIL` over `use_ssl` or `use_tls` verifies the server certificate (upstream accepted any certificate, so the SMTP password could go to an impostor). New `[email]` settings: `ca_file` to trust an internal CA, `verify_certificate = No` to turn the check off. |
|
|
332
332
|
|
|
333
333
|
### Bug Fixes
|
|
334
334
|
|
|
@@ -80,7 +80,7 @@ Each run has its own [file writer](#file-output), so two runs writing files at t
|
|
|
80
80
|
|
|
81
81
|
Three things are still shared by every thread in the process, so keep them apart yourself:
|
|
82
82
|
|
|
83
|
-
- **The working directory.** `CD` calls `os.chdir()`, which moves every thread. Use absolute paths in scripts that run concurrently, or don't use `CD` in them.
|
|
83
|
+
- **The working directory.** `CD` calls `os.chdir()`, which moves every thread while the script runs. Use absolute paths in scripts that run concurrently, or don't use `CD` in them. When a script that ran `CD` finishes, `run()` changes back to the directory it was in before that `CD`, so the caller ends where it started; a run without `CD` leaves the directory as it finds it.
|
|
84
84
|
- **The same output file.** Two runs writing one file at the same time can interleave their lines. Give each run its own output paths.
|
|
85
85
|
- **Interactive prompts.** `PROMPT` and the other GUI metacommands are not meant to be driven from several threads at once.
|
|
86
86
|
|
|
@@ -56,6 +56,8 @@ flowchart LR
|
|
|
56
56
|
UTILS["utils/<br/>auth, crypto,<br/>fileio, mail,<br/>regex, strings"]
|
|
57
57
|
PARSER["parser.py<br/>CondParser,<br/>NumericParser"]
|
|
58
58
|
DEBUG["debug/<br/>REPL debugger"]
|
|
59
|
+
LSP["lsp/<br/>execsql lsp,<br/>editor features"]
|
|
60
|
+
REF["metacommands/<br/>reference.py<br/>syntax registry"]
|
|
59
61
|
|
|
60
62
|
CLI --> CONFIG
|
|
61
63
|
CLI --> STATE
|
|
@@ -75,35 +77,66 @@ flowchart LR
|
|
|
75
77
|
EXPORT --> STATE
|
|
76
78
|
GUI --> STATE
|
|
77
79
|
SCRIPT --> PARSER
|
|
80
|
+
CLI --> LSP
|
|
81
|
+
LSP --> SCRIPT
|
|
82
|
+
LSP --> REF
|
|
83
|
+
LSP --> CLI
|
|
78
84
|
```
|
|
79
85
|
|
|
80
86
|
### Package summary
|
|
81
87
|
|
|
82
|
-
| Package
|
|
83
|
-
|
|
|
84
|
-
| `cli/`
|
|
85
|
-
| `api.py`
|
|
86
|
-
| `config.py`
|
|
87
|
-
| `state.py`
|
|
88
|
-
| `script/`
|
|
89
|
-
| `metacommands/`
|
|
90
|
-
| `db/`
|
|
91
|
-
| `exporters/`
|
|
92
|
-
| `importers/`
|
|
93
|
-
| `gui/`
|
|
94
|
-
| `utils/`
|
|
95
|
-
| `parser.py`
|
|
96
|
-
| `types.py`
|
|
97
|
-
| `models.py`
|
|
98
|
-
| `format.py`
|
|
99
|
-
| `exceptions.py`
|
|
100
|
-
| `plugins.py`
|
|
101
|
-
| `debug/`
|
|
102
|
-
| `interactive.py`
|
|
103
|
-
| `
|
|
88
|
+
| Package | Purpose |
|
|
89
|
+
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
90
|
+
| `cli/` | Typer app and help rendering, one module per command under `cli/commands/`, shared options, `_run()` orchestration, DSN URL parsing |
|
|
91
|
+
| `api.py` | Public `execsql.run()` Python entry point for notebooks, pipelines, and library use |
|
|
92
|
+
| `config.py` | `ConfigData` (INI merging), `StatObj` (runtime flags), `WriteHooks` (stdout/stderr redirection) |
|
|
93
|
+
| `state.py` | Thread-local runtime store — all shared mutable state lives here, isolated per-thread |
|
|
94
|
+
| `script/` | AST node types, parser, `MetaCommandList`, `SubVarSet`, `BatchLevels`, `ScriptExecSpec`, `set_system_vars()` |
|
|
95
|
+
| `metacommands/` | `build_dispatch_table()`, all `x_*` handlers, `build_conditional_table()`, all `xf_*` predicates |
|
|
96
|
+
| `db/` | `Database` ABC, `DatabasePool`, 9 adapter modules (postgres, sqlite, duckdb, mysql, sqlserver, oracle, firebird, access, dsn) |
|
|
97
|
+
| `exporters/` | `ExportRecord`, `ExportMetadata`, `WriteSpec`, 20+ format writers (CSV, JSON, XML, HTML, etc.) |
|
|
98
|
+
| `importers/` | `CsvFile`, `OdsFile`, `XlsFile`, `FeatherFile` — data import backends |
|
|
99
|
+
| `gui/` | `GuiBackend` ABC, `TkinterBackend`, `TextualBackend`, `ConsoleBackend` |
|
|
100
|
+
| `utils/` | Shared utilities: file I/O, encryption, mail, regex helpers, string manipulation, timers |
|
|
101
|
+
| `parser.py` | Recursive-descent parsers for conditional (`IF`) and arithmetic (`SET`) expressions |
|
|
102
|
+
| `types.py` | `DataType` subclasses and `DbType` per-DBMS type dialect mappings |
|
|
103
|
+
| `models.py` | `Column`, `DataTable`, `JsonDatatype` |
|
|
104
|
+
| `format.py` | `execsql format` formatter — opinionated formatter for execsql scripts |
|
|
105
|
+
| `exceptions.py` | `ExecSqlError` base, `ErrInfo`, `ConfigError`, `DataTypeError`, `DbTypeError`, etc. |
|
|
106
|
+
| `plugins.py` | Entry-point plugin discovery for metacommands, exporters, and importers |
|
|
107
|
+
| `debug/` | Interactive REPL debugger for stepping through script execution |
|
|
108
|
+
| `interactive.py` | Engine behind the debug REPL: input typed at a BREAKPOINT runs as the next lines of the paused script via `executor.execute_input`; errors return to the prompt |
|
|
109
|
+
| `lsp/` | `execsql lsp`, the language server editors start (pygls 2): diagnostics, completion, hover, navigation, rename, folding, quick fixes, Format Document. See [Language Server](#language-server) |
|
|
110
|
+
| `manifest.py` | `RunManifest`: the JSON record `--manifest FILE` writes when a run ends (script, database, statements, files read/written/deleted, connections, outcome) |
|
|
111
|
+
| `config_validation.py` | `execsql config --validate`: reads the same config files as a run and reports every problem with its file and line |
|
|
112
|
+
| `data/` | Bundled package data (`execsql.conf.template` powers `execsql config --init`) |
|
|
104
113
|
|
|
105
114
|
______________________________________________________________________
|
|
106
115
|
|
|
116
|
+
## Language Server { #language-server }
|
|
117
|
+
|
|
118
|
+
`execsql lsp` (`cli/commands/lsp.py` → `lsp/server.py:create_server()`) is a pygls 2 server on stdin/stdout. It never runs a script or connects to a database: it reuses the static tools.
|
|
119
|
+
|
|
120
|
+
| Module | Feature | Reuses |
|
|
121
|
+
| ------------------------------------------ | ------------------------------------------------------- | ------------------------------------------------------------------ |
|
|
122
|
+
| `server.py` | handlers, settings, debounced lint, watched files | `cli.run._tool_config` |
|
|
123
|
+
| `diagnostics.py` | lint findings as LSP diagnostics | `cli.lint.lint_source` |
|
|
124
|
+
| `document.py` | `ScriptIndex`: definitions, references, `INCLUDE` graph | `script.parser`, `cli.lint.variables_defined_by` |
|
|
125
|
+
| `cache.py` | each text's `FileFacts`, included files' text | `document` |
|
|
126
|
+
| `_util.py` | `span()`, `markdown()`, the metacommand-line regex | `lsprotocol` |
|
|
127
|
+
| `completion.py`, `hover.py` | completion and hover | `metacommands.reference` |
|
|
128
|
+
| `navigation.py`, `rename.py`, `folding.py` | definition, references, outline, links, rename, folding | `ScriptIndex`, the parser |
|
|
129
|
+
| `code_actions.py` | quick fixes for P002, P003, P004, V001 | the dispatch table (each fix is re-validated before it is offered) |
|
|
130
|
+
| `formatting.py` | Format Document | `format.format_file` with the `[format]` settings |
|
|
131
|
+
|
|
132
|
+
**Settings per workspace folder.** `ConfigData(start_dir=...)` (through `_tool_config(None, start_dir=folder)`) reads config as a run started in that directory would: its `execsql.conf`, and relative `config_file` chains resolved against it. `load_settings()` reads each folder's `[lint]` / `[format]` settings that way and keeps them by folder; a document uses its innermost folder's settings, a document in no folder those of the workspace root (`base_dir()`, or the server's working directory when there is no root or it is gone). The server never changes its working directory. An unsaved script's relative `INCLUDE` resolves against `base_dir()` too, for both lint (`lint_source(base_dir=...)`) and the index.
|
|
133
|
+
|
|
134
|
+
**Index lifetime.** A `ScriptIndex` is assembled on every request that needs one (hover, completion, definition, references, rename, links, code actions) from per-file `FileFacts`: what one file defines, calls, includes and refers to, independent of the files it includes. `lsp/cache.py` keeps each text's facts and each included file's text (by path, size and modification time, dropped when the client reports the file changed), so a request reparses only the edited buffer; a file with a `SUB_INI` is reparsed every time, since its INI file can change on its own. `INCLUDE`d files are read too (the editor's unsaved copy when the file is open), up to 200 files, 10 MiB each and 20 MiB together, regular files only; `SUB_INI` files at most 1 MiB, cached by path, size and modification time.
|
|
135
|
+
|
|
136
|
+
**Linting.** On open, and 200 ms after the last edit (`LINT_DELAY_SECONDS`), lint runs on the document and the result is published with the document's version. A change to a watched `**/execsql.conf` reloads the settings and relints every open document. Saving a script, or a change to a watched `**/*.sql`, relints only the open documents that are that file or `INCLUDE` it directly: lint reads no included file's text, it only checks that each exists. Both go through the same debounce, so the editor's `didSave` and its watcher's report of the same save lint once.
|
|
137
|
+
|
|
138
|
+
**Trust.** The server reads the files the workspace names, so the VS Code client (`extras/vscode-execsql/extension.js`) starts it only in a trusted workspace, resolves `execsql` through `PATH` (never from the open folder) and runs it from the home directory. Plugins load from the server's own Python environment, not from the workspace.
|
|
139
|
+
|
|
107
140
|
## AST Parser and Executor
|
|
108
141
|
|
|
109
142
|
execsql2 parses scripts into an AST and walks the tree to execute. There is no separate flat-command-list engine; the AST executor is the only path.
|
|
@@ -157,6 +190,10 @@ ______________________________________________________________________
|
|
|
157
190
|
|
|
158
191
|
Metacommands are lines in SQL scripts prefixed with `-- !x!`. At import time, `metacommands/__init__.py` calls `build_dispatch_table()`, which populates a `MetaCommandList` with all `mcl.add()` registrations (~225 regex patterns). This singleton is stored as `_state.metacommandlist`.
|
|
159
192
|
|
|
193
|
+
### The syntax registry
|
|
194
|
+
|
|
195
|
+
`metacommands/reference.py` describes every metacommand a second way: the syntax forms as the reference docs write them, a one-line summary, a category and the docs anchor. The regex dispatch table decides what *runs*; the registry is what people and editors *read*. `execsql list metacommands`, the language server's completion snippets and hover text come from it. `tests/test_reference.py` checks that every registry form is accepted by the dispatch table, that every dispatch keyword has an entry, and that each anchor exists in `docs/reference/metacommands.md`. A new metacommand therefore needs both: an `mcl.add()` registration and a registry entry.
|
|
196
|
+
|
|
160
197
|
### How dispatch works
|
|
161
198
|
|
|
162
199
|
For each `MetaCommandStatement` AST node, the executor calls `_exec_metacommand()` in `script/executor.py`, which delegates to `_state.metacommandlist.eval(cmd_str)`. The dispatcher extracts the leading keyword, narrows ~225 entries to a small candidate set via a keyword index, then tests each candidate's compiled regex against the full command. The matched handler is called with the regex's named groups as keyword arguments plus `metacommandline` (the original unmodified line), and its hit counter is incremented.
|
|
@@ -303,19 +340,19 @@ This import pattern (always as `_state`, always accessed inside function/method
|
|
|
303
340
|
|
|
304
341
|
### Key state variables
|
|
305
342
|
|
|
306
|
-
| Variable | Type
|
|
307
|
-
| ----------------- |
|
|
308
|
-
| `conf` | `ConfigData`
|
|
309
|
-
| `subvars` | `SubVarSet`
|
|
310
|
-
| `ast_exec_stack` | `list[ExecFrame]`
|
|
311
|
-
| `ast_scripts` | `dict[str, ScriptBlock]`
|
|
312
|
-
| `last_command` | `
|
|
313
|
-
| `dbs` | `DatabasePool`
|
|
314
|
-
| `metacommandlist` | `MetaCommandList`
|
|
315
|
-
| `conditionallist` | `MetaCommandList`
|
|
316
|
-
| `counters` | `CounterVars`
|
|
317
|
-
| `filewriter` | `FileWriter`
|
|
318
|
-
| `exec_log` | `Logger`
|
|
343
|
+
| Variable | Type | Purpose |
|
|
344
|
+
| ----------------- | ---------------------------- | ---------------------------------------------------------------- |
|
|
345
|
+
| `conf` | `ConfigData` | Merged configuration |
|
|
346
|
+
| `subvars` | `SubVarSet` | Global substitution variables |
|
|
347
|
+
| `ast_exec_stack` | `list[ExecFrame]` | Unified execution stack (scopes + IF/LOOP/BATCH/INCLUDE) |
|
|
348
|
+
| `ast_scripts` | `dict[str, ScriptBlock]` | Named scripts from `BEGIN/END SCRIPT` (AST registry) |
|
|
349
|
+
| `last_command` | `ExecutingStatement \| None` | Most-recently-executed statement; powers `current_script_line()` |
|
|
350
|
+
| `dbs` | `DatabasePool` | Open database connections |
|
|
351
|
+
| `metacommandlist` | `MetaCommandList` | Metacommand dispatch table |
|
|
352
|
+
| `conditionallist` | `MetaCommandList` | Conditional predicate dispatch table |
|
|
353
|
+
| `counters` | `CounterVars` | Auto-incrementing counters |
|
|
354
|
+
| `filewriter` | `FileWriter` | This run's background file-writing thread |
|
|
355
|
+
| `exec_log` | `Logger` | Execution log |
|
|
319
356
|
|
|
320
357
|
______________________________________________________________________
|
|
321
358
|
|
|
@@ -328,7 +365,7 @@ ______________________________________________________________________
|
|
|
328
365
|
1. System-wide (platform-dependent)
|
|
329
366
|
1. User home directory
|
|
330
367
|
1. Script file directory
|
|
331
|
-
1. Current working directory
|
|
368
|
+
1. Current working directory (or `start_dir`, when the caller passes one)
|
|
332
369
|
|
|
333
370
|
It exposes all recognized options as attributes (`db_type`, `server`, `db`, `db_file`, `username`, `script_encoding`, `output_encoding`, etc.).
|
|
334
371
|
|
|
@@ -300,8 +300,8 @@ The options below belong to `run`: `execsql run -tl script.sql mydb.sqlite`.
|
|
|
300
300
|
`--version` and `-o`/`--online-help` work on their own (`execsql --version`)
|
|
301
301
|
and anywhere on a `run` command line.
|
|
302
302
|
`format` has its own options, described in the [formatter guide](../guides/formatter.md);
|
|
303
|
-
`lint`'s are in the [lint rules reference](../reference/lint.md); `lsp`'s (`--check
|
|
304
|
-
[Editor Support](../guides/editors.md#
|
|
303
|
+
`lint`'s are in the [lint rules reference](../reference/lint.md); `lsp`'s (`--check`,
|
|
304
|
+
`--log-level`, `--log-file`) in [Editor Support](../guides/editors.md#troubleshooting); `config`, `list` and `init` are described
|
|
305
305
|
[above](#config_command).
|
|
306
306
|
|
|
307
307
|
### Connection options
|
|
@@ -479,7 +479,7 @@ Valid encoding names can be displayed with `execsql list encodings`. See also [C
|
|
|
479
479
|
}
|
|
480
480
|
```
|
|
481
481
|
|
|
482
|
-
Files and connections are recorded as each metacommand succeeds, after variable substitution, so paths are the ones used (`out/west.csv`, not `out/!!region!!.csv`); `INCLUDE`d scripts count as files read. When a run fails, `exit_status` is its exit code and `errors` holds the message, its `type`, `source`, `line` and the failing `command`. `variables` lists the names set with `-a` and `--var
|
|
482
|
+
Files and connections are recorded as each metacommand succeeds, after variable substitution, so paths are the ones used (`out/west.csv`, not `out/!!region!!.csv`); `INCLUDE`d scripts count as files read. When a run fails, `exit_status` is its exit code and `errors` holds the message, its `type`, `source`, `line` and the failing `command`. `variables` lists the names set with `-a` and `--var`, not their values. A password (from `--dsn`, a prompt or the keyring), a `SUB_DECRYPT` result, or a common secret shape (a URL's password, `password=...`, an API token) that ends up in a path, a connection target or an error message is written as `***`. Values given with `-a` and `--var` are kept where a path uses them, as in `out/west.csv`, although the log masks them: keep a secret out of `-a` and `--var` if the manifest is collected.
|
|
483
483
|
|
|
484
484
|
The path is checked before the run starts: if *FILE* cannot be written (its folder is a file, or not writable), `execsql run` exits 2 before any SQL runs.
|
|
485
485
|
|
|
@@ -101,7 +101,7 @@ underlined line). A fix is offered only when applying it clears the finding.
|
|
|
101
101
|
Format Document (VS Code: Shift-Alt-F, or `editor.formatOnSave`) runs
|
|
102
102
|
[`execsql format`](formatter.md) on the editor's text, with the
|
|
103
103
|
`[format]` settings of the workspace's configuration (`indent`, `sql`,
|
|
104
|
-
`leading_comma`), so the editor, the command line and the `execsql-format`
|
|
104
|
+
`leading_comma`, and [`rewrite_sql`](formatter.md#layout-only)), so the editor, the command line and the `execsql-format`
|
|
105
105
|
pre-commit hook agree. The editor's own tab-size setting is not used. Only
|
|
106
106
|
whole documents are formatted, not selections: a statement's indentation
|
|
107
107
|
depends on the IF, LOOP and SCRIPT blocks around it.
|
|
@@ -148,13 +148,18 @@ loads/ (no execsql.conf)
|
|
|
148
148
|
an unknown metacommand is reported in `loads/*.sql` but not in
|
|
149
149
|
`reports/*.sql`. Adding or removing a folder takes effect at once.
|
|
150
150
|
|
|
151
|
-
The server reads each folder's `execsql.conf` again when it changes
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
151
|
+
The server reads each folder's `execsql.conf` again when it changes (and lints
|
|
152
|
+
every open script with the new settings), and lints an open script again when a
|
|
153
|
+
file it `INCLUDE`s is created, deleted or saved, so a missing-file finding
|
|
154
|
+
clears once the file exists. Completion, hover and go-to-definition always use
|
|
155
|
+
the included files' current text, so a script sees the variables an edited
|
|
156
|
+
`INCLUDE` file now defines. An included file that is open in the editor is read
|
|
157
|
+
as you have it, saved or not. This needs an editor that reports file changes to the server: VS Code
|
|
158
|
+
does, and Neovim does on macOS and Windows. Elsewhere (Neovim on Linux, most
|
|
159
|
+
other clients) saving a script in the editor still relints the scripts that
|
|
160
|
+
include it, but an edit to `execsql.conf`, or a change made outside the editor
|
|
161
|
+
(a `git checkout`, another tool), is picked up only after restarting the server
|
|
162
|
+
(Neovim: `:LspRestart`).
|
|
158
163
|
|
|
159
164
|
The server only reads: it never connects to a database or runs a script, and
|
|
160
165
|
nothing in the workspace can make it run code. The only code it loads besides
|
|
@@ -182,7 +187,8 @@ The setting is a command name looked up in PATH or an absolute path; a relative
|
|
|
182
187
|
path is refused. The extension never looks for `execsql` in the open folder,
|
|
183
188
|
and starts the server from your home directory.
|
|
184
189
|
After upgrading execsql, run **execsql: Restart Language Server** from the
|
|
185
|
-
Command Palette. The
|
|
190
|
+
Command Palette. The server's log is in **View → Output → execsql**
|
|
191
|
+
([Troubleshooting](#troubleshooting)). The extension also highlights execsql syntax; that works
|
|
186
192
|
without the server.
|
|
187
193
|
|
|
188
194
|
In a folder you have not marked as trusted
|
|
@@ -227,3 +233,45 @@ Any editor with a language server client can use it: configure a server for
|
|
|
227
233
|
the `sql` language whose command is `execsql lsp`, run over stdio. Sublime Text
|
|
228
234
|
(the LSP package), Emacs (eglot or lsp-mode), Zed and JetBrains IDEs (the LSP4IJ
|
|
229
235
|
plugin) all work this way.
|
|
236
|
+
|
|
237
|
+
## Troubleshooting { #troubleshooting }
|
|
238
|
+
|
|
239
|
+
**Where the server's log is.** The server writes its log to stderr, which the
|
|
240
|
+
editor keeps:
|
|
241
|
+
|
|
242
|
+
| Editor | Where |
|
|
243
|
+
| ------- | ------------------------------------------------------------------------------------- |
|
|
244
|
+
| VS Code | **View → Output**, then choose **execsql** in the list. Start failures are there too. |
|
|
245
|
+
| Neovim | `:LspLog` (`~/.local/state/nvim/lsp.log`) |
|
|
246
|
+
| Helix | `:log-open` |
|
|
247
|
+
|
|
248
|
+
**How much it logs.** `execsql lsp --log-level` (or the `EXECSQL_LSP_LOG_LEVEL`
|
|
249
|
+
environment variable) takes `error`, `warning` (the default), `info` or `debug`:
|
|
250
|
+
|
|
251
|
+
- `info` adds a startup record and each workspace folder's settings, which is
|
|
252
|
+
what a bug report needs:
|
|
253
|
+
|
|
254
|
+
```text
|
|
255
|
+
INFO execsql.lsp.server: execsql lsp 2.x.y; Python 3.12.7 at /home/me/.local/share/uv/tools/execsql2/bin/python; pygls 2.x.y; formatter available
|
|
256
|
+
INFO execsql.lsp.server: workspace folders: /home/me/etl
|
|
257
|
+
INFO execsql.lsp.server: settings for /home/me/etl: config files /home/me/etl/execsql.conf; lint select all, ignore V; format {...}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
- `debug` adds every message between the editor and the server, including the
|
|
261
|
+
scripts' text.
|
|
262
|
+
|
|
263
|
+
The VS Code extension logs at `info` (setting **execsql.server.logLevel**). In
|
|
264
|
+
another editor, add the option to the server command, e.g. in Neovim
|
|
265
|
+
`cmd = { "execsql", "lsp", "--log-level", "info" }`. An editor that does not
|
|
266
|
+
keep the server's stderr can use `--log-file PATH` to append the log to a file.
|
|
267
|
+
|
|
268
|
+
**Tracing the protocol in VS Code.** Set **execsql.trace.server** to `messages`
|
|
269
|
+
(or `verbose`, which adds each message's content); the trace appears in the same
|
|
270
|
+
Output channel.
|
|
271
|
+
|
|
272
|
+
**Reporting a problem.** [Open an issue](https://github.com/geocoug/execsql/issues)
|
|
273
|
+
with:
|
|
274
|
+
|
|
275
|
+
1. The output of `execsql --version` and `execsql lsp --check`.
|
|
276
|
+
1. The server log at `info`, from start-up to the problem.
|
|
277
|
+
1. A small script that shows it, if you can share one.
|