The patch does 2 things:
Fixes a bug in the rule system that caused a crashing backend when a join-view with calculated column is used in subselect. Modifies EXPLAIN to explain rewritten queries instead of the plain SeqScan on a view. Rules can produce very deep MORE Jan.
This commit is contained in:
parent
858a3b570a
commit
524f4b2d10
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.24 1998/09/01 04:27:53 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.25 1998/10/21 16:21:20 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -26,6 +26,7 @@
|
|||||||
#include <optimizer/planner.h>
|
#include <optimizer/planner.h>
|
||||||
#include <access/xact.h>
|
#include <access/xact.h>
|
||||||
#include <utils/relcache.h>
|
#include <utils/relcache.h>
|
||||||
|
#include <rewrite/rewriteHandler.h>
|
||||||
|
|
||||||
typedef struct ExplainState
|
typedef struct ExplainState
|
||||||
{
|
{
|
||||||
@ -37,6 +38,8 @@ typedef struct ExplainState
|
|||||||
} ExplainState;
|
} ExplainState;
|
||||||
|
|
||||||
static char *Explain_PlanToString(Plan *plan, ExplainState *es);
|
static char *Explain_PlanToString(Plan *plan, ExplainState *es);
|
||||||
|
static void ExplainOneQuery(Query *query, bool verbose, CommandDest dest);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ExplainQuery -
|
* ExplainQuery -
|
||||||
@ -46,11 +49,8 @@ static char *Explain_PlanToString(Plan *plan, ExplainState *es);
|
|||||||
void
|
void
|
||||||
ExplainQuery(Query *query, bool verbose, CommandDest dest)
|
ExplainQuery(Query *query, bool verbose, CommandDest dest)
|
||||||
{
|
{
|
||||||
char *s = NULL,
|
List *rewritten;
|
||||||
*s2;
|
List *l;
|
||||||
Plan *plan;
|
|
||||||
ExplainState *es;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
if (IsAbortedTransactionBlockState())
|
if (IsAbortedTransactionBlockState())
|
||||||
{
|
{
|
||||||
@ -64,6 +64,35 @@ ExplainQuery(Query *query, bool verbose, CommandDest dest)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Rewrite through rule system */
|
||||||
|
rewritten = QueryRewrite(query);
|
||||||
|
|
||||||
|
/* In the case of an INSTEAD NOTHING, tell at least that */
|
||||||
|
if (rewritten == NIL)
|
||||||
|
{
|
||||||
|
elog(NOTICE, "query rewrites to nothing");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Explain every plan */
|
||||||
|
foreach(l, rewritten)
|
||||||
|
ExplainOneQuery(lfirst(l), verbose, dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ExplainOneQuery -
|
||||||
|
* print out the execution plan for one query
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ExplainOneQuery(Query *query, bool verbose, CommandDest dest)
|
||||||
|
{
|
||||||
|
char *s = NULL,
|
||||||
|
*s2;
|
||||||
|
Plan *plan;
|
||||||
|
ExplainState *es;
|
||||||
|
int len;
|
||||||
|
|
||||||
/* plan the queries (XXX we've ignored rewrite!!) */
|
/* plan the queries (XXX we've ignored rewrite!!) */
|
||||||
plan = planner(query);
|
plan = planner(query);
|
||||||
|
|
||||||
@ -202,8 +231,13 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es)
|
|||||||
{
|
{
|
||||||
RangeTblEntry *rte = nth(((Scan *) plan)->scanrelid - 1, es->rtable);
|
RangeTblEntry *rte = nth(((Scan *) plan)->scanrelid - 1, es->rtable);
|
||||||
|
|
||||||
sprintf(buf, " on %s", rte->refname);
|
appendStringInfo(str, " on ");
|
||||||
appendStringInfo(str, buf);
|
if (strcmp(rte->refname, rte->relname) != 0)
|
||||||
|
{
|
||||||
|
sprintf(buf, "%s ", rte->relname);
|
||||||
|
appendStringInfo(str, buf);
|
||||||
|
}
|
||||||
|
appendStringInfo(str, rte->refname);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -232,7 +266,7 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es)
|
|||||||
for (i = 0; i < indent; i++)
|
for (i = 0; i < indent; i++)
|
||||||
appendStringInfo(str, " ");
|
appendStringInfo(str, " ");
|
||||||
appendStringInfo(str, " -> ");
|
appendStringInfo(str, " -> ");
|
||||||
explain_outNode(str, ((SubPlan *) lfirst(lst))->plan, indent + 4, es);
|
explain_outNode(str, ((SubPlan *) lfirst(lst))->plan, indent + 2, es);
|
||||||
}
|
}
|
||||||
es->rtable = saved_rtable;
|
es->rtable = saved_rtable;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/recipe.c,v 1.24 1998/09/01 04:27:56 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/recipe.c,v 1.25 1998/10/21 16:21:21 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -350,8 +350,8 @@ tg_rewriteQuery(TgRecipe * r,
|
|||||||
* need to offset the var nodes in the qual and targetlist
|
* need to offset the var nodes in the qual and targetlist
|
||||||
* because they are indexed off the original rtable
|
* because they are indexed off the original rtable
|
||||||
*/
|
*/
|
||||||
OffsetVarNodes((Node *) inputQ->qual, rt_length);
|
OffsetVarNodes((Node *) inputQ->qual, rt_length, 0);
|
||||||
OffsetVarNodes((Node *) inputQ->targetList, rt_length);
|
OffsetVarNodes((Node *) inputQ->targetList, rt_length, 0);
|
||||||
|
|
||||||
/* append the range tables from the children nodes */
|
/* append the range tables from the children nodes */
|
||||||
rtable = nconc(rtable, input_rtable);
|
rtable = nconc(rtable, input_rtable);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/view.c,v 1.25 1998/09/01 04:28:10 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/view.c,v 1.26 1998/10/21 16:21:22 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -219,10 +219,10 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse)
|
|||||||
/*
|
/*
|
||||||
* first offset all var nodes by 2
|
* first offset all var nodes by 2
|
||||||
*/
|
*/
|
||||||
OffsetVarNodes((Node *) viewParse->targetList, 2);
|
OffsetVarNodes((Node *) viewParse->targetList, 2, 0);
|
||||||
OffsetVarNodes(viewParse->qual, 2);
|
OffsetVarNodes(viewParse->qual, 2, 0);
|
||||||
|
|
||||||
OffsetVarNodes(viewParse->havingQual, 2);
|
OffsetVarNodes(viewParse->havingQual, 2, 0);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.24 1998/10/20 17:21:43 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.25 1998/10/21 16:21:24 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -48,8 +48,6 @@ static RewriteInfo *gatherRewriteMeta(Query *parsetree,
|
|||||||
bool *instead_flag);
|
bool *instead_flag);
|
||||||
static bool rangeTableEntry_used(Node *node, int rt_index, int sublevels_up);
|
static bool rangeTableEntry_used(Node *node, int rt_index, int sublevels_up);
|
||||||
static bool attribute_used(Node *node, int rt_index, int attno, int sublevels_up);
|
static bool attribute_used(Node *node, int rt_index, int attno, int sublevels_up);
|
||||||
static void offset_varnodes(Node *node, int offset, int sublevels_up);
|
|
||||||
static void change_varnodes(Node *node, int rt_index, int new_index, int sublevels_up);
|
|
||||||
static void modifyAggregUplevel(Node *node);
|
static void modifyAggregUplevel(Node *node);
|
||||||
static void modifyAggregChangeVarnodes(Node **nodePtr, int rt_index, int new_index, int sublevels_up);
|
static void modifyAggregChangeVarnodes(Node **nodePtr, int rt_index, int new_index, int sublevels_up);
|
||||||
static void modifyAggregDropQual(Node **nodePtr, Node *orignode, Expr *expr);
|
static void modifyAggregDropQual(Node **nodePtr, Node *orignode, Expr *expr);
|
||||||
@ -107,9 +105,9 @@ gatherRewriteMeta(Query *parsetree,
|
|||||||
info->rt = append(info->rt, info->rule_action->rtable);
|
info->rt = append(info->rt, info->rule_action->rtable);
|
||||||
|
|
||||||
info->new_varno = PRS2_NEW_VARNO + rt_length;
|
info->new_varno = PRS2_NEW_VARNO + rt_length;
|
||||||
OffsetVarNodes(info->rule_action->qual, rt_length);
|
OffsetVarNodes(info->rule_action->qual, rt_length, 0);
|
||||||
OffsetVarNodes((Node *) info->rule_action->targetList, rt_length);
|
OffsetVarNodes((Node *) info->rule_action->targetList, rt_length, 0);
|
||||||
OffsetVarNodes(info->rule_qual, rt_length);
|
OffsetVarNodes(info->rule_qual, rt_length, 0);
|
||||||
ChangeVarNodes((Node *) info->rule_action->qual,
|
ChangeVarNodes((Node *) info->rule_action->qual,
|
||||||
PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
|
PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
|
||||||
ChangeVarNodes((Node *) info->rule_action->targetList,
|
ChangeVarNodes((Node *) info->rule_action->targetList,
|
||||||
@ -550,364 +548,6 @@ attribute_used(Node *node, int rt_index, int attno, int sublevels_up)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* offset_varnodes -
|
|
||||||
* We need another version of OffsetVarNodes() when processing
|
|
||||||
* RIR rules
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
offset_varnodes(Node *node, int offset, int sublevels_up)
|
|
||||||
{
|
|
||||||
if (node == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch(nodeTag(node)) {
|
|
||||||
case T_TargetEntry:
|
|
||||||
{
|
|
||||||
TargetEntry *tle = (TargetEntry *)node;
|
|
||||||
|
|
||||||
offset_varnodes(
|
|
||||||
(Node *)(tle->expr),
|
|
||||||
offset,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_Aggreg:
|
|
||||||
{
|
|
||||||
Aggreg *agg = (Aggreg *)node;
|
|
||||||
|
|
||||||
offset_varnodes(
|
|
||||||
(Node *)(agg->target),
|
|
||||||
offset,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_GroupClause:
|
|
||||||
{
|
|
||||||
GroupClause *grp = (GroupClause *)node;
|
|
||||||
|
|
||||||
offset_varnodes(
|
|
||||||
(Node *)(grp->entry),
|
|
||||||
offset,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_Expr:
|
|
||||||
{
|
|
||||||
Expr *exp = (Expr *)node;
|
|
||||||
|
|
||||||
offset_varnodes(
|
|
||||||
(Node *)(exp->args),
|
|
||||||
offset,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_Iter:
|
|
||||||
{
|
|
||||||
Iter *iter = (Iter *)node;
|
|
||||||
|
|
||||||
offset_varnodes(
|
|
||||||
(Node *)(iter->iterexpr),
|
|
||||||
offset,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_ArrayRef:
|
|
||||||
{
|
|
||||||
ArrayRef *ref = (ArrayRef *)node;
|
|
||||||
|
|
||||||
offset_varnodes(
|
|
||||||
(Node *)(ref->refupperindexpr),
|
|
||||||
offset,
|
|
||||||
sublevels_up);
|
|
||||||
offset_varnodes(
|
|
||||||
(Node *)(ref->reflowerindexpr),
|
|
||||||
offset,
|
|
||||||
sublevels_up);
|
|
||||||
offset_varnodes(
|
|
||||||
(Node *)(ref->refexpr),
|
|
||||||
offset,
|
|
||||||
sublevels_up);
|
|
||||||
offset_varnodes(
|
|
||||||
(Node *)(ref->refassgnexpr),
|
|
||||||
offset,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_Var:
|
|
||||||
{
|
|
||||||
Var *var = (Var *)node;
|
|
||||||
|
|
||||||
if (var->varlevelsup == sublevels_up) {
|
|
||||||
var->varno += offset;
|
|
||||||
var->varnoold += offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_Param:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_Const:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_List:
|
|
||||||
{
|
|
||||||
List *l;
|
|
||||||
|
|
||||||
foreach (l, (List *)node)
|
|
||||||
offset_varnodes(
|
|
||||||
(Node *)lfirst(l),
|
|
||||||
offset,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_SubLink:
|
|
||||||
{
|
|
||||||
SubLink *sub = (SubLink *)node;
|
|
||||||
|
|
||||||
offset_varnodes(
|
|
||||||
(Node *)(sub->lefthand),
|
|
||||||
offset,
|
|
||||||
sublevels_up);
|
|
||||||
|
|
||||||
offset_varnodes(
|
|
||||||
(Node *)(sub->subselect),
|
|
||||||
offset,
|
|
||||||
sublevels_up + 1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_Query:
|
|
||||||
{
|
|
||||||
Query *qry = (Query *)node;
|
|
||||||
|
|
||||||
offset_varnodes(
|
|
||||||
(Node *)(qry->targetList),
|
|
||||||
offset,
|
|
||||||
sublevels_up);
|
|
||||||
|
|
||||||
offset_varnodes(
|
|
||||||
(Node *)(qry->qual),
|
|
||||||
offset,
|
|
||||||
sublevels_up);
|
|
||||||
|
|
||||||
offset_varnodes(
|
|
||||||
(Node *)(qry->havingQual),
|
|
||||||
offset,
|
|
||||||
sublevels_up);
|
|
||||||
|
|
||||||
offset_varnodes(
|
|
||||||
(Node *)(qry->groupClause),
|
|
||||||
offset,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
elog(NOTICE, "unknown node tag %d in offset_varnodes()", nodeTag(node));
|
|
||||||
elog(NOTICE, "Node is: %s", nodeToString(node));
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* change_varnodes -
|
|
||||||
* and another ChangeVarNodes() too
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
change_varnodes(Node *node, int rt_index, int new_index, int sublevels_up)
|
|
||||||
{
|
|
||||||
if (node == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch(nodeTag(node)) {
|
|
||||||
case T_TargetEntry:
|
|
||||||
{
|
|
||||||
TargetEntry *tle = (TargetEntry *)node;
|
|
||||||
|
|
||||||
change_varnodes(
|
|
||||||
(Node *)(tle->expr),
|
|
||||||
rt_index,
|
|
||||||
new_index,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_Aggreg:
|
|
||||||
{
|
|
||||||
Aggreg *agg = (Aggreg *)node;
|
|
||||||
|
|
||||||
change_varnodes(
|
|
||||||
(Node *)(agg->target),
|
|
||||||
rt_index,
|
|
||||||
new_index,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_GroupClause:
|
|
||||||
{
|
|
||||||
GroupClause *grp = (GroupClause *)node;
|
|
||||||
|
|
||||||
change_varnodes(
|
|
||||||
(Node *)(grp->entry),
|
|
||||||
rt_index,
|
|
||||||
new_index,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_Expr:
|
|
||||||
{
|
|
||||||
Expr *exp = (Expr *)node;
|
|
||||||
|
|
||||||
change_varnodes(
|
|
||||||
(Node *)(exp->args),
|
|
||||||
rt_index,
|
|
||||||
new_index,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_Iter:
|
|
||||||
{
|
|
||||||
Iter *iter = (Iter *)node;
|
|
||||||
|
|
||||||
change_varnodes(
|
|
||||||
(Node *)(iter->iterexpr),
|
|
||||||
rt_index,
|
|
||||||
new_index,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_ArrayRef:
|
|
||||||
{
|
|
||||||
ArrayRef *ref = (ArrayRef *)node;
|
|
||||||
|
|
||||||
change_varnodes(
|
|
||||||
(Node *)(ref->refupperindexpr),
|
|
||||||
rt_index,
|
|
||||||
new_index,
|
|
||||||
sublevels_up);
|
|
||||||
change_varnodes(
|
|
||||||
(Node *)(ref->reflowerindexpr),
|
|
||||||
rt_index,
|
|
||||||
new_index,
|
|
||||||
sublevels_up);
|
|
||||||
change_varnodes(
|
|
||||||
(Node *)(ref->refexpr),
|
|
||||||
rt_index,
|
|
||||||
new_index,
|
|
||||||
sublevels_up);
|
|
||||||
change_varnodes(
|
|
||||||
(Node *)(ref->refassgnexpr),
|
|
||||||
rt_index,
|
|
||||||
new_index,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_Var:
|
|
||||||
{
|
|
||||||
Var *var = (Var *)node;
|
|
||||||
|
|
||||||
if (var->varlevelsup == sublevels_up &&
|
|
||||||
var->varno == rt_index) {
|
|
||||||
var->varno = new_index;
|
|
||||||
var->varnoold = new_index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_Param:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_Const:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_List:
|
|
||||||
{
|
|
||||||
List *l;
|
|
||||||
|
|
||||||
foreach (l, (List *)node)
|
|
||||||
change_varnodes(
|
|
||||||
(Node *)lfirst(l),
|
|
||||||
rt_index,
|
|
||||||
new_index,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_SubLink:
|
|
||||||
{
|
|
||||||
SubLink *sub = (SubLink *)node;
|
|
||||||
|
|
||||||
change_varnodes(
|
|
||||||
(Node *)(sub->lefthand),
|
|
||||||
rt_index,
|
|
||||||
new_index,
|
|
||||||
sublevels_up);
|
|
||||||
|
|
||||||
change_varnodes(
|
|
||||||
(Node *)(sub->subselect),
|
|
||||||
rt_index,
|
|
||||||
new_index,
|
|
||||||
sublevels_up + 1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_Query:
|
|
||||||
{
|
|
||||||
Query *qry = (Query *)node;
|
|
||||||
|
|
||||||
change_varnodes(
|
|
||||||
(Node *)(qry->targetList),
|
|
||||||
rt_index,
|
|
||||||
new_index,
|
|
||||||
sublevels_up);
|
|
||||||
|
|
||||||
change_varnodes(
|
|
||||||
(Node *)(qry->qual),
|
|
||||||
rt_index,
|
|
||||||
new_index,
|
|
||||||
sublevels_up);
|
|
||||||
|
|
||||||
change_varnodes(
|
|
||||||
(Node *)(qry->havingQual),
|
|
||||||
rt_index,
|
|
||||||
new_index,
|
|
||||||
sublevels_up);
|
|
||||||
|
|
||||||
change_varnodes(
|
|
||||||
(Node *)(qry->groupClause),
|
|
||||||
rt_index,
|
|
||||||
new_index,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
elog(NOTICE, "unknown node tag %d in change_varnodes()", nodeTag(node));
|
|
||||||
elog(NOTICE, "Node is: %s", nodeToString(node));
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* modifyAggregUplevel -
|
* modifyAggregUplevel -
|
||||||
* In the newly created sublink for an aggregate column used in
|
* In the newly created sublink for an aggregate column used in
|
||||||
@ -1655,6 +1295,121 @@ make_null(Oid type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
apply_RIR_adjust_sublevel(Node *node, int sublevels_up)
|
||||||
|
{
|
||||||
|
if (node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch(nodeTag(node)) {
|
||||||
|
case T_TargetEntry:
|
||||||
|
{
|
||||||
|
TargetEntry *tle = (TargetEntry *)node;
|
||||||
|
|
||||||
|
apply_RIR_adjust_sublevel(
|
||||||
|
(Node *)(tle->expr),
|
||||||
|
sublevels_up);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_Aggreg:
|
||||||
|
{
|
||||||
|
Aggreg *agg = (Aggreg *)node;
|
||||||
|
|
||||||
|
apply_RIR_adjust_sublevel(
|
||||||
|
(Node *)(agg->target),
|
||||||
|
sublevels_up);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_GroupClause:
|
||||||
|
{
|
||||||
|
GroupClause *grp = (GroupClause *)node;
|
||||||
|
|
||||||
|
apply_RIR_adjust_sublevel(
|
||||||
|
(Node *)(grp->entry),
|
||||||
|
sublevels_up);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_Expr:
|
||||||
|
{
|
||||||
|
Expr *exp = (Expr *)node;
|
||||||
|
|
||||||
|
apply_RIR_adjust_sublevel(
|
||||||
|
(Node *)(exp->args),
|
||||||
|
sublevels_up);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_Iter:
|
||||||
|
{
|
||||||
|
Iter *iter = (Iter *)node;
|
||||||
|
|
||||||
|
apply_RIR_adjust_sublevel(
|
||||||
|
(Node *)(iter->iterexpr),
|
||||||
|
sublevels_up);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_ArrayRef:
|
||||||
|
{
|
||||||
|
ArrayRef *ref = (ArrayRef *)node;
|
||||||
|
|
||||||
|
apply_RIR_adjust_sublevel(
|
||||||
|
(Node *)(ref->refupperindexpr),
|
||||||
|
sublevels_up);
|
||||||
|
|
||||||
|
apply_RIR_adjust_sublevel(
|
||||||
|
(Node *)(ref->reflowerindexpr),
|
||||||
|
sublevels_up);
|
||||||
|
|
||||||
|
apply_RIR_adjust_sublevel(
|
||||||
|
(Node *)(ref->refexpr),
|
||||||
|
sublevels_up);
|
||||||
|
|
||||||
|
apply_RIR_adjust_sublevel(
|
||||||
|
(Node *)(ref->refassgnexpr),
|
||||||
|
sublevels_up);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_Var:
|
||||||
|
{
|
||||||
|
Var *var = (Var *)node;
|
||||||
|
|
||||||
|
var->varlevelsup = sublevels_up;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_Param:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_Const:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_List:
|
||||||
|
{
|
||||||
|
List *l;
|
||||||
|
|
||||||
|
foreach (l, (List *)node) {
|
||||||
|
apply_RIR_adjust_sublevel(
|
||||||
|
(Node *)lfirst(l),
|
||||||
|
sublevels_up);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
elog(NOTICE, "unknown node tag %d in attribute_used()", nodeTag(node));
|
||||||
|
elog(NOTICE, "Node is: %s", nodeToString(node));
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
apply_RIR_view(Node **nodePtr, int rt_index, RangeTblEntry *rte, List *tlist, int *modified, int sublevels_up)
|
apply_RIR_view(Node **nodePtr, int rt_index, RangeTblEntry *rte, List *tlist, int *modified, int sublevels_up)
|
||||||
{
|
{
|
||||||
@ -1790,10 +1545,8 @@ apply_RIR_view(Node **nodePtr, int rt_index, RangeTblEntry *rte, List *tlist, in
|
|||||||
}
|
}
|
||||||
|
|
||||||
exp = copyObject(exp);
|
exp = copyObject(exp);
|
||||||
if (var->varlevelsup > 0 &&
|
if (var->varlevelsup > 0)
|
||||||
nodeTag(exp) == T_Var) {
|
apply_RIR_adjust_sublevel(exp, var->varlevelsup);
|
||||||
((Var *)exp)->varlevelsup = var->varlevelsup;
|
|
||||||
}
|
|
||||||
*nodePtr = exp;
|
*nodePtr = exp;
|
||||||
*modified = TRUE;
|
*modified = TRUE;
|
||||||
}
|
}
|
||||||
@ -1885,8 +1638,6 @@ apply_RIR_view(Node **nodePtr, int rt_index, RangeTblEntry *rte, List *tlist, in
|
|||||||
elog(NOTICE, "unknown node tag %d in apply_RIR_view()", nodeTag(node));
|
elog(NOTICE, "unknown node tag %d in apply_RIR_view()", nodeTag(node));
|
||||||
elog(NOTICE, "Node is: %s", nodeToString(node));
|
elog(NOTICE, "Node is: %s", nodeToString(node));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1938,12 +1689,12 @@ ApplyRetrieveRule(Query *parsetree,
|
|||||||
parsetree->rtable = rtable;
|
parsetree->rtable = rtable;
|
||||||
|
|
||||||
rule_action->rtable = rtable;
|
rule_action->rtable = rtable;
|
||||||
offset_varnodes((Node *) rule_qual, rt_length, 0);
|
OffsetVarNodes((Node *) rule_qual, rt_length, 0);
|
||||||
offset_varnodes((Node *) rule_action, rt_length, 0);
|
OffsetVarNodes((Node *) rule_action, rt_length, 0);
|
||||||
|
|
||||||
change_varnodes((Node *) rule_qual,
|
ChangeVarNodes((Node *) rule_qual,
|
||||||
PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
|
PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
|
||||||
change_varnodes((Node *) rule_action,
|
ChangeVarNodes((Node *) rule_action,
|
||||||
PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
|
PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
|
||||||
|
|
||||||
if (relation_level)
|
if (relation_level)
|
||||||
@ -2246,7 +1997,7 @@ CopyAndAddQual(Query *parsetree,
|
|||||||
rt_length = length(rtable);
|
rt_length = length(rtable);
|
||||||
rtable = append(rtable, listCopy(rule_action->rtable));
|
rtable = append(rtable, listCopy(rule_action->rtable));
|
||||||
new_tree->rtable = rtable;
|
new_tree->rtable = rtable;
|
||||||
OffsetVarNodes(new_qual, rt_length);
|
OffsetVarNodes(new_qual, rt_length, 0);
|
||||||
ChangeVarNodes(new_qual, PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
|
ChangeVarNodes(new_qual, PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
|
||||||
}
|
}
|
||||||
/* XXX -- where current doesn't work for instead nothing.... yet */
|
/* XXX -- where current doesn't work for instead nothing.... yet */
|
||||||
@ -2385,6 +2136,28 @@ fireRules(Query *parsetree,
|
|||||||
if (rule_action->commandType == CMD_NOTHING)
|
if (rule_action->commandType == CMD_NOTHING)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
* We copy the qualifications of the parsetree
|
||||||
|
* to the action and vice versa. So force
|
||||||
|
* hasSubLinks if one of them has it.
|
||||||
|
*
|
||||||
|
* As of 6.4 only parsetree qualifications can
|
||||||
|
* have sublinks. If this changes, we must make
|
||||||
|
* this a node lookup at the end of rewriting.
|
||||||
|
*
|
||||||
|
* Jan
|
||||||
|
*--------------------------------------------------
|
||||||
|
*/
|
||||||
|
if (parsetree->hasSubLinks && !rule_action->hasSubLinks)
|
||||||
|
{
|
||||||
|
rule_action = copyObject(rule_action);
|
||||||
|
rule_action->hasSubLinks = TRUE;
|
||||||
|
}
|
||||||
|
if (!parsetree->hasSubLinks && rule_action->hasSubLinks)
|
||||||
|
{
|
||||||
|
parsetree->hasSubLinks = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
* Step 1:
|
* Step 1:
|
||||||
* Rewrite current.attribute or current to tuple variable
|
* Rewrite current.attribute or current to tuple variable
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.21 1998/10/20 17:21:44 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.22 1998/10/21 16:21:26 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -32,222 +32,362 @@ static void ResolveNew(RewriteInfo *info, List *targetlist,
|
|||||||
Node **node, int sublevels_up);
|
Node **node, int sublevels_up);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OffsetVarnodes -
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
OffsetVarNodes(Node *node, int offset)
|
OffsetVarNodes(Node *node, int offset, int sublevels_up)
|
||||||
{
|
{
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
return;
|
return;
|
||||||
switch (nodeTag(node))
|
|
||||||
{
|
switch(nodeTag(node)) {
|
||||||
case T_TargetEntry:
|
case T_TargetEntry:
|
||||||
{
|
{
|
||||||
TargetEntry *tle = (TargetEntry *) node;
|
TargetEntry *tle = (TargetEntry *)node;
|
||||||
|
|
||||||
OffsetVarNodes(tle->expr, offset);
|
OffsetVarNodes(
|
||||||
|
(Node *)(tle->expr),
|
||||||
|
offset,
|
||||||
|
sublevels_up);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_Aggreg:
|
case T_Aggreg:
|
||||||
{
|
{
|
||||||
Aggreg *agg = (Aggreg *) node;
|
Aggreg *agg = (Aggreg *)node;
|
||||||
|
|
||||||
OffsetVarNodes(agg->target, offset);
|
OffsetVarNodes(
|
||||||
|
(Node *)(agg->target),
|
||||||
|
offset,
|
||||||
|
sublevels_up);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
|
||||||
* This has to be done to make queries using groupclauses work
|
|
||||||
* on views
|
|
||||||
*/
|
|
||||||
case T_GroupClause:
|
case T_GroupClause:
|
||||||
{
|
{
|
||||||
GroupClause *group = (GroupClause *) node;
|
GroupClause *grp = (GroupClause *)node;
|
||||||
|
|
||||||
OffsetVarNodes((Node *) (group->entry), offset);
|
OffsetVarNodes(
|
||||||
}
|
(Node *)(grp->entry),
|
||||||
break;
|
offset,
|
||||||
case T_Expr:
|
sublevels_up);
|
||||||
{
|
|
||||||
Expr *expr = (Expr *) node;
|
|
||||||
|
|
||||||
OffsetVarNodes((Node *) expr->args, offset);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case T_Iter:
|
|
||||||
{
|
|
||||||
Iter *iter = (Iter *) node;
|
|
||||||
|
|
||||||
OffsetVarNodes((Node *) iter->iterexpr, offset);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case T_ArrayRef:
|
|
||||||
{
|
|
||||||
ArrayRef *ref = (ArrayRef *) node;
|
|
||||||
|
|
||||||
OffsetVarNodes((Node *) ref->refupperindexpr, offset);
|
|
||||||
OffsetVarNodes((Node *) ref->reflowerindexpr, offset);
|
|
||||||
OffsetVarNodes((Node *) ref->refexpr, offset);
|
|
||||||
OffsetVarNodes((Node *) ref->refassgnexpr, offset);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case T_Var:
|
|
||||||
{
|
|
||||||
Var *var = (Var *) node;
|
|
||||||
|
|
||||||
var->varno += offset;
|
|
||||||
var->varnoold += offset;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case T_List:
|
|
||||||
{
|
|
||||||
List *l;
|
|
||||||
|
|
||||||
foreach(l, (List *) node)
|
|
||||||
OffsetVarNodes(lfirst(l), offset);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case T_SubLink:
|
|
||||||
{
|
|
||||||
SubLink *sublink = (SubLink *) node;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We also have to adapt the variables used in
|
|
||||||
* sublink->lefthand and sublink->oper
|
|
||||||
*/
|
|
||||||
OffsetVarNodes((Node *) (sublink->lefthand), offset);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure the first argument of sublink->oper points to
|
|
||||||
* the same var as sublink->lefthand does otherwise we
|
|
||||||
* will run into troubles using aggregates (aggno will not
|
|
||||||
* be set correctly)
|
|
||||||
*/
|
|
||||||
lfirst(((Expr *) lfirst(sublink->oper))->args) =
|
|
||||||
lfirst(sublink->lefthand);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* ignore the others */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ChangeVarNodes(Node *node, int old_varno, int new_varno, int sublevels_up)
|
|
||||||
{
|
|
||||||
if (node == NULL)
|
|
||||||
return;
|
|
||||||
switch (nodeTag(node))
|
|
||||||
{
|
|
||||||
case T_TargetEntry:
|
|
||||||
{
|
|
||||||
TargetEntry *tle = (TargetEntry *) node;
|
|
||||||
|
|
||||||
ChangeVarNodes(tle->expr, old_varno, new_varno, sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case T_Aggreg:
|
|
||||||
{
|
|
||||||
Aggreg *agg = (Aggreg *) node;
|
|
||||||
|
|
||||||
ChangeVarNodes(agg->target, old_varno, new_varno, sublevels_up);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This has to be done to make queries using groupclauses work
|
|
||||||
* on views
|
|
||||||
*/
|
|
||||||
case T_GroupClause:
|
|
||||||
{
|
|
||||||
GroupClause *group = (GroupClause *) node;
|
|
||||||
|
|
||||||
ChangeVarNodes((Node *) (group->entry), old_varno, new_varno,
|
|
||||||
sublevels_up);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_Expr:
|
case T_Expr:
|
||||||
{
|
{
|
||||||
Expr *expr = (Expr *) node;
|
Expr *exp = (Expr *)node;
|
||||||
|
|
||||||
ChangeVarNodes((Node *) expr->args, old_varno, new_varno, sublevels_up);
|
OffsetVarNodes(
|
||||||
|
(Node *)(exp->args),
|
||||||
|
offset,
|
||||||
|
sublevels_up);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_Iter:
|
case T_Iter:
|
||||||
{
|
{
|
||||||
Iter *iter = (Iter *) node;
|
Iter *iter = (Iter *)node;
|
||||||
|
|
||||||
ChangeVarNodes((Node *) iter->iterexpr, old_varno, new_varno, sublevels_up);
|
OffsetVarNodes(
|
||||||
|
(Node *)(iter->iterexpr),
|
||||||
|
offset,
|
||||||
|
sublevels_up);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_ArrayRef:
|
case T_ArrayRef:
|
||||||
{
|
{
|
||||||
ArrayRef *ref = (ArrayRef *) node;
|
ArrayRef *ref = (ArrayRef *)node;
|
||||||
|
|
||||||
ChangeVarNodes((Node *) ref->refupperindexpr, old_varno, new_varno, sublevels_up);
|
OffsetVarNodes(
|
||||||
ChangeVarNodes((Node *) ref->reflowerindexpr, old_varno, new_varno, sublevels_up);
|
(Node *)(ref->refupperindexpr),
|
||||||
ChangeVarNodes((Node *) ref->refexpr, old_varno, new_varno, sublevels_up);
|
offset,
|
||||||
ChangeVarNodes((Node *) ref->refassgnexpr, old_varno, new_varno, sublevels_up);
|
sublevels_up);
|
||||||
|
OffsetVarNodes(
|
||||||
|
(Node *)(ref->reflowerindexpr),
|
||||||
|
offset,
|
||||||
|
sublevels_up);
|
||||||
|
OffsetVarNodes(
|
||||||
|
(Node *)(ref->refexpr),
|
||||||
|
offset,
|
||||||
|
sublevels_up);
|
||||||
|
OffsetVarNodes(
|
||||||
|
(Node *)(ref->refassgnexpr),
|
||||||
|
offset,
|
||||||
|
sublevels_up);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_Var:
|
case T_Var:
|
||||||
{
|
{
|
||||||
Var *var = (Var *) node;
|
Var *var = (Var *)node;
|
||||||
|
|
||||||
if (var->varno == old_varno &&
|
if (var->varlevelsup == sublevels_up) {
|
||||||
var->varlevelsup == sublevels_up)
|
var->varno += offset;
|
||||||
{
|
var->varnoold += offset;
|
||||||
var->varno = new_varno;
|
|
||||||
var->varnoold = new_varno;
|
|
||||||
}
|
}
|
||||||
if (var->varlevelsup > 0)
|
|
||||||
OffsetVarNodes((Node *) var, 3);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case T_Param:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_Const:
|
||||||
|
break;
|
||||||
|
|
||||||
case T_List:
|
case T_List:
|
||||||
{
|
{
|
||||||
List *l;
|
List *l;
|
||||||
|
|
||||||
foreach(l, (List *) node)
|
foreach (l, (List *)node)
|
||||||
ChangeVarNodes(lfirst(l), old_varno, new_varno, sublevels_up);
|
OffsetVarNodes(
|
||||||
|
(Node *)lfirst(l),
|
||||||
|
offset,
|
||||||
|
sublevels_up);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_SubLink:
|
case T_SubLink:
|
||||||
{
|
{
|
||||||
SubLink *sublink = (SubLink *) node;
|
SubLink *sub = (SubLink *)node;
|
||||||
Query *query = (Query *) sublink->subselect;
|
|
||||||
|
|
||||||
ChangeVarNodes((Node *) query->qual, old_varno, new_varno,
|
OffsetVarNodes(
|
||||||
sublevels_up + 1);
|
(Node *)(sub->lefthand),
|
||||||
|
offset,
|
||||||
|
sublevels_up);
|
||||||
|
|
||||||
/*
|
OffsetVarNodes(
|
||||||
* We also have to adapt the variables used in
|
(Node *)(sub->subselect),
|
||||||
* sublink->lefthand and sublink->oper
|
offset,
|
||||||
*/
|
sublevels_up + 1);
|
||||||
ChangeVarNodes((Node *) (sublink->lefthand), old_varno, new_varno,
|
|
||||||
sublevels_up);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure the first argument of sublink->oper points to
|
|
||||||
* the same var as sublink->lefthand does otherwise we
|
|
||||||
* will run into troubles using aggregates (aggno will not
|
|
||||||
* be set correctly
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* lfirst(((Expr *) lfirst(sublink->oper))->args) =
|
|
||||||
* lfirst(sublink->lefthand);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
/* ignore the others */
|
case T_Query:
|
||||||
|
{
|
||||||
|
Query *qry = (Query *)node;
|
||||||
|
|
||||||
|
OffsetVarNodes(
|
||||||
|
(Node *)(qry->targetList),
|
||||||
|
offset,
|
||||||
|
sublevels_up);
|
||||||
|
|
||||||
|
OffsetVarNodes(
|
||||||
|
(Node *)(qry->qual),
|
||||||
|
offset,
|
||||||
|
sublevels_up);
|
||||||
|
|
||||||
|
OffsetVarNodes(
|
||||||
|
(Node *)(qry->havingQual),
|
||||||
|
offset,
|
||||||
|
sublevels_up);
|
||||||
|
|
||||||
|
OffsetVarNodes(
|
||||||
|
(Node *)(qry->groupClause),
|
||||||
|
offset,
|
||||||
|
sublevels_up);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
elog(NOTICE, "unknown node tag %d in OffsetVarNodes()", nodeTag(node));
|
||||||
|
elog(NOTICE, "Node is: %s", nodeToString(node));
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ChangeVarNodes -
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)
|
||||||
|
{
|
||||||
|
if (node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch(nodeTag(node)) {
|
||||||
|
case T_TargetEntry:
|
||||||
|
{
|
||||||
|
TargetEntry *tle = (TargetEntry *)node;
|
||||||
|
|
||||||
|
ChangeVarNodes(
|
||||||
|
(Node *)(tle->expr),
|
||||||
|
rt_index,
|
||||||
|
new_index,
|
||||||
|
sublevels_up);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_Aggreg:
|
||||||
|
{
|
||||||
|
Aggreg *agg = (Aggreg *)node;
|
||||||
|
|
||||||
|
ChangeVarNodes(
|
||||||
|
(Node *)(agg->target),
|
||||||
|
rt_index,
|
||||||
|
new_index,
|
||||||
|
sublevels_up);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_GroupClause:
|
||||||
|
{
|
||||||
|
GroupClause *grp = (GroupClause *)node;
|
||||||
|
|
||||||
|
ChangeVarNodes(
|
||||||
|
(Node *)(grp->entry),
|
||||||
|
rt_index,
|
||||||
|
new_index,
|
||||||
|
sublevels_up);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_Expr:
|
||||||
|
{
|
||||||
|
Expr *exp = (Expr *)node;
|
||||||
|
|
||||||
|
ChangeVarNodes(
|
||||||
|
(Node *)(exp->args),
|
||||||
|
rt_index,
|
||||||
|
new_index,
|
||||||
|
sublevels_up);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_Iter:
|
||||||
|
{
|
||||||
|
Iter *iter = (Iter *)node;
|
||||||
|
|
||||||
|
ChangeVarNodes(
|
||||||
|
(Node *)(iter->iterexpr),
|
||||||
|
rt_index,
|
||||||
|
new_index,
|
||||||
|
sublevels_up);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_ArrayRef:
|
||||||
|
{
|
||||||
|
ArrayRef *ref = (ArrayRef *)node;
|
||||||
|
|
||||||
|
ChangeVarNodes(
|
||||||
|
(Node *)(ref->refupperindexpr),
|
||||||
|
rt_index,
|
||||||
|
new_index,
|
||||||
|
sublevels_up);
|
||||||
|
ChangeVarNodes(
|
||||||
|
(Node *)(ref->reflowerindexpr),
|
||||||
|
rt_index,
|
||||||
|
new_index,
|
||||||
|
sublevels_up);
|
||||||
|
ChangeVarNodes(
|
||||||
|
(Node *)(ref->refexpr),
|
||||||
|
rt_index,
|
||||||
|
new_index,
|
||||||
|
sublevels_up);
|
||||||
|
ChangeVarNodes(
|
||||||
|
(Node *)(ref->refassgnexpr),
|
||||||
|
rt_index,
|
||||||
|
new_index,
|
||||||
|
sublevels_up);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_Var:
|
||||||
|
{
|
||||||
|
Var *var = (Var *)node;
|
||||||
|
|
||||||
|
if (var->varlevelsup == sublevels_up &&
|
||||||
|
var->varno == rt_index) {
|
||||||
|
var->varno = new_index;
|
||||||
|
var->varnoold = new_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_Param:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_Const:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_List:
|
||||||
|
{
|
||||||
|
List *l;
|
||||||
|
|
||||||
|
foreach (l, (List *)node)
|
||||||
|
ChangeVarNodes(
|
||||||
|
(Node *)lfirst(l),
|
||||||
|
rt_index,
|
||||||
|
new_index,
|
||||||
|
sublevels_up);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_SubLink:
|
||||||
|
{
|
||||||
|
SubLink *sub = (SubLink *)node;
|
||||||
|
|
||||||
|
ChangeVarNodes(
|
||||||
|
(Node *)(sub->lefthand),
|
||||||
|
rt_index,
|
||||||
|
new_index,
|
||||||
|
sublevels_up);
|
||||||
|
|
||||||
|
ChangeVarNodes(
|
||||||
|
(Node *)(sub->subselect),
|
||||||
|
rt_index,
|
||||||
|
new_index,
|
||||||
|
sublevels_up + 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_Query:
|
||||||
|
{
|
||||||
|
Query *qry = (Query *)node;
|
||||||
|
|
||||||
|
ChangeVarNodes(
|
||||||
|
(Node *)(qry->targetList),
|
||||||
|
rt_index,
|
||||||
|
new_index,
|
||||||
|
sublevels_up);
|
||||||
|
|
||||||
|
ChangeVarNodes(
|
||||||
|
(Node *)(qry->qual),
|
||||||
|
rt_index,
|
||||||
|
new_index,
|
||||||
|
sublevels_up);
|
||||||
|
|
||||||
|
ChangeVarNodes(
|
||||||
|
(Node *)(qry->havingQual),
|
||||||
|
rt_index,
|
||||||
|
new_index,
|
||||||
|
sublevels_up);
|
||||||
|
|
||||||
|
ChangeVarNodes(
|
||||||
|
(Node *)(qry->groupClause),
|
||||||
|
rt_index,
|
||||||
|
new_index,
|
||||||
|
sublevels_up);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
elog(NOTICE, "unknown node tag %d in ChangeVarNodes()", nodeTag(node));
|
||||||
|
elog(NOTICE, "Node is: %s", nodeToString(node));
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
AddQual(Query *parsetree, Node *qual)
|
AddQual(Query *parsetree, Node *qual)
|
||||||
{
|
{
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: rewriteManip.h,v 1.10 1998/10/08 18:30:41 momjian Exp $
|
* $Id: rewriteManip.h,v 1.11 1998/10/21 16:21:29 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -18,7 +18,7 @@
|
|||||||
#include "rewrite/rewriteHandler.h"
|
#include "rewrite/rewriteHandler.h"
|
||||||
|
|
||||||
/* RewriteManip.c */
|
/* RewriteManip.c */
|
||||||
void OffsetVarNodes(Node *node, int offset);
|
void OffsetVarNodes(Node *node, int offset, int sublevels_up);
|
||||||
void ChangeVarNodes(Node *node, int old_varno, int new_varno,
|
void ChangeVarNodes(Node *node, int old_varno, int new_varno,
|
||||||
int sublevels_up);
|
int sublevels_up);
|
||||||
void AddQual(Query *parsetree, Node *qual);
|
void AddQual(Query *parsetree, Node *qual);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user