这篇文章主要介绍“PostgreSQL中ExecInsert函数的实现逻辑是什么”,在日常操作中,相信很多人在PostgreSQL中ExecInsert函数的实现逻辑是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”PostgreSQL中ExecInsert函数的实现逻辑是什么”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

一、基础信息

按惯例,首先看看ExecInsert函数使用的数据结构、宏定义以及依赖的函数等。
数据结构/宏定义
1、ModifyTableState

/*----------------*PlanStatenode**WeneveractuallyinstantiateanyPlanStatenodes;thisisjustthecommon*abstractsuperclassforallPlanState-typenodes.*----------------*/typedefstructPlanState{NodeTagtype;Plan*plan;/*associatedPlannode*/EState*state;/*atexecutiontime,statesofindividual*nodespointtooneEStateforthewhole*top-levelplan*/ExecProcNodeMtdExecProcNode;/*functiontoreturnnexttuple*/ExecProcNodeMtdExecProcNodeReal;/*actualfunction,ifaboveisa*wrapper*/Instrumentation*instrument;/*Optionalruntimestatsforthisnode*/WorkerInstrumentation*worker_instrument;/*per-workerinstrumentation*//**CommonstructuraldataforallPlantypes.Theselinkstosubsidiary*statetreesparallellinksintheassociatedplantree(exceptforthe*subPlanlist,whichdoesnotexistintheplantree).*/ExprState*qual;/*booleanqualcondition*/structPlanState*lefttree;/*inputplantree(s)*/structPlanState*righttree;List*initPlan;/*InitSubPlanStatenodes(un-correlatedexpr*subselects)*/List*subPlan;/*SubPlanStatenodesinmyexpressions*//**Stateformanagementofparameter-change-drivenrescanning*/Bitmapset*chgParam;/*setofIDsofchangedParams*//**Otherrun-timestateneededbymostifnotallnodetypes.*/TupleTableSlot*ps_ResultTupleSlot;/*slotformyresulttuples*/ExprContext*ps_ExprContext;/*node'sexpression-evaluationcontext*/ProjectionInfo*ps_ProjInfo;/*infofordoingtupleprojection*//**Scanslot'sdescriptorifknown.Thisisabitofahack,butotherwise*it'shardforexpressioncompilationtooptimizebasedonthe*descriptor,withoutencodingknowledgeaboutallexecutornodes.*/TupleDescscandesc;}PlanState;/*----------------*ModifyTableStateinformation*----------------*/typedefstructModifyTableState{PlanStateps;/*itsfirstfieldisNodeTag*/CmdTypeoperation;/*INSERT,UPDATE,orDELETE*/boolcanSetTag;/*dowesetthecommandtag/es_processed?*/boolmt_done;/*arewedone?*/PlanState**mt_plans;/*subplans(onepertargetrel)*/intmt_nplans;/*numberofplansinthearray*/intmt_whichplan;/*whichoneisbeingexecuted(0..n-1)*/ResultRelInfo*resultRelInfo;/*per-subplantargetrelations*/ResultRelInfo*rootResultRelInfo;/*roottargetrelation(partitioned*tableroot)*/List**mt_arowmarks;/*per-subplanExecAuxRowMarklists*/EPQStatemt_epqstate;/*forevaluatingEvalPlanQualrechecks*/boolfireBSTriggers;/*doweneedtofirestmttriggers?*/TupleTableSlot*mt_existing;/*slottostoreexistingtargettuplein*/List*mt_excludedtlist;/*theexcludedpseudorelation'stlist*/TupleTableSlot*mt_conflproj;/*CONFLICT...SET...projectiontarget*//*Tuple-routingsupportinfo*/structPartitionTupleRouting*mt_partition_tuple_routing;/*controlstransitiontablepopulationforspecifiedoperation*/structTransitionCaptureState*mt_transition_capture;/*controlstransitiontablepopulationforINSERT...ONCONFLICTUPDATE*/structTransitionCaptureState*mt_oc_transition_capture;/*Perplanmapfortupleconversionfromchildtoroot*/TupleConversionMap**mt_per_subplan_tupconv_maps;}ModifyTableState;

2、TupleTableSlot

/*----------*Theexecutorstorestuplesina"tupletable"whichisaListof*independentTupleTableSlots.Thereareseveralcasesweneedtohandle:*1.physicaltupleinadiskbufferpage*2.physicaltupleconstructedinpalloc'edmemory*3."minimal"physicaltupleconstructedinpalloc'edmemory*4."virtual"tupleconsistingofDatum/isnullarrays**Thefirsttwocasesaresimilarinthattheybothdealwith"materialized"*tuples,butresourcemanagementisdifferent.Foratupleinadiskpage*weneedtoholdapinonthebufferuntiltheTupleTableSlot'sreference*tothetupleisdropped;whileforapalloc'dtupleweusuallywantthe*tuplepfree'dwhentheTupleTableSlot'sreferenceisdropped.**A"minimal"tupleishandledsimilarlytoapalloc'dregulartuple.*Atpresent,minimaltuplesneverarestoredinbuffers,sothereisno*paralleltocase1.Notethataminimaltuplehasno"systemcolumns".*(Actually,itcouldhaveanOID,butwehavenoneedtoaccesstheOID.)**A"virtual"tupleisanoptimizationusedtominimizephysicaldata*copyinginanestofplannodes.Anypass-by-referenceDatumsinthe*tuplepointtostoragethatisnotdirectlyassociatedwiththe*TupleTableSlot;generallytheywillpointtopartofatuplestoredin*alowerplannode'soutputTupleTableSlot,ortoafunctionresult*constructedinaplannode'sper-tupleecontext.Itistheresponsibility*ofthegeneratingplannodetobesuretheseresourcesarenotreleased*foraslongasthevirtualtupleneedstobevalid.Weonlyusevirtual*tuplesintheresultslotsofplannodes---tuplestobecopiedanywhere*elseneedtobe"materialized"intophysicaltuples.Notealsothata*virtualtupledoesnothaveany"systemcolumns".**ItisalsopossibleforaTupleTableSlottoholdbothphysicalandminimal*copiesofatuple.Thisisdonewhentheslotisrequestedtoprovide*theformatotherthantheoneitcurrentlyholds.(Originallyweattempted*tohandlesuchrequestsbyreplacingoneformatwiththeother,butthat*hadthefataldefectofinvalidatinganypass-by-referenceDatumspointing*intotheexistingslotcontents.)Bothcopiesmustcontainidenticaldata*payloadswhenthisisthecase.**TheDatum/isnullarraysofaTupleTableSlotservedoubleduty.Whenthe*slotcontainsavirtualtuple,theyaretheauthoritativedata.Whenthe*slotcontainsaphysicaltuple,thearrayscontaindataextractedfrom*thetuple.(Inthisstate,anypass-by-referenceDatumspointinto*thephysicaltuple.)Theextractedinformationisbuilt"lazily",*ie,onlyasneeded.Thisservestoavoidrepeatedextractionofdata*fromthephysicaltuple.**ATupleTableSlotcanalsobe"empty",holdingnovaliddata.Thisis*theonlyvalidstateforafreshly-createdslotthathasnotyethada*tupledescriptorassignedtoit.Inthisstate,tts_isemptymustbe*true,tts_shouldFreefalse,tts_tupleNULL,tts_bufferInvalidBuffer,*andtts_nvalidzero.**ThetupleDescriptorissimplyreferenced,notcopied,bytheTupleTableSlot*code.ThecallerofExecSetSlotDescriptor()isresponsibleforproviding*adescriptorthatwillliveaslongastheslotdoes.(Typically,both*slotsanddescriptorsareinper-querymemoryandarefreedbymemory*contextdeallocationatqueryend;soit'snotworthprovidinganyextra*mechanismtodomore.However,theslotwillincrementthetupdesc*referencecountifareference-countedtupdescissupplied.)**Whentts_shouldFreeistrue,thephysicaltupleis"owned"bytheslot*andshouldbefreedwhentheslot'sreferencetothetupleisdropped.**Iftts_bufferisnotInvalidBuffer,thentheslotisholdingapin*ontheindicatedbufferpage;dropthepinwhenwereleasethe*slot'sreferencetothatbuffer.(tts_shouldFreeshouldalwaysbe*falseinsuchacase,sincepresumablytts_tupleispointingatthe*bufferpage.)**tts_nvalidindicatesthenumberofvalidcolumnsinthetts_values/isnull*arrays.Whentheslotisholdinga"virtual"tuplethismustbeequal*tothedescriptor'snatts.Whentheslotisholdingaphysicaltuple*thisisequaltothenumberofcolumnswehaveextracted(wealways*extractcolumnsfromlefttoright,sotherearenoholes).**tts_values/tts_isnullareallocatedwhenadescriptorisassignedtothe*slot;theyareoflengthequaltothedescriptor'snatts.**tts_mintuplemustalwaysbeNULLiftheslotdoesnotholda"minimal"*tuple.Whenitdoes,tts_mintuplepointstotheactualMinimalTupleData*object(thethingtobepfree'diftts_shouldFreeMinistrue).Iftheslot*hasonlyaminimalandnotalsoaregularphysicaltuple,thentts_tuple*pointsattts_minhdrandthefieldsofthatstructaresetcorrectly*foraccesstotheminimaltuple;inparticular,tts_minhdr.t_datapoints*MINIMAL_TUPLE_OFFSETbytesbeforetts_mintuple.Thisallowscolumn*extractiontotreatthecaseidenticallytoregularphysicaltuples.**tts_slow/tts_offaresavedstateforslot_deform_tuple,andshouldnot*betouchedbyanyothercode.*----------*/typedefstructTupleTableSlot{NodeTagtype;booltts_isempty;/*true=slotisempty*/booltts_shouldFree;/*shouldpfreetts_tuple?*/booltts_shouldFreeMin;/*shouldpfreetts_mintuple?*/#defineFIELDNO_TUPLETABLESLOT_SLOW4booltts_slow;/*savedstateforslot_deform_tuple*/#defineFIELDNO_TUPLETABLESLOT_TUPLE5HeapTupletts_tuple;/*physicaltuple,orNULLifvirtual*/#defineFIELDNO_TUPLETABLESLOT_TUPLEDESCRIPTOR6TupleDesctts_tupleDescriptor;/*slot'stupledescriptor*/MemoryContexttts_mcxt;/*slotitselfisinthiscontext*/Buffertts_buffer;/*tuple'sbuffer,orInvalidBuffer*/#defineFIELDNO_TUPLETABLESLOT_NVALID9inttts_nvalid;/*#ofvalidvaluesintts_values*/#defineFIELDNO_TUPLETABLESLOT_VALUES10Datum*tts_values;/*currentper-attributevalues*/#defineFIELDNO_TUPLETABLESLOT_ISNULL11bool*tts_isnull;/*currentper-attributeisnullflags*/MinimalTupletts_mintuple;/*minimaltuple,orNULLifnone*/HeapTupleDatatts_minhdr;/*workspaceforminimal-tuple-onlycase*/#defineFIELDNO_TUPLETABLESLOT_OFF14uint32tts_off;/*savedstateforslot_deform_tuple*/booltts_fixedTupleDescriptor;/*descriptorcan'tbechanged*/}TupleTableSlot;

3、EState

/*----------------*EStateinformation**MasterworkingstateforanExecutorinvocation*----------------*/typedefstructEState{NodeTagtype;/*Basicstateforallquerytypes:*/ScanDirectiones_direction;/*currentscandirection*/Snapshotes_snapshot;/*timequaltouse*/Snapshotes_crosscheck_snapshot;/*crosschecktimequalforRI*/List*es_range_table;/*ListofRangeTblEntry*/PlannedStmt*es_plannedstmt;/*linktotopofplantree*/constchar*es_sourceText;/*SourcetextfromQueryDesc*/JunkFilter*es_junkFilter;/*top-leveljunkfilter,ifany*//*Ifquerycaninsert/deletetuples,thecommandIDtomarkthemwith*/CommandIdes_output_cid;/*Infoabouttargettable(s)forinsert/update/deletequeries:*/ResultRelInfo*es_result_relations;/*arrayofResultRelInfos*/intes_num_result_relations;/*lengthofarray*/ResultRelInfo*es_result_relation_info;/*currentlyactivearrayelt*//**Infoaboutthetargetpartitionedtargettableroot(s)for*update/deletequeries.Theyrequiredonlytofireanyper-statement*triggersdefinedonthetable.Itexistsseparatelyfrom*es_result_relations,becausepartitionedtablesdon'tappearinthe*plantreefortheupdate/deletecases.*/ResultRelInfo*es_root_result_relations;/*arrayofResultRelInfos*/intes_num_root_result_relations;/*lengthofthearray*//**ThefollowinglistcontainsResultRelInfoscreatedbythetuplerouting*codeforpartitionsthatdon'talreadyhaveone.*/List*es_tuple_routing_result_relations;/*Stuffusedforfiringtriggers:*/List*es_trig_target_relations;/*trigger-onlyResultRelInfos*/TupleTableSlot*es_trig_tuple_slot;/*fortriggeroutputtuples*/TupleTableSlot*es_trig_oldtup_slot;/*forTriggerEnabled*/TupleTableSlot*es_trig_newtup_slot;/*forTriggerEnabled*//*Parameterinfo:*/ParamListInfoes_param_list_info;/*valuesofexternalparams*/ParamExecData*es_param_exec_vals;/*valuesofinternalparams*/QueryEnvironment*es_queryEnv;/*queryenvironment*//*Otherworkingstate:*/MemoryContextes_query_cxt;/*per-querycontextinwhichEStatelives*/List*es_tupleTable;/*ListofTupleTableSlots*/List*es_rowMarks;/*ListofExecRowMarks*/uint64es_processed;/*#oftuplesprocessed*/Oides_lastoid;/*lastoidprocessed(byINSERT)*/intes_top_eflags;/*eflagspassedtoExecutorStart*/intes_instrument;/*ORofInstrumentOptionflags*/booles_finished;/*truewhenExecutorFinishisdone*/List*es_exprcontexts;/*ListofExprContextswithinEState*/List*es_subplanstates;/*ListofPlanStateforSubPlans*/List*es_auxmodifytables;/*ListofsecondaryModifyTableStates*//**thisExprContextisforper-output-tupleoperations,suchasconstraint*checksandindex-valuecomputations.Itwillberesetforeachoutput*tuple.Notethatitwillbecreatedonlyifneeded.*/ExprContext*es_per_tuple_exprcontext;/**Thesefieldsareforre-evaluatingplanqualswhenanupdatedtupleis*substitutedinREADCOMMITTEDmode.es_epqTuple[]containstuplesthat*scanplannodesshouldreturninsteadofwhateverthey'dnormally*return,orNULLifnothingtoreturn;es_epqTupleSet[]istrueifa*particulararrayentryisvalid;andes_epqScanDone[]isstateto*rememberifthetuplehasbeenreturnedalready.Arraysareofsize*list_length(es_range_table)andareindexedbyscannodescanrelid-1.*/HeapTuple*es_epqTuple;/*arrayofEPQsubstitutetuples*/bool*es_epqTupleSet;/*trueifEPQtupleisprovided*/bool*es_epqScanDone;/*trueifEPQtuplehasbeenfetched*/booles_use_parallel_mode;/*canweuseparallelworkers?*//*Theper-querysharedmemoryareatouseforparallelexecution.*/structdsa_area*es_query_dsa;/**JITinformation.es_jit_flagsindicateswhetherJITshouldbeperformed*andwithwhichoptions.es_jitiscreatedon-demandwhenJITingis*performed.*/intes_jit_flags;structJitContext*es_jit;}EState;

4、ResultRelInfo

/**ResultRelInfo**Wheneverweupdateanexistingrelation,wehavetoupdateindexesonthe*relation,andperhapsalsofiretriggers.ResultRelInfoholdsallthe*informationneededaboutaresultrelation,includingindexes.*/typedefstructResultRelInfo{NodeTagtype;/*resultrelation'srangetableindex*/Indexri_RangeTableIndex;/*relationdescriptorforresultrelation*/Relationri_RelationDesc;/*#ofindicesexistingonresultrelation*/intri_NumIndices;/*arrayofrelationdescriptorsforindices*/RelationPtrri_IndexRelationDescs;/*arrayofkey/attrinfoforindices*/IndexInfo**ri_IndexRelationInfo;/*triggerstobefired,ifany*/TriggerDesc*ri_TrigDesc;/*cachedlookupinfofortriggerfunctions*/FmgrInfo*ri_TrigFunctions;/*arrayoftriggerWHENexprstates*/ExprState**ri_TrigWhenExprs;/*optionalruntimemeasurementsfortriggers*/Instrumentation*ri_TrigInstrument;/*FDWcallbackfunctions,ifforeigntable*/structFdwRoutine*ri_FdwRoutine;/*availabletosaveprivatestateofFDW*/void*ri_FdwState;/*truewhenmodifyingforeigntabledirectly*/boolri_usesFdwDirectModify;/*listofWithCheckOption'stobechecked*/List*ri_WithCheckOptions;/*listofWithCheckOptionexprstates*/List*ri_WithCheckOptionExprs;/*arrayofconstraint-checkingexprstates*/ExprState**ri_ConstraintExprs;/*forremovingjunkattributesfromtuples*/JunkFilter*ri_junkFilter;/*listofRETURNINGexpressions*/List*ri_returningList;/*forcomputingaRETURNINGlist*/ProjectionInfo*ri_projectReturning;/*listofarbiterindexestousetocheckconflicts*/List*ri_onConflictArbiterIndexes;/*ONCONFLICTevaluationstate*/OnConflictSetState*ri_onConflict;/*partitioncheckexpression*/List*ri_PartitionCheck;/*partitioncheckexpressionstate*/ExprState*ri_PartitionCheckExpr;/*relationdescriptorforrootpartitionedtable*/Relationri_PartitionRoot;/*trueifreadyfortuplerouting*/boolri_PartitionReadyForRouting;}ResultRelInfo;

5、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;};

