返回顶部
首页 > 资讯 > 数据库 >PostgreSQL 源码解读(10)- 插入数据#9(ProcessQuery)
  • 639
分享到

PostgreSQL 源码解读(10)- 插入数据#9(ProcessQuery)

2024-04-02 19:04:59 639人浏览 泡泡鱼
摘要

本文简单介绍了PG插入数据部分的源码,主要内容包括ProcessQuery函数的实现逻辑,该函数位于文件pquery.c中。 一、基础信息 ProcessQuery函数使用的数据结

本文简单介绍了PG插入数据部分的源码,主要内容包括ProcessQuery函数的实现逻辑,该函数位于文件pquery.c中。

一、基础信息

ProcessQuery函数使用的数据结构、宏定义以及依赖的函数等。
数据结构/宏定义
1、nodeTag

//节点标记,枚举类型
 
 typedef enum NodeTag
 {
     T_Invalid = 0,
 
     
     T_IndexInfo,
     T_ExprContext,
     T_ProjectionInfo,
     T_JunkFilter,
     T_OnConflictSetState,
     T_ResultRelInfo,
     T_EState,
     T_TupleTableSlot,
 
     
     T_Plan,
     T_Result,
     T_ProjectSet,
     T_ModifyTable,
     T_Append,
     T_MergeAppend,
     T_RecursiveUNIOn,
     T_BitmapAnd,
     T_BitmapOr,
     T_Scan,
     T_SeqScan,
     T_SampleScan,
     T_IndexScan,
     T_IndexOnlyScan,
     T_BitmapindexScan,
     T_BitmapHeapScan,
     T_TidScan,
     T_SubqueryScan,
     T_FunctionScan,
     T_ValuesScan,
     T_TableFuncScan,
     T_CteScan,
     T_NamedTuplestoreScan,
     T_WorkTableScan,
     T_ForeignScan,
     T_CustomScan,
     T_Join,
     T_NestLoop,
     T_MergeJoin,
     T_HashJoin,
     T_Material,
     T_Sort,
     T_Group,
     T_Agg,
     T_WindowAgg,
     T_Unique,
     T_Gather,
     T_GatherMerge,
     T_Hash,
     T_SetOp,
     T_LockRows,
     T_Limit,
     
     T_NestLoopParam,
     T_PlanRowMark,
     T_PartitionPruneInfo,
     T_PartitionedRelPruneInfo,
     T_PartitionPruneStepOp,
     T_PartitionPruneStepCombine,
     T_PlanInvalItem,
 
     
     T_PlanState,
     T_ResultState,
     T_ProjectSetState,
     T_ModifyTableState,
     T_AppendState,
     T_MergeAppendState,
     T_RecursiveUnionState,
     T_BitmapAndState,
     T_BitmapOrState,
     T_ScanState,
     T_SeqScanState,
     T_SampleScanState,
     T_IndexScanState,
     T_IndexOnlyScanState,
     T_BitmapIndexScanState,
     T_BitmapHeapScanState,
     T_TidScanState,
     T_SubqueryScanState,
     T_FunctionScanState,
     T_TableFuncScanState,
     T_ValuesScanState,
     T_CteScanState,
     T_NamedTuplestoreScanState,
     T_WorkTableScanState,
     T_ForeignScanState,
     T_CustomScanState,
     T_JoinState,
     T_NestLoopState,
     T_MergeJoinState,
     T_HashJoinState,
     T_MaterialState,
     T_SortState,
     T_GroupState,
     T_AggState,
     T_WindowAggState,
     T_UniqueState,
     T_GatherState,
     T_GatherMergeState,
     T_HashState,
     T_SetOpState,
     T_LockRowsState,
     T_LimitState,
 
     
     T_Alias,
     T_RangeVar,
     T_TableFunc,
     T_Expr,
     T_Var,
     T_Const,
     T_Param,
     T_Aggref,
     T_GroupingFunc,
     T_WindowFunc,
     T_ArrayRef,
     T_FuncExpr,
     T_NamedArgExpr,
     T_OpExpr,
     T_DistinctExpr,
     T_NullIfExpr,
     T_ScalarArrayOpExpr,
     T_BoolExpr,
     T_SubLink,
     T_SubPlan,
     T_AlternativeSubPlan,
     T_FieldSelect,
     T_FieldStore,
     T_RelabelType,
     T_CoerceViaiO,
     T_ArrayCoerceExpr,
     T_ConvertRowtypeExpr,
     T_CollateExpr,
     T_CaseExpr,
     T_CaseWhen,
     T_CaseTestExpr,
     T_ArrayExpr,
     T_RowExpr,
     T_RowCompareExpr,
     T_CoalesceExpr,
     T_MinMaxExpr,
     T_sqlValueFunction,
     T_XmlExpr,
     T_NullTest,
     T_BooleanTest,
     T_CoerceToDomain,
     T_CoerceToDomainValue,
     T_SetToDefault,
     T_CurrentOfExpr,
     T_NextValueExpr,
     T_InferenceElem,
     T_TargetEntry,
     T_RangeTblRef,
     T_JoinExpr,
     T_FromExpr,
     T_OnConflictExpr,
     T_IntoClause,
 
     
     T_ExprState,
     T_AggrefExprState,
     T_WindowFuncExprState,
     T_SetExprState,
     T_SubPlanState,
     T_AlternativeSubPlanState,
     T_DomainConstraintState,
 
     
     T_PlannerInfo,
     T_PlannerGlobal,
     T_RelOptInfo,
     T_IndexOptInfo,
     T_ForeignKeyOptInfo,
     T_ParamPathInfo,
     T_Path,
     T_IndexPath,
     T_BitmapHeapPath,
     T_BitmapAndPath,
     T_BitmapOrPath,
     T_TidPath,
     T_SubqueryScanPath,
     T_ForeignPath,
     T_CustomPath,
     T_NestPath,
     T_MergePath,
     T_HashPath,
     T_AppendPath,
     T_MergeAppendPath,
     T_ResultPath,
     T_MaterialPath,
     T_UniquePath,
     T_GatherPath,
     T_GatherMergePath,
     T_ProjectionPath,
     T_ProjectSetPath,
     T_SortPath,
     T_GroupPath,
     T_UpperUniquePath,
     T_AggPath,
     T_GroupingSetsPath,
     T_MinMaxAggPath,
     T_WindowAggPath,
     T_SetOpPath,
     T_RecursiveUnionPath,
     T_LockRowsPath,
     T_ModifyTablePath,
     T_LimitPath,
     
     T_EquivalenceClass,
     T_EquivalenceMember,
     T_PathKey,
     T_PathTarget,
     T_RestrictInfo,
     T_PlaceHolderVar,
     T_SpecialJoinInfo,
     T_AppendRelInfo,
     T_PlaceHolderInfo,
     T_MinMaxAggInfo,
     T_PlannerParamItem,
     T_RollupData,
     T_GroupingSetData,
     T_StatisticExtInfo,
 
     
     T_MemoryContext,
     T_AllocSetContext,
     T_SlabContext,
     T_GenerationContext,
 
     
     T_Value,
     T_Integer,
     T_Float,
     T_String,
     T_BitString,
     T_Null,
 
     
     T_List,
     T_IntList,
     T_OidList,
 
     
     T_ExtensibleNode,
 
     
     T_RawStmt,
     T_Query,
     T_PlannedStmt,
     T_InsertStmt,
     T_DeleteStmt,
     T_UpdateStmt,
     T_SelectStmt,
     T_AlterTableStmt,
     T_AlterTableCmd,
     T_AlterDomainStmt,
     T_SetOperationStmt,
     T_GrantStmt,
     T_GrantRoleStmt,
     T_AlterDefaultPrivilegesStmt,
     T_ClosePortalStmt,
     T_ClusterStmt,
     T_CopyStmt,
     T_CreateStmt,
     T_DefineStmt,
     T_DropStmt,
     T_TruncateStmt,
     T_CommentStmt,
     T_FetchStmt,
     T_IndexStmt,
     T_CreateFunctionStmt,
     T_AlterFunctionStmt,
     T_DoStmt,
     T_RenameStmt,
     T_RuleStmt,
     T_NotifyStmt,
     T_ListenStmt,
     T_UnlistenStmt,
     T_TransactionStmt,
     T_ViewStmt,
     T_LoadStmt,
     T_CreateDomainStmt,
     T_CreatedbStmt,
     T_DropdbStmt,
     T_VacuumStmt,
     T_ExplainStmt,
     T_CreateTableAsStmt,
     T_CreateSeqStmt,
     T_AlterSeqStmt,
     T_VariableSetStmt,
     T_VariableShowStmt,
     T_DiscardStmt,
     T_CreateTrigStmt,
     T_CreatePLangStmt,
     T_CreateRoleStmt,
     T_AlterRoleStmt,
     T_DropRoleStmt,
     T_LockStmt,
     T_ConstraintsSetStmt,
     T_ReindexStmt,
     T_CheckPointStmt,
     T_CreateSchemaStmt,
     T_AlterDatabaseStmt,
     T_AlterDatabaseSetStmt,
     T_AlterRoleSetStmt,
     T_CreateConversionStmt,
     T_CreateCastStmt,
     T_CreateOpClassStmt,
     T_CreateOpFamilyStmt,
     T_AlterOpFamilyStmt,
     T_PrepareStmt,
     T_ExecuteStmt,
     T_DeallocateStmt,
     T_DeclareCursorStmt,
     T_CreateTableSpaceStmt,
     T_DropTableSpaceStmt,
     T_AlterObjectDependsStmt,
     T_AlterObjectSchemaStmt,
     T_AlterOwnerStmt,
     T_AlterOperatorStmt,
     T_DropOwnedStmt,
     T_ReassignOwnedStmt,
     T_CompositeTypeStmt,
     T_CreateEnumStmt,
     T_CreateRangeStmt,
     T_AlterEnumStmt,
     T_AlterTSDictionaryStmt,
     T_AlterTSConfigurationStmt,
     T_CreateFdwStmt,
     T_AlterFdwStmt,
     T_CreateForeignServerStmt,
     T_AlterForeignServerStmt,
     T_CreateUserMappingStmt,
     T_AlterUserMappingStmt,
     T_DropUserMappingStmt,
     T_AlterTableSpaceOptionsStmt,
     T_AlterTableMoveAllStmt,
     T_SecLabelStmt,
     T_CreateForeignTableStmt,
     T_ImportForeignSchemaStmt,
     T_CreateExtensionStmt,
     T_AlterExtensionStmt,
     T_AlterExtensionContentsStmt,
     T_CreateEventTrigStmt,
     T_AlterEventTrigStmt,
     T_RefreshMatViewStmt,
     T_ReplicaIdentityStmt,
     T_AlterSystemStmt,
     T_CreatePolicyStmt,
     T_AlterPolicyStmt,
     T_CreateTransfORMStmt,
     T_CreateAmStmt,
     T_CreatePublicationStmt,
     T_AlterPublicationStmt,
     T_CreateSubscriptionStmt,
     T_AlterSubscriptionStmt,
     T_DropSubscriptionStmt,
     T_CreateStatsStmt,
     T_AlterCollationStmt,
     T_CallStmt,
 
     
     T_A_Expr,
     T_ColumnRef,
     T_ParamRef,
     T_A_Const,
     T_FuncCall,
     T_A_Star,
     T_A_Indices,
     T_A_Indirection,
     T_A_ArrayExpr,
     T_ResTarget,
     T_MultiAssignRef,
     T_TypeCast,
     T_CollateClause,
     T_SortBy,
     T_WindowDef,
     T_RangeSubselect,
     T_RangeFunction,
     T_RangeTableSample,
     T_RangeTableFunc,
     T_RangeTableFuncCol,
     T_TypeName,
     T_ColumnDef,
     T_IndexElem,
     T_Constraint,
     T_DefElem,
     T_RangeTblEntry,
     T_RangeTblFunction,
     T_TableSampleClause,
     T_WithCheckOption,
     T_SortGroupClause,
     T_GroupingSet,
     T_WindowClause,
     T_ObjectWithArgs,
     T_AccessPriv,
     T_CreateOpClassItem,
     T_TableLikeClause,
     T_FunctionParameter,
     T_LockinGClause,
     T_RowMarkClause,
     T_XmlSerialize,
     T_WithClause,
     T_InferClause,
     T_OnConflictClause,
     T_CommonTableExpr,
     T_RoleSpec,
     T_TriggerTransition,
     T_PartitionElem,
     T_PartitionSpec,
     T_PartitionBoundSpec,
     T_PartitionRangeDatum,
     T_PartitionCmd,
     T_VacuumRelation,
 
     
     T_IdentifySystemCmd,
     T_BaseBackupCmd,
     T_CreateReplicationSlotCmd,
     T_DropReplicationSlotCmd,
     T_StartReplicationCmd,
     T_TimeLineHistoryCmd,
     T_SQLCmd,
 
     
     T_TriggerData,              
     T_EventTriggerData,         
     T_ReturnSetInfo,            
     T_WindowObjectData,         
     T_TIDBitmap,                
     T_InlineCodeBlock,          
     T_FdwRoutine,               
     T_IndexAmRoutine,           
     T_TsmRoutine,               
     T_ForeignKeyCacheInfo,      
     T_CallContext               
 } NodeTag;
 
 
 typedef struct Node
 {
     NodeTag     type;
 } Node;
 
 #define nodeTag(nodeptr)        (((const Node*)(nodeptr))->type)

