In query.stored query: make from_clause nullable, so that we can
[working/Evergreen.git] / Open-ILS / src / sql / Pg / 008.schema.query.sql
1 -- Script to create the query schema and the tables therein
2
3 BEGIN;
4
5 DROP SCHEMA IF EXISTS query CASCADE;
6 CREATE SCHEMA query;
7 COMMENT ON SCHEMA actor IS $$
8 /*
9  * Copyright (C) 2009  Equinox Software, Inc. / Georgia Public Library Service
10  * Scott McKellar <scott@esilibrary.com>
11  *
12  * Schema: query
13  *
14  * Contains tables designed to represent user-defined queries for
15  * reports and the like.
16  *
17  * ****
18  *
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.
23  *
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.
28  */
29 $$;
30
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
43 );
44
45 -- (Foreign keys to be defined later after other tables are created)
46
47 CREATE TABLE query.query_sequence (
48         id              SERIAL            PRIMARY KEY,
49         parent_query    INT               NOT NULL
50                                           REFERENCES query.stored_query
51                                                                           ON DELETE CASCADE
52                                                                           DEFERRABLE INITIALLY DEFERRED,
53         seq_no          INT               NOT NULL,
54         child_query     INT               NOT NULL
55                                           REFERENCES query.stored_query
56                                                                           ON DELETE CASCADE
57                                                                           DEFERRABLE INITIALLY DEFERRED,
58         CONSTRAINT query_query_seq UNIQUE( parent_query, seq_no )
59 );
60
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 )
68 );
69
70 CREATE TABLE query.subfield (
71         id              SERIAL            PRIMARY KEY,
72         composite_type  INT               NOT NULL
73                                           REFERENCES query.datatype(id)
74                                           ON DELETE CASCADE
75                                           DEFERRABLE INITIALLY DEFERRED,
76         seq_no          INT               NOT NULL
77                                           CONSTRAINT qsf_pos_seq_no
78                                           CHECK( seq_no > 0 ),
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)
83 );
84
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 )
93 );
94
95 CREATE INDEX query_function_sig_name_idx 
96         ON query.function_sig (function_name);
97
98 CREATE TABLE query.function_param_def (
99         id              SERIAL            PRIMARY KEY,
100         function_id     INT               NOT NULL
101                                           REFERENCES query.function_sig( id )
102                                           ON DELETE CASCADE
103                                           DEFERRABLE INITIALLY DEFERRED,
104         seq_no          INT               NOT NULL
105                                           CONSTRAINT qfpd_pos_seq_no CHECK
106                                           ( seq_no > 0 ),
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)
111 );
112
113 CREATE TABLE query.expression (
114         id            SERIAL        PRIMARY KEY,
115         type          TEXT          NOT NULL CONSTRAINT predicate_type CHECK
116                                     ( type IN (
117                                         'xbet',    -- between
118                                                                         'xbool',   -- boolean
119                                         'xcase',   -- case
120                                                                         'xcast',   -- cast
121                                                                         'xcol',    -- column
122                                                                         'xex',     -- exists
123                                                                         'xfld',    -- field
124                                                                         'xfunc',   -- function
125                                                                         'xin',     -- in
126                                                                         'xnbet',   -- not between
127                                         'xnex',    -- not exists
128                                                                         'xnin',    -- not in
129                                         'xnull',   -- null
130                                                                         'xnum',    -- number
131                                                                         'xop',     -- operator
132                                                                         'xstr',    -- string
133                                                 'xsubq'    -- subquery
134                                                                 ) ),
135         parenthesize  BOOL          NOT NULL DEFAULT FALSE,
136         parent_expr   INT           REFERENCES query.expression
137                                     ON DELETE CASCADE
138                                     DEFERRABLE INITIALLY DEFERRED,
139         seq_no        INT           NOT NULL DEFAULT 1,
140         literal       TEXT,
141         table_alias   TEXT,
142         column_name   TEXT,
143         left_operand  INT           REFERENCES query.expression
144                                     DEFERRABLE INITIALLY DEFERRED,
145         operator      TEXT,
146         right_operand INT           REFERENCES query.expression
147                                     DEFERRABLE INITIALLY DEFERRED,
148         function_id   INT           REFERENCES query.function_sig
149                                     DEFERRABLE INITIALLY DEFERRED,
150         subquery      INT           REFERENCES query.stored_query
151                                     DEFERRABLE INITIALLY DEFERRED,
152         cast_type     INT           REFERENCES query.datatype
153                                     DEFERRABLE INITIALLY DEFERRED
154 );
155
156 CREATE UNIQUE INDEX query_expr_parent_seq
157         ON query.expression( parent_expr, seq_no )
158         WHERE parent_expr IS NOT NULL;
159
160 -- Due to some circular references, the following foreign key definitions
161 -- had to be deferred until query.expression existed:
162
163 ALTER TABLE query.stored_query
164         ADD FOREIGN KEY ( where_clause )
165         REFERENCES query.expression( id )
166         DEFERRABLE INITIALLY DEFERRED;
167
168 ALTER TABLE query.stored_query
169         ADD FOREIGN KEY ( having_clause )
170         REFERENCES query.expression( id )
171         DEFERRABLE INITIALLY DEFERRED;
172
173 CREATE TABLE query.case_branch (
174         id            SERIAL        PRIMARY KEY,
175         parent_expr   INT           NOT NULL REFERENCES query.expression
176                                     ON DELETE CASCADE
177                                     DEFERRABLE INITIALLY DEFERRED,
178         seq_no        INT           NOT NULL,
179         condition     INT           REFERENCES query.expression
180                                     DEFERRABLE INITIALLY DEFERRED,
181         result        INT           NOT NULL REFERENCES query.expression
182                                     DEFERRABLE INITIALLY DEFERRED,
183         CONSTRAINT case_branch_parent_seq UNIQUE (parent_expr, seq_no)
184 );
185
186 CREATE TABLE query.from_relation (
187         id               SERIAL        PRIMARY KEY,
188         type             TEXT          NOT NULL CONSTRAINT relation_type CHECK (
189                                            type IN ( 'RELATION', 'SUBQUERY', 'FUNCTION' ) ),
190         table_name       TEXT,
191         class_name       TEXT,
192         subquery         INT           REFERENCES query.stored_query,
193         function_call    INT           REFERENCES query.expression,
194         table_alias      TEXT,
195         parent_relation  INT           REFERENCES query.from_relation
196                                        ON DELETE CASCADE
197                                        DEFERRABLE INITIALLY DEFERRED,
198         seq_no           INT           NOT NULL DEFAULT 1,
199         join_type        TEXT          CONSTRAINT good_join_type CHECK (
200                                            join_type IS NULL OR join_type IN
201                                            ( 'INNER', 'LEFT', 'RIGHT', 'FULL' )
202                                        ),
203         on_clause        INT           REFERENCES query.expression
204                                        DEFERRABLE INITIALLY DEFERRED,
205         CONSTRAINT join_or_core CHECK (
206             ( parent_relation IS NULL AND join_type IS NULL 
207               AND on_clause IS NULL )
208             OR
209             ( parent_relation IS NOT NULL AND join_type IS NOT NULL
210               AND on_clause IS NOT NULL )
211         )
212 );
213
214 CREATE UNIQUE INDEX from_parent_seq
215         ON query.from_relation( parent_relation, seq_no )
216         WHERE parent_relation IS NOT NULL;
217
218 -- The following foreign key had to be deferred until
219 -- query.from_relation existed
220
221 ALTER TABLE query.stored_query
222         ADD FOREIGN KEY (from_clause)
223         REFERENCES query.from_relation
224         DEFERRABLE INITIALLY DEFERRED;
225
226 CREATE TABLE query.record_column (
227         id            SERIAL            PRIMARY KEY,
228         from_relation INT               NOT NULL REFERENCES query.from_relation
229                                         ON DELETE CASCADE
230                                         DEFERRABLE INITIALLY DEFERRED,
231         seq_no        INT               NOT NULL,
232         column_name   TEXT              NOT NULL,
233     column_type   INT               NOT NULL REFERENCES query.datatype
234                                     ON DELETE CASCADE
235                                     DEFERRABLE INITIALLY DEFERRED,
236         CONSTRAINT column_sequence UNIQUE (from_relation, seq_no)
237 );
238
239 CREATE TABLE query.select_item (
240         id               SERIAL         PRIMARY KEY,
241         stored_query     INT            NOT NULL REFERENCES query.stored_query
242                                         ON DELETE CASCADE
243                                         DEFERRABLE INITIALLY DEFERRED,
244         seq_no           INT            NOT NULL,
245         expression       INT            NOT NULL REFERENCES query.expression
246                                         DEFERRABLE INITIALLY DEFERRED,
247         column_alias     TEXT,
248         grouped_by       BOOL           NOT NULL DEFAULT FALSE,
249         CONSTRAINT select_sequence UNIQUE( stored_query, seq_no )
250 );
251
252 CREATE TABLE query.order_by_item (
253         id               SERIAL         PRIMARY KEY,
254         stored_query     INT            NOT NULL REFERENCES query.stored_query
255                                         ON DELETE CASCADE
256                                         DEFERRABLE INITIALLY DEFERRED,
257         seq_no           INT            NOT NULL,
258         expression       INT            NOT NULL REFERENCES query.expression
259                                         ON DELETE CASCADE
260                                         DEFERRABLE INITIALLY DEFERRED,
261         CONSTRAINT order_by_sequence UNIQUE( stored_query, seq_no )
262 );
263
264 -- Create updatable views -------------------------------------------
265
266 -- Create updatable view for BETWEEN expressions
267
268 CREATE OR REPLACE VIEW query.expr_xbet AS
269     SELECT
270                 id,
271                 parenthesize,
272                 parent_expr,
273                 seq_no
274     FROM
275         query.expression
276     WHERE
277         type = 'xbet';
278
279 CREATE OR REPLACE RULE query_expr_xbet_insert_rule AS
280     ON INSERT TO query.expr_xbet
281     DO INSTEAD
282     INSERT INTO query.expression (
283                 id,
284                 type,
285                 parenthesize,
286                 parent_expr,
287                 seq_no
288     ) VALUES (
289         COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
290         'xbet',
291         COALESCE(NEW.parenthesize, FALSE),
292         NEW.parent_expr,
293         COALESCE(NEW.seq_no, 1)
294     );
295
296 CREATE OR REPLACE RULE query_expr_xbet_update_rule AS
297     ON UPDATE TO query.expr_xbet
298     DO INSTEAD
299     UPDATE query.expression SET
300         id = NEW.id,
301         parenthesize = NEW.parenthesize,
302         parent_expr = NEW.parent_expr,
303         seq_no = NEW.seq_no
304     WHERE
305         id = OLD.id;
306
307 CREATE OR REPLACE RULE query_expr_xbet_delete_rule AS
308     ON DELETE TO query.expr_xbet
309     DO INSTEAD
310     DELETE FROM query.expression WHERE id = OLD.id;
311
312 -- Create updatable view for boolean expressions
313
314 CREATE OR REPLACE VIEW query.expr_xbool AS
315     SELECT
316                 id,
317                 parenthesize,
318                 parent_expr,
319                 seq_no,
320                 literal
321     FROM
322         query.expression
323     WHERE
324         type = 'xbool';
325
326 CREATE OR REPLACE RULE query_expr_xbool_insert_rule AS
327     ON INSERT TO query.expr_xbool
328     DO INSTEAD
329     INSERT INTO query.expression (
330                 id,
331                 type,
332                 parenthesize,
333                 parent_expr,
334                 seq_no,
335                 literal
336     ) VALUES (
337         COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
338         'xbool',
339         COALESCE(NEW.parenthesize, FALSE),
340         NEW.parent_expr,
341         COALESCE(NEW.seq_no, 1),
342         NEW.literal
343     );
344
345 CREATE OR REPLACE RULE query_expr_xbool_update_rule AS
346     ON UPDATE TO query.expr_xbool
347     DO INSTEAD
348     UPDATE query.expression SET
349         id = NEW.id,
350         parenthesize = NEW.parenthesize,
351         parent_expr = NEW.parent_expr,
352         seq_no = NEW.seq_no,
353         literal = NEW.literal
354     WHERE
355         id = OLD.id;
356
357 CREATE OR REPLACE RULE query_expr_xbool_delete_rule AS
358     ON DELETE TO query.expr_xbool
359     DO INSTEAD
360     DELETE FROM query.expression WHERE id = OLD.id;
361
362 -- Create updatable view for CASE expressions
363
364 CREATE OR REPLACE VIEW query.expr_xcase AS
365     SELECT
366                 id,
367                 parenthesize,
368                 parent_expr,
369                 seq_no
370     FROM
371         query.expression
372     WHERE
373         type = 'xcase';
374
375 CREATE OR REPLACE RULE query_expr_xcase_insert_rule AS
376     ON INSERT TO query.expr_xcase
377     DO INSTEAD
378     INSERT INTO query.expression (
379                 id,
380                 type,
381                 parenthesize,
382                 parent_expr,
383                 seq_no
384     ) VALUES (
385         COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
386         'xcase',
387         COALESCE(NEW.parenthesize, FALSE),
388         NEW.parent_expr,
389         COALESCE(NEW.seq_no, 1)
390     );
391
392 CREATE OR REPLACE RULE query_expr_xcase_update_rule AS
393     ON UPDATE TO query.expr_xcase
394     DO INSTEAD
395     UPDATE query.expression SET
396         id = NEW.id,
397         parenthesize = NEW.parenthesize,
398         parent_expr = NEW.parent_expr,
399         seq_no = NEW.seq_no
400     WHERE
401         id = OLD.id;
402
403 CREATE OR REPLACE RULE query_expr_xcase_delete_rule AS
404     ON DELETE TO query.expr_xcase
405     DO INSTEAD
406     DELETE FROM query.expression WHERE id = OLD.id;
407
408 -- Create updatable view for cast expressions
409
410 CREATE OR REPLACE VIEW query.expr_xcast AS
411     SELECT
412                 id,
413                 parenthesize,
414                 parent_expr,
415                 seq_no,
416                 left_operand,
417                 cast_type
418     FROM
419         query.expression
420     WHERE
421         type = 'xcast';
422
423 CREATE OR REPLACE RULE query_expr_xcast_insert_rule AS
424     ON INSERT TO query.expr_xcast
425     DO INSTEAD
426     INSERT INTO query.expression (
427                 id,
428                 type,
429                 parenthesize,
430                 parent_expr,
431                 seq_no,
432                 left_operand,
433                 cast_type
434     ) VALUES (
435         COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
436         'xcast',
437         COALESCE(NEW.parenthesize, FALSE),
438         NEW.parent_expr,
439         COALESCE(NEW.seq_no, 1),
440                 NEW.left_operand,
441                 NEW.cast_type
442     );
443
444 CREATE OR REPLACE RULE query_expr_xcast_update_rule AS
445     ON UPDATE TO query.expr_xcast
446     DO INSTEAD
447     UPDATE query.expression SET
448         id = NEW.id,
449         parenthesize = NEW.parenthesize,
450         parent_expr = NEW.parent_expr,
451         seq_no = NEW.seq_no,
452                 left_operand = NEW.left_operand,
453                 cast_type = NEW.cast_type
454     WHERE
455         id = OLD.id;
456
457 CREATE OR REPLACE RULE query_expr_xcast_delete_rule AS
458     ON DELETE TO query.expr_xcast
459     DO INSTEAD
460     DELETE FROM query.expression WHERE id = OLD.id;
461
462 -- Create updatable view for column expressions
463
464 CREATE OR REPLACE VIEW query.expr_xcol AS
465     SELECT
466                 id,
467                 parenthesize,
468                 parent_expr,
469                 seq_no,
470                 table_alias,
471                 column_name
472     FROM
473         query.expression
474     WHERE
475         type = 'xcol';
476
477 CREATE OR REPLACE RULE query_expr_xcol_insert_rule AS
478     ON INSERT TO query.expr_xcol
479     DO INSTEAD
480     INSERT INTO query.expression (
481                 id,
482                 type,
483                 parenthesize,
484                 parent_expr,
485                 seq_no,
486                 table_alias,
487                 column_name
488     ) VALUES (
489         COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
490         'xcol',
491         COALESCE(NEW.parenthesize, FALSE),
492         NEW.parent_expr,
493         COALESCE(NEW.seq_no, 1),
494                 NEW.table_alias,
495                 NEW.column_name
496     );
497
498 CREATE OR REPLACE RULE query_expr_xcol_update_rule AS
499     ON UPDATE TO query.expr_xcol
500     DO INSTEAD
501     UPDATE query.expression SET
502         id = NEW.id,
503         parenthesize = NEW.parenthesize,
504         parent_expr = NEW.parent_expr,
505         seq_no = NEW.seq_no,
506                 table_alias = NEW.table_alias,
507                 column_name = NEW.column_name
508     WHERE
509         id = OLD.id;
510
511 CREATE OR REPLACE RULE query_expr_xcol_delete_rule AS
512     ON DELETE TO query.expr_xcol
513     DO INSTEAD
514     DELETE FROM query.expression WHERE id = OLD.id;
515
516 -- Create updatable view for EXISTS expressions
517
518 CREATE OR REPLACE VIEW query.expr_xex AS
519     SELECT
520                 id,
521                 parenthesize,
522                 parent_expr,
523                 seq_no,
524                 subquery
525     FROM
526         query.expression
527     WHERE
528         type = 'xex';
529
530 CREATE OR REPLACE RULE query_expr_xex_insert_rule AS
531     ON INSERT TO query.expr_xex
532     DO INSTEAD
533     INSERT INTO query.expression (
534                 id,
535                 type,
536                 parenthesize,
537                 parent_expr,
538                 seq_no,
539                 subquery
540     ) VALUES (
541         COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
542         'xex',
543         COALESCE(NEW.parenthesize, FALSE),
544         NEW.parent_expr,
545         COALESCE(NEW.seq_no, 1),
546                 NEW.subquery
547     );
548
549 CREATE OR REPLACE RULE query_expr_xex_update_rule AS
550     ON UPDATE TO query.expr_xex
551     DO INSTEAD
552     UPDATE query.expression SET
553         id = NEW.id,
554         parenthesize = NEW.parenthesize,
555         parent_expr = NEW.parent_expr,
556         seq_no = NEW.seq_no,
557                 subquery = NEW.subquery
558     WHERE
559         id = OLD.id;
560
561 CREATE OR REPLACE RULE query_expr_xex_delete_rule AS
562     ON DELETE TO query.expr_xex
563     DO INSTEAD
564     DELETE FROM query.expression WHERE id = OLD.id;
565
566 -- Create updatable view for field expressions
567
568 CREATE OR REPLACE VIEW query.expr_xfld AS
569     SELECT
570                 id,
571                 parenthesize,
572                 parent_expr,
573                 seq_no,
574                 column_name,
575                 left_operand
576     FROM
577         query.expression
578     WHERE
579         type = 'xfld';
580
581 CREATE OR REPLACE RULE query_expr_xfld_insert_rule AS
582     ON INSERT TO query.expr_xfld
583     DO INSTEAD
584     INSERT INTO query.expression (
585                 id,
586                 type,
587                 parenthesize,
588                 parent_expr,
589                 seq_no,
590                 column_name,
591                 left_operand
592     ) VALUES (
593         COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
594         'xfld',
595         COALESCE(NEW.parenthesize, FALSE),
596         NEW.parent_expr,
597         COALESCE(NEW.seq_no, 1),
598                 NEW.column_name,
599                 NEW.left_operand
600     );
601
602 CREATE OR REPLACE RULE query_expr_xfld_update_rule AS
603     ON UPDATE TO query.expr_xfld
604     DO INSTEAD
605     UPDATE query.expression SET
606         id = NEW.id,
607         parenthesize = NEW.parenthesize,
608         parent_expr = NEW.parent_expr,
609         seq_no = NEW.seq_no,
610                 column_name = NEW.column_name,
611                 left_operand = NEW.left_operand
612     WHERE
613         id = OLD.id;
614
615 CREATE OR REPLACE RULE query_expr_xfld_delete_rule AS
616     ON DELETE TO query.expr_xfld
617     DO INSTEAD
618     DELETE FROM query.expression WHERE id = OLD.id;
619
620 -- Create updatable view for function call expressions
621
622 CREATE OR REPLACE VIEW query.expr_xfunc AS
623     SELECT
624                 id,
625                 parenthesize,
626                 parent_expr,
627                 seq_no,
628                 function_id
629     FROM
630         query.expression
631     WHERE
632         type = 'xfunc';
633
634 CREATE OR REPLACE RULE query_expr_xfunc_insert_rule AS
635     ON INSERT TO query.expr_xfunc
636     DO INSTEAD
637     INSERT INTO query.expression (
638                 id,
639                 type,
640                 parenthesize,
641                 parent_expr,
642                 seq_no,
643                 function_id
644     ) VALUES (
645         COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
646         'xfunc',
647         COALESCE(NEW.parenthesize, FALSE),
648         NEW.parent_expr,
649         COALESCE(NEW.seq_no, 1),
650                 NEW.function_id
651     );
652
653 CREATE OR REPLACE RULE query_expr_xfunc_update_rule AS
654     ON UPDATE TO query.expr_xfunc
655     DO INSTEAD
656     UPDATE query.expression SET
657         id = NEW.id,
658         parenthesize = NEW.parenthesize,
659         parent_expr = NEW.parent_expr,
660         seq_no = NEW.seq_no,
661                 function_id = NEW.function_id
662     WHERE
663         id = OLD.id;
664
665 CREATE OR REPLACE RULE query_expr_xfunc_delete_rule AS
666     ON DELETE TO query.expr_xfunc
667     DO INSTEAD
668     DELETE FROM query.expression WHERE id = OLD.id;
669
670 -- Create updatable view for IN expressions
671
672 CREATE OR REPLACE VIEW query.expr_xin AS
673     SELECT
674                 id,
675                 parenthesize,
676                 parent_expr,
677                 seq_no,
678                 subquery
679     FROM
680         query.expression
681     WHERE
682         type = 'xin';
683
684 CREATE OR REPLACE RULE query_expr_xin_insert_rule AS
685     ON INSERT TO query.expr_xin
686     DO INSTEAD
687     INSERT INTO query.expression (
688                 id,
689                 type,
690                 parenthesize,
691                 parent_expr,
692                 seq_no,
693                 subquery
694     ) VALUES (
695         COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
696         'xin',
697         COALESCE(NEW.parenthesize, FALSE),
698         NEW.parent_expr,
699         COALESCE(NEW.seq_no, 1),
700                 NEW.subquery
701     );
702
703 CREATE OR REPLACE RULE query_expr_xin_update_rule AS
704     ON UPDATE TO query.expr_xin
705     DO INSTEAD
706     UPDATE query.expression SET
707         id = NEW.id,
708         parenthesize = NEW.parenthesize,
709         parent_expr = NEW.parent_expr,
710         seq_no = NEW.seq_no,
711                 subquery = NEW.subquery
712     WHERE
713         id = OLD.id;
714
715 CREATE OR REPLACE RULE query_expr_xin_delete_rule AS
716     ON DELETE TO query.expr_xin
717     DO INSTEAD
718     DELETE FROM query.expression WHERE id = OLD.id;
719
720 -- Create updatable view for NOT BETWEEN expressions
721
722 CREATE OR REPLACE VIEW query.expr_xnbet AS
723     SELECT
724                 id,
725                 parenthesize,
726                 parent_expr,
727                 seq_no
728     FROM
729         query.expression
730     WHERE
731         type = 'xnbet';
732
733 CREATE OR REPLACE RULE query_expr_xnbet_insert_rule AS
734     ON INSERT TO query.expr_xnbet
735     DO INSTEAD
736     INSERT INTO query.expression (
737                 id,
738                 type,
739                 parenthesize,
740                 parent_expr,
741                 seq_no
742     ) VALUES (
743         COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
744         'xnbet',
745         COALESCE(NEW.parenthesize, FALSE),
746         NEW.parent_expr,
747         COALESCE(NEW.seq_no, 1)
748     );
749
750 CREATE OR REPLACE RULE query_expr_xnbet_update_rule AS
751     ON UPDATE TO query.expr_xnbet
752     DO INSTEAD
753     UPDATE query.expression SET
754         id = NEW.id,
755         parenthesize = NEW.parenthesize,
756         parent_expr = NEW.parent_expr,
757         seq_no = NEW.seq_no
758     WHERE
759         id = OLD.id;
760
761 CREATE OR REPLACE RULE query_expr_xnbet_delete_rule AS
762     ON DELETE TO query.expr_xnbet
763     DO INSTEAD
764     DELETE FROM query.expression WHERE id = OLD.id;
765
766 -- Create updatable view for NOT EXISTS expressions
767
768 CREATE OR REPLACE VIEW query.expr_xnex AS
769     SELECT
770                 id,
771                 parenthesize,
772                 parent_expr,
773                 seq_no,
774                 subquery
775     FROM
776         query.expression
777     WHERE
778         type = 'xnex';
779
780 CREATE OR REPLACE RULE query_expr_xnex_insert_rule AS
781     ON INSERT TO query.expr_xnex
782     DO INSTEAD
783     INSERT INTO query.expression (
784                 id,
785                 type,
786                 parenthesize,
787                 parent_expr,
788                 seq_no,
789                 subquery
790     ) VALUES (
791         COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
792         'xnex',
793         COALESCE(NEW.parenthesize, FALSE),
794         NEW.parent_expr,
795         COALESCE(NEW.seq_no, 1),
796                 NEW.subquery
797     );
798
799 CREATE OR REPLACE RULE query_expr_xnex_update_rule AS
800     ON UPDATE TO query.expr_xnex
801     DO INSTEAD
802     UPDATE query.expression SET
803         id = NEW.id,
804         parenthesize = NEW.parenthesize,
805         parent_expr = NEW.parent_expr,
806         seq_no = NEW.seq_no,
807                 subquery = NEW.subquery
808     WHERE
809         id = OLD.id;
810
811 CREATE OR REPLACE RULE query_expr_xnex_delete_rule AS
812     ON DELETE TO query.expr_xnex
813     DO INSTEAD
814     DELETE FROM query.expression WHERE id = OLD.id;
815
816 -- Create updatable view for NOT IN expressions
817
818 CREATE OR REPLACE VIEW query.expr_xnin AS
819     SELECT
820                 id,
821                 parenthesize,
822                 parent_expr,
823                 seq_no,
824                 subquery
825     FROM
826         query.expression
827     WHERE
828         type = 'xnin';
829
830 CREATE OR REPLACE RULE query_expr_xnin_insert_rule AS
831     ON INSERT TO query.expr_xnin
832     DO INSTEAD
833     INSERT INTO query.expression (
834                 id,
835                 type,
836                 parenthesize,
837                 parent_expr,
838                 seq_no,
839                 subquery
840     ) VALUES (
841         COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
842         'xnin',
843         COALESCE(NEW.parenthesize, FALSE),
844         NEW.parent_expr,
845         COALESCE(NEW.seq_no, 1),
846                 NEW.subquery
847     );
848
849 CREATE OR REPLACE RULE query_expr_xnin_update_rule AS
850     ON UPDATE TO query.expr_xnin
851     DO INSTEAD
852     UPDATE query.expression SET
853         id = NEW.id,
854         parenthesize = NEW.parenthesize,
855         parent_expr = NEW.parent_expr,
856         seq_no = NEW.seq_no,
857                 subquery = NEW.subquery
858     WHERE
859         id = OLD.id;
860
861 CREATE OR REPLACE RULE query_expr_xnin_delete_rule AS
862     ON DELETE TO query.expr_xnin
863     DO INSTEAD
864     DELETE FROM query.expression WHERE id = OLD.id;
865
866 -- Create updatable view for NULL expressions
867
868 CREATE OR REPLACE VIEW query.expr_xnull AS
869     SELECT
870                 id,
871                 parenthesize,
872                 parent_expr,
873                 seq_no
874     FROM
875         query.expression
876     WHERE
877         type = 'xnull';
878
879 CREATE OR REPLACE RULE query_expr_xnull_insert_rule AS
880     ON INSERT TO query.expr_xnull
881     DO INSTEAD
882     INSERT INTO query.expression (
883                 id,
884                 type,
885                 parenthesize,
886                 parent_expr,
887                 seq_no
888     ) VALUES (
889         COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
890         'xnull',
891         COALESCE(NEW.parenthesize, FALSE),
892         NEW.parent_expr,
893         COALESCE(NEW.seq_no, 1)
894     );
895
896 CREATE OR REPLACE RULE query_expr_xnull_update_rule AS
897     ON UPDATE TO query.expr_xnull
898     DO INSTEAD
899     UPDATE query.expression SET
900         id = NEW.id,
901         parenthesize = NEW.parenthesize,
902         parent_expr = NEW.parent_expr,
903         seq_no = NEW.seq_no
904     WHERE
905         id = OLD.id;
906
907 CREATE OR REPLACE RULE query_expr_xnull_delete_rule AS
908     ON DELETE TO query.expr_xnull
909     DO INSTEAD
910     DELETE FROM query.expression WHERE id = OLD.id;
911
912 -- Create updatable view for numeric literal expressions
913
914 CREATE OR REPLACE VIEW query.expr_xnum AS
915     SELECT
916                 id,
917                 parenthesize,
918                 parent_expr,
919                 seq_no,
920                 literal
921     FROM
922         query.expression
923     WHERE
924         type = 'xnum';
925
926 CREATE OR REPLACE RULE query_expr_xnum_insert_rule AS
927     ON INSERT TO query.expr_xnum
928     DO INSTEAD
929     INSERT INTO query.expression (
930                 id,
931                 type,
932                 parenthesize,
933                 parent_expr,
934                 seq_no,
935                 literal
936     ) VALUES (
937         COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
938         'xnum',
939         COALESCE(NEW.parenthesize, FALSE),
940         NEW.parent_expr,
941         COALESCE(NEW.seq_no, 1),
942         NEW.literal
943     );
944
945 CREATE OR REPLACE RULE query_expr_xnum_update_rule AS
946     ON UPDATE TO query.expr_xnum
947     DO INSTEAD
948     UPDATE query.expression SET
949         id = NEW.id,
950         parenthesize = NEW.parenthesize,
951         parent_expr = NEW.parent_expr,
952         seq_no = NEW.seq_no,
953         literal = NEW.literal
954     WHERE
955         id = OLD.id;
956
957 CREATE OR REPLACE RULE query_expr_xnum_delete_rule AS
958     ON DELETE TO query.expr_xnum
959     DO INSTEAD
960     DELETE FROM query.expression WHERE id = OLD.id;
961
962 -- Create updatable view for operator expressions
963
964 CREATE OR REPLACE VIEW query.expr_xop AS
965     SELECT
966                 id,
967                 parenthesize,
968                 parent_expr,
969                 seq_no,
970                 left_operand,
971                 operator,
972                 right_operand
973     FROM
974         query.expression
975     WHERE
976         type = 'xop';
977
978 CREATE OR REPLACE RULE query_expr_xop_insert_rule AS
979     ON INSERT TO query.expr_xop
980     DO INSTEAD
981     INSERT INTO query.expression (
982                 id,
983                 type,
984                 parenthesize,
985                 parent_expr,
986                 seq_no,
987                 left_operand,
988                 operator,
989                 right_operand
990     ) VALUES (
991         COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
992         'xop',
993         COALESCE(NEW.parenthesize, FALSE),
994         NEW.parent_expr,
995         COALESCE(NEW.seq_no, 1),
996                 NEW.left_operand,
997                 NEW.operator,
998                 NEW.right_operand
999     );
1000
1001 CREATE OR REPLACE RULE query_expr_xop_update_rule AS
1002     ON UPDATE TO query.expr_xop
1003     DO INSTEAD
1004     UPDATE query.expression SET
1005         id = NEW.id,
1006         parenthesize = NEW.parenthesize,
1007         parent_expr = NEW.parent_expr,
1008         seq_no = NEW.seq_no,
1009                 left_operand = NEW.left_operand,
1010                 operator = NEW.operator,
1011                 right_operand = NEW.right_operand
1012     WHERE
1013         id = OLD.id;
1014
1015 CREATE OR REPLACE RULE query_expr_xop_delete_rule AS
1016     ON DELETE TO query.expr_xop
1017     DO INSTEAD
1018     DELETE FROM query.expression WHERE id = OLD.id;
1019
1020 -- Create updatable view for string literal expressions
1021
1022 CREATE OR REPLACE VIEW query.expr_string AS
1023     SELECT
1024         id,
1025         parenthesize,
1026         parent_expr,
1027         seq_no,
1028         literal
1029     FROM
1030         query.expression
1031     WHERE
1032         type = 'xstr';
1033
1034 CREATE OR REPLACE RULE query_expr_string_insert_rule AS
1035     ON INSERT TO query.expr_string
1036     DO INSTEAD
1037     INSERT INTO query.expression (
1038         id,
1039         type,
1040         parenthesize,
1041         parent_expr,
1042         seq_no,
1043         literal
1044     ) VALUES (
1045         COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
1046         'xstr',
1047         COALESCE(NEW.parenthesize, FALSE),
1048         NEW.parent_expr,
1049         COALESCE(NEW.seq_no, 1),
1050         NEW.literal
1051     );
1052
1053 CREATE OR REPLACE RULE query_expr_string_update_rule AS
1054     ON UPDATE TO query.expr_string
1055     DO INSTEAD
1056     UPDATE query.expression SET
1057         id = NEW.id,
1058         parenthesize = NEW.parenthesize,
1059         parent_expr = NEW.parent_expr,
1060         seq_no = NEW.seq_no,
1061         literal = NEW.literal
1062     WHERE
1063         id = OLD.id;
1064
1065 CREATE OR REPLACE RULE query_expr_string_delete_rule AS
1066     ON DELETE TO query.expr_string
1067     DO INSTEAD
1068     DELETE FROM query.expression WHERE id = OLD.id;
1069
1070 -- Create updatable view for subquery expressions
1071
1072 CREATE OR REPLACE VIEW query.expr_xsubq AS
1073     SELECT
1074                 id,
1075                 parenthesize,
1076                 parent_expr,
1077                 seq_no,
1078                 subquery
1079     FROM
1080         query.expression
1081     WHERE
1082         type = 'xsubq';
1083
1084 CREATE OR REPLACE RULE query_expr_xsubq_insert_rule AS
1085     ON INSERT TO query.expr_xsubq
1086     DO INSTEAD
1087     INSERT INTO query.expression (
1088                 id,
1089                 type,
1090                 parenthesize,
1091                 parent_expr,
1092                 seq_no,
1093                 subquery
1094     ) VALUES (
1095         COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
1096         'xsubq',
1097         COALESCE(NEW.parenthesize, FALSE),
1098         NEW.parent_expr,
1099         COALESCE(NEW.seq_no, 1),
1100                 NEW.subquery
1101     );
1102
1103 CREATE OR REPLACE RULE query_expr_xsubq_update_rule AS
1104     ON UPDATE TO query.expr_xsubq
1105     DO INSTEAD
1106     UPDATE query.expression SET
1107         id = NEW.id,
1108         parenthesize = NEW.parenthesize,
1109         parent_expr = NEW.parent_expr,
1110         seq_no = NEW.seq_no,
1111                 subquery = NEW.subquery
1112     WHERE
1113         id = OLD.id;
1114
1115 CREATE OR REPLACE RULE query_expr_xsubq_delete_rule AS
1116     ON DELETE TO query.expr_xsubq
1117     DO INSTEAD
1118     DELETE FROM query.expression WHERE id = OLD.id;
1119
1120 COMMIT;