6、TransitionCaptureState

typedefstructTransitionCaptureState{/**Isthereatleastonetriggerspecifyingeachtransitionrelationon*therelationexplicitlynamedintheDMLstatementorCOPYcommand?*Note:incurrentusage,theseflagscouldbepartoftheprivatestate,*butitseemspossiblyusefultoletcallersseethem.*/booltcs_delete_old_table;booltcs_update_old_table;booltcs_update_new_table;booltcs_insert_new_table;/**ForUPDATEandDELETE,AfterTriggerSaveEventmayneedtoconvertthe*newandoldtuplesfromachildtable'sformattotheformatofthe*relationnamedinaquerysothatitiscompatiblewiththetransition*tuplestores.Thecallermuststoretheconversionmaphereifso.*/TupleConversionMap*tcs_map;/**ForINSERTandCOPY,itwouldbewastefultoconverttuplesfromchild*formattoparentformataftertheyhavealreadybeenconvertedinthe*oppositedirectionduringrouting.Inthatcasewebypassconversion*andallowtheinsertingcode(copy.candnodeModifyTable.c)toprovide*theoriginaltupledirectly.*/HeapTupletcs_original_insert_tuple;/**Privatedataincludingthetuplestore(s)intowhichtoinserttuples.*/structAfterTriggersTableData*tcs_private;}TransitionCaptureState;

*7、ModifyTable *

/*----------------*ModifyTablenode-*Applyrowsproducedbysubplan(s)toresulttable(s),*byinserting,updating,ordeleting.**NotethatrowMarksandepqParamarepresumedtobevalidforallthe*subplan(s);theycan'tcontainanyinfothatvariesacrosssubplans.*----------------*/typedefstructModifyTable{Planplan;CmdTypeoperation;/*INSERT,UPDATE,orDELETE*/boolcanSetTag;/*dowesetthecommandtag/es_processed?*/IndexnominalRelation;/*ParentRTindexforuseofEXPLAIN*//*RTindexesofnon-leaftablesinapartitiontree*/List*partitioned_rels;boolpartColsUpdated;/*somepartkeyinhierarchyupdated*/List*resultRelations;/*integerlistofRTindexes*/intresultRelIndex;/*indexoffirstresultRelinplan'slist*/introotResultRelIndex;/*indexofthepartitionedtableroot*/List*plans;/*plan(s)producingsourcedata*/List*withCheckOptionLists;/*per-target-tableWCOlists*/List*returningLists;/*per-target-tableRETURNINGtlists*/List*fdwPrivLists;/*per-target-tableFDWprivatedatalists*/Bitmapset*fdwDirectModifyPlans;/*indicesofFDWDMplans*/List*rowMarks;/*PlanRowMarks(non-lockingonly)*/intepqParam;/*IDofParamforEvalPlanQualre-eval*/OnConflictActiononConflictAction;/*ONCONFLICTaction*/List*arbiterIndexes;/*ListofONCONFLICTarbiterindexOIDs*/List*onConflictSet;/*SETforINSERTONCONFLICTDOUPDATE*/Node*onConflictWhere;/*WHEREforONCONFLICTUPDATE*/IndexexclRelRTI;/*RTIoftheEXCLUDEDpseudorelation*/List*exclRelTlist;/*tlistoftheEXCLUDEDpseudorelation*/}ModifyTable;

8、OnConflictAction

/**OnConflictAction-*"ONCONFLICT"clausetypeofquery**Thisisneededinbothparsenodes.handplannodes.h,soputithere...*/typedefenumOnConflictAction{ONCONFLICT_NONE,/*No"ONCONFLICT"clause*/ONCONFLICT_NOTHING,/*ONCONFLICT...DONOTHING*/ONCONFLICT_UPDATE/*ONCONFLICT...DOUPDATE*/}OnConflictAction;

8、MemoryContext

typedefstructMemoryContextData{NodeTagtype;/*identifiesexactkindofcontext*//*thesetwofieldsareplacedheretominimizealignmentwastage:*/boolisReset;/*T=nospaceallocedsincelastreset*/boolallowInCritSection;/*allowpallocincriticalsection*/constMemoryContextMethods*methods;/*virtualfunctiontable*/MemoryContextparent;/*NULLifnoparent(toplevelcontext)*/MemoryContextfirstchild;/*headoflinkedlistofchildren*/MemoryContextprevchild;/*previouschildofsameparent*/MemoryContextnextchild;/*nextchildofsameparent*/constchar*name;/*contextname(justfordebugging)*/constchar*ident;/*contextIDifany(justfordebugging)*/MemoryContextCallback*reset_cbs;/*listofreset/deletecallbacks*/}MemoryContextData;/*utils/palloc.hcontainstypedefstructMemoryContextData*MemoryContext*//**TypeMemoryContextDataisdeclaredinnodes/memnodes.h.Mostusers*ofmemoryallocationshouldjusttreatitasanabstracttype,sowe*donotprovidethestructcontentshere.*/typedefstructMemoryContextData*MemoryContext;

依赖的函数
1、ExecMaterializeSlot

