]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/sql/Pg/upgrade/0035.schema.extract_metabib_field_entry.sql
Stamped upgrade script for "lp 823496: do not fail to index personal names that have...
[Evergreen.git] / Open-ILS / src / sql / Pg / upgrade / 0035.schema.extract_metabib_field_entry.sql
1 BEGIN;
2
3 INSERT INTO config.upgrade_log (version) VALUES ('0035'); -- miker
4
5 CREATE FUNCTION version_specific_xpath () RETURNS TEXT AS $wrapper_function$
6 DECLARE
7         out_text TEXT;
8 BEGIN
9
10         IF REGEXP_REPLACE(VERSION(),E'^.+?(\\d+\\.\\d+).*?$',E'\\1')::FLOAT < 8.3 THEN
11                 out_text := 'Creating XPath functions that work like the native XPATH function in 8.3+';
12
13                 EXECUTE $create_82_funcs$
14
15 CREATE OR REPLACE FUNCTION oils_xpath ( xpath TEXT, xml TEXT, ns ANYARRAY ) RETURNS TEXT[] AS $func$
16 DECLARE
17         node_text       TEXT;
18         ns_regexp       TEXT;
19         munged_xpath    TEXT;
20 BEGIN
21         
22         munged_xpath := xpath;
23
24         IF ns IS NOT NULL THEN
25                 FOR namespace IN 1 .. array_upper(ns, 1) LOOP
26                         munged_xpath := REGEXP_REPLACE(
27                                 munged_xpath,
28                                 E'(' || ns[namespace][1] || E'):(\\w+)',
29                                 E'*[local-name() = "\\2" and namespace-uri() = "' || ns[namespace][2] || E'"]',
30                                 'g'
31                         );
32                 END LOOP;
33
34                 munged_xpath := REGEXP_REPLACE( munged_xpath, E'\\]\\[(\\D)',E' and \\1', 'g');
35         END IF;
36
37         node_text := xpath_nodeset(xml, munged_xpath, 'XXX_OILS_NODESET');
38         node_text := REGEXP_REPLACE(node_text,'^<XXX_OILS_NODESET>', '');
39         node_text := REGEXP_REPLACE(node_text,'</XXX_OILS_NODESET>$', '');
40
41         RETURN  STRING_TO_ARRAY(node_text, '</XXX_OILS_NODESET><XXX_OILS_NODESET>');
42 END;
43 $func$ LANGUAGE PLPGSQL; 
44
45 CREATE OR REPLACE FUNCTION oils_xpath ( TEXT, TEXT ) RETURNS TEXT[] AS 'SELECT oils_xpath( $1, $2, NULL::TEXT[] );' LANGUAGE SQL; 
46
47                 $create_82_funcs$;
48         ELSE
49                 out_text := 'Creating XPath wrapper functions around the native XPATH function in 8.3+';
50
51                 EXECUTE $create_83_funcs$
52 -- 8.3 or after
53 CREATE OR REPLACE FUNCTION oils_xpath ( TEXT, TEXT, ANYARRAY ) RETURNS TEXT[] AS 'SELECT XPATH( $1, $2::XML, $3 )::TEXT[];' LANGUAGE SQL; 
54 CREATE OR REPLACE FUNCTION oils_xpath ( TEXT, TEXT ) RETURNS TEXT[] AS 'SELECT XPATH( $1, $2::XML )::TEXT[];' LANGUAGE SQL; 
55
56                 $create_83_funcs$;
57
58         END IF;
59
60         RETURN out_text;
61 END;
62 $wrapper_function$ LANGUAGE PLPGSQL;
63
64 SELECT version_specific_xpath();
65 DROP FUNCTION version_specific_xpath();
66
67 CREATE TYPE metabib.field_entry_template AS (
68         field_class     TEXT,
69         field           INT,
70         source          BIGINT,
71         value           TEXT
72 );
73
74 CREATE OR REPLACE FUNCTION biblio.extract_metabib_field_entry ( rid BIGINT, default_joiner TEXT ) RETURNS SETOF metabib.field_entry_template AS $func$
75 DECLARE
76         bib             biblio.record_entry%ROWTYPE;
77         idx             config.metabib_field%ROWTYPE;
78         xfrm            config.xml_transform%ROWTYPE;
79         prev_xfrm       TEXT;
80         transformed_xml TEXT;
81         xml_node        TEXT;
82         xml_node_list   TEXT[];
83         raw_text        TEXT;
84         joiner          TEXT := default_joiner; -- XXX will index defs supply a joiner?
85         output_row      metabib.field_entry_template%ROWTYPE;
86 BEGIN
87
88         -- Get the record
89         SELECT INTO bib * FROM biblio.record_entry WHERE id = rid;
90
91         -- Loop over the indexing entries
92         FOR idx IN SELECT * FROM config.metabib_field ORDER BY format LOOP
93
94                 SELECT INTO xfrm * from config.xml_transform WHERE name = idx.format;
95
96                 -- See if we can skip the XSLT ... it's expensive
97                 IF prev_xfrm IS NULL OR prev_xfrm <> xfrm.name THEN
98                         -- Can't skip the transform
99                         IF xfrm.xslt <> '---' THEN
100                                 transformed_xml := xslt_process(bib.marc,xfrm.xslt);
101                         ELSE
102                                 transformed_xml := bib.marc;
103                         END IF;
104
105                         prev_xfrm := xfrm.name;
106                 END IF;
107
108                 xml_node_list := oils_xpath( idx.xpath, transformed_xml, ARRAY[ARRAY[xfrm.prefix, xfrm.namespace_uri]] );
109
110                 raw_text := NULL;
111                 FOR xml_node IN SELECT x FROM explode_array(xml_node_list) AS x LOOP
112                         IF raw_text IS NOT NULL THEN
113                                 raw_text := raw_text || joiner;
114                         END IF;
115                         raw_text := COALESCE(raw_text,'') || ARRAY_TO_STRING(oils_xpath( '//text()', xml_node ), ' ');
116                 END LOOP;
117
118                 CONTINUE WHEN raw_text IS NULL;
119
120                 output_row.field_class = idx.field_class;
121                 output_row.field = idx.id;
122                 output_row.source = rid;
123                 output_row.value = BTRIM(REGEXP_REPLACE(raw_text, E'\\s+', ' ', 'gs'));
124
125                 RETURN NEXT output_row;
126
127         END LOOP;
128
129 END;
130 $func$ LANGUAGE PLPGSQL;
131
132 -- default to a space joiner
133 CREATE OR REPLACE FUNCTION biblio.extract_metabib_field_entry ( BIGINT ) RETURNS SETOF metabib.field_entry_template AS $func$
134         SELECT * FROM biblio.extract_metabib_field_entry($1, ' ');
135 $func$ LANGUAGE SQL;
136
137 COMMIT;
138