execsql2 2.10.1__py3-none-any.whl → 2.11.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.
- execsql/cli/__init__.py +6 -0
- execsql/cli/lint.py +1 -1
- execsql/cli/run.py +8 -3
- execsql/exporters/xlsx.py +5 -0
- execsql/exporters/yaml.py +2 -0
- execsql/metacommands/conditions.py +1 -1
- execsql/metacommands/control.py +4 -10
- execsql/metacommands/debug.py +1 -1
- execsql/metacommands/debug_repl.py +106 -44
- execsql/script/engine.py +21 -7
- execsql/state.py +2 -2
- execsql/utils/errors.py +41 -2
- execsql/utils/gui.py +26 -4
- {execsql2-2.10.1.dist-info → execsql2-2.11.1.dist-info}/METADATA +6 -2
- {execsql2-2.10.1.dist-info → execsql2-2.11.1.dist-info}/RECORD +34 -34
- {execsql2-2.10.1.data → execsql2-2.11.1.data}/data/execsql2_extras/README.md +0 -0
- {execsql2-2.10.1.data → execsql2-2.11.1.data}/data/execsql2_extras/config_settings.sqlite +0 -0
- {execsql2-2.10.1.data → execsql2-2.11.1.data}/data/execsql2_extras/example_config_prompt.sql +0 -0
- {execsql2-2.10.1.data → execsql2-2.11.1.data}/data/execsql2_extras/execsql.conf +0 -0
- {execsql2-2.10.1.data → execsql2-2.11.1.data}/data/execsql2_extras/make_config_db.sql +0 -0
- {execsql2-2.10.1.data → execsql2-2.11.1.data}/data/execsql2_extras/md_compare.sql +0 -0
- {execsql2-2.10.1.data → execsql2-2.11.1.data}/data/execsql2_extras/md_glossary.sql +0 -0
- {execsql2-2.10.1.data → execsql2-2.11.1.data}/data/execsql2_extras/md_upsert.sql +0 -0
- {execsql2-2.10.1.data → execsql2-2.11.1.data}/data/execsql2_extras/pg_compare.sql +0 -0
- {execsql2-2.10.1.data → execsql2-2.11.1.data}/data/execsql2_extras/pg_glossary.sql +0 -0
- {execsql2-2.10.1.data → execsql2-2.11.1.data}/data/execsql2_extras/pg_upsert.sql +0 -0
- {execsql2-2.10.1.data → execsql2-2.11.1.data}/data/execsql2_extras/script_template.sql +0 -0
- {execsql2-2.10.1.data → execsql2-2.11.1.data}/data/execsql2_extras/ss_compare.sql +0 -0
- {execsql2-2.10.1.data → execsql2-2.11.1.data}/data/execsql2_extras/ss_glossary.sql +0 -0
- {execsql2-2.10.1.data → execsql2-2.11.1.data}/data/execsql2_extras/ss_upsert.sql +0 -0
- {execsql2-2.10.1.dist-info → execsql2-2.11.1.dist-info}/WHEEL +0 -0
- {execsql2-2.10.1.dist-info → execsql2-2.11.1.dist-info}/entry_points.txt +0 -0
- {execsql2-2.10.1.dist-info → execsql2-2.11.1.dist-info}/licenses/LICENSE.txt +0 -0
- {execsql2-2.10.1.dist-info → execsql2-2.11.1.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/lint.py
CHANGED
|
@@ -194,7 +194,7 @@ def _lint_cmdlist(
|
|
|
194
194
|
for cmd in cmdlist.cmdlist:
|
|
195
195
|
src = cmd.source
|
|
196
196
|
lno = cmd.line_no
|
|
197
|
-
stmt = cmd.command.statement
|
|
197
|
+
stmt = cmd.command.statement
|
|
198
198
|
|
|
199
199
|
if cmd.command_type == "sql":
|
|
200
200
|
# SQL statements: check for variable references only
|
execsql/cli/run.py
CHANGED
|
@@ -8,6 +8,7 @@ and drives the main execution loop. Separated from argument parsing
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
10
|
import atexit
|
|
11
|
+
from typing import Any
|
|
11
12
|
import datetime
|
|
12
13
|
import getpass
|
|
13
14
|
import os
|
|
@@ -128,7 +129,7 @@ def _print_profile(profile_data: list[tuple]) -> None:
|
|
|
128
129
|
# ---------------------------------------------------------------------------
|
|
129
130
|
|
|
130
131
|
|
|
131
|
-
def _ping_db(db) -> None:
|
|
132
|
+
def _ping_db(db: Any) -> None:
|
|
132
133
|
"""Test connectivity for *db*, print connection details, and exit.
|
|
133
134
|
|
|
134
135
|
Attempts to execute ``SELECT version()`` (or ``SELECT sqlite_version()``
|
|
@@ -156,7 +157,7 @@ def _ping_db(db) -> None:
|
|
|
156
157
|
curs.close()
|
|
157
158
|
if row and row[0]:
|
|
158
159
|
version_str = str(row[0]).split("\n")[0].strip()
|
|
159
|
-
|
|
160
|
+
break
|
|
160
161
|
except Exception:
|
|
161
162
|
continue
|
|
162
163
|
|
|
@@ -214,6 +215,7 @@ def _run(
|
|
|
214
215
|
profile: bool = False,
|
|
215
216
|
ping: bool = False,
|
|
216
217
|
lint: bool = False,
|
|
218
|
+
debug: bool = False,
|
|
217
219
|
) -> None:
|
|
218
220
|
"""Initialise state, connect to the database, load the script, and run it.
|
|
219
221
|
|
|
@@ -547,6 +549,9 @@ def _run(
|
|
|
547
549
|
if profile:
|
|
548
550
|
_state.profile_data = []
|
|
549
551
|
|
|
552
|
+
if debug:
|
|
553
|
+
_state.step_mode = True
|
|
554
|
+
|
|
550
555
|
_execute_script_direct(conf, profile=profile)
|
|
551
556
|
|
|
552
557
|
|
|
@@ -653,7 +658,7 @@ def _execute_script_direct(conf: ConfigData, *, profile: bool = False) -> None:
|
|
|
653
658
|
lno = strace[0][1]
|
|
654
659
|
msg = f"{Path(sys.argv[0]).name}: Uncaught exception {sys.exc_info()[0]} ({sys.exc_info()[1]}) on line {lno}"
|
|
655
660
|
script, slno = current_script_line()
|
|
656
|
-
if script
|
|
661
|
+
if script:
|
|
657
662
|
msg += f" in script {script}, line {slno}"
|
|
658
663
|
from execsql.utils.errors import exit_now
|
|
659
664
|
|
execsql/exporters/xlsx.py
CHANGED
|
@@ -178,6 +178,11 @@ def write_query_to_xlsx(
|
|
|
178
178
|
wb.save(outfile)
|
|
179
179
|
wb.close()
|
|
180
180
|
|
|
181
|
+
if _state.export_metadata is not None:
|
|
182
|
+
_state.export_metadata.add(
|
|
183
|
+
ExportRecord(queryname=select_stmt, outfile=outfile, zipfile=None, description=desc),
|
|
184
|
+
)
|
|
185
|
+
|
|
181
186
|
|
|
182
187
|
def write_queries_to_xlsx(
|
|
183
188
|
table_list: str,
|
execsql/exporters/yaml.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
-
from execsql.exceptions import ErrInfo
|
|
3
2
|
|
|
4
3
|
"""
|
|
5
4
|
Conditional test handler functions for execsql.
|
|
@@ -15,6 +14,7 @@ at registration time.
|
|
|
15
14
|
"""
|
|
16
15
|
|
|
17
16
|
import os
|
|
17
|
+
from execsql.exceptions import ErrInfo
|
|
18
18
|
import time
|
|
19
19
|
from pathlib import Path
|
|
20
20
|
from typing import Any
|
execsql/metacommands/control.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
-
from execsql.exceptions import ErrInfo
|
|
3
2
|
|
|
4
3
|
"""
|
|
5
4
|
Control-flow metacommand handlers for execsql.
|
|
@@ -18,6 +17,8 @@ Implements the imperative ``x_*`` functions for script flow control:
|
|
|
18
17
|
"""
|
|
19
18
|
|
|
20
19
|
import time
|
|
20
|
+
|
|
21
|
+
from execsql.exceptions import ErrInfo
|
|
21
22
|
from typing import Any
|
|
22
23
|
|
|
23
24
|
import execsql.state as _state
|
|
@@ -62,7 +63,8 @@ def x_assert(**kwargs: Any) -> None:
|
|
|
62
63
|
|
|
63
64
|
result = _state.xcmd_test(condition)
|
|
64
65
|
if result:
|
|
65
|
-
_state.exec_log
|
|
66
|
+
if _state.exec_log is not None:
|
|
67
|
+
_state.exec_log.log_user_msg(f"ASSERT passed: {condition}")
|
|
66
68
|
else:
|
|
67
69
|
raise ErrInfo(type="cmd", other_msg=message)
|
|
68
70
|
|
|
@@ -134,14 +136,6 @@ def x_loop(**kwargs: Any) -> None:
|
|
|
134
136
|
)
|
|
135
137
|
|
|
136
138
|
|
|
137
|
-
def endloop() -> None:
|
|
138
|
-
if len(_state.loopcommandstack) == 0:
|
|
139
|
-
raise ErrInfo("error", other_msg="END LOOP metacommand without a matching preceding LOOP metacommand.")
|
|
140
|
-
_state.compiling_loop = False
|
|
141
|
-
_state.commandliststack.append(_state.loopcommandstack[-1])
|
|
142
|
-
_state.loopcommandstack.pop()
|
|
143
|
-
|
|
144
|
-
|
|
145
139
|
def x_halt(**kwargs: Any) -> None:
|
|
146
140
|
errmsg = kwargs["errmsg"]
|
|
147
141
|
tee = kwargs["tee"]
|
execsql/metacommands/debug.py
CHANGED
|
@@ -74,7 +74,7 @@ def x_debug_log_subvars(**kwargs: Any) -> None:
|
|
|
74
74
|
local = kwargs["local"]
|
|
75
75
|
user = kwargs["user"]
|
|
76
76
|
for s in _state.commandliststack[-1].localvars.substitutions:
|
|
77
|
-
_state.exec_log.log_status_info(f"Substitution [{s}] = [{s}]")
|
|
77
|
+
_state.exec_log.log_status_info(f"Substitution [{s[0]}] = [{s[1]}]")
|
|
78
78
|
if local is None:
|
|
79
79
|
for s in _state.subvars.substitutions:
|
|
80
80
|
if user is None or s[0][0].isalnum() or s[0][0] == "_":
|
|
@@ -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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
next n
|
|
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
|
|
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, '
|
|
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,49 @@ def _debug_repl() -> None:
|
|
|
87
96
|
if not line:
|
|
88
97
|
continue
|
|
89
98
|
|
|
90
|
-
|
|
99
|
+
# Dot-prefixed → REPL command
|
|
100
|
+
if line.startswith("."):
|
|
101
|
+
cmd = line[1:].strip().lower()
|
|
102
|
+
_handle_dot_command(line)
|
|
103
|
+
if cmd in ("continue", "c"):
|
|
104
|
+
return
|
|
105
|
+
if cmd in ("abort", "q", "quit"):
|
|
106
|
+
# _handle_dot_command already raised SystemExit, but guard anyway
|
|
107
|
+
return
|
|
108
|
+
if cmd in ("next", "n"):
|
|
109
|
+
return
|
|
110
|
+
continue
|
|
91
111
|
|
|
92
|
-
|
|
93
|
-
|
|
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(";"):
|
|
112
|
+
# SQL (ends with semicolon)
|
|
113
|
+
if line.rstrip().endswith(";"):
|
|
108
114
|
_run_sql(line)
|
|
109
|
-
|
|
110
|
-
|
|
115
|
+
continue
|
|
116
|
+
|
|
117
|
+
# Everything else → variable lookup
|
|
118
|
+
_print_var(line)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def _handle_dot_command(line: str) -> None:
|
|
122
|
+
"""Dispatch a dot-prefixed REPL command."""
|
|
123
|
+
# Strip the leading dot and normalize
|
|
124
|
+
cmd = line[1:].strip().lower()
|
|
125
|
+
|
|
126
|
+
if cmd in ("continue", "c"):
|
|
127
|
+
return # caller checks and returns from _debug_repl
|
|
128
|
+
elif cmd in ("abort", "q", "quit"):
|
|
129
|
+
raise SystemExit(1)
|
|
130
|
+
elif cmd == "help":
|
|
131
|
+
_write(_HELP_TEXT)
|
|
132
|
+
elif cmd == "vars all":
|
|
133
|
+
_print_all_vars(include_env=True)
|
|
134
|
+
elif cmd == "vars":
|
|
135
|
+
_print_all_vars()
|
|
136
|
+
elif cmd == "stack":
|
|
137
|
+
_print_stack()
|
|
138
|
+
elif cmd in ("next", "n"):
|
|
139
|
+
_enable_step_mode()
|
|
140
|
+
else:
|
|
141
|
+
_write(f" Unknown command: {line!r}. Type '.help' for available commands.\n")
|
|
111
142
|
|
|
112
143
|
|
|
113
144
|
# ---------------------------------------------------------------------------
|
|
@@ -125,8 +156,8 @@ def _write(text: str) -> None:
|
|
|
125
156
|
sys.stdout.flush()
|
|
126
157
|
|
|
127
158
|
|
|
128
|
-
def _print_all_vars() -> None:
|
|
129
|
-
"""Print
|
|
159
|
+
def _print_all_vars(*, include_env: bool = False) -> None:
|
|
160
|
+
"""Print substitution variables grouped by type."""
|
|
130
161
|
subvars = _state.subvars
|
|
131
162
|
if subvars is None:
|
|
132
163
|
_write(" (no substitution variables defined)\n")
|
|
@@ -135,17 +166,52 @@ def _print_all_vars() -> None:
|
|
|
135
166
|
if not items:
|
|
136
167
|
_write(" (no substitution variables defined)\n")
|
|
137
168
|
return
|
|
138
|
-
|
|
139
|
-
|
|
169
|
+
|
|
170
|
+
# Group by prefix.
|
|
171
|
+
user_vars: list[tuple[str, str]] = []
|
|
172
|
+
system_vars: list[tuple[str, str]] = []
|
|
173
|
+
counter_vars: list[tuple[str, str]] = []
|
|
174
|
+
local_vars: list[tuple[str, str]] = []
|
|
175
|
+
env_vars: list[tuple[str, str]] = []
|
|
176
|
+
|
|
140
177
|
for name, value in sorted(items):
|
|
141
|
-
|
|
178
|
+
if name.startswith("&"):
|
|
179
|
+
env_vars.append((name, value))
|
|
180
|
+
elif name.startswith("~"):
|
|
181
|
+
local_vars.append((name, value))
|
|
182
|
+
elif name.startswith("@"):
|
|
183
|
+
counter_vars.append((name, value))
|
|
184
|
+
elif name.startswith("$"):
|
|
185
|
+
system_vars.append((name, value))
|
|
186
|
+
else:
|
|
187
|
+
user_vars.append((name, value))
|
|
188
|
+
|
|
189
|
+
def _print_group(label: str, group: list[tuple[str, str]]) -> None:
|
|
190
|
+
if not group:
|
|
191
|
+
return
|
|
192
|
+
_write(f" {label}:\n")
|
|
193
|
+
max_name = max(len(n) for n, _ in group)
|
|
194
|
+
for name, value in group:
|
|
195
|
+
_write(f" {name:<{max_name}} = {value}\n")
|
|
196
|
+
|
|
197
|
+
_print_group("User variables", user_vars)
|
|
198
|
+
_print_group("System variables ($)", system_vars)
|
|
199
|
+
_print_group("Local variables (~)", local_vars)
|
|
200
|
+
_print_group("Counter variables (@)", counter_vars)
|
|
201
|
+
if include_env:
|
|
202
|
+
_print_group("Environment variables (&)", env_vars)
|
|
203
|
+
|
|
204
|
+
if not any([user_vars, system_vars, local_vars, counter_vars]):
|
|
205
|
+
if env_vars:
|
|
206
|
+
_write(" (no script variables defined — use '.vars all' to see environment variables)\n")
|
|
207
|
+
else:
|
|
208
|
+
_write(" (no variables defined)\n")
|
|
142
209
|
|
|
143
210
|
|
|
144
211
|
def _print_var(varname: str) -> None:
|
|
145
212
|
"""Print the value of a single substitution variable.
|
|
146
213
|
|
|
147
|
-
|
|
148
|
-
varname: The variable reference as typed by the user, e.g. ``$FOO``.
|
|
214
|
+
Tries the name as typed, then with the sigil prefix stripped.
|
|
149
215
|
"""
|
|
150
216
|
subvars = _state.subvars
|
|
151
217
|
if subvars is None:
|
|
@@ -153,14 +219,14 @@ def _print_var(varname: str) -> None:
|
|
|
153
219
|
return
|
|
154
220
|
# Try the name as typed first, then without the sigil prefix ($, &, @, #, ~).
|
|
155
221
|
# SUB creates variables without a prefix (e.g., "logfile"), but users
|
|
156
|
-
#
|
|
222
|
+
# may type "$logfile" at the prompt.
|
|
157
223
|
value = subvars.varvalue(varname)
|
|
158
224
|
if value is None and len(varname) > 1 and varname[0] in "$&@#~":
|
|
159
225
|
value = subvars.varvalue(varname[1:])
|
|
160
226
|
if value is None:
|
|
161
227
|
_write(f" {varname}: (undefined)\n")
|
|
162
228
|
else:
|
|
163
|
-
_write(f" {varname} = {value
|
|
229
|
+
_write(f" {varname} = {value}\n")
|
|
164
230
|
|
|
165
231
|
|
|
166
232
|
def _print_stack() -> None:
|
|
@@ -177,11 +243,7 @@ def _print_stack() -> None:
|
|
|
177
243
|
|
|
178
244
|
|
|
179
245
|
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
|
-
"""
|
|
246
|
+
"""Execute ad-hoc SQL against the current database and pretty-print the results."""
|
|
185
247
|
dbs = _state.dbs
|
|
186
248
|
if dbs is None:
|
|
187
249
|
_write(" (no database connection is active)\n")
|
execsql/script/engine.py
CHANGED
|
@@ -194,7 +194,7 @@ class MetaCommandList:
|
|
|
194
194
|
patterns; each compiles into a separate :class:`MetaCommand` prepended to
|
|
195
195
|
the dispatch list so that later registrations take priority.
|
|
196
196
|
"""
|
|
197
|
-
if
|
|
197
|
+
if isinstance(matching_regexes, (tuple, list)):
|
|
198
198
|
raw_patterns = list(matching_regexes)
|
|
199
199
|
regexes = [re.compile(rx, re.I) for rx in raw_patterns]
|
|
200
200
|
else:
|
|
@@ -305,8 +305,14 @@ class SqlStmt:
|
|
|
305
305
|
except Exception:
|
|
306
306
|
e = ErrInfo(type="exception", exception_msg=exception_desc())
|
|
307
307
|
if e:
|
|
308
|
+
from execsql.utils.errors import stamp_errinfo
|
|
309
|
+
|
|
310
|
+
stamp_errinfo(e)
|
|
308
311
|
_state.subvars.add_substitution("$LAST_ERROR", cmd)
|
|
312
|
+
_state.subvars.add_substitution("$ERROR_MESSAGE", e.errmsg())
|
|
309
313
|
_state.status.sql_error = True
|
|
314
|
+
if _state.exec_log is not None:
|
|
315
|
+
_state.exec_log.log_status_info(f"SQL error: {e.errmsg()}")
|
|
310
316
|
if _state.status.halt_on_err:
|
|
311
317
|
from execsql.utils.errors import exit_now
|
|
312
318
|
|
|
@@ -348,10 +354,18 @@ class MetacommandStmt:
|
|
|
348
354
|
except Exception:
|
|
349
355
|
e = ErrInfo(type="exception", exception_msg=exception_desc())
|
|
350
356
|
if e:
|
|
357
|
+
from execsql.utils.errors import stamp_errinfo
|
|
358
|
+
|
|
359
|
+
stamp_errinfo(e)
|
|
351
360
|
_state.status.metacommand_error = True
|
|
352
361
|
_state.subvars.add_substitution("$LAST_ERROR", cmd)
|
|
362
|
+
_state.subvars.add_substitution("$ERROR_MESSAGE", e.errmsg())
|
|
363
|
+
if _state.exec_log is not None:
|
|
364
|
+
_state.exec_log.log_status_info(f"Metacommand error: {e.errmsg()}")
|
|
353
365
|
if _state.status.halt_on_metacommand_err:
|
|
354
|
-
raise ErrInfo
|
|
366
|
+
# Re-raise the original ErrInfo so its message is preserved, not
|
|
367
|
+
# replaced with the generic "Unknown metacommand" text.
|
|
368
|
+
raise e
|
|
355
369
|
if _state.if_stack.all_true():
|
|
356
370
|
# but nothing applies, because we got here.
|
|
357
371
|
_state.status.metacommand_error = True
|
|
@@ -489,6 +503,11 @@ class CommandList:
|
|
|
489
503
|
_state.subvars.add_substitution("$CURRENT_SCRIPT_NAME", Path(cmditem.source).name)
|
|
490
504
|
_state.subvars.add_substitution("$CURRENT_SCRIPT_LINE", str(cmditem.line_no))
|
|
491
505
|
_state.subvars.add_substitution("$SCRIPT_LINE", str(cmditem.line_no))
|
|
506
|
+
if _state.step_mode:
|
|
507
|
+
_state.step_mode = False
|
|
508
|
+
from execsql.metacommands.debug_repl import _debug_repl
|
|
509
|
+
|
|
510
|
+
_debug_repl()
|
|
492
511
|
_profiling = _state.profile_data is not None
|
|
493
512
|
if _profiling:
|
|
494
513
|
import time as _time
|
|
@@ -506,11 +525,6 @@ class CommandList:
|
|
|
506
525
|
cmditem.command.commandline()[:100],
|
|
507
526
|
),
|
|
508
527
|
)
|
|
509
|
-
if _state.step_mode:
|
|
510
|
-
_state.step_mode = False
|
|
511
|
-
from execsql.metacommands.debug_repl import _debug_repl
|
|
512
|
-
|
|
513
|
-
_debug_repl()
|
|
514
528
|
self.cmdptr += 1
|
|
515
529
|
|
|
516
530
|
def run_next(self) -> None:
|
execsql/state.py
CHANGED
|
@@ -336,8 +336,7 @@ class _StateModule(types.ModuleType):
|
|
|
336
336
|
# via setattr (local) or delattr (non-local). Since context
|
|
337
337
|
# attrs live on _ctx, not __dict__, patch takes the delattr
|
|
338
338
|
# path. We reset to the default rather than truly deleting.
|
|
339
|
-
|
|
340
|
-
setattr(self.__dict__["_ctx"], name, getattr(_defaults, name))
|
|
339
|
+
setattr(self.__dict__["_ctx"], name, getattr(_DEFAULT_CTX, name))
|
|
341
340
|
else:
|
|
342
341
|
super().__delattr__(name)
|
|
343
342
|
|
|
@@ -468,4 +467,5 @@ def initialize(
|
|
|
468
467
|
# ---------------------------------------------------------------------------
|
|
469
468
|
|
|
470
469
|
_ctx = RuntimeContext()
|
|
470
|
+
_DEFAULT_CTX = RuntimeContext() # Cached defaults for __delattr__ reset
|
|
471
471
|
sys.modules[__name__].__class__ = _StateModule
|
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.
|
|
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
|
|
execsql/utils/gui.py
CHANGED
|
@@ -358,13 +358,35 @@ def gui_console_wait_user(message: str = "") -> None:
|
|
|
358
358
|
print(message, file=sys.stderr)
|
|
359
359
|
|
|
360
360
|
|
|
361
|
-
def gui_console_width() -> int:
|
|
362
|
-
"""
|
|
361
|
+
def gui_console_width(width: int | None = None) -> int:
|
|
362
|
+
"""Get or set the console width in characters.
|
|
363
|
+
|
|
364
|
+
When *width* is provided, updates the active GUI console (if any).
|
|
365
|
+
Always returns the current width.
|
|
366
|
+
"""
|
|
367
|
+
global _console_width
|
|
368
|
+
if width is not None:
|
|
369
|
+
import execsql.state as _state
|
|
370
|
+
|
|
371
|
+
_console_width = int(width)
|
|
372
|
+
if _state.gui_console is not None and hasattr(_state.gui_console, "set_width"):
|
|
373
|
+
_state.gui_console.set_width(_console_width)
|
|
363
374
|
return _console_width
|
|
364
375
|
|
|
365
376
|
|
|
366
|
-
def gui_console_height() -> int:
|
|
367
|
-
"""
|
|
377
|
+
def gui_console_height(height: int | None = None) -> int:
|
|
378
|
+
"""Get or set the console height in lines.
|
|
379
|
+
|
|
380
|
+
When *height* is provided, updates the active GUI console (if any).
|
|
381
|
+
Always returns the current height.
|
|
382
|
+
"""
|
|
383
|
+
global _console_height
|
|
384
|
+
if height is not None:
|
|
385
|
+
import execsql.state as _state
|
|
386
|
+
|
|
387
|
+
_console_height = int(height)
|
|
388
|
+
if _state.gui_console is not None and hasattr(_state.gui_console, "set_height"):
|
|
389
|
+
_state.gui_console.set_height(_console_height)
|
|
368
390
|
return _console_height
|
|
369
391
|
|
|
370
392
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: execsql2
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.11.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: Repository, https://github.com/geocoug/execsql
|
|
6
6
|
Project-URL: Issues, https://github.com/geocoug/execsql/issues
|
|
@@ -220,9 +220,13 @@ execsql script.sql # read connection from config file
|
|
|
220
220
|
| `-v {0,1,2,3}` | GUI level (0=none, 1=password, 2=selection, 3=full) |
|
|
221
221
|
| `-w` | Skip password prompt when a username is supplied |
|
|
222
222
|
| `--dsn URL` | Connection string (e.g. `postgresql://user:pass@host/db`) |
|
|
223
|
+
| `--output-dir DIR` | Default base directory for EXPORT output files |
|
|
223
224
|
| `--dry-run` | Parse the script and report commands without executing |
|
|
224
225
|
| `--lint` | Static analysis: check structure and warn on issues (no DB) |
|
|
226
|
+
| `--ping` | Test database connectivity and exit |
|
|
227
|
+
| `--profile` | Show per-statement timing summary after execution |
|
|
225
228
|
| `--progress` | Show a progress bar for long-running IMPORT operations |
|
|
229
|
+
| `--debug` | Start in step-through debug mode (REPL pauses before each stmt) |
|
|
226
230
|
| `--dump-keywords` | Print metacommand keywords as JSON and exit |
|
|
227
231
|
| `--gui-framework {tkinter,textual}` | GUI framework for interactive prompts |
|
|
228
232
|
|
|
@@ -297,7 +301,7 @@ execsql-format --check scripts/
|
|
|
297
301
|
```yaml
|
|
298
302
|
repos:
|
|
299
303
|
- repo: https://github.com/geocoug/execsql
|
|
300
|
-
rev: v2.
|
|
304
|
+
rev: v2.11.0
|
|
301
305
|
hooks:
|
|
302
306
|
- id: execsql-format
|
|
303
307
|
args: [--in-place]
|
|
@@ -7,13 +7,13 @@ 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=
|
|
10
|
+
execsql/state.py,sha256=29b3SwG4GirED2KVQc-cCC7Z_-FsGN3fEt9xQNN-Puo,15090
|
|
11
11
|
execsql/types.py,sha256=HVWb4umIB9lpxCGgqk3xy1hoGYPfN39xci5mHF0Izq4,31882
|
|
12
|
-
execsql/cli/__init__.py,sha256=
|
|
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
|
-
execsql/cli/lint.py,sha256=
|
|
16
|
-
execsql/cli/run.py,sha256=
|
|
15
|
+
execsql/cli/lint.py,sha256=XWuVcEsheZ8ql48VFWqICWEkAUezB2nIePX6SUiKSg8,16109
|
|
16
|
+
execsql/cli/run.py,sha256=eiD_5R2ZL8WzhbW78DBcoSbcibmOXcr3po_aYYSoPwg,30250
|
|
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
|
|
@@ -44,9 +44,9 @@ execsql/exporters/sqlite.py,sha256=XA0ALLvy-r6Pz1lpOFkWWbvpSP9Hm1tHHiuo_BvPVDk,2
|
|
|
44
44
|
execsql/exporters/templates.py,sha256=T9nk7vJrlxiPGfOWGc79xqqDxK3TCYu0wXq48U02npw,5564
|
|
45
45
|
execsql/exporters/values.py,sha256=HIyud31aux_dbCphfKHEGeZB9fkIPE5PoGXQz817XIE,2520
|
|
46
46
|
execsql/exporters/xls.py,sha256=nPROgxL8XK2oiBVoqN2L-o0j_jynRIMokwB8NpvOBt0,10623
|
|
47
|
-
execsql/exporters/xlsx.py,sha256=
|
|
47
|
+
execsql/exporters/xlsx.py,sha256=Gm8ns_KeqSMu2DONSSJ1DcwPBEjYwpbU7frmX0g5L7c,11487
|
|
48
48
|
execsql/exporters/xml.py,sha256=lqcOM8uKDoCayU42BPSLNH1_2DIHU5D3LtQItREU90c,2564
|
|
49
|
-
execsql/exporters/yaml.py,sha256=
|
|
49
|
+
execsql/exporters/yaml.py,sha256=1Vuc6uMDuLTkCuXCfXWKz4gLkkAVdEXkLs4gEB_67Xo,3110
|
|
50
50
|
execsql/exporters/zip.py,sha256=9-hExltQorONNThiMfxPDYHqHsbTeq9zM9zmtG4oFb8,4410
|
|
51
51
|
execsql/gui/__init__.py,sha256=oCb-cyhLZzVpWJ4WU5HbqEDBrV-lm0ytEwxemrOZyqs,2048
|
|
52
52
|
execsql/gui/base.py,sha256=sfNRkDrf7FhIgMRUOdyZpRLS1Xk9RqNhrV0A1RP6PXU,6068
|
|
@@ -60,12 +60,12 @@ execsql/importers/feather.py,sha256=g2B69d2uv9vmnXcmjFyTVsMP40LYEzFYkhk3gD26mGw,
|
|
|
60
60
|
execsql/importers/ods.py,sha256=MJsdsjropzCvxAA3DDZfAL_AnmZ4yij7DnrjGyDJqHQ,2843
|
|
61
61
|
execsql/importers/xls.py,sha256=e0Zfe47ZiCpA1Ae3XDJ1ko3sCiH3-8U6XLKi6NvD0jQ,3683
|
|
62
62
|
execsql/metacommands/__init__.py,sha256=TT1ARHgHltHqZ7qx4Y62o1h_GOPvUztZKCem-wAE560,11215
|
|
63
|
-
execsql/metacommands/conditions.py,sha256=
|
|
63
|
+
execsql/metacommands/conditions.py,sha256=Fzrk83-pWbFOoKahYdQW7CZjQeh3zByDUbfgpTM_bjQ,29259
|
|
64
64
|
execsql/metacommands/connect.py,sha256=Nsm0D91i3RX-R2rzQQ-Br-gULaI6Uvdn9fqb7DOAVfE,14804
|
|
65
|
-
execsql/metacommands/control.py,sha256=
|
|
65
|
+
execsql/metacommands/control.py,sha256=xNHyTrYUM042OgDarNq7HxslY7JuQs-KOKcb-fHUngM,8510
|
|
66
66
|
execsql/metacommands/data.py,sha256=tRQBGTAuW-eJ2tBNWaoZI9OjTyNNyHJISo7gOdL-sm8,11370
|
|
67
|
-
execsql/metacommands/debug.py,sha256=
|
|
68
|
-
execsql/metacommands/debug_repl.py,sha256=
|
|
67
|
+
execsql/metacommands/debug.py,sha256=pnT24dfvfOx8xFu86mO5czfVCGKbcvgBLyXnqaMWO4w,8184
|
|
68
|
+
execsql/metacommands/debug_repl.py,sha256=XQ09I7HI-drVjfIg4XqsPndvAmZSxpSmXVKjWjLqwE4,9785
|
|
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,38 +77,38 @@ 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=
|
|
80
|
+
execsql/script/engine.py,sha256=1_3qMn6a1nD4oYBBRNlwMU_YwZ4f2Om6-CjUGksJT4A,41087
|
|
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=
|
|
86
|
+
execsql/utils/errors.py,sha256=YKhYD27-3timuZavc2vIrRIfHa71vzih-KVPsAKgvkU,8163
|
|
87
87
|
execsql/utils/fileio.py,sha256=F6M4osE0Mb2ycTcvwwcYnhBXH1L36v6d7Oxdab6J16s,24110
|
|
88
|
-
execsql/utils/gui.py,sha256=
|
|
88
|
+
execsql/utils/gui.py,sha256=UFtwrXPNqNvZCJFCbumZ1aG2d9B-vyaJXIG83fDHteo,18409
|
|
89
89
|
execsql/utils/mail.py,sha256=75A1cMnEfyP0_QMMWuSLv8hrcIjc9cGBCrttLpr2TXQ,5372
|
|
90
90
|
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.
|
|
95
|
-
execsql2-2.
|
|
96
|
-
execsql2-2.
|
|
97
|
-
execsql2-2.
|
|
98
|
-
execsql2-2.
|
|
99
|
-
execsql2-2.
|
|
100
|
-
execsql2-2.
|
|
101
|
-
execsql2-2.
|
|
102
|
-
execsql2-2.
|
|
103
|
-
execsql2-2.
|
|
104
|
-
execsql2-2.
|
|
105
|
-
execsql2-2.
|
|
106
|
-
execsql2-2.
|
|
107
|
-
execsql2-2.
|
|
108
|
-
execsql2-2.
|
|
109
|
-
execsql2-2.
|
|
110
|
-
execsql2-2.
|
|
111
|
-
execsql2-2.
|
|
112
|
-
execsql2-2.
|
|
113
|
-
execsql2-2.
|
|
114
|
-
execsql2-2.
|
|
94
|
+
execsql2-2.11.1.data/data/execsql2_extras/README.md,sha256=sxwVyU0ZahCfANv56LahkyuM505kFjrMhe-1SvWE69E,4845
|
|
95
|
+
execsql2-2.11.1.data/data/execsql2_extras/config_settings.sqlite,sha256=aY5cxR7Q7J6zJ4bC9lu5mHUrhy211Cq3MNKPQVCt02E,20480
|
|
96
|
+
execsql2-2.11.1.data/data/execsql2_extras/example_config_prompt.sql,sha256=SY3Jxn1qcVm4kPW9xmmTfknHfvURXmeEYTbRjYrjGSw,7487
|
|
97
|
+
execsql2-2.11.1.data/data/execsql2_extras/execsql.conf,sha256=_45iJ-KWZnB8uMW_gEg067MM5pmGJ-dVl7VbAZMunAE,9530
|
|
98
|
+
execsql2-2.11.1.data/data/execsql2_extras/make_config_db.sql,sha256=WwyC6dK-Eh5CAVppiBCDHqiI1_wEI9U95Ytpr4lsZkg,8726
|
|
99
|
+
execsql2-2.11.1.data/data/execsql2_extras/md_compare.sql,sha256=B8Wd7LZ0vnMY2qvA139JIEBkPObgRH2i5xj6PejTQt8,24092
|
|
100
|
+
execsql2-2.11.1.data/data/execsql2_extras/md_glossary.sql,sha256=DJRHcU5NbFpxTTX-IwH3yRlsboj1q6BBGrUAHKn4Cuo,10796
|
|
101
|
+
execsql2-2.11.1.data/data/execsql2_extras/md_upsert.sql,sha256=v_7GbWh_N1mBTmw3gvTrkagOVp2q0KmXvM8hE-DlFxY,112524
|
|
102
|
+
execsql2-2.11.1.data/data/execsql2_extras/pg_compare.sql,sha256=9dWa8hnfy5dVJI-z2iGpd9JzQmI4j2ziMlEdpnr66ro,24352
|
|
103
|
+
execsql2-2.11.1.data/data/execsql2_extras/pg_glossary.sql,sha256=pKjIIDsROAgJq2H-1qNEcRMAWManivcZ_AEVHzUUlic,9908
|
|
104
|
+
execsql2-2.11.1.data/data/execsql2_extras/pg_upsert.sql,sha256=k7AFiGTLBy3nf-qO5QIaZrEYTAKvdxxU3JDLx9jqkzs,108315
|
|
105
|
+
execsql2-2.11.1.data/data/execsql2_extras/script_template.sql,sha256=1Estacb_vm1FgK41k_G9nuduP1yiA-fQ1Kn4Z4mv5Ao,11153
|
|
106
|
+
execsql2-2.11.1.data/data/execsql2_extras/ss_compare.sql,sha256=TsVxWm3cEpR5-EiMYXNhtaY0arSNeKZhsJdHdLA7xeI,24833
|
|
107
|
+
execsql2-2.11.1.data/data/execsql2_extras/ss_glossary.sql,sha256=cLM7nN8JOIu9ZVP9oY9qdSK3hrnWJiDcX6nZmQQbQWI,13065
|
|
108
|
+
execsql2-2.11.1.data/data/execsql2_extras/ss_upsert.sql,sha256=BCqmBykXBF-BpCgOFeG1qhf2XfScKsxPD17wd1hYfHw,120647
|
|
109
|
+
execsql2-2.11.1.dist-info/METADATA,sha256=cGmNeSCzZvJFmoCzDbMs_M3MjYP6YCZgQF0vNpIknVk,17381
|
|
110
|
+
execsql2-2.11.1.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
111
|
+
execsql2-2.11.1.dist-info/entry_points.txt,sha256=sUOxkM-dN1eBGGpSpDLsAaE0yNXYQKWZAfxPOlMkQyk,90
|
|
112
|
+
execsql2-2.11.1.dist-info/licenses/LICENSE.txt,sha256=LBdhuxejF8_bLCHZ2kWfmDXpDGUu914Gbd6_3JjCRe0,676
|
|
113
|
+
execsql2-2.11.1.dist-info/licenses/NOTICE,sha256=sqVrM73Ys9zfvWC_P797lHfTnoPW_ETeBSrUTFaob0A,339
|
|
114
|
+
execsql2-2.11.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
{execsql2-2.10.1.data → execsql2-2.11.1.data}/data/execsql2_extras/example_config_prompt.sql
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|