2、MemoryContext

//内存上下文
//AllocSetContext结构体的MemoryContextData与其共享
//
 typedef struct MemoryContextData
 {
     NodeTag     type;           
     
     bool        isReset;        
     bool        allowInCritSection; 
     const MemoryContextMethods *methods;    
     MemoryContext parent;       
     MemoryContext firstchild;   
     MemoryContext prevchild;    
     MemoryContext nextchild;    
     const char *name;           
     const char *ident;          
     MemoryContextCallback *reset_cbs;   
 } MemoryContextData;
 
 

 
 typedef struct MemoryContextData *MemoryContext;
 

3、AllocSet


 typedef struct AllocSetContext
 {
     MemoryContextData header;   
     
     AllocBlock  blocks;         
     AllocChunk  freelist[ALLOCSET_NUM_FREELISTS];   
     
     Size        initBlockSize;  
     Size        maxBlockSize;   
     Size        nextBlockSize;  
     Size        allocChunkLimit;    
     AllocBlock  keeper;         
     
     int         freeListIndex;  
 } AllocSetContext;
 
 typedef AllocSetContext *AllocSet;
 

4、AllocBlock

 
 typedef struct AllocBlockData
 {
     AllocSet    aset;           
     AllocBlock  prev;           
     AllocBlock  next;           
     char       *freeptr;        
     char       *endptr;         
 }           AllocBlockData;
 
 typedef struct AllocBlockData *AllocBlock; 

5、AllocChunk

 
 typedef struct AllocChunkData
 {
     
     Size        size;
 #ifdef MEMORY_CONTEXT_CHECKING
     
     
     Size        requested_size;
 
 #define ALLOCCHUNK_RAWSIZE  (SIZEOF_SIZE_T * 2 + SIZEOF_VOID_P)
 #else
 #define ALLOCCHUNK_RAWSIZE  (SIZEOF_SIZE_T + SIZEOF_VOID_P)
 #endif                          
 
     
 #if (ALLOCCHUNK_RAWSIZE % MAXIMUM_ALIGNOF) != 0
     char        padding[MAXIMUM_ALIGNOF - ALLOCCHUNK_RAWSIZE % MAXIMUM_ALIGNOF];
 #endif
 
     
     void       *aset;
     
 }           AllocChunkData;
 
 typedef struct AllocChunkData *AllocChunk;

6、AllocSetFreeList

 
typedef struct AllocSetFreeList
{
    int         num_free;       
    AllocSetContext *first_free;    
} AllocSetFreeList;

7、context_freelists


static AllocSetFreeList context_freelists[2] =
{
    {
        0, NULL
    },
    {
        0, NULL
    }
};

8、AllocSetMethods

//内存管理方法
 typedef struct MemoryContextMethods
 {
     void       *(*alloc) (MemoryContext context, Size size);
     
     void        (*free_p) (MemoryContext context, void *pointer);
     void       *(*realloc) (MemoryContext context, void *pointer, Size size);
     void        (*reset) (MemoryContext context);
     void        (*delete_context) (MemoryContext context);
     Size        (*get_chunk_space) (MemoryContext context, void *pointer);
     bool        (*is_empty) (MemoryContext context);
     void        (*stats) (MemoryContext context,
                           MemoryStatsPrintFunc printfunc, void *passthru,
                           MemoryContextCounters *totals);
 #ifdef MEMORY_CONTEXT_CHECKING
     void        (*check) (MemoryContext context);
 #endif
 } MemoryContextMethods;

//预定义
 
 static const MemoryContextMethods AllocSetMethods = {
     AllocSetAlloc,
     AllocSetFree,
     AllocSetRealloc,
     AllocSetReset,
     AllocSetDelete,
     AllocSetGetChunkSpace,
     AllocSetIsEmpty,
     AllocSetStats
 #ifdef MEMORY_CONTEXT_CHECKING
     ,AllocSetCheck
 #endif
 };

9、宏定义

 #define ALLOC_BLOCKHDRSZ    MAXALIGN(sizeof(AllocBlockData))
 #define ALLOC_CHUNKHDRSZ    sizeof(struct AllocChunkData)

 
 #define ALLOCSET_DEFAULT_MINSIZE   0
 #define ALLOCSET_DEFAULT_INITSIZE  (8 * 1024)
 #define ALLOCSET_DEFAULT_MAXSIZE   (8 * 1024 * 1024)
 #define ALLOCSET_DEFAULT_SIZES \
     ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE
 #define VALGRIND_MAKE_MEM_NOACCESS(addr, size) do {} while (0)

 #define ALLOC_MINBITS 3 
 #define ALLOCSET_NUM_FREELISTS 11
 #define ALLOC_CHUNK_LIMIT (1 << (ALLOCSET_NUM_FREELISTS-1+ALLOC_MINBITS))
 #define ALLOCSET_SEPARATE_THRESHOLD 8192
#define ALLOC_CHUNK_FRACTION 4
 

依赖的函数
1、CreateQueryDesc

//根据输入的参数构造QueryDesc
 
 QueryDesc *
 CreateQueryDesc(PlannedStmt *plannedstmt,
                 const char *sourceText,
                 Snapshot snapshot,
                 Snapshot crosscheck_snapshot,
                 DestReceiver *dest,
                 ParamListInfo params,
                 QueryEnvironment *queryEnv,
                 int instrument_options)
 {
     QueryDesc  *qd = (QueryDesc *) palloc(sizeof(QueryDesc));
 
     qd->operation = plannedstmt->commandType;   
     qd->plannedstmt = plannedstmt;  
     qd->sourceText = sourceText;    
     qd->snapshot = ReGISterSnapshot(snapshot);  
     
     qd->crosscheck_snapshot = RegisterSnapshot(crosscheck_snapshot);
     qd->dest = dest;            
     qd->params = params;        
     qd->queryEnv = queryEnv;
     qd->instrument_options = instrument_options;    
 
     
     qd->tupDesc = NULL;
     qd->estate = NULL;
     qd->planstate = NULL;
     qd->totaltime = NULL;
 
     
     qd->already_executed = false;
 
     return qd;
 }
 

