execsql2 2.9.0__py3-none-any.whl → 2.10.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 (27) hide show
  1. execsql/metacommands/__init__.py +3 -0
  2. execsql/metacommands/conditions.py +148 -0
  3. execsql/metacommands/debug_repl.py +223 -0
  4. execsql/metacommands/dispatch.py +12 -0
  5. execsql/script/engine.py +5 -0
  6. execsql/state.py +9 -0
  7. {execsql2-2.9.0.dist-info → execsql2-2.10.0.dist-info}/METADATA +1 -1
  8. {execsql2-2.9.0.dist-info → execsql2-2.10.0.dist-info}/RECORD +27 -26
  9. {execsql2-2.9.0.data → execsql2-2.10.0.data}/data/execsql2_extras/README.md +0 -0
  10. {execsql2-2.9.0.data → execsql2-2.10.0.data}/data/execsql2_extras/config_settings.sqlite +0 -0
  11. {execsql2-2.9.0.data → execsql2-2.10.0.data}/data/execsql2_extras/example_config_prompt.sql +0 -0
  12. {execsql2-2.9.0.data → execsql2-2.10.0.data}/data/execsql2_extras/execsql.conf +0 -0
  13. {execsql2-2.9.0.data → execsql2-2.10.0.data}/data/execsql2_extras/make_config_db.sql +0 -0
  14. {execsql2-2.9.0.data → execsql2-2.10.0.data}/data/execsql2_extras/md_compare.sql +0 -0
  15. {execsql2-2.9.0.data → execsql2-2.10.0.data}/data/execsql2_extras/md_glossary.sql +0 -0
  16. {execsql2-2.9.0.data → execsql2-2.10.0.data}/data/execsql2_extras/md_upsert.sql +0 -0
  17. {execsql2-2.9.0.data → execsql2-2.10.0.data}/data/execsql2_extras/pg_compare.sql +0 -0
  18. {execsql2-2.9.0.data → execsql2-2.10.0.data}/data/execsql2_extras/pg_glossary.sql +0 -0
  19. {execsql2-2.9.0.data → execsql2-2.10.0.data}/data/execsql2_extras/pg_upsert.sql +0 -0
  20. {execsql2-2.9.0.data → execsql2-2.10.0.data}/data/execsql2_extras/script_template.sql +0 -0
  21. {execsql2-2.9.0.data → execsql2-2.10.0.data}/data/execsql2_extras/ss_compare.sql +0 -0
  22. {execsql2-2.9.0.data → execsql2-2.10.0.data}/data/execsql2_extras/ss_glossary.sql +0 -0
  23. {execsql2-2.9.0.data → execsql2-2.10.0.data}/data/execsql2_extras/ss_upsert.sql +0 -0
  24. {execsql2-2.9.0.dist-info → execsql2-2.10.0.dist-info}/WHEEL +0 -0
  25. {execsql2-2.9.0.dist-info → execsql2-2.10.0.dist-info}/entry_points.txt +0 -0
  26. {execsql2-2.9.0.dist-info → execsql2-2.10.0.dist-info}/licenses/LICENSE.txt +0 -0
  27. {execsql2-2.9.0.dist-info → execsql2-2.10.0.dist-info}/licenses/NOTICE +0 -0
@@ -100,6 +100,7 @@ from execsql.metacommands.debug import (
100
100
  x_debug_write_subvars,
101
101
  x_debug_write_config,
102
102
  )
