execsql2 2.10.1__py3-none-any.whl → 2.11.0__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 (26) hide show
  1. execsql/cli/__init__.py +6 -0
  2. execsql/cli/run.py +5 -1
  3. execsql/metacommands/debug_repl.py +105 -44
  4. execsql/script/engine.py +10 -6
  5. execsql/utils/errors.py +41 -2
  6. {execsql2-2.10.1.dist-info → execsql2-2.11.0.dist-info}/METADATA +2 -1
  7. {execsql2-2.10.1.dist-info → execsql2-2.11.0.dist-info}/RECORD +26 -26
  8. {execsql2-2.10.1.data → execsql2-2.11.0.data}/data/execsql2_extras/README.md +0 -0
  9. {execsql2-2.10.1.data → execsql2-2.11.0.data}/data/execsql2_extras/config_settings.sqlite +0 -0
  10. {execsql2-2.10.1.data → execsql2-2.11.0.data}/data/execsql2_extras/example_config_prompt.sql +0 -0
  11. {execsql2-2.10.1.data → execsql2-2.11.0.data}/data/execsql2_extras/execsql.conf +0 -0
  12. {execsql2-2.10.1.data → execsql2-2.11.0.data}/data/execsql2_extras/make_config_db.sql +0 -0
  13. {execsql2-2.10.1.data → execsql2-2.11.0.data}/data/execsql2_extras/md_compare.sql +0 -0
  14. {execsql2-2.10.1.data → execsql2-2.11.0.data}/data/execsql2_extras/md_glossary.sql +0 -0
  15. {execsql2-2.10.1.data → execsql2-2.11.0.data}/data/execsql2_extras/md_upsert.sql +0 -0
  16. {execsql2-2.10.1.data → execsql2-2.11.0.data}/data/execsql2_extras/pg_compare.sql +0 -0
  17. {execsql2-2.10.1.data → execsql2-2.11.0.data}/data/execsql2_extras/pg_glossary.sql +0 -0
  18. {execsql2-2.10.1.data → execsql2-2.11.0.data}/data/execsql2_extras/pg_upsert.sql +0 -0
  19. {execsql2-2.10.1.data → execsql2-2.11.0.data}/data/execsql2_extras/script_template.sql +0 -0
  20. {execsql2-2.10.1.data → execsql2-2.11.0.data}/data/execsql2_extras/ss_compare.sql +0 -0
  21. {execsql2-2.10.1.data → execsql2-2.11.0.data}/data/execsql2_extras/ss_glossary.sql +0 -0
  22. {execsql2-2.10.1.data → execsql2-2.11.0.data}/data/execsql2_extras/ss_upsert.sql +0 -0
  23. {execsql2-2.10.1.dist-info → execsql2-2.11.0.dist-info}/WHEEL +0 -0
  24. {execsql2-2.10.1.dist-info → execsql2-2.11.0.dist-info}/entry_points.txt +0 -0
  25. {execsql2-2.10.1.dist-info → execsql2-2.11.0.dist-info}/licenses/LICENSE.txt +0 -0
  26. {execsql2-2.10.1.dist-info → execsql2-2.11.0.dist-info}/licenses/NOTICE +0 -0
execsql/cli/__init__.py CHANGED
@@ -278,6 +278,11 @@ def main(
278
278
  "--profile",
279
279
  help="Record per-statement execution times and print a timing summary after the script completes.",
280
280
  ),