2、CreateExecutorState


 
 EState *
 CreateExecutorState(void)//构建EState
 {
     EState     *estate;//EState指针
     MemoryContext qcontext;
     MemoryContext oldcontext;
 
     
     qcontext = AllocSetContextCreate(CurrentMemoryContext,
                                      "ExecutorState",
                                      ALLOCSET_DEFAULT_SIZES);//创建MemoryContext
 
     
     oldcontext = MemoryContextSwitchTo(qcontext);//切换至新创建的MemoryContext
 
     estate = makeNode(EState);//创建Node
 
     
     //初始化Executor State structure
     estate->es_direction = ForwardScanDirection;
     estate->es_snapshot = InvalidSnapshot;  
     estate->es_crosscheck_snapshot = InvalidSnapshot;   
     estate->es_range_table = NIL;
     estate->es_plannedstmt = NULL;
 
     estate->es_junkFilter = NULL;
 
     estate->es_output_cid = (CommandId) 0;
 
     estate->es_result_relations = NULL;
     estate->es_num_result_relations = 0;
     estate->es_result_relation_info = NULL;
 
     estate->es_root_result_relations = NULL;
     estate->es_num_root_result_relations = 0;
 
     estate->es_tuple_routing_result_relations = NIL;
 
     estate->es_trig_target_relations = NIL;
     estate->es_trig_tuple_slot = NULL;
     estate->es_trig_oldtup_slot = NULL;
     estate->es_trig_newtup_slot = NULL;
 
     estate->es_param_list_info = NULL;
     estate->es_param_exec_vals = NULL;
 
     estate->es_queryEnv = NULL;
 
     estate->es_query_cxt = qcontext;
 
     estate->es_tupleTable = NIL;
 
     estate->es_rowMarks = NIL;
 
     estate->es_processed = 0;
     estate->es_lastoid = InvalidOid;
 
     estate->es_top_eflags = 0;
     estate->es_instrument = 0;
     estate->es_finished = false;
 
     estate->es_exprcontexts = NIL;
 
     estate->es_subplanstates = NIL;
 
     estate->es_auxmodifytables = NIL;
 
     estate->es_per_tuple_exprcontext = NULL;
 
     estate->es_epQtuple = NULL;
     estate->es_epqTupleSet = NULL;
     estate->es_epqScanDone = NULL;
     estate->es_sourceText = NULL;
 
     estate->es_use_parallel_mode = false;
 
     estate->es_jit_flags = 0;
     estate->es_jit = NULL;
 
     
     MemoryContextSwitchTo(oldcontext);
 
     return estate;
 }
 
 #define makeNode(_type_)        ((_type_ *) newNode(sizeof(_type_),T_##_type_))
 
 #ifdef __GNUC__
 
 
 #define newNode(size, tag) \
 ({  Node   *_result; \
     AssertMacro((size) >= sizeof(Node));         \
     _result = (Node *) palloc0fast(size); \
     _result->type = (tag); \
     _result; \
 })
 #else
 
 extern PGDLLIMPORT Node *newNodeMacroHolder;
 
 #define newNode(size, tag) \
 ( \
     AssertMacro((size) >= sizeof(Node)),         \
     newNodeMacroHolder = (Node *) palloc0fast(size), \
     newNodeMacroHolder->type = (tag), \
     newNodeMacroHolder \
 )
 #endif                          

 

 #define AllocSetContextCreate(parent, name, allocparams) \
     AllocSetContextCreateExtended(parent, name, allocparams)
 #endif

 
 MemoryContext
 AllocSetContextCreateExtended(MemoryContext parent,//上一级的内存上下文
                               const char *name,//MemoryContext名称
                               Size minContextSize,//最小大小
                               Size initBlockSize,//初始化大小
                               Size maxBlockSize)//最大大小
 {
     int         freeListIndex;//空闲列表索引
     Size        firstBlockSize;//第一个Block的Size
     AllocSet    set;//AllocSetContext指针
     AllocBlock  block;//Context中的Block
 
     
     StaticAssertStmt(ALLOC_CHUNKHDRSZ == MAXALIGN(ALLOC_CHUNKHDRSZ),
                      "sizeof(AllocChunkData) is not maxaligned");//对齐
     StaticAssertStmt(offsetof(AllocChunkData, aset) + sizeof(MemoryContext) ==
                      ALLOC_CHUNKHDRSZ,
                      "padding calculation in AllocChunkData is wrong");//对齐
 
     
     //验证参数
     Assert(initBlockSize == MAXALIGN(initBlockSize) &&
            initBlockSize >= 1024);
     Assert(maxBlockSize == MAXALIGN(maxBlockSize) &&
            maxBlockSize >= initBlockSize &&
            AllocHugeSizeIsValid(maxBlockSize)); 
     Assert(minContextSize == 0 ||
            (minContextSize == MAXALIGN(minContextSize) &&
             minContextSize >= 1024 &&
             minContextSize <= maxBlockSize));
 
     
     if (minContextSize == ALLOCSET_DEFAULT_MINSIZE &&
         initBlockSize == ALLOCSET_DEFAULT_INITSIZE)
         freeListIndex = 0;
     else if (minContextSize == ALLOCSET_SMALL_MINSIZE &&
              initBlockSize == ALLOCSET_SMALL_INITSIZE)
         freeListIndex = 1;
     else
         freeListIndex = -1;//默认为-1
 
     
     if (freeListIndex >= 0)//SMALL/DEFAULT值
     {
         AllocSetFreeList *freelist = &context_freelists[freeListIndex];//使用预定义的freelist
 
         if (freelist->first_free != NULL)
         {
             
             set = freelist->first_free;//使用第一个空闲的AllocSetContext
             freelist->first_free = (AllocSet) set->header.nextchild;//指针指向下一个空闲的AllocSetContext
             freelist->num_free--;//free计数器减一
 
             
             set->maxBlockSize = maxBlockSize;//更新AllocSetContext的相关信息
 
             
             MemoryContextCreate((MemoryContext) set,
                                 T_AllocSetContext,
                                 &AllocSetMethods,
                                 parent,
                                 name);//创建MemoryContext
 
             return (MemoryContext) set;//返回
         }
     }

     //freeListIndex = -1,定制化自己的MemoryContext
     
     firstBlockSize = MAXALIGN(sizeof(AllocSetContext)) +
         ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;//申请内存:AllocSetContext大小+Block头部大小+Chunk头部大小
     if (minContextSize != 0)
         firstBlockSize = Max(firstBlockSize, minContextSize);
     else
         firstBlockSize = Max(firstBlockSize, initBlockSize);
 
     
     set = (AllocSet) malloc(firstBlockSize);//分配内存
     if (set == NULL)//OOM?
     {
         if (TopMemoryContext)
             MemoryContextStats(TopMemoryContext);
         ereport(ERROR,
                 (errcode(ERRCODE_OUT_OF_MEMORY),
                  errmsg("out of memory"),
                  errdetail("Failed while creating memory context \"%s\".",
                            name)));
     }
 
     
 
     
     //获取Block头部指针,开始填充Block头部信息
     block = (AllocBlock) (((char *) set) + MAXALIGN(sizeof(AllocSetContext)));
     block->aset = set;
     block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
     block->endptr = ((char *) set) + firstBlockSize;
     block->prev = NULL;
     block->next = NULL;
 
     
     VALGRIND_MAKE_MEM_NOACCESS(block->freeptr, block->endptr - block->freeptr);
 
     
     set->blocks = block;
     
     set->keeper = block;
 
     
     MemSetAligned(set->freelist, 0, sizeof(set->freelist));//对齐
 
     set->initBlockSize = initBlockSize;//初始化set的各项属性
     set->maxBlockSize = maxBlockSize;
     set->nextBlockSize = initBlockSize;
     set->freeListIndex = freeListIndex;
 
     
     StaticAssertStmt(ALLOC_CHUNK_LIMIT == ALLOCSET_SEPARATE_THRESHOLD,//ALLOCSET_SEPARATE_THRESHOLD,8192
                      "ALLOC_CHUNK_LIMIT != ALLOCSET_SEPARATE_THRESHOLD");
 
     set->allocChunkLimit = ALLOC_CHUNK_LIMIT;
     while ((Size) (set->allocChunkLimit + ALLOC_CHUNKHDRSZ) >
            (Size) ((maxBlockSize - ALLOC_BLOCKHDRSZ) / ALLOC_CHUNK_FRACTION))//ALLOC_CHUNK_FRACTION-4
         set->allocChunkLimit >>= 1;//计算ChunkLimit上限,每次/2
 
     
     MemoryContextCreate((MemoryContext) set,
                         T_AllocSetContext,
                         &AllocSetMethods,
                         parent,
                         name);//创建MemoryContext
 
     return (MemoryContext) set;
 }

 
 void
 MemoryContextCreate(MemoryContext node,
                     NodeTag tag,
                     const MemoryContextMethods *methods,
                     MemoryContext parent,
                     const char *name)
 {
     
     Assert(CritSectionCount == 0);
 
     
     node->type = tag;
     node->isReset = true;
     node->methods = methods;
     node->parent = parent;
     node->firstchild = NULL;
     node->prevchild = NULL;
     node->name = name;
     node->ident = NULL;
     node->reset_cbs = NULL;
 
     
     if (parent)
     {
         node->nextchild = parent->firstchild;
         if (parent->firstchild != NULL)
             parent->firstchild->prevchild = node;
         parent->firstchild = node;
         
         node->allowInCritSection = parent->allowInCritSection;
     }
     else
     {
         node->nextchild = NULL;
         node->allowInCritSection = false;
     }
 
     VALGRIND_CREATE_MEMPOOL(node, 0, false);
 }
 