/*--------------------------------*ExecMaterializeSlot*Forceaslotintothe"materialized"state.**Thiscausestheslot'stupletobealocalcopynotdependenton*anyexternalstorage.Apointertothecontainedtupleisreturned.**Atypicaluseforthisoperationistoprepareacomputedtuple*forbeingstoredondisk.Theoriginaldatamayormaynotbe*virtual,butinanycaseweneedaprivatecopyforheap_insert*toscribbleon.*--------------------------------*/HeapTupleExecMaterializeSlot(TupleTableSlot*slot){MemoryContextoldContext;/**sanitychecks*/Assert(slot!=NULL);Assert(!slot->tts_isempty);/**Ifwehavearegularphysicaltuple,andit'slocallypalloc'd,wehave*nothingtodo.*/if(slot->tts_tuple&&slot->tts_shouldFree)returnslot->tts_tuple;/**Otherwise,copyorbuildaphysicaltuple,andstoreitintotheslot.**Wemaybecalledinacontextthatisshorter-livedthanthetuple*slot,butwehavetoensurethatthematerializedtuplewillsurvive*anyway.*/oldContext=MemoryContextSwitchTo(slot->tts_mcxt);//内存上下文切换至slot->tts_mcxtslot->tts_tuple=ExecCopySlotTuple(slot);slot->tts_shouldFree=true;MemoryContextSwitchTo(oldContext);//内存上下文切换回原来/**Dropthepinonthereferencedbuffer,ifthereisone.*/if(BufferIsValid(slot->tts_buffer))ReleaseBuffer(slot->tts_buffer);slot->tts_buffer=InvalidBuffer;/**Markextractedstateinvalid.Thisisimportantbecausetheslotis*notsupposedtodependanymoreonthepreviousexternaldata;we*mustn'tleaveanydanglingpass-by-referencedatumsintts_values.*However,wehavenotactuallyinvalidatedanysuchdatums,ifthere*happentobeanypreviouslyfetchedfromtheslot.(Noteinparticular*thatwehavenotpfree'dtts_mintuple,ifthereisone.)*/slot->tts_nvalid=0;/**Onthesameprincipleofnotdependingonpreviousremotestorage,*forgetthemintupleifit'snotlocalstorage.(Ifitislocal*storage,wemustnotpfreeitnow,sincecallersmighthavealready*fetcheddatumpointersreferencingit.)*/if(!slot->tts_shouldFreeMin)slot->tts_mintuple=NULL;returnslot->tts_tuple;}#ifndefFRONTENDstaticinlineMemoryContextMemoryContextSwitchTo(MemoryContextcontext){MemoryContextold=CurrentMemoryContext;CurrentMemoryContext=context;returnold;}#endif/*FRONTEND*/

2、HeapTupleSetOid

#defineHeapTupleSetOid(tuple,oid)\HeapTupleHeaderSetOid((tuple)->t_data,(oid))

3、ExecBRInsertTriggers

TupleTableSlot*ExecBRInsertTriggers(EState*estate,ResultRelInfo*relinfo,TupleTableSlot*slot){TriggerDesc*trigdesc=relinfo->ri_TrigDesc;HeapTupleslottuple=ExecMaterializeSlot(slot);HeapTuplenewtuple=slottuple;HeapTupleoldtuple;TriggerDataLocTriggerData;inti;LocTriggerData.type=T_TriggerData;LocTriggerData.tg_event=TRIGGER_EVENT_INSERT|TRIGGER_EVENT_ROW|TRIGGER_EVENT_BEFORE;LocTriggerData.tg_relation=relinfo->ri_RelationDesc;LocTriggerData.tg_newtuple=NULL;LocTriggerData.tg_oldtable=NULL;LocTriggerData.tg_newtable=NULL;LocTriggerData.tg_newtuplebuf=InvalidBuffer;for(i=0;i<trigdesc->numtriggers;i++){Trigger*trigger=&trigdesc->triggers[i];if(!TRIGGER_TYPE_MATCHES(trigger->tgtype,TRIGGER_TYPE_ROW,TRIGGER_TYPE_BEFORE,TRIGGER_TYPE_INSERT))continue;if(!TriggerEnabled(estate,relinfo,trigger,LocTriggerData.tg_event,NULL,NULL,newtuple))continue;LocTriggerData.tg_trigtuple=oldtuple=newtuple;LocTriggerData.tg_trigtuplebuf=InvalidBuffer;LocTriggerData.tg_trigger=trigger;newtuple=ExecCallTriggerFunc(&LocTriggerData,i,relinfo->ri_TrigFunctions,relinfo->ri_TrigInstrument,GetPerTupleMemoryContext(estate));if(oldtuple!=newtuple&&oldtuple!=slottuple)heap_freetuple(oldtuple);if(newtuple==NULL)returnNULL;/*"donothing"*/}if(newtuple!=slottuple){/**Returnthemodifiedtupleusingthees_trig_tuple_slot.Weassume*thetuplewasallocatedinper-tuplememorycontext,andtherefore*willgoawaybyitself.Thetupletableslotshouldnottryto*clearit.*/TupleTableSlot*newslot=estate->es_trig_tuple_slot;TupleDesctupdesc=RelationGetDescr(relinfo->ri_RelationDesc);if(newslot->tts_tupleDescriptor!=tupdesc)ExecSetSlotDescriptor(newslot,tupdesc);ExecStoreTuple(newtuple,newslot,InvalidBuffer,false);slot=newslot;}returnslot;}

4、ExecIRInsertTriggers

TupleTableSlot*ExecIRInsertTriggers(EState*estate,ResultRelInfo*relinfo,TupleTableSlot*slot){TriggerDesc*trigdesc=relinfo->ri_TrigDesc;HeapTupleslottuple=ExecMaterializeSlot(slot);HeapTuplenewtuple=slottuple;HeapTupleoldtuple;TriggerDataLocTriggerData;inti;LocTriggerData.type=T_TriggerData;LocTriggerData.tg_event=TRIGGER_EVENT_INSERT|TRIGGER_EVENT_ROW|TRIGGER_EVENT_INSTEAD;LocTriggerData.tg_relation=relinfo->ri_RelationDesc;LocTriggerData.tg_newtuple=NULL;LocTriggerData.tg_oldtable=NULL;LocTriggerData.tg_newtable=NULL;LocTriggerData.tg_newtuplebuf=InvalidBuffer;for(i=0;i<trigdesc->numtriggers;i++){Trigger*trigger=&trigdesc->triggers[i];if(!TRIGGER_TYPE_MATCHES(trigger->tgtype,TRIGGER_TYPE_ROW,TRIGGER_TYPE_INSTEAD,TRIGGER_TYPE_INSERT))continue;if(!TriggerEnabled(estate,relinfo,trigger,LocTriggerData.tg_event,NULL,NULL,newtuple))continue;LocTriggerData.tg_trigtuple=oldtuple=newtuple;LocTriggerData.tg_trigtuplebuf=InvalidBuffer;LocTriggerData.tg_trigger=trigger;newtuple=ExecCallTriggerFunc(&LocTriggerData,i,relinfo->ri_TrigFunctions,relinfo->ri_TrigInstrument,GetPerTupleMemoryContext(estate));if(oldtuple!=newtuple&&oldtuple!=slottuple)heap_freetuple(oldtuple);if(newtuple==NULL)returnNULL;/*"donothing"*/}if(newtuple!=slottuple){/**Returnthemodifiedtupleusingthees_trig_tuple_slot.Weassume*thetuplewasallocatedinper-tuplememorycontext,andtherefore*willgoawaybyitself.Thetupletableslotshouldnottryto*clearit.*/TupleTableSlot*newslot=estate->es_trig_tuple_slot;TupleDesctupdesc=RelationGetDescr(relinfo->ri_RelationDesc);if(newslot->tts_tupleDescriptor!=tupdesc)ExecSetSlotDescriptor(newslot,tupdesc);ExecStoreTuple(newtuple,newslot,InvalidBuffer,false);slot=newslot;}returnslot;}

5、ExecForeignInsert

--函数指针typedefTupleTableSlot*(*ExecForeignInsert_function)(EState*estate,ResultRelInfo*rinfo,TupleTableSlot*slot,TupleTableSlot*planSlot);ExecForeignInsert_functionExecForeignInsert;

6、RelationGetRelid

/**RelationGetRelid*ReturnstheOIDoftherelation*/#defineRelationGetRelid(relation)((relation)->rd_id)

7、ExecWithCheckOptions

/**ExecWithCheckOptions--checkthattuplesatisfiesanyWITHCHECKOPTIONs*ofthespecifiedkind.**Notethatthisneedstobecalledmultipletimestoensurethatallkindsof*WITHCHECKOPTIONsarehandled(boththosefromviewswhichhavetheWITH*CHECKOPTIONsetandfromrowlevelsecuritypolicies).SeeExecInsert()*andExecUpdate().*/voidExecWithCheckOptions(WCOKindkind,ResultRelInfo*resultRelInfo,TupleTableSlot*slot,EState*estate){Relationrel=resultRelInfo->ri_RelationDesc;TupleDesctupdesc=RelationGetDescr(rel);ExprContext*econtext;ListCell*l1,*l2;/**WewillusetheEState'sper-tuplecontextforevaluatingconstraint*expressions(creatingitifit'snotalreadythere).*/econtext=GetPerTupleExprContext(estate);/*Arrangeforecontext'sscantupletobethetupleundertest*/econtext->ecxt_scantuple=slot;/*Checkeachoftheconstraints*/forboth(l1,resultRelInfo->ri_WithCheckOptions,l2,resultRelInfo->ri_WithCheckOptionExprs){WithCheckOption*wco=(WithCheckOption*)lfirst(l1);ExprState*wcoExpr=(ExprState*)lfirst(l2);/**SkipanyWCOswhicharenotthekindwearelookingforatthis*time.*/if(wco->kind!=kind)continue;/**WITHCHECKOPTIONchecksareintendedtoensurethatthenewtuple*isvisible(inthecaseofaview)orthatitpassesthe*'with-check'policy(inthecaseofrowsecurity).Ifthequal*evaluatestoNULLorFALSE,thenthenewtuplewon'tbeincludedin*theviewordoesn'tpassthe'with-check'policyforthetable.*/if(!ExecQual(wcoExpr,econtext)){char*val_desc;Bitmapset*modifiedCols;Bitmapset*insertedCols;Bitmapset*updatedCols;switch(wco->kind){/**ForWITHCHECKOPTIONscomingfromviews,wemightbe*abletoprovidethedetailsontherow,dependingon*thepermissionsontherelation(thatis,iftheuser*couldviewitdirectlyanyway).ForRLSviolations,we*don'tincludethedatasincewedon'tknowiftheuser*shouldbeabletoviewthetupleasthatdependsonthe*USINGpolicy.*/caseWCO_VIEW_CHECK:/*SeethecommentinExecConstraints().*/if(resultRelInfo->ri_PartitionRoot){HeapTupletuple=ExecFetchSlotTuple(slot);TupleDescold_tupdesc=RelationGetDescr(rel);TupleConversionMap*map;rel=resultRelInfo->ri_PartitionRoot;tupdesc=RelationGetDescr(rel);/*areversemap*/map=convert_tuples_by_name(old_tupdesc,tupdesc,gettext_noop("couldnotconvertrowtype"));if(map!=NULL){tuple=do_convert_tuple(tuple,map);ExecSetSlotDescriptor(slot,tupdesc);ExecStoreTuple(tuple,slot,InvalidBuffer,false);}}insertedCols=GetInsertedColumns(resultRelInfo,estate);updatedCols=GetUpdatedColumns(resultRelInfo,estate);modifiedCols=bms_union(insertedCols,updatedCols);val_desc=ExecBuildSlotValueDescription(RelationGetRelid(rel),slot,tupdesc,modifiedCols,64);ereport(ERROR,(errcode(ERRCODE_WITH_CHECK_OPTION_VIOLATION),errmsg("newrowviolatescheckoptionforview\"%s\"",wco->relname),val_desc?errdetail("Failingrowcontains%s.",val_desc):0));break;caseWCO_RLS_INSERT_CHECK:caseWCO_RLS_UPDATE_CHECK:if(wco->polname!=NULL)ereport(ERROR,(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),errmsg("newrowviolatesrow-levelsecuritypolicy\"%s\"fortable\"%s\"",wco->polname,wco->relname)));elseereport(ERROR,(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),errmsg("newrowviolatesrow-levelsecuritypolicyfortable\"%s\"",wco->relname)));break;caseWCO_RLS_CONFLICT_CHECK:if(wco->polname!=NULL)ereport(ERROR,(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),errmsg("newrowviolatesrow-levelsecuritypolicy\"%s\"(USINGexpression)fortable\"%s\"",wco->polname,wco->relname)));elseereport(ERROR,(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),errmsg("newrowviolatesrow-levelsecuritypolicy(USINGexpression)fortable\"%s\"",wco->relname)));break;default:elog(ERROR,"unrecognizedWCOkind:%u",wco->kind);break;}}}}

8、ExecConstraints

/**ExecConstraints-checkconstraintsofthetuplein'slot'**ThischecksthetraditionalNOTNULLandcheckconstraints.**Thepartitionconstraintis*NOT*checked.**Note:'slot'containsthetupletochecktheconstraintsof,whichmay*havebeenconvertedfromtheoriginalinputtupleaftertuplerouting.*'resultRelInfo'isthefinalresultrelation,aftertuplerouting.*/voidExecConstraints(ResultRelInfo*resultRelInfo,TupleTableSlot*slot,EState*estate){Relationrel=resultRelInfo->ri_RelationDesc;TupleDesctupdesc=RelationGetDescr(rel);TupleConstr*constr=tupdesc->constr;Bitmapset*modifiedCols;Bitmapset*insertedCols;Bitmapset*updatedCols;Assert(constr||resultRelInfo->ri_PartitionCheck);if(constr&&constr->has_not_null){intnatts=tupdesc->natts;intattrChk;for(attrChk=1;attrChk<=natts;attrChk++){Form_pg_attributeatt=TupleDescAttr(tupdesc,attrChk-1);if(att->attnotnull&&slot_attisnull(slot,attrChk)){char*val_desc;Relationorig_rel=rel;TupleDescorig_tupdesc=RelationGetDescr(rel);/**Ifthetuplehasbeenrouted,it'sbeenconvertedtothe*partition'srowtype,whichmightdifferfromtheroot*table's.Wemustconvertitbacktotheroottable's*rowtypesothatval_descshownerrormessagematchesthe*inputtuple.*/if(resultRelInfo->ri_PartitionRoot){HeapTupletuple=ExecFetchSlotTuple(slot);TupleConversionMap*map;rel=resultRelInfo->ri_PartitionRoot;tupdesc=RelationGetDescr(rel);/*areversemap*/map=convert_tuples_by_name(orig_tupdesc,tupdesc,gettext_noop("couldnotconvertrowtype"));if(map!=NULL){tuple=do_convert_tuple(tuple,map);ExecSetSlotDescriptor(slot,tupdesc);ExecStoreTuple(tuple,slot,InvalidBuffer,false);}}insertedCols=GetInsertedColumns(resultRelInfo,estate);updatedCols=GetUpdatedColumns(resultRelInfo,estate);modifiedCols=bms_union(insertedCols,updatedCols);val_desc=ExecBuildSlotValueDescription(RelationGetRelid(rel),slot,tupdesc,modifiedCols,64);ereport(ERROR,(errcode(ERRCODE_NOT_NULL_VIOLATION),errmsg("nullvalueincolumn\"%s\"violatesnot-nullconstraint",NameStr(att->attname)),val_desc?errdetail("Failingrowcontains%s.",val_desc):0,errtablecol(orig_rel,attrChk)));}}}if(constr&&constr->num_check>0){constchar*failed;if((failed=ExecRelCheck(resultRelInfo,slot,estate))!=NULL){char*val_desc;Relationorig_rel=rel;/*Seethecommentabove.*/if(resultRelInfo->ri_PartitionRoot){HeapTupletuple=ExecFetchSlotTuple(slot);TupleDescold_tupdesc=RelationGetDescr(rel);TupleConversionMap*map;rel=resultRelInfo->ri_PartitionRoot;tupdesc=RelationGetDescr(rel);/*areversemap*/map=convert_tuples_by_name(old_tupdesc,tupdesc,gettext_noop("couldnotconvertrowtype"));if(map!=NULL){tuple=do_convert_tuple(tuple,map);ExecSetSlotDescriptor(slot,tupdesc);ExecStoreTuple(tuple,slot,InvalidBuffer,false);}}insertedCols=GetInsertedColumns(resultRelInfo,estate);updatedCols=GetUpdatedColumns(resultRelInfo,estate);modifiedCols=bms_union(insertedCols,updatedCols);val_desc=ExecBuildSlotValueDescription(RelationGetRelid(rel),slot,tupdesc,modifiedCols,64);ereport(ERROR,(errcode(ERRCODE_CHECK_VIOLATION),errmsg("newrowforrelation\"%s\"violatescheckconstraint\"%s\"",RelationGetRelationName(orig_rel),failed),val_desc?errdetail("Failingrowcontains%s.",val_desc):0,errtableconstraint(orig_rel,failed)));}}}

9、ExecPartitionCheck

