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