~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to src/backend/rewrite/rewriteHandler.c

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * rewriteHandler.c
 
4
 *              Primary module of query rewriter.
 
5
 *
 
6
 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
 
7
 * Portions Copyright (c) 1994, Regents of the University of California
 
8
 *
 
9
 * IDENTIFICATION
 
10
 *        $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.147 2004-12-31 22:00:45 pgsql Exp $
 
11
 *
 
12
 *-------------------------------------------------------------------------
 
13
 */
 
14
#include "postgres.h"
 
15
 
 
16
#include "access/heapam.h"
 
17
#include "catalog/pg_operator.h"
 
18
#include "catalog/pg_type.h"
 
19
#include "miscadmin.h"
 
20
#include "nodes/makefuncs.h"
 
21
#include "optimizer/clauses.h"
 
22
#include "optimizer/prep.h"
 
23
#include "optimizer/var.h"
 
24
#include "parser/analyze.h"
 
25
#include "parser/parse_coerce.h"
 
26
#include "parser/parse_expr.h"
 
27
#include "parser/parse_oper.h"
 
28
#include "parser/parse_type.h"
 
29
#include "parser/parsetree.h"
 
30
#include "rewrite/rewriteHandler.h"
 
31
#include "rewrite/rewriteManip.h"
 
32
#include "utils/builtins.h"
 
33
#include "utils/lsyscache.h"
 
34
 
 
35
 
 
36
/* We use a list of these to detect recursion in RewriteQuery */
 
37
typedef struct rewrite_event
 
38
{
 
39
        Oid                     relation;               /* OID of relation having rules */
 
40
        CmdType         event;                  /* type of rule being fired */
 
41
} rewrite_event;
 
42
 
 
43
static Query *rewriteRuleAction(Query *parsetree,
 
44
                                  Query *rule_action,
 
45
                                  Node *rule_qual,
 
46
                                  int rt_index,
 
47
                                  CmdType event);
 
48
static List *adjustJoinTreeList(Query *parsetree, bool removert, int rt_index);
 
49
static void rewriteTargetList(Query *parsetree, Relation target_relation);
 
50
static TargetEntry *process_matched_tle(TargetEntry *src_tle,
 
51
                                        TargetEntry *prior_tle,
 
52
                                        const char *attrName);
 
53
static Node *get_assignment_input(Node *node);
 
54
static void markQueryForUpdate(Query *qry, bool skipOldNew);
 
55
static List *matchLocks(CmdType event, RuleLock *rulelocks,
 
56
                   int varno, Query *parsetree);
 
57
static Query *fireRIRrules(Query *parsetree, List *activeRIRs);
 
58
 
 
59
 
 
60
/*
 
61
 * rewriteRuleAction -
 
62
 *        Rewrite the rule action with appropriate qualifiers (taken from
 
63
 *        the triggering query).
 
64
 */
 
65
static Query *
 
66
rewriteRuleAction(Query *parsetree,
 
67
                                  Query *rule_action,
 
68
                                  Node *rule_qual,
 
69
                                  int rt_index,
 
70
                                  CmdType event)
 