/**ExecPartitionCheck---checkthattuplemeetsthepartitionconstraint.**Returnstrueifitmeetsthepartitionconstraint.Iftheconstraint*failsandwe'reaskedtoemittoerror,dosoanddon'treturn;otherwise*returnfalse.*/boolExecPartitionCheck(ResultRelInfo*resultRelInfo,TupleTableSlot*slot,EState*estate,boolemitError){ExprContext*econtext;boolsuccess;/**Iffirsttimethrough,buildexpressionstatetreeforthepartition*checkexpression.Keepitintheper-querymemorycontextsothey'll*survivethroughoutthequery.*/if(resultRelInfo->ri_PartitionCheckExpr==NULL){List*qual=resultRelInfo->ri_PartitionCheck;resultRelInfo->ri_PartitionCheckExpr=ExecPrepareCheck(qual,estate);}/**WewillusetheEState'sper-tuplecontextforevaluatingconstraint*expressions(creatingitifit'snotalreadythere).*/econtext=GetPerTupleExprContext(estate);/*Arrangeforecontext'sscantupletobethetupleundertest*/econtext->ecxt_scantuple=slot;/**Asincaseofthecataloguedconstraints,wetreataNULLresultas*successhere,notafailure.*/success=ExecCheck(resultRelInfo->ri_PartitionCheckExpr,econtext);/*ifaskedtoemiterror,don'tactuallyreturnonfailure*/if(!success&&emitError)ExecPartitionCheckEmitError(resultRelInfo,slot,estate);returnsuccess;}

10、ExecCheckIndexConstraints

/*----------------------------------------------------------------*ExecCheckIndexConstraints**Thisroutinechecksifatupleviolatesanyuniqueor*exclusionconstraints.Returnstrueifthereisnoconflict.*Otherwisereturnsfalse,andtheTIDoftheconflicting*tupleisreturnedin*conflictTid.**If'arbiterIndexes'isgiven,onlythoseindexesarechecked.*NILmeansallindexes.**Notethatthisdoesn'tlockthevaluesinanyway,soit's*possiblethataconflictingtupleisinsertedimmediately*afterthisreturns.Butthiscanbeusedforapre-check*beforeinsertion.*----------------------------------------------------------------*/boolExecCheckIndexConstraints(TupleTableSlot*slot,EState*estate,ItemPointerconflictTid,List*arbiterIndexes){ResultRelInfo*resultRelInfo;inti;intnumIndices;RelationPtrrelationDescs;RelationheapRelation;IndexInfo**indexInfoArray;ExprContext*econtext;Datumvalues[INDEX_MAX_KEYS];boolisnull[INDEX_MAX_KEYS];ItemPointerDatainvalidItemPtr;boolcheckedIndex=false;ItemPointerSetInvalid(conflictTid);ItemPointerSetInvalid(&invalidItemPtr);/**Getinformationfromtheresultrelationinfostructure.*/resultRelInfo=estate->es_result_relation_info;numIndices=resultRelInfo->ri_NumIndices;relationDescs=resultRelInfo->ri_IndexRelationDescs;indexInfoArray=resultRelInfo->ri_IndexRelationInfo;heapRelation=resultRelInfo->ri_RelationDesc;/**WewillusetheEState'sper-tuplecontextforevaluatingpredicates*andindexexpressions(creatingitifit'snotalreadythere).*/econtext=GetPerTupleExprContext(estate);/*Arrangeforecontext'sscantupletobethetupleundertest*/econtext->ecxt_scantuple=slot;/**Foreachindex,formindextupleandcheckifitsatisfiesthe*constraint.*/for(i=0;i<numIndices;i++){RelationindexRelation=relationDescs[i];IndexInfo*indexInfo;boolsatisfiesConstraint;if(indexRelation==NULL)continue;indexInfo=indexInfoArray[i];if(!indexInfo->ii_Unique&&!indexInfo->ii_ExclusionOps)continue;/*Iftheindexismarkedasread-only,ignoreit*/if(!indexInfo->ii_ReadyForInserts)continue;/*Whenspecificarbiterindexesrequested,onlyexaminethem*/if(arbiterIndexes!=NIL&&!list_member_oid(arbiterIndexes,indexRelation->rd_index->indexrelid))continue;if(!indexRelation->rd_index->indimmediate)ereport(ERROR,(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),errmsg("ONCONFLICTdoesnotsupportdeferrableuniqueconstraints/exclusionconstraintsasarbiters"),errtableconstraint(heapRelation,RelationGetRelationName(indexRelation))));checkedIndex=true;/*Checkforpartialindex*/if(indexInfo->ii_Predicate!=NIL){ExprState*predicate;/**Ifpredicatestatenotsetupyet,createit(intheestate's*per-querycontext)*/predicate=indexInfo->ii_PredicateState;if(predicate==NULL){predicate=ExecPrepareQual(indexInfo->ii_Predicate,estate);indexInfo->ii_PredicateState=predicate;}/*Skipthisindex-updateifthepredicateisn'tsatisfied*/if(!ExecQual(predicate,econtext))continue;}/**FormIndexDatumfillsinitsvaluesandisnullparameterswiththe*appropriatevaluesforthecolumn(s)oftheindex.*/FormIndexDatum(indexInfo,slot,estate,values,isnull);satisfiesConstraint=check_exclusion_or_unique_constraint(heapRelation,indexRelation,indexInfo,&invalidItemPtr,values,isnull,estate,false,CEOUC_WAIT,true,conflictTid);if(!satisfiesConstraint)returnfalse;}if(arbiterIndexes!=NIL&&!checkedIndex)elog(ERROR,"unexpectedfailuretofindarbiterindex");returntrue;}

11、ExecOnConflictUpdate

/**ExecOnConflictUpdate---executeUPDATEofINSERTONCONFLICTDOUPDATE**Trytolocktupleforupdateaspartofspeculativeinsertion.If*aqualoriginatingfromONCONFLICTDOUPDATEissatisfied,update*(butstilllockrow,eventhoughitmaynotsatisfyestate's*snapshot).**Returnstrueifwe'redone(withorwithoutanupdate),orfalseif*thecallermustretrytheINSERTfromscratch.*/staticboolExecOnConflictUpdate(ModifyTableState*mtstate,ResultRelInfo*resultRelInfo,ItemPointerconflictTid,TupleTableSlot*planSlot,TupleTableSlot*excludedSlot,EState*estate,boolcanSetTag,TupleTableSlot**returning){ExprContext*econtext=mtstate->ps.ps_ExprContext;Relationrelation=resultRelInfo->ri_RelationDesc;ExprState*onConflictSetWhere=resultRelInfo->ri_onConflict->oc_WhereClause;HeapTupleDatatuple;HeapUpdateFailureDatahufd;LockTupleModelockmode;HTSU_Resulttest;Bufferbuffer;/*Determinelockmodetouse*/lockmode=ExecUpdateLockMode(estate,resultRelInfo);/**Locktupleforupdate.Don'tfollowupdateswhentuplecannotbe*lockedwithoutdoingso.Arowlockingconflictheremeansour*previousconclusionthatthetupleisconclusivelycommittedisnot*trueanymore.*/tuple.t_self=*conflictTid;test=heap_lock_tuple(relation,&tuple,estate->es_output_cid,lockmode,LockWaitBlock,false,&buffer,&hufd);switch(test){caseHeapTupleMayBeUpdated:/*success!*/break;caseHeapTupleInvisible:/**Thiscanoccurwhenajustinsertedtupleisupdatedagainin*thesamecommand.E.g.becausemultiplerowswiththesame*conflictingkeyvaluesareinserted.**ThisissomewhatsimilartotheExecUpdate()*HeapTupleSelfUpdatedcase.Wedonotwanttoproceedbecause*itwouldleadtothesamerowbeingupdatedasecondtimein*someunspecifiedorder,andincontrasttoplainUPDATEs*there'snohistoricalbehaviortobreak.**Itistheuser'sresponsibilitytopreventthissituationfrom*occurring.TheseproblemsarewhySQL-2003similarlyspecifies*thatforSQLMERGE,anexceptionmustberaisedintheeventof*anattempttoupdatethesamerowtwice.*/if(TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple.t_data)))ereport(ERROR,(errcode(ERRCODE_CARDINALITY_VIOLATION),errmsg("ONCONFLICTDOUPDATEcommandcannotaffectrowasecondtime"),errhint("Ensurethatnorowsproposedforinsertionwithinthesamecommandhaveduplicateconstrainedvalues.")));/*Thisshouldn'thappen*/elog(ERROR,"attemptedtolockinvisibletuple");break;caseHeapTupleSelfUpdated:/**Thisstateshouldneverbereached.Asadirtysnapshotisused*tofindconflictingtuples,speculativeinsertionwouldn'thave*seenthisrowtoconflictwith.*/elog(ERROR,"unexpectedself-updatedtuple");break;caseHeapTupleUpdated:if(IsolationUsesXactSnapshot())ereport(ERROR,(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),errmsg("couldnotserializeaccessduetoconcurrentupdate")));/**Aslongaswedon'tsupportanUPDATEofINSERTONCONFLICTfor*apartitionedtableweshouldn'treachtoacasewheretupleto*belockismovedtoanotherpartitionduetoconcurrentupdate*ofthepartitionkey.*/Assert(!ItemPointerIndicatesMovedPartitions(&hufd.ctid));/**Tellcallertotryagainfromtheverystart.**ItdoesnotmakesensetousetheusualEvalPlanQual()style*loophere,asthenewversionoftherowmightnotconflict*anymore,ortheconflictingtuplehasactuallybeendeleted.*/ReleaseBuffer(buffer);returnfalse;default:elog(ERROR,"unrecognizedheap_lock_tuplestatus:%u",test);}/**Success,thetupleislocked.**Resetper-tuplememorycontexttofreeanyexpressionevaluation*storageallocatedinthepreviouscycle.*/ResetExprContext(econtext);/**VerifythatthetupleisvisibletoourMVCCsnapshotifthecurrent*isolationlevelmandatesthat.**It'snotsufficienttorelyonthecheckwithinExecUpdate()ase.g.*CONFLICT...WHEREclausemaypreventusfromreachingthat.**Thismeansweonlyevercontinuewhenanewcommandinthecurrent*transactioncouldseetherow,eventhoughinREADCOMMITTEDmodethe*tuplewillnotbevisibleaccordingtothecurrentstatement's*snapshot.ThisisinlinewiththewayUPDATEdealswithnewertuple*versions.*/ExecCheckHeapTupleVisible(estate,&tuple,buffer);/*Storetarget'sexistingtupleinthestate'sdedicatedslot*/ExecStoreTuple(&tuple,mtstate->mt_existing,buffer,false);/**MaketupleandanyneededjoinvariablesavailabletoExecQualand*ExecProject.TheEXCLUDEDtupleisinstalledinecxt_innertuple,while*thetarget'sexistingtupleisinstalledinthescantuple.EXCLUDED*hasbeenmadetoreferenceINNER_VARinsetrefs.c,butthereisno*otherredirection.*/econtext->ecxt_scantuple=mtstate->mt_existing;econtext->ecxt_innertuple=excludedSlot;econtext->ecxt_outertuple=NULL;if(!ExecQual(onConflictSetWhere,econtext)){ReleaseBuffer(buffer);InstrCountFiltered1(&mtstate->ps,1);returntrue;/*donewiththetuple*/}if(resultRelInfo->ri_WithCheckOptions!=NIL){/**Checktarget'sexistingtupleagainstUPDATE-applicableUSING*securitybarrierquals(ifany),enforcedhereasRLSchecks/WCOs.**TherewritercreatesUPDATERLSchecks/WCOsforUPDATEsecurity*quals,andstoresthemasWCOsof"kind"WCO_RLS_CONFLICT_CHECK,*butthat'salmosttheextentofitsspecialhandlingforON*CONFLICTDOUPDATE.**TherewriterwillalsohaveassociatedUPDATEapplicablestraight*RLSchecks/WCOsforthebenefitoftheExecUpdate()callthat*follows.INSERTsandUPDATEsnaturallyhavemutuallyexclusiveWCO*kinds,sothereisnodangerofspuriousover-enforcementinthe*INSERTorUPDATEpath.*/ExecWithCheckOptions(WCO_RLS_CONFLICT_CHECK,resultRelInfo,mtstate->mt_existing,mtstate->ps.state);}/*Projectthenewtupleversion*/ExecProject(resultRelInfo->ri_onConflict->oc_ProjInfo);/**Notethatitispossiblethatthetargettuplehasbeenmodifiedin*thissession,aftertheaboveheap_lock_tuple.Wechoosetonoterror*outinthatcase,inlinewithExecUpdate'streatmentofsimilarcases.*ThiscanhappenifanUPDATEistriggeredfromwithinExecQual(),*ExecWithCheckOptions()orExecProject()above,e.g.byselectingfroma*wCTEintheONCONFLICT'sSET.*//*ExecuteUPDATEwithprojection*/*returning=ExecUpdate(mtstate,&tuple.t_self,NULL,mtstate->mt_conflproj,planSlot,&mtstate->mt_epqstate,mtstate->ps.state,canSetTag);ReleaseBuffer(buffer);returntrue;}

12、InstrCountTuples2

/*Macrosforinlineaccesstocertaininstrumentationcounters*/#defineInstrCountTuples2(node,delta)\do{\if(((PlanState*)(node))->instrument)\((PlanState*)(node))->instrument->ntuples2+=(delta);\}while(0)

13、ExecCheckTIDVisible

