小编给大家分享一下PostgreSQL中查询重写的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!
重写后的Query结构
三、源码解读
pg_rewrite_query
static List *
pg_rewrite_query(Query *query) //输入查询树
{
List *querytree_list;
if (Debug_print_parse) //debug模式,输出parse tree树
elog_node_display(LOG, "parse tree", query,
Debug_pretty_print);
if (log_parser_stats)
ResetUsage();
if (query->commandType == CMD_UTILITY) //工具类语句
{
querytree_list = list_make1(query);
}
else//非工具类语句
{
querytree_list = QueryRewrite(query); //进入查询重写
}
if (log_parser_stats)
ShowUsage("REWRITER STATISTICS");
#ifdef COPY_PARSE_PLAN_TREES
{
List *new_list;
new_list = copyObject(querytree_list);
if (!equal(new_list, querytree_list))
elog(WARNING, "copyObject() failed to produce equal parse tree");
else
querytree_list = new_list;
}
#endif
if (Debug_print_rewritten)
elog_node_display(LOG, "rewritten parse tree", querytree_list,
Debug_pretty_print);
return querytree_list;
}
QueryRewrite
List *
QueryRewrite(Query *parsetree) //输入查询树
{
uint64 input_query_id = parsetree->queryId;//查询id
List *querylist;//查询树,中间结果
List *results;//最终结果
ListCell *l;//临时变量
CmdType origCmdType;//命令类型
bool foundOriginalQuery;
Query *lastInstead;
Assert(parsetree->querySource == QSRC_ORIGINAL);
Assert(parsetree->canSetTag);
querylist = RewriteQuery(parsetree, NIL);
results = NIL;
foreach(l, querylist) //循环
{
Query *query = (Query *) lfirst(l);//获取Query
query = fireRIRrules(query, NIL);//应用RIR规则
query->queryId = input_query_id;//设置查询id
results = lappend(results, query);//加入返回结果列表中
}
origCmdType = parsetree->commandType;
foundOriginalQuery = false;
lastInstead = NULL;
foreach(l, results)
{
Query *query = (Query *) lfirst(l);
if (query->querySource == QSRC_ORIGINAL)
{
Assert(query->canSetTag);
Assert(!foundOriginalQuery);
foundOriginalQuery = true;
#ifndef USE_ASSERT_CHECKING
break;
#endif
}
else
{
Assert(!query->canSetTag);
if (query->commandType == origCmdType &&
(query->querySource == QSRC_INSTEAD_RULE ||
query->querySource == QSRC_QUAL_INSTEAD_RULE))
lastInstead = query;
}
}
if (!foundOriginalQuery && lastInstead != NULL)
lastInstead->canSetTag = true;
return results;
}
fireRIRrules
static Query *
fireRIRrules(Query *parsetree, List *activeRIRs)
{
int origResultRelation = parsetree->resultRelation;//结果Relation
int rt_index;//RTE的index
ListCell *lc;//临时变量
rt_index = 0;
while (rt_index < list_length(parsetree->rtable)) //循环
{
RangeTblEntry *rte;//RTE
Relation rel;//关系
List *locks;//锁列表
RuleLock *rules;//规则锁
RewriteRule *rule;//重写规则
int i;//临时比那里
++rt_index;//索引+1
rte = rt_fetch(rt_index, parsetree->rtable);//获取RTE
if (rte->rtekind == RTE_SUBQUERY)//子查询
{
rte->subquery = fireRIRrules(rte->subquery, activeRIRs);//递归处理
continue;
}
if (rte->rtekind != RTE_RELATION)//非RTE_RELATION无需处理
continue;
if (rte->relkind == RELKIND_MATVIEW)//物化视图类的Relation无需处理
continue;
if (parsetree->onConflict &&
rt_index == parsetree->onConflict->exclRelIndex)//INSERT ... ON CONFLICT 无需处理
continue;
if (rt_index != parsetree->resultRelation &&
!rangeTableEntry_used((Node *) parsetree, rt_index, 0))//相应的RTE为NULL,无需处理
continue;
if (rt_index == parsetree->resultRelation &&
rt_index != origResultRelation)//结果关系
continue;
rel = heap_open(rte->relid, NoLock);//根据relid获取"关系"
rules = rel->rd_rules;//获取关系上的规则
if (rules != NULL)
{
locks = NIL;
for (i = 0; i < rules->numLocks; i++)
{
rule = rules->rules[i];//获取规则
if (rule->event != CMD_SELECT)
continue;//非SELECT类型,继续下一个规则
locks = lappend(locks, rule);//添加到列表中
}
if (locks != NIL)
{
ListCell *l;
if (list_member_oid(activeRIRs, RelationGetRelid(rel)))//检查是否存在递归
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("infinite recursion detected in rules for relation \"%s\"",
RelationGetRelationName(rel))));
activeRIRs = lcons_oid(RelationGetRelid(rel), activeRIRs);//
foreach(l, locks)//循环
{
rule = lfirst(l);
parsetree = ApplyRetrieveRule(parsetree,
rule,
rt_index,
rel,
activeRIRs);//应用规则
}
activeRIRs = list_delete_first(activeRIRs);//删除已应用的规则
}
}
heap_close(rel, NoLock);//释放资源
}
foreach(lc, parsetree->cteList) //WITH 语句处理
{
CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
cte->ctequery = (Node *)
fireRIRrules((Query *) cte->ctequery, activeRIRs);
}
if (parsetree->hasSubLinks) //存在子链接
query_tree_walker(parsetree, fireRIRonSubLink, (void *) activeRIRs,
QTW_IGNORE_RC_SUBQUERIES);
rt_index = 0;
foreach(lc, parsetree->rtable)//应用行级安全策略
{
RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
Relation rel;
List *securityQuals;
List *withCheckOptions;
bool hasRowSecurity;
bool hasSubLinks;
++rt_index;
if (rte->rtekind != RTE_RELATION ||
(rte->relkind != RELKIND_RELATION &&
rte->relkind != RELKIND_PARTITIONED_TABLE))
continue;
rel = heap_open(rte->relid, NoLock);
get_row_security_policies(parsetree, rte, rt_index,
&securityQuals, &withCheckOptions,
&hasRowSecurity, &hasSubLinks);
if (securityQuals != NIL || withCheckOptions != NIL)
{
if (hasSubLinks)
{
acquireLocksOnSubLinks_context context;
if (list_member_oid(activeRIRs, RelationGetRelid(rel)))
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("infinite recursion detected in policy for relation \"%s\"",
RelationGetRelationName(rel))));
activeRIRs = lcons_oid(RelationGetRelid(rel), activeRIRs);
context.for_execute = true;
(void) acquireLocksOnSubLinks((Node *) securityQuals, &context);
(void) acquireLocksOnSubLinks((Node *) withCheckOptions,
&context);
expression_tree_walker((Node *) securityQuals,
fireRIRonSubLink, (void *) activeRIRs);
expression_tree_walker((Node *) withCheckOptions,
fireRIRonSubLink, (void *) activeRIRs);
activeRIRs = list_delete_first(activeRIRs);
}
rte->securityQuals = list_concat(securityQuals,
rte->securityQuals);
parsetree->withCheckOptions = list_concat(withCheckOptions,
parsetree->withCheckOptions);
}
if (hasRowSecurity)
parsetree->hasRowSecurity = true;
if (hasSubLinks)
parsetree->hasSubLinks = true;
heap_close(rel, NoLock);
}
return parsetree;//返回
}
ApplyRetrieveRule
* ApplyRetrieveRule - expand an ON SELECT rule
*/
static Query *
ApplyRetrieveRule(Query *parsetree,//查询树
RewriteRule *rule,//重写规则
int rt_index,//RTE index
Relation relation,//关系
List *activeRIRs)//RIR链表
{
Query *rule_action;
RangeTblEntry *rte,
*subrte;//RTE
RowMarkClause *rc;
if (list_length(rule->actions) != 1)
elog(ERROR, "expected just one rule action");
if (rule->qual != NULL)
elog(ERROR, "cannot handle qualified ON SELECT rule");
if (rt_index == parsetree->resultRelation) //目标关系?
{
if (parsetree->commandType == CMD_INSERT)
return parsetree;
else if (parsetree->commandType == CMD_UPDATE ||
parsetree->commandType == CMD_DELETE)
{
RangeTblEntry *newrte;
Var *var;
TargetEntry *tle;
rte = rt_fetch(rt_index, parsetree->rtable);
newrte = copyObject(rte);
parsetree->rtable = lappend(parsetree->rtable, newrte);
parsetree->resultRelation = list_length(parsetree->rtable);
rte->requiredPerms = 0;
rte->checkAsUser = InvalidOid;
rte->selectedCols = NULL;
rte->insertedCols = NULL;
rte->updatedCols = NULL;
parsetree->returningList = copyObject(parsetree->returningList);
ChangeVarNodes((Node *) parsetree->returningList, rt_index,
parsetree->resultRelation, 0);
var = makeWholeRowVar(rte, rt_index, 0, false);
tle = makeTargetEntry((Expr *) var,
list_length(parsetree->targetList) + 1,
pstrdup("wholerow"),
true);
parsetree->targetList = lappend(parsetree->targetList, tle);
}
else
elog(ERROR, "unrecognized commandType: %d",
(int) parsetree->commandType);
}
rc = get_parse_rowmark(parsetree, rt_index);
//copy规则,上锁
rule_action = copyObject(linitial(rule->actions));
AcquireRewriteLocks(rule_action, true, (rc != NULL));
if (rc != NULL)
markQueryForLocking(rule_action, (Node *) rule_action->jointree,
rc->strength, rc->waitPolicy, true);
rule_action = fireRIRrules(rule_action, activeRIRs);
rte = rt_fetch(rt_index, parsetree->rtable);//获取原RTE
rte->rtekind = RTE_SUBQUERY;//转换为子查询
rte->relid = InvalidOid;//设置为0
rte->security_barrier = RelationIsSecurityView(relation);
rte->subquery = rule_action;//子查询设置为刚才构造的Query
rte->inh = false;
subrte = rt_fetch(PRS2_OLD_VARNO, rule_action->rtable);//OLD RTE仍需要检查权限
Assert(subrte->relid == relation->rd_id);
subrte->requiredPerms = rte->requiredPerms;
subrte->checkAsUser = rte->checkAsUser;
subrte->selectedCols = rte->selectedCols;
subrte->insertedCols = rte->insertedCols;
subrte->updatedCols = rte->updatedCols;
rte->requiredPerms = 0;
rte->checkAsUser = InvalidOid;
rte->selectedCols = NULL;
rte->insertedCols = NULL;
rte->updatedCols = NULL;
return parsetree;//返回结果
}
四、跟踪分析
SQL语句:
testdb=# select dw.dwmc,gr.grbh,gr.xm
from vw_dwxx dw inner join t_grxx gr
on dw.dwbh = gr.dwbh
where dw.dwbh = '1001';
启动gdb,跟踪调试:
(gdb) b QueryRewrite
Breakpoint 1 at 0x80a85e: file rewriteHandler.c, line 3571.
(gdb) c
Continuing.
Breakpoint 1, QueryRewrite (parsetree=0x2868820) at rewriteHandler.c:3571
3571 uint64 input_query_id = parsetree->queryId;
(gdb) n
3590 querylist = RewriteQuery(parsetree, NIL);
#parsetree查询树
#rtable有3个元素(RTE),查询重写注意处理这3个RTE
(gdb) p *parsetree
$6 = {type = T_Query, commandType = CMD_SELECT, querySource = QSRC_ORIGINAL, queryId = 0, canSetTag = true,
utilityStmt = 0x0, resultRelation = 0, hasAggs = false, hasWindowFuncs = false, hasTargetSRFs = false,
hasSubLinks = false, hasDistinctOn = false, hasRecursive = false, hasModifyingCTE = false,
hasForUpdate = false, hasRowSecurity = false, cteList = 0x0, rtable = 0x2868be0, jointree = 0x2962180,
targetList = 0x2961db8, override = OVERRIDING_NOT_SET, onConflict = 0x0, returningList = 0x0,
groupClause = 0x0, groupingSets = 0x0, havingQual = 0x0, windowClause = 0x0, distinctClause = 0x0,
sortClause = 0x0, limitOffset = 0x0, limitCount = 0x0, rowMarks = 0x0, setOperations = 0x0,
constraintDeps = 0x0, withCheckOptions = 0x0, stmt_location = 0, stmt_len = 110}
(gdb) p *parsetree->rtable
$7 = {type = T_List, length = 3, head = 0x2868bc0, tail = 0x2961bb8}
(gdb)
3604 query = fireRIRrules(query, NIL);
(gdb) step
fireRIRrules (parsetree=0x2868820, activeRIRs=0x0) at rewriteHandler.c:1721
1721 int origResultRelation = parsetree->resultRelation;
(gdb) n
...
1729 rt_index = 0;
(gdb)
1730 while (rt_index < list_length(parsetree->rtable))
1741 rte = rt_fetch(rt_index, parsetree->rtable);
(gdb)
1748 if (rte->rtekind == RTE_SUBQUERY)
#第1个RTE,视图vw_dwxx
#rtekind = RTE_RELATION, relid = 16403, relkind = 118 'v'
(gdb) p *rte
$12 = {type = T_RangeTblEntry, rtekind = RTE_RELATION, relid = 16403, relkind = 118 'v', tablesample = 0x0,
subquery = 0x0, security_barrier = false, jointype = JOIN_INNER, joinaliasvars = 0x0, functions = 0x0,
funcordinality = false, tablefunc = 0x0, values_lists = 0x0, ctename = 0x0, ctelevelsup = 0,
self_reference = false, coltypes = 0x0, coltypmods = 0x0, colcollations = 0x0, enrname = 0x0,
enrtuples = 0, alias = 0x2867f08, eref = 0x2868a40, lateral = false, inh = true, inFromCl = true,
requiredPerms = 2, checkAsUser = 0, selectedCols = 0x29614e8, insertedCols = 0x0, updatedCols = 0x0,
securityQuals = 0x0}
1796 rel = heap_open(rte->relid, NoLock);
(gdb)
1801 rules = rel->rd_rules;
#关系Relation
(gdb) p *rel
$13 = {rd_node = {spcNode = 1663, dbNode = 16384, relNode = 16403}, rd_smgr = 0x0, rd_refcnt = 1,
rd_backend = -1, rd_islocaltemp = false, rd_isnailed = false, rd_isvalid = true, rd_indexvalid = 0 '\000',
rd_statvalid = false, rd_createSubid = 0, rd_newRelfilenodeSubid = 0, rd_rel = 0x7f57a6b90df8,
rd_att = 0x7f57a6b90f08, rd_id = 16403, rd_lockInfo = {lockRelId = {relId = 16403, dbId = 16384}},
rd_rules = 0x2945bc0, rd_rulescxt = 0x2947140, trigdesc = 0x0, rd_rsdesc = 0x0, rd_fkeylist = 0x0,
rd_fkeyvalid = false, rd_partkeycxt = 0x0, rd_partkey = 0x0, rd_pdcxt = 0x0, rd_partdesc = 0x0,
rd_partcheck = 0x0, rd_indexlist = 0x0, rd_oidindex = 0, rd_pkindex = 0, rd_replidindex = 0,
rd_statlist = 0x0, rd_indexattr = 0x0, rd_projindexattr = 0x0, rd_keyattr = 0x0, rd_pkattr = 0x0,
rd_idattr = 0x0, rd_projidx = 0x0, rd_pubactions = 0x0, rd_options = 0x0, rd_index = 0x0,
rd_indextuple = 0x0, rd_amhandler = 0, rd_indexcxt = 0x0, rd_amroutine = 0x0, rd_opfamily = 0x0,
rd_opcintype = 0x0, rd_support = 0x0, rd_supportinfo = 0x0, rd_indoption = 0x0, rd_indexprs = 0x0,
rd_indpred = 0x0, rd_exclops = 0x0, rd_exclprocs = 0x0, rd_exclstrats = 0x0, rd_amcache = 0x0,
rd_indcollation = 0x0, rd_fdwroutine = 0x0, rd_toastoid = 0, pgstat_info = 0x0}
#rules
(gdb) p *rel->rd_rules #rules是指向RewriteRule数组的指针,元素只有一个(numLocks)
$15 = {numLocks = 1, rules = 0x2947268}
(gdb) p *(RewriteRule *)rel->rd_rules->rules[0]
$28 = {ruleId = 16406, event = CMD_SELECT, qual = 0x0, actions = 0x2945b90, enabled = 79 'O',
isInstead = true}
#查看rules中的actions链表
(gdb) p *rel->rd_rules->rules[0]->actions
$31 = {type = T_List, length = 1, head = 0x2945b70, tail = 0x2945b70}
(gdb) p *(Node *)rel->rd_rules->rules[0]->actions->head->data.ptr_value
$32 = {type = T_Query}
(gdb) set $action=(Query *)rel->rd_rules->rules[0]->actions->head->data.ptr_value
#重写规则中的action为Query!
(gdb) p $action
$34 = (Query *) 0x29472c8
(gdb) p *$action
$35 = {type = T_Query, commandType = CMD_SELECT, querySource = QSRC_ORIGINAL, queryId = 0, canSetTag = true,
utilityStmt = 0x0, resultRelation = 0, hasAggs = false, hasWindowFuncs = false, hasTargetSRFs = false,
hasSubLinks = false, hasDistinctOn = false, hasRecursive = false, hasModifyingCTE = false,
hasForUpdate = false, hasRowSecurity = false, cteList = 0x0, rtable = 0x2947708, jointree = 0x2945820,
targetList = 0x2945990, override = OVERRIDING_NOT_SET, onConflict = 0x0, returningList = 0x0,
groupClause = 0x0, groupingSets = 0x0, havingQual = 0x0, windowClause = 0x0, distinctClause = 0x0,
sortClause = 0x0, limitOffset = 0x0, limitCount = 0x0, rowMarks = 0x0, setOperations = 0x0,
constraintDeps = 0x0, withCheckOptions = 0x0, stmt_location = -1, stmt_len = -1}
(gdb) p *$action->rtable
$36 = {type = T_List, length = 3, head = 0x29476e8, tail = 0x2945800}
(gdb) p *(Node *)$action->rtable->head->data.ptr_value
$37 = {type = T_RangeTblEntry}
(gdb) p *(RangeTblEntry *)$action->rtable->head->data.ptr_value
$38 = {type = T_RangeTblEntry, rtekind = RTE_RELATION, relid = 16403, relkind = 118 'v', tablesample = 0x0,
subquery = 0x0, security_barrier = false, jointype = JOIN_INNER, joinaliasvars = 0x0, functions = 0x0,
funcordinality = false, tablefunc = 0x0, values_lists = 0x0, ctename = 0x0, ctelevelsup = 0,
self_reference = false, coltypes = 0x0, coltypmods = 0x0, colcollations = 0x0, enrname = 0x0,
enrtuples = 0, alias = 0x29474e8, eref = 0x2947588, lateral = false, inh = false, inFromCl = false,
requiredPerms = 0, checkAsUser = 10, selectedCols = 0x0, insertedCols = 0x0, updatedCols = 0x0,
securityQuals = 0x0}
(gdb) p *((RangeTblEntry *)$action->rtable->head->data.ptr_value)->eref
$42 = {type = T_Alias, aliasname = 0x29475b8 "old", colnames = 0x2947608}
(gdb) p *((RangeTblEntry *)$action->rtable->head->next->data.ptr_value)->eref
$43 = {type = T_Alias, aliasname = 0x29478c0 "new", colnames = 0x2947930}
(gdb) p *((RangeTblEntry *)$action->rtable->head->next->next->data.ptr_value)->eref
$44 = {type = T_Alias, aliasname = 0x2945698 "t_dwxx", colnames = 0x2945708}
...
1826 activeRIRs = lcons_oid(RelationGetRelid(rel), activeRIRs);
(gdb)
1828 foreach(l, locks)
(gdb) p *activeRIRs
$46 = {type = T_OidList, length = 1, head = 0x29320c8, tail = 0x29320c8}
(gdb) p activeRIRs->head->data.oid_value
$47 = 16403
#进入ApplyRetrieveRule
(gdb) n
1830 rule = lfirst(l);
(gdb)
1832 parsetree = ApplyRetrieveRule(parsetree,
(gdb) step
ApplyRetrieveRule (parsetree=0x2868820, rule=0x2947298, rt_index=1, relation=0x7f57a6b90be8,
activeRIRs=0x29320e8) at rewriteHandler.c:1462
...
#进入ApplyRetrieveRule调用fireRIRrules
1581 rule_action = fireRIRrules(rule_action, activeRIRs);
(gdb) step
fireRIRrules (parsetree=0x2970118, activeRIRs=0x29320e8) at rewriteHandler.c:1721
1721 int origResultRelation = parsetree->resultRelation;
...
(gdb) finish #结束ApplyRetrieveRule->fireRIRrules的调用
Run till exit from #0 fireRIRrules (parsetree=0x2970118, activeRIRs=0x29320e8) at rewriteHandler.c:1788
0x00000000008079cf in ApplyRetrieveRule (parsetree=0x2868820, rule=0x2947298, rt_index=1,
relation=0x7f57a6b90be8, activeRIRs=0x29320e8) at rewriteHandler.c:1581
1581 rule_action = fireRIRrules(rule_action, activeRIRs);
Value returned is $56 = (Query *) 0x2970118
...
#重写为子查询
(gdb) n
1589 rte->rtekind = RTE_SUBQUERY;
(gdb) p *rte
$58 = {type = T_RangeTblEntry, rtekind = RTE_RELATION, relid = 16403, relkind = 118 'v', tablesample = 0x0,
subquery = 0x0, security_barrier = false, jointype = JOIN_INNER, joinaliasvars = 0x0, functions = 0x0,
funcordinality = false, tablefunc = 0x0, values_lists = 0x0, ctename = 0x0, ctelevelsup = 0,
self_reference = false, coltypes = 0x0, coltypmods = 0x0, colcollations = 0x0, enrname = 0x0,
enrtuples = 0, alias = 0x2867f08, eref = 0x2868a40, lateral = false, inh = true, inFromCl = true,
requiredPerms = 2, checkAsUser = 0, selectedCols = 0x29614e8, insertedCols = 0x0, updatedCols = 0x0,
securityQuals = 0x0}
(gdb) n
1590 rte->relid = InvalidOid;
(gdb)
1591 rte->security_barrier = RelationIsSecurityView(relation);
(gdb)
1592 rte->subquery = rule_action;
(gdb)
1593 rte->inh = false;
(gdb)
1599 subrte = rt_fetch(PRS2_OLD_VARNO, rule_action->rtable);
(gdb) p *rte
$59 = {type = T_RangeTblEntry, rtekind = RTE_SUBQUERY, relid = 0, relkind = 118 'v', tablesample = 0x0,
subquery = 0x2970118, security_barrier = false, jointype = JOIN_INNER, joinaliasvars = 0x0,
functions = 0x0, funcordinality = false, tablefunc = 0x0, values_lists = 0x0, ctename = 0x0,
ctelevelsup = 0, self_reference = false, coltypes = 0x0, coltypmods = 0x0, colcollations = 0x0,
enrname = 0x0, enrtuples = 0, alias = 0x2867f08, eref = 0x2868a40, lateral = false, inh = false,
inFromCl = true, requiredPerms = 2, checkAsUser = 0, selectedCols = 0x29614e8, insertedCols = 0x0,
updatedCols = 0x0, securityQuals = 0x0}
...
#结束ApplyRetrieveRule调用,返回上层的fireRIRrules
(gdb) finish
Run till exit from #0 ApplyRetrieveRule (parsetree=0x2868820, rule=0x2947298, rt_index=1,
relation=0x7f57a6b90be8, activeRIRs=0x29320e8) at rewriteHandler.c:1601
0x0000000000807fe3 in fireRIRrules (parsetree=0x2868820, activeRIRs=0x29320e8) at rewriteHandler.c:1832
1832 parsetree = ApplyRetrieveRule(parsetree,
Value returned is $60 = (Query *) 0x2868820
(gdb) n
1828 foreach(l, locks)
(gdb)
1839 activeRIRs = list_delete_first(activeRIRs);
(gdb)
1843 heap_close(rel, NoLock);
#RIR处理完毕
(gdb) p activeRIRs
$61 = (List *) 0x0
(gdb) finish
Run till exit from #0 fireRIRrules (parsetree=0x2868820, activeRIRs=0x0) at rewriteHandler.c:1843
0x000000000080a8b5 in QueryRewrite (parsetree=0x2868820) at rewriteHandler.c:3604
3604 query = fireRIRrules(query, NIL);
Value returned is $62 = (Query *) 0x2868820
(gdb) finish
Run till exit from #0 0x000000000080a8b5 in QueryRewrite (parsetree=0x2868820) at rewriteHandler.c:3604
0x000000000084c945 in pg_rewrite_query (query=0x2868820) at postgres.c:759
759 querytree_list = QueryRewrite(query);
Value returned is $63 = (List *) 0x29320e8
(gdb) c
Continuing.
#DONE!
五、数据结构
RewriteRule
typedef struct RuleLock //rd_rules
{
int numLocks;
RewriteRule **rules;
} RuleLock;
typedef struct RewriteRule
{
Oid ruleId;
CmdType event;
Node *qual;
List *actions;
char enabled;
bool isInstead;
} RewriteRule;
以上是“PostgreSQL中查询重写的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!