execsql2 2.22.6__py3-none-any.whl → 2.22.8__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 +183 -34
- {execsql2-2.22.6.dist-info → execsql2-2.22.8.dist-info}/METADATA +2 -2
- {execsql2-2.22.6.dist-info → execsql2-2.22.8.dist-info}/RECORD +21 -21
- {execsql2-2.22.6.dist-info → execsql2-2.22.8.dist-info}/WHEEL +1 -1
- {execsql2-2.22.6.data → execsql2-2.22.8.data}/data/execsql2_extras/README.md +0 -0
- {execsql2-2.22.6.data → execsql2-2.22.8.data}/data/execsql2_extras/config_settings.sqlite +0 -0
- {execsql2-2.22.6.data → execsql2-2.22.8.data}/data/execsql2_extras/example_config_prompt.sql +0 -0
- {execsql2-2.22.6.data → execsql2-2.22.8.data}/data/execsql2_extras/make_config_db.sql +0 -0
- {execsql2-2.22.6.data → execsql2-2.22.8.data}/data/execsql2_extras/md_compare.sql +0 -0
- {execsql2-2.22.6.data → execsql2-2.22.8.data}/data/execsql2_extras/md_glossary.sql +0 -0
- {execsql2-2.22.6.data → execsql2-2.22.8.data}/data/execsql2_extras/md_upsert.sql +0 -0
- {execsql2-2.22.6.data → execsql2-2.22.8.data}/data/execsql2_extras/pg_compare.sql +0 -0
- {execsql2-2.22.6.data → execsql2-2.22.8.data}/data/execsql2_extras/pg_glossary.sql +0 -0
- {execsql2-2.22.6.data → execsql2-2.22.8.data}/data/execsql2_extras/pg_upsert.sql +0 -0
- {execsql2-2.22.6.data → execsql2-2.22.8.data}/data/execsql2_extras/script_template.sql +0 -0
- {execsql2-2.22.6.data → execsql2-2.22.8.data}/data/execsql2_extras/ss_compare.sql +0 -0
- {execsql2-2.22.6.data → execsql2-2.22.8.data}/data/execsql2_extras/ss_glossary.sql +0 -0
- {execsql2-2.22.6.data → execsql2-2.22.8.data}/data/execsql2_extras/ss_upsert.sql +0 -0
- {execsql2-2.22.6.dist-info → execsql2-2.22.8.dist-info}/entry_points.txt +0 -0
- {execsql2-2.22.6.dist-info → execsql2-2.22.8.dist-info}/licenses/LICENSE.txt +0 -0
- {execsql2-2.22.6.dist-info → execsql2-2.22.8.dist-info}/licenses/NOTICE +0 -0
execsql/format.py
CHANGED
|
@@ -176,13 +176,18 @@ _EXECSQL_VAR_RE = re.compile(r"""!(['"]?)!([^!\s][^!]*)!\1!|!\{[^}]+\}!""")
|
|
|
176
176
|
_IDENT_CHAR_RE = re.compile(r"[A-Za-z0-9_$]")
|
|
177
177
|
|
|
178
178
|
|
|
179
|
-
|
|
180
|
-
|
|
179
|
+
_LITERAL_KINDS = frozenset({"estring", "plain", "dollar"})
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def _iter_sql_spans(sql: str) -> Iterator[tuple[int, int, str]]:
|
|
183
|
+
"""Yield ``(start, end, kind)`` spans for every non-code region of *sql*.
|
|
181
184
|
|
|
182
185
|
This is a lexical walk rather than a regex sweep, because an apostrophe
|
|
183
|
-
only starts a literal in some contexts
|
|
184
|
-
(which
|
|
185
|
-
|
|
186
|
+
only starts a literal in some contexts: inside a line comment, a block
|
|
187
|
+
comment (which nests in PostgreSQL), or a quoted identifier it is just a
|
|
188
|
+
character. Those three regions are reported as spans of their own so
|
|
189
|
+
callers that care about code positions — :func:`_paren_depths` — can mask
|
|
190
|
+
them out, and :func:`_iter_sql_literals` filters them back off.
|
|
186
191
|
|
|
187
192
|
*kind* is one of:
|
|
188
193
|
|
|
@@ -195,6 +200,8 @@ def _iter_sql_literals(sql: str) -> Iterator[tuple[int, int, str]]:
|
|
|
195
200
|
``"dollar"``
|
|
196
201
|
A dollar-quoted body, ``$$...$$`` or ``$tag$...$tag$``, in which no
|
|
197
202
|
character is special.
|
|
203
|
+
``"line_comment"``, ``"block_comment"``, ``"quoted_ident"``
|
|
204
|
+
Regions that are not code and hold no literal.
|
|
198
205
|
"""
|
|
199
206
|
i, n = 0, len(sql)
|
|
200
207
|
while i < n:
|
|
@@ -202,10 +209,13 @@ def _iter_sql_literals(sql: str) -> Iterator[tuple[int, int, str]]:
|
|
|
202
209
|
|
|
203
210
|
if c == "-" and sql.startswith("--", i):
|
|
204
211
|
nl = sql.find("\n", i)
|
|
205
|
-
|
|
212
|
+
stop = n if nl < 0 else nl
|
|
213
|
+
yield i, stop, "line_comment"
|
|
214
|
+
i = stop
|
|
206
215
|
continue
|
|
207
216
|
|
|
208
217
|
if c == "/" and sql.startswith("/*", i):
|
|
218
|
+
start = i
|
|
209
219
|
depth, i = 1, i + 2
|
|
210
220
|
while i < n and depth:
|
|
211
221
|
if sql.startswith("/*", i):
|
|
@@ -214,9 +224,11 @@ def _iter_sql_literals(sql: str) -> Iterator[tuple[int, int, str]]:
|
|
|
214
224
|
depth, i = depth - 1, i + 2
|
|
215
225
|
else:
|
|
216
226
|
i += 1
|
|
227
|
+
yield start, i, "block_comment"
|
|
217
228
|
continue
|
|
218
229
|
|
|
219
230
|
if c == '"':
|
|
231
|
+
start = i
|
|
220
232
|
i += 1
|
|
221
233
|
while i < n:
|
|
222
234
|
if sql[i] == '"':
|
|
@@ -226,6 +238,7 @@ def _iter_sql_literals(sql: str) -> Iterator[tuple[int, int, str]]:
|
|
|
226
238
|
i += 1
|
|
227
239
|
break
|
|
228
240
|
i += 1
|
|
241
|
+
yield start, i, "quoted_ident"
|
|
229
242
|
continue
|
|
230
243
|
|
|
231
244
|
if c == "$":
|
|
@@ -273,6 +286,46 @@ def _iter_sql_literals(sql: str) -> Iterator[tuple[int, int, str]]:
|
|
|
273
286
|
i += 1
|
|
274
287
|
|
|
275
288
|
|
|
289
|
+
def _iter_sql_literals(sql: str) -> Iterator[tuple[int, int, str]]:
|
|
290
|
+
"""Yield ``(start, end, kind)`` spans for every string literal in *sql*.
|
|
291
|
+
|
|
292
|
+
The literal subset of :func:`_iter_sql_spans`; comments and quoted
|
|
293
|
+
identifiers are dropped, so quotes inside them never open a literal.
|
|
294
|
+
"""
|
|
295
|
+
for start, end, kind in _iter_sql_spans(sql):
|
|
296
|
+
if kind in _LITERAL_KINDS:
|
|
297
|
+
yield start, end, kind
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def _paren_depths(lines: list[str]) -> list[int]:
|
|
301
|
+
"""Return the parenthesis nesting depth at the start of each of *lines*.
|
|
302
|
+
|
|
303
|
+
Parentheses inside string literals, comments, and quoted identifiers do
|
|
304
|
+
not count. Depth resets at every ``;`` so one statement with unbalanced
|
|
305
|
+
parens — which only happens when the input is a fragment — cannot skew
|
|
306
|
+
the statements that follow.
|
|
307
|
+
"""
|
|
308
|
+
text = "\n".join(lines)
|
|
309
|
+
chars = list(text)
|
|
310
|
+
for start, end, _kind in _iter_sql_spans(text):
|
|
311
|
+
for i in range(start, min(end, len(chars))):
|
|
312
|
+
if chars[i] != "\n":
|
|
313
|
+
chars[i] = " "
|
|
314
|
+
|
|
315
|
+
depths: list[int] = []
|
|
316
|
+
depth = 0
|
|
317
|
+
for line in "".join(chars).split("\n"):
|
|
318
|
+
depths.append(depth)
|
|
319
|
+
for ch in line:
|
|
320
|
+
if ch == "(":
|
|
321
|
+
depth += 1
|
|
322
|
+
elif ch == ")":
|
|
323
|
+
depth = max(0, depth - 1)
|
|
324
|
+
elif ch == ";":
|
|
325
|
+
depth = 0
|
|
326
|
+
return depths
|
|
327
|
+
|
|
328
|
+
|
|
276
329
|
def _sql_literal_texts(sql: str) -> list[str]:
|
|
277
330
|
"""Return the source text of every string literal in *sql*, in order."""
|
|
278
331
|
return [sql[start:end] for start, end, _ in _iter_sql_literals(sql)]
|
|
@@ -456,7 +509,21 @@ def _sqlglot_format(
|
|
|
456
509
|
|
|
457
510
|
try:
|
|
458
511
|
with contextlib.redirect_stderr(io.StringIO()):
|
|
459
|
-
|
|
512
|
+
# Parse with RAISE, not IGNORE. Under IGNORE sqlglot answers a
|
|
513
|
+
# statement it cannot parse with a *partial* AST — the tokens it
|
|
514
|
+
# failed on are simply absent — and regenerating from that AST
|
|
515
|
+
# writes back SQL that no longer means what the author wrote.
|
|
516
|
+
# ``INSERT ... CROSS JOIN LATERAL (VALUES ...) AS g(a, b) ON
|
|
517
|
+
# CONFLICT (a) DO NOTHING`` came back with ``DO NOTHING`` deleted:
|
|
518
|
+
# still one statement, still 88% of the input's alphanumeric
|
|
519
|
+
# characters, no string literals to compare, so every guard below
|
|
520
|
+
# passed it through. The guards are quantitative and this loss is
|
|
521
|
+
# qualitative — a dropped ``DISTINCT``, ``CASCADE``, ``DESC`` or
|
|
522
|
+
# ``NOT`` is smaller still, and no threshold separates those from
|
|
523
|
+
# ordinary reformatting. Only the parser knows whether it
|
|
524
|
+
# understood the whole statement, so ask it: input that does not
|
|
525
|
+
# parse is left exactly as written.
|
|
526
|
+
ast = sqlglot.parse(protected, read="postgres", error_level=sqlglot_errors.ErrorLevel.RAISE)
|
|
460
527
|
statements: list[str] = []
|
|
461
528
|
for node in ast:
|
|
462
529
|
if node is None:
|
|
@@ -524,6 +591,10 @@ def _sqlglot_format(
|
|
|
524
591
|
if restored is None:
|
|
525
592
|
return sql_lines
|
|
526
593
|
return _restore_variables(restored, replacements).split("\n")
|
|
594
|
+
except sqlglot_errors.ParseError:
|
|
595
|
+
# Unparsable input: anything generated from a partial parse is
|
|
596
|
+
# untrustworthy, so emit the original lines untouched.
|
|
597
|
+
return sql_lines
|
|
527
598
|
except Exception:
|
|
528
599
|
return sql_lines
|
|
529
600
|
|
|
@@ -570,6 +641,34 @@ _CMT_MARKER_RE = re.compile(rf"/\*\s*({re.escape(_CMT_MARKER)}\d+)\s*\*/")
|
|
|
570
641
|
# converge. Matching the run as a unit removes it cleanly. See issue #35.
|
|
571
642
|
_CMT_MARKER_RUN_RE = re.compile(rf"\s*(?:/\*\s*{re.escape(_CMT_MARKER)}\d+\s*\*/\s*)+")
|
|
572
643
|
|
|
644
|
+
# Characters that must not be preceded by a space once a marker run between
|
|
645
|
+
# them and the previous token is removed.
|
|
646
|
+
_NO_SPACE_BEFORE = frozenset(",;).")
|
|
647
|
+
|
|
648
|
+
|
|
649
|
+
def _strip_marker_runs(line: str) -> str:
|
|
650
|
+
"""Remove every comment-marker run from *line*, leaving no stray spacing.
|
|
651
|
+
|
|
652
|
+
A run stands where the author wrote nothing, so it is replaced by the one
|
|
653
|
+
space that keeps its neighbours apart — ``AND /* m */ RTRIM(`` must not
|
|
654
|
+
become ``ANDRTRIM(``. At the ends of the line, or against punctuation
|
|
655
|
+
that binds to the token before it, that space is not a separator but
|
|
656
|
+
residue: sqlglot emitting ``1 = 1 /* m */;`` left ``1 = 1 ;``, which the
|
|
657
|
+
next run then normalised — costing a pass and making ``--check`` fail on a
|
|
658
|
+
file that was already formatted. See issue #35.
|
|
659
|
+
"""
|
|
660
|
+
|
|
661
|
+
def repl(match: re.Match[str]) -> str:
|
|
662
|
+
before = line[: match.start()]
|
|
663
|
+
after = line[match.end() :]
|
|
664
|
+
if not before.strip() or not after.strip():
|
|
665
|
+
return ""
|
|
666
|
+
if after[:1] in _NO_SPACE_BEFORE or before.endswith("("):
|
|
667
|
+
return ""
|
|
668
|
+
return " "
|
|
669
|
+
|
|
670
|
+
return _CMT_MARKER_RUN_RE.sub(repl, line)
|
|
671
|
+
|
|
573
672
|
|
|
574
673
|
def _format_preserving_comments(
|
|
575
674
|
lines: list[str],
|
|
@@ -595,6 +694,7 @@ def _format_preserving_comments(
|
|
|
595
694
|
comment_store: dict[str, str] = {} # marker → original comment line
|
|
596
695
|
# Track the SQL line that originally followed each comment, for fallback
|
|
597
696
|
anchor_sql: dict[str, str] = {} # marker → next SQL line (stripped)
|
|
697
|
+
anchor_line: dict[str, int] = {} # marker → index of that line in `processed`
|
|
598
698
|
pending_markers: list[str] = []
|
|
599
699
|
processed: list[str] = []
|
|
600
700
|
in_block = False
|
|
@@ -621,50 +721,87 @@ def _format_preserving_comments(
|
|
|
621
721
|
processed.append(f"{prefix} {line}" if prefix else line)
|
|
622
722
|
for m in pending_markers:
|
|
623
723
|
anchor_sql[m] = stripped
|
|
724
|
+
anchor_line[m] = len(processed) - 1
|
|
624
725
|
pending_markers.clear()
|
|
625
726
|
|
|
626
727
|
# Trailing comments with no following SQL — preserve as-is
|
|
627
728
|
trailing: list[str] = [comment_store[m] for m in pending_markers]
|
|
628
729
|
|
|
730
|
+
# Parenthesis depth each comment sat at in the input. A comment on its own
|
|
731
|
+
# line belongs to the SQL line below it, so it shares that line's depth.
|
|
732
|
+
in_depths = _paren_depths(processed)
|
|
733
|
+
anchor_depth: dict[str, int] = {m: in_depths[i] for m, i in anchor_line.items()}
|
|
734
|
+
|
|
629
735
|
# ---- Step 2: format through sqlglot ---------------------------------
|
|
630
736
|
formatted = _sqlglot_format(processed, sql_indent=sql_indent, leading_comma=leading_comma)
|
|
631
737
|
|
|
632
738
|
# ---- Step 3: restore surviving markers to comment lines -------------
|
|
633
739
|
found_markers: set[str] = set()
|
|
634
|
-
|
|
740
|
+
sql_out: list[str] = []
|
|
741
|
+
marker_sites: list[tuple[int, str]] = [] # (index in sql_out, marker)
|
|
635
742
|
for fline in formatted:
|
|
636
743
|
markers_here = _CMT_MARKER_RE.findall(fline)
|
|
637
|
-
if markers_here:
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
744
|
+
if not markers_here:
|
|
745
|
+
sql_out.append(fline)
|
|
746
|
+
continue
|
|
747
|
+
# Strip markers to get the underlying SQL line and its indent
|
|
748
|
+
cleaned = _strip_marker_runs(fline).strip()
|
|
749
|
+
# Indent comes from the line's own leading whitespace, never from
|
|
750
|
+
# what is left after removing the marker. Markers are injected as
|
|
751
|
+
# ``/* marker */ line`` — with a separating space — so measuring
|
|
752
|
+
# after removal counts that space as indentation. Whenever
|
|
753
|
+
# sqlglot leaves the line untouched (an unparsable statement falls
|
|
754
|
+
# back verbatim) the extra space is re-measured and re-added on the
|
|
755
|
+
# next run, growing the indent by one on every pass and never
|
|
756
|
+
# converging. See issue #35.
|
|
757
|
+
line_indent = fline[: len(fline) - len(fline.lstrip())]
|
|
758
|
+
for m in markers_here:
|
|
759
|
+
if m in comment_store:
|
|
760
|
+
marker_sites.append((len(sql_out), m))
|
|
761
|
+
found_markers.add(m)
|
|
762
|
+
if cleaned:
|
|
763
|
+
sql_out.append(line_indent + cleaned)
|
|
764
|
+
|
|
765
|
+
# Place each comment above the line where its expression *starts*, not
|
|
766
|
+
# above whatever line the marker landed on. sqlglot attaches an inline
|
|
767
|
+
# comment to a node, and when it then reflows that node across lines the
|
|
768
|
+
# marker can surface deep inside the expression — ``COALESCE((a.b).c,
|
|
769
|
+
# FALSE)`` puts it on the ``).c, FALSE)`` continuation line. Restoring
|
|
770
|
+
# there splits the expression around a comment that now documents a
|
|
771
|
+
# fragment of it. The comment's own line in the input sat at the
|
|
772
|
+
# parenthesis depth of the SQL line below it, so walk back from the marker
|
|
773
|
+
# to the nearest line at that depth: the line the reflowed expression
|
|
774
|
+
# opens on. A marker that did not move is already at its anchor depth and
|
|
775
|
+
# stays where it is.
|
|
776
|
+
out_depths = _paren_depths(sql_out)
|
|
777
|
+
comments_before: dict[int, list[str]] = {}
|
|
778
|
+
for idx, marker in marker_sites:
|
|
779
|
+
target = idx
|
|
780
|
+
want = anchor_depth.get(marker, 0)
|
|
781
|
+
while target > 0 and target < len(out_depths) and out_depths[target] > want:
|
|
782
|
+
target -= 1
|
|
783
|
+
orig_stripped = comment_store[marker].strip()
|
|
784
|
+
if not orig_stripped:
|
|
785
|
+
comments_before.setdefault(target, []).append("")
|
|
786
|
+
continue
|
|
787
|
+
# Re-indent the comment to match the SQL line it precedes
|
|
788
|
+
if target < len(sql_out):
|
|
789
|
+
anchor = sql_out[target]
|
|
790
|
+
indent_str = anchor[: len(anchor) - len(anchor.lstrip())]
|
|
661
791
|
else:
|
|
662
|
-
|
|
792
|
+
indent_str = ""
|
|
793
|
+
comments_before.setdefault(target, []).append(indent_str + orig_stripped)
|
|
794
|
+
|
|
795
|
+
result: list[str] = []
|
|
796
|
+
for i, line in enumerate(sql_out):
|
|
797
|
+
result.extend(comments_before.get(i, ()))
|
|
798
|
+
result.append(line)
|
|
799
|
+
result.extend(comments_before.get(len(sql_out), ()))
|
|
663
800
|
|
|
664
801
|
# ---- Step 4: reinsert lost markers ----------------------------------
|
|
665
802
|
lost = [m for m in comment_store if m not in found_markers and m not in set(pending_markers)]
|
|
666
803
|
if lost:
|
|
667
|
-
_reinsert_lost_comments(result, lost, comment_store, anchor_sql)
|
|
804
|
+
_reinsert_lost_comments(result, lost, comment_store, anchor_sql, anchor_depth)
|
|
668
805
|
|
|
669
806
|
result.extend(trailing)
|
|
670
807
|
return result
|
|
@@ -675,14 +812,22 @@ def _reinsert_lost_comments(
|
|
|
675
812
|
lost_markers: list[str],
|
|
676
813
|
comment_store: dict[str, str],
|
|
677
814
|
anchor_sql: dict[str, str],
|
|
815
|
+
anchor_depth: dict[str, int],
|
|
678
816
|
) -> None:
|
|
679
817
|
"""Best-effort reinsertion of comments that sqlglot dropped.
|
|
680
818
|
|
|
681
819
|
For each lost comment, extract key tokens from its anchor SQL line and
|
|
682
820
|
find the output line that best matches, then insert the comment before
|
|
683
821
|
that line (indented to match). Operates on *result* in place.
|
|
822
|
+
|
|
823
|
+
Token matching scores whole lines, so on a reflowed expression the best
|
|
824
|
+
match is often a continuation line — ``a.meas_value`` out of ``CASE WHEN
|
|
825
|
+
(a.meas_value).undetected``. Inserting there splits the expression, so
|
|
826
|
+
the match is pulled back to the line where the expression opens, the same
|
|
827
|
+
way surviving markers are placed in :func:`_format_preserving_comments`.
|
|
684
828
|
"""
|
|
685
829
|
_word_re = re.compile(r"[a-zA-Z_]\w*")
|
|
830
|
+
out_depths = _paren_depths(result)
|
|
686
831
|
|
|
687
832
|
# Process in reverse order so earlier inserts don't shift later indices.
|
|
688
833
|
insertions: list[tuple[int, str]] = []
|
|
@@ -709,6 +854,10 @@ def _reinsert_lost_comments(
|
|
|
709
854
|
best_score = score
|
|
710
855
|
best_idx = i
|
|
711
856
|
|
|
857
|
+
want = anchor_depth.get(marker, 0)
|
|
858
|
+
while best_idx > 0 and best_idx < len(out_depths) and out_depths[best_idx] > want:
|
|
859
|
+
best_idx -= 1
|
|
860
|
+
|
|
712
861
|
# Re-indent comment to match the target line
|
|
713
862
|
if best_idx < len(result):
|
|
714
863
|
target = result[best_idx]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: execsql2
|
|
3
|
-
Version: 2.22.
|
|
3
|
+
Version: 2.22.8
|
|
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.8
|
|
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=OOxsOX6g7otVgL3gI6uGxa5WIh8GTvjJ8WO-_P91zXg,52886
|
|
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
|
|
@@ -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.8.data/data/execsql2_extras/README.md,sha256=vX4NTL095dUoA_hesyRMGYBorEZ_Y_tJ9qrd-MVV09I,5032
|
|
105
|
+
execsql2-2.22.8.data/data/execsql2_extras/config_settings.sqlite,sha256=aY5cxR7Q7J6zJ4bC9lu5mHUrhy211Cq3MNKPQVCt02E,20480
|
|
106
|
+
execsql2-2.22.8.data/data/execsql2_extras/example_config_prompt.sql,sha256=2e8KzzVWhho8KxYVHETSVmZdhW7wodioDsqBLSL6m4s,7487
|
|
107
|
+
execsql2-2.22.8.data/data/execsql2_extras/make_config_db.sql,sha256=WwyC6dK-Eh5CAVppiBCDHqiI1_wEI9U95Ytpr4lsZkg,8726
|
|
108
|
+
execsql2-2.22.8.data/data/execsql2_extras/md_compare.sql,sha256=qYYVAjSeHZzjszxV3Bv6bg8Ckbq2kMHl87_gh4sywMU,24140
|
|
109
|
+
execsql2-2.22.8.data/data/execsql2_extras/md_glossary.sql,sha256=hkZ2Onn57LAKKsuXxzhR8tPtcWXkmWEQkwPE58-Tm2k,10796
|
|
110
|
+
execsql2-2.22.8.data/data/execsql2_extras/md_upsert.sql,sha256=_CAK4BzEboRXTNy03SJR-oOjcEdSNMuRBPL6noWUptY,112560
|
|
111
|
+
execsql2-2.22.8.data/data/execsql2_extras/pg_compare.sql,sha256=1zJd4hVUKHR0tncc2qTBC9B4qVV4Us2ITkJpsjN3tMw,24352
|
|
112
|
+
execsql2-2.22.8.data/data/execsql2_extras/pg_glossary.sql,sha256=IKuwna-_8b20ljSkXZruuiQigrCpo7ueQdUqd1MXiuI,9908
|
|
113
|
+
execsql2-2.22.8.data/data/execsql2_extras/pg_upsert.sql,sha256=HpPJtTHvpEjQy03j-3iPxDEOHMRkudOg7O4D4YR38UI,108315
|
|
114
|
+
execsql2-2.22.8.data/data/execsql2_extras/script_template.sql,sha256=2J35ddZPguJ-vwTsz83wErv0jiWUyJcdW_JM0mNKDXA,11155
|
|
115
|
+
execsql2-2.22.8.data/data/execsql2_extras/ss_compare.sql,sha256=j1qVNUPXQsEU7-DoVgDJCGcE0EuIl7whLBT3fgeiMAo,24833
|
|
116
|
+
execsql2-2.22.8.data/data/execsql2_extras/ss_glossary.sql,sha256=2gLxv34xzKt0vy7hSzJH7a9JiMC3ETrv9MofxQwAibU,13065
|
|
117
|
+
execsql2-2.22.8.data/data/execsql2_extras/ss_upsert.sql,sha256=G_8rQ0VzuKIZHWs24O_WrfzpC5S27R1JsL-bFBR3SUQ,117730
|
|
118
|
+
execsql2-2.22.8.dist-info/METADATA,sha256=YR0z4uOGh4ontDBb5qfx18stwbhiRyHkyZDAUwE_ST4,20382
|
|
119
|
+
execsql2-2.22.8.dist-info/WHEEL,sha256=THafob7ofN-NsuMN7Mg4qZyHaQI7KkD-QlcQatYhXPo,87
|
|
120
|
+
execsql2-2.22.8.dist-info/entry_points.txt,sha256=sUOxkM-dN1eBGGpSpDLsAaE0yNXYQKWZAfxPOlMkQyk,90
|
|
121
|
+
execsql2-2.22.8.dist-info/licenses/LICENSE.txt,sha256=LBdhuxejF8_bLCHZ2kWfmDXpDGUu914Gbd6_3JjCRe0,676
|
|
122
|
+
execsql2-2.22.8.dist-info/licenses/NOTICE,sha256=McYzgxYav3U1OaVsY4Su1sfBrfmplpRdA9b6-gCDQCg,342
|
|
123
|
+
execsql2-2.22.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
{execsql2-2.22.6.data → execsql2-2.22.8.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
|