<?xml version="1.0" encoding="UTF-8"?><database name="egdb3_11_7" schema="authority" type="PostgreSQL - 15.10 (Ubuntu 15.10-1.pgdg24.04+1)">
   <sequences>
      <sequence increment="1" name="authority_linking_id_seq" startValue="1"/>
      <sequence increment="1" name="bib_linking_id_seq" startValue="1"/>
      <sequence increment="1" name="browse_axis_authority_field_map_id_seq" startValue="1"/>
      <sequence increment="1" name="control_set_authority_field_id_seq" startValue="1"/>
      <sequence increment="1" name="control_set_bib_field_id_seq" startValue="1"/>
      <sequence increment="1" name="control_set_bib_field_metabib_field_map_id_seq" startValue="1"/>
      <sequence increment="1" name="control_set_id_seq" startValue="1"/>
      <sequence increment="1" name="full_rec_id_seq" startValue="1"/>
      <sequence increment="1" name="heading_field_id_seq" startValue="1"/>
      <sequence increment="1" name="heading_field_norm_map_id_seq" startValue="1"/>
      <sequence increment="1" name="rec_descriptor_id_seq" startValue="1"/>
      <sequence increment="1" name="record_entry_id_seq" startValue="1"/>
      <sequence increment="1" name="record_note_id_seq" startValue="1"/>
      <sequence increment="1" name="simple_heading_id_seq" startValue="1"/>
   </sequences>
   <tables>
      <table name="authority_linking" remarks="" schema="authority" type="TABLE">
         <column autoUpdated="true" defaultValue="nextval('authority.authority_linking_id_seq'::regclass)" digits="0" id="0" name="id" nullable="false" remarks="" size="19" type="bigserial" typeCode="-5"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="1" name="source" nullable="false" remarks="" size="19" type="int8" typeCode="-5">
            <parent column="id" foreignKey="authority_linking_source_fkey" implied="false" onDeleteCascade="false" schema="authority" table="record_entry"/>
         </column>
         <column autoUpdated="false" defaultValue="null" digits="0" id="2" name="target" nullable="false" remarks="" size="19" type="int8" typeCode="-5">
            <parent column="id" foreignKey="authority_linking_target_fkey" implied="false" onDeleteCascade="false" schema="authority" table="record_entry"/>
         </column>
         <column autoUpdated="false" defaultValue="null" digits="0" id="3" name="field" nullable="false" remarks="" size="10" type="int4" typeCode="4">
            <parent column="id" foreignKey="authority_linking_field_fkey" implied="false" onDeleteCascade="false" schema="authority" table="control_set_authority_field"/>
         </column>
         <primaryKey column="id" sequenceNumberInPK="1"/>
         <index name="authority_linking_pkey" unique="true">
            <column ascending="true" name="id"/>
         </index>
      </table>
      <table name="bib_linking" numRows="245" remarks="" schema="authority" type="TABLE">
         <column autoUpdated="true" defaultValue="nextval('authority.bib_linking_id_seq'::regclass)" digits="0" id="0" name="id" nullable="false" remarks="" size="19" type="bigserial" typeCode="-5"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="1" name="bib" nullable="false" remarks="" size="19" type="int8" typeCode="-5">
            <parent column="id" foreignKey="bib_linking_bib_fkey" implied="false" onDeleteCascade="false" schema="biblio" table="record_entry"/>
         </column>
         <column autoUpdated="false" defaultValue="null" digits="0" id="2" name="authority" nullable="false" remarks="" size="19" type="int8" typeCode="-5">
            <parent column="id" foreignKey="bib_linking_authority_fkey" implied="false" onDeleteCascade="false" schema="authority" table="record_entry"/>
         </column>
         <primaryKey column="id" sequenceNumberInPK="1"/>
         <index name="bib_linking_pkey" unique="true">
            <column ascending="true" name="id"/>
         </index>
         <index name="authority_bl_bib_authority_once_idx" unique="true">
            <column ascending="true" name="authority"/>
            <column ascending="true" name="bib"/>
         </index>
         <index name="authority_bl_bib_idx" unique="false">
            <column ascending="true" name="bib"/>
         </index>
      </table>
      <table name="browse_axis" remarks="" schema="authority" type="TABLE">
         <column autoUpdated="false" defaultValue="null" digits="0" id="0" name="code" nullable="false" remarks="" size="2147483647" type="text" typeCode="12">
            <child column="axis" foreignKey="browse_axis_authority_field_map_axis_fkey" implied="false" onDeleteCascade="true" schema="authority" table="browse_axis_authority_field_map"/>
         </column>
         <column autoUpdated="false" defaultValue="null" digits="0" id="1" name="name" nullable="false" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="2" name="sorter" nullable="true" remarks="" size="2147483647" type="text" typeCode="12">
            <parent column="name" foreignKey="browse_axis_sorter_fkey" implied="false" onDeleteCascade="true" schema="config" table="record_attr_definition"/>
         </column>
         <column autoUpdated="false" defaultValue="null" digits="0" id="3" name="description" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <primaryKey column="code" sequenceNumberInPK="1"/>
         <index name="browse_axis_pkey" unique="true">
            <column ascending="true" name="code"/>
         </index>
         <index name="browse_axis_name_key" unique="true">
            <column ascending="true" name="name"/>
         </index>
      </table>
      <table name="browse_axis_authority_field_map" remarks="" schema="authority" type="TABLE">
         <column autoUpdated="true" defaultValue="nextval('authority.browse_axis_authority_field_map_id_seq'::regclass)" digits="0" id="0" name="id" nullable="false" remarks="" size="10" type="serial" typeCode="4"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="1" name="axis" nullable="false" remarks="" size="2147483647" type="text" typeCode="12">
            <parent column="code" foreignKey="browse_axis_authority_field_map_axis_fkey" implied="false" onDeleteCascade="true" schema="authority" table="browse_axis"/>
         </column>
         <column autoUpdated="false" defaultValue="null" digits="0" id="2" name="field" nullable="false" remarks="" size="10" type="int4" typeCode="4">
            <parent column="id" foreignKey="browse_axis_authority_field_map_field_fkey" implied="false" onDeleteCascade="true" schema="authority" table="control_set_authority_field"/>
         </column>
         <primaryKey column="id" sequenceNumberInPK="1"/>
         <index name="browse_axis_authority_field_map_pkey" unique="true">
            <column ascending="true" name="id"/>
         </index>
      </table>
      <table name="control_set" remarks="" schema="authority" type="TABLE">
         <column autoUpdated="true" defaultValue="nextval('authority.control_set_id_seq'::regclass)" digits="0" id="0" name="id" nullable="false" remarks="" size="10" type="serial" typeCode="4">
            <child column="control_set" foreignKey="control_set_authority_field_control_set_fkey" implied="false" onDeleteCascade="true" schema="authority" table="control_set_authority_field"/>
            <child column="control_set" foreignKey="record_entry_control_set_fkey" implied="false" onDeleteCascade="false" schema="authority" table="record_entry"/>
            <child column="control_set" foreignKey="thesaurus_control_set_fkey" implied="false" onDeleteCascade="true" schema="authority" table="thesaurus"/>
         </column>
         <column autoUpdated="false" defaultValue="null" digits="0" id="1" name="name" nullable="false" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="2" name="description" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <primaryKey column="id" sequenceNumberInPK="1"/>
         <index name="control_set_pkey" unique="true">
            <column ascending="true" name="id"/>
         </index>
         <index name="control_set_name_key" unique="true">
            <column ascending="true" name="name"/>
         </index>
      </table>
      <table name="control_set_auth_field_metabib_field_map_blind_main" numRows="0" remarks="metabib fields for main entry auth fields that can't be linked to other records" schema="authority" type="VIEW" viewSql=" SELECT r.authority_field,&#10;    r.metabib_field&#10;   FROM (authority.control_set_auth_field_metabib_field_map_main r&#10;     JOIN authority.control_set_authority_field a ON ((r.authority_field = a.id)))&#10;  WHERE (a.linking_subfield IS NULL);">
         <column autoUpdated="false" defaultValue="null" digits="0" id="0" name="authority_field" nullable="true" remarks="" size="10" type="int4" typeCode="4"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="1" name="metabib_field" nullable="true" remarks="" size="10" type="int4" typeCode="4"/>
      </table>
      <table name="control_set_auth_field_metabib_field_map_blind_refs" numRows="0" remarks="metabib fields for all auth fields that can't be linked to other records" schema="authority" type="VIEW" viewSql=" SELECT r.authority_field,&#10;    r.metabib_field&#10;   FROM (authority.control_set_auth_field_metabib_field_map_refs r&#10;     JOIN authority.control_set_authority_field a ON ((r.authority_field = a.id)))&#10;  WHERE (a.linking_subfield IS NULL);">
         <column autoUpdated="false" defaultValue="null" digits="0" id="0" name="authority_field" nullable="true" remarks="" size="10" type="int4" typeCode="4"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="1" name="metabib_field" nullable="true" remarks="" size="10" type="int4" typeCode="4"/>
      </table>
      <table name="control_set_auth_field_metabib_field_map_blind_refs_only" numRows="0" remarks="metabib fields for NON-main entry auth fields that can't be linked to other records" schema="authority" type="VIEW" viewSql=" SELECT r.authority_field,&#10;    r.metabib_field&#10;   FROM (authority.control_set_auth_field_metabib_field_map_refs_only r&#10;     JOIN authority.control_set_authority_field a ON ((r.authority_field = a.id)))&#10;  WHERE (a.linking_subfield IS NULL);">
         <column autoUpdated="false" defaultValue="null" digits="0" id="0" name="authority_field" nullable="true" remarks="" size="10" type="int4" typeCode="4"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="1" name="metabib_field" nullable="true" remarks="" size="10" type="int4" typeCode="4"/>
      </table>
      <table name="control_set_auth_field_metabib_field_map_main" numRows="0" remarks="metabib fields for main entry auth fields" schema="authority" type="VIEW" viewSql=" SELECT DISTINCT b.authority_field,&#10;    m.metabib_field&#10;   FROM (authority.control_set_bib_field_metabib_field_map m&#10;     JOIN authority.control_set_bib_field b ON ((b.id = m.bib_field)));">
         <column autoUpdated="false" defaultValue="null" digits="0" id="0" name="authority_field" nullable="true" remarks="" size="10" type="int4" typeCode="4"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="1" name="metabib_field" nullable="true" remarks="" size="10" type="int4" typeCode="4"/>
      </table>
      <table name="control_set_auth_field_metabib_field_map_refs" numRows="0" remarks="metabib fields for all auth fields" schema="authority" type="VIEW" viewSql=" SELECT control_set_auth_field_metabib_field_map_main.authority_field,&#10;    control_set_auth_field_metabib_field_map_main.metabib_field&#10;   FROM authority.control_set_auth_field_metabib_field_map_main&#10;UNION&#10; SELECT control_set_auth_field_metabib_field_map_refs_only.authority_field,&#10;    control_set_auth_field_metabib_field_map_refs_only.metabib_field&#10;   FROM authority.control_set_auth_field_metabib_field_map_refs_only;">
         <column autoUpdated="false" defaultValue="null" digits="0" id="0" name="authority_field" nullable="true" remarks="" size="10" type="int4" typeCode="4"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="1" name="metabib_field" nullable="true" remarks="" size="10" type="int4" typeCode="4"/>
      </table>
      <table name="control_set_auth_field_metabib_field_map_refs_only" numRows="0" remarks="metabib fields for NON-main entry auth fields" schema="authority" type="VIEW" viewSql=" SELECT DISTINCT a.id AS authority_field,&#10;    m.metabib_field&#10;   FROM ((((authority.control_set_authority_field a&#10;     JOIN authority.control_set_authority_field ame ON ((a.main_entry = ame.id)))&#10;     JOIN authority.control_set_bib_field b ON ((b.authority_field = ame.id)))&#10;     JOIN authority.control_set_bib_field_metabib_field_map mf ON ((mf.bib_field = b.id)))&#10;     JOIN authority.control_set_auth_field_metabib_field_map_main m ON ((ame.id = m.authority_field)));">
         <column autoUpdated="false" defaultValue="null" digits="0" id="0" name="authority_field" nullable="true" remarks="" size="10" type="int4" typeCode="4"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="1" name="metabib_field" nullable="true" remarks="" size="10" type="int4" typeCode="4"/>
      </table>
      <table name="control_set_authority_field" numRows="48" remarks="" schema="authority" type="TABLE">
         <column autoUpdated="true" defaultValue="nextval('authority.control_set_authority_field_id_seq'::regclass)" digits="0" id="0" name="id" nullable="false" remarks="" size="10" type="serial" typeCode="4">
            <child column="field" foreignKey="authority_linking_field_fkey" implied="false" onDeleteCascade="false" schema="authority" table="authority_linking"/>
            <child column="field" foreignKey="browse_axis_authority_field_map_field_fkey" implied="false" onDeleteCascade="true" schema="authority" table="browse_axis_authority_field_map"/>
            <child column="main_entry" foreignKey="control_set_authority_field_main_entry_fkey" implied="false" onDeleteCascade="true" schema="authority" table="control_set_authority_field"/>
            <child column="authority_field" foreignKey="control_set_bib_field_authority_field_fkey" implied="false" onDeleteCascade="true" schema="authority" table="control_set_bib_field"/>
            <child column="atag" foreignKey="simple_heading_atag_fkey" implied="false" onDeleteCascade="false" schema="authority" table="simple_heading"/>
         </column>
         <column autoUpdated="false" defaultValue="null" digits="0" id="1" name="main_entry" nullable="true" remarks="" size="10" type="int4" typeCode="4">
            <parent column="id" foreignKey="control_set_authority_field_main_entry_fkey" implied="false" onDeleteCascade="true" schema="authority" table="control_set_authority_field"/>
         </column>
         <column autoUpdated="false" defaultValue="null" digits="0" id="2" name="control_set" nullable="false" remarks="" size="10" type="int4" typeCode="4">
            <parent column="id" foreignKey="control_set_authority_field_control_set_fkey" implied="false" onDeleteCascade="true" schema="authority" table="control_set"/>
         </column>
         <column autoUpdated="false" defaultValue="null" digits="0" id="3" name="tag" nullable="false" remarks="" size="3" type="bpchar" typeCode="1"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="4" name="nfi" nullable="true" remarks="" size="1" type="bpchar" typeCode="1"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="5" name="sf_list" nullable="false" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="6" name="display_sf_list" nullable="false" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="7" name="name" nullable="false" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="8" name="description" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="9" name="joiner" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="10" name="linking_subfield" nullable="true" remarks="" size="1" type="bpchar" typeCode="1"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="11" name="heading_field" nullable="true" remarks="" size="10" type="int4" typeCode="4">
            <parent column="id" foreignKey="control_set_authority_field_heading_field_fkey" implied="false" onDeleteCascade="false" schema="authority" table="heading_field"/>
         </column>
         <primaryKey column="id" sequenceNumberInPK="1"/>
         <index name="control_set_authority_field_pkey" unique="true">
            <column ascending="true" name="id"/>
         </index>
      </table>
      <table name="control_set_bib_field" remarks="" schema="authority" type="TABLE">
         <column autoUpdated="true" defaultValue="nextval('authority.control_set_bib_field_id_seq'::regclass)" digits="0" id="0" name="id" nullable="false" remarks="" size="10" type="serial" typeCode="4">
            <child column="bib_field" foreignKey="control_set_bib_field_metabib_field_map_bib_field_fkey" implied="false" onDeleteCascade="true" schema="authority" table="control_set_bib_field_metabib_field_map"/>
         </column>
         <column autoUpdated="false" defaultValue="null" digits="0" id="1" name="authority_field" nullable="false" remarks="" size="10" type="int4" typeCode="4">
            <parent column="id" foreignKey="control_set_bib_field_authority_field_fkey" implied="false" onDeleteCascade="true" schema="authority" table="control_set_authority_field"/>
         </column>
         <column autoUpdated="false" defaultValue="null" digits="0" id="2" name="tag" nullable="false" remarks="" size="3" type="bpchar" typeCode="1"/>
         <primaryKey column="id" sequenceNumberInPK="1"/>
         <index name="control_set_bib_field_pkey" unique="true">
            <column ascending="true" name="id"/>
         </index>
      </table>
      <table name="control_set_bib_field_metabib_field_map" remarks="" schema="authority" type="TABLE">
         <column autoUpdated="true" defaultValue="nextval('authority.control_set_bib_field_metabib_field_map_id_seq'::regclass)" digits="0" id="0" name="id" nullable="false" remarks="" size="10" type="serial" typeCode="4"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="1" name="bib_field" nullable="false" remarks="" size="10" type="int4" typeCode="4">
            <parent column="id" foreignKey="control_set_bib_field_metabib_field_map_bib_field_fkey" implied="false" onDeleteCascade="true" schema="authority" table="control_set_bib_field"/>
         </column>
         <column autoUpdated="false" defaultValue="null" digits="0" id="2" name="metabib_field" nullable="false" remarks="" size="10" type="int4" typeCode="4">
            <parent column="id" foreignKey="control_set_bib_field_metabib_field_map_metabib_field_fkey" implied="false" onDeleteCascade="true" schema="config" table="metabib_field"/>
         </column>
         <primaryKey column="id" sequenceNumberInPK="1"/>
         <index name="control_set_bib_field_metabib_field_map_pkey" unique="true">
            <column ascending="true" name="id"/>
         </index>
         <index name="a_bf_mf_map_once" unique="true">
            <column ascending="true" name="bib_field"/>
            <column ascending="true" name="metabib_field"/>
         </index>
      </table>
      <table name="full_rec" numRows="6247" remarks="" schema="authority" type="TABLE">
         <column autoUpdated="true" defaultValue="nextval('authority.full_rec_id_seq'::regclass)" digits="0" id="0" name="id" nullable="false" remarks="" size="19" type="bigserial" typeCode="-5"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="1" name="record" nullable="false" remarks="" size="19" type="int8" typeCode="-5"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="2" name="tag" nullable="false" remarks="" size="3" type="bpchar" typeCode="1"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="3" name="ind1" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="4" name="ind2" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="5" name="subfield" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="6" name="value" nullable="false" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="7" name="index_vector" nullable="false" remarks="" size="2147483647" type="tsvector" typeCode="1111"/>
         <primaryKey column="id" sequenceNumberInPK="1"/>
         <index name="full_rec_pkey" unique="true">
            <column ascending="true" name="id"/>
         </index>
         <index name="authority_full_rec_index_vector_idx" unique="false">
            <column ascending="true" name="index_vector"/>
         </index>
         <index name="authority_full_rec_record_idx" unique="false">
            <column ascending="true" name="record"/>
         </index>
         <index name="authority_full_rec_subfield_a_idx" unique="false">
            <column ascending="true" name="value"/>
         </index>
         <index name="authority_full_rec_tag_part_idx" unique="false"/>
         <index name="authority_full_rec_tag_subfield_idx" unique="false">
            <column ascending="true" name="tag"/>
            <column ascending="true" name="subfield"/>
         </index>
         <index name="authority_full_rec_value_index" unique="false"/>
         <index name="authority_full_rec_value_tpo_index" unique="false"/>
      </table>
      <table name="heading_field" remarks="" schema="authority" type="TABLE">
         <column autoUpdated="true" defaultValue="nextval('authority.heading_field_id_seq'::regclass)" digits="0" id="0" name="id" nullable="false" remarks="" size="10" type="serial" typeCode="4">
            <child column="heading_field" foreignKey="control_set_authority_field_heading_field_fkey" implied="false" onDeleteCascade="false" schema="authority" table="control_set_authority_field"/>
            <child column="field" foreignKey="heading_field_norm_map_field_fkey" implied="false" onDeleteCascade="true" schema="authority" table="heading_field_norm_map"/>
         </column>
         <column autoUpdated="false" defaultValue="null" digits="0" id="1" name="heading_type" nullable="false" remarks="" size="2147483647" type="&quot;authority&quot;.&quot;heading_type&quot;" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="2" name="heading_purpose" nullable="false" remarks="" size="2147483647" type="&quot;authority&quot;.&quot;heading_purpose&quot;" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="3" name="label" nullable="false" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="'mads21'::text" digits="0" id="4" name="format" nullable="false" remarks="" size="2147483647" type="text" typeCode="12">
            <parent column="name" foreignKey="heading_field_format_fkey" implied="false" onDeleteCascade="false" schema="config" table="xml_transform"/>
         </column>
         <column autoUpdated="false" defaultValue="null" digits="0" id="5" name="heading_xpath" nullable="false" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="6" name="component_xpath" nullable="false" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="7" name="type_xpath" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="8" name="thesaurus_xpath" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="9" name="thesaurus_override_xpath" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="10" name="joiner" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <primaryKey column="id" sequenceNumberInPK="1"/>
         <index name="heading_field_pkey" unique="true">
            <column ascending="true" name="id"/>
         </index>
      </table>
      <table name="heading_field_norm_map" remarks="" schema="authority" type="TABLE">
         <column autoUpdated="true" defaultValue="nextval('authority.heading_field_norm_map_id_seq'::regclass)" digits="0" id="0" name="id" nullable="false" remarks="" size="10" type="serial" typeCode="4"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="1" name="field" nullable="false" remarks="" size="10" type="int4" typeCode="4">
            <parent column="id" foreignKey="heading_field_norm_map_field_fkey" implied="false" onDeleteCascade="true" schema="authority" table="heading_field"/>
         </column>
         <column autoUpdated="false" defaultValue="null" digits="0" id="2" name="norm" nullable="false" remarks="" size="10" type="int4" typeCode="4">
            <parent column="id" foreignKey="heading_field_norm_map_norm_fkey" implied="false" onDeleteCascade="true" schema="config" table="index_normalizer"/>
         </column>
         <column autoUpdated="false" defaultValue="null" digits="0" id="3" name="params" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="0" digits="0" id="4" name="pos" nullable="false" remarks="" size="10" type="int4" typeCode="4"/>
         <primaryKey column="id" sequenceNumberInPK="1"/>
         <index name="heading_field_norm_map_pkey" unique="true">
            <column ascending="true" name="id"/>
         </index>
      </table>
      <table name="rec_descriptor" numRows="195" remarks="" schema="authority" type="TABLE">
         <column autoUpdated="true" defaultValue="nextval('authority.rec_descriptor_id_seq'::regclass)" digits="0" id="0" name="id" nullable="false" remarks="" size="19" type="bigserial" typeCode="-5"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="1" name="record" nullable="true" remarks="" size="19" type="int8" typeCode="-5"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="2" name="record_status" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="3" name="encoding_level" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="4" name="thesaurus" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <primaryKey column="id" sequenceNumberInPK="1"/>
         <index name="rec_descriptor_pkey" unique="true">
            <column ascending="true" name="id"/>
         </index>
         <index name="authority_rec_descriptor_record_idx" unique="false">
            <column ascending="true" name="record"/>
         </index>
      </table>
      <table name="record_entry" numRows="195" remarks="" schema="authority" type="TABLE">
         <column autoUpdated="true" defaultValue="nextval('authority.record_entry_id_seq'::regclass)" digits="0" id="0" name="id" nullable="false" remarks="" size="19" type="bigserial" typeCode="-5">
            <child column="source" foreignKey="authority_linking_source_fkey" implied="false" onDeleteCascade="false" schema="authority" table="authority_linking"/>
            <child column="target" foreignKey="authority_linking_target_fkey" implied="false" onDeleteCascade="false" schema="authority" table="authority_linking"/>
            <child column="authority" foreignKey="bib_linking_authority_fkey" implied="false" onDeleteCascade="false" schema="authority" table="bib_linking"/>
            <child column="record" foreignKey="record_note_record_fkey" implied="false" onDeleteCascade="false" schema="authority" table="record_note"/>
            <child column="record" foreignKey="simple_heading_record_fkey" implied="false" onDeleteCascade="false" schema="authority" table="simple_heading"/>
            <child column="authority" foreignKey="browse_entry_def_map_authority_fkey" implied="false" onDeleteCascade="false" schema="metabib" table="browse_entry_def_map"/>
            <child column="eg_record" foreignKey="authority_match_eg_record_fkey" implied="false" onDeleteCascade="false" schema="vandelay" table="authority_match"/>
            <child column="imported_as" foreignKey="queued_authority_record_imported_as_fkey" implied="false" onDeleteCascade="false" schema="vandelay" table="queued_authority_record"/>
         </column>
         <column autoUpdated="false" defaultValue="now()" digits="6" id="1" name="create_date" nullable="false" remarks="" size="35" type="timestamptz" typeCode="93"/>
         <column autoUpdated="false" defaultValue="now()" digits="6" id="2" name="edit_date" nullable="false" remarks="" size="35" type="timestamptz" typeCode="93"/>
         <column autoUpdated="false" defaultValue="1" digits="0" id="3" name="creator" nullable="false" remarks="" size="10" type="int4" typeCode="4"/>
         <column autoUpdated="false" defaultValue="1" digits="0" id="4" name="editor" nullable="false" remarks="" size="10" type="int4" typeCode="4"/>
         <column autoUpdated="false" defaultValue="true" digits="0" id="5" name="active" nullable="false" remarks="" size="1" type="bool" typeCode="-7"/>
         <column autoUpdated="false" defaultValue="false" digits="0" id="6" name="deleted" nullable="false" remarks="" size="1" type="bool" typeCode="-7"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="7" name="source" nullable="true" remarks="" size="10" type="int4" typeCode="4"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="8" name="control_set" nullable="true" remarks="" size="10" type="int4" typeCode="4">
            <parent column="id" foreignKey="record_entry_control_set_fkey" implied="false" onDeleteCascade="false" schema="authority" table="control_set"/>
         </column>
         <column autoUpdated="false" defaultValue="null" digits="0" id="9" name="marc" nullable="false" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="10" name="last_xact_id" nullable="false" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="11" name="owner" nullable="true" remarks="" size="10" type="int4" typeCode="4"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="12" name="heading" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="13" name="simple_heading" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <primaryKey column="id" sequenceNumberInPK="1"/>
         <index name="record_entry_pkey" unique="true">
            <column ascending="true" name="id"/>
         </index>
         <index name="authority_record_deleted_idx" unique="false">
            <column ascending="true" name="deleted"/>
         </index>
         <index name="authority_record_entry_create_date_idx" unique="false">
            <column ascending="true" name="create_date"/>
         </index>
         <index name="authority_record_entry_creator_idx" unique="false">
            <column ascending="true" name="creator"/>
         </index>
         <index name="authority_record_entry_edit_date_idx" unique="false">
            <column ascending="true" name="edit_date"/>
         </index>
         <index name="authority_record_entry_editor_idx" unique="false">
            <column ascending="true" name="editor"/>
         </index>
         <index name="by_heading" unique="false">
            <column ascending="true" name="simple_heading"/>
         </index>
         <index name="by_heading_and_thesaurus" unique="false">
            <column ascending="true" name="heading"/>
         </index>
      </table>
      <table name="record_note" remarks="" schema="authority" type="TABLE">
         <column autoUpdated="true" defaultValue="nextval('authority.record_note_id_seq'::regclass)" digits="0" id="0" name="id" nullable="false" remarks="" size="19" type="bigserial" typeCode="-5"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="1" name="record" nullable="false" remarks="" size="19" type="int8" typeCode="-5">
            <parent column="id" foreignKey="record_note_record_fkey" implied="false" onDeleteCascade="false" schema="authority" table="record_entry"/>
         </column>
         <column autoUpdated="false" defaultValue="null" digits="0" id="2" name="value" nullable="false" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="1" digits="0" id="3" name="creator" nullable="false" remarks="" size="10" type="int4" typeCode="4"/>
         <column autoUpdated="false" defaultValue="1" digits="0" id="4" name="editor" nullable="false" remarks="" size="10" type="int4" typeCode="4"/>
         <column autoUpdated="false" defaultValue="now()" digits="6" id="5" name="create_date" nullable="false" remarks="" size="35" type="timestamptz" typeCode="93"/>
         <column autoUpdated="false" defaultValue="now()" digits="6" id="6" name="edit_date" nullable="false" remarks="" size="35" type="timestamptz" typeCode="93"/>
         <primaryKey column="id" sequenceNumberInPK="1"/>
         <index name="record_note_pkey" unique="true">
            <column ascending="true" name="id"/>
         </index>
         <index name="authority_record_note_creator_idx" unique="false">
            <column ascending="true" name="creator"/>
         </index>
         <index name="authority_record_note_editor_idx" unique="false">
            <column ascending="true" name="editor"/>
         </index>
         <index name="authority_record_note_record_idx" unique="false">
            <column ascending="true" name="record"/>
         </index>
      </table>
      <table name="simple_heading" numRows="1108" remarks="" schema="authority" type="TABLE">
         <column autoUpdated="true" defaultValue="nextval('authority.simple_heading_id_seq'::regclass)" digits="0" id="0" name="id" nullable="false" remarks="" size="19" type="bigserial" typeCode="-5">
            <child column="simple_heading" foreignKey="browse_entry_simple_heading_map_simple_heading_fkey" implied="false" onDeleteCascade="true" schema="metabib" table="browse_entry_simple_heading_map"/>
         </column>
         <column autoUpdated="false" defaultValue="null" digits="0" id="1" name="record" nullable="false" remarks="" size="19" type="int8" typeCode="-5">
            <parent column="id" foreignKey="simple_heading_record_fkey" implied="false" onDeleteCascade="false" schema="authority" table="record_entry"/>
         </column>
         <column autoUpdated="false" defaultValue="null" digits="0" id="2" name="atag" nullable="false" remarks="" size="10" type="int4" typeCode="4">
            <parent column="id" foreignKey="simple_heading_atag_fkey" implied="false" onDeleteCascade="false" schema="authority" table="control_set_authority_field"/>
         </column>
         <column autoUpdated="false" defaultValue="null" digits="0" id="3" name="value" nullable="false" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="4" name="sort_value" nullable="false" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="5" name="index_vector" nullable="false" remarks="" size="2147483647" type="tsvector" typeCode="1111"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="6" name="thesaurus" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <primaryKey column="id" sequenceNumberInPK="1"/>
         <index name="simple_heading_pkey" unique="true">
            <column ascending="true" name="id"/>
         </index>
         <index name="authority_simple_heading_index_vector_idx" unique="false">
            <column ascending="true" name="index_vector"/>
         </index>
         <index name="authority_simple_heading_record_idx" unique="false">
            <column ascending="true" name="record"/>
         </index>
         <index name="authority_simple_heading_sort_value_idx" unique="false">
            <column ascending="true" name="sort_value"/>
         </index>
         <index name="authority_simple_heading_thesaurus_idx" unique="false">
            <column ascending="true" name="thesaurus"/>
         </index>
         <index name="authority_simple_heading_value_idx" unique="false">
            <column ascending="true" name="value"/>
         </index>
      </table>
      <table name="thesaurus" numRows="396" remarks="" schema="authority" type="TABLE">
         <column autoUpdated="false" defaultValue="null" digits="0" id="0" name="code" nullable="false" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="1" name="control_set" nullable="true" remarks="" size="10" type="int4" typeCode="4">
            <parent column="id" foreignKey="thesaurus_control_set_fkey" implied="false" onDeleteCascade="true" schema="authority" table="control_set"/>
         </column>
         <column autoUpdated="false" defaultValue="null" digits="0" id="2" name="name" nullable="false" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="3" name="description" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="4" name="short_code" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="5" name="uri" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <primaryKey column="code" sequenceNumberInPK="1"/>
         <index name="thesaurus_pkey" unique="true">
            <column ascending="true" name="code"/>
         </index>
         <index name="thesaurus_name_key" unique="true">
            <column ascending="true" name="name"/>
         </index>
      </table>
      <table name="tracing_links" numRows="0" remarks="" schema="authority" type="VIEW" viewSql=" SELECT main.record,&#10;    main.id AS main_id,&#10;    main.tag AS main_tag,&#10;    oils_xpath_string((('//*[@tag=&quot;'::text || (main.tag)::text) || '&quot;]/*[local-name()=&quot;subfield&quot;]'::text), are.marc) AS main_value,&#10;    substr(link.value, 1, 1) AS relationship,&#10;    substr(link.value, 2, 1) AS use_restriction,&#10;    substr(link.value, 3, 1) AS deprecation,&#10;    substr(link.value, 4, 1) AS display_restriction,&#10;    link.id AS link_id,&#10;    link.tag AS link_tag,&#10;    oils_xpath_string((('//*[@tag=&quot;'::text || (link.tag)::text) || '&quot;]/*[local-name()=&quot;subfield&quot;]'::text), are.marc) AS link_value,&#10;    are.heading AS normalized_main_value&#10;   FROM ((((authority.full_rec main&#10;     JOIN authority.record_entry are ON ((main.record = are.id)))&#10;     JOIN authority.control_set_authority_field main_entry ON (((main_entry.tag = main.tag) AND (main_entry.main_entry IS NULL) AND (main.subfield = 'a'::text))))&#10;     JOIN authority.control_set_authority_field sub_entry ON ((main_entry.id = sub_entry.main_entry)))&#10;     JOIN authority.full_rec link ON (((link.record = main.record) AND (link.tag = sub_entry.tag) AND (link.subfield = 'w'::text))));">
         <column autoUpdated="false" defaultValue="null" digits="0" id="0" name="record" nullable="true" remarks="" size="19" type="int8" typeCode="-5"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="1" name="main_id" nullable="true" remarks="" size="19" type="int8" typeCode="-5"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="2" name="main_tag" nullable="true" remarks="" size="3" type="bpchar" typeCode="1"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="3" name="main_value" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="4" name="relationship" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="5" name="use_restriction" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="6" name="deprecation" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="7" name="display_restriction" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="8" name="link_id" nullable="true" remarks="" size="19" type="int8" typeCode="-5"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="9" name="link_tag" nullable="true" remarks="" size="3" type="bpchar" typeCode="1"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="10" name="link_value" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
         <column autoUpdated="false" defaultValue="null" digits="0" id="11" name="normalized_main_value" nullable="true" remarks="" size="2147483647" type="text" typeCode="12"/>
      </table>
   </tables>
   <routines>
      <routine dataAccess="MODIFIES" deterministic="false" name="apply_propagate_changes(aid bigint, bid bigint)" returnType="bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="plpgsql"><![CDATA[DECLARE
    bib_forced  BOOL := FALSE;
    bib_rec     biblio.record_entry%ROWTYPE;
    new_marc    TEXT;
