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