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