BEGIN

    SELECT INTO bib_rec * FROM biblio.record_entry WHERE id = bid;

    new_marc := vandelay.merge_record_xml(
        bib_rec.marc, authority.generate_overlay_template(aid));

    IF new_marc = bib_rec.marc THEN
        -- Authority record change had no impact on this bib record.
        -- Nothing left to do.
        RETURN aid;
    END IF;

    PERFORM 1 FROM config.global_flag
        WHERE name = 'ingest.disable_authority_auto_update_bib_meta'
            AND enabled;

    IF NOT FOUND THEN
        -- update the bib record editor and edit_date
        bib_rec.editor := (
            SELECT editor FROM authority.record_entry WHERE id = aid);
        bib_rec.edit_date = NOW();
    END IF;

    PERFORM action.set_queued_ingest_force('ingest.queued.biblio.update.disabled');

    UPDATE biblio.record_entry SET
        marc = new_marc,
        editor = bib_rec.editor,
        edit_date = bib_rec.edit_date
    WHERE id = bid;

    PERFORM action.clear_queued_ingest_force();

    RETURN aid;

END;]]></definition>
         <parameters>
            <parameter mode="IN" name="aid" type="bigint"/>
            <parameter mode="IN" name="bid" type="bigint"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="atag_authority_tags(atag text)" returnType="integer[]" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT ARRAY_AGG(id) FROM authority.control_set_authority_field WHERE tag = $1]]></definition>
         <parameters>
            <parameter mode="IN" name="atag" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="atag_authority_tags_refs(atag text)" returnType="integer[]" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT ARRAY_AGG(y) from (
        SELECT  unnest(ARRAY_CAT(
                    ARRAY[a.id],
                    (SELECT ARRAY_AGG(x.id) FROM authority.control_set_authority_field x WHERE x.main_entry = a.id)
                )) y
      FROM  authority.control_set_authority_field a
      WHERE a.tag = $1) x]]></definition>
         <parameters>
            <parameter mode="IN" name="atag" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="atag_browse_center(a text, q text, page integer DEFAULT 0, pagesize integer DEFAULT 9, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT * FROM authority.simple_heading_browse_center(authority.atag_authority_tags($1), $2, $3, $4, $5)]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="atag_browse_center_refs(a text, q text, page integer DEFAULT 0, pagesize integer DEFAULT 9, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT * FROM authority.simple_heading_browse_center(authority.atag_authority_tags_refs($1), $2, $3, $4, $5)]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="atag_browse_top(a text, q text, page integer DEFAULT 0, pagesize integer DEFAULT 10, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT * FROM authority.simple_heading_browse_top(authority.atag_authority_tags($1), $2, $3, $4, $5)]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="atag_browse_top_refs(a text, q text, page integer DEFAULT 0, pagesize integer DEFAULT 10, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT * FROM authority.simple_heading_browse_top(authority.atag_authority_tags_refs($1), $2, $3, $4, $5)]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="atag_search_heading(a text, q text, page integer DEFAULT 0, pagesize integer DEFAULT 10, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT * FROM authority.simple_heading_search_heading(authority.atag_authority_tags($1), $2, $3, $4, $5)]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="atag_search_heading_refs(a text, q text, page integer DEFAULT 0, pagesize integer DEFAULT 10, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT * FROM authority.simple_heading_search_heading(authority.atag_authority_tags_refs($1), $2, $3, $4, $5)]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="atag_search_rank(a text, q text, page integer DEFAULT 0, pagesize integer DEFAULT 10, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT * FROM authority.simple_heading_search_rank(authority.atag_authority_tags($1), $2, $3, $4, $5)]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="atag_search_rank_refs(a text, q text, page integer DEFAULT 0, pagesize integer DEFAULT 10, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT * FROM authority.simple_heading_search_rank(authority.atag_authority_tags_refs($1), $2, $3, $4, $5)]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="axis_authority_tags(a text)" returnType="integer[]" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT ARRAY_AGG(field) FROM authority.browse_axis_authority_field_map WHERE axis = $1;]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="axis_authority_tags_refs(a text)" returnType="integer[]" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT ARRAY_AGG(y) from (
       SELECT  unnest(ARRAY_CAT(
                 ARRAY[a.field],
                 (SELECT ARRAY_AGG(x.id) FROM authority.control_set_authority_field x WHERE x.main_entry = a.field)
             )) y
       FROM  authority.browse_axis_authority_field_map a
       WHERE axis = $1) x]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="axis_browse_center(a text, q text, page integer DEFAULT 0, pagesize integer DEFAULT 9, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT * FROM authority.simple_heading_browse_center(authority.axis_authority_tags($1), $2, $3, $4, $5)]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="axis_browse_center_refs(a text, q text, page integer DEFAULT 0, pagesize integer DEFAULT 9, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT * FROM authority.simple_heading_browse_center(authority.axis_authority_tags_refs($1), $2, $3, $4, $5)]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="axis_browse_top(a text, q text, page integer DEFAULT 0, pagesize integer DEFAULT 10, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT * FROM authority.simple_heading_browse_top(authority.axis_authority_tags($1), $2, $3, $4, $5)]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="axis_browse_top_refs(a text, q text, page integer DEFAULT 0, pagesize integer DEFAULT 10, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT * FROM authority.simple_heading_browse_top(authority.axis_authority_tags_refs($1), $2, $3, $4, $5)]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="axis_search_heading(a text, q text, page integer DEFAULT 0, pagesize integer DEFAULT 10, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT * FROM authority.simple_heading_search_heading(authority.axis_authority_tags($1), $2, $3, $4, $5)]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="axis_search_heading_refs(a text, q text, page integer DEFAULT 0, pagesize integer DEFAULT 10, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT * FROM authority.simple_heading_search_heading(authority.axis_authority_tags_refs($1), $2, $3, $4, $5)]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="axis_search_rank(a text, q text, page integer DEFAULT 0, pagesize integer DEFAULT 10, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT * FROM authority.simple_heading_search_rank(authority.axis_authority_tags($1), $2, $3, $4, $5)]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="axis_search_rank_refs(a text, q text, page integer DEFAULT 0, pagesize integer DEFAULT 10, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT * FROM authority.simple_heading_search_rank(authority.axis_authority_tags_refs($1), $2, $3, $4, $5)]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="btag_authority_tags(btag text)" returnType="integer[]" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT ARRAY_AGG(authority_field) FROM authority.control_set_bib_field WHERE tag = $1]]></definition>
         <parameters>
            <parameter mode="IN" name="btag" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="btag_authority_tags_refs(btag text)" returnType="integer[]" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT ARRAY_AGG(y) from (
        SELECT  unnest(ARRAY_CAT(
                    ARRAY[a.authority_field],
                    (SELECT ARRAY_AGG(x.id) FROM authority.control_set_authority_field x WHERE x.main_entry = a.authority_field)
                )) y
      FROM  authority.control_set_bib_field a
      WHERE a.tag = $1) x]]></definition>
         <parameters>
            <parameter mode="IN" name="btag" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="btag_browse_center(a text, q text, page integer DEFAULT 0, pagesize integer DEFAULT 9, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT * FROM authority.simple_heading_browse_center(authority.btag_authority_tags($1), $2, $3, $4, $5)]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="btag_browse_center_refs(a text, q text, page integer DEFAULT 0, pagesize integer DEFAULT 9, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT * FROM authority.simple_heading_browse_center(authority.btag_authority_tags_refs($1), $2, $3, $4, $5)]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="btag_browse_top(a text, q text, page integer DEFAULT 0, pagesize integer DEFAULT 10, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT * FROM authority.simple_heading_browse_top(authority.btag_authority_tags($1), $2, $3, $4, $5)]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="btag_browse_top_refs(a text, q text, page integer DEFAULT 0, pagesize integer DEFAULT 10, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT * FROM authority.simple_heading_browse_top(authority.btag_authority_tags_refs($1), $2, $3, $4, $5)]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="btag_search_heading(a text, q text, page integer DEFAULT 0, pagesize integer DEFAULT 10, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT * FROM authority.simple_heading_search_heading(authority.btag_authority_tags($1), $2, $3, $4, $5)]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="btag_search_heading_refs(a text, q text, page integer DEFAULT 0, pagesize integer DEFAULT 10, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT * FROM authority.simple_heading_search_heading(authority.btag_authority_tags_refs($1), $2, $3, $4, $5)]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="btag_search_rank(a text, q text, page integer DEFAULT 0, pagesize integer DEFAULT 10, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT * FROM authority.simple_heading_search_rank(authority.btag_authority_tags($1), $2, $3, $4, $5)]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="btag_search_rank_refs(a text, q text, page integer DEFAULT 0, pagesize integer DEFAULT 10, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT * FROM authority.simple_heading_search_rank(authority.btag_authority_tags_refs($1), $2, $3, $4, $5)]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="text"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="calculate_authority_linking(rec_id bigint, rec_control_set integer, rec_marc_xml xml)" returnType="SETOF authority.authority_linking" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="plpgsql"><![CDATA[DECLARE
    acsaf       authority.control_set_authority_field%ROWTYPE;
    link        TEXT;
    aal         authority.authority_linking%ROWTYPE;
BEGIN
    IF rec_control_set IS NULL THEN
        -- No control_set on record?  Guess at one
        SELECT control_set INTO rec_control_set
            FROM authority.control_set_authority_field
            WHERE tag IN (
                SELECT UNNEST(
                    XPATH('//*[starts-with(@tag,"1")]/@tag',rec_marc_xml)::TEXT[]
                )
            ) LIMIT 1;

        IF NOT FOUND THEN
            RAISE WARNING 'Could not even guess at control set for authority record %', rec_id;
            RETURN;
        END IF;
    END IF;

    aal.source := rec_id;

    FOR acsaf IN
        SELECT * FROM authority.control_set_authority_field
        WHERE control_set = rec_control_set
            AND linking_subfield IS NOT NULL
            AND main_entry IS NOT NULL
    LOOP
        -- Loop over the trailing-number contents of all linking subfields
        FOR link IN
            SELECT  SUBSTRING( x::TEXT, '\d+$' )
              FROM  UNNEST(
                        XPATH(
                            '//*[@tag="'
                                || acsaf.tag
                                || '"]/*[@code="'
                                || acsaf.linking_subfield
                                || '"]/text()',
                            rec_marc_xml
                        )
                    ) x
        LOOP

            -- Ignore links that are null, malformed, circular, or point to
            -- non-existent authority records.
            IF link IS NOT NULL AND link::BIGINT <> rec_id THEN
                PERFORM * FROM authority.record_entry WHERE id = link::BIGINT;
                IF FOUND THEN
                    aal.target := link::BIGINT;
                    aal.field := acsaf.id;
                    RETURN NEXT aal;
                END IF;
            END IF;
        END LOOP;
    END LOOP;
END;]]></definition>
         <parameters>
            <parameter mode="IN" name="rec_id" type="bigint"/>
            <parameter mode="IN" name="rec_control_set" type="integer"/>
            <parameter mode="IN" name="rec_marc_xml" type="xml"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="extract_headings(marc text, restrict integer[] DEFAULT NULL::integer[])" returnType="SETOF authority.heading" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="plpgsql"><![CDATA[DECLARE
    idx         authority.heading_field%ROWTYPE;
    xfrm        config.xml_transform%ROWTYPE;
    prev_xfrm   TEXT;
    transformed_xml TEXT;
    heading_node    TEXT;
    heading_node_list   TEXT[];
    component_node    TEXT;
    component_node_list   TEXT[];
    raw_text    TEXT;
    normalized_text    TEXT;
    normalizer  RECORD;
    curr_text   TEXT;
    joiner      TEXT;
    type_value  TEXT;
    base_thesaurus TEXT := NULL;
    output_row  authority.heading;
BEGIN

    -- Loop over the indexing entries
    FOR idx IN SELECT * FROM authority.heading_field WHERE restrict IS NULL OR id = ANY (restrict) ORDER BY format LOOP

        output_row.field   := idx.id;
        output_row.type    := idx.heading_type;
        output_row.purpose := idx.heading_purpose;

        joiner := COALESCE(idx.joiner, ' ');

        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(marc, xfrm.xslt);
            ELSE
                transformed_xml := marc;
            END IF;

            prev_xfrm := xfrm.name;
        END IF;

        IF idx.thesaurus_xpath IS NOT NULL THEN
            base_thesaurus := ARRAY_TO_STRING(oils_xpath(idx.thesaurus_xpath, transformed_xml, ARRAY[ARRAY[xfrm.prefix, xfrm.namespace_uri]]), '');
        END IF;

        heading_node_list := oils_xpath( idx.heading_xpath, transformed_xml, ARRAY[ARRAY[xfrm.prefix, xfrm.namespace_uri]] );

        FOR heading_node IN SELECT x FROM unnest(heading_node_list) AS x LOOP

            CONTINUE WHEN heading_node !~ E'^\\s*<';

            output_row.variant_type := NULL;
            output_row.related_type := NULL;
            output_row.thesaurus    := NULL;
            output_row.heading      := NULL;

            IF idx.heading_purpose = 'variant' AND idx.type_xpath IS NOT NULL THEN
                type_value := ARRAY_TO_STRING(oils_xpath(idx.type_xpath, heading_node, ARRAY[ARRAY[xfrm.prefix, xfrm.namespace_uri]]), '');
                BEGIN
                    output_row.variant_type := type_value;
                EXCEPTION WHEN invalid_text_representation THEN
                    RAISE NOTICE 'Do not recognize variant heading type %', type_value;
                END;
            END IF;
            IF idx.heading_purpose = 'related' AND idx.type_xpath IS NOT NULL THEN
                type_value := ARRAY_TO_STRING(oils_xpath(idx.type_xpath, heading_node, ARRAY[ARRAY[xfrm.prefix, xfrm.namespace_uri]]), '');
                BEGIN
                    output_row.related_type := type_value;
                EXCEPTION WHEN invalid_text_representation THEN
                    RAISE NOTICE 'Do not recognize related heading type %', type_value;
                END;
            END IF;
 
            IF idx.thesaurus_override_xpath IS NOT NULL THEN
                output_row.thesaurus := ARRAY_TO_STRING(oils_xpath(idx.thesaurus_override_xpath, heading_node, ARRAY[ARRAY[xfrm.prefix, xfrm.namespace_uri]]), '');
            END IF;
            IF output_row.thesaurus IS NULL THEN
                output_row.thesaurus := base_thesaurus;
            END IF;

            raw_text := NULL;

            -- now iterate over components of heading
            component_node_list := oils_xpath( idx.component_xpath, heading_node, ARRAY[ARRAY[xfrm.prefix, xfrm.namespace_uri]] );
            FOR component_node IN SELECT x FROM unnest(component_node_list) AS x LOOP
            -- XXX much of this should be moved into oils_xpath_string...
                curr_text := ARRAY_TO_STRING(array_remove(array_remove(
                    oils_xpath( '//text()', -- get the content of all the nodes within the main selected node
                        REGEXP_REPLACE( component_node, E'\\s+', ' ', 'g' ) -- Translate adjacent whitespace to a single space
                    ), ' '), ''),  -- throw away morally empty (bankrupt?) strings
                    joiner
                );

                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;
            END LOOP;

            IF raw_text IS NOT NULL THEN
                output_row.heading := raw_text;
                normalized_text := raw_text;

                FOR normalizer IN
                    SELECT  n.func AS func,
                            n.param_count AS param_count,
                            m.params AS params
                    FROM  config.index_normalizer n
                            JOIN authority.heading_field_norm_map m ON (m.norm = n.id)
                    WHERE m.field = idx.id
                    ORDER BY m.pos LOOP
            
                        EXECUTE 'SELECT ' || normalizer.func || '(' ||
                            quote_literal( normalized_text ) ||
                            CASE
                                WHEN normalizer.param_count > 0
                                    THEN ',' || REPLACE(REPLACE(BTRIM(normalizer.params,'[]'),E'\'',E'\\\''),E'"',E'\'')
                                    ELSE ''
                                END ||
                            ')' INTO normalized_text;
            
                END LOOP;
            
                output_row.normalized_heading := normalized_text;
            
                RETURN NEXT output_row;
            END IF;
        END LOOP;

    END LOOP;
END;]]></definition>
         <parameters>
            <parameter mode="IN" name="marc" type="text"/>
            <parameter mode="IN" name="restrict" type="integer[]"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="extract_headings(rid bigint, restrict integer[] DEFAULT NULL::integer[])" returnType="SETOF authority.heading" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="plpgsql"><![CDATA[DECLARE
    auth        authority.record_entry%ROWTYPE;
    output_row  authority.heading;
BEGIN
    -- Get the record
    SELECT INTO auth * FROM authority.record_entry WHERE id = rid;

    RETURN QUERY SELECT * FROM authority.extract_headings(auth.marc, restrict);
END;]]></definition>
         <parameters>
            <parameter mode="IN" name="rid" type="bigint"/>
            <parameter mode="IN" name="restrict" type="integer[]"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="extract_thesaurus(marcxml text)" returnType="text" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="plpgsql"><![CDATA[DECLARE
    thes_code TEXT;
BEGIN
    thes_code := vandelay.marc21_extract_fixed_field(marcxml,'Subj');
    IF thes_code IS NULL THEN
        thes_code := '|';
    ELSIF thes_code = 'z' THEN
        thes_code := COALESCE( oils_xpath_string('//*[@tag="040"]/*[@code="f"][1]', marcxml), 'z' );
    ELSE
        SELECT code INTO thes_code FROM authority.thesaurus WHERE short_code = thes_code;
        IF NOT FOUND THEN
            thes_code := '|'; -- default
        END IF;
    END IF;
    RETURN thes_code;
END;]]></definition>
         <parameters>
            <parameter mode="IN" name="marcxml" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="flatten_marc(rid bigint)" returnType="SETOF authority.full_rec" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="plpgsql"><![CDATA[DECLARE
	auth	authority.record_entry%ROWTYPE;
	output	authority.full_rec%ROWTYPE;
	field	RECORD;
BEGIN
	SELECT INTO auth * FROM authority.record_entry WHERE id = rid;

	FOR field IN SELECT * FROM vandelay.flatten_marc( auth.marc ) LOOP
		output.record := rid;
		output.ind1 := field.ind1;
		output.ind2 := field.ind2;
		output.tag := field.tag;
		output.subfield := field.subfield;
		output.value := field.value;

		RETURN NEXT output;
	END LOOP;
END;]]></definition>
         <parameters>
            <parameter mode="IN" name="rid" type="bigint"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="generate_overlay_template(bigint)" returnType="text" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT authority.generate_overlay_template( marc ) FROM authority.record_entry WHERE id = $1;]]></definition>
         <parameters>
            <parameter mode="IN" type="bigint"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="generate_overlay_template(source_xml text)" returnType="text" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="plpgsql"><![CDATA[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;
    tmp_data            XML;
    replace_data        XML[] DEFAULT '{}'::XML[];
    replace_rules       TEXT[] DEFAULT '{}'::TEXT[];
    auth_field          XML[];
    auth_i1             TEXT;
    auth_i2             TEXT;
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('//*[local-name()="datafield" and 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('//*[local-name()="datafield" and @tag="'||main_entry.tag||'"][1]',source_xml::XML);
        auth_i1 := (XPATH('//*[local-name()="datafield"]/@ind1',auth_field[1]))[1];
        auth_i2 := (XPATH('//*[local-name()="datafield"]/@ind2',auth_field[1]))[1];
        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
                SELECT XMLELEMENT( -- XMLAGG avoids magical <element> creation, but requires unnest subquery
                    name datafield,
                    XMLATTRIBUTES(bib_field.tag AS tag, auth_i1 AS ind1, auth_i2 AS ind2),
                    XMLAGG(UNNEST)
                ) INTO tmp_data FROM UNNEST(XPATH('//*[local-name()="subfield"]', auth_field[1]));
                replace_data := replace_data || tmp_data;
                replace_rules := replace_rules || ( bib_field.tag || main_entry.sf_list || E'[0~\\)' || auth_id || '$]' );
                tmp_data = NULL;
            END LOOP;
            EXIT;
        END IF;
    END LOOP;

    SELECT XMLAGG(UNNEST) INTO tmp_data FROM UNNEST(replace_data);

    RETURN XMLELEMENT(
        name record,
        XMLATTRIBUTES('http://www.loc.gov/MARC21/slim' AS xmlns),
        XMLELEMENT( name leader, '00881nam a2200193   4500'),
        tmp_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;]]></definition>
         <parameters>
            <parameter mode="IN" name="source_xml" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="indexing_delete(auth authority.record_entry, extra text DEFAULT NULL::text)" returnType="boolean" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="plpgsql"><![CDATA[DECLARE
    tmp_bool BOOL;
    diag_detail     TEXT;
    diag_context    TEXT;
BEGIN
    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?

    -- XXX What do we about the actual linking subfields present in
    -- authority records that target this one when this happens?
    DELETE FROM authority.authority_linking WHERE source = NEW.id OR target = NEW.id;

    RETURN TRUE;
EXCEPTION WHEN OTHERS THEN
    GET STACKED DIAGNOSTICS diag_detail  = PG_EXCEPTION_DETAIL,
                            diag_context = PG_EXCEPTION_CONTEXT;
    RAISE WARNING '%\n%', diag_detail, diag_context;
    RETURN FALSE;
END;]]></definition>
         <parameters>
            <parameter mode="IN" name="auth" type="authority.record_entry"/>
            <parameter mode="IN" name="extra" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="indexing_update(auth authority.record_entry, insert_only boolean DEFAULT false, old_heading text DEFAULT NULL::text)" returnType="boolean" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="plpgsql"><![CDATA[DECLARE
    ashs    authority.simple_heading%ROWTYPE;
    mbe_row metabib.browse_entry%ROWTYPE;
    mbe_id  BIGINT;
    ash_id  BIGINT;
    diag_detail     TEXT;
    diag_context    TEXT;
BEGIN

    -- Unless there's a setting stopping us, propagate these updates to any linked bib records when the heading changes
    PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_authority_auto_update' AND enabled;

    IF NOT FOUND AND auth.heading <> old_heading THEN
        PERFORM authority.propagate_changes(auth.id);
    END IF;

    IF NOT insert_only THEN
        DELETE FROM authority.authority_linking WHERE source = auth.id;
        DELETE FROM authority.simple_heading WHERE record = auth.id;
    END IF;

    INSERT INTO authority.authority_linking (source, target, field)
        SELECT source, target, field FROM authority.calculate_authority_linking(
            auth.id, auth.control_set, auth.marc::XML
        );

    FOR ashs IN SELECT * FROM authority.simple_heading_set(auth.marc) LOOP

        INSERT INTO authority.simple_heading (record,atag,value,sort_value,thesaurus)
            VALUES (ashs.record, ashs.atag, ashs.value, ashs.sort_value, ashs.thesaurus);
            ash_id := CURRVAL('authority.simple_heading_id_seq'::REGCLASS);

        SELECT INTO mbe_row * FROM metabib.browse_entry
            WHERE value = ashs.value AND sort_value = ashs.sort_value;

        IF FOUND THEN
            mbe_id := mbe_row.id;
        ELSE
            INSERT INTO metabib.browse_entry
                ( value, sort_value ) VALUES
                ( ashs.value, ashs.sort_value );

            mbe_id := CURRVAL('metabib.browse_entry_id_seq'::REGCLASS);
        END IF;

        INSERT INTO metabib.browse_entry_simple_heading_map (entry,simple_heading) VALUES (mbe_id,ash_id);

    END LOOP;

    -- Flatten and insert the afr data
    PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_authority_full_rec' AND enabled;
    IF NOT FOUND THEN
        PERFORM authority.reingest_authority_full_rec(auth.id);
        PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_authority_rec_descriptor' AND enabled;
        IF NOT FOUND THEN
            PERFORM authority.reingest_authority_rec_descriptor(auth.id);
        END IF;
    END IF;

    PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_symspell_reification' AND enabled;
    IF NOT FOUND THEN
        PERFORM search.symspell_dictionary_reify();
    END IF;

    RETURN TRUE;
EXCEPTION WHEN OTHERS THEN
    GET STACKED DIAGNOSTICS diag_detail  = PG_EXCEPTION_DETAIL,
                            diag_context = PG_EXCEPTION_CONTEXT;
    RAISE WARNING '%\n%', diag_detail, diag_context;
    RETURN FALSE;
END;]]></definition>
         <parameters>
            <parameter mode="IN" name="auth" type="authority.record_entry"/>
            <parameter mode="IN" name="insert_only" type="boolean"/>
            <parameter mode="IN" name="old_heading" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="map_thesaurus_to_control_set()" returnType="trigger" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="plpgsql"><![CDATA[BEGIN
    IF NEW.control_set IS NULL THEN
        SELECT  control_set INTO NEW.control_set
          FROM  authority.thesaurus
          WHERE authority.extract_thesaurus(NEW.marc) = code;
    END IF;

    RETURN NEW;
END;]]></definition>
         <parameters>
            <parameter mode="IN"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="merge_records(target_record bigint, source_record bigint)" returnType="integer" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="plpgsql"><![CDATA[DECLARE
    moved_objects INT := 0;
    bib_id        INT := 0;
    bib_rec       biblio.record_entry%ROWTYPE;
    auth_link     authority.bib_linking%ROWTYPE;
    ingest_same   boolean;
BEGIN

    -- Defining our terms:
    -- "target record" = the record that will survive the merge
    -- "source record" = the record that is sacrifing its existence and being
    --   replaced by the target record

    -- 1. Update all bib records with the ID from target_record in their $0
    FOR bib_rec IN
            SELECT  bre.*
              FROM  biblio.record_entry bre 
                    JOIN authority.bib_linking abl ON abl.bib = bre.id
              WHERE abl.authority = source_record
        LOOP

        UPDATE  biblio.record_entry
          SET   marc = REGEXP_REPLACE(
                    marc,
                    E'(<subfield\\s+code="0"\\s*>[^<]*?\\))' || source_record || '<',
                    E'\\1' || target_record || '<',
                    'g'
                )
          WHERE id = bib_rec.id;

          moved_objects := moved_objects + 1;
    END LOOP;

    -- 2. Grab the current value of reingest on same MARC flag
    SELECT  enabled INTO ingest_same
      FROM  config.internal_flag
      WHERE name = 'ingest.reingest.force_on_same_marc'
    ;

    -- 3. Temporarily set reingest on same to TRUE
    UPDATE  config.internal_flag
      SET   enabled = TRUE
      WHERE name = 'ingest.reingest.force_on_same_marc'
    ;

    -- 4. Make a harmless update to target_record to trigger auto-update
    --    in linked bibliographic records
    UPDATE  authority.record_entry
      SET   deleted = FALSE
      WHERE id = target_record;

    -- 5. "Delete" source_record
    DELETE FROM authority.record_entry WHERE id = source_record;

    -- 6. Set "reingest on same MARC" flag back to initial value
    UPDATE  config.internal_flag
      SET   enabled = ingest_same
      WHERE name = 'ingest.reingest.force_on_same_marc'
    ;

    RETURN moved_objects;
END;]]></definition>
         <parameters>
            <parameter mode="IN" name="target_record" type="bigint"/>
            <parameter mode="IN" name="source_record" type="bigint"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="normalize_heading(marcxml text)" returnType="text" securityType="INVOKER" type="FUNCTION">
         <comment><![CDATA[Extract the authority heading, thesaurus, and NACO-normalized values
from an authority record. The primary purpose is to build a unique
index to defend against duplicated authority records from the same
thesaurus.]]></comment>
         <definition language="sql"><![CDATA[SELECT authority.normalize_heading($1, FALSE);]]></definition>
         <parameters>
            <parameter mode="IN" name="marcxml" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="normalize_heading(marcxml text, no_thesaurus boolean)" returnType="text" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="plpgsql"><![CDATA[DECLARE
    acsaf           authority.control_set_authority_field%ROWTYPE;
    tag_used        TEXT;
    nfi_used        TEXT;
    sf              TEXT;
    sf_node         TEXT;
    tag_node        TEXT;
    thes_code       TEXT;
    cset            INT;
    heading_text    TEXT;
    tmp_text        TEXT;
    first_sf        BOOL;
    auth_id         INT DEFAULT COALESCE(NULLIF(oils_xpath_string('//*[@tag="901"]/*[local-name()="subfield" and @code="c"]', marcxml), ''), '0')::INT;
BEGIN
    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;

    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 tag_node IN SELECT unnest(oils_xpath('//*[@tag="'||tag_used||'"]',marcxml))
        LOOP
            FOR sf_node IN SELECT unnest(oils_xpath('//*[local-name() = "subfield" and contains("'||acsaf.sf_list||'",@code)]',tag_node))
            LOOP

                tmp_text := oils_xpath_string('.', sf_node);
                sf := oils_xpath_string('//*/@code', sf_node);

                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('//*[local-name() = "datafield"]/@ind'||nfi_used, tag_node),
                                    $$\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;
            END LOOP;

            EXIT WHEN heading_text <> '';
        END LOOP;

        EXIT WHEN heading_text <> '';
    END LOOP;

    IF heading_text <> '' THEN
        IF no_thesaurus IS TRUE THEN
            heading_text := tag_used || ' ' || public.naco_normalize(heading_text);
        ELSE
            thes_code := authority.extract_thesaurus(marcxml);
            heading_text := tag_used || '_' || COALESCE(nfi_used,'-') || '_' || thes_code || ' ' || public.naco_normalize(heading_text);
        END IF;
    ELSE
        heading_text := 'NOHEADING_' || thes_code || ' ' || MD5(marcxml);
    END IF;

    RETURN heading_text;
END;]]></definition>
         <parameters>
            <parameter mode="IN" name="marcxml" type="text"/>
            <parameter mode="IN" name="no_thesaurus" type="boolean"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="normalize_heading_for_upsert()" returnType="trigger" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="plpgsql"><![CDATA[BEGIN
    NEW.heading := authority.normalize_heading( NEW.marc );
    NEW.simple_heading := authority.simple_normalize_heading( NEW.marc );
    RETURN NEW;
END;]]></definition>
         <parameters>
            <parameter mode="IN"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="propagate_changes(aid bigint)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT authority.propagate_changes( authority, bib ) FROM authority.bib_linking WHERE authority = $1;]]></definition>
         <parameters>
            <parameter mode="IN" name="aid" type="bigint"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="propagate_changes(aid bigint, bid bigint)" returnType="bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="plpgsql"><![CDATA[DECLARE
    queuing_success BOOL := FALSE;
BEGIN

    PERFORM 1 FROM config.global_flag
        WHERE name IN ('ingest.queued.all','ingest.queued.authority.propagate')
            AND enabled;

    IF FOUND THEN
        -- XXX enqueue special 'propagate' bib action
        SELECT action.enqueue_ingest_entry( bid, 'biblio', NOW(), NULL, 'propagate', aid::TEXT) INTO queuing_success;

        IF queuing_success THEN
            RETURN aid;
        END IF;
    END IF;

    PERFORM authority.apply_propagate_changes(aid, bid);
    RETURN aid;
END;]]></definition>
         <parameters>
            <parameter mode="IN" name="aid" type="bigint"/>
            <parameter mode="IN" name="bid" type="bigint"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="reingest_authority_full_rec(auth_id bigint)" returnType="void" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="plpgsql"><![CDATA[BEGIN
    DELETE FROM authority.full_rec WHERE record = auth_id;
    INSERT INTO authority.full_rec (record, tag, ind1, ind2, subfield, value)
        SELECT record, tag, ind1, ind2, subfield, value FROM authority.flatten_marc( auth_id );

    RETURN;
END;]]></definition>
         <parameters>
            <parameter mode="IN" name="auth_id" type="bigint"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="reingest_authority_rec_descriptor(auth_id bigint)" returnType="void" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="plpgsql"><![CDATA[BEGIN
    DELETE FROM authority.rec_descriptor WHERE record = auth_id;
    INSERT INTO authority.rec_descriptor (record, record_status, encoding_level, thesaurus)
        SELECT  auth_id,
                vandelay.marc21_extract_fixed_field(marc,'RecStat'),
                vandelay.marc21_extract_fixed_field(marc,'ELvl'),
                authority.extract_thesaurus(marc)
          FROM  authority.record_entry
          WHERE id = auth_id;
    RETURN;
END;]]></definition>
         <parameters>
            <parameter mode="IN" name="auth_id" type="bigint"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="simple_heading_browse_center(atag_list integer[], q text, page integer DEFAULT 0, pagesize integer DEFAULT 9, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="plpgsql"><![CDATA[DECLARE
    pivot_sort_value    TEXT;
    boffset             INT DEFAULT 0;
    aoffset             INT DEFAULT 0;
    blimit              INT DEFAULT 0;
    alimit              INT DEFAULT 0;