3、InitPlan

 
 static void
 InitPlan(QueryDesc *queryDesc, int eflags)
 {
     CmdType     operation = queryDesc->operation;//操作类型
     PlannedStmt *plannedstmt = queryDesc->plannedstmt;//已规划的Statement
     Plan       *plan = plannedstmt->planTree;//执行计划
     List       *rangeTable = plannedstmt->rtable;//本次执行涉及的Table
     EState     *estate = queryDesc->estate;//执行状态
     PlanState  *planstate;//计划状态
     TupleDesc   tupType;//Tuple信息
     ListCell   *l;//
     int         i;//
 
     
     ExecCheckRTPerms(rangeTable, true);//权限检查
 
     
     estate->es_range_table = rangeTable;
     estate->es_plannedstmt = plannedstmt;
 
     
     //初始化结果Relation
     if (plannedstmt->resultRelations)
     {
         List       *resultRelations = plannedstmt->resultRelations;
         int         numResultRelations = list_length(resultRelations);
         ResultRelInfo *resultRelInfos;
         ResultRelInfo *resultRelInfo;
 
         resultRelInfos = (ResultRelInfo *)
             palloc(numResultRelations * sizeof(ResultRelInfo));
         resultRelInfo = resultRelInfos;
         foreach(l, resultRelations)
         {
             Index       resultRelationIndex = lfirst_int(l);
             Oid         resultRelationOid;
             Relation    resultRelation;
 
             resultRelationOid = getrelid(resultRelationIndex, rangeTable);
             resultRelation = heap_open(resultRelationOid, RowExclusiveLock);
 
             InitResultRelInfo(resultRelInfo,
                               resultRelation,
                               resultRelationIndex,
                               NULL,
                               estate->es_instrument);
             resultRelInfo++;
         }
         estate->es_result_relations = resultRelInfos;
         estate->es_num_result_relations = numResultRelations;
         
         estate->es_result_relation_info = NULL;
 
         
         estate->es_root_result_relations = NULL;
         estate->es_num_root_result_relations = 0;
         if (plannedstmt->nonleafResultRelations)
         {
             int         num_roots = list_length(plannedstmt->rootResultRelations);
 
             
             resultRelInfos = (ResultRelInfo *)
                 palloc(num_roots * sizeof(ResultRelInfo));
             resultRelInfo = resultRelInfos;
             foreach(l, plannedstmt->rootResultRelations)
             {
                 Index       resultRelIndex = lfirst_int(l);
                 Oid         resultRelOid;
                 Relation    resultRelDesc;
 
                 resultRelOid = getrelid(resultRelIndex, rangeTable);
                 resultRelDesc = heap_open(resultRelOid, RowExclusiveLock);
                 InitResultRelInfo(resultRelInfo,
                                   resultRelDesc,
                                   lfirst_int(l),
                                   NULL,
                                   estate->es_instrument);
                 resultRelInfo++;
             }
 
             estate->es_root_result_relations = resultRelInfos;
             estate->es_num_root_result_relations = num_roots;
 
             
             foreach(l, plannedstmt->nonleafResultRelations)
             {
                 Index       resultRelIndex = lfirst_int(l);
 
                 
                 if (!list_member_int(plannedstmt->rootResultRelations,
                                      resultRelIndex))
                     LockRelationOid(getrelid(resultRelIndex, rangeTable),
                                     RowExclusiveLock);
             }
         }
     }
     else
     {
         
         estate->es_result_relations = NULL;
         estate->es_num_result_relations = 0;
         estate->es_result_relation_info = NULL;
         estate->es_root_result_relations = NULL;
         estate->es_num_root_result_relations = 0;
     }
 
     
     estate->es_rowMarks = NIL;
     foreach(l, plannedstmt->rowMarks)
     {
         PlanRowMark *rc = (PlanRowMark *) lfirst(l);
         Oid         relid;
         Relation    relation;
         ExecRowMark *erm;
 
         
         if (rc->isParent)
             continue;
 
         
         relid = getrelid(rc->rti, rangeTable);
 
         
         switch (rc->markType)
         {
             case ROW_MARK_EXCLUSIVE:
             case ROW_MARK_NOKEYEXCLUSIVE:
             case ROW_MARK_SHARE:
             case ROW_MARK_KEYSHARE:
                 relation = heap_open(relid, RowShareLock);
                 break;
             case ROW_MARK_REFERENCE:
                 relation = heap_open(relid, AccessshareLock);
                 break;
             case ROW_MARK_COPY:
                 
                 relation = NULL;
                 break;
             default:
                 elog(ERROR, "unrecognized markType: %d", rc->markType);
                 relation = NULL;    
                 break;
         }
 
         
         if (relation)
             CheckValidRowMarkRel(relation, rc->markType);
 
         erm = (ExecRowMark *) palloc(sizeof(ExecRowMark));
         erm->relation = relation;
         erm->relid = relid;
         erm->rti = rc->rti;
         erm->prti = rc->prti;
         erm->rowmarkId = rc->rowmarkId;
         erm->markType = rc->markType;
         erm->strength = rc->strength;
         erm->waitPolicy = rc->waitPolicy;
         erm->ermActive = false;
         ItemPointerSetInvalid(&(erm->curCtid));
         erm->ermExtra = NULL;
         estate->es_rowMarks = lappend(estate->es_rowMarks, erm);
     }
 
     
     estate->es_tupleTable = NIL;
     estate->es_trig_tuple_slot = NULL;
     estate->es_trig_oldtup_slot = NULL;
     estate->es_trig_newtup_slot = NULL;
 
     
     estate->es_epqTuple = NULL;
     estate->es_epqTupleSet = NULL;
     estate->es_epqScanDone = NULL;
 
     
     Assert(estate->es_subplanstates == NIL);
     i = 1;                      
     //初始化子Plan
     foreach(l, plannedstmt->subplans)
     {
         Plan       *subplan = (Plan *) lfirst(l);
         PlanState  *subplanstate;
         int         sp_eflags;
 
         
         sp_eflags = eflags
             & (EXEC_FLAG_EXPLAIN_ONLY | EXEC_FLAG_WITH_NO_DATA);
         if (bms_is_member(i, plannedstmt->rewindPlanIDs))
             sp_eflags |= EXEC_FLAG_REWIND;
 
         subplanstate = ExecInitNode(subplan, estate, sp_eflags);
 
         estate->es_subplanstates = lappend(estate->es_subplanstates,
                                            subplanstate);
 
         i++;
     }
 
     
     planstate = ExecInitNode(plan, estate, eflags);
 
     
     tupType = ExecGetResultType(planstate);
 
     
     if (operation == CMD_SELECT)
     {
         bool        junk_filter_needed = false;
         ListCell   *tlist;
 
         foreach(tlist, plan->targetlist)
         {
             TargetEntry *tle = (TargetEntry *) lfirst(tlist);
 
             if (tle->resjunk)
             {
                 junk_filter_needed = true;
                 break;
             }
         }
 
         if (junk_filter_needed)
         {
             JunkFilter *j;
 
             j = ExecInitJunkFilter(planstate->plan->targetlist,
                                    tupType->tdhasoid,
                                    ExecInitExtraTupleSlot(estate, NULL));
             estate->es_junkFilter = j;
 
             
             tupType = j->jf_cleanTupType;
         }
     }
 
     queryDesc->tupDesc = tupType;
     queryDesc->planstate = planstate;
 }


 bool
 ExecCheckRTPerms(List *rangeTable, bool ereport_on_violation)
 {
     ListCell   *l;
     bool        result = true;
 
     foreach(l, rangeTable)
     {
         RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
 
         result = ExecCheckRTEPerms(rte);//基于ACL Mode的权限检查
         if (!result)
         {
             Assert(rte->rtekind == RTE_RELATION);
             if (ereport_on_violation)
                 aclcheck_error(ACLCHECK_NO_PRIV, get_relkind_objtype(get_rel_relkind(rte->relid)),
                                get_rel_name(rte->relid));
             return false;
         }
     }
 
     if (ExecutorCheckPerms_hook)
         result = (*ExecutorCheckPerms_hook) (rangeTable,
                                              ereport_on_violation);
     return result;
 }
 
 
 //初始化节点,返回Plan状态
 PlanState *
 ExecInitNode(Plan *node, EState *estate, int eflags)
 {
     PlanState  *result;
     List       *subps;
     ListCell   *l;
 
     
     if (node == NULL)
         return NULL;
 
     
     check_stack_depth();
 
     switch (nodeTag(node))
     {
             
         case T_Result:
             result = (PlanState *) ExecInitResult((Result *) node,
                                                   estate, eflags);
             break;
 
         case T_ProjectSet:
             result = (PlanState *) ExecInitProjectSet((ProjectSet *) node,
                                                       estate, eflags);
             break;
 
         case T_ModifyTable://插入数据
             result = (PlanState *) ExecInitModifyTable((ModifyTable *) node,
                                                        estate, eflags);
             break;
 
         case T_Append:
             result = (PlanState *) ExecInitAppend((Append *) node,
                                                   estate, eflags);
             break;
 
         case T_MergeAppend:
             result = (PlanState *) ExecInitMergeAppend((MergeAppend *) node,
                                                        estate, eflags);
             break;
 
         case T_RecursiveUnion:
             result = (PlanState *) ExecInitRecursiveUnion((RecursiveUnion *) node,
                                                           estate, eflags);
             break;
 
         case T_BitmapAnd:
             result = (PlanState *) ExecInitBitmapAnd((BitmapAnd *) node,
                                                      estate, eflags);
             break;
 
         case T_BitmapOr:
             result = (PlanState *) ExecInitBitmapOr((BitmapOr *) node,
                                                     estate, eflags);
             break;
 
             
         case T_SeqScan:
             result = (PlanState *) ExecInitSeqScan((SeqScan *) node,
                                                    estate, eflags);
             break;
 
         case T_SampleScan:
             result = (PlanState *) ExecInitSampleScan((SampleScan *) node,
                                                       estate, eflags);
             break;
 
         case T_IndexScan:
             result = (PlanState *) ExecInitIndexScan((IndexScan *) node,
                                                      estate, eflags);
             break;
 
         case T_IndexOnlyScan:
             result = (PlanState *) ExecInitIndexOnlyScan((IndexOnlyScan *) node,
                                                          estate, eflags);
             break;
 
         case T_BitmapIndexScan:
             result = (PlanState *) ExecInitBitmapIndexScan((BitmapIndexScan *) node,
                                                            estate, eflags);
             break;
 
         case T_BitmapHeapScan:
             result = (PlanState *) ExecInitBitmapHeapScan((BitmapHeapScan *) node,
                                                           estate, eflags);
             break;
 
         case T_TidScan:
             result = (PlanState *) ExecInitTidScan((TidScan *) node,
                                                    estate, eflags);
             break;
 
         case T_SubqueryScan:
             result = (PlanState *) ExecInitSubqueryScan((SubqueryScan *) node,
                                                         estate, eflags);
             break;
 
         case T_FunctionScan:
             result = (PlanState *) ExecInitFunctionScan((FunctionScan *) node,
                                                         estate, eflags);
             break;
 
         case T_TableFuncScan:
             result = (PlanState *) ExecInitTableFuncScan((TableFuncScan *) node,
                                                          estate, eflags);
             break;
 
         case T_ValuesScan:
             result = (PlanState *) ExecInitValuesScan((ValuesScan *) node,
                                                       estate, eflags);
             break;
 
         case T_CteScan:
             result = (PlanState *) ExecInitCteScan((CteScan *) node,
                                                    estate, eflags);
             break;
 
         case T_NamedTuplestoreScan:
             result = (PlanState *) ExecInitNamedTuplestoreScan((NamedTuplestoreScan *) node,
                                                                estate, eflags);
             break;
 
         case T_WorkTableScan:
             result = (PlanState *) ExecInitWorkTableScan((WorkTableScan *) node,
                                                          estate, eflags);
             break;
 
         case T_ForeignScan:
             result = (PlanState *) ExecInitForeignScan((ForeignScan *) node,
                                                        estate, eflags);
             break;
 
         case T_CustomScan:
             result = (PlanState *) ExecInitCustomScan((CustomScan *) node,
                                                       estate, eflags);
             break;
 
             
         case T_NestLoop:
             result = (PlanState *) ExecInitNestLoop((NestLoop *) node,
                                                     estate, eflags);
             break;
 
         case T_MergeJoin:
             result = (PlanState *) ExecInitMergeJoin((MergeJoin *) node,
                                                      estate, eflags);
             break;
 
         case T_HashJoin:
             result = (PlanState *) ExecInitHashJoin((HashJoin *) node,
                                                     estate, eflags);
             break;
 
             
         case T_Material:
             result = (PlanState *) ExecInitMaterial((Material *) node,
                                                     estate, eflags);
             break;
 
         case T_Sort:
             result = (PlanState *) ExecInitSort((Sort *) node,
                                                 estate, eflags);
             break;
 
         case T_Group:
             result = (PlanState *) ExecInitGroup((Group *) node,
                                                  estate, eflags);
             break;
 
         case T_Agg:
             result = (PlanState *) ExecInitAgg((Agg *) node,
                                                estate, eflags);
             break;
 
         case T_WindowAgg:
             result = (PlanState *) ExecInitWindowAgg((WindowAgg *) node,
                                                      estate, eflags);
             break;
 
         case T_Unique:
             result = (PlanState *) ExecInitUnique((Unique *) node,
                                                   estate, eflags);
             break;
 
         case T_Gather:
             result = (PlanState *) ExecInitGather((Gather *) node,
                                                   estate, eflags);
             break;
 
         case T_GatherMerge:
             result = (PlanState *) ExecInitGatherMerge((GatherMerge *) node,
                                                        estate, eflags);
             break;
 
         case T_Hash:
             result = (PlanState *) ExecInitHash((Hash *) node,
                                                 estate, eflags);
             break;
 
         case T_SetOp:
             result = (PlanState *) ExecInitSetOp((SetOp *) node,
                                                  estate, eflags);
             break;
 
         case T_LockRows:
             result = (PlanState *) ExecInitLockRows((LockRows *) node,
                                                     estate, eflags);
             break;
 
         case T_Limit:
             result = (PlanState *) ExecInitLimit((Limit *) node,
                                                  estate, eflags);
             break;
 
         default:
             elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
             result = NULL;      
             break;
     }
 
     ExecSetExecProcNode(result, result->ExecProcNode);
 
     
     subps = NIL;
     foreach(l, node->initPlan)
     {
         SubPlan    *subplan = (SubPlan *) lfirst(l);
         SubPlanState *sstate;
 
         Assert(IsA(subplan, SubPlan));
         sstate = ExecInitSubPlan(subplan, result);
         subps = lappend(subps, sstate);
     }
     result->initPlan = subps;
 
     
     if (estate->es_instrument)
         result->instrument = InstrAlloc(1, estate->es_instrument);
 
     return result;
 }
 

 ModifyTableState *
 ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 {
     ModifyTableState *mtstate;//返回结果
     CmdType     operation = node->operation;//操作类型
     int         nplans = list_length(node->plans);//节点中的plan个数
     ResultRelInfo *saved_resultRelInfo;
     ResultRelInfo *resultRelInfo;//结果Relation信息
     Plan       *subplan;//子Plan
     ListCell   *l;//临时变量
     int         i;
     Relation    rel;
     bool        update_tuple_routing_needed = node->partColsUpdated;
 
     
     Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
 
     
     mtstate = makeNode(ModifyTableState);//构建节点
     mtstate->ps.plan = (Plan *) node;//设置Plan
     mtstate->ps.state = estate;//设置执行状态
     mtstate->ps.ExecProcNode = ExecModifyTable;//设置处理函数为ExecModifyTable
 
     mtstate->operation = operation;//操作类型
     mtstate->canSetTag = node->canSetTag;
     mtstate->mt_done = false;
 
     mtstate->mt_plans = (PlanState **) palloc0(sizeof(PlanState *) * nplans);//分配内存
     mtstate->resultRelInfo = estate->es_result_relations + node->resultRelIndex;//结果Relation信息
 
     
     if (node->rootResultRelIndex >= 0)
         mtstate->rootResultRelInfo = estate->es_root_result_relations +
             node->rootResultRelIndex;
 
     mtstate->mt_arowmarks = (List **) palloc0(sizeof(List *) * nplans);
     mtstate->mt_nplans = nplans;
 
     
     EvalPlanQualInit(&mtstate->mt_epqstate, estate, NULL, NIL, node->epqParam);
     mtstate->fireBSTriggers = true;
 
     
     saved_resultRelInfo = estate->es_result_relation_info;
 
     resultRelInfo = mtstate->resultRelInfo;
     i = 0;
     //初始化每个子Plan,保存在mt_plans数组中
     foreach(l, node->plans)
     {
         subplan = (Plan *) lfirst(l);
 
         
         resultRelInfo->ri_usesFdwDirectModify = bms_is_member(i,
                                                               node->fdwDirectModifyPlans);
 
         
         CheckValidResultRel(resultRelInfo, operation);
 
         
         if (resultRelInfo->ri_RelationDesc->rd_rel->relhasindex &&
             operation != CMD_DELETE &&
             resultRelInfo->ri_IndexRelationDescs == NULL)
             ExecOpenIndices(resultRelInfo,
                             node->onConflictAction != ONCONFLICT_NONE);//初始化Index
 
         
         if (resultRelInfo->ri_TrigDesc &&
             resultRelInfo->ri_TrigDesc->trig_update_before_row &&
             operation == CMD_UPDATE)
             update_tuple_routing_needed = true;
 
         
         estate->es_result_relation_info = resultRelInfo;
         mtstate->mt_plans[i] = ExecInitNode(subplan, estate, eflags);//初始化子节点
 
         
         if (!resultRelInfo->ri_usesFdwDirectModify &&
             resultRelInfo->ri_FdwRoutine != NULL &&
             resultRelInfo->ri_FdwRoutine->BeginForeignModify != NULL)
         {
             List       *fdw_private = (List *) list_nth(node->fdwPrivLists, i);
 
             resultRelInfo->ri_FdwRoutine->BeginForeignModify(mtstate,
                                                              resultRelInfo,
                                                              fdw_private,
                                                              i,
                                                              eflags);
         }
 
         resultRelInfo++;
         i++;
     }
 
     estate->es_result_relation_info = saved_resultRelInfo;
 
     
     rel = (getTargetResultRelInfo(mtstate))->ri_RelationDesc;
 
     
     if (rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
         update_tuple_routing_needed = false;
 
     
     if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
         (operation == CMD_INSERT || update_tuple_routing_needed))
         mtstate->mt_partition_tuple_routing =
             ExecSetupPartitionTupleRouting(mtstate, rel);
 
     
     if (!(eflags & EXEC_FLAG_EXPLAIN_ONLY))
         ExecSetupTransitionCaptureState(mtstate, estate);
 
     
     if (update_tuple_routing_needed)
         ExecSetupChildParentMapForSubplan(mtstate);
 
     
     resultRelInfo = mtstate->resultRelInfo;
     i = 0;
     //设置Check选项
     foreach(l, node->withCheckOptionLists)
     {
         List       *wcoList = (List *) lfirst(l);
         List       *wcoExprs = NIL;
         ListCell   *ll;
 
         foreach(ll, wcoList)
         {
             WithCheckOption *wco = (WithCheckOption *) lfirst(ll);
             ExprState  *wcoExpr = ExecInitQual((List *) wco->qual,
                                                mtstate->mt_plans[i]);
 
             wcoExprs = lappend(wcoExprs, wcoExpr);
         }
 
         resultRelInfo->ri_WithCheckOptions = wcoList;
         resultRelInfo->ri_WithCheckOptionExprs = wcoExprs;
         resultRelInfo++;
         i++;
     }
 
     
     if (node->returningLists)
     {
         TupleTableSlot *slot;
         ExprContext *econtext;
 
         
         mtstate->ps.plan->targetlist = (List *) linitial(node->returningLists);
 
         
         ExecInitResultTupleSlotTL(estate, &mtstate->ps);
         slot = mtstate->ps.ps_ResultTupleSlot;
 
         
         if (mtstate->ps.ps_ExprContext == NULL)
             ExecAssignExprContext(estate, &mtstate->ps);
         econtext = mtstate->ps.ps_ExprContext;
 
         
         resultRelInfo = mtstate->resultRelInfo;
         foreach(l, node->returningLists)
         {
             List       *rlist = (List *) lfirst(l);
 
             resultRelInfo->ri_returningList = rlist;
             resultRelInfo->ri_projectReturning =
                 ExecBuildProjectionInfo(rlist, econtext, slot, &mtstate->ps,
                                         resultRelInfo->ri_RelationDesc->rd_att);
             resultRelInfo++;
         }
     }
     else
     {
         
         mtstate->ps.plan->targetlist = NIL;
         ExecInitResultTupleSlotTL(estate, &mtstate->ps);
 
         mtstate->ps.ps_ExprContext = NULL;
     }
 
     
     resultRelInfo = mtstate->resultRelInfo;
     if (node->onConflictAction != ONCONFLICT_NONE)
         resultRelInfo->ri_onConflictArbiterIndexes = node->arbiterIndexes;
 
     
     if (node->onConflictAction == ONCONFLICT_UPDATE)
     {
         ExprContext *econtext;
         TupleDesc   relationDesc;
         TupleDesc   tupDesc;
 
         
         Assert(nplans == 1);
 
         
         if (mtstate->ps.ps_ExprContext == NULL)
             ExecAssignExprContext(estate, &mtstate->ps);
 
         econtext = mtstate->ps.ps_ExprContext;
         relationDesc = resultRelInfo->ri_RelationDesc->rd_att;
 
         
         mtstate->mt_existing =
             ExecInitExtraTupleSlot(mtstate->ps.state,
                                    mtstate->mt_partition_tuple_routing ?
                                    NULL : relationDesc);
 
         
         mtstate->mt_excludedtlist = node->exclRelTlist;
 
         
         resultRelInfo->ri_onConflict = makeNode(OnConflictSetState);
 
         
         tupDesc = ExecTypeFromTL((List *) node->onConflictSet,
                                  relationDesc->tdhasoid);
         mtstate->mt_conflproj =
             ExecInitExtraTupleSlot(mtstate->ps.state,
                                    mtstate->mt_partition_tuple_routing ?
                                    NULL : tupDesc);
         resultRelInfo->ri_onConflict->oc_ProjTupdesc = tupDesc;
 
         
         resultRelInfo->ri_onConflict->oc_ProjInfo =
             ExecBuildProjectionInfo(node->onConflictSet, econtext,
                                     mtstate->mt_conflproj, &mtstate->ps,
                                     relationDesc);
 
         
         if (node->onConflictWhere)
         {
             ExprState  *qualexpr;
 
             qualexpr = ExecInitQual((List *) node->onConflictWhere,
                                     &mtstate->ps);
             resultRelInfo->ri_onConflict->oc_WhereClause = qualexpr;
         }
     }
 
     
     foreach(l, node->rowMarks)
     {
         PlanRowMark *rc = lfirst_node(PlanRowMark, l);
         ExecRowMark *erm;
 
         
         if (rc->isParent)
             continue;
 
         
         erm = ExecFindRowMark(estate, rc->rti, false);
 
         
         for (i = 0; i < nplans; i++)
         {
             ExecAuxRowMark *aerm;
 
             subplan = mtstate->mt_plans[i]->plan;
             aerm = ExecBuildAuxRowMark(erm, subplan->targetlist);
             mtstate->mt_arowmarks[i] = lappend(mtstate->mt_arowmarks[i], aerm);
         }
     }
 
     
     mtstate->mt_whichplan = 0;
     subplan = (Plan *) linitial(node->plans);
     EvalPlanQualSetPlan(&mtstate->mt_epqstate, subplan,
                         mtstate->mt_arowmarks[0]);
 
     
     {
         bool        junk_filter_needed = false;
 
         switch (operation)
         {
             case CMD_INSERT:
                 foreach(l, subplan->targetlist)
                 {
                     TargetEntry *tle = (TargetEntry *) lfirst(l);
 
                     if (tle->resjunk)
                     {
                         junk_filter_needed = true;
                         break;
                     }
                 }
                 break;
             case CMD_UPDATE:
             case CMD_DELETE:
                 junk_filter_needed = true;
                 break;
             default:
                 elog(ERROR, "unknown operation");
                 break;
         }
 
         if (junk_filter_needed)
         {
             resultRelInfo = mtstate->resultRelInfo;
             for (i = 0; i < nplans; i++)
             {
                 JunkFilter *j;
 
                 subplan = mtstate->mt_plans[i]->plan;
                 if (operation == CMD_INSERT || operation == CMD_UPDATE)
                     ExecCheckPlanOutput(resultRelInfo->ri_RelationDesc,
                                         subplan->targetlist);
 
                 j = ExecInitJunkFilter(subplan->targetlist,
                                        resultRelInfo->ri_RelationDesc->rd_att->tdhasoid,
                                        ExecInitExtraTupleSlot(estate, NULL));
 
                 if (operation == CMD_UPDATE || operation == CMD_DELETE)
                 {
                     
                     char        relkind;
 
                     relkind = resultRelInfo->ri_RelationDesc->rd_rel->relkind;
                     if (relkind == RELKIND_RELATION ||
                         relkind == RELKIND_MATVIEW ||
                         relkind == RELKIND_PARTITIONED_TABLE)
                     {
                         j->jf_junkAttNo = ExecFindJunkAttribute(j, "ctid");
                         if (!AttributeNumberIsValid(j->jf_junkAttNo))
                             elog(ERROR, "could not find junk ctid column");
                     }
                     else if (relkind == RELKIND_FOREIGN_TABLE)
                     {
                         
                         j->jf_junkAttNo = ExecFindJunkAttribute(j, "wholerow");
                     }
                     else
                     {
                         j->jf_junkAttNo = ExecFindJunkAttribute(j, "wholerow");
                         if (!AttributeNumberIsValid(j->jf_junkAttNo))
                             elog(ERROR, "could not find junk wholerow column");
                     }
                 }
 
                 resultRelInfo->ri_junkFilter = j;
                 resultRelInfo++;
             }
         }
         else
         {
             if (operation == CMD_INSERT)
                 ExecCheckPlanOutput(mtstate->resultRelInfo->ri_RelationDesc,
                                     subplan->targetlist);
         }
     }
 
     
     if (estate->es_trig_tuple_slot == NULL)
         estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate, NULL);
 
     
     if (!mtstate->canSetTag)
         estate->es_auxmodifytables = lcons(mtstate,
                                            estate->es_auxmodifytables);
 
     return mtstate;
 }

 
 typedef struct ModifyTable
 {
     Plan        plan;
     CmdType     operation;      
     bool        canSetTag;      
     Index       nominalRelation;    
     
     List       *partitioned_rels;
     bool        partColsUpdated;    
     List       *resultRelations;    
     int         resultRelIndex; 
     int         rootResultRelIndex; 
     List       *plans;          
     List       *withCheckOptionLists;   
     List       *returningLists; 
     List       *fdwPrivLists;   
     Bitmapset  *fdwDirectModifyPlans;   
     List       *rowMarks;       
     int         epqParam;       
     OnConflictAction onConflictAction;  
     List       *arbiterIndexes; 
     List       *onConflictSet;  
     Node       *onConflictWhere;    
     Index       exclRelRTI;     
     List       *exclRelTlist;   
 } ModifyTable;

