-- Only consider main entry headings for bib overlay BEGIN; -- check whether patch can be applied SELECT evergreen.upgrade_deps_block_check('0750', :eg_version); -- Function to generate an ephemeral overlay template from an authority record CREATE OR REPLACE FUNCTION authority.generate_overlay_template (source_xml TEXT) RETURNS TEXT AS $f$ DECLARE cset INT; main_entry authority.control_set_authority_field%ROWTYPE; bib_field authority.control_set_bib_field%ROWTYPE; auth_id INT DEFAULT oils_xpath_string('//*[@tag="901"]/*[local-name()="subfield" and @code="c"]', source_xml)::INT; replace_data XML[] DEFAULT '{}'::XML[]; replace_rules TEXT[] DEFAULT '{}'::TEXT[]; auth_field XML[]; BEGIN IF auth_id IS NULL THEN RETURN NULL; END IF; -- Default to the LoC controll set SELECT control_set INTO cset FROM authority.record_entry WHERE id = auth_id; -- if none, make a best guess 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',marc::XML)::TEXT[]) FROM authority.record_entry WHERE id = auth_id ) LIMIT 1; END IF; -- if STILL none, no-op change IF cset IS NULL THEN RETURN XMLELEMENT( name record, XMLATTRIBUTES('http://www.loc.gov/MARC21/slim' AS xmlns), XMLELEMENT( name leader, '00881nam a2200193 4500'), XMLELEMENT( name datafield, XMLATTRIBUTES( '905' AS tag, ' ' AS ind1, ' ' AS ind2), XMLELEMENT( name subfield, XMLATTRIBUTES('d' AS code), '901c' ) ) )::TEXT; END IF; FOR main_entry IN SELECT * FROM authority.control_set_authority_field acsaf WHERE acsaf.control_set = cset AND acsaf.main_entry IS NULL LOOP auth_field := XPATH('//*[@tag="'||main_entry.tag||'"][1]',source_xml::XML); IF ARRAY_LENGTH(auth_field,1) > 0 THEN FOR bib_field IN SELECT * FROM authority.control_set_bib_field WHERE authority_field = main_entry.id LOOP replace_data := replace_data || XMLELEMENT( name datafield, XMLATTRIBUTES(bib_field.tag AS tag), XPATH('//*[local-name()="subfield"]',auth_field[1])::XML[]); replace_rules := replace_rules || ( bib_field.tag || main_entry.sf_list || E'[0~\\)' || auth_id || '$]' ); END LOOP; EXIT; END IF; END LOOP; RETURN XMLELEMENT( name record, XMLATTRIBUTES('http://www.loc.gov/MARC21/slim' AS xmlns), XMLELEMENT( name leader, '00881nam a2200193 4500'), replace_data, XMLELEMENT( name datafield, XMLATTRIBUTES( '905' AS tag, ' ' AS ind1, ' ' AS ind2), XMLELEMENT( name subfield, XMLATTRIBUTES('r' AS code), ARRAY_TO_STRING(replace_rules,',') ) ) )::TEXT; END; $f$ STABLE LANGUAGE PLPGSQL; -- Change the two argument form of vandelay.merge_record_xml to -- prevent bibliographic record destruction when there is nothing to -- do. CREATE OR REPLACE FUNCTION vandelay.merge_record_xml ( target_marc TEXT, template_marc TEXT ) RETURNS TEXT AS $$ DECLARE dyn_profile vandelay.compile_profile%ROWTYPE; replace_rule TEXT; tmp_marc TEXT; trgt_marc TEXT; tmpl_marc TEXT; match_count INT; BEGIN IF target_marc IS NULL OR template_marc IS NULL THEN -- RAISE NOTICE 'no marc for target or template record'; RETURN NULL; END IF; dyn_profile := vandelay.compile_profile( template_marc ); IF dyn_profile.replace_rule <> '' AND dyn_profile.preserve_rule <> '' THEN -- RAISE NOTICE 'both replace [%] and preserve [%] specified', dyn_profile.replace_rule, dyn_profile.preserve_rule; RETURN NULL; END IF; IF dyn_profile.replace_rule = '' AND dyn_profile.preserve_rule = '' AND dyn_profile.add_rule = '' THEN --Since we have nothing to do, just return what we were given. RETURN target_marc; ELSIF dyn_profile.replace_rule <> '' THEN trgt_marc = target_marc; tmpl_marc = template_marc; replace_rule = dyn_profile.replace_rule; ELSE tmp_marc = target_marc; trgt_marc = template_marc; tmpl_marc = tmp_marc; replace_rule = dyn_profile.preserve_rule; END IF; RETURN vandelay.merge_record_xml( trgt_marc, tmpl_marc, dyn_profile.add_rule, replace_rule, dyn_profile.strip_rule ); END; $$ LANGUAGE PLPGSQL; CREATE OR REPLACE FUNCTION vandelay.template_overlay_bib_record ( v_marc TEXT, eg_id BIGINT, merge_profile_id INT ) RETURNS BOOL AS $$ DECLARE merge_profile vandelay.merge_profile%ROWTYPE; dyn_profile vandelay.compile_profile%ROWTYPE; editor_string TEXT; editor_id INT; source_marc TEXT; target_marc TEXT; eg_marc TEXT; replace_rule TEXT; match_count INT; BEGIN SELECT b.marc INTO eg_marc FROM biblio.record_entry b WHERE b.id = eg_id LIMIT 1; IF eg_marc IS NULL OR v_marc IS NULL THEN -- RAISE NOTICE 'no marc for template or bib record'; RETURN FALSE; END IF; dyn_profile := vandelay.compile_profile( v_marc ); IF merge_profile_id IS NOT NULL THEN SELECT * INTO merge_profile FROM vandelay.merge_profile WHERE id = merge_profile_id; IF FOUND THEN dyn_profile.add_rule := BTRIM( dyn_profile.add_rule || ',' || COALESCE(merge_profile.add_spec,''), ','); dyn_profile.strip_rule := BTRIM( dyn_profile.strip_rule || ',' || COALESCE(merge_profile.strip_spec,''), ','); dyn_profile.replace_rule := BTRIM( dyn_profile.replace_rule || ',' || COALESCE(merge_profile.replace_spec,''), ','); dyn_profile.preserve_rule := BTRIM( dyn_profile.preserve_rule || ',' || COALESCE(merge_profile.preserve_spec,''), ','); END IF; END IF; IF dyn_profile.replace_rule <> '' AND dyn_profile.preserve_rule <> '' THEN -- RAISE NOTICE 'both replace [%] and preserve [%] specified', dyn_profile.replace_rule, dyn_profile.preserve_rule; RETURN FALSE; END IF; IF dyn_profile.replace_rule = '' AND dyn_profile.preserve_rule = '' AND dyn_profile.add_rule = '' AND dyn_profile.strip_rule = '' THEN --Since we have nothing to do, just return a NOOP "we did it" RETURN TRUE; ELSIF dyn_profile.replace_rule <> '' THEN source_marc = v_marc; target_marc = eg_marc; replace_rule = dyn_profile.replace_rule; ELSE source_marc = eg_marc; target_marc = v_marc; replace_rule = dyn_profile.preserve_rule; END IF; UPDATE biblio.record_entry SET marc = vandelay.merge_record_xml( target_marc, source_marc, dyn_profile.add_rule, replace_rule, dyn_profile.strip_rule ) WHERE id = eg_id; IF NOT FOUND THEN -- RAISE NOTICE 'update of biblio.record_entry failed'; RETURN FALSE; END IF; RETURN TRUE; END; $$ LANGUAGE PLPGSQL; CREATE OR REPLACE FUNCTION vandelay.overlay_authority_record ( import_id BIGINT, eg_id BIGINT, merge_profile_id INT ) RETURNS BOOL AS $$ DECLARE merge_profile vandelay.merge_profile%ROWTYPE; dyn_profile vandelay.compile_profile%ROWTYPE; source_marc TEXT; target_marc TEXT; eg_marc TEXT; v_marc TEXT; replace_rule TEXT; match_count INT; BEGIN SELECT b.marc INTO eg_marc FROM authority.record_entry b JOIN vandelay.authority_match m ON (m.eg_record = b.id AND m.queued_record = import_id) LIMIT 1; SELECT q.marc INTO v_marc FROM vandelay.queued_record q JOIN vandelay.authority_match m ON (m.queued_record = q.id AND q.id = import_id) LIMIT 1; IF eg_marc IS NULL OR v_marc IS NULL THEN -- RAISE NOTICE 'no marc for vandelay or authority record'; RETURN FALSE; END IF; dyn_profile := vandelay.compile_profile( v_marc ); IF merge_profile_id IS NOT NULL THEN SELECT * INTO merge_profile FROM vandelay.merge_profile WHERE id = merge_profile_id; IF FOUND THEN dyn_profile.add_rule := BTRIM( dyn_profile.add_rule || ',' || COALESCE(merge_profile.add_spec,''), ','); dyn_profile.strip_rule := BTRIM( dyn_profile.strip_rule || ',' || COALESCE(merge_profile.strip_spec,''), ','); dyn_profile.replace_rule := BTRIM( dyn_profile.replace_rule || ',' || COALESCE(merge_profile.replace_spec,''), ','); dyn_profile.preserve_rule := BTRIM( dyn_profile.preserve_rule || ',' || COALESCE(merge_profile.preserve_spec,''), ','); END IF; END IF; IF dyn_profile.replace_rule <> '' AND dyn_profile.preserve_rule <> '' THEN -- RAISE NOTICE 'both replace [%] and preserve [%] specified', dyn_profile.replace_rule, dyn_profile.preserve_rule; RETURN FALSE; END IF; IF dyn_profile.replace_rule = '' AND dyn_profile.preserve_rule = '' AND dyn_profile.add_rule = '' AND dyn_profile.strip_rule = '' THEN --Since we have nothing to do, just return a NOOP "we did it" RETURN TRUE; ELSIF dyn_profile.replace_rule <> '' THEN source_marc = v_marc; target_marc = eg_marc; replace_rule = dyn_profile.replace_rule; ELSE source_marc = eg_marc; target_marc = v_marc; replace_rule = dyn_profile.preserve_rule; END IF; UPDATE authority.record_entry SET marc = vandelay.merge_record_xml( target_marc, source_marc, dyn_profile.add_rule, replace_rule, dyn_profile.strip_rule ) WHERE id = eg_id; IF FOUND THEN UPDATE vandelay.queued_authority_record SET imported_as = eg_id, import_time = NOW() WHERE id = import_id; RETURN TRUE; END IF; -- RAISE NOTICE 'update of authority.record_entry failed'; RETURN FALSE; END; $$ LANGUAGE PLPGSQL; COMMIT;