71
{
 
72
        int                     current_varno,
 
73
                                new_varno;
 
74
        int                     rt_length;
 
75
        Query      *sub_action;
 
76
        Query     **sub_action_ptr;
 
77
 
 
78
        /*
 
79
         * Make modifiable copies of rule action and qual (what we're passed
 
80
         * are the stored versions in the relcache; don't touch 'em!).
 
81
         */
 
82
        rule_action = (Query *) copyObject(rule_action);
 
83
        rule_qual = (Node *) copyObject(rule_qual);
 
84
 
 
85
        current_varno = rt_index;
 
86
        rt_length = list_length(parsetree->rtable);
 
87
        new_varno = PRS2_NEW_VARNO + rt_length;
 
88
 
 
89
        /*
 
90
         * Adjust rule action and qual to offset its varnos, so that we can
 
91
         * merge its rtable with the main parsetree's rtable.
 
92
         *
 
93
         * If the rule action is an INSERT...SELECT, the OLD/NEW rtable entries
 
94
         * will be in the SELECT part, and we have to modify that rather than
 
95
         * the top-level INSERT (kluge!).
 
96
         */
 
97
        sub_action = getInsertSelectQuery(rule_action, &sub_action_ptr);
 
98
 
 
99
        OffsetVarNodes((Node *) sub_action, rt_length, 0);
 
100
        OffsetVarNodes(rule_qual, rt_length, 0);
 
101
        /* but references to *OLD* should point at original rt_index */
 
102
        ChangeVarNodes((Node *) sub_action,
 
103
                                   PRS2_OLD_VARNO + rt_length, rt_index, 0);
 
104
        ChangeVarNodes(rule_qual,
 
105
                                   PRS2_OLD_VARNO + rt_length, rt_index, 0);
 
106
 
 
107
        /*
 
108
         * Generate expanded rtable consisting of main parsetree's rtable plus
 
109
         * rule action's rtable; this becomes the complete rtable for the rule
 
110
         * action.      Some of the entries may be unused after we finish
 
111
         * rewriting, but we leave them all in place for two reasons:
 
112
         *
 
113
         * We'd have a much harder job to adjust the query's varnos if we
 
114
         * selectively removed RT entries.
 
115
         *
 
116
         * If the rule is INSTEAD, then the original query won't be executed at
 
117
         * all, and so its rtable must be preserved so that the executor will
 
118
         * do the correct permissions checks on it.
 
119
         *
 
120
         * RT entries that are not referenced in the completed jointree will be
 
121
         * ignored by the planner, so they do not affect query semantics.  But
 
122
         * any permissions checks specified in them will be applied during
 
123
         * executor startup (see ExecCheckRTEPerms()).  This allows us to
 
124
         * check that the caller has, say, insert-permission on a view, when
 
125
         * the view is not semantically referenced at all in the resulting
 
126
         * query.
 
127
         *
 
128
         * When a rule is not INSTEAD, the permissions checks done on its copied
 
129
         * RT entries will be redundant with those done during execution of
 
130
         * the original query, but we don't bother to treat that case
 
131
         * differently.
 
132
         *
 
133
         * NOTE: because planner will destructively alter rtable, we must ensure
 
134
         * that rule action's rtable is separate and shares no substructure
 
135
         * with the main rtable.  Hence do a deep copy here.
 
136
         */
 
137
        sub_action->rtable = list_concat((List *) copyObject(parsetree->rtable),
 
138
                                                                         sub_action->rtable);
 
139
 
 
140
        /*
 
141
         * Each rule action's jointree should be the main parsetree's jointree
 
142
         * plus that rule's jointree, but usually *without* the original
 
143
         * rtindex that we're replacing (if present, which it won't be for
 
144
         * INSERT). Note that if the rule action refers to OLD, its jointree
 
145
         * will add a reference to rt_index.  If the rule action doesn't refer
 
146
         * to OLD, but either the rule_qual or the user query quals do, then
 
147
         * we need to keep the original rtindex in the jointree to provide
 
148
         * data for the quals.  We don't want the original rtindex to be
 
149
         * joined twice, however, so avoid keeping it if the rule action
 
150
         * mentions it.
 
151
         *
 
152
         * As above, the action's jointree must not share substructure with the
 
153
         * main parsetree's.
 
154
         */
 
155
        if (sub_action->commandType != CMD_UTILITY)
 
156
        {
 
157
                bool            keeporig;
 
158
                List       *newjointree;
 
159
 
 
160
                Assert(sub_action->jointree != NULL);
 
161
                keeporig = (!rangeTableEntry_used((Node *) sub_action->jointree,
 
162
                                                                                  rt_index, 0)) &&
 
163
                        (rangeTableEntry_used(rule_qual, rt_index, 0) ||
 
164
                  rangeTableEntry_used(parsetree->jointree->quals, rt_index, 0));
 
165
                newjointree = adjustJoinTreeList(parsetree, !keeporig, rt_index);
 
166
                if (newjointree != NIL)
 
167
                {
 
168
                        /*
 
169
                         * If sub_action is a setop, manipulating its jointree will do
 
170
                         * no good at all, because the jointree is dummy.  (Perhaps
 
171
                         * someday we could push the joining and quals down to the
 
172
                         * member statements of the setop?)
 
173
                         */
 
174
                        if (sub_action->setOperations != NULL)
 
175
                                ereport(ERROR,
 
176
                                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 
177
                                                 errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
 
178
 
 
179
                        sub_action->jointree->fromlist =
 
180
                                list_concat(newjointree, sub_action->jointree->fromlist);
 
181
                }
 
182
        }
 
183
 
 
184
        /*
 
185
         * We copy the qualifications of the parsetree to the action and vice
 
186
         * versa. So force hasSubLinks if one of them has it. If this is not
 
187
         * right, the flag will get cleared later, but we mustn't risk having
 
188
         * it not set when it needs to be.      (XXX this should probably be
 
189
         * handled by AddQual and friends, not here...)
 
190
         */
 
191
        if (parsetree->hasSubLinks)
 
192
                sub_action->hasSubLinks = TRUE;
 
193
        else if (sub_action->hasSubLinks)
 
194
                parsetree->hasSubLinks = TRUE;
 
195
 
 
196
        /*
 
197
         * Event Qualification forces copying of parsetree and splitting into
 
198
         * two queries one w/rule_qual, one w/NOT rule_qual. Also add user
 
199
         * query qual onto rule action
 
200
         */
 
201
        AddQual(sub_action, rule_qual);
 
202
 
 
203
        AddQual(sub_action, parsetree->jointree->quals);
 
204
 
 
205
        /*
 
206
         * Rewrite new.attribute w/ right hand side of target-list entry for
 
207
         * appropriate field name in insert/update.
 
208
         *
 
209
         * KLUGE ALERT: since ResolveNew returns a mutated copy, we can't just
 
210
         * apply it to sub_action; we have to remember to update the sublink
 
211
         * inside rule_action, too.
 
212
         */
 
213
        if ((event == CMD_INSERT || event == CMD_UPDATE) &&
 
214
                sub_action->commandType != CMD_UTILITY)
 
215
        {
 
216
                sub_action = (Query *) ResolveNew((Node *) sub_action,
 
217
                                                                                  new_varno,
 
218
                                                                                  0,
 
219
                                                                                  sub_action->rtable,
 
220
                                                                                  parsetree->targetList,
 
221
                                                                                  event,
 
222
                                                                                  current_varno);
 
223
                if (sub_action_ptr)
 
224
                        *sub_action_ptr = sub_action;
 
225
                else
 
226
                        rule_action = sub_action;
 
227
        }
 
228
 
 
229
        return rule_action;
 
230
}
 
231
 
 
232
/*
 
233
 * Copy the query's jointree list, and optionally attempt to remove any
 
234
 * occurrence of the given rt_index as a top-level join item (we do not look
 
235
 * for it within join items; this is OK because we are only expecting to find
 
236
 * it as an UPDATE or DELETE target relation, which will be at the top level
 
237
 * of the join).  Returns modified jointree list --- this is a separate copy
 
238
 * sharing no nodes with the original.
 
239
 */
 
240
static List *
 
241
adjustJoinTreeList(Query *parsetree, bool removert, int rt_index)
 
242
{
 
243
        List       *newjointree = copyObject(parsetree->jointree->fromlist);
 
244
        ListCell   *l;
 
245
 
 
246
        if (removert)
 
247
        {
 
248
                foreach(l, newjointree)
 
249
                {
 
250
                        RangeTblRef *rtr = lfirst(l);
 
251
 
 
252
                        if (IsA(rtr, RangeTblRef) &&
 
253
                                rtr->rtindex == rt_index)
 
254
                        {
 
255
                                newjointree = list_delete_ptr(newjointree, rtr);
 
256
 
 
257
                                /*
 
258
                                 * foreach is safe because we exit loop after
 
259
                                 * list_delete...
 
260
                                 */
 
261
                                break;
 
262
                        }
 
263
                }
 
264
        }
 
265
        return newjointree;
 
266
}
 
267
 
 
268
 
 
269
/*
 
270
 * rewriteTargetList - rewrite INSERT/UPDATE targetlist into standard form
 
271
 *
 
272
 * This has the following responsibilities:
 
273
 *
 
274
 * 1. For an INSERT, add tlist entries to compute default values for any
 
275
 * attributes that have defaults and are not assigned to in the given tlist.
 
276
 * (We do not insert anything for default-less attributes, however.  The
 
277
 * planner will later insert NULLs for them, but there's no reason to slow
 
278
 * down rewriter processing with extra tlist nodes.)  Also, for both INSERT
 
279
 * and UPDATE, replace explicit DEFAULT specifications with column default
 
280
 * expressions.
 
281
 *
 
282
 * 2. Merge multiple entries for the same target attribute, or declare error
 
283
 * if we can't.  Multiple entries are only allowed for INSERT/UPDATE of
 
284
 * portions of an array or record field, for example
 
285
 *                      UPDATE table SET foo[2] = 42, foo[4] = 43;
 
286
 * We can merge such operations into a single assignment op.  Essentially,
 
287
 * the expression we want to produce in this case is like
 
288
 *              foo = array_set(array_set(foo, 2, 42), 4, 43)
 
289
 *
 
290
 * 3. Sort the tlist into standard order: non-junk fields in order by resno,
 
291
 * then junk fields (these in no particular order).
 
292
 *
 
293
 * We must do items 1 and 2 before firing rewrite rules, else rewritten
 
294
 * references to NEW.foo will produce wrong or incomplete results.      Item 3
 
295
 * is not needed for rewriting, but will be needed by the planner, and we
 
296
 * can do it essentially for free while handling items 1 and 2.
 
297
 */
 
298
static void
 
299
rewriteTargetList(Query *parsetree, Relation target_relation)
 
300
{
 
301
        CmdType         commandType = parsetree->commandType;
 
302
        List       *tlist = parsetree->targetList;
 
303
        List       *new_tlist = NIL;
 
304
        int                     attrno,
 
305
                                numattrs;
 
306
        ListCell   *temp;
 
307
 
 
308
        /*
 
309
         * Scan the tuple description in the relation's relcache entry to make
 
310
         * sure we have all the user attributes in the right order.
 
311
         */
 
312
        numattrs = RelationGetNumberOfAttributes(target_relation);
 
313
 
 
314
        for (attrno = 1; attrno <= numattrs; attrno++)
 
315
        {
 
316
                Form_pg_attribute att_tup = target_relation->rd_att->attrs[attrno - 1];
 
317
                TargetEntry *new_tle = NULL;
 
318
 
 
319
                /* We can ignore deleted attributes */
 
320
                if (att_tup->attisdropped)
 
321
                        continue;
 
322
 
 
323
                /*
 
324
                 * Look for targetlist entries matching this attr.
 
325
                 *
 
326
                 * Junk attributes are not candidates to be matched.
 
327
                 */
 
328
                foreach(temp, tlist)
 
329
                {
 
330
                        TargetEntry *old_tle = (TargetEntry *) lfirst(temp);
 
331
                        Resdom     *resdom = old_tle->resdom;
 
332
 
 
333
                        if (!resdom->resjunk && resdom->resno == attrno)
 
334
                        {
 
335
                                new_tle = process_matched_tle(old_tle, new_tle,
 
336
                                                                                          NameStr(att_tup->attname));
 
337
                                /* keep scanning to detect multiple assignments to attr */
 
338
                        }
 
339
                }
 
340
 
 
341
                /*
 
342
                 * Handle the two cases where we need to insert a default
 
343
                 * expression: it's an INSERT and there's no tlist entry for the
 
344
                 * column, or the tlist entry is a DEFAULT placeholder node.
 
345
                 */
 
346
                if ((new_tle == NULL && commandType == CMD_INSERT) ||
 
347
                  (new_tle && new_tle->expr && IsA(new_tle->expr, SetToDefault)))
 
348
                {
 
349
                        Node       *new_expr;
 
350
 
 
351
                        new_expr = build_column_default(target_relation, attrno);
 
352
 
 
353
                        /*
 
354
                         * If there is no default (ie, default is effectively NULL),
 
355
                         * we can omit the tlist entry in the INSERT case, since the
 
356
                         * planner can insert a NULL for itself, and there's no point
 
357
                         * in spending any more rewriter cycles on the entry.  But in
 
358
                         * the UPDATE case we've got to explicitly set the column to
 
359
                         * NULL.
 
360
                         */
 
361
                        if (!new_expr)
 
362
                        {
 
363
                                if (commandType == CMD_INSERT)
 
364
                                        new_tle = NULL;
 
365
                                else
 
366
                                {
 
367
                                        new_expr = (Node *) makeConst(att_tup->atttypid,
 
368
                                                                                                  att_tup->attlen,
 
369
                                                                                                  (Datum) 0,
 
370
                                                                                                  true, /* isnull */
 
371
                                                                                                  att_tup->attbyval);
 
372
                                        /* this is to catch a NOT NULL domain constraint */
 
373
                                        new_expr = coerce_to_domain(new_expr,
 
374
                                                                                                InvalidOid,
 
375
                                                                                                att_tup->atttypid,
 
376
                                                                                                COERCE_IMPLICIT_CAST,
 
377
                                                                                                false,
 
378
                                                                                                false);
 
379
                                }
 
380
                        }
 
381
 
 
382
                        if (new_expr)
 
383
                                new_tle = makeTargetEntry(makeResdom(attrno,
 
384
                                                                                                         att_tup->atttypid,
 
385
                                                                                                         att_tup->atttypmod,
 
386
                                                                          pstrdup(NameStr(att_tup->attname)),
 
387
                                                                                                         false),
 
388
                                                                                  (Expr *) new_expr);
 
389
                }
 
390
 
 
391
                if (new_tle)
 
392
                        new_tlist = lappend(new_tlist, new_tle);
 
393
        }
 
394
 
 
395
        /*
 
396
         * Copy all resjunk tlist entries to the end of the new tlist, and
 
397
         * assign them resnos above the last real resno.
 
398
         *
 
399
         * Typical junk entries include ORDER BY or GROUP BY expressions (are
 
400
         * these actually possible in an INSERT or UPDATE?), system attribute
 
401
         * references, etc.
 
402
         */
 
403
        foreach(temp, tlist)
 
404
        {
 
405
                TargetEntry *old_tle = (TargetEntry *) lfirst(temp);
 
406
                Resdom     *resdom = old_tle->resdom;
 
407
 
 
408
                if (resdom->resjunk)
 
409
                {
 
410
                        /* Get the resno right, but don't copy unnecessarily */
 
411
                        if (resdom->resno != attrno)
 
412
                        {
 
413
                                resdom = (Resdom *) copyObject((Node *) resdom);
 
414
                                resdom->resno = attrno;
 
415
                                old_tle = makeTargetEntry(resdom, old_tle->expr);
 
416
                        }
 
417
                        new_tlist = lappend(new_tlist, old_tle);
 
418
                        attrno++;
 
419
                }
 
420
                else
 
421
                {
 
422
                        /* Let's just make sure we processed all the non-junk items */
 
423
                        if (resdom->resno < 1 || resdom->resno > numattrs)
 
424
                                elog(ERROR, "bogus resno %d in targetlist", resdom->resno);
 
425
                }
 
426
        }
 
427
 
 
428
        parsetree->targetList = new_tlist;
 
429
}
 
430
 
 
431
 
 
432
/*
 
433
 * Convert a matched TLE from the original tlist into a correct new TLE.
 
434
 *
 
435
 * This routine detects and handles multiple assignments to the same target
 
436
 * attribute.  (The attribute name is needed only for error messages.)
 
437
 */
 
438
static TargetEntry *
 
439
process_matched_tle(TargetEntry *src_tle,
 
440
                                        TargetEntry *prior_tle,
 
441
                                        const char *attrName)
 
442
{
 
443
        Resdom     *resdom = src_tle->resdom;
 
444
        Node       *src_expr;
 
445
        Node       *prior_expr;
 
446
        Node       *src_input;
 
447
        Node       *prior_input;
 
448
        Node       *priorbottom;
 
449
        Node       *newexpr;
 
450
 
 
451
        if (prior_tle == NULL)
 
452
        {
 
453
                /*
 
454
                 * Normal case where this is the first assignment to the
 
455
                 * attribute.
 
456
                 */
 
457
                return src_tle;
 
458
        }
 
459
 
 
460
        /*----------
 
461
         * Multiple assignments to same attribute.      Allow only if all are
 
462
         * FieldStore or ArrayRef assignment operations.  This is a bit
 
463
         * tricky because what we may actually be looking at is a nest of
 
464
         * such nodes; consider
 
465
         *              UPDATE tab SET col.fld1.subfld1 = x, col.fld2.subfld2 = y
 
466
         * The two expressions produced by the parser will look like
 
467
         *              FieldStore(col, fld1, FieldStore(placeholder, subfld1, x))
 
468
         *              FieldStore(col, fld2, FieldStore(placeholder, subfld2, x))
 
469
         * However, we can ignore the substructure and just consider the top
 
470
         * FieldStore or ArrayRef from each assignment, because it works to
 
471
         * combine these as
 
472
         *              FieldStore(FieldStore(col, fld1,
 
473
         *                                                        FieldStore(placeholder, subfld1, x)),
 
474
         *                                 fld2, FieldStore(placeholder, subfld2, x))
 
475
         * Note the leftmost expression goes on the inside so that the
 
476
         * assignments appear to occur left-to-right.
 
477
         *
 
478
         * For FieldStore, instead of nesting we can generate a single
 
479
         * FieldStore with multiple target fields.      We must nest when
 
480
         * ArrayRefs are involved though.
 
481
         *----------
 
482
         */
 
483
        src_expr = (Node *) src_tle->expr;
 
484
        prior_expr = (Node *) prior_tle->expr;
 
485
        src_input = get_assignment_input(src_expr);
 
486
        prior_input = get_assignment_input(prior_expr);
 
487
        if (src_input == NULL ||
 
488
                prior_input == NULL ||
 
489
                exprType(src_expr) != exprType(prior_expr))
 
490
                ereport(ERROR,
 
491
                                (errcode(ERRCODE_SYNTAX_ERROR),
 
492
                                 errmsg("multiple assignments to same column \"%s\"",
 
493
                                                attrName)));
 
494
 
 
495
        /*
 
496
         * Prior TLE could be a nest of assignments if we do this more than
 
497
         * once.
 
498
         */
 
499
        priorbottom = prior_input;
 
500
        for (;;)
 
501
        {
 
502
                Node       *newbottom = get_assignment_input(priorbottom);
 
503
 
 
504
                if (newbottom == NULL)
 
505
                        break;                          /* found the original Var reference */
 
506
                priorbottom = newbottom;
 
507
        }
 
508
        if (!equal(priorbottom, src_input))
 
509
                ereport(ERROR,
 
510
                                (errcode(ERRCODE_SYNTAX_ERROR),
 
511
                                 errmsg("multiple assignments to same column \"%s\"",
 
512
                                                attrName)));
 
513
 
 
514
        /*
 
515
         * Looks OK to nest 'em.
 
516
         */
 
517
        if (IsA(src_expr, FieldStore))
 
518
        {
 
519
                FieldStore *fstore = makeNode(FieldStore);
 
520
 
 
521
                if (IsA(prior_expr, FieldStore))
 
522
                {
 
523
                        /* combine the two */
 
524
                        memcpy(fstore, prior_expr, sizeof(FieldStore));
 
525
                        fstore->newvals =
 
526
                                list_concat(list_copy(((FieldStore *) prior_expr)->newvals),
 
527
                                                  list_copy(((FieldStore *) src_expr)->newvals));
 
528
                        fstore->fieldnums =
 
529
                                list_concat(list_copy(((FieldStore *) prior_expr)->fieldnums),
 
530
                                                list_copy(((FieldStore *) src_expr)->fieldnums));
 
531
                }
 
532
                else
 
533
                {
 
534
                        /* general case, just nest 'em */
 
535
                        memcpy(fstore, src_expr, sizeof(FieldStore));
 
536
                        fstore->arg = (Expr *) prior_expr;
 
537
                }
 
538
                newexpr = (Node *) fstore;
 
539
        }
 
540
        else if (IsA(src_expr, ArrayRef))
 
541
        {
 
542
                ArrayRef   *aref = makeNode(ArrayRef);
 
543
 
 
544
                memcpy(aref, src_expr, sizeof(ArrayRef));
 
545
                aref->refexpr = (Expr *) prior_expr;
 
546
                newexpr = (Node *) aref;
 
547
        }
 
548
        else
 
549
        {
 
550
                elog(ERROR, "can't happen");
 
551
                newexpr = NULL;
 
552
        }
 
553
 
 
554
        return makeTargetEntry(resdom, (Expr *) newexpr);
 
555
}
 
556
 
 
557
/*
 
558
 * If node is an assignment node, return its input; else return NULL
 
559
 */
 
560
static Node *
 
561
get_assignment_input(Node *node)
 
562
{
 
563
        if (node == NULL)
 
564
                return NULL;
 
565
        if (IsA(node, FieldStore))
 
566
        {
 
567
                FieldStore *fstore = (FieldStore *) node;
 
568
 
 
569
                return (Node *) fstore->arg;
 
570
        }
 
571
        else if (IsA(node, ArrayRef))
 
572
        {
 
573
                ArrayRef   *aref = (ArrayRef *) node;
 
574
 
 
575
                if (aref->refassgnexpr == NULL)
 
576
                        return NULL;
 
577
                return (Node *) aref->refexpr;
 
578
        }
 
579
        return NULL;
 
580
}
 
581
 
 
582
/*
 
583
 * Make an expression tree for the default value for a column.
 
584
 *
 
585
 * If there is no default, return a NULL instead.
 
586
 */
 
587
Node *
 
588
build_column_default(Relation rel, int attrno)
 
589
{
 
590
        TupleDesc       rd_att = rel->rd_att;
 
591
        Form_pg_attribute att_tup = rd_att->attrs[attrno - 1];
 
592
        Oid                     atttype = att_tup->atttypid;
 
593
        int32           atttypmod = att_tup->atttypmod;
 
594
        Node       *expr = NULL;
 
595
        Oid                     exprtype;
 
596
 
 
597
        /*
 
598
         * Scan to see if relation has a default for this column.
 
599
         */
 
600
        if (rd_att->constr && rd_att->constr->num_defval > 0)
 
601
        {
 
602
                AttrDefault *defval = rd_att->constr->defval;
 
603
                int                     ndef = rd_att->constr->num_defval;
 
604
 
 
605
                while (--ndef >= 0)
 
606
                {
 
607
                        if (attrno == defval[ndef].adnum)
 
608
                        {
 
609
                                /*
 
610
                                 * Found it, convert string representation to node tree.
 
611
                                 */
 
612
                                expr = stringToNode(defval[ndef].adbin);
 
613
                                break;
 
614
                        }
 
615
                }
 
616
        }
 
617
 
 
618
        if (expr == NULL)
 
619
        {
 
620
                /*
 
621
                 * No per-column default, so look for a default for the type
 
622
                 * itself.
 
623
                 */
 
624
                expr = get_typdefault(atttype);
 
625
        }
 
626
 
 
627
        if (expr == NULL)
 
628
                return NULL;                    /* No default anywhere */
 
629
 
 
630
        /*
 
631
         * Make sure the value is coerced to the target column type; this will
 
632
         * generally be true already, but there seem to be some corner cases
 
633
         * involving domain defaults where it might not be true. This should
 
634
         * match the parser's processing of non-defaulted expressions --- see
 
635
         * updateTargetListEntry().
 
636
         */
 
637
        exprtype = exprType(expr);
 
638
 
 
639
        expr = coerce_to_target_type(NULL,      /* no UNKNOWN params here */
 
640
                                                                 expr, exprtype,
 
641
                                                                 atttype, atttypmod,
 
642
                                                                 COERCION_ASSIGNMENT,
 
643
                                                                 COERCE_IMPLICIT_CAST);
 
644
        if (expr == NULL)
 
645
                ereport(ERROR,
 
646
                                (errcode(ERRCODE_DATATYPE_MISMATCH),
 
647
                                 errmsg("column \"%s\" is of type %s"
 
648
                                                " but default expression is of type %s",
 
649
                                                NameStr(att_tup->attname),
 
650
                                                format_type_be(atttype),
 
651
                                                format_type_be(exprtype)),
 
652
                   errhint("You will need to rewrite or cast the expression.")));
 
653
 
 
654
        return expr;
 
655
}
 
656
 
 
657
 
 
658
/*
 
659
 * matchLocks -
 
660
 *        match the list of locks and returns the matching rules
 
661
 */
 
662
static List *
 
663
matchLocks(CmdType event,
 
664
                   RuleLock *rulelocks,
 
665
                   int varno,
 
666
                   Query *parsetree)
 
667
{
 
668
        List       *matching_locks = NIL;
 
669
        int                     nlocks;
 
670
        int                     i;
 
671
 
 
672
        if (rulelocks == NULL)
 
673
                return NIL;
 
674
 
 
675
        if (parsetree->commandType != CMD_SELECT)
 
676
        {
 
677
                if (parsetree->resultRelation != varno)
 
678
                        return NIL;
 
679
        }
 
680
 
 
681
        nlocks = rulelocks->numLocks;
 
682
 
 
683
        for (i = 0; i < nlocks; i++)
 
684
        {
 
685
                RewriteRule *oneLock = rulelocks->rules[i];
 
686
 
 
687
                if (oneLock->event == event)
 
688
                {
 
689
                        if (parsetree->commandType != CMD_SELECT ||
 
690
                                (oneLock->attrno == -1 ?
 
691
                                 rangeTableEntry_used((Node *) parsetree, varno, 0) :
 
692
                                 attribute_used((Node *) parsetree,
 
693
                                                                varno, oneLock->attrno, 0)))
 
694
                                matching_locks = lappend(matching_locks, oneLock);
 
695
                }
 
696
        }
 
697
 
 
698
        return matching_locks;
 
699
}
 
700
 
 
701
 
 
702
static Query *
 
703
ApplyRetrieveRule(Query *parsetree,
 
704
                                  RewriteRule *rule,
 
705
                                  int rt_index,
 
706
                                  bool relation_level,
 
707
                                  Relation relation,
 
708
                                  bool relIsUsed,
 
709
                                  List *activeRIRs)
 
710
{
 
711
        Query      *rule_action;
 
712
        RangeTblEntry *rte,
 
713
                           *subrte;
 
714
 
 
715
        if (list_length(rule->actions) != 1)
 
716
                elog(ERROR, "expected just one rule action");
 
717
        if (rule->qual != NULL)
 
718
                elog(ERROR, "cannot handle qualified ON SELECT rule");
 
719
        if (!relation_level)
 
720
                elog(ERROR, "cannot handle per-attribute ON SELECT rule");
 
721
 
 
722
        /*
 
723
         * Make a modifiable copy of the view query, and recursively expand
 
724
         * any view references inside it.
 
725
         */
 
726
        rule_action = copyObject(linitial(rule->actions));
 
727
 
 
728
        rule_action = fireRIRrules(rule_action, activeRIRs);
 
729
 
 
730
        /*
 
731
         * VIEWs are really easy --- just plug the view query in as a
 
732
         * subselect, replacing the relation's original RTE.
 
733
         */
 
734
        rte = rt_fetch(rt_index, parsetree->rtable);
 
735
 
 
736
        rte->rtekind = RTE_SUBQUERY;
 
737
        rte->relid = InvalidOid;
 
738
        rte->subquery = rule_action;
 
739
        rte->inh = false;                       /* must not be set for a subquery */
 
740
 
 
741
        /*
 
742
         * We move the view's permission check data down to its rangetable.
 
743
         * The checks will actually be done against the *OLD* entry therein.
 
744
         */
 
745
        subrte = rt_fetch(PRS2_OLD_VARNO, rule_action->rtable);
 
746
        Assert(subrte->relid == relation->rd_id);
 
747
        subrte->requiredPerms = rte->requiredPerms;
 
748
        subrte->checkAsUser = rte->checkAsUser;
 
749
 
 
750
        rte->requiredPerms = 0;         /* no permission check on subquery itself */
 
751
        rte->checkAsUser = 0;
 
752
 
 
753
        /*
 
754
         * FOR UPDATE of view?
 
755
         */
 
756
        if (list_member_int(parsetree->rowMarks, rt_index))
 
757
        {
 
758
                /*
 
759
                 * Remove the view from the list of rels that will actually be
 
760
                 * marked FOR UPDATE by the executor.  It will still be access-
 
761
                 * checked for write access, though.
 
762
                 */
 
763
                parsetree->rowMarks = list_delete_int(parsetree->rowMarks, rt_index);
 
764
 
 
765
                /*
 
766
                 * Set up the view's referenced tables as if FOR UPDATE.
 
767
                 */
 
768
                markQueryForUpdate(rule_action, true);
 
769
        }
 
770
 
 
771
        return parsetree;
 
772
}
 
773
 
 
774
/*
 
775
 * Recursively mark all relations used by a view as FOR UPDATE.
 
776
 *
 
777
 * This may generate an invalid query, eg if some sub-query uses an
 
778
 * aggregate.  We leave it to the planner to detect that.
 
779
 *
 
780
 * NB: this must agree with the parser's transformForUpdate() routine.
 
781
 */
 
782
static void
 
783
markQueryForUpdate(Query *qry, bool skipOldNew)
 
784
{
 
785
        Index           rti = 0;
 
786
        ListCell   *l;
 
787
 
 
788
        foreach(l, qry->rtable)
 
789
        {
 
790
                RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
 
791
 
 
792
                rti++;
 
793
 
 
794
                /* Ignore OLD and NEW entries if we are at top level of view */
 
795
                if (skipOldNew &&
 
796
                        (rti == PRS2_OLD_VARNO || rti == PRS2_NEW_VARNO))
 
797
                        continue;
 
798
 
 
799
                if (rte->rtekind == RTE_RELATION)
 
800
                {
 
801
                        if (!list_member_int(qry->rowMarks, rti))
 
802
                                qry->rowMarks = lappend_int(qry->rowMarks, rti);
 
803
                        rte->requiredPerms |= ACL_SELECT_FOR_UPDATE;
 
804
                }
 
805
                else if (rte->rtekind == RTE_SUBQUERY)
 
806
                {
 
807
                        /* FOR UPDATE of subquery is propagated to subquery's rels */
 
808
                        markQueryForUpdate(rte->subquery, false);
 
809
                }
 
810
        }
 
811
}
 
812
 
 
813
 
 
814
/*
 
815
 * fireRIRonSubLink -
 
816
 *      Apply fireRIRrules() to each SubLink (subselect in expression) found
 
817
 *      in the given tree.
 
818
 *
 
819
 * NOTE: although this has the form of a walker, we cheat and modify the
 
820
 * SubLink nodes in-place.      It is caller's responsibility to ensure that
 
821
 * no unwanted side-effects occur!
 
822
 *
 
823
 * This is unlike most of the other routines that recurse into subselects,
 
824
 * because we must take control at the SubLink node in order to replace
 
825
 * the SubLink's subselect link with the possibly-rewritten subquery.
 
826
 */
 
827
static bool
 
828
fireRIRonSubLink(Node *node, List *activeRIRs)
 
829
{
 
830
        if (node == NULL)
 
831
                return false;
 
832
        if (IsA(node, SubLink))
 
833
        {
 
834
                SubLink    *sub = (SubLink *) node;
 
835
 
 
836
                /* Do what we came for */
 
837
                sub->subselect = (Node *) fireRIRrules((Query *) sub->subselect,
 
838
                                                                                           activeRIRs);
 
839
                /* Fall through to process lefthand args of SubLink */
 
840
        }
 
841
 
 
842
        /*
 
843
         * Do NOT recurse into Query nodes, because fireRIRrules already
 
844
         * processed subselects of subselects for us.
 
845
         */
 
846
        return expression_tree_walker(node, fireRIRonSubLink,
 
847
                                                                  (void *) activeRIRs);
 
848
}
 
849
 
 
850
 
 
851
/*
 
852
 * fireRIRrules -
 
853
 *      Apply all RIR rules on each rangetable entry in a query
 
854
 */
 
855
static Query *
 
856
fireRIRrules(Query *parsetree, List *activeRIRs)
 
857
{
 
858
        int                     rt_index;
 
859
 
 
860
        /*
 
861
         * don't try to convert this into a foreach loop, because rtable list
 
862
         * can get changed each time through...
 
863
         */
 
864
        rt_index = 0;
 
865
        while (rt_index < list_length(parsetree->rtable))
 
866
        {
 
867
                RangeTblEntry *rte;
 
868
                Relation        rel;
 
869
                List       *locks;
 
870
                RuleLock   *rules;
 
871
                RewriteRule *rule;
 
872
                LOCKMODE        lockmode;
 
873
                bool            relIsUsed;
 
874
                int                     i;
 
875
 
 
876
                ++rt_index;
 
877
 
 
878
                rte = rt_fetch(rt_index, parsetree->rtable);
 
879
 
 
880
                /*
 
881
                 * A subquery RTE can't have associated rules, so there's nothing
 
882
                 * to do to this level of the query, but we must recurse into the
 
883
                 * subquery to expand any rule references in it.
 
884
                 */
 
885
                if (rte->rtekind == RTE_SUBQUERY)
 
886
                {
 
887
                        rte->subquery = fireRIRrules(rte->subquery, activeRIRs);
 
888
                        continue;
 
889
                }
 
890
 
 
891
                /*
 
892
                 * Joins and other non-relation RTEs can be ignored completely.
 
893
                 */
 
894
                if (rte->rtekind != RTE_RELATION)
 
895
                        continue;
 
896
 
 
897
                /*
 
898
                 * If the table is not referenced in the query, then we ignore it.
 
899
                 * This prevents infinite expansion loop due to new rtable entries
 
900
                 * inserted by expansion of a rule. A table is referenced if it is
 
901
                 * part of the join set (a source table), or is referenced by any
 
902
                 * Var nodes, or is the result table.
 
903
                 */
 
904
                relIsUsed = rangeTableEntry_used((Node *) parsetree, rt_index, 0);
 
905
 
 
906
                if (!relIsUsed && rt_index != parsetree->resultRelation)
 
907
                        continue;
 
908
 
 
909
                /*
 
910
                 * This may well be the first access to the relation during the
 
911
                 * current statement (it will be, if this Query was extracted from
 
912
                 * a rule or somehow got here other than via the parser).
 
913
                 * Therefore, grab the appropriate lock type for the relation, and
 
914
                 * do not release it until end of transaction.  This protects the
 
915
                 * rewriter and planner against schema changes mid-query.
 
916
                 *
 
917
                 * If the relation is the query's result relation, then
 
918
                 * RewriteQuery() already got the right lock on it, so we need no
 
919
                 * additional lock. Otherwise, check to see if the relation is
 
920
                 * accessed FOR UPDATE or not.
 
921
                 */
 
922
                if (rt_index == parsetree->resultRelation)
 
923
                        lockmode = NoLock;
 
924
                else if (list_member_int(parsetree->rowMarks, rt_index))
 
925
                        lockmode = RowShareLock;
 
926
                else
 
927
                        lockmode = AccessShareLock;
 
928
 
 
929
                rel = heap_open(rte->relid, lockmode);
 
930
 
 
931
                /*
 
932
                 * Collect the RIR rules that we must apply
 
933
                 */
 
934
                rules = rel->rd_rules;
 
935
                if (rules == NULL)
 
936
                {
 
937
                        heap_close(rel, NoLock);
 
938
                        continue;
 
939
                }
 
940
                locks = NIL;
 
941
                for (i = 0; i < rules->numLocks; i++)
 
942
                {
 
943
                        rule = rules->rules[i];
 
944
                        if (rule->event != CMD_SELECT)
 
945
                                continue;
 
946
 
 
947
                        if (rule->attrno > 0)
 
948
                        {
 
949
                                /* per-attr rule; do we need it? */
 
950
                                if (!attribute_used((Node *) parsetree, rt_index,
 
951
                                                                        rule->attrno, 0))
 
952
                                        continue;
 
953
                        }
 
954
 
 
955
                        locks = lappend(locks, rule);
 
956
                }
 
957
 
 
958
                /*
 
959
                 * If we found any, apply them --- but first check for recursion!
 
960
                 */
 
961
                if (locks != NIL)
 
962
                {
 
963
                        ListCell   *l;
 
964
 
 
965
                        if (list_member_oid(activeRIRs, RelationGetRelid(rel)))
 
966
                                ereport(ERROR,
 
967
                                                (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 
968
                                                 errmsg("infinite recursion detected in rules for relation \"%s\"",
 
969
                                                                RelationGetRelationName(rel))));
 
970
                        activeRIRs = lcons_oid(RelationGetRelid(rel), activeRIRs);
 
971
 
 
972
                        foreach(l, locks)
 
973
                        {
 
974
                                rule = lfirst(l);
 
975
 
 
976
                                parsetree = ApplyRetrieveRule(parsetree,
 
977
                                                                                          rule,
 
978
                                                                                          rt_index,
 
979
                                                                                          rule->attrno == -1,
 
980
                                                                                          rel,
 
981
                                                                                          relIsUsed,
 
982
                                                                                          activeRIRs);
 
983
                        }
 
984
 
 
985
                        activeRIRs = list_delete_first(activeRIRs);
 
986
                }
 
987
 
 
988
                heap_close(rel, NoLock);
 
989
        }
 
990
 
 
991
        /*
 
992
         * Recurse into sublink subqueries, too.  But we already did the ones
 
993
         * in the rtable.
 
994
         */
 
995
        if (parsetree->hasSubLinks)
 
996
                query_tree_walker(parsetree, fireRIRonSubLink, (void *) activeRIRs,
 
997
                                                  QTW_IGNORE_RT_SUBQUERIES);
 
998
 
 
999
        /*
 
1000
         * If the query was marked having aggregates, check if this is still
 
1001
         * true after rewriting.  Ditto for sublinks.  Note there should be no
 
1002
         * aggs in the qual at this point.      (Does this code still do anything
 
1003
         * useful?      The view-becomes-subselect-in-FROM approach doesn't look
 
1004
         * like it could remove aggs or sublinks...)
 
1005
         */
 
1006
        if (parsetree->hasAggs)
 
1007
        {
 
1008
                parsetree->hasAggs = checkExprHasAggs((Node *) parsetree);
 
1009
                if (parsetree->hasAggs)
 
1010
                        if (checkExprHasAggs((Node *) parsetree->jointree))
 
1011
                                elog(ERROR, "failed to remove aggregates from qual");
 
1012
        }
 
1013
        if (parsetree->hasSubLinks)
 
1014
                parsetree->hasSubLinks = checkExprHasSubLink((Node *) parsetree);
 
1015
 
 
1016
        return parsetree;
 
1017
}
 
1018
 
 
1019
 
 
1020
/*
 
1021
 * Modify the given query by adding 'AND rule_qual IS NOT TRUE' to its
 
1022
 * qualification.  This is used to generate suitable "else clauses" for
 
1023
 * conditional INSTEAD rules.  (Unfortunately we must use "x IS NOT TRUE",
 
1024
 * not just "NOT x" which the planner is much smarter about, else we will
 
1025
 * do the wrong thing when the qual evaluates to NULL.)
 
1026
 *
 
1027
 * The rule_qual may contain references to OLD or NEW.  OLD references are
 
1028
 * replaced by references to the specified rt_index (the relation that the
 
1029
 * rule applies to).  NEW references are only possible for INSERT and UPDATE
 
1030
 * queries on the relation itself, and so they should be replaced by copies
 
1031
 * of the related entries in the query's own targetlist.
 
1032
 */
 
1033
static Query *
 
1034
CopyAndAddInvertedQual(Query *parsetree,
 
1035
                                           Node *rule_qual,
 
1036
                                           int rt_index,
 
1037
                                           CmdType event)
 
1038
{
 
1039
        Query      *new_tree = (Query *) copyObject(parsetree);
 
1040
        Node       *new_qual = (Node *) copyObject(rule_qual);
 
1041
 
 
1042
        /* Fix references to OLD */
 
1043
        ChangeVarNodes(new_qual, PRS2_OLD_VARNO, rt_index, 0);
 
1044
        /* Fix references to NEW */
 
1045
        if (event == CMD_INSERT || event == CMD_UPDATE)
 
1046
                new_qual = ResolveNew(new_qual,
 
1047
                                                          PRS2_NEW_VARNO,
 
1048
                                                          0,
 
1049
                                                          parsetree->rtable,
 
1050
                                                          parsetree->targetList,
 
1051
                                                          event,
 
1052
                                                          rt_index);
 
1053
        /* And attach the fixed qual */
 
1054
        AddInvertedQual(new_tree, new_qual);
 
1055
 
 
1056
        return new_tree;
 
1057
}
 
1058
 
 
1059
 
 
1060
/*
 
1061
 *      fireRules -
 
1062
 *         Iterate through rule locks applying rules.
 
1063
 *
 
1064
 * Input arguments:
 
1065
 *      parsetree - original query
 
1066
 *      rt_index - RT index of result relation in original query
 
1067
 *      event - type of rule event
 
1068
 *      locks - list of rules to fire
 
1069
 * Output arguments:
 
1070
 *      *instead_flag - set TRUE if any unqualified INSTEAD rule is found
 
1071
 *                                      (must be initialized to FALSE)
 
1072
 *      *qual_product - filled with modified original query if any qualified
 
1073
 *                                      INSTEAD rule is found (must be initialized to NULL)
 
1074
 * Return value:
 
1075
 *      list of rule actions adjusted for use with this query
 
1076
 *
 
1077
 * Qualified INSTEAD rules generate their action with the qualification
 
1078
 * condition added.  They also generate a modified version of the original
 
1079
 * query with the negated qualification added, so that it will run only for
 
1080
 * rows that the qualified action doesn't act on.  (If there are multiple
 
1081
 * qualified INSTEAD rules, we AND all the negated quals onto a single
 
1082
 * modified original query.)  We won't execute the original, unmodified
 
1083
 * query if we find either qualified or unqualified INSTEAD rules.      If
 
1084
 * we find both, the modified original query is discarded too.
 
1085
 */
 
1086
static List *
 
1087
fireRules(Query *parsetree,
 
1088
                  int rt_index,
 
1089
                  CmdType event,
 
1090
                  List *locks,
 
1091
                  bool *instead_flag,
 
1092
                  Query **qual_product)
 
1093
{
 
1094
        List       *results = NIL;
 
1095
        ListCell   *l;
 
1096
 
 
1097
        foreach(l, locks)
 
1098
        {
 
1099
                RewriteRule *rule_lock = (RewriteRule *) lfirst(l);
 
1100
                Node       *event_qual = rule_lock->qual;
 
1101
                List       *actions = rule_lock->actions;
 
1102
                QuerySource qsrc;
 
1103
                ListCell   *r;
 
1104
 
 
1105
                /* Determine correct QuerySource value for actions */
 
1106
                if (rule_lock->isInstead)
 
1107
                {
 
1108
                        if (event_qual != NULL)
 
1109
                                qsrc = QSRC_QUAL_INSTEAD_RULE;
 
1110
                        else
 
1111
                        {
 
1112
                                qsrc = QSRC_INSTEAD_RULE;
 
1113
                                *instead_flag = true;   /* report unqualified INSTEAD */
 
1114
                        }
 
1115
                }
 
1116
                else
 
1117
                        qsrc = QSRC_NON_INSTEAD_RULE;
 
1118
 
 
1119
                if (qsrc == QSRC_QUAL_INSTEAD_RULE)
 
1120
                {
 
1121
                        /*
 
1122
                         * If there are INSTEAD rules with qualifications, the
 
1123
                         * original query is still performed. But all the negated rule
 
1124
                         * qualifications of the INSTEAD rules are added so it does
 
1125
                         * its actions only in cases where the rule quals of all
 
1126
                         * INSTEAD rules are false. Think of it as the default action
 
1127
                         * in a case. We save this in *qual_product so RewriteQuery()
 
1128
                         * can add it to the query list after we mangled it up enough.
 
1129
                         *
 
1130
                         * If we have already found an unqualified INSTEAD rule, then
 
1131
                         * *qual_product won't be used, so don't bother building it.
 
1132
                         */
 
1133
                        if (!*instead_flag)
 
1134
                        {
 
1135
                                if (*qual_product == NULL)
 
1136
                                        *qual_product = parsetree;
 
1137
                                *qual_product = CopyAndAddInvertedQual(*qual_product,
 
1138
                                                                                                           event_qual,
 
1139
                                                                                                           rt_index,
 
1140
                                                                                                           event);
 
1141
                        }
 
1142
                }
 
1143
 
 
1144
                /* Now process the rule's actions and add them to the result list */
 
1145
                foreach(r, actions)
 
1146
                {
 
1147
                        Query      *rule_action = lfirst(r);
 
1148
 
 
1149
                        if (rule_action->commandType == CMD_NOTHING)
 
1150
                                continue;
 
1151
 
 
1152
                        rule_action = rewriteRuleAction(parsetree, rule_action,
 
1153
                                                                                        event_qual, rt_index, event);
 
1154
 
 
1155
                        rule_action->querySource = qsrc;
 
1156
                        rule_action->canSetTag = false;         /* might change later */
 
1157
 
 
1158
                        results = lappend(results, rule_action);
 
1159
                }
 
1160
        }
 
1161
 
 
1162
        return results;
 
1163
}
 
1164
 
 
1165
 
 
1166
/*
 
1167
 * RewriteQuery -
 
1168
 *        rewrites the query and apply the rules again on the queries rewritten
 
1169
 *
 
1170
 * rewrite_events is a list of open query-rewrite actions, so we can detect
 
1171
 * infinite recursion.
 
1172
 */
 
1173
static List *
 
1174
RewriteQuery(Query *parsetree, List *rewrite_events)
 
1175
{
 
1176
        CmdType         event = parsetree->commandType;
 
1177
        bool            instead = false;
 
1178
        Query      *qual_product = NULL;
 
1179
        List       *rewritten = NIL;
 
1180
 
 
1181
        /*
 
1182
         * If the statement is an update, insert or delete - fire rules on it.
 
1183
         *
 
1184
         * SELECT rules are handled later when we have all the queries that
 
1185
         * should get executed.  Also, utilities aren't rewritten at all (do
 
1186
         * we still need that check?)
 
1187
         */
 
1188
        if (event != CMD_SELECT && event != CMD_UTILITY)
 
1189
        {
 
1190
                int                     result_relation;
 
1191
                RangeTblEntry *rt_entry;
 
1192
                Relation        rt_entry_relation;
 
1193
                List       *locks;
 
1194
 
 
1195
                result_relation = parsetree->resultRelation;
 
1196
                Assert(result_relation != 0);
 
1197
                rt_entry = rt_fetch(result_relation, parsetree->rtable);
 
1198
                Assert(rt_entry->rtekind == RTE_RELATION);
 
1199
 
 
1200
                /*
 
1201
                 * This may well be the first access to the result relation during
 
1202
                 * the current statement (it will be, if this Query was extracted
 
1203
                 * from a rule or somehow got here other than via the parser).
 
1204
                 * Therefore, grab the appropriate lock type for a result
 
1205
                 * relation, and do not release it until end of transaction.  This
 
1206
                 * protects the rewriter and planner against schema changes
 
1207
                 * mid-query.
 
1208
                 */
 
1209
                rt_entry_relation = heap_open(rt_entry->relid, RowExclusiveLock);
 
1210
 
 
1211
                /*
 
1212
                 * If it's an INSERT or UPDATE, rewrite the targetlist into
 
1213
                 * standard form.  This will be needed by the planner anyway, and
 
1214
                 * doing it now ensures that any references to NEW.field will
 
1215
                 * behave sanely.
 
1216
                 */
 
1217
                if (event == CMD_INSERT || event == CMD_UPDATE)
 
1218
                        rewriteTargetList(parsetree, rt_entry_relation);
 
1219
 
 
1220
                /*
 
1221
                 * Collect and apply the appropriate rules.
 
1222
                 */
 
1223
                locks = matchLocks(event, rt_entry_relation->rd_rules,
 
1224
                                                   result_relation, parsetree);
 
1225
 
 
1226
                if (locks != NIL)
 
1227
                {
 
1228
                        List       *product_queries;
 
1229
 
 
1230
                        product_queries = fireRules(parsetree,
 
1231
                                                                                result_relation,
 
1232
                                                                                event,
 
1233
                                                                                locks,
 
1234
                                                                                &instead,
 
1235
                                                                                &qual_product);
 
1236
 
 
1237
                        /*
 
1238
                         * If we got any product queries, recursively rewrite them ---
 
1239
                         * but first check for recursion!
 
1240
                         */
 
1241
                        if (product_queries != NIL)
 
1242
                        {
 
1243
                                ListCell   *n;
 
1244
                                rewrite_event *rev;
 
1245
 
 
1246
                                foreach(n, rewrite_events)
 
1247
                                {
 
1248
                                        rev = (rewrite_event *) lfirst(n);
 
1249
                                        if (rev->relation == RelationGetRelid(rt_entry_relation) &&
 
1250
                                                rev->event == event)
 
1251
                                                ereport(ERROR,
 
1252
                                                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 
1253
                                                          errmsg("infinite recursion detected in rules for relation \"%s\"",
 
1254
                                                   RelationGetRelationName(rt_entry_relation))));
 
1255
                                }
 
1256
 
 
1257
                                rev = (rewrite_event *) palloc(sizeof(rewrite_event));
 
1258
                                rev->relation = RelationGetRelid(rt_entry_relation);
 
1259
                                rev->event = event;
 
1260
                                rewrite_events = lcons(rev, rewrite_events);
 
1261
 
 
1262
                                foreach(n, product_queries)
 
1263
                                {
 
1264
                                        Query      *pt = (Query *) lfirst(n);
 
1265
                                        List       *newstuff;
 
1266
 
 
1267
                                        newstuff = RewriteQuery(pt, rewrite_events);
 
1268
                                        rewritten = list_concat(rewritten, newstuff);
 
1269
                                }
 
1270
 
 
1271
                                rewrite_events = list_delete_first(rewrite_events);
 
1272
                        }
 
1273
                }
 
1274
 
 
1275
                heap_close(rt_entry_relation, NoLock);  /* keep lock! */
 
1276
        }
 
1277
 
 
1278
        /*
 
1279
         * For INSERTs, the original query is done first; for UPDATE/DELETE,
 
1280
         * it is done last.  This is needed because update and delete rule
 
1281
         * actions might not do anything if they are invoked after the update
 
1282
         * or delete is performed. The command counter increment between the
 
1283
         * query executions makes the deleted (and maybe the updated) tuples
 
1284
         * disappear so the scans for them in the rule actions cannot find
 
1285
         * them.
 
1286
         *
 
1287
         * If we found any unqualified INSTEAD, the original query is not done at
 
1288
         * all, in any form.  Otherwise, we add the modified form if qualified
 
1289
         * INSTEADs were found, else the unmodified form.
 
1290
         */
 
1291
        if (!instead)
 
1292
        {
 
1293
                if (parsetree->commandType == CMD_INSERT)
 
1294
                {
 
1295
                        if (qual_product != NULL)
 
1296
                                rewritten = lcons(qual_product, rewritten);
 
1297
                        else
 
1298
                                rewritten = lcons(parsetree, rewritten);
 
1299
                }
 
1300
                else
 
1301
                {
 
1302
                        if (qual_product != NULL)
 
1303
                                rewritten = lappend(rewritten, qual_product);
 
1304
                        else
 
1305
                                rewritten = lappend(rewritten, parsetree);
 
1306
                }
 
1307
        }
 
1308
 
 
1309
        return rewritten;
 
1310
}
 