103
+ from execsql.metacommands.debug_repl import x_breakpoint
103
104
  from execsql.metacommands.io import (
104
105
  x_export,
105
106
  x_export_query,
@@ -300,6 +301,8 @@ __all__ = [
300
301
  "x_debug_log_config",
301
302
  "x_debug_write_subvars",
302
303
  "x_debug_write_config",
304
+ # debug repl handlers
305
+ "x_breakpoint",
303
306
  # io handlers
304
307
  "x_export",
305
308
  "x_export_query",
@@ -71,6 +71,124 @@ def xf_hasrows(**kwargs: Any) -> bool:
71
71
  return nrows > 0
72
72
 
73
73
 
74
+ def _row_count(queryname: str, sql_context: str, metacommandline: str) -> int:
75
+ """Return the number of rows in *queryname*, raising ErrInfo on failure.
76
+
77
+ Args:
78
+ queryname: Table or view name to count rows in.
79
+ sql_context: The SQL string to include in error messages.
80
+ metacommandline: The full metacommand line for error context.
81
+
82
+ Returns:
83
+ Integer row count.
84
+
85
+ Raises:
86
+ ErrInfo: If the query fails or the result is not numeric.
87
+ """
88
+ sql = f"select count(*) from {queryname};"
89
+ try:
90
+ _hdrs, rec = _state.dbs.current().select_data(sql)
91
+ except ErrInfo:
92
+ raise
93
+ except Exception as e:
94
+ raise ErrInfo("db", sql, exception_msg=exception_desc()) from e
95
+ try:
96
+ return int(rec[0][0])
97
+ except (IndexError, TypeError, ValueError) as e:
98
+ raise ErrInfo(
99
+ type="cmd",
100
+ command_text=metacommandline,
101
+ other_msg=f"Could not read row count for {queryname}.",
102
+ ) from e
103
+
104
+
105
+ def _parse_row_count_n(raw: str, metacommandline: str) -> int:
106
+ """Parse and return the numeric threshold N from the matched group.
107
+
108
+ Args:
109
+ raw: The raw string captured by the regex group (``n``).
110
+ metacommandline: The full metacommand line for error context.
111
+
112
+ Returns:
113
+ Integer value of *raw*.
114
+
115
+ Raises:
116
+ ErrInfo: If *raw* cannot be parsed as an integer.
117
+ """
118
+ try:
119
+ return int(raw.strip())
120
+ except (ValueError, TypeError) as e:
121
+ raise ErrInfo(
122
+ type="cmd",
123
+ command_text=metacommandline,
124
+ other_msg=f"ROW_COUNT threshold must be an integer; got {raw!r}.",
125
+ ) from e
126
+
127
+
128
+ def xf_row_count_gt(**kwargs: Any) -> bool:
129
+ """Return True if the row count of *queryname* is strictly greater than N.
130
+
131
+ Args:
132
+ **kwargs: Named groups from the regex match, plus ``metacommandline``.
133
+ Required keys: ``queryname``, ``n``.
134
+
135
+ Returns:
136
+ True if ``count(*) > N``.
137
+ """
138
+ queryname = kwargs["queryname"]
139
+ mcl = kwargs["metacommandline"]
140
+ n = _parse_row_count_n(kwargs["n"], mcl)
141
+ return _row_count(queryname, f"select count(*) from {queryname};", mcl) > n
142
+
143
+
144
+ def xf_row_count_gte(**kwargs: Any) -> bool:
145
+ """Return True if the row count of *queryname* is greater than or equal to N.
146
+
147
+ Args:
148
+ **kwargs: Named groups from the regex match, plus ``metacommandline``.
149
+ Required keys: ``queryname``, ``n``.
150
+
151
+ Returns:
152
+ True if ``count(*) >= N``.
153
+ """
154
+ queryname = kwargs["queryname"]
155
+ mcl = kwargs["metacommandline"]
156
+ n = _parse_row_count_n(kwargs["n"], mcl)
157
+ return _row_count(queryname, f"select count(*) from {queryname};", mcl) >= n
158
+
159
+
160
+ def xf_row_count_eq(**kwargs: Any) -> bool:
161
+ """Return True if the row count of *queryname* equals N exactly.
162
+
163
+ Args:
164
+ **kwargs: Named groups from the regex match, plus ``metacommandline``.
165
+ Required keys: ``queryname``, ``n``.
166
+
167
+ Returns:
168
+ True if ``count(*) == N``.
169
+ """
170
+ queryname = kwargs["queryname"]
171
+ mcl = kwargs["metacommandline"]
172
+ n = _parse_row_count_n(kwargs["n"], mcl)
173
+ return _row_count(queryname, f"select count(*) from {queryname};", mcl) == n
174
+
175
+
176
+ def xf_row_count_lt(**kwargs: Any) -> bool:
177
+ """Return True if the row count of *queryname* is strictly less than N.
178
+
179
+ Args:
180
+ **kwargs: Named groups from the regex match, plus ``metacommandline``.
181
+ Required keys: ``queryname``, ``n``.
182
+
183
+ Returns:
184
+ True if ``count(*) < N``.
185
+ """
186
+ queryname = kwargs["queryname"]
187
+ mcl = kwargs["metacommandline"]
188
+ n = _parse_row_count_n(kwargs["n"], mcl)
189
+ return _row_count(queryname, f"select count(*) from {queryname};", mcl) < n
190
+
191
+
74
192
  def xf_sqlerror(**kwargs: Any) -> bool:
75
193
  return _state.status.sql_error
76
194
 
@@ -495,6 +613,36 @@ def build_conditional_table() -> Any:
495
613
  mcl.add(r"^\s*HASROWS\((?P<queryname>[^)]+)\)", xf_hasrows, description="HASROWS", category="condition")
496
614
  mcl.add(r"^\s*HAS_ROWS\((?P<queryname>[^)]+)\)", xf_hasrows)
497
615
 
616
+ # ROW_COUNT comparisons — ROW_COUNT_GT/GTE/EQ/LT(table, N)
617
+ # Table name: unquoted, double-quoted, or single-quoted. N: integer literal.
618
+ _rc_table = r"(?P<queryname>[A-Za-z0-9_.\"'\[\]]+)"
619
+ _rc_n = r"(?P<n>\d+)"
620
+ _rc_sep = r"\s*,\s*"
621
+ mcl.add(
622
+ rf"^\s*ROW_COUNT_GT\s*\(\s*{_rc_table}{_rc_sep}{_rc_n}\s*\)",
623
+ xf_row_count_gt,
624
+ description="ROW_COUNT_GT",
625
+ category="condition",
626
+ )
627
+ mcl.add(
628
+ rf"^\s*ROW_COUNT_GTE\s*\(\s*{_rc_table}{_rc_sep}{_rc_n}\s*\)",
629
+ xf_row_count_gte,
630
+ description="ROW_COUNT_GTE",
631
+ category="condition",
632
+ )
633
+ mcl.add(
634
+ rf"^\s*ROW_COUNT_EQ\s*\(\s*{_rc_table}{_rc_sep}{_rc_n}\s*\)",
635
+ xf_row_count_eq,
636
+ description="ROW_COUNT_EQ",
637
+ category="condition",
638
+ )
639
+ mcl.add(
640
+ rf"^\s*ROW_COUNT_LT\s*\(\s*{_rc_table}{_rc_sep}{_rc_n}\s*\)",
641
+ xf_row_count_lt,
642
+ description="ROW_COUNT_LT",
643
+ category="condition",
644
+ )
645
+
498
646
  # Status predicates
499
647
  mcl.add(r"^\s*sql_error\(\s*\)", xf_sqlerror, description="SQL_ERROR", category="condition")
500
648
  mcl.add(r"^\s*dialog_canceled\(\s*\)", xf_dialogcanceled, description="DIALOG_CANCELED", category="condition")
@@ -0,0 +1,223 @@
1
+ from __future__ import annotations
2
+
3
+ """
4
+ Interactive debug REPL metacommand handler for execsql.
5
+
6
+ Implements ``x_breakpoint`` — the ``BREAKPOINT`` metacommand — which pauses
7
+ script execution and drops into an interactive read-eval-print loop.
8
+
9
+ The REPL allows the user to:
10
+
11
+ - Inspect and print substitution variables.
12
+ - Run ad-hoc SQL queries against the current database.
13
+ - Step through the script one statement at a time.
14
+ - Resume or abort execution.
15
+
16
+ In non-interactive environments (CI, piped input, ``sys.stdin.isatty()`` is
17
+ ``False``) the metacommand is silently skipped so automated pipelines are not
18
+ blocked.
19
+ """
20
+
21
+ import sys
22
+ from typing import Any
23
+
24
+ import execsql.state as _state
25
+
26
+ __all__ = ["x_breakpoint"]
27
+
28
+ # ---------------------------------------------------------------------------
29
+ # Public handler
30
+ # ---------------------------------------------------------------------------
31
+
32
+ _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
42
+ """
43
+
44
+
45
+ def x_breakpoint(**kwargs: Any) -> None:
46
+ """Pause execution and enter the interactive debug REPL.
47
+
48
+ If ``sys.stdin`` is not a TTY (CI, piped input), the metacommand is
49
+ silently skipped — scripts will not hang in automation.
50
+
51
+ Args:
52
+ **kwargs: Keyword arguments injected by the dispatch table (unused).
53
+ """
54
+ if not sys.stdin.isatty():
55
+ return
56
+ _debug_repl()
57
+
58
+
59
+ # ---------------------------------------------------------------------------
60
+ # REPL core
61
+ # ---------------------------------------------------------------------------
62
+
63
+
64
+ def _debug_repl() -> None:
65
+ """Interactive read-eval-print loop for script debugging.
66
+
67
+ Reads commands from stdin until the user types ``continue`` or ``abort``,
68
+ or until EOF / KeyboardInterrupt.
69
+ """
70
+ try:
71
+ import readline as _readline # noqa: F401 — side-effect: enables history/arrow keys
72
+ except ImportError:
73
+ pass # readline not available on Windows; continue without it
74
+
75
+ _write("\n[Breakpoint] Script paused. Type 'help' for commands, 'continue' to resume.\n")
76
+
77
+ while True:
78
+ try:
79
+ line = input("execsql debug> ").strip()
80
+ except EOFError:
81
+ _write("\n")
82
+ return # Ctrl-D → continue
83
+ except KeyboardInterrupt:
84
+ _write("\n")
85
+ return # Ctrl-C → continue
86
+
87
+ if not line:
88
+ continue
89
+
90
+ lower = line.lower()
91
+
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(";"):
108
+ _run_sql(line)
109
+ else:
110
+ _write(f"Unknown command: {line!r}. Type 'help' for available commands.\n")
111
+
112
+
113
+ # ---------------------------------------------------------------------------
114
+ # REPL command implementations
115
+ # ---------------------------------------------------------------------------
116
+
117
+
118
+ def _write(text: str) -> None:
119
+ """Write *text* to the execsql output stream (falls back to stdout)."""
120
+ output = _state.output
121
+ if output is not None:
122
+ output.write(text)
123
+ else:
124
+ sys.stdout.write(text)
125
+ sys.stdout.flush()
126
+
127
+
128
+ def _print_all_vars() -> None:
129
+ """Print all substitution variables and their current values."""
130
+ subvars = _state.subvars
131
+ if subvars is None:
132
+ _write(" (no substitution variables defined)\n")
133
+ return
134
+ items = subvars.substitutions # list of (name, value) tuples
135
+ if not items:
136
+ _write(" (no substitution variables defined)\n")
137
+ return
138
+ # Compute column width for aligned output.
139
+ max_name = max((len(name) for name, _ in items), default=0)
140
+ for name, value in sorted(items):
141
+ _write(f" {name:<{max_name}} = {value!r}\n")
142
+
143
+
144
+ def _print_var(varname: str) -> None:
145
+ """Print the value of a single substitution variable.
146
+
147
+ Args:
148
+ varname: The variable reference as typed by the user, e.g. ``$FOO``.
149
+ """
150
+ subvars = _state.subvars
151
+ if subvars is None:
152
+ _write(f" {varname}: (substitution variables not initialised)\n")
153
+ return
154
+ # varvalue() expects the name with its prefix (e.g. "$foo"); it lowercases internally.
155
+ value = subvars.varvalue(varname)
156
+ if value is None:
157
+ _write(f" {varname}: (undefined)\n")
158
+ else:
159
+ _write(f" {varname} = {value!r}\n")
160
+
161
+
162
+ def _print_stack() -> None:
163
+ """Print the current command-list stack (script name, line number, depth)."""
164
+ stack = _state.commandliststack
165
+ if not stack:
166
+ _write(" (command list stack is empty)\n")
167
+ return
168
+ _write(f" Stack depth: {len(stack)}\n")
169
+ for depth, cmdlist in enumerate(stack):
170
+ listname = getattr(cmdlist, "listname", "<unknown>")
171
+ cmdptr = getattr(cmdlist, "cmdptr", 0)
172
+ _write(f" [{depth}] {listname} (cursor at index {cmdptr})\n")
173
+
174
+
175
+ def _run_sql(sql: str) -> None:
176
+ """Execute ad-hoc SQL against the current database and pretty-print the results.
177
+
178
+ Args:
179
+ sql: A complete SQL statement ending with a semicolon.
180
+ """
181
+ dbs = _state.dbs
182
+ if dbs is None:
183
+ _write(" (no database connection is active)\n")
184
+ return
185
+ db = dbs.current()
186
+ if db is None:
187
+ _write(" (no database connection is active)\n")
188
+ return
189
+ try:
190
+ colnames, rows = db.select_data(sql)
191
+ except Exception as exc:
192
+ _write(f" SQL error: {exc}\n")
193
+ return
194
+
195
+ if not colnames:
196
+ _write(" (query returned no columns)\n")
197
+ return
198
+
199
+ # Build a simple text table.
200
+ col_widths = [len(c) for c in colnames]
201
+ str_rows: list[list[str]] = []
202
+ for row in rows:
203
+ str_row = [str(v) if v is not None else "NULL" for v in row]
204
+ str_rows.append(str_row)
205
+ for i, cell in enumerate(str_row):
206
+ col_widths[i] = max(col_widths[i], len(cell))
207
+
208
+ sep = "+-" + "-+-".join("-" * w for w in col_widths) + "-+"
209
+ header = "| " + " | ".join(c.ljust(col_widths[i]) for i, c in enumerate(colnames)) + " |"
210
+ _write(sep + "\n")
211
+ _write(header + "\n")
212
+ _write(sep + "\n")
213
+ for str_row in str_rows:
214
+ data_line = "| " + " | ".join(cell.ljust(col_widths[i]) for i, cell in enumerate(str_row)) + " |"
215
+ _write(data_line + "\n")
216
+ _write(sep + "\n")
217
+ row_word = "row" if len(str_rows) == 1 else "rows"
218
+ _write(f" ({len(str_rows)} {row_word})\n")
219
+
220
+
221
+ def _enable_step_mode() -> None:
222
+ """Activate step mode so the engine re-enters the REPL after the next statement."""
223
+ _state.step_mode = True
@@ -100,6 +100,7 @@ from execsql.metacommands.debug import (
100
100
  x_debug_write_odbc_drivers,
101
101
  x_debug_write_subvars,
102
102
  )
103
+ from execsql.metacommands.debug_repl import x_breakpoint
103
104
  from execsql.metacommands.io import (
104
105
  x_cd,
105
106
  x_copy,
@@ -1690,6 +1691,17 @@ def build_dispatch_table() -> MetaCommandList:
1690
1691
  run_when_false=False,
1691
1692
  )
1692
1693
 
1694
+ # ------------------------------------------------------------------
1695
+ # BREAKPOINT
1696
+ # ------------------------------------------------------------------
1697
+ mcl.add(
1698
+ r"^\s*BREAKPOINT\s*$",
1699
+ x_breakpoint,
1700
+ description="BREAKPOINT",
1701
+ category="action",
1702
+ run_when_false=False,
1703
+ )
1704
+
1693
1705
  # ------------------------------------------------------------------
1694
1706
  # IF / ORIF / ANDIF / ELSEIF / ELSE / ENDIF
1695
1707
  # ------------------------------------------------------------------
execsql/script/engine.py CHANGED
@@ -506,6 +506,11 @@ class CommandList:
506
506
  cmditem.command.commandline()[:100],
507
507
  ),
508
508
  )
509
+ if _state.step_mode:
510
+ _state.step_mode = False
511
+ from execsql.metacommands.debug_repl import _debug_repl
512
+
513
+ _debug_repl()
509
514
  self.cmdptr += 1
510
515
 
511
516
  def run_next(self) -> None:
execsql/state.py CHANGED
@@ -96,6 +96,8 @@ __all__ = [
96
96
  "gui_manager_thread",
97
97
  # Profiling
98
98
  "profile_data",
99
+ # Debug REPL
100
+ "step_mode",
99
101
  # Version
100
102
  "primary_vno",
101
103
  "secondary_vno",
@@ -195,6 +197,8 @@ _CONTEXT_ATTRS: frozenset[str] = frozenset(
195
197
  "gui_manager_thread",
196
198
  # Profiling
197
199
  "profile_data",
200
+ # Debug REPL
201
+ "step_mode",
198
202
  },
199
203
  )
200
204
 
@@ -248,6 +252,8 @@ class RuntimeContext:
248
252
  "gui_manager_thread",
249
253
  # Profiling
250
254
  "profile_data",
255
+ # Debug REPL
256
+ "step_mode",
251
257
  )
252
258
 
253
259
  def __init__(self) -> None:
@@ -299,6 +305,9 @@ class RuntimeContext:
299
305
  # Each entry: (source, line_no, command_type, elapsed_secs, command_text_preview)
300
306
  self.profile_data: list[tuple] | None = None
301
307
 
308
+ # Debug REPL — True after a ``next`` command; engine re-enters REPL after next statement.
309
+ self.step_mode: bool = False
310
+
302
311
 
303
312
  # ---------------------------------------------------------------------------
304
313
  # Module proxy — transparently delegates context attr access to _ctx
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: execsql2
3
- Version: 2.9.0
3
+ Version: 2.10.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
@@ -7,7 +7,7 @@ execsql/format.py,sha256=-6iknDddqbkapMo4NKmT5LAynDLqMW5kHgDWRg0KSws,11990
7
7
  execsql/models.py,sha256=DxkGp9iWbuZDWPGmnxZp9mvEeyOwxEJNx94fxQQiLfQ,13538
8
8
  execsql/parser.py,sha256=mbNSMiAMR1NvNvFtQAZq6nxBOupMGJZXSimLWLtZeNs,15537
9
9
  execsql/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- execsql/state.py,sha256=BodGWiLD7I3s7LFd8Mb6SHMp3I1BhVE4rYcR0UZWAoM,14799
10
+ execsql/state.py,sha256=ovUQOr78R3LzsDUzBLL9Bq9ZdHiiFVlBvCNzilQ-K-s,15055
11
11
  execsql/types.py,sha256=HVWb4umIB9lpxCGgqk3xy1hoGYPfN39xci5mHF0Izq4,31882
12
12
  execsql/cli/__init__.py,sha256=Y4lFKvKWyjtMgSLsmACHYG33DFpeAQxddIVrlKURwpg,16081
13
13
  execsql/cli/dsn.py,sha256=svaZtrUXFRL2W5G6FRRiKtR6kehOp7urrVhIx_642Z8,2820
@@ -59,13 +59,14 @@ execsql/importers/csv.py,sha256=Mu848WNzuhVO1ade-WurPyxqGOuVNRO8UwRF3-bav_I,4845
59
59
  execsql/importers/feather.py,sha256=g2B69d2uv9vmnXcmjFyTVsMP40LYEzFYkhk3gD26mGw,1900
60
60
  execsql/importers/ods.py,sha256=MJsdsjropzCvxAA3DDZfAL_AnmZ4yij7DnrjGyDJqHQ,2843
61
61
  execsql/importers/xls.py,sha256=e0Zfe47ZiCpA1Ae3XDJ1ko3sCiH3-8U6XLKi6NvD0jQ,3683
62
- execsql/metacommands/__init__.py,sha256=ejuY2GFHxNh5f_Yp_GOV0EBe2vuUcly0-zBrKiR3qes,11112
63
- execsql/metacommands/conditions.py,sha256=u-XdeIWj9QMht9hRGhvH0XlB9V09AliAPKDBHRXc02s,24540
62
+ execsql/metacommands/__init__.py,sha256=TT1ARHgHltHqZ7qx4Y62o1h_GOPvUztZKCem-wAE560,11215
63
+ execsql/metacommands/conditions.py,sha256=QUpevCHce9kbKpt6XpHkc73q3bYAIfaBin0b6eaJnYQ,29259
64
64
  execsql/metacommands/connect.py,sha256=Nsm0D91i3RX-R2rzQQ-Br-gULaI6Uvdn9fqb7DOAVfE,14804
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/dispatch.py,sha256=I6HoBKMofRalL1Cmdsnj1jQFZSFXCgntTofFaIZWgWQ,83670
68
+ execsql/metacommands/debug_repl.py,sha256=fjf8O25dQs-Nrl_Uw_0RahKSttkty4cbzUClNsZuV18,7303
69
+ execsql/metacommands/dispatch.py,sha256=1Mae6yqrea6wViFLBsvVt33Zgx4xP8tnhOuB_aQC89c,84054
69
70
  execsql/metacommands/io.py,sha256=Duh60caM4go9JczbGYNMKKYpcMimwPzF6EQ_tshKxdE,2971
70
71
  execsql/metacommands/io_export.py,sha256=7lkCSnPhXy9FVau9_hT1u68NOVdG2DsWmvUh9hM1QWI,18359
71
72
  execsql/metacommands/io_fileops.py,sha256=RKqbWPTYiwiqCZYG-lpih0w1JVOY4RBFdWr3BJb_pnY,9669
@@ -76,7 +77,7 @@ execsql/metacommands/script_ext.py,sha256=TUgAldB2LSJAwZrCvDDi804hQ1d9BDQD2GDqHN
76
77
  execsql/metacommands/system.py,sha256=sUR5kLL7idTVg8WXIMdd-Kv7nkERIiaeL0beWsz8NyY,7293
77
78
  execsql/script/__init__.py,sha256=pIo0EJ7-vg67rSMbOvbri_BOUgLoGoSEUfJgxUN7ZS0,3380
78
79
  execsql/script/control.py,sha256=s-1eZdGARM6H1FwZ6VDdO_f50j7bvvRtTHesfUm9tbc,6144
79
- execsql/script/engine.py,sha256=d3iUGF_r4OQAlqKpd8pIuWGAjDlYvzYiKqi-2Ew1-Yo,40213
80
+ execsql/script/engine.py,sha256=2WcOfYEOwO7L_NQAd3vk_c2wk1VZKJYSakSl07FBUts,40390
80
81
  execsql/script/variables.py,sha256=MOT9XEHucpuuuHQZM5bklxGMBQcwHzwTBxd0q3aO0XY,11641
81
82
  execsql/utils/__init__.py,sha256=0uR6JwVJQRX3vceByNBduCAf5dd5assKjeqJUWvpZoA,278
82
83
  execsql/utils/auth.py,sha256=onXzNkNZQZxGC5w7eey06sjvAIAX_Lf9g7nUJtcsel0,7009
@@ -90,24 +91,24 @@ execsql/utils/numeric.py,sha256=xh02ANSRk3nUpQ-rtm66ILoMqoi7HtzCoRMIOT9U8QI,1570
90
91
  execsql/utils/regex.py,sha256=diEzTZqU_HHwVMadPAvN1Vgzhl7I03eVaEFGCXyGGL8,3770
91
92
  execsql/utils/strings.py,sha256=5Dvzrk-9SIw2lpxXZQkiJbNyo1sy7iXXAtSULlZ0KG8,8488
92
93
  execsql/utils/timer.py,sha256=eDYf5VzCNFk7oo90InJucUm3XcBdhYMogjZMqeg9xzc,1899
93
- execsql2-2.9.0.data/data/execsql2_extras/README.md,sha256=sxwVyU0ZahCfANv56LahkyuM505kFjrMhe-1SvWE69E,4845
94
- execsql2-2.9.0.data/data/execsql2_extras/config_settings.sqlite,sha256=aY5cxR7Q7J6zJ4bC9lu5mHUrhy211Cq3MNKPQVCt02E,20480
95
- execsql2-2.9.0.data/data/execsql2_extras/example_config_prompt.sql,sha256=SY3Jxn1qcVm4kPW9xmmTfknHfvURXmeEYTbRjYrjGSw,7487
96
- execsql2-2.9.0.data/data/execsql2_extras/execsql.conf,sha256=_45iJ-KWZnB8uMW_gEg067MM5pmGJ-dVl7VbAZMunAE,9530
97
- execsql2-2.9.0.data/data/execsql2_extras/make_config_db.sql,sha256=WwyC6dK-Eh5CAVppiBCDHqiI1_wEI9U95Ytpr4lsZkg,8726
98
- execsql2-2.9.0.data/data/execsql2_extras/md_compare.sql,sha256=B8Wd7LZ0vnMY2qvA139JIEBkPObgRH2i5xj6PejTQt8,24092
99
- execsql2-2.9.0.data/data/execsql2_extras/md_glossary.sql,sha256=DJRHcU5NbFpxTTX-IwH3yRlsboj1q6BBGrUAHKn4Cuo,10796
100
- execsql2-2.9.0.data/data/execsql2_extras/md_upsert.sql,sha256=v_7GbWh_N1mBTmw3gvTrkagOVp2q0KmXvM8hE-DlFxY,112524
101
- execsql2-2.9.0.data/data/execsql2_extras/pg_compare.sql,sha256=9dWa8hnfy5dVJI-z2iGpd9JzQmI4j2ziMlEdpnr66ro,24352
102
- execsql2-2.9.0.data/data/execsql2_extras/pg_glossary.sql,sha256=pKjIIDsROAgJq2H-1qNEcRMAWManivcZ_AEVHzUUlic,9908
103
- execsql2-2.9.0.data/data/execsql2_extras/pg_upsert.sql,sha256=k7AFiGTLBy3nf-qO5QIaZrEYTAKvdxxU3JDLx9jqkzs,108315
104
- execsql2-2.9.0.data/data/execsql2_extras/script_template.sql,sha256=1Estacb_vm1FgK41k_G9nuduP1yiA-fQ1Kn4Z4mv5Ao,11153
105
- execsql2-2.9.0.data/data/execsql2_extras/ss_compare.sql,sha256=TsVxWm3cEpR5-EiMYXNhtaY0arSNeKZhsJdHdLA7xeI,24833
106
- execsql2-2.9.0.data/data/execsql2_extras/ss_glossary.sql,sha256=cLM7nN8JOIu9ZVP9oY9qdSK3hrnWJiDcX6nZmQQbQWI,13065
107
- execsql2-2.9.0.data/data/execsql2_extras/ss_upsert.sql,sha256=BCqmBykXBF-BpCgOFeG1qhf2XfScKsxPD17wd1hYfHw,120647
108
- execsql2-2.9.0.dist-info/METADATA,sha256=9IJPnmBiSv11eTc7x9Xswfv0KiAwzwizxJX_umIXaSo,16955
109
- execsql2-2.9.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
110
- execsql2-2.9.0.dist-info/entry_points.txt,sha256=sUOxkM-dN1eBGGpSpDLsAaE0yNXYQKWZAfxPOlMkQyk,90
111
- execsql2-2.9.0.dist-info/licenses/LICENSE.txt,sha256=LBdhuxejF8_bLCHZ2kWfmDXpDGUu914Gbd6_3JjCRe0,676
112
- execsql2-2.9.0.dist-info/licenses/NOTICE,sha256=sqVrM73Ys9zfvWC_P797lHfTnoPW_ETeBSrUTFaob0A,339
113
- execsql2-2.9.0.dist-info/RECORD,,
94
+ execsql2-2.10.0.data/data/execsql2_extras/README.md,sha256=sxwVyU0ZahCfANv56LahkyuM505kFjrMhe-1SvWE69E,4845
95
+ execsql2-2.10.0.data/data/execsql2_extras/config_settings.sqlite,sha256=aY5cxR7Q7J6zJ4bC9lu5mHUrhy211Cq3MNKPQVCt02E,20480
96
+ execsql2-2.10.0.data/data/execsql2_extras/example_config_prompt.sql,sha256=SY3Jxn1qcVm4kPW9xmmTfknHfvURXmeEYTbRjYrjGSw,7487
97
+ execsql2-2.10.0.data/data/execsql2_extras/execsql.conf,sha256=_45iJ-KWZnB8uMW_gEg067MM5pmGJ-dVl7VbAZMunAE,9530
98
+ execsql2-2.10.0.data/data/execsql2_extras/make_config_db.sql,sha256=WwyC6dK-Eh5CAVppiBCDHqiI1_wEI9U95Ytpr4lsZkg,8726
99
+ execsql2-2.10.0.data/data/execsql2_extras/md_compare.sql,sha256=B8Wd7LZ0vnMY2qvA139JIEBkPObgRH2i5xj6PejTQt8,24092
100
+ execsql2-2.10.0.data/data/execsql2_extras/md_glossary.sql,sha256=DJRHcU5NbFpxTTX-IwH3yRlsboj1q6BBGrUAHKn4Cuo,10796
101
+ execsql2-2.10.0.data/data/execsql2_extras/md_upsert.sql,sha256=v_7GbWh_N1mBTmw3gvTrkagOVp2q0KmXvM8hE-DlFxY,112524
102
+ execsql2-2.10.0.data/data/execsql2_extras/pg_compare.sql,sha256=9dWa8hnfy5dVJI-z2iGpd9JzQmI4j2ziMlEdpnr66ro,24352
103
+ execsql2-2.10.0.data/data/execsql2_extras/pg_glossary.sql,sha256=pKjIIDsROAgJq2H-1qNEcRMAWManivcZ_AEVHzUUlic,9908
104
+ execsql2-2.10.0.data/data/execsql2_extras/pg_upsert.sql,sha256=k7AFiGTLBy3nf-qO5QIaZrEYTAKvdxxU3JDLx9jqkzs,108315
105
+ execsql2-2.10.0.data/data/execsql2_extras/script_template.sql,sha256=1Estacb_vm1FgK41k_G9nuduP1yiA-fQ1Kn4Z4mv5Ao,11153
106
+ execsql2-2.10.0.data/data/execsql2_extras/ss_compare.sql,sha256=TsVxWm3cEpR5-EiMYXNhtaY0arSNeKZhsJdHdLA7xeI,24833
107
+ execsql2-2.10.0.data/data/execsql2_extras/ss_glossary.sql,sha256=cLM7nN8JOIu9ZVP9oY9qdSK3hrnWJiDcX6nZmQQbQWI,13065
108
+ execsql2-2.10.0.data/data/execsql2_extras/ss_upsert.sql,sha256=BCqmBykXBF-BpCgOFeG1qhf2XfScKsxPD17wd1hYfHw,120647
109
+ execsql2-2.10.0.dist-info/METADATA,sha256=V4hDmO7GKgx0ZRu8BsVES5C6oyRIUus-MIu7k7RJlfI,16956
110
+ execsql2-2.10.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
111
+ execsql2-2.10.0.dist-info/entry_points.txt,sha256=sUOxkM-dN1eBGGpSpDLsAaE0yNXYQKWZAfxPOlMkQyk,90
112
+ execsql2-2.10.0.dist-info/licenses/LICENSE.txt,sha256=LBdhuxejF8_bLCHZ2kWfmDXpDGUu914Gbd6_3JjCRe0,676
113
+ execsql2-2.10.0.dist-info/licenses/NOTICE,sha256=sqVrM73Ys9zfvWC_P797lHfTnoPW_ETeBSrUTFaob0A,339
114
+ execsql2-2.10.0.dist-info/RECORD,,