From: Mike Rylander Date: Tue, 17 May 2011 18:09:50 +0000 (-0400) Subject: Merge branch 'master' of git.evergreen-ils.org:Evergreen into authority-control-sets X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=a606ebc63080b51b9d04eb026cd2925e9f8594cc;p=evergreen%2Fequinox.git Merge branch 'master' of git.evergreen-ils.org:Evergreen into authority-control-sets Conflicts: Open-ILS/src/sql/Pg/020.schema.functions.sql --- a606ebc63080b51b9d04eb026cd2925e9f8594cc diff --cc Open-ILS/src/sql/Pg/020.schema.functions.sql index e20417eab1,f29239ef65..c086a01657 --- a/Open-ILS/src/sql/Pg/020.schema.functions.sql +++ b/Open-ILS/src/sql/Pg/020.schema.functions.sql @@@ -327,3 -327,181 +327,92 @@@ Search "up" the org_unit tree until we org_unit_setting with the given name. $$; --- Intended to be used in a unique index on authority.record_entry like so: --- CREATE UNIQUE INDEX unique_by_heading_and_thesaurus --- ON authority.record_entry (authority.normalize_heading(marc)) --- WHERE deleted IS FALSE or deleted = FALSE; -CREATE OR REPLACE FUNCTION authority.normalize_heading( TEXT ) RETURNS TEXT AS $func$ - use strict; - use warnings; - - use utf8; - use MARC::Record; - use MARC::File::XML (BinaryEncoding => 'UTF8'); - use MARC::Charset; - use UUID::Tiny ':std'; - - MARC::Charset->assume_unicode(1); - - my $xml = shift() or return undef; - - my $r; - - # Prevent errors in XML parsing from blowing out ungracefully - eval { - $r = MARC::Record->new_from_xml( $xml ); - 1; - } or do { - return 'BAD_MARCXML_' . create_uuid_as_string(UUID_MD5, $xml); - }; - - if (!$r) { - return 'BAD_MARCXML_' . create_uuid_as_string(UUID_MD5, $xml); - } - - # From http://www.loc.gov/standards/sourcelist/subject.html - my $thes_code_map = { - a => 'lcsh', - b => 'lcshac', - c => 'mesh', - d => 'nal', - k => 'cash', - n => 'notapplicable', - r => 'aat', - s => 'sears', - v => 'rvm', - }; - - # Default to "No attempt to code" if the leader is horribly broken - my $fixed_field = $r->field('008'); - my $thes_char = '|'; - if ($fixed_field) { - $thes_char = substr($fixed_field->data(), 11, 1) || '|'; - } - - my $thes_code = 'UNDEFINED'; - - if ($thes_char eq 'z') { - # Grab the 040 $f per http://www.loc.gov/marc/authority/ad040.html - $thes_code = $r->subfield('040', 'f') || 'UNDEFINED'; - } elsif ($thes_code_map->{$thes_char}) { - $thes_code = $thes_code_map->{$thes_char}; - } - - my $auth_txt = ''; - my $head = $r->field('1..'); - if ($head) { - # Concatenate all of these subfields together, prefixed by their code - # to prevent collisions along the lines of "Fiction, North Carolina" - foreach my $sf ($head->subfields()) { - $auth_txt .= '‡' . $sf->[0] . ' ' . $sf->[1]; - } - } - - if ($auth_txt) { - my $stmt = spi_prepare('SELECT public.naco_normalize($1) AS norm_text', 'TEXT'); - my $result = spi_exec_prepared($stmt, $auth_txt); - my $norm_txt = $result->{rows}[0]->{norm_text}; - spi_freeplan($stmt); - undef($stmt); - return $head->tag() . "_" . $thes_code . " " . $norm_txt; - } - - return 'NOHEADING_' . $thes_code . ' ' . create_uuid_as_string(UUID_MD5, $xml); -$func$ LANGUAGE 'plperlu' IMMUTABLE; - -COMMENT ON FUNCTION authority.normalize_heading( TEXT ) IS $$ -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. -$$; - + CREATE OR REPLACE FUNCTION evergreen.get_barcodes(select_ou INT, type TEXT, in_barcode TEXT) RETURNS SETOF evergreen.barcode_set AS $$ + DECLARE + cur_barcode TEXT; + barcode_len INT; + completion_len INT; + asset_barcodes TEXT[]; + actor_barcodes TEXT[]; + do_asset BOOL = false; + do_serial BOOL = false; + do_booking BOOL = false; + do_actor BOOL = false; + completion_set config.barcode_completion%ROWTYPE; + BEGIN + + IF position('asset' in type) > 0 THEN + do_asset = true; + END IF; + IF position('serial' in type) > 0 THEN + do_serial = true; + END IF; + IF position('booking' in type) > 0 THEN + do_booking = true; + END IF; + IF do_asset OR do_serial OR do_booking THEN + asset_barcodes = asset_barcodes || in_barcode; + END IF; + IF position('actor' in type) > 0 THEN + do_actor = true; + actor_barcodes = actor_barcodes || in_barcode; + END IF; + + barcode_len := length(in_barcode); + + FOR completion_set IN + SELECT * FROM config.barcode_completion + WHERE active + AND org_unit IN (SELECT aou.id FROM actor.org_unit_ancestors(select_ou) aou) + LOOP + IF completion_set.prefix IS NULL THEN + completion_set.prefix := ''; + END IF; + IF completion_set.suffix IS NULL THEN + completion_set.suffix := ''; + END IF; + IF completion_set.length = 0 OR completion_set.padding IS NULL OR length(completion_set.padding) = 0 THEN + cur_barcode = completion_set.prefix || in_barcode || completion_set.suffix; + ELSE + completion_len = completion_set.length - length(completion_set.prefix) - length(completion_set.suffix); + IF completion_len >= barcode_len THEN + IF completion_set.padding_end THEN + cur_barcode = rpad(in_barcode, completion_len, completion_set.padding); + ELSE + cur_barcode = lpad(in_barcode, completion_len, completion_set.padding); + END IF; + cur_barcode = completion_set.prefix || cur_barcode || completion_set.suffix; + END IF; + END IF; + IF completion_set.actor THEN + actor_barcodes = actor_barcodes || cur_barcode; + END IF; + IF completion_set.asset THEN + asset_barcodes = asset_barcodes || cur_barcode; + END IF; + END LOOP; + + IF do_asset AND do_serial THEN + RETURN QUERY SELECT 'asset'::TEXT, id, barcode FROM ONLY asset.copy WHERE barcode = ANY(asset_barcodes) AND deleted = false; + RETURN QUERY SELECT 'serial'::TEXT, id, barcode FROM serial.unit WHERE barcode = ANY(asset_barcodes) AND deleted = false; + ELSIF do_asset THEN + RETURN QUERY SELECT 'asset'::TEXT, id, barcode FROM asset.copy WHERE barcode = ANY(asset_barcodes) AND deleted = false; + ELSIF do_serial THEN + RETURN QUERY SELECT 'serial'::TEXT, id, barcode FROM serial.unit WHERE barcode = ANY(asset_barcodes) AND deleted = false; + END IF; + IF do_booking THEN + RETURN QUERY SELECT 'booking'::TEXT, id::BIGINT, barcode FROM booking.resource WHERE barcode = ANY(asset_barcodes); + END IF; + IF do_actor THEN + RETURN QUERY SELECT 'actor'::TEXT, c.usr::BIGINT, c.barcode FROM actor.card c JOIN actor.usr u ON c.usr = u.id WHERE c.barcode = ANY(actor_barcodes) AND c.active AND NOT u.deleted ORDER BY usr; + END IF; + RETURN; + END; + $$ LANGUAGE plpgsql; + + COMMENT ON FUNCTION evergreen.get_barcodes(INT, TEXT, TEXT) IS $$ + Given user input, find an appropriate barcode in the proper class. + + Will add prefix/suffix information to do so, and return all results. + $$; ++ diff --cc Open-ILS/src/sql/Pg/800.fkeys.sql index 7ccd9b8606,d0ee8877c2..fa0a7e5201 --- a/Open-ILS/src/sql/Pg/800.fkeys.sql +++ b/Open-ILS/src/sql/Pg/800.fkeys.sql @@@ -115,7 -115,8 +115,9 @@@ ALTER TABLE config.remote_account ADD C ALTER TABLE config.org_unit_setting_type ADD CONSTRAINT view_perm_fkey FOREIGN KEY (view_perm) REFERENCES permission.perm_list (id) ON UPDATE CASCADE ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED; ALTER TABLE config.org_unit_setting_type ADD CONSTRAINT update_perm_fkey FOREIGN KEY (update_perm) REFERENCES permission.perm_list (id) ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED; + ALTER TABLE config.barcode_completion ADD CONSTRAINT config_barcode_completion_org_unit_fkey FOREIGN KEY (org_unit) REFERENCES actor.org_unit (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED; + CREATE INDEX by_heading_and_thesaurus ON authority.record_entry (authority.normalize_heading(marc)) WHERE deleted IS FALSE or deleted = FALSE; +CREATE INDEX by_heading ON authority.record_entry (authority.simple_normalize_heading(marc)) WHERE deleted IS FALSE or deleted = FALSE; COMMIT;