execsql2 2.15.7__py3-none-any.whl → 2.15.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/metacommands/upsert.py +20 -10
- {execsql2-2.15.7.dist-info → execsql2-2.15.8.dist-info}/METADATA +3 -3
- {execsql2-2.15.7.dist-info → execsql2-2.15.8.dist-info}/RECORD +22 -22
- {execsql2-2.15.7.data → execsql2-2.15.8.data}/data/execsql2_extras/README.md +0 -0
- {execsql2-2.15.7.data → execsql2-2.15.8.data}/data/execsql2_extras/config_settings.sqlite +0 -0
- {execsql2-2.15.7.data → execsql2-2.15.8.data}/data/execsql2_extras/example_config_prompt.sql +0 -0
- {execsql2-2.15.7.data → execsql2-2.15.8.data}/data/execsql2_extras/execsql.conf +0 -0
- {execsql2-2.15.7.data → execsql2-2.15.8.data}/data/execsql2_extras/make_config_db.sql +0 -0
- {execsql2-2.15.7.data → execsql2-2.15.8.data}/data/execsql2_extras/md_compare.sql +0 -0
- {execsql2-2.15.7.data → execsql2-2.15.8.data}/data/execsql2_extras/md_glossary.sql +0 -0
- {execsql2-2.15.7.data → execsql2-2.15.8.data}/data/execsql2_extras/md_upsert.sql +0 -0
- {execsql2-2.15.7.data → execsql2-2.15.8.data}/data/execsql2_extras/pg_compare.sql +0 -0
- {execsql2-2.15.7.data → execsql2-2.15.8.data}/data/execsql2_extras/pg_glossary.sql +0 -0
- {execsql2-2.15.7.data → execsql2-2.15.8.data}/data/execsql2_extras/pg_upsert.sql +0 -0
- {execsql2-2.15.7.data → execsql2-2.15.8.data}/data/execsql2_extras/script_template.sql +0 -0
- {execsql2-2.15.7.data → execsql2-2.15.8.data}/data/execsql2_extras/ss_compare.sql +0 -0
- {execsql2-2.15.7.data → execsql2-2.15.8.data}/data/execsql2_extras/ss_glossary.sql +0 -0
- {execsql2-2.15.7.data → execsql2-2.15.8.data}/data/execsql2_extras/ss_upsert.sql +0 -0
- {execsql2-2.15.7.dist-info → execsql2-2.15.8.dist-info}/WHEEL +0 -0
- {execsql2-2.15.7.dist-info → execsql2-2.15.8.dist-info}/entry_points.txt +0 -0
- {execsql2-2.15.7.dist-info → execsql2-2.15.8.dist-info}/licenses/LICENSE.txt +0 -0
- {execsql2-2.15.7.dist-info → execsql2-2.15.8.dist-info}/licenses/NOTICE +0 -0
execsql/metacommands/upsert.py
CHANGED
|
@@ -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|EXPORT_FAILURES|EXPORT_FORMAT|EXPORT_MAX_ROWS)\b|\s*$)",
|
|
29
|
+
r"\bEXCLUDE\s+([\w\s,]+?)(?=\s+(?:METHOD|COMMIT|INTERACTIVE|COMPACT|EXCLUDE_NULL|LOGFILE|CLEANUP|EXPORT_FAILURES|EXPORT_FORMAT|EXPORT_MAX_ROWS|STRICT_COLUMNS)\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|EXPORT_FAILURES|EXPORT_FORMAT|EXPORT_MAX_ROWS)\b|\s*$)",
|
|
33
|
+
r"\bEXCLUDE_NULL\s+([\w\s,]+?)(?=\s+(?:METHOD|COMMIT|INTERACTIVE|COMPACT|EXCLUDE|LOGFILE|CLEANUP|EXPORT_FAILURES|EXPORT_FORMAT|EXPORT_MAX_ROWS|STRICT_COLUMNS)\b|\s*$)",
|
|
34
34
|
re.IGNORECASE,
|
|
35
35
|
)
|
|
36
36
|
_KW_COMMIT = re.compile(r"\bCOMMIT\b", re.IGNORECASE)
|
|
@@ -44,10 +44,11 @@ _KW_EXPORT_FAILURES = re.compile(
|
|
|
44
44
|
)
|
|
45
45
|
_KW_EXPORT_FORMAT = re.compile(r"\bEXPORT_FORMAT\s+(\S+)", re.IGNORECASE)
|
|
46
46
|
_KW_EXPORT_MAX_ROWS = re.compile(r"\bEXPORT_MAX_ROWS\s+(\S+)", re.IGNORECASE)
|
|
47
|
+
_KW_STRICT_COLUMNS = re.compile(r"\bSTRICT_COLUMNS\b", re.IGNORECASE)
|
|
47
48
|
|
|
48
49
|
# All recognized keywords — used to split table names from options.
|
|
49
50
|
_ALL_KEYWORDS = re.compile(
|
|
50
|
-
r"\b(?:METHOD|COMMIT|INTERACTIVE|COMPACT|EXCLUDE_NULL|EXCLUDE|LOGFILE|CLEANUP|EXPORT_FAILURES|EXPORT_FORMAT|EXPORT_MAX_ROWS)\b",
|
|
51
|
+
r"\b(?:METHOD|COMMIT|INTERACTIVE|COMPACT|EXCLUDE_NULL|EXCLUDE|LOGFILE|CLEANUP|EXPORT_FAILURES|EXPORT_FORMAT|EXPORT_MAX_ROWS|STRICT_COLUMNS)\b",
|
|
51
52
|
re.IGNORECASE,
|
|
52
53
|
)
|
|
53
54
|
|
|
@@ -145,6 +146,7 @@ def _parse_tables_and_options(tail: str) -> dict[str, Any]:
|
|
|
145
146
|
"export_failures": export_failures,
|
|
146
147
|
"export_format": export_format,
|
|
147
148
|
"export_max_rows": export_max_rows,
|
|
149
|
+
"strict_columns": bool(_KW_STRICT_COLUMNS.search(opts_part)),
|
|
148
150
|
}
|
|
149
151
|
|
|
150
152
|
|
|
@@ -191,6 +193,9 @@ def _set_subvars(result: Any) -> None:
|
|
|
191
193
|
sv("$PG_UPSERT_STARTED_AT", result.started_at)
|
|
192
194
|
sv("$PG_UPSERT_FINISHED_AT", result.finished_at)
|
|
193
195
|
sv("$PG_UPSERT_RESULT_JSON", json.dumps(result.to_dict(), separators=(",", ":")))
|
|
196
|
+
# Warnings: tables with WARNING-level findings (still qa_passed=True).
|
|
197
|
+
warned_tables = [t.table_name for t in result.tables if t.qa_warnings]
|
|
198
|
+
sv("$PG_UPSERT_QA_WARNINGS", ", ".join(warned_tables) if warned_tables else "")
|
|
194
199
|
# Default export path subvar to empty; _export_failures_if_requested
|
|
195
200
|
# will overwrite it with the actual path if an export was produced.
|
|
196
201
|
sv("$PG_UPSERT_EXPORT_PATH", "")
|
|
@@ -230,16 +235,20 @@ def _require_postgres(db: Any, metacommandline: str | None) -> None:
|
|
|
230
235
|
)
|
|
231
236
|
|
|
232
237
|
|
|
233
|
-
def
|
|
234
|
-
"""Build an UpsertResult from ``ups.
|
|
238
|
+
def _build_result_from_qa_findings(ups: Any) -> Any:
|
|
239
|
+
"""Build an UpsertResult from ``ups.qa_findings`` after a QA/CHECK run.
|
|
240
|
+
|
|
241
|
+
Uses ``qa_findings`` (all findings: errors + warnings) so that
|
|
242
|
+
``$PG_UPSERT_RESULT_JSON`` includes both severity levels.
|
|
243
|
+
"""
|
|
235
244
|
from pg_upsert.models import TableResult, UpsertResult
|
|
236
245
|
|
|
237
246
|
table_results: dict[str, Any] = {}
|
|
238
247
|
for table_name in ups.tables:
|
|
239
248
|
table_results[table_name] = TableResult(table_name=table_name)
|
|
240
|
-
for
|
|
241
|
-
if
|
|
242
|
-
table_results[
|
|
249
|
+
for finding in ups.qa_findings:
|
|
250
|
+
if finding.table in table_results:
|
|
251
|
+
table_results[finding.table]._qa_findings.append(finding)
|
|
243
252
|
return UpsertResult(
|
|
244
253
|
tables=list(table_results.values()),
|
|
245
254
|
committed=False,
|
|
@@ -289,6 +298,7 @@ def _create_pgupsert(
|
|
|
289
298
|
"upsert_method": opts["method"],
|
|
290
299
|
"exclude_cols": opts["exclude_cols"],
|
|
291
300
|
"exclude_null_check_cols": opts["exclude_null_check_cols"],
|
|
301
|
+
"strict_columns": opts.get("strict_columns", False),
|
|
292
302
|
"ui_mode": ui_mode,
|
|
293
303
|
"callback": _make_callback(),
|
|
294
304
|
}
|
|
@@ -508,7 +518,7 @@ def x_pg_upsert_qa(**kwargs: Any) -> None:
|
|
|
508
518
|
finally:
|
|
509
519
|
_detach_log_handlers(loggers, handlers, prev_levels)
|
|
510
520
|
|
|
511
|
-
result =
|
|
521
|
+
result = _build_result_from_qa_findings(ups)
|
|
512
522
|
_set_subvars(result)
|
|
513
523
|
_export_failures_if_requested(result, opts, metacommandline)
|
|
514
524
|
if opts.get("cleanup"):
|
|
@@ -551,7 +561,7 @@ def x_pg_upsert_check(**kwargs: Any) -> None:
|
|
|
551
561
|
finally:
|
|
552
562
|
_detach_log_handlers(loggers, handlers, prev_levels)
|
|
553
563
|
|
|
554
|
-
result =
|
|
564
|
+
result = _build_result_from_qa_findings(ups)
|
|
555
565
|
_set_subvars(result)
|
|
556
566
|
_export_failures_if_requested(result, opts, metacommandline)
|
|
557
567
|
if opts.get("cleanup"):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: execsql2
|
|
3
|
-
Version: 2.15.
|
|
3
|
+
Version: 2.15.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
|
|
@@ -52,7 +52,7 @@ Requires-Dist: keyring; extra == 'all'
|
|
|
52
52
|
Requires-Dist: odfpy; extra == 'all'
|
|
53
53
|
Requires-Dist: openpyxl; extra == 'all'
|
|
54
54
|
Requires-Dist: oracledb; extra == 'all'
|
|
55
|
-
Requires-Dist: pg-upsert>=1.
|
|
55
|
+
Requires-Dist: pg-upsert>=1.22.0; extra == 'all'
|
|
56
56
|
Requires-Dist: polars; extra == 'all'
|
|
57
57
|
Requires-Dist: psycopg2-binary; extra == 'all'
|
|
58
58
|
Requires-Dist: pymysql; extra == 'all'
|
|
@@ -117,7 +117,7 @@ Requires-Dist: oracledb; extra == 'oracle'
|
|
|
117
117
|
Provides-Extra: postgres
|
|
118
118
|
Requires-Dist: psycopg2-binary; extra == 'postgres'
|
|
119
119
|
Provides-Extra: upsert
|
|
120
|
-
Requires-Dist: pg-upsert>=1.
|
|
120
|
+
Requires-Dist: pg-upsert>=1.22.0; extra == 'upsert'
|
|
121
121
|
Description-Content-Type: text/markdown
|
|
122
122
|
|
|
123
123
|
> [!NOTE]
|
|
@@ -76,7 +76,7 @@ execsql/metacommands/io_write.py,sha256=NpL2aYGfBpbqmPpYsqniYltYfd_SCA1EQz3_4qSd
|
|
|
76
76
|
execsql/metacommands/prompt.py,sha256=E2e7q4pxbl_wEBrhco0B2gm5hO_HG3rNIF75PLdTgGg,36767
|
|
77
77
|
execsql/metacommands/script_ext.py,sha256=TUgAldB2LSJAwZrCvDDi804hQ1d9BDQD2GDqHNPVOcM,2280
|
|
78
78
|
execsql/metacommands/system.py,sha256=azRbv_P8l0t8BkDM9bmAUkhpnLSLHSCcmByqs-a3FxQ,7352
|
|
79
|
-
execsql/metacommands/upsert.py,sha256=
|
|
79
|
+
execsql/metacommands/upsert.py,sha256=DxtAhGpC6qD--sk932u40cbfQfvFlV-SXnV7WUTwk_8,19858
|
|
80
80
|
execsql/script/__init__.py,sha256=HbVQmQEVn4gBtzwy5_nlbDGuRnbWd4dI4nG-q1KyBxs,3498
|
|
81
81
|
execsql/script/control.py,sha256=s-1eZdGARM6H1FwZ6VDdO_f50j7bvvRtTHesfUm9tbc,6144
|
|
82
82
|
execsql/script/engine.py,sha256=HDlwm3_EqU6A4Z4O27dqQRvkpIACUuzYh3dZZAc8C98,43130
|
|
@@ -93,24 +93,24 @@ execsql/utils/numeric.py,sha256=xh02ANSRk3nUpQ-rtm66ILoMqoi7HtzCoRMIOT9U8QI,1570
|
|
|
93
93
|
execsql/utils/regex.py,sha256=diEzTZqU_HHwVMadPAvN1Vgzhl7I03eVaEFGCXyGGL8,3770
|
|
94
94
|
execsql/utils/strings.py,sha256=5Dvzrk-9SIw2lpxXZQkiJbNyo1sy7iXXAtSULlZ0KG8,8488
|
|
95
95
|
execsql/utils/timer.py,sha256=eDYf5VzCNFk7oo90InJucUm3XcBdhYMogjZMqeg9xzc,1899
|
|
96
|
-
execsql2-2.15.
|
|
97
|
-
execsql2-2.15.
|
|
98
|
-
execsql2-2.15.
|
|
99
|
-
execsql2-2.15.
|
|
100
|
-
execsql2-2.15.
|
|
101
|
-
execsql2-2.15.
|
|
102
|
-
execsql2-2.15.
|
|
103
|
-
execsql2-2.15.
|
|
104
|
-
execsql2-2.15.
|
|
105
|
-
execsql2-2.15.
|
|
106
|
-
execsql2-2.15.
|
|
107
|
-
execsql2-2.15.
|
|
108
|
-
execsql2-2.15.
|
|
109
|
-
execsql2-2.15.
|
|
110
|
-
execsql2-2.15.
|
|
111
|
-
execsql2-2.15.
|
|
112
|
-
execsql2-2.15.
|
|
113
|
-
execsql2-2.15.
|
|
114
|
-
execsql2-2.15.
|
|
115
|
-
execsql2-2.15.
|
|
116
|
-
execsql2-2.15.
|
|
96
|
+
execsql2-2.15.8.data/data/execsql2_extras/README.md,sha256=sxwVyU0ZahCfANv56LahkyuM505kFjrMhe-1SvWE69E,4845
|
|
97
|
+
execsql2-2.15.8.data/data/execsql2_extras/config_settings.sqlite,sha256=aY5cxR7Q7J6zJ4bC9lu5mHUrhy211Cq3MNKPQVCt02E,20480
|
|
98
|
+
execsql2-2.15.8.data/data/execsql2_extras/example_config_prompt.sql,sha256=SY3Jxn1qcVm4kPW9xmmTfknHfvURXmeEYTbRjYrjGSw,7487
|
|
99
|
+
execsql2-2.15.8.data/data/execsql2_extras/execsql.conf,sha256=_45iJ-KWZnB8uMW_gEg067MM5pmGJ-dVl7VbAZMunAE,9530
|
|
100
|
+
execsql2-2.15.8.data/data/execsql2_extras/make_config_db.sql,sha256=WwyC6dK-Eh5CAVppiBCDHqiI1_wEI9U95Ytpr4lsZkg,8726
|
|
101
|
+
execsql2-2.15.8.data/data/execsql2_extras/md_compare.sql,sha256=B8Wd7LZ0vnMY2qvA139JIEBkPObgRH2i5xj6PejTQt8,24092
|
|
102
|
+
execsql2-2.15.8.data/data/execsql2_extras/md_glossary.sql,sha256=DJRHcU5NbFpxTTX-IwH3yRlsboj1q6BBGrUAHKn4Cuo,10796
|
|
103
|
+
execsql2-2.15.8.data/data/execsql2_extras/md_upsert.sql,sha256=v_7GbWh_N1mBTmw3gvTrkagOVp2q0KmXvM8hE-DlFxY,112524
|
|
104
|
+
execsql2-2.15.8.data/data/execsql2_extras/pg_compare.sql,sha256=9dWa8hnfy5dVJI-z2iGpd9JzQmI4j2ziMlEdpnr66ro,24352
|
|
105
|
+
execsql2-2.15.8.data/data/execsql2_extras/pg_glossary.sql,sha256=pKjIIDsROAgJq2H-1qNEcRMAWManivcZ_AEVHzUUlic,9908
|
|
106
|
+
execsql2-2.15.8.data/data/execsql2_extras/pg_upsert.sql,sha256=k7AFiGTLBy3nf-qO5QIaZrEYTAKvdxxU3JDLx9jqkzs,108315
|
|
107
|
+
execsql2-2.15.8.data/data/execsql2_extras/script_template.sql,sha256=1Estacb_vm1FgK41k_G9nuduP1yiA-fQ1Kn4Z4mv5Ao,11153
|
|
108
|
+
execsql2-2.15.8.data/data/execsql2_extras/ss_compare.sql,sha256=TsVxWm3cEpR5-EiMYXNhtaY0arSNeKZhsJdHdLA7xeI,24833
|
|
109
|
+
execsql2-2.15.8.data/data/execsql2_extras/ss_glossary.sql,sha256=cLM7nN8JOIu9ZVP9oY9qdSK3hrnWJiDcX6nZmQQbQWI,13065
|
|
110
|
+
execsql2-2.15.8.data/data/execsql2_extras/ss_upsert.sql,sha256=BCqmBykXBF-BpCgOFeG1qhf2XfScKsxPD17wd1hYfHw,120647
|
|
111
|
+
execsql2-2.15.8.dist-info/METADATA,sha256=7S2K-cQV9yOTxpKpB6ehIskUEjjKU9ZHTBpznumVi04,18114
|
|
112
|
+
execsql2-2.15.8.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
113
|
+
execsql2-2.15.8.dist-info/entry_points.txt,sha256=sUOxkM-dN1eBGGpSpDLsAaE0yNXYQKWZAfxPOlMkQyk,90
|
|
114
|
+
execsql2-2.15.8.dist-info/licenses/LICENSE.txt,sha256=LBdhuxejF8_bLCHZ2kWfmDXpDGUu914Gbd6_3JjCRe0,676
|
|
115
|
+
execsql2-2.15.8.dist-info/licenses/NOTICE,sha256=sqVrM73Ys9zfvWC_P797lHfTnoPW_ETeBSrUTFaob0A,339
|
|
116
|
+
execsql2-2.15.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
{execsql2-2.15.7.data → execsql2-2.15.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
|
|
File without changes
|
|
File without changes
|