execsql2 2.16.16__py3-none-any.whl → 2.16.18__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 (25) hide show
  1. execsql/debug/repl.py +1 -1
  2. execsql/format.py +22 -4
  3. execsql/metacommands/debug.py +14 -4
  4. execsql/script/parser.py +45 -5
  5. {execsql2-2.16.16.dist-info → execsql2-2.16.18.dist-info}/METADATA +1 -1
  6. {execsql2-2.16.16.dist-info → execsql2-2.16.18.dist-info}/RECORD +25 -25
  7. {execsql2-2.16.16.data → execsql2-2.16.18.data}/data/execsql2_extras/README.md +0 -0
  8. {execsql2-2.16.16.data → execsql2-2.16.18.data}/data/execsql2_extras/config_settings.sqlite +0 -0
  9. {execsql2-2.16.16.data → execsql2-2.16.18.data}/data/execsql2_extras/example_config_prompt.sql +0 -0
  10. {execsql2-2.16.16.data → execsql2-2.16.18.data}/data/execsql2_extras/execsql.conf +0 -0
  11. {execsql2-2.16.16.data → execsql2-2.16.18.data}/data/execsql2_extras/make_config_db.sql +0 -0
  12. {execsql2-2.16.16.data → execsql2-2.16.18.data}/data/execsql2_extras/md_compare.sql +0 -0
  13. {execsql2-2.16.16.data → execsql2-2.16.18.data}/data/execsql2_extras/md_glossary.sql +0 -0
  14. {execsql2-2.16.16.data → execsql2-2.16.18.data}/data/execsql2_extras/md_upsert.sql +0 -0
  15. {execsql2-2.16.16.data → execsql2-2.16.18.data}/data/execsql2_extras/pg_compare.sql +0 -0
  16. {execsql2-2.16.16.data → execsql2-2.16.18.data}/data/execsql2_extras/pg_glossary.sql +0 -0
  17. {execsql2-2.16.16.data → execsql2-2.16.18.data}/data/execsql2_extras/pg_upsert.sql +0 -0
  18. {execsql2-2.16.16.data → execsql2-2.16.18.data}/data/execsql2_extras/script_template.sql +0 -0
  19. {execsql2-2.16.16.data → execsql2-2.16.18.data}/data/execsql2_extras/ss_compare.sql +0 -0
  20. {execsql2-2.16.16.data → execsql2-2.16.18.data}/data/execsql2_extras/ss_glossary.sql +0 -0
  21. {execsql2-2.16.16.data → execsql2-2.16.18.data}/data/execsql2_extras/ss_upsert.sql +0 -0
  22. {execsql2-2.16.16.dist-info → execsql2-2.16.18.dist-info}/WHEEL +0 -0
  23. {execsql2-2.16.16.dist-info → execsql2-2.16.18.dist-info}/entry_points.txt +0 -0
  24. {execsql2-2.16.16.dist-info → execsql2-2.16.18.dist-info}/licenses/LICENSE.txt +0 -0
  25. {execsql2-2.16.16.dist-info → execsql2-2.16.18.dist-info}/licenses/NOTICE +0 -0
execsql/debug/repl.py CHANGED
@@ -546,7 +546,7 @@ def _print_script_detail(name: str) -> None:
546
546
  return
547
547
  block = scripts[script_name]
548
548
  sig = _format_script_signature(block.name, block.param_defs)
549
- src = _format_script_source(block.span)
549
+ src = _format_script_source(block.span, full_path=True)
550
550
  _write_rule(f" {_c(_BOLD + _YELLOW, 'Script')} {_c(_DIM, '──')} {_c(_CYAN, sig)} ")
551
551
  _write(f" {_c(_BOLD, 'Source:')} {src}\n")
552
552
  if block.param_defs:
