execsql2 2.21.2__py3-none-any.whl → 2.22.1__py3-none-any.whl

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 (82) hide show
  1. execsql/api.py +29 -4
  2. execsql/cli/__init__.py +1 -1
  3. execsql/cli/run.py +37 -17
  4. execsql/config.py +40 -22
  5. execsql/data/execsql.conf.template +6 -0
  6. execsql/db/access.py +6 -5
  7. execsql/db/base.py +23 -5
  8. execsql/db/dsn.py +2 -0
  9. execsql/db/duckdb.py +1 -1
  10. execsql/db/mysql.py +6 -8
  11. execsql/db/sqlite.py +1 -1
  12. execsql/exceptions.py +14 -11
  13. execsql/exporters/base.py +1 -1
  14. execsql/exporters/delimited.py +22 -16
  15. execsql/exporters/duckdb.py +6 -1
  16. execsql/exporters/feather.py +1 -1
  17. execsql/exporters/json.py +5 -3
  18. execsql/exporters/latex.py +2 -2
  19. execsql/exporters/markdown.py +1 -0
  20. execsql/exporters/ods.py +7 -3
  21. execsql/exporters/raw.py +8 -8
  22. execsql/exporters/sqlite.py +11 -1
  23. execsql/exporters/templates.py +2 -1
  24. execsql/exporters/xls.py +10 -10
  25. execsql/exporters/xml.py +1 -0
  26. execsql/exporters/yaml.py +1 -0
  27. execsql/exporters/zip.py +9 -7
  28. execsql/format.py +6 -6
  29. execsql/gui/console.py +3 -3
  30. execsql/gui/desktop.py +28 -10
  31. execsql/gui/tui.py +8 -6
  32. execsql/importers/base.py +14 -8
  33. execsql/importers/csv.py +8 -3
  34. execsql/importers/xls.py +1 -0
  35. execsql/metacommands/conditions.py +14 -14
  36. execsql/metacommands/connect.py +2 -2
  37. execsql/metacommands/control.py +1 -1
  38. execsql/metacommands/data.py +2 -1
  39. execsql/metacommands/io_export.py +4 -0
  40. execsql/metacommands/io_fileops.py +85 -39
  41. execsql/metacommands/io_import.py +1 -0
  42. execsql/metacommands/io_write.py +1 -1
  43. execsql/metacommands/prompt.py +24 -22
  44. execsql/metacommands/system.py +14 -1
  45. execsql/models.py +56 -17
  46. execsql/parser.py +8 -8
  47. execsql/plugins.py +1 -1
  48. execsql/script/engine.py +4 -4
  49. execsql/script/executor.py +69 -28
  50. execsql/script/parser.py +13 -12
  51. execsql/script/variables.py +4 -2
  52. execsql/state.pyi +122 -0
  53. execsql/types.py +31 -26
  54. execsql/utils/auth.py +6 -2
  55. execsql/utils/datetime.py +3 -3
  56. execsql/utils/errors.py +7 -5
  57. execsql/utils/fileio.py +80 -32
  58. execsql/utils/gui.py +15 -11
  59. execsql/utils/mail.py +9 -2
  60. execsql/utils/numeric.py +1 -1
  61. execsql/utils/regex.py +9 -9
  62. {execsql2-2.21.2.dist-info → execsql2-2.22.1.dist-info}/METADATA +114 -132
  63. execsql2-2.22.1.dist-info/RECORD +123 -0
  64. execsql2-2.21.2.dist-info/RECORD +0 -122
  65. {execsql2-2.21.2.data → execsql2-2.22.1.data}/data/execsql2_extras/README.md +0 -0
  66. {execsql2-2.21.2.data → execsql2-2.22.1.data}/data/execsql2_extras/config_settings.sqlite +0 -0
  67. {execsql2-2.21.2.data → execsql2-2.22.1.data}/data/execsql2_extras/example_config_prompt.sql +0 -0
  68. {execsql2-2.21.2.data → execsql2-2.22.1.data}/data/execsql2_extras/make_config_db.sql +0 -0
  69. {execsql2-2.21.2.data → execsql2-2.22.1.data}/data/execsql2_extras/md_compare.sql +0 -0
  70. {execsql2-2.21.2.data → execsql2-2.22.1.data}/data/execsql2_extras/md_glossary.sql +0 -0
  71. {execsql2-2.21.2.data → execsql2-2.22.1.data}/data/execsql2_extras/md_upsert.sql +0 -0
  72. {execsql2-2.21.2.data → execsql2-2.22.1.data}/data/execsql2_extras/pg_compare.sql +0 -0
  73. {execsql2-2.21.2.data → execsql2-2.22.1.data}/data/execsql2_extras/pg_glossary.sql +0 -0
  74. {execsql2-2.21.2.data → execsql2-2.22.1.data}/data/execsql2_extras/pg_upsert.sql +0 -0
  75. {execsql2-2.21.2.data → execsql2-2.22.1.data}/data/execsql2_extras/script_template.sql +0 -0
  76. {execsql2-2.21.2.data → execsql2-2.22.1.data}/data/execsql2_extras/ss_compare.sql +0 -0
  77. {execsql2-2.21.2.data → execsql2-2.22.1.data}/data/execsql2_extras/ss_glossary.sql +0 -0
  78. {execsql2-2.21.2.data → execsql2-2.22.1.data}/data/execsql2_extras/ss_upsert.sql +0 -0
  79. {execsql2-2.21.2.dist-info → execsql2-2.22.1.dist-info}/WHEEL +0 -0
  80. {execsql2-2.21.2.dist-info → execsql2-2.22.1.dist-info}/entry_points.txt +0 -0
  81. {execsql2-2.21.2.dist-info → execsql2-2.22.1.dist-info}/licenses/LICENSE.txt +0 -0
  82. {execsql2-2.21.2.dist-info → execsql2-2.22.1.dist-info}/licenses/NOTICE +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: execsql2
3
- Version: 2.21.2
3
+ Version: 2.22.1
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
@@ -130,10 +130,7 @@ Requires-Dist: pg-upsert>=1.23.0; extra == 'upsert'
130
130
  Description-Content-Type: text/markdown
131
131
 
132
132
  > [!NOTE]