1311
 
 
1312
 
 
1313
/*
 
1314
 * QueryRewrite -
 
1315
 *        Primary entry point to the query rewriter.
 
1316
 *        Rewrite one query via query rewrite system, possibly returning 0
 
1317
 *        or many queries.
 
1318
 *
 
1319
 * NOTE: The code in QueryRewrite was formerly in pg_parse_and_plan(), and was
 
1320
 * moved here so that it would be invoked during EXPLAIN.
 
1321
 */
 
1322
List *
 
1323
QueryRewrite(Query *parsetree)
 
1324
{
 
1325
        List       *querylist;
 
1326
        List       *results = NIL;
 
1327
        ListCell   *l;
 
1328
        CmdType         origCmdType;
 
1329
        bool            foundOriginalQuery;
 
1330
        Query      *lastInstead;
 
1331
 
 
1332
        /*
 
1333
         * Step 1
 
1334
         *
 
1335
         * Apply all non-SELECT rules possibly getting 0 or many queries
 
1336
         */
 
1337
        querylist = RewriteQuery(parsetree, NIL);
 
1338
 
 
1339
        /*
 
1340
         * Step 2
 
1341
         *
 
1342
         * Apply all the RIR rules on each query
 
1343
         */
 
1344
        foreach(l, querylist)
 
1345
        {
 
1346
                Query      *query = (Query *) lfirst(l);
 
1347
 
 
1348
                query = fireRIRrules(query, NIL);
 
1349
 
 
1350
                /*
 
1351
                 * If the query target was rewritten as a view, complain.
 
1352
                 */
 
1353
                if (query->resultRelation)
 
1354
                {
 
1355
                        RangeTblEntry *rte = rt_fetch(query->resultRelation,
 
1356
                                                                                  query->rtable);
 
1357
 
 
1358
                        if (rte->rtekind == RTE_SUBQUERY)
 
1359
                        {
 
1360
                                switch (query->commandType)
 
1361
                                {
 
1362
                                        case CMD_INSERT:
 
1363
                                                ereport(ERROR,
 
1364
                                                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 
1365
                                                                 errmsg("cannot insert into a view"),
 
1366
                                                                 errhint("You need an unconditional ON INSERT DO INSTEAD rule.")));
 
1367
                                                break;
 
1368
                                        case CMD_UPDATE:
 
1369
                                                ereport(ERROR,
 
1370
                                                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 
1371
                                                                 errmsg("cannot update a view"),
 
1372
                                                                 errhint("You need an unconditional ON UPDATE DO INSTEAD rule.")));
 
1373
                                                break;
 
1374
                                        case CMD_DELETE:
 
1375
                                                ereport(ERROR,
 
1376
                                                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 
1377
                                                                 errmsg("cannot delete from a view"),
 
1378
                                                                 errhint("You need an unconditional ON DELETE DO INSTEAD rule.")));
 
1379
                                                break;
 
1380
                                        default:
 
1381
                                                elog(ERROR, "unrecognized commandType: %d",
 
1382
                                                         (int) query->commandType);
 
1383
                                                break;
 
1384
                                }
 
1385
                        }
 
