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