]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/sql/Pg/upgrade/0498.lowercase_via_perl.sql
Resolve inconsistent results when invoking LOWER() in C vs. UTF8 locale databases
[working/Evergreen.git] / Open-ILS / src / sql / Pg / upgrade / 0498.lowercase_via_perl.sql
1 BEGIN;
2
3 INSERT INTO config.upgrade_log (version) VALUES ('0498'); -- dbs
4
5 -- Rather than polluting the public schema with general Evergreen
6 -- functions, carve out a dedicated schema
7 CREATE SCHEMA evergreen;
8
9 -- Replace all uses of PostgreSQL's built-in LOWER() function with
10 -- a more locale-savvy PLPERLU evergreen.lowercase() function
11 CREATE OR REPLACE FUNCTION evergreen.lowercase( TEXT ) RETURNS TEXT AS $$
12     return lc(shift);
13 $$ LANGUAGE PLPERLU STRICT IMMUTABLE;
14
15 -- update actor.usr_address indexes
16 DROP INDEX IF EXISTS actor.actor_usr_addr_street1_idx;
17 DROP INDEX IF EXISTS actor.actor_usr_addr_street2_idx;
18 DROP INDEX IF EXISTS actor.actor_usr_addr_city_idx;
19 DROP INDEX IF EXISTS actor.actor_usr_addr_state_idx; 
20 DROP INDEX IF EXISTS actor.actor_usr_addr_post_code_idx;
21
22 CREATE INDEX actor_usr_addr_street1_idx ON actor.usr_address (evergreen.lowercase(street1));
23 CREATE INDEX actor_usr_addr_street2_idx ON actor.usr_address (evergreen.lowercase(street2));
24 CREATE INDEX actor_usr_addr_city_idx ON actor.usr_address (evergreen.lowercase(city));
25 CREATE INDEX actor_usr_addr_state_idx ON actor.usr_address (evergreen.lowercase(state));
26 CREATE INDEX actor_usr_addr_post_code_idx ON actor.usr_address (evergreen.lowercase(post_code));
27
28 -- update actor.usr indexes
29 DROP INDEX IF EXISTS actor.actor_usr_first_given_name_idx;
30 DROP INDEX IF EXISTS actor.actor_usr_second_given_name_idx;
31 DROP INDEX IF EXISTS actor.actor_usr_family_name_idx;
32 DROP INDEX IF EXISTS actor.actor_usr_email_idx;
33 DROP INDEX IF EXISTS actor.actor_usr_day_phone_idx;
34 DROP INDEX IF EXISTS actor.actor_usr_evening_phone_idx;
35 DROP INDEX IF EXISTS actor.actor_usr_other_phone_idx;
36 DROP INDEX IF EXISTS actor.actor_usr_ident_value_idx;
37 DROP INDEX IF EXISTS actor.actor_usr_ident_value2_idx;
38
39 CREATE INDEX actor_usr_first_given_name_idx ON actor.usr (evergreen.lowercase(first_given_name));
40 CREATE INDEX actor_usr_second_given_name_idx ON actor.usr (evergreen.lowercase(second_given_name));
41 CREATE INDEX actor_usr_family_name_idx ON actor.usr (evergreen.lowercase(family_name));
42 CREATE INDEX actor_usr_email_idx ON actor.usr (evergreen.lowercase(email));
43 CREATE INDEX actor_usr_day_phone_idx ON actor.usr (evergreen.lowercase(day_phone));
44 CREATE INDEX actor_usr_evening_phone_idx ON actor.usr (evergreen.lowercase(evening_phone));
45 CREATE INDEX actor_usr_other_phone_idx ON actor.usr (evergreen.lowercase(other_phone));
46 CREATE INDEX actor_usr_ident_value_idx ON actor.usr (evergreen.lowercase(ident_value));
47 CREATE INDEX actor_usr_ident_value2_idx ON actor.usr (evergreen.lowercase(ident_value2));
48
49 CREATE OR REPLACE FUNCTION vandelay.match_bib_record ( ) RETURNS TRIGGER AS $func$
50 DECLARE
51     attr        RECORD;
52     attr_def    RECORD;
53     eg_rec      RECORD;
54     id_value    TEXT;
55     exact_id    BIGINT;
56 BEGIN
57
58     DELETE FROM vandelay.bib_match WHERE queued_record = NEW.id;
59
60     SELECT * INTO attr_def FROM vandelay.bib_attr_definition WHERE xpath = '//*[@tag="901"]/*[@code="c"]' ORDER BY id LIMIT 1;
61
62     IF attr_def IS NOT NULL AND attr_def.id IS NOT NULL THEN
63         id_value := extract_marc_field('vandelay.queued_bib_record', NEW.id, attr_def.xpath, attr_def.remove);
64     
65         IF id_value IS NOT NULL AND id_value <> '' AND id_value ~ $r$^\d+$$r$ THEN
66             SELECT id INTO exact_id FROM biblio.record_entry WHERE id = id_value::BIGINT AND NOT deleted;
67             SELECT * INTO attr FROM vandelay.queued_bib_record_attr WHERE record = NEW.id and field = attr_def.id LIMIT 1;
68             IF exact_id IS NOT NULL THEN
69                 INSERT INTO vandelay.bib_match (field_type, matched_attr, queued_record, eg_record) VALUES ('id', attr.id, NEW.id, exact_id);
70             END IF;
71         END IF;
72     END IF;
73
74     IF exact_id IS NULL THEN
75         FOR attr IN SELECT a.* FROM vandelay.queued_bib_record_attr a JOIN vandelay.bib_attr_definition d ON (d.id = a.field) WHERE record = NEW.id AND d.ident IS TRUE LOOP
76     
77                 -- All numbers? check for an id match
78                 IF (attr.attr_value ~ $r$^\d+$$r$) THEN
79                 FOR eg_rec IN SELECT * FROM biblio.record_entry WHERE id = attr.attr_value::BIGINT AND deleted IS FALSE LOOP
80                         INSERT INTO vandelay.bib_match (field_type, matched_attr, queued_record, eg_record) VALUES ('id', attr.id, NEW.id, eg_rec.id);
81                         END LOOP;
82                 END IF;
83     
84                 -- Looks like an ISBN? check for an isbn match
85                 IF (attr.attr_value ~* $r$^[0-9x]+$$r$ AND character_length(attr.attr_value) IN (10,13)) THEN
86                 FOR eg_rec IN EXECUTE $$SELECT * FROM metabib.full_rec fr WHERE fr.value LIKE evergreen.lowercase('$$ || attr.attr_value || $$%') AND fr.tag = '020' AND fr.subfield = 'a'$$ LOOP
87                                 PERFORM id FROM biblio.record_entry WHERE id = eg_rec.record AND deleted IS FALSE;
88                                 IF FOUND THEN
89                                 INSERT INTO vandelay.bib_match (field_type, matched_attr, queued_record, eg_record) VALUES ('isbn', attr.id, NEW.id, eg_rec.record);
90                                 END IF;
91                         END LOOP;
92     
93                         -- subcheck for isbn-as-tcn
94                     FOR eg_rec IN SELECT * FROM biblio.record_entry WHERE tcn_value = 'i' || attr.attr_value AND deleted IS FALSE LOOP
95                             INSERT INTO vandelay.bib_match (field_type, matched_attr, queued_record, eg_record) VALUES ('tcn_value', attr.id, NEW.id, eg_rec.id);
96                 END LOOP;
97                 END IF;
98     
99                 -- check for an OCLC tcn_value match
100                 IF (attr.attr_value ~ $r$^o\d+$$r$) THEN
101                     FOR eg_rec IN SELECT * FROM biblio.record_entry WHERE tcn_value = regexp_replace(attr.attr_value,'^o','ocm') AND deleted IS FALSE LOOP
102                             INSERT INTO vandelay.bib_match (field_type, matched_attr, queued_record, eg_record) VALUES ('tcn_value', attr.id, NEW.id, eg_rec.id);
103                 END LOOP;
104                 END IF;
105     
106                 -- check for a direct tcn_value match
107             FOR eg_rec IN SELECT * FROM biblio.record_entry WHERE tcn_value = attr.attr_value AND deleted IS FALSE LOOP
108                 INSERT INTO vandelay.bib_match (field_type, matched_attr, queued_record, eg_record) VALUES ('tcn_value', attr.id, NEW.id, eg_rec.id);
109             END LOOP;
110     
111                 -- check for a direct item barcode match
112             FOR eg_rec IN
113                     SELECT  DISTINCT b.*
114                       FROM  biblio.record_entry b
115                             JOIN asset.call_number cn ON (cn.record = b.id)
116                             JOIN asset.copy cp ON (cp.call_number = cn.id)
117                       WHERE cp.barcode = attr.attr_value AND cp.deleted IS FALSE
118             LOOP
119                 INSERT INTO vandelay.bib_match (field_type, matched_attr, queued_record, eg_record) VALUES ('id', attr.id, NEW.id, eg_rec.id);
120             END LOOP;
121     
122         END LOOP;
123     END IF;
124
125     RETURN NULL;
126 END;
127 $func$ LANGUAGE PLPGSQL;
128
129
130 COMMIT;