1 /*-------------------------------------------------------------------------
5 * Copyright (c) 1994, Regents of the University of California
9 * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.3 1996/11/06 06:48:44 scrappy Exp $
11 *-------------------------------------------------------------------------
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"
27 #include "nodes/plannodes.h"
28 #include "optimizer/clauses.h"
30 static void ResolveNew(RewriteInfo *info, List *targetlist, Node **node);
35 OffsetVarNodes(Node *node, int offset)
39 switch (nodeTag(node)) {
42 TargetEntry *tle = (TargetEntry *)node;
43 OffsetVarNodes(tle->expr, offset);
48 Expr *expr = (Expr*)node;
49 OffsetVarNodes((Node*)expr->args, offset);
54 Var *var = (Var*)node;
56 var->varnoold += offset;
63 foreach(l, (List*)node) {
64 OffsetVarNodes(lfirst(l), offset);
69 /* ignore the others */
75 ChangeVarNodes(Node *node, int old_varno, int new_varno)
79 switch (nodeTag(node)) {
82 TargetEntry *tle = (TargetEntry *)node;
83 ChangeVarNodes(tle->expr, old_varno, new_varno);
88 Expr *expr = (Expr*)node;
89 ChangeVarNodes((Node*)expr->args, old_varno, new_varno);
94 Var *var = (Var*)node;
95 if (var->varno == old_varno) {
96 var->varno = new_varno;
97 var->varnoold = new_varno;
104 foreach (l, (List*)node) {
105 ChangeVarNodes(lfirst(l), old_varno, new_varno);
110 /* ignore the others */
116 AddQual(Query *parsetree, Node *qual)
123 copy = copyObject(qual);
124 old = parsetree->qual;
126 parsetree->qual = copy;
129 (Node*)make_andclause(makeList(parsetree->qual, copy, -1));
133 AddNotQual(Query *parsetree, Node *qual)
137 if (qual == NULL) return;
139 copy = (Node*)make_notclause(copyObject(qual));
141 AddQual(parsetree,copy);
147 Const *c = makeNode(Const);
150 c->constlen = get_typlen(type);
151 c->constvalue = PointerGetDatum(NULL);
152 c->constisnull = true;
153 c->constbyval = get_typbyval(type);
158 FixResdomTypes (List *tlist)
163 TargetEntry *tle = lfirst(i);
165 if (nodeTag(tle->expr) == T_Var) {
166 Var *var = (Var*)tle->expr;
168 tle->resdom->restype = var->vartype;
169 tle->resdom->reslen = get_typlen(var->vartype);
175 FindMatchingNew(List *tlist, int attno)
179 foreach (i, tlist ) {
180 TargetEntry *tle = lfirst(i);
182 if (tle->resdom->resno == attno ) {
190 FindMatchingTLEntry(List *tlist, char *e_attname)
195 TargetEntry *tle = lfirst(i);
198 resname = tle->resdom->resname;
199 if (!strcmp(e_attname, resname))
206 ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr)
208 Node *node = *nodePtr;
213 switch(nodeTag(node)) {
215 ResolveNew(info, targetlist, &((TargetEntry*)node)->expr);
218 ResolveNew(info, targetlist, (Node**)(&(((Expr*)node)->args)));
221 int this_varno = (int)((Var*)node)->varno;
224 if (this_varno == info->new_varno) {
225 n = FindMatchingNew(targetlist,
226 ((Var*)node)->varattno);
228 if (info->event == CMD_UPDATE) {
229 ((Var*)node)->varno = info->current_varno;
230 ((Var*)node)->varnoold = info->current_varno;
232 *nodePtr = make_null(((Var*)node)->vartype);
242 foreach(l, (List*)node) {
243 ResolveNew(info, targetlist, (Node**)&(lfirst(l)));
248 /* ignore the others */
254 FixNew(RewriteInfo* info, Query *parsetree)
256 ResolveNew(info, parsetree->targetList,
257 (Node**)&(info->rule_action->targetList));
258 ResolveNew(info, parsetree->targetList, &info->rule_action->qual);
262 nodeHandleRIRAttributeRule(Node **nodePtr,
270 Node *node = *nodePtr;
274 switch (nodeTag(node)) {
278 foreach(i, (List*)node) {
279 nodeHandleRIRAttributeRule((Node**)(&(lfirst(i))), rtable,
280 targetlist, rt_index, attr_num,
287 TargetEntry *tle = (TargetEntry *)node;
288 nodeHandleRIRAttributeRule(&tle->expr, rtable, targetlist,
289 rt_index, attr_num, modified, badsql);
294 Expr *expr = (Expr *)node;
295 nodeHandleRIRAttributeRule((Node**)(&(expr->args)), rtable,
296 targetlist, rt_index, attr_num,
302 int this_varno = (int) ((Var*)node)->varno;
303 NameData name_to_look_for;
304 memset(name_to_look_for.data, 0, NAMEDATALEN);
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);
314 namestrcpy(&name_to_look_for,
315 (char *)get_attname(getrelid(this_varno,
320 if (name_to_look_for.data[0]) {
323 n = FindMatchingTLEntry(targetlist, (char *)&name_to_look_for);
325 *nodePtr = make_null(((Var*) node)->vartype);
334 /* ignore the others */
340 * Handles 'on retrieve to relation.attribute
341 * do instead retrieve (attribute = expression) w/qual'
344 HandleRIRAttributeRule(Query *parsetree,
352 nodeHandleRIRAttributeRule((Node**)(&(parsetree->targetList)), rtable,
353 targetlist, rt_index, attr_num,
355 nodeHandleRIRAttributeRule(&parsetree->qual, rtable, targetlist,
356 rt_index, attr_num, modified, badsql);
361 nodeHandleViewRule(Node **nodePtr,
367 Node *node = *nodePtr;
372 switch (nodeTag(node)) {
376 foreach (l, (List*)node) {
377 nodeHandleViewRule((Node**) (&(lfirst(l))),
385 TargetEntry *tle = (TargetEntry *)node;
386 nodeHandleViewRule(&(tle->expr), rtable, targetlist,
392 Expr *expr = (Expr*)node;
393 nodeHandleViewRule((Node**)(&(expr->args)),
400 Var *var = (Var*)node;
401 int this_varno = var->varno;
404 if (this_varno == rt_index) {
405 n = FindMatchingTLEntry(targetlist,
406 get_attname(getrelid(this_varno,
410 *nodePtr = make_null(((Var*) node)->vartype);
419 /* ignore the others */
425 HandleViewRule(Query *parsetree,
431 nodeHandleViewRule(&parsetree->qual, rtable, targetlist, rt_index,
433 nodeHandleViewRule((Node**)(&(parsetree->targetList)), rtable, targetlist,