📄 rewritemanip.c
字号:
groupclause->tleGroupref) { tle = (TargetEntry *) copyObject(lfirst(tl)); break; } } if (tle == NULL) elog(ERROR, "AddGroupClause(): GROUP BY entry not found in rules targetlist"); tle->resdom->resno = ++new_resno; tle->resdom->resjunk = true; tle->resdom->resgroupref = length(parsetree->groupClause) + 1; groupclause->tleGroupref = tle->resdom->resgroupref; parsetree->targetList = lappend(parsetree->targetList, tle); parsetree->groupClause = lappend(parsetree->groupClause, groupclause); }}static Node *make_null(Oid type){ Const *c = makeNode(Const); c->consttype = type; c->constlen = get_typlen(type); c->constvalue = PointerGetDatum(NULL); c->constisnull = true; c->constbyval = get_typbyval(type); return (Node *) c;}#ifdef NOT_USEDvoidFixResdomTypes(List *tlist){ List *i; foreach(i, tlist) { TargetEntry *tle = lfirst(i); if (nodeTag(tle->expr) == T_Var) { Var *var = (Var *) tle->expr; tle->resdom->restype = var->vartype; tle->resdom->restypmod = var->vartypmod; } }}#endifstatic Node *FindMatchingNew(List *tlist, int attno){ List *i; foreach(i, tlist) { TargetEntry *tle = lfirst(i); if (tle->resdom->resno == attno) return tle->expr; } return NULL;}static Node *FindMatchingTLEntry(List *tlist, char *e_attname){ List *i; foreach(i, tlist) { TargetEntry *tle = lfirst(i); char *resname; resname = tle->resdom->resname; if (!strcmp(e_attname, resname)) return tle->expr; } return NULL;}static voidResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr, int sublevels_up){ Node *node = *nodePtr; if (node == NULL) return; switch (nodeTag(node)) { case T_TargetEntry: ResolveNew(info, targetlist, &((TargetEntry *) node)->expr, sublevels_up); break; case T_Aggref: ResolveNew(info, targetlist, &((Aggref *) node)->target, sublevels_up); break; case T_Expr: ResolveNew(info, targetlist, (Node **) (&(((Expr *) node)->args)), sublevels_up); break; case T_Iter: ResolveNew(info, targetlist, (Node **) (&(((Iter *) node)->iterexpr)), sublevels_up); break; case T_ArrayRef: ResolveNew(info, targetlist, (Node **) (&(((ArrayRef *) node)->refupperindexpr)), sublevels_up); ResolveNew(info, targetlist, (Node **) (&(((ArrayRef *) node)->reflowerindexpr)), sublevels_up); ResolveNew(info, targetlist, (Node **) (&(((ArrayRef *) node)->refexpr)), sublevels_up); ResolveNew(info, targetlist, (Node **) (&(((ArrayRef *) node)->refassgnexpr)), sublevels_up); break; case T_Var: { int this_varno = (int) ((Var *) node)->varno; int this_varlevelsup = (int) ((Var *) node)->varlevelsup; Node *n; if (this_varno == info->new_varno && this_varlevelsup == sublevels_up) { n = FindMatchingNew(targetlist, ((Var *) node)->varattno); if (n == NULL) { if (info->event == CMD_UPDATE) { *nodePtr = n = copyObject(node); ((Var *) n)->varno = info->current_varno; ((Var *) n)->varnoold = info->current_varno; } else *nodePtr = make_null(((Var *) node)->vartype); } else { *nodePtr = copyObject(n); ((Var *) *nodePtr)->varlevelsup = this_varlevelsup; } } break; } case T_List: { List *l; foreach(l, (List *) node) ResolveNew(info, targetlist, (Node **) &(lfirst(l)), sublevels_up); break; } case T_SubLink: { SubLink *sublink = (SubLink *) node; Query *query = (Query *) sublink->subselect; ResolveNew(info, targetlist, (Node **) &(query->qual), sublevels_up + 1); } break; case T_GroupClause: break; default: /* ignore the others */ break; }}voidFixNew(RewriteInfo *info, Query *parsetree){ ResolveNew(info, parsetree->targetList, (Node **) &(info->rule_action->targetList), 0); ResolveNew(info, parsetree->targetList, (Node **) &info->rule_action->qual, 0); ResolveNew(info, parsetree->targetList, (Node **) &(info->rule_action->groupClause), 0);}static voidnodeHandleRIRAttributeRule(Node **nodePtr, List *rtable, List *targetlist, int rt_index, int attr_num, int *modified, int *badsql, int sublevels_up){ Node *node = *nodePtr; if (node == NULL) return; switch (nodeTag(node)) { case T_TargetEntry: { TargetEntry *tle = (TargetEntry *) node; nodeHandleRIRAttributeRule(&tle->expr, rtable, targetlist, rt_index, attr_num, modified, badsql, sublevels_up); } break; case T_Aggref: { Aggref *aggref = (Aggref *) node; nodeHandleRIRAttributeRule(&aggref->target, rtable, targetlist, rt_index, attr_num, modified, badsql, sublevels_up); } break; case T_Expr: { Expr *expr = (Expr *) node; nodeHandleRIRAttributeRule((Node **) (&(expr->args)), rtable, targetlist, rt_index, attr_num, modified, badsql, sublevels_up); } break; case T_Iter: { Iter *iter = (Iter *) node; nodeHandleRIRAttributeRule((Node **) (&(iter->iterexpr)), rtable, targetlist, rt_index, attr_num, modified, badsql, sublevels_up); } break; case T_ArrayRef: { ArrayRef *ref = (ArrayRef *) node; nodeHandleRIRAttributeRule((Node **) (&(ref->refupperindexpr)), rtable, targetlist, rt_index, attr_num, modified, badsql, sublevels_up); nodeHandleRIRAttributeRule((Node **) (&(ref->reflowerindexpr)), rtable, targetlist, rt_index, attr_num, modified, badsql, sublevels_up); nodeHandleRIRAttributeRule((Node **) (&(ref->refexpr)), rtable, targetlist, rt_index, attr_num, modified, badsql, sublevels_up); nodeHandleRIRAttributeRule((Node **) (&(ref->refassgnexpr)), rtable, targetlist, rt_index, attr_num, modified, badsql, sublevels_up); } break; case T_Var: { int this_varno = ((Var *) node)->varno; int this_varattno = ((Var *) node)->varattno; int this_varlevelsup = ((Var *) node)->varlevelsup; if (this_varno == rt_index && this_varattno == attr_num && this_varlevelsup == sublevels_up) { if (((Var *) node)->vartype == 32) { /* HACK */ *nodePtr = make_null(((Var *) node)->vartype); *modified = TRUE; *badsql = TRUE; break; } else { NameData name_to_look_for; name_to_look_for.data[0] = '\0'; namestrcpy(&name_to_look_for, (char *) get_attname(getrelid(this_varno, rtable), attr_num)); if (name_to_look_for.data[0]) { Node *n; n = FindMatchingTLEntry(targetlist, (char *) &name_to_look_for); if (n == NULL) *nodePtr = make_null(((Var *) node)->vartype); else *nodePtr = n; *modified = TRUE; } } } } break; case T_List: { List *i; foreach(i, (List *) node) { nodeHandleRIRAttributeRule((Node **) (&(lfirst(i))), rtable, targetlist, rt_index, attr_num, modified, badsql, sublevels_up); } } break; case T_SubLink: { SubLink *sublink = (SubLink *) node; Query *query = (Query *) sublink->subselect; nodeHandleRIRAttributeRule((Node **) &(query->qual), rtable, targetlist, rt_index, attr_num, modified, badsql, sublevels_up + 1); } break; default: /* ignore the others */ break; }}/* * Handles 'on retrieve to relation.attribute * do instead retrieve (attribute = expression) w/qual' */voidHandleRIRAttributeRule(Query *parsetree, List *rtable, List *targetlist, int rt_index, int attr_num, int *modified, int *badsql){ nodeHandleRIRAttributeRule((Node **) (&(parsetree->targetList)), rtable, targetlist, rt_index, attr_num, modified, badsql, 0); nodeHandleRIRAttributeRule(&parsetree->qual, rtable, targetlist, rt_index, attr_num, modified, badsql, 0);}#ifdef NOT_USEDstatic voidnodeHandleViewRule(Node **nodePtr, List *rtable, List *targetlist, int rt_index, int *modified, int sublevels_up){ Node *node = *nodePtr; if (node == NULL) return; switch (nodeTag(node)) { case T_TargetEntry: { TargetEntry *tle = (TargetEntry *) node; nodeHandleViewRule(&(tle->expr), rtable, targetlist, rt_index, modified, sublevels_up); } break; case T_Aggref: { Aggref *aggref = (Aggref *) node; nodeHandleViewRule(&(aggref->target), rtable, targetlist, rt_index, modified, sublevels_up); } break; /* * This has to be done to make queries using groupclauses work * on views */ case T_GroupClause: { GroupClause *group = (GroupClause *) node; nodeHandleViewRule((Node **) (&(group->entry)), rtable, targetlist, rt_index, modified, sublevels_up); } break; case T_Expr: { Expr *expr = (Expr *) node; nodeHandleViewRule((Node **) (&(expr->args)), rtable, targetlist, rt_index, modified, sublevels_up); } break; case T_Iter: { Iter *iter = (Iter *) node; nodeHandleViewRule((Node **) (&(iter->iterexpr)), rtable, targetlist, rt_index, modified, sublevels_up); } break; case T_ArrayRef: { ArrayRef *ref = (ArrayRef *) node; nodeHandleViewRule((Node **) (&(ref->refupperindexpr)), rtable, targetlist, rt_index, modified, sublevels_up); nodeHandleViewRule((Node **) (&(ref->reflowerindexpr)), rtable, targetlist, rt_index, modified, sublevels_up); nodeHandleViewRule((Node **) (&(ref->refexpr)), rtable, targetlist, rt_index, modified, sublevels_up); nodeHandleViewRule((Node **) (&(ref->refassgnexpr)), rtable, targetlist, rt_index, modified, sublevels_up); } break; case T_Var: { Var *var = (Var *) node; int this_varno = var->varno; int this_varlevelsup = var->varlevelsup; Node *n; if (this_varno == rt_index && this_varlevelsup == sublevels_up) { n = FindMatchingTLEntry(targetlist, get_attname(getrelid(this_varno, rtable), var->varattno)); if (n == NULL) *nodePtr = make_null(((Var *) node)->vartype); else { /* * This is a hack: The varlevelsup of the orignal * variable and the new one should be the same. * Normally we adapt the node by changing a * pointer to point to a var contained in * 'targetlist'. In the targetlist all * varlevelsups are 0 so if we want to change it * to the original value we have to copy the node * before! (Maybe this will cause troubles with * some sophisticated queries on views?) */ if (this_varlevelsup > 0) *nodePtr = copyObject(n); else *nodePtr = n; if (nodeTag(nodePtr) == T_Var) ((Var *) *nodePtr)->varlevelsup = this_varlevelsup; else nodeHandleViewRule(&n, rtable, targetlist, rt_index, modified, sublevels_up); } *modified = TRUE; } break; } case T_List: { List *l; foreach(l, (List *) node) { nodeHandleViewRule((Node **) (&(lfirst(l))), rtable, targetlist, rt_index, modified, sublevels_up); } } break; case T_SubLink: { SubLink *sublink = (SubLink *) node; Query *query = (Query *) sublink->subselect; List *tmp_lefthand, *tmp_oper; nodeHandleViewRule((Node **) &(query->qual), rtable, targetlist, rt_index, modified, sublevels_up + 1); /***S*H*D***/ nodeHandleViewRule((Node **) &(query->havingQual), rtable, targetlist, rt_index, modified, sublevels_up + 1); nodeHandleViewRule((Node **) &(query->targetList), rtable, targetlist, rt_index, modified, sublevels_up + 1); /* * We also have to adapt the variables used in * sublink->lefthand and sublink->oper */ nodeHandleViewRule((Node **) &(sublink->lefthand), rtable, targetlist, rt_index, modified, 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 */ pfree(lfirst(((Expr *) lfirst(sublink->oper))->args)); lfirst(((Expr *) lfirst(sublink->oper))->args) = lfirst(sublink->lefthand); /***S*I***/ /* INTERSECT want's this - Jan */ /* * tmp_lefthand = sublink->lefthand; foreach(tmp_oper, * sublink->oper) { lfirst(((Expr *) * lfirst(tmp_oper))->args) = lfirst(tmp_lefthand); * tmp_lefthand = lnext(tmp_lefthand); } */ } break; default: /* ignore the others */ break; }}voidHandleViewRule(Query *parsetree, List *rtable, List *targetlist, int rt_index, int *modified){ nodeHandleViewRule(&parsetree->qual, rtable, targetlist, rt_index, modified, 0); nodeHandleViewRule((Node **) (&(parsetree->targetList)), rtable, targetlist, rt_index, modified, 0); /* * The variables in the havingQual and groupClause also have to be * adapted */ nodeHandleViewRule(&parsetree->havingQual, rtable, targetlist, rt_index, modified, 0); nodeHandleViewRule((Node **) (&(parsetree->groupClause)), rtable, targetlist, rt_index, modified, 0);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -