Merge branch 'master' of git.evergreen-ils.org:Evergreen into dbs/unnest_master
authorDan Scott <dan@coffeecode.net>
Sat, 11 Jun 2011 11:03:29 +0000 (07:03 -0400)
committerDan Scott <dan@coffeecode.net>
Sat, 11 Jun 2011 11:04:12 +0000 (07:04 -0400)
Also update the now-conflicting SQL upgrade scripts.

Conflicts:
Open-ILS/src/sql/Pg/002.schema.config.sql

1  2 
Open-ILS/src/sql/Pg/002.schema.config.sql
Open-ILS/src/sql/Pg/upgrade/0555.unnest_oils_xpath_table.sql
Open-ILS/src/sql/Pg/upgrade/0556.unnest_biblio_extract_metabib_field_entry.sql

@@@ -86,7 -86,7 +86,7 @@@ CREATE TRIGGER no_overlapping_dep
      BEFORE INSERT OR UPDATE ON config.db_patch_dependencies
      FOR EACH ROW EXECUTE PROCEDURE evergreen.array_overlap_check ('deprecates');
  
- INSERT INTO config.upgrade_log (version, applied_to) VALUES ('0554', :eg_version); -- dbs
 -INSERT INTO config.upgrade_log (version, applied_to) VALUES ('0550', :eg_version); -- phasefx/jamesrf
