]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/sql/Pg/upgrade/0216.schema.metabib.indexing-new-facets.sql
Stamping upgrade scripts for LP#818740
[working/Evergreen.git] / Open-ILS / src / sql / Pg / upgrade / 0216.schema.metabib.indexing-new-facets.sql
1 BEGIN;
2
3 INSERT INTO config.upgrade_log (version) VALUES ('0216');
4
5 DROP INDEX metabib.metabib_title_field_entry_value_idx;
6 DROP INDEX metabib.metabib_author_field_entry_value_idx;
7 DROP INDEX metabib.metabib_subject_field_entry_value_idx;
8 DROP INDEX metabib.metabib_keyword_field_entry_value_idx;
9 DROP INDEX metabib.metabib_series_field_entry_value_idx;
10
11 CREATE INDEX metabib_title_field_entry_value_idx ON metabib.title_field_entry (SUBSTRING(value,1,1024)) WHERE index_vector = ''::TSVECTOR;
12 CREATE INDEX metabib_author_field_entry_value_idx ON metabib.author_field_entry (SUBSTRING(value,1,1024)) WHERE index_vector = ''::TSVECTOR;
13 CREATE INDEX metabib_subject_field_entry_value_idx ON metabib.subject_field_entry (SUBSTRING(value,1,1024)) WHERE index_vector = ''::TSVECTOR;
14 CREATE INDEX metabib_keyword_field_entry_value_idx ON metabib.keyword_field_entry (SUBSTRING(value,1,1024)) WHERE index_vector = ''::TSVECTOR;
15 CREATE INDEX metabib_series_field_entry_value_idx ON metabib.series_field_entry (SUBSTRING(value,1,1024)) WHERE index_vector = ''::TSVECTOR;
16
17 INSERT INTO config.internal_flag (name) VALUES ('ingest.reingest.skip_located_uri');
18
19 CREATE OR REPLACE FUNCTION oils_tsearch2 () RETURNS TRIGGER AS $$
20 DECLARE 
21         normalizer      RECORD;
22         value           TEXT := '';
23 BEGIN
24         IF NEW.index_vector = ''::tsvector THEN
25             RETURN NEW;
26         END IF;
27
28         value := NEW.value;
29
30         IF TG_TABLE_NAME::TEXT ~ 'field_entry$' THEN
31                 FOR normalizer IN
32                         SELECT  n.func AS func,
33                                 n.param_count AS param_count,
34                                 m.params AS params
35                           FROM  config.index_normalizer n
36                                 JOIN config.metabib_field_index_norm_map m ON (m.norm = n.id)
37                           WHERE field = NEW.field
38                           ORDER BY m.pos
39                 LOOP
40                         EXECUTE 'SELECT ' || normalizer.func || '(' ||
41                                         quote_literal( value ) ||
42                                         CASE
43                                                 WHEN normalizer.param_count > 0 THEN ',' || BTRIM(normalizer.params,'[]')
44                                                 ELSE ''
45                                         END ||
46                                 ')' INTO value;
47
48                 END LOOP;
49         END IF;
50
51         IF REGEXP_REPLACE(VERSION(),E'^.+?(\\d+\\.\\d+).*?$',E'\\1')::FLOAT > 8.2 THEN
52                 NEW.index_vector = to_tsvector((TG_ARGV[0])::regconfig, value);
53         ELSE
54                 NEW.index_vector = to_tsvector(TG_ARGV[0], value);
55         END IF;
56
57         RETURN NEW;
58 END;
59 $$ LANGUAGE PLPGSQL;
60
61 CREATE OR REPLACE FUNCTION biblio.indexing_ingest_or_delete () RETURNS TRIGGER AS $func$
62 DECLARE
63     ind_data        metabib.field_entry_template%ROWTYPE;
64     old_mr          INT;
65     tmp_mr          metabib.metarecord%ROWTYPE;
66     source_count    INT;
67     deleted_mrs     INT[];
68     uris            TEXT[];
69     uri_xml         TEXT;
70     uri_label       TEXT;
71     uri_href        TEXT;
72     uri_use         TEXT;
73     uri_owner       TEXT;
74     uri_owner_id    INT;
75     uri_id          INT;
76     uri_cn_id       INT;
77     uri_map_id      INT;
78
79     ind_vector      TSVECTOR;
80 BEGIN
81
82     IF NEW.deleted IS TRUE THEN
83         DELETE FROM metabib.metarecord_source_map WHERE source = NEW.id; -- Rid ourselves of the search-estimate-killing linkage
84         RETURN NEW; -- and we're done
85     END IF;
86
87     IF TG_OP = 'UPDATE' THEN -- re-ingest?
88         PERFORM * FROM config.internal_flag WHERE name = 'ingest.reingest.force_on_same_marc' AND enabled;
89
90         IF NOT FOUND AND OLD.marc = NEW.marc THEN -- don't do anything if the MARC didn't change
91             RETURN NEW;
92         END IF;
93
94         DELETE FROM metabib.metarecord_source_map WHERE source = NEW.id; -- Rid ourselves of the search-estimate-killing linkage
95
96     END IF;
97
98     IF TG_OP = 'UPDATE' THEN -- Clean out the cruft
99         DELETE FROM metabib.title_field_entry WHERE source = NEW.id;
100         DELETE FROM metabib.author_field_entry WHERE source = NEW.id;
101         DELETE FROM metabib.subject_field_entry WHERE source = NEW.id;
102         DELETE FROM metabib.keyword_field_entry WHERE source = NEW.id;
103         DELETE FROM metabib.series_field_entry WHERE source = NEW.id;
104         DELETE FROM metabib.full_rec WHERE record = NEW.id;
105         DELETE FROM metabib.rec_descriptor WHERE record = NEW.id;
106
107     END IF;
108
109     -- Shove the flattened MARC in
110     INSERT INTO metabib.full_rec (record, tag, ind1, ind2, subfield, value)
111         SELECT record, tag, ind1, ind2, subfield, value FROM biblio.flatten_marc( NEW.id );
112
113     -- And now the indexing data
114     FOR ind_data IN SELECT * FROM biblio.extract_metabib_field_entry( NEW.id ) LOOP
115         IF ind_data.field < 0 THEN
116             ind_vector = '';
117             ind_data.field = -1 * ind_data.field;
118         ELSE
119             ind_vector = NULL;
120         END IF;
121
122         IF ind_data.field_class = 'title' THEN
123             INSERT INTO metabib.title_field_entry (field, source, value, index_vector)
124                 VALUES (ind_data.field, ind_data.source, ind_data.value, ind_vector);
125         ELSIF ind_data.field_class = 'author' THEN
126             INSERT INTO metabib.author_field_entry (field, source, value, index_vector)
127                 VALUES (ind_data.field, ind_data.source, ind_data.value, ind_vector);
128         ELSIF ind_data.field_class = 'subject' THEN
129             INSERT INTO metabib.subject_field_entry (field, source, value, index_vector)
130                 VALUES (ind_data.field, ind_data.source, ind_data.value, ind_vector);
131         ELSIF ind_data.field_class = 'keyword' THEN
132             INSERT INTO metabib.keyword_field_entry (field, source, value, index_vector)
133                 VALUES (ind_data.field, ind_data.source, ind_data.value, ind_vector);
134         ELSIF ind_data.field_class = 'series' THEN
135             INSERT INTO metabib.series_field_entry (field, source, value, index_vector)
136                 VALUES (ind_data.field, ind_data.source, ind_data.value, ind_vector);
137         END IF;
138     END LOOP;
139
140     -- Then, the rec_descriptor
141     INSERT INTO metabib.rec_descriptor (record, item_type, item_form, bib_level, control_type, enc_level, audience, lit_form, type_mat, cat_form, pub_status, item_lang, vr_format, date1, date2)
142         SELECT  NEW.id,
143                 biblio.marc21_extract_fixed_field( NEW.id, 'Type' ),
144                 biblio.marc21_extract_fixed_field( NEW.id, 'Form' ),
145                 biblio.marc21_extract_fixed_field( NEW.id, 'BLvl' ),
146                 biblio.marc21_extract_fixed_field( NEW.id, 'Ctrl' ),
147                 biblio.marc21_extract_fixed_field( NEW.id, 'ELvl' ),
148                 biblio.marc21_extract_fixed_field( NEW.id, 'Audn' ),
149                 biblio.marc21_extract_fixed_field( NEW.id, 'LitF' ),
150                 biblio.marc21_extract_fixed_field( NEW.id, 'TMat' ),
151                 biblio.marc21_extract_fixed_field( NEW.id, 'Desc' ),
152                 biblio.marc21_extract_fixed_field( NEW.id, 'DtSt' ),
153                 biblio.marc21_extract_fixed_field( NEW.id, 'Lang' ),
154                 (   SELECT  v.value
155                       FROM  biblio.marc21_physical_characteristics( NEW.id) p
156                             JOIN config.marc21_physical_characteristic_subfield_map s ON (s.id = p.subfield)
157                             JOIN config.marc21_physical_characteristic_value_map v ON (v.id = p.value)
158                       WHERE p.ptype = 'v' AND s.subfield = 'e'    ),
159                 biblio.marc21_extract_fixed_field( NEW.id, 'Date1'),
160                 biblio.marc21_extract_fixed_field( NEW.id, 'Date2');
161
162     -- On to URIs ...
163     PERFORM * FROM config.internal_flag WHERE name = 'ingest.reingest.skip_located_uri' AND enabled;
164
165     IF NOT FOUND OR TG_OP = 'INSERT' THEN
166         uris := oils_xpath('//*[@tag="856" and (@ind1="4" or @ind1="1") and (@ind2="0" or @ind2="1")]',NEW.marc);
167         IF ARRAY_UPPER(uris,1) > 0 THEN
168             FOR i IN 1 .. ARRAY_UPPER(uris, 1) LOOP
169                 -- First we pull infot out of the 856
170                 uri_xml     := uris[i];
171     
172                 uri_href    := (oils_xpath('//*[@code="u"]/text()',uri_xml))[1];
173                 CONTINUE WHEN uri_href IS NULL;
174     
175                 uri_label   := (oils_xpath('//*[@code="y"]/text()|//*[@code="3"]/text()|//*[@code="u"]/text()',uri_xml))[1];
176                 CONTINUE WHEN uri_label IS NULL;
177     
178                 uri_owner   := (oils_xpath('//*[@code="9"]/text()|//*[@code="w"]/text()|//*[@code="n"]/text()',uri_xml))[1];
179                 CONTINUE WHEN uri_owner IS NULL;
180         
181                 uri_use     := (oils_xpath('//*[@code="z"]/text()|//*[@code="2"]/text()|//*[@code="n"]/text()',uri_xml))[1];
182     
183                 uri_owner := REGEXP_REPLACE(uri_owner, $re$^.*?\((\w+)\).*$$re$, E'\\1');
184         
185                 SELECT id INTO uri_owner_id FROM actor.org_unit WHERE shortname = uri_owner;
186                 CONTINUE WHEN NOT FOUND;
187         
188                 -- now we look for a matching uri
189                 SELECT id INTO uri_id FROM asset.uri WHERE label = uri_label AND href = uri_href AND use_restriction = uri_use AND active;
190                 IF NOT FOUND THEN -- create one
191                     INSERT INTO asset.uri (label, href, use_restriction) VALUES (uri_label, uri_href, uri_use);
192                     SELECT id INTO uri_id FROM asset.uri WHERE label = uri_label AND href = uri_href AND use_restriction = uri_use AND active;
193                 END IF;
194         
195                 -- we need a call number to link through
196                 SELECT id INTO uri_cn_id FROM asset.call_number WHERE owning_lib = uri_owner_id AND record = NEW.id AND label = '##URI##' AND NOT deleted;
197                 IF NOT FOUND THEN
198                     INSERT INTO asset.call_number (owning_lib, record, create_date, edit_date, creator, editor, label)
199                         VALUES (uri_owner_id, NEW.id, 'now', 'now', NEW.editor, NEW.editor, '##URI##');
200                     SELECT id INTO uri_cn_id FROM asset.call_number WHERE owning_lib = uri_owner_id AND record = NEW.id AND label = '##URI##' AND NOT deleted;
201                 END IF;
202         
203                 -- now, link them if they're not already
204                 SELECT id INTO uri_map_id FROM asset.uri_call_number_map WHERE call_number = uri_cn_id AND uri = uri_id;
205                 IF NOT FOUND THEN
206                     INSERT INTO asset.uri_call_number_map (call_number, uri) VALUES (uri_cn_id, uri_id);
207                 END IF;
208         
209             END LOOP;
210         END IF;
211     END IF;
212
213     -- And, finally, metarecord mapping!
214
215     PERFORM * FROM config.internal_flag WHERE name = 'ingest.metarecord_mapping.skip_on_insert' AND enabled;
216
217     IF NOT FOUND OR TG_OP = 'UPDATE' THEN
218         FOR tmp_mr IN SELECT  m.* FROM  metabib.metarecord m JOIN metabib.metarecord_source_map s ON (s.metarecord = m.id) WHERE s.source = NEW.id LOOP
219     
220             IF old_mr IS NULL AND NEW.fingerprint = tmp_mr.fingerprint THEN -- Find the first fingerprint-matching
221                 old_mr := tmp_mr.id;
222             ELSE
223                 SELECT COUNT(*) INTO source_count FROM metabib.metarecord_source_map WHERE metarecord = tmp_mr.id;
224                 IF source_count = 0 THEN -- No other records
225                     deleted_mrs := ARRAY_APPEND(deleted_mrs, tmp_mr.id);
226                     DELETE FROM metabib.metarecord WHERE id = tmp_mr.id;
227                 END IF;
228             END IF;
229     
230         END LOOP;
231     
232         IF old_mr IS NULL THEN -- we found no suitable, preexisting MR based on old source maps
233             SELECT id INTO old_mr FROM metabib.metarecord WHERE fingerprint = NEW.fingerprint; -- is there one for our current fingerprint?
234             IF old_mr IS NULL THEN -- nope, create one and grab its id
235                 INSERT INTO metabib.metarecord ( fingerprint, master_record ) VALUES ( NEW.fingerprint, NEW.id );
236                 SELECT id INTO old_mr FROM metabib.metarecord WHERE fingerprint = NEW.fingerprint;
237             ELSE -- indeed there is. update it with a null cache and recalcualated master record
238                 UPDATE  metabib.metarecord
239                   SET   mods = NULL,
240                         master_record = ( SELECT id FROM biblio.record_entry WHERE fingerprint = NEW.fingerprint ORDER BY quality DESC LIMIT 1)
241                   WHERE id = old_mr;
242             END IF;
243         ELSE -- there was one we already attached to, update its mods cache and master_record
244             UPDATE  metabib.metarecord
245               SET   mods = NULL,
246                     master_record = ( SELECT id FROM biblio.record_entry WHERE fingerprint = NEW.fingerprint ORDER BY quality DESC LIMIT 1)
247               WHERE id = old_mr;
248         END IF;
249     
250         INSERT INTO metabib.metarecord_source_map (metarecord, source) VALUES (old_mr, NEW.id); -- new source mapping
251     
252         UPDATE action.hold_request SET target = old_mr WHERE target IN ( SELECT explode_array(deleted_mrs) ) AND hold_type = 'M'; -- if we had to delete any MRs above, make sure their holds are moved
253     END IF;
254  
255     RETURN NEW;
256
257 END;
258 $func$ LANGUAGE PLPGSQL;
259
260 COMMIT;