execsql2 1.130.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.
@@ -0,0 +1,2981 @@
1
+ -- md_upsert.sql
2
+ --
3
+ -- PURPOSE
4
+ -- A set of execsql scripts to check data in a staging table, or
5
+ -- a set of staging tables, and then update and insert rows of a base table
6
+ -- or base tables from the staging table(s) of the same name.
7
+ --
8
+ -- This script contains code specific to MariaDB/MySQL.
9
+ --
10
+ -- HOW TO USE THESE SCRIPTS
11
+ -- In the following steps, "call" means to use an execsql "execute script"
12
+ -- metacommand. Script names are displayed in uppercase to distinguish
13
+ -- them below, but execsql is not case-sensitive.
14
+ --
15
+ -- The simplest usage is:
16
+ -- 1. Call STAGED_TO_LOAD to create and initially populate a table
17
+ -- with the names of staging tables to be loaded, and initial
18
+ -- control variables used by other scripts.
19
+ -- 2. Call LOAD_STAGING to perform QA checks for erroneous nulls,
20
+ -- duplicated primary keys, and missing foreign keys, and to
21
+ -- load the data using update and insert statements if there were
22
+ -- no QA errors.
23
+ --
24
+ -- The control table that is produced in step 1 above can be edited to
25
+ -- add a list of columns to exclude from the update, or to change the
26
+ -- defaults for display of changed data. See the header notes for the
27
+ -- STAGED_TO_LOAD script.
28
+ --
29
+ -- The processes of performing QA checks and performing the upsert operations
30
+ -- can be further broken down into individual steps. See Note #1 below
31
+ -- for the other scripts that can be used to carry out these steps.
32
+ --
33
+ -- NOTES
34
+ -- 1. The scripts contained in this file that are intended to be called
35
+ -- directly by the user are:
36
+ -- STAGED_TO_LOAD : Initialize a control table to load multiple tables.
37
+ -- LOAD_STAGING : Perform all QA checks and load data from all staging tables.
38
+ -- QA_ALL : Perform null and foreign key checks on all staging tables.
39
+ -- UPSERT_ALL : Load data from all staging tables.
40
+ -- NULLQA_ONE : Perform null column checks on one staging table.
41
+ -- PKQA_ONE : Perform primary key checks on one staging table.
42
+ -- FKQA_ONE : Perform foreign key checks on one staging table.
43
+ -- UPSERT_ONE : Load data from one staging table.
44
+ -- This file contains other scripts that are intended to be used
45
+ -- only by one of the scripts listed above, and not called
46
+ -- directly by the user.
47
+ -- 2. These scripts query the information schema to obtain
48
+ -- the information needed to perform the checks and changes.
49
+ -- 3. These scripts create and delete tables in the active database.
50
+ -- Because MariaDB/MySQL does not (currently) support temporary
51
+ -- views, or views on temporary tables, most of the views and
52
+ -- tables that are created are potentially visible to other
53
+ -- database operations. See the header notes for invdividual
54
+ -- execsql scripts for names of the tables and views used.
55
+ -- 4. These scripts take arguments that control their functions. They
56
+ -- also use global variables pertinent to logging, if they are
57
+ -- defined. The logging-control variables are global because
58
+ -- they may also be used by other code that uses these scripts,
59
+ -- and some of that code may be older and only recognize global
60
+ -- variables rather than script arguments; logging is intended
61
+ -- to be compatible with them.
62
+ -- 5. The control table that is used to drive the loading of multiple
63
+ -- staging tables will be updated by the QA scripts with information
64
+ -- about any QA failures. This information consists of a list of
65
+ -- the names of the columns or constraints that failed the check,
66
+ -- with the number of failing rows in paretheses following the name.
67
+ -- 6. The control table that is used to drive the loading of multiple
68
+ -- staging tables will be updated by the upsert operation with
69
+ -- a count of the number of rows of the base table that are updated,
70
+ -- and a count of the number of rows that were inserted into the
71
+ -- base table.
72
+ -- 7. All of these scripts assume that schema, table, and column
73
+ -- names need not be quoted.
74
+ -- 8. These scripts create temporary tables and views. All of thes
75
+ -- have prefixes of "ups_". Scripts that include this file
76
+ -- should not use this prefix to avoid possible conflicts.
77
+ --
78
+ -- COPYRIGHT AND LICENSE
79
+ -- Copyright (c) 2019, R. Dreas Nielsen
80
+ -- This program is free software: you can redistribute it and/or modify it
81
+ -- under the terms of the GNU General Public License as published by the
82
+ -- Free Software Foundation, either version 3 of the License, or (at your
83
+ -- option) any later version. This program is distributed in the hope that
84
+ -- it will be useful, but WITHOUT ANY WARRANTY; without even the implied
85
+ -- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
86
+ -- GNU General Public License for more details. The GNU General Public
87
+ -- License is available at http://www.gnu.org/licenses/.
88
+
89
+ -- AUTHORS
90
+ -- Dreas Nielsen (RDN)
91
+ -- Elizabeth Shea (ES)
92
+ --
93
+ -- VERSION
94
+ -- 2.0.0
95
+ --
96
+ -- HISTORY
97
+ -- Date Remarks
98
+ -- ---------- -----------------------------------------------------
99
+ -- 2019-01-15 Began first component scripts. RDN.
100
+ -- 2019-01-30 Integrated separate scripts into this one file and
101
+ -- began modifications to set parameters and arguments. RDN.
102
+ -- 2019-01-31 Editing. RDN.
103
+ -- 2019-02-01 Completed revisions to set parameters and arguments.
104
+ -- Added scripts "staged_to_load", "upsert_all", and
105
+ -- "load_staging".
106
+ -- Added and modified documentation. RDN.
107
+ -- 2019-02-02 Debugging edits. RDN.
108
+ -- 2019-02-03 Edits from 2019-02-03 pg version for MariaDB/MySQL
109
+ -- compatibility. RDN.
110
+ -- 2019-02-05 Edits for MariaDB: conversion of staging schema to
111
+ -- a staging prefix. RDN.
112
+ -- 2019-02-14 Added where clause conditions for schema name equal
113
+ -- to the current database to prevent multiple null
114
+ -- checks when there are multiple databases with the
115
+ -- same table and column names. RDN.
116
+ -- 2019-02-15 Modified all internal table and view names to use a
117
+ -- prefix of "ups_". RDN.
118
+ -- 2019-02-16 Modified to include in the list of ordered tables all
119
+ -- tables that are not part of any foreign key relationship.
120
+ -- Modified to use an 'exclude_null_checks' setting. RDN.
121
+ -- 2019-02-17 Corrected the check to display changes in UPSERT_ONE. RDN.
122
+ -- 2019-02-21 Modifed QA_ALL_NULLLOOP and QA_ALL_FKLOOP to use local
123
+ -- variables and the new outer scope referent prefix for
124
+ -- the return values. RDN.
125
+ -- 2019-03-02 Changed to use 'autocommit with commit'. Modified
126
+ -- recursive CTE to order dependencies to protect against
127
+ -- multi-table cycles. RDN.
128
+ -- 2019-03-02 Modified to show the number of rows with each invalid
129
+ -- foreign key value, in both the GUI display and the
130
+ -- logfile. RDN.
131
+ -- 2019-03-03 Added the 'do_commit' argument to LOAD_STAGING. RDN.
132
+ -- 2019-03-09 Added FKQA_ONE with related changes from SS version
133
+ -- by ES. Modified addition of solo tables to the set
134
+ -- of ordered tables per ES revisions. Other fixes
135
+ -- following ES changes to pg_upsert.sql. Revised
136
+ -- recursive CTE for FK ordering to eliminate
137
+ -- hangs on referential cycles of >2 tables. RDN.
138
+ -- 2019-03-15 Added VALIDATE_ONE and calls to it. RDN.
139
+ -- 2019-03-24 Added constraints to PKQA_ONE to limit to the
140
+ -- current database. RDN.
141
+ -- 2019-06-08 Began addition of PK updating scripts. Complete
142
+ -- through QA check 8. RDN.
143
+ -- 2019-06-16 Nominally complete revisions of PK updating scripts. RDN.
144
+ -- 2019-06-23 Completed debugging of PK updating scripts. RDN.
145
+ -- 2020-04-28 Explicitly rolled back the changes if 'do_commit' = "No". RDN.
146
+ -- 2020-05-09 Moved the assignment of 'upsert_progress_denom' out of the
147
+ -- 'update_console_qa' script. RDN.
148
+ -- ==================================================================
149
+
150
+
151
+
152
+ -- ################################################################
153
+ -- Script VALIDATE_ONE
154
+ -- ===============================================================
155
+ --
156
+ -- Utility script to validate both base and staging versions of one table.
157
+ -- Halts script processing if either of the tables are not present.
158
+ --
159
+ -- Input parameters:
160
+ -- stage_pfx : The prefix for staging tables.
161
+ -- table_name : The name of the table.
162
+ -- script : The name of the script in which the
163
+ -- schemas and table were referenced
164
+ -- (for error reporting).
165
+ -- script_line : The script line in which they were referenced
166
+ -- (for error reporting).
167
+ -- ===============================================================
168
+ -- !x! BEGIN SCRIPT VALIDATE_ONE with parameters (stage_pfx, table, script, script_line)
169
+
170
+ -- Initialize the strings used to compile error information
171
+ -- !x! sub_empty ~err_info
172
+ -- !x! sub_empty ~error_list
173
+
174
+
175
+ -- !x! if(table_exists(ups_invl_table))
176
+ drop table if exists ups_invl_table cascade;
177
+ -- !x! endif
178
+ create table ups_invl_table
179
+ select
180
+ group_concat(concat(tt.table_name, ' (', tt.schema_type, ')') order by tt.table_name separator ';') as schema_table
181
+ from
182
+ (
183
+ select
184
+ 'base' as schema_type,
185
+ '!!#table!!' as table_name
186
+ union
187
+ select
188
+
189
+ 'staging' as schema_type,
190
+ '!!#stage_pfx!!!!#table!!' as table_name
191
+ ) as tt
192
+ left join information_schema.tables as iss on tt.table_name=iss.table_name
193
+ where
194
+ iss.table_name is null
195
+ and iss.table_schema = '!!$DB_NAME!!'
196
+ having count(*) > 0
197
+ ;
198
+
199
+ -- !x! if(hasrows(ups_invl_table))
200
+ -- !x! subdata ~err_info ups_invl_table
201
+ -- !x! sub ~error_list Non-existent table: !!~err_info!!
202
+ -- !x! endif
203
+
204
+
205
+
206
+ -- Halt script if any schemas or tables were found to be invalid
207
+ -- !x! if(not is_null("!!~error_list!!"))
208
+
209
+ -- !x! sub ~error_message ERROR - INVALID OBJECT IN SCRIPT ARGUMENT
210
+
211
+ -- !x! if(sub_defined(log_changes))
212
+ -- !x! andif(is_true(!!log_changes!!))
213
+ -- !x! write "==================================================================" to !!logfile!!
214
+ -- !x! write "!!$current_time!! -- !!~error_message!!" to !!logfile!!
215
+ -- !x! write "Script: !!#script!!; Line: !!#script_line!!" to !!logfile!!
216
+ -- !x! write "!!~error_list!!" to !!logfile!!
217
+ -- !x! endif
218
+
219
+ -- !x! sub_append ~error_message Script: !!#script!!; Line: !!#script_line!! -- !x! sub_append ~error_message !!~error_list!! -- !x! halt message "!!~error_message!!"
220
+
221
+ -- !x! endif
222
+
223
+ -- !x! if(table_exists(ups_invl_table))
224
+ drop table if exists ups_invl_table cascade;
225
+ -- !x! endif
226
+
227
+ -- !x! END SCRIPT
228
+ -- #################### End of VALIDATE_ONE #####################
229
+ -- ################################################################
230
+
231
+
232
+
233
+ -- ################################################################
234
+ -- Script VALIDATE_CONTROL
235
+ -- ===============================================================
236
+ --
237
+ -- Utility script to validate contents of control table against about
238
+ -- base and staging schema
239
+ --
240
+ -- Required input arguments:
241
+ -- stage_pfx : The name of the staging schema.
242
+ -- control_table : The name of a temporary table as created by the
243
+ -- script STAGED_TO_LOAD.
244
+ -- script : The name of the script in which the
245
+ -- schemas and control table were referenced
246
+ -- (for error reporting).
247
+ -- script_line : The script line in which they were referenced
248
+ -- (for error reporting).
249
+ -- ===============================================================
250
+ -- !x! BEGIN SCRIPT VALIDATE_CONTROL with parameters (stage_pfx, control_table, script, script_line)
251
+
252
+ -- Initialize the strings used to compile error information
253
+ -- !x! sub_empty ~err_info
254
+ -- !x! sub_empty ~error_list
255
+
256
+ -- !x! if(table_exists(ups_validate_control))
257
+ drop table if exists ups_validate_control cascade;
258
+ -- !x! endif
259
+ create table ups_validate_control
260
+ select
261
+ table_name,
262
+ False as base_exists,
263
+ False as staging_exists
264
+ from !!#control_table!!
265
+ ;
266
+
267
+ -- Update the validation table
268
+ update ups_validate_control as vc, information_schema.tables as bt
269
+ set vc.base_exists = True
270
+ where
271
+ vc.table_name=bt.table_name
272
+ and bt.table_type='BASE TABLE'
273
+ and bt.table_schema = '!!$DB_NAME!!'
274
+ ;
275
+
276
+ update ups_validate_control as vc, information_schema.tables as st
277
+ set vc.staging_exists = True
278
+ where
279
+ st.table_name= concat('!!#stage_pfx!!', vc.table_name)
280
+ and st.table_type='BASE TABLE'
281
+ and st.table_schema = '!!$DB_NAME!!'
282
+ ;
283
+
284
+ -- !x! if(table_exists(ups_ctrl_invl_table))
285
+ drop table if exists ups_ctrl_invl_table cascade;
286
+ -- !x! endif
287
+ create table ups_ctrl_invl_table
288
+ select
289
+ group_concat(schema_table order by it.schema_table separator '; ') as schema_table
290
+ from
291
+ (
292
+ select table_name as schema_table
293
+ from ups_validate_control
294
+ where not base_exists
295
+ union
296
+ select concat('!!#stage_pfx!!', table_name) as schema_table
297
+ from ups_validate_control
298
+ where not staging_exists
299
+ ) as it
300
+ having count(*) > 0
301
+ ;
302
+
303
+ -- Any table is invalid
304
+ -- !x! if(hasrows(ups_ctrl_invl_table))
305
+ -- !x! subdata ~err_info ups_validate_control
306
+ -- !x! sub ~error_list Non-existent table(s): !!~err_info!!
307
+ -- !x! endif
308
+
309
+
310
+ -- Halt script if any invalid objects found in control table
311
+ -- !x! if(not is_null("!!~error_list!!"))
312
+
313
+ -- !x! sub ~error_message ERROR - INVALID OBJECTS IN CONTROL TABLE
314
+
315
+ -- !x! if(sub_defined(log_changes))
316
+ -- !x! andif(is_true(!!log_changes!!))
317
+ -- !x! write "==================================================================" to !!logfile!!
318
+ -- !x! write "!!$current_time!! -- !!~error_message!!" to !!logfile!!
319
+ -- !x! write "Script: !!#script!!; Line: !!#script_line!!" to !!logfile!!
320
+ -- !x! write "!!~error_list!!" to !!logfile!!
321
+ -- !x! endif
322
+
323
+ -- !x! sub_append ~error_message Script: !!#script!!; Line: !!#script_line!!
324
+ -- !x! sub_append ~error_message !!~error_list!!
325
+ -- !x! halt message "!!~error_message!!"
326
+
327
+ -- !x! endif
328
+
329
+ -- !x! if(table_exists(ups_validate_control))
330
+ drop table if exists ups_validate_control cascade;
331
+ -- !x! endif
332
+ -- !x! if(table_exists(ups_ctrl_invl_table))
333
+ drop table if exists ups_ctrl_invl_table cascade;
334
+ -- !x! endif
335
+
336
+ -- !x! END SCRIPT
337
+ -- #################### End of VALIDATE_CONTROL #################
338
+ -- ################################################################
339
+
340
+
341
+ -- ################################################################
342
+ -- Script STAGED_TO_LOAD
343
+ -- ===============================================================
344
+ --
345
+ -- Creates a table having the structure that is used to drive other
346
+ -- scripts that perform QA checks and the upsert operation on multiple
347
+ -- staging tables.
348
+ --
349
+ -- Input parameters:
350
+ -- control_table : The name of the table to be created.
351
+ -- In MariaDB/MySQL, this must *not* be a
352
+ -- temporary table.
353
+ -- table_list : A string of comma-separated table names,
354
+ -- identifying the staging tables to be
355
+ -- checked or loaded.
356
+ --
357
+ -- Columns in the table created:
358
+ -- table_name : The name of a base table that has a
359
+ -- corresponding table in a staging schema
360
+ -- containing data to be used to modify
361
+ -- the base table.
362
+ -- exclude_cols : Contains a comma-separated list of columns
363
+ -- in the base table that are not to be
364
+ -- updated from the staging table. This is
365
+ -- uninitialized.
366
+ -- exclude_null_checks :
367
+ -- Contains a comma-separated list of single-quoted
368
+ -- column names identifying column in the
369
+ -- staging table for which null checks
370
+ -- should not be performed. This is
371
+ -- uninitialized.
372
+ -- display_changes : A Boolean indicating whether the 'upsert'
373
+ -- operation should display the changes to
374
+ -- be made to the base table. A separate
375
+ -- GUI display is used for updates and inserts.
376
+ -- Initialized to True.
377
+ -- display_final : A Boolean indicating whether the 'upsert'
378
+ -- operation should display the entire base
379
+ -- table after updates and inserts have been
380
+ -- made. Initialized to False.
381
+ -- null_errors : Will contain a comma-separated list of
382
+ -- columns that are non-nullable in the base
383
+ -- table but that have nulls in the staging
384
+ -- table. Initialized to null; may be filled
385
+ -- by the QA routines.
386
+ -- pk_errors : Will contain a count of the number of distinct
387
+ -- primary key values having duplicate rows,
388
+ -- followed by the total row count for the
389
+ -- duplicated keys. Initialized to null; may
390
+ -- be filled by the QA routines.
391
+ -- fk_errors : Will contain a comma-separated list of
392
+ -- foreign-key constraint names that are
393
+ -- not met by data in the staging table.
394
+ -- Initialized to null; may be filled by the
395
+ -- QA routines.
396
+ -- rows_updated : Will contain a count of the rows updated
397
+ -- in the table by the upsert operation.
398
+ -- rows_inserted : Will contain a count of the rows inserted
399
+ -- in the table by the upsert operation.
400
+ --
401
+ -- Example:
402
+ -- -- !x! execute script staged_to_load with (control_table=stagingtables, table_list="tbla, tblb, tblc")
403
+ -- ===============================================================
404
+
405
+ -- !x! BEGIN SCRIPT STAGED_TO_LOAD with parameters (control_table, table_list)
406
+
407
+ drop table if exists !!#control_table!! cascade;
408
+
409
+ create table !!#control_table!! (
410
+ table_name varchar(150) not null unique,
411
+ exclude_cols varchar(255),
412
+ exclude_null_checks varchar(255),
413
+ display_changes varchar(3) not null default 'Yes',
414
+ display_final varchar(3) not null default 'No',
415
+ null_errors varchar(255),
416
+ pk_errors varchar(255),
417
+ fk_errors varchar(255),
418
+ rows_updated integer,
419
+ rows_inserted integer,
420
+ constraint ck_chgyn check (display_changes in ('Yes', 'No')),
421
+ constraint ck_finalyn check (display_final in ('Yes', 'No'))
422
+ );
423
+
424
+ insert into !!#control_table!!
425
+ (table_name)
426
+ with recursive itemtable as (
427
+ select
428
+ trim(substring_index(data, ',', 1)) as table_name,
429
+ right(data, length(data) - locate(',', data, 1)) as data
430
+ from (select '!!#table_list!!' as data) as input
431
+ union
432
+ select
433
+ trim(substring_index(data, ',', 1)) as table_name,
434
+ right(data, length(data) - locate(',', data, 1)) as data
435
+ from itemtable
436
+ )
437
+ select table_name as item
438
+ from itemtable;
439
+
440
+
441
+ -- !x! END SCRIPT
442
+ -- ################## End of STAGED_TO_LOAD #####################
443
+ -- ################################################################
444
+
445
+
446
+
447
+ -- ################################################################
448
+ -- Script LOAD_STAGING
449
+ -- ===============================================================
450
+ --
451
+ -- Performs QA checks for nulls in non-null columns, for duplicated
452
+ -- primary key values, and for invalid foreign keys in a set of staging
453
+ -- tables to be loaded into base tables. If there are failures in the
454
+ -- QA checks, loading is not attempted. If the loading step is
455
+ -- carried out, it is done within a transaction.
456
+ --
457
+ -- The "null_errors" and "fk_errors" columns of the control table
458
+ -- will be updated to identify any errors that occur, so that this
459
+ -- information is available to the caller.
460
+ --
461
+ -- The "rows_updated" and "rows_inserted" columns of the control table
462
+ -- will be updated with counts of the number of rows affected by the
463
+ -- upsert operation for each table.
464
+ --
465
+ -- When the upsert operation updates the base table, all columns of the
466
+ -- base table that are also in the staging table are updated. The
467
+ -- update operation does not test to see if column contents are different,
468
+ -- and so does not update only those values that are different.
469
+ --
470
+ -- Input parameters:
471
+ -- stage_pfg : The prefix on staging tables that distinguish
472
+ -- them from the corresponding based table
473
+ -- (e.g., "stg_").
474
+ -- control_table : The name of a table as created by the
475
+ -- script STAGED_TO_LOAD.
476
+ -- do_commit : Whether or not the script should commit
477
+ -- the changes; should be 'Yes' or 'No'.
478
+ -- Global variables:
479
+ -- logfile : The name of a log file to which error
480
+ -- messages will be written. Optional.
481
+ -- log_sql : A value of 'Yes' or 'No' to indicate whether
482
+ -- the SQL that is generated for each foreign
483
+ -- key check, and for each update and insert
484
+ -- statement, is written to the logfile. Optional.
485
+ -- log_errors : A value of 'Yes' or 'No' to indicate whether
486
+ -- foreign key errors are written to the logfile.
487
+ -- Optional.
488
+ -- log_changes : A value of 'Yes' or 'No' indicating whether
489
+ -- the updated and inserted data should be
490
+ -- written to the logfile. Optional.
491
+ --
492
+ -- Tables and views created or modified:
493
+ -- ups_qa_fails : view
494
+ -- ===============================================================
495
+
496
+ -- !x! BEGIN SCRIPT LOAD_STAGING with parameters (stage_pfx, control_table, do_commit)
497
+
498
+ -- Clear the columns of return values from the control table, in case this control
499
+ -- table has been used previously.
500
+ update !!#control_table!!
501
+ set
502
+ null_errors = null,
503
+ pk_errors = null,
504
+ fk_errors = null,
505
+ rows_updated = null,
506
+ rows_inserted = null
507
+ ;
508
+
509
+
510
+ -- Run null checks, PK checks, and FK checks.
511
+ -- !x! execute script QA_ALL with arguments (stage_pfx=!!#stage_pfx!!, control_table=!!#control_table!!)
512
+ -- !x! if(view_exists(ups_qa_fails))
513
+ drop view if exists ups_qa_fails cascade;
514
+ -- !x! endif
515
+ create view ups_qa_fails as
516
+ select *
517
+ from !!#control_table!!
518
+ where null_errors is not null or pk_errors is not null or fk_errors is not null;
519
+ -- !x! if(not hasrows(ups_qa_fails))
520
+ -- !x! sub ~preautocommit !!$autocommit_state!!
521
+ -- !x! autocommit off
522
+ -- !x! execute script UPSERT_ALL with arguments (stage_pfx=!!#stage_pfx!!, control_table=!!#control_table!!)
523
+ -- !x! if(is_true(!!#do_commit!!))
524
+ -- !x! autocommit on with commit
525
+ -- !x! write "CHANGES COMMITTED."
526
+ -- !x! if(sub_defined(log_changes))
527
+ -- !x! andif(is_true(!!log_changes!!))
528
+ -- !x! write "" to !!logfile!!
529
+ -- !x! write "==================================================================" to !!logfile!!
530
+ -- !x! write "!!$current_time!! -- CHANGES COMMITTED." to !!logfile!!
531
+ -- !x! endif
532
+ -- !x! else
533
+ -- !x! autocommit on with rollback
534
+ -- !x! write "CHANGES NOT COMMITTED ('do_commit' argument = !!#do_commit!!)"
535
+ -- !x! if(sub_defined(log_changes))
536
+ -- !x! andif(is_true(!!log_changes!!))
537
+ -- !x! write "" to !!logfile!!
538
+ -- !x! write "==================================================================" to !!logfile!!
539
+ -- !x! write "!!$current_time!! -- CHANGES NOT COMMITTED ('do_commit' argument = !!#do_commit!!)" to !!logfile!!
540
+ -- !x! endif
541
+ -- !x! endif
542
+ -- !x! autocommit !!~preautocommit!!
543
+ -- !x! endif
544
+
545
+ -- Clean up.
546
+ drop view if exists ups_qa_fails cascade;
547
+
548
+ -- !x! END SCRIPT
549
+ -- ################### End of LOAD_STAGING ######################
550
+ -- ################################################################
551
+
552
+
553
+
554
+
555
+ -- ################################################################
556
+ -- Script NULLQA_ONE
557
+ -- ===============================================================
558
+ --
559
+ -- Checks that non-nullable columns are fully populated in a
560
+ -- staging table that is an image of the base table.
561
+ -- Reports any non-conforming columns to the console and optionally
562
+ -- to a log file.
563
+ --
564
+ -- Required input arguments:
565
+ -- stage_pfx : The name of the staging schema.
566
+ -- table : The table name--same for base and staging.
567
+ -- Optional input arguments:
568
+ -- exclude_null_checks : A comma-separated list of singly-quoted
569
+ -- column names to be excluded from null checks.
570
+ --
571
+ -- Output parameters:
572
+ -- error_list : The name of the variable to receive a comma-
573
+ -- delimited list of the names of non-null
574
+ -- columns that contain nulls; each column name
575
+ -- will be followed by the number of rows with
576
+ -- nulls, in parentheses.
577
+ --
578
+ -- Global variables:
579
+ -- logfile : The name of a log file to which error
580
+ -- messages will be written. Optional.
581
+ --
582
+ -- Tables and views created or modified:
583
+ -- ups_nonnull_columns : table
584
+ -- ups_next_column : view
585
+ -- ups_null_error_list : view
586
+ -- ups_qa_nonnull_col : view
587
+ -- ===============================================================
588
+
589
+ -- !x! BEGIN SCRIPT NULLQA_ONE with parameters (stage_pfx, table, error_list)
590
+
591
+ -- Write an initial header to the logfile.
592
+ -- !x! if(sub_defined(logfile))
593
+ -- !x! write "" to !!logfile!!
594
+ -- !x! write "==================================================================" to !!logfile!!
595
+ -- !x! write "!!$current_time!! -- Non-null QA checks on table !!#stage_pfx!!!!#table!!" to !!logfile!!
596
+ -- !x! endif
597
+
598
+ -- !x! write "Conducting non-null QA checks on table !!#stage_pfx!!!!#table!!"
599
+
600
+ -- Validate input table specifications.
601
+ -- !x! execute script validate_one with args (stage_pfx=!!#stage_pfx!!, table=!!#table!!, script=!!$CURRENT_SCRIPT!!, script_line=!!$SCRIPT_LINE!!)
602
+
603
+ -- Initialize the return value to empty (no foreign key errors)
604
+ -- !x! sub_empty !!#error_list!!
605
+
606
+ -- Create a table listing the columns of the base table that must
607
+ -- be non-null and that do not have a default expression.
608
+ -- Include a column for the number of rows with nulls in the staging table.
609
+ -- Include a 'processed' column for loop control.
610
+ -- !x! if(sub_defined(#exclude_null_checks))
611
+ -- !x! sub ~omitnull and column_name not in (!!#exclude_null_checks!!)
612
+ -- !x! else
613
+ -- !x! sub_empty ~omitnull
614
+ -- !x! endif
615
+ -- !x! if(table_exists(ups_nonnull_columns))
616
+ drop table if exists ups_nonnull_columns cascade;
617
+ -- !x! endif
618
+ create table ups_nonnull_columns
619
+ select
620
+ column_name,
621
+ 0 as null_rows,
622
+ 0 as processed
623
+ from
624
+ information_schema.columns
625
+ where
626
+ table_schema = '!!$DB_NAME!!'
627
+ and table_name = '!!#table!!'
628
+ and is_nullable = 'NO'
629
+ and column_default is null
630
+ !!~omitnull!!
631
+ ;
632
+
633
+ -- Create a view to select one column to process.
634
+ create or replace view ups_next_column as
635
+ select column_name
636
+ from ups_nonnull_columns
637
+ where processed = 0
638
+ limit 1;
639
+
640
+ -- Process all non-nullable columns.
641
+ -- !x! execute script nullqa_one_innerloop with (stage_pfx=!!#stage_pfx!!, table=!!#table!!)
642
+
643
+ -- Create the return value.
644
+ create or replace view ups_null_error_list as
645
+ select
646
+ group_concat(concat(column_name, ' (', cast(null_rows as varchar(100)), ')') separator ', ') as null_errors
647
+ from
648
+ ups_nonnull_columns
649
+ where
650
+ coalesce(null_rows, 0) > 0;
651
+ -- !x! if(hasrows(ups_null_error_list))
652
+ -- !x! subdata !!#error_list!! ups_null_error_list
653
+ -- !x! endif
654
+
655
+ -- Clean up.
656
+ drop view if exists ups_null_error_list;
657
+ drop view if exists ups_next_column cascade;
658
+ drop table if exists ups_nonnull_columns cascade;
659
+
660
+ -- !x! END SCRIPT
661
+ -- End of NULLQA_ONE
662
+ -- ****************************************************************
663
+ -- ****************************************************************
664
+ -- Script NULLQA_ONE_INNERLOOP
665
+ -- ---------------------------------------------------------------
666
+ -- !x! BEGIN SCRIPT NULLQA_ONE_INNERLOOP with parameters (stage_pfx, table)
667
+
668
+ -- !x! if(hasrows(ups_next_column))
669
+ -- !x! subdata ~column_name ups_next_column
670
+
671
+ -- !x! if(sub_defined(logfile))
672
+ -- !x! write "Checking column !!~column_name!!." to !!logfile!!
673
+ -- !x! endif
674
+
675
+ create or replace view ups_qa_nonnull_col as
676
+ select nrows
677
+ from (
678
+ select count(*) as nrows
679
+ from !!#stage_pfx!!!!#table!!
680
+ where !!~column_name!! is null
681
+ ) as nullcount
682
+ where nrows > 0
683
+ limit 1;
684
+ -- !x! if(hasrows(ups_qa_nonnull_col))
685
+ -- !x! subdata ~nullrows ups_qa_nonnull_col
686
+ -- !x! write " Column !!~column_name!! has !!~nullrows!! nulls."
687
+ -- !x! if(sub_defined(logfile))
688
+ -- !x! write " Column !!~column_name!! has !!~nullrows!! nulls." to !!logfile!!
689
+ -- !x! endif
690
+ update ups_nonnull_columns
691
+ set null_rows = (select nrows from ups_qa_nonnull_col limit 1)
692
+ where column_name = '!!~column_name!!';
693
+ -- !x! endif
694
+
695
+ -- Mark this constraint as processed.
696
+ update ups_nonnull_columns
697
+ set processed = 1
698
+ where column_name = '!!~column_name!!';
699
+
700
+ -- Loop.
701
+ -- !x! execute script nullqa_one_innerloop with (stage_pfx=!!#stage_pfx!!, table=!!#table!!)
702
+
703
+ -- !x! endif
704
+
705
+ -- Clean up.
706
+ -- !x! if(view_exists(ups_qa_nonnull_col))
707
+ drop view if exists ups_qa_nonnull_col;
708
+ -- !x! endif
709
+
710
+
711
+ -- !x! END SCRIPT
712
+ -- ################### End of NULL_QA_ONE #######################
713
+ -- ################################################################
714
+
715
+
716
+
717
+ -- ################################################################
718
+ -- Script PKQA_ONE
719
+ --
720
+ -- Check data in a staging table for violations of the primary key
721
+ -- of the corresponding base table.
722
+ -- Reports any PK violations found to the console and optionally
723
+ -- to a log file.
724
+ --
725
+ -- Input parameters:
726
+ -- stage_pfx : The name of the staging schema.
727
+ -- table : The table name--same for base and staging.
728
+ -- display_errors : A value of 'Yes' or 'No' to indicate whether
729
+ -- unrecognized values should be displayed
730
+ -- in a GUI.
731
+ -- Output parameters:
732
+ -- error_list : The name of the variable to receive a count
733
+ -- of the total number of distinct PK values
734
+ -- having violations, followed by a count of
735
+ -- the total rows associated with each.
736
+ --
737
+ -- Global variables:
738
+ -- logfile : The name of a log file to which update
739
+ -- messages will be written. Optional.
740
+ -- log_sql : A value of 'Yes' or 'No' to indicate whether
741
+ -- the SQL that is generated for each foreign
742
+ -- key check is written to the logfile. Optional.
743
+ -- log_errors : A value of 'Yes' or 'No' to indicate whether
744
+ -- foreign key errors are written to the logfile.
745
+ -- Optional.
746
+ --
747
+ -- Tables and views created or modified:
748
+ -- ups_primary_key_columns : table
749
+ -- ups_pk_check : table
750
+ -- ups_ercnt : view
751
+ -- ===============================================================
752
+
753
+ -- !x! BEGIN SCRIPT PKQA_ONE with parameters (stage_pfx, table, display_errors, error_list)
754
+
755
+ -- Write an initial header to the logfile.
756
+ -- !x! if(sub_defined(logfile))
757
+ -- !x! write "" to !!logfile!!
758
+ -- !x! write "==================================================================" to !!logfile!!
759
+ -- !x! write "!!$current_time!! -- Primary key QA checks on table !!#stage_pfx!!!!#table!!" to !!logfile!!
760
+ -- !x! endif
761
+
762
+ -- !x! write "Conducting primary key QA checks on table !!#stage_pfx!!!!#table!!"
763
+
764
+ -- Validate input table specifications.
765
+ -- !x! execute script validate_one with args (stage_pfx=!!#stage_pfx!!, table=!!#table!!, script=!!$CURRENT_SCRIPT!!, script_line=!!$SCRIPT_LINE!!)
766
+
767
+ -- Initialize the return value to False (no primary key errors)
768
+ -- !x! sub_empty !!#error_list!!
769
+
770
+ -- Create a table of primary key columns on this table
771
+ -- !x! if(table_exists(ups_primary_key_columns))
772
+ drop table ups_primary_key_columns cascade;
773
+ -- !x! endif
774
+ create table ups_primary_key_columns
775
+ select k.constraint_name, k.column_name, k.ordinal_position
776
+ from information_schema.table_constraints as tc
777
+ inner join information_schema.key_column_usage as k
778
+ on tc.constraint_type = 'PRIMARY KEY'
779
+ and tc.constraint_name = k.constraint_name
780
+ and tc.constraint_catalog = k.constraint_catalog
781
+ and tc.constraint_schema = k.constraint_schema
782
+ and tc.table_schema = k.table_schema
783
+ and tc.table_name = k.table_name
784
+ and tc.constraint_name = k.constraint_name
785
+ where
786
+ k.table_name = '!!#table!!'
787
+ and tc.constraint_schema = '!!$db_name!!'
788
+ order by k.ordinal_position
789
+ ;
790
+
791
+ -- !x! if(hasrows(ups_primary_key_columns))
792
+ -- !x! subdata ~constraint_name ups_primary_key_columns
793
+
794
+ -- !x! if(sub_defined(logfile))
795
+ -- !x! write "Checking constraint !!~constraint_name!!." to !!logfile!!
796
+ -- !x! endif
797
+
798
+ -- Get a comma-delimited list of primary key columns to build SQL selection for duplicate keys
799
+ -- !x! sub_empty ~pkcollist
800
+ -- !x! if(view_exists(ups_pkcollist))
801
+ drop view if exists ups_pkcollist cascade;
802
+ -- !x! endif
803
+ create view ups_pkcollist as
804
+ select group_concat(column_name separator ', ') as col_list
805
+ from ups_primary_key_columns
806
+ order by ordinal_position;
807
+ -- !x! subdata ~pkcollist ups_pkcollist
808
+
809
+ -- Construct a query to test for duplicate values for pk columns.
810
+ -- !x! sub ~pk_check select !!~pkcollist!!, count(*) as row_count
811
+ -- !x! sub_append ~pk_check from !!#stage_pfx!!!!#table!! as s
812
+ -- !x! sub_append ~pk_check group by !!~pkcollist!!
813
+ -- !x! sub_append ~pk_check having count(*) > 1
814
+
815
+ -- Write the SQL to the log file if requested.
816
+ -- !x! if(sub_defined(logfile))
817
+ -- !x! andif(sub_defined(log_sql))
818
+ -- !x! andif(is_true(!!log_sql!!))
819
+ -- !x! write "SQL for primary key check:" to !!logfile!!
820
+ -- !x! write [!!~pk_check!!] to !!logfile!!
821
+ -- !x! endif
822
+
823
+ -- Run the check.
824
+ -- !x! if(table_exists(ups_pk_check))
825
+ drop table if exists ups_pk_check cascade;
826
+ -- !x! endif
827
+ create table ups_pk_check
828
+ !!~pk_check!!;
829
+ -- !x! if(hasrows(ups_pk_check))
830
+ -- !x! write " Duplicate key error on columns: !!~pkcollist!!."
831
+ -- !x! if(view_exists(ups_ercnt))
832
+ drop view if exists ups_ercnt cascade;
833
+ -- !x! endif
834
+ create view ups_ercnt
835
+ select count(*) as errcnt, sum(row_count) as total_rows
836
+ from ups_pk_check;
837
+ -- !x! select_sub ups_ercnt
838
+ -- !x! sub !!#error_list!! !!@errcnt!! duplicated key(s) (!!@total_rows!! rows)
839
+ -- !x! if(sub_defined(logfile))
840
+ -- !x! write "Duplicate primary key values in !!#table!!" to !!logfile!!
841
+ -- !x! if(sub_defined(log_errors))
842
+ -- !x! andif(is_true(!!log_errors!!))
843
+ -- !x! export ups_pk_check append to !!logfile!! as txt
844
+ -- !x! endif
845
+ -- !x! endif
846
+ -- !x! if(is_true(!!#display_errors!!))
847
+ -- !x! prompt message "Primary key violations in !!stage_pfx!!!!#table!!" display ups_pk_check
848
+ -- !x! endif
849
+ -- !x! endif
850
+ -- !x! endif
851
+
852
+ -- Clean up.
853
+ drop view if exists ups_pkcollist cascade;
854
+ drop table if exists ups_primary_key_columns cascade;
855
+ drop table if exists ups_pk_check cascade;
856
+ -- !x! if(view_exists(ups_ercnt))
857
+ drop view if exists ups_ercnt cascade;
858
+ -- !x! endif
859
+
860
+
861
+ -- !x! END SCRIPT
862
+ -- #################### End of PKQA_ONE ########################
863
+ -- ################################################################
864
+
865
+
866
+
867
+ -- ################################################################
868
+ -- Script FKQA_ONE
869
+ --
870
+ -- Checks foreign keys from a staging table against a base table
871
+ -- and, if it exists, another staging table that is an image of the
872
+ -- base table.
873
+ -- Reports any bad references found to the console and optionally
874
+ -- to a log file.
875
+ --
876
+ -- Input parameters:
877
+ -- stage_pfx : The prefix for staging table names.
878
+ -- table : The table name--same for base and staging.
879
+ -- display_errors : A value of 'Yes' or 'No' to indicate whether
880
+ -- unrecognized values should be displayed
881
+ -- in a GUI. If not defined, unrecognized
882
+ -- values are not displayed.
883
+ -- Output parameters:
884
+ -- error_list : The name of the variable to receive a comma-
885
+ -- delimited list of the names of foreign key
886
+ -- constraints that are not met.
887
+ --
888
+ -- Global variables:
889
+ -- logfile : The name of a log file to which update
890
+ -- messages will be written. Optional.
891
+ -- log_sql : A value of 'Yes' or 'No' to indicate whether
892
+ -- the SQL that is generated for each foreign
893
+ -- key check is written to the logfile. Optional.
894
+ -- log_errors : A value of 'Yes' or 'No' to indicate whether
895
+ -- foreign key errors are written to the logfile.
896
+ -- Optional.
897
+ --
898
+ -- Tables and views created or modified:
899
+ -- ups_foreign_key_columns : table
900
+ -- ups_sel_fks : table
901
+ -- ups_fk_constraints : table
902
+ -- ups_next_constraint : view
903
+ -- ups_error_list : view
904
+ -- ups_one_fk : table
905
+ -- ups_fk_joins : view
906
+ -- ups_fk_check : view
907
+ -- ups_ercnt : view
908
+ -- ===============================================================
909
+
910
+ -- !x! BEGIN SCRIPT FKQA_ONE with parameters (stage_pfx, table, display_errors, error_list)
911
+
912
+ -- Write an initial header to the logfile.
913
+ -- !x! if(sub_defined(logfile))
914
+ -- !x! write "" to !!logfile!!
915
+ -- !x! write "==================================================================" to !!logfile!!
916
+ -- !x! write "!!$current_time!! -- Foreign key QA checks on table !!#stage_pfx!!!!#table!!" to !!logfile!!
917
+ -- !x! endif
918
+
919
+ -- !x! write "Conducting foreign key QA checks on table !!#stage_pfx!!!!#table!!"
920
+
921
+ -- Validate input table specifications.
922
+ -- !x! execute script validate_one with args (stage_pfx=!!#stage_pfx!!, table=!!#table!!, script=!!$CURRENT_SCRIPT!!, script_line=!!$SCRIPT_LINE!!)
923
+
924
+ -- Initialize the return value to False (no foreign key errors)
925
+ -- !x! sub_empty !!#error_list!!
926
+
927
+
928
+ -- Create a table of *all* foreign key dependencies in this database.
929
+ -- Because this may be an expensive operation (in terms of time), the
930
+ -- table is not re-created if it already exists. "Already exists"
931
+ -- means that a table with the expected name exists. No check is
932
+ -- done to ensure that this table has the correct structure. The
933
+ -- goal is to create the table of all foreign keys only once to
934
+ -- minimize the time required if QA checks are to be run on multiple
935
+ -- staging tables.
936
+ -- !x! if(not table_exists(ups_foreign_key_columns))
937
+ create table ups_foreign_key_columns
938
+ select
939
+ rc.constraint_name,
940
+ cu.table_schema,
941
+ cu.table_name,
942
+ cu.column_name,
943
+ cu.ordinal_position,
944
+ cu_uq.table_schema as uq_schema,
945
+ cu_uq.table_name as uq_table,
946
+ cu_uq.column_name as uq_column,
947
+ cu_uq.ordinal_position as uq_position
948
+ from
949
+ (select constraint_catalog, constraint_schema, constraint_name,
950
+ table_name,
951
+ unique_constraint_catalog, unique_constraint_schema, unique_constraint_name,
952
+ referenced_table_name
953
+ from information_schema.referential_constraints
954
+ where constraint_schema = '!!$db_name!!'
955
+ ) as rc
956
+ inner join (select * from information_schema.table_constraints
957
+ where constraint_type = 'FOREIGN KEY' and constraint_schema = '!!$db_name!!'
958
+ ) as tc
959
+ on tc.constraint_catalog = rc.constraint_catalog
960
+ and tc.constraint_schema = rc.constraint_schema
961
+ and tc.constraint_name = rc.constraint_name
962
+ and tc.table_name = rc.table_name
963
+ inner join (select * from information_schema.table_constraints
964
+ where constraint_type not in ('FOREIGN KEY', 'CHECK')
965
+ and constraint_schema = '!!$db_name!!'
966
+ ) as tc_uq
967
+ on tc_uq.constraint_catalog = rc.unique_constraint_catalog
968
+ and tc_uq.constraint_schema = rc.unique_constraint_schema
969
+ and tc_uq.constraint_name = rc.unique_constraint_name
970
+ and tc_uq.table_name = rc.referenced_table_name
971
+ inner join information_schema.key_column_usage as cu
972
+ on cu.constraint_catalog = tc.constraint_catalog
973
+ and cu.constraint_schema = tc.constraint_schema
974
+ and cu.constraint_name = tc.constraint_name
975
+ and cu.table_schema = tc.table_schema
976
+ and cu.table_name = tc.table_name
977
+ inner join information_schema.key_column_usage as cu_uq
978
+ on cu_uq.constraint_catalog = tc_uq.constraint_catalog
979
+ and cu_uq.constraint_schema = tc_uq.constraint_schema
980
+ and cu_uq.constraint_name = tc_uq.constraint_name
981
+ and cu_uq.table_schema = tc_uq.table_schema
982
+ and cu_uq.table_name = tc_uq.table_name
983
+ and cu_uq.ordinal_position = cu.ordinal_position
984
+ ;
985
+ -- !x! endif
986
+
987
+ -- Create a temporary table of just the foreign key relationships for the base
988
+ -- table corresponding to the staging table to check.
989
+ -- !x! if(table_exists(ups_sel_fks))
990
+ drop table if exists ups_sel_fks cascade;
991
+ -- !x! endif
992
+ create table ups_sel_fks
993
+ select
994
+ constraint_name, table_schema, table_name, column_name,
995
+ ordinal_position,
996
+ uq_schema, uq_table, uq_column
997
+ from
998
+ ups_foreign_key_columns
999
+ where
1000
+ table_schema = '!!$DB_NAME!!'
1001
+ and table_name = '!!#table!!';
1002
+
1003
+ -- Create a table of all unique constraint names for
1004
+ -- this table, with an integer column to be populated with the
1005
+ -- number of rows failing the foreign key check, and a 'processed'
1006
+ -- flag to control looping.
1007
+ -- !x! if(table_exists(ups_fk_constraints))
1008
+ drop table if exists ups_fk_constraints cascade;
1009
+ -- !x! endif
1010
+ create table ups_fk_constraints
1011
+ select distinct
1012
+ constraint_name,
1013
+ 0 as fkerror_values,
1014
+ 0 as processed
1015
+ from ups_sel_fks;
1016
+
1017
+ -- Create a view to select one constraint to process.
1018
+ create or replace view ups_next_constraint as
1019
+ select constraint_name
1020
+ from ups_fk_constraints
1021
+ where processed = 0
1022
+ limit 1;
1023
+
1024
+ -- Process all constraints: check every foreign key.
1025
+ -- !x! execute script fk_qa_one_innerloop with (stage_pfx=!!#stage_pfx!!, table=!!#table!!, display_errors=!!#display_errors!!)
1026
+
1027
+ -- Create the return value.
1028
+ create or replace view ups_error_list as
1029
+ select
1030
+ group_concat(concat(constraint_name, ' (', fkerror_values, ')') separator ', ') as fk_errors
1031
+ from
1032
+ ups_fk_constraints
1033
+ where
1034
+ coalesce(fkerror_values, 0) > 0;
1035
+ -- !x! if(hasrows(ups_error_list))
1036
+ -- !x! subdata !!#error_list!! ups_error_list
1037
+ -- !x! endif
1038
+
1039
+ -- Clean up.
1040
+ drop view if exists ups_error_list cascade;
1041
+ drop view if exists ups_next_constraint cascade;
1042
+ drop table if exists ups_fk_constraints cascade;
1043
+ drop table if exists ups_sel_fks;
1044
+
1045
+ -- !x! END SCRIPT
1046
+ -- End of FK_QA_ONE
1047
+ -- ****************************************************************
1048
+ -- ****************************************************************
1049
+ -- Script FK_QA_ONE_INNERLOOP
1050
+ -- ----------------------------------------------------------------
1051
+ -- !x! BEGIN SCRIPT FK_QA_ONE_INNERLOOP with parameters (stage_pfx, table, display_errors)
1052
+
1053
+ -- !x! if(hasrows(ups_next_constraint))
1054
+ -- !x! subdata constraint_name ups_next_constraint
1055
+
1056
+ -- !x! if(sub_defined(logfile))
1057
+ -- !x! write "Checking constraint !!constraint_name!!." to !!logfile!!
1058
+ -- !x! endif
1059
+
1060
+ -- !x! if(table_exists(ups_one_fk))
1061
+ drop table if exists ups_one_fk cascade;
1062
+ -- !x! endif
1063
+ create table ups_one_fk
1064
+ select column_name, ordinal_position, uq_schema, uq_table, uq_column
1065
+ from ups_sel_fks
1066
+ where constraint_name = '!!constraint_name!!';
1067
+
1068
+ -- Get the unique table schema and name into data variables.
1069
+ -- !x! select_sub ups_one_fk
1070
+
1071
+ -- Create join expressions from staging table (s) to unique table (u)
1072
+ -- and to staging table equivalent to unique table (su) (though we
1073
+ -- don't know yet if the latter exists). Also create a 'where'
1074
+ -- condition to ensure that all columns being matched are non-null.
1075
+ -- Also create a comma-separated list of the columns being checked.
1076
+ create or replace view ups_fk_joins as
1077
+ select
1078
+ group_concat(concat('s.', column_name, ' = u.', uq_column) separator ' and ') as u_join,
1079
+ group_concat(concat('s.', column_name, ' = su.', uq_column) separator ' and ') as su_join,
1080
+ group_concat(concat('s.', column_name, ' is not null') separator ' and ') as s_not_null,
1081
+ group_concat(concat('s.', column_name) separator ', ') as s_checked
1082
+ from
1083
+ (select * from ups_one_fk order by ordinal_position) as fkcols;
1084
+ -- !x! select_sub ups_fk_joins
1085
+
1086
+ -- Determine whether a staging-table equivalent of the unique table exists.
1087
+ -- !x! sub su_exists No
1088
+ -- !x! if(table_exists(!!#stage_pfx!!!!@uq_table!!))
1089
+ -- !x! sub su_exists Yes
1090
+ -- !x! endif
1091
+
1092
+ -- Construct a query to test for missing unique values for fk columns.
1093
+ -- !x! sub ~fk_check select !!@s_checked!!, count(*) as row_count
1094
+ -- !x! sub_append ~fk_check from !!#stage_pfx!!!!#table!! as s
1095
+ -- !x! sub_append ~fk_check left join !!@uq_table!! as u on !!@u_join!!
1096
+ -- !x! if(is_true(!!su_exists!!))
1097
+ -- !x! sub_append ~fk_check left join !!#stage_pfx!!!!@uq_table!! as su on !!@su_join!!
1098
+ -- !x! endif
1099
+ -- !x! sub_append ~fk_check where u.!!@uq_column!! is null
1100
+ -- !x! if(is_true(!!su_exists!!))
1101
+ -- !x! sub_append ~fk_check and su.!!@uq_column!! is null
1102
+ -- !x! endif
1103
+ -- !x! sub_append ~fk_check and !!@s_not_null!!
1104
+ -- !x! sub_append ~fk_check group by !!@s_checked!!
1105
+
1106
+ -- Write the SQL to the log file if requested.
1107
+ -- !x! if(sub_defined(logfile))
1108
+ -- !x! andif(sub_defined(log_sql))
1109
+ -- !x! andif(is_true(!!log_sql!!))
1110
+ -- !x! write "SQL for foreign key check:" to !!logfile!!
1111
+ -- !x! write [!!~fk_check!!] to !!logfile!!
1112
+ -- !x! endif
1113
+
1114
+ -- Run the check.
1115
+ create or replace view ups_fk_check as !!~fk_check!!;
1116
+ -- !x! if(hasrows(ups_fk_check))
1117
+ -- !x! write " Foreign key error referencing !!@uq_table!!."
1118
+ create or replace view ups_ercnt as select count(*) from ups_fk_check;
1119
+ -- !x! subdata ~errcnt ups_ercnt
1120
+ update ups_fk_constraints
1121
+ set fkerror_values = !!~errcnt!!
1122
+ where constraint_name = '!!constraint_name!!';
1123
+ -- !x! if(sub_defined(logfile))
1124
+ -- !x! write " Foreign key errors in !!#table!! referencing !!@uq_table!!" to !!logfile!!
1125
+ -- !x! if(sub_defined(log_errors))
1126
+ -- !x! andif(is_true(!!log_errors!!))
1127
+ -- !x! export ups_fk_check append to !!logfile!! as txt
1128
+ -- !x! endif
1129
+ -- !x! endif
1130
+ -- !x! if(is_true(!!#display_errors!!))
1131
+ -- !x! prompt message "Foreign key errors in !!#table!! referencing !!@uq_table!!" display ups_fk_check
1132
+ -- !x! endif
1133
+ -- !x! endif
1134
+
1135
+
1136
+ -- Mark this constraint as processed.
1137
+ update ups_fk_constraints
1138
+ set processed = 1
1139
+ where constraint_name = '!!constraint_name!!';
1140
+
1141
+ -- Loop.
1142
+ -- !x! execute script fk_qa_one_innerloop with (stage_pfx=!!#stage_pfx!!, table=!!#table!!, display_errors=!!#display_errors!!)
1143
+
1144
+ -- !x! endif
1145
+
1146
+ -- Clean up.
1147
+ -- !x! if(view_exists(ups_fk_check))
1148
+ drop view if exists ups_fk_check cascade;
1149
+ -- !x! endif
1150
+ -- !x! if(view_exists(ups_fk_joins))
1151
+ drop view if exists ups_fk_joins cascade;
1152
+ -- !x! endif
1153
+ -- !x! if(table_exists(ups_foreign_key_columns))
1154
+ drop table if exists ups_foreign_key_columns cascade;
1155
+ -- !x! endif
1156
+
1157
+ -- Clean up.
1158
+ -- !x! if(table_exists(ups_one_fk))
1159
+ drop table if exists ups_one_fk cascade;
1160
+ -- !x! endif
1161
+
1162
+ -- !x! END SCRIPT
1163
+ -- #################### End of FK_QA_ONE ########################
1164
+ -- ################################################################
1165
+
1166
+
1167
+
1168
+
1169
+ -- ################################################################
1170
+ -- Script UPSERT_ONE
1171
+ --
1172
+ -- Adds data from a staging table to a base table, using UPDATE
1173
+ -- and INSERT statements. Displays data to be modified to the
1174
+ -- user before any modifications are done. Reports the changes
1175
+ -- made to the console and optionally to a log file.
1176
+ --
1177
+ -- Input parameters:
1178
+ -- stage_pfx : The name of the staging schema.
1179
+ -- table : The table name--same for base and staging.
1180
+ -- exclude_cols : A comma-delimited list of single-quoted
1181
+ -- column names identifying the columns
1182
+ -- of the base table that are not to be
1183
+ -- modified. These may be autonumber
1184
+ -- columns or columns filled by triggers.
1185
+ -- display_changes : A boolean variable indicating whether
1186
+ -- or not the changes to be made to the
1187
+ -- base table should be displayed in a GUI.
1188
+ -- Optional. If not defined, the changes
1189
+ -- will be defined.
1190
+ -- display_final : A boolean variable indicating whether or
1191
+ -- not the base table should be displayed
1192
+ -- after updates and inserts are completed.
1193
+ -- Optional. If not defined, the final
1194
+ -- base table will not be displayed.
1195
+ -- updcntvar : The name of a substitution variable that
1196
+ -- will be set to the number of rows updated.
1197
+ -- inscntvar : The name of a substitution variable that
1198
+ -- will be set to the number of rows inserted.
1199
+ --
1200
+ -- Global variables:
1201
+ -- logfile : The name of a log file to which update
1202
+ -- messages will be written. Optional.
1203
+ -- log_sql : A value of 'Yes' or 'No' indicating whether
1204
+ -- the update and insert statements should
1205
+ -- also be written to the logfile. Optional.
1206
+ -- log_changes : A value of 'Yes' or 'No' indicating whether
1207
+ -- the updated and inserted data should be
1208
+ -- written to the logfile. Optional.
1209
+ --
1210
+ -- Tables and views created or modified:
1211
+ -- ups_cols : table
1212
+ -- ups_pks : table
1213
+ -- ups_allcollist : temporary view
1214
+ -- ups_allbasecollist : temporary view
1215
+ -- ups_allstgcollist : temporary view
1216
+ -- ups_pkcollist : temporary view
1217
+ -- ups_joinexpr : temporary view
1218
+ -- ups_basematches : temporary view
1219
+ -- ups_stgmatches : temporary view
1220
+ -- ups_assexpr : temporary view
1221
+ -- ups_newrows : temporary view
1222
+ -- ===============================================================
1223
+
1224
+ -- !x! BEGIN SCRIPT UPSERT_ONE with parameters (stage_pfx, table, exclude_cols, display_changes, display_final, updcntvar, inscntvar)
1225
+
1226
+ -- Remove substitution variables that will contain the generated
1227
+ -- update and insert statements so that the existence of valid
1228
+ -- statements can be later tested based on the existence of these variables.
1229
+ -- !x! rm_sub ~updatestmt
1230
+ -- !x! rm_sub ~insertstmt
1231
+
1232
+ -- !x! sub ~do_updates Yes
1233
+ -- !x! sub ~do_inserts Yes
1234
+
1235
+ -- !x! if(sub_defined(logfile))
1236
+ -- !x! write "" to !!logfile!!
1237
+ -- !x! write "==================================================================" to !!logfile!!
1238
+ -- !x! write "!!$current_time!! -- Performing upsert on table !!#table!!" to !!logfile!!
1239
+ -- !x! endif
1240
+
1241
+ -- !x! write "Performing upsert on table !!#table!!"
1242
+
1243
+ -- Validate input table specifications.
1244
+ -- !x! execute script validate_one with args (stage_pfx=!!#stage_pfx!!, table=!!#table!!, script=!!$CURRENT_SCRIPT!!, script_line=!!$SCRIPT_LINE!!)
1245
+
1246
+ -- Populate a (temporary) table with the names of the columns
1247
+ -- in the base table that are to be updated from the staging table.
1248
+ -- !x! if(is_null("!!#exclude_cols!!"))
1249
+ -- !x! sub_empty ~col_excl
1250
+ -- !x! else
1251
+ -- !x! sub ~col_excl and column_name not in (!!#exclude_cols!!)
1252
+ -- !x! endif
1253
+ -- !x! if(table_exists(ups_cols))
1254
+ drop table if exists ups_cols cascade;
1255
+ -- !x! endif
1256
+ create table ups_cols
1257
+ select column_name
1258
+ from information_schema.columns
1259
+ where
1260
+ table_name = '!!#stage_pfx!!!!#table!!'
1261
+ and table_schema = '!!$DB_NAME!!'
1262
+ !!~col_excl!!
1263
+ order by ordinal_position;
1264
+
1265
+
1266
+ -- Populate a (temporary) table with the names of the primary key
1267
+ -- columns of the base table.
1268
+ -- !x! if(table_exists(ups_pks))
1269
+ drop table if exists ups_pks cascade;
1270
+ -- !x! endif
1271
+ create table ups_pks
1272
+ select k.column_name
1273
+ from information_schema.table_constraints as tc
1274
+ inner join information_schema.key_column_usage as k
1275
+ on tc.constraint_type = 'PRIMARY KEY'
1276
+ and tc.constraint_name = k.constraint_name
1277
+ and tc.constraint_catalog = k.constraint_catalog
1278
+ and tc.constraint_schema = k.constraint_schema
1279
+ and tc.table_schema = k.table_schema
1280
+ and tc.table_name = k.table_name
1281
+ and tc.constraint_name = k.constraint_name
1282
+ where
1283
+ k.table_name = '!!#table!!'
1284
+ and k.table_schema = '!!$DB_NAME!!'
1285
+ order by k.ordinal_position;
1286
+
1287
+ -- Get all base table columns that are to be updated into a comma-delimited list.
1288
+ -- !x! if(view_exists(ups_allcollist))
1289
+ drop view ups_allcollist cascade;
1290
+ -- !x! endif
1291
+ create view ups_allcollist as
1292
+ select group_concat(column_name separator ', ')
1293
+ from ups_cols;
1294
+ -- !x! subdata ~allcollist ups_allcollist;
1295
+
1296
+
1297
+ -- Get all base table columns that are to be updated into a comma-delimited list
1298
+ -- with a "b." prefix.
1299
+ -- !x! if(view_exists(ups_allbasecollist))
1300
+ drop view ups_allbasecollist cascade;
1301
+ -- !x! endif
1302
+ create view ups_allbasecollist as
1303
+ select group_concat(concat('b.', column_name) separator ', ')
1304
+ from ups_cols;
1305
+ -- !x! subdata ~allbasecollist ups_allbasecollist;
1306
+
1307
+ -- Get all staging table column names for columns that are to be updated
1308
+ -- into a comma-delimited list with an "s." prefix.
1309
+ -- !x! if(view_exists(ups_allstgcollist))
1310
+ drop view ups_allstgcollist cascade;
1311
+ -- !x! endif
1312
+ create view ups_allstgcollist as
1313
+ select group_concat(concat('s.', column_name) separator ', ')
1314
+ from ups_cols;
1315
+ -- !x! subdata ~allstgcollist ups_allstgcollist;
1316
+
1317
+
1318
+ -- Get the primary key columns in a comma-delimited list.
1319
+ -- !x! if(view_exists(ups_pkcollist))
1320
+ drop view ups_pkcollist cascade;
1321
+ -- !x! endif
1322
+ create view ups_pkcollist as
1323
+ select group_concat(column_name separator ', ')
1324
+ from ups_pks;
1325
+ -- !x! subdata ~pkcollist ups_pkcollist;
1326
+
1327
+
1328
+ -- Create a join expression for key columns of the base (b) and
1329
+ -- staging (s) tables.
1330
+ -- !x! if(view_exists(ups_joinexpr))
1331
+ drop view ups_joinexpr cascade;
1332
+ -- !x! endif
1333
+ create view ups_joinexpr as
1334
+ select
1335
+ group_concat(concat('b.', column_name, ' = s.', column_name) separator ' and ')
1336
+ from
1337
+ ups_pks;
1338
+ -- !x! subdata ~joinexpr ups_joinexpr
1339
+
1340
+
1341
+ -- Create a FROM clause for an inner join between base and staging
1342
+ -- tables on the primary key column(s).
1343
+ -- !x! sub ~fromclause FROM !!#table!! as b INNER JOIN !!#stage_pfx!!!!#table!! as s ON !!~joinexpr!!
1344
+
1345
+ -- Create SELECT queries to pull all columns with matching keys from both
1346
+ -- base and staging tables.
1347
+ -- !x! if(view_exists(ups_basematches))
1348
+ drop view ups_basematches cascade;
1349
+ -- !x! endif
1350
+ create view ups_basematches as select !!~allbasecollist!! !!~fromclause!!;
1351
+
1352
+ -- !x! if(view_exists(ups_stgmatches))
1353
+ drop view ups_stgmatches cascade;
1354
+ -- !x! endif
1355
+ create view ups_stgmatches as select !!~allstgcollist!! !!~fromclause!!;
1356
+
1357
+ -- Get non-key columns to be updated.
1358
+ -- !x! if(view_exists(ups_nk))
1359
+ drop view if exists ups_nk cascade;
1360
+ -- !x! endif
1361
+ create view ups_nk as
1362
+ select cols.column_name
1363
+ from
1364
+ ups_cols as cols
1365
+ left join ups_pks as pks on pks.column_name = cols.column_name
1366
+ where
1367
+ pks.column_name is null;
1368
+
1369
+ -- Prompt user to examine matching data and commit, don't commit, or quit.
1370
+ -- !x! if(hasrows(ups_stgmatches))
1371
+ -- !x! andif(hasrows(ups_nk))
1372
+ -- !x! if(is_true(!!#display_changes!!))
1373
+ -- !x! prompt ask "Do you want to make these changes? For table !!#table!!, new data are shown in the top table below; existing data are in the lower table." sub ~do_updates compare ups_stgmatches and ups_basematches key (!!~pkcollist!!)
1374
+ -- !x! endif
1375
+
1376
+ -- !x! if(is_true(!!~do_updates!!))
1377
+ -- Create an assignment expression to update non-key columns of the
1378
+ -- base table (un-aliased) from columns of the staging table (as s).
1379
+ -- !x! if(view_exists(ups_assexpr))
1380
+ drop view ups_assexpr cascade;
1381
+ -- !x! endif
1382
+ create view ups_assexpr as
1383
+ select
1384
+ group_concat(concat('b.', column_name, ' = s.', column_name) separator ', ') as col
1385
+ from
1386
+ ups_nk;
1387
+ -- !x! subdata ~assexpr ups_assexpr
1388
+
1389
+ -- Create an UPDATE statement to update the base table with
1390
+ -- non-key columns from the staging table. No semicolon terminating generated SQL.
1391
+ -- !x! sub ~updatestmt UPDATE !!#table!! as b, !!#stage_pfx!!!!#table!! as s SET !!~assexpr!! WHERE !!~joinexpr!!
1392
+ -- !x! endif
1393
+ -- !x! endif
1394
+
1395
+
1396
+ -- Create a select statement to find all rows of the staging table
1397
+ -- that are not in the base table.
1398
+ -- !x! if(view_exists(ups_newrows))
1399
+ drop view ups_newrows cascade;
1400
+ -- !x! endif
1401
+ create view ups_newrows as
1402
+ with newpks as (
1403
+ select !!~pkcollist!! from !!#stage_pfx!!!!#table!!
1404
+ except
1405
+ select !!~pkcollist!! from !!#table!!
1406
+ )
1407
+ select
1408
+ s.*
1409
+ from
1410
+ !!#stage_pfx!!!!#table!! as s
1411
+ inner join newpks using (!!~pkcollist!!);
1412
+
1413
+
1414
+ -- Prompt user to examine new data and continue or quit.
1415
+ -- !x! if(hasrows(ups_newrows))
1416
+ -- !x! if(is_true(!!#display_changes!!))
1417
+ -- !x! prompt ask "Do you want to add these new data to the !!#table!! table?" sub ~do_inserts display ups_newrows
1418
+ -- !x! endif
1419
+
1420
+ -- !x! if(is_true(!!~do_inserts!!))
1421
+ -- Create an insert statement. No semicolon terminating generated SQL.
1422
+ -- !x! sub ~insertstmt INSERT INTO !!#table!! (!!~allcollist!!) SELECT !!~allcollist!! FROM ups_newrows
1423
+ -- !x! endif
1424
+ -- !x! endif
1425
+
1426
+
1427
+ -- Run the update and insert statements.
1428
+
1429
+ -- !x! if(sub_defined(~updatestmt))
1430
+ -- !x! andif(is_true(!!~do_updates!!))
1431
+ -- !x! write "Updating !!#table!!"
1432
+ -- !x! if(sub_defined(logfile))
1433
+ -- !x! write "" to !!logfile!!
1434
+ -- !x! if(sub_defined(log_sql))
1435
+ -- !x! andif(is_true(!!log_sql!!))
1436
+ -- !x! write "UPDATE statement for !!#table!!:" to !!logfile!!
1437
+ -- !x! write [!!~updatestmt!!] to !!logfile!!
1438
+ -- !x! endif
1439
+ -- !x! if(sub_defined(log_changes))
1440
+ -- !x! andif(is_true(!!log_changes!!))
1441
+ -- !x! write "Updates:" to !!logfile!!
1442
+ -- !x! export ups_stgmatches append to !!logfile!! as txt
1443
+ -- !x! endif
1444
+ -- !x! write "" to !!logfile!!
1445
+ -- !x! endif
1446
+ !!~updatestmt!!;
1447
+ -- !x! sub !!#updcntvar!! !!$last_rowcount!!
1448
+ -- !x! if(sub_defined(logfile))
1449
+ -- !x! write "!!$last_rowcount!! rows of !!#table!! updated." to !!logfile!!
1450
+ -- !x! endif
1451
+ -- !x! write " !!$last_rowcount!! rows updated."
1452
+ -- !x! endif
1453
+
1454
+
1455
+ -- !x! if(sub_defined(~insertstmt))
1456
+ -- !x! andif(is_true(!!~do_inserts!!))
1457
+ -- !x! write "Adding data to !!#table!!"
1458
+ -- !x! if(sub_defined(logfile))
1459
+ -- !x! write "" to !!logfile!!
1460
+ -- !x! if(sub_defined(log_sql))
1461
+ -- !x! andif(is_true(!!log_sql!!))
1462
+ -- !x! write "INSERT statement for !!#table!!:" to !!logfile!!
1463
+ -- !x! write [!!~insertstmt!!] to !!logfile!!
1464
+ -- !x! endif
1465
+ -- !x! if(sub_defined(log_changes))
1466
+ -- !x! andif(is_true(!!log_changes!!))
1467
+ -- !x! write "New data:" to !!logfile!!
1468
+ -- !x! export ups_newrows append to !!logfile!! as txt
1469
+ -- !x! endif
1470
+ -- !x! write "" to !!logfile!!
1471
+ -- !x! endif
1472
+ !!~insertstmt!!;
1473
+ -- !x! sub !!#inscntvar!! !!$last_rowcount!!
1474
+ -- !x! if(sub_defined(logfile))
1475
+ -- !x! write "!!$last_rowcount!! rows added to !!#table!!." to !!logfile!!
1476
+ -- !x! endif
1477
+ -- !x! write " !!$last_rowcount!! rows added."
1478
+ -- !x! endif
1479
+
1480
+
1481
+ -- !x! if(is_true(!!#display_final!!))
1482
+ -- !x! prompt message "Table !!#table!! after updates and inserts." display !!#table!!
1483
+ -- !x! endif
1484
+
1485
+ -- Clean up.
1486
+ drop view if exists ups_newrows cascade;
1487
+ -- !x! if(view_exists(ups_assexpr))
1488
+ drop view ups_assexpr cascade;
1489
+ -- !x! endif
1490
+ drop view if exists ups_stgmatches cascade;
1491
+ drop view if exists ups_basematches cascade;
1492
+ drop view if exists ups_joinexpr cascade;
1493
+ drop view if exists ups_pkcollist cascade;
1494
+ drop view if exists ups_allstgcollist cascade;
1495
+ drop view if exists ups_allbasecollist cascade;
1496
+ drop view if exists ups_allcollist cascade;
1497
+ drop view if exists ups_nk cascade;
1498
+ drop table if exists ups_pks cascade;
1499
+ drop table if exists ups_cols cascade;
1500
+
1501
+
1502
+ -- !x! END SCRIPT
1503
+ -- ################### End of UPSERT_ONE ########################
1504
+ -- ################################################################
1505
+
1506
+
1507
+
1508
+
1509
+ -- ################################################################
1510
+ -- Script UPSERT_ALL
1511
+ --
1512
+ -- Updates multiple base tables with new or revised data from
1513
+ -- staging tables, using the UPSERT_ONE script.
1514
+ --
1515
+ -- Input parameters:
1516
+ -- stage_pfx : The name of the staging schema.
1517
+ -- control_table : The name of a table containing at least the
1518
+ -- following four columns:
1519
+ -- table_name : The name of a table
1520
+ -- to be updated.
1521
+ -- exclude_cols : A comma-delimited
1522
+ -- list of single-
1523
+ -- quoted column
1524
+ -- names, as required
1525
+ -- by UPDATE_ANY.
1526
+ -- display_changes : A value of "Yes" or
1527
+ -- "No" indicating
1528
+ -- whether the changes
1529
+ -- for the table should
1530
+ -- be displayed.
1531
+ -- display_final : A value of "Yes" or
1532
+ -- "No" indicating
1533
+ -- whether the final
1534
+ -- state of the table
1535
+ -- should be displayed.
1536
+ -- A table with these columns will be created
1537
+ -- by the script STAGED_TO_LOAD.
1538
+ --
1539
+ -- Global variables:
1540
+ -- logfile : The name of a log file to which update
1541
+ -- messages will be written. Optional.
1542
+ -- log_sql : A boolean variable indicating whether
1543
+ -- the update and insert statements should
1544
+ -- also be written to the logfile.
1545
+ --
1546
+ -- Tables and view used:
1547
+ -- ups_dependencies : table
1548
+ -- ups_ordered_tables : table
1549
+ -- ups_proctables : table
1550
+ -- ups_toprocess : view
1551
+ -- ups_upsert_rows : view
1552
+ -- ===============================================================
1553
+
1554
+ -- !x! BEGIN SCRIPT UPSERT_ALL with parameters (stage_pfx, control_table)
1555
+
1556
+ -- Validate contents of control table
1557
+ -- !x! execute script validate_control with (stage_pfx=!!#stage_pfx!!, control_table=!!#control_table!!, script=!!$CURRENT_SCRIPT_NAME!!, script_line=!!$SCRIPT_LINE!!)
1558
+
1559
+ -- Initialize the status and progress bars if the console is running.
1560
+ -- !x! if(console_on)
1561
+ -- !x! reset counter 221585944
1562
+ -- !x! console status "Merging data"
1563
+ -- !x! console progress 0
1564
+ -- !x! if(view_exists(ups_upsert_rows))
1565
+ drop view if exists ups_upsert_rows;
1566
+ -- !x! endif
1567
+ create view ups_upsert_rows as
1568
+ select count(*) + 1 as upsert_rows
1569
+ from !!#control_table!!;
1570
+ -- !x! subdata upsert_progress_denom ups_upsert_rows
1571
+ -- !x! endif
1572
+
1573
+
1574
+ -- Get a table of all dependencies for the base schema.
1575
+ -- !x! if(table_exists(ups_dependencies))
1576
+ drop table if exists ups_dependencies cascade;
1577
+ -- !x! endif
1578
+ create table ups_dependencies
1579
+ select distinct
1580
+ tc.table_name as child,
1581
+ tc_uq.table_name as parent
1582
+ from
1583
+ (select distinct constraint_catalog, constraint_schema, constraint_name,
1584
+ table_name,
1585
+ unique_constraint_catalog, unique_constraint_schema, unique_constraint_name,
1586
+ referenced_table_name
1587
+ from information_schema.referential_constraints
1588
+ where constraint_schema = '!!$DB_NAME!!') as rc
1589
+ inner join (select * from information_schema.table_constraints
1590
+ where constraint_type = 'FOREIGN KEY') as tc
1591
+ on tc.constraint_catalog = rc.constraint_catalog
1592
+ and tc.constraint_schema = rc.constraint_schema
1593
+ and tc.constraint_name = rc.constraint_name
1594
+ and tc.table_name = rc.table_name
1595
+ inner join (select * from information_schema.table_constraints
1596
+ where constraint_type not in ('FOREIGN KEY', 'CHECK') ) as tc_uq
1597
+ on tc_uq.constraint_catalog = rc.unique_constraint_catalog
1598
+ and tc_uq.constraint_schema = rc.unique_constraint_schema
1599
+ and tc_uq.constraint_name = rc.unique_constraint_name
1600
+ and tc_uq.table_name = rc.referenced_table_name
1601
+ ;
1602
+
1603
+ -- Create a list of tables in the base schema ordered by dependency.
1604
+ -- !x! if(table_exists(ups_ordered_tables))
1605
+ drop table if exists ups_ordered_tables cascade;
1606
+ -- !x! endif
1607
+ create table ups_ordered_tables
1608
+ with recursive dep_depth as (
1609
+ select
1610
+ dep.child as first_child,
1611
+ dep.child,
1612
+ dep.parent,
1613
+ 1 as lvl
1614
+ from
1615
+ ups_dependencies as dep
1616
+ union all
1617
+ select
1618
+ dd.first_child,
1619
+ dep.child,
1620
+ dep.parent,
1621
+ dd.lvl + 1 as lvl
1622
+ from
1623
+ dep_depth as dd
1624
+ inner join ups_dependencies as dep on dep.parent = dd.child
1625
+ and dep.child <> dd.parent
1626
+ and not (dep.parent = dd.first_child and dd.lvl > 2)
1627
+ )
1628
+ select
1629
+ table_name,
1630
+ table_order
1631
+ from (
1632
+ -- All parents
1633
+ select
1634
+ dd.parent as table_name,
1635
+ max(lvl) as table_order
1636
+ from
1637
+ dep_depth as dd
1638
+ group by
1639
+ table_name
1640
+ union
1641
+ -- Children that are not parents
1642
+ select
1643
+ dd.child as table_name,
1644
+ max(lvl) + 1 as level
1645
+ from
1646
+ dep_depth as dd
1647
+ left join ups_dependencies as dp on dp.parent = dd.child
1648
+ where
1649
+ dp.parent is null
1650
+ group by
1651
+ dd.child
1652
+ union
1653
+ -- Neither parents nor children
1654
+ select distinct
1655
+ t.table_name,
1656
+ 0 as level
1657
+ from
1658
+ information_schema.tables as t
1659
+ left join ups_dependencies as p on t.table_name=p.parent
1660
+ left join ups_dependencies as c on t.table_name=c.child
1661
+ where
1662
+ t.table_schema = '!!$DB_NAME!!'
1663
+ and t.table_type = 'BASE TABLE'
1664
+ and p.parent is null
1665
+ and c.child is null
1666
+ ) as all_levels;
1667
+
1668
+
1669
+ -- Create a list of the selected tables with ordering information.
1670
+ -- !x! if(table_exists(ups_proctables))
1671
+ drop table if exists ups_proctables cascade;
1672
+ -- !x! endif
1673
+ create table ups_proctables
1674
+ select
1675
+ ot.table_order,
1676
+ tl.table_name,
1677
+ tl.exclude_cols,
1678
+ tl.display_changes,
1679
+ tl.display_final,
1680
+ tl.rows_updated,
1681
+ tl.rows_inserted,
1682
+ 0 as processed
1683
+ from
1684
+ !!#control_table!! as tl
1685
+ inner join ups_ordered_tables as ot on ot.table_name = tl.table_name
1686
+ ;
1687
+
1688
+ -- Create a view returning a single unprocessed table, in order.
1689
+ -- !x! if(view_exists(ups_toprocess))
1690
+ drop view if exists ups_toprocess cascade;
1691
+ -- !x! endif
1692
+ create view ups_toprocess as
1693
+ select
1694
+ table_name, exclude_cols,
1695
+ display_changes, display_final,
1696
+ rows_updated, rows_inserted
1697
+ from ups_proctables
1698
+ where processed = 0
1699
+ order by table_order
1700
+ limit 1;
1701
+
1702
+ -- Process all tables in order.
1703
+ -- !x! execute script upsert_all_innerloop with (stage_pfx=!!#stage_pfx!!)
1704
+
1705
+ -- Move the update/insert counts back into the control table.
1706
+ update !!#control_table!! as ct, ups_proctables as pt
1707
+ set
1708
+ ct.rows_updated = pt.rows_updated,
1709
+ ct.rows_inserted = pt.rows_inserted
1710
+ where
1711
+ pt.table_name = ct.table_name;
1712
+
1713
+
1714
+ -- Clean up
1715
+ drop table if exists ups_proctables cascade;
1716
+ drop view if exists ups_toprocess cascade;
1717
+ drop table if exists ups_ordered_tables cascade;
1718
+ drop table if exists ups_dependencies cascade;
1719
+ -- !x! if(view_exists(ups_upsert_rows))
1720
+ drop view if exists ups_upsert_rows;
1721
+ -- !x! endif
1722
+
1723
+
1724
+ -- Update the status bar if the console is running.
1725
+ -- !x! if(console_on)
1726
+ -- !x! console status "Data merge complete"
1727
+ -- !x! console progress 0
1728
+ -- !x! endif
1729
+
1730
+
1731
+ -- !x! END SCRIPT
1732
+ -- UPSERT_ALL
1733
+ -- ****************************************************************
1734
+ -- ****************************************************************
1735
+ -- Script UPSERT_ALL_INNERLOOP
1736
+ -- ---------------------------------------------------------------
1737
+
1738
+ -- !x! BEGIN SCRIPT UPSERT_ALL_INNERLOOP with parameters (stage_pfx)
1739
+
1740
+ -- Update the status bar if the console is running.
1741
+ -- !x! if(console_on)
1742
+ -- !x! console progress !!$counter_221585944!! / !!upsert_progress_denom!!
1743
+ -- !x! endif
1744
+
1745
+ -- !x! if(hasrows(ups_toprocess))
1746
+ -- Create variables to store the row counts from updates and inserts.
1747
+ -- !x! sub ~rows_updated 0
1748
+ -- !x! sub ~rows_inserted 0
1749
+
1750
+ -- !x! select_sub ups_toprocess
1751
+ -- !x! execute script upsert_one with (stage_pfx=!!#stage_pfx!!, table=!!@table_name!!, exclude_cols="!!@exclude_cols!!", display_changes=!!@display_changes!!, display_final=!!@display_final!!, updcntvar=+rows_updated, inscntvar=+rows_inserted)
1752
+
1753
+ update ups_proctables
1754
+ set rows_updated = !!~rows_updated!!,
1755
+ rows_inserted = !!~rows_inserted!!
1756
+ where table_name = '!!@table_name!!';
1757
+
1758
+ update ups_proctables
1759
+ set processed = 1
1760
+ where table_name = '!!@table_name!!';
1761
+ -- !x! execute script upsert_all_innerloop with (stage_pfx=!!#stage_pfx!!)
1762
+ -- !x! endif
1763
+
1764
+ -- !x! END SCRIPT
1765
+ -- ############### End of UPSERT_ALL_INNERLOOP ##################
1766
+ -- ################################################################
1767
+
1768
+
1769
+
1770
+
1771
+ -- ################################################################
1772
+ -- Script QA_ALL
1773
+ --
1774
+ -- Conducts null, primary key, and foreign key checks on multiple
1775
+ -- staging tables containing new or revised data for staging tables,
1776
+ -- using the NULLQA_ONE, PKQA_ONE, and FKQA_ONE scripts.
1777
+ --
1778
+ -- Input parameters:
1779
+ -- stage_pfx : The name of the staging schema.
1780
+ -- control_table : The name of a table containing at least the
1781
+ -- following four columns:
1782
+ -- table_name : The name of a table
1783
+ -- to be updated.
1784
+ -- null_errors : For a comma-separated
1785
+ -- list of columns that
1786
+ -- are non-nullable in
1787
+ -- the base table but
1788
+ -- null in the staging
1789
+ -- table.
1790
+ -- pk_errors : For a count of the number
1791
+ -- of distinct primary key
1792
+ -- values that are duplicated,
1793
+ -- followed by the total row
1794
+ -- count for the duplicated
1795
+ -- keys.
1796
+ -- fk_errors : For a comma-separated
1797
+ -- list of foreign-key
1798
+ -- constraint names that
1799
+ -- are not met by the
1800
+ -- staging table.
1801
+ -- A table with these columns will be created
1802
+ -- by the script STAGED_TO_LOAD.
1803
+ --
1804
+ -- Global variables:
1805
+ -- logfile : The name of a log file to which error
1806
+ -- messages will be written. Optional.
1807
+ -- log_sql : A value of 'Yes' or 'No' to indicate whether
1808
+ -- the SQL that is generated for each foreign
1809
+ -- key check is written to the logfile. Optional.
1810
+ -- log_errors : A value of 'Yes' or 'No' to indicate whether
1811
+ -- foreign key errors are written to the logfile.
1812
+ -- Optional.
1813
+ --
1814
+ -- Tables and views used:
1815
+ -- ups_proctables : temporary table
1816
+ -- ups_toprocess : temporary table
1817
+ -- ups_upsert_rows : temporary table
1818
+ --
1819
+ -- Counters used:
1820
+ -- 221585944 : Progress bar position
1821
+ --
1822
+ -- Global variables modified:
1823
+ -- upsert_progress_denom : Created or redefined.
1824
+ --
1825
+ -- ===============================================================
1826
+
1827
+ -- !x! BEGIN SCRIPT QA_ALL with parameters (stage_pfx, control_table)
1828
+
1829
+ -- Get denominator for progress bar if console is on.
1830
+ -- !x! if(console_on)
1831
+ -- !x! if(view_exists(ups_upsert_rows))
1832
+ drop view if exists ups_upsert_rows;
1833
+ -- !x! endif
1834
+ create view ups_upsert_rows as
1835
+ select count(*) + 1 as upsert_rows
1836
+ from !!#control_table!!;
1837
+ -- !x! subdata upsert_progress_denom ups_upsert_rows
1838
+ -- !x! endif
1839
+
1840
+ -- Initialize the status and progress bars if the console is running.
1841
+ -- !x! begin script update_console_qa with parameters (check_type)
1842
+ -- !x! if(console_on)
1843
+ -- !x! reset counter 221585944
1844
+ -- !x! console status "Performing !!#check_type!! QA checks"
1845
+ -- !x! console progress 0
1846
+ -- !x! endif
1847
+ -- !x! end script
1848
+
1849
+ -- Create a list of the selected tables with a loop control flag.
1850
+ -- !x! if(table_exists(ups_proctables))
1851
+ drop table if exists ups_proctables cascade;
1852
+ -- !x! endif
1853
+ create table ups_proctables
1854
+ select
1855
+ tl.table_name,
1856
+ tl.exclude_null_checks,
1857
+ tl.display_changes,
1858
+ 0 as processed
1859
+ from
1860
+ !!#control_table!! as tl
1861
+ ;
1862
+
1863
+ -- Create a view returning a single unprocessed table, in order.
1864
+ -- !x! if(table_exists(ups_toprocess))
1865
+ drop view if exists ups_toprocess;
1866
+ -- !x! endif
1867
+ create view ups_toprocess as
1868
+ select table_name, exclude_null_checks, display_changes
1869
+ from ups_proctables
1870
+ where processed = 0
1871
+ limit 1;
1872
+
1873
+ -- Perform null QA checks on all tables.
1874
+ -- !x! execute script update_console_qa with args (check_type=NULL)
1875
+ -- !x! execute script qa_all_nullloop with (stage_pfx=!!#stage_pfx!!, control_table=!!#control_table!!)
1876
+
1877
+ -- Perform primary key QA checks on all tables.
1878
+ update ups_proctables set processed = 0;
1879
+ -- !x! execute script update_console_qa with args (check_type="primary key")
1880
+ -- !x! execute script qa_all_pkloop with (stage_pfx=!!#stage_pfx!!, control_table=!!#control_table!!)
1881
+
1882
+ -- Perform foreign key QA checks on all tables.
1883
+ update ups_proctables set processed = 0;
1884
+ -- !x! execute script update_console_qa with args (check_type=foreign key)
1885
+ -- !x! execute script qa_all_fkloop with (stage_pfx=!!#stage_pfx!!, control_table=!!#control_table!!)
1886
+
1887
+
1888
+ -- Update the status bar if the console is running.
1889
+ -- !x! if(console_on)
1890
+ -- !x! console status "Data QA checks complete"
1891
+ -- !x! console progress 0
1892
+ -- !x! endif
1893
+
1894
+ -- Clean up.
1895
+ drop table if exists ups_proctables cascade;
1896
+ drop view if exists ups_toprocess;
1897
+ -- !x! if(view_exists(ups_upsert_rows))
1898
+ drop view if exists ups_upsert_rows;
1899
+ -- !x! endif
1900
+
1901
+
1902
+ -- !x! END SCRIPT
1903
+ -- QA_ALL
1904
+ -- ****************************************************************
1905
+ -- ****************************************************************
1906
+ -- Script QA_ALL_NULLLOOP
1907
+ -- ---------------------------------------------------------------
1908
+
1909
+ -- !x! BEGIN SCRIPT QA_ALL_NULLLOOP with parameters (stage_pfx, control_table)
1910
+
1911
+ -- !x! sub_empty ~ups_null_error_list
1912
+
1913
+ -- Update the status bar if the console is running.
1914
+ -- !x! if(console_on)
1915
+ -- !x! console progress !!$counter_221585944!! / !!upsert_progress_denom!!
1916
+ -- !x! endif
1917
+
1918
+ -- !x! if(hasrows(ups_toprocess))
1919
+ -- !x! select_sub ups_toprocess
1920
+ -- !x! if(is_null("!!@exclude_null_checks!!"))
1921
+ -- !x! execute script nullqa_one with (stage_pfx=!!#stage_pfx!!, table=!!@table_name!!, error_list=+ups_null_error_list)
1922
+ -- !x! else
1923
+ -- !x! execute script nullqa_one with (stage_pfx=!!#stage_pfx!!, table=!!@table_name!!, error_list=+ups_null_error_list, exclude_null_checks=[!!@exclude_null_checks!!])
1924
+ -- !x! endif
1925
+ -- !x! if(not is_null("!!~ups_null_error_list!!"))
1926
+ update !!#control_table!!
1927
+ set null_errors = '!!~ups_null_error_list!!'
1928
+ where table_name = '!!@table_name!!';
1929
+ -- !x! endif
1930
+
1931
+ update ups_proctables
1932
+ set processed = 1
1933
+ where table_name = '!!@table_name!!';
1934
+ -- !x! execute script qa_all_nullloop with (stage_pfx=!!#stage_pfx!!, control_table=!!#control_table!!)
1935
+ -- !x! endif
1936
+
1937
+ -- !x! END SCRIPT
1938
+ -- QA_ALL_NULLLOOP
1939
+ -- ****************************************************************
1940
+ -- ****************************************************************
1941
+ -- Script QA_ALL_PKLOOP
1942
+ -- ---------------------------------------------------------------
1943
+
1944
+ -- !x! BEGIN SCRIPT QA_ALL_PKLOOP with parameters (stage_pfx, control_table)
1945
+
1946
+ -- !x! sub_empty ~ups_pk_error_list
1947
+ -- Update the status bar if the console is running.
1948
+ -- !x! if(console_on)
1949
+ -- !x! console progress !!$counter_221585944!! / !!upsert_progress_denom!!
1950
+ -- !x! endif
1951
+
1952
+ -- !x! if(hasrows(ups_toprocess))
1953
+ -- !x! select_sub ups_toprocess
1954
+ -- !x! execute script pkqa_one with (stage_pfx=!!#stage_pfx!!, table=!!@table_name!!, display_errors=!!@display_changes!!, error_list=+ups_pk_error_list)
1955
+ -- !x! if(not is_null("!!~ups_pk_error_list!!"))
1956
+ update !!#control_table!!
1957
+ set pk_errors = '!!~ups_pk_error_list!!'
1958
+ where table_name = '!!@table_name!!';
1959
+ -- !x! endif
1960
+
1961
+ update ups_proctables
1962
+ set processed = 1
1963
+ where table_name = '!!@table_name!!';
1964
+ -- !x! execute script qa_all_pkloop with (stage_pfx=!!#stage_pfx!!, control_table=!!#control_table!!)
1965
+ -- !x! endif
1966
+
1967
+
1968
+ -- !x! END SCRIPT
1969
+ -- QA_ALL_PKLOOP
1970
+ -- ****************************************************************
1971
+ -- ****************************************************************
1972
+ -- Script QA_ALL_FKLOOP
1973
+ -- ---------------------------------------------------------------
1974
+
1975
+ -- !x! BEGIN SCRIPT QA_ALL_FKLOOP with parameters (stage_pfx, control_table)
1976
+
1977
+ -- !x! sub_empty ~ups_error_list
1978
+
1979
+ -- Update the status bar if the console is running.
1980
+ -- !x! if(console_on)
1981
+ -- !x! console progress !!$counter_221585944!! / !!upsert_progress_denom!!
1982
+ -- !x! endif
1983
+
1984
+ -- !x! if(hasrows(ups_toprocess))
1985
+ -- !x! select_sub ups_toprocess
1986
+ -- !x! execute script fkqa_one with (stage_pfx=!!#stage_pfx!!, table=!!@table_name!!, display_errors=!!@display_changes!!, error_list=+ups_error_list)
1987
+ -- !x! if(not is_null("!!~ups_error_list!!"))
1988
+ update !!#control_table!!
1989
+ set fk_errors = '!!~ups_error_list!!'
1990
+ where table_name = '!!@table_name!!';
1991
+ -- !x! endif
1992
+
1993
+ update ups_proctables
1994
+ set processed = 1
1995
+ where table_name = '!!@table_name!!';
1996
+ -- !x! execute script qa_all_fkloop with (stage_pfx=!!#stage_pfx!!, control_table=!!#control_table!!)
1997
+ -- !x! endif
1998
+
1999
+ -- !x! END SCRIPT
2000
+ -- ##################### End of QA_ALL ###########################
2001
+ -- #################################################################
2002
+
2003
+
2004
+
2005
+
2006
+ -- ################################################################
2007
+ -- Script UPDTPK_ONE
2008
+ --
2009
+ -- Updates primary keys in the base table, based on new and existing
2010
+ -- values of PK columns in a staging table, using UPDATE
2011
+ -- statements. Displays data to be modified to the
2012
+ -- user before any modifications are done. Reports the changes
2013
+ -- made to the console and optionally to a log file.
2014
+ --
2015
+ -- Input parameters:
2016
+ -- stage_pfx : The prefix to the name of the staging table.
2017
+ -- table : The table name--same for base and staging,
2018
+ -- except for the prefix on the staging table.
2019
+ -- display_errors : A value of 'Yes' or 'No' to indicate whether
2020
+ -- any errors should be displayed in a GUI.
2021
+ -- display_changes : A value of 'Yes' or 'No' to indicate whether
2022
+ -- or not the changes to be made to the
2023
+ -- base table should be displayed in a GUI.
2024
+ --
2025
+ -- Global variables:
2026
+ -- logfile : The name of a log file to which update
2027
+ -- messages will be written. Optional.
2028
+ -- log_sql : A value of 'Yes' or 'No' indicating whether
2029
+ -- the update and insert statements should
2030
+ -- also be written to the logfile. Optional.
2031
+ -- log_changes : A value of 'Yes' or 'No' indicating whether
2032
+ -- the updated and inserted data should be
2033
+ -- written to the logfile. Optional.
2034
+ --
2035
+ -- Tables and views created or modified:
2036
+ -- ups_pkqa_errors : temporary table
2037
+ -- ups_pkcol_info : temporary table
2038
+ -- ups_pkupdates : temporary table
2039
+ -- ups_pkupdate_strings : temporary view
2040
+ -- ups_pkupdates : temporary table
2041
+ -- ===============================================================
2042
+
2043
+ -- !x! BEGIN SCRIPT UPDTPK_ONE with parameters (stage_pfx, table, display_errors, display_changes)
2044
+
2045
+ -- !x! if(console_on)
2046
+ -- !x! console status "Primary key updates"
2047
+ -- !x! endif
2048
+
2049
+
2050
+ -- Validate inputs: base/staging schemas and table
2051
+ -- !x! execute script validate_one with args (stage_pfx=!!#stage_pfx!!, table=!!#table!!, script=!!$CURRENT_SCRIPT!!, script_line=!!$SCRIPT_LINE!!)
2052
+
2053
+ -- Write an initial header to the logfile.
2054
+ -- !x! if(sub_defined(logfile))
2055
+ -- !x! write "" to !!logfile!!
2056
+ -- !x! write "==================================================================" to !!logfile!!
2057
+ -- !x! write "!!$current_time!! -- Performing primary key updates on table !!#table!! from !!#stage_pfx!!!!#table!!" to !!logfile!!
2058
+ -- !x! endif
2059
+
2060
+ -- !x! write "Performing primary key updates on table !!#table!! from !!#stage_pfx!!!!#table!!"
2061
+
2062
+ -- Create a temp table to store the results of the PK update QA checks
2063
+ -- !x! if(table_exists(ups_pkqa_errors))
2064
+ drop table if exists ups_pkqa_errors cascade;
2065
+ -- !x! endif
2066
+ create table ups_pkqa_errors (
2067
+ error_code varchar(40),
2068
+ error_description varchar(500)
2069
+ );
2070
+
2071
+
2072
+ -- Populate a (temporary) table with the names of the primary key columns of the base table.
2073
+ -- Get the old and new primary key columns from staging table into various formats
2074
+ -- to use later to construct SQL statement to select records in various ways for both updates and QA checks.
2075
+ -- Include column lists, join expression, and where clause
2076
+ -- !x! if(table_exists(ups_pkcol_info))
2077
+ drop table if exists ups_pkcol_info cascade;
2078
+ -- !x! endif
2079
+ create table ups_pkcol_info
2080
+ select
2081
+ k.table_schema,
2082
+ k.table_name,
2083
+ k.column_name,
2084
+ cast(concat('b.', column_name) as varchar(2000)) as base_aliased,
2085
+ cast(concat('s.', column_name) as varchar(2000)) as staging_aliased,
2086
+ cast(concat('s.', column_name, ' as staging_', column_name) as varchar(2000)) as staging_aliased_prefix,
2087
+ cast(concat('b.', column_name, ' = s.', column_name) as varchar(2000)) as join_expr,
2088
+ cast(concat('new_', column_name) as varchar(2000)) as newpk_col,
2089
+ cast(concat('s.new_', column_name) as varchar(2000)) as newpk_col_aliased,
2090
+ cast(concat('new_', column_name, ' is null') as varchar(2000)) as newpk_col_empty,
2091
+ cast(concat('new_', column_name, ' is not null') as varchar(2000)) as newpk_col_not_empty,
2092
+ cast(concat('b.', column_name, ' = s.new_', column_name) as varchar(2000)) as assmt_expr,
2093
+ cast(concat('b.', column_name, ' = s.new_', column_name) as varchar(2000)) as join_expr_oldnew,
2094
+ cast(concat('s.new_', column_name, ' = b.new_', column_name) as varchar(2000)) as join_expr_new,
2095
+ k.ordinal_position
2096
+ from information_schema.table_constraints as tc
2097
+ inner join information_schema.key_column_usage as k
2098
+ on tc.constraint_type = 'PRIMARY KEY'
2099
+ and tc.constraint_name = k.constraint_name
2100
+ and tc.constraint_catalog = k.constraint_catalog
2101
+ and tc.constraint_schema = k.constraint_schema
2102
+ and tc.table_schema = k.table_schema
2103
+ and tc.table_name = k.table_name
2104
+ and tc.constraint_name = k.constraint_name
2105
+ where
2106
+ k.table_name = '!!#table!!'
2107
+ and k.table_schema = '!!$DB_NAME!!'
2108
+ ;
2109
+
2110
+
2111
+ -- Run QA checks
2112
+ -- !x! execute script UPDTPKQA_ONE with arguments(stage_pfx=!!#stage_pfx!!, table=!!#table!!, pkinfo_table=ups_pkcol_info, qaerror_table=ups_pkqa_errors, display_errors=!!#display_errors!!)
2113
+
2114
+
2115
+ -- Run the PK update ONLY if QA check script returned no errors
2116
+ -- !x! if(not hasrows(ups_pkqa_errors))
2117
+ -- !x! rm_sub ~updatestmt
2118
+
2119
+ -- !x! sub ~do_updates Yes
2120
+
2121
+ -- !x! if(sub_defined(logfile))
2122
+ -- !x! write "" to !!logfile!!
2123
+ -- !x! write "==================================================================" to !!logfile!!
2124
+ -- !x! write "!!$current_time!! -- Performing primary key update on table !!#table!!" to !!logfile!!
2125
+ -- !x! endif
2126
+
2127
+ -- !x! if(console_on)
2128
+ -- !x! console status "Performing PK updates"
2129
+ -- !x! console progress 0
2130
+ -- !x! endif
2131
+
2132
+ -- !x! write "Performing primary key update on table !!#table!!"
2133
+
2134
+ -- Create strings necessary to construct SQL to perform the updates
2135
+ -- !x! if(view_exists(ups_pkupdate_strings))
2136
+ drop view if exists ups_pkupdate_strings cascade;
2137
+ -- !x! endif
2138
+ create view ups_pkupdate_strings as
2139
+ select
2140
+ group_concat(base_aliased order by ordinal_position separator ', ') as oldpk_cols,
2141
+ group_concat(newpk_col order by ordinal_position separator ', ') as newpk_cols,
2142
+ group_concat(join_expr order by ordinal_position separator ' and ') as joinexpr,
2143
+ group_concat(newpk_col_not_empty order by ordinal_position separator ' and ') as all_newpk_col_not_empty,
2144
+ group_concat(assmt_expr order by ordinal_position separator ', ') as assmt_expr
2145
+ from ups_pkcol_info
2146
+ group by table_name
2147
+ ;
2148
+ -- !x! select_sub ups_pkupdate_strings
2149
+
2150
+ -- Create a FROM clause for an inner join between base and staging
2151
+ -- tables on the primary key column(s).
2152
+ -- !x! sub ~fromclause FROM !!#table!! as b INNER JOIN !!#stage_pfx!!!!#table!! as s ON !!@joinexpr!!
2153
+
2154
+ -- Create a WHERE clause for the rows to include in the selection (only those having new PK columns populated in the staging table)
2155
+ -- !x! sub ~whereclause WHERE !!@all_newpk_col_not_empty!!
2156
+
2157
+ -- Select all matches for PK update into temp table
2158
+ -- !x! if(table_exists(ups_pkupdates))
2159
+ drop table if exists ups_pkupdates cascade;
2160
+ -- !x! endif
2161
+ create table ups_pkupdates
2162
+ select
2163
+ !!@oldpk_cols!!,
2164
+ !!@newpk_cols!!
2165
+ !!~fromclause!!
2166
+ !!~whereclause!!
2167
+ ;
2168
+
2169
+ -- Prompt user to examine matching data and commit, don't commit, or quit.
2170
+ -- !x! if(hasrows(ups_pkupdates))
2171
+ -- !x! if(is_true(!!#display_changes!!))
2172
+ -- !x! prompt ask "Do you want to make these changes to primary key values for table !!#table!!?" sub ~do_updates display ups_pkupdates
2173
+ -- !x! endif
2174
+ -- !x! if(is_true(!!~do_updates!!))
2175
+
2176
+ -- Create an UPDATE statement to update PK columns of the base table with
2177
+ -- "new" PK columns from the staging table. No semicolon terminating generated SQL.
2178
+ -- !x! sub ~updatestmt UPDATE !!#table!! as b, !!#stage_pfx!!!!#table!! as s SET !!@assmt_expr!! WHERE !!@joinexpr!! and !!@all_newpk_col_not_empty!!
2179
+
2180
+ -- !x! write "Updating !!#table!!"
2181
+ -- !x! if(sub_defined(logfile))
2182
+ -- !x! write "" to !!logfile!!
2183
+ -- !x! if(sub_defined(log_sql))
2184
+ -- !x! andif(is_true(!!log_sql!!))
2185
+ -- !x! write "UPDATE statement for !!#table!!:" to !!logfile!!
2186
+ -- !x! write [!!~updatestmt!!] to !!logfile!!
2187
+ -- !x! endif
2188
+ -- !x! if(sub_defined(log_changes))
2189
+ -- !x! andif(is_true(!!log_changes!!))
2190
+ -- !x! write "Updates:" to !!logfile!!
2191
+ -- !x! export ups_pkupdates append to !!logfile!! as txt
2192
+ -- !x! endif
2193
+ -- !x! write "" to !!logfile!!
2194
+ -- !x! endif
2195
+ !!~updatestmt!!;
2196
+ -- !x! if(sub_defined(logfile))
2197
+ -- !x! write "!!$last_rowcount!! rows of !!#table!! updated." to !!logfile!!
2198
+ -- !x! endif
2199
+ -- !x! write " !!$last_rowcount!! rows updated."
2200
+ -- !x! endif
2201
+ -- !x! else
2202
+ --!x! write "No primary key updates specified for existing records in !!#table!!"
2203
+ -- !x! endif
2204
+ -- !x! endif
2205
+
2206
+
2207
+ -- !x! if(table_exists(ups_pkqa_errors))
2208
+ drop table if exists ups_pkqa_errors cascade;
2209
+ -- !x! endif
2210
+ -- !x! if(table_exists(ups_pkcol_info))
2211
+ drop table if exists ups_pkcol_info cascade;
2212
+ -- !x! endif
2213
+ -- !x! if(view_exists(ups_pkupdate_strings))
2214
+ drop view if exists ups_pkupdate_strings cascade;
2215
+ -- !x! endif
2216
+ -- !x! if(table_exists(ups_pkupdates))
2217
+ drop table if exists ups_pkupdates cascade;
2218
+ -- !x! endif
2219
+
2220
+
2221
+ -- !x! END SCRIPT
2222
+ -- ################### End of UPDTPK_ONE ########################
2223
+ -- ################################################################
2224
+
2225
+
2226
+ -- ################################################################
2227
+ -- Script UPDTPKQA_ONE
2228
+ --
2229
+ -- Performs QA checks on requested primary key updates to a table,
2230
+ -- based on old and new values of the table's primary key columns
2231
+ -- in a staging table.
2232
+ --
2233
+ -- Input parameters:
2234
+ -- stage_pfx : The prefix to the staging table name.
2235
+ -- table : The table name--same for base and staging,
2236
+ -- except for the prefix of the staging table.
2237
+ -- pkinfo_table : The name of a temporary table to be passed by
2238
+ -- the caller that contains information about the table PK,
2239
+ -- including strings to be used in constructing
2240
+ -- SQL for checks
2241
+ -- qaerror_table : The name of a temporary table to
2242
+ -- store any errors found by QA checks.
2243
+ -- display_errors : A value of 'Yes' or 'No' to indicate whether
2244
+ -- any errors should be displayed in a GUI.
2245
+ -- Output parameters:
2246
+ -- error_list : The name of the variable to receive FILL IN.
2247
+ --
2248
+ -- Global variables:
2249
+ -- logfile : The name of a log file to which update
2250
+ -- messages will be written. Optional.
2251
+ -- log_sql : A value of 'Yes' or 'No' indicating whether
2252
+ -- the update and insert statements should
2253
+ -- also be written to the logfile. Optional.
2254
+ -- Currently only writes SQL for foreign key checks
2255
+ -- (final check) to log.
2256
+ -- log_errors : A value of 'Yes' or 'No' to indicate whether
2257
+ -- errors are written to the logfile. Optional.
2258
+ --
2259
+ -- Tables and views created or modified:
2260
+ -- ups_missing_pk_cols : temporary table
2261
+ -- ups_pkqa_str_lib : tempoarary table
2262
+ -- ups_any_pk_cols : temporary table
2263
+ -- ups_empty_pk_cols : temporary table
2264
+ -- ups_empty_pk_cols_rwcnt : temporary view
2265
+ -- ups_old_pks_wc : temporary table
2266
+ -- ups_invalid_old_pks : temporary table
2267
+ -- ups_invld_pk_rwcnt : temporary view
2268
+ -- ups_existing_new_pks : temporary table
2269
+ -- ups_exst_nwpk_rwcnt : temporary view
2270
+ -- ups_pk_mapping_conflict : temporary table
2271
+ -- ups_map_conf_rwcnt : temporary view
2272
+ -- ups_pk_duplicate_keys : temporary table
2273
+ -- ups_dup_key_rwcnt : temporary view
2274
+ -- ups_fkcol_refs : temporary table
2275
+ -- ups_pkcol_deps : temporary table
2276
+ -- ups_pkfk_ctrl : temporary table
2277
+ -- ===============================================================
2278
+
2279
+ -- !x! BEGIN SCRIPT UPDTPKQA_ONE with parameters (stage_pfx, table, pkinfo_table, qaerror_table, display_errors)
2280
+
2281
+ -- Write an initial header to the logfile.
2282
+ -- !x! if(sub_defined(logfile))
2283
+ -- !x! write "" to !!logfile!!
2284
+ -- !x! write "==================================================================" to !!logfile!!
2285
+ -- !x! write "!!$current_time!! -- QA checks for primary key updates on table !!#table!!" to !!logfile!!
2286
+ -- !x! endif
2287
+
2288
+ -- !x! write "Conducting QA checks on table !!#stage_pfx!!!!#table!! for primary key updates to table !!#table!!"
2289
+
2290
+ -- Initialize the status and progress bars if the console is running.
2291
+ -- !x! if(console_on)
2292
+ -- !x! console status "QA checks for PK updates on !!#table!!"
2293
+ -- !x! endif
2294
+
2295
+
2296
+ -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2297
+ -- Check 1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2298
+ -- No primary key constraint on base table
2299
+ -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2300
+ -- !x! if(not hasrows(!!#pkinfo_table!!))
2301
+
2302
+ -- !x! sub ~error_description No primary key constraint on base table !!#table!!
2303
+ -- !x! write " !!~error_description!!"
2304
+ -- !x! if(sub_defined(logfile))
2305
+ -- !x! write "" to !!logfile!!
2306
+ -- !x! write "!!~error_description!!" to !!logfile!!
2307
+ -- !x! endif
2308
+ insert into !!#qaerror_table!! (error_code, error_description)
2309
+ values ('No PK on base table', '!!~error_description!!')
2310
+ ;
2311
+
2312
+ -- No other QA checks are conducted if this check fails:
2313
+ -- Remaining QA checks are conducted ONLY if base table has PK
2314
+ -- !x! else
2315
+
2316
+ -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2317
+ -- Check 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2318
+ -- A "new" PK column exists in staging table for every PK column of base table
2319
+ -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2320
+
2321
+ -- Find any MISSING PK columns in staging table
2322
+ -- !x! if(table_exists(ups_missing_pk_cols))
2323
+ drop table if exists ups_missing_pk_cols cascade;
2324
+ -- !x! endif
2325
+ create table ups_missing_pk_cols
2326
+ select
2327
+ group_concat(newpk_col order by ordinal_position separator ', ') as missing_newpk_cols
2328
+ from
2329
+ --Base table PK columns, with expected name in staging table ("new_" prepended to column name)
2330
+ !!#pkinfo_table!! as pk
2331
+ --Staging table columns
2332
+ left join
2333
+ (
2334
+ select table_name, column_name
2335
+ from information_schema.columns
2336
+ where
2337
+ table_schema = '!!$DB_NAME!!'
2338
+ and table_name = '!!#stage_pfx!!!!#table!!'
2339
+ ) as stag on pk.newpk_col=stag.column_name
2340
+ where
2341
+ stag.column_name is null
2342
+ having count(*)>0
2343
+ ;
2344
+
2345
+ -- !x! if(hasrows(ups_missing_pk_cols))
2346
+
2347
+ -- !x! subdata ~error_info ups_missing_pk_cols
2348
+
2349
+ -- !x! sub ~error_description New primary key column(s) missing from staging table: !!~error_info!!
2350
+
2351
+ -- !x! write " !!~error_description!!"
2352
+ -- !x! if(sub_defined(logfile))
2353
+ -- !x! write "" to !!logfile!!
2354
+ -- !x! write "!!~error_description!!" to !!logfile!!
2355
+ -- !x! endif
2356
+ insert into !!#qaerror_table!! (error_code, error_description)
2357
+ values ('Missing new PK column(s)', '!!~error_description!!')
2358
+ ;
2359
+
2360
+ -- No other QA checks are conducted if this check fails:
2361
+ -- Remaining QA checks are all conducted ONLY if all expected "new PK" columns exist in staging table
2362
+ -- !x! else
2363
+
2364
+ -- Library of aggregated strings used to construct SQL for the remaining checks
2365
+
2366
+ -- Just base table
2367
+ -- !x! sub ~base_table !!#table!!
2368
+
2369
+ -- Just staging table
2370
+ -- !x! sub ~staging_table !!#stage_pfx!!!!#table!!
2371
+
2372
+ -- !x! if(table_exists(ups_pkqa_str_lib))
2373
+ drop table if exists ups_pkqa_str_lib;
2374
+ -- !x! endif
2375
+ create table ups_pkqa_str_lib
2376
+ select
2377
+ group_concat(column_name order by ordinal_position separator ', ') as old_pkcol,
2378
+ group_concat(staging_aliased order by ordinal_position separator ', ') as old_pkcol_aliased,
2379
+ group_concat(staging_aliased_prefix order by ordinal_position separator ', ') as old_pkcol_aliased_prefix,
2380
+ group_concat(newpk_col order by ordinal_position separator ', ') as new_pkcol,
2381
+ group_concat(newpk_col_aliased order by ordinal_position separator ', ') as new_pkcol_aliased,
2382
+ group_concat(join_expr order by ordinal_position separator ' and ') as joincond_origorig,
2383
+ group_concat(join_expr_oldnew order by ordinal_position separator ' and ') as joincond_oldnew,
2384
+ group_concat(join_expr_new order by ordinal_position separator ' and ') as joincond_newnew,
2385
+ group_concat(newpk_col_not_empty order by ordinal_position separator ' or ') as any_newpk_col_not_empty,
2386
+ group_concat(newpk_col_not_empty order by ordinal_position separator ' and ') as all_newpk_col_not_empty,
2387
+ group_concat(newpk_col_empty order by ordinal_position separator ' or ') as any_newpk_col_empty,
2388
+ group_concat(newpk_col_empty order by ordinal_position separator ' and ') as all_newpk_col_empty
2389
+ from !!#pkinfo_table!!
2390
+ ;
2391
+ -- !x! select_sub ups_pkqa_str_lib
2392
+
2393
+
2394
+
2395
+ -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2396
+ -- Check 3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2397
+ -- There are any rows with PK updates specified.
2398
+ -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2399
+
2400
+ -- Find any populated new PK columns in staging table
2401
+ -- !x! if(table_exists(ups_any_pk_cols))
2402
+ drop table if exists ups_any_pk_cols cascade;
2403
+ -- !x! endif
2404
+ create table ups_any_pk_cols
2405
+ select *
2406
+ from !!~staging_table!!
2407
+ where !!@any_newpk_col_not_empty!!
2408
+ ;
2409
+ -- !x! if(not hasrows(ups_any_pk_cols))
2410
+ -- !x! sub ~error_description No primary key updates specified in !!#stage_pfx!!!!#table!!
2411
+ -- !x! write " !!~error_description!!"
2412
+ -- !x! if(sub_defined(logfile))
2413
+ -- !x! write "" to !!logfile!!
2414
+ -- !x! write "!!~error_description!!" to !!logfile!!
2415
+ -- !x! endif
2416
+ insert into !!#qaerror_table!! (error_code, error_description)
2417
+ values ('No PK updates specified in staging table', '!!~error_description!!')
2418
+ ;
2419
+ -- No other QA checks are conducted if this check fails
2420
+ -- !x! else
2421
+
2422
+ -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2423
+ -- Check 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2424
+ -- Where any "new" PK column is populated in the staging table, they are all populated.
2425
+ -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2426
+
2427
+ -- Construct SQL statement looking for any NULLs in "new" PK columns in rows where any PK columns are populated
2428
+ -- Find any EMPTY PK columns in staging table
2429
+ -- !x! if(table_exists(ups_empty_pk_cols))
2430
+ drop table if exists ups_empty_pk_cols cascade;
2431
+ -- !x! endif
2432
+ create table ups_empty_pk_cols
2433
+ select
2434
+ !!@old_pkcol!!,
2435
+ !!@new_pkcol!!
2436
+ from
2437
+ !!~staging_table!!
2438
+ where
2439
+ not (!!@all_newpk_col_empty!!)
2440
+ and (!!@any_newpk_col_empty!!)
2441
+ ;
2442
+
2443
+ -- !x! if(hasrows(ups_empty_pk_cols))
2444
+ -- !x! if(view_exists(ups_empty_pk_cols_rwcnt))
2445
+ drop view if exists ups_empty_pk_cols_rwcnt cascade;
2446
+ -- !x! endif
2447
+ create view ups_empty_pk_cols_rwcnt as
2448
+ select count(*) as rwcnt
2449
+ from ups_empty_pk_cols
2450
+ ;
2451
+ -- !x! subdata ~rowcount ups_empty_pk_cols_rwcnt
2452
+ -- !x! sub ~error_description Missing values in new PK columns in !!#stage_pfx!!!!#table!!: !!~rowcount!! row(s)
2453
+ -- !x! write " !!~error_description!!"
2454
+ insert into !!#qaerror_table!! (error_code, error_description)
2455
+ values ('Incomplete mapping', '!!~error_description!!')
2456
+ ;
2457
+ -- !x! if(sub_defined(logfile))
2458
+ -- !x! write "" to !!logfile!!
2459
+ -- !x! write "!!~error_description!!" to !!logfile!!
2460
+ -- !x! if(sub_defined(log_errors))
2461
+ -- !x! andif(is_true(!!log_errors!!))
2462
+ -- !x! export ups_empty_pk_cols append to !!logfile!! as txt
2463
+ -- !x! endif
2464
+ -- !x! endif
2465
+ -- !x! if(is_true(!!#display_errors!!))
2466
+ -- !x! prompt message "Missing values in new PK columns in !!#stage_pfx!!!!#table!!" display ups_empty_pk_cols
2467
+ -- !x! endif
2468
+ -- !x! endif
2469
+
2470
+ -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2471
+ -- Check 5 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2472
+ -- Where any "new" PK column is populated in the staging table, the value of the original PK for that row is valid
2473
+ -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2474
+
2475
+ -- New PK col in staging table are not empty
2476
+ -- !x! if(table_exists(ups_old_pks_wc))
2477
+ drop table if exists ups_old_pks_wc cascade;
2478
+ -- !x! endif
2479
+ create table ups_old_pks_wc
2480
+ select base_aliased
2481
+ from !!#pkinfo_table!!
2482
+ order by ordinal_position
2483
+ limit 1;
2484
+ -- !x! subdata ~old_pk_firstcol ups_old_pks_wc
2485
+
2486
+ -- !x! if(table_exists(ups_invalid_old_pks))
2487
+ drop table if exists ups_invalid_old_pks cascade;
2488
+ -- !x! endif
2489
+ create table ups_invalid_old_pks
2490
+ select
2491
+ !!@old_pkcol_aliased!!,
2492
+ !!@new_pkcol!!
2493
+ from !!~staging_table!! as s
2494
+ left join !!~base_table!! as b on !!@joincond_origorig!!
2495
+ where !!@all_newpk_col_not_empty!! and !!~old_pk_firstcol!! is null
2496
+ ;
2497
+
2498
+ -- !x! if(hasrows(ups_invalid_old_pks))
2499
+ -- !x! if(view_exists(ups_invalid_pk_rwcnt))
2500
+ drop view if exists ups_invld_pk_rwcnt cascade;
2501
+ -- !x! endif
2502
+ create view ups_invld_pk_rwcnt as
2503
+ select count(*) as rwcnt
2504
+ from ups_invalid_old_pks
2505
+ ;
2506
+ -- !x! subdata ~rowcount ups_invld_pk_rwcnt
2507
+ -- !x! sub ~error_description Invalid original PK in !!#stage_pfx!!!!#table!!: !!~rowcount!! row(s)
2508
+ -- !x! write " !!~error_description!!"
2509
+ insert into !!#qaerror_table!! (error_code, error_description)
2510
+ values ('Invalid old PK value', '!!~error_description!!')
2511
+ ;
2512
+ -- !x! if(sub_defined(logfile))
2513
+ -- !x! write "" to !!logfile!!
2514
+ -- !x! write "!!~error_description!!" to !!logfile!!
2515
+ -- !x! if(sub_defined(log_errors))
2516
+ -- !x! andif(is_true(!!log_errors!!))
2517
+ -- !x! export ups_invalid_old_pks append to !!logfile!! as txt
2518
+ -- !x! endif
2519
+ -- !x! endif
2520
+ -- !x! if(is_true(!!#display_errors!!))
2521
+ -- !x! prompt message "Invalid original PK in !!#stage_pfx!!!!#table!!" display ups_invalid_old_pks
2522
+ -- !x! endif
2523
+ -- !x! endif
2524
+
2525
+
2526
+ -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2527
+ -- Check 6 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2528
+ -- None of the "new" PK values already exist in the base table
2529
+ -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2530
+
2531
+ -- !x! if(table_exists(ups_existing_new_pks))
2532
+ drop table if exists ups_existing_new_pks cascade;
2533
+ -- !x! endif
2534
+ create table ups_existing_new_pks
2535
+ select
2536
+ !!@old_pkcol_aliased_prefix!!,
2537
+ !!@new_pkcol!!,
2538
+ b.*
2539
+ from !!~staging_table!! as s
2540
+ inner join !!~base_table!! as b on !!@joincond_oldnew!!
2541
+ ;
2542
+
2543
+ -- !x! if(hasrows(ups_existing_new_pks))
2544
+ -- !x! if(view_exists(ups_exst_nwpk_rwcnt))
2545
+ drop view if exists ups_exst_nwpk_rwcnt cascade;
2546
+ -- !x! endif
2547
+ create view ups_exst_nwpk_rwcnt as
2548
+ select count(*) as rwcnt
2549
+ from ups_existing_new_pks
2550
+ ;
2551
+ -- !x! subdata ~rowcount ups_exst_nwpk_rwcnt
2552
+ -- !x! sub ~error_description New PK already exists in !!#table!!: !!~rowcount!! row(s)
2553
+ -- !x! write " !!~error_description!!"
2554
+ insert into !!#qaerror_table!! (error_code, error_description)
2555
+ values ('Existing new PK value', '!!~error_description!!')
2556
+ ;
2557
+ -- !x! if(sub_defined(logfile))
2558
+ -- !x! write "" to !!logfile!!
2559
+ -- !x! write "!!~error_description!!" to !!logfile!!
2560
+ -- !x! if(sub_defined(log_errors))
2561
+ -- !x! andif(is_true(!!log_errors!!))
2562
+ -- !x! export ups_existing_new_pks append to !!logfile!! as txt
2563
+ -- !x! endif
2564
+ -- !x! endif
2565
+ -- !x! if(is_true(!!#display_errors!!))
2566
+ -- !x! prompt message "New PK already exists in !!#table!!" display ups_existing_new_pks
2567
+ -- !x! endif
2568
+ -- !x! endif
2569
+
2570
+
2571
+ -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2572
+ -- Check 7 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2573
+ -- No two (or more) original PK values map to same new PK value
2574
+ -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2575
+
2576
+ -- !x! if(table_exists(ups_pk_mapping_conflict))
2577
+ drop table if exists ups_pk_mapping_conflict cascade;
2578
+ -- !x! endif
2579
+ create table ups_pk_mapping_conflict
2580
+ select
2581
+ !!@old_pkcol_aliased!!,
2582
+ !!@new_pkcol_aliased!!
2583
+ from !!~staging_table!! as s
2584
+ inner join
2585
+ (
2586
+ select
2587
+ !!@new_pkcol!!
2588
+ from
2589
+ (select distinct !!@old_pkcol!!, !!@new_pkcol!! from !!~staging_table!! where !!@all_newpk_col_not_empty!!) as a
2590
+ group by
2591
+ !!@new_pkcol!!
2592
+ having count(*) >1
2593
+ ) as b on !!@joincond_newnew!!
2594
+ ;
2595
+
2596
+ -- !x! if(hasrows(ups_pk_mapping_conflict))
2597
+ -- !x! if(view_exists(ups_map_conf_rwcnt))
2598
+ drop view if exists ups_map_conf_rwcnt cascade;
2599
+ -- !x! endif
2600
+ create view ups_map_conf_rwcnt as
2601
+ select count(*) as rwcnt
2602
+ from ups_pk_mapping_conflict
2603
+ ;
2604
+ -- !x! subdata ~rowcount ups_map_conf_rwcnt
2605
+ -- !x! sub ~error_description Multiple original PKs mapped to same new PK in !!#stage_pfx!!!!#table!!: !!~rowcount!! row(s)
2606
+ -- !x! write " !!~error_description!!"
2607
+ insert into !!#qaerror_table!! (error_code, error_description)
2608
+ values ('Mapping conflict', '!!~error_description!!')
2609
+ ;
2610
+ -- !x! if(sub_defined(logfile))
2611
+ -- !x! write "" to !!logfile!!
2612
+ -- !x! write "!!~error_description!!" to !!logfile!!
2613
+ -- !x! if(sub_defined(log_errors))
2614
+ -- !x! andif(is_true(!!log_errors!!))
2615
+ -- !x! export ups_pk_mapping_conflict append to !!logfile!! as txt
2616
+ -- !x! endif
2617
+ -- !x! endif
2618
+ -- !x! if(is_true(!!#display_errors!!))
2619
+ -- !x! prompt message "Multiple original PKs mapped to same new PK in !!#stage_pfx!!!!#table!!" display ups_pk_mapping_conflict
2620
+ -- !x! endif
2621
+ -- !x! endif
2622
+
2623
+
2624
+ -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2625
+ -- Check 8 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2626
+ -- No single original PK value maps to multiple new PK values
2627
+ -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2628
+
2629
+ -- !x! if(table_exists(ups_pk_duplicate_keys))
2630
+ drop table if exists ups_pk_duplicate_keys cascade;
2631
+ -- !x! endif
2632
+ create table ups_pk_duplicate_keys
2633
+ select
2634
+ !!@old_pkcol_aliased!!,
2635
+ !!@new_pkcol_aliased!!
2636
+ from !!~staging_table!! as s
2637
+ inner join
2638
+ (
2639
+ select
2640
+ !!@old_pkcol!!
2641
+ from
2642
+ (select distinct !!@old_pkcol!!, !!@new_pkcol!! from !!~staging_table!! where !!@all_newpk_col_not_empty!!) as a
2643
+ group by
2644
+ !!@old_pkcol!!
2645
+ having count(*)>1
2646
+ ) as b on !!@joincond_origorig!!
2647
+ ;
2648
+
2649
+ -- !x! if(hasrows(ups_pk_duplicate_keys))
2650
+ -- !x! if(view_exists(ups_dup_key_rwcnt))
2651
+ drop view if exists ups_dup_key_rwcnt cascade;
2652
+ -- !x! endif
2653
+ create view ups_dup_key_rwcnt as
2654
+ select count(*) as rwcnt
2655
+ from ups_pk_duplicate_keys
2656
+ ;
2657
+ -- !x! subdata ~rowcount ups_dup_key_rwcnt
2658
+ -- !x! sub ~error_description Original PK mapped to multiple new PKs in !!#stage_pfx!!!!#table!!: !!~rowcount!! row(s)
2659
+ -- !x! write " !!~error_description!!"
2660
+ insert into !!#qaerror_table!! (error_code, error_description)
2661
+ values ('Duplicate keys', '!!~error_description!!')
2662
+ ;
2663
+ -- !x! if(sub_defined(logfile))
2664
+ -- !x! write "" to !!logfile!!
2665
+ -- !x! write "!!~error_description!!" to !!logfile!!
2666
+ -- !x! if(sub_defined(log_errors))
2667
+ -- !x! andif(is_true(!!log_errors!!))
2668
+ -- !x! export ups_pk_duplicate_keys append to !!logfile!! as txt
2669
+ -- !x! endif
2670
+ -- !x! endif
2671
+ -- !x! if(is_true(!!#display_errors!!))
2672
+ -- !x! prompt message "Original PK mapped to multiple new PKs in !!#stage_pfx!!!!#table!!" display ups_pk_duplicate_keys
2673
+ -- !x! endif
2674
+ -- !x! endif
2675
+
2676
+
2677
+ -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2678
+ -- Check 9 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2679
+ -- If any of the PK columns reference a parent table, all the "new" values of that column are valid
2680
+ -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2681
+
2682
+ -- Get ALL foreign key column references for the base table
2683
+ -- !x! if(table_exists(ups_fkcol_refs))
2684
+ drop table if exists ups_fkcol_refs cascade;
2685
+ -- !x! endif
2686
+ create table ups_fkcol_refs
2687
+ select
2688
+ rc.constraint_name as fk_constraint,
2689
+ cu.table_schema,
2690
+ cu.table_name,
2691
+ cu.column_name,
2692
+ cu.ordinal_position,
2693
+ cu_uq.table_schema as parent_schema,
2694
+ cu_uq.table_name as parent_table,
2695
+ cu_uq.column_name as parent_column,
2696
+ cu_uq.ordinal_position as parent_position
2697
+ from
2698
+ (select constraint_catalog, constraint_schema, constraint_name,
2699
+ table_name,
2700
+ unique_constraint_catalog, unique_constraint_schema, unique_constraint_name,
2701
+ referenced_table_name
2702
+ from information_schema.referential_constraints
2703
+ where constraint_schema = '!!$db_name!!'
2704
+ ) as rc
2705
+ inner join (select * from information_schema.table_constraints
2706
+ where constraint_type = 'FOREIGN KEY' and constraint_schema = '!!$db_name!!'
2707
+ ) as tc
2708
+ on tc.constraint_catalog = rc.constraint_catalog
2709
+ and tc.constraint_schema = rc.constraint_schema
2710
+ and tc.constraint_name = rc.constraint_name
2711
+ and tc.table_name = rc.table_name
2712
+ inner join (select * from information_schema.table_constraints
2713
+ where constraint_type not in ('FOREIGN KEY', 'CHECK')
2714
+ and constraint_schema = '!!$db_name!!'
2715
+ ) as tc_uq
2716
+ on tc_uq.constraint_catalog = rc.unique_constraint_catalog
2717
+ and tc_uq.constraint_schema = rc.unique_constraint_schema
2718
+ and tc_uq.constraint_name = rc.unique_constraint_name
2719
+ and tc_uq.table_name = rc.referenced_table_name
2720
+ inner join information_schema.key_column_usage as cu
2721
+ on cu.constraint_catalog = tc.constraint_catalog
2722
+ and cu.constraint_schema = tc.constraint_schema
2723
+ and cu.constraint_name = tc.constraint_name
2724
+ and cu.table_schema = tc.table_schema
2725
+ and cu.table_name = tc.table_name
2726
+ inner join information_schema.key_column_usage as cu_uq
2727
+ on cu_uq.constraint_catalog = tc_uq.constraint_catalog
2728
+ and cu_uq.constraint_schema = tc_uq.constraint_schema
2729
+ and cu_uq.constraint_name = tc_uq.constraint_name
2730
+ and cu_uq.table_schema = tc_uq.table_schema
2731
+ and cu_uq.table_name = tc_uq.table_name
2732
+ and cu_uq.ordinal_position = cu.ordinal_position
2733
+ where
2734
+ rc.table_name = '!!#table!!'
2735
+ ;
2736
+
2737
+ -- Narrow the list down to ONLY dependencies that affect PK columns
2738
+ -- Include not just the PK columns themselves, but ALL columns included in FKs
2739
+ -- that include ANY PK columns (probably rare/unlikely that a non-PK column would be
2740
+ -- part of the same foreign key as a PK column, but this ensures that ALL columns of the FK
2741
+ -- are included, whether or not the column is part of the PK)
2742
+ -- !x! if(table_exists(ups_pkcol_deps))
2743
+ drop table if exists ups_pkcol_deps cascade;
2744
+ -- !x! endif
2745
+ create table ups_pkcol_deps
2746
+ select
2747
+ refs.*
2748
+ from
2749
+ ups_fkcol_refs as refs
2750
+ inner join
2751
+ --Distinct list of FK constraints on the table that include ANY PK columns
2752
+ (
2753
+ select distinct
2754
+ fk_constraint, r.table_schema, r.table_name
2755
+ from
2756
+ ups_fkcol_refs as r
2757
+ inner join ups_pkcol_info as p on r.table_schema=p.table_schema and r.table_name=p.table_name and r.column_name=p.column_name
2758
+ ) as const on refs.fk_constraint=const.fk_constraint and refs.table_schema=const.table_schema and refs.table_name=const.table_name
2759
+ ;
2760
+
2761
+ -- Create a control table for looping to check each fk
2762
+ -- Include (for later use) some of the constructed strings that apply to the entire PK (not
2763
+ -- just the FK being checked)
2764
+ -- !x! if(table_exists(ups_pkfk_ctrl))
2765
+ drop table if exists ups_pkfk_ctrl cascade;
2766
+ -- !x! endif
2767
+ create table ups_pkfk_ctrl
2768
+ select
2769
+ fk_constraint,
2770
+ table_name, parent_table,
2771
+ min(parent_column) as any_referenced_column,
2772
+ '!!@old_pkcol_aliased!!' as old_pkcol_aliased,
2773
+ '!!@new_pkcol!!' as new_pkcol,
2774
+ '!!@all_newpk_col_not_empty!!' as all_newpk_col_not_empty,
2775
+ False as processed
2776
+ from ups_pkcol_deps
2777
+ group by
2778
+ fk_constraint, table_name, parent_table
2779
+ ;
2780
+
2781
+ -- Create a view to select one constraint to process.
2782
+ -- !x! if(view_exists(ups_next_fk))
2783
+ drop view if exists ups_next_fk cascade;
2784
+ -- !x! endif
2785
+ create view ups_next_fk as
2786
+ select *
2787
+ from ups_pkfk_ctrl
2788
+ where not processed
2789
+ limit 1
2790
+ ;
2791
+
2792
+ --Process all constraints: check every foreign key
2793
+ --!x! execute script updtpkqa_one_innerloop with (stage_pfx=!!#stage_pfx!!, qaerror_table=!!#qaerror_table!!, display_errors=!!#display_errors!!)
2794
+ -- !x! endif
2795
+ -- !x! endif
2796
+ -- !x! endif
2797
+
2798
+ -- !x! if(table_exists(ups_missing_pk_cols))
2799
+ drop table if exists ups_missing_pk_cols cascade;
2800
+ -- !x! endif
2801
+ -- !x! if(table_exists(ups_pkqa_str_lib))
2802
+ drop table if exists ups_pkqa_str_lib;
2803
+ -- !x! endif
2804
+ -- !x! if(table_exists(ups_any_pk_cols))
2805
+ drop table if exists ups_any_pk_cols cascade;
2806
+ -- !x! endif
2807
+ -- !x! if(table_exists(ups_empty_pk_cols))
2808
+ drop table if exists ups_empty_pk_cols cascade;
2809
+ -- !x! endif
2810
+ -- !x! if(view_exists(ups_empty_pk_cols_rwcnt))
2811
+ drop view if exists ups_empty_pk_cols_rwcnt cascade;
2812
+ -- !x! endif
2813
+ -- !x! if(table_exists(ups_old_pks_wc))
2814
+ drop table if exists ups_old_pks_wc cascade;
2815
+ -- !x! endif
2816
+ -- !x! if(table_exists(ups_invalid_old_pks))
2817
+ drop table if exists ups_invalid_old_pks cascade;
2818
+ -- !x! endif
2819
+ -- !x! if(view_exists(ups_invalid_pk_rwcnt))
2820
+ drop view if exists ups_invld_pk_rwcnt cascade;
2821
+ -- !x! endif
2822
+ -- !x! if(table_exists(ups_existing_new_pks))
2823
+ drop table if exists ups_existing_new_pks cascade;
2824
+ -- !x! endif
2825
+ -- !x! if(view_exists(ups_exst_nwpk_rwcnt))
2826
+ drop view if exists ups_exst_nwpk_rwcnt cascade;
2827
+ -- !x! endif
2828
+ -- !x! if(table_exists(ups_pk_mapping_conflict))
2829
+ drop table if exists ups_pk_mapping_conflict cascade;
2830
+ -- !x! endif
2831
+ -- !x! if(view_exists(ups_map_conf_rwcnt))
2832
+ drop view if exists ups_map_conf_rwcnt cascade;
2833
+ -- !x! endif
2834
+ -- !x! if(table_exists(ups_pk_duplicate_keys))
2835
+ drop table if exists ups_pk_duplicate_keys cascade;
2836
+ -- !x! endif
2837
+ -- !x! if(view_exists(ups_dup_key_rwcnt))
2838
+ drop view if exists ups_dup_key_rwcnt cascade;
2839
+ -- !x! endif
2840
+ -- !x! if(table_exists(ups_fkcol_refs))
2841
+ drop table if exists ups_fkcol_refs cascade;
2842
+ -- !x! endif
2843
+ -- !x! if(table_exists(ups_pkcol_deps))
2844
+ drop table if exists ups_pkcol_deps cascade;
2845
+ -- !x! endif
2846
+ -- !x! if(table_exists(ups_pkfk_ctrl))
2847
+ drop table if exists ups_pkfk_ctrl cascade;
2848
+ -- !x! endif
2849
+ -- !x! if(view_exists(ups_next_fk))
2850
+ drop view if exists ups_next_fk cascade;
2851
+ -- !x! endif
2852
+
2853
+ -- !x! END SCRIPT
2854
+ -- ################### UPDTPKQA_ONE ########################
2855
+ -- ################################################################
2856
+ -- Script UPDTPKQA_ONE_INNERLOOP
2857
+ -- ----------------------------------------------------------------
2858
+ -- !x! BEGIN SCRIPT UPDTPKQA_ONE_INNERLOOP with parameters(stage_pfx, qaerror_table, display_errors)
2859
+ -- !x! if(hasrows(ups_next_fk))
2860
+
2861
+ -- !x! select_sub ups_next_fk
2862
+
2863
+ -- Compile FK info for the selected constraint
2864
+ -- !x! if(table_exists(ups_sel_fk_cols))
2865
+ drop table if exists ups_sel_fk_cols cascade;
2866
+ -- !x! endif
2867
+ create table ups_sel_fk_cols
2868
+ select
2869
+ fk_constraint, table_name,
2870
+ parent_table,
2871
+ group_concat(parent_column order by column_name separator ', ') as referenced_cols,
2872
+ group_concat('s.new_' || column_name || '=' || 'b.' || parent_column order by column_name separator ' and ') as join_condition
2873
+ from ups_pkcol_deps
2874
+ where fk_constraint='!!@fk_constraint!!'
2875
+ group by
2876
+ fk_constraint, table_name,
2877
+ parent_table
2878
+ ;
2879
+ -- !x! select_sub ups_sel_fk_cols
2880
+
2881
+ -- Construct SQL to check the selected FK
2882
+ -- !x! sub ~select_stmt create table ups_pk_fk_check select !!@old_pkcol_aliased!!, !!@new_pkcol!! from !!#stage_pfx!!!!@table_name!! as s
2883
+ -- !x! sub ~join_stmt left join !!@parent_table!! as b on !!@join_condition!!
2884
+ -- !x! sub ~where_clause where !!@all_newpk_col_not_empty!! and b.!!@any_referenced_column!! is null
2885
+
2886
+ -- !x! sub ~fk_check !!~select_stmt!!
2887
+ -- !x! sub_append ~fk_check !!~join_stmt!!
2888
+ -- !x! sub_append ~fk_check !!~where_clause!!
2889
+
2890
+ -- Write the SQL to the log file if requested.
2891
+ -- !x! if(sub_defined(logfile))
2892
+ -- !x! andif(sub_defined(log_sql))
2893
+ -- !x! andif(is_true(!!log_sql!!))
2894
+ -- !x! write "" to !!logfile!!
2895
+ -- !x! write "SQL for checking foreign key !!@fk_constraint!! for PK update to !!@table_name!!:" to !!logfile!!
2896
+ -- !x! write [!!~fk_check!!] to !!logfile!!
2897
+ -- !x! endif
2898
+
2899
+ -- Run the check
2900
+ -- !x! if(table_exists(ups_pk_fk_check))
2901
+ drop table if exists ups_pk_fk_check cascade;
2902
+ -- !x! endif
2903
+
2904
+ !!~fk_check!!;
2905
+
2906
+ -- !x! if(hasrows(ups_pk_fk_check))
2907
+
2908
+ -- !x! if(view_exists(ups_pk_fk_check_rwcnt))
2909
+ drop view if exists ups_pk_fk_check_rwcnt cascade;
2910
+ -- !x! endif
2911
+ create or replace view ups_pk_fk_check_rwcnt as
2912
+ select count(*) as rwcnt
2913
+ from ups_pk_fk_check
2914
+ ;
2915
+
2916
+ -- !x! subdata ~rowcount ups_pk_fk_check_rwcnt
2917
+ -- !x! sub ~error_description !!@parent_table!! (!!@referenced_cols!!): !!~rowcount!! row(s)
2918
+
2919
+ -- !x! write " Violation of foreign key !!@fk_constraint!! in new primary key columns in !!@stag_pfx!!!!@table_name!! referencing !!@parent_table!!: !!~rowcount!! row(s)"
2920
+
2921
+ -- !x! if(view_exists(pk_fk_qa_error))
2922
+ drop view if exists ups_pk_fk_qa_error cascade;
2923
+ -- !x! endif
2924
+ create or replace view ups_pk_fk_qa_error as
2925
+ select
2926
+ error_code, error_description
2927
+ from !!#qaerror_table!!
2928
+ where error_code='Invalid reference to parent table(s)';
2929
+ -- !x! if(hasrows(ups_pk_fk_qa_error))
2930
+ update !!#qaerror_table!!
2931
+ set error_description=error_description || '; !!~error_description!!'
2932
+ where error_code='Invalid reference to parent table(s)';
2933
+
2934
+ -- !x! else
2935
+ insert into !!#qaerror_table!! (error_code, error_description)
2936
+ values ('Invalid reference to parent table(s)', '!!~error_description!!')
2937
+ ;
2938
+ -- !x! endif
2939
+
2940
+
2941
+ -- !x! if(sub_defined(logfile))
2942
+ -- !x! write "" to !!logfile!!
2943
+ -- !x! write "Violation of foreign key !!@fk_constraint!! in new primary key columns in !!@stage_pfx!!!!@table_name!! referencing !!@parent_table!!: !!~rowcount!! row(s)" to !!logfile!!
2944
+ -- !x! if(sub_defined(log_errors))
2945
+ -- !x! andif(is_true(!!log_errors!!))
2946
+ -- !x! export ups_pk_fk_check append to !!logfile!! as txt
2947
+ -- !x! endif
2948
+ -- !x! endif
2949
+ -- !x! if(is_true(!!#display_errors!!))
2950
+ -- !x! prompt message "Violation of foreign key !!@fk_constraint!! in new primary key columns in !!@stage_pfx!!!!@table_name!! referencing !!@parent_table!!" display ups_pk_fk_check
2951
+ -- !x! endif
2952
+
2953
+ -- !x! endif
2954
+
2955
+ -- Mark constraint as processed
2956
+ update ups_pkfk_ctrl
2957
+ set processed=True
2958
+ where fk_constraint='!!@fk_constraint!!';
2959
+
2960
+ -- !x! if(table_exists(ups_sel_fk_cols))
2961
+ drop table if exists ups_sel_fk_cols cascade;
2962
+ -- !x! endif
2963
+ -- !x! if(table_exists(ups_pk_fk_check))
2964
+ drop table if exists ups_pk_fk_check cascade;
2965
+ -- !x! endif
2966
+ -- !x! if(view_exists(ups_pk_fk_check_rwcnt))
2967
+ drop view if exists ups_pk_fk_check_rwcnt cascade;
2968
+ -- !x! endif
2969
+ -- !x! if(view_exists(pk_fk_qa_error))
2970
+ drop view if exists ups_pk_fk_qa_error cascade;
2971
+ -- !x! endif
2972
+
2973
+ --LOOP
2974
+ -- !x! execute script updtpkqa_one_innerloop with (stage_pfx=!!#stage_pfx!!, qaerror_table=!!#qaerror_table!!, display_errors=!!#display_errors!!)
2975
+
2976
+ -- !x! endif
2977
+
2978
+ -- !x! END SCRIPT
2979
+ -- #################### End of UPDTPKQA_ONE ########################
2980
+ -- ################################################################
2981
+