execsql2 2.30.0__py3-none-any.whl → 2.31.1__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/api.py +1 -0
- execsql/cli/application.py +1 -1
- execsql/cli/commands/lint.py +1 -1
- execsql/cli/dsn.py +35 -1
- execsql/cli/lint.py +10 -1
- execsql/cli/run.py +8 -3
- execsql/config.py +26 -4
- execsql/data/execsql.conf.template +8 -2
- execsql/db/access.py +7 -5
- execsql/db/base.py +18 -0
- execsql/db/factory.py +11 -1
- execsql/db/mysql.py +56 -3
- execsql/db/odbc.py +45 -0
- execsql/db/postgres.py +1 -1
- execsql/db/sqlserver.py +37 -21
- execsql/exporters/ods.py +146 -41
- execsql/exporters/values.py +166 -9
- execsql/importers/base.py +1 -1
- execsql/importers/csv.py +1 -1
- execsql/importers/ods.py +2 -0
- execsql/lsp/diagnostics.py +1 -1
- execsql/lsp/document.py +3 -0
- execsql/metacommands/io_fileops.py +11 -5
- execsql/metacommands/reference.py +1 -1
- execsql/metacommands/upsert.py +10 -1
- execsql/utils/auth.py +21 -14
- execsql/utils/errors.py +1 -1
- execsql/utils/paths.py +31 -0
- {execsql2-2.30.0.data → execsql2-2.31.1.data}/data/execsql2_extras/README.md +9 -8
- {execsql2-2.30.0.data → execsql2-2.31.1.data}/data/execsql2_extras/md_compare.sql +53 -29
- {execsql2-2.30.0.data → execsql2-2.31.1.data}/data/execsql2_extras/md_glossary.sql +20 -20
- {execsql2-2.30.0.data → execsql2-2.31.1.data}/data/execsql2_extras/md_upsert.sql +59 -66
- {execsql2-2.30.0.data → execsql2-2.31.1.data}/data/execsql2_extras/pg_compare.sql +19 -22
- {execsql2-2.30.0.data → execsql2-2.31.1.data}/data/execsql2_extras/pg_glossary.sql +13 -17
- {execsql2-2.30.0.data → execsql2-2.31.1.data}/data/execsql2_extras/script_template.sql +302 -299
- {execsql2-2.30.0.data → execsql2-2.31.1.data}/data/execsql2_extras/ss_compare.sql +39 -29
- {execsql2-2.30.0.data → execsql2-2.31.1.data}/data/execsql2_extras/ss_glossary.sql +13 -17
- {execsql2-2.30.0.data → execsql2-2.31.1.data}/data/execsql2_extras/ss_upsert.sql +56 -66
- {execsql2-2.30.0.dist-info → execsql2-2.31.1.dist-info}/METADATA +17 -41
- {execsql2-2.30.0.dist-info → execsql2-2.31.1.dist-info}/RECORD +47 -46
- execsql2-2.30.0.data/data/execsql2_extras/pg_upsert.sql +0 -2791
- {execsql2-2.30.0.data → execsql2-2.31.1.data}/data/execsql2_extras/config_settings.sqlite +0 -0
- {execsql2-2.30.0.data → execsql2-2.31.1.data}/data/execsql2_extras/example_config_prompt.sql +0 -0
- {execsql2-2.30.0.data → execsql2-2.31.1.data}/data/execsql2_extras/make_config_db.sql +0 -0
- {execsql2-2.30.0.dist-info → execsql2-2.31.1.dist-info}/WHEEL +0 -0
- {execsql2-2.30.0.dist-info → execsql2-2.31.1.dist-info}/entry_points.txt +0 -0
- {execsql2-2.30.0.dist-info → execsql2-2.31.1.dist-info}/licenses/LICENSE.txt +0 -0
- {execsql2-2.30.0.dist-info → execsql2-2.31.1.dist-info}/licenses/NOTICE +0 -0
execsql/utils/paths.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Telling a path on this machine from one that names another.
|
|
2
|
+
|
|
3
|
+
On Windows, checking or opening a path written as ``\\\\host\\share\\...``
|
|
4
|
+
(or ``//host/share/...``) makes the OS contact *host* and offer the logged-in
|
|
5
|
+
user's credentials. The static tools (``execsql lint``, ``execsql format``
|
|
6
|
+
and the language server) read paths written in scripts and config files
|
|
7
|
+
someone else may have written, so they never touch such a path.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
|
|
14
|
+
__all__ = ["is_network_path"]
|
|
15
|
+
|
|
16
|
+
# Read once; tests set it to check the Windows rules on any OS.
|
|
17
|
+
_WINDOWS = os.name == "nt"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def is_network_path(path: str | os.PathLike[str]) -> bool:
|
|
21
|
+
"""Whether *path*, as written, names another machine or a device.
|
|
22
|
+
|
|
23
|
+
On Windows: a UNC path (``\\\\host\\share``, ``//host/share``, either slash)
|
|
24
|
+
or a ``\\\\?\\`` / ``\\\\.\\`` device path. Elsewhere a leading double
|
|
25
|
+
slash is an ordinary local path, so nothing is. A relative path is never
|
|
26
|
+
one: it stays on the machine of the file that names it.
|
|
27
|
+
"""
|
|
28
|
+
if not _WINDOWS:
|
|
29
|
+
return False
|
|
30
|
+
text = os.fspath(path)
|
|
31
|
+
return len(text) >= 2 and text[0] in "\\/" and text[1] in "\\/"
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# Templates for execsql
|
|
2
2
|
|
|
3
|
+
The [Templates section](https://execsql2.readthedocs.io/en/stable/templates/) of the execsql2 documentation describes how to use these files.
|
|
4
|
+
|
|
3
5
|
Several types of templates are provided that may be useful in conjunction with execsql. These are:
|
|
4
6
|
|
|
5
7
|
- **execsql.conf** — An annotated reference of every configuration setting with notes on its usage. Generate a fresh copy in any directory with `execsql config --init > execsql.conf`; the canonical content ships inside the installed package and is loaded via `importlib.resources` (no need to find or copy a source file).
|
|
6
8
|
|
|
7
9
|
- **script_template.sql** — A framework for SQL scripts that make use of several execsql features. It includes sections for custom configuration settings, custom logfile creation, and reporting of unexpected script exits (through user cancellation or errors).
|
|
8
10
|
|
|
9
|
-
- **config_settings.sqlite** and **example_config_prompt.sql** — A SQLite database containing specifications for all settings configurable with the CONFIG metacommand, in the form used by the PROMPT ENTRY_FORM metacommand, and a SQL script illustrating how this database can be used to prompt the user for some or all of the configuration settings.
|
|
11
|
+
- **config_settings.sqlite** and **example_config_prompt.sql** — A SQLite database containing specifications for all settings configurable with the CONFIG metacommand, in the form used by the PROMPT ENTRY_FORM metacommand, and a SQL script illustrating how this database can be used to prompt the user for some or all of the configuration settings.
|
|
10
12
|
|
|
11
13
|
## Functional Scripts for execsql
|
|
12
14
|
|
|
@@ -16,7 +18,7 @@ These script files provide useful functionality that should be accessed by inclu
|
|
|
16
18
|
|
|
17
19
|
These scripts perform automated upsert operations on any tables of any database in a DBMS that supports the standard *information_schema* views. Currently that includes:
|
|
18
20
|
|
|
19
|
-
- **PostgreSQL:** `pg_upsert.sql
|
|
21
|
+
- **PostgreSQL:** use the [`PG_UPSERT`](https://execsql2.readthedocs.io/en/stable/reference/metacommands/#pg_upsert) metacommand, which does the same with the [pg-upsert](https://pg-upsert.readthedocs.io/) package; it replaced `pg_upsert.sql`.
|
|
20
22
|
- **MySQL/MariaDB:** `md_upsert.sql`
|
|
21
23
|
- **SQL Server:** `ss_upsert.sql`
|
|
22
24
|
|
|
@@ -35,7 +37,7 @@ Features of these upsert scripts include:
|
|
|
35
37
|
- Optionally, they will record all operations carried out in a custom log file; this log may include the SQL statements executed and the data values that were added or changed.
|
|
36
38
|
- If an execsql console is active, they will use the console's status bar and progress bar to indicate the activity underway.
|
|
37
39
|
|
|
38
|
-
Complete documentation is
|
|
40
|
+
Complete documentation is in the [Upsert Scripts](https://execsql2.readthedocs.io/en/stable/templates/upsert/) page of the execsql2 documentation.
|
|
39
41
|
|
|
40
42
|
### Table Comparison Scripts
|
|
41
43
|
|
|
@@ -47,7 +49,7 @@ These scripts work with any tables of any database in a DBMS that supports the s
|
|
|
47
49
|
- **MySQL/MariaDB:** `md_compare.sql`
|
|
48
50
|
- **SQL Server:** `ss_compare.sql`
|
|
49
51
|
|
|
50
|
-
Complete documentation is
|
|
52
|
+
Complete documentation is in the [Compare Scripts](https://execsql2.readthedocs.io/en/stable/templates/compare/) page of the execsql2 documentation.
|
|
51
53
|
|
|
52
54
|
### Glossary Creation Scripts
|
|
53
55
|
|
|
@@ -57,9 +59,8 @@ These scripts create a glossary of column names or other terms that can be expor
|
|
|
57
59
|
- **MySQL/MariaDB:** `md_glossary.sql`
|
|
58
60
|
- **SQL Server:** `ss_glossary.sql`
|
|
59
61
|
|
|
60
|
-
Complete documentation is
|
|
62
|
+
Complete documentation is in the [Glossary Scripts](https://execsql2.readthedocs.io/en/stable/templates/glossary/) page of the execsql2 documentation.
|
|
61
63
|
|
|
62
|
-
##
|
|
64
|
+
## Tests
|
|
63
65
|
|
|
64
|
-
|
|
65
|
-
- [ ] Integrate documentation for [execsql-upsert](https://execsql-upsert.readthedocs.io/en/latest/) into the main execsql2 documentation site.
|
|
66
|
+
`tests/templates/` runs these scripts against live databases: the glossary, compare and upsert scripts on PostgreSQL, MySQL, MariaDB and SQL Server (`md_` scripts on both MySQL and MariaDB), plus lint and INCLUDE checks for every file. Run them with `just test-templates`; see `CONTRIBUTING.md`.
|
|
@@ -29,8 +29,9 @@
|
|
|
29
29
|
-- 3. Temporary tables and views created by these scripts all
|
|
30
30
|
-- begin with "cmp_".
|
|
31
31
|
--
|
|
32
|
-
--
|
|
32
|
+
-- AUTHORS
|
|
33
33
|
-- Dreas Nielsen (RDN)
|
|
34
|
+
-- Caleb Grant (CG)
|
|
34
35
|
--
|
|
35
36
|
-- COPYRIGHT AND LICENSE
|
|
36
37
|
-- Copyright (c) 2020 R.Dreas Nielsen
|
|
@@ -45,7 +46,7 @@
|
|
|
45
46
|
-- The GNU General Public License is available at <http://www.gnu.org/licenses/>
|
|
46
47
|
--
|
|
47
48
|
-- VERSION
|
|
48
|
-
-- 1.
|
|
49
|
+
-- 1.2.0
|
|
49
50
|
--
|
|
50
51
|
-- HISTORY
|
|
51
52
|
-- Date Remarks
|
|
@@ -53,13 +54,20 @@
|
|
|
53
54
|
-- 2020-02-27 Created from v. 1.1.0 of pg_compare.sql RDN.
|
|
54
55
|
-- 2020-02-29 Excluded PK columns from output of COMPARE_COMMON_VALS.
|
|
55
56
|
-- Completed conversion to md. v. 1.1.1. RDN.
|
|
57
|
+
-- 2026-10-15 execsql2: text values compare case- and accent-sensitively (the
|
|
58
|
+
-- default collation reported 'y' -> 'Y' as unchanged); columns
|
|
59
|
+
-- are read from the current database only (a same-named table in
|
|
60
|
+
-- another database was mixed in); each script's notes are its
|
|
61
|
+
-- docstring; include_cols and exclude_cols are declared optional
|
|
62
|
+
-- parameters. v. 1.2.0. Tested in tests/templates of the
|
|
63
|
+
-- execsql2 repository. CG.
|
|
56
64
|
-- ==================================================================
|
|
57
65
|
|
|
58
66
|
|
|
59
67
|
-- ################################################################
|
|
60
68
|
-- Script COMPARE_COMMON
|
|
61
69
|
-- ===============================================================
|
|
62
|
-
--
|
|
70
|
+
-- !x! BEGIN SCRIPT COMPARE_COMMON with parameters (stage_pfx, table, sql_var, include_cols="", exclude_cols="")
|
|
63
71
|
-- Generate SQL to compare the attributes of base and staging
|
|
64
72
|
-- tables for only those primary keys in common. This uses an
|
|
65
73
|
-- inner join between the tables, and does not include any rows
|
|
@@ -97,8 +105,6 @@
|
|
|
97
105
|
--
|
|
98
106
|
-- Notes
|
|
99
107
|
-- 1. The generated SQL is not terminated with a semicolon.
|
|
100
|
-
-- ===============================================================
|
|
101
|
-
-- !x! BEGIN SCRIPT COMPARE_COMMON with parameters (stage_pfx, table, sql_var)
|
|
102
108
|
|
|
103
109
|
-- Create a table of primary key columns for the table
|
|
104
110
|
drop table if exists cmp_primary_key_columns cascade;
|
|
@@ -125,20 +131,26 @@ order by k.ordinal_position
|
|
|
125
131
|
-- that are to be compared.
|
|
126
132
|
-- Include only those columns from the staging table that are also in the base table.
|
|
127
133
|
-- !x! sub_empty ~col_sel
|
|
128
|
-
-- !x! if(
|
|
134
|
+
-- !x! if(not is_null("!!#include_cols!!"))
|
|
129
135
|
-- !x! sub ~col_sel and s.column_name in (!!#include_cols!!)
|
|
130
|
-
-- !x! elseif(
|
|
136
|
+
-- !x! elseif(not is_null("!!#exclude_cols!!"))
|
|
131
137
|
-- !x! sub ~col_sel and s.column_name not in (!!#exclude_cols!!)
|
|
132
138
|
-- !x! endif
|
|
133
139
|
drop table if exists cmp_cols cascade;
|
|
134
140
|
create table cmp_cols as
|
|
135
|
-
select
|
|
141
|
+
select
|
|
142
|
+
s.column_name,
|
|
143
|
+
-- Text compares case- and accent-sensitively below; the default collation does not.
|
|
144
|
+
(s.data_type in ('char', 'varchar', 'tinytext', 'text', 'mediumtext', 'longtext', 'enum', 'set') and b.data_type in ('char', 'varchar', 'tinytext', 'text', 'mediumtext', 'longtext', 'enum', 'set')) as is_text
|
|
136
145
|
from information_schema.columns as s
|
|
137
146
|
inner join information_schema.columns as b on s.column_name=b.column_name
|
|
138
147
|
left join cmp_primary_key_columns as pk on pk.column_name = s.column_name
|
|
139
148
|
where
|
|
140
149
|
s.table_name = concat(!'!#stage_pfx!'!, !'!#table!'!)
|
|
141
150
|
and b.table_name = !'!#table!'!
|
|
151
|
+
-- information_schema covers every database on the server.
|
|
152
|
+
and s.table_schema = database()
|
|
153
|
+
and b.table_schema = database()
|
|
142
154
|
and pk.column_name is null
|
|
143
155
|
!!~col_sel!!
|
|
144
156
|
order by s.ordinal_position;
|
|
@@ -157,7 +169,7 @@ from
|
|
|
157
169
|
alter table cmp_cols add column sqlcmd character varying(500);
|
|
158
170
|
update cmp_cols
|
|
159
171
|
set sqlcmd =
|
|
160
|
-
concat('case when b.', column_name, ' is null then case when s.', column_name, ' is null then ''Same'' else ''New'' end else case when s.', column_name, ' is null then ''Old'' else case when b.', column_name, ' = s.', column_name, ' then ''Same'' else ''Different'' end end end as ', column_name)
|
|
172
|
+
concat('case when b.', column_name, ' is null then case when s.', column_name, ' is null then ''Same'' else ''New'' end else case when s.', column_name, ' is null then ''Old'' else case when ', if(is_text, concat('cast(b.', column_name, ' as binary) = cast(s.', column_name, ' as binary)'), concat('b.', column_name, ' = s.', column_name)), ' then ''Same'' else ''Different'' end end end as ', column_name)
|
|
161
173
|
;
|
|
162
174
|
|
|
163
175
|
-- Create the comparison expression for all columns.
|
|
@@ -200,7 +212,7 @@ drop table if exists cmp_primary_key_columns cascade;
|
|
|
200
212
|
-- ################################################################
|
|
201
213
|
-- Script COMPARE_COMMON_VALS
|
|
202
214
|
-- ===============================================================
|
|
203
|
-
--
|
|
215
|
+
-- !x! BEGIN SCRIPT COMPARE_COMMON_VALS with parameters (stage_pfx, table, sql_var, include_cols="", exclude_cols="")
|
|
204
216
|
-- Generate SQL to compare the attributes of base and staging
|
|
205
217
|
-- tables for only those primary keys in common. This uses an
|
|
206
218
|
-- inner join between the tables, and does not include any rows
|
|
@@ -234,8 +246,6 @@ drop table if exists cmp_primary_key_columns cascade;
|
|
|
234
246
|
--
|
|
235
247
|
-- Notes
|
|
236
248
|
-- 1. The generated SQL is not terminated with a semicolon.
|
|
237
|
-
-- ===============================================================
|
|
238
|
-
-- !x! BEGIN SCRIPT COMPARE_COMMON_VALS with parameters (stage_pfx, table, sql_var)
|
|
239
249
|
|
|
240
250
|
-- Create a table of primary key columns for the table
|
|
241
251
|
drop table if exists cmp_primary_key_columns cascade;
|
|
@@ -262,20 +272,26 @@ order by k.ordinal_position
|
|
|
262
272
|
-- that are to be compared.
|
|
263
273
|
-- Include only those columns from the staging table that are also in the base table.
|
|
264
274
|
-- !x! sub_empty ~col_sel
|
|
265
|
-
-- !x! if(
|
|
275
|
+
-- !x! if(not is_null("!!#include_cols!!"))
|
|
266
276
|
-- !x! sub ~col_sel and s.column_name in (!!#include_cols!!)
|
|
267
|
-
-- !x! elseif(
|
|
277
|
+
-- !x! elseif(not is_null("!!#exclude_cols!!"))
|
|
268
278
|
-- !x! sub ~col_sel and s.column_name not in (!!#exclude_cols!!)
|
|
269
279
|
-- !x! endif
|
|
270
280
|
drop table if exists cmp_cols cascade;
|
|
271
281
|
create table cmp_cols as
|
|
272
|
-
select
|
|
282
|
+
select
|
|
283
|
+
s.column_name,
|
|
284
|
+
-- Text compares case- and accent-sensitively below; the default collation does not.
|
|
285
|
+
(s.data_type in ('char', 'varchar', 'tinytext', 'text', 'mediumtext', 'longtext', 'enum', 'set') and b.data_type in ('char', 'varchar', 'tinytext', 'text', 'mediumtext', 'longtext', 'enum', 'set')) as is_text
|
|
273
286
|
from information_schema.columns as s
|
|
274
287
|
inner join information_schema.columns as b on s.column_name=b.column_name
|
|
275
288
|
left join cmp_primary_key_columns as pk on pk.column_name = s.column_name
|
|
276
289
|
where
|
|
277
290
|
s.table_name = concat(!'!#stage_pfx!'!, !'!#table!'!)
|
|
278
291
|
and b.table_name = !'!#table!'!
|
|
292
|
+
-- information_schema covers every database on the server.
|
|
293
|
+
and s.table_schema = database()
|
|
294
|
+
and b.table_schema = database()
|
|
279
295
|
and pk.column_name is null
|
|
280
296
|
!!~col_sel!!
|
|
281
297
|
order by s.ordinal_position;
|
|
@@ -341,7 +357,7 @@ drop table if exists cmp_primary_key_columns cascade;
|
|
|
341
357
|
-- ################################################################
|
|
342
358
|
-- Script COMPARE_CHANGES
|
|
343
359
|
-- ===============================================================
|
|
344
|
-
--
|
|
360
|
+
-- !x! BEGIN SCRIPT COMPARE_CHANGES with parameters (stage_pfx, table, sql_var, include_cols="", exclude_cols="")
|
|
345
361
|
-- Generate SQL to characterize every row of the staging table
|
|
346
362
|
-- data as either a new row, a row with changed data, or a row
|
|
347
363
|
-- with data that are unchanged relative to the base table.
|
|
@@ -374,8 +390,6 @@ drop table if exists cmp_primary_key_columns cascade;
|
|
|
374
390
|
--
|
|
375
391
|
-- Notes
|
|
376
392
|
-- 1. The generated SQL is not terminated with a semicolon.
|
|
377
|
-
-- ===============================================================
|
|
378
|
-
-- !x! BEGIN SCRIPT COMPARE_CHANGES with parameters (stage_pfx, table, sql_var)
|
|
379
393
|
|
|
380
394
|
-- Create a table of primary key columns for the table
|
|
381
395
|
drop table if exists cmp_primary_key_columns cascade;
|
|
@@ -403,20 +417,26 @@ order by k.ordinal_position
|
|
|
403
417
|
-- that are to be compared.
|
|
404
418
|
-- Include only those columns from the staging table that are also in the base table.
|
|
405
419
|
-- !x! sub_empty ~col_sel
|
|
406
|
-
-- !x! if(
|
|
420
|
+
-- !x! if(not is_null("!!#include_cols!!"))
|
|
407
421
|
-- !x! sub ~col_sel and s.column_name in (!!#include_cols!!)
|
|
408
|
-
-- !x! elseif(
|
|
422
|
+
-- !x! elseif(not is_null("!!#exclude_cols!!"))
|
|
409
423
|
-- !x! sub ~col_sel and s.column_name not in (!!#exclude_cols!!)
|
|
410
424
|
-- !x! endif
|
|
411
425
|
drop table if exists cmp_cols cascade;
|
|
412
426
|
create table cmp_cols as
|
|
413
|
-
select
|
|
427
|
+
select
|
|
428
|
+
s.column_name,
|
|
429
|
+
-- Text compares case- and accent-sensitively below; the default collation does not.
|
|
430
|
+
(s.data_type in ('char', 'varchar', 'tinytext', 'text', 'mediumtext', 'longtext', 'enum', 'set') and b.data_type in ('char', 'varchar', 'tinytext', 'text', 'mediumtext', 'longtext', 'enum', 'set')) as is_text
|
|
414
431
|
from information_schema.columns as s
|
|
415
432
|
inner join information_schema.columns as b on s.column_name=b.column_name
|
|
416
433
|
left join cmp_primary_key_columns as pk on pk.column_name = s.column_name
|
|
417
434
|
where
|
|
418
435
|
s.table_name = concat(!'!#stage_pfx!'!, !'!#table!'!)
|
|
419
436
|
and b.table_name = !'!#table!'!
|
|
437
|
+
-- information_schema covers every database on the server.
|
|
438
|
+
and s.table_schema = database()
|
|
439
|
+
and b.table_schema = database()
|
|
420
440
|
and pk.column_name is null
|
|
421
441
|
!!~col_sel!!
|
|
422
442
|
order by s.ordinal_position;
|
|
@@ -436,7 +456,7 @@ from
|
|
|
436
456
|
alter table cmp_cols add column sqlcmd character varying(500);
|
|
437
457
|
update cmp_cols
|
|
438
458
|
set sqlcmd =
|
|
439
|
-
concat('case when b.', column_name, ' is null then case when s.', column_name, ' is null then 0 else 1 end else case when s.', column_name, ' is null then 1 else case when b.', column_name, ' = s.', column_name, ' then 0 else 1 end end end')
|
|
459
|
+
concat('case when b.', column_name, ' is null then case when s.', column_name, ' is null then 0 else 1 end else case when s.', column_name, ' is null then 1 else case when ', if(is_text, concat('cast(b.', column_name, ' as binary) = cast(s.', column_name, ' as binary)'), concat('b.', column_name, ' = s.', column_name)), ' then 0 else 1 end end end')
|
|
440
460
|
;
|
|
441
461
|
|
|
442
462
|
-- Create the expression to determine whether there is a difference for any column.
|
|
@@ -491,7 +511,7 @@ drop table if exists cmp_primary_key_columns cascade;
|
|
|
491
511
|
-- ################################################################
|
|
492
512
|
-- Script COMPARE_CHANGED
|
|
493
513
|
-- ===============================================================
|
|
494
|
-
--
|
|
514
|
+
-- !x! BEGIN SCRIPT COMPARE_CHANGED with parameters (stage_pfx, table, sql_var, include_cols="", exclude_cols="")
|
|
495
515
|
-- Generate SQL to characterize every row of the base table
|
|
496
516
|
-- depending on whether there is a matching row in the staging
|
|
497
517
|
-- table, whether a matching row has new data, or whether a
|
|
@@ -525,8 +545,6 @@ drop table if exists cmp_primary_key_columns cascade;
|
|
|
525
545
|
--
|
|
526
546
|
-- Notes
|
|
527
547
|
-- 1. The generated SQL is not terminated with a semicolon.
|
|
528
|
-
-- ===============================================================
|
|
529
|
-
-- !x! BEGIN SCRIPT COMPARE_CHANGED with parameters (stage_pfx, table, sql_var)
|
|
530
548
|
|
|
531
549
|
-- Create a table of primary key columns for the table
|
|
532
550
|
drop table if exists cmp_primary_key_columns cascade;
|
|
@@ -553,20 +571,26 @@ order by k.ordinal_position
|
|
|
553
571
|
-- that are to be compared.
|
|
554
572
|
-- Include only those columns from the staging table that are also in the base table.
|
|
555
573
|
-- !x! sub_empty ~col_sel
|
|
556
|
-
-- !x! if(
|
|
574
|
+
-- !x! if(not is_null("!!#include_cols!!"))
|
|
557
575
|
-- !x! sub ~col_sel and s.column_name in (!!#include_cols!!)
|
|
558
|
-
-- !x! elseif(
|
|
576
|
+
-- !x! elseif(not is_null("!!#exclude_cols!!"))
|
|
559
577
|
-- !x! sub ~col_sel and s.column_name not in (!!#exclude_cols!!)
|
|
560
578
|
-- !x! endif
|
|
561
579
|
drop table if exists cmp_cols cascade;
|
|
562
580
|
create table cmp_cols as
|
|
563
|
-
select
|
|
581
|
+
select
|
|
582
|
+
s.column_name,
|
|
583
|
+
-- Text compares case- and accent-sensitively below; the default collation does not.
|
|
584
|
+
(s.data_type in ('char', 'varchar', 'tinytext', 'text', 'mediumtext', 'longtext', 'enum', 'set') and b.data_type in ('char', 'varchar', 'tinytext', 'text', 'mediumtext', 'longtext', 'enum', 'set')) as is_text
|
|
564
585
|
from information_schema.columns as s
|
|
565
586
|
inner join information_schema.columns as b on s.column_name=b.column_name
|
|
566
587
|
left join cmp_primary_key_columns as pk on pk.column_name = s.column_name
|
|
567
588
|
where
|
|
568
589
|
s.table_name = concat(!'!#stage_pfx!'!, !'!#table!'!)
|
|
569
590
|
and b.table_name = !'!#table!'!
|
|
591
|
+
-- information_schema covers every database on the server.
|
|
592
|
+
and s.table_schema = database()
|
|
593
|
+
and b.table_schema = database()
|
|
570
594
|
and pk.column_name is null
|
|
571
595
|
!!~col_sel!!
|
|
572
596
|
order by s.ordinal_position;
|
|
@@ -586,7 +610,7 @@ from
|
|
|
586
610
|
alter table cmp_cols add column sqlcmd character varying(500);
|
|
587
611
|
update cmp_cols
|
|
588
612
|
set sqlcmd =
|
|
589
|
-
concat('case when b.', column_name, ' is null then case when s.', column_name, ' is null then 0 else 1 end else case when s.', column_name, ' is null then 1 else case when b.', column_name, ' = s.', column_name, ' then 0 else 1 end end end')
|
|
613
|
+
concat('case when b.', column_name, ' is null then case when s.', column_name, ' is null then 0 else 1 end else case when s.', column_name, ' is null then 1 else case when ', if(is_text, concat('cast(b.', column_name, ' as binary) = cast(s.', column_name, ' as binary)'), concat('b.', column_name, ' = s.', column_name)), ' then 0 else 1 end end end')
|
|
590
614
|
;
|
|
591
615
|
|
|
592
616
|
-- Create the expression to determine whether there is a difference for any column.
|
|
@@ -38,9 +38,10 @@
|
|
|
38
38
|
--
|
|
39
39
|
-- AUTHORS
|
|
40
40
|
-- Dreas Nielsen (RDN)
|
|
41
|
+
-- Caleb Grant (CG)
|
|
41
42
|
--
|
|
42
43
|
-- VERSION
|
|
43
|
-
-- 1.
|
|
44
|
+
-- 1.1.0
|
|
44
45
|
--
|
|
45
46
|
-- HISTORY
|
|
46
47
|
-- Date Remarks
|
|
@@ -50,13 +51,17 @@
|
|
|
50
51
|
-- existence, to eliminate spurious messages from the DBMS.
|
|
51
52
|
-- Made the 'gls_glossary' table and 'glossary' view non-temporary
|
|
52
53
|
-- because the 'glossary' view can't reference a temporary table. RDN.
|
|
54
|
+
-- 2026-10-15 execsql2: each script's notes are its docstring (SHOW SCRIPTS, the
|
|
55
|
+
-- language server); def_url is a declared optional parameter;
|
|
56
|
+
-- ADD_GLOSSARY_ITEM keeps def_url; MySQL 8 casts (CHAR, not VARCHAR or ::text). Version 1.1.0. Tested in
|
|
57
|
+
-- tests/templates of the execsql2 repository. CG.
|
|
53
58
|
-- ============================================================================
|
|
54
59
|
|
|
55
60
|
|
|
56
61
|
-- ################################################################
|
|
57
62
|
-- Script INIT_GLOSSARY
|
|
58
63
|
-- ===============================================================
|
|
59
|
-
--
|
|
64
|
+
-- !x! BEGIN SCRIPT INIT_GLOSSARY with parameters (glossary_db_alias, glossary_table, name_col, def_col, def_url="")
|
|
60
65
|
-- Initialize the custom glossary and describe the master glossary
|
|
61
66
|
-- that will provide descriptions to include in the custom glossary.
|
|
62
67
|
--
|
|
@@ -73,14 +78,12 @@
|
|
|
73
78
|
-- Optional input argument:
|
|
74
79
|
-- def_url : The URL of a page that provides additional
|
|
75
80
|
-- information about the column (or other object).
|
|
76
|
-
-- ===============================================================
|
|
77
|
-
-- !x! BEGIN SCRIPT INIT_GLOSSARY with parameters (glossary_db_alias, glossary_table, name_col, def_col)
|
|
78
81
|
|
|
79
82
|
-- !x! sub gls_alias !!#glossary_db_alias!!
|
|
80
83
|
-- !x! sub gls_table !!#glossary_table!!
|
|
81
84
|
-- !x! sub gls_name !!#name_col!!
|
|
82
85
|
-- !x! sub gls_def !!#def_col!!
|
|
83
|
-
-- !x! if(
|
|
86
|
+
-- !x! if(not is_null("!!#def_url!!"))
|
|
84
87
|
-- !x! sub gls_has_url Yes
|
|
85
88
|
-- !x! sub gls_url !!#def_url!!
|
|
86
89
|
-- !x! sub ~url_colspec !!gls_url!! text,
|
|
@@ -122,13 +125,11 @@ from gls_glossary order by !!gls_name!!;
|
|
|
122
125
|
-- ################################################################
|
|
123
126
|
-- Script ADD_GLOSSARY_LIST
|
|
124
127
|
-- ===============================================================
|
|
125
|
-
--
|
|
128
|
+
-- !x! BEGIN SCRIPT ADD_GLOSSARY_LIST with parameters (column_list)
|
|
126
129
|
-- Add a specific list of columns to the glossary.
|
|
127
130
|
--
|
|
128
131
|
-- Required input arguments:
|
|
129
132
|
-- column_list : A string of comma-separated column names.
|
|
130
|
-
-- ===============================================================
|
|
131
|
-
-- !x! BEGIN SCRIPT ADD_GLOSSARY_LIST with parameters (column_list)
|
|
132
133
|
|
|
133
134
|
-- !x! sub ~entry_alias !!$current_alias!!
|
|
134
135
|
-- !x! use initial
|
|
@@ -230,7 +231,7 @@ select !!gls_collist!! from gls_newglossary;
|
|
|
230
231
|
-- ################################################################
|
|
231
232
|
-- Script ADD_GLOSSARY_ITEM
|
|
232
233
|
-- ===============================================================
|
|
233
|
-
--
|
|
234
|
+
-- !x! BEGIN SCRIPT ADD_GLOSSARY_ITEM with parameters (item, definition, def_url="")
|
|
234
235
|
-- Add an object name and definition to the custom glossary.
|
|
235
236
|
-- This does not use the master glossary.
|
|
236
237
|
--
|
|
@@ -242,19 +243,21 @@ select !!gls_collist!! from gls_newglossary;
|
|
|
242
243
|
-- Optional input argument:
|
|
243
244
|
-- def_url : The URL of a page that provides additional
|
|
244
245
|
-- information about the item.
|
|
245
|
-
-- ===============================================================
|
|
246
|
-
-- !x! BEGIN SCRIPT ADD_GLOSSARY_ITEM with parameters (item, definition)
|
|
247
246
|
|
|
248
247
|
-- !x! sub ~entry_alias !!$current_alias!!
|
|
249
248
|
-- !x! use initial
|
|
250
249
|
|
|
251
|
-
-- !x! if(is_true(gls_has_url))
|
|
252
|
-
-- !x! andif(
|
|
250
|
+
-- !x! if(is_true(!!gls_has_url!!))
|
|
251
|
+
-- !x! andif(not is_null("!!#def_url!!"))
|
|
253
252
|
insert into gls_glossary (!!gls_name!!, !!gls_def!!, !!gls_url!!)
|
|
254
253
|
select
|
|
255
254
|
inp.item, inp.definition, inp.url
|
|
256
255
|
from
|
|
257
|
-
(select
|
|
256
|
+
(select
|
|
257
|
+
cast(!'!#item!'! as char(255)) as item,
|
|
258
|
+
cast(!'!#definition!'! as char(255)) as definition,
|
|
259
|
+
cast(!'!#def_url!'! as char(255)) as url
|
|
260
|
+
) as inp
|
|
258
261
|
left join gls_glossary as g on g.!!gls_name!! = inp.item
|
|
259
262
|
where
|
|
260
263
|
g.!!gls_name!! is null;
|
|
@@ -264,8 +267,8 @@ select !!gls_collist!! from gls_newglossary;
|
|
|
264
267
|
inp.item, inp.definition
|
|
265
268
|
from
|
|
266
269
|
(select
|
|
267
|
-
cast(!'!#item!'! as
|
|
268
|
-
cast(!'!#definition!'! as
|
|
270
|
+
cast(!'!#item!'! as char(255)) as item,
|
|
271
|
+
cast(!'!#definition!'! as char(255)) as definition
|
|
269
272
|
) as inp
|
|
270
273
|
left join gls_glossary as g on g.!!gls_name!! = inp.item
|
|
271
274
|
where
|
|
@@ -285,15 +288,12 @@ select !!gls_collist!! from gls_newglossary;
|
|
|
285
288
|
-- ################################################################
|
|
286
289
|
-- Script ADD_GLOSSARY_TABLE
|
|
287
290
|
-- ===============================================================
|
|
288
|
-
--
|
|
291
|
+
-- !x! BEGIN SCRIPT ADD_GLOSSARY_TABLE with parameters (table)
|
|
289
292
|
-- Add definitions of all columns in a specified table to the
|
|
290
293
|
-- custom glossary.
|
|
291
294
|
--
|
|
292
295
|
-- Required input arguments:
|
|
293
296
|
-- table : The table name.
|
|
294
|
-
--
|
|
295
|
-
-- ===============================================================
|
|
296
|
-
-- !x! BEGIN SCRIPT ADD_GLOSSARY_TABLE with parameters (table)
|
|
297
297
|
|
|
298
298
|
-- !x! sub ~entry_alias !!$current_alias!!
|
|
299
299
|
|