BEGIN

    pivot_sort_value := authority.simple_heading_find_pivot(atag_list,q,thesauruses);

    IF page = 0 THEN
        blimit := pagesize / 2;
        alimit := blimit;

        IF pagesize % 2 <> 0 THEN
            alimit := alimit + 1;
        END IF;
    ELSE
        blimit := pagesize;
        alimit := blimit;

        boffset := pagesize / 2;
        aoffset := boffset;

        IF pagesize % 2 <> 0 THEN
            boffset := boffset + 1;
        END IF;
    END IF;

    IF page <= 0 THEN
        RETURN QUERY
            -- "bottom" half of the browse results
            SELECT id FROM (
                SELECT  ash.id,
                        row_number() over ()
                  FROM  authority.simple_heading ash
                  WHERE ash.atag = ANY (atag_list)
                        AND CASE thesauruses
                            WHEN '' THEN TRUE
                            ELSE ash.thesaurus = ANY(regexp_split_to_array(thesauruses, ','))
                            END
                        AND ash.sort_value < pivot_sort_value
                  ORDER BY ash.sort_value DESC
                  LIMIT blimit
                  OFFSET ABS(page) * pagesize - boffset
            ) x ORDER BY row_number DESC;
    END IF;

    IF page >= 0 THEN
        RETURN QUERY
            -- "bottom" half of the browse results
            SELECT  ash.id
              FROM  authority.simple_heading ash
              WHERE ash.atag = ANY (atag_list)
                    AND CASE thesauruses
                        WHEN '' THEN TRUE
                        ELSE ash.thesaurus = ANY(regexp_split_to_array(thesauruses, ','))
                        END
                    AND ash.sort_value >= pivot_sort_value
              ORDER BY ash.sort_value
              LIMIT alimit
              OFFSET ABS(page) * pagesize - aoffset;
    END IF;
