execsql2 2.14.1__py3-none-any.whl → 2.15.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. execsql/metacommands/upsert.py +125 -17
  2. execsql/utils/gui.py +2 -2
  3. {execsql2-2.14.1.dist-info → execsql2-2.15.0.dist-info}/METADATA +3 -3
  4. {execsql2-2.14.1.dist-info → execsql2-2.15.0.dist-info}/RECORD +23 -23
  5. {execsql2-2.14.1.data → execsql2-2.15.0.data}/data/execsql2_extras/README.md +0 -0
  6. {execsql2-2.14.1.data → execsql2-2.15.0.data}/data/execsql2_extras/config_settings.sqlite +0 -0
  7. {execsql2-2.14.1.data → execsql2-2.15.0.data}/data/execsql2_extras/example_config_prompt.sql +0 -0
  8. {execsql2-2.14.1.data → execsql2-2.15.0.data}/data/execsql2_extras/execsql.conf +0 -0
  9. {execsql2-2.14.1.data → execsql2-2.15.0.data}/data/execsql2_extras/make_config_db.sql +0 -0
  10. {execsql2-2.14.1.data → execsql2-2.15.0.data}/data/execsql2_extras/md_compare.sql +0 -0
  11. {execsql2-2.14.1.data → execsql2-2.15.0.data}/data/execsql2_extras/md_glossary.sql +0 -0
  12. {execsql2-2.14.1.data → execsql2-2.15.0.data}/data/execsql2_extras/md_upsert.sql +0 -0
  13. {execsql2-2.14.1.data → execsql2-2.15.0.data}/data/execsql2_extras/pg_compare.sql +0 -0
  14. {execsql2-2.14.1.data → execsql2-2.15.0.data}/data/execsql2_extras/pg_glossary.sql +0 -0
  15. {execsql2-2.14.1.data → execsql2-2.15.0.data}/data/execsql2_extras/pg_upsert.sql +0 -0
  16. {execsql2-2.14.1.data → execsql2-2.15.0.data}/data/execsql2_extras/script_template.sql +0 -0
  17. {execsql2-2.14.1.data → execsql2-2.15.0.data}/data/execsql2_extras/ss_compare.sql +0 -0
  18. {execsql2-2.14.1.data → execsql2-2.15.0.data}/data/execsql2_extras/ss_glossary.sql +0 -0
  19. {execsql2-2.14.1.data → execsql2-2.15.0.data}/data/execsql2_extras/ss_upsert.sql +0 -0
  20. {execsql2-2.14.1.dist-info → execsql2-2.15.0.dist-info}/WHEEL +0 -0
  21. {execsql2-2.14.1.dist-info → execsql2-2.15.0.dist-info}/entry_points.txt +0 -0
  22. {execsql2-2.14.1.dist-info → execsql2-2.15.0.dist-info}/licenses/LICENSE.txt +0 -0
  23. {execsql2-2.14.1.dist-info → execsql2-2.15.0.dist-info}/licenses/NOTICE +0 -0
@@ -26,11 +26,11 @@ from execsql.utils.errors import exception_desc
26
26
 
27
27
  _KW_METHOD = re.compile(r"\bMETHOD\s+(upsert|update|insert)\b", re.IGNORECASE)
28
28
  _KW_EXCLUDE = re.compile(
29
- r"\bEXCLUDE\s+([\w\s,]+?)(?=\s+(?:METHOD|COMMIT|INTERACTIVE|COMPACT|EXCLUDE_NULL|LOGFILE|CLEANUP)\b|\s*$)",
29
+ r"\bEXCLUDE\s+([\w\s,]+?)(?=\s+(?:METHOD|COMMIT|INTERACTIVE|COMPACT|EXCLUDE_NULL|LOGFILE|CLEANUP|EXPORT_FAILURES|EXPORT_FORMAT|EXPORT_MAX_ROWS)\b|\s*$)",
30
30
  re.IGNORECASE,
31
31
  )
