execsql2 2.34.0__tar.gz → 2.35.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.
Files changed (584) hide show
  1. {execsql2-2.34.0 → execsql2-2.35.0}/CHANGELOG.md +16 -0
  2. {execsql2-2.34.0 → execsql2-2.35.0}/CONTRIBUTING.md +13 -0
  3. {execsql2-2.34.0 → execsql2-2.35.0}/PKG-INFO +2 -2
  4. {execsql2-2.34.0 → execsql2-2.35.0}/README.md +1 -1
  5. {execsql2-2.34.0 → execsql2-2.35.0}/docs/about/divergence.md +5 -0
  6. {execsql2-2.34.0 → execsql2-2.35.0}/docs/guides/formatter.md +1 -1
  7. {execsql2-2.34.0 → execsql2-2.35.0}/docs/reference/configuration.md +4 -0
  8. {execsql2-2.34.0 → execsql2-2.35.0}/docs/reference/lint.md +1 -1
  9. {execsql2-2.34.0 → execsql2-2.35.0}/docs/reference/metacommands.md +15 -0
  10. {execsql2-2.34.0 → execsql2-2.35.0}/extras/vscode-execsql/package-lock.json +2 -2
  11. {execsql2-2.34.0 → execsql2-2.35.0}/extras/vscode-execsql/package.json +1 -1
  12. {execsql2-2.34.0 → execsql2-2.35.0}/extras/vscode-execsql/syntaxes/execsql.tmLanguage.json +1 -1
  13. {execsql2-2.34.0 → execsql2-2.35.0}/pyproject.toml +2 -2
  14. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/api.py +1 -0
  15. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/config.py +2 -0
  16. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/data/execsql.conf.template +7 -0
  17. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/metacommands/data.py +7 -1
  18. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/metacommands/dispatch.py +7 -0
  19. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/metacommands/reference.py +1 -0
  20. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/models.py +30 -4
  21. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/script/executor.py +10 -10
  22. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/utils/errors.py +2 -2
  23. {execsql2-2.34.0 → execsql2-2.35.0}/tests/conftest.py +1 -0
  24. execsql2-2.35.0/tests/corpus/cases/batch_and_autocommit/script.sql +16 -0
  25. execsql2-2.35.0/tests/corpus/cases/boolean_and_empty_config/data.csv +4 -0
  26. execsql2-2.35.0/tests/corpus/cases/boolean_and_empty_config/script.sql +13 -0
  27. execsql2-2.35.0/tests/corpus/cases/copy_between_databases/script.sql +17 -0
  28. execsql2-2.35.0/tests/corpus/cases/counters/script.sql +11 -0
  29. execsql2-2.35.0/tests/corpus/cases/decimal_digits/long.csv +3 -0
  30. execsql2-2.35.0/tests/corpus/cases/decimal_digits/script.sql +3 -0
  31. execsql2-2.35.0/tests/corpus/cases/decimal_digits/short.csv +4 -0
  32. execsql2-2.35.0/tests/corpus/cases/error_halt_off/script.sql +13 -0
  33. execsql2-2.35.0/tests/corpus/cases/error_stops_script/script.sql +7 -0
  34. execsql2-2.35.0/tests/corpus/cases/execute_script_args/script.sql +21 -0
  35. execsql2-2.35.0/tests/corpus/cases/export_query_append/script.sql +8 -0
  36. execsql2-2.35.0/tests/corpus/cases/export_structured_formats/script.sql +7 -0
  37. execsql2-2.35.0/tests/corpus/cases/export_text_formats/script.sql +9 -0
  38. execsql2-2.35.0/tests/corpus/cases/halt_exit_status/script.sql +5 -0
  39. execsql2-2.35.0/tests/corpus/cases/if_conditions/script.sql +42 -0
  40. execsql2-2.35.0/tests/corpus/cases/import_csv_existing/data.csv +3 -0
  41. execsql2-2.35.0/tests/corpus/cases/import_csv_existing/script.sql +6 -0
  42. execsql2-2.35.0/tests/corpus/cases/import_csv_new/data.csv +4 -0
  43. execsql2-2.35.0/tests/corpus/cases/import_csv_new/data.tsv +3 -0
  44. execsql2-2.35.0/tests/corpus/cases/import_csv_new/script.sql +4 -0
  45. execsql2-2.35.0/tests/corpus/cases/include_file/part.sql +3 -0
  46. execsql2-2.35.0/tests/corpus/cases/include_file/script.sql +6 -0
  47. execsql2-2.35.0/tests/corpus/cases/loop_while_until/script.sql +28 -0
  48. execsql2-2.35.0/tests/corpus/cases/on_error_halt_write/script.sql +7 -0
  49. execsql2-2.35.0/tests/corpus/cases/select_sub_subdata/script.sql +9 -0
  50. execsql2-2.35.0/tests/corpus/cases/sub_backslash/script.sql +7 -0
  51. execsql2-2.35.0/tests/corpus/cases/sub_basic/script.sql +18 -0
  52. execsql2-2.35.0/tests/corpus/cases/sub_quoting/script.sql +6 -0
  53. execsql2-2.35.0/tests/corpus/cases/sub_quoting_upstream_idiom/script.sql +6 -0
  54. execsql2-2.35.0/tests/corpus/cases/unsubstituted_warning/script.sql +7 -0
  55. execsql2-2.35.0/tests/corpus/cases/write_console/script.sql +6 -0
  56. execsql2-2.35.0/tests/corpus/cases/write_create_table/data.csv +3 -0
  57. execsql2-2.35.0/tests/corpus/cases/write_create_table/script.sql +2 -0
  58. execsql2-2.35.0/tests/corpus/changes.json +513 -0
  59. execsql2-2.35.0/tests/corpus/record.py +53 -0
  60. execsql2-2.35.0/tests/corpus/results/batch_and_autocommit.json +37 -0
  61. execsql2-2.35.0/tests/corpus/results/boolean_and_empty_config.json +389 -0
  62. execsql2-2.35.0/tests/corpus/results/copy_between_databases.json +355 -0
  63. execsql2-2.35.0/tests/corpus/results/counters.json +55 -0
  64. execsql2-2.35.0/tests/corpus/results/decimal_digits.json +10 -0
  65. execsql2-2.35.0/tests/corpus/results/error_halt_off.json +39 -0
  66. execsql2-2.35.0/tests/corpus/results/error_stops_script.json +27 -0
  67. execsql2-2.35.0/tests/corpus/results/execute_script_args.json +51 -0
  68. execsql2-2.35.0/tests/corpus/results/export_query_append.json +58 -0
  69. execsql2-2.35.0/tests/corpus/results/export_structured_formats.json +72 -0
  70. execsql2-2.35.0/tests/corpus/results/export_text_formats.json +92 -0
  71. execsql2-2.35.0/tests/corpus/results/halt_exit_status.json +25 -0
  72. execsql2-2.35.0/tests/corpus/results/if_conditions.json +33 -0
  73. execsql2-2.35.0/tests/corpus/results/import_csv_existing.json +113 -0
  74. execsql2-2.35.0/tests/corpus/results/import_csv_new.json +183 -0
  75. execsql2-2.35.0/tests/corpus/results/include_file.json +33 -0
  76. execsql2-2.35.0/tests/corpus/results/loop_while_until.json +51 -0
  77. execsql2-2.35.0/tests/corpus/results/on_error_halt_write.json +20 -0
  78. execsql2-2.35.0/tests/corpus/results/select_sub_subdata.json +45 -0
  79. execsql2-2.35.0/tests/corpus/results/sub_backslash.json +18 -0
  80. execsql2-2.35.0/tests/corpus/results/sub_basic.json +45 -0
  81. execsql2-2.35.0/tests/corpus/results/sub_quoting.json +22 -0
  82. execsql2-2.35.0/tests/corpus/results/sub_quoting_upstream_idiom.json +27 -0
  83. execsql2-2.35.0/tests/corpus/results/unsubstituted_warning.json +27 -0
  84. execsql2-2.35.0/tests/corpus/results/write_console.json +10 -0
  85. execsql2-2.35.0/tests/corpus/results/write_create_table.json +10 -0
  86. execsql2-2.35.0/tests/corpus/runner.py +138 -0
  87. execsql2-2.35.0/tests/corpus/test_script_corpus.py +74 -0
  88. {execsql2-2.34.0 → execsql2-2.35.0}/tests/data/lint/every_metacommand.sql +1 -0
  89. {execsql2-2.34.0 → execsql2-2.35.0}/tests/security/test_log_secrets.py +3 -1
  90. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_models.py +54 -32
  91. execsql2-2.35.0/tests/utils/__init__.py +0 -0
  92. {execsql2-2.34.0 → execsql2-2.35.0}/uv.lock +1 -1
  93. {execsql2-2.34.0 → execsql2-2.35.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  94. {execsql2-2.34.0 → execsql2-2.35.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  95. {execsql2-2.34.0 → execsql2-2.35.0}/.github/dependabot.yml +0 -0
  96. {execsql2-2.34.0 → execsql2-2.35.0}/.github/workflows/ci-cd.yml +0 -0
  97. {execsql2-2.34.0 → execsql2-2.35.0}/.gitignore +0 -0
  98. {execsql2-2.34.0 → execsql2-2.35.0}/.pre-commit-config.yaml +0 -0
  99. {execsql2-2.34.0 → execsql2-2.35.0}/.pre-commit-hooks.yaml +0 -0
  100. {execsql2-2.34.0 → execsql2-2.35.0}/.python-version +0 -0
  101. {execsql2-2.34.0 → execsql2-2.35.0}/.readthedocs.yaml +0 -0
  102. {execsql2-2.34.0 → execsql2-2.35.0}/LICENSE.txt +0 -0
  103. {execsql2-2.34.0 → execsql2-2.35.0}/NOTICE +0 -0
  104. {execsql2-2.34.0 → execsql2-2.35.0}/SECURITY.md +0 -0
  105. {execsql2-2.34.0 → execsql2-2.35.0}/docs/about/contributors.md +0 -0
  106. {execsql2-2.34.0 → execsql2-2.35.0}/docs/about/copyright.md +0 -0
  107. {execsql2-2.34.0 → execsql2-2.35.0}/docs/api/cli.md +0 -0
  108. {execsql2-2.34.0 → execsql2-2.35.0}/docs/api/db.md +0 -0
  109. {execsql2-2.34.0 → execsql2-2.35.0}/docs/api/exporters.md +0 -0
  110. {execsql2-2.34.0 → execsql2-2.35.0}/docs/api/importers.md +0 -0
  111. {execsql2-2.34.0 → execsql2-2.35.0}/docs/api/index.md +0 -0
  112. {execsql2-2.34.0 → execsql2-2.35.0}/docs/api/metacommands.md +0 -0
  113. {execsql2-2.34.0 → execsql2-2.35.0}/docs/dev/adding_db_adapters.md +0 -0
  114. {execsql2-2.34.0 → execsql2-2.35.0}/docs/dev/adding_exporters.md +0 -0
  115. {execsql2-2.34.0 → execsql2-2.35.0}/docs/dev/adding_importers.md +0 -0
  116. {execsql2-2.34.0 → execsql2-2.35.0}/docs/dev/adding_metacommands.md +0 -0
  117. {execsql2-2.34.0 → execsql2-2.35.0}/docs/dev/architecture.md +0 -0
  118. {execsql2-2.34.0 → execsql2-2.35.0}/docs/dev/releasing.md +0 -0
  119. {execsql2-2.34.0 → execsql2-2.35.0}/docs/getting-started/installation.md +0 -0
  120. {execsql2-2.34.0 → execsql2-2.35.0}/docs/getting-started/requirements.md +0 -0
  121. {execsql2-2.34.0 → execsql2-2.35.0}/docs/getting-started/syntax.md +0 -0
  122. {execsql2-2.34.0 → execsql2-2.35.0}/docs/guides/debugging.md +0 -0
  123. {execsql2-2.34.0 → execsql2-2.35.0}/docs/guides/documentation.md +0 -0
  124. {execsql2-2.34.0 → execsql2-2.35.0}/docs/guides/editors.md +0 -0
  125. {execsql2-2.34.0 → execsql2-2.35.0}/docs/guides/encoding.md +0 -0
  126. {execsql2-2.34.0 → execsql2-2.35.0}/docs/guides/examples.md +0 -0
  127. {execsql2-2.34.0 → execsql2-2.35.0}/docs/guides/logging.md +0 -0
  128. {execsql2-2.34.0 → execsql2-2.35.0}/docs/guides/sql_syntax.md +0 -0
  129. {execsql2-2.34.0 → execsql2-2.35.0}/docs/guides/usage.md +0 -0
  130. {execsql2-2.34.0 → execsql2-2.35.0}/docs/guides/using_scripts.md +0 -0
  131. {execsql2-2.34.0 → execsql2-2.35.0}/docs/images/Compare_planets.png +0 -0
  132. {execsql2-2.34.0 → execsql2-2.35.0}/docs/images/actions.png +0 -0
  133. {execsql2-2.34.0 → execsql2-2.35.0}/docs/images/actions2.png +0 -0
  134. {execsql2-2.34.0 → execsql2-2.35.0}/docs/images/checkboxes.png +0 -0
  135. {execsql2-2.34.0 → execsql2-2.35.0}/docs/images/connect.png +0 -0
  136. {execsql2-2.34.0 → execsql2-2.35.0}/docs/images/data_error1_screenshot.jpg +0 -0
  137. {execsql2-2.34.0 → execsql2-2.35.0}/docs/images/execsql_logo_01.png +0 -0
  138. {execsql2-2.34.0 → execsql2-2.35.0}/docs/images/fatals.png +0 -0
  139. {execsql2-2.34.0 → execsql2-2.35.0}/docs/images/pause_terminal_sm.png +0 -0
  140. {execsql2-2.34.0 → execsql2-2.35.0}/docs/images/set_build_commands.jpg +0 -0
  141. {execsql2-2.34.0 → execsql2-2.35.0}/docs/images/unit_conversions_029.png +0 -0
  142. {execsql2-2.34.0 → execsql2-2.35.0}/docs/images/unmatched.png +0 -0
  143. {execsql2-2.34.0 → execsql2-2.35.0}/docs/images/vim_execsql_highlight.png +0 -0
  144. {execsql2-2.34.0 → execsql2-2.35.0}/docs/index.md +0 -0
  145. {execsql2-2.34.0 → execsql2-2.35.0}/docs/reference/security.md +0 -0
  146. {execsql2-2.34.0 → execsql2-2.35.0}/docs/reference/substitution_vars.md +0 -0
  147. {execsql2-2.34.0 → execsql2-2.35.0}/docs/templates/compare.md +0 -0
  148. {execsql2-2.34.0 → execsql2-2.35.0}/docs/templates/glossary.md +0 -0
  149. {execsql2-2.34.0 → execsql2-2.35.0}/docs/templates/index.md +0 -0
  150. {execsql2-2.34.0 → execsql2-2.35.0}/docs/templates/upsert.md +0 -0
  151. {execsql2-2.34.0 → execsql2-2.35.0}/extras/plugin-template/README.md +0 -0
  152. {execsql2-2.34.0 → execsql2-2.35.0}/extras/plugin-template/pyproject.toml +0 -0
  153. {execsql2-2.34.0 → execsql2-2.35.0}/extras/plugin-template/src/execsql_plugin_YOURNAME/__init__.py +0 -0
  154. {execsql2-2.34.0 → execsql2-2.35.0}/extras/plugin-template/tests/test_plugin.py.example +0 -0
  155. {execsql2-2.34.0 → execsql2-2.35.0}/extras/vscode-execsql/.vscodeignore +0 -0
  156. {execsql2-2.34.0 → execsql2-2.35.0}/extras/vscode-execsql/LICENSE.txt +0 -0
  157. {execsql2-2.34.0 → execsql2-2.35.0}/extras/vscode-execsql/README.md +0 -0
  158. {execsql2-2.34.0 → execsql2-2.35.0}/extras/vscode-execsql/extension.js +0 -0
  159. {execsql2-2.34.0 → execsql2-2.35.0}/extras/vscode-execsql/icon.png +0 -0
  160. {execsql2-2.34.0 → execsql2-2.35.0}/justfile +0 -0
  161. {execsql2-2.34.0 → execsql2-2.35.0}/scripts/benchmarks/README.md +0 -0
  162. {execsql2-2.34.0 → execsql2-2.35.0}/scripts/benchmarks/results/.gitignore +0 -0
  163. {execsql2-2.34.0 → execsql2-2.35.0}/scripts/benchmarks/run_benchmarks.py +0 -0
  164. {execsql2-2.34.0 → execsql2-2.35.0}/scripts/generate_vscode_grammar.py +0 -0
  165. {execsql2-2.34.0 → execsql2-2.35.0}/scripts/release_notes.py +0 -0
  166. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/__init__.py +0 -0
  167. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/__main__.py +0 -0
  168. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/cli/__init__.py +0 -0
  169. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/cli/application.py +0 -0
  170. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/cli/commands/__init__.py +0 -0
  171. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/cli/commands/config.py +0 -0
  172. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/cli/commands/format.py +0 -0
  173. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/cli/commands/init.py +0 -0
  174. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/cli/commands/lint.py +0 -0
  175. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/cli/commands/listing.py +0 -0
  176. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/cli/commands/lsp.py +0 -0
  177. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/cli/commands/run.py +0 -0
  178. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/cli/dispatch.py +0 -0
  179. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/cli/dsn.py +0 -0
  180. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/cli/help.py +0 -0
  181. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/cli/lint.py +0 -0
  182. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/cli/options.py +0 -0
  183. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/cli/run.py +0 -0
  184. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/config_validation.py +0 -0
  185. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/data/__init__.py +0 -0
  186. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/data/script_header.sql +0 -0
  187. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/db/__init__.py +0 -0
  188. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/db/access.py +0 -0
  189. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/db/base.py +0 -0
  190. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/db/dsn.py +0 -0
  191. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/db/duckdb.py +0 -0
  192. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/db/factory.py +0 -0
  193. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/db/firebird.py +0 -0
  194. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/db/mysql.py +0 -0
  195. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/db/odbc.py +0 -0
  196. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/db/oracle.py +0 -0
  197. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/db/postgres.py +0 -0
  198. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/db/sqlite.py +0 -0
  199. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/db/sqlserver.py +0 -0
  200. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/db/target_types.py +0 -0
  201. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/db/tiers.py +0 -0
  202. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/debug/__init__.py +0 -0
  203. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/debug/repl.py +0 -0
  204. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/exceptions.py +0 -0
  205. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/exporters/__init__.py +0 -0
  206. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/exporters/base.py +0 -0
  207. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/exporters/delimited.py +0 -0
  208. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/exporters/duckdb.py +0 -0
  209. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/exporters/feather.py +0 -0
  210. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/exporters/html.py +0 -0
  211. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/exporters/json.py +0 -0
  212. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/exporters/latex.py +0 -0
  213. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/exporters/markdown.py +0 -0
  214. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/exporters/ods.py +0 -0
  215. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/exporters/parquet.py +0 -0
  216. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/exporters/pretty.py +0 -0
  217. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/exporters/protocol.py +0 -0
  218. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/exporters/raw.py +0 -0
  219. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/exporters/sqlite.py +0 -0
  220. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/exporters/templates.py +0 -0
  221. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/exporters/values.py +0 -0
  222. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/exporters/xls.py +0 -0
  223. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/exporters/xlsx.py +0 -0
  224. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/exporters/xml.py +0 -0
  225. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/exporters/yaml.py +0 -0
  226. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/exporters/zip.py +0 -0
  227. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/format.py +0 -0
  228. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/gui/__init__.py +0 -0
  229. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/gui/base.py +0 -0
  230. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/gui/console.py +0 -0
  231. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/gui/desktop.py +0 -0
  232. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/gui/tui.py +0 -0
  233. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/importers/__init__.py +0 -0
  234. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/importers/base.py +0 -0
  235. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/importers/csv.py +0 -0
  236. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/importers/feather.py +0 -0
  237. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/importers/json.py +0 -0
  238. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/importers/ods.py +0 -0
  239. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/importers/xls.py +0 -0
  240. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/interactive.py +0 -0
  241. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/lsp/__init__.py +0 -0
  242. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/lsp/_util.py +0 -0
  243. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/lsp/cache.py +0 -0
  244. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/lsp/code_actions.py +0 -0
  245. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/lsp/completion.py +0 -0
  246. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/lsp/diagnostics.py +0 -0
  247. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/lsp/document.py +0 -0
  248. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/lsp/folding.py +0 -0
  249. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/lsp/formatting.py +0 -0
  250. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/lsp/hover.py +0 -0
  251. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/lsp/navigation.py +0 -0
  252. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/lsp/rename.py +0 -0
  253. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/lsp/server.py +0 -0
  254. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/manifest.py +0 -0
  255. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/metacommands/__init__.py +0 -0
  256. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/metacommands/conditions.py +0 -0
  257. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/metacommands/connect.py +0 -0
  258. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/metacommands/control.py +0 -0
  259. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/metacommands/debug.py +0 -0
  260. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/metacommands/effects.py +0 -0
  261. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/metacommands/io.py +0 -0
  262. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/metacommands/io_export.py +0 -0
  263. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/metacommands/io_fileops.py +0 -0
  264. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/metacommands/io_import.py +0 -0
  265. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/metacommands/io_write.py +0 -0
  266. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/metacommands/prompt.py +0 -0
  267. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/metacommands/script_ext.py +0 -0
  268. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/metacommands/system.py +0 -0
  269. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/metacommands/upsert.py +0 -0
  270. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/parser.py +0 -0
  271. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/plugins.py +0 -0
  272. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/py.typed +0 -0
  273. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/script/__init__.py +0 -0
  274. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/script/ast.py +0 -0
  275. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/script/control.py +0 -0
  276. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/script/engine.py +0 -0
  277. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/script/parser.py +0 -0
  278. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/script/variables.py +0 -0
  279. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/state.py +0 -0
  280. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/state.pyi +0 -0
  281. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/types.py +0 -0
  282. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/utils/__init__.py +0 -0
  283. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/utils/auth.py +0 -0
  284. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/utils/color.py +0 -0
  285. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/utils/crypto.py +0 -0
  286. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/utils/datetime.py +0 -0
  287. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/utils/fileio.py +0 -0
  288. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/utils/gui.py +0 -0
  289. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/utils/mail.py +0 -0
  290. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/utils/numeric.py +0 -0
  291. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/utils/paths.py +0 -0
  292. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/utils/regex.py +0 -0
  293. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/utils/strings.py +0 -0
  294. {execsql2-2.34.0 → execsql2-2.35.0}/src/execsql/utils/timer.py +0 -0
  295. {execsql2-2.34.0 → execsql2-2.35.0}/templates/README.md +0 -0
  296. {execsql2-2.34.0 → execsql2-2.35.0}/templates/config_settings.sqlite +0 -0
  297. {execsql2-2.34.0 → execsql2-2.35.0}/templates/example_config_prompt.sql +0 -0
  298. {execsql2-2.34.0 → execsql2-2.35.0}/templates/make_config_db.sql +0 -0
  299. {execsql2-2.34.0 → execsql2-2.35.0}/templates/md_compare.sql +0 -0
  300. {execsql2-2.34.0 → execsql2-2.35.0}/templates/md_glossary.sql +0 -0
  301. {execsql2-2.34.0 → execsql2-2.35.0}/templates/md_upsert.sql +0 -0
  302. {execsql2-2.34.0 → execsql2-2.35.0}/templates/pg_compare.sql +0 -0
  303. {execsql2-2.34.0 → execsql2-2.35.0}/templates/pg_glossary.sql +0 -0
  304. {execsql2-2.34.0 → execsql2-2.35.0}/templates/script_template.sql +0 -0
  305. {execsql2-2.34.0 → execsql2-2.35.0}/templates/ss_compare.sql +0 -0
  306. {execsql2-2.34.0 → execsql2-2.35.0}/templates/ss_glossary.sql +0 -0
  307. {execsql2-2.34.0 → execsql2-2.35.0}/templates/ss_upsert.sql +0 -0
  308. {execsql2-2.34.0 → execsql2-2.35.0}/tests/__init__.py +0 -0
  309. {execsql2-2.34.0 → execsql2-2.35.0}/tests/cli/__init__.py +0 -0
  310. {execsql2-2.34.0 → execsql2-2.35.0}/tests/cli/test_cli.py +0 -0
  311. {execsql2-2.34.0 → execsql2-2.35.0}/tests/cli/test_cli_e2e.py +0 -0
  312. {execsql2-2.34.0 → execsql2-2.35.0}/tests/cli/test_cli_run.py +0 -0
  313. {execsql2-2.34.0 → execsql2-2.35.0}/tests/cli/test_cli_surface.py +0 -0
  314. {execsql2-2.34.0 → execsql2-2.35.0}/tests/cli/test_commands.py +0 -0
  315. {execsql2-2.34.0 → execsql2-2.35.0}/tests/cli/test_config_validate.py +0 -0
  316. {execsql2-2.34.0 → execsql2-2.35.0}/tests/cli/test_dispatch.py +0 -0
  317. {execsql2-2.34.0 → execsql2-2.35.0}/tests/cli/test_error_location.py +0 -0
  318. {execsql2-2.34.0 → execsql2-2.35.0}/tests/cli/test_init.py +0 -0
  319. {execsql2-2.34.0 → execsql2-2.35.0}/tests/cli/test_lint.py +0 -0
  320. {execsql2-2.34.0 → execsql2-2.35.0}/tests/cli/test_lint_fixtures.py +0 -0
  321. {execsql2-2.34.0 → execsql2-2.35.0}/tests/cli/test_log_exit_record.py +0 -0
  322. {execsql2-2.34.0 → execsql2-2.35.0}/tests/cli/test_manifest.py +0 -0
  323. {execsql2-2.34.0 → execsql2-2.35.0}/tests/cli/test_ping.py +0 -0
  324. {execsql2-2.34.0 → execsql2-2.35.0}/tests/cli/test_profile.py +0 -0
  325. {execsql2-2.34.0 → execsql2-2.35.0}/tests/cli/test_sigterm.py +0 -0
  326. {execsql2-2.34.0 → execsql2-2.35.0}/tests/cli/test_undeclared_imports.py +0 -0
  327. {execsql2-2.34.0/tests/db → execsql2-2.35.0/tests/corpus}/__init__.py +0 -0
  328. {execsql2-2.34.0 → execsql2-2.35.0}/tests/data/existing_table_loads/changes.json +0 -0
  329. {execsql2-2.34.0 → execsql2-2.35.0}/tests/data/existing_table_loads/duckdb.json +0 -0
  330. {execsql2-2.34.0 → execsql2-2.35.0}/tests/data/existing_table_loads/mysql.json +0 -0
  331. {execsql2-2.34.0 → execsql2-2.35.0}/tests/data/existing_table_loads/mysql_files.json +0 -0
  332. {execsql2-2.34.0 → execsql2-2.35.0}/tests/data/existing_table_loads/postgres.json +0 -0
  333. {execsql2-2.34.0 → execsql2-2.35.0}/tests/data/existing_table_loads/postgres_files.json +0 -0
  334. {execsql2-2.34.0 → execsql2-2.35.0}/tests/data/existing_table_loads/sqlite.json +0 -0
  335. {execsql2-2.34.0 → execsql2-2.35.0}/tests/data/existing_table_loads/sqlserver.json +0 -0
  336. {execsql2-2.34.0 → execsql2-2.35.0}/tests/data/formatter_shapes/comment_anchoring.sql +0 -0
  337. {execsql2-2.34.0 → execsql2-2.35.0}/tests/data/formatter_shapes/escapes_and_literals.sql +0 -0
  338. {execsql2-2.34.0 → execsql2-2.35.0}/tests/data/formatter_shapes/substitution_and_metacommands.sql +0 -0
  339. {execsql2-2.34.0 → execsql2-2.35.0}/tests/data/formatter_shapes/unparsable_sql.sql +0 -0
  340. {execsql2-2.34.0 → execsql2-2.35.0}/tests/data/lint/conditions_and_blocks.sql +0 -0
  341. {execsql2-2.34.0 → execsql2-2.35.0}/tests/data/lint/does_not_parse.sql +0 -0
  342. {execsql2-2.34.0 → execsql2-2.35.0}/tests/data/lint/invalid.sql +0 -0
  343. {execsql2-2.34.0 → execsql2-2.35.0}/tests/data/ods/libreoffice.fods +0 -0
  344. {execsql2-2.34.0 → execsql2-2.35.0}/tests/data/ods/libreoffice.ods +0 -0
  345. {execsql2-2.34.0/tests/exporters → execsql2-2.35.0/tests/db}/__init__.py +0 -0
  346. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/conftest.py +0 -0
  347. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_access_windows.py +0 -0
  348. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_base.py +0 -0
  349. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_bulk_inserts.py +0 -0
  350. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_copy_new.py +0 -0
  351. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_db_adapters_mocked.py +0 -0
  352. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_db_adapters_mocked_extra.py +0 -0
  353. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_dsn.py +0 -0
  354. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_duckdb.py +0 -0
  355. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_existing_table_loads.py +0 -0
  356. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_factory.py +0 -0
  357. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_factory_postgres_encoding.py +0 -0
  358. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_import_atomic.py +0 -0
  359. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_import_replacement_quoted.py +0 -0
  360. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_import_short_rows.py +0 -0
  361. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_import_timezones.py +0 -0
  362. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_mysql_case_folding.py +0 -0
  363. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_mysql_inprocess.py +0 -0
  364. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_mysql_trailing_blank_lines.py +0 -0
  365. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_new_table_checks.py +0 -0
  366. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_odbc_fresh_sessions.py +0 -0
  367. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_oracle_driver.py +0 -0
  368. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_postgres.py +0 -0
  369. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_postgres_inprocess.py +0 -0
  370. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_quoted_substitution_roundtrip.py +0 -0
  371. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_replacement_missing_table.py +0 -0
  372. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_roundtrip_adapters.py +0 -0
  373. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_sqlite.py +0 -0
  374. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_sqlite_extra.py +0 -0
  375. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_sqlserver_driver18.py +0 -0
  376. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_sqlserver_inprocess.py +0 -0
  377. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_target_types.py +0 -0
  378. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_tiers.py +0 -0
  379. {execsql2-2.34.0 → execsql2-2.35.0}/tests/db/test_transactions.py +0 -0
  380. {execsql2-2.34.0/tests/gui → execsql2-2.35.0/tests/exporters}/__init__.py +0 -0
  381. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/conftest.py +0 -0
  382. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_base.py +0 -0
  383. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_db.py +0 -0
  384. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_delimited.py +0 -0
  385. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_duckdb_exporter.py +0 -0
  386. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_exporters.py +0 -0
  387. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_feather.py +0 -0
  388. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_html_extended.py +0 -0
  389. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_html_latex.py +0 -0
  390. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_json.py +0 -0
  391. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_json_extended.py +0 -0
  392. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_jsonl.py +0 -0
  393. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_latex_extended.py +0 -0
  394. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_markdown.py +0 -0
  395. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_ods.py +0 -0
  396. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_ods_export.py +0 -0
  397. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_parquet.py +0 -0
  398. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_pretty_extended.py +0 -0
  399. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_raw_extended.py +0 -0
  400. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_roundtrip_columnar.py +0 -0
  401. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_roundtrip_dbfile.py +0 -0
  402. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_roundtrip_delimited.py +0 -0
  403. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_roundtrip_json.py +0 -0
  404. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_roundtrip_latex_xml.py +0 -0
  405. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_roundtrip_markup.py +0 -0
  406. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_roundtrip_ods.py +0 -0
  407. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_roundtrip_pretty_raw.py +0 -0
  408. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_roundtrip_template.py +0 -0
  409. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_roundtrip_values.py +0 -0
  410. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_roundtrip_xlsx.py +0 -0
  411. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_sqlite_exporter.py +0 -0
  412. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_templates.py +0 -0
  413. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_templates_extended.py +0 -0
  414. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_values_extended.py +0 -0
  415. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_values_roundtrip.py +0 -0
  416. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_xls_xlsx.py +0 -0
  417. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_xlsx.py +0 -0
  418. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_xml.py +0 -0
  419. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_yaml.py +0 -0
  420. {execsql2-2.34.0 → execsql2-2.35.0}/tests/exporters/test_zip.py +0 -0
  421. {execsql2-2.34.0/tests/importers → execsql2-2.35.0/tests/gui}/__init__.py +0 -0
  422. {execsql2-2.34.0 → execsql2-2.35.0}/tests/gui/test_backends.py +0 -0
  423. {execsql2-2.34.0 → execsql2-2.35.0}/tests/gui/test_backends_extended.py +0 -0
  424. {execsql2-2.34.0 → execsql2-2.35.0}/tests/gui/test_compare_stats.py +0 -0
  425. {execsql2-2.34.0 → execsql2-2.35.0}/tests/gui/test_compute_row_diffs.py +0 -0
  426. {execsql2-2.34.0 → execsql2-2.35.0}/tests/gui/test_desktop_dialogs.py +0 -0
  427. {execsql2-2.34.0 → execsql2-2.35.0}/tests/gui/test_format_table.py +0 -0
  428. {execsql2-2.34.0 → execsql2-2.35.0}/tests/gui/test_tui_pilot.py +0 -0
  429. {execsql2-2.34.0 → execsql2-2.35.0}/tests/gui/test_tui_pilot_complex.py +0 -0
  430. {execsql2-2.34.0 → execsql2-2.35.0}/tests/gui/test_utils_gui_extended.py +0 -0
  431. {execsql2-2.34.0/tests/integration → execsql2-2.35.0/tests/importers}/__init__.py +0 -0
  432. {execsql2-2.34.0 → execsql2-2.35.0}/tests/importers/conftest.py +0 -0
  433. {execsql2-2.34.0 → execsql2-2.35.0}/tests/importers/test_base_extended.py +0 -0
  434. {execsql2-2.34.0 → execsql2-2.35.0}/tests/importers/test_csv_blank_lines.py +0 -0
  435. {execsql2-2.34.0 → execsql2-2.35.0}/tests/importers/test_csv_edge_cases.py +0 -0
  436. {execsql2-2.34.0 → execsql2-2.35.0}/tests/importers/test_csv_importer.py +0 -0
  437. {execsql2-2.34.0 → execsql2-2.35.0}/tests/importers/test_feather_importer.py +0 -0
  438. {execsql2-2.34.0 → execsql2-2.35.0}/tests/importers/test_json_importer.py +0 -0
  439. {execsql2-2.34.0 → execsql2-2.35.0}/tests/importers/test_ods_importer.py +0 -0
  440. {execsql2-2.34.0 → execsql2-2.35.0}/tests/importers/test_ods_values.py +0 -0
  441. {execsql2-2.34.0 → execsql2-2.35.0}/tests/importers/test_roundtrip_csv.py +0 -0
  442. {execsql2-2.34.0 → execsql2-2.35.0}/tests/importers/test_xls_importer.py +0 -0
  443. {execsql2-2.34.0/tests/lsp → execsql2-2.35.0/tests/integration}/__init__.py +0 -0
  444. {execsql2-2.34.0 → execsql2-2.35.0}/tests/integration/conftest.py +0 -0
  445. {execsql2-2.34.0 → execsql2-2.35.0}/tests/integration/test_dsn.py +0 -0
  446. {execsql2-2.34.0 → execsql2-2.35.0}/tests/integration/test_duckdb.py +0 -0
  447. {execsql2-2.34.0 → execsql2-2.35.0}/tests/integration/test_mysql.py +0 -0
  448. {execsql2-2.34.0 → execsql2-2.35.0}/tests/integration/test_postgres.py +0 -0
  449. {execsql2-2.34.0 → execsql2-2.35.0}/tests/integration/test_sqlite.py +0 -0
  450. {execsql2-2.34.0 → execsql2-2.35.0}/tests/live_db.py +0 -0
  451. {execsql2-2.34.0/tests/metacommands → execsql2-2.35.0/tests/lsp}/__init__.py +0 -0
  452. {execsql2-2.34.0 → execsql2-2.35.0}/tests/lsp/test_cache.py +0 -0
  453. {execsql2-2.34.0 → execsql2-2.35.0}/tests/lsp/test_code_actions.py +0 -0
  454. {execsql2-2.34.0 → execsql2-2.35.0}/tests/lsp/test_completion.py +0 -0
  455. {execsql2-2.34.0 → execsql2-2.35.0}/tests/lsp/test_diagnostics.py +0 -0
  456. {execsql2-2.34.0 → execsql2-2.35.0}/tests/lsp/test_document.py +0 -0
  457. {execsql2-2.34.0 → execsql2-2.35.0}/tests/lsp/test_folding.py +0 -0
  458. {execsql2-2.34.0 → execsql2-2.35.0}/tests/lsp/test_formatting.py +0 -0
  459. {execsql2-2.34.0 → execsql2-2.35.0}/tests/lsp/test_hover.py +0 -0
  460. {execsql2-2.34.0 → execsql2-2.35.0}/tests/lsp/test_lsp_command.py +0 -0
  461. {execsql2-2.34.0 → execsql2-2.35.0}/tests/lsp/test_navigation.py +0 -0
  462. {execsql2-2.34.0 → execsql2-2.35.0}/tests/lsp/test_rename.py +0 -0
  463. {execsql2-2.34.0 → execsql2-2.35.0}/tests/lsp/test_server.py +0 -0
  464. {execsql2-2.34.0/tests/scripts → execsql2-2.35.0/tests/metacommands}/__init__.py +0 -0
  465. {execsql2-2.34.0 → execsql2-2.35.0}/tests/metacommands/conftest.py +0 -0
  466. {execsql2-2.34.0 → execsql2-2.35.0}/tests/metacommands/test_assert.py +0 -0
  467. {execsql2-2.34.0 → execsql2-2.35.0}/tests/metacommands/test_breakpoint.py +0 -0
  468. {execsql2-2.34.0 → execsql2-2.35.0}/tests/metacommands/test_conditions_extra.py +0 -0
  469. {execsql2-2.34.0 → execsql2-2.35.0}/tests/metacommands/test_connect.py +0 -0
  470. {execsql2-2.34.0 → execsql2-2.35.0}/tests/metacommands/test_io_export.py +0 -0
  471. {execsql2-2.34.0 → execsql2-2.35.0}/tests/metacommands/test_io_import.py +0 -0
  472. {execsql2-2.34.0 → execsql2-2.35.0}/tests/metacommands/test_metacommands.py +0 -0
  473. {execsql2-2.34.0 → execsql2-2.35.0}/tests/metacommands/test_metacommands_connect.py +0 -0
  474. {execsql2-2.34.0 → execsql2-2.35.0}/tests/metacommands/test_metacommands_data.py +0 -0
  475. {execsql2-2.34.0 → execsql2-2.35.0}/tests/metacommands/test_metacommands_extended.py +0 -0
  476. {execsql2-2.34.0 → execsql2-2.35.0}/tests/metacommands/test_metacommands_fileops_extra.py +0 -0
  477. {execsql2-2.34.0 → execsql2-2.35.0}/tests/metacommands/test_metacommands_io.py +0 -0
  478. {execsql2-2.34.0 → execsql2-2.35.0}/tests/metacommands/test_metacommands_io_write_extra.py +0 -0
  479. {execsql2-2.34.0 → execsql2-2.35.0}/tests/metacommands/test_metacommands_script_ext.py +0 -0
  480. {execsql2-2.34.0 → execsql2-2.35.0}/tests/metacommands/test_metacommands_system.py +0 -0
  481. {execsql2-2.34.0 → execsql2-2.35.0}/tests/metacommands/test_metacommands_system_extra.py +0 -0
  482. {execsql2-2.34.0 → execsql2-2.35.0}/tests/metacommands/test_pg_upsert.py +0 -0
  483. {execsql2-2.34.0 → execsql2-2.35.0}/tests/metacommands/test_prompt.py +0 -0
  484. {execsql2-2.34.0 → execsql2-2.35.0}/tests/metacommands/test_row_count.py +0 -0
  485. {execsql2-2.34.0 → execsql2-2.35.0}/tests/metacommands/test_serve_output.py +0 -0
  486. {execsql2-2.34.0 → execsql2-2.35.0}/tests/metacommands/test_show_scripts.py +0 -0
  487. {execsql2-2.34.0/tests/security → execsql2-2.35.0/tests/scripts}/__init__.py +0 -0
  488. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/audit_lint_bad.sql +0 -0
  489. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/audit_smoke/sample.json +0 -0
  490. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/audit_smoke/sample.jsonl +0 -0
  491. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/audit_smoke.sql +0 -0
  492. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/config_runtime.sql +0 -0
  493. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/control_flow.sql +0 -0
  494. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/counters_and_locals.sql +0 -0
  495. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/error_handling.sql +0 -0
  496. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/import_options/has_comments.csv +0 -0
  497. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/import_options.sql +0 -0
  498. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/includes/helper.sql +0 -0
  499. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/includes.sql +0 -0
  500. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/io_formats.sql +0 -0
  501. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/io_roundtrip.sql +0 -0
  502. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/multi_db.sql +0 -0
  503. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/parquet_feather_roundtrip.sql +0 -0
  504. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/parse_only/parse_tree.sql +0 -0
  505. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/predicates.sql +0 -0
  506. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/scripts.sql +0 -0
  507. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/smoke.sql +0 -0
  508. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/subroutine_loops.sql +0 -0
  509. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/subvars_advanced.sql +0 -0
  510. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/template_export/greeting.tmpl +0 -0
  511. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/template_export.sql +0 -0
  512. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/timer.sql +0 -0
  513. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/transactions.sql +0 -0
  514. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/write_create_table.sql +0 -0
  515. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/fixtures/xlsx_ods_roundtrip.sql +0 -0
  516. {execsql2-2.34.0 → execsql2-2.35.0}/tests/scripts/test_sql_scripts.py +0 -0
  517. {execsql2-2.34.0/tests/templates → execsql2-2.35.0/tests/security}/__init__.py +0 -0
  518. {execsql2-2.34.0 → execsql2-2.35.0}/tests/security/test_env_detection.py +0 -0
  519. {execsql2-2.34.0 → execsql2-2.35.0}/tests/security/test_expansion_bomb.py +0 -0
  520. {execsql2-2.34.0 → execsql2-2.35.0}/tests/security/test_import_regex_hardening.py +0 -0
  521. {execsql2-2.34.0 → execsql2-2.35.0}/tests/security/test_log_redaction.py +0 -0
  522. {execsql2-2.34.0 → execsql2-2.35.0}/tests/security/test_network_paths.py +0 -0
  523. {execsql2-2.34.0 → execsql2-2.35.0}/tests/security/test_odbc_connection_strings.py +0 -0
  524. {execsql2-2.34.0 → execsql2-2.35.0}/tests/security/test_odbc_injection.py +0 -0
  525. {execsql2-2.34.0 → execsql2-2.35.0}/tests/security/test_path_containment.py +0 -0
  526. {execsql2-2.34.0 → execsql2-2.35.0}/tests/security/test_substitution_injection.py +0 -0
  527. {execsql2-2.34.0 → execsql2-2.35.0}/tests/security/test_zip_bomb.py +0 -0
  528. {execsql2-2.34.0/tests/utils → execsql2-2.35.0/tests/templates}/__init__.py +0 -0
  529. {execsql2-2.34.0 → execsql2-2.35.0}/tests/templates/conftest.py +0 -0
  530. {execsql2-2.34.0 → execsql2-2.35.0}/tests/templates/test_compare.py +0 -0
  531. {execsql2-2.34.0 → execsql2-2.35.0}/tests/templates/test_glossary.py +0 -0
  532. {execsql2-2.34.0 → execsql2-2.35.0}/tests/templates/test_static.py +0 -0
  533. {execsql2-2.34.0 → execsql2-2.35.0}/tests/templates/test_upsert.py +0 -0
  534. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_api.py +0 -0
  535. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_api_errors.py +0 -0
  536. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_api_extended.py +0 -0
  537. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_api_filewriter.py +0 -0
  538. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_api_isolation.py +0 -0
  539. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_api_subprocess.py +0 -0
  540. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_ast.py +0 -0
  541. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_ast_parser.py +0 -0
  542. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_bundled_templates.py +0 -0
  543. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_config.py +0 -0
  544. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_config_data.py +0 -0
  545. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_config_extended.py +0 -0
  546. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_date_inference.py +0 -0
  547. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_debug_repl.py +0 -0
  548. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_engine.py +0 -0
  549. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_error_messages.py +0 -0
  550. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_exceptions.py +0 -0
  551. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_executor.py +0 -0
  552. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_executor_inprocess.py +0 -0
  553. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_format.py +0 -0
  554. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_interactive.py +0 -0
  555. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_mail.py +0 -0
  556. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_metacommand_errors.py +0 -0
  557. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_package.py +0 -0
  558. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_parser.py +0 -0
  559. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_parser_params.py +0 -0
  560. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_plugins.py +0 -0
  561. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_reference.py +0 -0
  562. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_registry.py +0 -0
  563. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_release_notes.py +0 -0
  564. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_script.py +0 -0
  565. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_state.py +0 -0
  566. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_tooling_versions.py +0 -0
  567. {execsql2-2.34.0 → execsql2-2.35.0}/tests/test_types.py +0 -0
  568. {execsql2-2.34.0 → execsql2-2.35.0}/tests/utils/test_auth.py +0 -0
  569. {execsql2-2.34.0 → execsql2-2.35.0}/tests/utils/test_auth_extra.py +0 -0
  570. {execsql2-2.34.0 → execsql2-2.35.0}/tests/utils/test_crypto.py +0 -0
  571. {execsql2-2.34.0 → execsql2-2.35.0}/tests/utils/test_datetime.py +0 -0
  572. {execsql2-2.34.0 → execsql2-2.35.0}/tests/utils/test_encodedfile_context.py +0 -0
  573. {execsql2-2.34.0 → execsql2-2.35.0}/tests/utils/test_errors.py +0 -0
  574. {execsql2-2.34.0 → execsql2-2.35.0}/tests/utils/test_errors_extra.py +0 -0
  575. {execsql2-2.34.0 → execsql2-2.35.0}/tests/utils/test_fileio.py +0 -0
  576. {execsql2-2.34.0 → execsql2-2.35.0}/tests/utils/test_fileio_extra.py +0 -0
  577. {execsql2-2.34.0 → execsql2-2.35.0}/tests/utils/test_keyring_rules.py +0 -0
  578. {execsql2-2.34.0 → execsql2-2.35.0}/tests/utils/test_mail_tls.py +0 -0
  579. {execsql2-2.34.0 → execsql2-2.35.0}/tests/utils/test_numeric.py +0 -0
  580. {execsql2-2.34.0 → execsql2-2.35.0}/tests/utils/test_regex.py +0 -0
  581. {execsql2-2.34.0 → execsql2-2.35.0}/tests/utils/test_strings.py +0 -0
  582. {execsql2-2.34.0 → execsql2-2.35.0}/tests/utils/test_timer.py +0 -0
  583. {execsql2-2.34.0 → execsql2-2.35.0}/tests/utils/test_timer_extra.py +0 -0
  584. {execsql2-2.34.0 → execsql2-2.35.0}/zensical.toml +0 -0
@@ -13,6 +13,22 @@ ______________________________________________________________________
13
13
 
14
14
  ______________________________________________________________________
15
15
 
16
+ ## [2.35.0] - 2026-10-18
17
+
18
+ ### Added
19
+
20
+ - **`exact_decimals`** (`[input]`) and **`CONFIG EXACT_DECIMALS YES|NO`**: with Yes, `IMPORT` and `COPY … TO NEW` give a column of decimals with different numbers of places an exact `DECIMAL(p,s)` type instead of a floating-point one.
21
+
22
+ ### Changed
23
+
24
+ - **A column of decimals with different numbers of places** (`1.50`, `2`, `-3.25`) gets a floating-point type again when `IMPORT` or `COPY … TO NEW` creates a table (it was `DECIMAL(p,s)` from 2.22.0). A column with a value of more than 15 significant digits stays `DECIMAL(p,s)`, so no digit is lost. Set `exact_decimals` to keep every such column exact.
25
+
26
+ ### Fixed
27
+
28
+ - **The "potential un-substituted variable" warning** is printed only when `write_warnings` is on, to stderr as `**** Warning …`, as documented; it was printed to stdout for every command with an undefined `!!var!!`. It is always written to `execsql.log`.
29
+
30
+ ______________________________________________________________________
31
+
16
32
  ## [2.34.0] - 2026-10-18
17
33
 
18
34
  ### Added
@@ -64,6 +64,19 @@ just test-templates-down # removes the containers
64
64
 
65
65
  SQL Server is included only when an ODBC driver for it is installed. A template bug the tests have found but not yet fixed is marked with `known_bug(...)`, a strict expected failure: the fix makes the test pass, which fails the run until the marker is removed with it.
66
66
 
67
+ ### Script behavior corpus
68
+
69
+ `tests/corpus/` checks that whole scripts do under execsql2 what they did under upstream execsql 1.130.1: the same exit status, console output, files written and table contents. Each case is a directory in `tests/corpus/cases/` holding `script.sql` and the files it reads. Upstream's results are recorded in `tests/corpus/results/`, so the normal test run compares against them without upstream installed. A variable a case checks is `WRITE`n to a file, because upstream has no way to read variables after a run.
70
+
71
+ To add a case, create its directory, then record what upstream does (this installs execsql 1.130.1 from PyPI under Python 3.12 into `~/.cache/execsql-corpus/` on first use):
72
+
73
+ ```bash
74
+ uv run python -m tests.corpus.record my_new_case
75
+ uv run pytest tests/corpus
76
+ ```
77
+
78
+ Use only syntax upstream accepts; read `_execsql/execsql.py` when unsure. A case must not open a GUI dialog (`HALT "message"`, `PROMPT`) or loop forever under upstream: both hang the recording. A difference from upstream fails the test unless `tests/corpus/changes.json` lists it with both values, a `status` (`accepted` for an upstream bug execsql2 fixed on purpose, `open` for one not yet decided) and the reason.
79
+
67
80
  ## Building the Docs
68
81
 
69
82
  ```bash
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: execsql2
3
- Version: 2.34.0
3
+ Version: 2.35.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/en/stable/
6
6
  Project-URL: Repository, https://github.com/geocoug/execsql
@@ -441,7 +441,7 @@ execsql format --no-sql --in-place scripts/
441
441
  ```yaml
442
442
  repos:
443
443
  - repo: https://github.com/geocoug/execsql
444
- rev: v2.34.0
444
+ rev: v2.35.0
445
445
  hooks:
446
446
  - id: execsql-format
447
447
  - id: execsql-lint
@@ -321,7 +321,7 @@ execsql format --no-sql --in-place scripts/
321
321
  ```yaml
322
322
  repos:
323
323
  - repo: https://github.com/geocoug/execsql
324
- rev: v2.34.0
324
+ rev: v2.35.0
325
325
  hooks:
326
326
  - id: execsql-format
327
327
  - id: execsql-lint
@@ -92,6 +92,7 @@ New options in `execsql.conf`:
92
92
  | -------------------------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
93
93
  | `use_keyring` | `[connect]` | Use the OS keyring for credential storage (default: `yes`). |
94
94
  | `trust_server_certificate` | `[connect]` | SQL Server: accept a self-signed server certificate (ODBC Driver 18 verifies it by default); also `?trust_server_certificate=yes` on an `mssql://` URL. Default: `no`. |
95
+ | `exact_decimals` | `[input]` | Give a column of decimals with different numbers of places an exact `DECIMAL(p,s)` type instead of a float (default: `no`); also `CONFIG EXACT_DECIMALS`. |
95
96
  | `show_progress` | `[input]` | Enable Rich progress bar for IMPORT (default: `no`). |
96
97
  | `import_progress_interval` | `[input]` | Log a status line every N rows during IMPORT (default: `0`). |
97
98
  | `gui_framework` | `[interface]` | GUI backend: `tkinter` (default) or `textual` (terminal UI). |
@@ -257,6 +258,7 @@ All 33 mutable runtime globals in `state.py` have been consolidated into a `Runt
257
258
 
258
259
  - **`$HOSTNAME`** — Network name of the machine running execsql (`platform.node()`). Useful for log messages and environment detection.
259
260
  - **`$SYSTEM_CMD_PID`** — New system variable set to the PID of the background process when `SHELL … CONTINUE` is used.
261
+ - **`!'!var!'!` adds the quotes** — `!'!name!'!` becomes a complete string literal: the value is wrapped in single quotes and its apostrophes doubled (`O'Brien` → `'O''Brien'`), so a script writes `where author = !'!name!'!`. Upstream only doubled the apostrophes, so its scripts wrote the quotes themselves (`'!'!name!'!'`); in execsql2 that form has two sets of quotes and fails. Remove the outer quotes when moving such a script.
260
262
  - **Cycle detection** — `substitute_vars()` raises an error after 100 iterations to prevent infinite loops when variables reference each other cyclically. Upstream had no protection.
261
263
  - **O(1) substitution** — Variable substitution uses a single combined regex and dict lookup instead of O(V) per-variable regex passes. Behavior is identical; performance is improved.
262
264
  - **Lazy `$RANDOM`/`$UUID`** — These system variables are now computed on first access rather than generated unconditionally for every statement. Behavior is identical when referenced; scripts that never reference them skip the computation entirely.
@@ -288,6 +290,7 @@ The legacy flat command-list engine (`_parse_script_lines` / `runscripts` / `Com
288
290
 
289
291
  - **Native INCLUDE handling** — The AST executor parses INCLUDE'd files with the AST parser and executes them through the tree-walking executor. Control flow structures (IF/LOOP/BATCH/SCRIPT) in included files are fully tree-driven, with correct deferred variable handling and source-span error reporting.
290
292
  - **Circular INCLUDE detection** — The executor tracks the full include chain and detects circular references (e.g. A includes B includes A), reporting the full chain in the error message. Upstream has no such detection.
293
+ - **LOOP conditions are read on every pass** — The variables in a `LOOP WHILE` / `LOOP UNTIL` condition are substituted afresh before each pass, so `LOOP WHILE (IS_GT(10, !!n!!))` with `SUB_ADD n 1` in the body stops when `n` reaches 10. Upstream substituted them once, when the `LOOP` line ran, so a condition on a variable already defined never changed: the loop ran until a `BREAK`, or forever. Upstream scripts got per-pass conditions only from variables not yet defined when the loop started ("phantom variables") or from deferred `!{var}!` references, and both still work.
291
294
  - **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.
292
295
  - **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.
293
296
  - **Instance-scoped script registry** — Named SCRIPT blocks are stored on the `RuntimeContext` instance instead of a module-level dict, preventing cross-execution contamination.
@@ -435,6 +438,8 @@ These are behavioral changes driven by security or correctness issues in the ups
435
438
  | DuckDB float columns were single precision | `dbt_duckdb` mapped `DT_Float` to `REAL`. `DT_Float` is documented as IEEE double precision and a Python float always is one, so every float written to DuckDB was narrowed: `1234.567` was stored and returned as `1234.5670166015625`. PostgreSQL, SQLite, SQL Server, MySQL, Access, Firebird and DSN all map `DT_Float` to a double; DuckDB was the only backend that did not, and is now `DOUBLE`. |
436
439
  | VALUES export wrote dates and timestamps unquoted | The literal renderer quoted `str` and emitted `NULL` for `None`, but sent everything else through `str()` bare. A `date` became `2026-09-24` in the generated `INSERT`, which is not a syntax error — it is a valid SQL expression evaluating to 1993, so PostgreSQL inserted that and reported nothing. A `timestamp` contains a space and failed outright. Quoting is now the default and only numbers are emitted bare, so a type the renderer has not been taught about is safe rather than silently wrong. |
437
440
  | LaTeX export escaped only the underscore | Cells were written as `str(c).replace("_", r"\_")`, leaving every other LaTeX special raw. `&` is the column separator this exporter itself emits, so an ampersand in a value added a column and the `.tex` no longer compiled; `%` commented out the rest of the row. All of `\ & % $ # _ { } ~ ^` are now escaped, in both the header and the body. |
441
+ | `ON ERROR_HALT WRITE … TO` a file wrote nothing | Upstream passed the `(text, flag)` pair that variable substitution returns on as the text, so writing the message failed after the file was opened and the file stayed empty. The message is written. |
442
+ | Mixed-scale decimals keep every digit | `IMPORT` / `COPY … TO NEW` gave a column of decimals with different numbers of places (`1.50`, `2`, `-3.25`) a floating-point type, which also held values a double cannot store exactly: `1234567890.1234567891` was stored as `1234567890.1234567`. Such a column is still a float, unless a value has more than 15 significant digits; then it is `DECIMAL(p,s)`. The `exact_decimals` setting makes every such column exact. |
438
443
  | LaTeX export wrote NULL as the literal "None" | `str(c)` was applied to every value including `None`, so a NULL appeared in the typeset table as the word None. It is now an empty cell, matching every other exporter. |
439
444
  | HTML export rendered zero as an empty cell | Cells were written as `html.escape(str(v)) if v else ''`. `0`, `False`, and `""` are all falsy, so a zero measurement rendered exactly like a NULL and the two could not be told apart in the output. The test is now `if v is not None`. Both `export_html` and `export_cgi_html` were affected. |
440
445
  | Markdown export broke the table on an embedded newline | `_cell()` escaped pipes but not newlines, and a GFM table row is a single line: a value containing one ended the row mid-cell and left the rest of that row's values on a stray line outside the table entirely. Newlines are now written as `<br>`, which is how GFM expresses a line break inside a cell. |
@@ -272,7 +272,7 @@ select id,name,created_at from users where active = true order by name;
272
272
  ```yaml
273
273
  repos:
274
274
  - repo: https://github.com/geocoug/execsql
275
- rev: v2.34.0
275
+ rev: v2.35.0
276
276
  hooks:
277
277
  - id: execsql-format
278
278
  - id: execsql-lint # optional: fail the commit on lint errors
@@ -141,6 +141,10 @@ The section and property names that may be used in a configuration file are list
141
141
 
142
142
  : Determines whether empty strings in the input are preserved or, alternatively, will be replaced by NULL. The property value should be either "Yes" or "No". The default, "Yes", indicates that empty strings are allowed. A value of "No" will cause all empty strings to be replaced by NULL. When this is set to "No", a string value consisting of a sequence of zero or more space characters will be considered to be an empty string. There is no command-line option corresponding to this configuration parameter, but the metacommand [CONFIG EMPTY_STRINGS](metacommands.md#empty_strings) can also be used to change this configuration item.
143
143
 
144
+ `exact_decimals`
145
+
146
+ : Determines the data type of a column of decimal numbers with different numbers of decimal places, such as `1.50`, `2` and `-3.25`, when the [IMPORT](metacommands.md#import) or [COPY](metacommands.md#copy) metacommand creates a table. The default, "No", gives such a column a floating-point type (`double precision` on PostgreSQL, `double` on MySQL and DuckDB, `float` on SQL Server), unless a value has more than 15 significant digits, which a floating-point column cannot hold exactly: then the column is an exact decimal, so no digit is lost. "Yes" always gives such a column an exact decimal type wide enough for every value (`numeric(3,2)` for those values), for values such as money amounts that should be stored and compared exactly. A column whose values all have the same number of decimal places is an exact decimal either way. The metacommand [CONFIG EXACT_DECIMALS](metacommands.md#exact_decimals) can also be used to change this configuration item.
147
+
144
148
  `fold_column_headers` { #setting_fold_column_headers }
145
149
 
146
150
  : Whether or not to fold (convert) the case of all column headers to lowercase or uppercase, or to leave them unchanged when data are [IMPORTed](metacommands.md#import). Valid values are "No" (the default), "Lower", and "Upper". Case does not matter in the specification.
@@ -158,7 +158,7 @@ The `execsql-lint` [pre-commit](https://pre-commit.com/) hook runs `execsql lint
158
158
  ```yaml
159
159
  repos:
160
160
  - repo: https://github.com/geocoug/execsql
161
- rev: v2.34.0
161
+ rev: v2.35.0
162
162
  hooks:
163
163
  - id: execsql-lint
164
164
  args: [--ignore, V002] # optional: any execsql lint option
@@ -597,6 +597,21 @@ CONFIG MAX_INT <integer_value>
597
597
  Specifies the threshold between integer and bigint data types that is used by the [IMPORT](#import) and [COPY](#copy) metacommands when creating a new table. Any column with integer values less than or equal to this value (max_int) and greater than or equal to -1 × max_int - 1 will be considered to have an integer type. Any column with values outside this range will be considered to have a bigint type. The default value for max_int is 2147483647. The max_int value can also be altered using a configuration option. The bare form `MAX_INT <integer_value>`, without `CONFIG`, does the same.
598
598
 
599
599
 
600
+ <a id="exact_decimals"></a>
601
+ ```
602
+ CONFIG EXACT_DECIMALS YES|NO
603
+ ```
604
+
605
+ Controls the data type the [IMPORT](#import) and [COPY](#copy) metacommands give a column of decimal numbers with different numbers of decimal places when they create a table. With "No" (the default), `1.50`, `2` and `-3.25` make a floating-point column; a column with a value of more than 15 significant digits, such as `1234567890.1234567891`, is an exact decimal even then, because a floating-point column would cut it. With "Yes" every such column is an exact decimal wide enough for every value, `numeric(3,2)` for the first example:
606
+
607
+ ```
608
+ -- !x! CONFIG EXACT_DECIMALS YES
609
+ -- !x! IMPORT TO NEW payments FROM payments.csv
610
+ ```
611
+
612
+ A column whose values all have the same number of decimal places is an exact decimal either way. This can also be set with the `exact_decimals` [configuration setting](configuration.md#config_input).
613
+
614
+
600
615
  ```
601
616
  CONFIG ONLY_STRINGS YES|NO
602
617
  ```
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "execsql-syntax",
3
- "version": "2.34.0",
3
+ "version": "2.35.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "execsql-syntax",
9
- "version": "2.34.0",
9
+ "version": "2.35.0",
10
10
  "license": "GPL-3.0-or-later",
11
11
  "dependencies": {
12
12
  "vscode-languageclient": "10.1.2"
@@ -2,7 +2,7 @@
2
2
  "name": "execsql-syntax",
3
3
  "displayName": "execsql",
4
4
  "description": "Syntax highlighting, lint findings, completion, hover, navigation, quick fixes and formatting for execsql scripts.",
5
- "version": "2.34.0",
5
+ "version": "2.35.0",
6
6
  "publisher": "geocoug",
7
7
  "license": "GPL-3.0-or-later",
8
8
  "icon": "icon.png",
@@ -113,7 +113,7 @@
113
113
  },
114
114
  "config-option-names": {
115
115
  "comment": "Config option names used after the config keyword",
116
- "match": "(?i)\\b(import_only_common_columns|console_wait_when_error|console_wait_when_done|create_column_headers|clean_column_headers|dao_flush_delay_secs|dedup_column_headers|delete_empty_columns|fold_column_headers|trim_column_headers|log_write_messages|export_row_buffer|import_row_buffer|make_export_dirs|replace_newlines|quote_all_text|write_warnings|boolean_words|empty_strings|hdf5_text_len|show_progress|zip_buffer_mb|log_datavars|only_strings|trim_strings|write_prefix|write_suffix|boolean_int|empty_rows|scan_lines|gui_level|log_sql|max_int)\\b",
116
+ "match": "(?i)\\b(import_only_common_columns|console_wait_when_error|console_wait_when_done|create_column_headers|clean_column_headers|dao_flush_delay_secs|dedup_column_headers|delete_empty_columns|fold_column_headers|trim_column_headers|log_write_messages|export_row_buffer|import_row_buffer|make_export_dirs|replace_newlines|exact_decimals|quote_all_text|write_warnings|boolean_words|empty_strings|hdf5_text_len|show_progress|zip_buffer_mb|log_datavars|only_strings|trim_strings|write_prefix|write_suffix|boolean_int|empty_rows|scan_lines|gui_level|log_sql|max_int)\\b",
117
117
  "name": "support.constant.config.execsql"
118
118
  },
119
119
  "export-formats": {
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "execsql2"
7
- version = "2.34.0"
7
+ version = "2.35.0"
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" }
@@ -188,7 +188,7 @@ line-ending = "auto"
188
188
  exclude = ["*.md"]
189
189
 
190
190
  [tool.bumpversion]
191
- current_version = "2.34.0"
191
+ current_version = "2.35.0"
192
192
  commit = true
193
193
  tag = true
194
194
  tag_name = "v{new_version}"
@@ -178,6 +178,7 @@ class _LibraryConfig:
178
178
  self.boolean_int = True
179
179
  self.boolean_words = False
180
180
  self.empty_strings = True
181
+ self.exact_decimals = False
181
182
  self.only_strings = False
182
183
  self.empty_rows = True
183
184
  self.del_empty_cols = False
@@ -300,6 +300,7 @@ class ConfigData:
300
300
  self._get_bool(cp, self._INPUT_SECTION, "boolean_int", "boolean_int")
301
301
  self._get_bool(cp, self._INPUT_SECTION, "boolean_words", "boolean_words")
302
302
  self._get_bool(cp, self._INPUT_SECTION, "empty_strings", "empty_strings")
303
+ self._get_bool(cp, self._INPUT_SECTION, "exact_decimals", "exact_decimals")
303
304
  self._get_bool(cp, self._INPUT_SECTION, "only_strings", "only_strings")
304
305
  self._get_bool(cp, self._INPUT_SECTION, "empty_rows", "empty_rows")
305
306
  self._get_bool(cp, self._INPUT_SECTION, "delete_empty_columns", "del_empty_cols")
@@ -503,6 +504,7 @@ class ConfigData:
503
504
  self.boolean_int = True
504
505
  self.boolean_words = False
505
506
  self.empty_strings = True
507
+ self.exact_decimals = False
506
508
  self.only_strings = False
507
509
  self.empty_rows = True
508
510
  self.del_empty_cols = False
@@ -115,6 +115,13 @@
115
115
  # Values: Yes or No. Default: Yes.
116
116
  #empty_strings=Yes
117
117
 
118
+ # Whether a column of decimal numbers with different numbers of decimal places
119
+ # (1.5, 2.25) gets an exact DECIMAL(precision, scale) type when IMPORT or COPY
120
+ # creates a table. With No it gets a floating-point type, unless a value has
121
+ # more than 15 significant digits (then it is DECIMAL, so no digit is lost).
122
+ # Values: Yes or No. Default: No.
123
+ #exact_decimals=No
124
+
118
125
  # Whether to fold column headers to lowercase, uppercase, or leave unchanged.
119
126
  # Values: No, Lower, or Upper. Default: No.
120
127
  #fold_column_headers=No
@@ -21,7 +21,7 @@ What's actually here:
21
21
  ``x_set_counter``.
22
22
  - IMPORT / scanning configuration metacommands (the ``CONFIG …`` form):
23
23
  ``x_empty_strings``, ``x_trim_strings``, ``x_replace_newlines``,
24
- ``x_empty_rows``, ``x_only_strings``, ``x_boolean_int``,
24
+ ``x_empty_rows``, ``x_exact_decimals``, ``x_only_strings``, ``x_boolean_int``,
25
25
  ``x_boolean_words``, ``x_fold_col_hdrs``, ``x_trim_col_hdrs``,
26
26
  ``x_clean_col_hdrs``, ``x_del_empty_cols``, ``x_create_col_hdrs``,
27
27
  ``x_dedup_col_hdrs``, ``x_import_common_cols_only``, ``x_max_int``.
@@ -301,6 +301,12 @@ def x_only_strings(**kwargs: Any) -> None:
301
301
  return None
302
302
 
303
303
 
304
+ def x_exact_decimals(**kwargs: Any) -> None:
305
+ flag = kwargs["yesno"].lower()
306
+ _state.conf.exact_decimals = flag in ("yes", "on", "true", "1")
307
+ return None
308
+
309
+
304
310
  def x_boolean_int(**kwargs: Any) -> None:
305
311
  flag = kwargs["yesno"].lower()
306
312
  _state.conf.boolean_int = flag in ("yes", "on", "true", "1")
@@ -64,6 +64,7 @@ from execsql.metacommands.data import (
64
64
  x_dedup_col_hdrs,
65
65
  x_empty_rows,
66
66
  x_empty_strings,
67
+ x_exact_decimals,
67
68
  x_fold_col_hdrs,
68
69
  x_import_common_cols_only,
69
70
  x_max_int,
@@ -768,6 +769,12 @@ def build_dispatch_table() -> MetaCommandList:
768
769
  description="EMPTY_ROWS",
769
770
  category="config_option",
770
771
  )
772
+ mcl.add(
773
+ r"^\s*CONFIG\s+EXACT_DECIMALS\s+(?P<yesno>YES|NO|ON|OFF|TRUE|FALSE|0|1)\s*$",
774
+ x_exact_decimals,
775
+ description="EXACT_DECIMALS",
776
+ category="config_option",
777
+ )
771
778
  mcl.add(
772
779
  r"^\s*CONFIG\s+ONLY_STRINGS\s+(?P<yesno>YES|NO|ON|OFF|TRUE|FALSE|0|1)\s*$",
773
780
  x_only_strings,
@@ -254,6 +254,7 @@ _METACOMMANDS: tuple[Metacommand, ...] = (
254
254
  "CONFIG DELETE_EMPTY_COLUMNS YES|NO",
255
255
  "CONFIG EMPTY_ROWS YES|NO",
256
256
  "CONFIG EMPTY_STRINGS YES|NO",
257
+ "CONFIG EXACT_DECIMALS YES|NO",
257
258
  "CONFIG EXPORT_ROW_BUFFER <n>",
258
259
  "CONFIG FOLD_COLUMN_HEADERS NO|LOWER|UPPER",
259
260
  "CONFIG GUI_LEVEL <n>",
@@ -49,6 +49,10 @@ __all__ = [
49
49
 
50
50
  ColumnType = tuple[str, type[DataType], int | None, bool, int | None, int | None]
51
51
 
52
+ # Every decimal of up to this many significant digits reads back unchanged
53
+ # from an IEEE double (DBL_DIG).
54
+ _DOUBLE_EXACT_DIGITS = 15
55
+
52
56
 
53
57
  def _text_length(value: Any) -> int:
54
58
  """Return the length of *value* written as text (a column may turn out to be text)."""
@@ -71,9 +75,14 @@ class Column:
71
75
  """Accumulate match counts and length statistics for a single data type."""
72
76
 
73
77
  # Accumulates the count of matches for each data type, plus the maximum length if appropriate.
74
- def __init__(self, data_type_obj: DataType) -> None:
75
- """Initialise the accumulator for the given data type."""
78
+ def __init__(self, data_type_obj: DataType, *, exact_decimals: bool = False) -> None:
79
+ """Initialise the accumulator for the given data type.
80
+
81
+ *exact_decimals*: the ``exact_decimals`` setting; see
82
+ :meth:`chooses_float`.
83
+ """
76
84
  self.dt = data_type_obj
85
+ self.exact_decimals = exact_decimals
77
86
  self.failed = False
78
87
  self.count = 0
79
88
  self.maxlen = 0
@@ -127,6 +136,23 @@ class Column:
127
136
  self.maxscale = max(self.dt.scale, self.maxscale)
128
137
  self.max_int_digits = max(int_digits, self.max_int_digits)
129
138
 
139
+ def chooses_float(self) -> bool:
140
+ """Whether a decimal column gives way to a float column.
141
+
142
+ A column of decimals with different scales (``1.50``, ``2``,
143
+ ``-3.25``) is a float unless the ``exact_decimals`` setting is on,
144
+ or a value has more digits than a double holds exactly: every
145
+ decimal of up to 15 significant digits reads back unchanged from
146
+ a double, so such a column loses nothing, and a longer one
147
+ (``1234567890.1234567891``) stays ``DECIMAL(p, s)``.
148
+ """
149
+ return (
150
+ self.varscale
151
+ and not self.exact_decimals
152
+ and self.maxprecision is not None
153
+ and self.maxprecision <= _DOUBLE_EXACT_DIGITS
154
+ )
155
+
130
156
  def __init__(self, colname: str, infer_strings: bool = True) -> None:
131
157
  """Create a column characteriser for the named column.
132
158
 
@@ -169,7 +195,7 @@ class Column:
169
195
  self.Accum(DT_Boolean()),
170
196
  self.Accum(DT_Integer()),
171
197
  self.Accum(DT_Long()),
172
- self.Accum(DT_Decimal()),
198
+ self.Accum(DT_Decimal(), exact_decimals=conf.exact_decimals),
173
199
  self.Accum(DT_Float()),
174
200
  self.Accum(DT_Character()),
175
201
  self.Accum(DT_Varchar()),
@@ -262,7 +288,7 @@ class Column:
262
288
  break
263
289
  else:
264
290
  if ac.dt.precspec:
265
- if ac.dt.precision is not None and ac.dt.scale is not None:
291
+ if ac.dt.precision is not None and ac.dt.scale is not None and not ac.chooses_float():
266
292
  sel_type = ac
267
293
  break
268
294
  else:
@@ -85,6 +85,14 @@ _DEFER_RX = re.compile(r"!\{([$@&~#+]?\w+)\}!")
85
85
  _VARLIKE = re.compile(r"!![$@&~#]?\w+!!", re.I)
86
86
 
87
87
 
88
+ def _warn_unsubstituted(cmd: str) -> None:
89
+ """Log a command that still looks like it holds a variable; print it too if ``write_warnings`` is on."""
90
+ from execsql.utils.errors import write_warning
91
+ from execsql.utils.fileio import redact
92
+
93
+ write_warning(f"There is a potential un-substituted variable in the command\n {redact(cmd)}")
94
+
95
+
88
96
  def _stack_localvars(ctx: RuntimeContext) -> SubVarSet | None:
89
97
  """Build the merged ``~`` local + ``#`` param overlay for the current scope.
90
98
 
@@ -254,11 +262,7 @@ def _exec_sql(
254
262
  effective_locals = _stack_localvars(ctx) or localvars
255
263
  cmd = substitute_vars(text, effective_locals, ctx=ctx)
256
264
  if _VARLIKE.search(cmd):
257
- from execsql.utils.fileio import redact
258
-
259
- output.write(
260
- f"Warning: There is a potential un-substituted variable in the command\n {redact(cmd)}\n",
261
- )
265
+ _warn_unsubstituted(cmd)
262
266
  e = None
263
267
  result = None
264
268
  try:
@@ -323,11 +327,7 @@ def _exec_metacommand(
323
327
  assert subvars is not None
324
328
 
325
329
  if _VARLIKE.search(cmd):
326
- from execsql.utils.fileio import redact
327
-
328
- output.write(
329
- f"Warning: There is a potential un-substituted variable in the command\n {redact(cmd)}\n",
330
- )
330
+ _warn_unsubstituted(cmd)
331
331
  e = None
332
332
  try:
333
333
  applies, result = metacommandlist.eval(cmd)
@@ -274,8 +274,8 @@ def write_warning(warning_msg: str, *, always: bool = False) -> None:
274
274
  warning_msg: The warning text to emit.
275
275
  always: When ``True``, always write to stderr regardless of the
276
276
  ``conf.write_warnings`` setting. Use this for structural warnings
277
- (e.g. IF-level mismatch, unsubstituted variables) that should always
278
- be visible. When ``False`` (default), stderr output is gated by
277
+ (e.g. IF-level mismatch) that should always be visible. When
278
+ ``False`` (default), stderr output is gated by
279
279
  ``conf.write_warnings``.
280
280
  """
281
281
  if _state.exec_log is not None:
@@ -38,6 +38,7 @@ def minimal_conf():
38
38
  max_int=2_147_483_647,
39
39
  # Column / DataTable
40
40
  only_strings=False,
41
+ exact_decimals=False,
41
42
  trim_strings=False,
42
43
  replace_newlines=False,
43
44
  empty_strings=True,
@@ -0,0 +1,16 @@
1
+ -- BEGIN BATCH / ROLLBACK, BEGIN BATCH / END BATCH, and AUTOCOMMIT OFF.
2
+ create table t (v text);
3
+ -- !x! BEGIN BATCH
4
+ insert into t values ('batch rolled back');
5
+ -- !x! ROLLBACK
6
+ -- !x! END BATCH
7
+ -- !x! BEGIN BATCH
8
+ insert into t values ('batch kept');
9
+ -- !x! END BATCH
10
+ -- !x! AUTOCOMMIT OFF
11
+ insert into t values ('autocommit off, committed');
12
+ commit;
13
+ insert into t values ('autocommit off, rolled back');
14
+ rollback;
15
+ -- !x! AUTOCOMMIT ON
16
+ insert into t values ('autocommit on');
@@ -0,0 +1,4 @@
1
+ zero_one,words,padded,maybe_empty
2
+ 1,yes, a ,x
3
+ 0,no, b,
4
+ 1,yes,"c "," "
@@ -0,0 +1,13 @@
1
+ -- Settings that change how imported values are read.
2
+ -- !x! IMPORT TO NEW default_read FROM data.csv
3
+ -- !x! CONFIG BOOLEAN_INT NO
4
+ -- !x! IMPORT TO NEW boolean_int_off FROM data.csv
5
+ -- !x! CONFIG BOOLEAN_INT YES
6
+ -- !x! BOOLEAN_WORDS ON
7
+ -- !x! IMPORT TO NEW boolean_words_on FROM data.csv
8
+ -- !x! BOOLEAN_WORDS OFF
9
+ -- !x! EMPTY_STRINGS NO
10
+ -- !x! IMPORT TO NEW empty_strings_no FROM data.csv
11
+ -- !x! EMPTY_STRINGS YES
12
+ -- !x! TRIM_STRINGS YES
13
+ -- !x! IMPORT TO NEW trimmed FROM data.csv
@@ -0,0 +1,17 @@
1
+ -- CONNECT a second SQLite database and COPY between them.
2
+ create table src (id integer, name text, amt real, flag integer);
3
+ insert into src values (1, 'a', 1.5, 1), (2, 'b', null, 0), (3, '00701', 3, 1);
4
+ -- !x! CONNECT TO SQLITE(FILE=other.db, NEW) AS other
5
+ -- !x! COPY src FROM initial TO NEW copied IN other
6
+ -- !x! COPY QUERY <<select id, name from src where id > 1;>> FROM initial TO NEW q IN other
7
+ -- !x! USE other
8
+ create table existing (id integer, name text, amt real, flag integer);
9
+ -- !x! USE initial
10
+ -- !x! COPY src FROM initial TO existing IN other
11
+ -- !x! COPY copied FROM other TO NEW back IN initial
12
+ -- !x! USE other
13
+ -- !x! EXPORT copied TO copied.csv AS CSV
14
+ -- !x! EXPORT q TO q.csv AS CSV
15
+ -- !x! EXPORT existing TO existing.csv AS CSV
16
+ -- !x! USE initial
17
+ -- !x! DISCONNECT other
@@ -0,0 +1,11 @@
1
+ -- Counter variables advance on every reference.
2
+ create table t (n integer);
3
+ insert into t values (!!$COUNTER_1!!);
4
+ insert into t values (!!$COUNTER_1!!);
5
+ insert into t values (!!$COUNTER_2!!);
6
+ -- !x! SET COUNTER 1 TO 10
7
+ insert into t values (!!$COUNTER_1!!);
8
+ -- !x! RESET COUNTER 1
9
+ insert into t values (!!$COUNTER_1!!);
10
+ -- !x! RESET COUNTERS
11
+ insert into t values (!!$COUNTER_2!!);
@@ -0,0 +1,3 @@
1
+ v
2
+ 1234567890.1234567891
3
+ 1.5
@@ -0,0 +1,3 @@
1
+ -- The column type IMPORT gives decimals with different numbers of places.
2
+ -- !x! WRITE CREATE_TABLE short FROM short.csv TO ddl.sql
3
+ -- !x! WRITE CREATE_TABLE long FROM long.csv TO ddl.sql
@@ -0,0 +1,4 @@
1
+ v
2
+ 1.50
3
+ 2
4
+ -3.25
@@ -0,0 +1,13 @@
1
+ -- With ERROR_HALT OFF a failed statement does not stop the script.
2
+ create table t (id integer primary key);
3
+ insert into t values (1);
4
+ -- !x! ERROR_HALT OFF
5
+ insert into t values (1);
6
+ insert into no_such_table values (1);
7
+ -- !x! ERROR_HALT ON
8
+ insert into t values (2);
9
+ -- !x! METACOMMAND_ERROR_HALT OFF
10
+ -- !x! IMPORT TO t FROM missing.csv
11
+ -- !x! METACOMMAND_ERROR_HALT ON
12
+ insert into t values (3);
13
+ -- !x! WRITE "reached the end" TO out.txt
@@ -0,0 +1,7 @@
1
+ -- A failed statement stops the script: what ran before stays, nothing after runs.
2
+ create table t (id integer primary key);
3
+ insert into t values (1);
4
+ -- !x! WRITE "before" TO out.txt
5
+ insert into t values (1);
6
+ insert into t values (2);
7
+ -- !x! WRITE "after" TO out.txt
@@ -0,0 +1,21 @@
1
+ -- BEGIN SCRIPT / EXECUTE SCRIPT with arguments, local variables and nesting.
2
+ create table log (msg text);
3
+ -- !x! BEGIN SCRIPT add_row (what, times)
4
+ -- !x! SUB_LOCAL ~note from add_row
5
+ insert into log values ('!!#what!! x !!#times!! (!!~note!!)');
6
+ -- !x! END SCRIPT add_row
7
+ -- !x! BEGIN SCRIPT outer
8
+ -- !x! EXECUTE SCRIPT add_row WITH ARGS (what=inner, times=2)
9
+ -- !x! END SCRIPT outer
10
+ -- !x! EXECUTE SCRIPT add_row WITH ARGS (what=plain, times=1)
11
+ -- !x! EXECUTE SCRIPT outer
12
+ -- !x! SUB k 0
13
+ -- !x! BEGIN SCRIPT bump
14
+ -- !x! SUB_ADD k 1
15
+ insert into log values ('bump !!k!!');
16
+ -- !x! END SCRIPT bump
17
+ -- !x! EXECUTE SCRIPT bump
18
+ -- !x! EXECUTE SCRIPT bump
19
+ -- !x! EXECUTE SCRIPT bump
20
+ -- !x! WRITE "note outside=[!!~note!!] k=!!k!!" TO out.txt
21
+ -- !x! IF (SCRIPT_EXISTS(bump)) { WRITE "bump exists" TO out.txt }
@@ -0,0 +1,8 @@
1
+ -- EXPORT QUERY, APPEND, TEE and DESCRIPTION.
2
+ create table t (id integer, name text);
3
+ insert into t values (1, 'a'), (2, 'b'), (3, 'c');
4
+ -- !x! EXPORT QUERY <<select id, name from t where id < 3 order by id;>> TO q.csv AS CSV
5
+ -- !x! EXPORT QUERY <<select id, name from t where id = 3;>> APPEND TO q.csv AS CSV
6
+ -- !x! EXPORT t TO stdout AS CSV
7
+ -- !x! EXPORT QUERY <<select count(*) as n from t;>> TEE TO n.txt AS TXT
8
+ -- !x! EXPORT t TO d.txt AS TXT DESCRIPTION "the t table"
@@ -0,0 +1,7 @@
1
+ -- EXPORT to JSON, JSON table schema, VALUES and LaTeX.
2
+ create table t (id integer, name text, amt real, day text);
3
+ insert into t values (1, 'Ann', 1.5, '2024-01-05'), (2, 'O''Neil', null, null);
4
+ -- !x! EXPORT t TO t.json AS JSON
5
+ -- !x! EXPORT t TO t_schema.json AS JSON_TS
6
+ -- !x! EXPORT t TO t_values.sql AS VALUES
7
+ -- !x! EXPORT t TO t.tex AS LATEX
@@ -0,0 +1,9 @@
1
+ -- EXPORT to the delimited and text formats.
2
+ create table t (id integer, name text, amt real, note text);
3
+ insert into t values (1, 'Ann', 1.5, 'has, comma'), (2, 'Bob', null, 'say "hi"'), (3, 'Cé', -2, null);
4
+ -- !x! EXPORT t TO t.csv AS CSV
5
+ -- !x! EXPORT t TO t.tsv AS TSV
6
+ -- !x! EXPORT t TO t.tab AS TAB
7
+ -- !x! EXPORT t TO t.txt AS TXT
8
+ -- !x! EXPORT t TO t.plain AS PLAIN
9
+ -- !x! EXPORT t TO t.us AS US