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 NOT NULL , --REFERENCES query.from_clause
38 where_clause INT , --REFERENCES query.expression
39 --DEFERRABLE INITIALLY DEFERRED,
40 having_clause INT --REFERENCES query.expression
41 --DEFERRABLE INITIALLY DEFERRED
44 -- (Foreign keys to be defined later after other tables are created)
46 CREATE TABLE query.query_sequence (
47 id SERIAL PRIMARY KEY,
48 parent_query INT NOT NULL
49 REFERENCES query.stored_query
51 DEFERRABLE INITIALLY DEFERRED,
53 child_query INT NOT NULL
54 REFERENCES query.stored_query
56 DEFERRABLE INITIALLY DEFERRED,
57 CONSTRAINT query_query_seq UNIQUE( parent_query, seq_no )
60 CREATE TABLE query.datatype (
61 id SERIAL PRIMARY KEY,
62 datatype_name TEXT NOT NULL UNIQUE,
63 is_numeric BOOL NOT NULL DEFAULT FALSE,
64 is_composite BOOL NOT NULL DEFAULT FALSE,
65 CONSTRAINT qdt_comp_not_num CHECK
66 ( is_numeric IS FALSE OR is_composite IS FALSE )
69 CREATE TABLE query.subfield (
70 id SERIAL PRIMARY KEY,
71 composite_type INT NOT NULL
72 REFERENCES query.datatype(id)
74 DEFERRABLE INITIALLY DEFERRED,
76 CONSTRAINT qsf_pos_seq_no
78 subfield_type INT NOT NULL
79 REFERENCES query.datatype(id)
80 DEFERRABLE INITIALLY DEFERRED,
81 CONSTRAINT qsf_datatype_seq_no UNIQUE (composite_type, seq_no)
84 CREATE TABLE query.function_sig (
85 id SERIAL PRIMARY KEY,
86 function_name TEXT NOT NULL,
87 return_type INT REFERENCES query.datatype(id)
88 DEFERRABLE INITIALLY DEFERRED,
89 is_aggregate BOOL NOT NULL DEFAULT FALSE,
90 CONSTRAINT qfd_rtn_or_aggr CHECK
91 ( return_type IS NULL OR is_aggregate = FALSE )
94 CREATE INDEX query_function_sig_name_idx
95 ON query.function_sig (function_name);
97 CREATE TABLE query.function_param_def (
98 id SERIAL PRIMARY KEY,
99 function_id INT NOT NULL
100 REFERENCES query.function_sig( id )
102 DEFERRABLE INITIALLY DEFERRED,
104 CONSTRAINT qfpd_pos_seq_no CHECK
106 datatype INT NOT NULL
107 REFERENCES query.datatype( id )
108 DEFERRABLE INITIALLY DEFERRED,
109 CONSTRAINT qfpd_function_param_seq UNIQUE (function_id, seq_no)
112 CREATE TABLE query.expression (
113 id SERIAL PRIMARY KEY,
114 type TEXT NOT NULL CONSTRAINT predicate_type CHECK
125 'xnbet', -- not between
126 'xnex', -- not exists
134 parenthesize BOOL NOT NULL DEFAULT FALSE,
135 parent_expr INT REFERENCES query.expression
137 DEFERRABLE INITIALLY DEFERRED,
138 seq_no INT NOT NULL DEFAULT 1,
142 left_operand INT REFERENCES query.expression
143 DEFERRABLE INITIALLY DEFERRED,
145 right_operand INT REFERENCES query.expression
146 DEFERRABLE INITIALLY DEFERRED,
147 function_id INT REFERENCES query.function_sig
148 DEFERRABLE INITIALLY DEFERRED,
149 subquery INT REFERENCES query.stored_query
150 DEFERRABLE INITIALLY DEFERRED,
151 cast_type INT REFERENCES query.datatype
152 DEFERRABLE INITIALLY DEFERRED
155 CREATE UNIQUE INDEX query_expr_parent_seq
156 ON query.expression( parent_expr, seq_no )
157 WHERE parent_expr IS NOT NULL;
159 -- Due to some circular references, the following foreign key definitions
160 -- had to be deferred until query.expression existed:
162 ALTER TABLE query.stored_query
163 ADD FOREIGN KEY ( where_clause )
164 REFERENCES query.expression( id )
165 DEFERRABLE INITIALLY DEFERRED;
167 ALTER TABLE query.stored_query
168 ADD FOREIGN KEY ( having_clause )
169 REFERENCES query.expression( id )
170 DEFERRABLE INITIALLY DEFERRED;
172 CREATE TABLE query.case_branch (
173 id SERIAL PRIMARY KEY,
174 parent_expr INT NOT NULL REFERENCES query.expression
176 DEFERRABLE INITIALLY DEFERRED,
178 condition INT REFERENCES query.expression
179 DEFERRABLE INITIALLY DEFERRED,
180 result INT NOT NULL REFERENCES query.expression
181 DEFERRABLE INITIALLY DEFERRED,
182 CONSTRAINT case_branch_parent_seq UNIQUE (parent_expr, seq_no)
185 CREATE TABLE query.from_relation (
186 id SERIAL PRIMARY KEY,
187 type TEXT NOT NULL CONSTRAINT relation_type CHECK (
188 type IN ( 'RELATION', 'SUBQUERY', 'FUNCTION' ) ),
191 subquery INT REFERENCES query.stored_query,
192 function_call INT REFERENCES query.expression,
193 table_alias TEXT NOT NULL,
194 parent_relation INT REFERENCES query.from_relation
196 DEFERRABLE INITIALLY DEFERRED,
197 seq_no INT NOT NULL DEFAULT 1,
198 join_type TEXT CONSTRAINT good_join_type CHECK (
199 join_type IS NULL OR join_type IN
200 ( 'INNER', 'LEFT', 'RIGHT', 'FULL' )
202 on_clause INT REFERENCES query.expression
203 DEFERRABLE INITIALLY DEFERRED,
204 CONSTRAINT join_or_core CHECK (
205 ( parent_relation IS NULL AND join_type IS NULL
206 AND on_clause IS NULL and table_alias IS NULL )
208 ( parent_relation IS NOT NULL AND join_type IS NOT NULL
209 AND on_clause IS NOT NULL )
213 CREATE UNIQUE INDEX from_parent_seq
214 ON query.from_relation( parent_relation, seq_no )
215 WHERE parent_relation IS NOT NULL;
217 -- The following foreign key had to be deferred until
218 -- query.from_relation existed
220 ALTER TABLE query.stored_query
221 ADD FOREIGN KEY (from_clause)
222 REFERENCES query.from_relation
223 DEFERRABLE INITIALLY DEFERRED;
225 CREATE TABLE query.record_column (
226 id SERIAL PRIMARY KEY,
227 from_relation INT NOT NULL REFERENCES query.from_relation
229 DEFERRABLE INITIALLY DEFERRED,
231 column_name TEXT NOT NULL,
232 column_type INT NOT NULL REFERENCES query.datatype
234 DEFERRABLE INITIALLY DEFERRED,
235 CONSTRAINT column_sequence UNIQUE (from_relation, seq_no)
238 CREATE TABLE query.select_item (
239 id SERIAL PRIMARY KEY,
240 stored_query INT NOT NULL REFERENCES query.stored_query
242 DEFERRABLE INITIALLY DEFERRED,
244 expression INT NOT NULL REFERENCES query.expression
245 DEFERRABLE INITIALLY DEFERRED,
247 grouped_by BOOL NOT NULL DEFAULT FALSE,
248 CONSTRAINT select_sequence UNIQUE( stored_query, seq_no )
251 CREATE TABLE query.order_by_item (
252 id SERIAL PRIMARY KEY,
253 stored_query INT NOT NULL REFERENCES query.stored_query
255 DEFERRABLE INITIALLY DEFERRED,
257 expression INT NOT NULL REFERENCES query.expression
259 DEFERRABLE INITIALLY DEFERRED,
260 CONSTRAINT order_by_sequence UNIQUE( stored_query, seq_no )
263 -- Create updatable views
265 CREATE OR REPLACE VIEW query.expr_string AS
277 CREATE OR REPLACE RULE query_expr_string_insert_rule AS
278 ON INSERT TO query.expr_string
280 INSERT INTO query.expression (
288 COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
290 COALESCE(NEW.parenthesize, FALSE),
292 COALESCE(NEW.seq_no, 1),
296 CREATE OR REPLACE RULE query_expr_string_update_rule AS
297 ON UPDATE TO query.expr_string
299 UPDATE query.expression SET
301 parenthesize = NEW.parenthesize,
302 parent_expr = NEW.parent_expr,
304 literal = NEW.literal
308 CREATE OR REPLACE RULE query_expr_string_delete_rule AS
309 ON DELETE TO query.expr_string
311 DELETE FROM query.expression WHERE id = OLD.id;