133
- > **This is a maintained fork of [execsql](https://execsql.readthedocs.io/).**
134
- > The original monolith has been fully refactored into a modular package.
135
- > The CLI and configuration are backwards-compatible with upstream v1.130.1.
136
- > Report issues at [github.com/geocoug/execsql/issues](https://github.com/geocoug/execsql/issues).
133
+ > ***execsql2* is a maintained fork of [execsql](https://execsql.readthedocs.io/)**, originally authored by R.Dreas Nielsen and no longer actively maintained upstream. The monolith has been fully refactored into a modular package; the CLI and configuration remain backwards-compatible with upstream v1.130.1. Maintained by [Caleb Grant](https://github.com/geocoug) and distributed on PyPI as [`execsql2`](https://pypi.org/project/execsql2/). Report issues at [github.com/geocoug/execsql/issues](https://github.com/geocoug/execsql/issues).
137
134
 
138
135
  <div align="center">
139
136
 
@@ -155,48 +152,59 @@ Description-Content-Type: text/markdown
155
152
 
156
153
  </div>
157
154
 
158
- # Fork
155
+ ## Overview
159
156
 
160
- *execsql2* is a maintained fork of [execsql](https://execsql.readthedocs.io/) originally authored by R.Dreas Nielsen. The upstream project is no longer actively maintained. This fork is maintained by [Caleb Grant](https://github.com/geocoug) and is distributed on PyPI as `execsql2`. Complete documentation is at [execsql2.readthedocs.io](https://execsql2.readthedocs.io/).
157
+ *execsql* runs SQL scripts against PostgreSQL, MySQL/MariaDB, SQLite, DuckDB, MS-SQL-Server, MS-Access, Firebird, Oracle, or an ODBC DSN. In addition to standard SQL, it supports a set of metacommands (embedded in SQL comments) for importing and exporting data, copying data between databases, conditional execution, looping, substitution variables, and interactive prompts. Because metacommands live in SQL comments, scripts remain valid SQL and are ignored by other tools such as `psql` or `sqlcmd`.
161
158
 
162
- # Overview
159
+ ## Example
163
160
 
164
- *execsql* runs SQL scripts against PostgreSQL, MySQL/MariaDB, SQLite, DuckDB, MS-SQL-Server, MS-Access, Firebird, Oracle, or an ODBC DSN. In addition to standard SQL, it supports a set of metacommands (embedded in SQL comments) for importing and exporting data, copying data between databases, conditional execution, looping, substitution variables, and interactive prompts. Because metacommands live in SQL comments, scripts remain valid SQL and are ignored by other tools such as `psql` or `sqlcmd`.
161
+ Lines prefixed with `-- !x!` are metacommands; identifiers wrapped in `!!` are substitution variables:
165
162
 
166
- # Installation
163
+ ```sql
164
+ -- ==== Configuration ====
165
+ -- Put the (date-tagged) logfile name in the 'inputfile' substitution variable.
166
+ -- !x! SUB inputfile logs/errors_!!$date_tag!!
167
+ -- Ensure that the export directory will be created if necessary.
168
+ -- !x! CONFIG MAKE_EXPORT_DIRS Yes
167
169
 
168
- ```bash
169
- pip install execsql2
170
+ -- ==== Display Fatal Errors ====
171
+ -- !x! IF(file_exists(!!inputfile!!))
172
+ -- Import the data to a staging table.
173
+ -- !x! IMPORT TO REPLACEMENT staging.errorlog FROM !!inputfile!!
174
+ -- Create a view to display only fatal errors.
175
+ create temporary view fatals as
176
+ select user, run_time, process
177
+ from staging.errorlog
178
+ where severity = 'FATAL';
179
+ -- !x! IF(HASROWS(fatals))
180
+ -- Export the fatal errors to a dated report.
181
+ -- !x! EXPORT fatals TO reports/error_report_!!$date_tag!! AS CSV
182
+ -- Also display it to the user in a GUI.
183
+ -- !x! PROMPT MESSAGE "Fatal errors in !!inputfile!!:" DISPLAY fatals
184
+ -- !x! ELSE
185
+ -- !x! WRITE "There are no fatal errors."
186
+ -- !x! ENDIF
187
+ -- !x! ELSE
188
+ -- !x! WRITE "There is no error log."
189
+ -- !x! ENDIF
190
+ drop table if exists staging.errorlog cascade;
170
191
  ```
171
192
 
172
- Optional extras install database drivers and feature bundles:
193
+ The `PROMPT` metacommand produces a GUI display of the data:
194
+
195
+ ![PROMPT display of 'fatals' view](https://execsql2.readthedocs.io/en/latest/images/fatals.png)
196
+
197
+ ## Installation
173
198
 
174
199
  ```bash
175
- # Database drivers
176
- pip install execsql2[postgres] # PostgreSQL (psycopg2-binary)
177
- pip install execsql2[mysql] # MySQL / MariaDB (pymysql)
178
- pip install execsql2[mssql] # SQL Server (pyodbc)
179
- pip install execsql2[duckdb] # DuckDB
180
- pip install execsql2[firebird] # Firebird (firebird-driver)
181
- pip install execsql2[oracle] # Oracle (oracledb)
182
- pip install execsql2[odbc] # ODBC DSN (pyodbc)
183
-
184
- # Feature bundles
185
- pip install execsql2[formats] # ODS, Excel, Jinja2, Feather, Parquet, HDF5
186
- pip install execsql2[upsert] # pg-upsert for PostgreSQL upsert operations
187
- pip install execsql2[auth] # OS keyring integration
188
- pip install execsql2[auth-plaintext] # Keyring + plaintext file backend (headless Linux)
189
- pip install execsql2[auth-encrypted] # Keyring + encrypted file backend (headless Linux)
190
- pip install execsql2[map] # tkintermapview for PROMPT MAP
191
-
192
- # Convenience
193
- pip install execsql2[all-db] # All database drivers
194
- pip install execsql2[all] # Everything
200
+ pip install execsql2 # core — SQLite works with no extras
201
+ pip install "execsql2[postgres]" # add a driver: postgres, mysql, mssql, duckdb, firebird, oracle, odbc
202
+ pip install "execsql2[all]" # everything: all drivers plus all feature extras
195
203
  ```
196
204
 
197
- SQLite connections use Python's standard library and require no additional packages.
205
+ Feature extras cover spreadsheet and Parquet/Feather formats, keyring authentication, PostgreSQL upsert, and more see the [installation guide](https://execsql2.readthedocs.io/en/latest/getting-started/installation/) for the full list.
198
206
 
199
- # Usage
207
+ ## Usage
200
208
 
201
209
  ```text
202
210
  execsql [OPTIONS] SQL_SCRIPT [SERVER DATABASE | DATABASE_FILE]
@@ -214,7 +222,7 @@ execsql -to script.sql myserver myservice # Oracle
214
222
  execsql script.sql # read connection from config file
215
223
  ```
216
224
 
217
- ## Supported Databases
225
+ ### Supported Databases
218
226
 
219
227
  | Flag | Database |
220
228
  | ---- | --------------- |
@@ -228,67 +236,53 @@ execsql script.sql # read connection from config file
228
236
  | `o` | Oracle |
229
237
  | `d` | ODBC DSN |
230
238
 
231
- ## Options
232
-
233
- | Flag | Description |
234
- | ------------------------------------- | ------------------------------------------------------------------ |
235
- | `-t {p,m,s,l,k,a,f,o,d}` | Database type |
236
- | `-u USER` | Database username |
237
- | `-p PORT` | Server port |
238
- | `-a VALUE` | Set substitution variable `$ARG_x` |
239
- | `-b` / `--boolean-int` | Treat integers 0 and 1 as boolean values |
240
- | `-c SCRIPT` | Execute inline SQL or metacommand string |
241
- | `-d` | Auto-create export directories |
242
- | `-e ENCODING` / `--database-encoding` | Character encoding used in the database |
243
- | `-f ENCODING` | Script file encoding (default: UTF-8) |
244
- | `-g ENCODING` / `--output-encoding` | Encoding for WRITE and EXPORT output |
245
- | `-i ENCODING` / `--import-encoding` | Encoding for data files used with IMPORT |
246
- | `-l` | Write run log to `~/execsql.log` |
247
- | `-m` | List metacommands and exit |
248
- | `-n` | Create a new SQLite or PostgreSQL database if it does not exist |
249
- | `-o` / `--online-help` | Open the online documentation in the default browser |
250
- | `-s N` / `--scan-lines` | Lines to scan for IMPORT format detection (0 = scan entire file) |
251
- | `-v {0,1,2,3}` | GUI level (0=none, 1=password, 2=selection, 3=full) |
252
- | `-w` | Skip password prompt when a username is supplied |
253
- | `-y` / `--encodings` | List available encoding names and exit |
254
- | `-z KB` / `--import-buffer` | Import buffer size in KB (default: 32) |
255
- | `--dsn URL` | Connection string (e.g. `postgresql://user:pass@host/db`) |
256
- | `--output-dir DIR` | Default base directory for EXPORT output files |
257
- | `--dry-run` | Parse the script and report commands without executing |
258
- | `--lint` | Static analysis: check structure and warn on issues (no DB) |
259
- | `--parse-tree` | Print the script's AST structure and exit (no DB) |
260
- | `--list-plugins` | List discovered plugins and exit |
261
- | `--ping` | Test database connectivity and exit |
262
- | `--profile` | Show per-statement timing summary after execution |
263
- | `--profile-limit N` | Top N statements to display in `--profile` summary (default: 20) |
264
- | `--progress` | Show a progress bar for long-running IMPORT operations |
265
- | `--config FILE` | Load an explicit config file (highest priority after CLI args) |
266
- | `--no-system-cmd` | Disable the `SYSTEM_CMD` metacommand (safer for CI / shared envs) |
267
- | `--no-rm-file` | Disable the `RM_FILE` metacommand (no script-driven file deletion) |
268
- | `--no-serve` | Disable the `SERVE` metacommand (no script-driven file streaming) |
269
- | `--init-config` | Print a default `execsql.conf` template to stdout and exit |
270
- | `--debug` | Start in step-through debug mode (REPL pauses before each stmt) |
271
- | `--dump-keywords` | Print metacommand keywords as JSON and exit |
272
- | `--gui-framework {tkinter,textual}` | GUI framework for interactive prompts |
273
-
274
- Run `execsql --help` for the full option list, or `execsql -m` to list all metacommands.
275
-
276
- # Features
239
+ ### Common options
240
+
241
+ | Flag | Description |
242
+ | ------------------------------------------------- | --------------------------------------------------------------- |
243
+ | `-t {p,m,s,l,k,a,f,o,d}` | Database type |
244
+ | `-u USER` | Database username |
245
+ | `-p PORT` | Server port |
246
+ | `--dsn URL` | Connection string (e.g. `postgresql://user:pass@host/db`) |
247
+ | `-n` | Create a new SQLite or PostgreSQL database if it does not exist |
248
+ | `-c SCRIPT` | Execute inline SQL or metacommand string |
249
+ | `-a VALUE` | Set substitution variable `$ARG_x` |
250
+ | `-v {0,1,2,3}` | GUI level (0=none, 1=password, 2=selection, 3=full) |
251
+ | `--config FILE` | Load an explicit config file |
252
+ | `--dry-run` | Parse the script and report commands without executing |
253
+ | `--lint` | Static analysis: check structure and warn on issues (no DB) |
254
+ | `--ping` | Test database connectivity and exit |
255
+ | `--debug` | Start in step-through debug mode (REPL pauses before each stmt) |
256
+ | `--no-system-cmd` / `--no-rm-file` / `--no-serve` | Disable the `SYSTEM_CMD` / `RM_FILE` / `SERVE` metacommands |
257
+
258
+ See the [full options reference](https://execsql2.readthedocs.io/en/latest/getting-started/syntax/#options) or run `execsql --help` for the complete list, and `execsql -m` for all metacommands.
259
+
260
+ ## Features
261
+
262
+ **Data movement**
277
263
 
278
264
  - Import data from CSV, TSV, JSON, Excel, OpenDocument, Feather, or Parquet files into a database table.
279
265
  - Export query results in 20+ formats including CSV, TSV, JSON, YAML, XML, HTML, Markdown, LaTeX, XLSX, OpenDocument, Feather, Parquet, HDF5, DuckDB, SQLite, plain text, and Jinja2 templates.
280
266
  - Copy data between databases, including across different DBMS types.
267
+
268
+ **Script logic**
269
+
281
270
  - Conditionally execute SQL and metacommands using `IF`/`ELSE`/`ENDIF` based on data values, DBMS type, or user input.
282
- - Validate data with `ASSERT` halt the script with a clear error message if a condition is false (ideal for CI pipelines).
283
- - Loop over blocks of SQL and metacommands using `LOOP`/`ENDLOOP`.
271
+ - Loop over blocks of SQL and metacommands using `LOOP`/`ENDLOOP`; include or chain scripts with `INCLUDE` and `SCRIPT`.
284
272
  - Use substitution variables (`SUB`, `$ARG_x`, built-in variables like `$date_tag`) to parameterize scripts.
285
- - Include or chain scripts with `INCLUDE` and `SCRIPT`.
273
+ - Validate data with `ASSERT` halt the script with a clear error message if a condition is false (ideal for CI pipelines).
274
+
275
+ **Interaction & observability**
276
+
286
277
  - Display query results in a GUI dialog; optionally prompt the user to select a row, enter a value, or submit a form.
287
278
  - Write status messages or tabular output to the console or a file during execution.
288
279
  - Automatically log each run, recording databases used, scripts executed, and user responses.
280
+
281
+ **Extensibility**
282
+
289
283
  - Extend with custom metacommands, exporters, and importers via the plugin system.
290
284
 
291
- # Library API
285
+ ## Library API
292
286
 
293
287
  execsql can be used as a Python library for programmatic script execution:
294
288
 
@@ -331,56 +325,43 @@ if not result.success:
331
325
  result.raise_on_error() # raises ExecSqlError
332
326
  ```
333
327
 
334
- Use a pre-existing database connection instead of a DSN:
328
+ Use a pre-existing database connection instead of a DSN — useful for reusing one connection across multiple `run()` calls, or when connection parameters come from your application's configuration rather than a URL:
335
329
 
336
330
  ```python
337
- from execsql.db.factory import db_SQLite
338
- conn = db_SQLite("my.db", new_db=True)
339
- result = run(sql="SELECT 1;", connection=conn)
340
- # run() does NOT close this connection you manage its lifecycle
341
- ```
342
-
343
- Each call to `run()` uses an isolated `RuntimeContext`, so multiple calls do not share state.
344
-
345
- # An Illustration
331
+ from execsql import run
332
+ from execsql.db.factory import db_Postgres, db_SQLite
333
+
334
+ # PostgreSQL connection object (psycopg3 under the hood)
335
+ conn = db_Postgres(
336
+ "db.example.com", # server
337
+ "warehouse", # database
338
+ user="etl",
339
+ port=5432, # optional, default 5432
340
+ password="s3cret", # omit to use keyring / interactive prompt
341
+ )
346
342
 
347
- The following script demonstrates metacommands and substitution variables. Lines prefixed with `-- !x!` are metacommands; identifiers wrapped in `!!` are substitution variables.
343
+ # Reuse the same connection across multiple calls
344
+ staged = run(script="stage.sql", connection=conn)
345
+ loaded = run(
346
+ script="load.sql",
347
+ connection=conn,
348
+ variables={"RUN_DATE": "2026-07-03"},
349
+ )
348
350
 
349
- ```sql
350
- -- ==== Configuration ====
351
- -- Put the (date-tagged) logfile name in the 'inputfile' substitution variable.
352
- -- !x! SUB inputfile logs/errors_!!$date_tag!!
353
- -- Ensure that the export directory will be created if necessary.
354
- -- !x! CONFIG MAKE_EXPORT_DIRS Yes
351
+ # run() does NOT close the connection — you manage its lifecycle
352
+ conn.close()
355
353
 
356
- -- ==== Display Fatal Errors ====
357
- -- !x! IF(file_exists(!!inputfile!!))
358
- -- Import the data to a staging table.
359
- -- !x! IMPORT TO REPLACEMENT staging.errorlog FROM !!inputfile!!
360
- -- Create a view to display only fatal errors.
361
- create temporary view fatals as
362
- select user, run_time, process
363
- from staging.errorlog
364
- where severity = 'FATAL';
365
- -- !x! IF(HASROWS(fatals))
366
- -- Export the fatal errors to a dated report.
367
- -- !x! EXPORT fatals TO reports/error_report_!!$date_tag!! AS CSV
368
- -- Also display it to the user in a GUI.
369
- -- !x! PROMPT MESSAGE "Fatal errors in !!inputfile!!:" DISPLAY fatals
370
- -- !x! ELSE
371
- -- !x! WRITE "There are no fatal errors."
372
- -- !x! ENDIF
373
- -- !x! ELSE
374
- -- !x! WRITE "There is no error log."
375
- -- !x! ENDIF
376
- drop table if exists staging.errorlog cascade;
354
+ # SQLite works the same way
355
+ conn = db_SQLite("my.db", new_db=True)
356
+ result = run(sql="SELECT 1;", connection=conn)
357
+ conn.close()
377
358
  ```
378
359
 
379
- The `PROMPT` metacommand produces a GUI display of the data:
360
+ Factory functions exist for every supported backend (`db_Postgres`, `db_MySQL`, `db_SQLite`, `db_DuckDB`, `db_SqlServer`, `db_Oracle`, `db_Firebird`, `db_Access`, `db_Dsn`) — see [`execsql.db.factory`](https://execsql2.readthedocs.io/en/latest/api/db/).
380
361
 
381
- ![PROMPT display of 'fatals' view](https://execsql2.readthedocs.io/en/latest/images/fatals.png)
362
+ Each call to `run()` uses an isolated `RuntimeContext`, so multiple calls do not share state.
382
363
 
383
- # Formatting Scripts
364
+ ## Formatting Scripts
384
365
 
385
366
  The `execsql-format` command normalizes execsql script files: it uppercases metacommand keywords, corrects block indentation, and optionally reformats SQL via `sqlglot`. The metacommand / indent / keyword reformatting is built into `execsql2`; SQL reformatting requires the `[formatter]` extra (or pass `--no-sql` to skip it):
386
367
 
@@ -403,14 +384,14 @@ execsql-format --no-sql --in-place scripts/
403
384
  ```yaml
404
385
  repos:
405
386
  - repo: https://github.com/geocoug/execsql
406
- rev: v2.21.2
387
+ rev: v2.22.1
407
388
  hooks:
408
389
  - id: execsql-format
409
390
  ```
410
391
 
411
392
  The hook rewrites `*.sql` files in place by default. See the [formatter documentation](https://execsql2.readthedocs.io/en/latest/guides/formatter/) for `--check`, `--indent`, and other options.
412
393
 
413
- # VS Code Syntax Highlighting
394
+ ## VS Code Syntax Highlighting
414
395
 
415
396
  A VS Code extension for execsql syntax highlighting is included in [`extras/vscode-execsql`](extras/vscode-execsql). It injects a TextMate grammar into `.sql` files, adding highlighting for `-- !x!` metacommand markers, keywords (control flow, block, action, directive), variable substitutions (`!!var!!`, `!{var}!`), built-in functions, export formats, and config options — all layered on top of standard SQL highlighting.
416
397
 
@@ -422,7 +403,7 @@ ln -s /path/to/execsql/extras/vscode-execsql ~/.vscode/extensions/execsql-syntax
422
403
 
423
404
  See the [extension README](extras/vscode-execsql/README.md) for Windows instructions, color customization, and troubleshooting.
424
405
 
425
- # Templates
406
+ ## Templates
426
407
 
427
408
  The `templates/` directory in this repository includes ready-to-use execsql scripts:
428
409
 
@@ -432,13 +413,14 @@ The `templates/` directory in this repository includes ready-to-use execsql scri
432
413
  - **`script_template.sql`**: A framework for new scripts with sections for configuration, logging, and error reporting.
433
414
  - **`execsql.conf`**: An annotated configuration file covering all available settings.
434
415
 
435
- # Documentation
416
+ ## Documentation
436
417
 
437
418
  Full documentation, including a complete metacommand reference and 30+ examples, is at [execsql2.readthedocs.io](https://execsql2.readthedocs.io/).
438
419
 
439
- # Copyright and License
420
+ ## Copyright and License
440
421
 
441
422
  Copyright (c) 2007-2025 R.Dreas Nielsen
423
+
442
424
  Copyright (c) 2026-present Caleb Grant
443
425
 
444
426
  This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the [GNU General Public License](http://www.gnu.org/licenses/) for more details.
@@ -0,0 +1,123 @@
1
+ execsql/__init__.py,sha256=ZeVnpEWu8M2bn3qLmVM72NhWRueUGNbsX8UAPTermo0,901
2
+ execsql/__main__.py,sha256=HdbK-SAhyUmfB6xINY5AzxdMSxGzWSGEG_2dv42Jn64,315
3
+ execsql/api.py,sha256=EOtBwMnm-8fmB_KmvxyjglR6C7CjdYhCPBisJ9CFfJg,22227
4
+ execsql/config.py,sha256=txKziUJLV7UPonj2sGFgkmlinDdSV50aHmR_cuCbEIo,34369
5
+ execsql/exceptions.py,sha256=GlphAiR8iZu4UR4U50WgSqEUMd9_8AeQJ_hhPcJOeQU,9381
6
+ execsql/format.py,sha256=ON8Jy5BSen4UI4SGY5cHKRwsvR0ZoLhH0BdblMwydYE,33670
7
+ execsql/models.py,sha256=-DWTVrPNwM-n1h3e3rXMoBv9-wpWVdZahyy4RB7fRRE,15502
8
+ execsql/parser.py,sha256=aOxZ7Mzgvk7G4-nvy9Bgz7xlaZm6oo81cffDeBk_LCk,15597
9
+ execsql/plugins.py,sha256=l82VWa5NpvOQWD6vcO-WKP-vtn0wp9__wWDFAbwxZg0,12838
10
+ execsql/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ execsql/state.py,sha256=T6UoXXxAkUP-4KKQpfFAlI3WMzm2xUi3LSplJDuRLY0,21965
12
+ execsql/state.pyi,sha256=ES5xdoId-ALCGnLIQvQIGBZljZRB6aOOEMRLKXjO9hA,3770
13
+ execsql/types.py,sha256=eKMF2kb5LHrEwKsiFpy6z_fEH05yC0Cpsg98Ea4SpVA,32231
14
+ execsql/cli/__init__.py,sha256=WPwEIELz-9XFG3Dpf-037eeYBdjtZStxWkT1bc3tMek,23112
15
+ execsql/cli/dsn.py,sha256=svaZtrUXFRL2W5G6FRRiKtR6kehOp7urrVhIx_642Z8,2820
16
+ execsql/cli/help.py,sha256=ThwdZuMIfLPxLAPpGWwXFY_UfyWvYOCjdlBNK20Vzd8,5718
17
+ execsql/cli/lint.py,sha256=YqKzFNUhyb_Th69hYgKk1ZZVjCsZfJMIiUGqp06JwNs,17236
18
+ execsql/cli/run.py,sha256=Yb-Ri3cds0st1hUn4_w-PHMphTsArHhC4fx919SW9gU,39390
19
+ execsql/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
+ execsql/data/execsql.conf.template,sha256=w_rJ1mx3FOWi_7qWLGcxsf3HTR5nSMsbKAzlfcJh_tM,10959
21
+ execsql/db/__init__.py,sha256=jTbuafuKOqYtXFR1wvCOoKK5Lr3l1uErfaIbIr6UywI,1063
22
+ execsql/db/access.py,sha256=h2zAMr3mQrm6vFlOYaN7iaG19K7gitXDuonllelqbcE,19539
23
+ execsql/db/base.py,sha256=0K6mSCqFcheg_T91VOwEnagqqP_eLL2dP5VN4yDz36Q,35414
24
+ execsql/db/dsn.py,sha256=P17FwrjEkmhYiPCWZSRJuHYIQu_BCkumiXLkwZEMb4o,6334
25
+ execsql/db/duckdb.py,sha256=YxtjWSzkbJEzZcfoYKfsA9QRrRL08A31GYzkolJiIw0,3229
26
+ execsql/db/factory.py,sha256=C_cyi3GjNx0opuwc6maFFeCSkjfOfoUjuf68YT4VAHE,5377
27
+ execsql/db/firebird.py,sha256=cV5wUzQHoz7yugHdNxAn8IW7fL3v1riIsGLykCZhZwA,9480
28
+ execsql/db/mysql.py,sha256=hv_OqoJBVIaCh5e2lMTVrgBTNljAaVnxwlAoQYff8c4,18026
29
+ execsql/db/oracle.py,sha256=1_odb5xmlm8vjdJdQXz7SHm9dzIbZ5sxP_IxTklH3kA,12018
30
+ execsql/db/postgres.py,sha256=LIZgx4T_UPZvOk_mn0l832ShNKgzculdOrVrFO7Rj8I,22045
31
+ execsql/db/sqlite.py,sha256=mx56IDwLKAXdep--4C8j15qK22JkJjworSJkfnx1ZFw,11551
32
+ execsql/db/sqlserver.py,sha256=j2ViLoBWzizgaL0u6V4iHfjinrlJ4rpBD3XZiKKdwSU,8968
33
+ execsql/debug/__init__.py,sha256=j6EGUR0dHzUhWN1mHHtf1-Lhjq3Sb1V-vmnq2Ztgj1M,178
34
+ execsql/debug/repl.py,sha256=JObeoEXh15qyk4Q3WQCCqMcBtojlIcu_Xg-ZRDZJi5Q,25491
35
+ execsql/exporters/__init__.py,sha256=-Cnji-OgodJV8ftcDcOyTof0kQMy9J5kKVC8GVFpc3o,670
36
+ execsql/exporters/base.py,sha256=_GoO0YqwlTxrjogxHI3CxxRR64sMgIEjRogt0KCqzoY,6402
37
+ execsql/exporters/delimited.py,sha256=vd9Q74TzeeWSPU03EboqqCBOWwOOeFVL544sPXINI0w,32755
38
+ execsql/exporters/duckdb.py,sha256=912TMdYaSVD-kb-_oebTBHQp8FvYMbWTDEDD80w5Z50,3455
39
+ execsql/exporters/feather.py,sha256=tah48aep0cQRikZcmADXUPTzFddgDUT78Ndw_l0Hsj4,4178
40
+ execsql/exporters/html.py,sha256=BPTGYODiC5_5zaQsVkZ9QVAl67yfCWFTsjK0D-QOJkM,9717
41
+ execsql/exporters/json.py,sha256=wWGT6zjvIdWlO5FmXbaEw1xOhy23f1YY6bm5uQD_NS0,4393
42
+ execsql/exporters/latex.py,sha256=TiHH9EO4eF2AgdUyjpbHNZhvKhIJl8Ew6NoO1z0YbB0,4484
43
+ execsql/exporters/markdown.py,sha256=MOErBwkMHM552JE0QuNkCRyHpxTEI3Pw7o9bZOe3RE8,4447
44
+ execsql/exporters/ods.py,sha256=oenUeZuC34Urlh7rI-PXIWOc-cuKMfUU4HfYj4xzvkQ,19521
45
+ execsql/exporters/parquet.py,sha256=mbCo2Wlit1lkXmyo5EyLd_ATIHSICS49bouiBT2kdAs,1121
46
+ execsql/exporters/pretty.py,sha256=tG7Yr4lwFMs3a0Jrsq6qsNNkE8Q7sMePr61SS5QMaTs,3447
47
+ execsql/exporters/protocol.py,sha256=BxATgz0xKHbB2FpZBeNg7wZfIiCohhD1awlr3JCec0c,4372
48
+ execsql/exporters/raw.py,sha256=9o3BMt7UYmnjbP8OEzmM2kNKfwwERi2yDcuNfUoEfuQ,2530
49
+ execsql/exporters/sqlite.py,sha256=QjP_W90S-hecNqp2A-Vy58DD8MZitME1sTq4lqIS43w,3401
50
+ execsql/exporters/templates.py,sha256=wXvN6HwOHbro6t306Dq7WcnxwGdJMF1veXry9hwuI3k,6016
51
+ execsql/exporters/values.py,sha256=HIyud31aux_dbCphfKHEGeZB9fkIPE5PoGXQz817XIE,2520
52
+ execsql/exporters/xls.py,sha256=iZ_N7hneyfaDKbO1XdYv6doJCFPqJWEJql5rduoNyRU,11197
53
+ execsql/exporters/xlsx.py,sha256=0f-Gdp8DyB3muUdH6tyiGFKGx9UymZ4fL3ja6H0sBjI,11853
54
+ execsql/exporters/xml.py,sha256=t1PSr3i8xvTCWzd9jaxxAy5NcRpl6sqjnZALafKCqpM,2575
55
+ execsql/exporters/yaml.py,sha256=R61Rs_0rd5G3bg344L4hC84GM79IfYXaDO2tkF-BluY,3121
56
+ execsql/exporters/zip.py,sha256=341z4Z4MPtEkXJEtfiMSiuJigERh5_f8RDbNMBbt8KM,5078
57
+ execsql/gui/__init__.py,sha256=oCb-cyhLZzVpWJ4WU5HbqEDBrV-lm0ytEwxemrOZyqs,2048
58
+ execsql/gui/base.py,sha256=15wCaSLvSb21hToCczru46ghmd56ryMpEOOZ0R_dE3U,12740
59
+ execsql/gui/console.py,sha256=hgFnxPP7lLolKgmKCBTSMXIt4uU2L4C32XcA82ytr2U,19438
60
+ execsql/gui/desktop.py,sha256=922OdzjV4OGNDIesOxKOmlsrNp1aJ8St8cVwED0H2sE,59521
61
+ execsql/gui/tui.py,sha256=yXKBqbbJDNC6a25sUKpvy3BR10U2LhLSuGAxkw6ADcQ,65358
62
+ execsql/importers/__init__.py,sha256=zZwdQxMaValCNqUrVdvaA7XPU3J8NmqVJ4uolNWY2iU,299
63
+ execsql/importers/base.py,sha256=3Iq_Sr4cCXKHpjjJYkhZX6uhsIIRAdmvAvTdC4mFlWo,4326
64
+ execsql/importers/csv.py,sha256=Kec1VCycRdfstNoxIXsEsSFqQprZp_edpNiMZm43eTI,4914
65
+ execsql/importers/feather.py,sha256=g2B69d2uv9vmnXcmjFyTVsMP40LYEzFYkhk3gD26mGw,1900
66
+ execsql/importers/json.py,sha256=fL47h09Zzx4Qw3TTQRQJbdPdD3qVMiU-kK9C7j1IQzg,5534
67
+ execsql/importers/ods.py,sha256=VsxIkr7opBamB0PbSFmMWt7G11w8lLUH1k_kRwz28zw,2847
68
+ execsql/importers/xls.py,sha256=D7Ul42gIRYZZC5QxD35ft_wmqQv2f1jNMSbnqlzV0ZA,3851
69
+ execsql/metacommands/__init__.py,sha256=H_D1Z5kN6zfYtxatejQhQhQV1tlVZ7rcdFZ_9uhXu2Q,13010
70
+ execsql/metacommands/conditions.py,sha256=2bfdVV_LCl91quG4SRLur9Jk60NsIOStHlBCeJJ-Djc,30068
71
+ execsql/metacommands/connect.py,sha256=SPk4h9yiUgTD3w1gNOT_oYx8VShggsO357by5Hoy6OI,15344
72
+ execsql/metacommands/control.py,sha256=EAURAsBjEZm3YwOJG0Gr3oI2H5_8p3Cu8-AguhBD_ds,8007
73
+ execsql/metacommands/data.py,sha256=Rp18lHUKSTkwTFRjOQ7bDgZd42LNLVoTS3Zc_bcNEWY,12199
74
+ execsql/metacommands/debug.py,sha256=MeVXAob8ItEg2QzuSUkKDaQCEABnH6u0XcAwJzw36CE,13015
75
+ execsql/metacommands/dispatch.py,sha256=t7x0xWHJA0PeCrYf7jYeSMJgf0yxcZ_xh-_YAtBPHLw,87192
76
+ execsql/metacommands/io.py,sha256=vlGBje5sgnqeilooMdhJDgSRIhysHy5_7LrKtik9Xjs,3011
77
+ execsql/metacommands/io_export.py,sha256=YamxQwURRjZRpCG2z8W3QurncCmEmAyLFqDkxtHo5dY,14434
78
+ execsql/metacommands/io_fileops.py,sha256=l1ZaTMzvsXa88zaQp-scWvUy4TMmN4WVVhr4V6-b-tE,11645
79
+ execsql/metacommands/io_import.py,sha256=bIFQMTEW9Rc5FB0VAR-04eve7FL0g0gBKtdoGR_jXrI,15719
80
+ execsql/metacommands/io_write.py,sha256=yXDkMbQ3haDARVATVUYZprakyJHSyk1NywdKkFLpQ14,12783
81
+ execsql/metacommands/prompt.py,sha256=7pPURC11qBFcKEI7IdhrttbiBKTc1txjH59QN3dvFyQ,37865
82
+ execsql/metacommands/script_ext.py,sha256=CsUbyq8QFPnnvfX_k7fPlYNvvRw1xLmAWER4Exo5pwc,3658
83
+ execsql/metacommands/system.py,sha256=6X2qmMpGUHDzyEluEotXt0Ks9jKQTpc2x0eoYNgN12M,7997
84
+ execsql/metacommands/upsert.py,sha256=wzoMpM8g49pEvU9GkHZ62fPvqV3w1UIUfxVA7HAsS_o,20317
85
+ execsql/script/__init__.py,sha256=eGJPBDWj42aaId2lX_quSrqoKrvGwGElIrGDNCyoV1Y,3547
86
+ execsql/script/ast.py,sha256=TQ4_7Lfw1F8_k6ycdvMZdzwNafrZiljSrthVRWUsuIk,20585
87
+ execsql/script/control.py,sha256=WqLy-HLPqHG3vEzYpKMiIJsD7LpORjyQuUWzFzcGz4w,2327
88
+ execsql/script/engine.py,sha256=KbSB5aXkuDlazh3rRP4vRym_bVTDKmChLQ_OFf3-N8Q,21016
89
+ execsql/script/executor.py,sha256=NEIro9TIIcOvugoqdtk2xs08DQnrzkeQIo1CUwaTbIY,37092
90
+ execsql/script/parser.py,sha256=VhFTJK8kODNRWgIDc3LjYjA3_SMPFATkpjVl82dYnrM,35179
91
+ execsql/script/variables.py,sha256=_hklqCeqPbdOT646Yg3ZcpmPke38_8bukMG3eZMTKZw,16384
92
+ execsql/utils/__init__.py,sha256=0uR6JwVJQRX3vceByNBduCAf5dd5assKjeqJUWvpZoA,278
93
+ execsql/utils/auth.py,sha256=8Wixkx5nayEBG7RT4WTUQpCiElIKS3yOTV_6_-hHTRs,8889
94
+ execsql/utils/crypto.py,sha256=KlT6lPk-v0-qQQfAMfWvT9Q6kRdCD3_5JVaLajNocKM,3051
95
+ execsql/utils/datetime.py,sha256=8BrD24KWeMoouJZiFaXK4HF7plc-O_xrzIw12qOEyp8,3629
96
+ execsql/utils/errors.py,sha256=bDWooUmGdN8xqUt6csq466wPqKPLHHSi7U4hsmrFZxA,8577
97
+ execsql/utils/fileio.py,sha256=_15UIdcRZxZn2R6YP4xQn-6C9CVK2yxj1oEfxULo2_c,33329
98
+ execsql/utils/gui.py,sha256=T22ThhkedzQz9kBidxZwIArt1umIvrgrSUwsPWAwvug,23548
99
+ execsql/utils/mail.py,sha256=SXpTBDx0WIPl2NSjkjmnoChHYVEMyZhIKU4QiJFFZNY,6011
100
+ execsql/utils/numeric.py,sha256=_7bi5R6pHjMCkOPne_Sh5nUj-B8e9g6WFmjptFHaunA,1573
101
+ execsql/utils/regex.py,sha256=B3mSBhRRx_DpUnX_t9IoYd05KvWAebiLMCZqQAmEwcw,3885
102
+ execsql/utils/strings.py,sha256=UQNjpRCEFa1UO6feU-M-9e24wWAvizs_iu_4fFusLxo,8516
103
+ execsql/utils/timer.py,sha256=eDYf5VzCNFk7oo90InJucUm3XcBdhYMogjZMqeg9xzc,1899
104
+ execsql2-2.22.1.data/data/execsql2_extras/README.md,sha256=vX4NTL095dUoA_hesyRMGYBorEZ_Y_tJ9qrd-MVV09I,5032
105
+ execsql2-2.22.1.data/data/execsql2_extras/config_settings.sqlite,sha256=aY5cxR7Q7J6zJ4bC9lu5mHUrhy211Cq3MNKPQVCt02E,20480
106
+ execsql2-2.22.1.data/data/execsql2_extras/example_config_prompt.sql,sha256=2e8KzzVWhho8KxYVHETSVmZdhW7wodioDsqBLSL6m4s,7487
107
+ execsql2-2.22.1.data/data/execsql2_extras/make_config_db.sql,sha256=WwyC6dK-Eh5CAVppiBCDHqiI1_wEI9U95Ytpr4lsZkg,8726
108
+ execsql2-2.22.1.data/data/execsql2_extras/md_compare.sql,sha256=qYYVAjSeHZzjszxV3Bv6bg8Ckbq2kMHl87_gh4sywMU,24140
109
+ execsql2-2.22.1.data/data/execsql2_extras/md_glossary.sql,sha256=hkZ2Onn57LAKKsuXxzhR8tPtcWXkmWEQkwPE58-Tm2k,10796
110
+ execsql2-2.22.1.data/data/execsql2_extras/md_upsert.sql,sha256=_CAK4BzEboRXTNy03SJR-oOjcEdSNMuRBPL6noWUptY,112560
111
+ execsql2-2.22.1.data/data/execsql2_extras/pg_compare.sql,sha256=1zJd4hVUKHR0tncc2qTBC9B4qVV4Us2ITkJpsjN3tMw,24352
112
+ execsql2-2.22.1.data/data/execsql2_extras/pg_glossary.sql,sha256=IKuwna-_8b20ljSkXZruuiQigrCpo7ueQdUqd1MXiuI,9908
113
+ execsql2-2.22.1.data/data/execsql2_extras/pg_upsert.sql,sha256=HpPJtTHvpEjQy03j-3iPxDEOHMRkudOg7O4D4YR38UI,108315
114
+ execsql2-2.22.1.data/data/execsql2_extras/script_template.sql,sha256=2J35ddZPguJ-vwTsz83wErv0jiWUyJcdW_JM0mNKDXA,11155
115
+ execsql2-2.22.1.data/data/execsql2_extras/ss_compare.sql,sha256=j1qVNUPXQsEU7-DoVgDJCGcE0EuIl7whLBT3fgeiMAo,24833
116
+ execsql2-2.22.1.data/data/execsql2_extras/ss_glossary.sql,sha256=2gLxv34xzKt0vy7hSzJH7a9JiMC3ETrv9MofxQwAibU,13065
117
+ execsql2-2.22.1.data/data/execsql2_extras/ss_upsert.sql,sha256=G_8rQ0VzuKIZHWs24O_WrfzpC5S27R1JsL-bFBR3SUQ,117730
118
+ execsql2-2.22.1.dist-info/METADATA,sha256=z76Sqoh_SVHX3ygG4-PohP8X4SJL97UlO8LpmIu2tQ8,20382
119
+ execsql2-2.22.1.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
120
+ execsql2-2.22.1.dist-info/entry_points.txt,sha256=sUOxkM-dN1eBGGpSpDLsAaE0yNXYQKWZAfxPOlMkQyk,90
121
+ execsql2-2.22.1.dist-info/licenses/LICENSE.txt,sha256=LBdhuxejF8_bLCHZ2kWfmDXpDGUu914Gbd6_3JjCRe0,676
122
+ execsql2-2.22.1.dist-info/licenses/NOTICE,sha256=McYzgxYav3U1OaVsY4Su1sfBrfmplpRdA9b6-gCDQCg,342
123
+ execsql2-2.22.1.dist-info/RECORD,,
@@ -1,122 +0,0 @@
1
- execsql/__init__.py,sha256=ZeVnpEWu8M2bn3qLmVM72NhWRueUGNbsX8UAPTermo0,901
2
- execsql/__main__.py,sha256=HdbK-SAhyUmfB6xINY5AzxdMSxGzWSGEG_2dv42Jn64,315
3
- execsql/api.py,sha256=ZFTo_XZPhG21w2vxaeS1lS6o5XmF1FUJRIaypgTOjA8,20919
4
- execsql/config.py,sha256=OOrCcn9m3CNuXkxVOLp7uMhQikzUS2wh_QVhvIzRqIM,33296
5
- execsql/exceptions.py,sha256=EkM5cw2s0D9QCOgS4BU29FEyOnEtCxJ0esPT6l1hT9s,9205
6
- execsql/format.py,sha256=dC2cHGUldOTq1YRENm7vtIIv4vtUswRhxuqeMp99d70,33648
7
- execsql/models.py,sha256=kCTUQg9-vReM6WNFfB_ZrEppuOW5u1uMBQThSkfPC0o,13264
8
- execsql/parser.py,sha256=P3ea8k7T_XLMrbhpFNZXwytdShrY302MKnhosqza1lo,15493
9
- execsql/plugins.py,sha256=2voLwT6eFap6BCBoZYndNNC_bMEJO1f_aP6xQTVXwYI,12815
10
- execsql/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- execsql/state.py,sha256=T6UoXXxAkUP-4KKQpfFAlI3WMzm2xUi3LSplJDuRLY0,21965
12
- execsql/types.py,sha256=5K3aTuWQZHftz5slFODwqxlcvvt6lROISUnvUtRUazs,31799
13
- execsql/cli/__init__.py,sha256=aJknKKIGxYCXpny0cyHXfqJsJ95dBtlEXXhPASFG8GQ,23114
14
- execsql/cli/dsn.py,sha256=svaZtrUXFRL2W5G6FRRiKtR6kehOp7urrVhIx_642Z8,2820
15
- execsql/cli/help.py,sha256=ThwdZuMIfLPxLAPpGWwXFY_UfyWvYOCjdlBNK20Vzd8,5718
16
- execsql/cli/lint.py,sha256=YqKzFNUhyb_Th69hYgKk1ZZVjCsZfJMIiUGqp06JwNs,17236
17
- execsql/cli/run.py,sha256=0gmn7f7RjSYatOUZ34QIzK8gP_vgQFZE6U4P6EKU2H4,38188
18
- execsql/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
- execsql/data/execsql.conf.template,sha256=Sq1Huwb_Uf_lI7zW7m3h11fqU6zjGpGnCU4OVJ_tCe0,10696
20
- execsql/db/__init__.py,sha256=jTbuafuKOqYtXFR1wvCOoKK5Lr3l1uErfaIbIr6UywI,1063
21
- execsql/db/access.py,sha256=sRJOJJo1psSO5RV6QPsFY1YJE5wc5aNOYCFDtxIn_Wo,19413
22
- execsql/db/base.py,sha256=0Cy_M3GHdkQDJMbMeWpNyUIPux9m1cVDy21MGMjhJCI,35002
23
- execsql/db/dsn.py,sha256=CZd5NhUSVvK3irv2maeWsSqBsZjhFsTxIuT29Z0rP2A,6240
24
- execsql/db/duckdb.py,sha256=79lRzKRhw1Pjfqcrba27S4Oq8a8AbDO_d0XkaNKKPQo,3197
25
- execsql/db/factory.py,sha256=C_cyi3GjNx0opuwc6maFFeCSkjfOfoUjuf68YT4VAHE,5377
26
- execsql/db/firebird.py,sha256=cV5wUzQHoz7yugHdNxAn8IW7fL3v1riIsGLykCZhZwA,9480
27
- execsql/db/mysql.py,sha256=Z0vI_nQ6vhG3sYa2fv5NOO3JmAsH6_jVjM8FuujQpqI,17961
28
- execsql/db/oracle.py,sha256=1_odb5xmlm8vjdJdQXz7SHm9dzIbZ5sxP_IxTklH3kA,12018
29
- execsql/db/postgres.py,sha256=LIZgx4T_UPZvOk_mn0l832ShNKgzculdOrVrFO7Rj8I,22045
30
- execsql/db/sqlite.py,sha256=xooU6bvD9Y3frRpnbyesE63r6E1fwEHkkcN1YD_UIUE,11519
31
- execsql/db/sqlserver.py,sha256=j2ViLoBWzizgaL0u6V4iHfjinrlJ4rpBD3XZiKKdwSU,8968
32
- execsql/debug/__init__.py,sha256=j6EGUR0dHzUhWN1mHHtf1-Lhjq3Sb1V-vmnq2Ztgj1M,178
33
- execsql/debug/repl.py,sha256=JObeoEXh15qyk4Q3WQCCqMcBtojlIcu_Xg-ZRDZJi5Q,25491
34
- execsql/exporters/__init__.py,sha256=-Cnji-OgodJV8ftcDcOyTof0kQMy9J5kKVC8GVFpc3o,670
35
- execsql/exporters/base.py,sha256=XTPenHl5TbmbZ3cfPYLVFirGNiVps3Kt3AQKFVKy6ss,6408
36
- execsql/exporters/delimited.py,sha256=GIEeennL_elvcZgq5oSvgxAKAgwr8ea3o5_M_pLmc4g,32341
37
- execsql/exporters/duckdb.py,sha256=R4WbvzBEIK1ptnIc8w6c7jcinG-cuuFYC85_NYCumH0,3146
38
- execsql/exporters/feather.py,sha256=teCu48OBb1mPnTdanmHAWh9wHZ5dmCw_FONRBScYMNg,4157
39
- execsql/exporters/html.py,sha256=BPTGYODiC5_5zaQsVkZ9QVAl67yfCWFTsjK0D-QOJkM,9717
40
- execsql/exporters/json.py,sha256=G9lyJcjgmMvymu_MoVrkSqx2H6JRN7qwA5UEomnPkVQ,4343
41
- execsql/exporters/latex.py,sha256=w_B83_5vKPe8uYxCWGdqvxwJeq0mw5zzKYDiAb7dbN0,4503
42
- execsql/exporters/markdown.py,sha256=_ZX3dikbtAb6qZxYeWxDZAPF0-cNKTPR7or5kTbD2ZU,4436
43
- execsql/exporters/ods.py,sha256=G9dotsua8V6LcEl-rxs3KZOr-U_Dw8KPyJ8i-BQRDpc,19358
44
- execsql/exporters/parquet.py,sha256=mbCo2Wlit1lkXmyo5EyLd_ATIHSICS49bouiBT2kdAs,1121
45
- execsql/exporters/pretty.py,sha256=tG7Yr4lwFMs3a0Jrsq6qsNNkE8Q7sMePr61SS5QMaTs,3447
46
- execsql/exporters/protocol.py,sha256=BxATgz0xKHbB2FpZBeNg7wZfIiCohhD1awlr3JCec0c,4372
47
- execsql/exporters/raw.py,sha256=hqO5XEv_Ab9KiphPvZ9sZEdxWTg-kyn8PH9V3qFksyo,2488
48
- execsql/exporters/sqlite.py,sha256=WpiR6I42dWUzw6_BmN9Ihrx6TEfr_lKpnrrwLA9Aq7E,3074
49
- execsql/exporters/templates.py,sha256=XlWwOVSVItexaQUkmTsWB_mff0t8cdaZ5ocgSU2HsAA,6014
50
- execsql/exporters/values.py,sha256=HIyud31aux_dbCphfKHEGeZB9fkIPE5PoGXQz817XIE,2520
51
- execsql/exporters/xls.py,sha256=9H4Nf8VNwXPxc7Koq_pq-Izxi6zt2MxbsJ6Yxjao4u0,11094
52
- execsql/exporters/xlsx.py,sha256=0f-Gdp8DyB3muUdH6tyiGFKGx9UymZ4fL3ja6H0sBjI,11853
53
- execsql/exporters/xml.py,sha256=lqcOM8uKDoCayU42BPSLNH1_2DIHU5D3LtQItREU90c,2564
54
- execsql/exporters/yaml.py,sha256=1Vuc6uMDuLTkCuXCfXWKz4gLkkAVdEXkLs4gEB_67Xo,3110
55
- execsql/exporters/zip.py,sha256=kr0X6VLE_ULGVQtMzfqZZSUmc1Qupxg9HbMOAvnTQvI,4890
56
- execsql/gui/__init__.py,sha256=oCb-cyhLZzVpWJ4WU5HbqEDBrV-lm0ytEwxemrOZyqs,2048
57
- execsql/gui/base.py,sha256=15wCaSLvSb21hToCczru46ghmd56ryMpEOOZ0R_dE3U,12740
58
- execsql/gui/console.py,sha256=pCBUcFGjlKXMkMjztbmt9glP3me9jAKAgQxnmUE38-0,19396
59
- execsql/gui/desktop.py,sha256=hdy-1-QxeKXe3GDG1lhxkQHhTjZxH7KNl_mVg5ki1qw,59080
60
- execsql/gui/tui.py,sha256=INBCuW6iEEV15P_JrHeviI1JlNCXfoiyPBU-IC5MaLY,65200
61
- execsql/importers/__init__.py,sha256=zZwdQxMaValCNqUrVdvaA7XPU3J8NmqVJ4uolNWY2iU,299
62
- execsql/importers/base.py,sha256=k4ni92H33_-A32dNfxhBd6R5WPwM3o_8dSGABisUlR0,4136
63
- execsql/importers/csv.py,sha256=GUVRP294vHlOlF8XNecPEzatUBOOFIqnrEV9cBQkiv0,4849
64
- execsql/importers/feather.py,sha256=g2B69d2uv9vmnXcmjFyTVsMP40LYEzFYkhk3gD26mGw,1900
65
- execsql/importers/json.py,sha256=fL47h09Zzx4Qw3TTQRQJbdPdD3qVMiU-kK9C7j1IQzg,5534
66
- execsql/importers/ods.py,sha256=VsxIkr7opBamB0PbSFmMWt7G11w8lLUH1k_kRwz28zw,2847
67
- execsql/importers/xls.py,sha256=7mGYqXko5_wyvEUz186xSzIx8Eeobn5A6DCVAg4YfTM,3838
68
- execsql/metacommands/__init__.py,sha256=H_D1Z5kN6zfYtxatejQhQhQV1tlVZ7rcdFZ_9uhXu2Q,13010
69
- execsql/metacommands/conditions.py,sha256=5njexsBqSN_MNQdnw9Ra51BcS7ekACHNvBI2MXZF6_g,29995
70
- execsql/metacommands/connect.py,sha256=W24gYGmYDXNQyzBTsqWtl9-qbX2FS0v_c4s_OHj97mY,15327
71
- execsql/metacommands/control.py,sha256=btF9hP_jzTuTIODPK72CYF0v_oKYpwXpKLATt-Ti2kc,7988
72
- execsql/metacommands/data.py,sha256=PPO6AnF_swFxy9GNrtMsv3YttT5ZrjOMA4QtEORDcso,12136
73
- execsql/metacommands/debug.py,sha256=MeVXAob8ItEg2QzuSUkKDaQCEABnH6u0XcAwJzw36CE,13015
74
- execsql/metacommands/dispatch.py,sha256=t7x0xWHJA0PeCrYf7jYeSMJgf0yxcZ_xh-_YAtBPHLw,87192
75
- execsql/metacommands/io.py,sha256=vlGBje5sgnqeilooMdhJDgSRIhysHy5_7LrKtik9Xjs,3011
76
- execsql/metacommands/io_export.py,sha256=-7VDtUUQegwGRantw-NpdkI_9hwIKU-36ZvReIYC2QA,14285
77
- execsql/metacommands/io_fileops.py,sha256=6yED22UlVNXcRHNxZTgna8HmwFcR8s4nt6epMGLMtHY,10139
78
- execsql/metacommands/io_import.py,sha256=kUHIiI16WMuxXpqDMIRBc06KvI-_sYuYfJVNMTKOoAo,15706
79
- execsql/metacommands/io_write.py,sha256=RqOklmeGifu3lQgi_0glOoBWTY9FFIDlWIpOpb_hc3o,12789
80
- execsql/metacommands/prompt.py,sha256=LUl7doqKx8fLR0qt2lXbhdgNpdF1s6KZ6Ruitt10YnM,37483
81
- execsql/metacommands/script_ext.py,sha256=CsUbyq8QFPnnvfX_k7fPlYNvvRw1xLmAWER4Exo5pwc,3658
82
- execsql/metacommands/system.py,sha256=5ETiWbkVDGsdwTldDaMM4rwY_Smd02wCWUROtf6XH_M,7385
83
- execsql/metacommands/upsert.py,sha256=wzoMpM8g49pEvU9GkHZ62fPvqV3w1UIUfxVA7HAsS_o,20317
84
- execsql/script/__init__.py,sha256=eGJPBDWj42aaId2lX_quSrqoKrvGwGElIrGDNCyoV1Y,3547
85
- execsql/script/ast.py,sha256=TQ4_7Lfw1F8_k6ycdvMZdzwNafrZiljSrthVRWUsuIk,20585
86
- execsql/script/control.py,sha256=WqLy-HLPqHG3vEzYpKMiIJsD7LpORjyQuUWzFzcGz4w,2327
87
- execsql/script/engine.py,sha256=52RmtQJGk4KWqXpZY7jfKeiPojAoULHWaigOcm1azm4,20979
88
- execsql/script/executor.py,sha256=Y0con6Mz4n240krEVeVSqmeCLVvIXyF4aLlNBMyZQyc,35790
89
- execsql/script/parser.py,sha256=z19gERLqyvEoDx4hDUws3Z8EKqTM7huNOitTOSmg8_0,35300
90
- execsql/script/variables.py,sha256=t0BwrRuA8m1LYHGLkDPNbqW6QmudXroOFYsO0fwK2N0,16302
91
- execsql/utils/__init__.py,sha256=0uR6JwVJQRX3vceByNBduCAf5dd5assKjeqJUWvpZoA,278
92
- execsql/utils/auth.py,sha256=dnLie8jFxN_l7ZrrRufVuxGw92iG62DIVatIjlEb4pM,8717
93
- execsql/utils/crypto.py,sha256=KlT6lPk-v0-qQQfAMfWvT9Q6kRdCD3_5JVaLajNocKM,3051
94
- execsql/utils/datetime.py,sha256=rMCXAbvj6bxKCYzC97vrludO6PU5DYQ39buZ0smDC5A,3573
95
- execsql/utils/errors.py,sha256=C-9hlpJ7GM5gpDBdTsT4xFhK0OHNjonHgbq7fMl-Vvc,8577
96
- execsql/utils/fileio.py,sha256=38Z0WBvfaMa624aw3jo9ZOSlUCsacIeJWOhQKYe9YlU,31012
97
- execsql/utils/gui.py,sha256=kpJkvi8zblXFdO4PgsF8yE_gkOJrsDwWoQWmaDpjJEQ,23402
98
- execsql/utils/mail.py,sha256=ojdROW6Ti7paVpVMIxRXh7opOdE61fE2duS8xoA6d2Q,5758
99
- execsql/utils/numeric.py,sha256=xh02ANSRk3nUpQ-rtm66ILoMqoi7HtzCoRMIOT9U8QI,1570
100
- execsql/utils/regex.py,sha256=diEzTZqU_HHwVMadPAvN1Vgzhl7I03eVaEFGCXyGGL8,3770
101
- execsql/utils/strings.py,sha256=UQNjpRCEFa1UO6feU-M-9e24wWAvizs_iu_4fFusLxo,8516
102
- execsql/utils/timer.py,sha256=eDYf5VzCNFk7oo90InJucUm3XcBdhYMogjZMqeg9xzc,1899
103
- execsql2-2.21.2.data/data/execsql2_extras/README.md,sha256=vX4NTL095dUoA_hesyRMGYBorEZ_Y_tJ9qrd-MVV09I,5032
104
- execsql2-2.21.2.data/data/execsql2_extras/config_settings.sqlite,sha256=aY5cxR7Q7J6zJ4bC9lu5mHUrhy211Cq3MNKPQVCt02E,20480
105
- execsql2-2.21.2.data/data/execsql2_extras/example_config_prompt.sql,sha256=2e8KzzVWhho8KxYVHETSVmZdhW7wodioDsqBLSL6m4s,7487
106
- execsql2-2.21.2.data/data/execsql2_extras/make_config_db.sql,sha256=WwyC6dK-Eh5CAVppiBCDHqiI1_wEI9U95Ytpr4lsZkg,8726
107
- execsql2-2.21.2.data/data/execsql2_extras/md_compare.sql,sha256=qYYVAjSeHZzjszxV3Bv6bg8Ckbq2kMHl87_gh4sywMU,24140
108
- execsql2-2.21.2.data/data/execsql2_extras/md_glossary.sql,sha256=hkZ2Onn57LAKKsuXxzhR8tPtcWXkmWEQkwPE58-Tm2k,10796
109
- execsql2-2.21.2.data/data/execsql2_extras/md_upsert.sql,sha256=_CAK4BzEboRXTNy03SJR-oOjcEdSNMuRBPL6noWUptY,112560
110
- execsql2-2.21.2.data/data/execsql2_extras/pg_compare.sql,sha256=1zJd4hVUKHR0tncc2qTBC9B4qVV4Us2ITkJpsjN3tMw,24352
111
- execsql2-2.21.2.data/data/execsql2_extras/pg_glossary.sql,sha256=IKuwna-_8b20ljSkXZruuiQigrCpo7ueQdUqd1MXiuI,9908
112
- execsql2-2.21.2.data/data/execsql2_extras/pg_upsert.sql,sha256=HpPJtTHvpEjQy03j-3iPxDEOHMRkudOg7O4D4YR38UI,108315
113
- execsql2-2.21.2.data/data/execsql2_extras/script_template.sql,sha256=2J35ddZPguJ-vwTsz83wErv0jiWUyJcdW_JM0mNKDXA,11155
114
- execsql2-2.21.2.data/data/execsql2_extras/ss_compare.sql,sha256=j1qVNUPXQsEU7-DoVgDJCGcE0EuIl7whLBT3fgeiMAo,24833
115
- execsql2-2.21.2.data/data/execsql2_extras/ss_glossary.sql,sha256=2gLxv34xzKt0vy7hSzJH7a9JiMC3ETrv9MofxQwAibU,13065
116
- execsql2-2.21.2.data/data/execsql2_extras/ss_upsert.sql,sha256=G_8rQ0VzuKIZHWs24O_WrfzpC5S27R1JsL-bFBR3SUQ,117730
117
- execsql2-2.21.2.dist-info/METADATA,sha256=FxjzfphuMwSJ5e8lLMJkKTG4TFrh_Q4haGA2FlwBAFE,22612
118
- execsql2-2.21.2.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
119
- execsql2-2.21.2.dist-info/entry_points.txt,sha256=sUOxkM-dN1eBGGpSpDLsAaE0yNXYQKWZAfxPOlMkQyk,90
120
- execsql2-2.21.2.dist-info/licenses/LICENSE.txt,sha256=LBdhuxejF8_bLCHZ2kWfmDXpDGUu914Gbd6_3JjCRe0,676
121
- execsql2-2.21.2.dist-info/licenses/NOTICE,sha256=McYzgxYav3U1OaVsY4Su1sfBrfmplpRdA9b6-gCDQCg,342
122
- execsql2-2.21.2.dist-info/RECORD,,