From: Mike Rylander Date: Wed, 21 Sep 2011 20:38:08 +0000 (-0400) Subject: Record simple authority headings for search and sort, and respect Non-filing Indicato... X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=bfd05a2df0f77b69ab34a80cca17e5dcc552ee6f;p=evergreen%2Fequinox.git Record simple authority headings for search and sort, and respect Non-filing Indicators, if configured Signed-off-by: Mike Rylander --- diff --git a/Open-ILS/src/sql/Pg/011.schema.authority.sql b/Open-ILS/src/sql/Pg/011.schema.authority.sql index 329f3567d0..8dafc254ea 100644 --- a/Open-ILS/src/sql/Pg/011.schema.authority.sql +++ b/Open-ILS/src/sql/Pg/011.schema.authority.sql @@ -33,6 +33,7 @@ CREATE TABLE authority.control_set_authority_field ( main_entry INT REFERENCES authority.control_set_authority_field (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, control_set INT NOT NULL REFERENCES authority.control_set (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, tag CHAR(3) NOT NULL, + nfi CHAR(1), -- non-filing indicator sf_list TEXT NOT NULL, name TEXT NOT NULL, -- i18n description TEXT -- i18n @@ -149,27 +150,58 @@ CREATE OR REPLACE FUNCTION authority.normalize_heading( marcxml TEXT, no_thesaur DECLARE acsaf authority.control_set_authority_field%ROWTYPE; tag_used TEXT; + nfi_used TEXT; sf TEXT; thes_code TEXT; cset INT; heading_text TEXT; tmp_text TEXT; + first_sf BOOL; + auth_id INT DEFAULT oils_xpath_string('//*[@tag="901"]/*[local-name()="subfield" and @code="c"]', marcxml)::INT; BEGIN - thes_code := vandelay.marc21_extract_fixed_field(marcxml,'Subj'); - IF thes_code IS NULL THEN - thes_code := '|'; + SELECT control_set INTO cset FROM authority.record_entry WHERE id = auth_id; + + IF cset IS NULL THEN + SELECT control_set INTO cset + FROM authority.control_set_authority_field + WHERE tag IN ( SELECT UNNEST(XPATH('//*[starts-with(@tag,"1")]/@tag',marcxml::XML)::TEXT[])) + LIMIT 1; END IF; - SELECT control_set INTO cset FROM authority.thesaurus WHERE code = thes_code; - IF NOT FOUND THEN - cset = 1; + IF thes_code = 'z' THEN + thes_code := COALESCE( oils_xpath_string('//*[@tag="040"]/*[@code="f"][1]', marcxml), '' ); END IF; heading_text := ''; FOR acsaf IN SELECT * FROM authority.control_set_authority_field WHERE control_set = cset AND main_entry IS NULL LOOP tag_used := acsaf.tag; + nfi_used := acsaf.nfi; + first_sf := TRUE; FOR sf IN SELECT * FROM regexp_split_to_table(acsaf.sf_list,'') LOOP tmp_text := oils_xpath_string('//*[@tag="'||tag_used||'"]/*[@code="'||sf||'"]', marcxml); + + IF first_sf AND tmp_text IS NOT NULL AND nfi_used IS NOT NULL THEN + + tmp_text := SUBSTRING( + tmp_text FROM + COALESCE( + NULLIF( + REGEXP_REPLACE( + oils_xpath_string('//*[@tag="'||tag_used||'"]/@ind'||nfi_used, marcxml), + $$\D+$$, + '', + 'g' + ), + '' + )::INT, + 0 + ) + 1 + ); + + END IF; + + first_sf := FALSE; + IF tmp_text IS NOT NULL AND tmp_text <> '' THEN heading_text := heading_text || E'\u2021' || sf || ' ' || tmp_text; END IF; @@ -177,15 +209,11 @@ BEGIN EXIT WHEN heading_text <> ''; END LOOP; - IF thes_code = 'z' THEN - thes_code := oils_xpath_string('//*[@tag="040"]/*[@code="f"][1]', marcxml); - END IF; - IF heading_text <> '' THEN IF no_thesaurus IS TRUE THEN heading_text := tag_used || ' ' || public.naco_normalize(heading_text); ELSE - heading_text := tag_used || '_' || thes_code || ' ' || public.naco_normalize(heading_text); + heading_text := tag_used || '_' || COALESCE(nfi_used,'-') || '_' || thes_code || ' ' || public.naco_normalize(heading_text); END IF; ELSE heading_text := 'NOHEADING_' || thes_code || ' ' || MD5(marcxml); @@ -195,6 +223,88 @@ BEGIN END; $func$ LANGUAGE PLPGSQL IMMUTABLE; +CREATE TABLE authority.simple_heading ( + id BIGSERIAL PRIMARY KEY, + record BIGINT NOT NULL REFERENCES authority.record_entry (id), + atag INT NOT NULL REFERENCES authority.control_set_authority_field (id), + value TEXT NOT NULL, + index_vector tsvector NOT NULL +); +CREATE TRIGGER authority_simple_heading_fti_trigger + BEFORE UPDATE OR INSERT ON authority.simple_heading + FOR EACH ROW EXECUTE PROCEDURE tsearch2(index_vector, value); + +CREATE INDEX authority_simple_heading_index_vector_idx ON authority.full_rec USING GIST (index_vector); +CREATE INDEX authority_simple_heading_value_idx ON authority.simple_heading (value); + +CREATE OR REPLACE FUNCTION authority.simple_heading_set( marcxml TEXT ) RETURNS SETOF authority.simple_heading AS $func$ +DECLARE + res authority.simple_heading%ROWTYPE; + acsaf authority.control_set_authority_field%ROWTYPE; + tag_used TEXT; + nfi_used TEXT; + sf TEXT; + cset INT; + heading_text TEXT; + tmp_text TEXT; + tmp_xml TEXT; + first_sf BOOL; + auth_id INT DEFAULT oils_xpath_string('//*[@tag="901"]/*[local-name()="subfield" and @code="c"]', marcxml)::INT; +BEGIN + + res.record := auth_id; + + SELECT control_set INTO cset + FROM authority.control_set_authority_field + WHERE tag IN ( SELECT UNNEST(XPATH('//*[starts-with(@tag,"1")]/@tag',marcxml::XML)::TEXT[]) ) + LIMIT 1; + + FOR acsaf IN SELECT * FROM authority.control_set_authority_field WHERE control_set = cset LOOP + + res.atag := acsaf.id; + tag_used := acsaf.tag; + nfi_used := acsaf.nfi; + + FOR tmp_xml IN SELECT UNNEST(XPATH('//*[@tag="'||tag_used||'"]', marcxml::XML)) LOOP + heading_text := ''; + + FOR sf IN SELECT * FROM regexp_split_to_table(acsaf.sf_list,'') LOOP + heading_text := heading_text || COALESCE( ' ' || oils_xpath_string('//*[@code="'||sf||'"]',tmp_xml::TEXT), ''); + END LOOP; + + IF nfi_used IS NOT NULL THEN + + heading_text := SUBSTRING( + heading_text FROM + COALESCE( + NULLIF( + REGEXP_REPLACE( + oils_xpath_string('//*[@tag="'||tag_used||'"]/@ind'||nfi_used, marcxml), + $$\D+$$, + '', + 'g' + ), + '' + )::INT, + 0 + ) + 1 + ); + + END IF; + + IF heading_text IS NOT NULL AND heading_text <> '' THEN + res.value := public.naco_normalize( BTRIM(heading_text) ); + RETURN NEXT res; + END IF; + + END LOOP; + + END LOOP; + + RETURN; +END; +$func$ LANGUAGE PLPGSQL IMMUTABLE; + CREATE OR REPLACE FUNCTION authority.simple_normalize_heading( marcxml TEXT ) RETURNS TEXT AS $func$ SELECT authority.normalize_heading($1, TRUE); $func$ LANGUAGE SQL IMMUTABLE; @@ -210,6 +320,7 @@ index to defend against duplicated authority records from the same thesaurus. $$; + -- Adding indexes using oils_xpath_string() for the main entry tags described in -- authority.control_set_authority_field would speed this up, if we ever want to use it, though -- the existing index on authority.normalize_heading() helps already with a record in hand diff --git a/Open-ILS/src/sql/Pg/999.functions.global.sql b/Open-ILS/src/sql/Pg/999.functions.global.sql index 25dfb6aeac..3fedcf80bb 100644 --- a/Open-ILS/src/sql/Pg/999.functions.global.sql +++ b/Open-ILS/src/sql/Pg/999.functions.global.sql @@ -1421,6 +1421,7 @@ BEGIN IF NEW.deleted IS TRUE THEN -- If this authority is deleted DELETE FROM authority.bib_linking WHERE authority = NEW.id; -- Avoid updating fields in bibs that are no longer visible DELETE FROM authority.full_rec WHERE record = NEW.id; -- Avoid validating fields against deleted authority records + DELETE FROM authority.simple_heading WHERE record = NEW.id; -- Should remove matching $0 from controlled fields at the same time? RETURN NEW; -- and we're done END IF; @@ -1431,10 +1432,16 @@ BEGIN IF NOT FOUND AND OLD.marc = NEW.marc THEN -- don't do anything if the MARC didn't change RETURN NEW; END IF; + -- Propagate these updates to any linked bib records PERFORM authority.propagate_changes(NEW.id) FROM authority.record_entry WHERE id = NEW.id; + + DELETE FROM authority.simple_heading WHERE record = NEW.id; END IF; + INSERT INTO authority.simple_heading (record,atag,value) + SELECT record, atag, value FROM authority.simple_heading_set(NEW.marc); + -- Flatten and insert the afr data PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_authority_full_rec' AND enabled; IF NOT FOUND THEN