4、ExecutorStart

 
 void
 ExecutorStart(QueryDesc *queryDesc, int eflags)//eflags见后
 {
     if (ExecutorStart_hook)
         (*ExecutorStart_hook) (queryDesc, eflags);//提供了钩子函数
     else
         standard_ExecutorStart(queryDesc, eflags);//标准函数
 }
 
 void
 standard_ExecutorStart(QueryDesc *queryDesc, int eflags)//标准函数
 {
     EState     *estate;//执行器状态信息
     MemoryContext oldcontext;//原内存上下文
 
     
     Assert(queryDesc != NULL);
     Assert(queryDesc->estate == NULL);
 
     
     if ((XactReadOnly || IsInParallelMode()) &&
         !(eflags & EXEC_FLAG_EXPLAIN_ONLY))
         ExecCheckXactReadOnly(queryDesc->plannedstmt);//ReadOnly?
 
     
     estate = CreateExecutorState();//创建执行器状态信息
     queryDesc->estate = estate;//赋值
 
     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);//切换上下文
 
     
     estate->es_param_list_info = queryDesc->params;//设置参数
 
     if (queryDesc->plannedstmt->paramExecTypes != NIL)//TODO
     {
         int         nParamExec;
 
         nParamExec = list_length(queryDesc->plannedstmt->paramExecTypes);
         estate->es_param_exec_vals = (ParamExecData *)
             palloc0(nParamExec * sizeof(ParamExecData));
     }
 
     estate->es_sourceText = queryDesc->sourceText;//源SQL语句
 
     
     estate->es_queryEnv = queryDesc->queryEnv;//查询环境
 
     
     switch (queryDesc->operation)
     {
         case CMD_SELECT://查询语句 TODO
 
             
             if (queryDesc->plannedstmt->rowMarks != NIL ||
                 queryDesc->plannedstmt->hasModifyingCTE)
                 estate->es_output_cid = GetCurrentCommandId(true);
 
             
             if (!queryDesc->plannedstmt->hasModifyingCTE)
                 eflags |= EXEC_FLAG_SKIP_TRIGGERS;
             break;
 
         case CMD_INSERT://插入语句
         case CMD_DELETE:
         case CMD_UPDATE:
             estate->es_output_cid = GetCurrentCommandId(true);
             break;
 
         default:
             elog(ERROR, "unrecognized operation code: %d",
                  (int) queryDesc->operation);
             break;
     }
 
     
     estate->es_snapshot = RegisterSnapshot(queryDesc->snapshot);
     estate->es_crosscheck_snapshot = RegisterSnapshot(queryDesc->crosscheck_snapshot);
     estate->es_top_eflags = eflags;
     estate->es_instrument = queryDesc->instrument_options;
     estate->es_jit_flags = queryDesc->plannedstmt->jitFlags;
 
     
     if (!(eflags & (EXEC_FLAG_SKIP_TRIGGERS | EXEC_FLAG_EXPLAIN_ONLY)))
         AfterTriggerBeginQuery();
     
     
     InitPlan(queryDesc, eflags);//初始化Plan State tree
 
     MemoryContextSwitchTo(oldcontext);
 }
 
 
 CommandId
 GetCurrentCommandId(bool used)
 {
     
     if (used)
     {
         
         Assert(!IsParallelWorker());
         currentCommandIdUsed = true;
     }
     return currentCommandId;
 }
 