++INSERT INTO config.upgrade_log (version, applied_to) VALUES ('0556', :eg_version); -- dbs
  
  CREATE TABLE config.bib_source (
        id              SERIAL  PRIMARY KEY,
index 0000000,0000000..117dba2
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,71 @@@
++-- Evergreen DB patch 0549.unnest_oils_xpath_table.sql
++--
++-- Replace usage of custom explode_array() function with native unnest()
++--
++BEGIN;
++
++-- check whether patch can be applied
++SELECT evergreen.upgrade_deps_block_check('0549', :eg_version);
++
++CREATE OR REPLACE FUNCTION oils_xpath_table ( key TEXT, document_field TEXT, relation_name TEXT, xpaths TEXT, criteria TEXT ) RETURNS SETOF RECORD AS $func$
++DECLARE
++    xpath_list  TEXT[];
++    select_list TEXT[];
++    where_list  TEXT[];
++    q           TEXT;
++    out_record  RECORD;
++    empty_test  RECORD;
++BEGIN
++    xpath_list := STRING_TO_ARRAY( xpaths, '|' );
++
++    select_list := ARRAY_APPEND( select_list, key || '::INT AS key' );
++
++    FOR i IN 1 .. ARRAY_UPPER(xpath_list,1) LOOP
++        IF xpath_list[i] = 'null()' THEN
++            select_list := ARRAY_APPEND( select_list, 'NULL::TEXT AS c_' || i );
++        ELSE
++            select_list := ARRAY_APPEND(
++                select_list,
++                $sel$
++                unnest(
++                    COALESCE(
++                        NULLIF(
++                            oils_xpath(
++                                $sel$ ||
++                                    quote_literal(
++                                        CASE
++                                            WHEN xpath_list[i] ~ $re$/[^/[]*@[^/]+$$re$ OR xpath_list[i] ~ $re$text\(\)$$re$ THEN xpath_list[i]
++                                            ELSE xpath_list[i] || '//text()'
++                                        END
++                                    ) ||
++                                $sel$,
++                                $sel$ || document_field || $sel$
++                            ),
++                           '{}'::TEXT[]
++                        ),
++                        '{NULL}'::TEXT[]
++                    )
++                ) AS c_$sel$ || i
++            );
++            where_list := ARRAY_APPEND(
++                where_list,
++                'c_' || i || ' IS NOT NULL'
++            );
++        END IF;
++    END LOOP;
++
++    q := $q$
++SELECT * FROM (
++    SELECT $q$ || ARRAY_TO_STRING( select_list, ', ' ) || $q$ FROM $q$ || relation_name || $q$ WHERE ($q$ || criteria || $q$)
++)x WHERE $q$ || ARRAY_TO_STRING( where_list, ' OR ' );
++    -- RAISE NOTICE 'query: %', q;
++
++    FOR out_record IN EXECUTE q LOOP
++        RETURN NEXT out_record;
++    END LOOP;
++
++    RETURN;
++END;
++$func$ LANGUAGE PLPGSQL IMMUTABLE;
++
++COMMIT;
index 0000000,0000000..41d26e5
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,113 @@@
++-- Evergreen DB patch 0550.unnest_biblio_extract_metabib_field_entry.sql
++--
++-- Replace usage of custom explode_array() function with native unnest()
++--
++BEGIN;
++
++-- check whether patch can be applied
++SELECT evergreen.upgrade_deps_block_check('0550', :eg_version);
++
++CREATE OR REPLACE FUNCTION biblio.extract_metabib_field_entry ( rid BIGINT, default_joiner TEXT ) RETURNS SETOF metabib.field_entry_template AS $func$
++DECLARE
++    bib     biblio.record_entry%ROWTYPE;
++    idx     config.metabib_field%ROWTYPE;
++    xfrm        config.xml_transform%ROWTYPE;
++    prev_xfrm   TEXT;
++    transformed_xml TEXT;
++    xml_node    TEXT;
++    xml_node_list   TEXT[];
++    facet_text  TEXT;
++    raw_text    TEXT;
++    curr_text   TEXT;
++    joiner      TEXT := default_joiner; -- XXX will index defs supply a joiner?
++    output_row  metabib.field_entry_template%ROWTYPE;
++BEGIN
++
++    -- Get the record
++    SELECT INTO bib * FROM biblio.record_entry WHERE id = rid;
++
++    -- Loop over the indexing entries
++    FOR idx IN SELECT * FROM config.metabib_field ORDER BY format LOOP
++
++        SELECT INTO xfrm * from config.xml_transform WHERE name = idx.format;
++
++        -- See if we can skip the XSLT ... it's expensive
++        IF prev_xfrm IS NULL OR prev_xfrm <> xfrm.name THEN
++            -- Can't skip the transform
++            IF xfrm.xslt <> '---' THEN
++                transformed_xml := oils_xslt_process(bib.marc,xfrm.xslt);
++            ELSE
++                transformed_xml := bib.marc;
++            END IF;
++
++            prev_xfrm := xfrm.name;
++        END IF;
++
++        xml_node_list := oils_xpath( idx.xpath, transformed_xml, ARRAY[ARRAY[xfrm.prefix, xfrm.namespace_uri]] );
++
++        raw_text := NULL;
++        FOR xml_node IN SELECT x FROM unnest(xml_node_list) AS x LOOP
++            CONTINUE WHEN xml_node !~ E'^\\s*<';
++
++            curr_text := ARRAY_TO_STRING(
++                oils_xpath( '//text()',
++                    REGEXP_REPLACE( -- This escapes all &s not followed by "amp;".  Data ise returned from oils_xpath (above) in UTF-8, not entity encoded
++                        REGEXP_REPLACE( -- This escapes embeded <s
++                            xml_node,
++                            $re$(>[^<]+)(<)([^>]+<)$re$,
++                            E'\\1&lt;\\3',
++                            'g'
++                        ),
++                        '&(?!amp;)',
++                        '&amp;',
++                        'g'
++                    )
++                ),
++                ' '
++            );
++
++            CONTINUE WHEN curr_text IS NULL OR curr_text = '';
++
++            IF raw_text IS NOT NULL THEN
++                raw_text := raw_text || joiner;
++            END IF;
++
++            raw_text := COALESCE(raw_text,'') || curr_text;
++
++            -- insert raw node text for faceting
++            IF idx.facet_field THEN
++
++                IF idx.facet_xpath IS NOT NULL AND idx.facet_xpath <> '' THEN
++                    facet_text := oils_xpath_string( idx.facet_xpath, xml_node, joiner, ARRAY[ARRAY[xfrm.prefix, xfrm.namespace_uri]] );
++                ELSE
++                    facet_text := curr_text;
++                END IF;
++
++                output_row.field_class = idx.field_class;
++                output_row.field = -1 * idx.id;
++                output_row.source = rid;
++                output_row.value = BTRIM(REGEXP_REPLACE(facet_text, E'\\s+', ' ', 'g'));
++
++                RETURN NEXT output_row;
++            END IF;
++
++        END LOOP;
++
++        CONTINUE WHEN raw_text IS NULL OR raw_text = '';
++
++        -- insert combined node text for searching
++        IF idx.search_field THEN
++            output_row.field_class = idx.field_class;
++            output_row.field = idx.id;
++            output_row.source = rid;
++            output_row.value = BTRIM(REGEXP_REPLACE(raw_text, E'\\s+', ' ', 'g'));
++
++            RETURN NEXT output_row;
++        END IF;
++
++    END LOOP;
++
++END;
++$func$ LANGUAGE PLPGSQL;
++
++COMMIT;