merchant-0036.sql.in (5209B)
1 -- 2 -- This file is part of TALER 3 -- Copyright (C) 2026 Taler Systems SA 4 -- 5 -- TALER is free software; you can redistribute it and/or modify it under the 6 -- terms of the GNU General Public License as published by the Free Software 7 -- Foundation; either version 3, or (at your option) any later version. 8 -- 9 -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 -- 13 -- You should have received a copy of the GNU General Public License along with 14 -- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 16 -- @file merchant-0036.sql.in 17 -- @brief Move per-instance tables into per-instance schemas 18 -- merchant_instance_<merchant_serial>. Each existing row of 19 -- merchant_instances is converted by calling 20 -- merchant.create_instance_schema(serial), copying the rows of every 21 -- per-instance table into the new schema (dropping the merchant_serial 22 -- column), and finally dropping the now-empty merchant.<table>. 23 -- @author Christian Grothoff 24 25 BEGIN; 26 27 SELECT _v.register_patch('merchant-0036', NULL, NULL); 28 29 SET search_path TO merchant; 30 31 -- --------------------------------------------------------------------- 32 -- Step 0: Fold merchant_keys.merchant_priv into merchant_instances as a 33 -- nullable column. Setting merchant_priv to NULL replaces deleting the 34 -- key row. The merchant_keys table itself is dropped in step 4. 35 -- --------------------------------------------------------------------- 36 ALTER TABLE merchant.merchant_instances 37 ADD COLUMN merchant_priv BYTEA 38 CHECK (merchant_priv IS NULL OR LENGTH(merchant_priv) = 32); 39 COMMENT ON COLUMN merchant.merchant_instances.merchant_priv 40 IS 'private key of the instance, NULL once the key has been "deleted"'; 41 UPDATE merchant.merchant_instances mi 42 SET merchant_priv = mk.merchant_priv 43 FROM merchant.merchant_keys mk 44 WHERE mk.merchant_serial = mi.merchant_serial; 45 46 CREATE TABLE merchant.instance_fixups 47 (instance_fixup_serial_id INT8 GENERATED BY DEFAULT AS IDENTITY 48 ,migration_name TEXT NOT NULL 49 ,version INT8 NOT NULL); 50 COMMENT ON TABLE instance_fixups 51 IS 'Fixups to setup the per-instance tables'; 52 COMMENT ON COLUMN instance_fixups.migration_name 53 IS 'Name of the stored procedure to run to fix up the schema of the instance'; 54 COMMENT ON COLUMN instance_fixups.version 55 IS 'Version of the DB in which the given fix up should happen'; 56 57 CREATE INDEX instance_fixups_by_version 58 ON instance_fixups (version); 59 COMMENT ON INDEX instance_fixups_by_version 60 IS 'Used by create_instance_schema (and in the future on import)'; 61 62 -- --------------------------------------------------------------------- 63 -- Step 1: Install the schema constructor and actual fix-ups. 64 -- procedures.sql will re-install the same definition (DROP IF EXISTS), 65 -- so installing it here is harmless and lets the migration call it. 66 -- --------------------------------------------------------------------- 67 #include "../create_tables.sql" 68 #include "../pg_create_instance_schema.sql" 69 #include "../pg_fixup_instance_schema.sql" 70 #include "merchant-0036-init.sql.fragment" 71 72 -- --------------------------------------------------------------------- 73 -- Step 2: Build a per-instance schema for every existing instance. 74 -- --------------------------------------------------------------------- 75 DO $MIG$ 76 DECLARE 77 rec RECORD; 78 BEGIN 79 FOR rec IN 80 SELECT merchant_serial 81 FROM merchant.merchant_instances 82 LOOP 83 PERFORM merchant.create_instance_schema(rec.merchant_serial); 84 END LOOP; 85 END $MIG$; 86 87 -- --------------------------------------------------------------------- 88 -- Step 3: Migrate row data per instance. 89 -- Tables are copied in FK-dependency order. Every copy drops the 90 -- merchant_serial column. After each table is copied, its IDENTITY 91 -- sequence (if any) is advanced past MAX(serial). 92 -- Indirect-FK tables (merchant_kyc, merchant_deposits, ...) are copied 93 -- by JOINing back to the table that owns the merchant_serial. 94 -- --------------------------------------------------------------------- 95 -- Suppress USER triggers during the bulk copy: per-instance triggers 96 -- (e.g. merchant_kyc_insert_trigger) would otherwise fire on every 97 -- inserted row and CALL into per-instance procedures that may rely on 98 -- runtime invariants we do not have during migration. This setting is 99 -- transaction-local and does not affect normal callers. 100 SET session_replication_role = replica; 101 102 DO $MIG$ 103 DECLARE 104 rec RECORD; 105 s TEXT; 106 BEGIN 107 FOR rec IN 108 SELECT merchant_serial 109 FROM merchant.merchant_instances 110 LOOP 111 s := 'merchant_instance_' || rec.merchant_serial::TEXT; 112 #include "merchant-0036-copy.sql.fragment" 113 #include "merchant-0036-setval.sql.fragment" 114 END LOOP; 115 END $MIG$; 116 117 SET session_replication_role = origin; 118 119 -- --------------------------------------------------------------------- 120 -- Step 4: Drop old per-instance tables from the merchant schema, in 121 -- reverse FK-dependency order so CASCADE is not needed. 122 -- --------------------------------------------------------------------- 123 #include "merchant-0036-drop.sql.fragment" 124 125 COMMIT;