]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/sql/Pg/002.schema.config.sql
Make retargetting check less lax by including appropriate patron-side test
[working/Evergreen.git] / Open-ILS / src / sql / Pg / 002.schema.config.sql
1 /*
2  * Copyright (C) 2004-2008  Georgia Public Library Service
3  * Copyright (C) 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
18
19
20 DROP SCHEMA IF EXISTS stats CASCADE;
21 DROP SCHEMA IF EXISTS config CASCADE;
22
23 BEGIN;
24 CREATE SCHEMA stats;
25
26 CREATE SCHEMA config;
27 COMMENT ON SCHEMA config IS $$
28 /*
29  * Copyright (C) 2005  Georgia Public Library Service 
30  * Mike Rylander <mrylander@gmail.com>
31  *
32  * The config schema holds static configuration data for the
33  * Open-ILS installation.
34  *
35  * ****
36  *
37  * This program is free software; you can redistribute it and/or
38  * modify it under the terms of the GNU General Public License
39  * as published by the Free Software Foundation; either version 2
40  * of the License, or (at your option) any later version.
41  *
42  * This program is distributed in the hope that it will be useful,
43  * but WITHOUT ANY WARRANTY; without even the implied warranty of
44  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
45  * GNU General Public License for more details.
46  */
47 $$;
48
49 CREATE TABLE config.internal_flag (
50     name    TEXT    PRIMARY KEY,
51     value   TEXT,
52     enabled BOOL    NOT NULL DEFAULT FALSE
53 );
54 INSERT INTO config.internal_flag (name) VALUES ('ingest.metarecord_mapping.skip_on_insert');
55 INSERT INTO config.internal_flag (name) VALUES ('ingest.metarecord_mapping.skip_on_update');
56 INSERT INTO config.internal_flag (name) VALUES ('ingest.reingest.force_on_same_marc');
57 INSERT INTO config.internal_flag (name) VALUES ('ingest.disable_located_uri');
58 INSERT INTO config.internal_flag (name) VALUES ('ingest.disable_metabib_full_rec');
59 INSERT INTO config.internal_flag (name) VALUES ('ingest.disable_metabib_rec_descriptor');
60 INSERT INTO config.internal_flag (name) VALUES ('ingest.disable_metabib_field_entry');
61 INSERT INTO config.internal_flag (name) VALUES ('ingest.assume_inserts_only');
62
63 CREATE TABLE config.global_flag (
64     label   TEXT    NOT NULL
65 ) INHERITS (config.internal_flag);
66 ALTER TABLE config.global_flag ADD PRIMARY KEY (name);
67
68 CREATE TABLE config.upgrade_log (
69     version         TEXT    PRIMARY KEY,
70     install_date    TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
71 );
72
73 INSERT INTO config.upgrade_log (version) VALUES ('0431'); -- miker
74
75 CREATE TABLE config.bib_source (
76         id              SERIAL  PRIMARY KEY,
77         quality         INT     CHECK ( quality BETWEEN 0 AND 100 ),
78         source          TEXT    NOT NULL UNIQUE,
79         transcendant    BOOL    NOT NULL DEFAULT FALSE
80 );
81 COMMENT ON TABLE config.bib_source IS $$
82 /*
83  * Copyright (C) 2005  Georgia Public Library Service 
84  * Mike Rylander <mrylander@gmail.com>
85  *
86  * Valid sources of MARC records
87  *
88  * This is table is used to set up the relative "quality" of each
89  * MARC source, such as OCLC.
90  *
91  * ****
92  *
93  * This program is free software; you can redistribute it and/or
94  * modify it under the terms of the GNU General Public License
95  * as published by the Free Software Foundation; either version 2
96  * of the License, or (at your option) any later version.
97  *
98  * This program is distributed in the hope that it will be useful,
99  * but WITHOUT ANY WARRANTY; without even the implied warranty of
100  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
101  * GNU General Public License for more details.
102  */
103 $$;
104
105 CREATE TABLE config.standing (
106         id              SERIAL  PRIMARY KEY,
107         value           TEXT    NOT NULL UNIQUE
108 );
109 COMMENT ON TABLE config.standing IS $$
110 /*
111  * Copyright (C) 2005  Georgia Public Library Service 
112  * Mike Rylander <mrylander@gmail.com>
113  *
114  * Patron Standings
115  *
116  * This table contains the values that can be applied to a patron
117  * by a staff member.  These values should not be changed, other
118  * than for translation, as the ID column is currently a "magic
119  * number" in the source. :(
120  *
121  * ****
122  *
123  * This program is free software; you can redistribute it and/or
124  * modify it under the terms of the GNU General Public License
125  * as published by the Free Software Foundation; either version 2
126  * of the License, or (at your option) any later version.
127  *
128  * This program is distributed in the hope that it will be useful,
129  * but WITHOUT ANY WARRANTY; without even the implied warranty of
130  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
131  * GNU General Public License for more details.
132  */
133 $$;
134
135 CREATE TABLE config.standing_penalty (
136         id                      SERIAL  PRIMARY KEY,
137         name            TEXT    NOT NULL UNIQUE,
138         label           TEXT    NOT NULL,
139         block_list      TEXT,
140         org_depth       INTEGER
141 );
142 INSERT INTO config.standing_penalty (id,name,label,block_list)
143         VALUES (1,'PATRON_EXCEEDS_FINES','Patron exceeds fine threshold','CIRC|HOLD|RENEW');
144 INSERT INTO config.standing_penalty (id,name,label,block_list)
145         VALUES (2,'PATRON_EXCEEDS_OVERDUE_COUNT','Patron exceeds max overdue item threshold','CIRC|HOLD|RENEW');
146 INSERT INTO config.standing_penalty (id,name,label,block_list)
147         VALUES (3,'PATRON_EXCEEDS_CHECKOUT_COUNT','Patron exceeds max checked out item threshold','CIRC');
148 INSERT INTO config.standing_penalty (id,name,label,block_list)
149         VALUES (4,'PATRON_EXCEEDS_COLLECTIONS_WARNING','Patron exceeds pre-collections warning fine threshold','CIRC|HOLD|RENEW');
150
151 INSERT INTO config.standing_penalty (id,name,label) VALUES (20,'ALERT_NOTE','Alerting Note, no blocks');
152 INSERT INTO config.standing_penalty (id,name,label) VALUES (21,'SILENT_NOTE','Note, no blocks');
153 INSERT INTO config.standing_penalty (id,name,label,block_list) VALUES (22,'STAFF_C','Alerting block on Circ','CIRC');
154 INSERT INTO config.standing_penalty (id,name,label,block_list) VALUES (23,'STAFF_CH','Alerting block on Circ and Hold','CIRC|HOLD');
155 INSERT INTO config.standing_penalty (id,name,label,block_list) VALUES (24,'STAFF_CR','Alerting block on Circ and Renew','CIRC|RENEW');
156 INSERT INTO config.standing_penalty (id,name,label,block_list) VALUES (25,'STAFF_CHR','Alerting block on Circ, Hold and Renew','CIRC|HOLD|RENEW');
157 INSERT INTO config.standing_penalty (id,name,label,block_list) VALUES (26,'STAFF_HR','Alerting block on Hold and Renew','HOLD|RENEW');
158 INSERT INTO config.standing_penalty (id,name,label,block_list) VALUES (27,'STAFF_H','Alerting block on Hold','HOLD');
159 INSERT INTO config.standing_penalty (id,name,label,block_list) VALUES (28,'STAFF_R','Alerting block on Renew','RENEW');
160 INSERT INTO config.standing_penalty (id,name,label) VALUES (29,'INVALID_PATRON_ADDRESS','Patron has an invalid address');
161 INSERT INTO config.standing_penalty (id,name,label) VALUES (30,'PATRON_IN_COLLECTIONS','Patron has been referred to a collections agency');
162
163 SELECT SETVAL('config.standing_penalty_id_seq', 100);
164
165 CREATE TABLE config.xml_transform (
166         name            TEXT    PRIMARY KEY,
167         namespace_uri   TEXT    NOT NULL,
168         prefix          TEXT    NOT NULL,
169         xslt            TEXT    NOT NULL
170 );
171
172 CREATE TABLE config.biblio_fingerprint (
173         id                      SERIAL  PRIMARY KEY,
174         name            TEXT    NOT NULL, 
175         xpath           TEXT    NOT NULL,
176     first_word  BOOL    NOT NULL DEFAULT FALSE,
177         format          TEXT    NOT NULL DEFAULT 'marcxml'
178 );
179
180 INSERT INTO config.biblio_fingerprint (name, xpath, format)
181     VALUES (
182         'Title',
183         '//marc:datafield[@tag="700"]/marc:subfield[@code="t"]|' ||
184             '//marc:datafield[@tag="240"]/marc:subfield[@code="a"]|' ||
185             '//marc:datafield[@tag="242"]/marc:subfield[@code="a"]|' ||
186             '//marc:datafield[@tag="246"]/marc:subfield[@code="a"]|' ||
187             '//marc:datafield[@tag="245"]/marc:subfield[@code="a"]',
188         'marcxml'
189     );
190
191 INSERT INTO config.biblio_fingerprint (name, xpath, format, first_word)
192     VALUES (
193         'Author',
194         '//marc:datafield[@tag="700" and ./*[@code="t"]]/marc:subfield[@code="a"]|'
195             '//marc:datafield[@tag="100"]/marc:subfield[@code="a"]|'
196             '//marc:datafield[@tag="110"]/marc:subfield[@code="a"]|'
197             '//marc:datafield[@tag="111"]/marc:subfield[@code="a"]|'
198             '//marc:datafield[@tag="260"]/marc:subfield[@code="b"]',
199         'marcxml',
200         TRUE
201     );
202
203 CREATE TABLE config.metabib_class (
204     name    TEXT    PRIMARY KEY,
205     label   TEXT    NOT NULL UNIQUE
206 );
207
208 CREATE TABLE config.metabib_field (
209         id              SERIAL  PRIMARY KEY,
210         field_class     TEXT    NOT NULL REFERENCES config.metabib_class (name),
211         name            TEXT    NOT NULL,
212         label           TEXT    NOT NULL,
213         xpath           TEXT    NOT NULL,
214         weight          INT     NOT NULL DEFAULT 1,
215         format          TEXT    NOT NULL REFERENCES config.xml_transform (name) DEFAULT 'mods33',
216         search_field    BOOL    NOT NULL DEFAULT TRUE,
217         facet_field     BOOL    NOT NULL DEFAULT FALSE,
218     facet_xpath TEXT
219 );
220 COMMENT ON TABLE config.metabib_field IS $$
221 /*
222  * Copyright (C) 2005  Georgia Public Library Service 
223  * Mike Rylander <mrylander@gmail.com>
224  *
225  * XPath used for record indexing ingest
226  *
227  * This table contains the XPath used to chop up MODS into its
228  * indexable parts.  Each XPath entry is named and assigned to
229  * a "class" of either title, subject, author, keyword or series.
230  * 
231  *
232  * ****
233  *
234  * This program is free software; you can redistribute it and/or
235  * modify it under the terms of the GNU General Public License
236  * as published by the Free Software Foundation; either version 2
237  * of the License, or (at your option) any later version.
238  *
239  * This program is distributed in the hope that it will be useful,
240  * but WITHOUT ANY WARRANTY; without even the implied warranty of
241  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
242  * GNU General Public License for more details.
243  */
244 $$;
245
246 CREATE UNIQUE INDEX config_metabib_field_class_name_idx ON config.metabib_field (field_class, name);
247
248 CREATE TABLE config.metabib_search_alias (
249     alias       TEXT    PRIMARY KEY,
250     field_class TEXT    NOT NULL REFERENCES config.metabib_class (name),
251     field       INT     REFERENCES config.metabib_field (id)
252 );
253
254 CREATE TABLE config.non_cataloged_type (
255         id              SERIAL          PRIMARY KEY,
256         owning_lib      INT             NOT NULL, -- REFERENCES actor.org_unit (id),
257         name            TEXT            NOT NULL,
258         circ_duration   INTERVAL        NOT NULL DEFAULT '14 days'::INTERVAL,
259         in_house        BOOL            NOT NULL DEFAULT FALSE,
260         CONSTRAINT noncat_once_per_lib UNIQUE (owning_lib,name)
261 );
262 COMMENT ON TABLE config.non_cataloged_type IS $$
263 /*
264  * Copyright (C) 2005  Georgia Public Library Service 
265  * Mike Rylander <mrylander@gmail.com>
266  *
267  * Types of valid non-cataloged items.
268  *
269  *
270  * ****
271  *
272  * This program is free software; you can redistribute it and/or
273  * modify it under the terms of the GNU General Public License
274  * as published by the Free Software Foundation; either version 2
275  * of the License, or (at your option) any later version.
276  *
277  * This program is distributed in the hope that it will be useful,
278  * but WITHOUT ANY WARRANTY; without even the implied warranty of
279  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
280  * GNU General Public License for more details.
281  */
282 $$;
283
284 CREATE TABLE config.identification_type (
285         id              SERIAL  PRIMARY KEY,
286         name            TEXT    NOT NULL UNIQUE
287 );
288 COMMENT ON TABLE config.identification_type IS $$
289 /*
290  * Copyright (C) 2005  Georgia Public Library Service 
291  * Mike Rylander <mrylander@gmail.com>
292  *
293  * Types of valid patron identification.
294  *
295  * Each patron must display at least one valid form of identification
296  * in order to get a library card.  This table lists those forms.
297  * 
298  *
299  * ****
300  *
301  * This program is free software; you can redistribute it and/or
302  * modify it under the terms of the GNU General Public License
303  * as published by the Free Software Foundation; either version 2
304  * of the License, or (at your option) any later version.
305  *
306  * This program is distributed in the hope that it will be useful,
307  * but WITHOUT ANY WARRANTY; without even the implied warranty of
308  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
309  * GNU General Public License for more details.
310  */
311 $$;
312
313 CREATE TABLE config.rule_circ_duration (
314         id              SERIAL          PRIMARY KEY,
315         name            TEXT            NOT NULL UNIQUE CHECK ( name ~ E'^\\w+$' ),
316         extended        INTERVAL        NOT NULL,
317         normal          INTERVAL        NOT NULL,
318         shrt            INTERVAL        NOT NULL,
319         max_renewals    INT             NOT NULL
320 );
321 COMMENT ON TABLE config.rule_circ_duration IS $$
322 /*
323  * Copyright (C) 2005  Georgia Public Library Service 
324  * Mike Rylander <mrylander@gmail.com>
325  *
326  * Circulation Duration rules
327  *
328  * Each circulation is given a duration based on one of these rules.
329  * 
330  *
331  * ****
332  *
333  * This program is free software; you can redistribute it and/or
334  * modify it under the terms of the GNU General Public License
335  * as published by the Free Software Foundation; either version 2
336  * of the License, or (at your option) any later version.
337  *
338  * This program is distributed in the hope that it will be useful,
339  * but WITHOUT ANY WARRANTY; without even the implied warranty of
340  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
341  * GNU General Public License for more details.
342  */
343 $$;
344
345 CREATE TABLE config.rule_max_fine (
346     id          SERIAL          PRIMARY KEY,
347     name        TEXT            NOT NULL UNIQUE CHECK ( name ~ E'^\\w+$' ),
348     amount      NUMERIC(6,2)    NOT NULL,
349     is_percent  BOOL            NOT NULL DEFAULT FALSE
350 );
351 COMMENT ON TABLE config.rule_max_fine IS $$
352 /*
353  * Copyright (C) 2005  Georgia Public Library Service 
354  * Mike Rylander <mrylander@gmail.com>
355  *
356  * Circulation Max Fine rules
357  *
358  * Each circulation is given a maximum fine based on one of
359  * these rules.
360  * 
361  *
362  * ****
363  *
364  * This program is free software; you can redistribute it and/or
365  * modify it under the terms of the GNU General Public License
366  * as published by the Free Software Foundation; either version 2
367  * of the License, or (at your option) any later version.
368  *
369  * This program is distributed in the hope that it will be useful,
370  * but WITHOUT ANY WARRANTY; without even the implied warranty of
371  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
372  * GNU General Public License for more details.
373  */
374 $$;
375
376 CREATE TABLE config.rule_recurring_fine (
377         id                      SERIAL          PRIMARY KEY,
378         name                    TEXT            NOT NULL UNIQUE CHECK ( name ~ E'^\\w+$' ),
379         high                    NUMERIC(6,2)    NOT NULL,
380         normal                  NUMERIC(6,2)    NOT NULL,
381         low                     NUMERIC(6,2)    NOT NULL,
382         recurrence_interval     INTERVAL        NOT NULL DEFAULT '1 day'::INTERVAL
383 );
384 COMMENT ON TABLE config.rule_recurring_fine IS $$
385 /*
386  * Copyright (C) 2005  Georgia Public Library Service 
387  * Mike Rylander <mrylander@gmail.com>
388  *
389  * Circulation Recurring Fine rules
390  *
391  * Each circulation is given a recurring fine amount based on one of
392  * these rules.  The recurrence_interval should not be any shorter
393  * than the interval between runs of the fine_processor.pl script
394  * (which is run from CRON), or you could miss fines.
395  * 
396  *
397  * ****
398  *
399  * This program is free software; you can redistribute it and/or
400  * modify it under the terms of the GNU General Public License
401  * as published by the Free Software Foundation; either version 2
402  * of the License, or (at your option) any later version.
403  *
404  * This program is distributed in the hope that it will be useful,
405  * but WITHOUT ANY WARRANTY; without even the implied warranty of
406  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
407  * GNU General Public License for more details.
408  */
409 $$;
410
411
412 CREATE TABLE config.rule_age_hold_protect (
413         id      SERIAL          PRIMARY KEY,
414         name    TEXT            NOT NULL UNIQUE CHECK ( name ~ E'^\\w+$' ),
415         age     INTERVAL        NOT NULL,
416         prox    INT             NOT NULL
417 );
418 COMMENT ON TABLE config.rule_age_hold_protect IS $$
419 /*
420  * Copyright (C) 2005  Georgia Public Library Service 
421  * Mike Rylander <mrylander@gmail.com>
422  *
423  * Hold Item Age Protection rules
424  *
425  * A hold request can only capture new(ish) items when they are
426  * within a particular proximity of the home_ou of the requesting
427  * user.  The proximity ('prox' column) is calculated by counting
428  * the number of tree edges between the user's home_ou and the owning_lib
429  * of the copy that could fulfill the hold.
430  * 
431  *
432  * ****
433  *
434  * This program is free software; you can redistribute it and/or
435  * modify it under the terms of the GNU General Public License
436  * as published by the Free Software Foundation; either version 2
437  * of the License, or (at your option) any later version.
438  *
439  * This program is distributed in the hope that it will be useful,
440  * but WITHOUT ANY WARRANTY; without even the implied warranty of
441  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
442  * GNU General Public License for more details.
443  */
444 $$;
445
446 CREATE TABLE config.copy_status (
447         id              SERIAL  PRIMARY KEY,
448         name            TEXT    NOT NULL UNIQUE,
449         holdable        BOOL    NOT NULL DEFAULT FALSE,
450         opac_visible    BOOL    NOT NULL DEFAULT FALSE
451 );
452 COMMENT ON TABLE config.copy_status IS $$
453 /*
454  * Copyright (C) 2005  Georgia Public Library Service 
455  * Mike Rylander <mrylander@gmail.com>
456  *
457  * Copy Statuses
458  *
459  * The available copy statuses, and whether a copy in that
460  * status is available for hold request capture.  0 (zero) is
461  * the only special number in this set, meaning that the item
462  * is available for immediate checkout, and is counted as available
463  * in the OPAC.
464  *
465  * Statuses with an ID below 100 are not removable, and have special
466  * meaning in the code.  Do not change them except to translate the
467  * textual name.
468  *
469  * You may add and remove statuses above 100, and these can be used
470  * to remove items from normal circulation without affecting the rest
471  * of the copy's values or its location.
472  *
473  * ****
474  *
475  * This program is free software; you can redistribute it and/or
476  * modify it under the terms of the GNU General Public License
477  * as published by the Free Software Foundation; either version 2
478  * of the License, or (at your option) any later version.
479  *
480  * This program is distributed in the hope that it will be useful,
481  * but WITHOUT ANY WARRANTY; without even the implied warranty of
482  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
483  * GNU General Public License for more details.
484  */
485 $$;
486
487 CREATE TABLE config.net_access_level (
488         id      SERIAL          PRIMARY KEY,
489         name    TEXT            NOT NULL UNIQUE
490 );
491 COMMENT ON TABLE config.net_access_level IS $$
492 /*
493  * Copyright (C) 2005  Georgia Public Library Service 
494  * Mike Rylander <mrylander@gmail.com>
495  *
496  * Patron Network Access level
497  *
498  * This will be used to inform the in-library firewall of how much
499  * internet access the using patron should be allowed.
500  *
501  * ****
502  *
503  * This program is free software; you can redistribute it and/or
504  * modify it under the terms of the GNU General Public License
505  * as published by the Free Software Foundation; either version 2
506  * of the License, or (at your option) any later version.
507  *
508  * This program is distributed in the hope that it will be useful,
509  * but WITHOUT ANY WARRANTY; without even the implied warranty of
510  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
511  * GNU General Public License for more details.
512  */
513 $$;
514
515
516 CREATE TABLE config.remote_account (
517     id          SERIAL  PRIMARY KEY,
518     label       TEXT    NOT NULL,
519     host        TEXT    NOT NULL,   -- name or IP, :port optional
520     username    TEXT,               -- optional, since we could default to $USER
521     password    TEXT,               -- optional, since we could use SSH keys, or anonymous login.
522     account     TEXT,               -- aka profile or FTP "account" command
523     path        TEXT,               -- aka directory
524     owner       INT     NOT NULL,   -- REFERENCES actor.org_unit (id) DEFERRABLE INITIALLY DEFERRED,
525     last_activity TIMESTAMP WITH TIME ZONE
526 );
527
528 CREATE TABLE config.audience_map (
529         code            TEXT    PRIMARY KEY,
530         value           TEXT    NOT NULL,
531         description     TEXT
532 );
533
534 CREATE TABLE config.lit_form_map (
535         code            TEXT    PRIMARY KEY,
536         value           TEXT    NOT NULL,
537         description     TEXT
538 );
539
540 CREATE TABLE config.language_map (
541         code    TEXT    PRIMARY KEY,
542         value   TEXT    NOT NULL
543 );
544
545 CREATE TABLE config.item_form_map (
546         code    TEXT    PRIMARY KEY,
547         value   TEXT    NOT NULL
548 );
549
550 CREATE TABLE config.item_type_map (
551         code    TEXT    PRIMARY KEY,
552         value   TEXT    NOT NULL
553 );
554
555 CREATE TABLE config.bib_level_map (
556         code    TEXT    PRIMARY KEY,
557         value   TEXT    NOT NULL
558 );
559
560 CREATE TABLE config.marc21_rec_type_map (
561     code        TEXT    PRIMARY KEY,
562     type_val    TEXT    NOT NULL,
563     blvl_val    TEXT    NOT NULL
564 );
565
566 CREATE TABLE config.marc21_ff_pos_map (
567     id          SERIAL  PRIMARY KEY,
568     fixed_field TEXT    NOT NULL,
569     tag         TEXT    NOT NULL,
570     rec_type    TEXT    NOT NULL,
571     start_pos   INT     NOT NULL,
572     length      INT     NOT NULL,
573     default_val TEXT    NOT NULL DEFAULT ' '
574 );
575
576 CREATE TABLE config.marc21_physical_characteristic_type_map (
577     ptype_key   TEXT    PRIMARY KEY,
578     label       TEXT    NOT NULL -- I18N
579 );
580
581 CREATE TABLE config.marc21_physical_characteristic_subfield_map (
582     id          SERIAL  PRIMARY KEY,
583     ptype_key   TEXT    NOT NULL REFERENCES config.marc21_physical_characteristic_type_map (ptype_key) ON DELETE CASCADE ON UPDATE CASCADE,
584     subfield    TEXT    NOT NULL,
585     start_pos   INT     NOT NULL,
586     length      INT     NOT NULL,
587     label       TEXT    NOT NULL -- I18N
588 );
589
590 CREATE TABLE config.marc21_physical_characteristic_value_map (
591     id              SERIAL  PRIMARY KEY,
592     value           TEXT    NOT NULL,
593     ptype_subfield  INT     NOT NULL REFERENCES config.marc21_physical_characteristic_subfield_map (id),
594     label           TEXT    NOT NULL -- I18N
595 );
596
597
598 CREATE TABLE config.z3950_source (
599     name                TEXT    PRIMARY KEY,
600     label               TEXT    NOT NULL UNIQUE,
601     host                TEXT    NOT NULL,
602     port                INT     NOT NULL,
603     db                  TEXT    NOT NULL,
604     record_format       TEXT    NOT NULL DEFAULT 'FI',
605     transmission_format TEXT    NOT NULL DEFAULT 'usmarc',
606     auth                BOOL    NOT NULL DEFAULT TRUE
607 );
608
609 COMMENT ON TABLE config.z3950_source IS $$
610 Z39.50 Sources
611
612 Each row in this table represents a database searchable via Z39.50.
613 $$;
614
615 COMMENT ON COLUMN config.z3950_source.record_format IS $$
616 Z39.50 element set.
617 $$;
618
619 COMMENT ON COLUMN config.z3950_source.transmission_format IS $$
620 Z39.50 preferred record syntax..
621 $$;
622
623
624 CREATE TABLE config.z3950_attr (
625     id          SERIAL  PRIMARY KEY,
626     source      TEXT    NOT NULL REFERENCES config.z3950_source (name) DEFERRABLE INITIALLY DEFERRED,
627     name        TEXT    NOT NULL,
628     label       TEXT    NOT NULL,
629     code        INT     NOT NULL,
630     format      INT     NOT NULL,
631     truncation  INT     NOT NULL DEFAULT 0,
632     CONSTRAINT z_code_format_once_per_source UNIQUE (code,format,source)
633 );
634
635 CREATE TABLE config.i18n_locale (
636     code        TEXT    PRIMARY KEY,
637     marc_code   TEXT    NOT NULL REFERENCES config.language_map (code) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
638     name        TEXT    UNIQUE NOT NULL,
639     description TEXT
640 );
641
642 CREATE TABLE config.i18n_core (
643     id              BIGSERIAL   PRIMARY KEY,
644     fq_field        TEXT        NOT NULL,
645     identity_value  TEXT        NOT NULL,
646     translation     TEXT        NOT NULL    REFERENCES config.i18n_locale (code) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
647     string          TEXT        NOT NULL
648 );
649
650 CREATE UNIQUE INDEX i18n_identity ON config.i18n_core (fq_field,identity_value,translation);
651
652 CREATE OR REPLACE FUNCTION oils_i18n_update_apply(old_ident TEXT, new_ident TEXT, hint TEXT) RETURNS VOID AS $_$
653 BEGIN
654
655     EXECUTE $$
656         UPDATE  config.i18n_core
657           SET   identity_value = $$ || quote_literal(new_ident) || $$ 
658           WHERE fq_field LIKE '$$ || hint || $$.%' 
659                 AND identity_value = $$ || quote_literal(old_ident) || $$::TEXT;$$;
660
661     RETURN;
662
663 END;
664 $_$ LANGUAGE PLPGSQL;
665
666 CREATE OR REPLACE FUNCTION oils_i18n_id_tracking(/* hint */) RETURNS TRIGGER AS $_$
667 BEGIN
668     PERFORM oils_i18n_update_apply( OLD.id::TEXT, NEW.id::TEXT, TG_ARGV[0]::TEXT );
669     RETURN NEW;
670 END;
671 $_$ LANGUAGE PLPGSQL;
672
673 CREATE OR REPLACE FUNCTION oils_i18n_code_tracking(/* hint */) RETURNS TRIGGER AS $_$
674 BEGIN
675     PERFORM oils_i18n_update_apply( OLD.code::TEXT, NEW.code::TEXT, TG_ARGV[0]::TEXT );
676     RETURN NEW;
677 END;
678 $_$ LANGUAGE PLPGSQL;
679
680 CREATE TABLE config.billing_type (
681     id              SERIAL  PRIMARY KEY,
682     name            TEXT    NOT NULL,
683     owner           INT     NOT NULL, -- REFERENCES actor.org_unit (id)
684     default_price   NUMERIC(6,2),
685     CONSTRAINT billing_type_once_per_lib UNIQUE (name, owner)
686 );
687
688 CREATE TABLE config.settings_group (
689     name    TEXT PRIMARY KEY,
690     label   TEXT UNIQUE NOT NULL -- I18N
691 );
692
693 CREATE TABLE config.org_unit_setting_type (
694     name            TEXT    PRIMARY KEY,
695     label           TEXT    UNIQUE NOT NULL,
696     grp             TEXT    REFERENCES config.settings_group (name),
697     description     TEXT,
698     datatype        TEXT    NOT NULL DEFAULT 'string',
699     fm_class        TEXT,
700     view_perm       INT,
701     update_perm     INT,
702     --
703     -- define valid datatypes
704     --
705     CONSTRAINT coust_valid_datatype CHECK ( datatype IN
706     ( 'bool', 'integer', 'float', 'currency', 'interval',
707       'date', 'string', 'object', 'array', 'link' ) ),
708     --
709     -- fm_class is meaningful only for 'link' datatype
710     --
711     CONSTRAINT coust_no_empty_link CHECK
712     ( ( datatype =  'link' AND fm_class IS NOT NULL ) OR
713       ( datatype <> 'link' AND fm_class IS NULL ) )
714 );
715
716 CREATE TABLE config.usr_setting_type (
717
718     name TEXT PRIMARY KEY,
719     opac_visible BOOL NOT NULL DEFAULT FALSE,
720     label TEXT UNIQUE NOT NULL,
721     description TEXT,
722     grp             TEXT    REFERENCES config.settings_group (name),
723     datatype TEXT NOT NULL DEFAULT 'string',
724     fm_class TEXT,
725
726     --
727     -- define valid datatypes
728     --
729     CONSTRAINT coust_valid_datatype CHECK ( datatype IN
730     ( 'bool', 'integer', 'float', 'currency', 'interval',
731         'date', 'string', 'object', 'array', 'link' ) ),
732
733     --
734     -- fm_class is meaningful only for 'link' datatype
735     --
736     CONSTRAINT coust_no_empty_link CHECK
737     ( ( datatype = 'link' AND fm_class IS NOT NULL ) OR
738         ( datatype <> 'link' AND fm_class IS NULL ) )
739
740 );
741
742 -- Some handy functions, based on existing ones, to provide optional ingest normalization
743
744 CREATE OR REPLACE FUNCTION public.left_trunc( TEXT, INT ) RETURNS TEXT AS $func$
745         SELECT SUBSTRING($1,$2);
746 $func$ LANGUAGE SQL STRICT IMMUTABLE;
747
748 CREATE OR REPLACE FUNCTION public.right_trunc( TEXT, INT ) RETURNS TEXT AS $func$
749         SELECT SUBSTRING($1,1,$2);
750 $func$ LANGUAGE SQL STRICT IMMUTABLE;
751
752 CREATE OR REPLACE FUNCTION public.split_date_range( TEXT ) RETURNS TEXT AS $func$
753         SELECT REGEXP_REPLACE( $1, E'(\\d{4})-(\\d{4})', E'\\1 \\2', 'g' );
754 $func$ LANGUAGE SQL STRICT IMMUTABLE;
755
756 CREATE OR REPLACE FUNCTION public.translate_isbn1013( TEXT ) RETURNS TEXT AS $func$
757     use Business::ISBN;
758     use strict;
759     use warnings;
760
761     # For each ISBN found in a single string containing a set of ISBNs:
762     #   * Normalize an incoming ISBN to have the correct checksum and no hyphens
763     #   * Convert an incoming ISBN10 or ISBN13 to its counterpart and return
764
765     my $input = shift;
766     my $output = '';
767
768     foreach my $word (split(/\s/, $input)) {
769         my $isbn = Business::ISBN->new($word);
770
771         # First check the checksum; if it is not valid, fix it and add the original
772         # bad-checksum ISBN to the output
773         if ($isbn && $isbn->is_valid_checksum() == Business::ISBN::BAD_CHECKSUM) {
774             $output .= $isbn->isbn() . " ";
775             $isbn->fix_checksum();
776         }
777
778         # If we now have a valid ISBN, convert it to its counterpart ISBN10/ISBN13
779         # and add the normalized original ISBN to the output
780         if ($isbn && $isbn->is_valid()) {
781             my $isbn_xlated = ($isbn->type eq "ISBN13") ? $isbn->as_isbn10 : $isbn->as_isbn13;
782             $output .= $isbn->isbn . " ";
783
784             # If we successfully converted the ISBN to its counterpart, add the
785             # converted ISBN to the output as well
786             $output .= ($isbn_xlated->isbn . " ") if ($isbn_xlated);
787         }
788     }
789     return $output if $output;
790
791     # If there were no valid ISBNs, just return the raw input
792     return $input;
793 $func$ LANGUAGE PLPERLU;
794
795 COMMENT ON FUNCTION public.translate_isbn1013(TEXT) IS $$
796 /*
797  * Copyright (C) 2010 Merrimack Valley Library Consortium
798  * Jason Stephenson <jstephenson@mvlc.org>
799  * Copyright (C) 2010 Laurentian University
800  * Dan Scott <dscott@laurentian.ca>
801  *
802  * The translate_isbn1013 function takes an input ISBN and returns the
803  * following in a single space-delimited string if the input ISBN is valid:
804  *   - The normalized input ISBN (hyphens stripped)
805  *   - The normalized input ISBN with a fixed checksum if the checksum was bad
806  *   - The ISBN converted to its ISBN10 or ISBN13 counterpart, if possible
807  */
808 $$;
809
810 -- And ... a table in which to register them
811
812 CREATE TABLE config.index_normalizer (
813         id              SERIAL  PRIMARY KEY,
814         name            TEXT    UNIQUE NOT NULL,
815         description     TEXT,
816         func            TEXT    NOT NULL,
817         param_count     INT     NOT NULL DEFAULT 0
818 );
819
820 CREATE TABLE config.metabib_field_index_norm_map (
821         id      SERIAL  PRIMARY KEY,
822         field   INT     NOT NULL REFERENCES config.metabib_field (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
823         norm    INT     NOT NULL REFERENCES config.index_normalizer (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
824         params  TEXT,
825         pos     INT     NOT NULL DEFAULT 0
826 );
827
828 CREATE OR REPLACE FUNCTION oils_tsearch2 () RETURNS TRIGGER AS $$
829 DECLARE
830     normalizer      RECORD;
831     value           TEXT := '';
832 BEGIN
833
834     value := NEW.value;
835
836     IF TG_TABLE_NAME::TEXT ~ 'field_entry$' THEN
837         FOR normalizer IN
838             SELECT  n.func AS func,
839                     n.param_count AS param_count,
840                     m.params AS params
841               FROM  config.index_normalizer n
842                     JOIN config.metabib_field_index_norm_map m ON (m.norm = n.id)
843               WHERE field = NEW.field AND m.pos < 0
844               ORDER BY m.pos LOOP
845                 EXECUTE 'SELECT ' || normalizer.func || '(' ||
846                     quote_literal( value ) ||
847                     CASE
848                         WHEN normalizer.param_count > 0
849                             THEN ',' || REPLACE(REPLACE(BTRIM(normalizer.params,'[]'),E'\'',E'\\\''),E'"',E'\'')
850                             ELSE ''
851                         END ||
852                     ')' INTO value;
853
854         END LOOP;
855
856         NEW.value := value;
857     END IF;
858
859     IF NEW.index_vector = ''::tsvector THEN
860         RETURN NEW;
861     END IF;
862
863     IF TG_TABLE_NAME::TEXT ~ 'field_entry$' THEN
864         FOR normalizer IN
865             SELECT  n.func AS func,
866                     n.param_count AS param_count,
867                     m.params AS params
868               FROM  config.index_normalizer n
869                     JOIN config.metabib_field_index_norm_map m ON (m.norm = n.id)
870               WHERE field = NEW.field AND m.pos >= 0
871               ORDER BY m.pos LOOP
872                 EXECUTE 'SELECT ' || normalizer.func || '(' ||
873                     quote_literal( value ) ||
874                     CASE
875                         WHEN normalizer.param_count > 0
876                             THEN ',' || REPLACE(REPLACE(BTRIM(normalizer.params,'[]'),E'\'',E'\\\''),E'"',E'\'')
877                             ELSE ''
878                         END ||
879                     ')' INTO value;
880
881         END LOOP;
882     END IF;
883
884     IF REGEXP_REPLACE(VERSION(),E'^.+?(\\d+\\.\\d+).*?$',E'\\1')::FLOAT > 8.2 THEN
885         NEW.index_vector = to_tsvector((TG_ARGV[0])::regconfig, value);
886     ELSE
887         NEW.index_vector = to_tsvector(TG_ARGV[0], value);
888     END IF;
889
890     RETURN NEW;
891 END;
892 $$ LANGUAGE PLPGSQL;
893
894 COMMIT;