PostgreSQL中查询重写的示例分析
小编给大家分享一下PostgreSQL中查询重写的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!
重写后的Query结构
三、源码解读pg_rewrite_query
/**Performrewritingofaqueryproducedbyparseanalysis.**Note:querymustjusthavecomefromtheparser,becausewedonotdo*AcquireRewriteLocks()onit.*/staticList*pg_rewrite_query(Query*query)//输入查询树{List*querytree_list;if(Debug_print_parse)//debug模式,输出parsetree树elog_node_display(LOG,"parsetree",query,Debug_pretty_print);if(log_parser_stats)ResetUsage();if(query->commandType==CMD_UTILITY)//工具类语句{/*don'trewriteutilities,justdump'emintoresultlist*/querytree_list=list_make1(query);}else//非工具类语句{/*rewriteregularqueries*/querytree_list=QueryRewrite(query);//进入查询重写}if(log_parser_stats)ShowUsage("REWRITERSTATISTICS");#ifdefCOPY_PARSE_PLAN_TREES/*Optionaldebuggingcheck:passquerytreeoutputthroughcopyObject()*/{List*new_list;new_list=copyObject(querytree_list);/*ThischecksbothcopyObject()andtheequal()routines...*/if(!equal(new_list,querytree_list))elog(WARNING,"copyObject()failedtoproduceequalparsetree");elsequerytree_list=new_list;}#endifif(Debug_print_rewritten)elog_node_display(LOG,"rewrittenparsetree",querytree_list,Debug_pretty_print);returnquerytree_list;}
QueryRewrite
/**QueryRewrite-*Primaryentrypointtothequeryrewriter.*Rewriteonequeryviaqueryrewritesystem,possiblyreturning0*ormanyqueries.**NOTE:theparsetreemusteitherhavecomestraightfromtheparser,*orhavebeenscannedbyAcquireRewriteLockstoacquiresuitablelocks.*/List*QueryRewrite(Query*parsetree)//输入查询树{uint64input_query_id=parsetree->queryId;//查询idList*querylist;//查询树,中间结果List*results;//最终结果ListCell*l;//临时变量CmdTypeorigCmdType;//命令类型boolfoundOriginalQuery;Query*lastInstead;/**Thisfunctionisonlyappliedtotop-leveloriginalqueries*/Assert(parsetree->querySource==QSRC_ORIGINAL);Assert(parsetree->canSetTag);/**Step1**Applyallnon-SELECTrulespossiblygetting0ormanyqueries*第1步,应用所有非SELECT规则(UPDATE/INSERT等),查询不需要执行*/querylist=RewriteQuery(parsetree,NIL);/**Step2**ApplyalltheRIRrulesoneachquery**ThisisalsoahandyplacetomarkeachquerywiththeoriginalqueryId*第2步,应用所有RIR规则*RIR是Retrieve-Instead-Retrieve的缩写,Thenameisbasedonhistory.RETRIEVEwasthePostQUELkeyword*forwhatyouknowasSELECT.ArulefiredonaRETRIEVEevent,thatisanunconditionalINSTEADrule*withexactlyoneRETRIEVEactioniscalledRIR-rule.*/results=NIL;foreach(l,querylist)//循环{Query*query=(Query*)lfirst(l);//获取Queryquery=fireRIRrules(query,NIL);//应用RIR规则query->queryId=input_query_id;//设置查询idresults=lappend(results,query);//加入返回结果列表中}/**Step3**第3步,确定哪一个Query设置命令结果标签,并更新canSetTag字段*Determinewhich,ifany,oftheresultingqueriesissupposedtoset*thecommand-resulttag;andupdatethecanSetTagfieldsaccordingly.***Iftheoriginalqueryisstillinthelist,itsetsthecommandtag.*Otherwise,thelastINSTEADqueryofthesamekindastheoriginalis*allowedtosetthetag.(Notetheserulescanleaveuswithnoquery*settingthetag.Thetcopcodehastocopewiththisbysettingupa*defaulttagbasedontheoriginalun-rewrittenquery.)**TheAssertsverifythatatmostonequeryintheresultlistismarked*canSetTag.Ifwearen'tcheckingasserts,wecanfalloutoftheloop*assoonaswefindtheoriginalquery.*/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;#ifndefUSE_ASSERT_CHECKINGbreak;#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;returnresults;}
fireRIRrules
/**fireRIRrules-*ApplyallRIRrulesoneachrangetableentryinthegivenquery*在每一个RTE上应用所有的RIR规则**activeRIRsisalistoftheOIDsofviewswe'realreadyprocessingRIR*rulesfor,usedtodetect/rejectrecursion.*/staticQuery*fireRIRrules(Query*parsetree,List*activeRIRs){intorigResultRelation=parsetree->resultRelation;//结果Relationintrt_index;//RTE的indexListCell*lc;//临时变量/**don'ttrytoconvertthisintoaforeachloop,becausertablelistcan*getchangedeachtimethrough...*/rt_index=0;while(rt_index<list_length(parsetree->rtable))//循环{RangeTblEntry*rte;//RTERelationrel;//关系List*locks;//锁列表RuleLock*rules;//规则锁RewriteRule*rule;//重写规则inti;//临时比那里++rt_index;//索引+1rte=rt_fetch(rt_index,parsetree->rtable);//获取RTE/**AsubqueryRTEcan'thaveassociatedrules,sothere'snothingto*dotothislevelofthequery,butwemustrecurseintothe*subquerytoexpandanyrulereferencesinit.*/if(rte->rtekind==RTE_SUBQUERY)//子查询{rte->subquery=fireRIRrules(rte->subquery,activeRIRs);//递归处理continue;}/**Joinsandothernon-relationRTEscanbeignoredcompletely.*/if(rte->rtekind!=RTE_RELATION)//非RTE_RELATION无需处理continue;/**AlwaysignoreRIRrulesformaterializedviewsreferencedin*queries.(ThisdoesnotpreventrefreshingMVs,sincetheyaren't*referencedintheirownquerydefinitions.)**Note:inthefuturewemightwanttoallowMVstobeconditionally*expandedasiftheywereregularviews,iftheyarenotscannable.*Inthatcasethistestwouldneedtobepostponedtillafterwe've*openedtherel,sothatwecouldcheckitsstate.*/if(rte->relkind==RELKIND_MATVIEW)//物化视图类的Relation无需处理continue;/**InINSERT...ONCONFLICT,ignoretheEXCLUDEDpseudo-relation;*evenifitpointstoaview,weneedn'texpandit,andshouldnot*becausewewanttheRTEtoremainofRTE_RELATIONtype.Otherwise,*itwouldgetchangedtoRTE_SUBQUERYtype,whichisan*untested/unsupportedsituation.*/if(parsetree->onConflict&&rt_index==parsetree->onConflict->exclRelIndex)//INSERT...ONCONFLICT无需处理continue;/**Ifthetableisnotreferencedinthequery,thenweignoreit.*Thispreventsinfiniteexpansionloopduetonewrtableentries*insertedbyexpansionofarule.Atableisreferencedifitis*partofthejoinset(asourcetable),orisreferencedbyanyVar*nodes,oristheresulttable.*/if(rt_index!=parsetree->resultRelation&&!rangeTableEntry_used((Node*)parsetree,rt_index,0))//相应的RTE为NULL,无需处理continue;/**Also,ifthisisanewresultrelationintroducedby*ApplyRetrieveRule,wedon'twanttodoanythingmorewithit.*/if(rt_index==parsetree->resultRelation&&rt_index!=origResultRelation)//结果关系continue;/**WecanuseNoLockheresinceeithertheparseror*AcquireRewriteLocksshouldhavelockedtherelalready.*/rel=heap_open(rte->relid,NoLock);//根据relid获取"关系"/**CollecttheRIRrulesthatwemustapply*/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);//添加到列表中}/**Ifwefoundany,applythem---butfirstcheckforrecursion!*/if(locks!=NIL){ListCell*l;if(list_member_oid(activeRIRs,RelationGetRelid(rel)))//检查是否存在递归ereport(ERROR,(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),errmsg("infiniterecursiondetectedinrulesforrelation\"%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);//释放资源}/*RecurseintosubqueriesinWITH*/foreach(lc,parsetree->cteList)//WITH语句处理{CommonTableExpr*cte=(CommonTableExpr*)lfirst(lc);cte->ctequery=(Node*)fireRIRrules((Query*)cte->ctequery,activeRIRs);}/**Recurseintosublinksubqueries,too.Butwealreadydidtheonesin*thertableandcteList.*/if(parsetree->hasSubLinks)//存在子链接query_tree_walker(parsetree,fireRIRonSubLink,(void*)activeRIRs,QTW_IGNORE_RC_SUBQUERIES);/**Applyanyrowlevelsecuritypolicies.Wedothislastbecauseit*requiresspecialrecursiondetectionifthenewqualshavesublink*subqueries,andifwediditintheloopabovequery_tree_walkerwould*thenrecurseintothosequalsasecondtime.*/rt_index=0;foreach(lc,parsetree->rtable)//应用行级安全策略{RangeTblEntry*rte=(RangeTblEntry*)lfirst(lc);Relationrel;List*securityQuals;List*withCheckOptions;boolhasRowSecurity;boolhasSubLinks;++rt_index;/*OnlynormalrelationscanhaveRLSpolicies*/if(rte->rtekind!=RTE_RELATION||(rte->relkind!=RELKIND_RELATION&&rte->relkind!=RELKIND_PARTITIONED_TABLE))continue;rel=heap_open(rte->relid,NoLock);/**FetchanynewsecurityqualsthatmustbeappliedtothisRTE.*/get_row_security_policies(parsetree,rte,rt_index,&securityQuals,&withCheckOptions,&hasRowSecurity,&hasSubLinks);if(securityQuals!=NIL||withCheckOptions!=NIL){if(hasSubLinks){acquireLocksOnSubLinks_contextcontext;/**Recursivelyprocessthenewquals,checkingforinfinite*recursion.*/if(list_member_oid(activeRIRs,RelationGetRelid(rel)))ereport(ERROR,(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),errmsg("infiniterecursiondetectedinpolicyforrelation\"%s\"",RelationGetRelationName(rel))));activeRIRs=lcons_oid(RelationGetRelid(rel),activeRIRs);/**get_row_security_policiesjustpassedbacksecurityQuals*and/orwithCheckOptions,andtherewereSubLinks,makesure*welockanyrelationswhicharereferenced.**Theselockswouldnormallybeacquiredbytheparser,but*securityQualsandwithCheckOptionsareaddedpost-parsing.*/context.for_execute=true;(void)acquireLocksOnSubLinks((Node*)securityQuals,&context);(void)acquireLocksOnSubLinks((Node*)withCheckOptions,&context);/**Nowthatwehavethelocksonanythingaddedby*get_row_security_policies,fireanyRIRrulesforthem.*/expression_tree_walker((Node*)securityQuals,fireRIRonSubLink,(void*)activeRIRs);expression_tree_walker((Node*)withCheckOptions,fireRIRonSubLink,(void*)activeRIRs);activeRIRs=list_delete_first(activeRIRs);}/**AddthenewsecuritybarrierqualstothestartoftheRTE's*listsothattheygetappliedbeforeanyexistingbarrierquals*(whichwouldhavecomefromasecurity-barrierview,andshould*getlowerprioritythanRLSconditionsonthetableitself).*/rte->securityQuals=list_concat(securityQuals,rte->securityQuals);parsetree->withCheckOptions=list_concat(withCheckOptions,parsetree->withCheckOptions);}/**Makesurethequeryismarkedcorrectlyifrowlevelsecurity*applies,orifthenewqualshadsublinks.*/if(hasRowSecurity)parsetree->hasRowSecurity=true;if(hasSubLinks)parsetree->hasSubLinks=true;heap_close(rel,NoLock);}returnparsetree;//返回}
ApplyRetrieveRule
*ApplyRetrieveRule-expandanONSELECTrule*/staticQuery*ApplyRetrieveRule(Query*parsetree,//查询树RewriteRule*rule,//重写规则intrt_index,//RTEindexRelationrelation,//关系List*activeRIRs)//RIR链表{Query*rule_action;RangeTblEntry*rte,*subrte;//RTERowMarkClause*rc;if(list_length(rule->actions)!=1)elog(ERROR,"expectedjustoneruleaction");if(rule->qual!=NULL)elog(ERROR,"cannothandlequalifiedONSELECTrule");if(rt_index==parsetree->resultRelation)//目标关系?{/**Wehaveaviewastheresultrelationofthequery,anditwasn't*rewrittenbyanyrule.Thiscaseissupportedifthereisan*INSTEADOFtriggerthatwilltrapattemptstoinsert/update/delete*viewrows.Theexecutorwillcheckthat;forthemomentjustplow*ahead.Wehavetwocases:**ForINSERT,weneedn'tdoanything.TheunmodifiedRTEwillserve*fineastheresultrelation.**ForUPDATE/DELETE,weneedtoexpandtheviewsoastohavesource*datafortheoperation.ButwealsoneedanunmodifiedRTEto*serveasthetarget.So,copytheRTEandaddthecopytothe*rangetable.Notethatthecopydoesnotgetaddedtothejointree.*Alsonotethatthere'sahackinfireRIRrulestoavoidcallingthis*functionagainwhenitarrivesatthecopiedRTE.*/if(parsetree->commandType==CMD_INSERT)returnparsetree;elseif(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);/**There'snoneedtodopermissionscheckstwice,sowipeoutthe*permissionsinfofortheoriginalRTE(weprefertokeepthe*bitssetontheresultRTE).*/rte->requiredPerms=0;rte->checkAsUser=InvalidOid;rte->selectedCols=NULL;rte->insertedCols=NULL;rte->updatedCols=NULL;/**Forthemostpart,Varsreferencingtheviewshouldremainas*theyare,meaningthattheyimplicitlyrepresentOLDvalues.*ButintheRETURNINGlistifany,wewantsuchVarsto*representNEWvalues,sochangethemtoreferencethenewRTE.**SinceChangeVarNodesscribblesonthetreein-place,copythe*RETURNINGlistfirstforsafety.*/parsetree->returningList=copyObject(parsetree->returningList);ChangeVarNodes((Node*)parsetree->returningList,rt_index,parsetree->resultRelation,0);/**Toallowtheexecutortocomputetheoriginalviewrowtopass*totheINSTEADOFtrigger,weaddaresjunkwhole-rowVar*referencingtheoriginalRTE.Thiswilllatergetexpanded*intoaRowExprcomputingalltheOLDvaluesoftheviewrow.*/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);/*Now,continuewithexpandingtheoriginalviewRTE*/}elseelog(ERROR,"unrecognizedcommandType:%d",(int)parsetree->commandType);}/**Checkifthere'saFOR[KEY]UPDATE/SHAREclauseapplyingtothisview.*检查是否有FORUPDATE/SHARE语句*Note:weneedn'texplicitlyconsideranysuchclausesappearingin*ancestorquerylevels;theireffectshavealreadybeenpusheddownto*herebymarkQueryForLocking,andwillbereflectedin"rc".*/rc=get_parse_rowmark(parsetree,rt_index);/**Makeamodifiablecopyoftheviewquery,andacquireneededlockson*therelationsitmentions.ForceatleastRowShareLockforallsuch*relsifthere'saFOR[KEY]UPDATE/SHAREclauseaffectingthisview.*///copy规则,上锁rule_action=copyObject(linitial(rule->actions));AcquireRewriteLocks(rule_action,true,(rc!=NULL));/**IfFOR[KEY]UPDATE/SHAREofview,markallthecontainedtablesas*implicitFOR[KEY]UPDATE/SHARE,thesameastheparserwouldhavedone*iftheview'ssubqueryhadbeenwrittenoutexplicitly.*/if(rc!=NULL)markQueryForLocking(rule_action,(Node*)rule_action->jointree,rc->strength,rc->waitPolicy,true);/**Recursivelyexpandanyviewreferencesinsidetheview.*递归展开*Note:thismusthappenaftermarkQueryForLocking.Thatway,anyUPDATE*permissionbitsneededforsub-viewsareinitiallyappliedtotheir*RTE_RELATIONRTEsbymarkQueryForLocking,andthentransferredtotheir*OLDrangetableentriesbytheactionbelow(inarecursivecallofthis*routine).*/rule_action=fireRIRrules(rule_action,activeRIRs);/**Now,plugtheviewqueryinasasubselect,replacingtherelation's*originalRTE.*/rte=rt_fetch(rt_index,parsetree->rtable);//获取原RTErte->rtekind=RTE_SUBQUERY;//转换为子查询rte->relid=InvalidOid;//设置为0rte->security_barrier=RelationIsSecurityView(relation);rte->subquery=rule_action;//子查询设置为刚才构造的Queryrte->inh=false;/*mustnotbesetforasubquery*//**Wemovetheview'spermissioncheckdatadowntoitsrangetable.The*checkswillactuallybedoneagainsttheOLDentrytherein.*/subrte=rt_fetch(PRS2_OLD_VARNO,rule_action->rtable);//OLDRTE仍需要检查权限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;/*nopermissioncheckonsubqueryitself*/rte->checkAsUser=InvalidOid;rte->selectedCols=NULL;rte->insertedCols=NULL;rte->updatedCols=NULL;returnparsetree;//返回结果}四、跟踪分析
SQL语句:
testdb=#selectdw.dwmc,gr.grbh,gr.xmfromvw_dwxxdwinnerjoint_grxxgrondw.dwbh=gr.dwbhwheredw.dwbh='1001';
启动gdb,跟踪调试:
(gdb)bQueryRewriteBreakpoint1at0x80a85e:filerewriteHandler.c,line3571.(gdb)cContinuing.Breakpoint1,QueryRewrite(parsetree=0x2868820)atrewriteHandler.c:35713571uint64input_query_id=parsetree->queryId;(gdb)n3590querylist=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)3604query=fireRIRrules(query,NIL);(gdb)stepfireRIRrules(parsetree=0x2868820,activeRIRs=0x0)atrewriteHandler.c:17211721intorigResultRelation=parsetree->resultRelation;(gdb)n...1729rt_index=0;(gdb)1730while(rt_index<list_length(parsetree->rtable))1741rte=rt_fetch(rt_index,parsetree->rtable);(gdb)1748if(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}1796rel=heap_open(rte->relid,NoLock);(gdb)1801rules=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}...1826activeRIRs=lcons_oid(RelationGetRelid(rel),activeRIRs);(gdb)1828foreach(l,locks)(gdb)p*activeRIRs$46={type=T_OidList,length=1,head=0x29320c8,tail=0x29320c8}(gdb)pactiveRIRs->head->data.oid_value$47=16403#进入ApplyRetrieveRule(gdb)n1830rule=lfirst(l);(gdb)1832parsetree=ApplyRetrieveRule(parsetree,(gdb)stepApplyRetrieveRule(parsetree=0x2868820,rule=0x2947298,rt_index=1,relation=0x7f57a6b90be8,activeRIRs=0x29320e8)atrewriteHandler.c:1462...#进入ApplyRetrieveRule调用fireRIRrules1581rule_action=fireRIRrules(rule_action,activeRIRs);(gdb)stepfireRIRrules(parsetree=0x2970118,activeRIRs=0x29320e8)atrewriteHandler.c:17211721intorigResultRelation=parsetree->resultRelation;...(gdb)finish#结束ApplyRetrieveRule->fireRIRrules的调用Runtillexitfrom#0fireRIRrules(parsetree=0x2970118,activeRIRs=0x29320e8)atrewriteHandler.c:17880x00000000008079cfinApplyRetrieveRule(parsetree=0x2868820,rule=0x2947298,rt_index=1,relation=0x7f57a6b90be8,activeRIRs=0x29320e8)atrewriteHandler.c:15811581rule_action=fireRIRrules(rule_action,activeRIRs);Valuereturnedis$56=(Query*)0x2970118...#重写为子查询(gdb)n1589rte->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)n1590rte->relid=InvalidOid;(gdb)1591rte->security_barrier=RelationIsSecurityView(relation);(gdb)1592rte->subquery=rule_action;(gdb)1593rte->inh=false;/*mustnotbesetforasubquery*/(gdb)1599subrte=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)finishRuntillexitfrom#0ApplyRetrieveRule(parsetree=0x2868820,rule=0x2947298,rt_index=1,relation=0x7f57a6b90be8,activeRIRs=0x29320e8)atrewriteHandler.c:16010x0000000000807fe3infireRIRrules(parsetree=0x2868820,activeRIRs=0x29320e8)atrewriteHandler.c:18321832parsetree=ApplyRetrieveRule(parsetree,Valuereturnedis$60=(Query*)0x2868820(gdb)n1828foreach(l,locks)(gdb)1839activeRIRs=list_delete_first(activeRIRs);(gdb)1843heap_close(rel,NoLock);#RIR处理完毕(gdb)pactiveRIRs$61=(List*)0x0(gdb)finishRuntillexitfrom#0fireRIRrules(parsetree=0x2868820,activeRIRs=0x0)atrewriteHandler.c:18430x000000000080a8b5inQueryRewrite(parsetree=0x2868820)atrewriteHandler.c:36043604query=fireRIRrules(query,NIL);Valuereturnedis$62=(Query*)0x2868820(gdb)finishRuntillexitfrom#00x000000000080a8b5inQueryRewrite(parsetree=0x2868820)atrewriteHandler.c:36040x000000000084c945inpg_rewrite_query(query=0x2868820)atpostgres.c:759759querytree_list=QueryRewrite(query);Valuereturnedis$63=(List*)0x29320e8(gdb)cContinuing.#DONE!五、数据结构
RewriteRule
/**RuleLock-*allrulesthatapplytoaparticularrelation.Eventhoughweonly*havetherewriterulesystemleftandthesearenotreally"locks",*thenameiskeptforhistoricalreasons.*/typedefstructRuleLock//rd_rules{intnumLocks;RewriteRule**rules;}RuleLock;/**RewriteRule-*holdsaninfoforarewriterule**/typedefstructRewriteRule{OidruleId;CmdTypeevent;Node*qual;List*actions;charenabled;boolisInstead;}RewriteRule;
以上是“PostgreSQL中查询重写的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。