1 /*-------------------------------------------------------------------------
5 * Copyright (c) 1994, Regents of the University of California
9 * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.4 1996/11/10 03:02:04 momjian 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/rewriteManip.h"
25 #include "rewrite/rewriteSupport.h"
26 #include "rewrite/locks.h"
28 #include "nodes/plannodes.h"
29 #include "optimizer/clauses.h"
31 static void ResolveNew(RewriteInfo *info, List *targetlist, Node **node);
36 OffsetVarNodes(Node *node, int offset)
40 switch (nodeTag(node)) {
43 TargetEntry *tle = (TargetEntry *)node;
44 OffsetVarNodes(tle->expr, offset);
49 Expr *expr = (Expr*)node;
50 OffsetVarNodes((Node*)expr->args, offset);
55 Var *var = (Var*)node;
57 var->varnoold += offset;
64 foreach(l, (List*)node) {
65 OffsetVarNodes(lfirst(l), offset);
70 /* ignore the others */
76 ChangeVarNodes(Node *node, int old_varno, int new_varno)
80 switch (nodeTag(node)) {
83 TargetEntry *tle = (TargetEntry *)node;
84 ChangeVarNodes(tle->expr, old_varno, new_varno);
89 Expr *expr = (Expr*)node;
90 ChangeVarNodes((Node*)expr->args, old_varno, new_varno);
95 Var *var = (Var*)node;
96 if (var->varno == old_varno) {
97 var->varno = new_varno;
98 var->varnoold = new_varno;
105 foreach (l, (List*)node) {
106 ChangeVarNodes(lfirst(l), old_varno, new_varno);
111 /* ignore the others */
117 AddQual(Query *parsetree, Node *qual)
124 copy = copyObject(qual);
125 old = parsetree->qual;
127 parsetree->qual = copy;
130 (Node*)make_andclause(makeList(parsetree->qual, copy, -1));
134 AddNotQual(Query *parsetree, Node *qual)
138 if (qual == NULL) return;
140 copy = (Node*)make_notclause(copyObject(qual));
142 AddQual(parsetree,copy);
148 Const *c = makeNode(Const);
151 c->constlen = get_typlen(type);
152 c->constvalue = PointerGetDatum(NULL);
153 c->constisnull = true;
154 c->constbyval = get_typbyval(type);
159 FixResdomTypes (List *tlist)
164 TargetEntry *tle = lfirst(i);
166 if (nodeTag(tle->expr) == T_Var) {
167 Var *var = (Var*)tle->expr;
169 tle->resdom->restype = var->vartype;
170 tle->resdom->reslen = get_typlen(var->vartype);
176 FindMatchingNew(List *tlist, int attno)
180 foreach (i, tlist ) {
181 TargetEntry *tle = lfirst(i);
183 if (tle->resdom->resno == attno ) {
191 FindMatchingTLEntry(List *tlist, char *e_attname)
196 TargetEntry *tle = lfirst(i);
199 resname = tle->resdom->resname;
200 if (!strcmp(e_attname, resname))
207 ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr)
209 Node *node = *nodePtr;
214 switch(nodeTag(node)) {
216 ResolveNew(info, targetlist, &((TargetEntry*)node)->expr);
219 ResolveNew(info, targetlist, (Node**)(&(((Expr*)node)->args)));
222 int this_varno = (int)((Var*)node)->varno;
225 if (this_varno == info->new_varno) {
226 n = FindMatchingNew(targetlist,
227 ((Var*)node)->varattno);
229 if (info->event == CMD_UPDATE) {
230 ((Var*)node)->varno = info->current_varno;
231 ((Var*)node)->varnoold = info->current_varno;
233 *nodePtr = make_null(((Var*)node)->vartype);
243 foreach(l, (List*)node) {
244 ResolveNew(info, targetlist, (Node**)&(lfirst(l)));
249 /* ignore the others */
255 FixNew(RewriteInfo* info, Query *parsetree)
257 ResolveNew(info, parsetree->targetList,
258 (Node**)&(info->rule_action->targetList));
259 ResolveNew(info, parsetree->targetList, &info->rule_action->qual);
263 nodeHandleRIRAttributeRule(Node **nodePtr,
271 Node *node = *nodePtr;
275 switch (nodeTag(node)) {
279 foreach(i, (List*)node) {
280 nodeHandleRIRAttributeRule((Node**)(&(lfirst(i))), rtable,
281 targetlist, rt_index, attr_num,
288 TargetEntry *tle = (TargetEntry *)node;
289 nodeHandleRIRAttributeRule(&tle->expr, rtable, targetlist,
290 rt_index, attr_num, modified, badsql);
295 Expr *expr = (Expr *)node;
296 nodeHandleRIRAttributeRule((Node**)(&(expr->args)), rtable,
297 targetlist, rt_index, attr_num,
303 int this_varno = (int) ((Var*)node)->varno;
304 NameData name_to_look_for;
305 memset(name_to_look_for.data, 0, NAMEDATALEN);
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);
315 namestrcpy(&name_to_look_for,
316 (char *)get_attname(getrelid(this_varno,
321 if (name_to_look_for.data[0]) {
324 n = FindMatchingTLEntry(targetlist, (char *)&name_to_look_for);
326 *nodePtr = make_null(((Var*) node)->vartype);
335 /* ignore the others */
341 * Handles 'on retrieve to relation.attribute
342 * do instead retrieve (attribute = expression) w/qual'
345 HandleRIRAttributeRule(Query *parsetree,
353 nodeHandleRIRAttributeRule((Node**)(&(parsetree->targetList)), rtable,
354 targetlist, rt_index, attr_num,
356 nodeHandleRIRAttributeRule(&parsetree->qual, rtable, targetlist,
357 rt_index, attr_num, modified, badsql);
362 nodeHandleViewRule(Node **nodePtr,
368 Node *node = *nodePtr;
373 switch (nodeTag(node)) {
377 foreach (l, (List*)node) {
378 nodeHandleViewRule((Node**) (&(lfirst(l))),
386 TargetEntry *tle = (TargetEntry *)node;
387 nodeHandleViewRule(&(tle->expr), rtable, targetlist,
393 Expr *expr = (Expr*)node;
394 nodeHandleViewRule((Node**)(&(expr->args)),
401 Var *var = (Var*)node;
402 int this_varno = var->varno;
405 if (this_varno == rt_index) {
406 n = FindMatchingTLEntry(targetlist,
407 get_attname(getrelid(this_varno,
411 *nodePtr = make_null(((Var*) node)->vartype);
420 /* ignore the others */
426 HandleViewRule(Query *parsetree,
432 nodeHandleViewRule(&parsetree->qual, rtable, targetlist, rt_index,
434 nodeHandleViewRule((Node**)(&(parsetree->targetList)), rtable, targetlist,