]> granicus.if.org Git - postgresql/blob - src/backend/rewrite/rewriteManip.c
Make functions static or ifdef NOT_USED. Prevent pg_version creation.
[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.20 1998/10/08 18:29:52 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 void
37 OffsetVarNodes(Node *node, int offset)
38 {
39         if (node == NULL)
40                 return;
41         switch (nodeTag(node))
42         {
43                 case T_TargetEntry:
44                         {
45                                 TargetEntry *tle = (TargetEntry *) node;
46
47                                 OffsetVarNodes(tle->expr, offset);
48                         }
49                         break;
50                 case T_Aggreg:
51                         {
52                                 Aggreg     *agg = (Aggreg *) node;
53
54                                 OffsetVarNodes(agg->target, offset);
55                         }
56                         break;
57
58                         /*
59                          * This has to be done to make queries using groupclauses work
60                          * on views
61                          */
62                 case T_GroupClause:
63                         {
64                                 GroupClause *group = (GroupClause *) node;
65
66                                 OffsetVarNodes((Node *) (group->entry), offset);
67                         }
68                         break;
69                 case T_Expr:
70                         {
71                                 Expr       *expr = (Expr *) node;
72
73                                 OffsetVarNodes((Node *) expr->args, offset);
74                         }
75                         break;
76                 case T_Iter:
77                         {
78                                 Iter       *iter = (Iter *) node;
79
80                                 OffsetVarNodes((Node *) iter->iterexpr, offset);
81                         }
82                         break;
83                 case T_ArrayRef:
84                         {
85                                 ArrayRef           *ref = (ArrayRef *) node;
86
87                                 OffsetVarNodes((Node *) ref->refupperindexpr, offset);
88                                 OffsetVarNodes((Node *) ref->reflowerindexpr, offset);
89                                 OffsetVarNodes((Node *) ref->refexpr, offset);
90                                 OffsetVarNodes((Node *) ref->refassgnexpr, offset);
91                         }
92                         break;
93                 case T_Var:
94                         {
95                                 Var                *var = (Var *) node;
96
97                                 var->varno += offset;
98                                 var->varnoold += offset;
99                         }
100                         break;
101                 case T_List:
102                         {
103                                 List       *l;
104
105                                 foreach(l, (List *) node)
106                                         OffsetVarNodes(lfirst(l), offset);
107                         }
108                         break;
109                 case T_SubLink:
110                         {
111                                 SubLink    *sublink = (SubLink *) node;
112
113                                 /*
114                                  * We also have to adapt the variables used in
115                                  * sublink->lefthand and sublink->oper
116                                  */
117                                 OffsetVarNodes((Node *) (sublink->lefthand), offset);
118
119                                 /*
120                                  * Make sure the first argument of sublink->oper points to
121                                  * the same var as sublink->lefthand does otherwise we
122                                  * will run into troubles using aggregates (aggno will not
123                                  * be set correctly)
124                                  */
125                                 lfirst(((Expr *) lfirst(sublink->oper))->args) =
126                                         lfirst(sublink->lefthand);
127                         }
128                         break;
129                 default:
130                         /* ignore the others */
131                         break;
132         }
133 }
134
135 void
136 ChangeVarNodes(Node *node, int old_varno, int new_varno, int sublevels_up)
137 {
138         if (node == NULL)
139                 return;
140         switch (nodeTag(node))
141         {
142                 case T_TargetEntry:
143                         {
144                                 TargetEntry *tle = (TargetEntry *) node;
145
146                                 ChangeVarNodes(tle->expr, old_varno, new_varno, sublevels_up);
147                         }
148                         break;
149                 case T_Aggreg:
150                         {
151                                 Aggreg     *agg = (Aggreg *) node;
152
153                                 ChangeVarNodes(agg->target, old_varno, new_varno, sublevels_up);
154                         }
155                         break;
156
157                         /*
158                          * This has to be done to make queries using groupclauses work
159                          * on views
160                          */
161                 case T_GroupClause:
162                         {
163                                 GroupClause *group = (GroupClause *) node;
164
165                                 ChangeVarNodes((Node *) (group->entry), old_varno, new_varno,
166                                                            sublevels_up);
167                         }
168                         break;
169
170                 case T_Expr:
171                         {
172                                 Expr       *expr = (Expr *) node;
173
174                                 ChangeVarNodes((Node *) expr->args, old_varno, new_varno, sublevels_up);
175                         }
176                         break;
177                 case T_Iter:
178                         {
179                                 Iter       *iter = (Iter *) node;
180
181                                 ChangeVarNodes((Node *) iter->iterexpr, old_varno, new_varno, sublevels_up);
182                         }
183                         break;
184                 case T_ArrayRef:
185                         {
186                                 ArrayRef           *ref = (ArrayRef *) node;
187
188                                 ChangeVarNodes((Node *) ref->refupperindexpr, old_varno, new_varno, sublevels_up);
189                                 ChangeVarNodes((Node *) ref->reflowerindexpr, old_varno, new_varno, sublevels_up);
190                                 ChangeVarNodes((Node *) ref->refexpr, old_varno, new_varno, sublevels_up);
191                                 ChangeVarNodes((Node *) ref->refassgnexpr, old_varno, new_varno, sublevels_up);
192                         }
193                         break;
194                 case T_Var:
195                         {
196                                 Var                *var = (Var *) node;
197
198                                 if (var->varno == old_varno &&
199                                         var->varlevelsup == sublevels_up)
200                                 {
201                                         var->varno = new_varno;
202                                         var->varnoold = new_varno;
203                                 }
204                                 if (var->varlevelsup > 0)
205                                         OffsetVarNodes((Node *) var, 3);
206
207                         }
208                         break;
209                 case T_List:
210                         {
211                                 List       *l;
212
213                                 foreach(l, (List *) node)
214                                         ChangeVarNodes(lfirst(l), old_varno, new_varno, sublevels_up);
215                         }
216                         break;
217                 case T_SubLink:
218                         {
219                                 SubLink    *sublink = (SubLink *) node;
220                                 Query      *query = (Query *) sublink->subselect;
221
222                                 ChangeVarNodes((Node *) query->qual, old_varno, new_varno,
223                                                            sublevels_up + 1);
224
225                                 /*
226                                  * We also have to adapt the variables used in
227                                  * sublink->lefthand and sublink->oper
228                                  */
229                                 ChangeVarNodes((Node *) (sublink->lefthand), old_varno, new_varno,
230                                                            sublevels_up);
231
232                                 /*
233                                  * Make sure the first argument of sublink->oper points to
234                                  * the same var as sublink->lefthand does otherwise we
235                                  * will run into troubles using aggregates (aggno will not
236                                  * be set correctly
237                                  */
238
239                                 /*
240                                  * lfirst(((Expr *) lfirst(sublink->oper))->args) =
241                                  * lfirst(sublink->lefthand);
242                                  */
243                         }
244                         break;
245                 default:
246                         /* ignore the others */
247                         break;
248         }
249 }
250
251 void
252 AddQual(Query *parsetree, Node *qual)
253 {
254         Node       *copy,
255                            *old;
256
257         if (qual == NULL)
258                 return;
259
260         copy = copyObject(qual);
261         old = parsetree->qual;
262         if (old == NULL)
263                 parsetree->qual = copy;
264         else
265                 parsetree->qual =
266                         (Node *) make_andclause(makeList(parsetree->qual, copy, -1));
267 }
268
269 /* Adds the given havingQual to the one already contained in the parsetree just as
270  * AddQual does for the normal 'where' qual */
271 void
272 AddHavingQual(Query *parsetree, Node *havingQual)
273 {
274         Node       *copy,
275                            *old;
276
277         if (havingQual == NULL)
278                 return;
279
280         copy = copyObject(havingQual);
281         old = parsetree->havingQual;
282         if (old == NULL)
283                 parsetree->havingQual = copy;
284         else
285                 parsetree->havingQual =
286                         (Node *) make_andclause(makeList(parsetree->havingQual, copy, -1));
287 }
288
289
290 void
291 AddNotQual(Query *parsetree, Node *qual)
292 {
293         Node       *copy;
294
295         if (qual == NULL)
296                 return;
297
298         copy = (Node *) make_notclause(copyObject(qual));
299
300         AddQual(parsetree, copy);
301 }
302
303 static Node *
304 make_null(Oid type)
305 {
306         Const      *c = makeNode(Const);
307
308         c->consttype = type;
309         c->constlen = get_typlen(type);
310         c->constvalue = PointerGetDatum(NULL);
311         c->constisnull = true;
312         c->constbyval = get_typbyval(type);
313         return (Node *) c;
314 }
315
316 #ifdef NOT_USED
317 void
318 FixResdomTypes(List *tlist)
319 {
320         List       *i;
321
322         foreach(i, tlist)
323         {
324                 TargetEntry *tle = lfirst(i);
325
326                 if (nodeTag(tle->expr) == T_Var)
327                 {
328                         Var                *var = (Var *) tle->expr;
329
330                         tle->resdom->restype = var->vartype;
331                         tle->resdom->restypmod = var->vartypmod;
332                 }
333         }
334 }
335 #endif
336
337 static Node *
338 FindMatchingNew(List *tlist, int attno)
339 {
340         List       *i;
341
342         foreach(i, tlist)
343         {
344                 TargetEntry *tle = lfirst(i);
345
346                 if (tle->resdom->resno == attno)
347                         return tle->expr;
348         }
349         return NULL;
350 }
351
352 static Node *
353 FindMatchingTLEntry(List *tlist, char *e_attname)
354 {
355         List       *i;
356
357         foreach(i, tlist)
358         {
359                 TargetEntry *tle = lfirst(i);
360                 char       *resname;
361
362                 resname = tle->resdom->resname;
363                 if (!strcmp(e_attname, resname))
364                         return tle->expr;
365         }
366         return NULL;
367 }
368
369 static void
370 ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr,
371                    int sublevels_up)
372 {
373         Node       *node = *nodePtr;
374
375         if (node == NULL)
376                 return;
377
378         switch (nodeTag(node))
379         {
380                 case T_TargetEntry:
381                         ResolveNew(info, targetlist, &((TargetEntry *) node)->expr,
382                                            sublevels_up);
383                         break;
384                 case T_Aggreg:
385                         ResolveNew(info, targetlist, &((Aggreg *) node)->target,
386                                            sublevels_up);
387                         break;
388                 case T_Expr:
389                         ResolveNew(info, targetlist, (Node **) (&(((Expr *) node)->args)),
390                                            sublevels_up);
391                         break;
392                 case T_Iter:
393                         ResolveNew(info, targetlist, (Node **) (&(((Iter *) node)->iterexpr)),
394                                            sublevels_up);
395                         break;
396                 case T_ArrayRef:
397                         ResolveNew(info, targetlist, (Node **) (&(((ArrayRef *) node)->refupperindexpr)),
398                                            sublevels_up);
399                         ResolveNew(info, targetlist, (Node **) (&(((ArrayRef *) node)->reflowerindexpr)),
400                                            sublevels_up);
401                         ResolveNew(info, targetlist, (Node **) (&(((ArrayRef *) node)->refexpr)),
402                                            sublevels_up);
403                         ResolveNew(info, targetlist, (Node **) (&(((ArrayRef *) node)->refassgnexpr)),
404                                            sublevels_up);
405                         break;
406                 case T_Var:
407                         {
408                                 int                     this_varno = (int) ((Var *) node)->varno;
409                                 int                     this_varlevelsup = (int) ((Var *) node)->varlevelsup;
410                                 Node       *n;
411
412                                 if (this_varno == info->new_varno &&
413                                         this_varlevelsup == sublevels_up)
414                                 {
415                                         n = FindMatchingNew(targetlist,
416                                                                                 ((Var *) node)->varattno);
417                                         if (n == NULL)
418                                         {
419                                                 if (info->event == CMD_UPDATE)
420                                                 {
421                                                         ((Var *) node)->varno = info->current_varno;
422                                                         ((Var *) node)->varnoold = info->current_varno;
423                                                 }
424                                                 else
425                                                         *nodePtr = make_null(((Var *) node)->vartype);
426                                         }
427                                         else
428                                                 *nodePtr = n;
429                                 }
430                                 break;
431                         }
432                 case T_List:
433                         {
434                                 List       *l;
435
436                                 foreach(l, (List *) node)
437                                         ResolveNew(info, targetlist, (Node **) &(lfirst(l)),
438                                                            sublevels_up);
439                                 break;
440                         }
441                 case T_SubLink:
442                         {
443                                 SubLink    *sublink = (SubLink *) node;
444                                 Query      *query = (Query *) sublink->subselect;
445
446                                 ResolveNew(info, targetlist, (Node **) &(query->qual), sublevels_up + 1);
447                         }
448                         break;
449                 default:
450                         /* ignore the others */
451                         break;
452         }
453 }
454
455 void
456 FixNew(RewriteInfo *info, Query *parsetree)
457 {
458         ResolveNew(info, parsetree->targetList,
459                            (Node **) &(info->rule_action->targetList), 0);
460         ResolveNew(info, parsetree->targetList, &info->rule_action->qual, 0);
461 }
462
463 static void
464 nodeHandleRIRAttributeRule(Node **nodePtr,
465                                                    List *rtable,
466                                                    List *targetlist,
467                                                    int rt_index,
468                                                    int attr_num,
469                                                    int *modified,
470                                                    int *badsql,
471                                                    int sublevels_up)
472 {
473         Node       *node = *nodePtr;
474
475         if (node == NULL)
476                 return;
477         switch (nodeTag(node))
478         {
479                 case T_TargetEntry:
480                         {
481                                 TargetEntry *tle = (TargetEntry *) node;
482
483                                 nodeHandleRIRAttributeRule(&tle->expr, rtable, targetlist,
484                                                                         rt_index, attr_num, modified, badsql,
485                                                                                    sublevels_up);
486                         }
487                         break;
488                 case T_Aggreg:
489                         {
490                                 Aggreg     *agg = (Aggreg *) node;
491
492                                 nodeHandleRIRAttributeRule(&agg->target, rtable, targetlist,
493                                                                         rt_index, attr_num, modified, badsql,
494                                                                                    sublevels_up);
495                         }
496                         break;
497                 case T_Expr:
498                         {
499                                 Expr       *expr = (Expr *) node;
500
501                                 nodeHandleRIRAttributeRule((Node **) (&(expr->args)), rtable,
502                                                                                    targetlist, rt_index, attr_num,
503                                                                                    modified, badsql,
504                                                                                    sublevels_up);
505                         }
506                         break;
507                 case T_Iter:
508                         {
509                                 Iter       *iter = (Iter *) node;
510
511                                 nodeHandleRIRAttributeRule((Node **) (&(iter->iterexpr)), rtable,
512                                                                                    targetlist, rt_index, attr_num,
513                                                                                    modified, badsql,
514                                                                                    sublevels_up);
515                         }
516                         break;
517                 case T_ArrayRef:
518                         {
519                                 ArrayRef           *ref = (ArrayRef *) node;
520
521                                 nodeHandleRIRAttributeRule((Node **) (&(ref->refupperindexpr)), rtable,
522                                                                                    targetlist, rt_index, attr_num,
523                                                                                    modified, badsql,
524                                                                                    sublevels_up);
525                                 nodeHandleRIRAttributeRule((Node **) (&(ref->reflowerindexpr)), rtable,
526                                                                                    targetlist, rt_index, attr_num,
527                                                                                    modified, badsql,
528                                                                                    sublevels_up);
529                                 nodeHandleRIRAttributeRule((Node **) (&(ref->refexpr)), rtable,
530                                                                                    targetlist, rt_index, attr_num,
531                                                                                    modified, badsql,
532                                                                                    sublevels_up);
533                                 nodeHandleRIRAttributeRule((Node **) (&(ref->refassgnexpr)), rtable,
534                                                                                    targetlist, rt_index, attr_num,
535                                                                                    modified, badsql,
536                                                                                    sublevels_up);
537                         }
538                         break;
539                 case T_Var:
540                         {
541                                 int                     this_varno = ((Var *) node)->varno;
542                                 int                     this_varattno = ((Var *) node)->varattno;
543                                 int                     this_varlevelsup = ((Var *) node)->varlevelsup;
544
545                                 if (this_varno == rt_index &&
546                                         this_varattno == attr_num &&
547                                         this_varlevelsup == sublevels_up)
548                                 {
549                                         if (((Var *) node)->vartype == 32)
550                                         {                       /* HACK */
551                                                 *nodePtr = make_null(((Var *) node)->vartype);
552                                                 *modified = TRUE;
553                                                 *badsql = TRUE;
554                                                 break;
555                                         }
556                                         else
557                                         {
558                                                 NameData        name_to_look_for;
559
560                                                 name_to_look_for.data[0] = '\0';
561                                                 namestrcpy(&name_to_look_for,
562                                                                 (char *) get_attname(getrelid(this_varno,
563                                                                                                                           rtable),
564                                                                                                          attr_num));
565                                                 if (name_to_look_for.data[0])
566                                                 {
567                                                         Node       *n;
568
569                                                         n = FindMatchingTLEntry(targetlist, (char *) &name_to_look_for);
570                                                         if (n == NULL)
571                                                                 *nodePtr = make_null(((Var *) node)->vartype);
572                                                         else
573                                                                 *nodePtr = n;
574                                                         *modified = TRUE;
575                                                 }
576                                         }
577                                 }
578                         }
579                         break;
580                 case T_List:
581                         {
582                                 List       *i;
583
584                                 foreach(i, (List *) node)
585                                 {
586                                         nodeHandleRIRAttributeRule((Node **) (&(lfirst(i))), rtable,
587                                                                                   targetlist, rt_index, attr_num,
588                                                                                  modified, badsql, sublevels_up);
589                                 }
590                         }
591                         break;
592                 case T_SubLink:
593                         {
594                                 SubLink    *sublink = (SubLink *) node;
595                                 Query      *query = (Query *) sublink->subselect;
596
597                                 nodeHandleRIRAttributeRule((Node **) &(query->qual), rtable, targetlist,
598                                                                         rt_index, attr_num, modified, badsql,
599                                                                                    sublevels_up + 1);
600                         }
601                         break;
602                 default:
603                         /* ignore the others */
604                         break;
605         }
606 }
607
608 /*
609  * Handles 'on retrieve to relation.attribute
610  *                      do instead retrieve (attribute = expression) w/qual'
611  */
612 void
613 HandleRIRAttributeRule(Query *parsetree,
614                                            List *rtable,
615                                            List *targetlist,
616                                            int rt_index,
617                                            int attr_num,
618                                            int *modified,
619                                            int *badsql)
620 {
621
622         nodeHandleRIRAttributeRule((Node **) (&(parsetree->targetList)), rtable,
623                                                            targetlist, rt_index, attr_num,
624                                                            modified, badsql, 0);
625         nodeHandleRIRAttributeRule(&parsetree->qual, rtable, targetlist,
626                                                            rt_index, attr_num, modified, badsql, 0);
627 }
628
629
630 static void
631 nodeHandleViewRule(Node **nodePtr,
632                                    List *rtable,
633                                    List *targetlist,
634                                    int rt_index,
635                                    int *modified,
636                                    int sublevels_up)
637 {
638         Node       *node = *nodePtr;
639
640         if (node == NULL)
641                 return;
642
643         switch (nodeTag(node))
644         {
645                 case T_TargetEntry:
646                         {
647                                 TargetEntry *tle = (TargetEntry *) node;
648
649                                 nodeHandleViewRule(&(tle->expr), rtable, targetlist,
650                                                                    rt_index, modified, sublevels_up);
651                         }
652                         break;
653                 case T_Aggreg:
654                         {
655                                 Aggreg     *agg = (Aggreg *) node;
656
657                                 nodeHandleViewRule(&(agg->target), rtable, targetlist,
658                                                                    rt_index, modified, sublevels_up);
659                         }
660                         break;
661
662                         /*
663                          * This has to be done to make queries using groupclauses work
664                          * on views
665                          */
666                 case T_GroupClause:
667                         {
668                                 GroupClause *group = (GroupClause *) node;
669
670                                 nodeHandleViewRule((Node **) (&(group->entry)), rtable, targetlist,
671                                                                    rt_index, modified, sublevels_up);
672                         }
673                         break;
674                 case T_Expr:
675                         {
676                                 Expr       *expr = (Expr *) node;
677
678                                 nodeHandleViewRule((Node **) (&(expr->args)),
679                                                                    rtable, targetlist,
680                                                                    rt_index, modified, sublevels_up);
681                         }
682                         break;
683                 case T_Iter:
684                         {
685                                 Iter       *iter = (Iter *) node;
686
687                                 nodeHandleViewRule((Node **) (&(iter->iterexpr)),
688                                                                    rtable, targetlist,
689                                                                    rt_index, modified, sublevels_up);
690                         }
691                         break;
692                 case T_ArrayRef:
693                         {
694                                 ArrayRef           *ref = (ArrayRef *) node;
695
696                                 nodeHandleViewRule((Node **) (&(ref->refupperindexpr)),
697                                                                    rtable, targetlist,
698                                                                    rt_index, modified, sublevels_up);
699                                 nodeHandleViewRule((Node **) (&(ref->reflowerindexpr)),
700                                                                    rtable, targetlist,
701                                                                    rt_index, modified, sublevels_up);
702                                 nodeHandleViewRule((Node **) (&(ref->refexpr)),
703                                                                    rtable, targetlist,
704                                                                    rt_index, modified, sublevels_up);
705                                 nodeHandleViewRule((Node **) (&(ref->refassgnexpr)),
706                                                                    rtable, targetlist,
707                                                                    rt_index, modified, sublevels_up);
708                         }
709                         break;
710                 case T_Var:
711                         {
712                                 Var                *var = (Var *) node;
713                                 int                     this_varno = var->varno;
714                                 int                     this_varlevelsup = var->varlevelsup;
715                                 Node       *n;
716
717                                 if (this_varno == rt_index &&
718                                         this_varlevelsup == sublevels_up)
719                                 {
720                                         n = FindMatchingTLEntry(targetlist,
721                                                                                  get_attname(getrelid(this_varno,
722                                                                                                                           rtable),
723                                                                                                          var->varattno));
724                                         if (n == NULL)
725                                                 *nodePtr = make_null(((Var *) node)->vartype);
726                                         else
727                                         {
728                                                 /*
729                                                  * This is a hack: The varlevelsup of the orignal
730                                                  * variable and the new one should be the same.
731                                                  * Normally we adapt the node by changing a
732                                                  * pointer to point to a var contained in
733                                                  * 'targetlist'. In the targetlist all
734                                                  * varlevelsups are 0 so if we want to change it
735                                                  * to the original value we have to copy the node
736                                                  * before! (Maybe this will cause troubles with
737                                                  * some sophisticated queries on views?)
738                                                  */
739                                                 if (this_varlevelsup > 0)
740                                                         *nodePtr = copyObject(n);
741                                                 else
742                                                         *nodePtr = n;
743
744                                                 if (nodeTag(nodePtr) == T_Var)
745                                                         ((Var *) *nodePtr)->varlevelsup = this_varlevelsup;
746                                                 else
747                                                         nodeHandleViewRule(&n, rtable, targetlist,
748                                                                                    rt_index, modified, sublevels_up);
749                                         }
750                                         *modified = TRUE;
751                                 }
752                                 break;
753                         }
754                 case T_List:
755                         {
756                                 List       *l;
757
758                                 foreach(l, (List *) node)
759                                 {
760                                         nodeHandleViewRule((Node **) (&(lfirst(l))),
761                                                                            rtable, targetlist,
762                                                                            rt_index, modified, sublevels_up);
763                                 }
764                         }
765                         break;
766                 case T_SubLink:
767                         {
768                                 SubLink    *sublink = (SubLink *) node;
769                                 Query      *query = (Query *) sublink->subselect;
770
771                                 nodeHandleViewRule((Node **) &(query->qual), rtable, targetlist,
772                                                                    rt_index, modified, sublevels_up + 1);
773
774                                 /*
775                                  * We also have to adapt the variables used in
776                                  * sublink->lefthand and sublink->oper
777                                  */
778                                 nodeHandleViewRule((Node **) &(sublink->lefthand), rtable,
779                                                    targetlist, rt_index, modified, sublevels_up);
780
781                                 /*
782                                  * Make sure the first argument of sublink->oper points to
783                                  * the same var as sublink->lefthand does otherwise we
784                                  * will run into troubles using aggregates (aggno will not
785                                  * be set correctly
786                                  */
787                                 pfree(lfirst(((Expr *) lfirst(sublink->oper))->args));
788                                 lfirst(((Expr *) lfirst(sublink->oper))->args) =
789                                         lfirst(sublink->lefthand);
790                         }
791                         break;
792                 default:
793                         /* ignore the others */
794                         break;
795         }
796 }
797
798 #ifdef NOT_USED
799 void
800 HandleViewRule(Query *parsetree,
801                            List *rtable,
802                            List *targetlist,
803                            int rt_index,
804                            int *modified)
805 {
806         nodeHandleViewRule(&parsetree->qual, rtable, targetlist, rt_index,
807                                            modified, 0);
808         nodeHandleViewRule((Node **) (&(parsetree->targetList)), rtable, targetlist,
809                                            rt_index, modified, 0);
810
811         /*
812          * The variables in the havingQual and groupClause also have to be
813          * adapted
814          */
815         nodeHandleViewRule(&parsetree->havingQual, rtable, targetlist, rt_index,
816                                            modified, 0);
817         nodeHandleViewRule((Node **) (&(parsetree->groupClause)), rtable, targetlist, rt_index,
818                                            modified, 0);
819 }
820 #endif
821