oops; put this into the migration_tools schema
[migration-tools.git] / sql / base / 00-infrastructure.sql
index ff0bbc9..ea79446 100644 (file)
@@ -49,9 +49,9 @@ CREATE OR REPLACE FUNCTION migration_tools.init (TEXT) RETURNS VOID AS $$
         migration_schema ALIAS FOR $1;
         sql TEXT;
     BEGIN
-        EXECUTE 'DROP TABLE IF EXISTS ' || migration_schema || '.config;' );
-        EXECUTE 'CREATE TABLE ' || migration_schema || '.config ( key TEXT UNIQUE, value TEXT);' );
-        EXECUTE 'INSERT INTO ' || migration_schema || '.config (key,value) VALUES ( ''production_tables'', ''asset.call_number,asset.call_number_prefix,asset.call_number_suffix,asset.copy_location,asset.copy,asset.copy_alert,asset.stat_cat,asset.stat_cat_entry,asset.stat_cat_entry_copy_map,asset.copy_note,actor.usr,actor.card,actor.usr_address,actor.stat_cat,actor.stat_cat_entry,actor.stat_cat_entry_usr_map,actor.usr_note,actor.usr_standing_penalty,actor.usr_setting,action.circulation,action.hold_request,action.hold_notification,action.hold_request_note,action.hold_transit_copy,action.transit_copy,money.grocery,money.billing,money.cash_payment,money.forgive_payment,acq.provider,acq.provider_address,acq.provider_note,acq.provider_contact,acq.provider_contact_address,acq.fund,acq.fund_allocation,acq.fund_tag,acq.fund_tag_map,acq.funding_source,acq.funding_source_credit,acq.lineitem,acq.purchase_order,acq.po_item,acq.invoice,acq.invoice_item,acq.invoice_entry,acq.lineitem_detail,acq.fund_debit,acq.fund_transfer,acq.po_note,config.circ_matrix_matchpoint,config.circ_matrix_limit_set_map,config.hold_matrix_matchpoint,asset.copy_tag,asset.copy_tag_copy_map,config.copy_tag_type,serial.item,serial.item_note,serial.record_entry,biblio.record_entry'' );' );
+        EXECUTE 'DROP TABLE IF EXISTS ' || migration_schema || '.config;';
+        EXECUTE 'CREATE TABLE ' || migration_schema || '.config ( key TEXT UNIQUE, value TEXT);';
+        EXECUTE 'INSERT INTO ' || migration_schema || '.config (key,value) VALUES ( ''production_tables'', ''asset.call_number,asset.call_number_prefix,asset.call_number_suffix,asset.copy_location,asset.copy,asset.copy_alert,asset.stat_cat,asset.stat_cat_entry,asset.stat_cat_entry_copy_map,asset.copy_note,actor.usr,actor.card,actor.usr_address,actor.stat_cat,actor.stat_cat_entry,actor.stat_cat_entry_usr_map,actor.usr_note,actor.usr_standing_penalty,actor.usr_setting,action.circulation,action.hold_request,action.hold_notification,action.hold_request_note,action.hold_transit_copy,action.transit_copy,money.grocery,money.billing,money.cash_payment,money.forgive_payment,acq.provider,acq.provider_address,acq.provider_note,acq.provider_contact,acq.provider_contact_address,acq.fund,acq.fund_allocation,acq.fund_tag,acq.fund_tag_map,acq.funding_source,acq.funding_source_credit,acq.lineitem,acq.purchase_order,acq.po_item,acq.invoice,acq.invoice_item,acq.invoice_entry,acq.lineitem_detail,acq.fund_debit,acq.fund_transfer,acq.po_note,config.circ_matrix_matchpoint,config.circ_matrix_limit_set_map,config.hold_matrix_matchpoint,asset.copy_tag,asset.copy_tag_copy_map,config.copy_tag_type,serial.item,serial.item_note,serial.record_entry,biblio.record_entry'' );';
     END;
 $$ LANGUAGE PLPGSQL STRICT VOLATILE;
 
@@ -62,13 +62,13 @@ CREATE OR REPLACE FUNCTION migration_tools.build (TEXT) RETURNS VOID AS $$
     BEGIN
         SELECT migration_tools.production_tables(migration_schema) INTO STRICT production_tables;
         PERFORM migration_tools.build_base_staging_tables(migration_schema,production_tables);
-        EXECUTE 'CREATE UNIQUE INDEX ' || migration_schema || '_patron_barcode_key ON ' || migration_schema || '.actor_card ( barcode );' );
-        EXECUTE 'CREATE UNIQUE INDEX ' || migration_schema || '_patron_usrname_key ON ' || migration_schema || '.actor_usr ( usrname );' );
-        EXECUTE 'CREATE UNIQUE INDEX ' || migration_schema || '_copy_barcode_key ON ' || migration_schema || '.asset_copy ( barcode );' );
-        EXECUTE 'CREATE UNIQUE INDEX ' || migration_schema || '_copy_id_key ON ' || migration_schema || '.asset_copy ( id );' );
-        EXECUTE 'CREATE INDEX ' || migration_schema || '_callnum_record_idx ON ' || migration_schema || '.asset_call_number ( record );' );
-        EXECUTE 'CREATE INDEX ' || migration_schema || '_callnum_upper_label_id_lib_idx ON ' || migration_schema || '.asset_call_number ( UPPER(label),id,owning_lib );' );
-        EXECUTE 'CREATE UNIQUE INDEX ' || migration_schema || '_callnum_label_once_per_lib ON ' || migration_schema || '.asset_call_number ( record,owning_lib,label,prefix,suffix );' );
+        EXECUTE 'CREATE UNIQUE INDEX ' || migration_schema || '_patron_barcode_key ON ' || migration_schema || '.actor_card ( barcode );';
+        EXECUTE 'CREATE UNIQUE INDEX ' || migration_schema || '_patron_usrname_key ON ' || migration_schema || '.actor_usr ( usrname );';
+        EXECUTE 'CREATE UNIQUE INDEX ' || migration_schema || '_copy_barcode_key ON ' || migration_schema || '.asset_copy ( barcode );';
+        EXECUTE 'CREATE UNIQUE INDEX ' || migration_schema || '_copy_id_key ON ' || migration_schema || '.asset_copy ( id );';
+        EXECUTE 'CREATE INDEX ' || migration_schema || '_callnum_record_idx ON ' || migration_schema || '.asset_call_number ( record );';
+        EXECUTE 'CREATE INDEX ' || migration_schema || '_callnum_upper_label_id_lib_idx ON ' || migration_schema || '.asset_call_number ( UPPER(label),id,owning_lib );';
+        EXECUTE 'CREATE UNIQUE INDEX ' || migration_schema || '_callnum_label_once_per_lib ON ' || migration_schema || '.asset_call_number ( record,owning_lib,label,prefix,suffix );';
     END;
 $$ LANGUAGE PLPGSQL STRICT VOLATILE;
 
@@ -91,13 +91,13 @@ CREATE OR REPLACE FUNCTION migration_tools.build_specific_base_staging_table (TE
         columns RECORD;
     BEGIN
         base_staging_table = REPLACE( production_table, '.', '_' );
-        EXECUTE 'CREATE TABLE ' || migration_schema || '.' || base_staging_table || ' ( LIKE ' || production_table || ' INCLUDING DEFAULTS EXCLUDING CONSTRAINTS );' );
+        EXECUTE 'CREATE TABLE ' || migration_schema || '.' || base_staging_table || ' ( LIKE ' || production_table || ' INCLUDING DEFAULTS EXCLUDING CONSTRAINTS );';
         FOR columns IN 
             SELECT table_schema, table_name, column_name, data_type
             FROM information_schema.columns 
             WHERE table_schema = migration_schema AND table_name = base_staging_table AND is_nullable = 'NO' AND column_default IS NULL
         LOOP
-            EXECUTE( $1, 'ALTER TABLE ' || columns.table_schema || '.' || columns.table_name || ' ALTER COLUMN ' || columns.column_name || ' DROP NOT NULL;' );
+            EXECUTE 'ALTER TABLE ' || columns.table_schema || '.' || columns.table_name || ' ALTER COLUMN ' || columns.column_name || ' DROP NOT NULL;';
         END LOOP;
     END;
 $$ LANGUAGE PLPGSQL STRICT VOLATILE;