1386
                }
 
1387
 
 
1388
                results = lappend(results, query);
 
1389
        }
 
1390
 
 
1391
        /*
 
1392
         * Step 3
 
1393
         *
 
1394
         * Determine which, if any, of the resulting queries is supposed to set
 
1395
         * the command-result tag; and update the canSetTag fields
 
1396
         * accordingly.
 
1397
         *
 
1398
         * If the original query is still in the list, it sets the command tag.
 
1399
         * Otherwise, the last INSTEAD query of the same kind as the original
 
1400
         * is allowed to set the tag.  (Note these rules can leave us with no
 
1401
         * query setting the tag.  The tcop code has to cope with this by
 
1402
         * setting up a default tag based on the original un-rewritten query.)
 
1403
         *
 
1404
         * The Asserts verify that at most one query in the result list is marked
 
1405
         * canSetTag.  If we aren't checking asserts, we can fall out of the
 
1406
         * loop as soon as we find the original query.
 
1407
         */
 
1408
        origCmdType = parsetree->commandType;
 
1409
        foundOriginalQuery = false;
 
1410
        lastInstead = NULL;
 
1411
 
 
1412
        foreach(l, results)
 
1413
        {
 
1414
                Query      *query = (Query *) lfirst(l);
 
1415
 
 
1416
                if (query->querySource == QSRC_ORIGINAL)
 
1417
                {
 
1418
                        Assert(query->canSetTag);
 
1419
                        Assert(!foundOriginalQuery);
 
1420
                        foundOriginalQuery = true;
 
1421
#ifndef USE_ASSERT_CHECKING
 
1422
                        break;
 
1423
#endif
 
1424
                }
 
1425
                else
 
1426
                {
 
1427
                        Assert(!query->canSetTag);
 
1428
                        if (query->commandType == origCmdType &&
 
1429
                                (query->querySource == QSRC_INSTEAD_RULE ||
 
1430
                                 query->querySource == QSRC_QUAL_INSTEAD_RULE))
 
1431
                                lastInstead = query;
 
1432
                }
 
1433
        }
 
1434
 
 
1435
        if (!foundOriginalQuery && lastInstead != NULL)
 
1436
                lastInstead->canSetTag = true;
 
1437
 
 
1438
        return results;
 
1439
}