#define EXEC_FLAG_EXPLAIN_ONLY  0x0001  
#define EXEC_FLAG_REWIND        0x0002  
#define EXEC_FLAG_BACKWARD      0x0004  
#define EXEC_FLAG_MARK          0x0008  
#define EXEC_FLAG_SKIP_TRIGGERS 0x0010  
#define EXEC_FLAG_WITH_OIDS     0x0020  
#define EXEC_FLAG_WITHOUT_OIDS  0x0040  
#define EXEC_FLAG_WITH_NO_DATA  0x0080  

5、ExecutorRun

//上一节已介绍

6、ExecutorFinish


 void
 ExecutorFinish(QueryDesc *queryDesc)
 {
     if (ExecutorFinish_hook)
         (*ExecutorFinish_hook) (queryDesc);
     else
         standard_ExecutorFinish(queryDesc);
 }
 
 void
 standard_ExecutorFinish(QueryDesc *queryDesc)
 {
     EState     *estate;
     MemoryContext oldcontext;
 
     
     Assert(queryDesc != NULL);
 
     estate = queryDesc->estate;
 
     Assert(estate != NULL);
     Assert(!(estate->es_top_eflags & EXEC_FLAG_EXPLAIN_ONLY));
 
     
     Assert(!estate->es_finished);
 
     
     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
 
     
     if (queryDesc->totaltime)
         InstrStartNode(queryDesc->totaltime);
 
     
     ExecPostprocessPlan(estate);
 
     
     if (!(estate->es_top_eflags & EXEC_FLAG_SKIP_TRIGGERS))
         AfterTriggerEndQuery(estate);
 
     if (queryDesc->totaltime)
         InstrStopNode(queryDesc->totaltime, 0);
 
     MemoryContextSwitchTo(oldcontext);
 
     estate->es_finished = true;
 }
 
 
 static void
 ExecPostprocessPlan(EState *estate)
 {
     ListCell   *lc;
 
     
     estate->es_direction = ForwardScanDirection;
 
     
     foreach(lc, estate->es_auxmodifytables)
     {
         PlanState  *ps = (PlanState *) lfirst(lc);
 
         for (;;)
         {
             TupleTableSlot *slot;
 
             
             ResetPerTupleExprContext(estate);
 
             slot = ExecProcNode(ps);
 
             if (TupIsNull(slot))
                 break;
         }
  }

7、ExecutorEnd

 
 void
 ExecutorEnd(QueryDesc *queryDesc)
 {
     if (ExecutorEnd_hook)
         (*ExecutorEnd_hook) (queryDesc);
     else
         standard_ExecutorEnd(queryDesc);
 }
 
 void
 standard_ExecutorEnd(QueryDesc *queryDesc)
 {
     EState     *estate;
     MemoryContext oldcontext;
 
     
     Assert(queryDesc != NULL);
 
     estate = queryDesc->estate;
 
     Assert(estate != NULL);
 
     
     Assert(estate->es_finished ||
            (estate->es_top_eflags & EXEC_FLAG_EXPLAIN_ONLY));
 
     
     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
 
     ExecEndPlan(queryDesc->planstate, estate);
 
     
     UnregisterSnapshot(estate->es_snapshot);
     UnregisterSnapshot(estate->es_crosscheck_snapshot);
 
     
     MemoryContextSwitchTo(oldcontext);
 
     
     FreeExecutorState(estate);
 
     
     queryDesc->tupDesc = NULL;
     queryDesc->estate = NULL;
     queryDesc->planstate = NULL;
     queryDesc->totaltime = NULL;
 }

 
 static void
 ExecEndPlan(PlanState *planstate, EState *estate)
 {
     ResultRelInfo *resultRelInfo;
     int         i;
     ListCell   *l;
 
     
     ExecEndNode(planstate);
 
     
     foreach(l, estate->es_subplanstates)
     {
         PlanState  *subplanstate = (PlanState *) lfirst(l);
 
         ExecEndNode(subplanstate);
     }
 
     
     ExecResetTupleTable(estate->es_tupleTable, false);
 
     
     resultRelInfo = estate->es_result_relations;
     for (i = estate->es_num_result_relations; i > 0; i--)
     {
         
         ExecCloseIndices(resultRelInfo);
         heap_close(resultRelInfo->ri_RelationDesc, NoLock);
         resultRelInfo++;
     }
 
     
     resultRelInfo = estate->es_root_result_relations;
     for (i = estate->es_num_root_result_relations; i > 0; i--)
     {
         heap_close(resultRelInfo->ri_RelationDesc, NoLock);
         resultRelInfo++;
     }
 
     
     ExecCleanUpTriggerState(estate);
 
     
     foreach(l, estate->es_rowMarks)
     {
         ExecRowMark *erm = (ExecRowMark *) lfirst(l);
 
         if (erm->relation)
             heap_close(erm->relation, NoLock);
     }
 }

8、FreeQueryDesc

//释放资源
 
 void
 FreeQueryDesc(QueryDesc *qdesc)
 {
     
     Assert(qdesc->estate == NULL);
 
     
     UnregisterSnapshot(qdesc->snapshot);
     UnregisterSnapshot(qdesc->crosscheck_snapshot);
 
     
     pfree(qdesc);
 }
 

二、源码解读




static void
ProcessQuery(PlannedStmt *plan,
             const char *sourceText,
             ParamListInfo params,
             QueryEnvironment *queryEnv,
             DestReceiver *dest,
             char *completionTag)
{
    QueryDesc  *queryDesc;//查询描述符

    
    queryDesc = CreateQueryDesc(plan, sourceText,
                                GetActiveSnapshot(), InvalidSnapshot,
                                dest, params, queryEnv, 0);//构造查询描述符

    
    ExecutorStart(queryDesc, 0);//启动执行器

    
    ExecutorRun(queryDesc, ForwardScanDirection, 0L, true);//执行

    
    if (completionTag)//如果需要完成标记
    {
        Oid         lastOid;

        switch (queryDesc->operation)
        {
            case CMD_SELECT:
                snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
                         "SELECT " UINT64_FORMAT,
                         queryDesc->estate->es_processed);
                break;
            case CMD_INSERT://插入语句
                if (queryDesc->estate->es_processed == 1)
                    lastOid = queryDesc->estate->es_lastoid;
                else
                    lastOid = InvalidOid;
                snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
                         "INSERT %u " UINT64_FORMAT,
                         lastOid, queryDesc->estate->es_processed);
                break;
            case CMD_UPDATE:
                snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
                         "UPDATE " UINT64_FORMAT,
                         queryDesc->estate->es_processed);
                break;
            case CMD_DELETE:
                snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
                         "DELETE " UINT64_FORMAT,
                         queryDesc->estate->es_processed);
                break;
            default:
                strcpy(completionTag, "???");
                break;
        }
    }

    
    ExecutorFinish(queryDesc);//完成
    ExecutorEnd(queryDesc);//结束

    FreeQueryDesc(queryDesc);//释放资源
}

三、跟踪分析

插入测试数据:

testdb=# -- #9.1 ProcessQuery
testdb=# -- 获取pid
testdb=# select pg_backend_pid();
 pg_backend_pid 
----------------
           2551
(1 row)
testdb=# -- 插入1行
testdb=# insert into t_insert values(17,'ProcessQuery','ProcessQuery','ProcessQuery');
(挂起)

启动gdb,跟踪调试:

[root@localhost ~]# gdb -p 2551
GNU gdb (GDB) Red Hat Enterprise linux 7.6.1-100.el7
Copyright (C) 2013 Free Software Foundation, Inc.
...
(gdb) b ProcessQuery
Breakpoint 1 at 0x851d19: file pquery.c, line 149.
(gdb) c
Continuing.

Breakpoint 1, ProcessQuery (plan=0x2ccb378, sourceText=0x2c09ef0 "insert into t_insert values(17,'ProcessQuery','ProcessQuery','ProcessQuery');", params=0x0, queryEnv=0x0, dest=0x2ccb4d8, 
    completionTag=0x7ffe94ba4940 "") at pquery.c:149
