Constrain serial.issuance.holding_code to be valid JSON or NULL
[working/Evergreen.git] / Open-ILS / src / sql / Pg / upgrade / 0706.schema.serial-holding-code-constraint.sql
1 BEGIN;
2
3 SELECT evergreen.upgrade_deps_block_check('0706', :eg_version);
4
5 -- This throws away data, but only data that causes breakage anyway.
6 UPDATE serial.issuance SET holding_code = NULL WHERE NOT is_json(holding_code);
7
8 -- If we don't do this, we have unprocessed triggers and we can't alter the table
9 SET CONSTRAINTS serial.issuance_caption_and_pattern_fkey IMMEDIATE;
10
11 ALTER TABLE serial.issuance ADD CHECK (holding_code IS NULL OR is_json(holding_code));
12
13 -- For the sake of completeness if these sneaked through
14 ALTER TABLE serial.materialized_holding_code DROP COLUMN IF EXISTS holding_type;
15 ALTER TABLE serial.materialized_holding_code DROP COLUMN IF EXISTS ind1;
16 ALTER TABLE serial.materialized_holding_code DROP COLUMN IF EXISTS ind2;
17
18 CREATE OR REPLACE FUNCTION serial.materialize_holding_code() RETURNS TRIGGER
19 AS $func$ 
20 use strict;
21
22 use MARC::Field;
23 use JSON::XS;
24
25 if (not defined $_TD->{new}{holding_code}) {
26     elog(WARNING, 'NULL in "holding_code" column of serial.issuance allowed for now, but may not be useful');
27     return;
28 }
29
30 # Do nothing if holding_code has not changed...
31
32 if ($_TD->{new}{holding_code} eq $_TD->{old}{holding_code}) {
33     # ... unless the following internal flag is set.
34
35     my $flag_rv = spi_exec_query(q{
36         SELECT * FROM config.internal_flag
37         WHERE name = 'serial.rematerialize_on_same_holding_code' AND enabled
38     }, 1);
39     return unless $flag_rv->{processed};
40 }
41
42
43 my $holding_code = (new JSON::XS)->decode($_TD->{new}{holding_code});
44
45 my $field = new MARC::Field('999', @$holding_code); # tag doesnt matter
46
47 my $dstmt = spi_prepare(
48     'DELETE FROM serial.materialized_holding_code WHERE issuance = $1',
49     'INT'
50 );
51 spi_exec_prepared($dstmt, $_TD->{new}{id});
52
53 my $istmt = spi_prepare(
54     q{
55         INSERT INTO serial.materialized_holding_code (
56             issuance, subfield, value
57         ) VALUES ($1, $2, $3)
58     }, qw{INT CHAR TEXT}
59 );
60
61 foreach ($field->subfields) {
62     spi_exec_prepared(
63         $istmt,
64         $_TD->{new}{id},
65         $_->[0],
66         $_->[1]
67     );
68 }
69
70 return;
71
72 $func$ LANGUAGE 'plperlu';
73
74 COMMIT;