/**ExecCheckTIDVisible--conveniencevariantofExecCheckHeapTupleVisible()*/staticvoidExecCheckTIDVisible(EState*estate,ResultRelInfo*relinfo,ItemPointertid){Relationrel=relinfo->ri_RelationDesc;Bufferbuffer;HeapTupleDatatuple;/*Redundantlycheckisolationlevel*/if(!IsolationUsesXactSnapshot())return;tuple.t_self=*tid;if(!heap_fetch(rel,SnapshotAny,&tuple,&buffer,false,NULL))elog(ERROR,"failedtofetchconflictingtupleforONCONFLICT");ExecCheckHeapTupleVisible(estate,&tuple,buffer);ReleaseBuffer(buffer);}

14、SpeculativeInsertionLockAcquire

/**SpeculativeInsertionLockAcquire**InsertalockshowingthatthegiventransactionIDisinsertingatuple,*buthasn'tyetdecidedwhetherit'sgoingtokeepit.Thelockcanthenbe*usedtowaitforthedecisiontogoaheadwiththeinsertion,oraborting*it.**Thetokenisusedtodistinguishmultipleinsertionsbythesame*transaction.Itisreturnedtocaller.*/uint32SpeculativeInsertionLockAcquire(TransactionIdxid){LOCKTAGtag;speculativeInsertionToken++;/**Checkforwrap-around.Zeromeansnotokenisheld,sodon'tusethat.*/if(speculativeInsertionToken==0)speculativeInsertionToken=1;SET_LOCKTAG_SPECULATIVE_INSERTION(tag,xid,speculativeInsertionToken);(void)LockAcquire(&tag,ExclusiveLock,false,false);returnspeculativeInsertionToken;}

15、HeapTupleHeaderSetSpeculativeToken

#defineHeapTupleHeaderSetSpeculativeToken(tup,token)\(\ItemPointerSet(&(tup)->t_ctid,token,SpecTokenOffsetNumber)\)

16、heap_insert

//上一节已介绍

17、ExecInsertIndexTuples

/*----------------------------------------------------------------*ExecInsertIndexTuples**Thisroutinetakescareofinsertingindextuples*intoalltherelationsindexingtheresultrelation*whenaheaptupleisinsertedintotheresultrelation.**Uniqueandexclusionconstraintsareenforcedatthesame*time.ThisreturnsalistofindexOIDsforanyuniqueor*exclusionconstraintsthataredeferredandthathad*potential(unconfirmed)conflicts.(ifnoDupErr==true,*thesameisdonefornon-deferredconstraints,butreport*ifconflictwasspeculativeordeferredconflicttocaller)**If'arbiterIndexes'isnonempty,noDupErrappliesonlyto*thoseindexes.NILmeansnoDupErrappliestoallindexes.**CAUTION:thismustnotbecalledforaHOTupdate.*Wecan'tdefendagainstthathereforlackofinfo.*ShouldwechangetheAPItomakeitsafer?*----------------------------------------------------------------*/List*ExecInsertIndexTuples(TupleTableSlot*slot,ItemPointertupleid,EState*estate,boolnoDupErr,bool*specConflict,List*arbiterIndexes){List*result=NIL;ResultRelInfo*resultRelInfo;inti;intnumIndices;RelationPtrrelationDescs;RelationheapRelation;IndexInfo**indexInfoArray;ExprContext*econtext;Datumvalues[INDEX_MAX_KEYS];boolisnull[INDEX_MAX_KEYS];/**Getinformationfromtheresultrelationinfostructure.*/resultRelInfo=estate->es_result_relation_info;numIndices=resultRelInfo->ri_NumIndices;relationDescs=resultRelInfo->ri_IndexRelationDescs;indexInfoArray=resultRelInfo->ri_IndexRelationInfo;heapRelation=resultRelInfo->ri_RelationDesc;/**WewillusetheEState'sper-tuplecontextforevaluatingpredicates*andindexexpressions(creatingitifit'snotalreadythere).*/econtext=GetPerTupleExprContext(estate);/*Arrangeforecontext'sscantupletobethetupleundertest*/econtext->ecxt_scantuple=slot;/**foreachindex,formandinserttheindextuple*/for(i=0;i<numIndices;i++){RelationindexRelation=relationDescs[i];IndexInfo*indexInfo;boolapplyNoDupErr;IndexUniqueCheckcheckUnique;boolsatisfiesConstraint;if(indexRelation==NULL)continue;indexInfo=indexInfoArray[i];/*Iftheindexismarkedasread-only,ignoreit*/if(!indexInfo->ii_ReadyForInserts)continue;/*Checkforpartialindex*/if(indexInfo->ii_Predicate!=NIL){ExprState*predicate;/**Ifpredicatestatenotsetupyet,createit(intheestate's*per-querycontext)*/predicate=indexInfo->ii_PredicateState;if(predicate==NULL){predicate=ExecPrepareQual(indexInfo->ii_Predicate,estate);indexInfo->ii_PredicateState=predicate;}/*Skipthisindex-updateifthepredicateisn'tsatisfied*/if(!ExecQual(predicate,econtext))continue;}/**FormIndexDatumfillsinitsvaluesandisnullparameterswiththe*appropriatevaluesforthecolumn(s)oftheindex.*/FormIndexDatum(indexInfo,slot,estate,values,isnull);/*CheckwhethertoapplynoDupErrtothisindex*/applyNoDupErr=noDupErr&&(arbiterIndexes==NIL||list_member_oid(arbiterIndexes,indexRelation->rd_index->indexrelid));/**TheindexAMdoestheactualinsertion,plusuniquenesschecking.**Foranimmediate-modeuniqueindex,wejusttelltheindexAMto*throwerrorifnotunique.**Foradeferrableuniqueindex,wetelltheindexAMtojustdetect*possiblenon-uniqueness,andweaddtheindexOIDtotheresult*listiffurthercheckingisneeded.**Foraspeculativeinsertion(usedbyINSERT...ONCONFLICT),do*thesameasforadeferrableuniqueindex.*/if(!indexRelation->rd_index->indisunique)checkUnique=UNIQUE_CHECK_NO;elseif(applyNoDupErr)checkUnique=UNIQUE_CHECK_PARTIAL;elseif(indexRelation->rd_index->indimmediate)checkUnique=UNIQUE_CHECK_YES;elsecheckUnique=UNIQUE_CHECK_PARTIAL;satisfiesConstraint=index_insert(indexRelation,/*indexrelation*/values,/*arrayofindexDatums*/isnull,/*nullflags*/tupleid,/*tidofheaptuple*/heapRelation,/*heaprelation*/checkUnique,/*typeofuniquenesschecktodo*/indexInfo);/*indexAMmayneedthis*//**Iftheindexhasanassociatedexclusionconstraint,checkthat.*Thisissimplerthantheprocessforuniquenesscheckssincewe*alwaysinsertfirstandthencheck.Iftheconstraintisdeferred,*wechecknowanyway,butdon'tthrowerroronviolationorwaitfor*aconclusiveoutcomefromaconcurrentinsertion;insteadwe'll*queuearecheckevent.Similarly,noDupErrcallers(speculative*inserters)willrechecklater,andwaitforaconclusiveoutcome*then.**Anindexforanexclusionconstraintcan'talsobeUNIQUE(notan*essentialproperty,wejustdon'tallowitinthegrammar),sono*needtopreservethepriorstateofsatisfiesConstraint.*/if(indexInfo->ii_ExclusionOps!=NULL){boolviolationOK;CEOUC_WAIT_MODEwaitMode;if(applyNoDupErr){violationOK=true;waitMode=CEOUC_LIVELOCK_PREVENTING_WAIT;}elseif(!indexRelation->rd_index->indimmediate){violationOK=true;waitMode=CEOUC_NOWAIT;}else{violationOK=false;waitMode=CEOUC_WAIT;}satisfiesConstraint=check_exclusion_or_unique_constraint(heapRelation,indexRelation,indexInfo,tupleid,values,isnull,estate,false,waitMode,violationOK,NULL);}if((checkUnique==UNIQUE_CHECK_PARTIAL||indexInfo->ii_ExclusionOps!=NULL)&&!satisfiesConstraint){/**Thetuplepotentiallyviolatestheuniquenessorexclusion*constraint,somakeanoteoftheindexsothatwecanre-check*itlater.Speculativeinsertersaretoldiftherewasa*speculativeconflict,sincethatalwaysrequiresarestart.*/result=lappend_oid(result,RelationGetRelid(indexRelation));if(indexRelation->rd_index->indimmediate&&specConflict)*specConflict=true;}}returnresult;}

18、heap_finish_speculative

/**heap_finish_speculative-markspeculativeinsertionassuccessful**Tosuccessfullyfinishaspeculativeinsertionwehavetoclearspeculative*tokenfromtuple.Todosothet_ctidfield,whichwillcontaina*speculativetokenvalue,ismodifiedinplacetopointtothetupleitself,*whichischaracteristicofanewlyinsertedordinarytuple.**NB:Itisnotoktocommitwithouteitherfinishingorabortinga*speculativeinsertion.Wecouldtreatspeculativetuplesofcommitted*transactionsimplicitlyascompleted,butthenwewouldhavetobeprepared*todealwithspeculativetokensoncommittedtuples.Thatwouldn'tbe*difficult-no-onelooksatthectidfieldofatuplewithinvalidxmax-*butclearingthetokenatcompletionisn'tveryexpensiveeither.*AnexplicitconfirmationWALrecordalsomakeslogicaldecodingsimpler.*/voidheap_finish_speculative(Relationrelation,HeapTupletuple){Bufferbuffer;Pagepage;OffsetNumberoffnum;ItemIdlp=NULL;HeapTupleHeaderhtup;buffer=ReadBuffer(relation,ItemPointerGetBlockNumber(&(tuple->t_self)));LockBuffer(buffer,BUFFER_LOCK_EXCLUSIVE);page=(Page)BufferGetPage(buffer);offnum=ItemPointerGetOffsetNumber(&(tuple->t_self));if(PageGetMaxOffsetNumber(page)>=offnum)lp=PageGetItemId(page,offnum);if(PageGetMaxOffsetNumber(page)<offnum||!ItemIdIsNormal(lp))elog(ERROR,"invalidlp");htup=(HeapTupleHeader)PageGetItem(page,lp);/*SpecTokenOffsetNumbershouldbedistinguishablefromanyrealoffset*/StaticAssertStmt(MaxOffsetNumber<SpecTokenOffsetNumber,"invalidspeculativetokenconstant");/*NOEREPORT(ERROR)fromheretillchangesarelogged*/START_CRIT_SECTION();Assert(HeapTupleHeaderIsSpeculative(tuple->t_data));MarkBufferDirty(buffer);/**Replacethespeculativeinsertiontokenwitharealt_ctid,pointingto*itselflikeitdoesonregulartuples.*/htup->t_ctid=tuple->t_self;/*XLOGstuff*/if(RelationNeedsWAL(relation)){xl_heap_confirmxlrec;XLogRecPtrrecptr;xlrec.offnum=ItemPointerGetOffsetNumber(&tuple->t_self);XLogBeginInsert();/*Wewantthesamefilteringonthisasonaplaininsert*/XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);XLogRegisterData((char*)&xlrec,SizeOfHeapConfirm);XLogRegisterBuffer(0,buffer,REGBUF_STANDARD);recptr=XLogInsert(RM_HEAP_ID,XLOG_HEAP_CONFIRM);PageSetLSN(page,recptr);}END_CRIT_SECTION();UnlockReleaseBuffer(buffer);}

19、heap_abort_speculative

