PostgreSQL中exec_simple_query函数的实现逻辑是什么
这篇文章主要介绍“PostgreSQL中exec_simple_query函数的实现逻辑是什么”,在日常操作中,相信很多人在PostgreSQL中exec_simple_query函数的实现逻辑是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”PostgreSQL中exec_simple_query函数的实现逻辑是什么”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
一、源码解读exec_simple_query函数,顾名思义,执行简单“查询”(包括INSERT/UPDATE/DELETE等语句)
/**exec_simple_query**Executea"simpleQuery"protocolmessage.*//*输入:query_string-SQL语句输出:无*/staticvoidexec_simple_query(constchar*query_string){CommandDestdest=whereToSendOutput;//输出到哪里的定义MemoryContextoldcontext;//存储原内存上下文List*parsetree_list;//分析树列表ListCell*parsetree_item;//分析树中的ITEMboolsave_log_statement_stats=log_statement_stats;//是否保存统计信息,falseboolwas_logged=false;//Log?booluse_implicit_block;//是否使用隐式事务块charmsec_str[32];/**Reportquerytovariousmonitoringfacilities.*/debug_query_string=query_string;pgstat_report_activity(STATE_RUNNING,query_string);//统计信息TRACE_POSTGRESQL_QUERY_START(query_string);/**Weusesave_log_statement_statssoShowUsagedoesn'treportincorrect*resultsbecauseResetUsagewasn'tcalled.*/if(save_log_statement_stats)ResetUsage();/**Startupatransactioncommand.Allqueriesgeneratedbythe*query_stringwillbeinthissamecommandblock,*unless*wefinda*BEGIN/COMMIT/ABORTstatement;wehavetoforceanewxactcommandafter*oneofthose,elsebadthingswillhappeninxact.c.(Notethatthis*willnormallychangecurrentmemorycontext.)*/start_xact_command();//启动事务/**Zapanypre-existingunnamedstatement.(Whilenotstrictlynecessary,*itseemsbesttodefinesimple-Querymodeasifitusedtheunnamed*statementandportal;thisensureswerecoveranystorageusedbyprior*unnamedoperations.)*/drop_unnamed_stmt();//清除匿名语句/**Switchtoappropriatecontextforconstructingparsetrees.*/oldcontext=MemoryContextSwitchTo(MessageContext);//切换内存上下文/**Dobasicparsingofthequeryorqueries(thisshouldbesafeevenif*weareinabortedtransactionstate!)*/parsetree_list=pg_parse_query(query_string);//解析输入的查询语句,获得分析树List(元素是RawStmtnodes)/*Logimmediatelyifdictatedbylog_statement*/if(check_log_statement(parsetree_list))//日志记录{ereport(LOG,(errmsg("statement:%s",query_string),errhidestmt(true),errdetail_execute(parsetree_list)));was_logged=true;}/**Switchbacktotransactioncontexttoentertheloop.*/MemoryContextSwitchTo(oldcontext);//切换回原内存上下文/**Forhistoricalreasons,ifmultipleSQLstatementsaregivenina*single"simpleQuery"message,weexecutethemasasingletransaction,*unlessexplicittransactioncontrolcommandsareincludedtomake*portionsofthelistbeseparatetransactions.Torepresentthis*behaviorproperlyinthetransactionmachinery,weusean"implicit"*transactionblock.*/use_implicit_block=(list_length(parsetree_list)>1);//如果分析树条目>1,使用隐式事务块(多条SQL语句在同一个事务中)/**Runthroughtherawparsetree(s)andprocesseachone.*/foreach(parsetree_item,parsetree_list)//对分析树中的每一个条目进行处理{RawStmt*parsetree=lfirst_node(RawStmt,parsetree_item);//分析树List中的元素为RawStmt指针类型boolsnapshot_set=false;//是否设置快照?constchar*commandTag;//命令标识charcompletionTag[COMPLETION_TAG_BUFSIZE];//完成标记,如INSERT01之类的字符串List*querytree_list,//查询树List*plantree_list;//执行计划ListPortalportal;//“门户”变量DestReceiver*receiver;//目标接收端int16format;///**Getthecommandnameforuseinstatusdisplay(italsobecomesthe*defaultcompletiontag,downinsidePortalRun).Setps_statusand*doanyspecialstart-of-SQL-commandprocessingneededbythe*destination.*/commandTag=CreateCommandTag(parsetree->stmt);//创建命令标记,插入数据则为INSERTset_ps_display(commandTag,false);BeginCommand(commandTag,dest);//doNothing!/**Ifweareinanabortedtransaction,rejectallcommandsexcept*COMMIT/ABORT.Itisimportantthatthistestoccurbeforewetry*todoparseanalysis,rewrite,orplanning,sinceallthosephases*trytododatabaseaccesses,whichmayfailinabortstate.(It*mightbesafetoallowsomeadditionalutilitycommandsinthis*state,butnotmany...)*/if(IsAbortedTransactionBlockState()&&!IsTransactionExitStmt(parsetree->stmt))ereport(ERROR,(errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),errmsg("currenttransactionisaborted,""commandsignoreduntilendoftransactionblock"),errdetail_abort()));/*Makesureweareinatransactioncommand*/start_xact_command();//确认在事务中/**Ifusinganimplicittransactionblock,andwe'renotalreadyina*transactionblock,startanimplicitblocktoforcethisstatement*tobegroupedtogetherwithanyfollowingones.(Wemustdothis*eachtimethroughtheloop;otherwise,aCOMMIT/ROLLBACKinthe*listwouldcauselaterstatementstonotbegrouped.)*/if(use_implicit_block)BeginImplicitTransactionBlock();//隐式事务,进入事务块/*Ifwegotacancelsignalinparsingorpriorcommand,quit*/CHECK_FOR_INTERRUPTS();/**Setupasnapshotifparseanalysis/planningwillneedone.*/if(analyze_requires_snapshot(parsetree))//是否需要快照进行分析?增删改查均需要{PushActiveSnapshot(GetTransactionSnapshot());//snapshot_set=true;}/**OKtoanalyze,rewrite,andplanthisquery.**Switchtoappropriatecontextforconstructingquerytrees(again,*thesemustoutlivetheexecutioncontext).*/oldcontext=MemoryContextSwitchTo(MessageContext);//切换内存上下文querytree_list=pg_analyze_and_rewrite(parsetree,query_string,NULL,0,NULL);//根据分析树获得查询树,返回List(元素为Query)plantree_list=pg_plan_queries(querytree_list,CURSOR_OPT_PARALLEL_OK,NULL);//根据查询树获取计划树,返回List(元素为PlannedStmt)/*Donewiththesnapshotusedforparsing/planning*/if(snapshot_set)PopActiveSnapshot();///*Ifwegotacancelsignalinanalysisorplanning,quit*/CHECK_FOR_INTERRUPTS();/**Createunnamedportaltorunthequeryorqueriesin.Ifthere*alreadyisone,silentlydropit.*/portal=CreatePortal("",true,true);//创建匿名Portal变量/*Don'tdisplaytheportalinpg_cursors*/portal->visible=false;/**Wedon'thavetocopyanythingintotheportal,becauseeverything*wearepassinghereisinMessageContext,whichwilloutlivethe*portalanyway.*/PortalDefineQuery(portal,NULL,query_string,commandTag,plantree_list,NULL);//给Portal变量赋值/**Starttheportal.Noparametershere.*/PortalStart(portal,NULL,0,InvalidSnapshot);//为PortalRun作准备/**Selecttheappropriateoutputformat:textunlesswearedoinga*FETCHfromabinarycursor.(Prettygrottytohavetodothishere*---butitavoidsgrottinessinotherplaces.Ah,thejoysof*backwardcompatibility...)*/format=0;/*TEXTisdefault*/if(IsA(parsetree->stmt,FetchStmt)){FetchStmt*stmt=(FetchStmt*)parsetree->stmt;if(!stmt->ismove){Portalfportal=GetPortalByName(stmt->portalname);if(PortalIsValid(fportal)&&(fportal->cursorOptions&CURSOR_OPT_BINARY))format=1;/*BINARY*/}}PortalSetResultFormat(portal,1,&format);//设置结果返回的格式,默认为TEXT/**Nowwecancreatethedestinationreceiverobject.*/receiver=CreateDestReceiver(dest);//创建目标接收器(如使用psql则为:printtupDestReceiver)if(dest==DestRemote)SetRemoteDestReceiverParams(receiver,portal);/**Switchbacktotransactioncontextforexecution.*/MemoryContextSwitchTo(oldcontext);//切换回原内存上下文/**Runtheportaltocompletion,andthendropit(andthereceiver).*/(void)PortalRun(portal,FETCH_ALL,true,/*alwaystoplevel*/true,receiver,receiver,completionTag);//执行receiver->rDestroy(receiver);//执行完毕,销毁接收器PortalDrop(portal,false);//清除Portal中的资源&Portalif(lnext(parsetree_item)==NULL)//所有语句已执行完毕{/**Ifthisisthelastparsetreeofthequerystring,closedown*transactionstatementbeforereportingcommand-complete.This*issothatanyend-of-transactionerrorsarereportedbefore*thecommand-completemessageisissued,toavoidconfusing*clientswhowillexpecteitheracommand-completemessageoran*error,notoneandthentheother.Also,ifwe'reusingan*implicittransactionblock,wemustclosethatoutfirst.*/if(use_implicit_block)EndImplicitTransactionBlock();//结束事务finish_xact_command();//结束事务}elseif(IsA(parsetree->stmt,TransactionStmt))//事务语句?BEGIN/COMMIT/ABORT...{/**Ifthiswasatransactioncontrolstatement,commitit.Wewill*startanewxactcommandforthenextcommand.*/finish_xact_command();}else{/**WeneedaCommandCounterIncrementaftereveryquery,except*thosethatstartorendatransactionblock.*/CommandCounterIncrement();//命令+1(对应Tuple中的cid)}/**Tellclientthatwe'redonewiththisquery.Noteweemitexactly*oneEndCommandreportforeachrawparsetree,thusoneforeachSQL*commandtheclientsent,regardlessofrewriting.(Butacommand*abortedbyerrorwillnotsendanEndCommandreportatall.)*/EndCommand(completionTag,dest);//命令Done}/*endloopoverparsetrees*///所有语句结束/**Closedowntransactionstatement,ifoneisopen.(Thiswillonlydo*somethingiftheparsetreelistwasempty;otherwisethelastloop*iterationalreadydidit.)*/finish_xact_command();/**Iftherewerenoparsetrees,returnEmptyQueryResponsemessage.*/if(!parsetree_list)NullCommand(dest);/**Emitdurationloggingifappropriate.*/switch(check_log_duration(msec_str,was_logged)){case1:ereport(LOG,(errmsg("duration:%sms",msec_str),errhidestmt(true)));break;case2:ereport(LOG,(errmsg("duration:%smsstatement:%s",msec_str,query_string),errhidestmt(true),errdetail_execute(parsetree_list)));break;}if(save_log_statement_stats)ShowUsage("QUERYSTATISTICS");TRACE_POSTGRESQL_QUERY_DONE(query_string);debug_query_string=NULL;}二、基础信息
exec_simple_query函数使用的数据结构、宏定义以及依赖的函数等。
数据结构/宏定义
*1、whereToSendOutput *
/*Note:whereToSendOutputisinitializedforthebootstrap/standalonecase*/CommandDestwhereToSendOutput=DestDebug;/*----------------*CommandDestisasimplisticmeansofidentifyingthedesired*destination.Somedaythiswillprobablyneedtobeimproved.**Note:onlythevaluesDestNone,DestDebug,DestRemotearelegalforthe*globalvariablewhereToSendOutput.Theothervaluesmaybeused*asthedestinationforindividualcommands.*----------------*/typedefenum{DestNone,/*resultsarediscarded*/DestDebug,/*resultsgotodebuggingoutput*/DestRemote,/*resultssenttofrontendprocess*/DestRemoteExecute,/*senttofrontend,inExecutecommand*/DestRemoteSimple,/*senttofrontend,w/nocatalogaccess*/DestSPI,/*resultssenttoSPImanager*/DestTuplestore,/*resultssenttoTuplestore*/DestIntoRel,/*resultssenttorelation(SELECTINTO)*/DestCopyOut,/*resultssenttoCOPYTOcode*/DestSQLFunction,/*resultssenttoSQL-languagefuncmgr*/DestTransientRel,/*resultssenttotransientrelation*/DestTupleQueue/*resultssenttotuplequeue*/}CommandDest;
2、RawStmt
/**RawStmt---containerforanyonestatement'srawparsetree**ParseanalysisconvertsarawparsetreeheadedbyaRawStmtnodeinto*ananalyzedstatementheadedbyaQuerynode.Foroptimizablestatements,*theconversioniscomplex.Forutilitystatements,theparserusuallyjust*transferstherawparsetree(sansRawStmt)intotheutilityStmtfieldof*theQuerynode,andalltheusefulworkhappensatexecutiontime.**stmt_location/stmt_lenidentifytheportionofthesourcetextstring*containingthisrawstatement(usefulformulti-statementstrings).*/typedefstructRawStmt{NodeTagtype;Node*stmt;/*rawparsetree*/intstmt_location;/*startlocation,or-1ifunknown*/intstmt_len;/*lengthinbytes;0means"restofstring"*/}RawStmt;
3、Query
//在解析查询语句时再深入解析/******************************************************************************QueryTree*****************************************************************************//**Query-*ParseanalysisturnsallstatementsintoaQuerytree*forfurtherprocessingbytherewriterandplanner.**Utilitystatements(i.e.non-optimizablestatements)havethe*utilityStmtfieldset,andtherestoftheQueryismostlydummy.**PlanningconvertsaQuerytreeintoaPlantreeheadedbyaPlannedStmt*node---theQuerystructureisnotusedbytheexecutor.*/typedefstructQuery{NodeTagtype;CmdTypecommandType;/*select|insert|update|delete|utility*/QuerySourcequerySource;/*wheredidIcomefrom?*/uint64queryId;/*queryidentifier(canbesetbyplugins)*/boolcanSetTag;/*doIsetthecommandresulttag?*/Node*utilityStmt;/*non-nullifcommandType==CMD_UTILITY*/intresultRelation;/*rtableindexoftargetrelationfor*INSERT/UPDATE/DELETE;0forSELECT*/boolhasAggs;/*hasaggregatesintlistorhavingQual*/boolhasWindowFuncs;/*haswindowfunctionsintlist*/boolhasTargetSRFs;/*hasset-returningfunctionsintlist*/boolhasSubLinks;/*hassubquerySubLink*/boolhasDistinctOn;/*distinctClauseisfromDISTINCTON*/boolhasRecursive;/*WITHRECURSIVEwasspecified*/boolhasModifyingCTE;/*hasINSERT/UPDATE/DELETEinWITH*/boolhasForUpdate;/*FOR[KEY]UPDATE/SHAREwasspecified*/boolhasRowSecurity;/*rewriterhasappliedsomeRLSpolicy*/List*cteList;/*WITHlist(ofCommonTableExpr's)*/List*rtable;/*listofrangetableentries*/FromExpr*jointree;/*tablejointree(FROMandWHEREclauses)*/List*targetList;/*targetlist(ofTargetEntry)*/OverridingKindoverride;/*OVERRIDINGclause*/OnConflictExpr*onConflict;/*ONCONFLICTDO[NOTHING|UPDATE]*/List*returningList;/*return-valueslist(ofTargetEntry)*/List*groupClause;/*alistofSortGroupClause's*/List*groupingSets;/*alistofGroupingSet'sifpresent*/Node*havingQual;/*qualificationsappliedtogroups*/List*windowClause;/*alistofWindowClause's*/List*distinctClause;/*alistofSortGroupClause's*/List*sortClause;/*alistofSortGroupClause's*/Node*limitOffset;/*#ofresulttuplestoskip(int8expr)*/Node*limitCount;/*#ofresulttuplestoreturn(int8expr)*/List*rowMarks;/*alistofRowMarkClause's*/Node*setOperations;/*set-operationtreeifthisistoplevelof*aUNION/INTERSECT/EXCEPTquery*/List*constraintDeps;/*alistofpg_constraintOIDsthatthequery*dependsontobesemanticallyvalid*/List*withCheckOptions;/*alistofWithCheckOption's,whichare*onlyaddedduringrewriteandtherefore*arenotwrittenoutaspartofQuery.*//**Thefollowingtwofieldsidentifytheportionofthesourcetextstring*containingthisquery.Theyaretypicallyonlypopulatedintop-level*Queries,notinsub-queries.Whennotset,theymightbothbezero,or*bothbe-1meaning"unknown".*/intstmt_location;/*startlocation,or-1ifunknown*/intstmt_len;/*lengthinbytes;0means"restofstring"*/}Query;
4、ParseState
/**Functionsignaturesforparserhooks*/typedefstructParseStateParseState;typedefNode*(*PreParseColumnRefHook)(ParseState*pstate,ColumnRef*cref);typedefNode*(*PostParseColumnRefHook)(ParseState*pstate,ColumnRef*cref,Node*var);typedefNode*(*ParseParamRefHook)(ParseState*pstate,ParamRef*pref);typedefNode*(*CoerceParamHook)(ParseState*pstate,Param*param,OidtargetTypeId,int32targetTypeMod,intlocation);/**Stateinformationusedduringparseanalysis**parentParseState:NULLinatop-levelParseState.Whenparsingasubquery,*linkstocurrentparsestateofouterquery.**p_sourcetext:sourcestringthatgeneratedtherawparsetreebeing*analyzed,orNULLifnotavailable.(Thestringisusedonlyto*generatecursorpositionsinerrormessages:weneedittoconvert*byte-wiselocationsinparsestructurestocharacter-wisecursor*positions.)**p_rtable:listofRTEsthatwillbecometherangetableofthequery.*Notethatneitherrelnamenorrefnameoftheseentriesarenecessarily*unique;searchingthertablebynameisabadidea.**p_joinexprs:listofJoinExprnodesassociatedwithp_rtableentries.*Thisisone-for-onewithp_rtable,butcontainsNULLsfornon-join*RTEs,andmaybeshorterthanp_rtableifthelastRTE(s)aren'tjoins.**p_joinlist:listofjoinitems(RangeTblRefandJoinExprnodes)that*willbecomethefromlistofthequery'stop-levelFromExprnode.**p_namespace:listofParseNamespaceItemsthatrepresentsthecurrent*namespacefortableandcolumnlookup.(TheRTEslistedheremaybejust*asubsetofthewholertable.SeeParseNamespaceItemcommentsbelow.)**p_lateral_active:trueifwearecurrentlyparsingaLATERALsubexpression*ofthisparselevel.Thismakesp_lateral_onlynamespaceitemsvisible,*whereastheyarenotvisiblewhenp_lateral_activeisFALSE.**p_ctenamespace:listofCommonTableExprs(WITHitems)thatarevisible*atthemoment.Thisisentirelydifferentfromp_namespacebecauseaCTE*isnotanRTE,rather"visibility"meansyoucouldmakeanRTEfromit.**p_future_ctes:listofCommonTableExprs(WITHitems)thatarenotyet*visibleduetoscoperules.Thisisusedtohelpimproveerrormessages.**p_parent_cte:CommonTableExprthatimmediatelycontainsthecurrentquery,*ifany.**p_target_relation:targetrelation,ifqueryisINSERT,UPDATE,orDELETE.**p_target_rangetblentry:targetrelation'sentryinthertablelist.**p_is_insert:truetoprocessassignmentexpressionslikeINSERT,false*toprocessthemlikeUPDATE.(Notethiscanchangeintra-statement,for*caseslikeINSERTONCONFLICTUPDATE.)**p_windowdefs:listofWindowDefsrepresentingWINDOWandOVERclauses.*Wecollectthesewhiletransformingexpressionsandthentransformthem*afterwards(sothatanyresjunktlistitemsneededforthesort/group*clausesendupattheendofthequerytlist).AWindowDef'slocationin*thislist,countingfrom1,isthewinrefnumbertousetoreferenceit.**p_expr_kind:kindofexpressionwe'recurrentlyparsing,asperenumabove;*EXPR_KIND_NONEwhennotinanexpression.**p_next_resno:nextTargetEntry.resnotoassign,startingfrom1.**p_multiassign_exprs:partially-processedMultiAssignRefsourceexpressions.**p_locking_clause:query'sFORUPDATE/FORSHAREclause,ifany.**p_locked_from_parent:trueifparentquerylevelappliesFORUPDATE/SHARE*tothissubqueryasawhole.**p_resolve_unknowns:resolveunknown-typeSELECToutputcolumnsastypeTEXT*(thisistruebydefault).**p_hasAggs,p_hasWindowFuncs,etc:trueifwe'vefoundanyoftheindicated*constructsinthequery.**p_last_srf:theset-returningFuncExprorOpExprmostrecentlyfoundin*thequery,orNULLifnone.**p_pre_columnref_hook,etc:optionalparserhookfunctionsformodifyingthe*interpretationofColumnRefsandParamRefs.**p_ref_hook_state:passthroughstatefortheparserhookfunctions.*/structParseState{structParseState*parentParseState;/*stacklink*/constchar*p_sourcetext;/*sourcetext,orNULLifnotavailable*/List*p_rtable;/*rangetablesofar*/List*p_joinexprs;/*JoinExprsforRTE_JOINp_rtableentries*/List*p_joinlist;/*joinitemssofar(willbecomeFromExpr*node'sfromlist)*/List*p_namespace;/*currently-referenceableRTEs(Listof*ParseNamespaceItem)*/boolp_lateral_active;/*p_lateral_onlyitemsvisible?*/List*p_ctenamespace;/*currentnamespaceforcommontableexprs*/List*p_future_ctes;/*commontableexprsnotyetinnamespace*/CommonTableExpr*p_parent_cte;/*thisquery'scontainingCTE*/Relationp_target_relation;/*INSERT/UPDATE/DELETEtargetrel*/RangeTblEntry*p_target_rangetblentry;/*targetrel'sRTE*/boolp_is_insert;/*processassignmentlikeINSERTnotUPDATE*/List*p_windowdefs;/*rawrepresentationsofwindowclauses*/ParseExprKindp_expr_kind;/*whatkindofexpressionwe'reparsing*/intp_next_resno;/*nexttargetlistresnotoassign*/List*p_multiassign_exprs;/*junktlistentriesformultiassign*/List*p_locking_clause;/*rawFORUPDATE/FORSHAREinfo*/boolp_locked_from_parent;/*parenthasmarkedthissubquery*withFORUPDATE/FORSHARE*/boolp_resolve_unknowns;/*resolveunknown-typeSELECToutputsas*typetext*/QueryEnvironment*p_queryEnv;/*currenv,inclrefstoenclosingenv*//*Flagstellingaboutthingsfoundinthequery:*/boolp_hasAggs;boolp_hasWindowFuncs;boolp_hasTargetSRFs;boolp_hasSubLinks;boolp_hasModifyingCTE;Node*p_last_srf;/*mostrecentset-returningfunc/opfound*//**Optionalhookfunctionsforparsercallbacks.Thesearenullunless*setupbythecallerofmake_parsestate.*/PreParseColumnRefHookp_pre_columnref_hook;PostParseColumnRefHookp_post_columnref_hook;ParseParamRefHookp_paramref_hook;CoerceParamHookp_coerce_param_hook;void*p_ref_hook_state;/*commonpassthroughlinkforabove*/};
5、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;
6、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;
7、全局变量定义
boollog_parser_stats=false;boollog_planner_stats=false;boollog_executor_stats=false;boollog_statement_stats=false;/*thisissortofallthreeabove*together*/
依赖的函数
1、start_xact_command
/**Convenienceroutinesforstarting/committingasinglecommand.*/staticvoidstart_xact_command(void){if(!xact_started){StartTransactionCommand();//开启事务xact_started=true;}/**Startstatementtimeoutifnecessary.Notethatthis'llintentionally*notresettheclockonanalreadystartedtimeout,toavoidthetiming*overheadwhenstart_xact_command()isinvokedrepeatedly,withoutan*intercedingfinish_xact_command()(e.g.parse/bind/execute).Ifthat's*notdesired,thetimeouthastobedisabledexplicitly.*/enable_statement_timeout();}/**StartTransactionCommand*/voidStartTransactionCommand(void){TransactionStates=CurrentTransactionState;switch(s->blockState){/**ifwearen'tinatransactionblock,wejustdoourusualstart*transaction.*/caseTBLOCK_DEFAULT:StartTransaction();s->blockState=TBLOCK_STARTED;break;/**Wearesomewhereinatransactionblockorsubtransactionand*abouttostartanewcommand.Fornowwedonothing,but*somedaywemaydocommand-localresourceinitialization.(Note*thatanyneededCommandCounterIncrementwasdonebythe*previousCommitTransactionCommand.)*/caseTBLOCK_INPROGRESS:caseTBLOCK_IMPLICIT_INPROGRESS:caseTBLOCK_SUBINPROGRESS:break;/**Hereweareinafailedtransactionblock(oneofthecommands*causedanabort)sowedonothingbutremainintheabort*state.EventuallywewillgetaROLLBACKcommandwhichwill*getusoutofthisstate.(Itisuptoothercodetoensure*thatnocommandsotherthanROLLBACKwillbeprocessedinthese*states.)*/caseTBLOCK_ABORT:caseTBLOCK_SUBABORT:break;/*Thesecasesareinvalid.*/caseTBLOCK_STARTED:caseTBLOCK_BEGIN:caseTBLOCK_PARALLEL_INPROGRESS:caseTBLOCK_SUBBEGIN:caseTBLOCK_END:caseTBLOCK_SUBRELEASE:caseTBLOCK_SUBCOMMIT:caseTBLOCK_ABORT_END:caseTBLOCK_SUBABORT_END:caseTBLOCK_ABORT_PENDING:caseTBLOCK_SUBABORT_PENDING:caseTBLOCK_SUBRESTART:caseTBLOCK_SUBABORT_RESTART:caseTBLOCK_PREPARE:elog(ERROR,"StartTransactionCommand:unexpectedstate%s",BlockStateAsString(s->blockState));break;}/**WemustswitchtoCurTransactionContextbeforereturning.Thisis*alreadydoneifwecalledStartTransaction,otherwisenot.*/Assert(CurTransactionContext!=NULL);MemoryContextSwitchTo(CurTransactionContext);//内存上下文切换至当前事务上下文}
2、drop_unnamed_stmt
/*Releaseanyexistingunnamedpreparedstatement*/staticvoiddrop_unnamed_stmt(void){/*paranoiatoavoidadanglingpointerincaseoferror*/if(unnamed_stmt_psrc){CachedPlanSource*psrc=unnamed_stmt_psrc;unnamed_stmt_psrc=NULL;DropCachedPlan(psrc);}}/**Ifanunnamedpreparedstatementexists,it'sstoredhere.*Wekeepitseparatefromthehashtablekeptbycommands/prepare.c*inordertoreduceoverheadforshort-livedqueries.*/staticCachedPlanSource*unnamed_stmt_psrc=NULL;
3、pg_parse_query
//执行语句解析,返回RawStmtnodes(List)/**Dorawparsing(only).**Alistofparsetrees(RawStmtnodes)isreturned,sincetheremightbe*multiplecommandsinthegivenstring.**NOTE:forinteractivequeries,itisimportanttokeepthisroutine*separatefromtheanalysis&rewritestages.Analysisandrewriting*cannotbedoneinanabortedtransaction,sincetheyrequireaccessto*databasetables.So,werelyontherawparsertodeterminewhether*we'veseenaCOMMITorABORTcommand;whenweareinabortstate,other*commandsarenotprocessedanyfurtherthantherawparsestage.*/List*pg_parse_query(constchar*query_string){List*raw_parsetree_list;TRACE_POSTGRESQL_QUERY_PARSE_START(query_string);if(log_parser_stats)ResetUsage();raw_parsetree_list=raw_parser(query_string);if(log_parser_stats)ShowUsage("PARSERSTATISTICS");#ifdefCOPY_PARSE_PLAN_TREES/*Optionaldebuggingcheck:passrawparsetreesthroughcopyObject()*/{List*new_list=copyObject(raw_parsetree_list);/*ThischecksbothcopyObject()andtheequal()routines...*/if(!equal(new_list,raw_parsetree_list))elog(WARNING,"copyObject()failedtoproduceanequalrawparsetree");elseraw_parsetree_list=new_list;}#endifTRACE_POSTGRESQL_QUERY_PARSE_DONE(query_string);returnraw_parsetree_list;}
4、raw_parser
//执行词法和语法分析,返回rawparsetrees(List,其中的元素是RawStmt)/**raw_parser*Givenaqueryinstringform,dolexicalandgrammaticalanalysis.**Returnsalistofraw(un-analyzed)parsetrees.Theimmediateelements*ofthelistarealwaysRawStmtnodes.*/List*raw_parser(constchar*str){core_yyscan_tyyscanner;base_yy_extra_typeyyextra;intyyresult;/*initializetheflexscanner*/yyscanner=scanner_init(str,&yyextra.core_yy_extra,ScanKeywords,NumScanKeywords);/*base_yylex()onlyneedsthismuchinitialization*/yyextra.have_lookahead=false;/*initializethebisonparser*/parser_init(&yyextra);/*Parse!*/yyresult=base_yyparse(yyscanner);/*Cleanup(releasememory)*/scanner_finish(yyscanner);if(yyresult)/*error*/returnNIL;returnyyextra.parsetree;}
5、CreateCommandTag
//创建命令Tag//基本上,所有的PG命令类型都可以在这里找到/**CreateCommandTag*utilitytogetastringrepresentationofthecommandoperation,*giveneitheraraw(un-analyzed)parsetree,ananalyzedQuery,*oraPlannedStmt.**Thismusthandleallcommandtypes,butsincethevastmajority*of'emareutilitycommands,itseemssensibletokeepithere.**NB:allresultstringsmustbeshorterthanCOMPLETION_TAG_BUFSIZE.*Also,theresultmustpointatatrueconstant(permanentstorage).*/constchar*CreateCommandTag(Node*parsetree){constchar*tag;switch(nodeTag(parsetree)){/*recurseifwe'regivenaRawStmt*/caseT_RawStmt:tag=CreateCommandTag(((RawStmt*)parsetree)->stmt);break;/*rawplannablequeries*/caseT_InsertStmt:tag="INSERT";break;caseT_DeleteStmt:tag="DELETE";break;caseT_UpdateStmt:tag="UPDATE";break;caseT_SelectStmt:tag="SELECT";break;/*utilitystatements---samewhetherraworcooked*/caseT_TransactionStmt:{TransactionStmt*stmt=(TransactionStmt*)parsetree;switch(stmt->kind){caseTRANS_STMT_BEGIN:tag="BEGIN";break;caseTRANS_STMT_START:tag="STARTTRANSACTION";break;caseTRANS_STMT_COMMIT:tag="COMMIT";break;caseTRANS_STMT_ROLLBACK:caseTRANS_STMT_ROLLBACK_TO:tag="ROLLBACK";break;caseTRANS_STMT_SAVEPOINT:tag="SAVEPOINT";break;caseTRANS_STMT_RELEASE:tag="RELEASE";break;caseTRANS_STMT_PREPARE:tag="PREPARETRANSACTION";break;caseTRANS_STMT_COMMIT_PREPARED:tag="COMMITPREPARED";break;caseTRANS_STMT_ROLLBACK_PREPARED:tag="ROLLBACKPREPARED";break;default:tag="???";break;}}break;caseT_DeclareCursorStmt:tag="DECLARECURSOR";break;caseT_ClosePortalStmt:{ClosePortalStmt*stmt=(ClosePortalStmt*)parsetree;if(stmt->portalname==NULL)tag="CLOSECURSORALL";elsetag="CLOSECURSOR";}break;caseT_FetchStmt:{FetchStmt*stmt=(FetchStmt*)parsetree;tag=(stmt->ismove)?"MOVE":"FETCH";}break;caseT_CreateDomainStmt:tag="CREATEDOMAIN";break;caseT_CreateSchemaStmt:tag="CREATESCHEMA";break;caseT_CreateStmt:tag="CREATETABLE";break;caseT_CreateTableSpaceStmt:tag="CREATETABLESPACE";break;caseT_DropTableSpaceStmt:tag="DROPTABLESPACE";break;caseT_AlterTableSpaceOptionsStmt:tag="ALTERTABLESPACE";break;caseT_CreateExtensionStmt:tag="CREATEEXTENSION";break;caseT_AlterExtensionStmt:tag="ALTEREXTENSION";break;caseT_AlterExtensionContentsStmt:tag="ALTEREXTENSION";break;caseT_CreateFdwStmt:tag="CREATEFOREIGNDATAWRAPPER";break;caseT_AlterFdwStmt:tag="ALTERFOREIGNDATAWRAPPER";break;caseT_CreateForeignServerStmt:tag="CREATESERVER";break;caseT_AlterForeignServerStmt:tag="ALTERSERVER";break;caseT_CreateUserMappingStmt:tag="CREATEUSERMAPPING";break;caseT_AlterUserMappingStmt:tag="ALTERUSERMAPPING";break;caseT_DropUserMappingStmt:tag="DROPUSERMAPPING";break;caseT_CreateForeignTableStmt:tag="CREATEFOREIGNTABLE";break;caseT_ImportForeignSchemaStmt:tag="IMPORTFOREIGNSCHEMA";break;caseT_DropStmt:switch(((DropStmt*)parsetree)->removeType){caseOBJECT_TABLE:tag="DROPTABLE";break;caseOBJECT_SEQUENCE:tag="DROPSEQUENCE";break;caseOBJECT_VIEW:tag="DROPVIEW";break;caseOBJECT_MATVIEW:tag="DROPMATERIALIZEDVIEW";break;caseOBJECT_INDEX:tag="DROPINDEX";break;caseOBJECT_TYPE:tag="DROPTYPE";break;caseOBJECT_DOMAIN:tag="DROPDOMAIN";break;caseOBJECT_COLLATION:tag="DROPCOLLATION";break;caseOBJECT_CONVERSION:tag="DROPCONVERSION";break;caseOBJECT_SCHEMA:tag="DROPSCHEMA";break;caseOBJECT_TSPARSER:tag="DROPTEXTSEARCHPARSER";break;caseOBJECT_TSDICTIONARY:tag="DROPTEXTSEARCHDICTIONARY";break;caseOBJECT_TSTEMPLATE:tag="DROPTEXTSEARCHTEMPLATE";break;caseOBJECT_TSCONFIGURATION:tag="DROPTEXTSEARCHCONFIGURATION";break;caseOBJECT_FOREIGN_TABLE:tag="DROPFOREIGNTABLE";break;caseOBJECT_EXTENSION:tag="DROPEXTENSION";break;caseOBJECT_FUNCTION:tag="DROPFUNCTION";break;caseOBJECT_PROCEDURE:tag="DROPPROCEDURE";break;caseOBJECT_ROUTINE:tag="DROPROUTINE";break;caseOBJECT_AGGREGATE:tag="DROPAGGREGATE";break;caseOBJECT_OPERATOR:tag="DROPOPERATOR";break;caseOBJECT_LANGUAGE:tag="DROPLANGUAGE";break;caseOBJECT_CAST:tag="DROPCAST";break;caseOBJECT_TRIGGER:tag="DROPTRIGGER";break;caseOBJECT_EVENT_TRIGGER:tag="DROPEVENTTRIGGER";break;caseOBJECT_RULE:tag="DROPRULE";break;caseOBJECT_FDW:tag="DROPFOREIGNDATAWRAPPER";break;caseOBJECT_FOREIGN_SERVER:tag="DROPSERVER";break;caseOBJECT_OPCLASS:tag="DROPOPERATORCLASS";break;caseOBJECT_OPFAMILY:tag="DROPOPERATORFAMILY";break;caseOBJECT_POLICY:tag="DROPPOLICY";break;caseOBJECT_TRANSFORM:tag="DROPTRANSFORM";break;caseOBJECT_ACCESS_METHOD:tag="DROPACCESSMETHOD";break;caseOBJECT_PUBLICATION:tag="DROPPUBLICATION";break;caseOBJECT_STATISTIC_EXT:tag="DROPSTATISTICS";break;default:tag="???";}break;caseT_TruncateStmt:tag="TRUNCATETABLE";break;caseT_CommentStmt:tag="COMMENT";break;caseT_SecLabelStmt:tag="SECURITYLABEL";break;caseT_CopyStmt:tag="COPY";break;caseT_RenameStmt:tag=AlterObjectTypeCommandTag(((RenameStmt*)parsetree)->renameType);break;caseT_AlterObjectDependsStmt:tag=AlterObjectTypeCommandTag(((AlterObjectDependsStmt*)parsetree)->objectType);break;caseT_AlterObjectSchemaStmt:tag=AlterObjectTypeCommandTag(((AlterObjectSchemaStmt*)parsetree)->objectType);break;caseT_AlterOwnerStmt:tag=AlterObjectTypeCommandTag(((AlterOwnerStmt*)parsetree)->objectType);break;caseT_AlterTableMoveAllStmt:tag=AlterObjectTypeCommandTag(((AlterTableMoveAllStmt*)parsetree)->objtype);break;caseT_AlterTableStmt:tag=AlterObjectTypeCommandTag(((AlterTableStmt*)parsetree)->relkind);break;caseT_AlterDomainStmt:tag="ALTERDOMAIN";break;caseT_AlterFunctionStmt:switch(((AlterFunctionStmt*)parsetree)->objtype){caseOBJECT_FUNCTION:tag="ALTERFUNCTION";break;caseOBJECT_PROCEDURE:tag="ALTERPROCEDURE";break;caseOBJECT_ROUTINE:tag="ALTERROUTINE";break;default:tag="???";}break;caseT_GrantStmt:{GrantStmt*stmt=(GrantStmt*)parsetree;tag=(stmt->is_grant)?"GRANT":"REVOKE";}break;caseT_GrantRoleStmt:{GrantRoleStmt*stmt=(GrantRoleStmt*)parsetree;tag=(stmt->is_grant)?"GRANTROLE":"REVOKEROLE";}break;caseT_AlterDefaultPrivilegesStmt:tag="ALTERDEFAULTPRIVILEGES";break;caseT_DefineStmt:switch(((DefineStmt*)parsetree)->kind){caseOBJECT_AGGREGATE:tag="CREATEAGGREGATE";break;caseOBJECT_OPERATOR:tag="CREATEOPERATOR";break;caseOBJECT_TYPE:tag="CREATETYPE";break;caseOBJECT_TSPARSER:tag="CREATETEXTSEARCHPARSER";break;caseOBJECT_TSDICTIONARY:tag="CREATETEXTSEARCHDICTIONARY";break;caseOBJECT_TSTEMPLATE:tag="CREATETEXTSEARCHTEMPLATE";break;caseOBJECT_TSCONFIGURATION:tag="CREATETEXTSEARCHCONFIGURATION";break;caseOBJECT_COLLATION:tag="CREATECOLLATION";break;caseOBJECT_ACCESS_METHOD:tag="CREATEACCESSMETHOD";break;default:tag="???";}break;caseT_CompositeTypeStmt:tag="CREATETYPE";break;caseT_CreateEnumStmt:tag="CREATETYPE";break;caseT_CreateRangeStmt:tag="CREATETYPE";break;caseT_AlterEnumStmt:tag="ALTERTYPE";break;caseT_ViewStmt:tag="CREATEVIEW";break;caseT_CreateFunctionStmt:if(((CreateFunctionStmt*)parsetree)->is_procedure)tag="CREATEPROCEDURE";elsetag="CREATEFUNCTION";break;caseT_IndexStmt:tag="CREATEINDEX";break;caseT_RuleStmt:tag="CREATERULE";break;caseT_CreateSeqStmt:tag="CREATESEQUENCE";break;caseT_AlterSeqStmt:tag="ALTERSEQUENCE";break;caseT_DoStmt:tag="DO";break;caseT_CreatedbStmt:tag="CREATEDATABASE";break;caseT_AlterDatabaseStmt:tag="ALTERDATABASE";break;caseT_AlterDatabaseSetStmt:tag="ALTERDATABASE";break;caseT_DropdbStmt:tag="DROPDATABASE";break;caseT_NotifyStmt:tag="NOTIFY";break;caseT_ListenStmt:tag="LISTEN";break;caseT_UnlistenStmt:tag="UNLISTEN";break;caseT_LoadStmt:tag="LOAD";break;caseT_CallStmt:tag="CALL";break;caseT_ClusterStmt:tag="CLUSTER";break;caseT_VacuumStmt:if(((VacuumStmt*)parsetree)->options&VACOPT_VACUUM)tag="VACUUM";elsetag="ANALYZE";break;caseT_ExplainStmt:tag="EXPLAIN";break;caseT_CreateTableAsStmt:switch(((CreateTableAsStmt*)parsetree)->relkind){caseOBJECT_TABLE:if(((CreateTableAsStmt*)parsetree)->is_select_into)tag="SELECTINTO";elsetag="CREATETABLEAS";break;caseOBJECT_MATVIEW:tag="CREATEMATERIALIZEDVIEW";break;default:tag="???";}break;caseT_RefreshMatViewStmt:tag="REFRESHMATERIALIZEDVIEW";break;caseT_AlterSystemStmt:tag="ALTERSYSTEM";break;caseT_VariableSetStmt:switch(((VariableSetStmt*)parsetree)->kind){caseVAR_SET_VALUE:caseVAR_SET_CURRENT:caseVAR_SET_DEFAULT:caseVAR_SET_MULTI:tag="SET";break;caseVAR_RESET:caseVAR_RESET_ALL:tag="RESET";break;default:tag="???";}break;caseT_VariableShowStmt:tag="SHOW";break;caseT_DiscardStmt:switch(((DiscardStmt*)parsetree)->target){caseDISCARD_ALL:tag="DISCARDALL";break;caseDISCARD_PLANS:tag="DISCARDPLANS";break;caseDISCARD_TEMP:tag="DISCARDTEMP";break;caseDISCARD_SEQUENCES:tag="DISCARDSEQUENCES";break;default:tag="???";}break;caseT_CreateTransformStmt:tag="CREATETRANSFORM";break;caseT_CreateTrigStmt:tag="CREATETRIGGER";break;caseT_CreateEventTrigStmt:tag="CREATEEVENTTRIGGER";break;caseT_AlterEventTrigStmt:tag="ALTEREVENTTRIGGER";break;caseT_CreatePLangStmt:tag="CREATELANGUAGE";break;caseT_CreateRoleStmt:tag="CREATEROLE";break;caseT_AlterRoleStmt:tag="ALTERROLE";break;caseT_AlterRoleSetStmt:tag="ALTERROLE";break;caseT_DropRoleStmt:tag="DROPROLE";break;caseT_DropOwnedStmt:tag="DROPOWNED";break;caseT_ReassignOwnedStmt:tag="REASSIGNOWNED";break;caseT_LockStmt:tag="LOCKTABLE";break;caseT_ConstraintsSetStmt:tag="SETCONSTRAINTS";break;caseT_CheckPointStmt:tag="CHECKPOINT";break;caseT_ReindexStmt:tag="REINDEX";break;caseT_CreateConversionStmt:tag="CREATECONVERSION";break;caseT_CreateCastStmt:tag="CREATECAST";break;caseT_CreateOpClassStmt:tag="CREATEOPERATORCLASS";break;caseT_CreateOpFamilyStmt:tag="CREATEOPERATORFAMILY";break;caseT_AlterOpFamilyStmt:tag="ALTEROPERATORFAMILY";break;caseT_AlterOperatorStmt:tag="ALTEROPERATOR";break;caseT_AlterTSDictionaryStmt:tag="ALTERTEXTSEARCHDICTIONARY";break;caseT_AlterTSConfigurationStmt:tag="ALTERTEXTSEARCHCONFIGURATION";break;caseT_CreatePolicyStmt:tag="CREATEPOLICY";break;caseT_AlterPolicyStmt:tag="ALTERPOLICY";break;caseT_CreateAmStmt:tag="CREATEACCESSMETHOD";break;caseT_CreatePublicationStmt:tag="CREATEPUBLICATION";break;caseT_AlterPublicationStmt:tag="ALTERPUBLICATION";break;caseT_CreateSubscriptionStmt:tag="CREATESUBSCRIPTION";break;caseT_AlterSubscriptionStmt:tag="ALTERSUBSCRIPTION";break;caseT_DropSubscriptionStmt:tag="DROPSUBSCRIPTION";break;caseT_AlterCollationStmt:tag="ALTERCOLLATION";break;caseT_PrepareStmt:tag="PREPARE";break;caseT_ExecuteStmt:tag="EXECUTE";break;caseT_CreateStatsStmt:tag="CREATESTATISTICS";break;caseT_DeallocateStmt:{DeallocateStmt*stmt=(DeallocateStmt*)parsetree;if(stmt->name==NULL)tag="DEALLOCATEALL";elsetag="DEALLOCATE";}break;/*already-plannedqueries*/caseT_PlannedStmt:{PlannedStmt*stmt=(PlannedStmt*)parsetree;switch(stmt->commandType){caseCMD_SELECT:/**Wetakealittleextracareheresothattheresult*willbeusefulforcomplaintsaboutread-only*statements*/if(stmt->rowMarks!=NIL){/*not100%butprobablycloseenough*/switch(((PlanRowMark*)linitial(stmt->rowMarks))->strength){caseLCS_FORKEYSHARE:tag="SELECTFORKEYSHARE";break;caseLCS_FORSHARE:tag="SELECTFORSHARE";break;caseLCS_FORNOKEYUPDATE:tag="SELECTFORNOKEYUPDATE";break;caseLCS_FORUPDATE:tag="SELECTFORUPDATE";break;default:tag="SELECT";break;}}elsetag="SELECT";break;caseCMD_UPDATE:tag="UPDATE";break;caseCMD_INSERT:tag="INSERT";break;caseCMD_DELETE:tag="DELETE";break;caseCMD_UTILITY:tag=CreateCommandTag(stmt->utilityStmt);break;default:elog(WARNING,"unrecognizedcommandType:%d",(int)stmt->commandType);tag="???";break;}}break;/*parsed-and-rewritten-but-not-plannedqueries*/caseT_Query:{Query*stmt=(Query*)parsetree;switch(stmt->commandType){caseCMD_SELECT:/**Wetakealittleextracareheresothattheresult*willbeusefulforcomplaintsaboutread-only*statements*/if(stmt->rowMarks!=NIL){/*not100%butprobablycloseenough*/switch(((RowMarkClause*)linitial(stmt->rowMarks))->strength){caseLCS_FORKEYSHARE:tag="SELECTFORKEYSHARE";break;caseLCS_FORSHARE:tag="SELECTFORSHARE";break;caseLCS_FORNOKEYUPDATE:tag="SELECTFORNOKEYUPDATE";break;caseLCS_FORUPDATE:tag="SELECTFORUPDATE";break;default:tag="???";break;}}elsetag="SELECT";break;caseCMD_UPDATE:tag="UPDATE";break;caseCMD_INSERT:tag="INSERT";break;caseCMD_DELETE:tag="DELETE";break;caseCMD_UTILITY:tag=CreateCommandTag(stmt->utilityStmt);break;default:elog(WARNING,"unrecognizedcommandType:%d",(int)stmt->commandType);tag="???";break;}}break;default:elog(WARNING,"unrecognizednodetype:%d",(int)nodeTag(parsetree));tag="???";break;}returntag;}
6、BeginCommand
/*----------------*BeginCommand-initializethedestinationatstartofcommand*----------------*/voidBeginCommand(constchar*commandTag,CommandDestdest){/*Nothingtodoatpresent*/}
7、analyze_requires_snapshot
//是否需要快照?//增删改查均需要/**analyze_requires_snapshot*Returnstrueifasnapshotmustbesetbeforedoingparseanalysis*onthegivenrawparsetree.**ClassificationhereshouldmatchtransformStmt().*/boolanalyze_requires_snapshot(RawStmt*parseTree){boolresult;switch(nodeTag(parseTree->stmt)){/**Optimizablestatements*/caseT_InsertStmt:caseT_DeleteStmt:caseT_UpdateStmt:caseT_SelectStmt:result=true;break;/**Specialcases*/caseT_DeclareCursorStmt:caseT_ExplainStmt:caseT_CreateTableAsStmt:/*yes,becausewemustanalyzethecontainedstatement*/result=true;break;default:/*otherutilitystatementsdon'thaveanyrealparseanalysis*/result=false;break;}returnresult;}
8、pg_analyze_and_rewrite
/**Givenarawparsetree(gram.youtput),andoptionallyinformationabout*typesofparametersymbols($n),performparseanalysisandrulerewriting.**AlistofQuerynodesisreturned,sinceeithertheanalyzerorthe*rewritermightexpandonequerytoseveral.**NOTE:forreasonsmentionedabove,thismustbeseparatefromrawparsing.*/List*pg_analyze_and_rewrite(RawStmt*parsetree,constchar*query_string,Oid*paramTypes,intnumParams,QueryEnvironment*queryEnv){Query*query;List*querytree_list;TRACE_POSTGRESQL_QUERY_REWRITE_START(query_string);/**(1)Performparseanalysis.*/if(log_parser_stats)ResetUsage();query=parse_analyze(parsetree,query_string,paramTypes,numParams,queryEnv);//解析&分析if(log_parser_stats)ShowUsage("PARSEANALYSISSTATISTICS");/**(2)Rewritethequeries,asnecessary*/querytree_list=pg_rewrite_query(query);//查询重写TRACE_POSTGRESQL_QUERY_REWRITE_DONE(query_string);returnquerytree_list;}/**parse_analyze*AnalyzearawparsetreeandtransformittoQueryform.**Optionally,informationabout$nparametertypescanbesupplied.*Referencesto$nindexesnotdefinedbyparamTypes[]aredisallowed.**TheresultisaQuerynode.Optimizablestatementsrequireconsiderable*transformation,whileutility-typestatementsaresimplyhungoff*adummyCMD_UTILITYQuerynode.*/Query*parse_analyze(RawStmt*parseTree,constchar*sourceText,Oid*paramTypes,intnumParams,QueryEnvironment*queryEnv){ParseState*pstate=make_parsestate(NULL);Query*query;Assert(sourceText!=NULL);/*requiredasof8.4*/pstate->p_sourcetext=sourceText;if(numParams>0)parse_fixed_parameters(pstate,paramTypes,numParams);pstate->p_queryEnv=queryEnv;query=transformTopLevelStmt(pstate,parseTree);if(post_parse_analyze_hook)(*post_parse_analyze_hook)(pstate,query);free_parsestate(pstate);returnquery;}/**make_parsestate*AllocateandinitializeanewParseState.**CallershouldeventuallyreleasetheParseStateviafree_parsestate().*/ParseState*make_parsestate(ParseState*parentParseState){ParseState*pstate;pstate=palloc0(sizeof(ParseState));pstate->parentParseState=parentParseState;/*Fillinfieldsthatdon'tstartatnull/false/zero*/pstate->p_next_resno=1;pstate->p_resolve_unknowns=true;if(parentParseState){pstate->p_sourcetext=parentParseState->p_sourcetext;/*allhooksarecopiedfromparent*/pstate->p_pre_columnref_hook=parentParseState->p_pre_columnref_hook;pstate->p_post_columnref_hook=parentParseState->p_post_columnref_hook;pstate->p_paramref_hook=parentParseState->p_paramref_hook;pstate->p_coerce_param_hook=parentParseState->p_coerce_param_hook;pstate->p_ref_hook_state=parentParseState->p_ref_hook_state;/*queryenvironmentstaysincontextforthewholeparseanalysis*/pstate->p_queryEnv=parentParseState->p_queryEnv;}returnpstate;}/**transformTopLevelStmt-*transformaParsetreeintoaQuerytree.**Thisfunctionisjustresponsiblefortransferringstatementlocationdata*fromtheRawStmtintothefinishedQuery.*/Query*transformTopLevelStmt(ParseState*pstate,RawStmt*parseTree){Query*result;/*We'reattoplevel,soallowSELECTINTO*/result=transformOptionalSelectInto(pstate,parseTree->stmt);result->stmt_location=parseTree->stmt_location;result->stmt_len=parseTree->stmt_len;returnresult;}/**transformOptionalSelectInto-*IfSELECThasINTO,convertittoCREATETABLEAS.**Theonlythingwedoherethatwedon'tdointransformStmt()isto*convertSELECT...INTOintoCREATETABLEAS.Sinceutilitystatements*aren'tallowedwithinlargerstatements,thisisonlyallowedatthetop*oftheparsetree,andsoweonlytryitbeforeenteringtherecursive*transformStmt()processing.*/staticQuery*transformOptionalSelectInto(ParseState*pstate,Node*parseTree){if(IsA(parseTree,SelectStmt)){SelectStmt*stmt=(SelectStmt*)parseTree;/*Ifit'saset-operationtree,drilldowntoleftmostSelectStmt*/while(stmt&&stmt->op!=SETOP_NONE)stmt=stmt->larg;Assert(stmt&&IsA(stmt,SelectStmt)&&stmt->larg==NULL);if(stmt->intoClause){CreateTableAsStmt*ctas=makeNode(CreateTableAsStmt);ctas->query=parseTree;ctas->into=stmt->intoClause;ctas->relkind=OBJECT_TABLE;ctas->is_select_into=true;/**RemovetheintoClausefromtheSelectStmt.Thismakesitsafe*fortransformSelectStmttocomplainifitfindsintoClauseset*(implyingthattheINTOappearedinadisallowedplace).*/stmt->intoClause=NULL;parseTree=(Node*)ctas;}}returntransformStmt(pstate,parseTree);}/**transformStmt-*recursivelytransformaParsetreeintoaQuerytree.*/Query*transformStmt(ParseState*pstate,Node*parseTree){Query*result;/**WeapplyRAW_EXPRESSION_COVERAGE_TESTtestingtobasicDMLstatements;*wecan'tjustrunitoneverythingbecauseraw_expression_tree_walker()*doesn'tclaimtohandleutilitystatements.*/#ifdefRAW_EXPRESSION_COVERAGE_TESTswitch(nodeTag(parseTree)){caseT_SelectStmt:caseT_InsertStmt:caseT_UpdateStmt:caseT_DeleteStmt:(void)test_raw_expression_coverage(parseTree,NULL);break;default:break;}#endif/*RAW_EXPRESSION_COVERAGE_TEST*/switch(nodeTag(parseTree)){/**Optimizablestatements*/caseT_InsertStmt:result=transformInsertStmt(pstate,(InsertStmt*)parseTree);break;caseT_DeleteStmt:result=transformDeleteStmt(pstate,(DeleteStmt*)parseTree);break;caseT_UpdateStmt:result=transformUpdateStmt(pstate,(UpdateStmt*)parseTree);break;caseT_SelectStmt:{SelectStmt*n=(SelectStmt*)parseTree;if(n->valuesLists)result=transformValuesClause(pstate,n);elseif(n->op==SETOP_NONE)result=transformSelectStmt(pstate,n);elseresult=transformSetOperationStmt(pstate,n);}break;/**Specialcases*/caseT_DeclareCursorStmt:result=transformDeclareCursorStmt(pstate,(DeclareCursorStmt*)parseTree);break;caseT_ExplainStmt:result=transformExplainStmt(pstate,(ExplainStmt*)parseTree);break;caseT_CreateTableAsStmt:result=transformCreateTableAsStmt(pstate,(CreateTableAsStmt*)parseTree);break;caseT_CallStmt:result=transformCallStmt(pstate,(CallStmt*)parseTree);break;default:/**otherstatementsdon'trequireanytransformation;justreturn*theoriginalparsetreewithaQuerynodeplasteredontop.*/result=makeNode(Query);result->commandType=CMD_UTILITY;result->utilityStmt=(Node*)parseTree;break;}/*Markasoriginalqueryuntilwelearndifferently*/result->querySource=QSRC_ORIGINAL;result->canSetTag=true;returnresult;}/**transformInsertStmt-*transformanInsertStatement*/staticQuery*transformInsertStmt(ParseState*pstate,InsertStmt*stmt){Query*qry=makeNode(Query);SelectStmt*selectStmt=(SelectStmt*)stmt->selectStmt;List*exprList=NIL;boolisGeneralSelect;List*sub_rtable;List*sub_namespace;List*icolumns;List*attrnos;RangeTblEntry*rte;RangeTblRef*rtr;ListCell*icols;ListCell*attnos;ListCell*lc;boolisOnConflictUpdate;AclModetargetPerms;/*Therecan'tbeanyouterWITHtoworryabout*/Assert(pstate->p_ctenamespace==NIL);qry->commandType=CMD_INSERT;pstate->p_is_insert=true;/*processtheWITHclauseindependentlyofallelse*/if(stmt->withClause){qry->hasRecursive=stmt->withClause->recursive;qry->cteList=transformWithClause(pstate,stmt->withClause);qry->hasModifyingCTE=pstate->p_hasModifyingCTE;}qry->override=stmt->override;isOnConflictUpdate=(stmt->onConflictClause&&stmt->onConflictClause->action==ONCONFLICT_UPDATE);/**Wehavethreecasestodealwith:DEFAULTVALUES(selectStmt==NULL),*VALUESlist,orgeneralSELECTinput.Wespecial-caseVALUES,bothfor*efficiencyandsowecanhandleDEFAULTspecifications.**ThegrammarallowsattachingORDERBY,LIMIT,FORUPDATE,orWITHtoa*VALUESclause.Ifwehaveanyofthose,treatitasageneralSELECT;*soitwillwork,butyoucan'tuseDEFAULTitemstogetherwiththose.*/isGeneralSelect=(selectStmt&&(selectStmt->valuesLists==NIL||selectStmt->sortClause!=NIL||selectStmt->limitOffset!=NULL||selectStmt->limitCount!=NULL||selectStmt->lockingClause!=NIL||selectStmt->withClause!=NULL));/**Ifanon-nilrangetable/namespacewaspassedin,andwearedoing*INSERT/SELECT,arrangetopasstherangetable/namespacedowntothe*SELECT.ThiscanonlyhappenifweareinsideaCREATERULE,andin*thatcasewewanttherule'sOLDandNEWrtableentriestoappearas*partoftheSELECT'srtable,notasouterreferencesforit.(Kluge!)*TheSELECT'sjoinlistisnotaffectedhowever.Wemustdothisbefore*addingthetargettabletotheINSERT'srtable.*/if(isGeneralSelect){sub_rtable=pstate->p_rtable;pstate->p_rtable=NIL;sub_namespace=pstate->p_namespace;pstate->p_namespace=NIL;}else{sub_rtable=NIL;/*notused,butkeepcompilerquiet*/sub_namespace=NIL;}/**MustgetwritelockonINSERTtargettablebeforescanningSELECT,else*wewillgrabthewrongkindofinitiallockifthetargettableisalso*mentionedintheSELECTpart.Notethatthetargettableisnotadded*tothejoinlistornamespace.*/targetPerms=ACL_INSERT;if(isOnConflictUpdate)targetPerms|=ACL_UPDATE;qry->resultRelation=setTargetTable(pstate,stmt->relation,false,false,targetPerms);/*Validatestmt->colslist,orbuilddefaultlistifnolistgiven*/icolumns=checkInsertTargets(pstate,stmt->cols,&attrnos);Assert(list_length(icolumns)==list_length(attrnos));/**DeterminewhichvariantofINSERTwehave.*/if(selectStmt==NULL){/**WehaveINSERT...DEFAULTVALUES.Wecanhandlethiscaseby*emittinganemptytargetlist---allcolumnswillbedefaultedwhen*theplannerexpandsthetargetlist.*/exprList=NIL;}elseif(isGeneralSelect){/**Wemakethesub-pstateachildoftheouterpstatesothatitcan*seeanyParamdefinitionssuppliedfromabove.Sincetheouter*pstate'srtableandnamespacearepresentlyempty,thereareno*side-effectsofexposingnamesthesub-SELECTshouldn'tbeableto*see.*/ParseState*sub_pstate=make_parsestate(pstate);Query*selectQuery;/**ProcessthesourceSELECT.**ItisimportantthatthisbehandledjustlikeastandaloneSELECT;*otherwisethebehaviorofSELECTwithinINSERTmightbedifferent*fromastand-aloneSELECT.(Indeed,Postgresupthrough6.5had*bugsofjustthatnature...)**Thesoleexceptionisthatwepreventresolvingunknown-type*outputsasTEXT.Thisdoesnotchangethesemanticssinceifthe*columntypematterssemantically,itwouldhavebeenresolvedto*somethingelseanyway.Doingthisletsusresolvesuchoutputsas*thetargetcolumn'stype,whichwehandlebelow.*/sub_pstate->p_rtable=sub_rtable;sub_pstate->p_joinexprs=NIL;/*sub_rtablehasnojoins*/sub_pstate->p_namespace=sub_namespace;sub_pstate->p_resolve_unknowns=false;selectQuery=transformStmt(sub_pstate,stmt->selectStmt);free_parsestate(sub_pstate);/*ThegrammarshouldhaveproducedaSELECT*/if(!IsA(selectQuery,Query)||selectQuery->commandType!=CMD_SELECT)elog(ERROR,"unexpectednon-SELECTcommandinINSERT...SELECT");/**MakethesourcebeasubqueryintheINSERT'srangetable,andadd*ittotheINSERT'sjoinlist.*/rte=addRangeTableEntryForSubquery(pstate,selectQuery,makeAlias("*SELECT*",NIL),false,false);rtr=makeNode(RangeTblRef);/*assumenewrteisatend*/rtr->rtindex=list_length(pstate->p_rtable);Assert(rte==rt_fetch(rtr->rtindex,pstate->p_rtable));pstate->p_joinlist=lappend(pstate->p_joinlist,rtr);/*----------*GenerateanexpressionlistfortheINSERTthatselectsallthe*non-resjunkcolumnsfromthesubquery.(INSERT'stlistmustbe*separatefromthesubquery'stlistbecausewemayaddcolumns,*insertdatatypecoercions,etc.)**HACK:unknown-typeconstantsandparamsintheSELECT'stargetlist*arecopiedupas-isratherthanbeingreferencedassubquery*outputs.Thisistoensurethatwhenwetrytocoercethemto*thetargetcolumn'sdatatype,therightthingshappen(see*specialcasesincoerce_type).Otherwise,thisfails:*INSERTINTOfooSELECT'bar',...FROMbaz*----------*/exprList=NIL;foreach(lc,selectQuery->targetList){TargetEntry*tle=(TargetEntry*)lfirst(lc);Expr*expr;if(tle->resjunk)continue;if(tle->expr&&(IsA(tle->expr,Const)||IsA(tle->expr,Param))&&exprType((Node*)tle->expr)==UNKNOWNOID)expr=tle->expr;else{Var*var=makeVarFromTargetEntry(rtr->rtindex,tle);var->location=exprLocation((Node*)tle->expr);expr=(Expr*)var;}exprList=lappend(exprList,expr);}/*Preparerowforassignmenttotargettable*/exprList=transformInsertRow(pstate,exprList,stmt->cols,icolumns,attrnos,false);}elseif(list_length(selectStmt->valuesLists)>1){/**ProcessINSERT...VALUESwithmultipleVALUESsublists.We*generateaVALUESRTEholdingthetransformedexpressionlists,and*buildupatargetlistcontainingVarsthatreferencetheVALUES*RTE.*/List*exprsLists=NIL;List*coltypes=NIL;List*coltypmods=NIL;List*colcollations=NIL;intsublist_length=-1;boollateral=false;Assert(selectStmt->intoClause==NULL);foreach(lc,selectStmt->valuesLists){List*sublist=(List*)lfirst(lc);/**Dobasicexpressiontransformation(sameasaROW()expr,but*allowSetToDefaultattoplevel)*/sublist=transformExpressionList(pstate,sublist,EXPR_KIND_VALUES,true);/**Allthesublistsmustbethesamelength,*after**transformation(whichmightexpand'*'intomultipleitems).*TheVALUESRTEcan'thandleanythingdifferent.*/if(sublist_length<0){/*Rememberpost-transformationlengthoffirstsublist*/sublist_length=list_length(sublist);}elseif(sublist_length!=list_length(sublist)){ereport(ERROR,(errcode(ERRCODE_SYNTAX_ERROR),errmsg("VALUESlistsmustallbethesamelength"),parser_errposition(pstate,exprLocation((Node*)sublist))));}/**Preparerowforassignmenttotargettable.Weprocessany*indirectiononthetargetcolumnspecsnormallybutthenstrip*offtheresultingfield/arrayassignmentnodes,sincewedon't*wanttheparsedstatementtocontaincopiesofthoseineach*VALUESrow.(It'sannoyingtohavetotransformthe*indirectionspecsoverandoverlikethis,butavoidingit*wouldtakesomereallymessyrefactoringof*transformAssignmentIndirection.)*/sublist=transformInsertRow(pstate,sublist,stmt->cols,icolumns,attrnos,true);/**Wemustassigncollationsnowbecauseassign_query_collations*doesn'tprocessrangetableentries.Wejustassignallthe*collationsindependentlyineachrow,anddon'tworryabout*whethertheyareconsistentvertically.TheouterINSERTquery*isn'tgoingtocareaboutthecollationsoftheVALUEScolumns,*soit'snotworththeefforttoidentifyacommoncollationfor*eachonehere.(Butnotethisdoeshaveoneuser-visible*consequence:INSERT...VALUESwon'tcomplainaboutconflicting*explicitCOLLATEsinacolumn,whereasthesameVALUES*constructinanothercontextwouldcomplain.)*/assign_list_collations(pstate,sublist);exprsLists=lappend(exprsLists,sublist);}/**Constructcolumntype/typmod/collationlistsfortheVALUESRTE.*Everyexpressionineachcolumnhasbeencoercedtothetype/typmod*ofthecorrespondingtargetcolumnorsubfield,soit'ssufficient*tolookattheexprType/exprTypmodofthefirstrow.Wedon'tcare*aboutthecollationlabeling,sojustfillinInvalidOidforthat.*/foreach(lc,(List*)linitial(exprsLists)){Node*val=(Node*)lfirst(lc);coltypes=lappend_oid(coltypes,exprType(val));coltypmods=lappend_int(coltypmods,exprTypmod(val));colcollations=lappend_oid(colcollations,InvalidOid);}/**Ordinarilytherecan'tbeanycurrent-levelVarsintheexpression*lists,becausethenamespacewasempty...butifwe'reinside*CREATERULE,thenNEW/OLDreferencesmightappear.Inthatcasewe*havetomarktheVALUESRTEasLATERAL.*/if(list_length(pstate->p_rtable)!=1&&contain_vars_of_level((Node*)exprsLists,0))lateral=true;/**GeneratetheVALUESRTE*/rte=addRangeTableEntryForValues(pstate,exprsLists,coltypes,coltypmods,colcollations,NULL,lateral,true);rtr=makeNode(RangeTblRef);/*assumenewrteisatend*/rtr->rtindex=list_length(pstate->p_rtable);Assert(rte==rt_fetch(rtr->rtindex,pstate->p_rtable));pstate->p_joinlist=lappend(pstate->p_joinlist,rtr);/**GeneratelistofVarsreferencingtheRTE*/expandRTE(rte,rtr->rtindex,0,-1,false,NULL,&exprList);/**Re-applyanyindirectiononthetargetcolumnspecstotheVars*/exprList=transformInsertRow(pstate,exprList,stmt->cols,icolumns,attrnos,false);}else{/**ProcessINSERT...VALUESwithasingleVALUESsublist.Wetreat*thiscaseseparatelyforefficiency.Thesublistisjustcomputed*directlyastheQuery'stargetlist,withnoVALUESRTE.Soit*worksjustlikeaSELECTwithoutanyFROM.*/List*valuesLists=selectStmt->valuesLists;Assert(list_length(valuesLists)==1);Assert(selectStmt->intoClause==NULL);/**Dobasicexpressiontransformation(sameasaROW()expr,butallow*SetToDefaultattoplevel)*/exprList=transformExpressionList(pstate,(List*)linitial(valuesLists),EXPR_KIND_VALUES_SINGLE,true);/*Preparerowforassignmenttotargettable*/exprList=transformInsertRow(pstate,exprList,stmt->cols,icolumns,attrnos,false);}/**Generatequery'stargetlistusingthecomputedlistofexpressions.*Also,markallthetargetcolumnsasneedinginsertpermissions.*/rte=pstate->p_target_rangetblentry;qry->targetList=NIL;icols=list_head(icolumns);attnos=list_head(attrnos);foreach(lc,exprList){Expr*expr=(Expr*)lfirst(lc);ResTarget*col;AttrNumberattr_num;TargetEntry*tle;col=lfirst_node(ResTarget,icols);attr_num=(AttrNumber)lfirst_int(attnos);tle=makeTargetEntry(expr,attr_num,col->name,false);qry->targetList=lappend(qry->targetList,tle);rte->insertedCols=bms_add_member(rte->insertedCols,attr_num-FirstLowInvalidHeapAttributeNumber);icols=lnext(icols);attnos=lnext(attnos);}/*ProcessONCONFLICT,ifany.*/if(stmt->onConflictClause)qry->onConflict=transformOnConflictClause(pstate,stmt->onConflictClause);/**IfwehaveaRETURNINGclause,weneedtoaddthetargetrelationto*thequerynamespacebeforeprocessingit,sothatVarreferencesin*RETURNINGwillwork.Also,removeanynamespaceentriesaddedina*sub-SELECTorVALUESlist.*/if(stmt->returningList){pstate->p_namespace=NIL;addRTEtoQuery(pstate,pstate->p_target_rangetblentry,false,true,true);qry->returningList=transformReturningList(pstate,stmt->returningList);}/*donebuildingtherangetableandjointree*/qry->rtable=pstate->p_rtable;qry->jointree=makeFromExpr(pstate->p_joinlist,NULL);qry->hasTargetSRFs=pstate->p_hasTargetSRFs;qry->hasSubLinks=pstate->p_hasSubLinks;assign_query_collations(pstate,qry);returnqry;}
9、pg_plan_queries
/**Generateplansforalistofalready-rewrittenqueries.**Fornormaloptimizablestatements,invoketheplanner.Forutility*statements,justmakeawrapperPlannedStmtnode.**TheresultisalistofPlannedStmtnodes.*/List*pg_plan_queries(List*querytrees,intcursorOptions,ParamListInfoboundParams){List*stmt_list=NIL;ListCell*query_list;foreach(query_list,querytrees){Query*query=lfirst_node(Query,query_list);PlannedStmt*stmt;if(query->commandType==CMD_UTILITY){/*Utilitycommandsrequirenoplanning.*/stmt=makeNode(PlannedStmt);stmt->commandType=CMD_UTILITY;stmt->canSetTag=query->canSetTag;stmt->utilityStmt=query->utilityStmt;stmt->stmt_location=query->stmt_location;stmt->stmt_len=query->stmt_len;}else{stmt=pg_plan_query(query,cursorOptions,boundParams);}stmt_list=lappend(stmt_list,stmt);}returnstmt_list;}/**Generateaplanforasinglealready-rewrittenquery.*Thisisathinwrapperaroundplanner()andtakesthesameparameters.*/PlannedStmt*pg_plan_query(Query*querytree,intcursorOptions,ParamListInfoboundParams){PlannedStmt*plan;/*Utilitycommandshavenoplans.*/if(querytree->commandType==CMD_UTILITY)returnNULL;/*Plannermusthaveasnapshotincaseitcallsuser-definedfunctions.*/Assert(ActiveSnapshotSet());TRACE_POSTGRESQL_QUERY_PLAN_START();if(log_planner_stats)ResetUsage();/*calltheoptimizer*/plan=planner(querytree,cursorOptions,boundParams);if(log_planner_stats)ShowUsage("PLANNERSTATISTICS");#ifdefCOPY_PARSE_PLAN_TREES/*Optionaldebuggingcheck:passplanoutputthroughcopyObject()*/{PlannedStmt*new_plan=copyObject(plan);/**equal()currentlydoesnothaveroutinestocomparePlannodes,so*don'ttrytotestequalityhere.Perhapsfixsomeday?*/#ifdefNOT_USED/*ThischecksbothcopyObject()andtheequal()routines...*/if(!equal(new_plan,plan))elog(WARNING,"copyObject()failedtoproduceanequalplantree");else#endifplan=new_plan;}#endif/**Printplanifdebugging.*/if(Debug_print_plan)elog_node_display(LOG,"plan",plan,Debug_pretty_print);TRACE_POSTGRESQL_QUERY_PLAN_DONE();returnplan;}/*******************************************************************************Queryoptimizerentrypoint**Tosupportloadablepluginsthatmonitorormodifyplannerbehavior,*weprovideahookvariablethatletsaplugingetcontrolbeforeand*afterthestandardplanningprocess.Thepluginwouldnormallycall*standard_planner().**Notetopluginauthors:standard_planner()scribblesonitsQueryinput,*soyou'dbettercopythatdatastructureifyouwanttoplanmorethanonce.******************************************************************************/PlannedStmt*planner(Query*parse,intcursorOptions,ParamListInfoboundParams){PlannedStmt*result;if(planner_hook)result=(*planner_hook)(parse,cursorOptions,boundParams);elseresult=standard_planner(parse,cursorOptions,boundParams);returnresult;}
10、CreatePortal
/**CreatePortal*Returnsanewportalgivenaname.**allowDup:iftrue,automaticallydropanypre-existingportalofthe*samename(iffalse,anerrorisraised).**dupSilent:iftrue,don'tevenemitaWARNING.*/PortalCreatePortal(constchar*name,boolallowDup,booldupSilent){Portalportal;AssertArg(PointerIsValid(name));portal=GetPortalByName(name);if(PortalIsValid(portal)){if(!allowDup)ereport(ERROR,(errcode(ERRCODE_DUPLICATE_CURSOR),errmsg("cursor\"%s\"alreadyexists",name)));if(!dupSilent)ereport(WARNING,(errcode(ERRCODE_DUPLICATE_CURSOR),errmsg("closingexistingcursor\"%s\"",name)));PortalDrop(portal,false);}/*makenewportalstructure*/portal=(Portal)MemoryContextAllocZero(TopPortalContext,sizeof*portal);/*initializeportalcontext;typicallyitwon'tstoremuch*/portal->portalContext=AllocSetContextCreate(TopPortalContext,"PortalContext",ALLOCSET_SMALL_SIZES);/*createaresourceownerfortheportal*/portal->resowner=ResourceOwnerCreate(CurTransactionResourceOwner,"Portal");/*initializeportalfieldsthatdon'tstartoffzero*/portal->status=PORTAL_NEW;portal->cleanup=PortalCleanup;portal->createSubid=GetCurrentSubTransactionId();portal->activeSubid=portal->createSubid;portal->strategy=PORTAL_MULTI_QUERY;portal->cursorOptions=CURSOR_OPT_NO_SCROLL;portal->atStart=true;portal->atEnd=true;/*disallowfetchesuntilqueryisset*/portal->visible=true;portal->creation_time=GetCurrentStatementStartTimestamp();/*putportalintable(setsportal->name)*/PortalHashTableInsert(portal,name);/*reuseportal->namecopy*/MemoryContextSetIdentifier(portal->portalContext,portal->name);returnportal;}
11、PortalDefineQuery
/**PortalDefineQuery*Asimplesubroutinetoestablishaportal'squery.**Notes:asofPG8.4,callerMUSTsupplyasourceTextstring;itisnot*allowedanymoretopassNULL.(Ifyoureallydon'thavesourcetext,*youcanpassaconstantstring,perhaps"(querynotavailable)".)**commandTagshallbeNULLifandonlyiftheoriginalquerystring*(beforerewriting)wasanemptystring.Also,thepassedcommandTagmust*beapointertoaconstantstring,sinceitisnotcopied.**Ifcplanisprovided,thenitisacachedplancontainingthestmts,and*thecallermusthavedoneGetCachedPlan(),causingarefcountincrement.*Therefcountwillbereleasedwhentheportalisdestroyed.**IfcplanisNULL,thenitisthecaller'sresponsibilitytoensurethat*thepassedplantreeshaveadequatelifetime.Typicallythisisdoneby*copyingthemintotheportal'scontext.**ThecallerisalsoresponsibleforensuringthatthepassedprepStmtName*(ifnotNULL)andsourceTexthaveadequatelifetime.**NB:thisfunctionmustn'tdomuchbeyondstoringthepassedvalues;in*particulardon'tdoanythingthatriskselog(ERROR).Ifthatwereto*happenherebeforestoringthecplanreference,we'dleaktheplancache*refcountthatthecalleristryingtohandofftous.*/voidPortalDefineQuery(Portalportal,constchar*prepStmtName,constchar*sourceText,constchar*commandTag,List*stmts,CachedPlan*cplan){AssertArg(PortalIsValid(portal));AssertState(portal->status==PORTAL_NEW);AssertArg(sourceText!=NULL);AssertArg(commandTag!=NULL||stmts==NIL);portal->prepStmtName=prepStmtName;portal->sourceText=sourceText;portal->commandTag=commandTag;portal->stmts=stmts;portal->cplan=cplan;portal->status=PORTAL_DEFINED;}
12、PortalStart
/**PortalStart*Prepareaportalforexecution.**Callermustalreadyhavecreatedtheportal,donePortalDefineQuery(),*andadjustedportaloptionsifneeded.**Ifparametersareneededbythequery,theymustbepassedin"params"*(callerisresponsibleforgivingthemappropriatelifetime).**Thecallercanalsoprovideaninitialsetof"eflags"tobepassedto*ExecutorStart(butnotethesecanbemodifiedinternally,andtheyare*currentlyonlyhonoredforPORTAL_ONE_SELECTportals).Mostcallers*shouldsimplypasszero.**Thecallercanoptionallypassasnapshottobeused;passInvalidSnapshot*forthenormalbehaviorofsettinganewsnapshot.Thisparameteris*presentlyignoredfornon-PORTAL_ONE_SELECTportals(it'sonlyintended*tobeusedforcursors).**Onreturn,portalisreadytoacceptPortalRun()calls,andtheresult*tupdesc(ifany)isknown.*/voidPortalStart(Portalportal,ParamListInfoparams,inteflags,Snapshotsnapshot){PortalsaveActivePortal;ResourceOwnersaveResourceOwner;MemoryContextsavePortalContext;MemoryContextoldContext;QueryDesc*queryDesc;intmyeflags;AssertArg(PortalIsValid(portal));AssertState(portal->status==PORTAL_DEFINED);/**Setupglobalportalcontextpointers.*/saveActivePortal=ActivePortal;saveResourceOwner=CurrentResourceOwner;savePortalContext=PortalContext;PG_TRY();{ActivePortal=portal;if(portal->resowner)CurrentResourceOwner=portal->resowner;PortalContext=portal->portalContext;oldContext=MemoryContextSwitchTo(PortalContext);/*Mustrememberportalparamlist,ifany*/portal->portalParams=params;/**Determinetheportalexecutionstrategy*/portal->strategy=ChoosePortalStrategy(portal->stmts);/**Fireherupaccordingtothestrategy*/switch(portal->strategy){casePORTAL_ONE_SELECT:/*Mustsetsnapshotbeforestartingexecutor.*/if(snapshot)PushActiveSnapshot(snapshot);elsePushActiveSnapshot(GetTransactionSnapshot());/**CreateQueryDescinportal'scontext;forthemoment,set*thedestinationtoDestNone.*/queryDesc=CreateQueryDesc(linitial_node(PlannedStmt,portal->stmts),portal->sourceText,GetActiveSnapshot(),InvalidSnapshot,None_Receiver,params,portal->queryEnv,0);/**Ifit'sascrollablecursor,executorneedstosupport*REWINDandbackwardsscan,aswellaswhateverthecaller*might'veaskedfor.*/if(portal->cursorOptions&CURSOR_OPT_SCROLL)myeflags=eflags|EXEC_FLAG_REWIND|EXEC_FLAG_BACKWARD;elsemyeflags=eflags;/**CallExecutorStarttopreparetheplanforexecution*/ExecutorStart(queryDesc,myeflags);/**ThistellsPortalCleanuptoshutdowntheexecutor*/portal->queryDesc=queryDesc;/**Remembertupledescriptor(computedbyExecutorStart)*/portal->tupDesc=queryDesc->tupDesc;/**Resetcursorpositiondatato"startofquery"*/portal->atStart=true;portal->atEnd=false;/*allowfetches*/portal->portalPos=0;PopActiveSnapshot();break;casePORTAL_ONE_RETURNING:casePORTAL_ONE_MOD_WITH:/**Wedon'tstarttheexecutoruntilwearetoldtorunthe*portal.Wedoneedtosetuptheresulttupdesc.*/{PlannedStmt*pstmt;pstmt=PortalGetPrimaryStmt(portal);portal->tupDesc=ExecCleanTypeFromTL(pstmt->planTree->targetlist,false);}/**Resetcursorpositiondatato"startofquery"*/portal->atStart=true;portal->atEnd=false;/*allowfetches*/portal->portalPos=0;break;casePORTAL_UTIL_SELECT:/**Wedon'tsetsnapshothere,becausePortalRunUtilitywill*takecareofitifneeded.*/{PlannedStmt*pstmt=PortalGetPrimaryStmt(portal);Assert(pstmt->commandType==CMD_UTILITY);portal->tupDesc=UtilityTupleDescriptor(pstmt->utilityStmt);}/**Resetcursorpositiondatato"startofquery"*/portal->atStart=true;portal->atEnd=false;/*allowfetches*/portal->portalPos=0;break;casePORTAL_MULTI_QUERY:/*Needdonothingnow*/portal->tupDesc=NULL;break;}}PG_CATCH();{/*Uncaughterrorwhileexecutingportal:markitdead*/MarkPortalFailed(portal);/*Restoreglobalvarsandpropagateerror*/ActivePortal=saveActivePortal;CurrentResourceOwner=saveResourceOwner;PortalContext=savePortalContext;PG_RE_THROW();}PG_END_TRY();MemoryContextSwitchTo(oldContext);ActivePortal=saveActivePortal;CurrentResourceOwner=saveResourceOwner;PortalContext=savePortalContext;portal->status=PORTAL_READY;}
13、PortalSetResultFormat
/**PortalSetResultFormat*Selecttheformatcodesforaportal'soutput.**ThismustberunafterPortalStartforaportalthatwillbereadby*aDestRemoteorDestRemoteExecutedestination.Itisnotpresentlyneeded*forotherdestinationtypes.**formats[]istheclientformatrequest,asperBindmessageconventions.*/voidPortalSetResultFormat(Portalportal,intnFormats,int16*formats){intnatts;inti;/*Donothingifportalwon'treturntuples*/if(portal->tupDesc==NULL)return;natts=portal->tupDesc->natts;portal->formats=(int16*)MemoryContextAlloc(portal->portalContext,natts*sizeof(int16));if(nFormats>1){/*formatspecifiedforeachcolumn*/if(nFormats!=natts)ereport(ERROR,(errcode(ERRCODE_PROTOCOL_VIOLATION),errmsg("bindmessagehas%dresultformatsbutqueryhas%dcolumns",nFormats,natts)));memcpy(portal->formats,formats,natts*sizeof(int16));}elseif(nFormats>0){/*singleformatspecified,useforallcolumns*/int16format1=formats[0];for(i=0;i<natts;i++)portal->formats[i]=format1;}else{/*usedefaultformatforallcolumns*/for(i=0;i<natts;i++)portal->formats[i]=0;}}
14、CreateDestReceiver
/*----------------*CreateDestReceiver-returnappropriatereceiverfunctionsetfordest*----------------*/DestReceiver*CreateDestReceiver(CommandDestdest){switch(dest){caseDestRemote:caseDestRemoteExecute:returnprinttup_create_DR(dest);caseDestRemoteSimple:return&printsimpleDR;caseDestNone:return&donothingDR;caseDestDebug:return&debugtupDR;caseDestSPI:return&spi_printtupDR;caseDestTuplestore:returnCreateTuplestoreDestReceiver();caseDestIntoRel:returnCreateIntoRelDestReceiver(NULL);caseDestCopyOut:returnCreateCopyDestReceiver();caseDestSQLFunction:returnCreateSQLFunctionDestReceiver();caseDestTransientRel:returnCreateTransientRelDestReceiver(InvalidOid);caseDestTupleQueue:returnCreateTupleQueueDestReceiver(NULL);}/*shouldnevergethere*/return&donothingDR;}
15、printtup_create_DR
/*----------------*Initialize:createaDestReceiverforprinttup*----------------*/DestReceiver*printtup_create_DR(CommandDestdest){DR_printtup*self=(DR_printtup*)palloc0(sizeof(DR_printtup));self->pub.receiveSlot=printtup;/*mightgetchangedlater*/self->pub.rStartup=printtup_startup;self->pub.rShutdown=printtup_shutdown;self->pub.rDestroy=printtup_destroy;self->pub.mydest=dest;/**SendTmessageautomaticallyifDestRemote,butnotif*DestRemoteExecute*/self->sendDescrip=(dest==DestRemote);self->attrinfo=NULL;self->nattrs=0;self->myinfo=NULL;self->tmpcontext=NULL;return(DestReceiver*)self;}
16、PortalDrop
/**PortalDrop*Destroytheportal.*/voidPortalDrop(Portalportal,boolisTopCommit){AssertArg(PortalIsValid(portal));/**Don'tallowdroppingapinnedportal,it'sstillneededbywhoever*pinnedit.*/if(portal->portalPinned)ereport(ERROR,(errcode(ERRCODE_INVALID_CURSOR_STATE),errmsg("cannotdroppinnedportal\"%s\"",portal->name)));/**NotsureifthePORTAL_ACTIVEcasecanvalidlyhappenornot...*/if(portal->status==PORTAL_ACTIVE)ereport(ERROR,(errcode(ERRCODE_INVALID_CURSOR_STATE),errmsg("cannotdropactiveportal\"%s\"",portal->name)));/**Allowportalcmds.ctocleanupthestateitknowsabout,inparticular*shuttingdowntheexecutorifstillactive.Thissteppotentiallyruns*user-definedcodesofailurehastobeexpected.It'sthecleanup*hook'sresponsibilitytonottrytodothatmorethanonce,inthecase*thatfailureoccursandthenwecomebacktodroptheportalagain*duringtransactionabort.**Note:inmostpathsofcontrol,thiswillhavebeendonealreadyin*MarkPortalDoneorMarkPortalFailed.We'rejustmakingsure.*/if(PointerIsValid(portal->cleanup)){portal->cleanup(portal);portal->cleanup=NULL;}/**Removeportalfromhashtable.Becausewedothishere,wewillnot*comebacktotrytoremovetheportalagainifthere'sanyerrorinthe*subsequentsteps.Bettertoleakalittlememorythantogetintoan*infiniteerror-recoveryloop.*/PortalHashTableDelete(portal);/*dropcachedplanreference,ifany*/PortalReleaseCachedPlan(portal);/**Ifportalhasasnapshotprotectingitsdata,releasethat.Thisneeds*alittlecaresincetheregistrationwillbeattachedtotheportal's*resowner;iftheportalfailed,wewillalreadyhavereleasedthe*resowner(andthesnapshot)duringtransactionabort.*/if(portal->holdSnapshot){if(portal->resowner)UnregisterSnapshotFromOwner(portal->holdSnapshot,portal->resowner);portal->holdSnapshot=NULL;}/**Releaseanyresourcesstillattachedtotheportal.Thereareseveral*casesbeingcoveredhere:**Toptransactioncommit(indicatedbyisTopCommit):normallyweshould*donothinghereandlettheregularend-of-transactionresource*releasingmechanismhandletheseresourcestoo.However,ifwehavea*FAILEDportal(eg,acursorthatgotanerror),we'dbettercleanup*itsresourcestoavoidresource-leakagewarningmessages.**Subtransactioncommit:nevercomeshereatall,sincewedon'tkill*anyportalsinAtSubCommit_Portals().**Mainorsubtransactionabort:wewilldonothingherebecause*portal->resownerwasalreadysetNULL;theresourceswerealready*cleanedupintransactionabort.**Ordinaryportaldrop:mustreleaseresources.However,iftheportal*isnotFAILEDthenwedonotreleaseitslocks.Thelocksbecomethe*responsibilityofthetransaction'sResourceOwner(sinceitisthe*parentoftheportal'sowner)andwillbereleasedwhenthetransaction*eventuallyends.*/if(portal->resowner&&(!isTopCommit||portal->status==PORTAL_FAILED)){boolisCommit=(portal->status!=PORTAL_FAILED);ResourceOwnerRelease(portal->resowner,RESOURCE_RELEASE_BEFORE_LOCKS,isCommit,false);ResourceOwnerRelease(portal->resowner,RESOURCE_RELEASE_LOCKS,isCommit,false);ResourceOwnerRelease(portal->resowner,RESOURCE_RELEASE_AFTER_LOCKS,isCommit,false);ResourceOwnerDelete(portal->resowner);}portal->resowner=NULL;/**Deletetuplestoreifpresent.Weshoulddothisevenundererror*conditions;sincethetuplestorewouldhavebeenusingcross-*transactionstorage,itstempfilesneedtobeexplicitlydeleted.*/if(portal->holdStore){MemoryContextoldcontext;oldcontext=MemoryContextSwitchTo(portal->holdContext);tuplestore_end(portal->holdStore);MemoryContextSwitchTo(oldcontext);portal->holdStore=NULL;}/*deletetuplestorestorage,ifany*/if(portal->holdContext)MemoryContextDelete(portal->holdContext);/*releasesubsidiarystorage*/MemoryContextDelete(portal->portalContext);/*releaseportalstruct(it'sinTopPortalContext)*/pfree(portal);}
17、EndImplicitTransactionBlock
/**EndImplicitTransactionBlock*Endanimplicittransactionblock,ifwe'reinone.**LikeEndTransactionBlock,wejustmakeanyneededblockStatechangehere.*TherealworkwillbedoneintheupcomingCommitTransactionCommand().*/voidEndImplicitTransactionBlock(void){TransactionStates=CurrentTransactionState;/**IfweareinIMPLICIT_INPROGRESSstate,switchbacktoSTARTEDstate,*allowingCommitTransactionCommandtocommitwhateverhappenedduring*theimplicittransactionblockasthoughitwereasinglestatement.**Forcallerconvenience,weconsiderallothertransactionstatesas*legalhere;otherwisethecallerwouldneeditsownstatecheck,which*seemsratherpointless.*/if(s->blockState==TBLOCK_IMPLICIT_INPROGRESS)s->blockState=TBLOCK_STARTED;}
18、finish_xact_command
staticvoidfinish_xact_command(void){/*cancelactivestatementtimeoutaftereachcommand*/disable_statement_timeout();if(xact_started){CommitTransactionCommand();#ifdefMEMORY_CONTEXT_CHECKING/*Checkallmemorycontextsthatweren'tfreedduringcommit*//*(thosethatwere,werecheckedbeforebeingdeleted)*/MemoryContextCheck(TopMemoryContext);#endif#ifdefSHOW_MEMORY_STATS/*Printmemstatsaftereachcommitforleaktracking*/MemoryContextStats(TopMemoryContext);#endifxact_started=false;}}
19、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();}}
20、EndCommand
/*----------------*EndCommand-cleanupthedestinationatendofcommand*----------------*/voidEndCommand(constchar*commandTag,CommandDestdest){switch(dest){caseDestRemote:caseDestRemoteExecute:caseDestRemoteSimple:/**WeassumethecommandTagisplainASCIIandthereforerequires*noencodingconversion.*/pq_putmessage('C',commandTag,strlen(commandTag)+1);break;caseDestNone:caseDestDebug:caseDestSPI:caseDestTuplestore:caseDestIntoRel:caseDestCopyOut:caseDestSQLFunction:caseDestTransientRel:caseDestTupleQueue:break;}}三、跟踪分析
插入测试数据:
testdb=#--获取pidtestdb=#selectpg_backend_pid();pg_backend_pid----------------1893(1row)testdb=#--插入1行testdb=#insertintot_insertvalues(22,'exec_simple_query','exec_simple_query','exec_simple_query');(挂起)
启动gdb,跟踪调试:
[root@localhost~]#gdb-p1893GNUgdb(GDB)RedHatEnterpriseLinux7.6.1-100.el7Copyright(C)2013FreeSoftwareFoundation,Inc....(gdb)bexec_simple_queryBreakpoint1at0x84cad8:filepostgres.c,line893.(gdb)cContinuing.Breakpoint1,exec_simple_query(query_string=0x1508ef0"insertintot_insertvalues(22,'exec_simple_query','exec_simple_query','exec_simple_query');")atpostgres.c:893893CommandDestdest=whereToSendOutput;#输入参数#query_string(gdb)pquery_string$1=0x1508ef0"insertintot_insertvalues(22,'exec_simple_query','exec_simple_query','exec_simple_query');"#单步调试938oldcontext=MemoryContextSwitchTo(MessageContext);(gdb)p*MessageContext$2={type=T_AllocSetContext,isReset=false,allowInCritSection=false,methods=0xb8c720<AllocSetMethods>,parent=0x1503ba0,firstchild=0x0,prevchild=0x157c3c0,nextchild=0x15956d0,name=0xb4e87c"MessageContext",ident=0x0,reset_cbs=0x0}(gdb)n944parsetree_list=pg_parse_query(query_string);(gdb)poldcontext$3=(MemoryContext)0x15a8320(gdb)p*oldcontext$4={type=T_AllocSetContext,isReset=true,allowInCritSection=false,methods=0xb8c720<AllocSetMethods>,parent=0x1503ba0,firstchild=0x0,prevchild=0x0,nextchild=0x157c3c0,name=0xa1b4ff"TopTransactionContext",ident=0x0,reset_cbs=0x0}(gdb)steppg_parse_query(query_string=0x1508ef0"insertintot_insertvalues(22,'exec_simple_query','exec_simple_query','exec_simple_query');")atpostgres.c:615615if(log_parser_stats)(gdb)618raw_parsetree_list=raw_parser(query_string);#进入raw_parser(gdb)stepraw_parser(str=0x1508ef0"insertintot_insertvalues(22,'exec_simple_query','exec_simple_query','exec_simple_query');")atparser.c:4343yyscanner=scanner_init(str,&yyextra.core_yy_extra,(gdb)...61returnyyextra.parsetree;(gdb)pyyextra$8={core_yy_extra={scanbuf=0x1509820"insertintot_insertvalues(22,'exec_simple_query','exec_simple_query','exec_simple_query');",scanbuflen=92,keywords=0xbb8d40<ScanKeywords>,num_keywords=440,backslash_quote=2,escape_string_warning=true,standard_conforming_strings=true,literalbuf=0x1509300"exec_simple_query",literallen=17,literalalloc=1024,xcdepth=1087033144,dolqstart=0x0,utf16_first_part=16777215,warn_on_first_escape=true,saw_non_ascii=false},have_lookahead=false,lookahead_token=32765,lookahead_yylval={ival=10027008,str=0x300990000<Address0x300990000outofbounds>,keyword=0x300990000<Address0x300990000outofbounds>},lookahead_yylloc=2015867616,lookahead_end=0xa1b62b"StartTransaction",lookahead_hold_char=16'\020',parsetree=0x1509d88}(gdb)p*(yyextra.parsetree)$10={type=T_List,length=1,head=0x1509d68,tail=0x1509d68}#解析树中的内容(gdb)p*((RawStmt*)(yyextra.parsetree->head->data.ptr_value))$25={type=T_RawStmt,stmt=0x1509ce8,stmt_location=0,stmt_len=91}(gdb)p*(((RawStmt*)(yyextra.parsetree->head->data.ptr_value))->stmt)$27={type=T_InsertStmt}#跳出子函数,重新进入主函数(gdb)exec_simple_query(query_string=0x1508ef0"insertintot_insertvalues(22,'exec_simple_query','exec_simple_query','exec_simple_query');")atpostgres.c:947947if(check_log_statement(parsetree_list))...#解析树只有一个元素(gdb)n974foreach(parsetree_item,parsetree_list)(gdb)plist_length(parsetree_list)$30=1(gdb)n976RawStmt*parsetree=lfirst_node(RawStmt,parsetree_item);(gdb)977boolsnapshot_set=false;(gdb)p*parsetree$31={type=T_RawStmt,stmt=0x1509ce8,stmt_location=0,stmt_len=91}(gdb)p*(parsetree->stmt)$32={type=T_InsertStmt}#commandTag(gdb)n992commandTag=CreateCommandTag(parsetree->stmt);(gdb)994set_ps_display(commandTag,false);(gdb)pcommandTag$33=0xb50908"INSERT"#进入分析&查询重写1047querytree_list=pg_analyze_and_rewrite(parsetree,query_string,(gdb)steppg_analyze_and_rewrite(parsetree=0x1509d38,query_string=0x1508ef0"insertintot_insertvalues(22,'exec_simple_query','exec_simple_query','exec_simple_query');",paramTypes=0x0,numParams=0,queryEnv=0x0)atpostgres.c:663663if(log_parser_stats)...#分析后的Query数据结构(gdb)p*query$34={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=0x150a788,jointree=0x152cf40,targetList=0x152cda8,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=91}...#回到主函数(gdb)exec_simple_query(query_string=0x1508ef0"insertintot_insertvalues(22,'exec_simple_query','exec_simple_query','exec_simple_query');")atpostgres.c:10501050plantree_list=pg_plan_queries(querytree_list,(gdb)1054if(snapshot_set)(gdb)1055PopActiveSnapshot();(gdb)1058CHECK_FOR_INTERRUPTS();(gdb)1064portal=CreatePortal("",true,true);(gdb)p*plantree_list$36={type=T_List,length=1,head=0x15c03e8,tail=0x15c03e8}(gdb)p(PlannedStmt*)(plantree_list->head->data.ptr_value)$37=(PlannedStmt*)0x150a4a8(gdb)p*((PlannedStmt*)(plantree_list->head->data.ptr_value))$38={type=T_PlannedStmt,commandType=CMD_INSERT,queryId=0,hasReturning=false,hasModifyingCTE=false,canSetTag=true,transientPlan=false,dependsOnRole=false,parallelModeNeeded=false,jitFlags=0,planTree=0x150a028,rtable=0x15c0318,resultRelations=0x15c03b8,nonleafResultRelations=0x0,rootResultRelations=0x0,subplans=0x0,rewindPlanIDs=0x0,rowMarks=0x0,relationOids=0x15c0368,invalItems=0x0,paramExecTypes=0x152e720,utilityStmt=0x0,stmt_location=0,stmt_len=91}#Portal...(gdb)p*portal$40={name=0x1571e98"",prepStmtName=0x0,portalContext=0x152c3d0,resowner=0x1539d10,cleanup=0x62f15c<PortalCleanup>,createSubid=1,activeSubid=1,sourceText=0x0,commandTag=0x0,stmts=0x0,cplan=0x0,portalParams=0x0,queryEnv=0x0,strategy=PORTAL_MULTI_QUERY,cursorOptions=4,run_once=false,status=PORTAL_NEW,portalPinned=false,autoHeld=false,queryDesc=0x0,tupDesc=0x0,formats=0x0,holdStore=0x0,holdContext=0x0,holdSnapshot=0x0,atStart=true,atEnd=true,portalPos=0,creation_time=587101481469205,visible=true}(gdb)n1073PortalDefineQuery(portal,(gdb)1083PortalStart(portal,NULL,0,InvalidSnapshot);(gdb)1091format=0;/*TEXTisdefault*/(gdb)1092if(IsA(parsetree->stmt,FetchStmt))(gdb)p*portal$41={name=0x1571e98"",prepStmtName=0x0,portalContext=0x152c3d0,resowner=0x1539d10,cleanup=0x62f15c<PortalCleanup>,createSubid=1,activeSubid=1,sourceText=0x1508ef0"insertintot_insertvalues(22,'exec_simple_query','exec_simple_query','exec_simple_query');",commandTag=0xb50908"INSERT",stmts=0x15c0408,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=587101481469205,visible=false}#Receiver1110receiver=CreateDestReceiver(dest);(gdb)1111if(dest==DestRemote)(gdb)p*receiver$42={receiveSlot=0x4857ad<printtup>,rStartup=0x485196<printtup_startup>,rShutdown=0x485bad<printtup_shutdown>,rDestroy=0x485c21<printtup_destroy>,mydest=DestRemote}(gdb)#执行...1122(void)PortalRun(portal,(gdb)...#DONE!(gdb)PostgresMain(argc=1,argv=0x1532aa8,dbname=0x1532990"testdb",username=0x1532978"xdb")atpostgres.c:41554155send_ready_for_query=true;
到此,关于“PostgreSQL中exec_simple_query函数的实现逻辑是什么”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。