END;]]></definition>
         <parameters>
            <parameter mode="IN" name="atag_list" type="integer[]"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="simple_heading_browse_top(atag_list integer[], q text, page integer DEFAULT 0, pagesize integer DEFAULT 10, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="plpgsql"><![CDATA[DECLARE
    pivot_sort_value    TEXT;
BEGIN

    pivot_sort_value := authority.simple_heading_find_pivot(atag_list,q,thesauruses);

    IF page < 0 THEN
        RETURN QUERY
            -- "bottom" half of the browse results
            SELECT id FROM (
                SELECT  ash.id,
                        row_number() over ()
                  FROM  authority.simple_heading ash
                  WHERE ash.atag = ANY (atag_list)
                        AND CASE thesauruses
                            WHEN '' THEN TRUE
                            ELSE ash.thesaurus = ANY(regexp_split_to_array(thesauruses, ','))
                            END
                        AND ash.sort_value < pivot_sort_value
                  ORDER BY ash.sort_value DESC
                  LIMIT pagesize
                  OFFSET (ABS(page) - 1) * pagesize
            ) x ORDER BY row_number DESC;
    END IF;

    IF page >= 0 THEN
        RETURN QUERY
            -- "bottom" half of the browse results
            SELECT  ash.id
              FROM  authority.simple_heading ash
              WHERE ash.atag = ANY (atag_list)
                AND CASE thesauruses
                    WHEN '' THEN TRUE
                    ELSE ash.thesaurus = ANY(regexp_split_to_array(thesauruses, ','))
                    END
                    AND ash.sort_value >= pivot_sort_value
              ORDER BY ash.sort_value
              LIMIT pagesize
              OFFSET ABS(page) * pagesize ;
    END IF;