@@ -115,7 +115,7 @@ CREATE OR REPLACE FUNCTION migration_tools.create_linked_legacy_table_from (TEXT
     BEGIN
         create_sql := 'CREATE TABLE ' || migration_schema || '.' || parent_table || '_legacy ( ';
         FOR columns IN
-            SELECT table_schema, table_name, column_name, data_type
+            SELECT table_schema, table_name, column_name, data_type, numeric_precision, numeric_scale
             FROM information_schema.columns
             WHERE table_schema = migration_schema AND table_name = source_table
         LOOP
@@ -127,6 +127,8 @@ CREATE OR REPLACE FUNCTION migration_tools.create_linked_legacy_table_from (TEXT
             create_sql := create_sql || columns.column_name || ' ';
             if columns.data_type = 'ARRAY' then
                 create_sql := create_sql || 'TEXT[]';
+            elsif columns.data_type = 'numeric' then
+                create_sql := create_sql || 'NUMERIC('||columns.numeric_precision||','||columns.numeric_scale||')';
             else
                 create_sql := create_sql || columns.data_type;
             end if;
@@ -141,147 +143,67 @@ CREATE OR REPLACE FUNCTION migration_tools.create_linked_legacy_table_from (TEXT
     END;
 $$ LANGUAGE PLPGSQL STRICT VOLATILE;
 
-CREATE OR REPLACE FUNCTION migration_tools.attempt_cast (TEXT, TEXT) RETURNS TEXT AS $$
-    DECLARE
-        attempt_value ALIAS FOR $1;
-        datatype ALIAS FOR $2;
-    BEGIN
-        EXECUTE 'SELECT ' || quote_literal(attempt_value) || '::' || datatype || ' AS a;';
-        RETURN attempt_value;
-    EXCEPTION
-        WHEN OTHERS THEN RETURN NULL;
-    END;
-$$ LANGUAGE PLPGSQL STRICT STABLE;
-
-CREATE OR REPLACE FUNCTION migration_tools.attempt_date (TEXT,TEXT) RETURNS DATE AS $$
-    DECLARE
-        attempt_value ALIAS FOR $1;
-        fail_value ALIAS FOR $2;
-        output DATE;
-    BEGIN
-        FOR output IN
-            EXECUTE 'SELECT ' || quote_literal(REGEXP_REPLACE(attempt_value,'^(\d\d)(\d\d)(\d\d)$','\1-\2-\3')) || '::date AS a;'
-        LOOP
-            RETURN output;
-        END LOOP;
-    EXCEPTION
-        WHEN OTHERS THEN
-            FOR output IN
-                EXECUTE 'SELECT ' || quote_literal(fail_value) || '::date AS a;'
-            LOOP
-                RETURN output;
-            END LOOP;
-    END;
-$$ LANGUAGE PLPGSQL STRICT STABLE;
-
-CREATE OR REPLACE FUNCTION migration_tools.attempt_timestamptz (TEXT,TEXT) RETURNS TIMESTAMPTZ AS $$
-    DECLARE
-        attempt_value ALIAS FOR $1;
-        fail_value ALIAS FOR $2;
-        output TIMESTAMPTZ;
-    BEGIN
-        FOR output IN
-            EXECUTE 'SELECT ' || quote_literal(attempt_value) || '::TIMESTAMPTZ AS a;'
-        LOOP
-            RETURN output;
-        END LOOP;
-    EXCEPTION
-        WHEN OTHERS THEN
-            FOR output IN
-                EXECUTE 'SELECT ' || quote_literal(fail_value) || '::TIMESTAMPTZ AS a;'
-            LOOP
-                RETURN output;
-            END LOOP;
-    END;
-$$ LANGUAGE PLPGSQL STRICT STABLE;
-
-CREATE OR REPLACE FUNCTION migration_tools.attempt_money (TEXT,TEXT) RETURNS NUMERIC(8,2) AS $$
+-- creates other child table so you can have more than one child table in a schema from a base table 
+CREATE OR REPLACE FUNCTION migration_tools.build_variant_staging_table(text, text, text)
+ RETURNS void
+ LANGUAGE plpgsql
+ STRICT
+AS $function$
     DECLARE
-        attempt_value ALIAS FOR $1;
-        fail_value ALIAS FOR $2;
-        output NUMERIC(8,2);
+        migration_schema ALIAS FOR $1;
+        production_table ALIAS FOR $2;
+        base_staging_table ALIAS FOR $3;
+        columns RECORD;
     BEGIN
-        FOR output IN
-            EXECUTE 'SELECT ' || quote_literal(REPLACE(REPLACE(attempt_value,'$',''),',','')) || '::NUMERIC(8,2) AS a;'
+        --RAISE INFO 'In migration_tools.build_specific_base_staging_table(%,%) -> %', migration_schema, production_table, base_staging_table;
+        EXECUTE 'CREATE TABLE ' || migration_schema || '.' || base_staging_table || ' ( LIKE ' || production_table || ' INCLUDING DEFAULTS EXCLUDING CONSTRAINTS );';
+        EXECUTE '
+            INSERT INTO ' || migration_schema || '.fields_requiring_mapping
+                SELECT table_schema, table_name, column_name, data_type
+                FROM information_schema.columns
+                WHERE table_schema = ''' || migration_schema || ''' AND table_name = ''' || base_staging_table || ''' AND is_nullable = ''NO'' AND column_default IS NULL;
+        ';
+        FOR columns IN
+            SELECT table_schema, table_name, column_name, data_type
+            FROM information_schema.columns
+            WHERE table_schema = migration_schema AND table_name = base_staging_table AND is_nullable = 'NO' AND column_default IS NULL
         LOOP
-            RETURN output;
+            EXECUTE 'ALTER TABLE ' || columns.table_schema || '.' || columns.table_name || ' ALTER COLUMN ' || columns.column_name || ' DROP NOT NULL;';
         END LOOP;
-    EXCEPTION
-        WHEN OTHERS THEN
-            FOR output IN
-                EXECUTE 'SELECT ' || quote_literal(fail_value) || '::NUMERIC(8,2) AS a;'
-            LOOP
-                RETURN output;
-            END LOOP;
     END;
-$$ LANGUAGE PLPGSQL STRICT STABLE;
+$function$;
 
-CREATE OR REPLACE FUNCTION migration_tools.attempt_money6 (TEXT,TEXT) RETURNS NUMERIC(6,2) AS $$
+CREATE OR REPLACE FUNCTION migration_tools.assert (BOOLEAN) RETURNS VOID AS $$
     DECLARE
-        attempt_value ALIAS FOR $1;
-        fail_value ALIAS FOR $2;
-        output NUMERIC(6,2);
+        test ALIAS FOR $1;
     BEGIN
-        FOR output IN
-            EXECUTE 'SELECT ' || quote_literal(REPLACE(REPLACE(attempt_value,'$',''),',','')) || '::NUMERIC(6,2) AS a;'
-        LOOP
-            RETURN output;
-        END LOOP;
-    EXCEPTION
-        WHEN OTHERS THEN
-            FOR output IN
-                EXECUTE 'SELECT ' || quote_literal(fail_value) || '::NUMERIC(6,2) AS a;'
-            LOOP
-                RETURN output;
-            END LOOP;
+        IF NOT test THEN
+            RAISE EXCEPTION 'assertion';
+        END IF;
     END;
-$$ LANGUAGE PLPGSQL STRICT STABLE;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
 
-CREATE OR REPLACE FUNCTION migration_tools.attempt_money_from_pennies (TEXT,TEXT) RETURNS NUMERIC(8,2) AS $$
+CREATE OR REPLACE FUNCTION migration_tools.assert (BOOLEAN,TEXT) RETURNS VOID AS $$
     DECLARE
-        attempt_value ALIAS FOR $1;
-        fail_value ALIAS FOR $2;
-        output NUMERIC(8,2);
+        test ALIAS FOR $1;
+        msg ALIAS FOR $2;
     BEGIN
-        IF length(regexp_replace(attempt_value,'^0+','')) > 10 THEN
-            RAISE EXCEPTION 'too many digits';
+        IF NOT test THEN
+            RAISE EXCEPTION '%', msg;
         END IF;
-        FOR output IN
-            EXECUTE 'SELECT ' || quote_literal((left(lpad(regexp_replace(attempt_value,'^0+',''),10,'0'),-2) || '.' || right(lpad(regexp_replace(attempt_value,'^0+',''),10,'0'),2))::numeric(8,2)) || '::NUMERIC(8,2) AS a;'
-        LOOP
-            RETURN output;
-        END LOOP;
-    EXCEPTION
-        WHEN OTHERS THEN
-            FOR output IN
-                EXECUTE 'SELECT ' || quote_literal(fail_value) || '::NUMERIC(8,2) AS a;'
-            LOOP
-                RETURN output;
-            END LOOP;
     END;
-$$ LANGUAGE PLPGSQL STRICT STABLE;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
 
-CREATE OR REPLACE FUNCTION migration_tools.attempt_money_from_pennies6 (TEXT,TEXT) RETURNS NUMERIC(6,2) AS $$
+CREATE OR REPLACE FUNCTION migration_tools.assert (BOOLEAN,TEXT,TEXT) RETURNS TEXT AS $$
     DECLARE
-        attempt_value ALIAS FOR $1;
-        fail_value ALIAS FOR $2;
-        output NUMERIC(6,2);
+        test ALIAS FOR $1;
+        fail_msg ALIAS FOR $2;
+        success_msg ALIAS FOR $3;
     BEGIN
-        IF length(regexp_replace(attempt_value,'^0+','')) > 8 THEN
-            RAISE EXCEPTION 'too many digits';
+        IF NOT test THEN
+            RAISE EXCEPTION '%', fail_msg;
         END IF;
-        FOR output IN
-            EXECUTE 'SELECT ' || quote_literal((left(lpad(regexp_replace(attempt_value,'^0+',''),8,'0'),-2) || '.' || right(lpad(regexp_replace(attempt_value,'^0+',''),8,'0'),2))::numeric(6,2)) || '::NUMERIC(6,2) AS a;'
-        LOOP
-            RETURN output;
-        END LOOP;
-    EXCEPTION
-        WHEN OTHERS THEN
-            FOR output IN
-                EXECUTE 'SELECT ' || quote_literal(fail_value) || '::NUMERIC(6,2) AS a;'
-            LOOP
-                RETURN output;
-            END LOOP;
+        RETURN success_msg;
     END;
-$$ LANGUAGE PLPGSQL STRICT STABLE;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;