790187692d98e307df27d248ed020871a179a5b2
[working/Evergreen.git] / Open-ILS / src / sql / Pg / upgrade / 0815.schema.config-metabib-interauthority.sql
1 BEGIN;
2
3 -- check whether patch can be applied
4 -- SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
5
6 ALTER TABLE authority.control_set_authority_field
7     ADD COLUMN linking_subfield CHAR(1);
8
9 UPDATE authority.control_set_authority_field
10     SET linking_subfield = '0' WHERE main_entry IS NOT NULL;
11
12 CREATE TABLE authority.authority_linking (
13     id      BIGSERIAL PRIMARY KEY,
14     source  BIGINT REFERENCES authority.record_entry (id) NOT NULL,
15     target  BIGINT REFERENCES authority.record_entry (id) NOT NULL,
16     field   INT REFERENCES authority.control_set_authority_field (id) NOT NULL
17 );
18
19 -- Given an authority record's ID, control set ID (if known), and marc::XML,
20 -- return all links to other authority records in the form of rows that
21 -- can be inserted into authority.authority_linking.
22 CREATE OR REPLACE FUNCTION authority.calculate_authority_linking(
23     rec_id BIGINT, rec_control_set INT, rec_marc_xml XML
24 ) RETURNS SETOF authority.authority_linking AS $func$
25 DECLARE
26     acsaf       authority.control_set_authority_field%ROWTYPE;
27     link        TEXT;
28     aal         authority.authority_linking%ROWTYPE;
29 BEGIN
30     IF rec_control_set IS NULL THEN
31         -- No control_set on record?  Guess at one
32         SELECT control_set INTO rec_control_set
33             FROM authority.control_set_authority_field
34             WHERE tag IN (
35                 SELECT UNNEST(
36                     XPATH('//*[starts-with(@tag,"1")]/@tag',rec_marc_xml::XML)::TEXT[]
37                 )
38             ) LIMIT 1;
39
40         IF NOT FOUND THEN
41             RAISE WARNING 'Could not even guess at control set for authority record %', rec_id;
42             RETURN;
43         END IF;
44     END IF;
45
46     aal.source := rec_id;
47
48     FOR acsaf IN
49         SELECT * FROM authority.control_set_authority_field
50         WHERE control_set = rec_control_set
51             AND linking_subfield IS NOT NULL
52             AND main_entry IS NOT NULL
53     LOOP
54         link := SUBSTRING(
55             (XPATH('//*[@tag="' || acsaf.tag || '"]/*[@code="' ||
56                 acsaf.linking_subfield || '"]/text()', rec_marc_xml))[1]::TEXT,
57             '\d+$'
58         );
59
60         -- Ignore links that are null, malformed, circular, or point to
61         -- non-existent authority records.
62         IF link IS NOT NULL AND link::BIGINT <> rec_id THEN
63             PERFORM * FROM authority.record_entry WHERE id = link::BIGINT;
64             IF FOUND THEN
65                 aal.target := link::BIGINT;
66                 aal.field := acsaf.id;
67                 RETURN NEXT aal;
68             END IF;
69         END IF;
70     END LOOP;
71 END;
72 $func$ LANGUAGE PLPGSQL;
73
74
75 -- AFTER UPDATE OR INSERT trigger for authority.record_entry
76 CREATE OR REPLACE FUNCTION authority.indexing_ingest_or_delete () RETURNS TRIGGER AS $func$
77 BEGIN
78
79     IF NEW.deleted IS TRUE THEN -- If this authority is deleted
80         DELETE FROM authority.bib_linking WHERE authority = NEW.id; -- Avoid updating fields in bibs that are no longer visible
81         DELETE FROM authority.full_rec WHERE record = NEW.id; -- Avoid validating fields against deleted authority records
82         DELETE FROM authority.simple_heading WHERE record = NEW.id;
83           -- Should remove matching $0 from controlled fields at the same time?
84
85         -- XXX What do we about the actual linking subfields present in
86         -- authority records that target this one when this happens?
87         DELETE FROM authority.authority_linking
88             WHERE source = NEW.id OR target = NEW.id;
89
90         RETURN NEW; -- and we're done
91     END IF;
92
93     IF TG_OP = 'UPDATE' THEN -- re-ingest?
94         PERFORM * FROM config.internal_flag WHERE name = 'ingest.reingest.force_on_same_marc' AND enabled;
95
96         IF NOT FOUND AND OLD.marc = NEW.marc THEN -- don't do anything if the MARC didn't change
97             RETURN NEW;
98         END IF;
99
100         -- Propagate these updates to any linked bib records
101         PERFORM authority.propagate_changes(NEW.id) FROM authority.record_entry WHERE id = NEW.id;
102
103         DELETE FROM authority.simple_heading WHERE record = NEW.id;
104         DELETE FROM authority.authority_linking WHERE source = NEW.id;
105     END IF;
106
107     INSERT INTO authority.authority_linking (source, target, field)
108         SELECT source, target, field FROM authority.calculate_authority_linking(
109             NEW.id, NEW.control_set, NEW.marc::XML
110         );
111
112     INSERT INTO authority.simple_heading (record,atag,value,sort_value)
113         SELECT record, atag, value, sort_value FROM authority.simple_heading_set(NEW.marc);
114
115     -- Flatten and insert the afr data
116     PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_authority_full_rec' AND enabled;
117     IF NOT FOUND THEN
118         PERFORM authority.reingest_authority_full_rec(NEW.id);
119         PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_authority_rec_descriptor' AND enabled;
120         IF NOT FOUND THEN
121             PERFORM authority.reingest_authority_rec_descriptor(NEW.id);
122         END IF;
123     END IF;
124
125     RETURN NEW;
126 END;
127 $func$ LANGUAGE PLPGSQL;
128
129 COMMIT;