]> granicus.if.org Git - postgresql/blob - src/backend/rewrite/rewriteManip.c
Add support for the CASE statement in the rewrite handling.
[postgresql] / src / backend / rewrite / rewriteManip.c
1 /*-------------------------------------------------------------------------
2  *
3  * rewriteManip.c--
4  *
5  * Copyright (c) 1994, Regents of the University of California
6  *
7  *
8  * IDENTIFICATION
9  *        $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.23 1998/12/14 00:02:17 thomas Exp $
10  *
11  *-------------------------------------------------------------------------
12  */
13 #include <string.h>
14 #include "postgres.h"
15 #include "nodes/pg_list.h"
16 #include "utils/elog.h"
17 #include "nodes/nodes.h"
18 #include "nodes/relation.h"
19 #include "nodes/primnodes.h"
20 #include "parser/parsetree.h"   /* for getrelid() */
21 #include "utils/lsyscache.h"
22 #include "utils/builtins.h"
23 #include "rewrite/rewriteHandler.h"
24 #include "rewrite/rewriteManip.h"
25 #include "rewrite/rewriteSupport.h"
26 #include "rewrite/locks.h"
27
28 #include "nodes/plannodes.h"
29 #include "optimizer/clauses.h"
30
31 static void ResolveNew(RewriteInfo *info, List *targetlist,
32                    Node **node, int sublevels_up);
33
34
35 /*
36  * OffsetVarnodes -
37  */
38 void
39 OffsetVarNodes(Node *node, int offset, int sublevels_up)
40 {
41         if (node == NULL)
42                 return;
43
44         switch(nodeTag(node)) {
45                 case T_TargetEntry:
46                         {
47                                 TargetEntry     *tle = (TargetEntry *)node;
48
49                                 OffsetVarNodes(
50                                                 (Node *)(tle->expr),
51                                                 offset,
52                                                 sublevels_up);
53                         }
54                         break;
55
56                 case T_Aggreg:
57                         {
58                                 Aggreg  *agg = (Aggreg *)node;
59
60                                 OffsetVarNodes(
61                                                 (Node *)(agg->target),
62                                                 offset,
63                                                 sublevels_up);
64                         }
65                         break;
66
67                 case T_GroupClause:
68                         {
69                                 GroupClause     *grp = (GroupClause *)node;
70
71                                 OffsetVarNodes(
72                                                 (Node *)(grp->entry),
73                                                 offset,
74                                                 sublevels_up);
75                         }
76                         break;
77
78                 case T_Expr:
79                         {
80                                 Expr    *exp = (Expr *)node;
81
82                                 OffsetVarNodes(
83                                                 (Node *)(exp->args),
84                                                 offset,
85                                                 sublevels_up);
86                         }
87                         break;
88
89                 case T_Iter:
90                         {
91                                 Iter    *iter = (Iter *)node;
92
93                                 OffsetVarNodes(
94                                                 (Node *)(iter->iterexpr),
95                                                 offset,
96                                                 sublevels_up);
97                         }
98                         break;
99
100                 case T_ArrayRef:
101                         {
102                                 ArrayRef        *ref = (ArrayRef *)node;
103
104                                 OffsetVarNodes(
105                                                 (Node *)(ref->refupperindexpr),
106                                                 offset,
107                                                 sublevels_up);
108                                 OffsetVarNodes(
109                                                 (Node *)(ref->reflowerindexpr),
110                                                 offset,
111                                                 sublevels_up);
112                                 OffsetVarNodes(
113                                                 (Node *)(ref->refexpr),
114                                                 offset,
115                                                 sublevels_up);
116                                 OffsetVarNodes(
117                                                 (Node *)(ref->refassgnexpr),
118                                                 offset,
119                                                 sublevels_up);
120                         }
121                         break;
122
123                 case T_Var:
124                         {
125                                 Var     *var = (Var *)node;
126
127                                 if (var->varlevelsup == sublevels_up) {
128                                         var->varno += offset;
129                                         var->varnoold += offset;
130                                 }
131                         }
132                         break;
133
134                 case T_Param:
135                         break;
136
137                 case T_Const:
138                         break;
139
140                 case T_List:
141                         {
142                                 List    *l;
143
144                                 foreach (l, (List *)node)
145                                         OffsetVarNodes(
146                                                         (Node *)lfirst(l),
147                                                         offset,
148                                                         sublevels_up);
149                         }
150                         break;
151
152                 case T_SubLink:
153                         {
154                                 SubLink *sub = (SubLink *)node;
155
156                                 OffsetVarNodes(
157                                                 (Node *)(sub->lefthand),
158                                                 offset,
159                                                 sublevels_up);
160
161                                 OffsetVarNodes(
162                                                 (Node *)(sub->subselect),
163                                                 offset,
164                                                 sublevels_up + 1);
165                         }
166                         break;
167
168                 case T_Query:
169                         {
170                                 Query   *qry = (Query *)node;
171
172                                 OffsetVarNodes(
173                                                 (Node *)(qry->targetList),
174                                                 offset,
175                                                 sublevels_up);
176
177                                 OffsetVarNodes(
178                                                 (Node *)(qry->qual),
179                                                 offset,
180                                                 sublevels_up);
181
182                                 OffsetVarNodes(
183                                                 (Node *)(qry->havingQual),
184                                                 offset,
185                                                 sublevels_up);
186
187                                 OffsetVarNodes(
188                                                 (Node *)(qry->groupClause),
189                                                 offset,
190                                                 sublevels_up);
191                         }
192                         break;
193
194                 case T_CaseExpr:
195                         {
196                                 CaseExpr        *exp = (CaseExpr *)node;
197
198                                 OffsetVarNodes(
199                                                 (Node *)(exp->args),
200                                                 offset,
201                                                 sublevels_up);
202
203                                 OffsetVarNodes(
204                                                 (Node *)(exp->defresult),
205                                                 offset,
206                                                 sublevels_up);
207                         }
208                         break;
209
210                 case T_CaseWhen:
211                         {
212                                 CaseWhen        *exp = (CaseWhen *)node;
213
214                                 OffsetVarNodes(
215                                                 (Node *)(exp->expr),
216                                                 offset,
217                                                 sublevels_up);
218
219                                 OffsetVarNodes(
220                                                 (Node *)(exp->result),
221                                                 offset,
222                                                 sublevels_up);
223                         }
224                         break;
225
226                 default:
227                         elog(NOTICE, "unknown node tag %d in OffsetVarNodes()", nodeTag(node));
228                         elog(NOTICE, "Node is: %s", nodeToString(node));
229                         break;
230
231
232         }
233 }
234
235
236 /*
237  * ChangeVarNodes -
238  */
239 void
240 ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)
241 {
242         if (node == NULL)
243                 return;
244
245         switch(nodeTag(node)) {
246                 case T_TargetEntry:
247                         {
248                                 TargetEntry     *tle = (TargetEntry *)node;
249
250                                 ChangeVarNodes(
251                                                 (Node *)(tle->expr),
252                                                 rt_index,
253                                                 new_index,
254                                                 sublevels_up);
255                         }
256                         break;
257
258                 case T_Aggreg:
259                         {
260                                 Aggreg  *agg = (Aggreg *)node;
261
262                                 ChangeVarNodes(
263                                                 (Node *)(agg->target),
264                                                 rt_index,
265                                                 new_index,
266                                                 sublevels_up);
267                         }
268                         break;
269
270                 case T_GroupClause:
271                         {
272                                 GroupClause     *grp = (GroupClause *)node;
273
274                                 ChangeVarNodes(
275                                                 (Node *)(grp->entry),
276                                                 rt_index,
277                                                 new_index,
278                                                 sublevels_up);
279                         }
280                         break;
281
282                 case T_Expr:
283                         {
284                                 Expr    *exp = (Expr *)node;
285
286                                 ChangeVarNodes(
287                                                 (Node *)(exp->args),
288                                                 rt_index,
289                                                 new_index,
290                                                 sublevels_up);
291                         }
292                         break;
293
294                 case T_Iter:
295                         {
296                                 Iter    *iter = (Iter *)node;
297
298                                 ChangeVarNodes(
299                                                 (Node *)(iter->iterexpr),
300                                                 rt_index,
301                                                 new_index,
302                                                 sublevels_up);
303                         }
304                         break;
305
306                 case T_ArrayRef:
307                         {
308                                 ArrayRef        *ref = (ArrayRef *)node;
309
310                                 ChangeVarNodes(
311                                                 (Node *)(ref->refupperindexpr),
312                                                 rt_index,
313                                                 new_index,
314                                                 sublevels_up);
315                                 ChangeVarNodes(
316                                                 (Node *)(ref->reflowerindexpr),
317                                                 rt_index,
318                                                 new_index,
319                                                 sublevels_up);
320                                 ChangeVarNodes(
321                                                 (Node *)(ref->refexpr),
322                                                 rt_index,
323                                                 new_index,
324                                                 sublevels_up);
325                                 ChangeVarNodes(
326                                                 (Node *)(ref->refassgnexpr),
327                                                 rt_index,
328                                                 new_index,
329                                                 sublevels_up);
330                         }
331                         break;
332
333                 case T_Var:
334                         {
335                                 Var     *var = (Var *)node;
336
337                                 if (var->varlevelsup == sublevels_up &&
338                                                 var->varno == rt_index) {
339                                         var->varno = new_index;
340                                         var->varnoold = new_index;
341                                 }
342                         }
343                         break;
344
345                 case T_Param:
346                         break;
347
348                 case T_Const:
349                         break;
350
351                 case T_List:
352                         {
353                                 List    *l;
354
355                                 foreach (l, (List *)node)
356                                         ChangeVarNodes(
357                                                         (Node *)lfirst(l),
358                                                         rt_index,
359                                                         new_index,
360                                                         sublevels_up);
361                         }
362                         break;
363
364                 case T_SubLink:
365                         {
366                                 SubLink *sub = (SubLink *)node;
367
368                                 ChangeVarNodes(
369                                                 (Node *)(sub->lefthand),
370                                                 rt_index,
371                                                 new_index,
372                                                 sublevels_up);
373
374                                 ChangeVarNodes(
375                                                 (Node *)(sub->subselect),
376                                                 rt_index,
377                                                 new_index,
378                                                 sublevels_up + 1);
379                         }
380                         break;
381
382                 case T_Query:
383                         {
384                                 Query   *qry = (Query *)node;
385
386                                 ChangeVarNodes(
387                                                 (Node *)(qry->targetList),
388                                                 rt_index,
389                                                 new_index,
390                                                 sublevels_up);
391
392                                 ChangeVarNodes(
393                                                 (Node *)(qry->qual),
394                                                 rt_index,
395                                                 new_index,
396                                                 sublevels_up);
397
398                                 ChangeVarNodes(
399                                                 (Node *)(qry->havingQual),
400                                                 rt_index,
401                                                 new_index,
402                                                 sublevels_up);
403
404                                 ChangeVarNodes(
405                                                 (Node *)(qry->groupClause),
406                                                 rt_index,
407                                                 new_index,
408                                                 sublevels_up);
409                         }
410                         break;
411
412                 case T_CaseExpr:
413                         {
414                                 CaseExpr        *exp = (CaseExpr *)node;
415
416                                 ChangeVarNodes(
417                                                 (Node *)(exp->args),
418                                                 rt_index,
419                                                 new_index,
420                                                 sublevels_up);
421
422                                 ChangeVarNodes(
423                                                 (Node *)(exp->defresult),
424                                                 rt_index,
425                                                 new_index,
426                                                 sublevels_up);
427                         }
428                         break;
429
430                 case T_CaseWhen:
431                         {
432                                 CaseWhen        *exp = (CaseWhen *)node;
433
434                                 ChangeVarNodes(
435                                                 (Node *)(exp->expr),
436                                                 rt_index,
437                                                 new_index,
438                                                 sublevels_up);
439
440                                 ChangeVarNodes(
441                                                 (Node *)(exp->result),
442                                                 rt_index,
443                                                 new_index,
444                                                 sublevels_up);
445                         }
446                         break;
447
448                 default:
449                         elog(NOTICE, "unknown node tag %d in ChangeVarNodes()", nodeTag(node));
450                         elog(NOTICE, "Node is: %s", nodeToString(node));
451                         break;
452
453
454         }
455 }
456
457
458
459 void
460 AddQual(Query *parsetree, Node *qual)
461 {
462         Node       *copy,
463                            *old;
464
465         if (qual == NULL)
466                 return;
467
468         copy = copyObject(qual);
469         old = parsetree->qual;
470         if (old == NULL)
471                 parsetree->qual = copy;
472         else
473                 parsetree->qual =
474                         (Node *) make_andclause(makeList(parsetree->qual, copy, -1));
475 }
476
477 /* Adds the given havingQual to the one already contained in the parsetree just as
478  * AddQual does for the normal 'where' qual */
479 void
480 AddHavingQual(Query *parsetree, Node *havingQual)
481 {
482         Node       *copy,
483                            *old;
484
485         if (havingQual == NULL)
486                 return;
487
488         copy = copyObject(havingQual);
489         old = parsetree->havingQual;
490         if (old == NULL)
491                 parsetree->havingQual = copy;
492         else
493                 parsetree->havingQual =
494                         (Node *) make_andclause(makeList(parsetree->havingQual, copy, -1));
495 }
496
497
498 void
499 AddNotQual(Query *parsetree, Node *qual)
500 {
501         Node       *copy;
502
503         if (qual == NULL)
504                 return;
505
506         copy = (Node *) make_notclause(copyObject(qual));
507
508         AddQual(parsetree, copy);
509 }
510
511 static Node *
512 make_null(Oid type)
513 {
514         Const      *c = makeNode(Const);
515
516         c->consttype = type;
517         c->constlen = get_typlen(type);
518         c->constvalue = PointerGetDatum(NULL);
519         c->constisnull = true;
520         c->constbyval = get_typbyval(type);
521         return (Node *) c;
522 }
523
524 #ifdef NOT_USED
525 void
526 FixResdomTypes(List *tlist)
527 {
528         List       *i;
529
530         foreach(i, tlist)
531         {
532                 TargetEntry *tle = lfirst(i);
533
534                 if (nodeTag(tle->expr) == T_Var)
535                 {
536                         Var                *var = (Var *) tle->expr;
537
538                         tle->resdom->restype = var->vartype;
539                         tle->resdom->restypmod = var->vartypmod;
540                 }
541         }
542 }
543 #endif
544
545 static Node *
546 FindMatchingNew(List *tlist, int attno)
547 {
548         List       *i;
549
550         foreach(i, tlist)
551         {
552                 TargetEntry *tle = lfirst(i);
553
554                 if (tle->resdom->resno == attno)
555                         return tle->expr;
556         }
557         return NULL;
558 }
559
560 static Node *
561 FindMatchingTLEntry(List *tlist, char *e_attname)
562 {
563         List       *i;
564
565         foreach(i, tlist)
566         {
567                 TargetEntry *tle = lfirst(i);
568                 char       *resname;
569
570                 resname = tle->resdom->resname;
571                 if (!strcmp(e_attname, resname))
572                         return tle->expr;
573         }
574         return NULL;
575 }
576
577 static void
578 ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr,
579                    int sublevels_up)
580 {
581         Node       *node = *nodePtr;
582
583         if (node == NULL)
584                 return;
585
586         switch (nodeTag(node))
587         {
588                 case T_TargetEntry:
589                         ResolveNew(info, targetlist, &((TargetEntry *) node)->expr,
590                                            sublevels_up);
591                         break;
592                 case T_Aggreg:
593                         ResolveNew(info, targetlist, &((Aggreg *) node)->target,
594                                            sublevels_up);
595                         break;
596                 case T_Expr:
597                         ResolveNew(info, targetlist, (Node **) (&(((Expr *) node)->args)),
598                                            sublevels_up);
599                         break;
600                 case T_Iter:
601                         ResolveNew(info, targetlist, (Node **) (&(((Iter *) node)->iterexpr)),
602                                            sublevels_up);
603                         break;
604                 case T_ArrayRef:
605                         ResolveNew(info, targetlist, (Node **) (&(((ArrayRef *) node)->refupperindexpr)),
606                                            sublevels_up);
607                         ResolveNew(info, targetlist, (Node **) (&(((ArrayRef *) node)->reflowerindexpr)),
608                                            sublevels_up);
609                         ResolveNew(info, targetlist, (Node **) (&(((ArrayRef *) node)->refexpr)),
610                                            sublevels_up);
611                         ResolveNew(info, targetlist, (Node **) (&(((ArrayRef *) node)->refassgnexpr)),
612                                            sublevels_up);
613                         break;
614                 case T_Var:
615                         {
616                                 int                     this_varno = (int) ((Var *) node)->varno;
617                                 int                     this_varlevelsup = (int) ((Var *) node)->varlevelsup;
618                                 Node       *n;
619
620                                 if (this_varno == info->new_varno &&
621                                         this_varlevelsup == sublevels_up)
622                                 {
623                                         n = FindMatchingNew(targetlist,
624                                                                                 ((Var *) node)->varattno);
625                                         if (n == NULL)
626                                         {
627                                                 if (info->event == CMD_UPDATE)
628                                                 {
629                                                         *nodePtr = n = copyObject(node);
630                                                         ((Var *) n)->varno = info->current_varno;
631                                                         ((Var *) n)->varnoold = info->current_varno;
632                                                 }
633                                                 else
634                                                         *nodePtr = make_null(((Var *) node)->vartype);
635                                         }
636                                         else
637                                                 *nodePtr = copyObject(n);
638                                 }
639                                 break;
640                         }
641                 case T_List:
642                         {
643                                 List       *l;
644
645                                 foreach(l, (List *) node)
646                                         ResolveNew(info, targetlist, (Node **) &(lfirst(l)),
647                                                            sublevels_up);
648                                 break;
649                         }
650                 case T_SubLink:
651                         {
652                                 SubLink    *sublink = (SubLink *) node;
653                                 Query      *query = (Query *) sublink->subselect;
654
655                                 ResolveNew(info, targetlist, (Node **) &(query->qual), sublevels_up + 1);
656                         }
657                         break;
658                 default:
659                         /* ignore the others */
660                         break;
661         }
662 }
663
664 void
665 FixNew(RewriteInfo *info, Query *parsetree)
666 {
667         ResolveNew(info, parsetree->targetList,
668                            (Node **) &(info->rule_action->targetList), 0);
669         ResolveNew(info, parsetree->targetList, &info->rule_action->qual, 0);
670 }
671
672 static void
673 nodeHandleRIRAttributeRule(Node **nodePtr,
674                                                    List *rtable,
675                                                    List *targetlist,
676                                                    int rt_index,
677                                                    int attr_num,
678                                                    int *modified,
679                                                    int *badsql,
680                                                    int sublevels_up)
681 {
682         Node       *node = *nodePtr;
683
684         if (node == NULL)
685                 return;
686         switch (nodeTag(node))
687         {
688                 case T_TargetEntry:
689                         {
690                                 TargetEntry *tle = (TargetEntry *) node;
691
692                                 nodeHandleRIRAttributeRule(&tle->expr, rtable, targetlist,
693                                                                         rt_index, attr_num, modified, badsql,
694                                                                                    sublevels_up);
695                         }
696                         break;
697                 case T_Aggreg:
698                         {
699                                 Aggreg     *agg = (Aggreg *) node;
700
701                                 nodeHandleRIRAttributeRule(&agg->target, rtable, targetlist,
702                                                                         rt_index, attr_num, modified, badsql,
703                                                                                    sublevels_up);
704                         }
705                         break;
706                 case T_Expr:
707                         {
708                                 Expr       *expr = (Expr *) node;
709
710                                 nodeHandleRIRAttributeRule((Node **) (&(expr->args)), rtable,
711                                                                                    targetlist, rt_index, attr_num,
712                                                                                    modified, badsql,
713                                                                                    sublevels_up);
714                         }
715                         break;
716                 case T_Iter:
717                         {
718                                 Iter       *iter = (Iter *) node;
719
720                                 nodeHandleRIRAttributeRule((Node **) (&(iter->iterexpr)), rtable,
721                                                                                    targetlist, rt_index, attr_num,
722                                                                                    modified, badsql,
723                                                                                    sublevels_up);
724                         }
725                         break;
726                 case T_ArrayRef:
727                         {
728                                 ArrayRef           *ref = (ArrayRef *) node;
729
730                                 nodeHandleRIRAttributeRule((Node **) (&(ref->refupperindexpr)), rtable,
731                                                                                    targetlist, rt_index, attr_num,
732                                                                                    modified, badsql,
733                                                                                    sublevels_up);
734                                 nodeHandleRIRAttributeRule((Node **) (&(ref->reflowerindexpr)), rtable,
735                                                                                    targetlist, rt_index, attr_num,
736                                                                                    modified, badsql,
737                                                                                    sublevels_up);
738                                 nodeHandleRIRAttributeRule((Node **) (&(ref->refexpr)), rtable,
739                                                                                    targetlist, rt_index, attr_num,
740                                                                                    modified, badsql,
741                                                                                    sublevels_up);
742                                 nodeHandleRIRAttributeRule((Node **) (&(ref->refassgnexpr)), rtable,
743                                                                                    targetlist, rt_index, attr_num,
744                                                                                    modified, badsql,
745                                                                                    sublevels_up);
746                         }
747                         break;
748                 case T_Var:
749                         {
750                                 int                     this_varno = ((Var *) node)->varno;
751                                 int                     this_varattno = ((Var *) node)->varattno;
752                                 int                     this_varlevelsup = ((Var *) node)->varlevelsup;
753
754                                 if (this_varno == rt_index &&
755                                         this_varattno == attr_num &&
756                                         this_varlevelsup == sublevels_up)
757                                 {
758                                         if (((Var *) node)->vartype == 32)
759                                         {                       /* HACK */
760                                                 *nodePtr = make_null(((Var *) node)->vartype);
761                                                 *modified = TRUE;
762                                                 *badsql = TRUE;
763                                                 break;
764                                         }
765                                         else
766                                         {
767                                                 NameData        name_to_look_for;
768
769                                                 name_to_look_for.data[0] = '\0';
770                                                 namestrcpy(&name_to_look_for,
771                                                                 (char *) get_attname(getrelid(this_varno,
772                                                                                                                           rtable),
773                                                                                                          attr_num));
774                                                 if (name_to_look_for.data[0])
775                                                 {
776                                                         Node       *n;
777
778                                                         n = FindMatchingTLEntry(targetlist, (char *) &name_to_look_for);
779                                                         if (n == NULL)
780                                                                 *nodePtr = make_null(((Var *) node)->vartype);
781                                                         else
782                                                                 *nodePtr = n;
783                                                         *modified = TRUE;
784                                                 }
785                                         }
786                                 }
787                         }
788                         break;
789                 case T_List:
790                         {
791                                 List       *i;
792
793                                 foreach(i, (List *) node)
794                                 {
795                                         nodeHandleRIRAttributeRule((Node **) (&(lfirst(i))), rtable,
796                                                                                   targetlist, rt_index, attr_num,
797                                                                                  modified, badsql, sublevels_up);
798                                 }
799                         }
800                         break;
801                 case T_SubLink:
802                         {
803                                 SubLink    *sublink = (SubLink *) node;
804                                 Query      *query = (Query *) sublink->subselect;
805
806                                 nodeHandleRIRAttributeRule((Node **) &(query->qual), rtable, targetlist,
807                                                                         rt_index, attr_num, modified, badsql,
808                                                                                    sublevels_up + 1);
809                         }
810                         break;
811                 default:
812                         /* ignore the others */
813                         break;
814         }
815 }
816
817 /*
818  * Handles 'on retrieve to relation.attribute
819  *                      do instead retrieve (attribute = expression) w/qual'
820  */
821 void
822 HandleRIRAttributeRule(Query *parsetree,
823                                            List *rtable,
824                                            List *targetlist,
825                                            int rt_index,
826                                            int attr_num,
827                                            int *modified,
828                                            int *badsql)
829 {
830
831         nodeHandleRIRAttributeRule((Node **) (&(parsetree->targetList)), rtable,
832                                                            targetlist, rt_index, attr_num,
833                                                            modified, badsql, 0);
834         nodeHandleRIRAttributeRule(&parsetree->qual, rtable, targetlist,
835                                                            rt_index, attr_num, modified, badsql, 0);
836 }
837
838
839 static void
840 nodeHandleViewRule(Node **nodePtr,
841                                    List *rtable,
842                                    List *targetlist,
843                                    int rt_index,
844                                    int *modified,
845                                    int sublevels_up)
846 {
847         Node       *node = *nodePtr;
848
849         if (node == NULL)
850                 return;
851
852         switch (nodeTag(node))
853         {
854                 case T_TargetEntry:
855                         {
856                                 TargetEntry *tle = (TargetEntry *) node;
857
858                                 nodeHandleViewRule(&(tle->expr), rtable, targetlist,
859                                                                    rt_index, modified, sublevels_up);
860                         }
861                         break;
862                 case T_Aggreg:
863                         {
864                                 Aggreg     *agg = (Aggreg *) node;
865
866                                 nodeHandleViewRule(&(agg->target), rtable, targetlist,
867                                                                    rt_index, modified, sublevels_up);
868                         }
869                         break;
870
871                         /*
872                          * This has to be done to make queries using groupclauses work
873                          * on views
874                          */
875                 case T_GroupClause:
876                         {
877                                 GroupClause *group = (GroupClause *) node;
878
879                                 nodeHandleViewRule((Node **) (&(group->entry)), rtable, targetlist,
880                                                                    rt_index, modified, sublevels_up);
881                         }
882                         break;
883                 case T_Expr:
884                         {
885                                 Expr       *expr = (Expr *) node;
886
887                                 nodeHandleViewRule((Node **) (&(expr->args)),
888                                                                    rtable, targetlist,
889                                                                    rt_index, modified, sublevels_up);
890                         }
891                         break;
892                 case T_Iter:
893                         {
894                                 Iter       *iter = (Iter *) node;
895
896                                 nodeHandleViewRule((Node **) (&(iter->iterexpr)),
897                                                                    rtable, targetlist,
898                                                                    rt_index, modified, sublevels_up);
899                         }
900                         break;
901                 case T_ArrayRef:
902                         {
903                                 ArrayRef           *ref = (ArrayRef *) node;
904
905                                 nodeHandleViewRule((Node **) (&(ref->refupperindexpr)),
906                                                                    rtable, targetlist,
907                                                                    rt_index, modified, sublevels_up);
908                                 nodeHandleViewRule((Node **) (&(ref->reflowerindexpr)),
909                                                                    rtable, targetlist,
910                                                                    rt_index, modified, sublevels_up);
911                                 nodeHandleViewRule((Node **) (&(ref->refexpr)),
912                                                                    rtable, targetlist,
913                                                                    rt_index, modified, sublevels_up);
914                                 nodeHandleViewRule((Node **) (&(ref->refassgnexpr)),
915                                                                    rtable, targetlist,
916                                                                    rt_index, modified, sublevels_up);
917                         }
918                         break;
919                 case T_Var:
920                         {
921                                 Var                *var = (Var *) node;
922                                 int                     this_varno = var->varno;
923                                 int                     this_varlevelsup = var->varlevelsup;
924                                 Node       *n;
925
926                                 if (this_varno == rt_index &&
927                                         this_varlevelsup == sublevels_up)
928                                 {
929                                         n = FindMatchingTLEntry(targetlist,
930                                                                                  get_attname(getrelid(this_varno,
931                                                                                                                           rtable),
932                                                                                                          var->varattno));
933                                         if (n == NULL)
934                                                 *nodePtr = make_null(((Var *) node)->vartype);
935                                         else
936                                         {
937                                                 /*
938                                                  * This is a hack: The varlevelsup of the orignal
939                                                  * variable and the new one should be the same.
940                                                  * Normally we adapt the node by changing a
941                                                  * pointer to point to a var contained in
942                                                  * 'targetlist'. In the targetlist all
943                                                  * varlevelsups are 0 so if we want to change it
944                                                  * to the original value we have to copy the node
945                                                  * before! (Maybe this will cause troubles with
946                                                  * some sophisticated queries on views?)
947                                                  */
948                                                 if (this_varlevelsup > 0)
949                                                         *nodePtr = copyObject(n);
950                                                 else
951                                                         *nodePtr = n;
952
953                                                 if (nodeTag(nodePtr) == T_Var)
954                                                         ((Var *) *nodePtr)->varlevelsup = this_varlevelsup;
955                                                 else
956                                                         nodeHandleViewRule(&n, rtable, targetlist,
957                                                                                    rt_index, modified, sublevels_up);
958                                         }
959                                         *modified = TRUE;
960                                 }
961                                 break;
962                         }
963                 case T_List:
964                         {
965                                 List       *l;
966
967                                 foreach(l, (List *) node)
968                                 {
969                                         nodeHandleViewRule((Node **) (&(lfirst(l))),
970                                                                            rtable, targetlist,
971                                                                            rt_index, modified, sublevels_up);
972                                 }
973                         }
974                         break;
975                 case T_SubLink:
976                         {
977                                 SubLink    *sublink = (SubLink *) node;
978                                 Query      *query = (Query *) sublink->subselect;
979
980                                 nodeHandleViewRule((Node **) &(query->qual), rtable, targetlist,
981                                                                    rt_index, modified, sublevels_up + 1);
982
983                                 /*
984                                  * We also have to adapt the variables used in
985                                  * sublink->lefthand and sublink->oper
986                                  */
987                                 nodeHandleViewRule((Node **) &(sublink->lefthand), rtable,
988                                                    targetlist, rt_index, modified, sublevels_up);
989
990                                 /*
991                                  * Make sure the first argument of sublink->oper points to
992                                  * the same var as sublink->lefthand does otherwise we
993                                  * will run into troubles using aggregates (aggno will not
994                                  * be set correctly
995                                  */
996                                 pfree(lfirst(((Expr *) lfirst(sublink->oper))->args));
997                                 lfirst(((Expr *) lfirst(sublink->oper))->args) =
998                                         lfirst(sublink->lefthand);
999                         }
1000                         break;
1001                 default:
1002                         /* ignore the others */
1003                         break;
1004         }
1005 }
1006
1007 #ifdef NOT_USED
1008 void
1009 HandleViewRule(Query *parsetree,
1010                            List *rtable,
1011                            List *targetlist,
1012                            int rt_index,
1013                            int *modified)
1014 {
1015         nodeHandleViewRule(&parsetree->qual, rtable, targetlist, rt_index,
1016                                            modified, 0);
1017         nodeHandleViewRule((Node **) (&(parsetree->targetList)), rtable, targetlist,
1018                                            rt_index, modified, 0);
1019
1020         /*
1021          * The variables in the havingQual and groupClause also have to be
1022          * adapted
1023          */
1024         nodeHandleViewRule(&parsetree->havingQual, rtable, targetlist, rt_index,
1025                                            modified, 0);
1026         nodeHandleViewRule((Node **) (&(parsetree->groupClause)), rtable, targetlist, rt_index,
1027                                            modified, 0);
1028 }
1029 #endif
1030