149     queryDesc = CreateQueryDesc(plan, sourceText,
#查看参数
#1、plan
(gdb) p *plan
$1 = {type = T_PlannedStmt, commandType = CMD_INSERT, queryId = 0, hasReturning = false, hasModifyingCTE = false, canSetTag = true, transientPlan = false, dependsOnRole = false, 
  parallelModeNeeded = false, jitFlags = 0, planTree = 0x2ccafe8, rtable = 0x2ccb2a8, resultRelations = 0x2ccb348, nonleafResultRelations = 0x0, rootResultRelations = 0x0, subplans = 0x0, 
  rewindPlanIDs = 0x0, rowMarks = 0x0, relationOids = 0x2ccb2f8, invalItems = 0x0, paramExecTypes = 0x2c31370, utilityStmt = 0x0, stmt_location = 0, stmt_len = 76}
(gdb) p *(plan->planTree)
#执行树,左右均无兄弟节点
$2 = {type = T_ModifyTable, startup_cost = 0, total_cost = 0.01, plan_rows = 1, plan_width = 298, parallel_aware = false, parallel_safe = false, plan_node_id = 0, targetlist = 0x0, qual = 0x0, 
  lefttree = 0x0, righttree = 0x0, initPlan = 0x0, extParam = 0x0, allParam = 0x0}
(gdb) p *(plan->rtable)
$3 = {type = T_List, length = 1, head = 0x2ccb288, tail = 0x2ccb288}
(gdb) p *(plan->rtable->head)
#Oid=46969208,可使用pg_class查询
$4 = {data = {ptr_value = 0x2ccb178, int_value = 46969208, oid_value = 46969208}, next = 0x0}
(gdb) p *(plan->resultRelations)
$5 = {type = T_IntList, length = 1, head = 0x2ccb328, tail = 0x2ccb328}
(gdb) p *(plan->resultRelations->head)
#Oid=1?,可使用pg_class查询
$6 = {data = {ptr_value = 0x1, int_value = 1, oid_value = 1}, next = 0x0}
(gdb) p *(plan->relationOids)
$7 = {type = T_OidList, length = 1, head = 0x2ccb2d8, tail = 0x2ccb2d8}
(gdb) p *(plan->relationOids->head)
#Oid=26731,可使用pg_class查询
$8 = {data = {ptr_value = 0x686b, int_value = 26731, oid_value = 26731}, next = 0x0}
#2、sourceText
(gdb) p sourceText
$11 = 0x2c09ef0 "insert into t_insert values(17,'ProcessQuery','ProcessQuery','ProcessQuery');"
#3、params
(gdb) p params
#NULL
$12 = (ParamListInfo) 0x0
#4、queryEnv
(gdb) p queryEnv
#NULL
$13 = (QueryEnvironment *) 0x0
#5、dest
(gdb) p dest
$14 = (DestReceiver *) 0x2ccb4d8
(gdb) p *dest
$15 = {receiveSlot = 0x4857ad <printtup>, rStartup = 0x485196 <printtup_startup>, rShutdown = 0x485bad <printtup_shutdown>, rDestroy = 0x485c21 <printtup_destroy>, mydest = DestRemote}
(gdb) 
#6、completionTag
(gdb) p completionTag
#空字符串
$16 = 0x7ffe94ba4940 ""
(gdb) next
156     ExecutorStart(queryDesc, 0);
(gdb) 
161     ExecutorRun(queryDesc, ForwardScanDirection, 0L, true);
(gdb) 
166     if (completionTag)
(gdb) 
170         switch (queryDesc->operation)
(gdb) 
178                 if (queryDesc->estate->es_processed == 1)
(gdb) 
179                     lastOid = queryDesc->estate->es_lastoid;
(gdb) p queryDesc->estate->es_lastoid
$18 = 0
(gdb) 
$19 = 0
(gdb) next
184                          lastOid, queryDesc->estate->es_processed);
(gdb) p lastOid
$20 = 0
(gdb) next
182                 snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
(gdb) 
185                 break;
(gdb) p completionTag
#返回标记,在psql中输出的信息
$21 = 0x7ffe94ba4940 "INSERT 0 1"
(gdb) 
$22 = 0x7ffe94ba4940 "INSERT 0 1"
(gdb) next
205     ExecutorFinish(queryDesc);
(gdb) 
206     ExecutorEnd(queryDesc);
(gdb) 
208     FreeQueryDesc(queryDesc);
(gdb) 
209 }
(gdb) 
PortalRunMulti (portal=0x2c6f490, isTopLevel=true, setHoldSnapshot=false, dest=0x2ccb4d8, altdest=0x2ccb4d8, completionTag=0x7ffe94ba4940 "INSERT 0 1") at pquery.c:1302
1302                if (log_executor_stats)
(gdb) 
#DONE!

为了更深入理解整个执行过程中最重要的两个数据结构PlanState和EState,对子函数InitPlan和CreateExecutorState作进一步的跟踪分析:
InitPlan

testdb=# -- 插入1行
testdb=# insert into t_insert values(18,'ProcessQuery.InitPlan','ProcessQuery.InitPlan','ProcessQuery.InitPlan');
(挂起)

(gdb) b InitPlan
Breakpoint 1 at 0x691560: file execMain.c, line 811.
#查看参数
#1、queryDesc
(gdb) p *queryDesc
$8 = {operation = CMD_INSERT, plannedstmt = 0x2ccb408, sourceText = 0x2c09ef0 "insert into t_insert values(18,'ProcessQuery.InitPlan','ProcessQuery.InitPlan','ProcessQuery.InitPlan');", 
  snapshot = 0x2c2d920, crosscheck_snapshot = 0x0, dest = 0x2ccb568, params = 0x0, queryEnv = 0x0, instrument_options = 0, tupDesc = 0x0, estate = 0x2cbcc70, planstate = 0x0, already_executed = false, 
  totaltime = 0x0}
#2、eflags
(gdb) p eflags
$9 = 0
(gdb) next
812     PlannedStmt *plannedstmt = queryDesc->plannedstmt;
(gdb) 
813     Plan       *plan = plannedstmt->planTree;
(gdb) 
814     List       *rangeTable = plannedstmt->rtable;
(gdb) p *(queryDesc->plannedstmt)
$10 = {type = T_PlannedStmt, commandType = CMD_INSERT, queryId = 0, hasReturning = false, hasModifyingCTE = false, canSetTag = true, transientPlan = false, dependsOnRole = false, 
  parallelModeNeeded = false, jitFlags = 0, planTree = 0x2ccb078, rtable = 0x2ccb338, resultRelations = 0x2ccb3D8, nonleafResultRelations = 0x0, rootResultRelations = 0x0, subplans = 0x0, 
  rewindPlanIDs = 0x0, rowMarks = 0x0, relationOids = 0x2ccb388, invalItems = 0x0, paramExecTypes = 0x2c313f8, utilityStmt = 0x0, stmt_location = 0, stmt_len = 103}
