execsql2 2.16.12__tar.gz → 2.16.14__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.16.12 → execsql2-2.16.14}/CHANGELOG.md +43 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/PKG-INFO +1 -1
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/about/divergence.md +5 -3
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/guides/formatter.md +54 -15
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/reference/metacommands.md +13 -2
- {execsql2-2.16.12 → execsql2-2.16.14}/pyproject.toml +2 -2
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/db/base.py +2 -0
- execsql2-2.16.14/src/execsql/format.py +657 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/metacommands/io_export.py +14 -10
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/metacommands/io_fileops.py +4 -6
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/script/ast.py +3 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/script/executor.py +7 -3
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/script/parser.py +20 -14
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/test_ast_parser.py +56 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/test_executor.py +75 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/test_format.py +749 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/uv.lock +1 -1
- execsql2-2.16.12/src/execsql/format.py +0 -384
- {execsql2-2.16.12 → execsql2-2.16.14}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/.github/workflows/ci-cd.yml +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/.gitignore +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/.pre-commit-config.yaml +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/.pre-commit-hooks.yaml +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/.python-version +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/.readthedocs.yaml +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/CONTRIBUTING.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/LICENSE.txt +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/NOTICE +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/README.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/SECURITY.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/about/contributors.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/about/copyright.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/api/cli.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/api/db.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/api/exporters.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/api/importers.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/api/index.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/api/metacommands.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/dev/adding_db_adapters.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/dev/adding_exporters.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/dev/adding_importers.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/dev/adding_metacommands.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/dev/architecture.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/getting-started/installation.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/getting-started/requirements.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/getting-started/syntax.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/guides/debugging.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/guides/documentation.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/guides/encoding.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/guides/examples.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/guides/logging.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/guides/sql_syntax.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/guides/usage.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/guides/using_scripts.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/images/Compare_planets.png +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/images/actions.png +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/images/actions2.png +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/images/checkboxes.png +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/images/connect.b64 +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/images/connect.png +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/images/create_conf.png +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/images/data_error1_screenshot.jpg +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/images/entry_form.png +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/images/execsql_console.png +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/images/execsql_logo_01.png +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/images/fatals.png +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/images/logo_small.png +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/images/pause_terminal.png +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/images/pause_terminal_sm.b64 +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/images/pause_terminal_sm.png +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/images/prompt_compare.png +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/images/set_build_commands.jpg +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/images/unit_conversions.b64 +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/images/unit_conversions_029.png +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/images/unmatched.png +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/images/vim_execsql_highlight.png +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/index.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/reference/configuration.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/reference/security.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/docs/reference/substitution_vars.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/extras/plugin-template/README.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/extras/plugin-template/pyproject.toml +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/extras/plugin-template/src/execsql_plugin_YOURNAME/__init__.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/extras/plugin-template/tests/test_plugin.py.example +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/extras/vscode-execsql/README.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/extras/vscode-execsql/package.json +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/extras/vscode-execsql/syntaxes/execsql.tmLanguage.json +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/justfile +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/scripts/generate_vscode_grammar.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/__init__.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/__main__.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/api.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/cli/__init__.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/cli/dsn.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/cli/help.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/cli/lint.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/cli/lint_ast.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/cli/run.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/config.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/db/__init__.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/db/access.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/db/dsn.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/db/duckdb.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/db/factory.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/db/firebird.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/db/mysql.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/db/oracle.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/db/postgres.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/db/sqlite.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/db/sqlserver.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/debug/__init__.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/debug/repl.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/exceptions.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/exporters/__init__.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/exporters/base.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/exporters/delimited.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/exporters/duckdb.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/exporters/feather.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/exporters/html.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/exporters/json.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/exporters/latex.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/exporters/markdown.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/exporters/ods.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/exporters/parquet.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/exporters/pretty.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/exporters/protocol.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/exporters/raw.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/exporters/sqlite.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/exporters/templates.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/exporters/values.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/exporters/xls.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/exporters/xlsx.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/exporters/xml.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/exporters/yaml.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/exporters/zip.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/gui/__init__.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/gui/base.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/gui/console.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/gui/desktop.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/gui/tui.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/importers/__init__.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/importers/base.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/importers/csv.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/importers/feather.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/importers/json.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/importers/ods.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/importers/xls.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/metacommands/__init__.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/metacommands/conditions.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/metacommands/connect.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/metacommands/control.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/metacommands/data.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/metacommands/debug.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/metacommands/dispatch.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/metacommands/io.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/metacommands/io_import.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/metacommands/io_write.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/metacommands/prompt.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/metacommands/script_ext.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/metacommands/system.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/metacommands/upsert.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/models.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/parser.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/plugins.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/py.typed +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/script/__init__.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/script/control.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/script/engine.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/script/variables.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/state.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/types.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/utils/__init__.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/utils/auth.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/utils/crypto.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/utils/datetime.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/utils/errors.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/utils/fileio.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/utils/gui.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/utils/mail.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/utils/numeric.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/utils/regex.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/utils/strings.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/src/execsql/utils/timer.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/templates/README.md +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/templates/config_settings.sqlite +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/templates/example_config_prompt.sql +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/templates/execsql.conf +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/templates/make_config_db.sql +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/templates/md_compare.sql +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/templates/md_glossary.sql +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/templates/md_upsert.sql +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/templates/pg_compare.sql +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/templates/pg_glossary.sql +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/templates/pg_upsert.sql +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/templates/script_template.sql +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/templates/ss_compare.sql +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/templates/ss_glossary.sql +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/templates/ss_upsert.sql +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/__init__.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/cli/__init__.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/cli/test_cli.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/cli/test_cli_e2e.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/cli/test_cli_run.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/cli/test_lint.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/cli/test_ping.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/cli/test_profile.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/conftest.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/db/__init__.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/db/test_base.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/db/test_db_adapters_mocked.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/db/test_dsn.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/db/test_duckdb.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/db/test_factory.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/db/test_postgres.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/db/test_sqlite.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/db/test_sqlite_extra.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/__init__.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_base.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_db.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_delimited.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_duckdb_exporter.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_exporters.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_feather.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_html_extended.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_html_latex.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_json.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_json_extended.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_latex_extended.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_markdown.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_ods.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_parquet.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_pretty_extended.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_raw_extended.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_sqlite_exporter.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_templates.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_templates_extended.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_values_extended.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_xls_xlsx.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_xlsx.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_xml.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_yaml.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/exporters/test_zip.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/gui/__init__.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/gui/test_backends.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/gui/test_compare_stats.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/gui/test_compute_row_diffs.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/importers/__init__.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/importers/test_base_extended.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/importers/test_csv_edge_cases.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/importers/test_csv_importer.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/importers/test_feather_importer.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/importers/test_json_importer.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/importers/test_ods_importer.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/importers/test_xls_importer.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/integration/__init__.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/integration/conftest.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/integration/test_dsn.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/integration/test_duckdb.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/integration/test_mysql.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/integration/test_postgres.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/integration/test_sqlite.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/metacommands/__init__.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/metacommands/test_assert.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/metacommands/test_breakpoint.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/metacommands/test_connect.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/metacommands/test_io_export.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/metacommands/test_io_import.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/metacommands/test_metacommands.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/metacommands/test_metacommands_connect.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/metacommands/test_metacommands_data.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/metacommands/test_metacommands_extended.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/metacommands/test_metacommands_fileops_extra.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/metacommands/test_metacommands_io.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/metacommands/test_metacommands_io_write_extra.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/metacommands/test_metacommands_script_ext.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/metacommands/test_metacommands_system.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/metacommands/test_metacommands_system_extra.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/metacommands/test_pg_upsert.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/metacommands/test_row_count.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/metacommands/test_show_scripts.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/scripts/__init__.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/scripts/fixtures/control_flow.sql +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/scripts/fixtures/io_roundtrip.sql +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/scripts/fixtures/parse_only/parse_tree.sql +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/scripts/fixtures/smoke.sql +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/scripts/test_sql_scripts.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/test_api.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/test_ast.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/test_config.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/test_config_data.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/test_config_extended.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/test_debug_repl.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/test_engine.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/test_error_messages.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/test_exceptions.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/test_mail.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/test_models.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/test_package.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/test_parser.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/test_parser_params.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/test_plugins.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/test_registry.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/test_script.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/test_state.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/test_types.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/utils/__init__.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/utils/test_auth.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/utils/test_auth_extra.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/utils/test_crypto.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/utils/test_datetime.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/utils/test_errors.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/utils/test_errors_extra.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/utils/test_fileio.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/utils/test_fileio_extra.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/utils/test_numeric.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/utils/test_regex.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/utils/test_strings.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/utils/test_timer.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/tests/utils/test_timer_extra.py +0 -0
- {execsql2-2.16.12 → execsql2-2.16.14}/zensical.toml +0 -0
|
@@ -13,12 +13,55 @@ ______________________________________________________________________
|
|
|
13
13
|
|
|
14
14
|
______________________________________________________________________
|
|
15
15
|
|
|
16
|
+
## [2.16.14] - 2026-05-01
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- ELSEIF conditions now support ANDIF/ORIF modifiers. Previously, ANDIF/ORIF after an ELSEIF were silently attached to the parent IF condition instead of the ELSEIF clause, meaning the compound condition was never evaluated correctly. ELSEIF + ANDIF/ORIF now works the same way as IF + ANDIF/ORIF.
|
|
21
|
+
- Unknown AST node types now raise an error instead of being silently ignored during execution.
|
|
22
|
+
- Cursor leak in `select_rowsource()` and `select_rowdict()`: cursor is now closed on query execution failure. High-traffic callers (EXPORT, COPY) now explicitly close the row generator on error instead of relying on garbage collection.
|
|
23
|
+
|
|
24
|
+
______________________________________________________________________
|
|
25
|
+
|
|
26
|
+
## [2.16.13] - 2026-05-01
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- `execsql-format`: The `--indent` flag now controls SQL indentation in addition to metacommand indentation. Previously only metacommand depth was affected; now sqlglot's `pad` and `indent` parameters follow the same value (default 4).
|
|
31
|
+
- `execsql-format`: New `--leading-comma` flag places commas at the start of lines instead of the end (e.g., ` , col2` instead of `col1,`).
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
|
|
35
|
+
- `execsql-format`: Fixed SQL corruption when formatting scripts with comments interleaved within multi-line SQL statements (e.g., `SELECT` with comment lines between columns, `CASE` with comments before `WHEN` clauses). Previously, the formatter split statements at comment boundaries and sent each fragment to sqlglot independently, which produced broken output (commas became semicolons, CASE expressions were split apart, content was silently dropped). The formatter now uses a marker-based round-trip: comments are replaced with inline markers before formatting so sqlglot sees the complete statement, then markers are restored to their original `--` comment style and position in the output. Comments that sqlglot's AST drops (e.g., inside CASE expressions) are detected and re-inserted at the best matching position using token-based heuristics.
|
|
36
|
+
- `execsql-format`: Fixed `/* */` block comments containing `-- !x!` metacommand markers being incorrectly processed as real metacommands. This caused the block comment to be broken apart, with `*/` becoming `* /` and commented-out code being mangled. The formatter now tracks block comment boundaries and skips metacommand processing inside them.
|
|
37
|
+
- `execsql-format`: Fixed blank lines within multi-line SQL statements (e.g., between column groups in a large `SELECT`) incorrectly splitting the statement into separate formatting blocks, causing each fragment to be formatted independently and producing invalid SQL.
|
|
38
|
+
- `execsql-format`: Added safety checks to the sqlglot formatting pass — if sqlglot produces more statements than the input contained or drops significant content, the formatter now falls back to the original text instead of emitting corrupted SQL.
|
|
39
|
+
|
|
40
|
+
______________________________________________________________________
|
|
41
|
+
|
|
16
42
|
## [2.16.12] - 2026-05-01
|
|
17
43
|
|
|
44
|
+
### Changed
|
|
45
|
+
|
|
46
|
+
- Lowered coverage threshold from 90% to 89% — SCRIPT introspection code is tested via subprocess integration tests which don't contribute to in-process coverage, and Windows CI skips TTY/POSIX tests that contribute ~1% on other platforms.
|
|
47
|
+
|
|
48
|
+
### Added
|
|
49
|
+
|
|
50
|
+
- Unit tests for `_parse_param_defs`, `_format_script_signature`, `_format_script_source`, and `SHOW SCRIPTS`/`SHOW SCRIPT` handlers.
|
|
51
|
+
- Parser coverage tests for default parameters and docstring extraction.
|
|
52
|
+
|
|
18
53
|
______________________________________________________________________
|
|
19
54
|
|
|
20
55
|
## [2.16.11] - 2026-05-01
|
|
21
56
|
|
|
57
|
+
### Fixed
|
|
58
|
+
|
|
59
|
+
- Multi-line `/* */` block comment docstrings in `BEGIN SCRIPT` blocks now capture all lines correctly. Previously, the doc collection guard ran on block comment continuation lines, classified them as "non-comment", and stopped doc collection before the block comment handler could process them.
|
|
60
|
+
|
|
61
|
+
### Added
|
|
62
|
+
|
|
63
|
+
- 12 parser tests covering default parameters and docstring extraction (single-line, multi-line, block comments, empty separators, metacommand termination, required-after-optional validation).
|
|
64
|
+
|
|
22
65
|
______________________________________________________________________
|
|
23
66
|
|
|
24
67
|
## [2.16.10] - 2026-05-01
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: execsql2
|
|
3
|
-
Version: 2.16.
|
|
3
|
+
Version: 2.16.14
|
|
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
|
|
@@ -93,9 +93,9 @@ New options in `execsql.conf`:
|
|
|
93
93
|
|
|
94
94
|
### Tools
|
|
95
95
|
|
|
96
|
-
| Tool | Description
|
|
97
|
-
| ---------------- |
|
|
98
|
-
| `execsql-format` | Standalone CLI for normalizing metacommand indentation and uppercasing SQL keywords. Supports `--check` and `--
|
|
96
|
+
| Tool | Description |
|
|
97
|
+
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
98
|
+
| `execsql-format` | Standalone CLI for normalizing metacommand indentation and uppercasing SQL keywords. Supports `--check`, `--in-place`, `--indent N` (controls both metacommand and SQL indentation), and `--leading-comma` (commas at start of lines) modes. Also available as a [pre-commit hook](../guides/formatter.md). |
|
|
99
99
|
|
|
100
100
|
### GUI
|
|
101
101
|
|
|
@@ -310,6 +310,8 @@ These are behavioral changes driven by security or correctness issues in the ups
|
|
|
310
310
|
| Empty script name in error msg | `_execute_script_direct()` and `_execute_script_textual_console()` no longer append "in script , line 0" to uncaught-exception messages when `current_script_line()` returns an empty string. |
|
|
311
311
|
| `PROMPT COMPARE` diff comparison | Diff engine uses native Python equality instead of string comparison — numeric types, Decimals, and booleans compare correctly. `None` is distinguished from empty string. Columns are matched by name (not position), key columns are excluded from comparison, and duplicate PKs keep the first row. |
|
|
312
312
|
| `win_config_file` broken | Checked `os.name == "windows"` which Python never returns (correct value is `"nt"`). Fixed to `os.name == "nt"`. Inherited from upstream. |
|
|
313
|
+
| ELSEIF + ANDIF/ORIF | ANDIF/ORIF after an ELSEIF were silently attached to the parent IF condition instead of the ELSEIF clause. The compound condition was never evaluated for the ELSEIF branch. Fixed in the AST parser and executor. |
|
|
314
|
+
| Cursor leak in `select_rowsource()` | Cursor was not closed on query execution failure. Row generators in EXPORT and COPY paths were not explicitly closed on error, relying on garbage collection for cleanup. |
|
|
313
315
|
| `NumericParser` right-associative | Arithmetic operators were parsed right-to-left. `10 - 3 - 2` evaluated as `9` instead of `5`. Fixed to left-associative parsing. Inherited from upstream. |
|
|
314
316
|
| Empty-column check precedence | `DataTable` and `Database.populate_table()` had an operator precedence bug in the extra-column emptiness check — a redundant `and conf.del_empty_cols` caused incorrect short-circuit evaluation. Inherited from upstream. |
|
|
315
317
|
| SQLite import string processing | `SQLiteDatabase.populate_table()` applied `trim_strings`, `replace_newlines`, and `empty_strings` after copying row data, so processing never reached the INSERT. Fixed to process before extraction. Inherited from upstream. |
|
|
@@ -24,13 +24,14 @@ By default, formatted output is written to stdout. Use `--in-place` to overwrite
|
|
|
24
24
|
|
|
25
25
|
### Options { #options }
|
|
26
26
|
|
|
27
|
-
| Option | Default | Description
|
|
28
|
-
| ------------------ | -------- |
|
|
29
|
-
| `FILE_OR_DIR` | required | One or more files or directories to format. Directories are searched recursively for `*.sql` files.
|
|
30
|
-
| `--check` | off | Exit with code 1 if any file would be reformatted. Does not write any changes. Useful in CI.
|
|
31
|
-
| `-i`, `--in-place` | off | Modify files in place instead of writing to stdout.
|
|
32
|
-
| `--no-sql` | off | Skip SQL reformatting via sqlglot. Only normalizes metacommand indentation and keyword casing.
|
|
33
|
-
| `--indent N` | `4` |
|
|
27
|
+
| Option | Default | Description |
|
|
28
|
+
| ------------------ | -------- | -------------------------------------------------------------------------------------------------------------- |
|
|
29
|
+
| `FILE_OR_DIR` | required | One or more files or directories to format. Directories are searched recursively for `*.sql` files. |
|
|
30
|
+
| `--check` | off | Exit with code 1 if any file would be reformatted. Does not write any changes. Useful in CI. |
|
|
31
|
+
| `-i`, `--in-place` | off | Modify files in place instead of writing to stdout. |
|
|
32
|
+
| `--no-sql` | off | Skip SQL reformatting via sqlglot. Only normalizes metacommand indentation and keyword casing. |
|
|
33
|
+
| `--indent N` | `4` | Spaces per indent level. Controls both metacommand block depth and SQL indentation (columns, subqueries, etc). |
|
|
34
|
+
| `--leading-comma` | off | Place commas at the start of lines instead of the end (e.g. ` , col2` instead of `col1,`). |
|
|
34
35
|
|
|
35
36
|
## What Gets Formatted { #what-gets-formatted }
|
|
36
37
|
|
|
@@ -64,11 +65,28 @@ Metacommands that open a block (`IF`, `LOOP`, `BEGIN SCRIPT`, `BEGIN BATCH`, `BE
|
|
|
64
65
|
|
|
65
66
|
### SQL block formatting { #sql-formatting }
|
|
66
67
|
|
|
67
|
-
SQL statements between metacommands are re-indented to match the current block depth and reformatted using [sqlglot](https://sqlglot.com/) in PostgreSQL dialect with pretty-printing enabled.
|
|
68
|
+
SQL statements between metacommands are re-indented to match the current block depth and reformatted using [sqlglot](https://sqlglot.com/) in PostgreSQL dialect with pretty-printing enabled.
|
|
68
69
|
|
|
69
|
-
|
|
70
|
+
The `--indent` flag controls SQL indentation in addition to metacommand depth. For example, `--indent 4` (the default) produces 4-space indented column lists, subqueries, and CASE branches. `--indent 2` gives a more compact style.
|
|
70
71
|
|
|
71
|
-
|
|
72
|
+
#### Comment handling
|
|
73
|
+
|
|
74
|
+
Comments interleaved within SQL statements (e.g. `--` comments between SELECT columns, or inside CASE expressions) are preserved through formatting using a marker-based round-trip:
|
|
75
|
+
|
|
76
|
+
1. Each comment line is replaced with a unique inline marker attached to the next SQL line.
|
|
77
|
+
1. sqlglot formats the complete statement (no fragmentation).
|
|
78
|
+
1. Markers are restored to their original `--` comment style and position.
|
|
79
|
+
1. Comments that sqlglot's AST drops (e.g. inside CASE WHEN) are detected and re-inserted at the best matching position.
|
|
80
|
+
|
|
81
|
+
Block comments (`/* */`) that contain `-- !x!` metacommand markers (e.g. commented-out code blocks) are recognized and passed through without metacommand processing.
|
|
82
|
+
|
|
83
|
+
#### Variable preservation
|
|
84
|
+
|
|
85
|
+
execsql substitution variables (`!!varname!!`, `!{varname}!`) are replaced with valid SQL identifiers before formatting, then restored afterward, so the formatter does not corrupt them — including in schema-qualified names (`!!staging!!.!!table!!`), CASE expressions, JOIN conditions, and string concatenation.
|
|
86
|
+
|
|
87
|
+
#### Fallback behavior
|
|
88
|
+
|
|
89
|
+
If sqlglot cannot parse a SQL statement, or if safety checks detect that formatting would corrupt the SQL (e.g. statement count changes, significant content loss), the original text is preserved unchanged.
|
|
72
90
|
|
|
73
91
|
Use `--no-sql` to skip SQL reformatting entirely and only normalize metacommands.
|
|
74
92
|
|
|
@@ -112,6 +130,22 @@ Exit code is `0` if all files are already formatted, `1` if any file would chang
|
|
|
112
130
|
execsql-format --indent 2 --in-place myscript.sql
|
|
113
131
|
```
|
|
114
132
|
|
|
133
|
+
### Use leading commas
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
execsql-format --leading-comma --in-place myscript.sql
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
This places commas at the start of each line instead of the end:
|
|
140
|
+
|
|
141
|
+
```sql
|
|
142
|
+
SELECT
|
|
143
|
+
a
|
|
144
|
+
, b
|
|
145
|
+
, c
|
|
146
|
+
FROM t;
|
|
147
|
+
```
|
|
148
|
+
|
|
115
149
|
### Skip SQL reformatting
|
|
116
150
|
|
|
117
151
|
Format only metacommand indentation and casing, leaving SQL statements untouched:
|
|
@@ -143,13 +177,14 @@ select id,name,created_at from users where active = true order by name;
|
|
|
143
177
|
-- !x! IF(EQUAL(!!schema!!, "public"))
|
|
144
178
|
-- !x! WRITE "Checking public schema..."
|
|
145
179
|
SELECT
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
180
|
+
id,
|
|
181
|
+
name,
|
|
182
|
+
created_at
|
|
149
183
|
FROM users
|
|
150
184
|
WHERE
|
|
151
|
-
|
|
152
|
-
ORDER BY
|
|
185
|
+
active = TRUE
|
|
186
|
+
ORDER BY
|
|
187
|
+
name;
|
|
153
188
|
-- !x! ENDIF
|
|
154
189
|
```
|
|
155
190
|
|
|
@@ -180,6 +215,10 @@ The hook runs on `*.sql` files. Pass any CLI options via `args`:
|
|
|
180
215
|
# Custom indent width
|
|
181
216
|
- id: execsql-format
|
|
182
217
|
args: [--in-place, --indent, "2"]
|
|
218
|
+
|
|
219
|
+
# Leading commas
|
|
220
|
+
- id: execsql-format
|
|
221
|
+
args: [--in-place, --leading-comma]
|
|
183
222
|
```
|
|
184
223
|
|
|
185
224
|
## Exit Codes { #exit-codes }
|
|
@@ -1372,7 +1372,7 @@ ENDIF
|
|
|
1372
1372
|
|
|
1373
1373
|
Multiple ELSEIF clauses can be used within a single multi-line IF metacommand. An ELSE clause can be used in combination with ELSEIF clauses, but this is not recommended because the results are not likely to be what you expect---the ELSE keyword only inverts the current truth state, it does not provide an alternative to all preceding ELSEIF clauses. To achieve the effect of a case or switch statement, use only ELSEIF clauses without a final ELSE clause.
|
|
1374
1374
|
|
|
1375
|
-
The ANDIF metacommand allows you to test for the conjunction of two conditional expressions using two separate metacommands instead of one. This may be beneficial for clarity. The simplest form of usage of the ANDIF clause is:
|
|
1375
|
+
The ANDIF metacommand allows you to test for the conjunction of two conditional expressions using two separate metacommands instead of one. This may be beneficial for clarity. ANDIF and ORIF can follow either an IF or an ELSEIF metacommand. The simplest form of usage of the ANDIF clause is:
|
|
1376
1376
|
|
|
1377
1377
|
```
|
|
1378
1378
|
IF(<conditional expression>)
|
|
@@ -1381,7 +1381,7 @@ ANDIF(<conditional expression>)
|
|
|
1381
1381
|
ENDIF
|
|
1382
1382
|
```
|
|
1383
1383
|
|
|
1384
|
-
The ANDIF metacommand does not have to immediately follow the IF metacommand. It could instead follow an
|
|
1384
|
+
The ANDIF metacommand does not have to immediately follow the IF metacommand. It could instead follow an ELSEIF statement. Usage patterns other than those illustrated here may be difficult to interpret, however, and nested IF metacommands may be preferable to complex uses of the ANDIF clause.
|
|
1385
1385
|
|
|
1386
1386
|
The ORIF metacommand is similar to the ANDIF clause, but allows you to test for the disjunction of two conditional expressions using two different metacommands. The simplest form of usage of the ORIF clause is:
|
|
1387
1387
|
|
|
@@ -1392,6 +1392,17 @@ ORIF(<conditional expression>)
|
|
|
1392
1392
|
ENDIF
|
|
1393
1393
|
```
|
|
1394
1394
|
|
|
1395
|
+
ANDIF and ORIF can also compound an ELSEIF condition:
|
|
1396
|
+
|
|
1397
|
+
```
|
|
1398
|
+
IF(<conditional expression>)
|
|
1399
|
+
<SQL statements and metacommands>
|
|
1400
|
+
ELSEIF(<conditional expression>)
|
|
1401
|
+
ANDIF(<conditional expression>)
|
|
1402
|
+
<SQL statements and metacommands>
|
|
1403
|
+
ENDIF
|
|
1404
|
+
```
|
|
1405
|
+
|
|
1395
1406
|
The IF metacommands can be used not only to control a single stream of script commands, but also to loop over sets of SQL statements and metacommands, as shown in [Example 6](../guides/examples.md#example6).
|
|
1396
1407
|
|
|
1397
1408
|
The IF metacommands cannot be used within a SQL statement (nor can any other metacommands). This restriction prohibits constructions such as:
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "execsql2"
|
|
7
|
-
version = "2.16.
|
|
7
|
+
version = "2.16.14"
|
|
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" }
|
|
@@ -165,7 +165,7 @@ skip-magic-trailing-comma = false
|
|
|
165
165
|
line-ending = "auto"
|
|
166
166
|
|
|
167
167
|
[tool.bumpversion]
|
|
168
|
-
current_version = "2.16.
|
|
168
|
+
current_version = "2.16.14"
|
|
169
169
|
commit = true
|
|
170
170
|
tag = true
|
|
171
171
|
tag_name = "v{new_version}"
|
|
@@ -226,6 +226,7 @@ class Database(ABC):
|
|
|
226
226
|
try:
|
|
227
227
|
curs.execute(sql)
|
|
228
228
|
except Exception:
|
|
229
|
+
curs.close()
|
|
229
230
|
self.rollback()
|
|
230
231
|
raise
|
|
231
232
|
try:
|
|
@@ -264,6 +265,7 @@ class Database(ABC):
|
|
|
264
265
|
try:
|
|
265
266
|
curs.execute(sql)
|
|
266
267
|
except Exception:
|
|
268
|
+
curs.close()
|
|
267
269
|
self.rollback()
|
|
268
270
|
raise
|
|
269
271
|
try:
|