END;]]></definition>
         <parameters>
            <parameter mode="IN" name="atag_list" type="integer[]"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="simple_heading_find_pivot(a integer[], q text, thesauruses text DEFAULT ''::text)" returnType="text" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="plpgsql"><![CDATA[DECLARE
    sort_value_row  RECORD;
    value_row       RECORD;
    t_term          TEXT;
BEGIN

    t_term := public.naco_normalize(q);

    SELECT  CASE WHEN ash.sort_value LIKE t_term || '%' THEN 1 ELSE 0 END
                + CASE WHEN ash.value LIKE t_term || '%' THEN 1 ELSE 0 END AS rank,
            ash.sort_value
      INTO  sort_value_row
      FROM  authority.simple_heading ash
      WHERE ash.atag = ANY (a)
            AND ash.sort_value >= t_term
            AND CASE thesauruses
                WHEN '' THEN TRUE
                ELSE ash.thesaurus = ANY(regexp_split_to_array(thesauruses, ','))
                END
      ORDER BY rank DESC, ash.sort_value
      LIMIT 1;

    SELECT  CASE WHEN ash.sort_value LIKE t_term || '%' THEN 1 ELSE 0 END
                + CASE WHEN ash.value LIKE t_term || '%' THEN 1 ELSE 0 END AS rank,
            ash.sort_value
      INTO  value_row
      FROM  authority.simple_heading ash
      WHERE ash.atag = ANY (a)
            AND ash.value >= t_term
            AND CASE thesauruses
                WHEN '' THEN TRUE
                ELSE ash.thesaurus = ANY(regexp_split_to_array(thesauruses, ','))
                END
      ORDER BY rank DESC, ash.sort_value
      LIMIT 1;

    IF value_row.rank > sort_value_row.rank THEN
        RETURN value_row.sort_value;
    ELSE
        RETURN sort_value_row.sort_value;
    END IF;
END;]]></definition>
         <parameters>
            <parameter mode="IN" name="a" type="integer[]"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="simple_heading_search_heading(atag_list integer[], q text, page integer DEFAULT 0, pagesize integer DEFAULT 10, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT  ash.id
      FROM  authority.simple_heading ash,
            public.naco_normalize($2) t(term),
            plainto_tsquery('keyword'::regconfig,$2) ptsq(term)
      WHERE ash.atag = ANY ($1)
            AND ash.index_vector @@ ptsq.term
            AND CASE $5
                WHEN '' THEN TRUE
                ELSE ash.thesaurus = ANY(regexp_split_to_array($5, ','))
                END
      ORDER BY ash.sort_value
      LIMIT $4
      OFFSET $4 * $3;]]></definition>
         <parameters>
            <parameter mode="IN" name="atag_list" type="integer[]"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="simple_heading_search_rank(atag_list integer[], q text, page integer DEFAULT 0, pagesize integer DEFAULT 10, thesauruses text DEFAULT ''::text)" returnType="SETOF bigint" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT  ash.id
      FROM  authority.simple_heading ash,
            public.naco_normalize($2) t(term),
            plainto_tsquery('keyword'::regconfig,$2) ptsq(term)
      WHERE ash.atag = ANY ($1)
            AND ash.index_vector @@ ptsq.term
            AND CASE $5
                WHEN '' THEN TRUE
                ELSE ash.thesaurus = ANY(regexp_split_to_array($5, ','))
                END
      ORDER BY ts_rank_cd(ash.index_vector,ptsq.term,14)::numeric
                    + CASE WHEN ash.sort_value LIKE t.term || '%' THEN 2 ELSE 0 END
                    + CASE WHEN ash.value LIKE t.term || '%' THEN 1 ELSE 0 END DESC
      LIMIT $4
      OFFSET $4 * $3;]]></definition>
         <parameters>
            <parameter mode="IN" name="atag_list" type="integer[]"/>
            <parameter mode="IN" name="q" type="text"/>
            <parameter mode="IN" name="page" type="integer"/>
            <parameter mode="IN" name="pagesize" type="integer"/>
            <parameter mode="IN" name="thesauruses" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="simple_heading_set(marcxml text)" returnType="SETOF authority.simple_heading" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="plpgsql"><![CDATA[DECLARE
    res             authority.simple_heading%ROWTYPE;
    acsaf           authority.control_set_authority_field%ROWTYPE;
    heading_row     authority.heading%ROWTYPE;
    tag_used        TEXT;
    nfi_used        TEXT;
    sf              TEXT;
    cset            INT;
    heading_text    TEXT;
    joiner_text     TEXT;
    sort_text       TEXT;
    tmp_text        TEXT;
    tmp_xml         TEXT;
    first_sf        BOOL;
    auth_id         INT DEFAULT COALESCE(NULLIF(oils_xpath_string('//*[@tag="901"]/*[local-name()="subfield" and @code="c"]', marcxml), ''), '0')::INT;
BEGIN

    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;

    res.record := auth_id;
    res.thesaurus := authority.extract_thesaurus(marcxml);

    FOR acsaf IN SELECT * FROM authority.control_set_authority_field WHERE control_set = cset LOOP
        res.atag := acsaf.id;

        IF acsaf.heading_field IS NULL THEN
            tag_used := acsaf.tag;
            nfi_used := acsaf.nfi;
            joiner_text := COALESCE(acsaf.joiner, ' ');

            FOR tmp_xml IN SELECT UNNEST(XPATH('//*[@tag="'||tag_used||'"]', marcxml::XML)::TEXT[]) LOOP

                heading_text := COALESCE(
                    oils_xpath_string('//*[local-name()="subfield" and contains("'||acsaf.display_sf_list||'",@code)]', tmp_xml, joiner_text),
                    ''
                );

                IF nfi_used IS NOT NULL THEN

                    sort_text := SUBSTRING(
                        heading_text FROM
                        COALESCE(
                            NULLIF(
                                REGEXP_REPLACE(
                                    oils_xpath_string('//*[local-name()="datafield"]/@ind'||nfi_used, tmp_xml::TEXT),
                                    $$\D+$$,
                                    '',
                                    'g'
                                ),
                                ''
                            )::INT,
                            0
                        ) + 1
                    );

                ELSE
                    sort_text := heading_text;
                END IF;

                IF heading_text IS NOT NULL AND heading_text <> '' THEN
                    res.value := heading_text;
                    res.sort_value := public.naco_normalize(sort_text);
                    res.index_vector = to_tsvector('keyword'::regconfig, res.sort_value);
                    RETURN NEXT res;
                END IF;

            END LOOP;
        ELSE
            FOR heading_row IN SELECT * FROM authority.extract_headings(marcxml, ARRAY[acsaf.heading_field]) LOOP
                res.value := heading_row.heading;
                res.sort_value := heading_row.normalized_heading;
                res.index_vector = to_tsvector('keyword'::regconfig, res.sort_value);
                RETURN NEXT res;
            END LOOP;
        END IF;
    END LOOP;

    RETURN;
END;]]></definition>
         <parameters>
            <parameter mode="IN" name="marcxml" type="text"/>
         </parameters>
      </routine>
      <routine dataAccess="MODIFIES" deterministic="false" name="simple_normalize_heading(marcxml text)" returnType="text" securityType="INVOKER" type="FUNCTION">
         <comment/>
         <definition language="sql"><![CDATA[SELECT authority.normalize_heading($1, TRUE);]]></definition>
         <parameters>
            <parameter mode="IN" name="marcxml" type="text"/>
         </parameters>
      </routine>
   </routines>
</database>