32
32
  _KW_EXCLUDE_NULL = re.compile(
33
- r"\bEXCLUDE_NULL\s+([\w\s,]+?)(?=\s+(?:METHOD|COMMIT|INTERACTIVE|COMPACT|EXCLUDE|LOGFILE|CLEANUP)\b|\s*$)",
33
+ r"\bEXCLUDE_NULL\s+([\w\s,]+?)(?=\s+(?:METHOD|COMMIT|INTERACTIVE|COMPACT|EXCLUDE|LOGFILE|CLEANUP|EXPORT_FAILURES|EXPORT_FORMAT|EXPORT_MAX_ROWS)\b|\s*$)",
34
34
  re.IGNORECASE,
35
35
  )
36
36
  _KW_COMMIT = re.compile(r"\bCOMMIT\b", re.IGNORECASE)
@@ -38,13 +38,21 @@ _KW_INTERACTIVE = re.compile(r"\bINTERACTIVE\b", re.IGNORECASE)
38
38
  _KW_COMPACT = re.compile(r"\bCOMPACT\b", re.IGNORECASE)
39
39
  _KW_CLEANUP = re.compile(r"\bCLEANUP\b", re.IGNORECASE)
40
40
  _KW_LOGFILE = re.compile(r"""\bLOGFILE\s+(?:"([^"]+)"|'([^']+)'|(\S+))""", re.IGNORECASE)
41
+ _KW_EXPORT_FAILURES = re.compile(
42
+ r"""\bEXPORT_FAILURES\s+(?:"([^"]+)"|'([^']+)'|(\S+))""",
43
+ re.IGNORECASE,
44
+ )
45
+ _KW_EXPORT_FORMAT = re.compile(r"\bEXPORT_FORMAT\s+(\S+)", re.IGNORECASE)
46
+ _KW_EXPORT_MAX_ROWS = re.compile(r"\bEXPORT_MAX_ROWS\s+(\S+)", re.IGNORECASE)
41
47
 
42
48
  # All recognized keywords — used to split table names from options.
43
49
  _ALL_KEYWORDS = re.compile(
44
- r"\b(?:METHOD|COMMIT|INTERACTIVE|COMPACT|EXCLUDE_NULL|EXCLUDE|LOGFILE|CLEANUP)\b",
50
+ r"\b(?:METHOD|COMMIT|INTERACTIVE|COMPACT|EXCLUDE_NULL|EXCLUDE|LOGFILE|CLEANUP|EXPORT_FAILURES|EXPORT_FORMAT|EXPORT_MAX_ROWS)\b",
45
51
  re.IGNORECASE,
46
52
  )
47
53
 
54
+ _VALID_EXPORT_FORMATS = ("csv", "json", "xlsx")
55
+
48
56
 
49
57
  def _parse_tables_and_options(tail: str) -> dict[str, Any]:
