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