]> granicus.if.org Git - postgresql/blob - src/backend/rewrite/rewriteManip.c
Postgres95 1.01 Distribution - Virgin Sources
[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.1.1.1 1996/07/09 06:21:52 scrappy Exp $
10  *
11  *-------------------------------------------------------------------------
12  */
13 #include "postgres.h"
14 #include "nodes/pg_list.h"
15 #include "utils/elog.h"
16 #include "nodes/nodes.h"
17 #include "nodes/relation.h"
18 #include "nodes/primnodes.h"
19 #include "parser/parsetree.h"           /* for getrelid() */
20 #include "utils/lsyscache.h"
21 #include "utils/builtins.h"
22 #include "rewrite/rewriteHandler.h"
23 #include "rewrite/rewriteSupport.h"
24 #include "rewrite/locks.h"
25
26 #include "nodes/plannodes.h"
27 #include "optimizer/clauses.h"
28
29 static void ResolveNew(RewriteInfo *info, List *targetlist, Node **node);
30
31
32
33 void
34 OffsetVarNodes(Node *node, int offset)
35 {
36     if (node==NULL)
37         return;
38     switch (nodeTag(node)) {
39     case T_TargetEntry:
40         {
41             TargetEntry *tle = (TargetEntry *)node;
42             OffsetVarNodes(tle->expr, offset);
43         }
44         break;
45     case T_Expr:
46         {
47             Expr *expr = (Expr*)node;
48             OffsetVarNodes((Node*)expr->args, offset);
49         }
50         break;
51     case T_Var:
52         {
53             Var *var = (Var*)node;
54             var->varno += offset;
55             var->varnoold += offset;
56         }
57         break;
58     case T_List:
59         {
60             List *l;
61
62             foreach(l, (List*)node) {
63                 OffsetVarNodes(lfirst(l), offset);
64             }
65         }
66         break;
67     default:
68         /* ignore the others */
69         break;
70     }
71 }
72
73 void
74 ChangeVarNodes(Node *node, int old_varno, int new_varno)
75 {
76     if (node==NULL)
77         return;
78     switch (nodeTag(node)) {
79     case T_TargetEntry:
80         {
81             TargetEntry *tle = (TargetEntry *)node;
82             ChangeVarNodes(tle->expr, old_varno, new_varno);
83         }
84         break;
85     case T_Expr:
86         {
87             Expr *expr = (Expr*)node;
88             ChangeVarNodes((Node*)expr->args, old_varno, new_varno);
89         }
90         break;
91     case T_Var:
92         {
93             Var *var = (Var*)node;
94             if (var->varno == old_varno) {
95                 var->varno = new_varno;
96                 var->varnoold = new_varno;
97             }
98         }
99         break;
100     case T_List:
101         {
102             List *l;
103             foreach (l, (List*)node) {
104                 ChangeVarNodes(lfirst(l), old_varno, new_varno);
105             }
106         }
107         break;
108     default:
109         /* ignore the others */
110         break;
111     }
112 }
113
114 void
115 AddQual(Query *parsetree, Node *qual)
116 {
117     Node *copy, *old;
118     
119     if (qual == NULL)
120         return;
121     
122     copy = copyObject(qual);
123     old = parsetree->qual;
124     if (old == NULL)
125         parsetree->qual = copy;
126     else 
127         parsetree->qual = 
128             (Node*)make_andclause(makeList(parsetree->qual, copy, -1));
129 }
130
131 void
132 AddNotQual(Query *parsetree, Node *qual)
133 {
134     Node *copy;
135     
136     if (qual == NULL) return;
137     
138     copy = (Node*)make_notclause(copyObject(qual));
139
140     AddQual(parsetree,copy);
141 }
142
143 static Node *
144 make_null(Oid type)
145 {
146     Const *c = makeNode(Const);
147     
148     c->consttype = type;
149     c->constlen = get_typlen(type);
150     c->constvalue = PointerGetDatum(NULL);
151     c->constisnull = true;
152     c->constbyval = get_typbyval(type);
153     return (Node*)c;
154 }
155
156 void
157 FixResdomTypes (List *tlist)
158 {
159     List *i;
160
161     foreach (i, tlist) {
162         TargetEntry *tle = lfirst(i);
163
164         if (nodeTag(tle->expr) == T_Var) {
165             Var *var = (Var*)tle->expr;
166
167             tle->resdom->restype = var->vartype;
168             tle->resdom->reslen = get_typlen(var->vartype);
169         }
170     }
171 }
172
173 static Node *
174 FindMatchingNew(List *tlist, int attno)
175 {
176     List *i;
177     
178     foreach (i, tlist ) {
179         TargetEntry *tle = lfirst(i);
180
181         if (tle->resdom->resno == attno ) {
182             return (tle->expr);
183         }
184     }
185     return NULL;
186 }
187
188 static Node *
189 FindMatchingTLEntry(List *tlist, char *e_attname)
190 {
191     List *i;
192     
193     foreach (i, tlist) {
194         TargetEntry *tle = lfirst(i);
195         char *resname;
196
197         resname = tle->resdom->resname;
198         if (!strcmp(e_attname, resname))
199             return (tle->expr);
200     }
201     return NULL;
202 }
203
204 static void
205 ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr)
206 {
207     Node *node = *nodePtr;
208
209     if (node == NULL)
210         return;
211
212     switch(nodeTag(node)) {
213     case T_TargetEntry:
214         ResolveNew(info, targetlist, &((TargetEntry*)node)->expr);
215         break;
216     case T_Expr:
217         ResolveNew(info, targetlist, (Node**)(&(((Expr*)node)->args)));
218         break;
219     case T_Var: {
220         int this_varno = (int)((Var*)node)->varno;
221         Node *n;
222             
223         if (this_varno == info->new_varno) {
224             n = FindMatchingNew(targetlist,
225                                 ((Var*)node)->varattno);
226             if (n == NULL) {
227                 if (info->event == CMD_UPDATE) {
228                     ((Var*)node)->varno = info->current_varno;
229                     ((Var*)node)->varnoold = info->current_varno;
230                 } else {
231                     *nodePtr = make_null(((Var*)node)->vartype);
232                 }
233             } else {
234                 *nodePtr = n;
235             }
236         }
237         break;
238     }
239     case T_List: {
240         List *l;
241         foreach(l, (List*)node) {
242             ResolveNew(info, targetlist, (Node**)&(lfirst(l)));
243         }
244         break;
245     }
246     default:
247         /* ignore the others */
248         break;
249     }
250 }
251
252 void
253 FixNew(RewriteInfo* info, Query *parsetree)
254 {
255     ResolveNew(info, parsetree->targetList,
256                (Node**)&(info->rule_action->targetList));
257     ResolveNew(info, parsetree->targetList, &info->rule_action->qual);
258 }
259
260 static void
261 nodeHandleRIRAttributeRule(Node **nodePtr,
262                            List *rtable,
263                            List *targetlist,
264                            int rt_index,
265                            int attr_num,
266                            int *modified,
267                            int *badsql)
268 {
269     Node *node = *nodePtr;
270
271     if (node == NULL)
272         return;
273     switch (nodeTag(node)) {
274     case T_List:
275         {
276             List *i;
277             foreach(i, (List*)node) {
278                 nodeHandleRIRAttributeRule((Node**)(&(lfirst(i))), rtable,
279                                            targetlist, rt_index, attr_num,
280                                            modified, badsql);
281             }
282         }
283         break;
284     case T_TargetEntry:
285         {
286             TargetEntry *tle = (TargetEntry *)node;
287             nodeHandleRIRAttributeRule(&tle->expr, rtable, targetlist,
288                                        rt_index, attr_num, modified, badsql);
289         }
290         break;
291     case T_Expr:
292         {
293             Expr *expr = (Expr *)node;
294             nodeHandleRIRAttributeRule((Node**)(&(expr->args)), rtable,
295                                        targetlist, rt_index, attr_num,
296                                        modified, badsql);
297         }
298         break;
299     case T_Var:
300         {
301             int this_varno = (int) ((Var*)node)->varno;
302             NameData name_to_look_for;
303             memset(name_to_look_for.data, 0, NAMEDATALEN);
304
305             if (this_varno == rt_index &&
306                 ((Var*) node)->varattno == attr_num) {
307                 if (((Var*)node)->vartype == 32) { /* HACK */
308                     *nodePtr = make_null(((Var*)node)->vartype);
309                     *modified = TRUE;
310                     *badsql = TRUE;
311                     break;
312                 } else {
313                     namestrcpy(&name_to_look_for,
314                                (char *)get_attname(getrelid(this_varno,
315                                                             rtable),
316                                                    attr_num));
317                 }
318             }
319             if (name_to_look_for.data[0]) {
320                 Node *n;
321                 
322                 n = FindMatchingTLEntry(targetlist, &name_to_look_for);
323                 if (n == NULL) {
324                     *nodePtr = make_null(((Var*) node)->vartype);
325                 } else {
326                     *nodePtr = n;
327                 }
328                 *modified = TRUE;
329             }
330         }
331         break;
332     default:
333         /* ignore the others */
334         break;
335     }
336 }
337
338 /* 
339  * Handles 'on retrieve to relation.attribute
340  *          do instead retrieve (attribute = expression) w/qual'
341  */
342 void
343 HandleRIRAttributeRule(Query *parsetree,
344                        List *rtable,
345                        List *targetlist,
346                        int rt_index,
347                        int attr_num,
348                        int *modified,
349                        int *badsql)
350 {
351     nodeHandleRIRAttributeRule((Node**)(&(parsetree->targetList)), rtable,
352                                targetlist, rt_index, attr_num,
353                                modified, badsql);
354     nodeHandleRIRAttributeRule(&parsetree->qual, rtable, targetlist,
355                                rt_index, attr_num, modified, badsql);
356 }
357
358
359 static void
360 nodeHandleViewRule(Node **nodePtr,
361                    List *rtable,
362                    List *targetlist,
363                    int rt_index,
364                    int *modified)
365 {
366     Node *node = *nodePtr;
367     
368     if (node == NULL)
369         return;
370
371     switch (nodeTag(node)) {
372     case T_List:
373         {
374             List *l;
375             foreach (l, (List*)node) {
376                 nodeHandleViewRule((Node**) (&(lfirst(l))),
377                                    rtable, targetlist,
378                                    rt_index, modified);
379             }
380         }
381         break;
382     case T_TargetEntry:
383         {
384             TargetEntry *tle = (TargetEntry *)node;
385             nodeHandleViewRule(&(tle->expr), rtable, targetlist,
386                                rt_index, modified);
387         }
388         break;
389     case T_Expr:
390         {
391             Expr *expr = (Expr*)node;
392             nodeHandleViewRule((Node**)(&(expr->args)),
393                                rtable, targetlist,
394                                rt_index, modified);
395         }
396         break;
397     case T_Var:
398         {
399             Var *var = (Var*)node;
400             int this_varno = var->varno;
401             Node *n;
402
403             if (this_varno == rt_index) {
404                 n = FindMatchingTLEntry(targetlist,
405                                         get_attname(getrelid(this_varno,
406                                                              rtable),
407                                                     var->varattno));
408                 if (n == NULL) {
409                     *nodePtr = make_null(((Var*) node)->vartype);
410                 } else {
411                     *nodePtr = n;
412                 }
413                 *modified = TRUE;
414             }
415             break;
416         }
417     default:
418         /* ignore the others */
419         break;
420     }
421 }
422
423 void
424 HandleViewRule(Query *parsetree,
425                List *rtable,
426                List *targetlist,
427                int rt_index,
428                int *modified)
429 {
430     nodeHandleViewRule(&parsetree->qual, rtable, targetlist, rt_index,
431                        modified);
432     nodeHandleViewRule((Node**)(&(parsetree->targetList)), rtable, targetlist,
433                        rt_index, modified);
434 }
435