/**heap_abort_speculative-killaspeculativelyinsertedtuple**Marksatuplethatwasspeculativelyinsertedinthesamecommandasdead,*bysettingitsxminasinvalid.Thatmakesitimmediatelyappearasdead*toalltransactions,includingourown.Inparticular,itmakes*HeapTupleSatisfiesDirty()regardthetupleasdead,sothatanotherbackend*insertingaduplicatekeyvaluewon'tunnecessarilywaitforourwhole*transactiontofinish(it'lljustwaitforourspeculativeinsertionto*finish).**Killingthetupleprevents"unprincipleddeadlocks",whicharedeadlocks*thatariseduetoamutualdependencythatisnotuservisible.By*definition,unprincipleddeadlockscannotbepreventedbytheuser*reorderinglockacquisitioninclientcode,becausetheimplementationlevel*lockacquisitionsarenotundertheuser'sdirectcontrol.Ifspeculative*insertersdidnottakethisprecaution,thenunderhighconcurrencythey*coulddeadlockwitheachother,whichwouldnotbeacceptable.**Thisissomewhatredundantwithheap_delete,butweprefertohavea*dedicatedroutinewithstrippeddownrequirements.Notethatthisisalso*usedtodeletetheTOASTtuplescreatedduringspeculativeinsertion.**Thisroutinedoesnotaffectlogicaldecodingasitonlylooksat*confirmationrecords.*/voidheap_abort_speculative(Relationrelation,HeapTupletuple){TransactionIdxid=GetCurrentTransactionId();ItemPointertid=&(tuple->t_self);ItemIdlp;HeapTupleDatatp;Pagepage;BlockNumberblock;Bufferbuffer;Assert(ItemPointerIsValid(tid));block=ItemPointerGetBlockNumber(tid);buffer=ReadBuffer(relation,block);page=BufferGetPage(buffer);LockBuffer(buffer,BUFFER_LOCK_EXCLUSIVE);/**Pagecan'tbeallvisible,wejustinsertedintoit,andarestill*running.*/Assert(!PageIsAllVisible(page));lp=PageGetItemId(page,ItemPointerGetOffsetNumber(tid));Assert(ItemIdIsNormal(lp));tp.t_tableOid=RelationGetRelid(relation);tp.t_data=(HeapTupleHeader)PageGetItem(page,lp);tp.t_len=ItemIdGetLength(lp);tp.t_self=*tid;/**Sanitycheckthatthetuplereallyisaspeculativelyinsertedtuple,*insertedbyus.*/if(tp.t_data->t_choice.t_heap.t_xmin!=xid)elog(ERROR,"attemptedtokillatupleinsertedbyanothertransaction");if(!(IsToastRelation(relation)||HeapTupleHeaderIsSpeculative(tp.t_data)))elog(ERROR,"attemptedtokillanon-speculativetuple");Assert(!HeapTupleHeaderIsHeapOnly(tp.t_data));/**Noneedtocheckforserializableconflictshere.Thereisnevera*needforacombocid,either.Noneedtoextractreplicaidentity,or*doanythingspecialwithinfomaskbits.*/START_CRIT_SECTION();/**ThetuplewillbecomeDEADimmediately.Flagthatthispage*immediatelyisacandidateforpruningbysettingxminto*RecentGlobalXmin.That'snotpretty,butitdoesn'tseemworth*inventinganicerAPIforthis.*/Assert(TransactionIdIsValid(RecentGlobalXmin));PageSetPrunable(page,RecentGlobalXmin);/*storetransactioninformationofxactdeletingthetuple*/tp.t_data->t_infomask&=~(HEAP_XMAX_BITS|HEAP_MOVED);tp.t_data->t_infomask2&=~HEAP_KEYS_UPDATED;/**SetthetupleheaderxmintoInvalidTransactionId.Thismakesthe*tupleimmediatelyinvisibleeveryone.(Inparticular,toany*transactionswaitingonthespeculativetoken,wokenuplater.)*/HeapTupleHeaderSetXmin(tp.t_data,InvalidTransactionId);/*Clearthespeculativeinsertiontokentoo*/tp.t_data->t_ctid=tp.t_self;MarkBufferDirty(buffer);/**XLOGstuff**TheWALrecordsgeneratedherematchheap_delete().Thesamerecovery*routinesareused.*/if(RelationNeedsWAL(relation)){xl_heap_deletexlrec;XLogRecPtrrecptr;xlrec.flags=XLH_DELETE_IS_SUPER;xlrec.infobits_set=compute_infobits(tp.t_data->t_infomask,tp.t_data->t_infomask2);xlrec.offnum=ItemPointerGetOffsetNumber(&tp.t_self);xlrec.xmax=xid;XLogBeginInsert();XLogRegisterData((char*)&xlrec,SizeOfHeapDelete);XLogRegisterBuffer(0,buffer,REGBUF_STANDARD);/*Noreplicaidentity&replicationoriginlogged*/recptr=XLogInsert(RM_HEAP_ID,XLOG_HEAP_DELETE);PageSetLSN(page,recptr);}END_CRIT_SECTION();LockBuffer(buffer,BUFFER_LOCK_UNLOCK);if(HeapTupleHasExternal(&tp)){Assert(!IsToastRelation(relation));toast_delete(relation,&tp,true);}/**Neverneedtomarktupleforinvalidation,sincecatalogsdon'tsupport*speculativeinsertion*//*Nowwecanreleasethebuffer*/ReleaseBuffer(buffer);/*countdeletion,aswecountedtheinsertiontoo*/pgstat_count_heap_delete(relation);}

20、SpeculativeInsertionLockRelease

/**SpeculativeInsertionLockRelease**Deletethelockshowingthatthegiventransactionisspeculatively*insertingatuple.*/voidSpeculativeInsertionLockRelease(TransactionIdxid){LOCKTAGtag;SET_LOCKTAG_SPECULATIVE_INSERTION(tag,xid,speculativeInsertionToken);LockRelease(&tag,ExclusiveLock,false);}

21、list_free

/**Freeallthecellsofthelist,aswellasthelistitself.Any*objectsthatarepointed-tobythecellsofthelistareNOT*free'd.**Onreturn,theargumenttothisfunctionhasbeenfreed,sothe*callerwouldbewisetosetittoNILforsafety'ssake.*/voidlist_free(List*list){list_free_private(list,false);}/**Freeallstorageinalist,andoptionallythepointed-toelements*/staticvoidlist_free_private(List*list,booldeep){ListCell*cell;check_list_invariants(list);cell=list_head(list);while(cell!=NULL){ListCell*tmp=cell;cell=lnext(cell);if(deep)pfree(lfirst(tmp));pfree(tmp);}if(list)pfree(list);}

22、setLastTid

voidsetLastTid(constItemPointertid){Current_last_tid=*tid;}

23、ExecARUpdateTriggers

voidExecARUpdateTriggers(EState*estate,ResultRelInfo*relinfo,ItemPointertupleid,HeapTuplefdw_trigtuple,HeapTuplenewtuple,List*recheckIndexes,TransitionCaptureState*transition_capture){TriggerDesc*trigdesc=relinfo->ri_TrigDesc;if((trigdesc&&trigdesc->trig_update_after_row)||(transition_capture&&(transition_capture->tcs_update_old_table||transition_capture->tcs_update_new_table))){HeapTupletrigtuple;/**Note:iftheUPDATEisconvertedintoaDELETE+INSERTaspartof*update-partition-keyoperation,thenthisfunctionisalsocalled*separatelyforDELETEandINSERTtocapturetransitiontablerows.*Insuchcase,eitheroldtupleornewtuplecanbeNULL.*/if(fdw_trigtuple==NULL&&ItemPointerIsValid(tupleid))trigtuple=GetTupleForTrigger(estate,NULL,relinfo,tupleid,LockTupleExclusive,NULL);elsetrigtuple=fdw_trigtuple;AfterTriggerSaveEvent(estate,relinfo,TRIGGER_EVENT_UPDATE,true,trigtuple,newtuple,recheckIndexes,GetUpdatedColumns(relinfo,estate),transition_capture);if(trigtuple!=fdw_trigtuple)heap_freetuple(trigtuple);}}

24、ExecARInsertTriggers

voidExecARInsertTriggers(EState*estate,ResultRelInfo*relinfo,HeapTupletrigtuple,List*recheckIndexes,TransitionCaptureState*transition_capture){TriggerDesc*trigdesc=relinfo->ri_TrigDesc;if((trigdesc&&trigdesc->trig_insert_after_row)||(transition_capture&&transition_capture->tcs_insert_new_table))AfterTriggerSaveEvent(estate,relinfo,TRIGGER_EVENT_INSERT,true,NULL,trigtuple,recheckIndexes,NULL,transition_capture);}

25、ExecProcessReturning

/**ExecProcessReturning---evaluateaRETURNINGlist**resultRelInfo:currentresultrel*tupleSlot:slotholdingtupleactuallyinserted/updated/deleted*planSlot:slotholdingtuplereturnedbytopsubplannode**Note:IftupleSlotisNULL,theFDWshouldhavealreadyprovidedecontext's*scantuple.**Returnsaslotholdingtheresulttuple*/staticTupleTableSlot*ExecProcessReturning(ResultRelInfo*resultRelInfo,TupleTableSlot*tupleSlot,TupleTableSlot*planSlot){ProjectionInfo*projectReturning=resultRelInfo->ri_projectReturning;ExprContext*econtext=projectReturning->pi_exprContext;/**Resetper-tuplememorycontexttofreeanyexpressionevaluation*storageallocatedinthepreviouscycle.*/ResetExprContext(econtext);/*MaketupleandanyneededjoinvariablesavailabletoExecProject*/if(tupleSlot)econtext->ecxt_scantuple=tupleSlot;else{HeapTupletuple;/**RETURNINGexpressionsmightreferencethetableoidcolumn,so*initializet_tableOidbeforeevaluatingthem.*/Assert(!TupIsNull(econtext->ecxt_scantuple));tuple=ExecMaterializeSlot(econtext->ecxt_scantuple);tuple->t_tableOid=RelationGetRelid(resultRelInfo->ri_RelationDesc);}econtext->ecxt_outertuple=planSlot;/*ComputetheRETURNINGexpressions*/returnExecProject(projectReturning);}二、源码解读

这部分源码需要二次解读(2018-8-6 Mark)