281
+ debug: bool = typer.Option(
282
+ False,
283
+ "--debug",
284
+ help="Start in step-through debug mode. The debug REPL pauses before each statement.",
285
+ ),
281
286
  version: bool | None = typer.Option(
282
287
  None,
283
288
  "--version",
@@ -446,6 +451,7 @@ def main(
446
451
  profile=profile,
447
452
  ping=ping,
448
453
  lint=lint,
454
+ debug=debug,
449
455
  )
450
456
 
451
457
 
execsql/cli/run.py CHANGED
@@ -214,6 +214,7 @@ def _run(
214
214
  profile: bool = False,
215
215
  ping: bool = False,
216
216
  lint: bool = False,
217
+ debug: bool = False,
217
218
  ) -> None:
218
219
  """Initialise state, connect to the database, load the script, and run it.
219
220
 
@@ -547,6 +548,9 @@ def _run(
547
548
  if profile:
548
549
  _state.profile_data = []
549
550
 
551
+ if debug:
552
+ _state.step_mode = True
553
+
550
554
  _execute_script_direct(conf, profile=profile)
551
555
 
552
556
 
@@ -653,7 +657,7 @@ def _execute_script_direct(conf: ConfigData, *, profile: bool = False) -> None:
653
657
  lno = strace[0][1]
654
658
  msg = f"{Path(sys.argv[0]).name}: Uncaught exception {sys.exc_info()[0]} ({sys.exc_info()[1]}) on line {lno}"
655
659
  script, slno = current_script_line()
656
- if script is not None:
660
+ if script:
657
661
  msg += f" in script {script}, line {slno}"
658
662
  from execsql.utils.errors import exit_now
659
663
 
@@ -13,6 +13,11 @@ The REPL allows the user to:
13
13
  - Step through the script one statement at a time.
14
14
  - Resume or abort execution.
15
15
 
16
+ All REPL commands are dot-prefixed (``.continue``, ``.vars``, ``.next``)
17
+ to avoid ambiguity with variable names and SQL. Anything not starting
18
+ with ``.`` is treated as either a variable lookup (if it matches a known
19
+ variable) or SQL (if it ends with ``;``).
20
+
16
21
  In non-interactive environments (CI, piped input, ``sys.stdin.isatty()`` is
17
22
  ``False``) the metacommand is silently skipped so automated pipelines are not
18
23
  blocked.
@@ -30,15 +35,19 @@ __all__ = ["x_breakpoint"]
30
35
  # ---------------------------------------------------------------------------
31
36
 
32
37
  _HELP_TEXT = """\
33
- execsql debug REPL commands:
34
- continue c Resume script execution
35
- abort q quit Halt the script (exit 1)
36
- vars List all substitution variables and their values
37
- $VARNAME Print a single variable's value (also &VAR, @VAR)
38
- SELECT ...; Run ad-hoc SQL against the current database
39
- next n Execute the next statement then pause again (step mode)
40
- stack Show the command-list stack (script name, line, depth)
41
- help Show this help text
38
+ execsql debug REPL — all commands start with '.'
39
+
40
+ .continue .c Resume script execution
41
+ .abort .q Halt the script (exit 1)
42
+ .vars List user, system, local, and counter variables
43
+ .vars all Include environment variables (&) in the listing
44
+ .next .n Execute the next statement then pause again (step mode)
45
+ .stack Show the command-list stack (script name, line, depth)
46
+ .help Show this help text
47
+
48
+ Everything else:
49
+ varname Print a variable's value (e.g. logfile, $ARG_1, &HOME)
50
+ SELECT ...; Run ad-hoc SQL against the current database
42
51
  """
43
52
 
44
53
 
@@ -64,7 +73,7 @@ def x_breakpoint(**kwargs: Any) -> None:
64
73
  def _debug_repl() -> None:
65
74
  """Interactive read-eval-print loop for script debugging.
66
75
 
67
- Reads commands from stdin until the user types ``continue`` or ``abort``,
76
+ Reads commands from stdin until the user types ``.continue`` or ``.abort``,
68
77
  or until EOF / KeyboardInterrupt.
69
78
  """
70
79
  try:
@@ -72,7 +81,7 @@ def _debug_repl() -> None:
72
81
  except ImportError:
73
82
  pass # readline not available on Windows; continue without it
74
83
 
75
- _write("\n[Breakpoint] Script paused. Type 'help' for commands, 'continue' to resume.\n")
84
+ _write("\n[Breakpoint] Script paused. Type '.help' for commands, '.c' to resume.\n")
76
85
 
77
86
  while True:
78
87
  try:
@@ -87,27 +96,48 @@ def _debug_repl() -> None:
87
96
  if not line:
88
97
  continue
89
98
 
90
- lower = line.lower()
99
+ # Dot-prefixed → REPL command
100
+ if line.startswith("."):
101
+ _handle_dot_command(line)
102
+ if line.lower().lstrip(".") in ("continue", "c"):
103
+ return
104
+ if line.lower().lstrip(".") in ("abort", "q", "quit"):
105
+ # _handle_dot_command already raised SystemExit, but guard anyway
106
+ return
107
+ if line.lower().lstrip(".") in ("next", "n"):
108
+ return
109
+ continue
91
110
 
92
- if lower in ("continue", "c"):
93
- return
94
- elif lower in ("abort", "q", "quit"):
95
- raise SystemExit(1)
96
- elif lower == "help":
97
- _write(_HELP_TEXT)
98
- elif lower == "vars":
99
- _print_all_vars()
100
- elif lower == "stack":
101
- _print_stack()
102
- elif lower in ("next", "n"):
103
- _enable_step_mode()
104
- return
105
- elif line[0] in ("$", "&", "@"):
106
- _print_var(line)
107
- elif line.rstrip().endswith(";"):
111
+ # SQL (ends with semicolon)
112
+ if line.rstrip().endswith(";"):
108
113
  _run_sql(line)
109
- else:
110
- _write(f"Unknown command: {line!r}. Type 'help' for available commands.\n")
114
+ continue
115
+
116
+ # Everything else → variable lookup
117
+ _print_var(line)
118
+
119
+
120
+ def _handle_dot_command(line: str) -> None:
121
+ """Dispatch a dot-prefixed REPL command."""
122
+ # Strip the leading dot and normalize
123
+ cmd = line[1:].strip().lower()
124
+
125
+ if cmd in ("continue", "c"):
126
+ return # caller checks and returns from _debug_repl
127
+ elif cmd in ("abort", "q", "quit"):
128
+ raise SystemExit(1)
129
+ elif cmd == "help":
130
+ _write(_HELP_TEXT)
131
+ elif cmd == "vars all":
132
+ _print_all_vars(include_env=True)
133
+ elif cmd == "vars":
134
+ _print_all_vars()
135
+ elif cmd == "stack":
136
+ _print_stack()
137
+ elif cmd in ("next", "n"):
138
+ _enable_step_mode()
139
+ else:
140
+ _write(f" Unknown command: {line!r}. Type '.help' for available commands.\n")
111
141
 
112
142
 
113
143
  # ---------------------------------------------------------------------------
@@ -125,8 +155,8 @@ def _write(text: str) -> None:
125
155
  sys.stdout.flush()
126
156
 
127
157
 
128
- def _print_all_vars() -> None:
129
- """Print all substitution variables and their current values."""
158
+ def _print_all_vars(*, include_env: bool = False) -> None:
159
+ """Print substitution variables grouped by type."""
130
160
  subvars = _state.subvars
131
161
  if subvars is None:
132
162
  _write(" (no substitution variables defined)\n")
@@ -135,17 +165,52 @@ def _print_all_vars() -> None:
135
165
  if not items:
136
166
  _write(" (no substitution variables defined)\n")
137
167
  return
138
- # Compute column width for aligned output.
139
- max_name = max((len(name) for name, _ in items), default=0)
168
+
169
+ # Group by prefix.
170
+ user_vars: list[tuple[str, str]] = []
171
+ system_vars: list[tuple[str, str]] = []
172
+ counter_vars: list[tuple[str, str]] = []
173
+ local_vars: list[tuple[str, str]] = []
174
+ env_vars: list[tuple[str, str]] = []
175
+
140
176
  for name, value in sorted(items):
141
- _write(f" {name:<{max_name}} = {value!r}\n")
177
+ if name.startswith("&"):
178
+ env_vars.append((name, value))
179
+ elif name.startswith("~"):
180
+ local_vars.append((name, value))
181
+ elif name.startswith("@"):
182
+ counter_vars.append((name, value))
183
+ elif name.startswith("$"):
184
+ system_vars.append((name, value))
185
+ else:
186
+ user_vars.append((name, value))
187
+
188
+ def _print_group(label: str, group: list[tuple[str, str]]) -> None:
189
+ if not group:
190
+ return
191
+ _write(f" {label}:\n")
192
+ max_name = max(len(n) for n, _ in group)
193
+ for name, value in group:
194
+ _write(f" {name:<{max_name}} = {value}\n")
195
+
196
+ _print_group("User variables", user_vars)
197
+ _print_group("System variables ($)", system_vars)
198
+ _print_group("Local variables (~)", local_vars)
199
+ _print_group("Counter variables (@)", counter_vars)
200
+ if include_env:
201
+ _print_group("Environment variables (&)", env_vars)
202
+
203
+ if not any([user_vars, system_vars, local_vars, counter_vars]):
204
+ if env_vars:
205
+ _write(" (no script variables defined — use '.vars all' to see environment variables)\n")
206
+ else:
207
+ _write(" (no variables defined)\n")
142
208
 
143
209
 
144
210
  def _print_var(varname: str) -> None:
145
211
  """Print the value of a single substitution variable.
146
212
 
147
- Args:
148
- varname: The variable reference as typed by the user, e.g. ``$FOO``.
213
+ Tries the name as typed, then with the sigil prefix stripped.
149
214
  """
150
215
  subvars = _state.subvars
151
216
  if subvars is None:
@@ -153,14 +218,14 @@ def _print_var(varname: str) -> None:
153
218
  return
154
219
  # Try the name as typed first, then without the sigil prefix ($, &, @, #, ~).
155
220
  # SUB creates variables without a prefix (e.g., "logfile"), but users
156
- # naturally type "$logfile" at the prompt.
221
+ # may type "$logfile" at the prompt.
157
222
  value = subvars.varvalue(varname)
158
223
  if value is None and len(varname) > 1 and varname[0] in "$&@#~":
159
224
  value = subvars.varvalue(varname[1:])
160
225
  if value is None:
161
226
  _write(f" {varname}: (undefined)\n")
162
227
  else:
163
- _write(f" {varname} = {value!r}\n")
228
+ _write(f" {varname} = {value}\n")
164
229
 
165
230
 
166
231
  def _print_stack() -> None:
@@ -177,11 +242,7 @@ def _print_stack() -> None:
177
242
 
178
243
 
179
244
  def _run_sql(sql: str) -> None:
180
- """Execute ad-hoc SQL against the current database and pretty-print the results.
181
-
182
- Args:
183
- sql: A complete SQL statement ending with a semicolon.
184
- """
245
+ """Execute ad-hoc SQL against the current database and pretty-print the results."""
185
246
  dbs = _state.dbs
186
247
  if dbs is None:
187
248
  _write(" (no database connection is active)\n")
execsql/script/engine.py CHANGED
@@ -306,6 +306,7 @@ class SqlStmt:
306
306
  e = ErrInfo(type="exception", exception_msg=exception_desc())
307
307
  if e:
308
308
  _state.subvars.add_substitution("$LAST_ERROR", cmd)
309
+ _state.subvars.add_substitution("$ERROR_MESSAGE", str(e))
309
310
  _state.status.sql_error = True
310
311
  if _state.status.halt_on_err:
311
312
  from execsql.utils.errors import exit_now
@@ -350,8 +351,11 @@ class MetacommandStmt:
350
351
  if e:
351
352
  _state.status.metacommand_error = True
352
353
  _state.subvars.add_substitution("$LAST_ERROR", cmd)
354
+ _state.subvars.add_substitution("$ERROR_MESSAGE", str(e))
353
355
  if _state.status.halt_on_metacommand_err:
354
- raise ErrInfo(type="cmd", command_text=cmd, other_msg=errmsg)
356
+ # Re-raise the original ErrInfo so its message is preserved, not
357
+ # replaced with the generic "Unknown metacommand" text.
358
+ raise e
355
359
  if _state.if_stack.all_true():
356
360
  # but nothing applies, because we got here.
357
361
  _state.status.metacommand_error = True
@@ -489,6 +493,11 @@ class CommandList:
489
493
  _state.subvars.add_substitution("$CURRENT_SCRIPT_NAME", Path(cmditem.source).name)
490
494
  _state.subvars.add_substitution("$CURRENT_SCRIPT_LINE", str(cmditem.line_no))
491
495
  _state.subvars.add_substitution("$SCRIPT_LINE", str(cmditem.line_no))
496
+ if _state.step_mode:
497
+ _state.step_mode = False
498
+ from execsql.metacommands.debug_repl import _debug_repl
499
+
500
+ _debug_repl()
492
501
  _profiling = _state.profile_data is not None
493
502
  if _profiling:
494
503
  import time as _time
@@ -506,11 +515,6 @@ class CommandList:
506
515
  cmditem.command.commandline()[:100],
507
516
  ),
508
517
  )
509
- if _state.step_mode:
510
- _state.step_mode = False
511
- from execsql.metacommands.debug_repl import _debug_repl
512
-
513
- _debug_repl()
514
518
  self.cmdptr += 1
515
519
 
516
520
  def run_next(self) -> None:
execsql/utils/errors.py CHANGED
@@ -30,6 +30,7 @@ __all__ = [
30
30
  "exception_desc",
31
31
  "exit_now",
32
32
  "fatal_error",
33
+ "stamp_errinfo",
33
34
  "write_warning",
34
35
  "file_size_date",
35
36
  "chainfuncs",
@@ -70,9 +71,37 @@ def exception_desc() -> str:
70
71
  return f"{exc_type}: {exc_strval} in {exc_filename} on line {exc_lineno} of execsql."
71
72
 
72
73
 
74
+ def stamp_errinfo(errinfo: ErrInfo) -> ErrInfo:
75
+ """Attach script location from ``_state.last_command`` to an :class:`~execsql.exceptions.ErrInfo`.
76
+
77
+ Reads the source file name, line number, command text, and command type from
78
+ the most-recently-executed :class:`~execsql.script.engine.ScriptCmd` and
79
+ populates any ``None`` fields on *errinfo*. This ensures that error messages
80
+ include "Line N of script foo.sql" context even when the ErrInfo was originally
81
+ created deep inside a handler that had no access to execution state.
82
+
83
+ Args:
84
+ errinfo: The :class:`~execsql.exceptions.ErrInfo` to stamp.
85
+
86
+ Returns:
87
+ The same *errinfo* object, with location fields populated.
88
+ """
89
+ lc = _state.last_command
90
+ if lc is not None and errinfo.script_file is None:
91
+ errinfo.script_file = lc.source
92
+ errinfo.script_line_no = lc.line_no
93
+ if errinfo.cmd is None:
94
+ errinfo.cmd = lc.command.commandline() if hasattr(lc.command, "commandline") else None
95
+ errinfo.cmdtype = lc.command_type
96
+ return errinfo
97
+
98
+
73
99
  def exit_now(exit_status: int, errinfo: ErrInfo | None, logmsg: str | None = None) -> None:
74
100
  em = None
75
101
  if errinfo is not None:
102
+ stamp_errinfo(errinfo)
103
+ if _state.subvars is not None:
104
+ _state.subvars.add_substitution("$ERROR_MESSAGE", errinfo.errmsg())
76
105
  em = errinfo.write()
77
106
  if _state.err_halt_writespec is not None:
78
107
  try:
@@ -147,10 +176,20 @@ def fatal_error(error_msg: str | None = None) -> None:
147
176
  exit_now(1, ErrInfo("error", other_msg=error_msg))
148
177
 
149
178
 
150
- def write_warning(warning_msg: str) -> None:
179
+ def write_warning(warning_msg: str, *, always: bool = False) -> None:
180
+ """Write a non-fatal warning message to the log and optionally to stderr.
181
+
182
+ Args:
183
+ warning_msg: The warning text to emit.
184
+ always: When ``True``, always write to stderr regardless of the
185
+ ``conf.write_warnings`` setting. Use this for structural warnings
186
+ (e.g. IF-level mismatch, unsubstituted variables) that should always
187
+ be visible. When ``False`` (default), stderr output is gated by
188
+ ``conf.write_warnings``.
189
+ """
151
190
  if _state.exec_log is not None:
152
191
  _state.exec_log.log_status_warning(warning_msg)
153
- if _state.conf is not None and _state.conf.write_warnings and _state.output is not None:
192
+ if _state.output is not None and (always or (_state.conf is not None and _state.conf.write_warnings)):
154
193
  _state.output.write_err(f"**** Warning {warning_msg}")
155
194
 
156
195
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: execsql2
3
- Version: 2.10.1
3
+ Version: 2.11.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: Repository, https://github.com/geocoug/execsql
6
6
  Project-URL: Issues, https://github.com/geocoug/execsql/issues
@@ -223,6 +223,7 @@ execsql script.sql # read connection from config file
223
223
  | `--dry-run` | Parse the script and report commands without executing |
224
224
  | `--lint` | Static analysis: check structure and warn on issues (no DB) |
225
225
  | `--progress` | Show a progress bar for long-running IMPORT operations |
226
+ | `--debug` | Start in step-through debug mode (REPL pauses before each stmt) |
226
227
  | `--dump-keywords` | Print metacommand keywords as JSON and exit |
227
228
  | `--gui-framework {tkinter,textual}` | GUI framework for interactive prompts |
228
229
 
@@ -9,11 +9,11 @@ execsql/parser.py,sha256=mbNSMiAMR1NvNvFtQAZq6nxBOupMGJZXSimLWLtZeNs,15537
9
9
  execsql/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  execsql/state.py,sha256=ovUQOr78R3LzsDUzBLL9Bq9ZdHiiFVlBvCNzilQ-K-s,15055
11
11
  execsql/types.py,sha256=HVWb4umIB9lpxCGgqk3xy1hoGYPfN39xci5mHF0Izq4,31882
12
- execsql/cli/__init__.py,sha256=Y4lFKvKWyjtMgSLsmACHYG33DFpeAQxddIVrlKURwpg,16081
12
+ execsql/cli/__init__.py,sha256=dPKq7KOY7soD1GfBEztoRWcKuDLY5QyhzgC6PuyeyII,16270
13
13
  execsql/cli/dsn.py,sha256=svaZtrUXFRL2W5G6FRRiKtR6kehOp7urrVhIx_642Z8,2820
14
14
  execsql/cli/help.py,sha256=Sn_TgSJiQeBx-xZH0fuP5OvR_wasSTumjWF9UHfIX5k,5414
15
15
  execsql/cli/lint.py,sha256=KluYROdjGJNUrVbO3cJym-H296zbih4no-F10HF0P4U,16165
16
- execsql/cli/run.py,sha256=i0ip8tm21Sm4EFbfBdcekETmiABzrRfeP84SqA4IF68,30158
16
+ execsql/cli/run.py,sha256=p4QWuBO7WvMPAJDyLtwiVZAdpwjgq1H3wz__WgUiRKA,30218
17
17
  execsql/db/__init__.py,sha256=jTbuafuKOqYtXFR1wvCOoKK5Lr3l1uErfaIbIr6UywI,1063
18
18
  execsql/db/access.py,sha256=L79gUnAnnM9EJ_f4k42jr7DI0qGcKtLOnJTlBC7uPm0,17879
19
19
  execsql/db/base.py,sha256=hfMFj8fXY0T1aXLvWJHqb0aU4EQUDFOc-YrS29HH8U4,30405
@@ -65,7 +65,7 @@ execsql/metacommands/connect.py,sha256=Nsm0D91i3RX-R2rzQQ-Br-gULaI6Uvdn9fqb7DOAV
65
65
  execsql/metacommands/control.py,sha256=CBCg0ZKSR-BGejBW5cXwk6aJ9VrYBzCg9C40ofi8qi8,8776
66
66
  execsql/metacommands/data.py,sha256=tRQBGTAuW-eJ2tBNWaoZI9OjTyNNyHJISo7gOdL-sm8,11370
67
67
  execsql/metacommands/debug.py,sha256=nmfQ2ijUbTQO3drnyV9EzFueGSTfMl-CddP_NlQyI14,8178
68
- execsql/metacommands/debug_repl.py,sha256=UsTup7oYsJ0bNsKKynxQz-4wplFKnIcKSNrkz6gl0VM,7530
68
+ execsql/metacommands/debug_repl.py,sha256=TA4aDWgl_wvR63R9ddBIF-vUB2wRamsxdxzeM8F3WZo,9805
69
69
  execsql/metacommands/dispatch.py,sha256=1Mae6yqrea6wViFLBsvVt33Zgx4xP8tnhOuB_aQC89c,84054
70
70
  execsql/metacommands/io.py,sha256=Duh60caM4go9JczbGYNMKKYpcMimwPzF6EQ_tshKxdE,2971
71
71
  execsql/metacommands/io_export.py,sha256=7lkCSnPhXy9FVau9_hT1u68NOVdG2DsWmvUh9hM1QWI,18359
@@ -77,13 +77,13 @@ execsql/metacommands/script_ext.py,sha256=TUgAldB2LSJAwZrCvDDi804hQ1d9BDQD2GDqHN
77
77
  execsql/metacommands/system.py,sha256=sUR5kLL7idTVg8WXIMdd-Kv7nkERIiaeL0beWsz8NyY,7293
78
78
  execsql/script/__init__.py,sha256=pIo0EJ7-vg67rSMbOvbri_BOUgLoGoSEUfJgxUN7ZS0,3380
79
79
  execsql/script/control.py,sha256=s-1eZdGARM6H1FwZ6VDdO_f50j7bvvRtTHesfUm9tbc,6144
80
- execsql/script/engine.py,sha256=2WcOfYEOwO7L_NQAd3vk_c2wk1VZKJYSakSl07FBUts,40390
80
+ execsql/script/engine.py,sha256=PqR8_5CUoHu1Wm8uLfudGN08h_vWD_3diYzlKhuqdgU,40633
81
81
  execsql/script/variables.py,sha256=MOT9XEHucpuuuHQZM5bklxGMBQcwHzwTBxd0q3aO0XY,11641
82
82
  execsql/utils/__init__.py,sha256=0uR6JwVJQRX3vceByNBduCAf5dd5assKjeqJUWvpZoA,278
83
83
  execsql/utils/auth.py,sha256=onXzNkNZQZxGC5w7eey06sjvAIAX_Lf9g7nUJtcsel0,7009
84
84
  execsql/utils/crypto.py,sha256=2OnBWwn9bCBGc1ZkyRv16TvhottoCNYtXqgbE3mG3Sg,2960
85
85
  execsql/utils/datetime.py,sha256=V_itd5vVvUPjT86P_z_hh4mlerMDGhDzI5MwPMDBaI4,7715
86
- execsql/utils/errors.py,sha256=2Nxp_uivLbhgeFNuAPCiGQzE9VAdF4b1kcPClOpvme8,6380
86
+ execsql/utils/errors.py,sha256=YKhYD27-3timuZavc2vIrRIfHa71vzih-KVPsAKgvkU,8163
87
87
  execsql/utils/fileio.py,sha256=F6M4osE0Mb2ycTcvwwcYnhBXH1L36v6d7Oxdab6J16s,24110
88
88
  execsql/utils/gui.py,sha256=kCfHvqY60jdoJa1k5HlxhrmzM4HPp7uajV6nxz3_Qh4,17583
89
89
  execsql/utils/mail.py,sha256=75A1cMnEfyP0_QMMWuSLv8hrcIjc9cGBCrttLpr2TXQ,5372
@@ -91,24 +91,24 @@ execsql/utils/numeric.py,sha256=xh02ANSRk3nUpQ-rtm66ILoMqoi7HtzCoRMIOT9U8QI,1570
91
91
  execsql/utils/regex.py,sha256=diEzTZqU_HHwVMadPAvN1Vgzhl7I03eVaEFGCXyGGL8,3770
92
92
  execsql/utils/strings.py,sha256=5Dvzrk-9SIw2lpxXZQkiJbNyo1sy7iXXAtSULlZ0KG8,8488
93
93
  execsql/utils/timer.py,sha256=eDYf5VzCNFk7oo90InJucUm3XcBdhYMogjZMqeg9xzc,1899
94
- execsql2-2.10.1.data/data/execsql2_extras/README.md,sha256=sxwVyU0ZahCfANv56LahkyuM505kFjrMhe-1SvWE69E,4845
95
- execsql2-2.10.1.data/data/execsql2_extras/config_settings.sqlite,sha256=aY5cxR7Q7J6zJ4bC9lu5mHUrhy211Cq3MNKPQVCt02E,20480
96
- execsql2-2.10.1.data/data/execsql2_extras/example_config_prompt.sql,sha256=SY3Jxn1qcVm4kPW9xmmTfknHfvURXmeEYTbRjYrjGSw,7487
97
- execsql2-2.10.1.data/data/execsql2_extras/execsql.conf,sha256=_45iJ-KWZnB8uMW_gEg067MM5pmGJ-dVl7VbAZMunAE,9530
98
- execsql2-2.10.1.data/data/execsql2_extras/make_config_db.sql,sha256=WwyC6dK-Eh5CAVppiBCDHqiI1_wEI9U95Ytpr4lsZkg,8726
99
- execsql2-2.10.1.data/data/execsql2_extras/md_compare.sql,sha256=B8Wd7LZ0vnMY2qvA139JIEBkPObgRH2i5xj6PejTQt8,24092
100
- execsql2-2.10.1.data/data/execsql2_extras/md_glossary.sql,sha256=DJRHcU5NbFpxTTX-IwH3yRlsboj1q6BBGrUAHKn4Cuo,10796
101
- execsql2-2.10.1.data/data/execsql2_extras/md_upsert.sql,sha256=v_7GbWh_N1mBTmw3gvTrkagOVp2q0KmXvM8hE-DlFxY,112524
102
- execsql2-2.10.1.data/data/execsql2_extras/pg_compare.sql,sha256=9dWa8hnfy5dVJI-z2iGpd9JzQmI4j2ziMlEdpnr66ro,24352
103
- execsql2-2.10.1.data/data/execsql2_extras/pg_glossary.sql,sha256=pKjIIDsROAgJq2H-1qNEcRMAWManivcZ_AEVHzUUlic,9908
104
- execsql2-2.10.1.data/data/execsql2_extras/pg_upsert.sql,sha256=k7AFiGTLBy3nf-qO5QIaZrEYTAKvdxxU3JDLx9jqkzs,108315
105
- execsql2-2.10.1.data/data/execsql2_extras/script_template.sql,sha256=1Estacb_vm1FgK41k_G9nuduP1yiA-fQ1Kn4Z4mv5Ao,11153
106
- execsql2-2.10.1.data/data/execsql2_extras/ss_compare.sql,sha256=TsVxWm3cEpR5-EiMYXNhtaY0arSNeKZhsJdHdLA7xeI,24833
107
- execsql2-2.10.1.data/data/execsql2_extras/ss_glossary.sql,sha256=cLM7nN8JOIu9ZVP9oY9qdSK3hrnWJiDcX6nZmQQbQWI,13065
108
- execsql2-2.10.1.data/data/execsql2_extras/ss_upsert.sql,sha256=BCqmBykXBF-BpCgOFeG1qhf2XfScKsxPD17wd1hYfHw,120647
109
- execsql2-2.10.1.dist-info/METADATA,sha256=uRqE2iIiqGuy00GvroEk5nPDMg8PXCozmOtfi1DJr4Y,16956
110
- execsql2-2.10.1.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
111
- execsql2-2.10.1.dist-info/entry_points.txt,sha256=sUOxkM-dN1eBGGpSpDLsAaE0yNXYQKWZAfxPOlMkQyk,90
112
- execsql2-2.10.1.dist-info/licenses/LICENSE.txt,sha256=LBdhuxejF8_bLCHZ2kWfmDXpDGUu914Gbd6_3JjCRe0,676
113
- execsql2-2.10.1.dist-info/licenses/NOTICE,sha256=sqVrM73Ys9zfvWC_P797lHfTnoPW_ETeBSrUTFaob0A,339
114
- execsql2-2.10.1.dist-info/RECORD,,
94
+ execsql2-2.11.0.data/data/execsql2_extras/README.md,sha256=sxwVyU0ZahCfANv56LahkyuM505kFjrMhe-1SvWE69E,4845
95
+ execsql2-2.11.0.data/data/execsql2_extras/config_settings.sqlite,sha256=aY5cxR7Q7J6zJ4bC9lu5mHUrhy211Cq3MNKPQVCt02E,20480
96
+ execsql2-2.11.0.data/data/execsql2_extras/example_config_prompt.sql,sha256=SY3Jxn1qcVm4kPW9xmmTfknHfvURXmeEYTbRjYrjGSw,7487
97
+ execsql2-2.11.0.data/data/execsql2_extras/execsql.conf,sha256=_45iJ-KWZnB8uMW_gEg067MM5pmGJ-dVl7VbAZMunAE,9530
98
+ execsql2-2.11.0.data/data/execsql2_extras/make_config_db.sql,sha256=WwyC6dK-Eh5CAVppiBCDHqiI1_wEI9U95Ytpr4lsZkg,8726
99
+ execsql2-2.11.0.data/data/execsql2_extras/md_compare.sql,sha256=B8Wd7LZ0vnMY2qvA139JIEBkPObgRH2i5xj6PejTQt8,24092
100
+ execsql2-2.11.0.data/data/execsql2_extras/md_glossary.sql,sha256=DJRHcU5NbFpxTTX-IwH3yRlsboj1q6BBGrUAHKn4Cuo,10796
101
+ execsql2-2.11.0.data/data/execsql2_extras/md_upsert.sql,sha256=v_7GbWh_N1mBTmw3gvTrkagOVp2q0KmXvM8hE-DlFxY,112524
102
+ execsql2-2.11.0.data/data/execsql2_extras/pg_compare.sql,sha256=9dWa8hnfy5dVJI-z2iGpd9JzQmI4j2ziMlEdpnr66ro,24352
103
+ execsql2-2.11.0.data/data/execsql2_extras/pg_glossary.sql,sha256=pKjIIDsROAgJq2H-1qNEcRMAWManivcZ_AEVHzUUlic,9908
104
+ execsql2-2.11.0.data/data/execsql2_extras/pg_upsert.sql,sha256=k7AFiGTLBy3nf-qO5QIaZrEYTAKvdxxU3JDLx9jqkzs,108315
105
+ execsql2-2.11.0.data/data/execsql2_extras/script_template.sql,sha256=1Estacb_vm1FgK41k_G9nuduP1yiA-fQ1Kn4Z4mv5Ao,11153
106
+ execsql2-2.11.0.data/data/execsql2_extras/ss_compare.sql,sha256=TsVxWm3cEpR5-EiMYXNhtaY0arSNeKZhsJdHdLA7xeI,24833
107
+ execsql2-2.11.0.data/data/execsql2_extras/ss_glossary.sql,sha256=cLM7nN8JOIu9ZVP9oY9qdSK3hrnWJiDcX6nZmQQbQWI,13065
108
+ execsql2-2.11.0.data/data/execsql2_extras/ss_upsert.sql,sha256=BCqmBykXBF-BpCgOFeG1qhf2XfScKsxPD17wd1hYfHw,120647
109
+ execsql2-2.11.0.dist-info/METADATA,sha256=Cmn0y2Xx2ZC-S3lsADP1gSyoCCfAsUGj8wlbyVJ6e8c,17062
110
+ execsql2-2.11.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
111
+ execsql2-2.11.0.dist-info/entry_points.txt,sha256=sUOxkM-dN1eBGGpSpDLsAaE0yNXYQKWZAfxPOlMkQyk,90
112
+ execsql2-2.11.0.dist-info/licenses/LICENSE.txt,sha256=LBdhuxejF8_bLCHZ2kWfmDXpDGUu914Gbd6_3JjCRe0,676
113
+ execsql2-2.11.0.dist-info/licenses/NOTICE,sha256=sqVrM73Ys9zfvWC_P797lHfTnoPW_ETeBSrUTFaob0A,339
114
+ execsql2-2.11.0.dist-info/RECORD,,