root / trunk / Open-ILS / src / sql / Pg / 040.schema.asset.sql

Revision 20468, 28.1 kB (checked in by gmc, 9 months ago)

fix query in various copy count functions

Signed-off-by: Galen Charlton <gmc@esilibrary.com>

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * Copyright (C) 2004-2008  Georgia Public Library Service
3 * Copyright (C) 2007-2008  Equinox Software, Inc.
4 * Mike Rylander <miker@esilibrary.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 */
17
18DROP SCHEMA IF EXISTS asset CASCADE;
19
20BEGIN;
21
22CREATE SCHEMA asset;
23
24CREATE TABLE asset.copy_location (
25        id              SERIAL  PRIMARY KEY,
26        name            TEXT    NOT NULL,
27        owning_lib      INT     NOT NULL REFERENCES actor.org_unit (id) DEFERRABLE INITIALLY DEFERRED,
28        holdable        BOOL    NOT NULL DEFAULT TRUE,
29        hold_verify     BOOL    NOT NULL DEFAULT FALSE,
30        opac_visible    BOOL    NOT NULL DEFAULT TRUE,
31        circulate       BOOL    NOT NULL DEFAULT TRUE,
32        label_prefix    TEXT,
33        label_suffix    TEXT,
34        CONSTRAINT acl_name_once_per_lib UNIQUE (name, owning_lib)
35);
36
37CREATE TABLE asset.copy_location_order
38(
39        id              SERIAL           PRIMARY KEY,
40        location        INT              NOT NULL
41                                             REFERENCES asset.copy_location
42                                             ON DELETE CASCADE
43                                             DEFERRABLE INITIALLY DEFERRED,
44        org             INT              NOT NULL
45                                             REFERENCES actor.org_unit
46                                             ON DELETE CASCADE
47                                             DEFERRABLE INITIALLY DEFERRED,
48        position        INT              NOT NULL DEFAULT 0,
49        CONSTRAINT acplo_once_per_org UNIQUE ( location, org )
50);
51
52CREATE TABLE asset.copy (
53        id              BIGSERIAL                       PRIMARY KEY,
54        circ_lib        INT                             NOT NULL REFERENCES actor.org_unit (id) DEFERRABLE INITIALLY DEFERRED,
55        creator         BIGINT                          NOT NULL,
56        call_number     BIGINT                          NOT NULL,
57        editor          BIGINT                          NOT NULL,
58        create_date     TIMESTAMP WITH TIME ZONE        DEFAULT NOW(),
59        edit_date       TIMESTAMP WITH TIME ZONE        DEFAULT NOW(),
60        copy_number     INT,
61        status          INT                             NOT NULL DEFAULT 0 REFERENCES config.copy_status (id) DEFERRABLE INITIALLY DEFERRED,
62        location        INT                             NOT NULL DEFAULT 1 REFERENCES asset.copy_location (id) DEFERRABLE INITIALLY DEFERRED,
63        loan_duration   INT                             NOT NULL CHECK ( loan_duration IN (1,2,3) ),
64        fine_level      INT                             NOT NULL CHECK ( fine_level IN (1,2,3) ),
65        age_protect     INT,
66        circulate       BOOL                            NOT NULL DEFAULT TRUE,
67        deposit         BOOL                            NOT NULL DEFAULT FALSE,
68        ref             BOOL                            NOT NULL DEFAULT FALSE,
69        holdable        BOOL                            NOT NULL DEFAULT TRUE,
70        deposit_amount  NUMERIC(6,2)                    NOT NULL DEFAULT 0.00,
71        price           NUMERIC(8,2),
72        barcode         TEXT                            NOT NULL,
73        circ_modifier   TEXT,
74        circ_as_type    TEXT,
75        dummy_title     TEXT,
76        dummy_author    TEXT,
77        alert_message   TEXT,
78        opac_visible    BOOL                            NOT NULL DEFAULT TRUE,
79        deleted         BOOL                            NOT NULL DEFAULT FALSE,
80        floating                BOOL                            NOT NULL DEFAULT FALSE,
81        dummy_isbn      TEXT,
82        status_changed_time TIMESTAMP WITH TIME ZONE,
83        mint_condition      BOOL        NOT NULL DEFAULT TRUE,
84    cost    NUMERIC(8,2)
85);
86CREATE UNIQUE INDEX copy_barcode_key ON asset.copy (barcode) WHERE deleted = FALSE OR deleted IS FALSE;
87CREATE INDEX cp_cn_idx ON asset.copy (call_number);
88CREATE INDEX cp_avail_cn_idx ON asset.copy (call_number);
89CREATE INDEX cp_creator_idx  ON asset.copy ( creator );
90CREATE INDEX cp_editor_idx   ON asset.copy ( editor );
91CREATE INDEX cp_create_date  ON asset.copy (create_date);
92CREATE RULE protect_copy_delete AS ON DELETE TO asset.copy DO INSTEAD UPDATE asset.copy SET deleted = TRUE WHERE OLD.id = asset.copy.id;
93
94CREATE TABLE asset.copy_part_map (
95    id          SERIAL  PRIMARY KEY,
96    target_copy BIGINT  NOT NULL, -- points o asset.copy
97    part        INT     NOT NULL REFERENCES biblio.monograph_part (id) ON DELETE CASCADE
98);
99CREATE UNIQUE INDEX copy_part_map_cp_part_idx ON asset.copy_part_map (target_copy, part);
100
101CREATE TABLE asset.opac_visible_copies (
102  id        BIGSERIAL primary key,
103  copy_id   BIGINT, -- copy id
104  record    BIGINT,
105  circ_lib  INTEGER
106);
107COMMENT ON TABLE asset.opac_visible_copies IS $$
108Materialized view of copies that are visible in the OPAC, used by
109search.query_parser_fts() to speed up OPAC visibility checks on large
110databases.  Contents are maintained by a set of triggers.
111$$;
112CREATE INDEX opac_visible_copies_idx1 on asset.opac_visible_copies (record, circ_lib);
113CREATE INDEX opac_visible_copies_copy_id_idx on asset.opac_visible_copies (copy_id);
114CREATE UNIQUE INDEX opac_visible_copies_once_per_record_idx on asset.opac_visible_copies (copy_id, record);
115
116CREATE OR REPLACE FUNCTION asset.acp_status_changed()
117RETURNS TRIGGER AS $$
118BEGIN
119    IF NEW.status <> OLD.status THEN
120        NEW.status_changed_time := now();
121    END IF;
122    RETURN NEW;
123END;
124$$ LANGUAGE plpgsql;
125
126CREATE TRIGGER acp_status_changed_trig
127    BEFORE UPDATE ON asset.copy
128    FOR EACH ROW EXECUTE PROCEDURE asset.acp_status_changed();
129
130CREATE TABLE asset.stat_cat_entry_transparency_map (
131        id                      BIGSERIAL       PRIMARY KEY,
132        stat_cat                INT             NOT NULL, -- needs ON DELETE CASCADE
133        stat_cat_entry          INT             NOT NULL, -- needs ON DELETE CASCADE
134        owning_transparency     INT             NOT NULL, -- needs ON DELETE CASCADE
135        CONSTRAINT scte_once_per_trans UNIQUE (owning_transparency,stat_cat)
136);
137
138CREATE TABLE asset.stat_cat (
139        id              SERIAL  PRIMARY KEY,
140        owner           INT     NOT NULL,
141        opac_visible    BOOL    NOT NULL DEFAULT FALSE,
142        name            TEXT    NOT NULL,
143        required        BOOL    NOT NULL DEFAULT FALSE,
144        CONSTRAINT sc_once_per_owner UNIQUE (owner,name)
145);
146
147CREATE TABLE asset.stat_cat_entry (
148        id              SERIAL  PRIMARY KEY,
149        stat_cat        INT     NOT NULL,
150        owner           INT     NOT NULL,
151        value           TEXT    NOT NULL,
152        CONSTRAINT sce_once_per_owner UNIQUE (stat_cat,owner,value)
153);
154
155CREATE TABLE asset.stat_cat_entry_copy_map (
156        id              BIGSERIAL       PRIMARY KEY,
157        stat_cat        INT             NOT NULL,
158        stat_cat_entry  INT             NOT NULL,
159        owning_copy     BIGINT          NOT NULL,
160        CONSTRAINT sce_once_per_copy UNIQUE (owning_copy,stat_cat)
161);
162CREATE INDEX scecm_owning_copy_idx ON asset.stat_cat_entry_copy_map(owning_copy);
163
164CREATE TABLE asset.copy_note (
165        id              BIGSERIAL                       PRIMARY KEY,
166        owning_copy     BIGINT                          NOT NULL,
167        creator         BIGINT                          NOT NULL,
168        create_date     TIMESTAMP WITH TIME ZONE        DEFAULT NOW(),
169        pub             BOOL                            NOT NULL DEFAULT FALSE,
170        title           TEXT                            NOT NULL,
171        value           TEXT                            NOT NULL
172);
173CREATE INDEX asset_copy_note_creator_idx ON asset.copy_note ( creator );
174CREATE INDEX asset_copy_note_owning_copy_idx ON asset.copy_note ( owning_copy );
175
176CREATE TABLE asset.uri (
177    id  SERIAL  PRIMARY KEY,
178    href    TEXT    NOT NULL,
179    label   TEXT,
180    use_restriction TEXT,
181    active  BOOL    NOT NULL DEFAULT TRUE
182);
183
184CREATE TABLE asset.call_number_class (
185    id             bigserial     PRIMARY KEY,
186    name           TEXT          NOT NULL,
187    normalizer     TEXT          NOT NULL DEFAULT 'asset.normalize_generic',
188    field          TEXT          NOT NULL DEFAULT '050ab,055ab,060ab,070ab,080ab,082ab,086ab,088ab,090,092,096,098,099'
189);
190COMMENT ON TABLE asset.call_number_class IS $$
191Defines the call number normalization database functions in the "normalizer"
192column and the tag/subfield combinations to use to lookup the call number in
193the "field" column for a given classification scheme. Tag/subfield combinations
194are delimited by commas.
195$$;
196
197CREATE OR REPLACE FUNCTION asset.label_normalizer() RETURNS TRIGGER AS $func$
198DECLARE
199    sortkey        TEXT := '';
200BEGIN
201    sortkey := NEW.label_sortkey;
202
203    EXECUTE 'SELECT ' || acnc.normalizer || '(' ||
204       quote_literal( NEW.label ) || ')'
205       FROM asset.call_number_class acnc
206       WHERE acnc.id = NEW.label_class
207       INTO sortkey;
208
209    NEW.label_sortkey = sortkey;
210
211    RETURN NEW;
212END;
213$func$ LANGUAGE PLPGSQL;
214
215CREATE OR REPLACE FUNCTION asset.label_normalizer_generic(TEXT) RETURNS TEXT AS $func$
216    # Created after looking at the Koha C4::ClassSortRoutine::Generic module,
217    # thus could probably be considered a derived work, although nothing was
218    # directly copied - but to err on the safe side of providing attribution:
219    # Copyright (C) 2007 LibLime
220    # Copyright (C) 2011 Equinox Software, Inc (Steve Callendar)
221    # Licensed under the GPL v2 or later
222
223    use strict;
224    use warnings;
225
226    # Converts the callnumber to uppercase
227    # Strips spaces from start and end of the call number
228    # Converts anything other than letters, digits, and periods into spaces
229    # Collapses multiple spaces into a single underscore
230    my $callnum = uc(shift);
231    $callnum =~ s/^\s//g;
232    $callnum =~ s/\s$//g;
233    # NOTE: this previously used underscores, but this caused sorting issues
234    # for the "before" half of page 0 on CN browse, sorting CNs containing a
235    # decimal before "whole number" CNs
236    $callnum =~ s/[^A-Z0-9_.]/ /g;
237    $callnum =~ s/ {2,}/ /g;
238
239    return $callnum;
240$func$ LANGUAGE PLPERLU;
241
242CREATE OR REPLACE FUNCTION asset.label_normalizer_dewey(TEXT) RETURNS TEXT AS $func$
243    # Derived from the Koha C4::ClassSortRoutine::Dewey module
244    # Copyright (C) 2007 LibLime
245    # Licensed under the GPL v2 or later
246
247    use strict;
248    use warnings;
249
250    my $init = uc(shift);
251    $init =~ s/^\s+//;
252    $init =~ s/\s+$//;
253    $init =~ s!/!!g;
254    $init =~ s/^([\p{IsAlpha}]+)/$1 /;
255    my @tokens = split /\.|\s+/, $init;
256    my $digit_group_count = 0;
257    for (my $i = 0; $i <= $#tokens; $i++) {
258        if ($tokens[$i] =~ /^\d+$/) {
259            $digit_group_count++;
260            if (2 == $digit_group_count) {
261                $tokens[$i] = sprintf("%-15.15s", $tokens[$i]);
262                $tokens[$i] =~ tr/ /0/;
263            }
264        }
265    }
266    my $key = join("_", @tokens);
267    $key =~ s/[^\p{IsAlnum}_]//g;
268
269    return $key;
270
271$func$ LANGUAGE PLPERLU;
272
273CREATE OR REPLACE FUNCTION asset.label_normalizer_lc(TEXT) RETURNS TEXT AS $func$
274    use strict;
275    use warnings;
276
277    # Library::CallNumber::LC is currently hosted at http://code.google.com/p/library-callnumber-lc/
278    # The author hopes to upload it to CPAN some day, which would make our lives easier
279    use Library::CallNumber::LC;
280
281    my $callnum = Library::CallNumber::LC->new(shift);
282    return $callnum->normalize();
283
284$func$ LANGUAGE PLPERLU;
285
286INSERT INTO asset.call_number_class (name, normalizer, field) VALUES 
287    ('Generic', 'asset.label_normalizer_generic', '050ab,055ab,060ab,070ab,080ab,082ab,086ab,088ab,090,092,096,098,099'),
288    ('Dewey (DDC)', 'asset.label_normalizer_dewey', '080ab,082ab,092abef'),
289    ('Library of Congress (LC)', 'asset.label_normalizer_lc', '050ab,055ab,090abef')
290;
291
292CREATE OR REPLACE FUNCTION asset.normalize_affix_sortkey () RETURNS TRIGGER AS $$
293BEGIN
294    NEW.label_sortkey := REGEXP_REPLACE(
295        evergreen.lpad_number_substrings(
296            naco_normalize(NEW.label),
297            '0',
298            10
299        ),
300        E'\\s+',
301        '',
302        'g'
303    );
304    RETURN NEW;
305END;
306$$ LANGUAGE PLPGSQL;
307
308CREATE TABLE asset.call_number_prefix (
309        id                      SERIAL   PRIMARY KEY,
310        owning_lib          INT                 NOT NULL REFERENCES actor.org_unit (id),
311        label               TEXT                NOT NULL, -- i18n
312        label_sortkey   TEXT
313);
314CREATE TRIGGER prefix_normalize_tgr BEFORE INSERT OR UPDATE ON asset.call_number_prefix FOR EACH ROW EXECUTE PROCEDURE asset.normalize_affix_sortkey();
315CREATE UNIQUE INDEX asset_call_number_prefix_once_per_lib ON asset.call_number_prefix (label, owning_lib);
316CREATE INDEX asset_call_number_prefix_sortkey_idx ON asset.call_number_prefix (label_sortkey);
317
318CREATE TABLE asset.call_number_suffix (
319        id                      SERIAL   PRIMARY KEY,
320        owning_lib          INT                 NOT NULL REFERENCES actor.org_unit (id),
321        label               TEXT                NOT NULL, -- i18n
322        label_sortkey   TEXT
323);
324CREATE TRIGGER suffix_normalize_tgr BEFORE INSERT OR UPDATE ON asset.call_number_suffix FOR EACH ROW EXECUTE PROCEDURE asset.normalize_affix_sortkey();
325CREATE UNIQUE INDEX asset_call_number_suffix_once_per_lib ON asset.call_number_suffix (label, owning_lib);
326CREATE INDEX asset_call_number_suffix_sortkey_idx ON asset.call_number_suffix (label_sortkey);
327
328CREATE TABLE asset.call_number (
329        id              bigserial PRIMARY KEY,
330        creator         BIGINT                          NOT NULL,
331        create_date     TIMESTAMP WITH TIME ZONE        DEFAULT NOW(),
332        editor          BIGINT                          NOT NULL,
333        edit_date       TIMESTAMP WITH TIME ZONE        DEFAULT NOW(),
334        record          bigint                          NOT NULL,
335        owning_lib      INT                                 NOT NULL,
336        label           TEXT                            NOT NULL,
337        deleted         BOOL                            NOT NULL DEFAULT FALSE,
338        prefix          INT                                 NOT NULL DEFAULT -1 REFERENCES asset.call_number_prefix(id) DEFERRABLE INITIALLY DEFERRED,
339        suffix          INT                                 NOT NULL DEFAULT -1 REFERENCES asset.call_number_suffix(id) DEFERRABLE INITIALLY DEFERRED,
340        label_class     BIGINT                          DEFAULT 1 NOT NULL
341                                                        REFERENCES asset.call_number_class(id)
342                                                        DEFERRABLE INITIALLY DEFERRED,
343        label_sortkey   TEXT
344);
345CREATE INDEX asset_call_number_record_idx ON asset.call_number (record);
346CREATE INDEX asset_call_number_creator_idx ON asset.call_number (creator);
347CREATE INDEX asset_call_number_editor_idx ON asset.call_number (editor);
348CREATE INDEX asset_call_number_dewey_idx ON asset.call_number (public.call_number_dewey(label));
349CREATE INDEX asset_call_number_upper_label_id_owning_lib_idx ON asset.call_number (oils_text_as_bytea(label),id,owning_lib);
350CREATE INDEX asset_call_number_label_sortkey ON asset.call_number(oils_text_as_bytea(label_sortkey));
351CREATE UNIQUE INDEX asset_call_number_label_once_per_lib ON asset.call_number (record, owning_lib, label, prefix, suffix) WHERE deleted = FALSE OR deleted IS FALSE;
352CREATE INDEX asset_call_number_label_sortkey_browse ON asset.call_number(oils_text_as_bytea(label_sortkey), oils_text_as_bytea(label), id, owning_lib) WHERE deleted IS FALSE OR deleted = FALSE;
353CREATE RULE protect_cn_delete AS ON DELETE TO asset.call_number DO INSTEAD UPDATE asset.call_number SET deleted = TRUE WHERE OLD.id = asset.call_number.id;
354CREATE TRIGGER asset_label_sortkey_trigger
355    BEFORE UPDATE OR INSERT ON asset.call_number
356    FOR EACH ROW EXECUTE PROCEDURE asset.label_normalizer();
357
358CREATE TABLE asset.uri_call_number_map (
359    id          BIGSERIAL   PRIMARY KEY,
360    uri         INT         NOT NULL REFERENCES asset.uri (id),
361    call_number INT         NOT NULL REFERENCES asset.call_number (id),
362    CONSTRAINT uri_cn_once UNIQUE (uri,call_number)
363);
364CREATE INDEX asset_uri_call_number_map_cn_idx ON asset.uri_call_number_map (call_number);
365
366CREATE TABLE asset.call_number_note (
367        id              BIGSERIAL                       PRIMARY KEY,
368        call_number     BIGINT                          NOT NULL,
369        creator         BIGINT                          NOT NULL,
370        create_date     TIMESTAMP WITH TIME ZONE        DEFAULT NOW(),
371        pub             BOOL                            NOT NULL DEFAULT FALSE,
372        title           TEXT                            NOT NULL,
373        value           TEXT                            NOT NULL
374);
375CREATE INDEX asset_call_number_note_creator_idx ON asset.call_number_note ( creator );
376
377CREATE TABLE asset.copy_template (
378        id             SERIAL   PRIMARY KEY,
379        owning_lib     INT      NOT NULL
380                                REFERENCES actor.org_unit (id)
381                                DEFERRABLE INITIALLY DEFERRED,
382        creator        BIGINT   NOT NULL
383                                REFERENCES actor.usr (id)
384                                DEFERRABLE INITIALLY DEFERRED,
385        editor         BIGINT   NOT NULL
386                                REFERENCES actor.usr (id)
387                                DEFERRABLE INITIALLY DEFERRED,
388        create_date    TIMESTAMP WITH TIME ZONE    DEFAULT NOW(),
389        edit_date      TIMESTAMP WITH TIME ZONE    DEFAULT NOW(),
390        name           TEXT     NOT NULL,
391        -- columns above this point are attributes of the template itself
392        -- columns after this point are attributes of the copy this template modifies/creates
393        circ_lib       INT      REFERENCES actor.org_unit (id)
394                                DEFERRABLE INITIALLY DEFERRED,
395        status         INT      REFERENCES config.copy_status (id)
396                                DEFERRABLE INITIALLY DEFERRED,
397        location       INT      REFERENCES asset.copy_location (id)
398                                DEFERRABLE INITIALLY DEFERRED,
399        loan_duration  INT      CONSTRAINT valid_loan_duration CHECK (
400                                    loan_duration IS NULL OR loan_duration IN (1,2,3)),
401        fine_level     INT      CONSTRAINT valid_fine_level CHECK (
402                                    fine_level IS NULL OR loan_duration IN (1,2,3)),
403        age_protect    INT,
404        circulate      BOOL,
405        deposit        BOOL,
406        ref            BOOL,
407        holdable       BOOL,
408        deposit_amount NUMERIC(6,2),
409        price          NUMERIC(8,2),
410        circ_modifier  TEXT,
411        circ_as_type   TEXT,
412        alert_message  TEXT,
413        opac_visible   BOOL,
414        floating       BOOL,
415        mint_condition BOOL
416);
417
418CREATE OR REPLACE FUNCTION asset.opac_ou_record_copy_count (org INT, rid BIGINT) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
419DECLARE
420    ans RECORD;
421    trans INT;
422BEGIN
423    SELECT 1 INTO trans FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = rid;
424
425    FOR ans IN SELECT u.id, t.depth FROM actor.org_unit_ancestors(org) AS u JOIN actor.org_unit_type t ON (u.ou_type = t.id) LOOP
426        RETURN QUERY
427        SELECT  ans.depth,
428                ans.id,
429                COUNT( av.id ),
430                SUM( CASE WHEN cp.status IN (0,7,12) THEN 1 ELSE 0 END ),
431                COUNT( av.id ),
432                trans
433          FROM 
434                actor.org_unit_descendants(ans.id) d
435                JOIN asset.opac_visible_copies av ON (av.record = rid AND av.circ_lib = d.id)
436                JOIN asset.copy cp ON (cp.id = av.copy_id)
437          GROUP BY 1,2,6;
438
439        IF NOT FOUND THEN
440            RETURN QUERY SELECT ans.depth, ans.id, 0::BIGINT, 0::BIGINT, 0::BIGINT, trans;
441        END IF;
442
443    END LOOP;
444
445    RETURN;
446END;
447$f$ LANGUAGE PLPGSQL;
448
449CREATE OR REPLACE FUNCTION asset.opac_lasso_record_copy_count (i_lasso INT, rid BIGINT) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
450DECLARE
451    ans RECORD;
452    trans INT;
453BEGIN
454    SELECT 1 INTO trans FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = rid;
455
456    FOR ans IN SELECT u.org_unit AS id FROM actor.org_lasso_map AS u WHERE lasso = i_lasso LOOP
457        RETURN QUERY
458        SELECT  -1,
459                ans.id,
460                COUNT( av.id ),
461                SUM( CASE WHEN cp.status IN (0,7,12) THEN 1 ELSE 0 END ),
462                COUNT( av.id ),
463                trans
464          FROM
465                actor.org_unit_descendants(ans.id) d
466                JOIN asset.opac_visible_copies av ON (av.record = rid AND av.circ_lib = d.id)
467                JOIN asset.copy cp ON (cp.id = av.copy_id)
468          GROUP BY 1,2,6;
469
470        IF NOT FOUND THEN
471            RETURN QUERY SELECT ans.depth, ans.id, 0::BIGINT, 0::BIGINT, 0::BIGINT, trans;
472        END IF;
473
474    END LOOP;   
475               
476    RETURN;     
477END;           
478$f$ LANGUAGE PLPGSQL;
479
480CREATE OR REPLACE FUNCTION asset.staff_ou_record_copy_count (org INT, rid BIGINT) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
481DECLARE         
482    ans RECORD;
483    trans INT;
484BEGIN           
485    SELECT 1 INTO trans FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = rid;
486
487    FOR ans IN SELECT u.id, t.depth FROM actor.org_unit_ancestors(org) AS u JOIN actor.org_unit_type t ON (u.ou_type = t.id) LOOP
488        RETURN QUERY
489        SELECT  ans.depth,
490                ans.id,
491                COUNT( cp.id ),
492                SUM( CASE WHEN cp.status IN (0,7,12) THEN 1 ELSE 0 END ),
493                COUNT( cp.id ),
494                trans
495          FROM
496                actor.org_unit_descendants(ans.id) d
497                JOIN asset.copy cp ON (cp.circ_lib = d.id AND NOT cp.deleted)
498                JOIN asset.call_number cn ON (cn.record = rid AND cn.id = cp.call_number AND NOT cn.deleted)
499          GROUP BY 1,2,6;
500
501        IF NOT FOUND THEN
502            RETURN QUERY SELECT ans.depth, ans.id, 0::BIGINT, 0::BIGINT, 0::BIGINT, trans;
503        END IF;
504
505    END LOOP;
506
507    RETURN;
508END;
509$f$ LANGUAGE PLPGSQL;
510
511CREATE OR REPLACE FUNCTION asset.staff_lasso_record_copy_count (i_lasso INT, rid BIGINT) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
512DECLARE
513    ans RECORD;
514    trans INT;
515BEGIN
516    SELECT 1 INTO trans FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = rid;
517
518    FOR ans IN SELECT u.org_unit AS id FROM actor.org_lasso_map AS u WHERE lasso = i_lasso LOOP
519        RETURN QUERY
520        SELECT  -1,
521                ans.id,
522                COUNT( cp.id ),
523                SUM( CASE WHEN cp.status IN (0,7,12) THEN 1 ELSE 0 END ),
524                COUNT( cp.id ),
525                trans
526          FROM
527                actor.org_unit_descendants(ans.id) d
528                JOIN asset.copy cp ON (cp.circ_lib = d.id AND NOT cp.deleted)
529                JOIN asset.call_number cn ON (cn.record = rid AND cn.id = cp.call_number AND NOT cn.deleted)
530          GROUP BY 1,2,6;
531
532        IF NOT FOUND THEN
533            RETURN QUERY SELECT ans.depth, ans.id, 0::BIGINT, 0::BIGINT, 0::BIGINT, trans;
534        END IF;
535
536    END LOOP;
537
538    RETURN;
539END;
540$f$ LANGUAGE PLPGSQL;
541
542CREATE OR REPLACE FUNCTION asset.record_copy_count ( place INT, rid BIGINT, staff BOOL) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
543BEGIN
544    IF staff IS TRUE THEN
545        IF place > 0 THEN
546            RETURN QUERY SELECT * FROM asset.staff_ou_record_copy_count( place, rid );
547        ELSE
548            RETURN QUERY SELECT * FROM asset.staff_lasso_record_copy_count( -place, rid );
549        END IF;
550    ELSE
551        IF place > 0 THEN
552            RETURN QUERY SELECT * FROM asset.opac_ou_record_copy_count( place, rid );
553        ELSE
554            RETURN QUERY SELECT * FROM asset.opac_lasso_record_copy_count( -place, rid );
555        END IF;
556    END IF;
557
558    RETURN;
559END;
560$f$ LANGUAGE PLPGSQL;
561
562CREATE OR REPLACE FUNCTION asset.opac_ou_metarecord_copy_count (org INT, rid BIGINT) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
563DECLARE
564    ans RECORD;
565    trans INT;
566BEGIN
567    SELECT 1 INTO trans FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = rid;
568
569    FOR ans IN SELECT u.id, t.depth FROM actor.org_unit_ancestors(org) AS u JOIN actor.org_unit_type t ON (u.ou_type = t.id) LOOP
570        RETURN QUERY
571        SELECT  ans.depth,
572                ans.id,
573                COUNT( av.id ),
574                SUM( CASE WHEN cp.status IN (0,7,12) THEN 1 ELSE 0 END ),
575                COUNT( av.id ),
576                trans
577          FROM 
578                actor.org_unit_descendants(ans.id) d
579                JOIN asset.opac_visible_copies av ON (av.record = rid AND av.circ_lib = d.id)
580                JOIN asset.copy cp ON (cp.id = av.copy_id)
581                JOIN metabib.metarecord_source_map m ON (m.source = av.record)
582          GROUP BY 1,2,6;
583
584        IF NOT FOUND THEN
585            RETURN QUERY SELECT ans.depth, ans.id, 0::BIGINT, 0::BIGINT, 0::BIGINT, trans;
586        END IF;
587
588    END LOOP;
589
590    RETURN;
591END;
592$f$ LANGUAGE PLPGSQL;
593
594CREATE OR REPLACE FUNCTION asset.opac_lasso_metarecord_copy_count (i_lasso INT, rid BIGINT) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
595DECLARE
596    ans RECORD;
597    trans INT;
598BEGIN
599    SELECT 1 INTO trans FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = rid;
600
601    FOR ans IN SELECT u.org_unit AS id FROM actor.org_lasso_map AS u WHERE lasso = i_lasso LOOP
602        RETURN QUERY
603        SELECT  -1,
604                ans.id,
605                COUNT( av.id ),
606                SUM( CASE WHEN cp.status IN (0,7,12) THEN 1 ELSE 0 END ),
607                COUNT( av.id ),
608                trans
609          FROM
610                actor.org_unit_descendants(ans.id) d
611                JOIN asset.opac_visible_copies av ON (av.record = rid AND av.circ_lib = d.id)
612                JOIN asset.copy cp ON (cp.id = av.copy_id)
613                JOIN metabib.metarecord_source_map m ON (m.source = av.record)
614          GROUP BY 1,2,6;
615
616        IF NOT FOUND THEN
617            RETURN QUERY SELECT ans.depth, ans.id, 0::BIGINT, 0::BIGINT, 0::BIGINT, trans;
618        END IF;
619
620    END LOOP;   
621               
622    RETURN;     
623END;           
624$f$ LANGUAGE PLPGSQL;
625
626CREATE OR REPLACE FUNCTION asset.staff_ou_metarecord_copy_count (org INT, rid BIGINT) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
627DECLARE         
628    ans RECORD;
629    trans INT;
630BEGIN
631    SELECT 1 INTO trans FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = rid;
632
633    FOR ans IN SELECT u.id, t.depth FROM actor.org_unit_ancestors(org) AS u JOIN actor.org_unit_type t ON (u.ou_type = t.id) LOOP
634        RETURN QUERY
635        SELECT  ans.depth,
636                ans.id,
637                COUNT( cp.id ),
638                SUM( CASE WHEN cp.status IN (0,7,12) THEN 1 ELSE 0 END ),
639                COUNT( cp.id ),
640                trans
641          FROM
642                actor.org_unit_descendants(ans.id) d
643                JOIN asset.copy cp ON (cp.circ_lib = d.id AND NOT cp.deleted)
644                JOIN asset.call_number cn ON (cn.record = rid AND cn.id = cp.call_number AND NOT cn.deleted)
645                JOIN metabib.metarecord_source_map m ON (m.source = cn.record)
646          GROUP BY 1,2,6;
647
648        IF NOT FOUND THEN
649            RETURN QUERY SELECT ans.depth, ans.id, 0::BIGINT, 0::BIGINT, 0::BIGINT, trans;
650        END IF;
651
652    END LOOP;
653
654    RETURN;
655END;
656$f$ LANGUAGE PLPGSQL;
657
658CREATE OR REPLACE FUNCTION asset.staff_lasso_metarecord_copy_count (i_lasso INT, rid BIGINT) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
659DECLARE
660    ans RECORD;
661    trans INT;
662BEGIN
663    SELECT 1 INTO trans FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = rid;
664
665    FOR ans IN SELECT u.org_unit AS id FROM actor.org_lasso_map AS u WHERE lasso = i_lasso LOOP
666        RETURN QUERY
667        SELECT  -1,
668                ans.id,
669                COUNT( cp.id ),
670                SUM( CASE WHEN cp.status IN (0,7,12) THEN 1 ELSE 0 END ),
671                COUNT( cp.id ),
672                trans
673          FROM
674                actor.org_unit_descendants(ans.id) d
675                JOIN asset.copy cp ON (cp.circ_lib = d.id AND NOT cp.deleted)
676                JOIN asset.call_number cn ON (cn.record = rid AND cn.id = cp.call_number AND NOT cn.deleted)
677                JOIN metabib.metarecord_source_map m ON (m.source = cn.record)
678          GROUP BY 1,2,6;
679
680        IF NOT FOUND THEN
681            RETURN QUERY SELECT ans.depth, ans.id, 0::BIGINT, 0::BIGINT, 0::BIGINT, trans;
682        END IF;
683
684    END LOOP;
685
686    RETURN;
687END;
688$f$ LANGUAGE PLPGSQL;
689
690CREATE OR REPLACE FUNCTION asset.metarecord_copy_count ( place INT, rid BIGINT, staff BOOL) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
691BEGIN
692    IF staff IS TRUE THEN
693        IF place > 0 THEN
694            RETURN QUERY SELECT * FROM asset.staff_ou_metarecord_copy_count( place, rid );
695        ELSE
696            RETURN QUERY SELECT * FROM asset.staff_lasso_metarecord_copy_count( -place, rid );
697        END IF;
698    ELSE
699        IF place > 0 THEN
700            RETURN QUERY SELECT * FROM asset.opac_ou_metarecord_copy_count( place, rid );
701        ELSE
702            RETURN QUERY SELECT * FROM asset.opac_lasso_metarecord_copy_count( -place, rid );
703        END IF;
704    END IF;
705
706    RETURN;
707END;
708$f$ LANGUAGE PLPGSQL;
709
710CREATE OR REPLACE FUNCTION asset.autogenerate_placeholder_barcode ( ) RETURNS TRIGGER AS $f$
711BEGIN
712        IF NEW.barcode LIKE '@@%' THEN
713                NEW.barcode := '@@' || NEW.id;
714        END IF;
715        RETURN NEW;
716END;
717$f$ LANGUAGE PLPGSQL;
718
719CREATE TRIGGER autogenerate_placeholder_barcode
720        BEFORE INSERT OR UPDATE ON asset.copy
721        FOR EACH ROW EXECUTE PROCEDURE asset.autogenerate_placeholder_barcode();
722
723CREATE OR REPLACE FUNCTION evergreen.fake_fkey_tgr () RETURNS TRIGGER AS $F$
724DECLARE
725    copy_id BIGINT;
726BEGIN
727    EXECUTE 'SELECT ($1).' || quote_ident(TG_ARGV[0]) INTO copy_id USING NEW;
728    PERFORM * FROM asset.copy WHERE id = copy_id;
729    IF NOT FOUND THEN
730        RAISE EXCEPTION 'Key (%.%=%) does not exist in asset.copy', TG_TABLE_SCHEMA, TG_TABLE_NAME, copy_id;
731    END IF;
732    RETURN NULL;
733END;
734$F$ LANGUAGE PLPGSQL;
735
736COMMIT;
Note: See TracBrowser for help on using the browser.