PostgreSQL中PortalRunMulti函数和PortalRun函数的实现逻辑是什么
本篇内容主要讲解“PostgreSQL中PortalRunMulti函数和PortalRun函数的实现逻辑是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PostgreSQL中PortalRunMulti函数和PortalRun函数的实现逻辑是什么”吧!
一、基础信息PortalRunMulti函数使用的数据结构、宏定义以及依赖的函数等。
数据结构/宏定义
1、Portal
typedefstructPortalData*Portal;typedefstructPortalData{/*Bookkeepingdata*/constchar*name;/*portal'sname*/constchar*prepStmtName;/*sourcepreparedstatement(NULLifnone)*/MemoryContextportalContext;/*subsidiarymemoryforportal*/ResourceOwnerresowner;/*resourcesownedbyportal*/void(*cleanup)(Portalportal);/*cleanuphook*//**Statedataforrememberingwhichsubtransaction(s)theportalwas*createdorusedin.Iftheportalisheldoverfromaprevious*transaction,bothsubxidsareInvalidSubTransactionId.Otherwise,*createSubidisthecreatingsubxactandactiveSubidisthelastsubxact*inwhichwerantheportal.*/SubTransactionIdcreateSubid;/*thecreatingsubxact*/SubTransactionIdactiveSubid;/*thelastsubxactwithactivity*//*Thequeryorqueriestheportalwillexecute*/constchar*sourceText;/*textofquery(asof8.4,neverNULL)*/constchar*commandTag;/*commandtagfororiginalquery*/List*stmts;/*listofPlannedStmts*/CachedPlan*cplan;/*CachedPlan,ifstmtsarefromone*/ParamListInfoportalParams;/*paramstopasstoquery*/QueryEnvironment*queryEnv;/*environmentforquery*//*Features/options*/PortalStrategystrategy;/*seeabove*/intcursorOptions;/*DECLARECURSORoptionbits*/boolrun_once;/*portalwillonlyberunonce*//*Statusdata*/PortalStatusstatus;/*seeabove*/boolportalPinned;/*apinnedportalcan'tbedropped*/boolautoHeld;/*wasautomaticallyconvertedfrompinnedto*held(seeHoldPinnedPortals())*//*IfnotNULL,Executorisactive;callExecutorEndeventually:*/QueryDesc*queryDesc;/*infoneededforexecutorinvocation*//*Ifportalreturnstuples,thisistheirtupdesc:*/TupleDesctupDesc;/*descriptorforresulttuples*//*andthesearetheformatcodestouseforthecolumns:*/int16*formats;/*aformatcodeforeachcolumn*//**WherewestoretuplesforaheldcursororaPORTAL_ONE_RETURNINGor*PORTAL_UTIL_SELECTquery.(Acursorheldpasttheendofits*transactionnolongerhasanyactiveexecutorstate.)*/Tuplestorestate*holdStore;/*storeforholdablecursors*/MemoryContextholdContext;/*memorycontainingholdStore*//**SnapshotunderwhichtuplesintheholdStorewereread.Wemustkeepa*referencetothissnapshotifthereisanypossibilitythatthetuples*containTOASTreferences,becausereleasingthesnapshotcouldallow*recently-deadrowstobevacuumedaway,alongwithanytoastdata*belongingtothem.Inthecaseofaheldcursor,weavoidneedingto*keepsuchasnapshotbyforciblydetoastingthedata.*/SnapshotholdSnapshot;/*registeredsnapshot,orNULLifnone*//**atStart,atEndandportalPosindicatethecurrentcursorposition.*portalPosiszerobeforethefirstrow,NafterfetchingN'throwof*query.Afterwerunofftheend,portalPos=#ofrowsinquery,and*atEndistrue.NotethatatStartimpliesportalPos==0,butnotthe*reverse:wemighthavebackeduponlyasfarasthefirstrow,notto*thestart.AlsonotethatvariouscodeinspectsatStartandatEnd,but*onlytheportalmovementroutinesshouldtouchportalPos.*/boolatStart;boolatEnd;uint64portalPos;/*Presentationdata,primarilyusedbythepg_cursorssystemview*/TimestampTzcreation_time;/*timeatwhichthisportalwasdefined*/boolvisible;/*includethisportalinpg_cursors?*/}PortalData;
2、List
typedefstructListCellListCell;typedefstructList{NodeTagtype;/*T_List,T_IntList,orT_OidList*/intlength;ListCell*head;ListCell*tail;}List;structListCell{union{void*ptr_value;intint_value;Oidoid_value;}data;ListCell*next;};
3、Snapshot
typedefstructSnapshotData*Snapshot;/**Structrepresentingallkindofpossiblesnapshots.**Thereareseveraldifferentkindsofsnapshots:**NormalMVCCsnapshots**MVCCsnapshotstakenduringrecovery(inHot-Standbymode)**HistoricMVCCsnapshotsusedduringlogicaldecoding**snapshotspassedtoHeapTupleSatisfiesDirty()**snapshotspassedtoHeapTupleSatisfiesNonVacuumable()**snapshotsusedforSatisfiesAny,Toast,Selfwherenomembersare*accessed.**TODO:It'sprobablyagoodideatosplitthisstructusingaNodeTag*similartohowparserandexecutornodesarehandled,withonetypefor*eachdifferentkindofsnapshottoavoidoverloadingthemeaningof*individualfields.*/typedefstructSnapshotData{SnapshotSatisfiesFuncsatisfies;/*tupletestfunction*//**TheremainingfieldsareusedonlyforMVCCsnapshots,andarenormally*justzeroesinspecialsnapshots.(Butxminandxmaxareused*speciallybyHeapTupleSatisfiesDirty,andxminisusedspeciallyby*HeapTupleSatisfiesNonVacuumable.)**AnMVCCsnapshotcanneverseetheeffectsofXIDs>=xmax.Itcansee*theeffectsofallolderXIDsexceptthoselistedinthesnapshot.xmin*isstoredasanoptimizationtoavoidneedingtosearchtheXIDarrays*formosttuples.*/TransactionIdxmin;/*allXID<xminarevisibletome*/TransactionIdxmax;/*allXID>=xmaxareinvisibletome*//**FornormalMVCCsnapshotthiscontainstheallxactIDsthatarein*progress,unlessthesnapshotwastakenduringrecoveryinwhichcase*it'sempty.ForhistoricMVCCsnapshots,themeaningisinverted,i.e.*itcontains*committed*transactionsbetweenxminandxmax.**note:allidsinxip[]satisfyxmin<=xip[i]<xmax*/TransactionId*xip;uint32xcnt;/*#ofxactidsinxip[]*//**Fornon-historicMVCCsnapshots,thiscontainssubxactIDsthatarein*progress(andothertransactionsthatareinprogressiftakenduring*recovery).Forhistoricsnapshotitcontains*all*xidsassignedtothe*replayedtransaction,includingthetoplevelxid.**note:allidsinsubxip[]are>=xmin,butwedon'tbotherfiltering*outanythatare>=xmax*/TransactionId*subxip;int32subxcnt;/*#ofxactidsinsubxip[]*/boolsuboverflowed;/*hasthesubxiparrayoverflowed?*/booltakenDuringRecovery;/*recovery-shapedsnapshot?*/boolcopied;/*falseifit'sastaticsnapshot*/CommandIdcurcid;/*inmyxact,CID<curcidarevisible*//**AnextrareturnvalueforHeapTupleSatisfiesDirty,notusedinMVCC*snapshots.*/uint32speculativeToken;/**Book-keepinginformation,usedbythesnapshotmanager*/uint32active_count;/*refcountonActiveSnapshotstack*/uint32regd_count;/*refcountonRegisteredSnapshots*/pairingheap_nodeph_node;/*linkintheRegisteredSnapshotsheap*/TimestampTzwhenTaken;/*timestampwhensnapshotwastaken*/XLogRecPtrlsn;/*positionintheWALstreamwhentaken*/}SnapshotData;
依赖的函数
1、lfirst_*
/**NB:Thereisanunfortunatelegacyfromapreviousincarnationof*theListAPI:themacrolfirst()wasusedtomean"thedatainthis*conscell".Toavoidchangingeveryusageoflfirst(),thatmeaning*hasbeenkept.Asaresult,lfirst()takesaListCellandreturns*thedataitcontains;togetthedatainthefirstcellofa*List,uselinitial().Worse,lsecond()ismorecloselyrelatedto*linitial()thanlfirst():givenaList,lsecond()returnsthedata*inthesecondconscell.*/#definelnext(lc)((lc)->next)#definelfirst(lc)((lc)->data.ptr_value)#definelfirst_int(lc)((lc)->data.int_value)#definelfirst_oid(lc)((lc)->data.oid_value)#definelfirst_node(type,lc)castNode(type,lfirst(lc))/**castNode(type,ptr)castsptrto"type*",andifassertionsareenabled,*verifiesthatthenodehastheappropriatetype(usingitsnodeTag()).**Useaninlinefunctionwhenassertionsareenabled,toavoidmultiple*evaluationsoftheptrargument(whichcoulde.g.beafunctioncall).*/#ifdefUSE_ASSERT_CHECKINGstaticinlineNode*castNodeImpl(NodeTagtype,void*ptr){Assert(ptr==NULL||nodeTag(ptr)==type);return(Node*)ptr;}#definecastNode(_type_,nodeptr)((_type_*)castNodeImpl(T_##_type_,nodeptr))#else#definecastNode(_type_,nodeptr)((_type_*)(nodeptr))#endif/*USE_ASSERT_CHECKING*/
2、Snapshot相关
//留待MVCC再行解读GetTransactionSnapshotRegisterSnapshotPushCopiedSnapshotUpdateActiveSnapshotCommandIdPopActiveSnapshot
3、ProcessQuery
//上一节已介绍
4、CommandCounterIncrement
/**CommandCounterIncrement*/voidCommandCounterIncrement(void){/**Ifthecurrentvalueofthecommandcounterhasn'tbeen"used"tomark*tuples,weneednotincrementit,sincethere'snoneedtodistinguish*aread-onlycommandfromothers.Thishelpspostponecommandcounter*overflow,andkeepsno-opCommandCounterIncrementoperationscheap.*/if(currentCommandIdUsed){/**Workerssynchronizetransactionstateatthebeginningofeach*paralleloperation,sowecan'taccountfornewcommandsafterthat*point.*/if(IsInParallelMode()||IsParallelWorker())elog(ERROR,"cannotstartcommandsduringaparalleloperation");currentCommandId+=1;if(currentCommandId==InvalidCommandId){currentCommandId-=1;ereport(ERROR,(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),errmsg("cannothavemorethan2^32-2commandsinatransaction")));}currentCommandIdUsed=false;/*PropagatenewcommandIDintostaticsnapshots*/SnapshotSetCommandId(currentCommandId);/**Makeanycatalogchangesdonebythejust-completedcommandvisible*inthelocalsyscache.Weobviouslydon'tneedtodothisaftera*read-onlycommand.(Butseehacksininval.ctomakerealsurewe*don'tthinkacommandthatqueuedinvalmessageswasread-only.)*/AtCCI_LocalCache();}}
5、MemoryContextDeleteChildren
/**MemoryContextDeleteChildren*Deleteallthedescendantsofthenamedcontextandreleaseall*spaceallocatedtherein.Thenamedcontextitselfisnottouched.*/voidMemoryContextDeleteChildren(MemoryContextcontext){AssertArg(MemoryContextIsValid(context));/**MemoryContextDeletewilldelinkthechildfromme,sojustiterateas*longasthereisachild.*/while(context->firstchild!=NULL)MemoryContextDelete(context->firstchild);}二、源码解读
1、PortalRun
/**PortalRun*Runaportal'squeryorqueries.**count<=0isinterpretedasano-op:thedestinationgetsstartedup*andshutdown,butnothingelsehappens.Also,count==FETCH_ALLis*interpretedas"allrows".Notethatcountisignoredinmulti-query*situations,wherewealwaysruntheportaltocompletion.**isTopLevel:trueifqueryisbeingexecutedatbackend"toplevel"*(thatis,directlyfromaclientcommandmessage)**dest:wheretosendoutputofprimary(canSetTag)query**altdest:wheretosendoutputofnon-primaryqueries**completionTag:pointstoabufferofsizeCOMPLETION_TAG_BUFSIZE*inwhichtostoreacommandcompletionstatusstring.*MaybeNULLifcallerdoesn'twantastatusstring.**Returnstrueiftheportal'sexecutioniscomplete,falseifitwas*suspendedduetoexhaustionofthecountparameter.*//*输入:参照PortalRunMulti输出:布尔变量,成功true,失败false*/boolPortalRun(Portalportal,longcount,boolisTopLevel,boolrun_once,DestReceiver*dest,DestReceiver*altdest,char*completionTag){boolresult;//返回结果uint64nprocessed;ResourceOwnersaveTopTransactionResourceOwner;//高层事务资源宿主MemoryContextsaveTopTransactionContext;//内存上下文PortalsaveActivePortal;//活动的PortalResourceOwnersaveResourceOwner;MemoryContextsavePortalContext;MemoryContextsaveMemoryContext;AssertArg(PortalIsValid(portal));TRACE_POSTGRESQL_QUERY_EXECUTE_START();/*Initializecompletiontagtoemptystring*/if(completionTag)completionTag[0]='\0';if(log_executor_stats&&portal->strategy!=PORTAL_MULTI_QUERY){elog(DEBUG3,"PortalRun");/*PORTAL_MULTI_QUERYlogsitsownstatsperquery*/ResetUsage();}/**Checkforimproperportaluse,andmarkportalactive.*/MarkPortalActive(portal);/*Setrun_onceflag.Shouldn'tbeclearifpreviouslyset.*/Assert(!portal->run_once||run_once);portal->run_once=run_once;/**Setupglobalportalcontextpointers.**Wehavetoplayaspecialgameheretosupportutilitycommandslike*VACUUMandCLUSTER,whichinternallystartandcommittransactions.*Whenwearecalledtoexecutesuchacommand,CurrentResourceOwnerwill*bepointingtotheTopTransactionResourceOwner---whichwillbe*destroyedandreplacedinthecourseoftheinternalcommitand*restart.Soweneedtobepreparedtorestoreitaspointingtothe*exit-timeTopTransactionResourceOwner.(Ain'tthatugly?Thisideaof*internallystartingwholenewtransactionsisnotgood.)*CurrentMemoryContexthasasimilarproblem,buttheotherpointerswe*saveherewillbeNULLorpointingtolonger-livedobjects.*///保护现场saveTopTransactionResourceOwner=TopTransactionResourceOwner;saveTopTransactionContext=TopTransactionContext;saveActivePortal=ActivePortal;saveResourceOwner=CurrentResourceOwner;savePortalContext=PortalContext;saveMemoryContext=CurrentMemoryContext;PG_TRY();{ActivePortal=portal;if(portal->resowner)CurrentResourceOwner=portal->resowner;PortalContext=portal->portalContext;MemoryContextSwitchTo(PortalContext);switch(portal->strategy){casePORTAL_ONE_SELECT:casePORTAL_ONE_RETURNING:casePORTAL_ONE_MOD_WITH:casePORTAL_UTIL_SELECT:/**Ifwehavenotyetrunthecommand,doso,storingits*resultsintheportal'stuplestore.Butwedon'tdothat*forthePORTAL_ONE_SELECTcase.*/if(portal->strategy!=PORTAL_ONE_SELECT&&!portal->holdStore)FillPortalStore(portal,isTopLevel);/**Nowfetchdesiredportionofresults.*/nprocessed=PortalRunSelect(portal,true,count,dest);/**Iftheportalresultcontainsacommandtagandthecaller*gaveusapointertostoreit,copyit.Patchthe"SELECT"*tagtoalsoprovidetherowcount.*/if(completionTag&&portal->commandTag){if(strcmp(portal->commandTag,"SELECT")==0)snprintf(completionTag,COMPLETION_TAG_BUFSIZE,"SELECT"UINT64_FORMAT,nprocessed);elsestrcpy(completionTag,portal->commandTag);}/*Markportalnotactive*/portal->status=PORTAL_READY;/**Sinceit'saforwardfetch,sayDONEiffatEndisnowtrue.*/result=portal->atEnd;break;casePORTAL_MULTI_QUERY://INSERT语句PortalRunMulti(portal,isTopLevel,false,dest,altdest,completionTag);/*Preventportal'scommandsfrombeingre-executed*/MarkPortalDone(portal);/*AlwayscompleteatendofRunMulti*/result=true;break;default:elog(ERROR,"unrecognizedportalstrategy:%d",(int)portal->strategy);result=false;/*keepcompilerquiet*/break;}}PG_CATCH();{/*Uncaughterrorwhileexecutingportal:markitdead*/MarkPortalFailed(portal);/*Restoreglobalvarsandpropagateerror*/if(saveMemoryContext==saveTopTransactionContext)MemoryContextSwitchTo(TopTransactionContext);elseMemoryContextSwitchTo(saveMemoryContext);ActivePortal=saveActivePortal;if(saveResourceOwner==saveTopTransactionResourceOwner)CurrentResourceOwner=TopTransactionResourceOwner;elseCurrentResourceOwner=saveResourceOwner;PortalContext=savePortalContext;PG_RE_THROW();}PG_END_TRY();if(saveMemoryContext==saveTopTransactionContext)MemoryContextSwitchTo(TopTransactionContext);elseMemoryContextSwitchTo(saveMemoryContext);ActivePortal=saveActivePortal;if(saveResourceOwner==saveTopTransactionResourceOwner)CurrentResourceOwner=TopTransactionResourceOwner;elseCurrentResourceOwner=saveResourceOwner;PortalContext=savePortalContext;if(log_executor_stats&&portal->strategy!=PORTAL_MULTI_QUERY)ShowUsage("EXECUTORSTATISTICS");TRACE_POSTGRESQL_QUERY_EXECUTE_DONE();returnresult;}
2、PortalRunMulti
/**PortalRunMulti*Executeaportal'squeriesinthegeneralcase(multiqueries*ornon-SELECT-likequeries)*//*输入:portal-“门户”数据结构isTopLevel-顶层?setHoldSnapshot-是否持有快照dest-目标端altdest-?completionTag-完成标记(用于语句执行结果输出)输出:无*/staticvoidPortalRunMulti(Portalportal,boolisTopLevel,boolsetHoldSnapshot,DestReceiver*dest,DestReceiver*altdest,char*completionTag){boolactive_snapshot_set=false;//活跃snapshot?ListCell*stmtlist_item;//SQL语句,临时变量/**IfthedestinationisDestRemoteExecute,changetoDestNone.The*reasonisthattheclientwon'tbeexpectinganytuples,andindeedhas*nowaytoknowwhattheyare,sincethereisnoprovisionforDescribe*tosendaRowDescriptionmessagewhenthisportalexecutionstrategyis*ineffect.ThispresentlywillonlyaffectSELECTcommandsaddedto*non-SELECTqueriesbyrewriterules:suchcommandswillbeexecuted,*buttheresultswillbediscardedunlessyouuse"simpleQuery"*protocol.*/if(dest->mydest==DestRemoteExecute)dest=None_Receiver;if(altdest->mydest==DestRemoteExecute)altdest=None_Receiver;/**Looptohandletheindividualqueriesgeneratedfromasingleparsetree*byanalysisandrewrite.*/foreach(stmtlist_item,portal->stmts)//循环处理SQL语句{PlannedStmt*pstmt=lfirst_node(PlannedStmt,stmtlist_item);//获取已规划的语句/**Ifwegotacancelsignalinpriorcommand,quit*/CHECK_FOR_INTERRUPTS();if(pstmt->utilityStmt==NULL)//非“工具类”语句{/**processaplannablequery.*/TRACE_POSTGRESQL_QUERY_EXECUTE_START();if(log_executor_stats)ResetUsage();/**Mustalwayshaveasnapshotforplannablequeries.Firsttime*through,takeanewsnapshot;forsubsequentqueriesinthe*sameportal,justupdatethesnapshot'scopyofthecommand*counter.*/if(!active_snapshot_set){Snapshotsnapshot=GetTransactionSnapshot();//获取事务快照/*Iftoldto,registerthesnapshotandsaveinportal*/if(setHoldSnapshot){snapshot=RegisterSnapshot(snapshot);portal->holdSnapshot=snapshot;}/**Wecan'thavetheholdSnapshotalsobetheactiveone,*becauseUpdateActiveSnapshotCommandIdwouldcomplain.So*forceanextrasnapshotcopy.PlainPushActiveSnapshot*wouldhavecopiedthetransactionsnapshotanyway,sothis*onlyaddsacopystepwhensetHoldSnapshotistrue.(It's*okayforthecommandIDoftheactivesnapshottodiverge*fromwhatholdSnapshothas.)*/PushCopiedSnapshot(snapshot);active_snapshot_set=true;}elseUpdateActiveSnapshotCommandId();//处理查询if(pstmt->canSetTag){/*statementcansettagstring*/ProcessQuery(pstmt,portal->sourceText,portal->portalParams,portal->queryEnv,dest,completionTag);}else{/*stmtaddedbyrewritecannotsettag*/ProcessQuery(pstmt,portal->sourceText,portal->portalParams,portal->queryEnv,altdest,NULL);}if(log_executor_stats)ShowUsage("EXECUTORSTATISTICS");TRACE_POSTGRESQL_QUERY_EXECUTE_DONE();}else//“工具类”语句{/**processutilityfunctions(create,destroy,etc..)**Wemustnotsetasnapshothereforutilitycommands(ifoneis*needed,PortalRunUtilitywilldoit).Ifautilitycommandis*aloneinaportaltheneverything'sfine.Theonlycasewhere*autilitycommandcanbepartofalongerlististhatrules*areallowedtoincludeNotifyStmt.NotifyStmtdoesn'tcare*whetherithasasnapshotornot,sowejustleavethecurrent*snapshotaloneifwehaveone.*/if(pstmt->canSetTag){Assert(!active_snapshot_set);/*statementcansettagstring*/PortalRunUtility(portal,pstmt,isTopLevel,false,dest,completionTag);}else{Assert(IsA(pstmt->utilityStmt,NotifyStmt));/*stmtaddedbyrewritecannotsettag*/PortalRunUtility(portal,pstmt,isTopLevel,false,altdest,NULL);}}/**Incrementcommandcounterbetweenqueries,butnotafterthelast*one.*/if(lnext(stmtlist_item)!=NULL)CommandCounterIncrement();/**Clearsubsidiarycontextstorecovertemporarymemory.*/Assert(portal->portalContext==CurrentMemoryContext);MemoryContextDeleteChildren(portal->portalContext);//释放资源}/*Popthesnapshotifwepushedone.*/if(active_snapshot_set)PopActiveSnapshot();/**Ifacommandcompletiontagwassupplied,useit.Otherwiseusethe*portal'scommandTagasthedefaultcompletiontag.**Exception:ClientsexpectINSERT/UPDATE/DELETEtagstohavecounts,so*fakethemwithzeros.ThiscanhappenwithDOINSTEADrulesifthere*isnoreplacementqueryofthesametypeastheoriginal.Weprint"0*0"herebecausetechnicallythereisnoqueryofthematchingtagtype,*andprintinganon-zerocountforadifferentquerytypeseemswrong,*e.g.anINSERTthatdoesanUPDATEinsteadshouldnotprint"01"if*onerowwasupdated.SeeQueryRewrite(),step3,fordetails.*/if(completionTag&&completionTag[0]=='\0')//操作提示{if(portal->commandTag)strcpy(completionTag,portal->commandTag);if(strcmp(completionTag,"SELECT")==0)sprintf(completionTag,"SELECT00");elseif(strcmp(completionTag,"INSERT")==0)strcpy(completionTag,"INSERT00");elseif(strcmp(completionTag,"UPDATE")==0)strcpy(completionTag,"UPDATE0");elseif(strcmp(completionTag,"DELETE")==0)strcpy(completionTag,"DELETE0");}}三、跟踪分析
插入测试数据:
testdb=#--获取pidtestdb=#selectpg_backend_pid();pg_backend_pid----------------2551(1row)testdb=#--插入1行testdb=#insertintot_insertvalues(20,'PortalRun','PortalRun','PortalRun');
启动gdb,跟踪调试:
1、PortalRun
[root@localhost~]#gdb-p2551GNUgdb(GDB)RedHatEnterpriseLinux7.6.1-100.el7Copyright(C)2013FreeSoftwareFoundation,Inc....(gdb)bPortalRunBreakpoint1at0x8528af:filepquery.c,line707.(gdb)cContinuing.Breakpoint1,PortalRun(portal=0x2c6f490,count=9223372036854775807,isTopLevel=true,run_once=true,dest=0x2ccb4d8,altdest=0x2ccb4d8,completionTag=0x7ffe94ba4940"")atpquery.c:707707if(completionTag)#查看输入参数#1、portal(gdb)p*portal$1={name=0x2c72e98"",prepStmtName=0x0,portalContext=0x2cc1470,resowner=0x2c3ad10,cleanup=0x62f15c<PortalCleanup>,createSubid=1,activeSubid=1,sourceText=0x2c09ef0"insertintot_insertvalues(20,'PortalRun','PortalRun','PortalRun');",commandTag=0xb50908"INSERT",stmts=0x2ccb4a8,cplan=0x0,portalParams=0x0,queryEnv=0x0,strategy=PORTAL_MULTI_QUERY,cursorOptions=4,run_once=false,status=PORTAL_READY,portalPinned=false,autoHeld=false,queryDesc=0x0,tupDesc=0x0,formats=0x0,holdStore=0x0,holdContext=0x0,holdSnapshot=0x0,atStart=true,atEnd=true,portalPos=0,creation_time=587033564125509,visible=false}(gdb)p*(portal->portalContext)$2={type=T_AllocSetContext,isReset=true,allowInCritSection=false,methods=0xb8c720<AllocSetMethods>,parent=0x2c6f380,firstchild=0x0,prevchild=0x0,nextchild=0x0,name=0xb8d2f1"PortalContext",ident=0x2c72e98"",reset_cbs=0x0}(gdb)p*(portal->resowner)$3={parent=0x2c35518,firstchild=0x0,nextchild=0x0,name=0xb8d2ff"Portal",bufferarr={itemsarr=0x0,invalidval=0,capacity=0,nitems=0,maxitems=0,lastidx=0},catrefarr={itemsarr=0x0,invalidval=0,capacity=0,nitems=0,maxitems=0,lastidx=0},catlistrefarr={itemsarr=0x0,invalidval=0,capacity=0,nitems=0,maxitems=0,lastidx=0},relrefarr={itemsarr=0x0,invalidval=0,capacity=0,nitems=0,maxitems=0,lastidx=0},planrefarr={itemsarr=0x0,invalidval=0,capacity=0,nitems=0,maxitems=0,lastidx=0},tupdescarr={itemsarr=0x0,invalidval=0,capacity=0,nitems=0,maxitems=0,lastidx=0},snapshotarr={itemsarr=0x0,invalidval=0,capacity=0,nitems=0,maxitems=0,lastidx=0},filearr={itemsarr=0x0,invalidval=18446744073709551615,capacity=0,nitems=0,maxitems=0,lastidx=0},dsmarr={itemsarr=0x0,invalidval=0,capacity=0,nitems=0,maxitems=0,lastidx=0},jitarr={itemsarr=0x0,invalidval=0,capacity=0,nitems=0,maxitems=0,lastidx=0},nlocks=0,locks={0x0<repeats15times>}}(gdb)p*(portal->resowner->parent)$4={parent=0x0,firstchild=0x2c3ad10,nextchild=0x0,name=0xa1b515"TopTransaction",bufferarr={itemsarr=0x0,invalidval=0,capacity=0,nitems=0,maxitems=0,lastidx=0},catrefarr={itemsarr=0x2c3b040,invalidval=0,capacity=16,nitems=0,maxitems=16,lastidx=4294967295},catlistrefarr={itemsarr=0x0,invalidval=0,capacity=0,nitems=0,maxitems=0,lastidx=0},relrefarr={itemsarr=0x2c35728,invalidval=0,capacity=16,nitems=0,maxitems=16,lastidx=4294967295},planrefarr={itemsarr=0x0,invalidval=0,capacity=0,nitems=0,maxitems=0,lastidx=0},tupdescarr={itemsarr=0x0,invalidval=0,capacity=0,nitems=0,maxitems=0,lastidx=0},snapshotarr={itemsarr=0x0,invalidval=0,capacity=0,nitems=0,maxitems=0,lastidx=0},filearr={itemsarr=0x0,invalidval=18446744073709551615,capacity=0,nitems=0,maxitems=0,lastidx=0},dsmarr={itemsarr=0x0,invalidval=0,capacity=0,nitems=0,maxitems=0,lastidx=0},jitarr={itemsarr=0x0,invalidval=0,capacity=0,nitems=0,maxitems=0,lastidx=0},nlocks=1,locks={0x2c28320,0x0<repeats14times>}}#2、count(gdb)pcount$5=9223372036854775807#3、isTopLevel(gdb)pisTopLevel$6=true#4、run_once(gdb)prun_once$7=true#5、dest$8=(DestReceiver*)0x2ccb4d8(gdb)p*dest$9={receiveSlot=0x4857ad<printtup>,rStartup=0x485196<printtup_startup>,rShutdown=0x485bad<printtup_shutdown>,rDestroy=0x485c21<printtup_destroy>,mydest=DestRemote}(gdb)#6、altdest(gdb)paltdest$10=(DestReceiver*)0x2ccb4d8(gdb)p*altdest$11={receiveSlot=0x4857ad<printtup>,rStartup=0x485196<printtup_startup>,rShutdown=0x485bad<printtup_shutdown>,rDestroy=0x485c21<printtup_destroy>,mydest=DestRemote}(gdb)#7、completionTag(gdb)pcompletionTag$12=0x7ffe94ba4940""#单步调试710if(log_executor_stats&&portal->strategy!=PORTAL_MULTI_QUERY)(gdb)720MarkPortalActive(portal);(gdb)724portal->run_once=run_once;(gdb)740saveTopTransactionResourceOwner=TopTransactionResourceOwner;(gdb)741saveTopTransactionContext=TopTransactionContext;(gdb)742saveActivePortal=ActivePortal;(gdb)743saveResourceOwner=CurrentResourceOwner;(gdb)744savePortalContext=PortalContext;(gdb)745saveMemoryContext=CurrentMemoryContext;(gdb)746PG_TRY();(gdb)748ActivePortal=portal;(gdb)749if(portal->resowner)(gdb)750CurrentResourceOwner=portal->resowner;(gdb)751PortalContext=portal->portalContext;(gdb)753MemoryContextSwitchTo(PortalContext);(gdb)755switch(portal->strategy)(gdb)pportal->strategy$13=PORTAL_MULTI_QUERY(gdb)next799PortalRunMulti(portal,isTopLevel,false,(gdb)803MarkPortalDone(portal);(gdb)806result=true;(gdb)807break;(gdb)835PG_END_TRY();(gdb)837if(saveMemoryContext==saveTopTransactionContext)(gdb)838MemoryContextSwitchTo(TopTransactionContext);(gdb)841ActivePortal=saveActivePortal;(gdb)842if(saveResourceOwner==saveTopTransactionResourceOwner)(gdb)843CurrentResourceOwner=TopTransactionResourceOwner;(gdb)846PortalContext=savePortalContext;(gdb)848if(log_executor_stats&&portal->strategy!=PORTAL_MULTI_QUERY)(gdb)853returnresult;(gdb)854}#DONE!
2、PortalRunMulti
(gdb)bPortalRunMultiBreakpoint1at0x8533df:filepquery.c,line1210.(gdb)cContinuing.Breakpoint1,PortalRunMulti(portal=0x2c6f490,isTopLevel=true,setHoldSnapshot=false,dest=0x2cbe8f8,altdest=0x2cbe8f8,completionTag=0x7ffe94ba4940"")atpquery.c:12101210boolactive_snapshot_set=false;#输入参数#1、portal(gdb)p*portal$1={name=0x2c72e98"",prepStmtName=0x0,portalContext=0x2c2d3d0,resowner=0x2c3ad10,cleanup=0x62f15c<PortalCleanup>,createSubid=1,activeSubid=1,sourceText=0x2c09ef0"insertintot_insertvalues(21,'PortalRunMulti','PortalRunMulti','PortalRunMulti');",commandTag=0xb50908"INSERT",stmts=0x2cbe8c8,cplan=0x0,portalParams=0x0,queryEnv=0x0,strategy=PORTAL_MULTI_QUERY,cursorOptions=4,run_once=true,status=PORTAL_ACTIVE,portalPinned=false,autoHeld=false,queryDesc=0x0,tupDesc=0x0,formats=0x0,holdStore=0x0,holdContext=0x0,holdSnapshot=0x0,atStart=true,atEnd=true,portalPos=0,creation_time=587034112962796,visible=false}(gdb)p*(portal->portalContext)$2={type=T_AllocSetContext,isReset=true,allowInCritSection=false,methods=0xb8c720<AllocSetMethods>,parent=0x2c6f380,firstchild=0x0,prevchild=0x0,nextchild=0x0,name=0xb8d2f1"PortalContext",ident=0x2c72e98"",reset_cbs=0x0}#2、isTopLevel(gdb)pisTopLevel$3=true#3、setHoldSnapshot(gdb)psetHoldSnapshot$4=false#4、dest(gdb)p*dest$5={receiveSlot=0x4857ad<printtup>,rStartup=0x485196<printtup_startup>,rShutdown=0x485bad<printtup_shutdown>,rDestroy=0x485c21<printtup_destroy>,mydest=DestRemote}#5、altdest(gdb)p*altdest$6={receiveSlot=0x4857ad<printtup>,rStartup=0x485196<printtup_startup>,rShutdown=0x485bad<printtup_shutdown>,rDestroy=0x485c21<printtup_destroy>,mydest=DestRemote}#6、completionTag(gdb)p*completionTag$7=0'\000'#单步调试...(gdb)next1234PlannedStmt*pstmt=lfirst_node(PlannedStmt,stmtlist_item);(gdb)1239CHECK_FOR_INTERRUPTS();(gdb)p*pstmt$12={type=T_PlannedStmt,commandType=CMD_INSERT,queryId=0,hasReturning=false,hasModifyingCTE=false,canSetTag=true,transientPlan=false,dependsOnRole=false,parallelModeNeeded=false,jitFlags=0,planTree=0x2c0aff8,rtable=0x2cbe7d8,resultRelations=0x2cbe878,nonleafResultRelations=0x0,rootResultRelations=0x0,subplans=0x0,rewindPlanIDs=0x0,rowMarks=0x0,relationOids=0x2cbe828,invalItems=0x0,paramExecTypes=0x2c31700,utilityStmt=0x0,stmt_location=0,stmt_len=82}(gdb)next1241if(pstmt->utilityStmt==NULL)(gdb)1248if(log_executor_stats)(gdb)1257if(!active_snapshot_set)(gdb)1259Snapshotsnapshot=GetTransactionSnapshot();(gdb)1262if(setHoldSnapshot)(gdb)p*snapshot$13={satisfies=0x9f73fc<HeapTupleSatisfiesMVCC>,xmin=1612887,xmax=1612887,xip=0x2c2d1c0,xcnt=0,subxip=0x2c81c70,subxcnt=0,suboverflowed=false,takenDuringRecovery=false,copied=false,curcid=0,speculativeToken=0,active_count=0,regd_count=0,ph_node={first_child=0x0,next_sibling=0x0,prev_or_parent=0x0},whenTaken=0,lsn=0}(gdb)...(gdb)PortalRun(portal=0x2c6f490,count=9223372036854775807,isTopLevel=true,run_once=true,dest=0x2cbe8f8,altdest=0x2cbe8f8,completionTag=0x7ffe94ba4940"INSERT01")atpquery.c:803803MarkPortalDone(portal);#DONE!
到此,相信大家对“PostgreSQL中PortalRunMulti函数和PortalRun函数的实现逻辑是什么”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。