execsql2 2.19.0__tar.gz → 2.19.2__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.19.0 → execsql2-2.19.2}/.pre-commit-hooks.yaml +1 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/CHANGELOG.md +16 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/PKG-INFO +1 -1
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/about/divergence.md +1 -1
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/getting-started/installation.md +3 -1
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/getting-started/requirements.md +29 -2
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/guides/debugging.md +14 -7
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/guides/formatter.md +8 -2
- {execsql2-2.19.0 → execsql2-2.19.2}/pyproject.toml +2 -2
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/format.py +9 -3
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_format.py +24 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/uv.lock +1 -1
- {execsql2-2.19.0 → execsql2-2.19.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/.github/dependabot.yml +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/.github/workflows/ci-cd.yml +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/.gitignore +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/.pre-commit-config.yaml +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/.python-version +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/.readthedocs.yaml +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/CONTRIBUTING.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/LICENSE.txt +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/NOTICE +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/README.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/SECURITY.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/about/contributors.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/about/copyright.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/api/cli.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/api/db.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/api/exporters.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/api/importers.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/api/index.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/api/metacommands.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/dev/adding_db_adapters.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/dev/adding_exporters.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/dev/adding_importers.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/dev/adding_metacommands.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/dev/architecture.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/getting-started/syntax.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/guides/documentation.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/guides/encoding.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/guides/examples.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/guides/logging.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/guides/sql_syntax.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/guides/usage.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/guides/using_scripts.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/images/Compare_planets.png +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/images/actions.png +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/images/actions2.png +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/images/checkboxes.png +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/images/connect.b64 +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/images/connect.png +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/images/create_conf.png +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/images/data_error1_screenshot.jpg +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/images/entry_form.png +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/images/execsql_console.png +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/images/execsql_logo_01.png +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/images/fatals.png +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/images/logo_small.png +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/images/pause_terminal.png +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/images/pause_terminal_sm.b64 +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/images/pause_terminal_sm.png +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/images/prompt_compare.png +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/images/set_build_commands.jpg +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/images/unit_conversions.b64 +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/images/unit_conversions_029.png +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/images/unmatched.png +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/images/vim_execsql_highlight.png +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/index.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/reference/configuration.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/reference/metacommands.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/reference/security.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/docs/reference/substitution_vars.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/extras/plugin-template/README.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/extras/plugin-template/pyproject.toml +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/extras/plugin-template/src/execsql_plugin_YOURNAME/__init__.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/extras/plugin-template/tests/test_plugin.py.example +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/extras/vscode-execsql/README.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/extras/vscode-execsql/package.json +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/extras/vscode-execsql/syntaxes/execsql.tmLanguage.json +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/justfile +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/scripts/generate_vscode_grammar.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/__init__.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/__main__.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/api.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/cli/__init__.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/cli/dsn.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/cli/help.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/cli/lint.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/cli/run.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/config.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/data/__init__.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/data/execsql.conf.template +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/db/__init__.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/db/access.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/db/base.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/db/dsn.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/db/duckdb.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/db/factory.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/db/firebird.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/db/mysql.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/db/oracle.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/db/postgres.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/db/sqlite.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/db/sqlserver.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/debug/__init__.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/debug/repl.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/exceptions.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/exporters/__init__.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/exporters/base.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/exporters/delimited.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/exporters/duckdb.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/exporters/feather.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/exporters/html.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/exporters/json.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/exporters/latex.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/exporters/markdown.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/exporters/ods.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/exporters/parquet.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/exporters/pretty.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/exporters/protocol.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/exporters/raw.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/exporters/sqlite.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/exporters/templates.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/exporters/values.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/exporters/xls.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/exporters/xlsx.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/exporters/xml.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/exporters/yaml.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/exporters/zip.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/gui/__init__.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/gui/base.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/gui/console.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/gui/desktop.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/gui/tui.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/importers/__init__.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/importers/base.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/importers/csv.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/importers/feather.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/importers/json.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/importers/ods.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/importers/xls.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/metacommands/__init__.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/metacommands/conditions.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/metacommands/connect.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/metacommands/control.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/metacommands/data.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/metacommands/debug.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/metacommands/dispatch.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/metacommands/io.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/metacommands/io_export.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/metacommands/io_fileops.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/metacommands/io_import.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/metacommands/io_write.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/metacommands/prompt.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/metacommands/script_ext.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/metacommands/system.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/metacommands/upsert.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/models.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/parser.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/plugins.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/py.typed +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/script/__init__.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/script/ast.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/script/control.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/script/engine.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/script/executor.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/script/parser.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/script/variables.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/state.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/types.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/utils/__init__.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/utils/auth.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/utils/crypto.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/utils/datetime.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/utils/errors.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/utils/fileio.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/utils/gui.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/utils/mail.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/utils/numeric.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/utils/regex.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/utils/strings.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/src/execsql/utils/timer.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/templates/README.md +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/templates/config_settings.sqlite +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/templates/example_config_prompt.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/templates/execsql.conf +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/templates/make_config_db.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/templates/md_compare.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/templates/md_glossary.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/templates/md_upsert.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/templates/pg_compare.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/templates/pg_glossary.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/templates/pg_upsert.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/templates/script_template.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/templates/ss_compare.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/templates/ss_glossary.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/templates/ss_upsert.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/__init__.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/cli/__init__.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/cli/test_cli.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/cli/test_cli_e2e.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/cli/test_cli_run.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/cli/test_lint.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/cli/test_ping.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/cli/test_profile.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/conftest.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/db/__init__.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/db/test_access_windows.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/db/test_base.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/db/test_db_adapters_mocked.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/db/test_db_adapters_mocked_extra.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/db/test_dsn.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/db/test_duckdb.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/db/test_factory.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/db/test_mysql_case_folding.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/db/test_mysql_inprocess.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/db/test_postgres.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/db/test_postgres_inprocess.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/db/test_sqlite.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/db/test_sqlite_extra.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/db/test_sqlserver_inprocess.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/__init__.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_base.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_db.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_delimited.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_duckdb_exporter.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_exporters.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_feather.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_html_extended.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_html_latex.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_json.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_json_extended.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_latex_extended.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_markdown.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_ods.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_ods_export.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_parquet.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_pretty_extended.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_raw_extended.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_sqlite_exporter.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_templates.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_templates_extended.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_values_extended.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_xls_xlsx.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_xlsx.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_xml.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_yaml.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/exporters/test_zip.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/gui/__init__.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/gui/test_backends.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/gui/test_backends_extended.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/gui/test_compare_stats.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/gui/test_compute_row_diffs.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/gui/test_desktop_dialogs.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/gui/test_tui_pilot.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/gui/test_tui_pilot_complex.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/gui/test_utils_gui_extended.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/importers/__init__.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/importers/test_base_extended.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/importers/test_csv_edge_cases.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/importers/test_csv_importer.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/importers/test_feather_importer.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/importers/test_json_importer.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/importers/test_ods_importer.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/importers/test_xls_importer.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/integration/__init__.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/integration/conftest.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/integration/test_dsn.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/integration/test_duckdb.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/integration/test_mysql.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/integration/test_postgres.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/integration/test_sqlite.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/metacommands/__init__.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/metacommands/test_assert.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/metacommands/test_breakpoint.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/metacommands/test_conditions_extra.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/metacommands/test_connect.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/metacommands/test_io_export.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/metacommands/test_io_import.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/metacommands/test_metacommands.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/metacommands/test_metacommands_connect.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/metacommands/test_metacommands_data.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/metacommands/test_metacommands_extended.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/metacommands/test_metacommands_fileops_extra.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/metacommands/test_metacommands_io.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/metacommands/test_metacommands_io_write_extra.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/metacommands/test_metacommands_script_ext.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/metacommands/test_metacommands_system.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/metacommands/test_metacommands_system_extra.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/metacommands/test_pg_upsert.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/metacommands/test_prompt.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/metacommands/test_row_count.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/metacommands/test_show_scripts.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/__init__.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/audit_lint_bad.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/audit_smoke/sample.json +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/audit_smoke/sample.jsonl +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/audit_smoke.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/config_runtime.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/control_flow.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/counters_and_locals.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/error_handling.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/import_options/has_comments.csv +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/import_options.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/includes/helper.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/includes.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/io_formats.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/io_roundtrip.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/multi_db.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/parquet_feather_roundtrip.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/parse_only/parse_tree.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/predicates.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/scripts.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/smoke.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/subroutine_loops.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/subvars_advanced.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/template_export/greeting.tmpl +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/template_export.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/timer.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/transactions.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/write_create_table.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/fixtures/xlsx_ods_roundtrip.sql +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/scripts/test_sql_scripts.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/security/__init__.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/security/test_env_detection.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/security/test_expansion_bomb.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/security/test_import_regex_hardening.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/security/test_log_redaction.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/security/test_odbc_injection.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/security/test_path_containment.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/security/test_substitution_injection.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/security/test_zip_bomb.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_api.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_api_extended.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_ast.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_ast_parser.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_bundled_templates.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_config.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_config_data.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_config_extended.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_debug_repl.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_engine.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_error_messages.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_exceptions.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_executor.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_executor_inprocess.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_mail.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_models.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_package.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_parser.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_parser_params.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_plugins.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_registry.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_script.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_state.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/test_types.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/utils/__init__.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/utils/test_auth.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/utils/test_auth_extra.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/utils/test_crypto.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/utils/test_datetime.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/utils/test_encodedfile_context.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/utils/test_errors.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/utils/test_errors_extra.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/utils/test_fileio.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/utils/test_fileio_extra.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/utils/test_numeric.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/utils/test_regex.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/utils/test_strings.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/utils/test_timer.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/tests/utils/test_timer_extra.py +0 -0
- {execsql2-2.19.0 → execsql2-2.19.2}/zensical.toml +0 -0
|
@@ -13,6 +13,22 @@ ______________________________________________________________________
|
|
|
13
13
|
|
|
14
14
|
______________________________________________________________________
|
|
15
15
|
|
|
16
|
+
## [2.19.2] - 2026-06-03
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- `pre-commit` hook `execsql-format` now installs `sqlglot` into its isolated env. Since 2.19.0 moved `sqlglot` to the `[formatter]` extra, the hook env (which installs the bare package) was missing it and crashed with `ModuleNotFoundError: No module named 'sqlglot'`. Re-run `pre-commit clean && pre-commit install --install-hooks` after upgrading to pick up the new dependency.
|
|
21
|
+
|
|
22
|
+
______________________________________________________________________
|
|
23
|
+
|
|
24
|
+
## [2.19.1] - 2026-06-03
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- `execsql-format` no longer mangles quoted substitution variables: `!'!var!'!` and `!"!var!"!` were being parsed by sqlglot as `NOT` operators (e.g. `!'!myvar!'!` → `NOT NOT '!myvar!'`). All three quote forms plus deferred `!{var}!` are now hidden from SQL formatting.
|
|
29
|
+
|
|
30
|
+
______________________________________________________________________
|
|
31
|
+
|
|
16
32
|
## [2.19.0] - 2026-06-02
|
|
17
33
|
|
|
18
34
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: execsql2
|
|
3
|
-
Version: 2.19.
|
|
3
|
+
Version: 2.19.2
|
|
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
|
|
@@ -147,7 +147,7 @@ New options in `execsql.conf`:
|
|
|
147
147
|
|
|
148
148
|
### Debugging { #debugging }
|
|
149
149
|
|
|
150
|
-
execsql2 adds an interactive debug REPL (no upstream equivalent), triggered either by the `BREAKPOINT` metacommand or the `--debug` CLI flag (step-through mode). The REPL prompts with `execsql debug>` and
|
|
150
|
+
execsql2 adds an interactive debug REPL (no upstream equivalent), triggered either by the `BREAKPOINT` metacommand or the `--debug` CLI flag (step-through mode). The REPL prompts with `execsql debug>` and uses two-way dispatch (as of 2.19.0): input starting with `.` is a REPL command (`.continue`, `.quit`, `.next`, `.vars`, `.vars VAR`, `.where`, `.stack`, `.set`, `.scripts`, `.cancel`, `.help`); everything else is SQL, buffered across lines until terminated with `;` and executed against the live connection (DML reports rows affected, DDL / transaction-control reports `(statement executed)`, errors print inline without ending the session). `BREAKPOINT` is silently skipped when stdin is not a TTY so it does not hang CI. Full command list and behavior: [Debugging guide](../guides/debugging.md).
|
|
151
151
|
|
|
152
152
|
### Library API
|
|
153
153
|
|
|
@@ -27,12 +27,14 @@ pip install "execsql2[odbc]" # Generic ODBC DSN (pyodbc)
|
|
|
27
27
|
pip install "execsql2[firebird]" # Firebird
|
|
28
28
|
pip install "execsql2[oracle]" # Oracle
|
|
29
29
|
pip install "execsql2[formats]" # ODS, Excel, Jinja2, Feather/Parquet, HDF5, YAML
|
|
30
|
+
pip install "execsql2[formatter]" # SQL pass for execsql-format (sqlglot)
|
|
30
31
|
pip install "execsql2[auth]" # OS keyring integration (desktop/native)
|
|
31
32
|
pip install "execsql2[auth-plaintext]" # Headless keyring (plaintext file backend)
|
|
32
33
|
pip install "execsql2[auth-encrypted]" # Headless keyring (encrypted file backend)
|
|
33
34
|
pip install "execsql2[upsert]" # PG_UPSERT metacommand (pg-upsert)
|
|
35
|
+
pip install "execsql2[map]" # PROMPT MAP widget (tkintermapview)
|
|
34
36
|
pip install "execsql2[all-db]" # All database drivers
|
|
35
|
-
pip install "execsql2[all]" # Everything (all-db + formats + auth + upsert)
|
|
37
|
+
pip install "execsql2[all]" # Everything (all-db + formats + formatter + auth + upsert + map)
|
|
36
38
|
```
|
|
37
39
|
|
|
38
40
|
In addition to the *execsql* program itself, additional Python libraries may need to be installed to use *execsql* with specific types of DBMSs and spreadsheets. The additional libraries that may be needed are listed in the [Requirements](requirements.md#requirements) section.
|
|
@@ -18,11 +18,16 @@ pip install "execsql2[odbc]" # ODBC DSN (pyodbc)
|
|
|
18
18
|
|
|
19
19
|
# Feature bundles
|
|
20
20
|
pip install "execsql2[formats]" # ODS, Excel, Jinja2, Feather, Parquet, HDF5
|
|
21
|
-
pip install "execsql2[
|
|
21
|
+
pip install "execsql2[formatter]" # SQL pass for execsql-format (sqlglot)
|
|
22
|
+
pip install "execsql2[upsert]" # PG_UPSERT metacommand (pg-upsert)
|
|
23
|
+
pip install "execsql2[map]" # PROMPT MAP widget (tkintermapview)
|
|
24
|
+
pip install "execsql2[auth]" # OS keyring integration (desktop / native)
|
|
25
|
+
pip install "execsql2[auth-plaintext]" # Headless keyring (plaintext file backend)
|
|
26
|
+
pip install "execsql2[auth-encrypted]" # Headless keyring (encrypted file backend)
|
|
22
27
|
|
|
23
28
|
# Convenience
|
|
24
29
|
pip install "execsql2[all-db]" # All database drivers
|
|
25
|
-
pip install "execsql2[all]" # Everything
|
|
30
|
+
pip install "execsql2[all]" # Everything (all-db + formats + formatter + auth + upsert + map)
|
|
26
31
|
```
|
|
27
32
|
|
|
28
33
|
Multiple extras can be combined: `pip install "execsql2[postgres,duckdb,formats]"`.
|
|
@@ -55,12 +60,34 @@ The specific libraries installed by each extra are:
|
|
|
55
60
|
| [Parquet](https://parquet.apache.org/) files | [polars](https://pypi.org/project/polars/) |
|
|
56
61
|
| [HDF5](https://www.hdfgroup.org/solutions/hdf5/) files | [tables](https://pypi.org/project/tables/) |
|
|
57
62
|
|
|
63
|
+
### `formatter` extra
|
|
64
|
+
|
|
65
|
+
Required for the SQL-formatting pass of the `execsql-format` CLI. Without this extra, `execsql-format` still normalizes metacommand indentation and keyword casing (use `--no-sql` or import scripts without SQL); the SQL pretty-printing pass calls [sqlglot](https://sqlglot.com/) and raises `ModuleNotFoundError` if it isn't installed.
|
|
66
|
+
|
|
67
|
+
| Feature | Library |
|
|
68
|
+
| ------------------------------------- | -------------------------------------------- |
|
|
69
|
+
| SQL reformatting via `execsql-format` | [sqlglot](https://pypi.org/project/sqlglot/) |
|
|
70
|
+
|
|
71
|
+
### `upsert` extra
|
|
72
|
+
|
|
73
|
+
| Feature | Library |
|
|
74
|
+
| ----------------------------------------- | ------------------------------------------------ |
|
|
75
|
+
| `PG_UPSERT` PostgreSQL upsert metacommand | [pg-upsert](https://pypi.org/project/pg-upsert/) |
|
|
76
|
+
|
|
77
|
+
### `map` extra
|
|
78
|
+
|
|
79
|
+
| Feature | Library |
|
|
80
|
+
| ------------------------------------- | ---------------------------------------------------------- |
|
|
81
|
+
| `PROMPT MAP` lat/lon selection widget | [tkintermapview](https://pypi.org/project/tkintermapview/) |
|
|
82
|
+
|
|
58
83
|
### `auth` bundle
|
|
59
84
|
|
|
60
85
|
| Feature | Library |
|
|
61
86
|
| -------------------- | -------------------------------------------- |
|
|
62
87
|
| OS keyring / secrets | [keyring](https://pypi.org/project/keyring/) |
|
|
63
88
|
|
|
89
|
+
The `auth-plaintext` and `auth-encrypted` variants add a fallback keyring backend for headless Linux: `auth-plaintext` adds [keyrings.alt](https://pypi.org/project/keyrings.alt/) (plaintext file storage — **secrets are not encrypted at rest**), and `auth-encrypted` adds `keyrings.alt` plus [pycryptodome](https://pypi.org/project/pycryptodome/) for an encrypted file backend. See [Keyring Platform Setup](../reference/security.md#keyring_setup).
|
|
90
|
+
|
|
64
91
|
Connections to SQLite databases use Python's standard library and require no additional packages.
|
|
65
92
|
|
|
66
93
|
## Additional System Requirements { #system_requirements }
|
|
@@ -57,22 +57,29 @@ execsql debug>
|
|
|
57
57
|
|
|
58
58
|
| Command | Shortcut | Description |
|
|
59
59
|
| --------------- | -------- | ------------------------------------------------------------------------- |
|
|
60
|
-
| `.continue` | `.c` | Resume
|
|
61
|
-
| `.
|
|
62
|
-
| `.vars` | `.v` | List
|
|
63
|
-
| `.vars
|
|
60
|
+
| `.continue` | `.c` | Resume script execution |
|
|
61
|
+
| `.quit` | `.q` | Halt the script (exit 1). `.abort` is accepted as an alias. |
|
|
62
|
+
| `.vars` | `.v` | List all execsql substitution variables |
|
|
63
|
+
| `.vars VAR` | `.v VAR` | Print the value of one variable (e.g. `.vars logfile`, `.vars $ARG_1`) |
|
|
64
64
|
| `.next` | `.n` | Execute the next statement, then pause again (step mode) |
|
|
65
65
|
| `.where` | `.w` | Re-display the current script location and upcoming statement |
|
|
66
66
|
| `.stack` | | Show the command-list stack (script name, cursor position, nesting depth) |
|
|
67
67
|
| `.set VAR VAL` | `.s` | Set or update a substitution variable |
|
|
68
68
|
| `.scripts` | | List all registered SCRIPT definitions with parameters and source |
|
|
69
69
|
| `.scripts NAME` | | Show detail for a specific SCRIPT (parameters, source file/line range) |
|
|
70
|
+
| `.cancel` | | Discard the current partial multi-line SQL buffer (also Ctrl-C / EOF) |
|
|
70
71
|
| `.help` | `.h` | Show available commands |
|
|
71
72
|
|
|
72
|
-
|
|
73
|
+
**Dispatch is two-way** (changed in 2.19.0): input starting with `.` is a REPL command, everything else is SQL. There is no bare-name variable lookup — use `.vars VAR` to print a single variable.
|
|
73
74
|
|
|
74
|
-
|
|
75
|
-
|
|
75
|
+
**SQL execution:**
|
|
76
|
+
|
|
77
|
+
- Input is buffered as SQL until a line ends with `;`, at which point the buffered statement is sent to the live connection. Multi-line statements are accepted; the prompt switches to a continuation indicator while a partial statement is being entered.
|
|
78
|
+
- `SELECT` (and other row-returning statements) print the result rows in tabular form.
|
|
79
|
+
- DML (`INSERT` / `UPDATE` / `DELETE`) prints `(N rows affected)`.
|
|
80
|
+
- DDL and transaction-control statements (`CREATE`, `DROP`, `BEGIN`, `COMMIT`, `ROLLBACK`, …) print `(statement executed)`.
|
|
81
|
+
- A SQL error prints the database error inline and returns to the prompt — the REPL session is not terminated.
|
|
82
|
+
- `.cancel` (or Ctrl-C / EOF mid-statement) discards a partial buffer without executing it.
|
|
76
83
|
|
|
77
84
|
The `--debug` CLI flag starts execution in step mode, pausing before every statement.
|
|
78
85
|
|
|
@@ -4,13 +4,19 @@
|
|
|
4
4
|
|
|
5
5
|
## Installation { #installation }
|
|
6
6
|
|
|
7
|
-
`execsql-format` is installed automatically
|
|
7
|
+
The `execsql-format` command is installed automatically with the `execsql2` package and is available on your PATH after install:
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
pip install execsql2
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
The metacommand-indentation and keyword-casing passes work out of the box. **SQL reformatting** (the optional sqlglot pass) requires the `[formatter]` extra, as of execsql2 2.19.0:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install "execsql2[formatter]"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Without the extra, `execsql-format` works in `--no-sql` mode (metacommand indentation and keyword casing only); invoking the SQL pass without `[formatter]` installed raises `ModuleNotFoundError: No module named 'sqlglot'`.
|
|
14
20
|
|
|
15
21
|
## Usage { #usage }
|
|
16
22
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "execsql2"
|
|
7
|
-
version = "2.19.
|
|
7
|
+
version = "2.19.2"
|
|
8
8
|
description = "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."
|
|
9
9
|
readme = { file = "README.md", content-type = "text/markdown" }
|
|
10
10
|
license = { file = "LICENSE.txt" }
|
|
@@ -170,7 +170,7 @@ skip-magic-trailing-comma = false
|
|
|
170
170
|
line-ending = "auto"
|
|
171
171
|
|
|
172
172
|
[tool.bumpversion]
|
|
173
|
-
current_version = "2.19.
|
|
173
|
+
current_version = "2.19.2"
|
|
174
174
|
commit = true
|
|
175
175
|
tag = true
|
|
176
176
|
tag_name = "v{new_version}"
|
|
@@ -129,9 +129,15 @@ def parse_keyword(payload: str) -> str:
|
|
|
129
129
|
# SQL block formatting helpers
|
|
130
130
|
# ---------------------------------------------------------------------------
|
|
131
131
|
|
|
132
|
-
# Matches execsql variable substitutions:
|
|
133
|
-
#
|
|
134
|
-
|
|
132
|
+
# Matches execsql variable substitutions:
|
|
133
|
+
# !!varname!! verbatim
|
|
134
|
+
# !'!varname!'! single-quoted (apostrophes doubled at expansion)
|
|
135
|
+
# !"!varname!"! double-quoted (quotes doubled at expansion)
|
|
136
|
+
# !{varname}! deferred
|
|
137
|
+
# The bare/quoted forms mirror src/execsql/script/variables.py:_TOKEN_RX so
|
|
138
|
+
# every token the executor recognises is hidden from sqlglot — otherwise the
|
|
139
|
+
# `!` in a quoted form is parsed as a NOT operator (e.g. `!'!v!'!` -> `NOT NOT '!v!'`).
|
|
140
|
+
_EXECSQL_VAR_RE = re.compile(r"""!(['"]?)!([^!\s][^!]*)!\1!|!\{[^}]+\}!""")
|
|
135
141
|
|
|
136
142
|
|
|
137
143
|
def _protect_variables(sql: str) -> tuple[str, list[tuple[str, str]]]:
|
|
@@ -279,6 +279,18 @@ class TestProtectVariables:
|
|
|
279
279
|
assert len(replacements) == 1
|
|
280
280
|
assert replacements[0][1] == "!{myvar}!"
|
|
281
281
|
|
|
282
|
+
def test_single_quoted_var(self):
|
|
283
|
+
protected, replacements = _protect_variables("WHERE a = !'!myvar!'!")
|
|
284
|
+
assert "!'!myvar!'!" not in protected
|
|
285
|
+
assert len(replacements) == 1
|
|
286
|
+
assert replacements[0][1] == "!'!myvar!'!"
|
|
287
|
+
|
|
288
|
+
def test_double_quoted_var(self):
|
|
289
|
+
protected, replacements = _protect_variables('WHERE a = !"!myvar!"!')
|
|
290
|
+
assert '!"!myvar!"!' not in protected
|
|
291
|
+
assert len(replacements) == 1
|
|
292
|
+
assert replacements[0][1] == '!"!myvar!"!'
|
|
293
|
+
|
|
282
294
|
def test_multiple_vars(self):
|
|
283
295
|
protected, replacements = _protect_variables("SELECT !!a!!, !!b!!")
|
|
284
296
|
assert len(replacements) == 2
|
|
@@ -649,6 +661,18 @@ class TestFormatFileEdgeCases:
|
|
|
649
661
|
assert "!!$my_var!!" in result
|
|
650
662
|
assert "!!table_name!!" in result
|
|
651
663
|
|
|
664
|
+
def test_quoted_subvar_not_mangled_as_not(self):
|
|
665
|
+
# Regression: !'!var!'! used to be parsed by sqlglot as NOT NOT '!var!'.
|
|
666
|
+
source = "select * from documents where author = !'!myvar!'!;\n"
|
|
667
|
+
result = format_file(source)
|
|
668
|
+
assert "!'!myvar!'!" in result
|
|
669
|
+
assert "NOT" not in result
|
|
670
|
+
|
|
671
|
+
def test_double_quoted_subvar_preserved(self):
|
|
672
|
+
source = 'select * from t where col = !"!myvar!"!;\n'
|
|
673
|
+
result = format_file(source)
|
|
674
|
+
assert '!"!myvar!"!' in result
|
|
675
|
+
|
|
652
676
|
def test_elseif_depth(self):
|
|
653
677
|
source = "-- !x! IF 1=1\n-- !x! WRITE 'a'\n-- !x! ELSEIF 2=2\n-- !x! WRITE 'b'\n-- !x! ENDIF\n"
|
|
654
678
|
result = format_file(source, use_sql=False)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{execsql2-2.19.0 → execsql2-2.19.2}/extras/plugin-template/src/execsql_plugin_YOURNAME/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|