📄 rewritehandler.c
字号:
break; case T_Expr: { Expr *exp = (Expr *) node; modifyAggrefUplevel( (Node *) (exp->args)); } break; case T_Iter: { Iter *iter = (Iter *) node; modifyAggrefUplevel( (Node *) (iter->iterexpr)); } break; case T_ArrayRef: { ArrayRef *ref = (ArrayRef *) node; modifyAggrefUplevel( (Node *) (ref->refupperindexpr)); modifyAggrefUplevel( (Node *) (ref->reflowerindexpr)); modifyAggrefUplevel( (Node *) (ref->refexpr)); modifyAggrefUplevel( (Node *) (ref->refassgnexpr)); } break; case T_Var: { Var *var = (Var *) node; var->varlevelsup++; } break; case T_Param: break; case T_Const: break; case T_List: { List *l; foreach(l, (List *) node) modifyAggrefUplevel( (Node *) lfirst(l)); } break; case T_SubLink: { SubLink *sub = (SubLink *) node; modifyAggrefUplevel( (Node *) (sub->lefthand)); modifyAggrefUplevel( (Node *) (sub->oper)); modifyAggrefUplevel( (Node *) (sub->subselect)); } break; case T_Query: { Query *qry = (Query *) node; modifyAggrefUplevel( (Node *) (qry->targetList)); modifyAggrefUplevel( (Node *) (qry->qual)); modifyAggrefUplevel( (Node *) (qry->havingQual)); } break; default: elog(NOTICE, "unknown node tag %d in modifyAggrefUplevel()", nodeTag(node)); elog(NOTICE, "Node is: %s", nodeToString(node)); break; }}/* * modifyAggrefChangeVarnodes - * Change the var nodes in a sublink created for an aggregate column * used in the qualification that is subject of the aggregate * function to point to the correct local RTE. */static voidmodifyAggrefChangeVarnodes(Node **nodePtr, int rt_index, int new_index, int sublevels_up){ Node *node = *nodePtr; if (node == NULL) return; switch (nodeTag(node)) { case T_TargetEntry: { TargetEntry *tle = (TargetEntry *) node; modifyAggrefChangeVarnodes( (Node **) (&(tle->expr)), rt_index, new_index, sublevels_up); } break; case T_Aggref: { Aggref *aggref = (Aggref *) node; modifyAggrefChangeVarnodes( (Node **) (&(aggref->target)), rt_index, new_index, sublevels_up); } break; case T_GroupClause: break; case T_Expr: { Expr *exp = (Expr *) node; modifyAggrefChangeVarnodes( (Node **) (&(exp->args)), rt_index, new_index, sublevels_up); } break; case T_Iter: { Iter *iter = (Iter *) node; modifyAggrefChangeVarnodes( (Node **) (&(iter->iterexpr)), rt_index, new_index, sublevels_up); } break; case T_ArrayRef: { ArrayRef *ref = (ArrayRef *) node; modifyAggrefChangeVarnodes( (Node **) (&(ref->refupperindexpr)), rt_index, new_index, sublevels_up); modifyAggrefChangeVarnodes( (Node **) (&(ref->reflowerindexpr)), rt_index, new_index, sublevels_up); modifyAggrefChangeVarnodes( (Node **) (&(ref->refexpr)), rt_index, new_index, sublevels_up); modifyAggrefChangeVarnodes( (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 = copyObject(var); var->varno = new_index; var->varnoold = new_index; var->varlevelsup = 0; *nodePtr = (Node *) var; } } break; case T_Param: break; case T_Const: break; case T_List: { List *l; foreach(l, (List *) node) modifyAggrefChangeVarnodes( (Node **) (&lfirst(l)), rt_index, new_index, sublevels_up); } break; case T_SubLink: { SubLink *sub = (SubLink *) node; modifyAggrefChangeVarnodes( (Node **) (&(sub->lefthand)), rt_index, new_index, sublevels_up); modifyAggrefChangeVarnodes( (Node **) (&(sub->oper)), rt_index, new_index, sublevels_up); modifyAggrefChangeVarnodes( (Node **) (&(sub->subselect)), rt_index, new_index, sublevels_up + 1); } break; case T_Query: { Query *qry = (Query *) node; modifyAggrefChangeVarnodes( (Node **) (&(qry->targetList)), rt_index, new_index, sublevels_up); modifyAggrefChangeVarnodes( (Node **) (&(qry->qual)), rt_index, new_index, sublevels_up); modifyAggrefChangeVarnodes( (Node **) (&(qry->havingQual)), rt_index, new_index, sublevels_up); } break; default: elog(NOTICE, "unknown node tag %d in modifyAggrefChangeVarnodes()", nodeTag(node)); elog(NOTICE, "Node is: %s", nodeToString(node)); break; }}/* * modifyAggrefDropQual - * remove the pure aggref clase from a qualification */static voidmodifyAggrefDropQual(Node **nodePtr, Node *orignode, Expr *expr){ Node *node = *nodePtr; if (node == NULL) return; switch (nodeTag(node)) { case T_Var: break; case T_Aggref: { Aggref *aggref = (Aggref *) node; Aggref *oaggref = (Aggref *) orignode; modifyAggrefDropQual( (Node **) (&(aggref->target)), (Node *) (oaggref->target), expr); } break; case T_Param: break; case T_Const: break; case T_GroupClause: break; case T_Expr: { Expr *this_expr = (Expr *) node; Expr *orig_expr = (Expr *) orignode; if (orig_expr == expr) { Const *ctrue; if (expr->typeOid != BOOLOID) elog(ERROR, "aggregate expression in qualification isn't of type bool"); ctrue = makeNode(Const); ctrue->consttype = BOOLOID; ctrue->constlen = 1; ctrue->constisnull = FALSE; ctrue->constvalue = (Datum) TRUE; ctrue->constbyval = TRUE; *nodePtr = (Node *) ctrue; } else modifyAggrefDropQual( (Node **) (&(this_expr->args)), (Node *) (orig_expr->args), expr); } break; case T_Iter: { Iter *iter = (Iter *) node; Iter *oiter = (Iter *) orignode; modifyAggrefDropQual( (Node **) (&(iter->iterexpr)), (Node *) (oiter->iterexpr), expr); } break; case T_ArrayRef: { ArrayRef *ref = (ArrayRef *) node; ArrayRef *oref = (ArrayRef *) orignode; modifyAggrefDropQual( (Node **) (&(ref->refupperindexpr)), (Node *) (oref->refupperindexpr), expr); modifyAggrefDropQual( (Node **) (&(ref->reflowerindexpr)), (Node *) (oref->reflowerindexpr), expr); modifyAggrefDropQual( (Node **) (&(ref->refexpr)), (Node *) (oref->refexpr), expr); modifyAggrefDropQual( (Node **) (&(ref->refassgnexpr)), (Node *) (oref->refassgnexpr), expr); } break; case T_List: { List *l; List *ol = (List *) orignode; int li = 0; foreach(l, (List *) node) { modifyAggrefDropQual( (Node **) (&(lfirst(l))), (Node *) nth(li, ol), expr); li++; } } break; case T_SubLink: { SubLink *sub = (SubLink *) node; SubLink *osub = (SubLink *) orignode; modifyAggrefDropQual( (Node **) (&(sub->subselect)), (Node *) (osub->subselect), expr); } break; case T_Query: { Query *qry = (Query *) node; Query *oqry = (Query *) orignode; modifyAggrefDropQual( (Node **) (&(qry->qual)), (Node *) (oqry->qual), expr); modifyAggrefDropQual( (Node **) (&(qry->havingQual)), (Node *) (oqry->havingQual), expr); } break; default: elog(NOTICE, "unknown node tag %d in modifyAggrefDropQual()", nodeTag(node)); elog(NOTICE, "Node is: %s", nodeToString(node)); break; }}/* * modifyAggrefMakeSublink - * Create a sublink node for a qualification expression that * uses an aggregate column of a view */static SubLink *modifyAggrefMakeSublink(Expr *origexp, Query *parsetree){ SubLink *sublink; Query *subquery; Node *subqual; RangeTblEntry *rte; Aggref *aggref; Var *target; TargetEntry *tle; Resdom *resdom; Expr *exp = copyObject(origexp); if (nodeTag(nth(0, exp->args)) == T_Aggref) { if (nodeTag(nth(1, exp->args)) == T_Aggref) elog(ERROR, "rewrite: comparision of 2 aggregate columns not supported"); else elog(ERROR, "rewrite: aggregate column of view must be at rigth side in qual"); } aggref = (Aggref *) nth(1, exp->args); target = (Var *) (aggref->target); rte = (RangeTblEntry *) nth(target->varno - 1, parsetree->rtable); tle = makeNode(TargetEntry); resdom = makeNode(Resdom); aggref->usenulls = TRUE; resdom->resno = 1; resdom->restype = ((Oper *) (exp->oper))->opresulttype; resdom->restypmod = -1; resdom->resname = pstrdup("<noname>"); resdom->reskey = 0; resdom->reskeyop = 0; resdom->resjunk = false; tle->resdom = resdom; tle->expr = (Node *) aggref; subqual = copyObject(parsetree->qual); modifyAggrefDropQual((Node **) &subqual, (Node *) parsetree->qual, origexp); sublink = makeNode(SubLink); sublink->subLinkType = EXPR_SUBLINK; sublink->useor = FALSE; sublink->lefthand = lappend(NIL, copyObject(lfirst(exp->args))); sublink->oper = lappend(NIL, copyObject(exp)); sublink->subselect = NULL; subquery = makeNode(Query); sublink->subselect = (Node *) subquery; subquery->commandType = CMD_SELECT; subquery->utilityStmt = NULL; subquery->resultRelation = 0; subquery->into = NULL; subquery->isPortal = FALSE; subquery->isBinary = FALSE; subquery->isTemp = FALSE; subquery->unionall = FALSE; subquery->uniqueFlag = NULL; subquery->sortClause = NULL; subquery->rtable = lappend(NIL, rte); subquery->targetList = lappend(NIL, tle); subquery->qual = subqual; subquery->groupClause = NIL; subquery->havingQual = NULL; subquery->hasAggs = TRUE; subquery->hasSubLinks = FALSE; subquery->unionClause = NULL; modifyAggrefUplevel((Node *) sublink); modifyAggrefChangeVarnodes((Node **) &(sublink->lefthand), target->varno, 1, target->varlevelsup); modifyAggrefChangeVarnodes((Node **) &(sublink->oper), target->varno, 1, target->varlevelsup); modifyAggrefChangeVarnodes((Node **) &(sublink->subselect), target->varno, 1, target->varlevelsup); return sublink;}/* * modifyAggrefQual - * Search for qualification expressions that contain aggregate * functions and substiture them by sublinks. These expressions * originally come from qualifications that use aggregate columns * of a view. */static voidmodifyAggrefQual(Node **nodePtr, Query *parsetree){ Node *node = *nodePtr; if (node == NULL) return; switch (nodeTag(node)) { case T_Var: break; case T_Param: break; case T_Const: break; case T_GroupClause: break; case T_Expr: { Expr *exp = (Expr *) node; SubLink *sub; if (length(exp->args) != 2) { modifyAggrefQual( (Node **) (&(exp->args)), parsetree); break; } if (nodeTag(nth(0, exp->args)) != T_Aggref && nodeTag(nth(1, exp->args)) != T_Aggref) { modifyAggrefQual( (Node **) (&(exp->args)), parsetree); break; } sub = modifyAggrefMakeSublink(exp, parsetree); *nodePtr = (Node *) sub; parsetree->hasSubLinks = TRUE; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -