execsql2 2.22.2__py3-none-any.whl → 2.22.4__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/format.py +12 -1
- execsql/gui/base.py +56 -1
- execsql/gui/console.py +10 -33
- execsql/gui/tui.py +45 -15
- execsql/metacommands/control.py +26 -0
- {execsql2-2.22.2.dist-info → execsql2-2.22.4.dist-info}/METADATA +3 -3
- {execsql2-2.22.2.dist-info → execsql2-2.22.4.dist-info}/RECORD +25 -25
- {execsql2-2.22.2.dist-info → execsql2-2.22.4.dist-info}/WHEEL +1 -1
- {execsql2-2.22.2.data → execsql2-2.22.4.data}/data/execsql2_extras/README.md +0 -0
- {execsql2-2.22.2.data → execsql2-2.22.4.data}/data/execsql2_extras/config_settings.sqlite +0 -0
- {execsql2-2.22.2.data → execsql2-2.22.4.data}/data/execsql2_extras/example_config_prompt.sql +0 -0
- {execsql2-2.22.2.data → execsql2-2.22.4.data}/data/execsql2_extras/make_config_db.sql +0 -0
- {execsql2-2.22.2.data → execsql2-2.22.4.data}/data/execsql2_extras/md_compare.sql +0 -0
- {execsql2-2.22.2.data → execsql2-2.22.4.data}/data/execsql2_extras/md_glossary.sql +0 -0
- {execsql2-2.22.2.data → execsql2-2.22.4.data}/data/execsql2_extras/md_upsert.sql +0 -0
- {execsql2-2.22.2.data → execsql2-2.22.4.data}/data/execsql2_extras/pg_compare.sql +0 -0
- {execsql2-2.22.2.data → execsql2-2.22.4.data}/data/execsql2_extras/pg_glossary.sql +0 -0
- {execsql2-2.22.2.data → execsql2-2.22.4.data}/data/execsql2_extras/pg_upsert.sql +0 -0
- {execsql2-2.22.2.data → execsql2-2.22.4.data}/data/execsql2_extras/script_template.sql +0 -0
- {execsql2-2.22.2.data → execsql2-2.22.4.data}/data/execsql2_extras/ss_compare.sql +0 -0
- {execsql2-2.22.2.data → execsql2-2.22.4.data}/data/execsql2_extras/ss_glossary.sql +0 -0
- {execsql2-2.22.2.data → execsql2-2.22.4.data}/data/execsql2_extras/ss_upsert.sql +0 -0
- {execsql2-2.22.2.dist-info → execsql2-2.22.4.dist-info}/entry_points.txt +0 -0
- {execsql2-2.22.2.dist-info → execsql2-2.22.4.dist-info}/licenses/LICENSE.txt +0 -0
- {execsql2-2.22.2.dist-info → execsql2-2.22.4.dist-info}/licenses/NOTICE +0 -0
execsql/format.py
CHANGED
|
@@ -642,6 +642,12 @@ def format_file(source: str, indent: int = 4, use_sql: bool = True, leading_comm
|
|
|
642
642
|
# "body" for `$body$`, etc.). Nested markers with a different tag
|
|
643
643
|
# are ignored — only a matching close marker re-opens us.
|
|
644
644
|
current_dq_tag: str | None = None
|
|
645
|
+
# Sticky flag: True once the current accumulator has seen ANY dollar-quote
|
|
646
|
+
# marker. `in_dollar_quote` alone is False by the time a complete
|
|
647
|
+
# `CREATE FUNCTION ... $$ ... $$;` is flushed (the closing `$$` reset it),
|
|
648
|
+
# which would wrongly hand the PL/pgSQL body to sqlglot. This flag keeps the
|
|
649
|
+
# whole containing statement opaque to sqlglot. Reset in flush_sql().
|
|
650
|
+
sql_acc_contains_dollar_quote = False
|
|
645
651
|
in_block_comment = False
|
|
646
652
|
# Track whether we are inside an open SQL statement (last SQL line
|
|
647
653
|
# did not end with ';'). Blank lines mid-statement should NOT flush
|
|
@@ -655,15 +661,19 @@ def format_file(source: str, indent: int = 4, use_sql: bool = True, leading_comm
|
|
|
655
661
|
|
|
656
662
|
def flush_sql() -> None:
|
|
657
663
|
nonlocal in_dollar_quote, current_dq_tag, in_sql_statement
|
|
664
|
+
nonlocal sql_acc_contains_dollar_quote
|
|
658
665
|
if sql_acc:
|
|
659
666
|
# If any line in the accumulated block is inside a $$-delimited
|
|
660
667
|
# region, skip sqlglot formatting entirely. PL/pgSQL function
|
|
661
668
|
# bodies contain IF/END IF, LOOP, RETURN, etc. that sqlglot does
|
|
662
669
|
# not understand and will corrupt (e.g., rewriting to COMMIT).
|
|
663
|
-
|
|
670
|
+
# `sql_acc_contains_dollar_quote` catches the case where the region
|
|
671
|
+
# already closed (`... $$;`) so `in_dollar_quote` is False at flush.
|
|
672
|
+
safe_for_sqlglot = use_sql and not in_dollar_quote and not sql_acc_contains_dollar_quote
|
|
664
673
|
output.extend(format_sql_block(sql_acc, depth, indent, safe_for_sqlglot, leading_comma=leading_comma))
|
|
665
674
|
sql_acc.clear()
|
|
666
675
|
in_sql_statement = False
|
|
676
|
+
sql_acc_contains_dollar_quote = False
|
|
667
677
|
|
|
668
678
|
for raw_line in source.expandtabs(4).splitlines():
|
|
669
679
|
stripped_line = raw_line.strip()
|
|
@@ -727,6 +737,7 @@ def format_file(source: str, indent: int = 4, use_sql: bool = True, leading_comm
|
|
|
727
737
|
# PL/pgSQL. Walk every dollar-quote marker on the line; toggle
|
|
728
738
|
# state only when we hit the matching open or close.
|
|
729
739
|
for m in _DOLLAR_QUOTE_RE.finditer(raw_line):
|
|
740
|
+
sql_acc_contains_dollar_quote = True
|
|
730
741
|
tag = m.group(1) or ""
|
|
731
742
|
if not in_dollar_quote:
|
|
732
743
|
in_dollar_quote = True
|
execsql/gui/base.py
CHANGED
|
@@ -9,11 +9,66 @@ from typing import TYPE_CHECKING, Any
|
|
|
9
9
|
if TYPE_CHECKING:
|
|
10
10
|
pass
|
|
11
11
|
|
|
12
|
-
__all__ = ["DiffResult", "GuiBackend", "compare_stats", "compute_row_diffs"]
|
|
12
|
+
__all__ = ["DiffResult", "GuiBackend", "compare_stats", "compute_row_diffs", "format_table", "row_count_text"]
|
|
13
13
|
|
|
14
14
|
DIFF_MARKER = "● "
|
|
15
15
|
|
|
16
16
|
|
|
17
|
+
# ---------------------------------------------------------------------------
|
|
18
|
+
# Plain-text table rendering (shared by the console backend and by
|
|
19
|
+
# non-interactive metacommand fallbacks such as HALT ... DISPLAY)
|
|
20
|
+
# ---------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def row_count_text(n: int) -> str:
|
|
24
|
+
"""Return a human-readable row count string, e.g. ``'3 rows'`` or ``'1 row'``."""
|
|
25
|
+
return f"{n:,} row{'s' if n != 1 else ''}"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def format_table(
|
|
29
|
+
headers: list,
|
|
30
|
+
rows: list,
|
|
31
|
+
row_states: list[str] | None = None,
|
|
32
|
+
changed_cols: list[set[str]] | None = None,
|
|
33
|
+
) -> str:
|
|
34
|
+
"""Render *headers* and *rows* as a plain-text table.
|
|
35
|
+
|
|
36
|
+
Columns are left-aligned and padded to the widest value. When *row_states*
|
|
37
|
+
and *changed_cols* are provided, cells that differ in ``"changed"`` rows are
|
|
38
|
+
prefixed with the diff marker (``"● "``) and the marker width is included in
|
|
39
|
+
the column sizing.
|
|
40
|
+
|
|
41
|
+
Returns an empty string when *headers* is empty. The result has no trailing
|
|
42
|
+
newline.
|
|
43
|
+
"""
|
|
44
|
+
if not headers:
|
|
45
|
+
return ""
|
|
46
|
+
headers_str = [str(h) for h in headers]
|
|
47
|
+
|
|
48
|
+
# Pre-compute display values so column widths account for markers.
|
|
49
|
+
display_rows: list[list[str]] = []
|
|
50
|
+
for ridx, row in enumerate(rows):
|
|
51
|
+
cells: list[str] = []
|
|
52
|
+
state = row_states[ridx] if row_states and ridx < len(row_states) else ""
|
|
53
|
+
diff_set = changed_cols[ridx] if changed_cols and ridx < len(changed_cols) else set()
|
|
54
|
+
for ci, cell in enumerate(row):
|
|
55
|
+
val = str(cell) if cell is not None else ""
|
|
56
|
+
if state == "changed" and ci < len(headers_str) and headers_str[ci] in diff_set:
|
|
57
|
+
val = f"{DIFF_MARKER}{val}"
|
|
58
|
+
cells.append(val)
|
|
59
|
+
display_rows.append(cells)
|
|
60
|
+
|
|
61
|
+
col_widths = [len(h) for h in headers_str]
|
|
62
|
+
for cells in display_rows:
|
|
63
|
+
for i, cell in enumerate(cells):
|
|
64
|
+
col_widths[i] = max(col_widths[i], len(cell))
|
|
65
|
+
fmt = " " + " ".join(f"{{:<{w}}}" for w in col_widths)
|
|
66
|
+
sep = " " + " ".join("-" * w for w in col_widths)
|
|
67
|
+
lines = [fmt.format(*headers_str), sep]
|
|
68
|
+
lines.extend(fmt.format(*cells) for cells in display_rows)
|
|
69
|
+
return "\n".join(lines)
|
|
70
|
+
|
|
71
|
+
|
|
17
72
|
# ---------------------------------------------------------------------------
|
|
18
73
|
# Value comparison helpers
|
|
19
74
|
# ---------------------------------------------------------------------------
|
execsql/gui/console.py
CHANGED
|
@@ -11,7 +11,13 @@ import sys
|
|
|
11
11
|
import time
|
|
12
12
|
from typing import Any, cast
|
|
13
13
|
|
|
14
|
-
from execsql.gui.base import
|
|
14
|
+
from execsql.gui.base import (
|
|
15
|
+
GuiBackend,
|
|
16
|
+
compare_stats as _compare_stats,
|
|
17
|
+
compute_row_diffs,
|
|
18
|
+
format_table,
|
|
19
|
+
row_count_text as _row_count_text,
|
|
20
|
+
)
|
|
15
21
|
|
|
16
22
|
__all__ = ["ConsoleBackend"]
|
|
17
23
|
|
|
@@ -23,11 +29,6 @@ def _print_help_url(args: dict) -> None:
|
|
|
23
29
|
print(f" Help: {url}", file=sys.stderr)
|
|
24
30
|
|
|
25
31
|
|
|
26
|
-
def _row_count_text(n: int) -> str:
|
|
27
|
-
"""Return a human-readable row count string, e.g. '3 rows' or '1 row'."""
|
|
28
|
-
return f"{n:,} row{'s' if n != 1 else ''}"
|
|
29
|
-
|
|
30
|
-
|
|
31
32
|
def _print_table(
|
|
32
33
|
headers: list,
|
|
33
34
|
rows: list,
|
|
@@ -42,33 +43,9 @@ def _print_table(
|
|
|
42
43
|
"""
|
|
43
44
|
if file is None:
|
|
44
45
|
file = sys.stderr
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
# Pre-compute display values so column widths account for markers.
|
|
50
|
-
display_rows: list[list[str]] = []
|
|
51
|
-
for ridx, row in enumerate(rows):
|
|
52
|
-
cells: list[str] = []
|
|
53
|
-
state = row_states[ridx] if row_states and ridx < len(row_states) else ""
|
|
54
|
-
diff_set = changed_cols[ridx] if changed_cols and ridx < len(changed_cols) else set()
|
|
55
|
-
for ci, cell in enumerate(row):
|
|
56
|
-
val = str(cell) if cell is not None else ""
|
|
57
|
-
if state == "changed" and ci < len(headers_str) and headers_str[ci] in diff_set:
|
|
58
|
-
val = f"{DIFF_MARKER}{val}"
|
|
59
|
-
cells.append(val)
|
|
60
|
-
display_rows.append(cells)
|
|
61
|
-
|
|
62
|
-
col_widths = [len(h) for h in headers_str]
|
|
63
|
-
for cells in display_rows:
|
|
64
|
-
for i, cell in enumerate(cells):
|
|
65
|
-
col_widths[i] = max(col_widths[i], len(cell))
|
|
66
|
-
fmt = " " + " ".join(f"{{:<{w}}}" for w in col_widths)
|
|
67
|
-
sep = " " + " ".join("-" * w for w in col_widths)
|
|
68
|
-
print(fmt.format(*headers_str), file=file)
|
|
69
|
-
print(sep, file=file)
|
|
70
|
-
for cells in display_rows:
|
|
71
|
-
print(fmt.format(*cells), file=file)
|
|
46
|
+
rendered = format_table(headers, rows, row_states=row_states, changed_cols=changed_cols)
|
|
47
|
+
if rendered:
|
|
48
|
+
print(rendered, file=file)
|
|
72
49
|
|
|
73
50
|
|
|
74
51
|
def _prompt_buttons(button_list: list) -> int | None:
|
execsql/gui/tui.py
CHANGED
|
@@ -89,14 +89,18 @@ def _help_button(url: str | None) -> Button | None:
|
|
|
89
89
|
return None
|
|
90
90
|
|
|
91
91
|
|
|
92
|
-
def _button_row(button_list: list) -> list[Button]:
|
|
92
|
+
def _button_row(button_list: list, no_cancel: bool = False) -> list[Button]:
|
|
93
93
|
"""Create Button widgets from a button_list of (label, value, key?) tuples.
|
|
94
94
|
|
|
95
|
-
A Cancel button (id ``btn_cancel_exit``) is
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
95
|
+
A Cancel button (id ``btn_cancel_exit``) is prepended so it appears on the
|
|
96
|
+
left while the primary action button sits on the far right. Entries in
|
|
97
|
+
*button_list* with a falsy value (0 or None) are treated as the cancel
|
|
98
|
+
label source and are otherwise excluded from the numbered buttons so that
|
|
99
|
+
``btn_N`` indices stay aligned with ``button_list`` positions.
|
|
100
|
+
|
|
101
|
+
When *no_cancel* is set, the Cancel button is omitted — dialogs such as
|
|
102
|
+
HALT have no meaningful cancel action, and cancelling one would exit with
|
|
103
|
+
the generic status 2 rather than the status the caller asked for.
|
|
100
104
|
"""
|
|
101
105
|
cancel_label = "Cancel"
|
|
102
106
|
primary_buttons = []
|
|
@@ -107,6 +111,8 @@ def _button_row(button_list: list) -> list[Button]:
|
|
|
107
111
|
else:
|
|
108
112
|
variant: Literal["primary", "default"] = "primary" if i == 0 else "default"
|
|
109
113
|
primary_buttons.append(Button(label, id=f"btn_{i}", variant=variant))
|
|
114
|
+
if no_cancel:
|
|
115
|
+
return primary_buttons
|
|
110
116
|
return [Button(cancel_label, id="btn_cancel_exit", variant="warning")] + primary_buttons
|
|
111
117
|
|
|
112
118
|
|
|
@@ -182,7 +188,14 @@ class _BaseDialog(ModalScreen):
|
|
|
182
188
|
return self._result
|
|
183
189
|
|
|
184
190
|
def action_cancel(self) -> None:
|
|
185
|
-
"""Dismiss the dialog as cancelled (triggered by Escape key).
|
|
191
|
+
"""Dismiss the dialog as cancelled (triggered by Escape key).
|
|
192
|
+
|
|
193
|
+
Ignored for dialogs that pass ``no_cancel`` (e.g. HALT), which have no
|
|
194
|
+
meaningful cancel action. This matches the Tkinter backend, which does
|
|
195
|
+
not bind ``<Escape>`` to cancellation in that case.
|
|
196
|
+
"""
|
|
197
|
+
if self.args.get("no_cancel", False):
|
|
198
|
+
return
|
|
186
199
|
self._result = {"button": None, "cancelled": True}
|
|
187
200
|
self.dismiss(self._result)
|
|
188
201
|
|
|
@@ -210,31 +223,48 @@ class _BaseDialog(ModalScreen):
|
|
|
210
223
|
|
|
211
224
|
|
|
212
225
|
class MsgScreen(_BaseDialog):
|
|
213
|
-
"""
|
|
226
|
+
"""Message dialog with an optional data table.
|
|
227
|
+
|
|
228
|
+
Honours the caller's ``button_list`` and ``no_cancel`` arguments, and
|
|
229
|
+
renders ``column_headers``/``rowset`` when supplied (as the HALT
|
|
230
|
+
metacommand's DISPLAY clause does), matching the Tkinter MsgDialog.
|
|
231
|
+
"""
|
|
214
232
|
|
|
215
233
|
BINDINGS = [
|
|
216
234
|
*_BaseDialog.BINDINGS,
|
|
217
235
|
Binding("enter", "submit", "Continue", show=True),
|
|
218
236
|
]
|
|
219
237
|
|
|
238
|
+
def _button_list(self) -> list:
|
|
239
|
+
return cast(list, self.args.get("button_list") or [("Continue", 1, "<Return>")])
|
|
240
|
+
|
|
220
241
|
def compose(self) -> ComposeResult:
|
|
221
242
|
title = self.args.get("title", "Message")
|
|
222
243
|
message = self.args.get("message", "")
|
|
244
|
+
headers = self.args.get("column_headers")
|
|
245
|
+
rows = self.args.get("rowset")
|
|
223
246
|
with Container(id="dialog"):
|
|
224
247
|
yield Label(title, id="title")
|
|
225
248
|
yield Static(message, id="message")
|
|
249
|
+
if headers and rows:
|
|
250
|
+
with ScrollableContainer(id="table_container"):
|
|
251
|
+
yield _make_table_widget("msg_table", headers, rows)
|
|
252
|
+
yield Static(_row_count_text(len(rows)), classes="row-count")
|
|
226
253
|
with Horizontal(id="buttons"):
|
|
227
|
-
yield
|
|
228
|
-
yield Button("Continue", id="btn_close", variant="primary")
|
|
254
|
+
yield from _button_row(self._button_list(), no_cancel=self.args.get("no_cancel", False))
|
|
229
255
|
|
|
230
256
|
def action_submit(self) -> None:
|
|
231
|
-
"""
|
|
232
|
-
self.
|
|
233
|
-
|
|
257
|
+
"""Dismiss with the first non-cancel button value (triggered by Enter)."""
|
|
258
|
+
for btn in self._button_list():
|
|
259
|
+
if btn[1]:
|
|
260
|
+
self._result = {"button": btn[1]}
|
|
261
|
+
self.dismiss(self._result)
|
|
262
|
+
return
|
|
234
263
|
|
|
235
264
|
def on_button_pressed(self, event: Button.Pressed) -> None:
|
|
236
|
-
|
|
237
|
-
|
|
265
|
+
btn_id = event.button.id
|
|
266
|
+
if btn_id and btn_id.startswith("btn_") and btn_id[4:].isdigit():
|
|
267
|
+
self._result = {"button": self._button_list()[int(btn_id[4:])][1]}
|
|
238
268
|
self.dismiss(self._result)
|
|
239
269
|
|
|
240
270
|
|
execsql/metacommands/control.py
CHANGED
|
@@ -33,6 +33,7 @@ from execsql.exceptions import ErrInfo
|
|
|
33
33
|
from typing import Any
|
|
34
34
|
|
|
35
35
|
import execsql.state as _state
|
|
36
|
+
from execsql.gui.base import format_table, row_count_text
|
|
36
37
|
from execsql.script import current_script_line
|
|
37
38
|
from execsql.utils.errors import exit_now
|
|
38
39
|
from execsql.utils.fileio import EncodedFile, check_dir
|
|
@@ -214,6 +215,14 @@ def x_wait_until(**kwargs: Any) -> None:
|
|
|
214
215
|
|
|
215
216
|
# x_halt_msg is also needed by x_halt - define it here
|
|
216
217
|
def x_halt_msg(**kwargs: Any) -> None:
|
|
218
|
+
"""Halt the script, reporting *errmsg* in a dialog or on the console.
|
|
219
|
+
|
|
220
|
+
The dialog is used only when the run is interactive — either a GUI console
|
|
221
|
+
is already running, or ``gui_level`` is greater than 1. Otherwise the
|
|
222
|
+
message (and any ``DISPLAY`` rowset) is written to the error output and the
|
|
223
|
+
script exits, so that unattended runs fail instead of blocking forever on a
|
|
224
|
+
modal nobody can dismiss.
|
|
225
|
+
"""
|
|
217
226
|
import queue as _queue
|
|
218
227
|
|
|
219
228
|
errmsg = kwargs["errmsg"]
|
|
@@ -242,6 +251,23 @@ def x_halt_msg(**kwargs: Any) -> None:
|
|
|
242
251
|
headers, rows = db.select_data(sql)
|
|
243
252
|
else:
|
|
244
253
|
headers, rows = None, None
|
|
254
|
+
|
|
255
|
+
# Non-interactive runs (no GUI console, gui_level 0 or 1) must not block on
|
|
256
|
+
# a modal dialog: report on the console and exit instead. This mirrors the
|
|
257
|
+
# guard in x_halt, which the message-bearing HALT forms never reach because
|
|
258
|
+
# their metacommand patterns are registered later and so take priority.
|
|
259
|
+
if not (gui_console_isrunning() or conf.gui_level > 1):
|
|
260
|
+
if errmsg:
|
|
261
|
+
_state.output.write_err(errmsg)
|
|
262
|
+
if headers:
|
|
263
|
+
# Unlike the dialog, render an empty rowset too — a HALT diagnostic
|
|
264
|
+
# showing zero rows is more useful than showing nothing at all.
|
|
265
|
+
_state.output.write_err(format_table(headers, rows or []))
|
|
266
|
+
_state.output.write_err(row_count_text(len(rows or [])))
|
|
267
|
+
_state.exec_log.log_exit_halt(*current_script_line(), msg=errmsg)
|
|
268
|
+
exit_now(errlevel, None)
|
|
269
|
+
return
|
|
270
|
+
|
|
245
271
|
enable_gui()
|
|
246
272
|
return_queue: _queue.Queue[Any] = _queue.Queue()
|
|
247
273
|
gui_args = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: execsql2
|
|
3
|
-
Version: 2.22.
|
|
3
|
+
Version: 2.22.4
|
|
4
4
|
Summary: Runs a SQL script against a PostgreSQL, SQLite, MariaDB/MySQL, DuckDB, Firebird, MS-Access, MS-SQL-Server, or Oracle database, or an ODBC DSN. Provides metacommands to import and export data, copy data between databases, conditionally execute SQL and metacommands, and dynamically alter SQL and metacommands with substitution variables.
|
|
5
5
|
Project-URL: Homepage, https://execsql2.readthedocs.io
|
|
6
6
|
Project-URL: Repository, https://github.com/geocoug/execsql
|
|
@@ -384,7 +384,7 @@ execsql-format --no-sql --in-place scripts/
|
|
|
384
384
|
```yaml
|
|
385
385
|
repos:
|
|
386
386
|
- repo: https://github.com/geocoug/execsql
|
|
387
|
-
rev: v2.22.
|
|
387
|
+
rev: v2.22.4
|
|
388
388
|
hooks:
|
|
389
389
|
- id: execsql-format
|
|
390
390
|
```
|
|
@@ -3,7 +3,7 @@ execsql/__main__.py,sha256=HdbK-SAhyUmfB6xINY5AzxdMSxGzWSGEG_2dv42Jn64,315
|
|
|
3
3
|
execsql/api.py,sha256=EOtBwMnm-8fmB_KmvxyjglR6C7CjdYhCPBisJ9CFfJg,22227
|
|
4
4
|
execsql/config.py,sha256=txKziUJLV7UPonj2sGFgkmlinDdSV50aHmR_cuCbEIo,34369
|
|
5
5
|
execsql/exceptions.py,sha256=GlphAiR8iZu4UR4U50WgSqEUMd9_8AeQJ_hhPcJOeQU,9381
|
|
6
|
-
execsql/format.py,sha256=
|
|
6
|
+
execsql/format.py,sha256=3w-m0EsHapBdSKx6oTFWYlXspFLdUR_RF79gMvHhrqQ,34440
|
|
7
7
|
execsql/models.py,sha256=-DWTVrPNwM-n1h3e3rXMoBv9-wpWVdZahyy4RB7fRRE,15502
|
|
8
8
|
execsql/parser.py,sha256=aOxZ7Mzgvk7G4-nvy9Bgz7xlaZm6oo81cffDeBk_LCk,15597
|
|
9
9
|
execsql/plugins.py,sha256=l82VWa5NpvOQWD6vcO-WKP-vtn0wp9__wWDFAbwxZg0,12838
|
|
@@ -55,10 +55,10 @@ execsql/exporters/xml.py,sha256=t1PSr3i8xvTCWzd9jaxxAy5NcRpl6sqjnZALafKCqpM,2575
|
|
|
55
55
|
execsql/exporters/yaml.py,sha256=R61Rs_0rd5G3bg344L4hC84GM79IfYXaDO2tkF-BluY,3121
|
|
56
56
|
execsql/exporters/zip.py,sha256=341z4Z4MPtEkXJEtfiMSiuJigERh5_f8RDbNMBbt8KM,5078
|
|
57
57
|
execsql/gui/__init__.py,sha256=oCb-cyhLZzVpWJ4WU5HbqEDBrV-lm0ytEwxemrOZyqs,2048
|
|
58
|
-
execsql/gui/base.py,sha256=
|
|
59
|
-
execsql/gui/console.py,sha256=
|
|
58
|
+
execsql/gui/base.py,sha256=DMTqHLlpZlGCsNKyrLlJPbaxvukC0n1YmR4aHEN3jPY,14983
|
|
59
|
+
execsql/gui/console.py,sha256=dzdSl4NJNvRd9VvlwRCXHvfnXjQPimyTx7NcibcUZC8,18305
|
|
60
60
|
execsql/gui/desktop.py,sha256=922OdzjV4OGNDIesOxKOmlsrNp1aJ8St8cVwED0H2sE,59521
|
|
61
|
-
execsql/gui/tui.py,sha256=
|
|
61
|
+
execsql/gui/tui.py,sha256=jlCoP1lsEJgFsFikKVqF4B3s3KyKRs6JbWfwtlFHyDc,66800
|
|
62
62
|
execsql/importers/__init__.py,sha256=zZwdQxMaValCNqUrVdvaA7XPU3J8NmqVJ4uolNWY2iU,299
|
|
63
63
|
execsql/importers/base.py,sha256=3Iq_Sr4cCXKHpjjJYkhZX6uhsIIRAdmvAvTdC4mFlWo,4326
|
|
64
64
|
execsql/importers/csv.py,sha256=Kec1VCycRdfstNoxIXsEsSFqQprZp_edpNiMZm43eTI,4914
|
|
@@ -69,7 +69,7 @@ execsql/importers/xls.py,sha256=D7Ul42gIRYZZC5QxD35ft_wmqQv2f1jNMSbnqlzV0ZA,3851
|
|
|
69
69
|
execsql/metacommands/__init__.py,sha256=H_D1Z5kN6zfYtxatejQhQhQV1tlVZ7rcdFZ_9uhXu2Q,13010
|
|
70
70
|
execsql/metacommands/conditions.py,sha256=2bfdVV_LCl91quG4SRLur9Jk60NsIOStHlBCeJJ-Djc,30068
|
|
71
71
|
execsql/metacommands/connect.py,sha256=SPk4h9yiUgTD3w1gNOT_oYx8VShggsO357by5Hoy6OI,15344
|
|
72
|
-
execsql/metacommands/control.py,sha256=
|
|
72
|
+
execsql/metacommands/control.py,sha256=QT3CJyneANrHxgnbK7vlwmLbckRCbSSwSxy4D3oxN4A,9375
|
|
73
73
|
execsql/metacommands/data.py,sha256=Rp18lHUKSTkwTFRjOQ7bDgZd42LNLVoTS3Zc_bcNEWY,12199
|
|
74
74
|
execsql/metacommands/debug.py,sha256=MeVXAob8ItEg2QzuSUkKDaQCEABnH6u0XcAwJzw36CE,13015
|
|
75
75
|
execsql/metacommands/dispatch.py,sha256=t7x0xWHJA0PeCrYf7jYeSMJgf0yxcZ_xh-_YAtBPHLw,87192
|
|
@@ -101,23 +101,23 @@ execsql/utils/numeric.py,sha256=_7bi5R6pHjMCkOPne_Sh5nUj-B8e9g6WFmjptFHaunA,1573
|
|
|
101
101
|
execsql/utils/regex.py,sha256=B3mSBhRRx_DpUnX_t9IoYd05KvWAebiLMCZqQAmEwcw,3885
|
|
102
102
|
execsql/utils/strings.py,sha256=UQNjpRCEFa1UO6feU-M-9e24wWAvizs_iu_4fFusLxo,8516
|
|
103
103
|
execsql/utils/timer.py,sha256=eDYf5VzCNFk7oo90InJucUm3XcBdhYMogjZMqeg9xzc,1899
|
|
104
|
-
execsql2-2.22.
|
|
105
|
-
execsql2-2.22.
|
|
106
|
-
execsql2-2.22.
|
|
107
|
-
execsql2-2.22.
|
|
108
|
-
execsql2-2.22.
|
|
109
|
-
execsql2-2.22.
|
|
110
|
-
execsql2-2.22.
|
|
111
|
-
execsql2-2.22.
|
|
112
|
-
execsql2-2.22.
|
|
113
|
-
execsql2-2.22.
|
|
114
|
-
execsql2-2.22.
|
|
115
|
-
execsql2-2.22.
|
|
116
|
-
execsql2-2.22.
|
|
117
|
-
execsql2-2.22.
|
|
118
|
-
execsql2-2.22.
|
|
119
|
-
execsql2-2.22.
|
|
120
|
-
execsql2-2.22.
|
|
121
|
-
execsql2-2.22.
|
|
122
|
-
execsql2-2.22.
|
|
123
|
-
execsql2-2.22.
|
|
104
|
+
execsql2-2.22.4.data/data/execsql2_extras/README.md,sha256=vX4NTL095dUoA_hesyRMGYBorEZ_Y_tJ9qrd-MVV09I,5032
|
|
105
|
+
execsql2-2.22.4.data/data/execsql2_extras/config_settings.sqlite,sha256=aY5cxR7Q7J6zJ4bC9lu5mHUrhy211Cq3MNKPQVCt02E,20480
|
|
106
|
+
execsql2-2.22.4.data/data/execsql2_extras/example_config_prompt.sql,sha256=2e8KzzVWhho8KxYVHETSVmZdhW7wodioDsqBLSL6m4s,7487
|
|
107
|
+
execsql2-2.22.4.data/data/execsql2_extras/make_config_db.sql,sha256=WwyC6dK-Eh5CAVppiBCDHqiI1_wEI9U95Ytpr4lsZkg,8726
|
|
108
|
+
execsql2-2.22.4.data/data/execsql2_extras/md_compare.sql,sha256=qYYVAjSeHZzjszxV3Bv6bg8Ckbq2kMHl87_gh4sywMU,24140
|
|
109
|
+
execsql2-2.22.4.data/data/execsql2_extras/md_glossary.sql,sha256=hkZ2Onn57LAKKsuXxzhR8tPtcWXkmWEQkwPE58-Tm2k,10796
|
|
110
|
+
execsql2-2.22.4.data/data/execsql2_extras/md_upsert.sql,sha256=_CAK4BzEboRXTNy03SJR-oOjcEdSNMuRBPL6noWUptY,112560
|
|
111
|
+
execsql2-2.22.4.data/data/execsql2_extras/pg_compare.sql,sha256=1zJd4hVUKHR0tncc2qTBC9B4qVV4Us2ITkJpsjN3tMw,24352
|
|
112
|
+
execsql2-2.22.4.data/data/execsql2_extras/pg_glossary.sql,sha256=IKuwna-_8b20ljSkXZruuiQigrCpo7ueQdUqd1MXiuI,9908
|
|
113
|
+
execsql2-2.22.4.data/data/execsql2_extras/pg_upsert.sql,sha256=HpPJtTHvpEjQy03j-3iPxDEOHMRkudOg7O4D4YR38UI,108315
|
|
114
|
+
execsql2-2.22.4.data/data/execsql2_extras/script_template.sql,sha256=2J35ddZPguJ-vwTsz83wErv0jiWUyJcdW_JM0mNKDXA,11155
|
|
115
|
+
execsql2-2.22.4.data/data/execsql2_extras/ss_compare.sql,sha256=j1qVNUPXQsEU7-DoVgDJCGcE0EuIl7whLBT3fgeiMAo,24833
|
|
116
|
+
execsql2-2.22.4.data/data/execsql2_extras/ss_glossary.sql,sha256=2gLxv34xzKt0vy7hSzJH7a9JiMC3ETrv9MofxQwAibU,13065
|
|
117
|
+
execsql2-2.22.4.data/data/execsql2_extras/ss_upsert.sql,sha256=G_8rQ0VzuKIZHWs24O_WrfzpC5S27R1JsL-bFBR3SUQ,117730
|
|
118
|
+
execsql2-2.22.4.dist-info/METADATA,sha256=gD2Dm8BheKQrFz6xAs7KyfpqGzs93Rpv7vxWyPWXeQE,20382
|
|
119
|
+
execsql2-2.22.4.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
|
|
120
|
+
execsql2-2.22.4.dist-info/entry_points.txt,sha256=sUOxkM-dN1eBGGpSpDLsAaE0yNXYQKWZAfxPOlMkQyk,90
|
|
121
|
+
execsql2-2.22.4.dist-info/licenses/LICENSE.txt,sha256=LBdhuxejF8_bLCHZ2kWfmDXpDGUu914Gbd6_3JjCRe0,676
|
|
122
|
+
execsql2-2.22.4.dist-info/licenses/NOTICE,sha256=McYzgxYav3U1OaVsY4Su1sfBrfmplpRdA9b6-gCDQCg,342
|
|
123
|
+
execsql2-2.22.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
{execsql2-2.22.2.data → execsql2-2.22.4.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
|