execsql/format.py CHANGED
@@ -82,6 +82,14 @@ BLOCK_CLOSE = frozenset({"ENDIF", "END LOOP", "ENDLOOP", "END SCRIPT", "END BATC
82
82
  PIVOT = frozenset({"ELSE", "ELSEIF"}) # decrease depth before emit, increase after
83
83
  CONTINUATION = frozenset({"ANDIF", "ORIF"}) # emit at depth-1, no depth change
84
84
 
85
+ # Inline IF: "IF (cond) { command }" — self-contained, no ENDIF, no depth change.
86
+ # Mirrors src/execsql/cli/lint.py:_RX_IF_INLINE so formatter and linter agree.
87
+ _IF_INLINE_RE = re.compile(r"^\s*IF\s*\(\s*.+\s*\)\s*\{.+\}\s*$", re.I)
88
+ # BLOCK_OPEN keywords whose bodies are guaranteed-SQL (not metacommand-driven).
89
+ # Blank lines inside these belong to the SQL accumulator, not the output stream.
90
+ _SQL_BODY_BLOCKS = frozenset({"BEGIN SQL", "BEGIN BATCH"})
91
+ _SQL_BODY_BLOCK_CLOSES = frozenset({"END SQL", "END BATCH"})
92
+
85
93
 
86
94
  # ---------------------------------------------------------------------------
87
95
  # Keyword parsing
@@ -488,6 +496,10 @@ def format_file(source: str, indent: int = 4, use_sql: bool = True, leading_comm
488
496
  # the accumulator — doing so would split a single statement into
489
497
  # fragments that sqlglot cannot parse.
490
498
  in_sql_statement = False
499
+ # True between BEGIN SQL/BATCH and END SQL/BATCH. Blank lines inside
500
+ # these blocks belong to the SQL accumulator so they re-emit at the
501
+ # block's indent depth, not flush-left in the output stream.
502
+ in_explicit_sql_block = False
491
503
 
492
504
  def flush_sql() -> None:
493
505
  nonlocal in_dollar_quote, in_sql_statement
@@ -520,12 +532,13 @@ def format_file(source: str, indent: int = 4, use_sql: bool = True, leading_comm
520
532
  m = METACOMMAND_RE.match(raw_line)
521
533
 
522
534
  if not stripped_line:
523
- if not in_dollar_quote and not in_sql_statement:
535
+ if not in_dollar_quote and not in_sql_statement and not in_explicit_sql_block:
524
536
  flush_sql()
525
537
  output.append("")
526
538
  else:
527
- # Mid-statement blank line stays in the accumulator and
528
- # will appear in the output when the block is formatted.
539
+ # Mid-statement OR mid-explicit-SQL-block blank line stays in
540
+ # the accumulator and will appear in the output at the block's
541
+ # indent depth when the SQL is formatted.
529
542
  sql_acc.append(raw_line)
530
543
 
531
544
  elif m:
@@ -536,6 +549,8 @@ def format_file(source: str, indent: int = 4, use_sql: bool = True, leading_comm
536
549
  if keyword in BLOCK_CLOSE:
537
550
  depth = max(0, depth - 1)
538
551
  output.append(format_metacommand(payload, depth, indent))
552
+ if keyword in _SQL_BODY_BLOCK_CLOSES:
553
+ in_explicit_sql_block = False
539
554
 
540
555
  elif keyword in PIVOT:
541
556
  depth = max(0, depth - 1)
@@ -547,7 +562,10 @@ def format_file(source: str, indent: int = 4, use_sql: bool = True, leading_comm
547
562
 
548
563
  elif keyword in BLOCK_OPEN:
549
564
  output.append(format_metacommand(payload, depth, indent))
550
- depth += 1
565
+ if not (keyword == "IF" and _IF_INLINE_RE.match(payload)):
566
+ depth += 1
567
+ if keyword in _SQL_BODY_BLOCKS:
568
+ in_explicit_sql_block = True
551
569
 
552
570
  else:
553
571
  output.append(format_metacommand(payload, depth, indent))
@@ -203,9 +203,19 @@ def _format_script_signature(name: str, param_defs: Any) -> str:
203
203
  return f"{name}({', '.join(parts)})"
204
204
 
205
205
 
206
- def _format_script_source(span: Any) -> str:
207
- """Return ``file:start-end`` from a SourceSpan."""
208
- filename = Path(span.file).name if span and span.file else "<unknown>"
206
+ def _format_script_source(span: Any, *, full_path: bool = False) -> str:
207
+ """Return ``file:start-end`` from a SourceSpan.
208
+
209
+ By default the filename is the basename, suitable for compact list-view
210
+ output. Pass ``full_path=True`` to retain the full source path (used by
211
+ detail views like ``SHOW SCRIPTS <name>`` and ``.scripts <name>``).
212
+ """
213
+ if not span or not span.file:
214
+ filename = "<unknown>"
215
+ elif full_path:
216
+ filename = span.file
217
+ else:
218
+ filename = Path(span.file).name
209
219
  if span and span.start_line is not None:
210
220
  if span.end_line is not None and span.end_line != span.start_line:
211
221
  return f"{filename}:{span.start_line}-{span.end_line}"
@@ -235,7 +245,7 @@ def x_show_scripts(**kwargs: Any) -> None:
235
245
  return
236
246
  block = scripts[script_name]
237
247
  sig = _format_script_signature(block.name, block.param_defs)
238
- src = _format_script_source(block.span)
248
+ src = _format_script_source(block.span, full_path=True)
239
249
  _state.output.write(f"Script: {sig}\n")
240
250
  _state.output.write(f"Source: {src}\n")
241
251
  if block.param_defs:
execsql/script/parser.py CHANGED
@@ -114,14 +114,48 @@ _EXEC_SCRIPT_RX = re.compile(
114
114
  re.I,
115
115
  )
116
116
 
117
+ # A parameter default value is either a double-quoted string, a single-quoted
118
+ # string (both may contain spaces, commas, and other special characters), or
119
+ # a bare run of non-whitespace characters. Unquoted values must not begin
120
+ # with a quote — that catches mismatched / unterminated quoted values
121
+ # (e.g. ``name="value``) instead of silently treating them as literals.
122
+ _PARAM_VALUE = r'(?:"[^"]*"|\'[^\']*\'|[^\s\'"]\S*)'
123
+
117
124
  _WITH_PARAMS_RX = re.compile(
118
125
  r"(?:\s+WITH)?(?:\s+PARAM(?:ETER)?S)?\s*\(\s*(?P<params>"
119
- r"\w+(?:\s*=\s*\S+)?(?:\s*,\s*\w+(?:\s*=\s*\S+)?)*"
126
+ rf"\w+(?:\s*=\s*{_PARAM_VALUE})?(?:\s*,\s*\w+(?:\s*=\s*{_PARAM_VALUE})?)*"
120
127
  r")\s*\)\s*$",
121
128
  re.I,
122
129
  )
123
130
 
124
- _PARAM_TOKEN_RX = re.compile(r"(\w+)(?:\s*=\s*(\S+))?")
131
+ _PARAM_TOKEN_RX = re.compile(rf"(\w+)(?:\s*=\s*({_PARAM_VALUE}))?\s*\Z")
132
+
133
+
134
+ def _split_param_tokens(params_str: str) -> list[str]:
135
+ """Split a parameter list on commas, respecting quoted values.
136
+
137
+ Quoted segments (``"..."`` or ``'...'``) are kept intact so that commas
138
+ inside quotes do not split the token. Each returned token is stripped
139
+ of surrounding whitespace.
140
+ """
141
+ tokens: list[str] = []
142
+ current: list[str] = []
143
+ in_quote: str | None = None
144
+ for ch in params_str:
145
+ if in_quote is not None:
146
+ current.append(ch)
147
+ if ch == in_quote:
148
+ in_quote = None
149
+ elif ch in ('"', "'"):
150
+ current.append(ch)
151
+ in_quote = ch
152
+ elif ch == ",":
153
+ tokens.append("".join(current))
154
+ current = []
155
+ else:
156
+ current.append(ch)
157
+ tokens.append("".join(current))
158
+ return [t.strip() for t in tokens]
125
159
 
126
160
 
127
161
  def _parse_param_defs(
@@ -129,16 +163,21 @@ def _parse_param_defs(
129
163
  lineno: int,
130
164
  source: str,
131
165
  ) -> list[ParamDef]:
132
- """Parse ``'a, b, c=100, d=false'`` into a list of :class:`ParamDef`.
166
+ """Parse ``'a, b, c=100, d="hello world"'`` into a list of :class:`ParamDef`.
167
+
168
+ Defaults may be unquoted (``key=value``), double-quoted (``key="v a l"``),
169
+ or single-quoted (``key='v,a,l'``). Surrounding quotes are stripped so
170
+ that ``ParamDef.default`` always holds the resolved value, mirroring the
171
+ quote-handling done at the call site for passed arguments.
133
172
 
134
173
  Required parameters (no default) must precede optional parameters
135
174
  (with default). Raises :class:`ErrInfo` if ordering is violated.
136
175
  """
137
- tokens = [t.strip() for t in params_str.split(",")]
176
+ tokens = _split_param_tokens(params_str)
138
177
  defs: list[ParamDef] = []
139
178
  seen_optional: str | None = None # name of first optional param
140
179
  for token in tokens:
141
- m = _PARAM_TOKEN_RX.match(token.strip())
180
+ m = _PARAM_TOKEN_RX.match(token)
142
181
  if not m:
143
182
  raise ErrInfo(
144
183
  type="cmd",
@@ -146,6 +185,7 @@ def _parse_param_defs(
146
185
  )
147
186
  name, default = m.group(1), m.group(2)
148
187
  if default is not None:
188
+ default = _strip_quotes(default)
149
189
  if seen_optional is None:
150
190
  seen_optional = name
151
191
  elif seen_optional is not None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: execsql2
3
- Version: 2.16.16
3
+ Version: 2.16.18
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
@@ -3,7 +3,7 @@ execsql/__main__.py,sha256=HdbK-SAhyUmfB6xINY5AzxdMSxGzWSGEG_2dv42Jn64,315
3
3
  execsql/api.py,sha256=6Jw5p89DYZXyoDFGk5mE4UyVUGLok5DUdhikpUy39RE,19928
4
4
  execsql/config.py,sha256=nJwcFiDaEnvqLX4hBjYkH7WW8HmMq5F3sLoqIFJCayU,29614
5
5
  execsql/exceptions.py,sha256=j8hykBiof9H3Za9hwLIbDcVB2Xn65ODXXplp1jkvdgM,8453
6
- execsql/format.py,sha256=Nvkvi1nWw1iTcLDPAlXwdnZfifJib2_kszojMSdZtBA,24365
6
+ execsql/format.py,sha256=el_gQyMbj4VllToGEcU_61PtxUFotD1hXjrVzEhackM,25507
7
7
  execsql/models.py,sha256=kCTUQg9-vReM6WNFfB_ZrEppuOW5u1uMBQThSkfPC0o,13264
8
8
  execsql/parser.py,sha256=P3ea8k7T_XLMrbhpFNZXwytdShrY302MKnhosqza1lo,15493
9
9
  execsql/plugins.py,sha256=2voLwT6eFap6BCBoZYndNNC_bMEJO1f_aP6xQTVXwYI,12815
@@ -31,7 +31,7 @@ execsql/db/postgres.py,sha256=-GpaA9fi6_vdIDTGyRGxNRaPYAAkEB_aCb-EyLFShsM,21120
31
31
  execsql/db/sqlite.py,sha256=n44ldZ-afQFSnUuYJ1phcvWFnxp3SwgrD2YQcyr7zLM,10664
32
32
  execsql/db/sqlserver.py,sha256=d8PwfNumt-Spit_0llafqQ900suv3CZMbrRsHLU1iB4,7683
33
33
  execsql/debug/__init__.py,sha256=j6EGUR0dHzUhWN1mHHtf1-Lhjq3Sb1V-vmnq2Ztgj1M,178
34
- execsql/debug/repl.py,sha256=TlIw6XrxwP3QUxuOaQZKp9vbJI55kEfiMtRNMxQRZo8,20747
34
+ execsql/debug/repl.py,sha256=snR_ErOOXyWBHeGdE_PaP8dwnysxaue5T-C6mGNFgeI,20763
35
35
  execsql/exporters/__init__.py,sha256=-Cnji-OgodJV8ftcDcOyTof0kQMy9J5kKVC8GVFpc3o,670
36
36
  execsql/exporters/base.py,sha256=Uhq0PBz8N_pJ7WlIN9225wY-HyxfzWSb9YabHXicBA8,6387
37
37
  execsql/exporters/delimited.py,sha256=Po9RV4UwBLOuRZmPFJk5CErpFvTdLCy--nFJJffZgxM,32383
@@ -71,7 +71,7 @@ execsql/metacommands/conditions.py,sha256=B6fBumkqoPO4wcQbw_ypYITaSnzPemAA1g5GrN
71
71
  execsql/metacommands/connect.py,sha256=Wnlp5PeeaNDaVlaWjCetvarTgQIwIeMPYe8cyslPYeA,14969
72
72
  execsql/metacommands/control.py,sha256=PlTAq34OkcmnOsPm3bZxF4mg1MaNBpENa8wzIKVEY10,8302
73
73
  execsql/metacommands/data.py,sha256=tRQBGTAuW-eJ2tBNWaoZI9OjTyNNyHJISo7gOdL-sm8,11370
74
- execsql/metacommands/debug.py,sha256=bFEQhNnKjIJHfc7FuZXIhUwWA-D8bMX7b3Anm5BWJT0,12051
74
+ execsql/metacommands/debug.py,sha256=aTTI5yg7JTUYWBDve8QeLHtufMPnaWg8XG8M-rKwtw4,12415
75
75
  execsql/metacommands/dispatch.py,sha256=DvpgpkX1yMWnJrVW8ir_o1xKgfZgXzlTt6IwP0Lwoek,87441
76
76
  execsql/metacommands/io.py,sha256=vlGBje5sgnqeilooMdhJDgSRIhysHy5_7LrKtik9Xjs,3011
77
77
  execsql/metacommands/io_export.py,sha256=iX4L3lpZGT2P5ca2C3XJ3MYxXJ_loC7nWmfKcWv4UGQ,13379
@@ -87,7 +87,7 @@ execsql/script/ast.py,sha256=AviMXseSpZtaPpJtJEs3olaXuk23kN_dU5raHbymy6s,20266
87
87
  execsql/script/control.py,sha256=s-1eZdGARM6H1FwZ6VDdO_f50j7bvvRtTHesfUm9tbc,6144
88
88
  execsql/script/engine.py,sha256=EhuVBniOrFkzAW4I3NIZLt3INHTZJvlYoF7B99rZBLI,29391
89
89
  execsql/script/executor.py,sha256=RclV-uG33yEWs8p_sj9KbW5IpHbmkRyG2DO5L4UJK50,37678
90
- execsql/script/parser.py,sha256=a8ufVvyK6X-E6PbTiOpETscyi38XbiTypkgP8COHrQg,32171
90
+ execsql/script/parser.py,sha256=-7v6yJIYgTHyYzE57fy-xEoLy--NWFnQsbAvGh17cqY,33825
91
91
  execsql/script/variables.py,sha256=ZSBGQUsoii6w3dLDVY9xxoPIV6wY0sAV_BNIQ6pgQAE,14328
92
92
  execsql/utils/__init__.py,sha256=0uR6JwVJQRX3vceByNBduCAf5dd5assKjeqJUWvpZoA,278
93
93
  execsql/utils/auth.py,sha256=onXzNkNZQZxGC5w7eey06sjvAIAX_Lf9g7nUJtcsel0,7009
@@ -101,24 +101,24 @@ execsql/utils/numeric.py,sha256=xh02ANSRk3nUpQ-rtm66ILoMqoi7HtzCoRMIOT9U8QI,1570
101
101
  execsql/utils/regex.py,sha256=diEzTZqU_HHwVMadPAvN1Vgzhl7I03eVaEFGCXyGGL8,3770
102
102
  execsql/utils/strings.py,sha256=5Dvzrk-9SIw2lpxXZQkiJbNyo1sy7iXXAtSULlZ0KG8,8488
103
103
  execsql/utils/timer.py,sha256=eDYf5VzCNFk7oo90InJucUm3XcBdhYMogjZMqeg9xzc,1899
104
- execsql2-2.16.16.data/data/execsql2_extras/README.md,sha256=sxwVyU0ZahCfANv56LahkyuM505kFjrMhe-1SvWE69E,4845
105
- execsql2-2.16.16.data/data/execsql2_extras/config_settings.sqlite,sha256=aY5cxR7Q7J6zJ4bC9lu5mHUrhy211Cq3MNKPQVCt02E,20480
106
- execsql2-2.16.16.data/data/execsql2_extras/example_config_prompt.sql,sha256=SY3Jxn1qcVm4kPW9xmmTfknHfvURXmeEYTbRjYrjGSw,7487
107
- execsql2-2.16.16.data/data/execsql2_extras/execsql.conf,sha256=1a2g2Vga7s128wcu3ftIFRkHlKKtuvkuOHSD1XuNT7o,9404
108
- execsql2-2.16.16.data/data/execsql2_extras/make_config_db.sql,sha256=WwyC6dK-Eh5CAVppiBCDHqiI1_wEI9U95Ytpr4lsZkg,8726
109
- execsql2-2.16.16.data/data/execsql2_extras/md_compare.sql,sha256=B8Wd7LZ0vnMY2qvA139JIEBkPObgRH2i5xj6PejTQt8,24092
110
- execsql2-2.16.16.data/data/execsql2_extras/md_glossary.sql,sha256=DJRHcU5NbFpxTTX-IwH3yRlsboj1q6BBGrUAHKn4Cuo,10796
111
- execsql2-2.16.16.data/data/execsql2_extras/md_upsert.sql,sha256=v_7GbWh_N1mBTmw3gvTrkagOVp2q0KmXvM8hE-DlFxY,112524
112
- execsql2-2.16.16.data/data/execsql2_extras/pg_compare.sql,sha256=9dWa8hnfy5dVJI-z2iGpd9JzQmI4j2ziMlEdpnr66ro,24352
113
- execsql2-2.16.16.data/data/execsql2_extras/pg_glossary.sql,sha256=pKjIIDsROAgJq2H-1qNEcRMAWManivcZ_AEVHzUUlic,9908
114
- execsql2-2.16.16.data/data/execsql2_extras/pg_upsert.sql,sha256=k7AFiGTLBy3nf-qO5QIaZrEYTAKvdxxU3JDLx9jqkzs,108315
115
- execsql2-2.16.16.data/data/execsql2_extras/script_template.sql,sha256=1Estacb_vm1FgK41k_G9nuduP1yiA-fQ1Kn4Z4mv5Ao,11153
116
- execsql2-2.16.16.data/data/execsql2_extras/ss_compare.sql,sha256=TsVxWm3cEpR5-EiMYXNhtaY0arSNeKZhsJdHdLA7xeI,24833
117
- execsql2-2.16.16.data/data/execsql2_extras/ss_glossary.sql,sha256=cLM7nN8JOIu9ZVP9oY9qdSK3hrnWJiDcX6nZmQQbQWI,13065
118
- execsql2-2.16.16.data/data/execsql2_extras/ss_upsert.sql,sha256=BCqmBykXBF-BpCgOFeG1qhf2XfScKsxPD17wd1hYfHw,120647
119
- execsql2-2.16.16.dist-info/METADATA,sha256=5oMr4vnGosHd4GUlwVVbH6h2zM88z2NvIsrXUlS0-l0,20921
120
- execsql2-2.16.16.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
121
- execsql2-2.16.16.dist-info/entry_points.txt,sha256=sUOxkM-dN1eBGGpSpDLsAaE0yNXYQKWZAfxPOlMkQyk,90
122
- execsql2-2.16.16.dist-info/licenses/LICENSE.txt,sha256=LBdhuxejF8_bLCHZ2kWfmDXpDGUu914Gbd6_3JjCRe0,676
123
- execsql2-2.16.16.dist-info/licenses/NOTICE,sha256=sqVrM73Ys9zfvWC_P797lHfTnoPW_ETeBSrUTFaob0A,339
124
- execsql2-2.16.16.dist-info/RECORD,,
104
+ execsql2-2.16.18.data/data/execsql2_extras/README.md,sha256=sxwVyU0ZahCfANv56LahkyuM505kFjrMhe-1SvWE69E,4845
105
+ execsql2-2.16.18.data/data/execsql2_extras/config_settings.sqlite,sha256=aY5cxR7Q7J6zJ4bC9lu5mHUrhy211Cq3MNKPQVCt02E,20480
106
+ execsql2-2.16.18.data/data/execsql2_extras/example_config_prompt.sql,sha256=SY3Jxn1qcVm4kPW9xmmTfknHfvURXmeEYTbRjYrjGSw,7487
107
+ execsql2-2.16.18.data/data/execsql2_extras/execsql.conf,sha256=1a2g2Vga7s128wcu3ftIFRkHlKKtuvkuOHSD1XuNT7o,9404
108
+ execsql2-2.16.18.data/data/execsql2_extras/make_config_db.sql,sha256=WwyC6dK-Eh5CAVppiBCDHqiI1_wEI9U95Ytpr4lsZkg,8726
109
+ execsql2-2.16.18.data/data/execsql2_extras/md_compare.sql,sha256=B8Wd7LZ0vnMY2qvA139JIEBkPObgRH2i5xj6PejTQt8,24092
110
+ execsql2-2.16.18.data/data/execsql2_extras/md_glossary.sql,sha256=DJRHcU5NbFpxTTX-IwH3yRlsboj1q6BBGrUAHKn4Cuo,10796
111
+ execsql2-2.16.18.data/data/execsql2_extras/md_upsert.sql,sha256=v_7GbWh_N1mBTmw3gvTrkagOVp2q0KmXvM8hE-DlFxY,112524
112
+ execsql2-2.16.18.data/data/execsql2_extras/pg_compare.sql,sha256=9dWa8hnfy5dVJI-z2iGpd9JzQmI4j2ziMlEdpnr66ro,24352
113
+ execsql2-2.16.18.data/data/execsql2_extras/pg_glossary.sql,sha256=pKjIIDsROAgJq2H-1qNEcRMAWManivcZ_AEVHzUUlic,9908
114
+ execsql2-2.16.18.data/data/execsql2_extras/pg_upsert.sql,sha256=k7AFiGTLBy3nf-qO5QIaZrEYTAKvdxxU3JDLx9jqkzs,108315
115
+ execsql2-2.16.18.data/data/execsql2_extras/script_template.sql,sha256=1Estacb_vm1FgK41k_G9nuduP1yiA-fQ1Kn4Z4mv5Ao,11153
116
+ execsql2-2.16.18.data/data/execsql2_extras/ss_compare.sql,sha256=TsVxWm3cEpR5-EiMYXNhtaY0arSNeKZhsJdHdLA7xeI,24833
117
+ execsql2-2.16.18.data/data/execsql2_extras/ss_glossary.sql,sha256=cLM7nN8JOIu9ZVP9oY9qdSK3hrnWJiDcX6nZmQQbQWI,13065
118
+ execsql2-2.16.18.data/data/execsql2_extras/ss_upsert.sql,sha256=BCqmBykXBF-BpCgOFeG1qhf2XfScKsxPD17wd1hYfHw,120647
119
+ execsql2-2.16.18.dist-info/METADATA,sha256=hPLRDAvfoHEorELirzBdvd7voDbrO7zg3ULOymxvSX0,20921
120
+ execsql2-2.16.18.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
121
+ execsql2-2.16.18.dist-info/entry_points.txt,sha256=sUOxkM-dN1eBGGpSpDLsAaE0yNXYQKWZAfxPOlMkQyk,90
122
+ execsql2-2.16.18.dist-info/licenses/LICENSE.txt,sha256=LBdhuxejF8_bLCHZ2kWfmDXpDGUu914Gbd6_3JjCRe0,676
123
+ execsql2-2.16.18.dist-info/licenses/NOTICE,sha256=sqVrM73Ys9zfvWC_P797lHfTnoPW_ETeBSrUTFaob0A,339
124
+ execsql2-2.16.18.dist-info/RECORD,,