/*----------------------------------------------------------------*ExecInsert**ForINSERT,wehavetoinsertthetupleintothetargetrelation*andinsertappropriatetuplesintotheindexrelations.**ReturnsRETURNINGresultifany,otherwiseNULL.*----------------------------------------------------------------*//*输入:mtstate-存储“更新”数据表(包括INSERT,UPDATE,orDELETE)时的状态slot-执行器使用TupleTable存储Tuples,每个Tuple存储在该Table的一个TupleSlot中planSlot-TODOestate-管理Executor调用的工作状态canSetTag-TODO输出:TupleTableSlot-相应的Tuple的Slot*/staticTupleTableSlot*ExecInsert(ModifyTableState*mtstate,TupleTableSlot*slot,TupleTableSlot*planSlot,EState*estate,boolcanSetTag){HeapTupletuple;//要插入的tupleResultRelInfo*resultRelInfo;//执行更新操作时Relation相关的所有信息RelationresultRelationDesc;//目标Relation信息OidnewId;//数据表OidList*recheckIndexes=NIL;//需要检查的Index的列表TupleTableSlot*result=NULL;//结果Tuple对应的SlotTransitionCaptureState*ar_insert_trig_tcs;//TODOModifyTable*node=(ModifyTable*)mtstate->ps.plan;//更新表NodeOnConflictActiononconflict=node->onConflictAction;//冲突处理/**gettheheaptupleoutofthetupletableslot,makingsurewehavea*writablecopy*/tuple=ExecMaterializeSlot(slot);//"物化"Tuple/**getinformationonthe(current)resultrelation*///获取Relation相关信息resultRelInfo=estate->es_result_relation_info;resultRelationDesc=resultRelInfo->ri_RelationDesc;/**IftheresultrelationhasOIDs,forcethetuple'sOIDtozerosothat*heap_insertwillassignafreshOID.UsuallytheOIDalreadywillbe*zeroatthispoint,buttherearecornercaseswheretheplantreecan*returnatupleextractedliterallyfromsometablewiththesame*rowtype.**XXXifweeverwantedtoallowuserstoassigntheirownOIDstonew*rows,this'dbetheplacetodoit.Forthemoment,wemakeapointof*doingthisbeforecallingtriggers,sothatauser-suppliedtrigger*couldhacktheOIDifdesired.*///设置Oid为InvalidOid(0),在heap_insert时会更新Oidif(resultRelationDesc->rd_rel->relhasoids)HeapTupleSetOid(tuple,InvalidOid);/**BEFOREROWINSERTTriggers.**Note:WefireBEFOREROWTRIGGERSforeveryattemptedinsertioninan*INSERT...ONCONFLICTstatement.Wecannotcheckforconstraint*violationsbeforefiringthesetriggers,becausetheycanchangethe*valuestoinsert.Also,theycanrunarbitraryuser-definedcodewith*side-effectsthatwecan'tcancelbyjustnotinsertingthetuple.*///触发器-TODOif(resultRelInfo->ri_TrigDesc&&resultRelInfo->ri_TrigDesc->trig_insert_before_row){slot=ExecBRInsertTriggers(estate,resultRelInfo,slot);if(slot==NULL)/*"donothing"*/returnNULL;/*triggermighthavechangedtuple*/tuple=ExecMaterializeSlot(slot);}//触发器-TODO/*INSTEADOFROWINSERTTriggers*/if(resultRelInfo->ri_TrigDesc&&resultRelInfo->ri_TrigDesc->trig_insert_instead_row){slot=ExecIRInsertTriggers(estate,resultRelInfo,slot);if(slot==NULL)/*"donothing"*/returnNULL;/*triggermighthavechangedtuple*/tuple=ExecMaterializeSlot(slot);newId=InvalidOid;}elseif(resultRelInfo->ri_FdwRoutine)//FDW-TODO{/**insertintoforeigntable:lettheFDWdoit*/slot=resultRelInfo->ri_FdwRoutine->ExecForeignInsert(estate,resultRelInfo,slot,planSlot);if(slot==NULL)/*"donothing"*/returnNULL;/*FDWmighthavechangedtuple*/tuple=ExecMaterializeSlot(slot);/**AFTERROWTriggersorRETURNINGexpressionsmightreferencethe*tableoidcolumn,soinitializet_tableOidbeforeevaluatingthem.*/tuple->t_tableOid=RelationGetRelid(resultRelationDesc);newId=InvalidOid;}else//正常数据表{WCOKindwco_kind;//WithCheckOption类型/**Constraintsmightreferencethetableoidcolumn,soinitialize*t_tableOidbeforeevaluatingthem.*///获取RelationIDtuple->t_tableOid=RelationGetRelid(resultRelationDesc);/**CheckanyRLSWITHCHECKpolicies.**NormallyweshouldcheckINSERTpolicies.Butiftheinsertisthe*resultofapartitionkeyupdatethatmovedthetupletoanew*partition,weshouldinsteadcheckUPDATEpolicies,becauseweare*executingpoliciesdefinedonthetargettable,andnotthose*definedonthechildpartitions.*///WithCheckOption类型:UpdateORInsert?wco_kind=(mtstate->operation==CMD_UPDATE)?WCO_RLS_UPDATE_CHECK:WCO_RLS_INSERT_CHECK;/**ExecWithCheckOptions()willskipanyWCOswhicharenotofthekind*wearelookingforatthispoint.*///执行检查if(resultRelInfo->ri_WithCheckOptions!=NIL)ExecWithCheckOptions(wco_kind,resultRelInfo,slot,estate);/**Checktheconstraintsofthetuple.*///检查约束if(resultRelationDesc->rd_att->constr)ExecConstraints(resultRelInfo,slot,estate);/**Alsocheckthetupleagainstthepartitionconstraint,ifthereis*one;exceptthatifwegothereviatuple-routing,wedon'tneedto*ifthere'snoBRtriggerdefinedonthepartition.*///分区表if(resultRelInfo->ri_PartitionCheck&&(resultRelInfo->ri_PartitionRoot==NULL||(resultRelInfo->ri_TrigDesc&&resultRelInfo->ri_TrigDesc->trig_insert_before_row)))ExecPartitionCheck(resultRelInfo,slot,estate,true);//索引检查if(onconflict!=ONCONFLICT_NONE&&resultRelInfo->ri_NumIndices>0){/*Performaspeculativeinsertion.*/uint32specToken;//TokenItemPointerDataconflictTid;//数据行指针boolspecConflict;//冲突声明List*arbiterIndexes;//相关索引arbiterIndexes=resultRelInfo->ri_onConflictArbiterIndexes;/**Doanon-conclusivecheckforconflictsfirst.**We'renotholdinganylocksyet,sothisdoesn'tguaranteethat*thelaterinsertwon'tconflict.Butitavoidsleavingbehind*alotofcanceledspeculativeinsertions,ifyourunalotof*INSERTONCONFLICTstatementsthatdoconflict.**Weloopbackhereifwefindaconflictbelow,eitherduring*thepre-check,orwhenwere-checkafterinsertingthetuple*speculatively.*/vlock:specConflict=false;if(!ExecCheckIndexConstraints(slot,estate,&conflictTid,arbiterIndexes)){/*committedconflicttuplefound*/if(onconflict==ONCONFLICT_UPDATE){/**IncaseofONCONFLICTDOUPDATE,executetheUPDATE*part.BepreparedtoretryiftheUPDATEfailsbecause*ofanotherconcurrentUPDATE/DELETEtotheconflict*tuple.*/TupleTableSlot*returning=NULL;if(ExecOnConflictUpdate(mtstate,resultRelInfo,&conflictTid,planSlot,slot,estate,canSetTag,&returning)){InstrCountTuples2(&mtstate->ps,1);returnreturning;}elsegotovlock;}else{/**IncaseofONCONFLICTDONOTHING,donothing.However,*verifythatthetupleisvisibletotheexecutor'sMVCC*snapshotathigherisolationlevels.*/Assert(onconflict==ONCONFLICT_NOTHING);ExecCheckTIDVisible(estate,resultRelInfo,&conflictTid);InstrCountTuples2(&mtstate->ps,1);returnNULL;}}/**Beforewestartinsertionproper,acquireour"speculative*insertionlock".Otherscanusethattowaitforustodecide*ifwe'regoingtogoaheadwiththeinsertion,insteadof*waitingforthewholetransactiontocomplete.*/specToken=SpeculativeInsertionLockAcquire(GetCurrentTransactionId());HeapTupleHeaderSetSpeculativeToken(tuple->t_data,specToken);/*insertthetuple,withthespeculativetoken*/newId=heap_insert(resultRelationDesc,tuple,estate->es_output_cid,HEAP_INSERT_SPECULATIVE,NULL);/*insertindexentriesfortuple*/recheckIndexes=ExecInsertIndexTuples(slot,&(tuple->t_self),estate,true,&specConflict,arbiterIndexes);/*adjustthetuple'sstateaccordingly*/if(!specConflict)heap_finish_speculative(resultRelationDesc,tuple);elseheap_abort_speculative(resultRelationDesc,tuple);/**Wakeupanyonewaitingforourdecision.Theywillre-check*thetuple,seethatit'snolongerspeculative,andwaitonour*XIDasifthiswasaregularlyinsertedtupleallalong.Orif*wekilledthetuple,theywillseeit'sdead,andproceedasif*thetupleneverexisted.*/SpeculativeInsertionLockRelease(GetCurrentTransactionId());/**Iftherewasaconflict,startfromthebeginning.We'lldo*thepre-checkagain,whichwillnowfindtheconflictingtuple*(unlessitabortsbeforewegetthere).*/if(specConflict){list_free(recheckIndexes);gotovlock;}/*Sincetherewasnoinsertionconflict,we'redone*/}else//无需Index检查{/**insertthetuplenormally.**Note:heap_insertreturnsthetid(location)ofthenewtuple*inthet_selffield.*/newId=heap_insert(resultRelationDesc,tuple,estate->es_output_cid,0,NULL);//插入数据/*insertindexentriesfortuple*/if(resultRelInfo->ri_NumIndices>0)recheckIndexes=ExecInsertIndexTuples(slot,&(tuple->t_self),estate,false,NULL,NIL);//索引}}if(canSetTag){(estate->es_processed)++;estate->es_lastoid=newId;setLastTid(&(tuple->t_self));}/**Ifthisinsertistheresultofapartitionkeyupdatethatmovedthe*tupletoanewpartition,putthisrowintothetransitionNEWTABLE,*ifthereisone.WeneedtodothisseparatelyforDELETEandINSERT*becausetheyhappenondifferenttables.*///触发器-TODOar_insert_trig_tcs=mtstate->mt_transition_capture;if(mtstate->operation==CMD_UPDATE&&mtstate->mt_transition_capture&&mtstate->mt_transition_capture->tcs_update_new_table){ExecARUpdateTriggers(estate,resultRelInfo,NULL,NULL,tuple,NULL,mtstate->mt_transition_capture);/**We'vealreadycapturedtheNEWTABLErow,somakesureanyAR*INSERTtriggerfiredbelowdoesn'tcaptureitagain.*/ar_insert_trig_tcs=NULL;}/*AFTERROWINSERTTriggers*/ExecARInsertTriggers(estate,resultRelInfo,tuple,recheckIndexes,ar_insert_trig_tcs);list_free(recheckIndexes);/**CheckanyWITHCHECKOPTIONconstraintsfromparentviews.Weare*requiredtodothisaftertestingallconstraintsanduniqueness*violationspertheSQLspec,sowedoitafteractuallyinsertingthe*recordintotheheapandallindexes.**ExecWithCheckOptionswillelog(ERROR)ifaviolationisfound,sothe*tuplewillneverbeseen,ifitviolatestheWITHCHECKOPTION.**ExecWithCheckOptions()willskipanyWCOswhicharenotofthekindwe*arelookingforatthispoint.*/if(resultRelInfo->ri_WithCheckOptions!=NIL)ExecWithCheckOptions(WCO_VIEW_CHECK,resultRelInfo,slot,estate);/*ProcessRETURNINGifpresent*/if(resultRelInfo->ri_projectReturning)result=ExecProcessReturning(resultRelInfo,slot,planSlot);returnresult;}三、跟踪分析

添加主键,插入测试数据:

testdb=#--获取pidtestdb=#selectpg_backend_pid();pg_backend_pid----------------1527(1row)testdb=#testdb=#--添加主键testdb=#altertablet_insertaddconstraintpk_t_insertprimarykey(id);ALTERTABLEtestdb=#insertintot_insertvalues(12,'12','12','12');(挂起)

启动gdb

[root@localhost~]#gdb-p1527GNUgdb(GDB)RedHatEnterpriseLinux7.6.1-100.el7Copyright(C)2013FreeSoftwareFoundation,Inc....(gdb)bExecInsertBreakpoint1at0x6c0227:filenodeModifyTable.c,line273.#查看输入参数(gdb)p*mtstate$1={ps={type=T_ModifyTableState,plan=0x1257fa0,state=0x130bf80,ExecProcNode=0x6c2485<ExecModifyTable>,ExecProcNodeReal=0x6c2485<ExecModifyTable>,instrument=0x0,worker_instrument=0x0,qual=0x0,lefttree=0x0,righttree=0x0,initPlan=0x0,subPlan=0x0,chgParam=0x0,ps_ResultTupleSlot=0x130d1e0,ps_ExprContext=0x0,ps_ProjInfo=0x0,scandesc=0x0},operation=CMD_INSERT,canSetTag=true,mt_done=false,mt_plans=0x130c4e0,mt_nplans=1,mt_whichplan=0,resultRelInfo=0x130c1c0,rootResultRelInfo=0x0,mt_arowmarks=0x130c4f8,mt_epqstate={estate=0x0,planstate=0x0,origslot=0x130c950,plan=0x132de88,arowMarks=0x0,epqParam=0},fireBSTriggers=false,mt_existing=0x0,mt_excludedtlist=0x0,mt_conflproj=0x0,mt_partition_tuple_routing=0x0,mt_transition_capture=0x0,mt_oc_transition_capture=0x0,mt_per_subplan_tupconv_maps=0x0}(gdb)p*(mtstate->ps->plan)$2={type=T_ModifyTable,startup_cost=0,total_cost=0.01,plan_rows=1,plan_width=136,parallel_aware=false,parallel_safe=false,plan_node_id=0,targetlist=0x0,qual=0x0,lefttree=0x0,righttree=0x0,initPlan=0x0,extParam=0x0,allParam=0x0}(gdb)p*(mtstate->ps->state)$3={type=T_EState,es_direction=ForwardScanDirection,es_snapshot=0x1309fa0,es_crosscheck_snapshot=0x0,es_range_table=0x132e1f8,es_plannedstmt=0x1258420,es_sourceText=0x1256ef0"insertintot_insertvalues(12,'12','12','12');",es_junkFilter=0x0,es_output_cid=0,es_result_relations=0x130c1c0,es_num_result_relations=1,es_result_relation_info=0x130c1c0,es_root_result_relations=0x0,es_num_root_result_relations=0,es_tuple_routing_result_relations=0x0,es_trig_target_relations=0x0,es_trig_tuple_slot=0x130d290,es_trig_oldtup_slot=0x0,es_trig_newtup_slot=0x0,es_param_list_info=0x0,es_param_exec_vals=0x130c190,es_queryEnv=0x0,es_query_cxt=0x130be70,es_tupleTable=0x130c810,es_rowMarks=0x0,es_processed=0,es_lastoid=0,es_top_eflags=0,es_instrument=0,es_finished=false,es_exprcontexts=0x130c7b0,es_subplanstates=0x0,es_auxmodifytables=0x0,es_per_tuple_exprcontext=0x0,es_epqTuple=0x0,es_epqTupleSet=0x0,es_epqScanDone=0x0,es_use_parallel_mode=false,es_query_dsa=0x0,es_jit_flags=0,es_jit=0x0}(gdb)p*(mtstate->ps->ps_ResultTupleSlot)$4={type=T_TupleTableSlot,tts_isempty=true,tts_shouldFree=false,tts_shouldFreeMin=false,tts_slow=false,tts_tuple=0x0,tts_tupleDescriptor=0x130d1b0,tts_mcxt=0x130be70,tts_buffer=0,tts_nvalid=0,tts_values=0x130d240,tts_isnull=0x130d240,tts_mintuple=0x0,tts_minhdr={t_len=0,t_self={ip_blkid={bi_hi=0,bi_lo=0},ip_posid=0},t_tableOid=0,t_data=0x0},tts_off=0,tts_fixedTupleDescriptor=true}(gdb)p*(mtstate->ps->ps_ResultTupleSlot->tts_tupleDescriptor)$5={natts=0,tdtypeid=2249,tdtypmod=-1,tdhasoid=false,tdrefcount=-1,constr=0x0,attrs=0x130d1d0}(gdb)p*(mtstate->ps->ps_ResultTupleSlot->tts_tupleDescriptor->attrs)$6={attrelid=128,attname={data="\000\000\000\000p\276\060\001\000\000\000\000\b\000\000\000\001",'\000'<repeats11times>,"\260\321\060\001\000\000\000\000p\276\060\001",'\000'<repeats12times>,"@\322\060\001\000\000\000\000@\322\060\001"},atttypid=0,attstattarget=0,attlen=0,attnum=0,attndims=0,attcacheoff=0,atttypmod=0,attbyval=false,attstorage=0'\000',attalign=0'\000',attnotnull=false,atthasdef=false,atthasmissing=false,attidentity=0'\000',attisdropped=false,attislocal=false,attinhcount=0,attcollation=1}$7=(PlanState*)0x130c560(gdb)p**(mtstate->mt_plans)$8={type=T_ResultState,plan=0x132de88,state=0x130bf80,ExecProcNode=0x6c5094<ExecResult>,ExecProcNodeReal=0x6c5094<ExecResult>,instrument=0x0,worker_instrument=0x0,qual=0x0,lefttree=0x0,righttree=0x0,initPlan=0x0,subPlan=0x0,chgParam=0x0,ps_ResultTupleSlot=0x130c950,ps_ExprContext=0x130c670,ps_ProjInfo=0x130c700,scandesc=0x0}(gdb)p**(mtstate->resultRelInfo)Structurehasnocomponentnamedoperator*.(gdb)p*(mtstate->resultRelInfo)$9={type=T_ResultRelInfo,ri_RangeTableIndex=1,ri_RelationDesc=0x7f2af957d9e8,ri_NumIndices=1,ri_IndexRelationDescs=0x130c7e0,ri_IndexRelationInfo=0x130c7f8,ri_TrigDesc=0x0,ri_TrigFunctions=0x0,ri_TrigWhenExprs=0x0,ri_TrigInstrument=0x0,ri_FdwRoutine=0x0,ri_FdwState=0x0,ri_usesFdwDirectModify=false,ri_WithCheckOptions=0x0,ri_WithCheckOptionExprs=0x0,ri_ConstraintExprs=0x0,ri_junkFilter=0x0,ri_returningList=0x0,ri_projectReturning=0x0,ri_onConflictArbiterIndexes=0x0,ri_onConflict=0x0,ri_PartitionCheck=0x0,ri_PartitionCheckExpr=0x0,ri_PartitionRoot=0x0,ri_PartitionReadyForRouting=false}(gdb)p*(mtstate->resultRelInfo->ri_RelationDesc)$10={rd_node={spcNode=1663,dbNode=16477,relNode=26731},rd_smgr=0x0,rd_refcnt=1,rd_backend=-1,rd_islocaltemp=false,rd_isnailed=false,rd_isvalid=true,rd_indexvalid=1'\001',rd_statvalid=false,rd_createSubid=0,rd_newRelfilenodeSubid=0,rd_rel=0x7f2af94c31a8,rd_att=0x7f2af957f6e8,rd_id=26731,rd_lockInfo={lockRelId={relId=26731,dbId=16477}},rd_rules=0x0,rd_rulescxt=0x0,trigdesc=0x0,rd_rsdesc=0x0,rd_fkeylist=0x0,rd_fkeyvalid=false,rd_partkeycxt=0x0,rd_partkey=0x0,rd_pdcxt=0x0,rd_partdesc=0x0,rd_partcheck=0x0,rd_indexlist=0x7f2af94c2818,rd_oidindex=0,rd_pkindex=26737,rd_replidindex=26737,rd_statlist=0x0,rd_indexattr=0x0,rd_projindexattr=0x0,rd_keyattr=0x0,rd_pkattr=0x0,rd_idattr=0x0,rd_projidx=0x0,rd_pubactions=0x0,rd_options=0x0,rd_index=0x0,rd_indextuple=0x0,rd_amhandler=0,rd_indexcxt=0x0,rd_amroutine=0x0,rd_opfamily=0x0,rd_opcintype=0x0,rd_support=0x0,rd_supportinfo=0x0,rd_indoption=0x0,rd_indexprs=0x0,rd_indpred=0x0,rd_exclops=0x0,rd_exclprocs=0x0,rd_exclstrats=0x0,rd_amcache=0x0,rd_indcollation=0x0,rd_fdwroutine=0x0,rd_toastoid=0,pgstat_info=0x12d5850}(gdb)#第2个参数slot(gdb)p*slot$11={type=T_TupleTableSlot,tts_isempty=false,tts_shouldFree=false,tts_shouldFreeMin=false,tts_slow=false,tts_tuple=0x0,tts_tupleDescriptor=0x130cb70,tts_mcxt=0x130be70,tts_buffer=0,tts_nvalid=4,tts_values=0x130c9b0,tts_isnull=0x130c9d0,tts_mintuple=0x0,tts_minhdr={t_len=0,t_self={ip_blkid={bi_hi=0,bi_lo=0},ip_posid=0},t_tableOid=0,t_data=0x0},tts_off=0,tts_fixedTupleDescriptor=true}(gdb)p*(slot->tts_tupleDescriptor)$12={natts=4,tdtypeid=2249,tdtypmod=-1,tdhasoid=false,tdrefcount=-1,constr=0x0,attrs=0x130cb90}(gdb)p*(slot->tts_values)$13=12(gdb)p*(slot->tts_isnull)$14=false#参数planSlot(gdb)p*planSlot$15={type=T_TupleTableSlot,tts_isempty=false,tts_shouldFree=false,tts_shouldFreeMin=false,tts_slow=false,tts_tuple=0x0,tts_tupleDescriptor=0x130cb70,tts_mcxt=0x130be70,tts_buffer=0,tts_nvalid=4,tts_values=0x130c9b0,tts_isnull=0x130c9d0,tts_mintuple=0x0,tts_minhdr={t_len=0,t_self={ip_blkid={bi_hi=0,bi_lo=0},ip_posid=0},t_tableOid=0,t_data=0x0},tts_off=0,tts_fixedTupleDescriptor=true}(gdb)p*(planSlot->tts_mcxt)$16={type=T_AllocSetContext,isReset=false,allowInCritSection=false,methods=0xb8c720<AllocSetMethods>,parent=0x131f150,firstchild=0x130fe90,prevchild=0x0,nextchild=0x0,name=0xb1a840"ExecutorState",ident=0x0,reset_cbs=0x0}#参数estate(gdb)p*estate$17={type=T_EState,es_direction=ForwardScanDirection,es_snapshot=0x1309fa0,es_crosscheck_snapshot=0x0,es_range_table=0x132e1f8,es_plannedstmt=0x1258420,es_sourceText=0x1256ef0"insertintot_insertvalues(12,'12','12','12');",es_junkFilter=0x0,es_output_cid=0,es_result_relations=0x130c1c0,es_num_result_relations=1,es_result_relation_info=0x130c1c0,es_root_result_relations=0x0,es_num_root_result_relations=0,es_tuple_routing_result_relations=0x0,es_trig_target_relations=0x0,es_trig_tuple_slot=0x130d290,es_trig_oldtup_slot=0x0,es_trig_newtup_slot=0x0,es_param_list_info=0x0,es_param_exec_vals=0x130c190,es_queryEnv=0x0,es_query_cxt=0x130be70,es_tupleTable=0x130c810,es_rowMarks=0x0,es_processed=0,es_lastoid=0,es_top_eflags=0,es_instrument=0,es_finished=false,es_exprcontexts=0x130c7b0,es_subplanstates=0x0,es_auxmodifytables=0x0,es_per_tuple_exprcontext=0x0,es_epqTuple=0x0,es_epqTupleSet=0x0,es_epqScanDone=0x0,es_use_parallel_mode=false,es_query_dsa=0x0,es_jit_flags=0,es_jit=0x0}(gdb)p*(estate->es_snapshot)$18={satisfies=0x9f73fc<HeapTupleSatisfiesMVCC>,xmin=1612861,xmax=1612861,xip=0x0,xcnt=0,subxip=0x0,subxcnt=0,suboverflowed=false,takenDuringRecovery=false,copied=true,curcid=0,speculativeToken=0,active_count=1,regd_count=2,ph_node={first_child=0xe7bac0<CatalogSnapshotData+64>,next_sibling=0x0,prev_or_parent=0x0},whenTaken=0,lsn=0}(gdb)#参数canSetTag(gdb)pcanSetTag$19=true#进入函数内部(gdb)next274TupleTableSlot*result=NULL;(gdb)276ModifyTable*node=(ModifyTable*)mtstate->ps.plan;(gdb)p*node$20={plan={type=1005513616,startup_cost=3.502247076882698e-317,total_cost=9.8678822363083824e-317,plan_rows=4.1888128009757547e-314,plan_width=3,parallel_aware=253,parallel_safe=127,plan_node_id=10076823,targetlist=0x686b0000405d,qual=0x130c2d0,lefttree=0x0,righttree=0x130c1c0,initPlan=0x6c2485<ExecModifyTable>,extParam=0x0,allParam=0x7ffd3beeeb50},operation=6923989,canSetTag=false,nominalRelation=4183284200,partitioned_rels=0x130c1c0,partColsUpdated=128,resultRelations=0x1257fa0,resultRelIndex=19974480,rootResultRelIndex=0,plans=0x0,withCheckOptionLists=0x33beeeb50,returningLists=0x130bf80,fdwPrivLists=0x0,fdwDirectModifyPlans=0x130c2d0,rowMarks=0x0,epqParam=0,onConflictAction=ONCONFLICT_NONE,arbiterIndexes=0x130c950,onConflictSet=0x0,onConflictWhere=0x130c560,exclRelRTI=19972544,exclRelTlist=0x0}(gdb)(gdb)ponconflict$21=ONCONFLICT_NONE...(gdb)next289resultRelationDesc=resultRelInfo->ri_RelationDesc;(gdb)p*resultRelInfo$26={type=T_ResultRelInfo,ri_RangeTableIndex=1,ri_RelationDesc=0x7f2af957d9e8,ri_NumIndices=1,ri_IndexRelationDescs=0x130c7e0,ri_IndexRelationInfo=0x130c7f8,ri_TrigDesc=0x0,ri_TrigFunctions=0x0,ri_TrigWhenExprs=0x0,ri_TrigInstrument=0x0,ri_FdwRoutine=0x0,ri_FdwState=0x0,ri_usesFdwDirectModify=false,ri_WithCheckOptions=0x0,ri_WithCheckOptionExprs=0x0,ri_ConstraintExprs=0x0,ri_junkFilter=0x0,ri_returningList=0x0,ri_projectReturning=0x0,ri_onConflictArbiterIndexes=0x0,ri_onConflict=0x0,ri_PartitionCheck=0x0,ri_PartitionCheckExpr=0x0,ri_PartitionRoot=0x0,ri_PartitionReadyForRouting=false}(gdb)p*(tuple->t_data)$27={t_choice={t_heap={t_xmin=244,t_xmax=4294967295,t_field3={t_cid=2249,t_xvac=2249}},t_datum={datum_len_=244,datum_typmod=-1,datum_typeid=2249}},t_ctid={ip_blkid={bi_hi=65535,bi_lo=65535},ip_posid=0},t_infomask2=4,t_infomask=2,t_hoff=24'\030',t_bits=0x130d36f""}(gdb)p*(tuple)$28={t_len=61,t_self={ip_blkid={bi_hi=65535,bi_lo=65535},ip_posid=0},t_tableOid=0,t_data=0x130d358}(gdb)(gdb)p*resultRelationDesc$29={rd_node={spcNode=1663,dbNode=16477,relNode=26731},rd_smgr=0x0,rd_refcnt=1,rd_backend=-1,rd_islocaltemp=false,rd_isnailed=false,rd_isvalid=true,rd_indexvalid=1'\001',rd_statvalid=false,rd_createSubid=0,rd_newRelfilenodeSubid=0,rd_rel=0x7f2af94c31a8,rd_att=0x7f2af957f6e8,rd_id=26731,rd_lockInfo={lockRelId={relId=26731,dbId=16477}},rd_rules=0x0,rd_rulescxt=0x0,trigdesc=0x0,rd_rsdesc=0x0,rd_fkeylist=0x0,rd_fkeyvalid=false,rd_partkeycxt=0x0,rd_partkey=0x0,rd_pdcxt=0x0,rd_partdesc=0x0,rd_partcheck=0x0,rd_indexlist=0x7f2af94c2818,rd_oidindex=0,rd_pkindex=26737,rd_replidindex=26737,rd_statlist=0x0,rd_indexattr=0x0,rd_projindexattr=0x0,rd_keyattr=0x0,rd_pkattr=0x0,rd_idattr=0x0,rd_projidx=0x0,rd_pubactions=0x0,rd_options=0x0,rd_index=0x0,rd_indextuple=0x0,rd_amhandler=0,rd_indexcxt=0x0,rd_amroutine=0x0,rd_opfamily=0x0,rd_opcintype=0x0,rd_support=0x0,rd_supportinfo=0x0,rd_indoption=0x0,rd_indexprs=0x0,rd_indpred=0x0,rd_exclops=0x0,rd_exclprocs=0x0,rd_exclstrats=0x0,rd_amcache=0x0,rd_indcollation=0x0,rd_fdwroutine=0x0,rd_toastoid=0,pgstat_info=0x12d5850}#以上,获取了Relation相关的信息#没有触发器,无需执行触发器相关逻辑#进入正常数据表的处理逻辑line373行(gdb)next315if(resultRelInfo->ri_TrigDesc&&(gdb)next328if(resultRelInfo->ri_TrigDesc&&(gdb)341elseif(resultRelInfo->ri_FdwRoutine)(gdb)373tuple->t_tableOid=RelationGetRelid(resultRelationDesc);(gdb)next384wco_kind=(mtstate->operation==CMD_UPDATE)?(gdb)next391if(resultRelInfo->ri_WithCheckOptions!=NIL)(gdb)ptuple->t_tableOid$31=26731(gdb)pwco_kind$32=WCO_RLS_INSERT_CHECK#检查约束(gdb)next397if(resultRelationDesc->rd_att->constr)(gdb)398ExecConstraints(resultRelInfo,slot,estate);(gdb)#非分区表,无需检查#进入正常数据插入逻辑411if(onconflict!=ONCONFLICT_NONE&&resultRelInfo->ri_NumIndices>0)(gdb)529newId=heap_insert(resultRelationDesc,tuple,(gdb)presultRelInfo->ri_NumIndices$33=1(gdb)ponconflict$34=ONCONFLICT_NONE(gdb)(gdb)next534if(resultRelInfo->ri_NumIndices>0)(gdb)pnewId$35=0(gdb)next535recheckIndexes=ExecInsertIndexTuples(slot,&(tuple->t_self),(gdb)541if(canSetTag)(gdb)543(estate->es_processed)++;(gdb)544estate->es_lastoid=newId;(gdb)545setLastTid(&(tuple->t_self));(gdb)554ar_insert_trig_tcs=mtstate->mt_transition_capture;(gdb)555if(mtstate->operation==CMD_UPDATE&&mtstate->mt_transition_capture(gdb)572ExecARInsertTriggers(estate,resultRelInfo,tuple,recheckIndexes,(gdb)575list_free(recheckIndexes);(gdb)589if(resultRelInfo->ri_WithCheckOptions!=NIL)(gdb)593if(resultRelInfo->ri_projectReturning)(gdb)596returnresult;(gdb)597}#DONE!

到此,关于“PostgreSQL中ExecInsert函数的实现逻辑是什么”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!