1 -- Script to create the query schema and the tables therein
5 DROP SCHEMA IF EXISTS query CASCADE;
7 COMMENT ON SCHEMA actor IS $$
9 * Copyright (C) 2009 Equinox Software, Inc. / Georgia Public Library Service
10 * Scott McKellar <scott@esilibrary.com>
14 * Contains tables designed to represent user-defined queries for
15 * reports and the like.
19 * This program is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU General Public License
21 * as published by the Free Software Foundation; either version 2
22 * of the License, or (at your option) any later version.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
31 CREATE TABLE query.stored_query (
32 id SERIAL PRIMARY KEY,
33 type TEXT NOT NULL CONSTRAINT query_type CHECK
34 ( type IN ( 'SELECT', 'UNION', 'INTERSECT', 'EXCEPT' ) ),
35 use_all BOOLEAN NOT NULL DEFAULT FALSE,
36 use_distinct BOOLEAN NOT NULL DEFAULT FALSE,
37 from_clause INT, --REFERENCES query.from_clause
38 --DEFERRABLE INITIALLY DEFERRED,
39 where_clause INT, --REFERENCES query.expression
40 --DEFERRABLE INITIALLY DEFERRED,
41 having_clause INT --REFERENCES query.expression
42 --DEFERRABLE INITIALLY DEFERRED
45 -- (Foreign keys to be defined later after other tables are created)
47 CREATE TABLE query.query_sequence (
48 id SERIAL PRIMARY KEY,
49 parent_query INT NOT NULL
50 REFERENCES query.stored_query
52 DEFERRABLE INITIALLY DEFERRED,
54 child_query INT NOT NULL
55 REFERENCES query.stored_query
57 DEFERRABLE INITIALLY DEFERRED,
58 CONSTRAINT query_query_seq UNIQUE( parent_query, seq_no )
61 CREATE TABLE query.datatype (
62 id SERIAL PRIMARY KEY,
63 datatype_name TEXT NOT NULL UNIQUE,
64 is_numeric BOOL NOT NULL DEFAULT FALSE,
65 is_composite BOOL NOT NULL DEFAULT FALSE,
66 CONSTRAINT qdt_comp_not_num CHECK
67 ( is_numeric IS FALSE OR is_composite IS FALSE )
70 CREATE TABLE query.subfield (
71 id SERIAL PRIMARY KEY,
72 composite_type INT NOT NULL
73 REFERENCES query.datatype(id)
75 DEFERRABLE INITIALLY DEFERRED,
77 CONSTRAINT qsf_pos_seq_no
79 subfield_type INT NOT NULL
80 REFERENCES query.datatype(id)
81 DEFERRABLE INITIALLY DEFERRED,
82 CONSTRAINT qsf_datatype_seq_no UNIQUE (composite_type, seq_no)
85 CREATE TABLE query.function_sig (
86 id SERIAL PRIMARY KEY,
87 function_name TEXT NOT NULL,
88 return_type INT REFERENCES query.datatype(id)
89 DEFERRABLE INITIALLY DEFERRED,
90 is_aggregate BOOL NOT NULL DEFAULT FALSE,
91 CONSTRAINT qfd_rtn_or_aggr CHECK
92 ( return_type IS NULL OR is_aggregate = FALSE )
95 CREATE INDEX query_function_sig_name_idx
96 ON query.function_sig (function_name);
98 CREATE TABLE query.function_param_def (
99 id SERIAL PRIMARY KEY,
100 function_id INT NOT NULL
101 REFERENCES query.function_sig( id )
103 DEFERRABLE INITIALLY DEFERRED,
105 CONSTRAINT qfpd_pos_seq_no CHECK
107 datatype INT NOT NULL
108 REFERENCES query.datatype( id )
109 DEFERRABLE INITIALLY DEFERRED,
110 CONSTRAINT qfpd_function_param_seq UNIQUE (function_id, seq_no)
113 CREATE TABLE query.bind_variable (
114 name TEXT PRIMARY KEY,
116 CONSTRAINT bind_variable_type CHECK
117 ( type in ( 'string', 'number', 'string_list', 'number_list' )),
118 description TEXT NOT NULL,
119 default_value TEXT -- to be encoded in JSON
122 CREATE TABLE query.expression (
123 id SERIAL PRIMARY KEY,
124 type TEXT NOT NULL CONSTRAINT predicate_type CHECK
141 parenthesize BOOL NOT NULL DEFAULT FALSE,
142 parent_expr INT REFERENCES query.expression
144 DEFERRABLE INITIALLY DEFERRED,
145 seq_no INT NOT NULL DEFAULT 1,
149 left_operand INT REFERENCES query.expression
150 DEFERRABLE INITIALLY DEFERRED,
152 right_operand INT REFERENCES query.expression
153 DEFERRABLE INITIALLY DEFERRED,
154 function_id INT REFERENCES query.function_sig
155 DEFERRABLE INITIALLY DEFERRED,
156 subquery INT REFERENCES query.stored_query
157 DEFERRABLE INITIALLY DEFERRED,
158 cast_type INT REFERENCES query.datatype
159 DEFERRABLE INITIALLY DEFERRED,
160 negate BOOL NOT NULL DEFAULT FALSE
163 CREATE UNIQUE INDEX query_expr_parent_seq
164 ON query.expression( parent_expr, seq_no )
165 WHERE parent_expr IS NOT NULL;
167 -- Due to some circular references, the following foreign key definitions
168 -- had to be deferred until query.expression existed:
170 ALTER TABLE query.stored_query
171 ADD FOREIGN KEY ( where_clause )
172 REFERENCES query.expression( id )
173 DEFERRABLE INITIALLY DEFERRED;
175 ALTER TABLE query.stored_query
176 ADD FOREIGN KEY ( having_clause )
177 REFERENCES query.expression( id )
178 DEFERRABLE INITIALLY DEFERRED;
180 CREATE TABLE query.case_branch (
181 id SERIAL PRIMARY KEY,
182 parent_expr INT NOT NULL REFERENCES query.expression
184 DEFERRABLE INITIALLY DEFERRED,
186 condition INT REFERENCES query.expression
187 DEFERRABLE INITIALLY DEFERRED,
188 result INT NOT NULL REFERENCES query.expression
189 DEFERRABLE INITIALLY DEFERRED,
190 CONSTRAINT case_branch_parent_seq UNIQUE (parent_expr, seq_no)
193 CREATE TABLE query.from_relation (
194 id SERIAL PRIMARY KEY,
195 type TEXT NOT NULL CONSTRAINT relation_type CHECK (
196 type IN ( 'RELATION', 'SUBQUERY', 'FUNCTION' ) ),
199 subquery INT REFERENCES query.stored_query,
200 function_call INT REFERENCES query.expression,
202 parent_relation INT REFERENCES query.from_relation
204 DEFERRABLE INITIALLY DEFERRED,
205 seq_no INT NOT NULL DEFAULT 1,
206 join_type TEXT CONSTRAINT good_join_type CHECK (
207 join_type IS NULL OR join_type IN
208 ( 'INNER', 'LEFT', 'RIGHT', 'FULL' )
210 on_clause INT REFERENCES query.expression
211 DEFERRABLE INITIALLY DEFERRED,
212 CONSTRAINT join_or_core CHECK (
213 ( parent_relation IS NULL AND join_type IS NULL
214 AND on_clause IS NULL )
216 ( parent_relation IS NOT NULL AND join_type IS NOT NULL
217 AND on_clause IS NOT NULL )
221 CREATE UNIQUE INDEX from_parent_seq
222 ON query.from_relation( parent_relation, seq_no )
223 WHERE parent_relation IS NOT NULL;
225 -- The following foreign key had to be deferred until
226 -- query.from_relation existed
228 ALTER TABLE query.stored_query
229 ADD FOREIGN KEY (from_clause)
230 REFERENCES query.from_relation
231 DEFERRABLE INITIALLY DEFERRED;
233 CREATE TABLE query.record_column (
234 id SERIAL PRIMARY KEY,
235 from_relation INT NOT NULL REFERENCES query.from_relation
237 DEFERRABLE INITIALLY DEFERRED,
239 column_name TEXT NOT NULL,
240 column_type INT NOT NULL REFERENCES query.datatype
242 DEFERRABLE INITIALLY DEFERRED,
243 CONSTRAINT column_sequence UNIQUE (from_relation, seq_no)
246 CREATE TABLE query.select_item (
247 id SERIAL PRIMARY KEY,
248 stored_query INT NOT NULL REFERENCES query.stored_query
250 DEFERRABLE INITIALLY DEFERRED,
252 expression INT NOT NULL REFERENCES query.expression
253 DEFERRABLE INITIALLY DEFERRED,
255 grouped_by BOOL NOT NULL DEFAULT FALSE,
256 CONSTRAINT select_sequence UNIQUE( stored_query, seq_no )
259 CREATE TABLE query.order_by_item (
260 id SERIAL PRIMARY KEY,
261 stored_query INT NOT NULL REFERENCES query.stored_query
263 DEFERRABLE INITIALLY DEFERRED,
265 expression INT NOT NULL REFERENCES query.expression
267 DEFERRABLE INITIALLY DEFERRED,
268 CONSTRAINT order_by_sequence UNIQUE( stored_query, seq_no )
271 -- Create updatable views -------------------------------------------
273 -- Create updatable view for BETWEEN expressions
275 CREATE OR REPLACE VIEW query.expr_xbet AS
287 CREATE OR REPLACE RULE query_expr_xbet_insert_rule AS
288 ON INSERT TO query.expr_xbet
290 INSERT INTO query.expression (
298 COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
300 COALESCE(NEW.parenthesize, FALSE),
302 COALESCE(NEW.seq_no, 1),
306 CREATE OR REPLACE RULE query_expr_xbet_update_rule AS
307 ON UPDATE TO query.expr_xbet
309 UPDATE query.expression SET
311 parenthesize = NEW.parenthesize,
312 parent_expr = NEW.parent_expr,
318 CREATE OR REPLACE RULE query_expr_xbet_delete_rule AS
319 ON DELETE TO query.expr_xbet
321 DELETE FROM query.expression WHERE id = OLD.id;
323 -- Create updatable view for boolean expressions
325 CREATE OR REPLACE VIEW query.expr_xbool AS
338 CREATE OR REPLACE RULE query_expr_xbool_insert_rule AS
339 ON INSERT TO query.expr_xbool
341 INSERT INTO query.expression (
350 COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
352 COALESCE(NEW.parenthesize, FALSE),
354 COALESCE(NEW.seq_no, 1),
359 CREATE OR REPLACE RULE query_expr_xbool_update_rule AS
360 ON UPDATE TO query.expr_xbool
362 UPDATE query.expression SET
364 parenthesize = NEW.parenthesize,
365 parent_expr = NEW.parent_expr,
367 literal = NEW.literal,
372 CREATE OR REPLACE RULE query_expr_xbool_delete_rule AS
373 ON DELETE TO query.expr_xbool
375 DELETE FROM query.expression WHERE id = OLD.id;
377 -- Create updatable view for CASE expressions
379 CREATE OR REPLACE VIEW query.expr_xcase AS
391 CREATE OR REPLACE RULE query_expr_xcase_insert_rule AS
392 ON INSERT TO query.expr_xcase
394 INSERT INTO query.expression (
402 COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
404 COALESCE(NEW.parenthesize, FALSE),
406 COALESCE(NEW.seq_no, 1),
410 CREATE OR REPLACE RULE query_expr_xcase_update_rule AS
411 ON UPDATE TO query.expr_xcase
413 UPDATE query.expression SET
415 parenthesize = NEW.parenthesize,
416 parent_expr = NEW.parent_expr,
422 CREATE OR REPLACE RULE query_expr_xcase_delete_rule AS
423 ON DELETE TO query.expr_xcase
425 DELETE FROM query.expression WHERE id = OLD.id;
427 -- Create updatable view for cast expressions
429 CREATE OR REPLACE VIEW query.expr_xcast AS
443 CREATE OR REPLACE RULE query_expr_xcast_insert_rule AS
444 ON INSERT TO query.expr_xcast
446 INSERT INTO query.expression (
456 COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
458 COALESCE(NEW.parenthesize, FALSE),
460 COALESCE(NEW.seq_no, 1),
466 CREATE OR REPLACE RULE query_expr_xcast_update_rule AS
467 ON UPDATE TO query.expr_xcast
469 UPDATE query.expression SET
471 parenthesize = NEW.parenthesize,
472 parent_expr = NEW.parent_expr,
474 left_operand = NEW.left_operand,
475 cast_type = NEW.cast_type,
480 CREATE OR REPLACE RULE query_expr_xcast_delete_rule AS
481 ON DELETE TO query.expr_xcast
483 DELETE FROM query.expression WHERE id = OLD.id;
485 -- Create updatable view for column expressions
487 CREATE OR REPLACE VIEW query.expr_xcol AS
501 CREATE OR REPLACE RULE query_expr_xcol_insert_rule AS
502 ON INSERT TO query.expr_xcol
504 INSERT INTO query.expression (
514 COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
516 COALESCE(NEW.parenthesize, FALSE),
518 COALESCE(NEW.seq_no, 1),
524 CREATE OR REPLACE RULE query_expr_xcol_update_rule AS
525 ON UPDATE TO query.expr_xcol
527 UPDATE query.expression SET
529 parenthesize = NEW.parenthesize,
530 parent_expr = NEW.parent_expr,
532 table_alias = NEW.table_alias,
533 column_name = NEW.column_name,
538 CREATE OR REPLACE RULE query_expr_xcol_delete_rule AS
539 ON DELETE TO query.expr_xcol
541 DELETE FROM query.expression WHERE id = OLD.id;
543 -- Create updatable view for EXISTS expressions
545 CREATE OR REPLACE VIEW query.expr_xex AS
558 CREATE OR REPLACE RULE query_expr_xex_insert_rule AS
559 ON INSERT TO query.expr_xex
561 INSERT INTO query.expression (
570 COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
572 COALESCE(NEW.parenthesize, FALSE),
574 COALESCE(NEW.seq_no, 1),
579 CREATE OR REPLACE RULE query_expr_xex_update_rule AS
580 ON UPDATE TO query.expr_xex
582 UPDATE query.expression SET
584 parenthesize = NEW.parenthesize,
585 parent_expr = NEW.parent_expr,
587 subquery = NEW.subquery,
592 CREATE OR REPLACE RULE query_expr_xex_delete_rule AS
593 ON DELETE TO query.expr_xex
595 DELETE FROM query.expression WHERE id = OLD.id;
597 -- Create updatable view for field expressions
599 CREATE OR REPLACE VIEW query.expr_xfld AS
613 CREATE OR REPLACE RULE query_expr_xfld_insert_rule AS
614 ON INSERT TO query.expr_xfld
616 INSERT INTO query.expression (
626 COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
628 COALESCE(NEW.parenthesize, FALSE),
630 COALESCE(NEW.seq_no, 1),
636 CREATE OR REPLACE RULE query_expr_xfld_update_rule AS
637 ON UPDATE TO query.expr_xfld
639 UPDATE query.expression SET
641 parenthesize = NEW.parenthesize,
642 parent_expr = NEW.parent_expr,
644 column_name = NEW.column_name,
645 left_operand = NEW.left_operand,
650 CREATE OR REPLACE RULE query_expr_xfld_delete_rule AS
651 ON DELETE TO query.expr_xfld
653 DELETE FROM query.expression WHERE id = OLD.id;
655 -- Create updatable view for function call expressions
657 CREATE OR REPLACE VIEW query.expr_xfunc AS
670 CREATE OR REPLACE RULE query_expr_xfunc_insert_rule AS
671 ON INSERT TO query.expr_xfunc
673 INSERT INTO query.expression (
682 COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
684 COALESCE(NEW.parenthesize, FALSE),
686 COALESCE(NEW.seq_no, 1),
691 CREATE OR REPLACE RULE query_expr_xfunc_update_rule AS
692 ON UPDATE TO query.expr_xfunc
694 UPDATE query.expression SET
696 parenthesize = NEW.parenthesize,
697 parent_expr = NEW.parent_expr,
699 function_id = NEW.function_id,
704 CREATE OR REPLACE RULE query_expr_xfunc_delete_rule AS
705 ON DELETE TO query.expr_xfunc
707 DELETE FROM query.expression WHERE id = OLD.id;
709 -- Create updatable view for IN expressions
711 CREATE OR REPLACE VIEW query.expr_xin AS
725 CREATE OR REPLACE RULE query_expr_xin_insert_rule AS
726 ON INSERT TO query.expr_xin
728 INSERT INTO query.expression (
738 COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
740 COALESCE(NEW.parenthesize, FALSE),
742 COALESCE(NEW.seq_no, 1),
748 CREATE OR REPLACE RULE query_expr_xin_update_rule AS
749 ON UPDATE TO query.expr_xin
751 UPDATE query.expression SET
753 parenthesize = NEW.parenthesize,
754 parent_expr = NEW.parent_expr,
756 left_operand = NEW.left_operand,
757 subquery = NEW.subquery,
762 CREATE OR REPLACE RULE query_expr_xin_delete_rule AS
763 ON DELETE TO query.expr_xin
765 DELETE FROM query.expression WHERE id = OLD.id;
767 -- Create updatable view for NULL expressions
769 CREATE OR REPLACE VIEW query.expr_xnull AS
781 CREATE OR REPLACE RULE query_expr_xnull_insert_rule AS
782 ON INSERT TO query.expr_xnull
784 INSERT INTO query.expression (
792 COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
794 COALESCE(NEW.parenthesize, FALSE),
796 COALESCE(NEW.seq_no, 1),
800 CREATE OR REPLACE RULE query_expr_xnull_update_rule AS
801 ON UPDATE TO query.expr_xnull
803 UPDATE query.expression SET
805 parenthesize = NEW.parenthesize,
806 parent_expr = NEW.parent_expr,
812 CREATE OR REPLACE RULE query_expr_xnull_delete_rule AS
813 ON DELETE TO query.expr_xnull
815 DELETE FROM query.expression WHERE id = OLD.id;
817 -- Create updatable view for numeric literal expressions
819 CREATE OR REPLACE VIEW query.expr_xnum AS
831 CREATE OR REPLACE RULE query_expr_xnum_insert_rule AS
832 ON INSERT TO query.expr_xnum
834 INSERT INTO query.expression (
842 COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
844 COALESCE(NEW.parenthesize, FALSE),
846 COALESCE(NEW.seq_no, 1),
850 CREATE OR REPLACE RULE query_expr_xnum_update_rule AS
851 ON UPDATE TO query.expr_xnum
853 UPDATE query.expression SET
855 parenthesize = NEW.parenthesize,
856 parent_expr = NEW.parent_expr,
858 literal = NEW.literal
862 CREATE OR REPLACE RULE query_expr_xnum_delete_rule AS
863 ON DELETE TO query.expr_xnum
865 DELETE FROM query.expression WHERE id = OLD.id;
867 -- Create updatable view for operator expressions
869 CREATE OR REPLACE VIEW query.expr_xop AS
884 CREATE OR REPLACE RULE query_expr_xop_insert_rule AS
885 ON INSERT TO query.expr_xop
887 INSERT INTO query.expression (
898 COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
900 COALESCE(NEW.parenthesize, FALSE),
902 COALESCE(NEW.seq_no, 1),
909 CREATE OR REPLACE RULE query_expr_xop_update_rule AS
910 ON UPDATE TO query.expr_xop
912 UPDATE query.expression SET
914 parenthesize = NEW.parenthesize,
915 parent_expr = NEW.parent_expr,
917 left_operand = NEW.left_operand,
918 operator = NEW.operator,
919 right_operand = NEW.right_operand,
924 CREATE OR REPLACE RULE query_expr_xop_delete_rule AS
925 ON DELETE TO query.expr_xop
927 DELETE FROM query.expression WHERE id = OLD.id;
929 -- Create updatable view for string literal expressions
931 CREATE OR REPLACE VIEW query.expr_xstr AS
943 CREATE OR REPLACE RULE query_expr_string_insert_rule AS
944 ON INSERT TO query.expr_xstr
946 INSERT INTO query.expression (
954 COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
956 COALESCE(NEW.parenthesize, FALSE),
958 COALESCE(NEW.seq_no, 1),
962 CREATE OR REPLACE RULE query_expr_string_update_rule AS
963 ON UPDATE TO query.expr_xstr
965 UPDATE query.expression SET
967 parenthesize = NEW.parenthesize,
968 parent_expr = NEW.parent_expr,
970 literal = NEW.literal
974 CREATE OR REPLACE RULE query_expr_string_delete_rule AS
975 ON DELETE TO query.expr_xstr
977 DELETE FROM query.expression WHERE id = OLD.id;
979 -- Create updatable view for subquery expressions
981 CREATE OR REPLACE VIEW query.expr_xsubq AS
994 CREATE OR REPLACE RULE query_expr_xsubq_insert_rule AS
995 ON INSERT TO query.expr_xsubq
997 INSERT INTO query.expression (
1006 COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
1008 COALESCE(NEW.parenthesize, FALSE),
1010 COALESCE(NEW.seq_no, 1),
1015 CREATE OR REPLACE RULE query_expr_xsubq_update_rule AS
1016 ON UPDATE TO query.expr_xsubq
1018 UPDATE query.expression SET
1020 parenthesize = NEW.parenthesize,
1021 parent_expr = NEW.parent_expr,
1022 seq_no = NEW.seq_no,
1023 subquery = NEW.subquery,
1028 CREATE OR REPLACE RULE query_expr_xsubq_delete_rule AS
1029 ON DELETE TO query.expr_xsubq
1031 DELETE FROM query.expression WHERE id = OLD.id;