返回顶部
首页 > 资讯 > 数据库 >PostgreSQL中查询重写的示例分析
  • 386
分享到

PostgreSQL中查询重写的示例分析

2024-04-02 19:04:59 386人浏览 薄情痞子
摘要

小编给大家分享一下postgresql中查询重写的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!重写后的Query结构三

小编给大家分享一下postgresql中查询重写的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

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中查询重写的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网数据库频道!

您可能感兴趣的文档:

--结束END--

本文标题: PostgreSQL中查询重写的示例分析

本文链接: https://lsjlt.com/news/64725.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • PostgreSQL中查询重写的示例分析
    小编给大家分享一下PostgreSQL中查询重写的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!重写后的Query结构三...
    99+
    2024-04-02
  • PostgreSQL中查询优化的示例分析
    小编给大家分享一下PostgreSQL中查询优化的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!一、总体说明下面是PG源码目录(/src/backend/optimizer)中的R...
    99+
    2024-04-02
  • MySQL中子查询的示例分析
    这篇文章主要介绍了MySQL中子查询的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一、子查询定义   定义:  子查询允许把一个查询嵌套在另一个查询当中。...
    99+
    2023-06-20
  • LINQ查询的示例分析
    这篇文章主要介绍LINQ查询的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!在之前的C#版中,开发者应用许多不同的查询语言来访问不同的数据源。例如,要查询一个XML文件,开发者会使用XPath,要查询一个SQ...
    99+
    2023-06-17
  • OJB查询的示例分析
    这篇文章主要为大家展示了“OJB查询的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“OJB查询的示例分析”这篇文章吧。OJB查询该文档介绍了不同查询机制的使用。文档中的代码都通过Juni...
    99+
    2023-06-03
  • MySQL中逻辑查询的示例分析
    这篇文章主要介绍了MySQL中逻辑查询的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。在MySQL中,查询是用于构建DELET...
    99+
    2024-04-02
  • mysql中查询缓存的示例分析
    这篇文章主要介绍mysql中查询缓存的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完! 对mysql查询缓存从五个角度进行详细的分析:Query Cache的工作原理、如何配...
    99+
    2024-04-02
  • oracle中空间查询的示例分析
    这篇文章主要介绍oracle中空间查询的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完! ~~~~~~~~~~~~~ORACLE查看某用户占用了多少...
    99+
    2024-04-02
  • Oracle中集合查询的示例分析
    这篇文章主要介绍了Oracle中集合查询的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。使用并集运算,查询20号部门或30号部门的员...
    99+
    2024-04-02
  • CSS3中媒体查询的示例分析
    这篇文章将为大家详细讲解有关CSS3中媒体查询的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。   媒体查询   CSS3中的媒体查询,它可以根据用户设备的尺...
    99+
    2024-04-02
  • Oracle分页查询的示例分析
    这篇文章主要介绍Oracle分页查询的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!Oracle分页查询的实例详解1.Oracle分页查询:SELECT *...
    99+
    2024-04-02
  • ajax分页查询的示例分析
    这篇文章主要为大家展示了“ajax分页查询的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“ajax分页查询的示例分析”这篇文章吧。(1)先写个显示数据的...
    99+
    2024-04-02
  • innodb查询锁的示例分析
    这篇文章主要为大家展示了“innodb查询锁的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“innodb查询锁的示例分析”这篇文章吧。 ...
    99+
    2024-04-02
  • PostgreSQL查询语句分析
    这篇文章主要介绍“PostgreSQL查询语句分析”,在日常操作中,相信很多人在PostgreSQL查询语句分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”PostgreS...
    99+
    2024-04-02
  • Redis中慢查询操作的示例分析
    这篇文章将为大家详细讲解有关Redis中慢查询操作的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。什么是慢查询慢查询的作用:通过慢查询分析,找到有问题的命令进行优...
    99+
    2024-04-02
  • SQL中DQL查询语言的示例分析
    这篇文章将为大家详细讲解有关SQL中DQL查询语言的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。DQLDQL:data Query language 数据查询语...
    99+
    2024-04-02
  • mysql中慢查询优化的示例分析
    这篇文章主要介绍mysql中慢查询优化的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一个用户反映线上一个SQL语句执行时间慢得无法接受。SQL语句看上去很简单(本文描述中修...
    99+
    2024-04-02
  • CSS3中多媒体查询的示例分析
    小编给大家分享一下CSS3中多媒体查询的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!   CSS2多媒体查询:  ...
    99+
    2024-04-02
  • Hive中向量化查询的示例分析
    这篇文章主要介绍了Hive中向量化查询的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。向量化Hive中的向量化查询执行大大减少了典型...
    99+
    2024-04-02
  • PHP中ThinkPHP高级查询的示例分析
    小编给大家分享一下PHP中ThinkPHP高级查询的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!php的框架有哪些php的框架:1、Laravel,La...
    99+
    2023-06-14
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作