50
58
  """Parse the trailing text after ``TABLES`` into table names and options.
@@ -90,6 +98,40 @@ def _parse_tables_and_options(tail: str) -> dict[str, Any]:
90
98
  if m:
91
99
  logfile = m.group(1) or m.group(2) or m.group(3)
92
100
 
101
+ export_failures: str | None = None
102
+ m = _KW_EXPORT_FAILURES.search(opts_part)
103
+ if m:
104
+ export_failures = m.group(1) or m.group(2) or m.group(3)
105
+
106
+ export_format = "csv"
107
+ m = _KW_EXPORT_FORMAT.search(opts_part)
108
+ if m:
109
+ fmt = m.group(1).lower()
110
+ if fmt not in _VALID_EXPORT_FORMATS:
111
+ raise ErrInfo(
112
+ "cmd",
113
+ other_msg=(
114
+ f"PG_UPSERT: unsupported EXPORT_FORMAT {m.group(1)!r}. "
115
+ f"Supported: {', '.join(_VALID_EXPORT_FORMATS)}"
116
+ ),
117
+ )
118
+ export_format = fmt
119
+
120
+ export_max_rows = 1000
121
+ m = _KW_EXPORT_MAX_ROWS.search(opts_part)
122
+ if m:
123
+ raw = m.group(1)
124
+ try:
125
+ val = int(raw)
126
+ if val <= 0:
127
+ raise ValueError
128
+ except ValueError as exc:
129
+ raise ErrInfo(
130
+ "cmd",
131
+ other_msg=(f"PG_UPSERT: EXPORT_MAX_ROWS must be a positive integer, got {raw!r}"),
132
+ ) from exc
133
+ export_max_rows = val
134
+
93
135
  return {
94
136
  "tables": tables,
95
137
  "method": method,
@@ -100,6 +142,9 @@ def _parse_tables_and_options(tail: str) -> dict[str, Any]:
100
142
  "exclude_null_check_cols": exclude_null,
101
143
  "logfile": logfile,
102
144
  "cleanup": bool(_KW_CLEANUP.search(opts_part)),
145
+ "export_failures": export_failures,
146
+ "export_format": export_format,
147
+ "export_max_rows": export_max_rows,
103
148
  }
104
149
 
105
150
 
@@ -157,6 +202,9 @@ def _set_subvars(result: Any) -> None:
157
202
  sv("$PG_UPSERT_STARTED_AT", result.started_at)
158
203
  sv("$PG_UPSERT_FINISHED_AT", result.finished_at)
159
204
  sv("$PG_UPSERT_RESULT_JSON", json.dumps(result.to_dict(), separators=(",", ":")))
205
+ # Default export path subvar to empty; _export_failures_if_requested
206
+ # will overwrite it with the actual path if an export was produced.
207
+ sv("$PG_UPSERT_EXPORT_PATH", "")
160
208
 
161
209
 
162
210
  def _qa_failure_msg(result: Any) -> str:
@@ -241,20 +289,26 @@ def _create_pgupsert(
241
289
  if _state.conf:
242
290
  ui_mode = _state.conf.gui_framework
243
291
 
244
- ups = PgUpsert(
245
- conn=db.conn,
246
- staging_schema=staging_schema,
247
- base_schema=base_schema,
248
- tables=opts["tables"],
249
- do_commit=opts["commit"],
250
- interactive=opts["interactive"],
251
- compact=opts["compact"],
252
- upsert_method=opts["method"],
253
- exclude_cols=opts["exclude_cols"],
254
- exclude_null_check_cols=opts["exclude_null_check_cols"],
255
- ui_mode=ui_mode,
256
- callback=_make_callback(),
257
- )
292
+ kwargs: dict[str, Any] = {
293
+ "conn": db.conn,
294
+ "staging_schema": staging_schema,
295
+ "base_schema": base_schema,
296
+ "tables": opts["tables"],
297
+ "do_commit": opts["commit"],
298
+ "interactive": opts["interactive"],
299
+ "compact": opts["compact"],
300
+ "upsert_method": opts["method"],
301
+ "exclude_cols": opts["exclude_cols"],
302
+ "exclude_null_check_cols": opts["exclude_null_check_cols"],
303
+ "ui_mode": ui_mode,
304
+ "callback": _make_callback(),
305
+ }
306
+ # Only pass fix-sheet capture args when an export was requested, so the
307
+ # metacommand stays compatible with any pg-upsert build that lacks them.
308
+ if opts.get("export_failures"):
309
+ kwargs["capture_detail_rows"] = True
310
+ kwargs["max_export_rows"] = opts.get("export_max_rows", 1000)
311
+ ups = PgUpsert(**kwargs)
258
312
  return ups
259
313
 
260
314
 
@@ -328,6 +382,57 @@ def _run_with_autocommit_guard(db: Any, fn: Any) -> Any:
328
382
  db.autocommit_on()
329
383
 
330
384
 
385
+ def _export_failures_if_requested(
386
+ result: Any,
387
+ opts: dict[str, Any],
388
+ metacommandline: str | None,
389
+ ) -> None:
390
+ """Export a QA fix sheet if EXPORT_FAILURES was given in the metacommand.
391
+
392
+ Always called after ``_set_subvars(result)`` so ``$PG_UPSERT_EXPORT_PATH``
393
+ is initialized to empty first, then overwritten here on a successful
394
+ export. Called even when QA failed — that's the whole point of the
395
+ fix sheet.
396
+ """
397
+ path = opts.get("export_failures")
398
+ if not path:
399
+ return
400
+ fmt = opts["export_format"]
401
+ try:
402
+ exported = result.export_failures(path, fmt=fmt)
403
+ except Exception as exc:
404
+ raise ErrInfo(
405
+ "exception",
406
+ exception_msg=exception_desc(),
407
+ other_msg=(f"PG_UPSERT failed to export failure sheet to {path}"),
408
+ ) from exc
409
+ _state.subvars.add_substitution(
410
+ "$PG_UPSERT_EXPORT_PATH",
411
+ str(exported) if exported else "",
412
+ )
413
+ if exported:
414
+ msg = f"PG_UPSERT: exported QA failures to {exported} ({fmt})"
415
+ else:
416
+ msg = f"PG_UPSERT: no QA failures to export (EXPORT_FAILURES {path} skipped)"
417
+ _state.exec_log.log_user_msg(msg)
418
+ try:
419
+ _state.output.write(msg + "\n")
420
+ except Exception:
421
+ # Output sink may be unavailable in some contexts (e.g. tests);
422
+ # the log message above is sufficient in that case.
423
+ pass
424
+ # Tee to the LOGFILE keyword target if one was given, matching how the
425
+ # pg-upsert display output is routed there via _FileWriterHandler.
426
+ logfile = opts.get("logfile")
427
+ if logfile:
428
+ try:
429
+ from execsql.utils.fileio import filewriter_write
430
+
431
+ filewriter_write(logfile, msg + "\n")
432
+ except Exception:
433
+ pass
434
+
435
+
331
436
  def _handle_pg_upsert_errors(fn: Any, metacommandline: str | None) -> Any:
332
437
  """Run *fn*, translating pg-upsert exceptions to ErrInfo."""
333
438
  from pg_upsert import UserCancelledError
@@ -381,6 +486,7 @@ def x_pg_upsert(**kwargs: Any) -> None:
381
486
  _detach_log_handlers(loggers, handlers, prev_levels)
382
487
 
383
488
  _set_subvars(result)
489
+ _export_failures_if_requested(result, opts, metacommandline)
384
490
  if opts.get("cleanup"):
385
491
  ups.cleanup()
386
492
 
@@ -420,6 +526,7 @@ def x_pg_upsert_qa(**kwargs: Any) -> None:
420
526
 
421
527
  result = _build_result_from_qa_errors(ups)
422
528
  _set_subvars(result)
529
+ _export_failures_if_requested(result, opts, metacommandline)
423
530
  if opts.get("cleanup"):
424
531
  ups.cleanup()
425
532
 
@@ -462,6 +569,7 @@ def x_pg_upsert_check(**kwargs: Any) -> None:
462
569
 
463
570
  result = _build_result_from_qa_errors(ups)
464
571
  _set_subvars(result)
572
+ _export_failures_if_requested(result, opts, metacommandline)
465
573
  if opts.get("cleanup"):
466
574
  ups.cleanup()
467
575
 
execsql/utils/gui.py CHANGED
@@ -498,10 +498,10 @@ def gui_credentials(
498
498
  cmd:
499
499
  The originating metacommand line (for logging only).
500
500
  """
501
+ import getpass as _getpass
501
502
  import queue as _queue
502
503
 
503
504
  import execsql.state as _state
504
- from execsql.utils.auth import get_password
505
505
 
506
506
  gui_level = _state.conf.gui_level if _state.conf else 0
507
507
  if gui_level > 0 and _state.gui_manager_thread is not None and _state.gui_manager_thread.is_alive():
@@ -515,7 +515,7 @@ def gui_credentials(
515
515
  if message:
516
516
  print(message, file=sys.stderr)
517
517
  uname = input("Username: ")
518
- passwd = get_password(f"Password for {uname}: ")
518
+ passwd = _getpass.getpass(f"Password for {uname}: ")
519
519
 
520
520
  if username:
521
521
  _state.subvars.add_substitution(username, uname)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: execsql2
3
- Version: 2.14.1
3
+ Version: 2.15.0
4
4
  Summary: Runs a SQL script against a PostgreSQL, SQLite, MariaDB/MySQL, DuckDB, Firebird, MS-Access, MS-SQL-Server, or Oracle database, or an ODBC DSN. Provides metacommands to import and export data, copy data between databases, conditionally execute SQL and metacommands, and dynamically alter SQL and metacommands with substitution variables.
5
5
  Project-URL: Homepage, https://execsql2.readthedocs.io
6
6
  Project-URL: Repository, https://github.com/geocoug/execsql
@@ -51,7 +51,7 @@ Requires-Dist: keyring; extra == 'all'
51
51
  Requires-Dist: odfpy; extra == 'all'
52
52
  Requires-Dist: openpyxl; extra == 'all'
53
53
  Requires-Dist: oracledb; extra == 'all'
54
- Requires-Dist: pg-upsert>=1.20.0; extra == 'all'
54
+ Requires-Dist: pg-upsert>=1.21.0; extra == 'all'
55
55
  Requires-Dist: polars; extra == 'all'
56
56
  Requires-Dist: psycopg2-binary; extra == 'all'
57
57
  Requires-Dist: pymysql; extra == 'all'
@@ -109,7 +109,7 @@ Requires-Dist: oracledb; extra == 'oracle'
109
109
  Provides-Extra: postgres
110
110
  Requires-Dist: psycopg2-binary; extra == 'postgres'
111
111
  Provides-Extra: upsert
112
- Requires-Dist: pg-upsert>=1.20.0; extra == 'upsert'
112
+ Requires-Dist: pg-upsert>=1.21.0; extra == 'upsert'
113
113
  Description-Content-Type: text/markdown
114
114
 
115
115
  > [!NOTE]
@@ -77,7 +77,7 @@ execsql/metacommands/io_write.py,sha256=NpL2aYGfBpbqmPpYsqniYltYfd_SCA1EQz3_4qSd
77
77
  execsql/metacommands/prompt.py,sha256=E2e7q4pxbl_wEBrhco0B2gm5hO_HG3rNIF75PLdTgGg,36767
78
78
  execsql/metacommands/script_ext.py,sha256=TUgAldB2LSJAwZrCvDDi804hQ1d9BDQD2GDqHNPVOcM,2280
79
79
  execsql/metacommands/system.py,sha256=AeyxbMLZVOi2nThbHiZ2F_UAIrZ1r4kjI3G80TtnSD4,7385
80
- execsql/metacommands/upsert.py,sha256=P2935aQHDZPiVwnXi0fGQ7Guxrm-Sy_YunyuSqVSegI,15880
80
+ execsql/metacommands/upsert.py,sha256=W_5EEcp4QbDpq1LdS7Dz9eTa6do1D1a9aro2OCYZaMY,20032
81
81
  execsql/script/__init__.py,sha256=HbVQmQEVn4gBtzwy5_nlbDGuRnbWd4dI4nG-q1KyBxs,3498
82
82
  execsql/script/control.py,sha256=s-1eZdGARM6H1FwZ6VDdO_f50j7bvvRtTHesfUm9tbc,6144
83
83
  execsql/script/engine.py,sha256=6LYabzy1LI-_ISjYzTJos0BrLO62QF6FEKdqcN0YzK4,42995
@@ -88,30 +88,30 @@ execsql/utils/crypto.py,sha256=2OnBWwn9bCBGc1ZkyRv16TvhottoCNYtXqgbE3mG3Sg,2960
88
88
  execsql/utils/datetime.py,sha256=V_itd5vVvUPjT86P_z_hh4mlerMDGhDzI5MwPMDBaI4,7715
89
89
  execsql/utils/errors.py,sha256=YKhYD27-3timuZavc2vIrRIfHa71vzih-KVPsAKgvkU,8163
90
90
  execsql/utils/fileio.py,sha256=RGaMUe-e0xIw32OeprNJCezh0Jr9gQimQNqOXBEaJ2M,24338
91
- execsql/utils/gui.py,sha256=UFtwrXPNqNvZCJFCbumZ1aG2d9B-vyaJXIG83fDHteo,18409
91
+ execsql/utils/gui.py,sha256=eZeFJm8EaWnzeHIw_O-tn9hO8sxGjZRX_aUFDtGQp4w,18396
92
92
  execsql/utils/mail.py,sha256=Sd7vWj-dz3w0XDSFU9PM8gmy41pojk-Vsgbfven2DMk,5786
93
93
  execsql/utils/numeric.py,sha256=xh02ANSRk3nUpQ-rtm66ILoMqoi7HtzCoRMIOT9U8QI,1570
94
94
  execsql/utils/regex.py,sha256=diEzTZqU_HHwVMadPAvN1Vgzhl7I03eVaEFGCXyGGL8,3770
95
95
  execsql/utils/strings.py,sha256=5Dvzrk-9SIw2lpxXZQkiJbNyo1sy7iXXAtSULlZ0KG8,8488
96
96
  execsql/utils/timer.py,sha256=eDYf5VzCNFk7oo90InJucUm3XcBdhYMogjZMqeg9xzc,1899
97
- execsql2-2.14.1.data/data/execsql2_extras/README.md,sha256=sxwVyU0ZahCfANv56LahkyuM505kFjrMhe-1SvWE69E,4845
98
- execsql2-2.14.1.data/data/execsql2_extras/config_settings.sqlite,sha256=aY5cxR7Q7J6zJ4bC9lu5mHUrhy211Cq3MNKPQVCt02E,20480
99
- execsql2-2.14.1.data/data/execsql2_extras/example_config_prompt.sql,sha256=SY3Jxn1qcVm4kPW9xmmTfknHfvURXmeEYTbRjYrjGSw,7487
100
- execsql2-2.14.1.data/data/execsql2_extras/execsql.conf,sha256=_45iJ-KWZnB8uMW_gEg067MM5pmGJ-dVl7VbAZMunAE,9530
101
- execsql2-2.14.1.data/data/execsql2_extras/make_config_db.sql,sha256=WwyC6dK-Eh5CAVppiBCDHqiI1_wEI9U95Ytpr4lsZkg,8726
102
- execsql2-2.14.1.data/data/execsql2_extras/md_compare.sql,sha256=B8Wd7LZ0vnMY2qvA139JIEBkPObgRH2i5xj6PejTQt8,24092
103
- execsql2-2.14.1.data/data/execsql2_extras/md_glossary.sql,sha256=DJRHcU5NbFpxTTX-IwH3yRlsboj1q6BBGrUAHKn4Cuo,10796
104
- execsql2-2.14.1.data/data/execsql2_extras/md_upsert.sql,sha256=v_7GbWh_N1mBTmw3gvTrkagOVp2q0KmXvM8hE-DlFxY,112524
105
- execsql2-2.14.1.data/data/execsql2_extras/pg_compare.sql,sha256=9dWa8hnfy5dVJI-z2iGpd9JzQmI4j2ziMlEdpnr66ro,24352
106
- execsql2-2.14.1.data/data/execsql2_extras/pg_glossary.sql,sha256=pKjIIDsROAgJq2H-1qNEcRMAWManivcZ_AEVHzUUlic,9908
107
- execsql2-2.14.1.data/data/execsql2_extras/pg_upsert.sql,sha256=k7AFiGTLBy3nf-qO5QIaZrEYTAKvdxxU3JDLx9jqkzs,108315
108
- execsql2-2.14.1.data/data/execsql2_extras/script_template.sql,sha256=1Estacb_vm1FgK41k_G9nuduP1yiA-fQ1Kn4Z4mv5Ao,11153
109
- execsql2-2.14.1.data/data/execsql2_extras/ss_compare.sql,sha256=TsVxWm3cEpR5-EiMYXNhtaY0arSNeKZhsJdHdLA7xeI,24833
110
- execsql2-2.14.1.data/data/execsql2_extras/ss_glossary.sql,sha256=cLM7nN8JOIu9ZVP9oY9qdSK3hrnWJiDcX6nZmQQbQWI,13065
111
- execsql2-2.14.1.data/data/execsql2_extras/ss_upsert.sql,sha256=BCqmBykXBF-BpCgOFeG1qhf2XfScKsxPD17wd1hYfHw,120647
112
- execsql2-2.14.1.dist-info/METADATA,sha256=4H299Jz_SqnoHxbxOxobQ42CCgTOv0ynOarTVEQxMqo,17566
113
- execsql2-2.14.1.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
114
- execsql2-2.14.1.dist-info/entry_points.txt,sha256=sUOxkM-dN1eBGGpSpDLsAaE0yNXYQKWZAfxPOlMkQyk,90
115
- execsql2-2.14.1.dist-info/licenses/LICENSE.txt,sha256=LBdhuxejF8_bLCHZ2kWfmDXpDGUu914Gbd6_3JjCRe0,676
116
- execsql2-2.14.1.dist-info/licenses/NOTICE,sha256=sqVrM73Ys9zfvWC_P797lHfTnoPW_ETeBSrUTFaob0A,339
117
- execsql2-2.14.1.dist-info/RECORD,,
97
+ execsql2-2.15.0.data/data/execsql2_extras/README.md,sha256=sxwVyU0ZahCfANv56LahkyuM505kFjrMhe-1SvWE69E,4845
98
+ execsql2-2.15.0.data/data/execsql2_extras/config_settings.sqlite,sha256=aY5cxR7Q7J6zJ4bC9lu5mHUrhy211Cq3MNKPQVCt02E,20480
99
+ execsql2-2.15.0.data/data/execsql2_extras/example_config_prompt.sql,sha256=SY3Jxn1qcVm4kPW9xmmTfknHfvURXmeEYTbRjYrjGSw,7487
100
+ execsql2-2.15.0.data/data/execsql2_extras/execsql.conf,sha256=_45iJ-KWZnB8uMW_gEg067MM5pmGJ-dVl7VbAZMunAE,9530
101
+ execsql2-2.15.0.data/data/execsql2_extras/make_config_db.sql,sha256=WwyC6dK-Eh5CAVppiBCDHqiI1_wEI9U95Ytpr4lsZkg,8726
102
+ execsql2-2.15.0.data/data/execsql2_extras/md_compare.sql,sha256=B8Wd7LZ0vnMY2qvA139JIEBkPObgRH2i5xj6PejTQt8,24092
103
+ execsql2-2.15.0.data/data/execsql2_extras/md_glossary.sql,sha256=DJRHcU5NbFpxTTX-IwH3yRlsboj1q6BBGrUAHKn4Cuo,10796
104
+ execsql2-2.15.0.data/data/execsql2_extras/md_upsert.sql,sha256=v_7GbWh_N1mBTmw3gvTrkagOVp2q0KmXvM8hE-DlFxY,112524
105
+ execsql2-2.15.0.data/data/execsql2_extras/pg_compare.sql,sha256=9dWa8hnfy5dVJI-z2iGpd9JzQmI4j2ziMlEdpnr66ro,24352
106
+ execsql2-2.15.0.data/data/execsql2_extras/pg_glossary.sql,sha256=pKjIIDsROAgJq2H-1qNEcRMAWManivcZ_AEVHzUUlic,9908
107
+ execsql2-2.15.0.data/data/execsql2_extras/pg_upsert.sql,sha256=k7AFiGTLBy3nf-qO5QIaZrEYTAKvdxxU3JDLx9jqkzs,108315
108
+ execsql2-2.15.0.data/data/execsql2_extras/script_template.sql,sha256=1Estacb_vm1FgK41k_G9nuduP1yiA-fQ1Kn4Z4mv5Ao,11153
109
+ execsql2-2.15.0.data/data/execsql2_extras/ss_compare.sql,sha256=TsVxWm3cEpR5-EiMYXNhtaY0arSNeKZhsJdHdLA7xeI,24833
110
+ execsql2-2.15.0.data/data/execsql2_extras/ss_glossary.sql,sha256=cLM7nN8JOIu9ZVP9oY9qdSK3hrnWJiDcX6nZmQQbQWI,13065
111
+ execsql2-2.15.0.data/data/execsql2_extras/ss_upsert.sql,sha256=BCqmBykXBF-BpCgOFeG1qhf2XfScKsxPD17wd1hYfHw,120647
112
+ execsql2-2.15.0.dist-info/METADATA,sha256=4EszZ5kfmBXU3czXlw0mfPpf7vNyPYLd69_Y20nlzMw,17566
113
+ execsql2-2.15.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
114
+ execsql2-2.15.0.dist-info/entry_points.txt,sha256=sUOxkM-dN1eBGGpSpDLsAaE0yNXYQKWZAfxPOlMkQyk,90
115
+ execsql2-2.15.0.dist-info/licenses/LICENSE.txt,sha256=LBdhuxejF8_bLCHZ2kWfmDXpDGUu914Gbd6_3JjCRe0,676
116
+ execsql2-2.15.0.dist-info/licenses/NOTICE,sha256=sqVrM73Ys9zfvWC_P797lHfTnoPW_ETeBSrUTFaob0A,339
117
+ execsql2-2.15.0.dist-info/RECORD,,