(gdb) next
815     EState     *estate = queryDesc->estate;
(gdb) 
824     ExecCheckRTPerms(rangeTable, true);
(gdb) 
829     estate->es_range_table = rangeTable;
(gdb) 
830     estate->es_plannedstmt = plannedstmt;
(gdb) p *rangeTable
$11 = {type = T_List, length = 1, head = 0x2ccb318, tail = 0x2ccb318}
(gdb) p *(rangeTable->head)
$12 = {data = {ptr_value = 0x2ccb208, int_value = 46969352, oid_value = 46969352}, next = 0x0}
(gdb) next
838     if (plannedstmt->resultRelations)
(gdb) 
840         List       *resultRelations = plannedstmt->resultRelations;
(gdb) 
841         int         numResultRelations = list_length(resultRelations);
(gdb) 
846             palloc(numResultRelations * sizeof(ResultRelInfo));
(gdb) p numResultRelations
$13 = 1
(gdb) p *(resultRelations->head)
$14 = {data = {ptr_value = 0x1, int_value = 1, oid_value = 1}, next = 0x0}
(gdb) 
(gdb) next
845         resultRelInfos = (ResultRelInfo *)
(gdb) 
847         resultRelInfo = resultRelInfos;
(gdb) 
848         foreach(l, resultRelations)
(gdb) 
850             Index       resultRelationIndex = lfirst_int(l);
(gdb) 
854             resultRelationOid = getrelid(resultRelationIndex, rangeTable);
(gdb) 
855             resultRelation = heap_open(resultRelationOid, RowExclusiveLock);
(gdb) 
857             InitResultRelInfo(resultRelInfo,
(gdb) p resultRelationOid
$15 = 26731
(gdb) p resultRelation
$16 = (Relation) 0x7f3a64247b78
#目标Relation,t_insert
(gdb) p *resultRelation
$17 = {rd_node = {spcNode = 1663, dbNode = 16477, relNode = 26747}, rd_smgr = 0x2c99328, rd_refcnt = 1, rd_backend = -1, rd_islocaltemp = false, rd_isnailed = false, rd_isvalid = true, 
  rd_indexvalid = 1 '\001', rd_statvalid = true, rd_createSubid = 0, rd_newRelfilenodeSubid = 0, rd_rel = 0x7f3a64247d88, rd_att = 0x7f3a64247e98, 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 = 0x7f3a64249cf0, 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 = 0x2c8ae98}
(gdb) 
gdb) next
848         foreach(l, resultRelations)
(gdb) 
864         estate->es_result_relations = resultRelInfos;
(gdb) 
865         estate->es_num_result_relations = numResultRelations;
(gdb) 
867         estate->es_result_relation_info = NULL;
(gdb) 
874         estate->es_root_result_relations = NULL;
(gdb) 
875         estate->es_num_root_result_relations = 0;
(gdb) 
876         if (plannedstmt->nonleafResultRelations)
(gdb) p *plannedstmt->nonleafResultRelations
Cannot access memory at address 0x0
(gdb) next
941     estate->es_rowMarks = NIL;
942     foreach(l, plannedstmt->rowMarks)
(gdb) p plannedstmt->rowMarks
$19 = (List *) 0x0
(gdb) next
1003        estate->es_tupleTable = NIL;
(gdb) 
1004        estate->es_trig_tuple_slot = NULL;
(gdb) 
1005        estate->es_trig_oldtup_slot = NULL;
(gdb) 
1006        estate->es_trig_newtup_slot = NULL;
(gdb) 
1009        estate->es_epqTuple = NULL;
(gdb) 
1010        estate->es_epqTupleSet = NULL;
(gdb) 
1011        estate->es_epqScanDone = NULL;
(gdb) 
1019        i = 1;                      
(gdb) 
1020        foreach(l, plannedstmt->subplans)
(gdb) p *plannedstmt->subplans
Cannot access memory at address 0x0
(gdb) next
1049        planstate = ExecInitNode(plan, estate, eflags);
(gdb) step
ExecInitNode (node=0x2ccb078, estate=0x2cbcc70, eflags=0) at execProcnode.c:148
148     if (node == NULL)
(gdb) next
156     check_stack_depth();
(gdb) 
158     switch (nodeTag(node))
(gdb) 
174             result = (PlanState *) ExecInitModifyTable((ModifyTable *) node,
(gdb) step
ExecInitModifyTable (node=0x2ccb078, estate=0x2cbcc70, eflags=0) at nodeModifyTable.c:2179
2179        CmdType     operation = node->operation;
(gdb) next
2180        int         nplans = list_length(node->plans);
(gdb) 
2187        bool        update_tuple_routing_needed = node->partColsUpdated;
(gdb) p node->plans
$20 = (List *) 0x2c317c8
(gdb) p *(node->plans)
$21 = {type = T_List, length = 1, head = 0x2ccb058, tail = 0x2ccb058}
(gdb) p *(node->plans->head)
$22 = {data = {ptr_value = 0x2c315b8, int_value = 46339512, oid_value = 46339512}, next = 0x0}
(gdb) next
2195        mtstate = makeNode(ModifyTableState);
(gdb) 
2196        mtstate->ps.plan = (Plan *) node;
(gdb) p *mtstate
$23 = {ps = {type = T_ModifyTableState, plan = 0x0, state = 0x0, ExecProcNode = 0x0, ExecProcNodeReal = 0x0, instrument = 0x0, worker_instrument = 0x0, qual = 0x0, lefttree = 0x0, righttree = 0x0, 
    initPlan = 0x0, subPlan = 0x0, chgParam = 0x0, ps_ResultTupleSlot = 0x0, ps_ExprContext = 0x0, ps_ProjInfo = 0x0, scandesc = 0x0}, operation = CMD_UNKNOWN, canSetTag = false, mt_done = false, 
  mt_plans = 0x0, mt_nplans = 0, mt_whichplan = 0, resultRelInfo = 0x0, rootResultRelInfo = 0x0, mt_arowmarks = 0x0, mt_epqstate = {estate = 0x0, planstate = 0x0, origslot = 0x0, plan = 0x0, 
    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) next
2197        mtstate->ps.state = estate;
(gdb) 
2198        mtstate->ps.ExecProcNode = ExecModifyTable;
(gdb) 
2200        mtstate->operation = operation;
(gdb) 
2201        mtstate->canSetTag = node->canSetTag;
(gdb) 
2202        mtstate->mt_done = false;
(gdb) 
2204        mtstate->mt_plans = (PlanState **) palloc0(sizeof(PlanState *) * nplans);
(gdb) 
2205        mtstate->resultRelInfo = estate->es_result_relations + node->resultRelIndex;
(gdb) 
2208        if (node->rootResultRelIndex >= 0)
(gdb) 
2212        mtstate->mt_arowmarks = (List **) palloc0(sizeof(List *) * nplans);
(gdb) 
2213        mtstate->mt_nplans = nplans;
(gdb) 
2216        EvalPlanQualInit(&mtstate->mt_epqstate, estate, NULL, NIL, node->epqParam);
(gdb) 
2217        mtstate->fireBSTriggers = true;
(gdb) 
2227        saved_resultRelInfo = estate->es_result_relation_info;
(gdb) p *(mtstate->mt_epqstate)
Structure has no component named operator*.
(gdb) p mtstate->mt_epqstate
$24 = {estate = 0x0, planstate = 0x0, origslot = 0x0, plan = 0x0, arowMarks = 0x0, epqParam = 0}
(gdb) next
2229        resultRelInfo = mtstate->resultRelInfo;
(gdb) 
2230        i = 0;
(gdb) 
2231        foreach(l, node->plans)
(gdb) 
2233            subplan = (Plan *) lfirst(l);
(gdb) 
2237                                                                  node->fdwDirectModifyPlans);
(gdb) 
2236            resultRelInfo->ri_usesFdwDirectModify = bms_is_member(i,
(gdb) 
2242            CheckValidResultRel(resultRelInfo, operation);
(gdb) 
2253            if (resultRelInfo->ri_RelationDesc->rd_rel->relhasindex &&
(gdb) 
2255                resultRelInfo->ri_IndexRelationDescs == NULL)
(gdb) 
2254                operation != CMD_DELETE &&
(gdb) 
2257                                node->onConflictAction != ONCONFLICT_NONE);
(gdb) 
2256                ExecOpenIndices(resultRelInfo,
(gdb) 
2264            if (resultRelInfo->ri_TrigDesc &&
(gdb) 
2270            estate->es_result_relation_info = resultRelInfo;
(gdb) 
2271            mtstate->mt_plans[i] = ExecInitNode(subplan, estate, eflags);
(gdb) finish
Run till exit from #0  ExecInitModifyTable (node=0x2ccb078, estate=0x2cbcc70, eflags=0) at nodeModifyTable.c:2294
0x000000000069a21a in ExecInitNode (node=0x2ccb078, estate=0x2cbcc70, eflags=0) at execProcnode.c:174
174             result = (PlanState *) ExecInitModifyTable((ModifyTable *) node,
Value returned is $25 = (ModifyTableState *) 0x2cbcfc0
(gdb) next
176             break;
(gdb) 
373     ExecSetExecProcNode(result, result->ExecProcNode);
(gdb) p result->ExecProcNode
$26 = (ExecProcNodeMtd) 0x6c2485 <ExecModifyTable>
(gdb) finish
Run till exit from #0  ExecInitNode (node=0x2ccb078, estate=0x2cbcc70, eflags=0) at execProcnode.c:392
0x0000000000691c2f in InitPlan (queryDesc=0x2cc1580, eflags=0) at execMain.c:1049
1049        planstate = ExecInitNode(plan, estate, eflags);
Value returned is $27 = (PlanState *) 0x2cbcfc0
(gdb) next
1054        tupType = ExecGetResultType(planstate);
(gdb) 
1060        if (operation == CMD_SELECT)
(gdb) p tupType
$28 = (TupleDesc) 0x2cbdd40
(gdb) p *tupType
$29 = {natts = 0, tdtypeid = 2249, tdtypmod = -1, tdhasoid = false, tdrefcount = -1, constr = 0x0, attrs = 0x2cbdd60}
(gdb) next
1090        queryDesc->tupDesc = tupType;
(gdb) 
1091        queryDesc->planstate = planstate;
(gdb) 
1092    }
(gdb) 
standard_ExecutorStart (queryDesc=0x2cc1580, eflags=0) at execMain.c:266
266     MemoryContextSwitchTo(oldcontext);
(gdb) 
#DONE!

CreateExecutorState

#gdb
(gdb) b CreateExecutorState
Breakpoint 1 at 0x69f2c5: file execUtils.c, line 89.
#psql
testdb=# -- 插入1行
testdb=# insert into t_insert values(19,'ProcessQuery.CreateExecutorState','ProcessQuery.CreateExecutorState','ProcessQuery.CreateExecutorState');
(挂起)
#gdb
(gdb) c
Continuing.

Breakpoint 1, CreateExecutorState () at execUtils.c:89
89      qcontext = AllocSetContextCreate(CurrentMemoryContext,
#查看输入参数
#该函数无输入参数
(gdb) step #进入AllocSetContextCreate函数内部
AllocSetContextCreateExtended (parent=0x2c09de0, name=0xb1a840 "ExecutorState", minContextSize=0, initBlockSize=8192, maxBlockSize=8388608) at aset.c:426
426     if (minContextSize == ALLOCSET_DEFAULT_MINSIZE &&
(gdb) next
428         freeListIndex = 0;
#查看AllocSetContextCreate的输入参数
#1、parent
(gdb) p *parent
$3 = {type = T_AllocSetContext, isReset = false, allowInCritSection = false, methods = 0xb8c720 <AllocSetMethods>, parent = 0x2c04ba0, firstchild = 0x0, prevchild = 0x2c7fc60, nextchild = 0x2cb6b30, 
  name = 0xb4e87c "MessageContext", ident = 0x0, reset_cbs = 0x0}
#顶层Context
(gdb) p *(parent->parent)
$4 = {type = T_AllocSetContext, isReset = false, allowInCritSection = false, methods = 0xb8c720 <AllocSetMethods>, parent = 0x0, firstchild = 0x2c2d7e0, prevchild = 0x0, nextchild = 0x0, 
  name = 0xb8d050 "TopMemoryContext", ident = 0x0, reset_cbs = 0x0}
#2、name
(gdb) p name
$5 = 0xb1a840 "ExecutorState"
#3、minContextSize
(gdb) p minContextSize
$6 = 0
#4、initBlockSize
(gdb) p initBlockSize
$7 = 8192 #8KB
#5、maxBlockSize
(gdb) p maxBlockSize
$8 = 8388608 #8MB
(gdb) next
440         AllocSetFreeList *freelist = &context_freelists[freeListIndex];
(gdb) p freeListIndex 
$9 = 0
(gdb) 
$10 = 0
(gdb) next
442         if (freelist->first_free != NULL)
(gdb) p *freelist
$11 = {num_free = 4, first_free = 0x2cbcb60}
(gdb) p *(freelist->first_free)
$12 = {header = {type = T_AllocSetContext, isReset = true, allowInCritSection = false, methods = 0xb8c720 <AllocSetMethods>, parent = 0x0, firstchild = 0x0, prevchild = 0x0, nextchild = 0x2cbeb70, 
    name = 0xb1a840 "ExecutorState", ident = 0x0, reset_cbs = 0x0}, blocks = 0x2cbcc38, freelist = {0x0 <repeats 11 times>}, initBlockSize = 8192, maxBlockSize = 8388608, nextBlockSize = 8192, 
  allocChunkLimit = 8192, keeper = 0x2cbcc38, freeListIndex = 0}
(gdb) next
445             set = freelist->first_free;
(gdb) 
446             freelist->first_free = (AllocSet) set->header.nextchild;
(gdb) 
447             freelist->num_free--;
(gdb) 
450             set->maxBlockSize = maxBlockSize;
(gdb) 
453             MemoryContextCreate((MemoryContext) set,
(gdb) 
459             return (MemoryContext) set;
(gdb) p *set
$13 = {header = {type = T_AllocSetContext, isReset = true, allowInCritSection = false, methods = 0xb8c720 <AllocSetMethods>, parent = 0x2c09de0, firstchild = 0x0, prevchild = 0x0, nextchild = 0x0, 
    name = 0xb1a840 "ExecutorState", ident = 0x0, reset_cbs = 0x0}, blocks = 0x2cbcc38, freelist = {0x0 <repeats 11 times>}, initBlockSize = 8192, maxBlockSize = 8388608, nextBlockSize = 8192, 
  allocChunkLimit = 8192, keeper = 0x2cbcc38, freeListIndex = 0}
(gdb) next
548 }
(gdb) 
CreateExecutorState () at execUtils.c:97
97      oldcontext = MemoryContextSwitchTo(qcontext);
(gdb) 
99      estate = makeNode(EState);
(gdb) 
104     estate->es_direction = ForwardScanDirection;
(gdb) finish
Run till exit from #0  CreateExecutorState () at execUtils.c:104
0x000000000078cc2f in evaluate_expr (expr=0x2c30520, result_type=1043, result_typmod=44, result_collation=100) at clauses.c:4858
4858        estate = CreateExecutorState();
Value returned is $14 = (EState *) 0x2cbcc70

四、小结

1、TODO:更进一步的理解,在执行查询语句时再进一步解读;
2、EState&PlanState数据结构:在此函数中构造,需进一步理解;
3、List数据结构:PG广泛的使用List这样的数据结构对各种信息进行管理。

您可能感兴趣的文档:

--结束END--

本文标题: PostgreSQL 源码解读(10)- 插入数据#9(ProcessQuery)

本文链接: https://lsjlt.com/news/49712.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作