]> granicus.if.org Git - postgresql/blob - src/backend/rewrite/rewriteManip.c
The patch does 2 things:
[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.22 1998/10/21 16:21:26 momjian 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                 default:
195                         elog(NOTICE, "unknown node tag %d in OffsetVarNodes()", nodeTag(node));
196                         elog(NOTICE, "Node is: %s", nodeToString(node));
197                         break;
198
199
200         }
201 }
202
203
204 /*
205  * ChangeVarNodes -
206  */
207 void
208 ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)
209 {
210         if (node == NULL)
211                 return;
212
213         switch(nodeTag(node)) {
214                 case T_TargetEntry:
215                         {
216                                 TargetEntry     *tle = (TargetEntry *)node;
217
218                                 ChangeVarNodes(
219                                                 (Node *)(tle->expr),
220                                                 rt_index,
221                                                 new_index,
222                                                 sublevels_up);
223                         }
224                         break;
225
226                 case T_Aggreg:
227                         {
228                                 Aggreg  *agg = (Aggreg *)node;
229
230                                 ChangeVarNodes(
231                                                 (Node *)(agg->target),
232                                                 rt_index,
233                                                 new_index,
234                                                 sublevels_up);
235                         }
236                         break;
237
238                 case T_GroupClause:
239                         {
240                                 GroupClause     *grp = (GroupClause *)node;
241
242                                 ChangeVarNodes(
243                                                 (Node *)(grp->entry),
244                                                 rt_index,
245                                                 new_index,
246                                                 sublevels_up);
247                         }
248                         break;
249
250                 case T_Expr:
251                         {
252                                 Expr    *exp = (Expr *)node;
253
254                                 ChangeVarNodes(
255                                                 (Node *)(exp->args),
256                                                 rt_index,
257                                                 new_index,
258                                                 sublevels_up);
259                         }
260                         break;
261
262                 case T_Iter:
263                         {
264                                 Iter    *iter = (Iter *)node;
265
266                                 ChangeVarNodes(
267                                                 (Node *)(iter->iterexpr),
268                                                 rt_index,
269                                                 new_index,
270                                                 sublevels_up);
271                         }
272                         break;
273
274                 case T_ArrayRef:
275                         {
276                                 ArrayRef        *ref = (ArrayRef *)node;
277
278                                 ChangeVarNodes(
279                                                 (Node *)(ref->refupperindexpr),
280                                                 rt_index,
281                                                 new_index,
282                                                 sublevels_up);
283                                 ChangeVarNodes(
284                                                 (Node *)(ref->reflowerindexpr),
285                                                 rt_index,
286                                                 new_index,
287                                                 sublevels_up);
288                                 ChangeVarNodes(
289                                                 (Node *)(ref->refexpr),
290                                                 rt_index,
291                                                 new_index,
292                                                 sublevels_up);
293                                 ChangeVarNodes(
294                                                 (Node *)(ref->refassgnexpr),
295                                                 rt_index,
296                                                 new_index,
297                                                 sublevels_up);
298                         }
299                         break;
300
301                 case T_Var:
302                         {
303                                 Var     *var = (Var *)node;
304
305                                 if (var->varlevelsup == sublevels_up &&
306                                                 var->varno == rt_index) {
307                                         var->varno = new_index;
308                                         var->varnoold = new_index;
309                                 }
310                         }
311                         break;
312
313                 case T_Param:
314                         break;
315
316                 case T_Const:
317                         break;
318
319                 case T_List:
320                         {
321                                 List    *l;
322
323                                 foreach (l, (List *)node)
324                                         ChangeVarNodes(
325                                                         (Node *)lfirst(l),
326                                                         rt_index,
327                                                         new_index,
328                                                         sublevels_up);
329                         }
330                         break;
331
332                 case T_SubLink:
333                         {
334                                 SubLink *sub = (SubLink *)node;
335
336                                 ChangeVarNodes(
337                                                 (Node *)(sub->lefthand),
338                                                 rt_index,
339                                                 new_index,
340                                                 sublevels_up);
341
342                                 ChangeVarNodes(
343                                                 (Node *)(sub->subselect),
344                                                 rt_index,
345                                                 new_index,
346                                                 sublevels_up + 1);
347                         }
348                         break;
349
350                 case T_Query:
351                         {
352                                 Query   *qry = (Query *)node;
353
354                                 ChangeVarNodes(
355                                                 (Node *)(qry->targetList),
356                                                 rt_index,
357                                                 new_index,
358                                                 sublevels_up);
359
360                                 ChangeVarNodes(
361                                                 (Node *)(qry->qual),
362                                                 rt_index,
363                                                 new_index,
364                                                 sublevels_up);
365
366                                 ChangeVarNodes(
367                                                 (Node *)(qry->havingQual),
368                                                 rt_index,
369                                                 new_index,
370                                                 sublevels_up);
371
372                                 ChangeVarNodes(
373                                                 (Node *)(qry->groupClause),
374                                                 rt_index,
375                                                 new_index,
376                                                 sublevels_up);
377                         }
378                         break;
379
380                 default:
381                         elog(NOTICE, "unknown node tag %d in ChangeVarNodes()", nodeTag(node));
382                         elog(NOTICE, "Node is: %s", nodeToString(node));
383                         break;
384
385
386         }
387 }
388
389
390
391 void
392 AddQual(Query *parsetree, Node *qual)
393 {
394         Node       *copy,
395                            *old;
396
397         if (qual == NULL)
398                 return;
399
400         copy = copyObject(qual);
401         old = parsetree->qual;
402         if (old == NULL)
403                 parsetree->qual = copy;
404         else
405                 parsetree->qual =
406                         (Node *) make_andclause(makeList(parsetree->qual, copy, -1));
407 }
408
409 /* Adds the given havingQual to the one already contained in the parsetree just as
410  * AddQual does for the normal 'where' qual */
411 void
412 AddHavingQual(Query *parsetree, Node *havingQual)
413 {
414         Node       *copy,
415                            *old;
416
417         if (havingQual == NULL)
418                 return;
419
420         copy = copyObject(havingQual);
421         old = parsetree->havingQual;
422         if (old == NULL)
423                 parsetree->havingQual = copy;
424         else
425                 parsetree->havingQual =
426                         (Node *) make_andclause(makeList(parsetree->havingQual, copy, -1));
427 }
428
429
430 void
431 AddNotQual(Query *parsetree, Node *qual)
432 {
433         Node       *copy;
434
435         if (qual == NULL)
436                 return;
437
438         copy = (Node *) make_notclause(copyObject(qual));
439
440         AddQual(parsetree, copy);
441 }
442
443 static Node *
444 make_null(Oid type)
445 {
446         Const      *c = makeNode(Const);
447
448         c->consttype = type;
449         c->constlen = get_typlen(type);
450         c->constvalue = PointerGetDatum(NULL);
451         c->constisnull = true;
452         c->constbyval = get_typbyval(type);
453         return (Node *) c;
454 }
455
456 #ifdef NOT_USED
457 void
458 FixResdomTypes(List *tlist)
459 {
460         List       *i;
461
462         foreach(i, tlist)
463         {
464                 TargetEntry *tle = lfirst(i);
465
466                 if (nodeTag(tle->expr) == T_Var)
467                 {
468                         Var                *var = (Var *) tle->expr;
469
470                         tle->resdom->restype = var->vartype;
471                         tle->resdom->restypmod = var->vartypmod;
472                 }
473         }
474 }
475 #endif
476
477 static Node *
478 FindMatchingNew(List *tlist, int attno)
479 {
480         List       *i;
481
482         foreach(i, tlist)
483         {
484                 TargetEntry *tle = lfirst(i);
485
486                 if (tle->resdom->resno == attno)
487                         return tle->expr;
488         }
489         return NULL;
490 }
491
492 static Node *
493 FindMatchingTLEntry(List *tlist, char *e_attname)
494 {
495         List       *i;
496
497         foreach(i, tlist)
498         {
499                 TargetEntry *tle = lfirst(i);
500                 char       *resname;
501
502                 resname = tle->resdom->resname;
503                 if (!strcmp(e_attname, resname))
504                         return tle->expr;
505         }
506         return NULL;
507 }
508
509 static void
510 ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr,
511                    int sublevels_up)
512 {
513         Node       *node = *nodePtr;
514
515         if (node == NULL)
516                 return;
517
518         switch (nodeTag(node))
519         {
520                 case T_TargetEntry:
521                         ResolveNew(info, targetlist, &((TargetEntry *) node)->expr,
522                                            sublevels_up);
523                         break;
524                 case T_Aggreg:
525                         ResolveNew(info, targetlist, &((Aggreg *) node)->target,
526                                            sublevels_up);
527                         break;
528                 case T_Expr:
529                         ResolveNew(info, targetlist, (Node **) (&(((Expr *) node)->args)),
530                                            sublevels_up);
531                         break;
532                 case T_Iter:
533                         ResolveNew(info, targetlist, (Node **) (&(((Iter *) node)->iterexpr)),
534                                            sublevels_up);
535                         break;
536                 case T_ArrayRef:
537                         ResolveNew(info, targetlist, (Node **) (&(((ArrayRef *) node)->refupperindexpr)),
538                                            sublevels_up);
539                         ResolveNew(info, targetlist, (Node **) (&(((ArrayRef *) node)->reflowerindexpr)),
540                                            sublevels_up);
541                         ResolveNew(info, targetlist, (Node **) (&(((ArrayRef *) node)->refexpr)),
542                                            sublevels_up);
543                         ResolveNew(info, targetlist, (Node **) (&(((ArrayRef *) node)->refassgnexpr)),
544                                            sublevels_up);
545                         break;
546                 case T_Var:
547                         {
548                                 int                     this_varno = (int) ((Var *) node)->varno;
549                                 int                     this_varlevelsup = (int) ((Var *) node)->varlevelsup;
550                                 Node       *n;
551
552                                 if (this_varno == info->new_varno &&
553                                         this_varlevelsup == sublevels_up)
554                                 {
555                                         n = FindMatchingNew(targetlist,
556                                                                                 ((Var *) node)->varattno);
557                                         if (n == NULL)
558                                         {
559                                                 if (info->event == CMD_UPDATE)
560                                                 {
561                                                         *nodePtr = n = copyObject(node);
562                                                         ((Var *) n)->varno = info->current_varno;
563                                                         ((Var *) n)->varnoold = info->current_varno;
564                                                 }
565                                                 else
566                                                         *nodePtr = make_null(((Var *) node)->vartype);
567                                         }
568                                         else
569                                                 *nodePtr = copyObject(n);
570                                 }
571                                 break;
572                         }
573                 case T_List:
574                         {
575                                 List       *l;
576
577                                 foreach(l, (List *) node)
578                                         ResolveNew(info, targetlist, (Node **) &(lfirst(l)),
579                                                            sublevels_up);
580                                 break;
581                         }
582                 case T_SubLink:
583                         {
584                                 SubLink    *sublink = (SubLink *) node;
585                                 Query      *query = (Query *) sublink->subselect;
586
587                                 ResolveNew(info, targetlist, (Node **) &(query->qual), sublevels_up + 1);
588                         }
589                         break;
590                 default:
591                         /* ignore the others */
592                         break;
593         }
594 }
595
596 void
597 FixNew(RewriteInfo *info, Query *parsetree)
598 {
599         ResolveNew(info, parsetree->targetList,
600                            (Node **) &(info->rule_action->targetList), 0);
601         ResolveNew(info, parsetree->targetList, &info->rule_action->qual, 0);
602 }
603
604 static void
605 nodeHandleRIRAttributeRule(Node **nodePtr,
606                                                    List *rtable,
607                                                    List *targetlist,
608                                                    int rt_index,
609                                                    int attr_num,
610                                                    int *modified,
611                                                    int *badsql,
612                                                    int sublevels_up)
613 {
614         Node       *node = *nodePtr;
615
616         if (node == NULL)
617                 return;
618         switch (nodeTag(node))
619         {
620                 case T_TargetEntry:
621                         {
622                                 TargetEntry *tle = (TargetEntry *) node;
623
624                                 nodeHandleRIRAttributeRule(&tle->expr, rtable, targetlist,
625                                                                         rt_index, attr_num, modified, badsql,
626                                                                                    sublevels_up);
627                         }
628                         break;
629                 case T_Aggreg:
630                         {
631                                 Aggreg     *agg = (Aggreg *) node;
632
633                                 nodeHandleRIRAttributeRule(&agg->target, rtable, targetlist,
634                                                                         rt_index, attr_num, modified, badsql,
635                                                                                    sublevels_up);
636                         }
637                         break;
638                 case T_Expr:
639                         {
640                                 Expr       *expr = (Expr *) node;
641
642                                 nodeHandleRIRAttributeRule((Node **) (&(expr->args)), rtable,
643                                                                                    targetlist, rt_index, attr_num,
644                                                                                    modified, badsql,
645                                                                                    sublevels_up);
646                         }
647                         break;
648                 case T_Iter:
649                         {
650                                 Iter       *iter = (Iter *) node;
651
652                                 nodeHandleRIRAttributeRule((Node **) (&(iter->iterexpr)), rtable,
653                                                                                    targetlist, rt_index, attr_num,
654                                                                                    modified, badsql,
655                                                                                    sublevels_up);
656                         }
657                         break;
658                 case T_ArrayRef:
659                         {
660                                 ArrayRef           *ref = (ArrayRef *) node;
661
662                                 nodeHandleRIRAttributeRule((Node **) (&(ref->refupperindexpr)), rtable,
663                                                                                    targetlist, rt_index, attr_num,
664                                                                                    modified, badsql,
665                                                                                    sublevels_up);
666                                 nodeHandleRIRAttributeRule((Node **) (&(ref->reflowerindexpr)), rtable,
667                                                                                    targetlist, rt_index, attr_num,
668                                                                                    modified, badsql,
669                                                                                    sublevels_up);
670                                 nodeHandleRIRAttributeRule((Node **) (&(ref->refexpr)), rtable,
671                                                                                    targetlist, rt_index, attr_num,
672                                                                                    modified, badsql,
673                                                                                    sublevels_up);
674                                 nodeHandleRIRAttributeRule((Node **) (&(ref->refassgnexpr)), rtable,
675                                                                                    targetlist, rt_index, attr_num,
676                                                                                    modified, badsql,
677                                                                                    sublevels_up);
678                         }
679                         break;
680                 case T_Var:
681                         {
682                                 int                     this_varno = ((Var *) node)->varno;
683                                 int                     this_varattno = ((Var *) node)->varattno;
684                                 int                     this_varlevelsup = ((Var *) node)->varlevelsup;
685
686                                 if (this_varno == rt_index &&
687                                         this_varattno == attr_num &&
688                                         this_varlevelsup == sublevels_up)
689                                 {
690                                         if (((Var *) node)->vartype == 32)
691                                         {                       /* HACK */
692                                                 *nodePtr = make_null(((Var *) node)->vartype);
693                                                 *modified = TRUE;
694                                                 *badsql = TRUE;
695                                                 break;
696                                         }
697                                         else
698                                         {
699                                                 NameData        name_to_look_for;
700
701                                                 name_to_look_for.data[0] = '\0';
702                                                 namestrcpy(&name_to_look_for,
703                                                                 (char *) get_attname(getrelid(this_varno,
704                                                                                                                           rtable),
705                                                                                                          attr_num));
706                                                 if (name_to_look_for.data[0])
707                                                 {
708                                                         Node       *n;
709
710                                                         n = FindMatchingTLEntry(targetlist, (char *) &name_to_look_for);
711                                                         if (n == NULL)
712                                                                 *nodePtr = make_null(((Var *) node)->vartype);
713                                                         else
714                                                                 *nodePtr = n;
715                                                         *modified = TRUE;
716                                                 }
717                                         }
718                                 }
719                         }
720                         break;
721                 case T_List:
722                         {
723                                 List       *i;
724
725                                 foreach(i, (List *) node)
726                                 {
727                                         nodeHandleRIRAttributeRule((Node **) (&(lfirst(i))), rtable,
728                                                                                   targetlist, rt_index, attr_num,
729                                                                                  modified, badsql, sublevels_up);
730                                 }
731                         }
732                         break;
733                 case T_SubLink:
734                         {
735                                 SubLink    *sublink = (SubLink *) node;
736                                 Query      *query = (Query *) sublink->subselect;
737
738                                 nodeHandleRIRAttributeRule((Node **) &(query->qual), rtable, targetlist,
739                                                                         rt_index, attr_num, modified, badsql,
740                                                                                    sublevels_up + 1);
741                         }
742                         break;
743                 default:
744                         /* ignore the others */
745                         break;
746         }
747 }
748
749 /*
750  * Handles 'on retrieve to relation.attribute
751  *                      do instead retrieve (attribute = expression) w/qual'
752  */
753 void
754 HandleRIRAttributeRule(Query *parsetree,
755                                            List *rtable,
756                                            List *targetlist,
757                                            int rt_index,
758                                            int attr_num,
759                                            int *modified,
760                                            int *badsql)
761 {
762
763         nodeHandleRIRAttributeRule((Node **) (&(parsetree->targetList)), rtable,
764                                                            targetlist, rt_index, attr_num,
765                                                            modified, badsql, 0);
766         nodeHandleRIRAttributeRule(&parsetree->qual, rtable, targetlist,
767                                                            rt_index, attr_num, modified, badsql, 0);
768 }
769
770
771 static void
772 nodeHandleViewRule(Node **nodePtr,
773                                    List *rtable,
774                                    List *targetlist,
775                                    int rt_index,
776                                    int *modified,
777                                    int sublevels_up)
778 {
779         Node       *node = *nodePtr;
780
781         if (node == NULL)
782                 return;
783
784         switch (nodeTag(node))
785         {
786                 case T_TargetEntry:
787                         {
788                                 TargetEntry *tle = (TargetEntry *) node;
789
790                                 nodeHandleViewRule(&(tle->expr), rtable, targetlist,
791                                                                    rt_index, modified, sublevels_up);
792                         }
793                         break;
794                 case T_Aggreg:
795                         {
796                                 Aggreg     *agg = (Aggreg *) node;
797
798                                 nodeHandleViewRule(&(agg->target), rtable, targetlist,
799                                                                    rt_index, modified, sublevels_up);
800                         }
801                         break;
802
803                         /*
804                          * This has to be done to make queries using groupclauses work
805                          * on views
806                          */
807                 case T_GroupClause:
808                         {
809                                 GroupClause *group = (GroupClause *) node;
810
811                                 nodeHandleViewRule((Node **) (&(group->entry)), rtable, targetlist,
812                                                                    rt_index, modified, sublevels_up);
813                         }
814                         break;
815                 case T_Expr:
816                         {
817                                 Expr       *expr = (Expr *) node;
818
819                                 nodeHandleViewRule((Node **) (&(expr->args)),
820                                                                    rtable, targetlist,
821                                                                    rt_index, modified, sublevels_up);
822                         }
823                         break;
824                 case T_Iter:
825                         {
826                                 Iter       *iter = (Iter *) node;
827
828                                 nodeHandleViewRule((Node **) (&(iter->iterexpr)),
829                                                                    rtable, targetlist,
830                                                                    rt_index, modified, sublevels_up);
831                         }
832                         break;
833                 case T_ArrayRef:
834                         {
835                                 ArrayRef           *ref = (ArrayRef *) node;
836
837                                 nodeHandleViewRule((Node **) (&(ref->refupperindexpr)),
838                                                                    rtable, targetlist,
839                                                                    rt_index, modified, sublevels_up);
840                                 nodeHandleViewRule((Node **) (&(ref->reflowerindexpr)),
841                                                                    rtable, targetlist,
842                                                                    rt_index, modified, sublevels_up);
843                                 nodeHandleViewRule((Node **) (&(ref->refexpr)),
844                                                                    rtable, targetlist,
845                                                                    rt_index, modified, sublevels_up);
846                                 nodeHandleViewRule((Node **) (&(ref->refassgnexpr)),
847                                                                    rtable, targetlist,
848                                                                    rt_index, modified, sublevels_up);
849                         }
850                         break;
851                 case T_Var:
852                         {
853                                 Var                *var = (Var *) node;
854                                 int                     this_varno = var->varno;
855                                 int                     this_varlevelsup = var->varlevelsup;
856                                 Node       *n;
857
858                                 if (this_varno == rt_index &&
859                                         this_varlevelsup == sublevels_up)
860                                 {
861                                         n = FindMatchingTLEntry(targetlist,
862                                                                                  get_attname(getrelid(this_varno,
863                                                                                                                           rtable),
864                                                                                                          var->varattno));
865                                         if (n == NULL)
866                                                 *nodePtr = make_null(((Var *) node)->vartype);
867                                         else
868                                         {
869                                                 /*
870                                                  * This is a hack: The varlevelsup of the orignal
871                                                  * variable and the new one should be the same.
872                                                  * Normally we adapt the node by changing a
873                                                  * pointer to point to a var contained in
874                                                  * 'targetlist'. In the targetlist all
875                                                  * varlevelsups are 0 so if we want to change it
876                                                  * to the original value we have to copy the node
877                                                  * before! (Maybe this will cause troubles with
878                                                  * some sophisticated queries on views?)
879                                                  */
880                                                 if (this_varlevelsup > 0)
881                                                         *nodePtr = copyObject(n);
882                                                 else
883                                                         *nodePtr = n;
884
885                                                 if (nodeTag(nodePtr) == T_Var)
886                                                         ((Var *) *nodePtr)->varlevelsup = this_varlevelsup;
887                                                 else
888                                                         nodeHandleViewRule(&n, rtable, targetlist,
889                                                                                    rt_index, modified, sublevels_up);
890                                         }
891                                         *modified = TRUE;
892                                 }
893                                 break;
894                         }
895                 case T_List:
896                         {
897                                 List       *l;
898
899                                 foreach(l, (List *) node)
900                                 {
901                                         nodeHandleViewRule((Node **) (&(lfirst(l))),
902                                                                            rtable, targetlist,
903                                                                            rt_index, modified, sublevels_up);
904                                 }
905                         }
906                         break;
907                 case T_SubLink:
908                         {
909                                 SubLink    *sublink = (SubLink *) node;
910                                 Query      *query = (Query *) sublink->subselect;
911
912                                 nodeHandleViewRule((Node **) &(query->qual), rtable, targetlist,
913                                                                    rt_index, modified, sublevels_up + 1);
914
915                                 /*
916                                  * We also have to adapt the variables used in
917                                  * sublink->lefthand and sublink->oper
918                                  */
919                                 nodeHandleViewRule((Node **) &(sublink->lefthand), rtable,
920                                                    targetlist, rt_index, modified, sublevels_up);
921
922                                 /*
923                                  * Make sure the first argument of sublink->oper points to
924                                  * the same var as sublink->lefthand does otherwise we
925                                  * will run into troubles using aggregates (aggno will not
926                                  * be set correctly
927                                  */
928                                 pfree(lfirst(((Expr *) lfirst(sublink->oper))->args));
929                                 lfirst(((Expr *) lfirst(sublink->oper))->args) =
930                                         lfirst(sublink->lefthand);
931                         }
932                         break;
933                 default:
934                         /* ignore the others */
935                         break;
936         }
937 }
938
939 #ifdef NOT_USED
940 void
941 HandleViewRule(Query *parsetree,
942                            List *rtable,
943                            List *targetlist,
944                            int rt_index,
945                            int *modified)
946 {
947         nodeHandleViewRule(&parsetree->qual, rtable, targetlist, rt_index,
948                                            modified, 0);
949         nodeHandleViewRule((Node **) (&(parsetree->targetList)), rtable, targetlist,
950                                            rt_index, modified, 0);
951
952         /*
953          * The variables in the havingQual and groupClause also have to be
954          * adapted
955          */
956         nodeHandleViewRule(&parsetree->havingQual, rtable, targetlist, rt_index,
957                                            modified, 0);
958         nodeHandleViewRule((Node **) (&(parsetree->groupClause)), rtable, targetlist, rt_index,
959                                            modified, 0);
960 }
961 #endif
962