PostgreSQL中Insert语句如何使用
PostgreSQL中Insert语句如何使用,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
一、源码解读standard_planner函数,生成PlannedStmt,其中最重要的信息是可用于后续执行SQL语句的planTree.
PlannedStmt*standard_planner(Query*parse,intcursorOptions,ParamListInfoboundParams){PlannedStmt*result;//返回结果PlannerGlobal*glob;//全局的Plan信息-Globalinformationforplanning/optimizationdoubletuple_fraction;//PlannerInfo*root;//每个Query的Plan信息-Per-queryinformationforplanning/optimizationRelOptInfo*final_rel;//Plan中的每个Relation信息-Per-relationinformationforplanning/optimizationPath*best_path;//最优路径Plan*top_plan;//最上层的PlanListCell*lp,//临时变量*lr;/**Setupglobalstateforthisplannerinvocation.Thisdataisneeded*acrossalllevelsofsub-Querythatmightexistinthegivencommand,*sowekeepitinaseparatestructthat'slinkedtobyeachper-Query*PlannerInfo.*/glob=makeNode(PlannerGlobal);//构建PlannerGlobal//初始化参数glob->boundParams=boundParams;glob->subplans=NIL;glob->subroots=NIL;glob->rewindPlanIDs=NULL;glob->finalrtable=NIL;glob->finalrowmarks=NIL;glob->resultRelations=NIL;glob->nonleafResultRelations=NIL;glob->rootResultRelations=NIL;glob->relationOids=NIL;glob->invalItems=NIL;glob->paramExecTypes=NIL;glob->lastPHId=0;glob->lastRowMarkId=0;glob->lastPlanNodeId=0;glob->transientPlan=false;glob->dependsOnRole=false;/**Assesswhetherit'sfeasibletouseparallelmodeforthisquery.We*can'tdothisinastandalonebackend,orifthecommandwilltryto*modifyanydata,orifthisisacursoroperation,orifGUCsareset*tovaluesthatdon'tpermitparallelism,orifparallel-unsafe*functionsarepresentinthequerytree.**(NotethatwedoallowCREATETABLEAS,SELECTINTO,andCREATE*MATERIALIZEDVIEWtouseparallelplans,butthisissafeonlybecause*thecommandiswritingintoacompletelynewtablewhichworkerswon't*beabletosee.Iftheworkerscouldseethetable,thefactthat*grouplockingwouldcausethemtoignoretheleader'sheavyweight*relationextensionlockandGINpagelockswouldmakethisunsafe.*We'llhavetofixthatsomehowifwewanttoallowparallelinsertsin*general;updatesanddeleteshaveadditionalproblemsespeciallyaround*comboCIDs.)**Fornow,wedon'ttrytouseparallelmodeifwe'rerunninginsidea*parallelworker.Wemighteventuallybeabletorelaxthis*restriction,butfornowitseemsbestnottohaveparallelworkers*tryingtocreatetheirownparallelworkers.**Wecan'tuseparallelisminserializablemodebecausethepredicate*lockingcodeisnotparallel-aware.It'snotcatastrophicifsomeone*triestorunaparallelplaninserializablemode;itjustwon'tget*anyworkersandwillrunserially.Butitseemslikeagoodheuristic*toassumethatthesameserializationlevelwillbeineffectatplan*timeandexecutiontime,sodon'tgenerateaparallelplanifwe'rein*serializablemode.*/if((cursorOptions&CURSOR_OPT_PARALLEL_OK)!=0&&IsUnderPostmaster&&parse->commandType==CMD_SELECT&&!parse->hasModifyingCTE&&max_parallel_workers_per_gather>0&&!IsParallelWorker()&&!IsolationIsSerializable())//并行模式的判断{/*allthecheaptestspass,soscanthequerytree*/glob->maxParallelHazard=max_parallel_hazard(parse);glob->parallelModeOK=(glob->maxParallelHazard!=PROPARALLEL_UNSAFE);}else{/*skipthequerytreescan,justassumeit'sunsafe*/glob->maxParallelHazard=PROPARALLEL_UNSAFE;glob->parallelModeOK=false;}/**glob->parallelModeNeededisnormallysettofalsehereandchangedto*trueduringplancreationifaGatherorGatherMergeplanisactually*created(cf.create_gather_plan,create_gather_merge_plan).**However,ifforce_parallel_mode=onorforce_parallel_mode=regress,*thenweimposeparallelmodewheneverit'ssafetodoso,evenifthe*finalplandoesn'tuseparallelism.It'snotsafetodosoifthe*querycontainsanythingparallel-unsafe;parallelModeOKwillbefalse*inthatcase.NotethatparallelModeOKcan'tchangeafterthispoint.*Otherwise,everythinginthequeryiseitherparallel-safeor*parallel-restricted,andineithercaseitshouldbeOKtoimpose*parallel-moderestrictions.Ifthatendsupbreakingsomething,then*eithersomefunctiontheuserincludedinthequeryisincorrectly*labelledasparallel-safeorparallel-restrictedwheninrealityit's*parallel-unsafe,orelsethequeryplanneritselfhasabug.*/glob->parallelModeNeeded=glob->parallelModeOK&&(force_parallel_mode!=FORCE_PARALLEL_OFF);/*Determinewhatfractionoftheplanislikelytobescanned*/if(cursorOptions&CURSOR_OPT_FAST_PLAN){/**WehavenorealideahowmanytuplestheuserwillultimatelyFETCH*fromacursor,butitisoftenthecasethathedoesn'twant'em*all,orwouldpreferafast-startplananywaysothathecan*processsomeofthetuplessooner.UseaGUCparametertodecide*whatfractiontooptimizefor.*/tuple_fraction=cursor_tuple_fraction;//使用GUC参数/**Wedocumentcursor_tuple_fractionassimplybeingafraction,which*meanstheedgecases0and1havetobetreatedspeciallyhere.We*convert1to0("allthetuples")and0toaverysmallfraction.*/if(tuple_fraction>=1.0)tuple_fraction=0.0;elseif(tuple_fraction<=0.0)tuple_fraction=1e-10;}else{/*Defaultassumptionisweneedallthetuples*/tuple_fraction=0.0;}/*primaryplanningentrypoint(mayrecurseforsubqueries)*/root=subquery_planner(glob,parse,NULL,false,tuple_fraction);//获取PlannerInfo根节点/*SelectbestPathandturnitintoaPlan*/final_rel=fetch_upper_rel(root,UPPERREL_FINAL,NULL);//获取顶层的RelOptInfobest_path=get_cheapest_fractional_path(final_rel,tuple_fraction);//选择最佳路径top_plan=create_plan(root,best_path);//生成执行计划/**Ifcreatingaplanforascrollablecursor,makesureitcanrun*backwardsondemand.AddaMaterialnodeatthetopatneed.*/if(cursorOptions&CURSOR_OPT_SCROLL){if(!ExecSupportsBackwardScan(top_plan))top_plan=materialize_finished_plan(top_plan);}/**OptionallyaddaGathernodefortestingpurposes,providedthisis*actuallyasafethingtodo.*/if(force_parallel_mode!=FORCE_PARALLEL_OFF&&top_plan->parallel_safe){Gather*gather=makeNode(Gather);/**IfthereareanyinitPlansattachedtotheformerly-topplannode,*movethemuptotheGathernode;sameaswedoforMaterialnodein*materialize_finished_plan.*/gather->plan.initPlan=top_plan->initPlan;top_plan->initPlan=NIL;gather->plan.targetlist=top_plan->targetlist;gather->plan.qual=NIL;gather->plan.lefttree=top_plan;gather->plan.righttree=NULL;gather->num_workers=1;gather->single_copy=true;gather->invisible=(force_parallel_mode==FORCE_PARALLEL_REGRESS);/**SincethisGatherhasnoparallel-awaredescendantstosignalto,*wedon'tneedarescanParam.*/gather->rescan_param=-1;/**Ideallywe'dusecost_gatherhere,butsettingupdummypathdata*tosatisfyitdoesn'tseemmuchcleanerthanknowingwhatitdoes.*/gather->plan.startup_cost=top_plan->startup_cost+parallel_setup_cost;gather->plan.total_cost=top_plan->total_cost+parallel_setup_cost+parallel_tuple_cost*top_plan->plan_rows;gather->plan.plan_rows=top_plan->plan_rows;gather->plan.plan_width=top_plan->plan_width;gather->plan.parallel_aware=false;gather->plan.parallel_safe=false;/*useparallelmodeforparallelplans.*/root->glob->parallelModeNeeded=true;top_plan=&gather->plan;}/**IfanyParamsweregenerated,runthroughtheplantreeandcompute*eachplannode'sextParam/allParamsets.Ideallywe'dmergethisinto*set_plan_references'treetraversal,butfornowithastobeseparate*becauseweneedtovisitsubplansbeforenotaftermainplan.*/if(glob->paramExecTypes!=NIL){Assert(list_length(glob->subplans)==list_length(glob->subroots));forboth(lp,glob->subplans,lr,glob->subroots){Plan*subplan=(Plan*)lfirst(lp);PlannerInfo*subroot=lfirst_node(PlannerInfo,lr);SS_finalize_plan(subroot,subplan);}SS_finalize_plan(root,top_plan);}/*finalcleanupoftheplan*/Assert(glob->finalrtable==NIL);Assert(glob->finalrowmarks==NIL);Assert(glob->resultRelations==NIL);Assert(glob->nonleafResultRelations==NIL);Assert(glob->rootResultRelations==NIL);top_plan=set_plan_references(root,top_plan);/*...andthesubplans(bothregularsubplansandinitplans)*/Assert(list_length(glob->subplans)==list_length(glob->subroots));forboth(lp,glob->subplans,lr,glob->subroots){Plan*subplan=(Plan*)lfirst(lp);PlannerInfo*subroot=lfirst_node(PlannerInfo,lr);lfirst(lp)=set_plan_references(subroot,subplan);}/*buildthePlannedStmtresult*/result=makeNode(PlannedStmt);result->commandType=parse->commandType;//命令类型result->queryId=parse->queryId;result->hasReturning=(parse->returningList!=NIL);result->hasModifyingCTE=parse->hasModifyingCTE;result->canSetTag=parse->canSetTag;result->transientPlan=glob->transientPlan;result->dependsOnRole=glob->dependsOnRole;result->parallelModeNeeded=glob->parallelModeNeeded;result->planTree=top_plan;//执行计划(这是后续执行SQL使用到的最重要的地方)result->rtable=glob->finalrtable;result->resultRelations=glob->resultRelations;result->nonleafResultRelations=glob->nonleafResultRelations;result->rootResultRelations=glob->rootResultRelations;result->subplans=glob->subplans;result->rewindPlanIDs=glob->rewindPlanIDs;result->rowMarks=glob->finalrowmarks;result->relationOids=glob->relationOids;result->invalItems=glob->invalItems;result->paramExecTypes=glob->paramExecTypes;/*utilityStmtshouldbenull,butwemightaswellcopyit*/result->utilityStmt=parse->utilityStmt;result->stmt_location=parse->stmt_location;result->stmt_len=parse->stmt_len;result->jitFlags=PGJIT_NONE;if(jit_enabled&&jit_above_cost>=0&&top_plan->total_cost>jit_above_cost){result->jitFlags|=PGJIT_PERFORM;/**Decidehowmucheffortshouldbeputintogeneratingbettercode.*/if(jit_optimize_above_cost>=0&&top_plan->total_cost>jit_optimize_above_cost)result->jitFlags|=PGJIT_OPT3;if(jit_inline_above_cost>=0&&top_plan->total_cost>jit_inline_above_cost)result->jitFlags|=PGJIT_INLINE;/**DecidewhichoperationsshouldbeJITed.*/if(jit_expressions)result->jitFlags|=PGJIT_EXPR;if(jit_tuple_deforming)result->jitFlags|=PGJIT_DEFORM;}returnresult;}二、基础信息
standard_planner函数使用的数据结构、宏定义以及依赖的函数等。
数据结构/宏定义
1、PlannerGlobal
/*----------*PlannerGlobal*Globalinformationforplanning/optimization**PlannerGlobalholdsstateforanentireplannerinvocation;thisstate*issharedacrossalllevelsofsub-Queriesthatexistinthecommandbeing*planned.*----------*/typedefstructPlannerGlobal{NodeTagtype;ParamListInfoboundParams;/*Paramvaluesprovidedtoplanner()*/List*subplans;/*PlansforSubPlannodes*/List*subroots;/*PlannerInfosforSubPlannodes*/Bitmapset*rewindPlanIDs;/*indicesofsubplansthatrequireREWIND*/List*finalrtable;/*"flat"rangetableforexecutor*/List*finalrowmarks;/*"flat"listofPlanRowMarks*/List*resultRelations;/*"flat"listofintegerRTindexes*/List*nonleafResultRelations;/*"flat"listofintegerRTindexes*/List*rootResultRelations;/*"flat"listofintegerRTindexes*/List*relationOids;/*OIDsofrelationstheplandependson*/List*invalItems;/*otherdependencies,asPlanInvalItems*/List*paramExecTypes;/*typeOIDsforPARAM_EXECParams*/IndexlastPHId;/*highestPlaceHolderVarIDassigned*/IndexlastRowMarkId;/*highestPlanRowMarkIDassigned*/intlastPlanNodeId;/*highestplannodeIDassigned*/booltransientPlan;/*redoplanwhenTransactionXminchanges?*/booldependsOnRole;/*isplanspecifictocurrentrole?*/boolparallelModeOK;/*parallelmodepotentiallyOK?*/boolparallelModeNeeded;/*parallelmodeactuallyrequired?*/charmaxParallelHazard;/*worstPROPARALLELhazardlevel*/}PlannerGlobal;
2、PlannerInfo
/*----------*PlannerInfo*Per-queryinformationforplanning/optimization**Thisstructisconventionallycalled"root"inalltheplannerroutines.*Itholdslinkstoalloftheplanner'sworkingstate,inadditiontothe*originalQuery.Notethatatpresenttheplannerextensivelymodifies*thepassed-inQuerydatastructure;somedaythatshouldstop.*----------*/structAppendRelInfo;typedefstructPlannerInfo{NodeTagtype;Query*parse;/*theQuerybeingplanned*/PlannerGlobal*glob;/*globalinfoforcurrentplannerrun*/Indexquery_level;/*1attheoutermostQuery*/structPlannerInfo*parent_root;/*NULLatoutermostQuery*//**plan_paramscontainstheexpressionsthatthisquerylevelneedsto*makeavailabletoalowerquerylevelthatiscurrentlybeingplanned.*outer_paramscontainstheparamIdsofPARAM_EXECParamsthatouter*querylevelswillmakeavailabletothisquerylevel.*/List*plan_params;/*listofPlannerParamItems,seebelow*/Bitmapset*outer_params;/**simple_rel_arrayholdspointersto"baserels"and"otherrels"(see*commentsforRelOptInfoformoreinfo).Itisindexedbyrangetable*index(soentry0isalwayswasted).EntriescanbeNULLwhenanRTE*doesnotcorrespondtoabaserelation,suchasajoinRTEoran*unreferencedviewRTE;oriftheRelOptInfohasn'tbeenmadeyet.*/structRelOptInfo**simple_rel_array;/*All1-relRelOptInfos*/intsimple_rel_array_size;/*allocatedsizeofarray*//**simple_rte_arrayisthesamelengthassimple_rel_arrayandholds*pointerstotheassociatedrangetableentries.Thisletsusavoid*rt_fetch(),whichcanbeabitslowoncelargeinheritancesetshave*beenexpanded.*/RangeTblEntry**simple_rte_array;/*rangetableasanarray*//**append_rel_arrayisthesamelengthastheabovearrays,andholds*pointerstothecorrespondingAppendRelInfoentryindexedby*child_relid,orNULLifnone.Thearrayitselfisnotallocatedif*append_rel_listisempty.*/structAppendRelInfo**append_rel_array;/**all_baserelsisaRelidssetofallbaserelids(butnot"other"*relids)inthequery;thatis,theRelidsidentifierofthefinaljoin*weneedtoform.Thisiscomputedinmake_one_rel,justbeforewe*startmakingPaths.*/Relidsall_baserels;/**nullable_baserelsisaRelidssetofbaserelidsthatarenullableby*someouterjoininthejointree;thesearerelsthatarepotentially*nullablebelowtheWHEREclause,SELECTtargetlist,etc.Thisis*computedindeconstruct_jointree.*/Relidsnullable_baserels;/**join_rel_listisalistofalljoin-relationRelOptInfoswehave*consideredinthisplanningrun.Forsmallproblemswejustscanthe*listtodolookups,butwhentherearemanyjoinrelationswebuilda*hashtableforfasterlookups.Thehashtableispresentandvalid*whenjoin_rel_hashisnotNULL.Notethatwestillmaintainthelist*evenwhenusingthehashtableforlookups;thissimplifieslifefor*GEQO.*/List*join_rel_list;/*listofjoin-relationRelOptInfos*/structHTAB*join_rel_hash;/*optionalhashtableforjoinrelations*//**Whendoingadynamic-programming-stylejoinsearch,join_rel_level[k]*isalistofalljoin-relationRelOptInfosoflevelk,and*join_cur_levelisthecurrentlevel.Newjoin-relationRelOptInfosare*automaticallyaddedtothejoin_rel_level[join_cur_level]list.*join_rel_levelisNULLifnotinuse.*/List**join_rel_level;/*listsofjoin-relationRelOptInfos*/intjoin_cur_level;/*indexoflistbeingextended*/List*init_plans;/*initSubPlansforquery*/List*cte_plan_ids;/*per-CTE-itemlistofsubplanIDs*/List*multiexpr_params;/*ListofListsofParamsforMULTIEXPR*subqueryoutputs*/List*eq_classes;/*listofactiveEquivalenceClasses*/List*canon_pathkeys;/*listof"canonical"PathKeys*/List*left_join_clauses;/*listofRestrictInfosformergejoinable*outerjoinclausesw/nonnullablevaron*left*/List*right_join_clauses;/*listofRestrictInfosformergejoinable*outerjoinclausesw/nonnullablevaron*right*/List*full_join_clauses;/*listofRestrictInfosformergejoinable*fulljoinclauses*/List*join_info_list;/*listofSpecialJoinInfos*/List*append_rel_list;/*listofAppendRelInfos*/List*rowMarks;/*listofPlanRowMarks*/List*placeholder_list;/*listofPlaceHolderInfos*/List*fkey_list;/*listofForeignKeyOptInfos*/List*query_pathkeys;/*desiredpathkeysforquery_planner()*/List*group_pathkeys;/*groupClausepathkeys,ifany*/List*window_pathkeys;/*pathkeysofbottomwindow,ifany*/List*distinct_pathkeys;/*distinctClausepathkeys,ifany*/List*sort_pathkeys;/*sortClausepathkeys,ifany*/List*part_schemes;/*Canonicalisedpartitionschemesusedinthe*query.*/List*initial_rels;/*RelOptInfoswearenowtryingtojoin*//*Usefetch_upper_rel()togetanyparticularupperrel*/List*upper_rels[UPPERREL_FINAL+1];/*upper-relRelOptInfos*//*Resulttlistschosenbygrouping_plannerforupper-stageprocessing*/structPathTarget*upper_targets[UPPERREL_FINAL+1];//参见UpperRelationKind/**grouping_plannerpassesbackitsfinalprocessedtargetlisthere,for*useinrelabelingthetopmosttlistofthefinishedPlan.*/List*processed_tlist;/*Fieldsfilledduringcreate_plan()foruseinsetrefs.c*/AttrNumber*grouping_map;/*forGroupingFuncfixup*/List*minmax_aggs;/*ListofMinMaxAggInfos*/MemoryContextplanner_cxt;/*contextholdingPlannerInfo*/doubletotal_table_pages;/*#ofpagesinalltablesofquery*/doubletuple_fraction;/*tuple_fractionpassedtoquery_planner*/doublelimit_tuples;/*limit_tuplespassedtoquery_planner*/Indexqual_security_level;/*minimumsecurity_levelforquals*//*Note:qual_security_leveliszeroiftherearenosecurityQuals*/InheritanceKindinhTargetKind;/*indicatesifthetargetrelationisan*inheritancechildorpartitionora*partitionedtable*/boolhasJoinRTEs;/*trueifanyRTEsareRTE_JOINkind*/boolhasLateralRTEs;/*trueifanyRTEsaremarkedLATERAL*/boolhasDeletedRTEs;/*trueifanyRTEwasdeletedfromjointree*/boolhasHavingQual;/*trueifhavingQualwasnon-null*/boolhasPseudoConstantQuals;/*trueifanyRestrictInfohas*pseudoconstant=true*/boolhasRecursion;/*trueifplanningarecursiveWITHitem*//*ThesefieldsareusedonlywhenhasRecursionistrue:*/intwt_param_id;/*PARAM_EXECIDfortheworktable*/structPath*non_recursive_path;/*apathfornon-recursiveterm*//*Thesefieldsareworkspaceforcreateplan.c*/RelidscurOuterRels;/*outerrelsabovecurrentnode*/List*curOuterParams;/*not-yet-assignedNestLoopParams*//*optionalprivatedataforjoin_search_hook,e.g.,GEQO*/void*join_search_private;/*Doesthisquerymodifyanypartitionkeycolumns?*/boolpartColsUpdated;}PlannerInfo;/**Thisenumidentifiesthedifferenttypesof"upper"(post-scan/join)*relationsthatwemightdealwithduringplanning.*/typedefenumUpperRelationKind{UPPERREL_SETOP,/*resultofUNION/INTERSECT/EXCEPT,ifany*/UPPERREL_PARTIAL_GROUP_AGG,/*resultofpartialgrouping/aggregation,if*any*/UPPERREL_GROUP_AGG,/*resultofgrouping/aggregation,ifany*/UPPERREL_WINDOW,/*resultofwindowfunctions,ifany*/UPPERREL_DISTINCT,/*resultof"SELECTDISTINCT",ifany*/UPPERREL_ORDERED,/*resultofORDERBY,ifany*/UPPERREL_FINAL/*resultofanyremainingtop-levelactions*//*NB:UPPERREL_FINALmustbelastenumentry;it'susedtosizearrays*/}UpperRelationKind;
3、RangeTblEntry
/*--------------------*RangeTblEntry-*ArangetableisaListofRangeTblEntrynodes.**Arangetableentrymayrepresentaplainrelation,asub-selectin*FROM,ortheresultofaJOINclause.(OnlyexplicitJOINsyntax*producesanRTE,nottheimplicitjoinresultingfrommultipleFROM*items.ThisisbecauseweonlyneedtheRTEtodealwithSQLfeatures*likeouterjoinsandjoin-output-columnaliasing.)Otherspecial*RTEtypesalsoexist,asindicatedbyRTEKind.**NotethatweconsiderRTE_RELATIONtocoveranythingthathasapg_class*entry.relkinddistinguishesthesub-cases.**aliasisanAliasnoderepresentingtheASalias-clauseattachedtothe*FROMexpression,orNULLifnoclause.**erefisthetablereferencenameandcolumnreferencenames(either*realoraliases).Notethatsystemcolumns(OIDetc)arenotincluded*inthecolumnlist.*eref->aliasnameisrequiredtobepresent,andshouldgenerallybeused*toidentifytheRTEforerrormessagesetc.**InRELATIONRTEs,thecolnamesinbothaliasanderefareindexedby*physicalattributenumber;thismeanstheremustbecolnameentriesfor*droppedcolumns.WhenbuildinganRTEweinsertemptystrings("")for*droppedcolumns.Notehoweverthatastoredrulemayhavenonempty*colnamesforcolumnsdroppedsincetherulewascreated(andforthat*matterthecolnamesmightbeoutofdateduetocolumnrenamings).*ThesamecommentsapplytoFUNCTIONRTEswhenafunction'sreturntype*isanamedcompositetype.**InJOINRTEs,thecolnamesinbothaliasanderefareone-to-onewith*joinaliasvarsentries.AJOINRTEwillomitcolumnsofitsinputswhen*thosecolumnsareknowntobedroppedatparsetime.Again,however,*astoredrulemightcontainentriesforcolumnsdroppedsincetherule*wascreated.(Thisisonlypossibleforcolumnsnotactuallyreferenced*intherule.)Whenloadingastoredrule,wereplacethejoinaliasvars*itemsforanysuchcolumnswithnullpointers.(Wecan'tsimplydelete*themfromthejoinaliasvarslist,becausethatwouldaffecttheattnums*ofVarsreferencingtherestofthelist.)**inhistrueforrelationreferencesthatshouldbeexpandedtoinclude*inheritancechildren,iftherelhasany.This*must*befalsefor*RTEsotherthanRTE_RELATIONentries.**inFromClmarksthoserangevariablesthatarelistedintheFROMclause.*It'sfalseforRTEsthatareaddedtoaquerybehindthescenes,such*astheNEWandOLDvariablesforarule,orthesubqueriesofaUNION.*Thisflagisnotusedanymoreduringparsing,sincetheparsernowuses*aseparate"namespace"datastructuretocontrolvisibility,butitis*neededbyruleutils.ctodeterminewhetherRTEsshouldbeshownin*decompiledqueries.**requiredPermsandcheckAsUserspecifyrun-timeaccesspermissions*checkstobeperformedatquerystartup.Theusermusthave*all**ofthepermissionsthatareOR'dtogetherinrequiredPerms(zero*indicatesnopermissionschecking).IfcheckAsUserisnotzero,*thendothepermissionschecksusingtheaccessrightsofthatuser,*notthecurrenteffectiveuserID.(Thisallowsrulestoactas*setuidgateways.)PermissionschecksonlyapplytoRELATIONRTEs.**ForSELECT/INSERT/UPDATEpermissions,iftheuserdoesn'thave*table-widepermissionsthenitissufficienttohavethepermissions*onallcolumnsidentifiedinselectedCols(forSELECT)and/or*insertedColsand/orupdatedCols(INSERTwithONCONFLICTDOUPDATEmay*haveall3).selectedCols,insertedColsandupdatedColsarebitmapsets,*whichcannothavenegativeintegermembers,sowesubtract*FirstLowInvalidHeapAttributeNumberfromcolumnnumbersbeforestoring*theminthesefields.Awhole-rowVarreferenceisrepresentedby*settingthebitforInvalidAttrNumber.**securityQualsisalistofsecuritybarrierquals(booleanexpressions),*tobetestedinthelistedorderbeforereturningarowfromthe*relation.ItisalwaysNILinparseroutput.Entriesareaddedbythe*rewritertoimplementsecurity-barrierviewsand/orrow-levelsecurity.*Notethattheplannerturnseachbooleanexpressionintoanimplicitly*AND'edsublist,asisitsusualhabitwithqualificationexpressions.*--------------------*/typedefenumRTEKind{RTE_RELATION,/*ordinaryrelationreference*/RTE_SUBQUERY,/*subqueryinFROM*/RTE_JOIN,/*join*/RTE_FUNCTION,/*functioninFROM*/RTE_TABLEFUNC,/*TableFunc(..,columnlist)*/RTE_VALUES,/*VALUES(<exprlist>),(<exprlist>),...*/RTE_CTE,/*commontableexpr(WITHlistelement)*/RTE_NAMEDTUPLESTORE/*tuplestore,e.g.forAFTERtriggers*/}RTEKind;typedefstructRangeTblEntry{NodeTagtype;RTEKindrtekind;/*seeabove*//**XXXthefieldsapplicabletoonlysomertekindsshouldbemergedinto*aunion.Ididn'tdothisyetbecausethediffswouldimpactalotof*codethatisbeingactivelyworkedon.FIXMEsomeday.*//**FieldsvalidforaplainrelationRTE(elsezero):**Asaspecialcase,RTE_NAMEDTUPLESTOREcanalsosetrelidtoindicate*thatthetupleformatofthetuplestoreisthesameasthereferenced*relation.ThisallowsplansreferencingAFTERtriggertransition*tablestobeinvalidatediftheunderlyingtableisaltered.*/Oidrelid;/*OIDoftherelation*/charrelkind;/*relationkind(seepg_class.relkind)*/structTableSampleClause*tablesample;/*samplinginfo,orNULL*//**FieldsvalidforasubqueryRTE(elseNULL):*/Query*subquery;/*thesub-query*/boolsecurity_barrier;/*isfromsecurity_barrierview?*//**FieldsvalidforajoinRTE(elseNULL/zero):**joinaliasvarsisalistof(usually)Varscorrespondingtothecolumns*ofthejoinresult.AnaliasVarreferencingcolumnKofthejoin*resultcanbereplacedbytheK'thelementofjoinaliasvars---butto*simplifythetaskofreverse-listingaliasescorrectly,wedonotdo*thatuntilplanningtime.Indetail:anelementofjoinaliasvarscan*beaVarofoneofthejoin'sinputrelations,orsuchaVarwithan*implicitcoerciontothejoin'soutputcolumntype,oraCOALESCE*expressioncontainingthetwoinputcolumnVars(possiblycoerced).*WithinaQueryloadedfromastoredrule,itisalsopossiblefor*joinaliasvarsitemstobenullpointers,whichareplaceholdersfor*(necessarilyunreferenced)columnsdroppedsincetherulewasmade.*Also,onceplanningbegins,joinaliasvarsitemscanbealmostanything,*asaresultofsubquery-flatteningsubstitutions.*/JoinTypejointype;/*typeofjoin*/List*joinaliasvars;/*listofalias-varexpansions*//**FieldsvalidforafunctionRTE(elseNIL/zero):**Whenfuncordinalityistrue,theeref->colnameslistincludesanalias*fortheordinalitycolumn.Theordinalitycolumnisotherwise*implicit,andmustbeaccountedfor"byhand"inplacessuchas*expandRTE().*/List*functions;/*listofRangeTblFunctionnodes*/boolfuncordinality;/*isthiscalledWITHORDINALITY?*//**FieldsvalidforaTableFuncRTE(elseNULL):*/TableFunc*tablefunc;/**FieldsvalidforavaluesRTE(elseNIL):*/List*values_lists;/*listofexpressionlists*//**FieldsvalidforaCTERTE(elseNULL/zero):*/char*ctename;/*nameoftheWITHlistitem*/Indexctelevelsup;/*numberofquerylevelsup*/boolself_reference;/*isthisarecursiveself-reference?*//**Fieldsvalidfortablefunctions,values,CTEandENRRTEs(elseNIL):**WeneedtheseforCTERTEssothatthetypesofself-referential*columnsarewell-defined.ForVALUESRTEs,storingtheseexplicitly*saveshavingtore-determinetheinfobyscanningthevalues_lists.For*ENRs,westorethetypesexplicitlyhere(wecouldgettheinformation*fromthecatalogsif'relid'wassupplied,butwe'dstillneedthese*forTupleDesc-basedENRs,sowemightaswellalwaysstorethetype*infohere).**ForENRsonly,wehavetoconsiderthepossibilityofdroppedcolumns.*Adroppedcolumnisincludedintheselists,butitwillhavezeroesin*allthreelists(aswellasanempty-stringentryineref).Testing*forzerocoltypeisthestandardwaytodetectadroppedcolumn.*/List*coltypes;/*OIDlistofcolumntypeOIDs*/List*coltypmods;/*integerlistofcolumntypmods*/List*colcollations;/*OIDlistofcolumncollationOIDs*//**FieldsvalidforENRRTEs(elseNULL/zero):*/char*enrname;/*nameofephemeralnamedrelation*/doubleenrtuples;/*estimatedoractualfromcaller*//**FieldsvalidinallRTEs:*/Alias*alias;/*user-writtenaliasclause,ifany*/Alias*eref;/*expandedreferencenames*/boollateral;/*subquery,function,orvaluesisLATERAL?*/boolinh;/*inheritancerequested?*/boolinFromCl;/*presentinFROMclause?*/AclModerequiredPerms;/*bitmaskofrequiredaccesspermissions*/OidcheckAsUser;/*ifvalid,checkaccessasthisrole*/Bitmapset*selectedCols;/*columnsneedingSELECTpermission*/Bitmapset*insertedCols;/*columnsneedingINSERTpermission*/Bitmapset*updatedCols;/*columnsneedingUPDATEpermission*/List*securityQuals;/*securitybarrierqualstoapply,ifany*/}RangeTblEntry;
4、TargetEntry
/*--------------------*TargetEntry-*atargetentry(usedinquerytargetlists)**Strictlyspeaking,aTargetEntryisn'tanexpressionnode(sinceitcan't*beevaluatedbyExecEvalExpr).Butwetreatitasoneanyway,sincein*verymanyplacesit'sconvenienttoprocessawholequerytargetlistasa*singleexpressiontree.**InaSELECT'stargetlist,resnoshouldalwaysbeequaltotheitem's*ordinalposition(countingfrom1).However,inanINSERTorUPDATE*targetlist,resnorepresentstheattributenumberofthedestination*columnfortheitem;sotheremaybemissingorout-of-orderresnos.*Itisevenlegaltohaveduplicatedresnos;consider*UPDATEtableSETarraycol[1]=...,arraycol[2]=...,...*Thetwomeaningscometogetherintheexecutor,becausetheplanner*transformsINSERT/UPDATEtlistsintoanormalizedformwithexactly*oneentryforeachcolumnofthedestinationtable.Beforethat's*happened,however,itisriskytoassumethatresno==position.*Generallyget_tle_by_resno()shouldbeusedratherthanlist_nth()*tofetchtlistentriesbyresno,andonlyinSELECTshouldyouassume*thatresnoisauniqueidentifier.**resnameisrequiredtorepresentthecorrectcolumnnameinnon-resjunk*entriesoftop-levelSELECTtargetlists,sinceitwillbeusedasthe*columntitlesenttothefrontend.Inmostothercontextsitisonly*adebuggingaid,andmaybewrongorevenNULL.(Inparticular,itmay*bewronginatlistfromastoredrule,ifthereferencedcolumnhasbeen*renamedbyALTERTABLEsincetherulewasmade.Also,theplannertends*tostoreNULLratherthanlookupavalidnamefortlistentriesin*non-toplevelplannodes.)Inresjunkentries,resnameshouldbeeither*aspecificsystem-generatedname(suchas"ctid")orNULL;anythingelse*risksconfusingExecGetJunkAttribute!**ressortgrouprefisusedintherepresentationofORDERBY,GROUPBY,and*DISTINCTitems.Targetlistentrieswithressortgroupref=0arenot*sort/groupitems.Ifressortgroupref>0,thenthisitemisanORDERBY,*GROUPBY,and/orDISTINCTtargetvalue.Notwoentriesinatargetlist*mayhavethesamenonzeroressortgroupref---butthereisnoparticular*meaningtothenonzerovalues,exceptastags.(Forexample,onemust*notassumethatlowerressortgrouprefmeansamoresignificantsortkey.)*TheorderoftheassociatedSortGroupClauselistsdeterminethesemantics.**resorigtbl/resorigcolidentifythesourceofthecolumn,ifitisa*simplereferencetoacolumnofabasetable(orview).Ifitisnot*asimplereference,thesefieldsarezeroes.**Ifresjunkistruethenthecolumnisaworkingcolumn(suchasasortkey)*thatshouldberemovedfromthefinaloutputofthequery.Resjunkcolumns*musthaveresnosthatcannotduplicateanyregularcolumn'sresno.Also*notethatthereareplacesthatassumeresjunkcolumnscomeafternon-junk*columns.*--------------------*/typedefstructTargetEntry{Exprxpr;Expr*expr;/*expressiontoevaluate*/AttrNumberresno;/*attributenumber(seenotesabove)*/char*resname;/*nameofthecolumn(couldbeNULL)*/Indexressortgroupref;/*nonzeroifreferencedbyasort/group*clause*/Oidresorigtbl;/*OIDofcolumn'ssourcetable*/AttrNumberresorigcol;/*column'snumberinsourcetable*/boolresjunk;/*settotruetoeliminatetheattributefrom*finaltargetlist*/}TargetEntry;
5、RelOptInfo
/*----------*RelOptInfo*Per-relationinformationforplanning/optimization**Forplanningpurposes,a"baserel"iseitheraplainrelation(atable)*ortheoutputofasub-SELECTorfunctionthatappearsintherangetable.*IneithercaseitisuniquelyidentifiedbyanRTindex.A"joinrel"*isthejoiningoftwoormorebaserels.Ajoinrelisidentifiedby*thesetofRTindexesforitscomponentbaserels.WecreateRelOptInfo*nodesforeachbaserelandjoinrel,andstoretheminthePlannerInfo's*simple_rel_arrayandjoin_rel_listrespectively.**Notethatthereisonlyonejoinrelforanygivensetofcomponent*baserels,nomatterwhatorderweassemblethemin;soanunordered*setistherightdatatypetoidentifyitwith.**Wealsohave"otherrels",whicharelikebaserelsinthattheyreferto*singleRTindexes;buttheyarenotpartofthejointree,andaregiven*adifferentRelOptKindtoidentifythem.*Currentlytheonlykindofotherrelsarethosemadeformemberrelations*ofan"appendrelation",thatisaninheritancesetorUNIONALLsubquery.*AnappendrelationhasaparentRTEthatisabaserel,whichrepresents*theentireappendrelation.ThememberRTEsareotherrels.Theparent*ispresentinthequeryjointreebutthemembersarenot.Themember*RTEsandotherrelsareusedtoplanthescansoftheindividualtablesor*subqueriesoftheappendset;thentheparentbaserelisgivenAppend*and/orMergeAppendpathscomprisingthebestpathsfortheindividual*memberrels.(SeecommentsforAppendRelInfoformoreinformation.)**AtonetimewealsomadeotherrelstorepresentjoinRTEs,forusein*handlingjoinaliasVars.Currentlythisisnotneededbecausealljoin*aliasVarsareexpandedtonon-aliasedformduringpreprocess_expression.**Wealsohaverelationsrepresentingjoinsbetweenchildrelationsof*differentpartitionedtables.Theserelationsarenotaddedto*join_rel_levellistsastheyarenotjoineddirectlybythedynamic*programmingalgorithm.**ThereisalsoaRelOptKindfor"upper"relations,whichareRelOptInfos*thatdescribepost-scan/joinprocessingsteps,suchasaggregation.*ManyofthefieldsintheseRelOptInfosaremeaningless,buttheirPath*fieldsalwaysholdPathsshowingwaystodothatprocessingstep.**Lastly,thereisaRelOptKindfor"dead"relations,whicharebaserels*thatwehaveprovenwedon'tneedtojoinafterall.**Partsofthisdatastructurearespecifictovariousscanandjoin*mechanisms.Itdidn'tseemworthcreatingnewnodetypesforthem.**relids-Setofbase-relationidentifiers;itisabaserelation*ifthereisjustone,ajoinrelationifmorethanone*rows-estimatednumberoftuplesintherelationafterrestriction*clauseshavebeenapplied(ie,outputrowsofaplanforit)*consider_startup-trueifthereisanyvalueinkeepingplainpathsfor*thisrelonthebasisofhavingcheapstartupcost*consider_param_startup-thesameforparameterizedpaths*reltarget-DefaultPathoutputtlistforthisrel;normallycontains*VarandPlaceHolderVarnodesforthevaluesweneedto*outputfromthisrelation.*Listisinnoparticularorder,butallrelsofan*appendrelsetmustusecorrespondingorders.*NOTE:inanappendrelchildrelation,maycontain*arbitraryexpressionspulledupfromasubquery!*pathlist-ListofPathnodes,oneforeachpotentiallyuseful*methodofgeneratingtherelation*ppilist-ParamPathInfonodesforparameterizedPaths,ifany*cheapest_startup_path-thepathlistmemberwithloweststartupcost*(regardlessofordering)amongtheunparameterizedpaths;*orNULLifthereisnounparameterizedpath*cheapest_total_path-thepathlistmemberwithlowesttotalcost*(regardlessofordering)amongtheunparameterizedpaths;*orifthereisnounparameterizedpath,thepathwithlowest*totalcostamongthepathswithminimumparameterization*cheapest_unique_path-forcachingcheapestpathtoproduceunique*(noduplicates)outputfromrelation;NULLifnotyetrequested*cheapest_parameterized_paths-bestpathsfortheirparameterizations;*alwaysincludescheapest_total_path,evenifthat'sunparameterized*direct_lateral_relids-relsthisrelhasdirectLATERALreferencesto*lateral_relids-requiredouterrelsforLATERAL,asaRelidsset*(includesbothdirectandindirectlateralreferences)**Iftherelationisabaserelationitwillhavethesefieldsset:**relid-RTEindex(thisisredundantwiththerelidsfield,but*isprovidedforconvenienceofaccess)*rtekind-copyofRTE'srtekindfield*min_attr,max_attr-rangeofvalidAttrNumbersforrel*attr_needed-arrayofbitmapsetsindicatingthehighestjoinrel*inwhicheachattributeisneeded;ifbit0issetthen*theattributeisneededaspartoffinaltargetlist*attr_widths-cachespaceforper-attributewidthestimates;*zeromeansnotcomputedyet*lateral_vars-lateralcross-referencesofrel,ifany(listof*VarsandPlaceHolderVars)*lateral_referencers-relidsofrelsthatreferencethisonelaterally*(includesbothdirectandindirectlateralreferences)*indexlist-listofIndexOptInfonodesforrelation'sindexes*(alwaysNILifit'snotatable)*pages-numberofdiskpagesinrelation(zeroifnotatable)*tuples-numberoftuplesinrelation(notconsideringrestrictions)*allvisfrac-fractionofdiskpagesthataremarkedall-visible*subroot-PlannerInfoforsubquery(NULLifit'snotasubquery)*subplan_params-listofPlannerParamItemstobepassedtosubquery**Note:forasubquery,tuplesandsubrootarenotsetimmediately*uponcreationoftheRelOptInfoobject;theyarefilledinwhen*set_subquery_pathlistprocessestheobject.**Forotherrelsthatareappendrelmembers,thesefieldsarefilled*injustasforabaserel,exceptwedon'tbotherwithlateral_vars.**Iftherelationiseitheraforeigntableorajoinofforeigntablesthat*allbelongtothesameforeignserverandareassignedtothesameuserto*checkaccesspermissionsas(cfcheckAsUser),thesefieldswillbeset:**serverid-OIDofforeignserver,ifforeigntable(elseInvalidOid)*userid-OIDofusertocheckaccessas(InvalidOidmeanscurrentuser)*useridiscurrent-we'veassumedthatuseridequalscurrentuser*fdwroutine-functionhooksforFDW,ifforeigntable(elseNULL)*fdw_private-privatestateforFDW,ifforeigntable(elseNULL)**Twofieldsareusedtocacheknowledgeacquiredduringthejoinsearch*aboutwhetherthisrelisprovablyuniquewhenbeingjoinedtogivenother*relation(s),ie,itcanhaveatmostonerowmatchinganygivenrowfrom*thatjoinrelation.Currentlyweonlyattemptsuchproofs,andthusonly*populatethesefields,forbaserels;butsomedaytheymightbeusedfor*joinrelstoo:**unique_for_rels-listofRelidsets,eachonebeingasetofother*relsforwhichthisonehasbeenprovenunique*non_unique_for_rels-listofRelidsets,eachonebeingasetof*otherrelsforwhichwehavetriedandfailedtoprove*thisoneunique**Thepresenceofthefollowingfieldsdependsontherestrictions*andjoinsthattherelationparticipatesin:**baserestrictinfo-ListofRestrictInfonodes,containinginfoabout*eachnon-joinqualificationclauseinwhichthisrelation*participates(onlyusedforbaserels)*baserestrictcost-Estimatedcostofevaluatingthebaserestrictinfo*clausesatasingletuple(onlyusedforbaserels)*baserestrict_min_security-Smallestsecurity_levelfoundamong*clausesinbaserestrictinfo*joininfo-ListofRestrictInfonodes,containinginfoabouteach*joinclauseinwhichthisrelationparticipates(but*notethisexcludesclausesthatmightbederivablefrom*EquivalenceClasses)*has_eclass_joins-flagthatEquivalenceClassjoinsarepossible**Note:KeepingarestrictinfolistintheRelOptInfoisusefulonlyfor*baserels,becauseforajoinrelthesetofclausesthataretreatedas*restrictclausesvariesdependingonwhichsub-relationswechoosetojoin.*(Forexample,ina3-base-reljoin,aclauserelatingrels1and2mustbe*treatedasarestrictclauseifwejoin{1}and{23}tomake{123};but*ifwejoin{12}and{3}thenthatclausewillbearestrictclausein{12}*andshouldnotbeprocessedagainatthelevelof{123}.)Therefore,*therestrictinfolistinthejoincaseappearsinindividualJoinPaths*(fieldjoinrestrictinfo),notintheparentrelation.Butit'sOKfor*theRelOptInfotostorethejoininfolist,becausethatisthesame*foragivenrelnomatterhowweformit.**WestorebaserestrictcostintheRelOptInfo(forbaserelations)because*weknowwewillneeditatleastonce(topricethesequentialscan)*andmayneeditmultipletimestopriceindexscans.**Iftherelationispartitioned,thesefieldswillbeset:**part_scheme-Partitioningschemeoftherelation*nparts-Numberofpartitions*boundinfo-Partitionbounds*partition_qual-Partitionconstraintifnottheroot*part_rels-RelOptInfosforeachpartition*partexprs,nullable_partexprs-Partitionkeyexpressions*partitioned_child_rels-RTindexesofunprunedpartitionsof*thisrelationthatarepartitionedtables*themselves,inhierarchicalorder**Note:Abaserelationalwayshasonlyonesetofpartitionkeys,butajoin*relationmayhaveasmanysetsofpartitionkeysasthenumberofrelations*beingjoined.partexprsandnullable_partexprsarearrayscontaining*part_scheme->partnattselementseach.Eachoftheseelementsisalistof*partitionkeyexpressions.Forabaserelationeachlistinpartexprs*containsonlyoneexpressionandnullable_partexprsisnotpopulated.Fora*joinrelation,partexprsandnullable_partexprscontainpartitionkey*expressionsfromnon-nullableandnullablerelationsresp.Listsatany*givenpositioninthosearraystogethercontainasmanyelementsasthe*numberofjoiningrelations.*----------*/typedefenumRelOptKind{RELOPT_BASEREL,RELOPT_JOINREL,RELOPT_OTHER_MEMBER_REL,RELOPT_OTHER_JOINREL,RELOPT_UPPER_REL,RELOPT_OTHER_UPPER_REL,RELOPT_DEADREL}RelOptKind;/**Isthegivenrelationasimplerelationi.eabaseor"other"member*relation?*/#defineIS_SIMPLE_REL(rel)\((rel)->reloptkind==RELOPT_BASEREL||\(rel)->reloptkind==RELOPT_OTHER_MEMBER_REL)/*Isthegivenrelationajoinrelation?*/#defineIS_JOIN_REL(rel)\((rel)->reloptkind==RELOPT_JOINREL||\(rel)->reloptkind==RELOPT_OTHER_JOINREL)/*Isthegivenrelationanupperrelation?*/#defineIS_UPPER_REL(rel)\((rel)->reloptkind==RELOPT_UPPER_REL||\(rel)->reloptkind==RELOPT_OTHER_UPPER_REL)/*Isthegivenrelationan"other"relation?*/#defineIS_OTHER_REL(rel)\((rel)->reloptkind==RELOPT_OTHER_MEMBER_REL||\(rel)->reloptkind==RELOPT_OTHER_JOINREL||\(rel)->reloptkind==RELOPT_OTHER_UPPER_REL)typedefstructRelOptInfo{NodeTagtype;RelOptKindreloptkind;/*allrelationsincludedinthisRelOptInfo*/Relidsrelids;/*setofbaserelids(rangetableindexes)*//*sizeestimatesgeneratedbyplanner*/doublerows;/*estimatednumberofresulttuples*//*per-relationplannercontrolflags*/boolconsider_startup;/*keepcheap-startup-costpaths?*/boolconsider_param_startup;/*ditto,forparameterizedpaths?*/boolconsider_parallel;/*considerparallelpaths?*//*defaultresulttargetlistforPathsscanningthisrelation*/structPathTarget*reltarget;/*listofVars/Exprs,cost,width*//*materializationinformation*/List*pathlist;/*Pathstructures*/List*ppilist;/*ParamPathInfosusedinpathlist*/List*partial_pathlist;/*partialPaths*/structPath*cheapest_startup_path;structPath*cheapest_total_path;structPath*cheapest_unique_path;List*cheapest_parameterized_paths;/*parameterizationinformationneededforbothbaserelsandjoinrels*//*(seealsolateral_varsandlateral_referencers)*/Relidsdirect_lateral_relids;/*relsdirectlylaterallyreferenced*/Relidslateral_relids;/*minimumparameterizationofrel*//*informationaboutabaserel(notsetforjoinrels!)*/Indexrelid;Oidreltablespace;/*containingtablespace*/RTEKindrtekind;/*RELATION,SUBQUERY,FUNCTION,etc*/AttrNumbermin_attr;/*smallestattrnoofrel(often<0)*/AttrNumbermax_attr;/*largestattrnoofrel*/Relids*attr_needed;/*arrayindexed[min_attr..max_attr]*/int32*attr_widths;/*arrayindexed[min_attr..max_attr]*/List*lateral_vars;/*LATERALVarsandPHVsreferencedbyrel*/Relidslateral_referencers;/*relsthatreferencemelaterally*/List*indexlist;/*listofIndexOptInfo*/List*statlist;/*listofStatisticExtInfo*/BlockNumberpages;/*sizeestimatesderivedfrompg_class*/doubletuples;doubleallvisfrac;PlannerInfo*subroot;/*ifsubquery*/List*subplan_params;/*ifsubquery*/intrel_parallel_workers;/*wantednumberofparallelworkers*//*Informationaboutforeigntablesandforeignjoins*/Oidserverid;/*identifiesserverforthetableorjoin*/Oiduserid;/*identifiesusertocheckaccessas*/booluseridiscurrent;/*joinisonlyvalidforcurrentuser*//*use"structFdwRoutine"toavoidincludingfdwapi.hhere*/structFdwRoutine*fdwroutine;void*fdw_private;/*cachespaceforrememberingifwehaveproventhisrelationunique*/List*unique_for_rels;/*knownuniquefortheseotherrelid*set(s)*/List*non_unique_for_rels;/*knownnotuniquefortheseset(s)*//*usedbyvariousscansandjoins:*/List*baserestrictinfo;/*RestrictInfostructures(ifbaserel)*/QualCostbaserestrictcost;/*costofevaluatingtheabove*/Indexbaserestrict_min_security;/*minsecurity_levelfoundin*baserestrictinfo*/List*joininfo;/*RestrictInfostructuresforjoinclauses*involvingthisrel*/boolhas_eclass_joins;/*Tmeansjoininfoisincomplete*//*usedby"other"relations*/Relidstop_parent_relids;/*Relidsoftopmostparents*//*usedforpartitionedrelations*/PartitionSchemepart_scheme;/*Partitioningscheme.*/intnparts;/*numberofpartitions*/structPartitionBoundInfoData*boundinfo;/*Partitionbounds*/List*partition_qual;/*partitionconstraint*/structRelOptInfo**part_rels;/*ArrayofRelOptInfosofpartitions,*storedinthesameorderofbounds*/List**partexprs;/*Non-nullablepartitionkeyexpressions.*/List**nullable_partexprs;/*Nullablepartitionkeyexpressions.*/List*partitioned_child_rels;/*ListofRTindexes.*/}RelOptInfo;
6、Path
/**Type"Path"isusedas-isforsequential-scanpaths,aswellassomeother*simpleplantypesthatwedon'tneedanyextrainformationinthepathfor.*Forotherpathtypesitisthefirstcomponentofalargerstruct.**"pathtype"istheNodeTagofthePlannodewecouldbuildfromthisPath.*ItispartiallyredundantwiththePath'sNodeTag,butallowsustouse*thesamePathtypeformultiplePlantypeswhenthereisnoneedto*distinguishthePlantypeduringpathprocessing.**"parent"identifiestherelationthisPathscans,and"pathtarget"*describestheprecisesetofoutputcolumnsthePathwouldcompute.*InsimplecasesallPathsforagivenrelsharethesametargetlist,*whichwerepresentbyhavingpath->pathtargetequaltoparent->reltarget.**"param_info",ifnotNULL,linkstoaParamPathInfothatidentifiesouter*relation(s)thatprovideparametervaluestoeachscanofthispath.*Thatmeansthispathcanonlybejoinedtothoserelsbymeansofnestloop*joinswiththispathontheinside.Alsonotethataparameterizedpath*isresponsiblefortestingall"movable"joinclausesinvolvingthisrel*andthespecifiedouterrel(s).**"rows"isthesameasparent->rowsinsimplepaths,butinparameterized*pathsandUniquePathsitcanbelessthanparent->rows,reflectingthe*factthatwe'vefilteredbyextrajoinconditionsorremovedduplicates.**"pathkeys"isaListofPathKeynodes(seeabove),describingthesort*orderingofthepath'soutputrows.*/typedefstructPath{NodeTagtype;NodeTagpathtype;/*tagidentifyingscan/joinmethod*/RelOptInfo*parent;/*therelationthispathcanbuild*/PathTarget*pathtarget;/*listofVars/Exprs,cost,width*/ParamPathInfo*param_info;/*parameterizationinfo,orNULLifnone*/boolparallel_aware;/*engageparallel-awarelogic?*/boolparallel_safe;/*OKtouseaspartofparallelplan?*/intparallel_workers;/*desired#ofworkers;0=notparallel*//*estimatedsize/costsforpath(seecostsize.cformoreinfo)*/doublerows;/*estimatednumberofresulttuples*/Coststartup_cost;/*costexpendedbeforefetchinganytuples*/Costtotal_cost;/*totalcost(assumingalltuplesfetched)*/List*pathkeys;/*sortorderingofpath'soutput*//*pathkeysisaListofPathKeynodes;seeabove*/}Path;/**PathKeys**ThesortorderingofapathisrepresentedbyalistofPathKeynodes.*Anemptylistimpliesnoknownordering.Otherwisethefirstitem*representstheprimarysortkey,thesecondthefirstsecondarysortkey,*etc.Thevaluebeingsortedisrepresentedbylinkingtoan*EquivalenceClasscontainingthatvalueandincludingpk_opfamilyamongits*ec_opfamilies.TheEquivalenceClasstellswhichcollationtouse,too.*Thisisaconvenientmethodbecauseitmakesittrivialtodetect*equivalentandclosely-relatedorderings.(Seeoptimizer/READMEformore*information.)**Note:pk_strategyiseitherBTLessStrategyNumber(forASC)or*BTGreaterStrategyNumber(forDESC).Weassumethatallordering-capable*indextypeswillusebtree-compatiblestrategynumbers.*/typedefstructPathKey{NodeTagtype;EquivalenceClass*pk_eclass;/*thevaluethatisordered*/Oidpk_opfamily;/*btreeopfamilydefiningtheordering*/intpk_strategy;/*sortdirection(ASCorDESC)*/boolpk_nulls_first;/*doNULLscomebeforenormalvalues?*/}PathKey;/**PathTarget**Thisstructcontainswhatweneedtoknowduringplanningaboutthe*targetlist(outputcolumns)thataPathwillcompute.EachRelOptInfo*includesadefaultPathTarget,whichitsindividualPathsmaysimply*reference.However,insomecasesaPathmaycomputeoutputsdifferent*fromotherPaths,andinthatcasewemakeacustomPathTargetforit.*Forexample,anindexscanmightreturnindexexpressionsthatwould*otherwiseneedtobeexplicitlycalculated.(Notealsothat"upper"*relationsgenerallydon'thaveusefuldefaultPathTargets.)**exprscontainsbareexpressions;theydonothaveTargetEntrynodesontop,*thoughthosewillappearinfinishedPlans.**sortgrouprefs[]isanarrayofthesamelengthasexprs,containingthe*correspondingsort/grouprefnos,orzeroesforexpressionsnotreferenced*bysort/groupclauses.IfsortgrouprefsisNULL(whichitgenerallyisin*RelOptInfo.reltargettargets;onlyupper-levelPathscontainthisinfo),*wehavenotidentifiedsort/groupcolumnsinthistlist.Thisallowsusto*dealwithsort/grouprefnoswhenneededwithlessexpensethanincluding*TargetEntrynodesintheexprslist.*/typedefstructPathTarget{NodeTagtype;List*exprs;/*listofexpressionstobecomputed*/Index*sortgrouprefs;/*correspondingsort/grouprefnos,or0*/QualCostcost;/*costofevaluatingtheexpressions*/intwidth;/*estimatedavgwidthofresulttuples*/}PathTarget;/*Conveniencemacrotogetasort/grouprefnofromaPathTarget*/#defineget_pathtarget_sortgroupref(target,colno)\((target)->sortgrouprefs?(target)->sortgrouprefs[colno]:(Index)0)
7、ModifyTable
/*----------------*ModifyTablenode-*Applyrowsproducedbysubplan(s)toresulttable(s),*byinserting,updating,ordeleting.**NotethatrowMarksandepqParamarepresumedtobevalidforallthe*subplan(s);theycan'tcontainanyinfothatvariesacrosssubplans.*----------------*/typedefstructModifyTable{Planplan;CmdTypeoperation;/*INSERT,UPDATE,orDELETE*/boolcanSetTag;/*dowesetthecommandtag/es_processed?*/IndexnominalRelation;/*ParentRTindexforuseofEXPLAIN*//*RTindexesofnon-leaftablesinapartitiontree*/List*partitioned_rels;boolpartColsUpdated;/*somepartkeyinhierarchyupdated*/List*resultRelations;/*integerlistofRTindexes*/intresultRelIndex;/*indexoffirstresultRelinplan'slist*/introotResultRelIndex;/*indexofthepartitionedtableroot*/List*plans;/*plan(s)producingsourcedata*/List*withCheckOptionLists;/*per-target-tableWCOlists*/List*returningLists;/*per-target-tableRETURNINGtlists*/List*fdwPrivLists;/*per-target-tableFDWprivatedatalists*/Bitmapset*fdwDirectModifyPlans;/*indicesofFDWDMplans*/List*rowMarks;/*PlanRowMarks(non-lockingonly)*/intepqParam;/*IDofParamforEvalPlanQualre-eval*/OnConflictActiononConflictAction;/*ONCONFLICTaction*/List*arbiterIndexes;/*ListofONCONFLICTarbiterindexOIDs*/List*onConflictSet;/*SETforINSERTONCONFLICTDOUPDATE*/Node*onConflictWhere;/*WHEREforONCONFLICTUPDATE*/IndexexclRelRTI;/*RTIoftheEXCLUDEDpseudorelation*/List*exclRelTlist;/*tlistoftheEXCLUDEDpseudorelation*/}ModifyTable;
依赖的函数
1、grouping_planner
/*--------------------*grouping_planner*Performplanningstepsrelatedtogrouping,aggregation,etc.**Thisfunctionaddsallrequiredtop-levelprocessingtothescan/join*Path(s)producedbyquery_planner.**Ifinheritance_updateistrue,we'rebeingcalledfrominheritance_planner*andshouldnotincludeaModifyTablestepintheresultingPath(s).*(inheritance_plannerwillcreateasingleModifyTablenodecoveringallthe*targettables.)**tuple_fractionisthefractionoftuplesweexpectwillberetrieved.*tuple_fractionisinterpretedasfollows:*0:expectalltuplestoberetrieved(normalcase)*0<tuple_fraction<1:expectthegivenfractionoftuplesavailable*fromtheplantoberetrieved*tuple_fraction>=1:tuple_fractionistheabsolutenumberoftuples*expectedtoberetrieved(ie,aLIMITspecification)**Returnsnothing;theusefuloutputisinthePathsweattachtothe*(UPPERREL_FINAL,NULL)upperrelin*root.Inaddition,*root->processed_tlistcontainsthefinalprocessedtargetlist.**Notethatwehavenotdoneset_cheapest()onthefinalrel;it'sconvenient*toleavethistothecaller.*--------------------*/staticvoidgrouping_planner(PlannerInfo*root,boolinheritance_update,doubletuple_fraction){Query*parse=root->parse;List*tlist;int64offset_est=0;int64count_est=0;doublelimit_tuples=-1.0;boolhave_postponed_srfs=false;PathTarget*final_target;List*final_targets;List*final_targets_contain_srfs;boolfinal_target_parallel_safe;RelOptInfo*current_rel;RelOptInfo*final_rel;ListCell*lc;/*Tweakcaller-suppliedtuple_fractionifhaveLIMIT/OFFSET*/if(parse->limitCount||parse->limitOffset){tuple_fraction=preprocess_limit(root,tuple_fraction,&offset_est,&count_est);/**IfwehaveaknownLIMIT,anddon'thaveanunknownOFFSET,wecan*estimatetheeffectsofusingaboundedsort.*/if(count_est>0&&offset_est>=0)limit_tuples=(double)count_est+(double)offset_est;}/*Maketuple_fractionaccessibletolower-levelroutines*/root->tuple_fraction=tuple_fraction;if(parse->setOperations){/**Ifthere'satop-levelORDERBY,assumewehavetofetchallthe*tuples.Thismightbetoosimplisticgivenallthehackerybelow*topossiblyavoidthesort;buttheoddsofaccurateestimateshere*areprettylowanyway.XXXtrytogetridofthisinfavorof*lettingplan_set_operationsgeneratebothfast-startand*cheapest-totalpaths.*/if(parse->sortClause)root->tuple_fraction=0.0;/**ConstructPathsforsetoperations.Theresultswillnotneedany*workexceptperhapsatop-levelsortand/orLIMIT.Notethatany*specialworkforrecursiveunionsistheresponsibilityof*plan_set_operations.*/current_rel=plan_set_operations(root);/**Weshouldnotneedtocallpreprocess_targetlist,sincewemustbe*inaSELECTquerynode.Instead,usethetargetlistreturnedby*plan_set_operations(sincethistellswhetheritreturnedany*resjunkcolumns!),andtransferanysortkeyinformationfromthe*originaltlist.*/Assert(parse->commandType==CMD_SELECT);tlist=root->processed_tlist;/*fromplan_set_operations*//*forsafety,copyprocessed_tlistinsteadofmodifyingin-place*/tlist=postprocess_setop_tlist(copyObject(tlist),parse->targetList);/*Saveasidethefinaldecoratedtlist*/root->processed_tlist=tlist;/*AlsoextractthePathTargetformofthesetopresulttlist*/final_target=current_rel->cheapest_total_path->pathtarget;/*Andcheckwhetherit'sparallelsafe*/final_target_parallel_safe=is_parallel_safe(root,(Node*)final_target->exprs);/*Thesetopresulttlistcouldn'tcontainanySRFs*/Assert(!parse->hasTargetSRFs);final_targets=final_targets_contain_srfs=NIL;/**Can'thandleFOR[KEY]UPDATE/SHAREhere(parsershouldhave*checkedalready,butlet'smakesure).*/if(parse->rowMarks)ereport(ERROR,(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),/*------translator:%sisaSQLrowlockingclausesuchasFORUPDATE*/errmsg("%sisnotallowedwithUNION/INTERSECT/EXCEPT",LCS_asString(linitial_node(RowMarkClause,parse->rowMarks)->strength))));/**Calculatepathkeysthatrepresentresultorderingrequirements*/Assert(parse->distinctClause==NIL);root->sort_pathkeys=make_pathkeys_for_sortclauses(root,parse->sortClause,tlist);}else{/*Nosetoperations,doregularplanning*/PathTarget*sort_input_target;List*sort_input_targets;List*sort_input_targets_contain_srfs;boolsort_input_target_parallel_safe;PathTarget*grouping_target;List*grouping_targets;List*grouping_targets_contain_srfs;boolgrouping_target_parallel_safe;PathTarget*scanjoin_target;List*scanjoin_targets;List*scanjoin_targets_contain_srfs;boolscanjoin_target_parallel_safe;boolscanjoin_target_same_exprs;boolhave_grouping;AggClauseCostsagg_costs;WindowFuncLists*wflists=NULL;List*activeWindows=NIL;grouping_sets_data*gset_data=NULL;standard_qp_extraqp_extra;/*ArecursivequeryshouldalwayshavesetOperations*/Assert(!root->hasRecursion);/*PreprocessgroupingsetsandGROUPBYclause,ifany*/if(parse->groupingSets){gset_data=preprocess_grouping_sets(root);}else{/*PreprocessregularGROUPBYclause,ifany*/if(parse->groupClause)parse->groupClause=preprocess_groupclause(root,NIL);}/*Preprocesstargetlist*/tlist=preprocess_targetlist(root);/**Wearenowdonehackingupthequery'stargetlist.Mostofthe*remainingplanningworkwillbedonewiththePathTarget*representationoftlists,butsaveasidethefullrepresentationso*thatwecantransferitsdecoration(resnamesetc)tothetopmost*tlistofthefinishedPlan.*/root->processed_tlist=tlist;/**Collectstatisticsaboutaggregatesforestimatingcosts,andmark*alltheaggregateswithresolvedaggtranstypes.Wemustdothis*beforeslicinganddicingthetlistintovariouspathtargets,else*somecopiesoftheAggrefnodesmightescapebeingmarkedwiththe*correcttranstypes.**Note:currently,wedonotdetectduplicateaggregateshere.This*mayresultinsomewhat-overestimatedcost,whichisfineforour*purposessinceallPathswillgetchargedthesame.Butatsome*pointwemightwishtodothatdetectionintheplanner,rather*thanduringexecutorstartup.*/MemSet(&agg_costs,0,sizeof(AggClauseCosts));if(parse->hasAggs){get_agg_clause_costs(root,(Node*)tlist,AGGSPLIT_SIMPLE,&agg_costs);get_agg_clause_costs(root,parse->havingQual,AGGSPLIT_SIMPLE,&agg_costs);}/**Locateanywindowfunctionsinthetlist.(Wedon'tneedtolook*anywhereelse,sinceexpressionsusedinORDERBYwillbeinthere*too.)Notethattheycouldallhavebeeneliminatedbyconstant*folding,inwhichcasewedon'tneedtodoanymorework.*/if(parse->hasWindowFuncs){wflists=find_window_functions((Node*)tlist,list_length(parse->windowClause));if(wflists->numWindowFuncs>0)activeWindows=select_active_windows(root,wflists);elseparse->hasWindowFuncs=false;}/**PreprocessMIN/MAXaggregates,ifany.Note:becarefulabout*addinglogicbetweenhereandthequery_planner()call.Anything*thatisneededinMIN/MAX-optimizablecaseswillhavetobe*duplicatedinplanagg.c.*/if(parse->hasAggs)preprocess_minmax_aggregates(root,tlist);/**Figureoutwhetherthere'sahardlimitonthenumberofrowsthat*query_planner'sresultsubplanneedstoreturn.Evenifweknowa*hardlimitoverall,itdoesn'tapplyifthequeryhasany*grouping/aggregationoperations,orSRFsinthetlist.*/if(parse->groupClause||parse->groupingSets||parse->distinctClause||parse->hasAggs||parse->hasWindowFuncs||parse->hasTargetSRFs||root->hasHavingQual)root->limit_tuples=-1.0;elseroot->limit_tuples=limit_tuples;/*Setupdataneededbystandard_qp_callback*/qp_extra.tlist=tlist;qp_extra.activeWindows=activeWindows;qp_extra.groupClause=(gset_data?(gset_data->rollups?linitial_node(RollupData,gset_data->rollups)->groupClause:NIL):parse->groupClause);/**Generatethebestunsortedandpresortedpathsforthescan/join*portionofthisQuery,ietheprocessingrepresentedbythe*FROM/WHEREclauses.(Notetheremaynotbeanypresortedpaths.)*Wealsogenerate(instandard_qp_callback)pathkeyrepresentations*ofthequery'ssortclause,distinctclause,etc.*/current_rel=query_planner(root,tlist,standard_qp_callback,&qp_extra);/**Convertthequery'sresulttlistintoPathTargetformat.**Note:it'sdesirabletonotdothistillafterquery_planner(),*becausethetargetwidthestimatescanuseper-Varwidthnumbers*thatwereobtainedwithinquery_planner().*/final_target=create_pathtarget(root,tlist);final_target_parallel_safe=is_parallel_safe(root,(Node*)final_target->exprs);/**IfORDERBYwasgiven,considerwhetherweshoulduseapost-sort*projection,andcomputetheadjustedtargetforprecedingstepsif*so.*/if(parse->sortClause){sort_input_target=make_sort_input_target(root,final_target,&have_postponed_srfs);sort_input_target_parallel_safe=is_parallel_safe(root,(Node*)sort_input_target->exprs);}else{sort_input_target=final_target;sort_input_target_parallel_safe=final_target_parallel_safe;}/**Ifwehavewindowfunctionstodealwith,theoutputfromany*groupingstepneedstobewhatthewindowfunctionswant;*otherwise,itshouldbesort_input_target.*/if(activeWindows){grouping_target=make_window_input_target(root,final_target,activeWindows);grouping_target_parallel_safe=is_parallel_safe(root,(Node*)grouping_target->exprs);}else{grouping_target=sort_input_target;grouping_target_parallel_safe=sort_input_target_parallel_safe;}/**Ifwehavegroupingoraggregationtodo,thetopmostscan/join*plannodemustemitwhatthegroupingstepwants;otherwise,it*shouldemitgrouping_target.*/have_grouping=(parse->groupClause||parse->groupingSets||parse->hasAggs||root->hasHavingQual);if(have_grouping){scanjoin_target=make_group_input_target(root,final_target);scanjoin_target_parallel_safe=is_parallel_safe(root,(Node*)grouping_target->exprs);}else{scanjoin_target=grouping_target;scanjoin_target_parallel_safe=grouping_target_parallel_safe;}/**IfthereareanySRFsinthetargetlist,wemustseparateeachof*thesePathTargetsintoSRF-computingandSRF-freetargets.Replace*eachofthenamedtargetswithaSRF-freeversion,andrememberthe*listofadditionalprojectionstepsweneedtoaddafterwards.*/if(parse->hasTargetSRFs){/*final_targetdoesn'trecomputeanySRFsinsort_input_target*/split_pathtarget_at_srfs(root,final_target,sort_input_target,&final_targets,&final_targets_contain_srfs);final_target=linitial_node(PathTarget,final_targets);Assert(!linitial_int(final_targets_contain_srfs));/*likewiseforsort_input_targetvs.grouping_target*/split_pathtarget_at_srfs(root,sort_input_target,grouping_target,&sort_input_targets,&sort_input_targets_contain_srfs);sort_input_target=linitial_node(PathTarget,sort_input_targets);Assert(!linitial_int(sort_input_targets_contain_srfs));/*likewiseforgrouping_targetvs.scanjoin_target*/split_pathtarget_at_srfs(root,grouping_target,scanjoin_target,&grouping_targets,&grouping_targets_contain_srfs);grouping_target=linitial_node(PathTarget,grouping_targets);Assert(!linitial_int(grouping_targets_contain_srfs));/*scanjoin_targetwillnothaveanySRFsprecomputedforit*/split_pathtarget_at_srfs(root,scanjoin_target,NULL,&scanjoin_targets,&scanjoin_targets_contain_srfs);scanjoin_target=linitial_node(PathTarget,scanjoin_targets);Assert(!linitial_int(scanjoin_targets_contain_srfs));}else{/*initializelists;formostofthese,dummyvaluesareOK*/final_targets=final_targets_contain_srfs=NIL;sort_input_targets=sort_input_targets_contain_srfs=NIL;grouping_targets=grouping_targets_contain_srfs=NIL;scanjoin_targets=list_make1(scanjoin_target);scanjoin_targets_contain_srfs=NIL;}/*Applyscan/jointarget.*/scanjoin_target_same_exprs=list_length(scanjoin_targets)==1&&equal(scanjoin_target->exprs,current_rel->reltarget->exprs);apply_scanjoin_target_to_paths(root,current_rel,scanjoin_targets,scanjoin_targets_contain_srfs,scanjoin_target_parallel_safe,scanjoin_target_same_exprs);/**Savethevariousupper-relPathTargetswejustcomputedinto*root->upper_targets[].Thecorecodedoesn'tusethis,butit*providesaconvenientplaceforextensionstogetattheinfo.For*consistency,wesavealltheintermediatetargets,eventhoughsome*ofthecorrespondingupperrelsmightnotbeneededforthisquery.*/root->upper_targets[UPPERREL_FINAL]=final_target;root->upper_targets[UPPERREL_WINDOW]=sort_input_target;root->upper_targets[UPPERREL_GROUP_AGG]=grouping_target;/**Ifwehavegroupingand/oraggregation,considerwaystoimplement*that.Webuildanewupperrelrepresentingtheoutputofthis*phase.*/if(have_grouping){current_rel=create_grouping_paths(root,current_rel,grouping_target,grouping_target_parallel_safe,&agg_costs,gset_data);/*Fixthingsupifgrouping_targetcontainsSRFs*/if(parse->hasTargetSRFs)adjust_paths_for_srfs(root,current_rel,grouping_targets,grouping_targets_contain_srfs);}/**Ifwehavewindowfunctions,considerwaystoimplementthose.We*buildanewupperrelrepresentingtheoutputofthisphase.*/if(activeWindows){current_rel=create_window_paths(root,current_rel,grouping_target,sort_input_target,sort_input_target_parallel_safe,tlist,wflists,activeWindows);/*Fixthingsupifsort_input_targetcontainsSRFs*/if(parse->hasTargetSRFs)adjust_paths_for_srfs(root,current_rel,sort_input_targets,sort_input_targets_contain_srfs);}/**IfthereisaDISTINCTclause,considerwaystoimplementthat.We*buildanewupperrelrepresentingtheoutputofthisphase.*/if(parse->distinctClause){current_rel=create_distinct_paths(root,current_rel);}}/*endofif(setOperations)*//**IfORDERBYwasgiven,considerwaystoimplementthat,andgeneratea*newupperrelcontainingonlypathsthatemitthecorrectorderingand*projectthecorrectfinal_target.Wecanapplytheoriginal*limit_tupleslimitinsortcostinghere,butonlyifthereareno*postponedSRFs.*/if(parse->sortClause){current_rel=create_ordered_paths(root,current_rel,final_target,final_target_parallel_safe,have_postponed_srfs?-1.0:limit_tuples);/*Fixthingsupiffinal_targetcontainsSRFs*/if(parse->hasTargetSRFs)adjust_paths_for_srfs(root,current_rel,final_targets,final_targets_contain_srfs);}/**Nowwearepreparedtobuildthefinal-outputupperrel.*/final_rel=fetch_upper_rel(root,UPPERREL_FINAL,NULL);/**Iftheinputrelismarkedconsider_parallelandthere'snothingthat's*notparallel-safeintheLIMITclause,thenthefinal_relcanbemarked*consider_parallelaswell.NotethatifthequeryhasrowMarksoris*notaSELECT,consider_parallelwillbefalseforeveryrelationinthe*query.*/if(current_rel->consider_parallel&&is_parallel_safe(root,parse->limitOffset)&&is_parallel_safe(root,parse->limitCount))final_rel->consider_parallel=true;/**Ifthecurrent_relbelongstoasingleFDW,sodoesthefinal_rel.*/final_rel->serverid=current_rel->serverid;final_rel->userid=current_rel->userid;final_rel->useridiscurrent=current_rel->useridiscurrent;final_rel->fdwroutine=current_rel->fdwroutine;/**Generatepathsforthefinal_rel.Insertallsurvivingpaths,with*LockRows,Limit,and/orModifyTablestepsaddedifneeded.*/foreach(lc,current_rel->pathlist){Path*path=(Path*)lfirst(lc);/**IfthereisaFOR[KEY]UPDATE/SHAREclause,addtheLockRowsnode.*(Note:weintentionallytestparse->rowMarksnotroot->rowMarks*here.Ifthereareonlynon-lockingrowmarks,theyshouldbe*handledbytheModifyTablenodeinstead.However,root->rowMarks*iswhatgoesintotheLockRowsnode.)*/if(parse->rowMarks){path=(Path*)create_lockrows_path(root,final_rel,path,root->rowMarks,SS_assign_special_param(root));}/**IfthereisaLIMIT/OFFSETclause,addtheLIMITnode.*/if(limit_needed(parse)){path=(Path*)create_limit_path(root,final_rel,path,parse->limitOffset,parse->limitCount,offset_est,count_est);}/**IfthisisanINSERT/UPDATE/DELETE,andwe'renotbeingcalledfrom*inheritance_planner,addtheModifyTablenode.*/if(parse->commandType!=CMD_SELECT&&!inheritance_update){List*withCheckOptionLists;List*returningLists;List*rowMarks;/**SetuptheWITHCHECKOPTIONandRETURNINGlists-of-lists,if*needed.*/if(parse->withCheckOptions)withCheckOptionLists=list_make1(parse->withCheckOptions);elsewithCheckOptionLists=NIL;if(parse->returningList)returningLists=list_make1(parse->returningList);elsereturningLists=NIL;/**IftherewasaFOR[KEY]UPDATE/SHAREclause,theLockRowsnode*willhavedealtwithfetchingnon-lockedmarkedrows,elsewe*needtohaveModifyTabledothat.*/if(parse->rowMarks)rowMarks=NIL;elserowMarks=root->rowMarks;path=(Path*)create_modifytable_path(root,final_rel,parse->commandType,parse->canSetTag,parse->resultRelation,NIL,false,list_make1_int(parse->resultRelation),list_make1(path),list_make1(root),withCheckOptionLists,returningLists,rowMarks,parse->onConflict,SS_assign_special_param(root));}/*Andshoveitintofinal_rel*/add_path(final_rel,path);}/**Generatepartialpathsforfinal_rel,too,ifouterquerylevelsmight*beabletomakeuseofthem.*/if(final_rel->consider_parallel&&root->query_level>1&&!limit_needed(parse)){Assert(!parse->rowMarks&&parse->commandType==CMD_SELECT);foreach(lc,current_rel->partial_pathlist){Path*partial_path=(Path*)lfirst(lc);add_partial_path(final_rel,partial_path);}}/**IfthereisanFDWthat'sresponsibleforallbaserelsofthequery,*letitconsideraddingForeignPaths.*/if(final_rel->fdwroutine&&final_rel->fdwroutine->GetForeignUpperPaths)final_rel->fdwroutine->GetForeignUpperPaths(root,UPPERREL_FINAL,current_rel,final_rel,NULL);/*Letextensionspossiblyaddsomemorepaths*/if(create_upper_paths_hook)(*create_upper_paths_hook)(root,UPPERREL_FINAL,current_rel,final_rel,NULL);/*Note:currently,weleaveittocallerstodoset_cheapest()*/}/**query_planner*Generateapath(thatis,asimplifiedplan)forabasicquery,*whichmayinvolvejoinsbutnotanyfancierfeatures.**Sincequery_plannerdoesnothandlethetoplevelprocessing(grouping,*sorting,etc)itcannotselectthebestpathbyitself.Instead,it*returnstheRelOptInfoforthetoplevelofjoining,andthecaller*(grouping_planner)canchooseamongthesurvivingpathsfortherel.**rootdescribesthequerytoplan*tlististhetargetlistthequeryshouldproduce*(thisisNOTnecessarilyroot->parse->targetList!)*qp_callbackisafunctiontocomputequery_pathkeysonceit'ssafetodoso*qp_extraisoptionalextradatatopasstoqp_callback**Note:thePlannerInfonodealsoincludesaquery_pathkeysfield,which*tellsquery_plannerthesortorderthatisdesiredinthefinaloutput*plan.Thisvalueis*not*availableatcalltime,butiscomputedby*qp_callbackoncewehavecompletedmergingthequery'sequivalenceclasses.*(Wecannotconstructcanonicalpathkeysuntilthat'sdone.)*/RelOptInfo*query_planner(PlannerInfo*root,List*tlist,query_pathkeys_callbackqp_callback,void*qp_extra){Query*parse=root->parse;List*joinlist;RelOptInfo*final_rel;Indexrti;doubletotal_pages;/**Ifthequeryhasanemptyjointree,thenit'ssomethingeasylike*"SELECT2+2;"or"INSERT...VALUES()".Fallthroughquickly.*/if(parse->jointree->fromlist==NIL){/*Weneedadummyjoinreltodescribetheemptysetofbaserels*/final_rel=build_empty_join_rel(root);/**Ifqueryallowsparallelismingeneral,checkwhetherthequalsare*parallel-restricted.(Weneednotcheckfinal_rel->reltarget*becauseit'semptyatthispoint.Anythingparallel-restrictedin*thequerytlistwillbedealtwithlater.)*/if(root->glob->parallelModeOK)final_rel->consider_parallel=is_parallel_safe(root,parse->jointree->quals);/*TheonlypathforitisatrivialResultpath*/add_path(final_rel,(Path*)create_result_path(root,final_rel,final_rel->reltarget,(List*)parse->jointree->quals));/*Selectcheapestpath(prettyeasyinthiscase...)*/set_cheapest(final_rel);/**Westillarerequiredtocallqp_callback,incaseit'ssomething*like"SELECT2+2ORDERBY1".*/root->canon_pathkeys=NIL;(*qp_callback)(root,qp_extra);returnfinal_rel;}/**create_modifytable_path*CreatesapathnodethatrepresentsperformingINSERT/UPDATE/DELETEmods**'rel'istheparentrelationassociatedwiththeresult*'operation'istheoperationtype*'canSetTag'istrueifwesetthecommandtag/es_processed*'nominalRelation'istheparentRTindexforuseofEXPLAIN*'partitioned_rels'isanintegerlistofRTindexesofnon-leaftablesin*thepartitiontree,ifthisisanUPDATE/DELETEtoapartitionedtable.*OtherwiseNIL.*'partColsUpdated'istrueifanypartitioningcolumnsarebeingupdated,*eitherfromthetargetrelationoradescendentpartitionedtable.*'resultRelations'isanintegerlistofactualRTindexesoftargetrel(s)*'subpaths'isalistofPath(s)producingsourcedata(oneperrel)*'subroots'isalistofPlannerInfostructs(oneperrel)*'withCheckOptionLists'isalistofWCOlists(oneperrel)*'returningLists'isalistofRETURNINGtlists(oneperrel)*'rowMarks'isalistofPlanRowMarks(non-lockingonly)*'onconflict'istheONCONFLICTclause,orNULL*'epqParam'istheIDofParamforEvalPlanQualre-eval*/ModifyTablePath*create_modifytable_path(PlannerInfo*root,RelOptInfo*rel,CmdTypeoperation,boolcanSetTag,IndexnominalRelation,List*partitioned_rels,boolpartColsUpdated,List*resultRelations,List*subpaths,List*subroots,List*withCheckOptionLists,List*returningLists,List*rowMarks,OnConflictExpr*onconflict,intepqParam){ModifyTablePath*pathnode=makeNode(ModifyTablePath);doubletotal_size;ListCell*lc;Assert(list_length(resultRelations)==list_length(subpaths));Assert(list_length(resultRelations)==list_length(subroots));Assert(withCheckOptionLists==NIL||list_length(resultRelations)==list_length(withCheckOptionLists));Assert(returningLists==NIL||list_length(resultRelations)==list_length(returningLists));pathnode->path.pathtype=T_ModifyTable;pathnode->path.parent=rel;/*pathtargetisnotinteresting,justmakeitminimallyvalid*/pathnode->path.pathtarget=rel->reltarget;/*Fornow,assumeweareaboveanyjoins,sonoparameterization*/pathnode->path.param_info=NULL;pathnode->path.parallel_aware=false;pathnode->path.parallel_safe=false;pathnode->path.parallel_workers=0;pathnode->path.pathkeys=NIL;/**Computecost&rowcountassumofsubpathcosts&rowcounts.**Currently,wedon'tchargeanythingextrafortheactualtable*modificationwork,norfortheWITHCHECKOPTIONSorRETURNING*expressionsifany.Itwouldonlybewindowdressing,since*ModifyTableisalwaysatop-levelnodeandthereisnowayforthe*coststochangeanyhigher-levelplanningchoices.Butwemightwant*tomakeitlookbettersometime.*/pathnode->path.startup_cost=0;pathnode->path.total_cost=0;pathnode->path.rows=0;total_size=0;foreach(lc,subpaths){Path*subpath=(Path*)lfirst(lc);if(lc==list_head(subpaths))/*firstnode?*/pathnode->path.startup_cost=subpath->startup_cost;pathnode->path.total_cost+=subpath->total_cost;pathnode->path.rows+=subpath->rows;total_size+=subpath->pathtarget->width*subpath->rows;}/**Setwidthtotheaveragewidthofthesubpathoutputs.XXXthisis*totallywrong:weshouldreportzeroifnoRETURNING,elseanaverage*oftheRETURNINGtlistwidths.Butit'swhathappenedhistorically,*andimprovingitisataskforanotherday.*/if(pathnode->path.rows>0)total_size/=pathnode->path.rows;pathnode->path.pathtarget->width=rint(total_size);pathnode->operation=operation;pathnode->canSetTag=canSetTag;pathnode->nominalRelation=nominalRelation;pathnode->partitioned_rels=list_copy(partitioned_rels);pathnode->partColsUpdated=partColsUpdated;pathnode->resultRelations=resultRelations;pathnode->subpaths=subpaths;pathnode->subroots=subroots;pathnode->withCheckOptionLists=withCheckOptionLists;pathnode->returningLists=returningLists;pathnode->rowMarks=rowMarks;pathnode->onconflict=onconflict;pathnode->epqParam=epqParam;returnpathnode;}
2、subquery_planner
/*--------------------*subquery_planner*Invokestheplanneronasubquery.Werecursetohereforeach*sub-SELECTfoundinthequerytree.**globistheglobalstateforthecurrentplannerrun.*parseisthequerytreeproducedbytheparser&rewriter.*parent_rootistheimmediateparentQuery'sinfo(NULLatthetoplevel).*hasRecursionistrueifthisisarecursiveWITHquery.*tuple_fractionisthefractionoftuplesweexpectwillberetrieved.*tuple_fractionisinterpretedasexplainedforgrouping_planner,below.**Basically,thisroutinedoesthestuffthatshouldonlybedoneonce*perQueryobject.Itthencallsgrouping_planner.Atonetime,*grouping_plannercouldbeinvokedrecursivelyonthesameQueryobject;*that'snotcurrentlytrue,butwekeeptheseparationbetweenthetwo*routinesanyway,incaseweneeditagainsomeday.**subquery_plannerwillbecalledrecursivelytohandlesub-Querynodes*foundwithinthequery'sexpressionsandrangetable.**ReturnsthePlannerInfostruct("root")thatcontainsalldatagenerated*whileplanningthesubquery.Inparticular,thePath(s)attachedto*the(UPPERREL_FINAL,NULL)upperrelrepresentourconclusionsaboutthe*cheapestway(s)toimplementthequery.Thetoplevelwillselectthe*bestPathandpassitthroughcreateplan.ctoproduceafinishedPlan.*--------------------*//*输入:glob-PlannerGlobalparse-Query结构体指针parent_root-父PlannerInfoRoot节点hasRecursion-是否递归?tuple_fraction-扫描Tuple比例输出:PlannerInfo指针*/PlannerInfo*subquery_planner(PlannerGlobal*glob,Query*parse,PlannerInfo*parent_root,boolhasRecursion,doubletuple_fraction){PlannerInfo*root;//返回值List*newWithCheckOptions;//List*newHaving;//Having子句boolhasOuterJoins;//是否存在OuterJoin?RelOptInfo*final_rel;//ListCell*l;//临时变量/*CreateaPlannerInfodatastructureforthissubquery*/root=makeNode(PlannerInfo);//构造返回值root->parse=parse;root->glob=glob;root->query_level=parent_root?parent_root->query_level+1:1;root->parent_root=parent_root;root->plan_params=NIL;root->outer_params=NULL;root->planner_cxt=CurrentMemoryContext;root->init_plans=NIL;root->cte_plan_ids=NIL;root->multiexpr_params=NIL;root->eq_classes=NIL;root->append_rel_list=NIL;root->rowMarks=NIL;memset(root->upper_rels,0,sizeof(root->upper_rels));memset(root->upper_targets,0,sizeof(root->upper_targets));root->processed_tlist=NIL;root->grouping_map=NULL;root->minmax_aggs=NIL;root->qual_security_level=0;root->inhTargetKind=INHKIND_NONE;root->hasRecursion=hasRecursion;if(hasRecursion)root->wt_param_id=SS_assign_special_param(root);elseroot->wt_param_id=-1;root->non_recursive_path=NULL;root->partColsUpdated=false;/**IfthereisaWITHlist,processeachWITHqueryandbuildaninitplan*SubPlanstructureforit.*/if(parse->cteList)SS_process_ctes(root);//With语句/**LookforANYandEXISTSSubLinksinWHEREandJOIN/ONclauses,andtry*totransformthemintojoins.Notethatthisstepdoesnotdescend*intosubqueries;ifwepullupanysubqueriesbelow,theirSubLinksare*processedjustbeforepullingthemup.*/if(parse->hasSubLinks)pull_up_sublinks(root);//转换ANY/EXISTS为JOIN/**Scantherangetableforset-returningfunctions,andinlinethemif*possible(producingsubqueriesthatmightgetpulledupnext).*RecursionissuesherearehandledinthesamewayasforSubLinks.*/inline_set_returning_functions(root);/**Checktoseeifanysubqueriesinthejointreecanbemergedintothis*query.*/pull_up_subqueries(root);///**IfthisisasimpleUNIONALLquery,flattenitintoanappendrel.We*dothisnowbecauseitrequiresapplyingpull_up_subqueriestotheleaf*queriesoftheUNIONALL,whichweren'ttouchedabovebecausethey*weren'treferencedbythejointree(theywillbeafterwedothis).*/if(parse->setOperations)flatten_simple_union_all(root);/**DetectwhetheranyrangetableentriesareRTE_JOINkind;ifnot,wecan*avoidtheexpenseofdoingflatten_join_alias_vars().Alsocheckfor*outerjoins---ifnone,wecanskipreduce_outer_joins().Andcheck*forLATERALRTEs,too.Thismustbedoneafterwehavedone*pull_up_subqueries(),ofcourse.*/root->hasJoinRTEs=false;root->hasLateralRTEs=false;hasOuterJoins=false;foreach(l,parse->rtable){RangeTblEntry*rte=lfirst_node(RangeTblEntry,l);if(rte->rtekind==RTE_JOIN){root->hasJoinRTEs=true;if(IS_OUTER_JOIN(rte->jointype))hasOuterJoins=true;}if(rte->lateral)root->hasLateralRTEs=true;}/**PreprocessRowMarkinformation.Weneedtodothisaftersubquery*pullup(sothatallnon-inheritedRTEsarepresent)andbefore*inheritanceexpansion(sothattheinfoisavailablefor*expand_inherited_tablestoexamineandmodify).*/preprocess_rowmarks(root);/**Expandanyrangetableentriesthatareinheritancesetsinto"append*relations".Thiscanaddentriestotherangetable,buttheymustbe*plainbaserelationsnotjoins,soit'sOK(andmarginallymore*efficient)todoitaftercheckingforjoinRTEs.Wemustdoitafter*pullingupsubqueries,elsewe'dfailtohandleinheritedtablesin*subqueries.*/expand_inherited_tables(root);/**SethasHavingQualtorememberifHAVINGclauseispresent.Needed*becausepreprocess_expressionwillreduceaconstant-trueconditionto*anemptyquallist...but"HAVINGTRUE"isnotasemanticno-op.*/root->hasHavingQual=(parse->havingQual!=NULL);/*Clearthisflag;mightgetsetindistribute_qual_to_rels*/root->hasPseudoConstantQuals=false;/**Doexpressionpreprocessingontargetlistandquals,aswellasother*randomexpressionsinthequerytree.Notethatwedonotneedto*handlesort/groupexpressionsexplicitly,becausetheyareactually*partofthetargetlist.*/parse->targetList=(List*)preprocess_expression(root,(Node*)parse->targetList,EXPRKIND_TARGET);/*Constant-foldingmighthaveremovedallset-returningfunctions*/if(parse->hasTargetSRFs)parse->hasTargetSRFs=expression_returns_set((Node*)parse->targetList);newWithCheckOptions=NIL;foreach(l,parse->withCheckOptions){WithCheckOption*wco=lfirst_node(WithCheckOption,l);wco->qual=preprocess_expression(root,wco->qual,EXPRKIND_QUAL);if(wco->qual!=NULL)newWithCheckOptions=lappend(newWithCheckOptions,wco);}parse->withCheckOptions=newWithCheckOptions;parse->returningList=(List*)preprocess_expression(root,(Node*)parse->returningList,EXPRKIND_TARGET);preprocess_qual_conditions(root,(Node*)parse->jointree);parse->havingQual=preprocess_expression(root,parse->havingQual,EXPRKIND_QUAL);foreach(l,parse->windowClause){WindowClause*wc=lfirst_node(WindowClause,l);/*partitionClause/orderClausearesort/groupexpressions*/wc->startOffset=preprocess_expression(root,wc->startOffset,EXPRKIND_LIMIT);wc->endOffset=preprocess_expression(root,wc->endOffset,EXPRKIND_LIMIT);}parse->limitOffset=preprocess_expression(root,parse->limitOffset,EXPRKIND_LIMIT);parse->limitCount=preprocess_expression(root,parse->limitCount,EXPRKIND_LIMIT);if(parse->onConflict){parse->onConflict->arbiterElems=(List*)preprocess_expression(root,(Node*)parse->onConflict->arbiterElems,EXPRKIND_ARBITER_ELEM);parse->onConflict->arbiterWhere=preprocess_expression(root,parse->onConflict->arbiterWhere,EXPRKIND_QUAL);parse->onConflict->onConflictSet=(List*)preprocess_expression(root,(Node*)parse->onConflict->onConflictSet,EXPRKIND_TARGET);parse->onConflict->onConflictWhere=preprocess_expression(root,parse->onConflict->onConflictWhere,EXPRKIND_QUAL);/*exclRelTlistcontainsonlyVars,sonopreprocessingneeded*/}root->append_rel_list=(List*)preprocess_expression(root,(Node*)root->append_rel_list,EXPRKIND_APPINFO);/*AlsoneedtopreprocessexpressionswithinRTEs*/foreach(l,parse->rtable){RangeTblEntry*rte=lfirst_node(RangeTblEntry,l);intkind;ListCell*lcsq;if(rte->rtekind==RTE_RELATION){if(rte->tablesample)rte->tablesample=(TableSampleClause*)preprocess_expression(root,(Node*)rte->tablesample,EXPRKIND_TABLESAMPLE);}elseif(rte->rtekind==RTE_SUBQUERY){/**Wedon'twanttodoallpreprocessingyetonthesubquery's*expressions,sincethatwillhappenwhenweplanit.Butifit*containsanyjoinaliasesofourlevel,thosehavetoget*expandednow,becauseplanningofthesubquerywon'tdoit.*That'sonlypossibleifthesubqueryisLATERAL.*/if(rte->lateral&&root->hasJoinRTEs)rte->subquery=(Query*)flatten_join_alias_vars(root,(Node*)rte->subquery);}elseif(rte->rtekind==RTE_FUNCTION){/*Preprocessthefunctionexpression(s)fully*/kind=rte->lateral?EXPRKIND_RTFUNC_LATERAL:EXPRKIND_RTFUNC;rte->functions=(List*)preprocess_expression(root,(Node*)rte->functions,kind);}elseif(rte->rtekind==RTE_TABLEFUNC){/*Preprocessthefunctionexpression(s)fully*/kind=rte->lateral?EXPRKIND_TABLEFUNC_LATERAL:EXPRKIND_TABLEFUNC;rte->tablefunc=(TableFunc*)preprocess_expression(root,(Node*)rte->tablefunc,kind);}elseif(rte->rtekind==RTE_VALUES){/*Preprocessthevalueslistsfully*/kind=rte->lateral?EXPRKIND_VALUES_LATERAL:EXPRKIND_VALUES;rte->values_lists=(List*)preprocess_expression(root,(Node*)rte->values_lists,kind);}/**ProcesseachelementofthesecurityQualslistasifitwerea*separatequalexpression(asindeeditis).Weneedtodoitthis*waytogetpropercanonicalizationofAND/ORstructure.Notethat*thisconvertseachelementintoanimplicit-ANDsublist.*/foreach(lcsq,rte->securityQuals){lfirst(lcsq)=preprocess_expression(root,(Node*)lfirst(lcsq),EXPRKIND_QUAL);}}/**Nowthatwearedonepreprocessingexpressions,andinparticulardone*flatteningjoinaliasvariables,getridofthejoinaliasvarslists.*Theynolongermatchwhatexpressionsintherestofthetreelook*like,becausewehavenotpreprocessedexpressionsinthoselists(and*donotwantto;forexample,expandingaSubLinktherewouldresultin*auselessunreferencedsubplan).Leavingtheminplacesimplycreates*ahazardforlaterscansofthetree.Wecouldtrytopreventthatby*usingQTW_IGNORE_JOINALIASESineverytreescandoneafterthispoint,*butthatdoesn'tsoundveryreliable.*/if(root->hasJoinRTEs){foreach(l,parse->rtable){RangeTblEntry*rte=lfirst_node(RangeTblEntry,l);rte->joinaliasvars=NIL;}}/**InsomecaseswemaywanttotransferaHAVINGclauseintoWHERE.We*cannotdosoiftheHAVINGclausecontainsaggregates(obviously)or*volatilefunctions(sinceaHAVINGclauseissupposedtobeexecuted*onlyoncepergroup).Wealsocan'tdothisifthereareanynonempty*groupingsets;movingsuchaclauseintoWHEREwouldpotentiallychange*theresults,ifanyreferencedcolumnisn'tpresentinallthegrouping*sets.(Ifthereareonlyemptygroupingsets,thentheHAVINGclause*mustbedegenerateasdiscussedbelow.)**Also,itmaybethattheclauseissoexpensivetoexecutethatwe're*betteroffdoingitonlyoncepergroup,despitethelossof*selectivity.Thisishardtoestimateshortofdoingtheentire*planningprocesstwice,soweuseaheuristic:clausescontaining*subplansareleftinHAVING.Otherwise,wemoveorcopytheHAVING*clauseintoWHERE,inhopesofeliminatingtuplesbeforeaggregation*insteadofafter.**Ifthequeryhasexplicitgroupingthenwecansimplymovesucha*clauseintoWHERE;anygroupthatfailstheclausewillnotbeinthe*outputbecausenoneofitstupleswillreachthegroupingor*aggregationstage.Otherwisewemusthaveadegenerate(variable-free)*HAVINGclause,whichweputinWHEREsothatquery_planner()canuseit*inagatingResultnode,butalsokeepinHAVINGtoensurethatwe*don'temitabogusaggregatedrow.(Thiscouldbedonebetter,butit*seemsnotworthoptimizing.)**NotethatbothhavingQualandparse->jointree->qualsarein*implicitly-ANDed-listformatthispoint,eventhoughtheyaredeclared*asNode*.*/newHaving=NIL;foreach(l,(List*)parse->havingQual){Node*havingclause=(Node*)lfirst(l);if((parse->groupClause&&parse->groupingSets)||contain_agg_clause(havingclause)||contain_volatile_functions(havingclause)||contain_subplans(havingclause)){/*keepitinHAVING*/newHaving=lappend(newHaving,havingclause);}elseif(parse->groupClause&&!parse->groupingSets){/*moveittoWHERE*/parse->jointree->quals=(Node*)lappend((List*)parse->jointree->quals,havingclause);}else{/*putacopyinWHERE,keepitinHAVING*/parse->jointree->quals=(Node*)lappend((List*)parse->jointree->quals,copyObject(havingclause));newHaving=lappend(newHaving,havingclause);}}parse->havingQual=(Node*)newHaving;/*RemoveanyredundantGROUPBYcolumns*/remove_useless_groupby_columns(root);/**Ifwehaveanyouterjoins,trytoreducethemtoplaininnerjoins.*Thisstepismosteasilydoneafterwe'vedoneexpression*preprocessing.*/if(hasOuterJoins)reduce_outer_joins(root);/**Dothemainplanning.Ifwehaveaninheritedtargetrelation,that*needsspecialprocessing,elsegostraighttogrouping_planner.*/if(parse->resultRelation&&rt_fetch(parse->resultRelation,parse->rtable)->inh)inheritance_planner(root);elsegrouping_planner(root,false,tuple_fraction);/**Capturethesetofouter-levelparamIDswehaveaccessto,forusein*extParam/allParamcalculationslater.*/SS_identify_outer_params(root);/**IfanyinitPlanswerecreatedinthisquerylevel,adjustthesurviving*Paths'costsandparallel-safetyflagstoaccountforthem.The*initPlanswon'tactuallygetattachedtotheplantreetill*create_plan()runs,butwemustincludetheireffectsnow.*/final_rel=fetch_upper_rel(root,UPPERREL_FINAL,NULL);SS_charge_for_initplans(root,final_rel);/**Makesurewe'veidentifiedthecheapestPathforthefinalrel.(By*doingthisherenotingrouping_planner,weincludeinitPlancostsin*thedecision,thoughit'sunlikelythatwillchangeanything.)*/set_cheapest(final_rel);returnroot;}
3.create_plan
/**create_plan*Createstheaccessplanforaquerybyrecursivelyprocessingthe*desiredtreeofpathnodes,startingatthenode'best_path'.For*everypathnodefound,wecreateacorrespondingplannodecontaining*appropriateid,targetlist,andqualificationinformation.**Thetlistsandqualsintheplantreearestillinplannerformat,*ie,Varsstillcorrespondtotheparser'snumbering.Thiswillbe*fixedlaterbysetrefs.c.**best_pathisthebestaccesspath**ReturnsaPlantree.*/Plan*create_plan(PlannerInfo*root,Path*best_path){Plan*plan;/*plan_paramsshouldnotbeinuseincurrentquerylevel*/Assert(root->plan_params==NIL);/*Initializethismodule'sprivateworkspaceinPlannerInfo*/root->curOuterRels=NULL;root->curOuterParams=NIL;/*Recursivelyprocessthepathtree,demandingthecorrecttlistresult*/plan=create_plan_recurse(root,best_path,CP_EXACT_TLIST);/**Makesurethetopmostplannode'stargetlistexposestheoriginal*columnnamesandotherdecorativeinfo.Targetlistsgeneratedwithin*theplannerdon'tbotherwiththatstuff,butwemusthaveitonthe*top-leveltlistseenatexecutiontime.However,ModifyTableplan*nodesdon'thaveatlistmatchingthequerytreetargetlist.*/if(!IsA(plan,ModifyTable))apply_tlist_labeling(plan->targetlist,root->processed_tlist);/**AttachanyinitPlanscreatedinthisqueryleveltothetopmostplan*node.(Inprincipletheinitplanscouldgoinanyplannodeator*abovewherethey'rereferenced,butthereseemsnoreasontoputthem*anylowerthanthetopmostnodeforthequerylevel.Also,see*commentsforSS_finalize_planbeforeyoutrytochangethis.)*/SS_attach_initplans(root,plan);/*CheckwesuccessfullyassignedallNestLoopParamstoplannodes*/if(root->curOuterParams!=NIL)elog(ERROR,"failedtoassignallNestLoopParamstoplannodes");/**Resetplan_paramstoensureparamIDsusedfornestloopparamsarenot*re-usedlater*/root->plan_params=NIL;returnplan;}/**create_plan_recurse*Recursivegutsofcreate_plan().*/staticPlan*create_plan_recurse(PlannerInfo*root,Path*best_path,intflags){Plan*plan;/*Guardagainststackoverflowduetooverlycomplexplans*/check_stack_depth();switch(best_path->pathtype){caseT_SeqScan:caseT_SampleScan:caseT_IndexScan:caseT_IndexOnlyScan:caseT_BitmapHeapScan:caseT_TidScan:caseT_SubqueryScan:caseT_FunctionScan:caseT_TableFuncScan:caseT_ValuesScan:caseT_CteScan:caseT_WorkTableScan:caseT_NamedTuplestoreScan:caseT_ForeignScan:caseT_CustomScan:plan=create_scan_plan(root,best_path,flags);break;caseT_HashJoin:caseT_MergeJoin:caseT_NestLoop:plan=create_join_plan(root,(JoinPath*)best_path);break;caseT_Append:plan=create_append_plan(root,(AppendPath*)best_path);break;caseT_MergeAppend:plan=create_merge_append_plan(root,(MergeAppendPath*)best_path);break;caseT_Result:if(IsA(best_path,ProjectionPath)){plan=create_projection_plan(root,(ProjectionPath*)best_path,flags);}elseif(IsA(best_path,MinMaxAggPath)){plan=(Plan*)create_minmaxagg_plan(root,(MinMaxAggPath*)best_path);}else{Assert(IsA(best_path,ResultPath));plan=(Plan*)create_result_plan(root,(ResultPath*)best_path);}break;caseT_ProjectSet:plan=(Plan*)create_project_set_plan(root,(ProjectSetPath*)best_path);break;caseT_Material:plan=(Plan*)create_material_plan(root,(MaterialPath*)best_path,flags);break;caseT_Unique:if(IsA(best_path,UpperUniquePath)){plan=(Plan*)create_upper_unique_plan(root,(UpperUniquePath*)best_path,flags);}else{Assert(IsA(best_path,UniquePath));plan=create_unique_plan(root,(UniquePath*)best_path,flags);}break;caseT_Gather:plan=(Plan*)create_gather_plan(root,(GatherPath*)best_path);break;caseT_Sort:plan=(Plan*)create_sort_plan(root,(SortPath*)best_path,flags);break;caseT_Group:plan=(Plan*)create_group_plan(root,(GroupPath*)best_path);break;caseT_Agg:if(IsA(best_path,GroupingSetsPath))plan=create_groupingsets_plan(root,(GroupingSetsPath*)best_path);else{Assert(IsA(best_path,AggPath));plan=(Plan*)create_agg_plan(root,(AggPath*)best_path);}break;caseT_WindowAgg:plan=(Plan*)create_windowagg_plan(root,(WindowAggPath*)best_path);break;caseT_SetOp:plan=(Plan*)create_setop_plan(root,(SetOpPath*)best_path,flags);break;caseT_RecursiveUnion:plan=(Plan*)create_recursiveunion_plan(root,(RecursiveUnionPath*)best_path);break;caseT_LockRows:plan=(Plan*)create_lockrows_plan(root,(LockRowsPath*)best_path,flags);break;caseT_ModifyTable:plan=(Plan*)create_modifytable_plan(root,(ModifyTablePath*)best_path);break;caseT_Limit:plan=(Plan*)create_limit_plan(root,(LimitPath*)best_path,flags);break;caseT_GatherMerge:plan=(Plan*)create_gather_merge_plan(root,(GatherMergePath*)best_path);break;default:elog(ERROR,"unrecognizednodetype:%d",(int)best_path->pathtype);plan=NULL;/*keepcompilerquiet*/break;}returnplan;}/**create_modifytable_plan*CreateaModifyTableplanfor'best_path'.**ReturnsaPlannode.*/staticModifyTable*create_modifytable_plan(PlannerInfo*root,ModifyTablePath*best_path){ModifyTable*plan;List*subplans=NIL;ListCell*subpaths,*subroots;/*Buildtheplanforeachinputpath*/forboth(subpaths,best_path->subpaths,subroots,best_path->subroots){Path*subpath=(Path*)lfirst(subpaths);PlannerInfo*subroot=(PlannerInfo*)lfirst(subroots);Plan*subplan;/**InaninheritedUPDATE/DELETE,referencetheper-childmodified*subrootwhilecreatingPlansfromPathsforthechildrel.Thisis*akluge,butotherwiseit'stoohardtoensurethatPlancreation*functions(particularlyinFDWs)don'tdependonthecontentsof*"root"matchingwhattheysawatPathcreationtime.Themain*downsideisthatcreationfunctionsforPlansthatmightappear*belowaModifyTablecannotexpecttomodifythecontentsof"root"*andhaveit"stick"forsubsequentprocessingsuchassetrefs.c.*That'snotgreat,butitseemsbetterthanthealternative.*/subplan=create_plan_recurse(subroot,subpath,CP_EXACT_TLIST);/*Transferresname/resjunklabeling,too,tokeepexecutorhappy*/apply_tlist_labeling(subplan->targetlist,subroot->processed_tlist);subplans=lappend(subplans,subplan);}plan=make_modifytable(root,best_path->operation,best_path->canSetTag,best_path->nominalRelation,best_path->partitioned_rels,best_path->partColsUpdated,best_path->resultRelations,subplans,best_path->subroots,best_path->withCheckOptionLists,best_path->returningLists,best_path->rowMarks,best_path->onconflict,best_path->epqParam);copy_generic_path_info(&plan->plan,&best_path->path);returnplan;}/**make_modifytable*BuildaModifyTableplannode*/staticModifyTable*make_modifytable(PlannerInfo*root,CmdTypeoperation,boolcanSetTag,IndexnominalRelation,List*partitioned_rels,boolpartColsUpdated,List*resultRelations,List*subplans,List*subroots,List*withCheckOptionLists,List*returningLists,List*rowMarks,OnConflictExpr*onconflict,intepqParam){ModifyTable*node=makeNode(ModifyTable);List*fdw_private_list;Bitmapset*direct_modify_plans;ListCell*lc;ListCell*lc2;inti;Assert(list_length(resultRelations)==list_length(subplans));Assert(list_length(resultRelations)==list_length(subroots));Assert(withCheckOptionLists==NIL||list_length(resultRelations)==list_length(withCheckOptionLists));Assert(returningLists==NIL||list_length(resultRelations)==list_length(returningLists));node->plan.lefttree=NULL;node->plan.righttree=NULL;node->plan.qual=NIL;/*setrefs.cwillfillinthetargetlist,ifneeded*/node->plan.targetlist=NIL;node->operation=operation;node->canSetTag=canSetTag;node->nominalRelation=nominalRelation;node->partitioned_rels=flatten_partitioned_rels(partitioned_rels);node->partColsUpdated=partColsUpdated;node->resultRelations=resultRelations;node->resultRelIndex=-1;/*willbesetcorrectlyinsetrefs.c*/node->rootResultRelIndex=-1;/*willbesetcorrectlyinsetrefs.c*/node->plans=subplans;if(!onconflict){node->onConflictAction=ONCONFLICT_NONE;node->onConflictSet=NIL;node->onConflictWhere=NULL;node->arbiterIndexes=NIL;node->exclRelRTI=0;node->exclRelTlist=NIL;}else{node->onConflictAction=onconflict->action;node->onConflictSet=onconflict->onConflictSet;node->onConflictWhere=onconflict->onConflictWhere;/**Ifasetofuniqueindexinferenceelementswasprovided(an*INSERT...ONCONFLICT"inferencespecification"),theninfer*appropriateuniqueindexes(orthrowanerrorifnoneare*available).*/node->arbiterIndexes=infer_arbiter_indexes(root);node->exclRelRTI=onconflict->exclRelIndex;node->exclRelTlist=onconflict->exclRelTlist;}node->withCheckOptionLists=withCheckOptionLists;node->returningLists=returningLists;node->rowMarks=rowMarks;node->epqParam=epqParam;/**Foreachresultrelationthatisaforeigntable,allowtheFDWto*constructprivateplandata,andaccumulateitallintoalist.*/fdw_private_list=NIL;direct_modify_plans=NULL;i=0;forboth(lc,resultRelations,lc2,subroots){Indexrti=lfirst_int(lc);PlannerInfo*subroot=lfirst_node(PlannerInfo,lc2);FdwRoutine*fdwroutine;List*fdw_private;booldirect_modify;/**Ifpossible,wewanttogettheFdwRoutinefromourRelOptInfofor*thetable.Butsometimeswedon'thaveaRelOptInfoandmustget*itthehardway.(InINSERT,thetargetrelationisnotscanned,*soit'snotabaserel;andtherearealsocornercasesfor*updatableviewswherethetargetrelisn'tabaserel.)*/if(rti<subroot->simple_rel_array_size&&subroot->simple_rel_array[rti]!=NULL){RelOptInfo*resultRel=subroot->simple_rel_array[rti];fdwroutine=resultRel->fdwroutine;}else{RangeTblEntry*rte=planner_rt_fetch(rti,subroot);Assert(rte->rtekind==RTE_RELATION);if(rte->relkind==RELKIND_FOREIGN_TABLE)fdwroutine=GetFdwRoutineByRelId(rte->relid);elsefdwroutine=NULL;}/**Trytomodifytheforeigntabledirectlyif(1)theFDWprovides*callbackfunctionsneededforthat,(2)therearenorow-level*triggersontheforeigntable,and(3)therearenoWITHCHECK*OPTIONsfromparentviews.*/direct_modify=false;if(fdwroutine!=NULL&&fdwroutine->PlanDirectModify!=NULL&&fdwroutine->BeginDirectModify!=NULL&&fdwroutine->IterateDirectModify!=NULL&&fdwroutine->EndDirectModify!=NULL&&withCheckOptionLists==NIL&&!has_row_triggers(subroot,rti,operation))direct_modify=fdwroutine->PlanDirectModify(subroot,node,rti,i);if(direct_modify)direct_modify_plans=bms_add_member(direct_modify_plans,i);if(!direct_modify&&fdwroutine!=NULL&&fdwroutine->PlanForeignModify!=NULL)fdw_private=fdwroutine->PlanForeignModify(subroot,node,rti,i);elsefdw_private=NIL;fdw_private_list=lappend(fdw_private_list,fdw_private);i++;}node->fdwPrivLists=fdw_private_list;node->fdwDirectModifyPlans=direct_modify_plans;returnnode;}三、跟踪分析
插入测试数据:
testdb=#insertintot_insertvalues(1000,'Iamtest','Iamtest','Iamtest');(挂起)
启动gdb,跟踪调试:
standard_planner
[root@localhost~]#gdb-p1610GNUgdb(GDB)RedHatEnterpriseLinux7.6.1-100.el7Copyright(C)2013FreeSoftwareFoundation,Inc....#跟踪进入subquery_planner(见后)(gdb)n409final_rel=fetch_upper_rel(root,UPPERREL_FINAL,NULL);(gdb)410best_path=get_cheapest_fractional_path(final_rel,tuple_fraction);#最优路径,INSERT语句,Plan为T_ModifyTable(gdb)p*best_path$51={type=T_ModifyTablePath,pathtype=T_ModifyTable,parent=0x21c40a0,pathtarget=0x21c42b0,param_info=0x0,parallel_aware=false,parallel_safe=false,parallel_workers=0,rows=1,startup_cost=0,total_cost=0.01,pathkeys=0x0}(gdb)412top_plan=create_plan(root,best_path);(gdb)stepcreate_plan(root=0x21c2cb0,best_path=0x219dd88)atcreateplan.c:323323root->curOuterRels=NULL;(gdb)n324root->curOuterParams=NIL;(gdb)327plan=create_plan_recurse(root,best_path,CP_EXACT_TLIST);(gdb)336if(!IsA(plan,ModifyTable))#plan可用于后续的执行(gdb)p*plan$53={type=T_ModifyTable,startup_cost=0,total_cost=0.01,plan_rows=1,plan_width=298,parallel_aware=false,parallel_safe=false,plan_node_id=0,targetlist=0x0,qual=0x0,lefttree=0x0,righttree=0x0,initPlan=0x0,extParam=0x0,allParam=0x0}
subquery_planner
[root@localhost~]#gdb-p1610GNUgdb(GDB)RedHatEnterpriseLinux7.6.1-100.el7Copyright(C)2013FreeSoftwareFoundation,Inc....(gdb)bsubquery_plannerBreakpoint1at0x76a0bb:fileplanner.c,line606.(gdb)cContinuing....Breakpoint1,subquery_planner(glob=0x21c2c20,parse=0x219de98,parent_root=0x0,hasRecursion=false,tuple_fraction=0)atplanner.c:606606root=makeNode(PlannerInfo);#输入参数#1,glob(gdb)p*glob$1={type=T_PlannerGlobal,boundParams=0x0,subplans=0x0,subroots=0x0,rewindPlanIDs=0x0,finalrtable=0x0,finalrowmarks=0x0,resultRelations=0x0,nonleafResultRelations=0x0,rootResultRelations=0x0,relationOids=0x0,invalItems=0x0,paramExecTypes=0x0,lastPHId=0,lastRowMarkId=0,lastPlanNodeId=0,transientPlan=false,dependsOnRole=false,parallelModeOK=false,parallelModeNeeded=false,maxParallelHazard=117'u'}#2,parse#Query结构体(gdb)p*parse$2={type=T_Query,commandType=CMD_INSERT,querySource=QSRC_ORIGINAL,queryId=0,canSetTag=true,utilityStmt=0x0,resultRelation=1,hasAggs=false,hasWindowFuncs=false,hasTargetSRFs=false,hasSubLinks=false,hasDistinctOn=false,hasRecursive=false,hasModifyingCTE=false,hasForUpdate=false,hasRowSecurity=false,cteList=0x0,rtable=0x219e2b8,jointree=0x21c2aa0,targetList=0x21c2b20,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=69}#targetList中的元素为TargetEntry*#在insert语句中,是数据表列(gdb)p*(parse->targetList)$3={type=T_List,length=4,head=0x21c2b00,tail=0x21c2b90}(gdb)p*((TargetEntry*)(parse->targetList->head->data.ptr_value))$4={xpr={type=T_TargetEntry},expr=0x219e5e8,resno=1,resname=0x219e338"id",ressortgroupref=0,resorigtbl=0,resorigcol=0,resjunk=false}#rtable中的元素是RangeTblEntry*#在insert操作中,是数据表(gdb)p*(parse->rtable)$5={type=T_List,length=1,head=0x219e298,tail=0x219e298}(gdb)p*((RangeTblEntry*)(parse->rtable->head->data.ptr_value))$6={type=T_RangeTblEntry,rtekind=RTE_RELATION,relid=26731,relkind=114'r',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=0x0,eref=0x219e0b8,lateral=false,inh=false,inFromCl=false,requiredPerms=1,checkAsUser=0,selectedCols=0x0,insertedCols=0x21c2938,updatedCols=0x0,securityQuals=0x0}(gdb)p*(((RangeTblEntry*)(parse->rtable->head->data.ptr_value))->insertedCols)$7={nwords=1,words=0x21c293c}#3,parent_root(gdb)p*parent_rootCannotaccessmemoryataddress0x0#4,hasRecursion(gdb)phasRecursion$9=false#5,tuple_fraction(gdb)ptuple_fraction$10=0...639if(parse->cteList)(gdb)648if(parse->hasSubLinks)(gdb)656inline_set_returning_functions(root);(gdb)662pull_up_subqueries(root);(gdb)670if(parse->setOperations)(gdb)680root->hasJoinRTEs=false;(gdb)681root->hasLateralRTEs=false;682hasOuterJoins=false;(gdb)683foreach(l,parse->rtable)(gdb)685RangeTblEntry*rte=lfirst_node(RangeTblEntry,l);(gdb)687if(rte->rtekind==RTE_JOIN)(gdb)p*rte$11={type=T_RangeTblEntry,rtekind=RTE_RELATION,relid=26731,relkind=114'r',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=0x0,eref=0x219e0b8,lateral=false,inh=false,inFromCl=false,requiredPerms=1,checkAsUser=0,selectedCols=0x0,insertedCols=0x21c2938,updatedCols=0x0,securityQuals=0x0}...731parse->targetList=(List*)(gdb)736if(parse->hasTargetSRFs)(gdb)p*((TargetEntry*)(parse->targetList->head->data.ptr_value))$12={xpr={type=T_TargetEntry},expr=0x21c3110,resno=1,resname=0x219e338"id",ressortgroupref=0,resorigtbl=0,resorigcol=0,resjunk=false}(gdb)p*(((TargetEntry*)(parse->targetList->head->data.ptr_value))->expr)$13={type=T_Const}...#进入grouping_planner函数,此函数生成root->upper_rels&upper_targets#注意upper_rels,grouping_planner函数执行完毕,upper_rels最后一个元素会填入相应的值(gdb)p*root$22={type=T_PlannerInfo,parse=0x219de98,glob=0x21c2c20,query_level=1,parent_root=0x0,plan_params=0x0,outer_params=0x0,simple_rel_array=0x0,simple_rel_array_size=0,simple_rte_array=0x0,all_baserels=0x0,nullable_baserels=0x0,join_rel_list=0x0,join_rel_hash=0x0,join_rel_level=0x0,join_cur_level=0,init_plans=0x0,cte_plan_ids=0x0,multiexpr_params=0x0,eq_classes=0x0,canon_pathkeys=0x0,left_join_clauses=0x0,right_join_clauses=0x0,full_join_clauses=0x0,join_info_list=0x0,append_rel_list=0x0,rowMarks=0x0,placeholder_list=0x0,fkey_list=0x0,query_pathkeys=0x0,group_pathkeys=0x0,window_pathkeys=0x0,distinct_pathkeys=0x0,sort_pathkeys=0x0,part_schemes=0x0,initial_rels=0x0,upper_rels={0x0,0x0,0x0,0x0,0x0,0x0,0x0},upper_targets={0x0,0x0,0x0,0x0,0x0,0x0,0x0},processed_tlist=0x0,grouping_map=0x0,minmax_aggs=0x0,planner_cxt=0x219cde0,total_table_pages=0,tuple_fraction=0,limit_tuples=0,qual_security_level=0,inhTargetKind=INHKIND_NONE,hasJoinRTEs=false,hasLateralRTEs=false,hasDeletedRTEs=false,hasHavingQual=false,hasPseudoConstantQuals=false,hasRecursion=false,wt_param_id=-1,non_recursive_path=0x0,curOuterRels=0x0,curOuterParams=0x0,join_search_private=0x0,partColsUpdated=false}(gdb)pinheritance_update$23=false(gdb)pinheritance_update$24=false(gdb)ptuple_fraction$25=0(gdb)...(gdb)1808tlist=preprocess_targetlist(root);(gdb)p*root$27={type=T_PlannerInfo,parse=0x219de98,glob=0x21c2c20,query_level=1,parent_root=0x0,plan_params=0x0,outer_params=0x0,simple_rel_array=0x0,simple_rel_array_size=0,simple_rte_array=0x0,all_baserels=0x0,nullable_baserels=0x0,join_rel_list=0x0,join_rel_hash=0x0,join_rel_level=0x0,join_cur_level=0,init_plans=0x0,cte_plan_ids=0x0,multiexpr_params=0x0,eq_classes=0x0,canon_pathkeys=0x0,left_join_clauses=0x0,right_join_clauses=0x0,full_join_clauses=0x0,join_info_list=0x0,append_rel_list=0x0,rowMarks=0x0,placeholder_list=0x0,fkey_list=0x0,query_pathkeys=0x0,group_pathkeys=0x0,window_pathkeys=0x0,distinct_pathkeys=0x0,sort_pathkeys=0x0,part_schemes=0x0,initial_rels=0x0,upper_rels={0x0,0x0,0x0,0x0,0x0,0x0,0x0},upper_targets={0x0,0x0,0x0,0x0,0x0,0x0,0x0},processed_tlist=0x21c39e0,grouping_map=0x0,minmax_aggs=0x0,planner_cxt=0x219cde0,total_table_pages=0,tuple_fraction=0,limit_tuples=0,qual_security_level=0,inhTargetKind=INHKIND_NONE,hasJoinRTEs=false,hasLateralRTEs=false,hasDeletedRTEs=false,hasHavingQual=false,hasPseudoConstantQuals=false,hasRecursion=false,wt_param_id=-1,non_recursive_path=0x0,curOuterRels=0x0,curOuterParams=0x0,join_search_private=0x0,partColsUpdated=false}#processed_tlist中的元素为TargetEntry*,也就是字段Column(gdb)p*(root->processed_tlist)$28={type=T_List,length=4,head=0x21c39c0,tail=0x21c3a50}(gdb)p*(root->processed_tlist->head)$29={data={ptr_value=0x21c30c0,int_value=35401920,oid_value=35401920},next=0x21c3a10}(gdb)p*(TargetEntry*)(root->processed_tlist->head.data->ptr_value)$30={xpr={type=T_TargetEntry},expr=0x21c3110,resno=1,resname=0x219e338"id",ressortgroupref=0,resorigtbl=0,resorigcol=0,resjunk=false}...2026root->upper_targets[UPPERREL_FINAL]=final_target;(gdb)2027root->upper_targets[UPPERREL_WINDOW]=sort_input_target;(gdb)2028root->upper_targets[UPPERREL_GROUP_AGG]=grouping_target;(gdb)2035if(have_grouping)(gdb)p*final_target$45={type=T_PathTarget,exprs=0x21c3ee0,sortgrouprefs=0x21c3ea0,cost={startup=0,...(gdb)2197create_modifytable_path(root,final_rel,(gdb)2200parse->resultRelation,(gdb)p*root$49={type=T_PlannerInfo,parse=0x219de98,glob=0x21c2c20,query_level=1,parent_root=0x0,plan_params=0x0,outer_params=0x0,simple_rel_array=0x0,simple_rel_array_size=0,simple_rte_array=0x0,all_baserels=0x0,nullable_baserels=0x0,join_rel_list=0x21c3cf0,join_rel_hash=0x0,join_rel_level=0x0,join_cur_level=0,init_plans=0x0,cte_plan_ids=0x0,multiexpr_params=0x0,eq_classes=0x0,canon_pathkeys=0x0,left_join_clauses=0x0,right_join_clauses=0x0,full_join_clauses=0x0,join_info_list=0x0,append_rel_list=0x0,rowMarks=0x0,placeholder_list=0x0,fkey_list=0x0,query_pathkeys=0x0,group_pathkeys=0x0,window_pathkeys=0x0,distinct_pathkeys=0x0,sort_pathkeys=0x0,part_schemes=0x0,initial_rels=0x0,upper_rels={0x0,0x0,0x0,0x0,0x0,0x0,0x21c4320},upper_targets={0x0,0x0,0x21c3e50,0x21c3e50,0x0,0x0,0x21c3e50},processed_tlist=0x21c39e0,grouping_map=0x0,minmax_aggs=0x0,planner_cxt=0x219cde0,total_table_pages=0,tuple_fraction=0,limit_tuples=-1,qual_security_level=0,inhTargetKind=INHKIND_NONE,hasJoinRTEs=false,hasLateralRTEs=false,hasDeletedRTEs=false,hasHavingQual=false,hasPseudoConstantQuals=false,hasRecursion=false,wt_param_id=-1,non_recursive_path=0x0,curOuterRels=0x0,curOuterParams=0x0,join_search_private=0x0,partColsUpdated=false}(gdb)finishRuntillexitfrom#0grouping_planner(root=0x21c2cb0,inheritance_update=false,tuple_fraction=0)atplanner.c:2200subquery_planner(glob=0x21c2c20,parse=0x219de98,parent_root=0x0,hasRecursion=false,tuple_fraction=0)atplanner.c:972#退出grouping_planner函数...#最终的返回值#INSERTVALUES语句相对比较简单,没有复杂的JOIN/WITH/HAVING/GROUP等语句,这里只是简单的返回一个root节点(gdb)p*root$17={type=T_PlannerInfo,parse=0x219de98,glob=0x21c2c20,query_level=1,parent_root=0x0,plan_params=0x0,outer_params=0x0,simple_rel_array=0x0,simple_rel_array_size=0,simple_rte_array=0x0,all_baserels=0x0,nullable_baserels=0x0,join_rel_list=0x21c3cf0,join_rel_hash=0x0,join_rel_level=0x0,join_cur_level=0,init_plans=0x0,cte_plan_ids=0x0,multiexpr_params=0x0,eq_classes=0x0,canon_pathkeys=0x0,left_join_clauses=0x0,right_join_clauses=0x0,full_join_clauses=0x0,join_info_list=0x0,append_rel_list=0x0,rowMarks=0x0,placeholder_list=0x0,fkey_list=0x0,query_pathkeys=0x0,group_pathkeys=0x0,window_pathkeys=0x0,distinct_pathkeys=0x0,sort_pathkeys=0x0,part_schemes=0x0,initial_rels=0x0,upper_rels={0x0,0x0,0x0,0x0,0x0,0x0,0x21c4320},upper_targets={0x0,0x0,0x21c3e50,0x21c3e50,0x0,0x0,0x21c3e50},processed_tlist=0x21c39e0,grouping_map=0x0,minmax_aggs=0x0,planner_cxt=0x219cde0,total_table_pages=0,tuple_fraction=0,limit_tuples=-1,qual_security_level=0,inhTargetKind=INHKIND_NONE,hasJoinRTEs=false,hasLateralRTEs=false,hasDeletedRTEs=false,hasHavingQual=false,hasPseudoConstantQuals=false,hasRecursion=false,wt_param_id=-1,non_recursive_path=0x0,curOuterRels=0x0,curOuterParams=0x0,join_search_private=0x0,partColsUpdated=false}四、小结
1.重要的数据结构:PlannedStmt/PlannerGlobal/PlannerInfo/RelOptInfo/Path
2.重要的函数:subquery_planner/grouping_planner/create_plan
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注亿速云行业资讯频道,感谢您对亿速云的支持。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。