转载:数据库查询过程是怎么实现的?

来源:互联网 发布:gg大玩家怎么修改数据 编辑:程序博客网 时间:2024/05/16 17:11

转载来自:http://www.newsmth.net/nForum/#!article/Database/122316

例如一条查询语句 
select person.id from department; 
数据库底层是如何实现的呢


**************************************************************************************** 
***  位于tcop目录下的函数  *** 
**************************************************************************************** 
  
exec_simple_query (tcop/postgres.c) 
  |->pgstat_report_activity (postmaster/pgstat.c) 
  |->start_xact_command (*) 
  |->drop_unnamed_stmt (*) 
  |->MemoryContextSwitchTo (utils/palloc.h) (内存上下文切换到MessageContext) 
  |->pg_parse_query (*) (对查询串做basic parse,获得raw parse tree) 
  |->(根据log_statement配置往日志中输出语句) 
  |->MemoryContextSwitchTo (utils/palloc.h) (切换到以前的内存上下文) 
  |->foreach(parsetree_item, parsetree_list) (处理每个parse tree) 
  |  |->CreateCommandTag (tcop/utility.c) (创建命令tag) 
  |  |->set_ps_display (utils/misc/pg_status.c) (在ps中显示命令tag) 
  |  |->BeginCommand (tcop/dest.c) 
  |  |->(检查事务状态,如果是aborted则除了ABORT/COMMIT,其他语句都报错) 
  |  |->start_xact_command (*) 
  |  |->CHECK_FOR_INTERRUPTS 
  |  |->if (analyze_requires_snapshot(parsetree)) (parser/analyze.c) (parse analyze是否需要快照) 
  |  |  |->PushActiveSnapshot(GetTransactionSnapshot()) (utils/time/snapmgr.c) (获取并设置快照) 
  |  |->(OK to analyze,rewrite and plan this query) 
  |  |->MemoryContextSwitchTo (切换到MessageContext内存上下文)\ 
  |  |->pg_analyze_and_rewrite (*) (analyze and rewrite parsetree,获得querytree_list) 
  |  |->pg_plan_queries (*) (plan querytree_list,获得plantree_list) 
  |  |->PopActiveSnapshot (utils/time/snapmgr.c) 
  |  |->CHECK_FOR_INTERRUPTS 
  |  |->CreatePortal (utils/mmgr/portalmem.c) (创建匿名portal,用于运行查询,设为invisible,这样就不会在pg_cursors中显示) 
  |  |->PortalDefineQuery (utils/mmgr/portalmem.c) (设置portal中的各项) 
  |  |->PortalStart (tcop/pquery.c) (准备portal运行) 
  |  |->MemoryContextSwitchTo (切换到以前的内存上下文) 
  |  |->PortalRun (tcop/pquery.c) (运行portal中的查询) 
  |  |->PortalDrop (utils/mmgr/portalmem.c) 
  |  |->EndCommand (tcop/dest.c) 
  | 
  |->finish_xact_command (*) 
  |->(根据log_duration配置往日志输出语句执行信息) 
   
   
exec_parse_message (tcop/postgres.c) 
  |->pgstat_report_activity (postmaster/pgstat.c) 
  |->set_ps_display (utils/misc/pg_status.c) 
  |->start_xact_command (*) 
  |->(检查是否是命名语句) 
  |  |*->(is_named 命名语句) 
  |  |   |->MemoryContextSwitchTo (切换到MessageContext内存上下文) 
  |  |*->(not is_named 匿名语句) 
  |      |->drop_unnamed_stmt (*) 
  |      |->AllocSetContextCreate (utils/mmgr/aset.c) (创建匿名语句内存上下文) 
  |      |->MemoryContextSwitchTo (切换到匿名语句内存上下文) 
  |->pg_parse_query (*) (parse query_string,获得parsetree_list) 
  |->(检查是否包含多条语句,如果多条就报错) 
  |->if (parsetree_list != NIL) 
  |  |->CreateCommandTag (tcop/utility.c) 
  |  |->(检查事务状态,如果是aborted则除了ABORT/COMMIT,其他语句都报错) 
  |  |->CreateCachedPlan (utils/cache/plancache.c) (创建并初始化CachedPlanSource) 
  |  |->(检查analyze是否需要快照,如果需要则获得并设置当前快照) 
  |  |->parse_analyze_varparams (parser/analyze.c) (analyze parsetree,获得Query) 
  |  |->(检查参数类型是否已确定) 
  |  |->pg_rewrite_query (*) (rewrite query,获得querytree_list) 
  |  |->PopActiveSnapshot (utils/time/snapmgr.c) 
  |->CompleteCachedPlan (最后设置CachedPlanSource) 
  |->CHECK_FOR_INTERRUPTS 
  |->(检查是否是命名语句) 
  |  |*->(is_named 命名语句) 
  |  |   |->StorePreparedStatement (commands/prepare.c) (保存为prepared语句) 
  |  |*->(not is_named 匿名语句) 
  |      |->SaveCachedPlan (utils/cache/plancache.c) 
  |->MemoryContextSwitchTo (切换到以前的内存上下文) 
  |->(根据log_duration配置往日志输出语句执行信息) 
  
  
exec_bind_message (tcop/postgres.c) 
  |->(从客户端获得portal_name和stmt_name) 
  |->(如果是命名语句则从中获得CachedPlanSource,否则直接从unnamed_stmt_psrc获得CachedPlanSource) 
  |->pgstat_report_activity (postmaster/pgstat.c) 
  |->set_ps_display (utils/misc/pg_status.c) 
  |->start_xact_command (*) 
  |->MemoryContextSwitchTo (切换到MessageContext内存上下文) 
  |->(从客户端获得参数格式和参数个数) 
  |->CreatePortal (utils/mmgr/portalmem.c) 
  |->MemoryContextSwitchTo (切换到portal使用的内存上下文) 
  |->(如果需要则设置快照) 
  |->(从客户端获得参数值,然后调用相应类型的input/receive函数) 
  |->MemoryContextSwitchTo (切换到以前的内存上下文) 
  |->(从客户端获得result format代码) 
  |->GetCachedPlan (utils/cache/plancache.c) (从CachedPlanSource获得CachedPlan) 
  |->PortalDefineQuery (utils/mmgr/portalmem.c) 
  |->PopActiveSnapshot (utils/time/snapmgr.c) 
  |->PortalStart (tcop/pquery.c) 
  |->PortalSetResultFormat (tcop/pquery.c) 
  |->(根据log_duration配置往日志输出语句执行信息) 
  
  
exec_execute_message (tcop/postgres.c) 
  |->GetPortalByName (utils/mmgr/portalmem.c) 
  |->pgstat_report_activity (postmaster/pgstat.c) 
  |->set_ps_display (utils/misc/pg_status.c) 
  |->BeginCommand (tcop/dest.c) 
  |->start_xact_command (*) 
  |->(根据log_statement配置往日志中输出信息) 
  |->(检查事务状态) 
  |->CHECK_FOR_INTERRUPTS 
  |->PortalRun (tcop/pquery.c) 
  |->(根据log_duration配置往日志输出语句执行信息) 
   
   
  
exec_describe_statement_message (tcop/postgres.c) 
  |-> 
   
   
exec_describe_portal_message (tcop/postgres.c) 
  |-> 
  
  
pg_parse_query (tcop/postgres.c) (对查询串做raw parse,返回parsetree_list) 
  |->raw_parser (parser/parser.c) 
  
  
pg_analyze_and_rewrite (tcop/postgres.c) (对parsetree analyze并且rewrite,获得querytree_list) 
  |->parse_analyze (parser/analyze.c) 
  |->pg_rewrite_query (*) 
  
  
pg_rewrite_query (tcop/postgres.c) 
  |->(检查命令类型) 
    |*->(CMD_UTILITY) 
    |   |->list_make1 (nodes/pg_list.h) (对于utility命令,不rewrite,直接返回) 
    |*->(其他) 
        |->QueryRewrite (rewrite/rewriteHandler.c) 
  
  
pg_plan_queries (tcop/postgres.c) 
  |->(对querytree_list中的每个querytree做处理) 
     |->pg_plan_query (*) (如果是utility命令,则直接从Query中拷贝utilityStmt,否则调用pg_plan_query,其返回PlannedStmt) 
        |->planner (optimizer/plan/planner.c) 
  
  
PortalStart (tcop/pquery.c) 
  |->ChoosePortalStrategy (*) 
  |->(根据PortalStrategy做分别处理) 
     |*->(PORTAL_ONE_SELECT) 
     |   |->PushActiveSnapshot (utils/time/snapmgr.c) 
     |   |->CreateQueryDesc (*) (创建并初始化QueryDesc) 
     |   |->ExecutorStart (executor/execMain.c) 
     |   |->PopActiveSnapshot (utils/time/snapmgr.c) 
     |*->(PORTAL_ONE_RETURNING) 
     |*->(PORTAL_ONE_MOD_WITH) 
     |   |->(设置portal的tupDesc,以及其他项) 
     |*->(PORTAL_UTIL_SELECT) 
     |   |->(设置portal的tupDesc,以及其他项) 
     |*->(PORTAL_MULTI_QUERY) 
        |->(NULL) 
  
   
PortalRun (tcop/pquery.c) 
  |->(根据PortalStrategy做分别处理) 
     |*->(PORTAL_ONE_SELECT) 
     |*->(PORTAL_ONE_RETURNING) 
     |*->(PORTAL_ONE_MOD_WITH) 
     |*->(PORTAL_UTIL_SELECT) 
     |   |->FillPortalStore (*) (如果不是PORTAL_ONE_SELECT,并且portal的holdStore没有初始化,则调用该函数去填充holdStore) 
     |   |->PortalRunSelect (*) 
     |*->(PORTAL_MULTI_QUERY) 
         |->PortalRunMulti (*) 
         |->MarkPortalDone (utils/mmgr/portalmem.c) 
  
  
  
PortalRunSelect (tcop/pquery.c) 
  |->(检查方向) 
    |*->(forward 向前读取) 
    |   |->(检查holdStore) 
    |   |  |*->(hodlStore!=NULL) 
    |   |  |   |->RunFromStore (*) (直接从holdStore中读取) 
    |   |  |*->(holdStore==NULL) 
    |   |      |->PushActiveSnapshot (utils/time/snapmgr.c) 
    |   |      |->ExecutorRun (executor/execMain.c) 
    |   |      |->PopActiveSnapshot (utils/time/snapmgr.c) 
    |   |->(设置portal中位置相关的项) 
    |*->(not forward 向后读取) 
    |   |->(检查holdStore) 
    |   |  |*->(hodlStore!=NULL) 
    |   |  |   |->RunFromStore (*) (直接从holdStore中读取) 
    |   |  |*->(holdStore==NULL) 
    |   |      |->PushActiveSnapshot (utils/time/snapmgr.c) 
    |   |      |->ExecutorRun (executor/execMain.c) 
    |   |      |->PopActiveSnapshot (utils/time/snapmgr.c) 
    |   |->(设置portal中位置相关的项) 
     
  
FillPortalStore (tcop/pquery.c) 
  |->PortalCreateHoldStore (utils/mmgr/portalmem.c) 
  |->CreateDestReceiver (tcop/dest.c) 
  |->SetTuplestoreDestReceiverParams (executor/tstoreReceiver.c) 
  |->(根据PortalStrategy做分别处理) 
    |*->(PORTAL_ONE_RETURNING) 
    |*->(PORTAL_ONE_MOD_WITH) 
    |   |->PortalRunMulti (*) 
    |*->(PORTAL_UTIL_SELECT) 
        |->PortalRunUtility (*) 
   
   
PortalRunMulti (tcop/pquery.c) 
  |->(对portal中的每个计划语句做处理) 
  |->(检查计划语句类型) 
  |  |*->(PlannedStmt) 
  |  |   |->ProcessQuery (*) 
  |  |*->(utility语句) 
  |      |->PortalRunUtility (*) 
   
   
  
PortalRunUtility (tcop/pquery.c) 
  |->(根据utility语句类型设置快照) 
  |->ProcessUtility (*) 
   
   
RunFromStore (tcop/pquery.c) 
  |->MakeSingleTupleTableSlot (executor/execTuples.c) 
  |->(调用dest的rStartup函数) 
  |->for(;;) 
  |  |->tuplestore_gettupleslot (utils/sort/tuplestore.c) 
  |  |->(调用dest的receiveSlot函数) 
  |  |->ExecClearTuple (executor/execTuples.c) 
  |->(调用dest的rShutdown函数) 
  |->ExecDropSingleTupleTableSlot (executor/execTuples.c) 
  
   
ProcessQuery (tcop/pquery.c) 
  |->CreateQueryDesc (*) 
  |->ExecutorStart (executor/execMain.c) 
  |->ExecutorRun (executor/execMain.c) 
  |->ExecutorFinish (xecutor/execMain.c) 
  |->ExecutorEnd (xecutor/execMain.c) 
  |->FreeQueryDesc (*) 
   
   
ProcessUtility (tcop/utility.c) 
  |->if (ProcessUtility_hook) (如果设置了hook,则调用它) 
     |*->(*ProcessUtility_hook)  
     |*->standard_ProcessUtility (*) 
standard_ProcessUtility (tcop/utility.c) 
  |->check_xact_readonly (*) (检查是否在只读事务中执行的是会修改数据库的命令) 
  |->switch (nodeTag(parsetree)) 
    |*->(T_TransactionStmt) 
    |   |->switch (stmt->kind) 
    |     |*->(TRANS_STMT_BEGIN) 
    |     |*->(TRANS_STMT_START) 
    |     |   |->BeginTransactionBlock (access/transam/xact.c) 
    |     |   |->(处理每个事务选项:transaction_isolation/transaction_read_only/transaction_deferrable) 
    |     |*->(TRANS_STMT_COMMIT) 
    |     |   |->EndTransactionBlock (access/transam/xact.c) 
    |     |*->(TRANS_STMT_PREPARE) 
    |     |   |->PreventCommandDuringRecovery (*)  
    |     |   |->PrepareTransactionBlock (access/transam/xact.c) 
    |     |*->(TRANS_STMT_COMMIT_PREPARED) 
    |     |   |->PreventTransactionChain (access/transam/xact.c) 
    |     |   |->PreventCommandDuringRecovery (*) 
    |     |   |->FinishPreparedTransaction (access/transam/twophase.c) 
    |     |*->(TRANS_STMT_ROLLBACK_PREPARED) 
    |     |   |->PreventTransactionChain (access/transam/xact.c) 
    |     |   |->PreventCommandDuringRecovery (*) 
    |     |   |->FinishPreparedTransaction (access/transam/twophase.c) 
    |     |*->(TRANS_STMT_ROLLBACK) 
    |     |   |->UserAbortTransactionBlock (access/transam/xact.c) 
    |     |*->(TRANS_STMT_SAVEPOINT) 
    |     |   |->RequireTransactionChain (access/transam/xact.c) 
    |     |   |->(获得savepoint_name) 
    |     |   |->DefineSavepoint (access/transam/xact.c) 
    |     |*->(TRANS_STMT_RELEASE) 
    |     |   |->RequireTransactionChain (access/transam/xact.c) 
    |     |   |->ReleaseSavepoint (access/transam/xact.c) 
    |     |*->(TRANS_STMT_ROLLBACK_TO) 
    |         |->RequireTransactionChain (access/transam/xact.c) 
    |         |->RollbackToSavepoint (access/transam/xact.c) 
    |*->(T_PlannedStmt) 
    |   |->PerformCursorOpen (commands/portalcmds.c) 
    |*->(T_ClosePortalStmt) 
    |   |->PerformPortalClose (commands/portalcmds.c) 
    |*->(T_FetchStmt) 
    |   |->PerformPortalFetch (commands/portalcmds.c) 
    |*->(T_DoStmt) 
    |   |->ExecuteDoStmt (commands/functioncmds.c) 
    |*->(T_CreateTableSpaceStmt) 
    |   |->PreventTransactionChain (access/transam/xact.c) 
    |   |->CreateTableSpace (commands/tablespace.c) 
    |*->(T_DropTableSpaceStmt) 
    |   |->PreventTransactionChain (access/transam/xact.c) 
    |   |->DropTableSpace (commands/tablespace.c) 
    |*->(T_AlterTableSpaceOptionsStmt) 
    |   |->AlterTableSpaceOptions (commands/tablespace.c) 
    |*->(T_TruncateStmt) 
    |   |->ExecuteTruncate (commands/tablecmds.c) 
    |*->(T_CommentStmt) 
    |   |->CommentObject (commands/comment.c) 
    |*->(T_SecLabelStmt) 
    |   |->ExecSecLabelStmt (commands/seclable.c) 
    |*->(T_CopyStmt) 
    |   |->DoCopy (commands/copy.c) 
    |*->(T_PrepareStmt) 
    |   |->CheckRestrictedOperation (*) 
    |   |->PrepareQuery (commands/prepare.c) 
    |*->(T_ExecuteStmt) 
    |   |->ExecuteQuery (commands/prepare.c) 
    |*->(T_DeallocateStmt) 
    |   |->CheckRestrictedOperation (*) 
    |   |->DeallocateQuery (commands/prepare.c) 
    |*->(T_GrantStmt) 
    |   |->ExecuteGrantStmt (catalog/aclchk.c) 
    |*->(T_GrantRoleStmt) 
    |   |->GrantRole (commands/user.c) 
    |*->(T_CreatedbStmt) 
    |   |->PreventTransactionChain (access/transam/xact.c) 
    |   |->createdb (commands/dbcommands.c) 
    |*->(T_AlterDatabaseStmt) 
    |   |->AlterDatabase (commands/dbcommands.c) 
    |*->(T_AlterDatabaseSetStmt) 
    |   |->AlterDatabaseSet (commands/dbcommands.c) 
    |*->(T_DropdbStmt) 
    |   |->PreventTransactionChain (access/transam/xact.c) 
    |   |->dropdb (commands/dbcommands.c) 
    |*->(T_NotifyStmt) 
    |   |->PreventCommandDuringRecovery (*) 
    |   |->Async_Notify (commands/async.c) 
    |*->(T_ListenStmt) 
    |   |->PreventCommandDuringRecovery (*) 
    |   |->CheckRestrictedOperation (*) 
    |   |->Async_Listen (commands/async.c) 
    |*->(T_UnlistenStmt) 
    |   |->PreventCommandDuringRecovery (*) 
    |   |->CheckRestrictedOperation (*) 
    |   |->if (stmt->conditionname) 
    |      |*->Async_Unlisten (commands/async.c) 
    |      |*->Async_UnlistenAll (commands/async.c) 
    |*->(T_LoadStmt) 
    |   |->closeAllVfds (storage/file/fd.c) 
    |   |->load_file (utils/fmgr/dfmgr.c) 
    |*->(T_ClusterStmt) 
    |   |->PreventCommandDuringRecovery (*) 
    |   |->cluster (commands/cluster.c) 
    |*->(T_VacuumStmt) 
    |   |->PreventCommandDuringRecovery (*) 
    |   |->vacuum (commands/vacuum.c) 
    |*->(T_ExplainStmt) 
    |   |->ExplainQuery (commands/explain.c) 
    |*->(T_VariableSetStmt) 
    |   |->ExecSetVariableStmt (utils/misc/guc.c) 
    |*->(T_VariableShowStmt) 
    |   |->GetPGVariable (utils/misc/guc.c) 
    |*->(T_DiscardStmt) 
    |   |->CheckRestrictedOperation (*) 
    |   |->DiscardCommand (commands/discard.c) 
    |*->(T_CreateEventTrigStmt) 
    |   |->CreateEventTrigger (commands/event_trigger.c) 
    |*->(T_AlterEventTrigStmt) 
    |   |->AlterEventTrigger (commands/event_trigger.c) 
    |*->(T_CreateRoleStmt) 
    |   |->CreateRole (commands/user.c) 
    |*->(T_AlterRoleStmt) 
    |   |->AlterRole (commands/user.c) 
    |*->(T_AlterRoleSetStmt) 
    |   |->AlterRoleSet (commands/user.c) 
    |*->(T_DropRoleStmt) 
    |   |->DropRole (commands/user.c) 
    |*->(T_ReassignOwnedStmt) 
    |   |->ReassignOwnedObjects (commands/user.c) 
    |*->(T_LockStmt) 
    |   |->RequireTransactionChain (access/transam/xact.c) 
    |   |->LockTableCommand (commands/lockcmds.c) 
    |*->(T_ConstraintsSetStmt) 
    |   |->AfterTriggerSetState (commands/trigger.c) 
    |*->(T_CheckPointStmt) 
    |   |->(检查是否是超级用户) 
    |   |->RequestCheckpoint (postmaster/checkpointer.c) 
    |*->(T_ReindexStmt) 
    |   |->PreventCommandDuringRecovery (*) 
    |   |->switch (stmt->kind) 
    |      |*->(OBJECT_INDEX) 
    |      |   |->ReindexIndex (commands/indexcmds.c) 
    |      |*->(OBJECT_TABLE) 
    |      |*->(OBJECT_MATVIEW) 
    |      |   |->ReindexTable (commands/indexcmds.c) 
    |      |*->(OBJECT_DATABASE) 
    |          |->PreventTransactionChain (access/transam/xact.c) 
    |          |->ReindexDatabase (commands/indexcmds.c) 
    |*->(T_DropStmt) 
    |   |->if (EventTriggerSupportsObjectType(stmt->removeType)) (commands/event_trigger.c) 
    |      |*->ProcessUtilitySlow (*) 
    |      |*->ExecDropStmt (*) 
    |*->(T_RenameStmt) 
    |   |->if (EventTriggerSupportsObjectType(stmt->removeType)) (commands/event_trigger.c) 
    |      |*->ProcessUtilitySlow (*) 
    |      |*->ExecRenameStmt (commands/alter.c) 
    |*->(T_AlterObjectSchemaStmt) 
    |   |->if (EventTriggerSupportsObjectType(stmt->removeType)) (commands/event_trigger.c) 
    |      |*->ProcessUtilitySlow (*) 
    |      |*->ExecAlterObjectSchemaStmt (commands/alter.c) 
    |*->(T_AlterOwnerStmt) 
    |   |->if (EventTriggerSupportsObjectType(stmt->removeType)) (commands/event_trigger.c) 
    |      |*->ProcessUtilitySlow (*) 
    |      |*->ExecAlterOwnerStmt (commands/alter.c) 
    |*->(default) 
    |   |->ProcessUtilitySlow (*) (该函数用于处理支持event trigger的语句) 
  
ProcessUtilitySlow (tcop/utility.c) 
  |-> 
  
************************************************************************************************* 
***  位于parser/rewrite/optimizer/executor目录下的函数  *** 
************************************************************************************************* 
  
************** 
**  parser  ** 
************** 
  
raw_parser (parser/parser.c) (返回parsetree list(也就是各种语句列表)) 
  |->scanner_init (parser/scan.c) 
  |->parser_init (parser/gram.c) 
  |->base_yyparse (parser/gram.c) 
  |->scanner_finish (parser/scan.c) 
  
  
parse_analyze (parser/analyze.c) (analyze一个parsetree,返回一个Query) 
  |->make_parsestate (parser/parse_node.c) 
  |->if (numParams > 0) 
  |  |*->parse_fixed_parameters (parser/parse_param.c) 
  |->transformTopLevelStmt (*) 
  |->if (post_parse_analyze_hook) 
  |  |*->(*post_parse_analyze_hook)(...)  
  |->free_parsestate (parser/parse_node.c) 
  
transformTopLevelStmt (parser/analyze.c) 
  |->(把select into语句变成create table as语句) 
  |->transformStmt (*) 
  
transformStmt (parser/analyze.c) 
  |->switch (nodeTag(parseTree)) 
  |  |*->(T_InsertStmt) 
  |  |   |->transformInsertStmt (*) 
  |  |*->(T_DeleteStmt) 
  |  |   |->transformDeleteStmt (*) 
  |  |*->(T_UpdateStmt) 
  |  |   |->transformUpdateStmt (*) 
  |  |*->(T_SelectStmt) 
  |  |   |->(根据不同类型的语句做分别处理) 
  |  |      |*->transformValuesClause (*) (VALUES列表) 
  |  |      |*->transformSelectStmt (*) (普通的SELECT语句) 
  |  |      |*->transformSetOperationStmt (*) (有集合操作的SELECT语句) 
  |  |*->(T_DeclareCursorStmt) 
  |  |   |->transformDeclareCursorStmt (*) 
  |  |*->(T_ExplainStmt) 
  |  |   |->transformExplainStmt (*) 
  |  |*->(T_CreateTableAsStmt) 
  |  |   |->transformCreateTableAsStmt (*) 
  |  |*->(default) 
  |      |->(其他类型的语句不需要transform) 
  |      |->result = makeNode(Query) 
  |      |->result->commandType = CMD_UTILITY 
  |      |->result->utilityStmt = (Node *) parseTree 
  |->(设置Query中的其他项) 
  
*** 具体语句的transform *** 
  
transformInsertStmt (parser/analyze.c) 
  |->if (stmt->withClause) 
  |  |*->transformWithClause (parser/parse_cte.c) 
  |->setTargetTable (parser/parse_clause.c) 
  |->checkInsertTargets (parser/parse_target.c) (检查插入列) 
  |->(根据INSERT语句类型做分别处理) 
  | |*->(selectStmt == NULL : DEFAULT VALUES) 
  | |   |->(把targetlist设为空) 
  | |*->(isGeneralSelect : 普通的SELECT语句) 
  | |   |->make_parsestate (parser/parse_node.c) 
  | |   |->transformStmt (*) 
  | |   |->free_parsestate (parser/parse_node.c) 
  | |   |->addRangeTableEntryForSubquery (parser/parse_relation.c) 
  | |   |->(创建RangeTblRef,并把它添加到ParseState中的p_joinlist) 
  | |   |->(从SELECT的targetList创建exprList) 
  | |   |->transformInsertRow (*) 
  | |*->(list_length(selectStmt->valuesLists) > 1 : VALUES中有多个列表) 
  | |   |->foreach(lc, selectStmt->valuesLists) (处理VALUES中的每个list,生成exprLists) 
  | |   |  |->transformExpressionList (parser/parse_target.c) 
  | |   |  |->(检查每个列表的长度是否相等) 
  | |   |  |->transformInsertRow (*) 
  | |   |  |->assign_list_collations (parser/parse_collate.c) 
  | |   |->addRangeTableEntryForValues (parser/parse_relation.c) 
  | |   |->(创建RangeTblRef,并把它添加到ParseState中的p_joinlist) 
  | |   |->expandRTE (parser/parse_relation.c) (生成引用RTE的Var列表) 
  | |*->(VALUES中只有一个列表,也就是插入一行) 
  |     |->transformExpressionList (parser/parse_target.c) 
  |     |->transformInsertRow (*) 
  |->(从前面生成的exprLists生成targetList) 
  |->if (stmt->returningList) (如果有RETURNING子句) 
  |  |->addRTEtoQuery (parser/parse_relation.c) 
  |  |->transformReturningList (*) 
  |->(设置Query的range table) 
  |->makeFromExpr (nodes/makefuncs.c) (设置Query的join tree) 
  |->assign_query_collations (parser/parse_collate.c) (设置Query中所有表达式的collate信息) 
  
transformDeleteStmt (parser/analyze.c) 
  |->if (stmt->withClause) 
  |  |*->transformWithClause (parser/parse_cte.c) 
  |->setTargetTable (parser/parse_clause.c) 
  |->transformFromClause (parser/parse_clause.c) (transform USING子句,该子句和FROM类似) 
  |->transformWhereClause (parser/parse_clause.c) 
  |->transformReturningList (*) 
  |->(设置Query的range table) 
  |->makeFromExpr (nodes/makefuncs.c) (设置Query的join tree) 
  |->(设置Query的其他项) 
  |->if (pstate->p_hasAggs) 
  |  |->parseCheckAggregates (parser/parse_agg.c) 
  |->assign_query_collations (parser/parse_collate.c) 
  
transformUpdateStmt (parser/analyze.c) 
  |->if (stmt->withClause) 
  |  |*->transformWithClause (parser/parse_cte.c) 
  |->setTargetTable (parser/parse_clause.c) 
  |->transformFromClause (parser/parse_clause.c) 
  |->transformTargetList (parser/parse_target.c) 
  |->transformWhereClause (parser/parse_clause.c) 
  |->transformReturningList (*) 
  |->(设置Query的range table) 
  |->makeFromExpr (nodes/makefuncs.c) (设置Query的join tree) 
  |->(从stmt->targetList更新上面获得的targetList中的所有TargetEntry) 
  |->assign_query_collations (parser/parse_collate.c) 
  
transformValuesClause (parser/analyze.c) 
  |->if (stmt->withClause) 
  |  |*->transformWithClause (parser/parse_cte.c) 
  |->foreach(lc, stmt->valuesLists) (处理每一行) 
  |  |->transformExpressionList (parser/parse_target.c) 
  |  |->(检查每个VALUES列表是否相同大小) 
  |  |->(把VALUES从行结构变成列结构) 
  |->(对VALUES中的每一列列表做处理) 
  |  |->select_common_type (parser/parse_coerce.c) (获得列的common类型) 
  |  |->(把列列表中的所有列coerce_to_common_type) (parser/parse_coerce.c) 
  |  |->select_common_collation (parser/parse_collate.c) (获得common collation) 
  |->(把VALUES从列结构变成行结构) 
  |->addRangeTableEntryForValues (parser/parse_relation.c) 
  |->addRTEtoQuery (parser/parse_relation.c) 
  |->expandRelAttrs (parser/parse_relation.c) (生成targetList) 
  |->transformSortClause (parser/parse_clause.c) (处理ORDER BY子句) 
  |->transformLimitClause (parser/parse_clause.c) (处理OFFSET子句) 
  |->transformLimitClause (parser/parse_clause.c) (处理LIMIT子句) 
  |->(设置Query的range table) 
  |->makeFromExpr (nodes/makefuncs.c) (设置Query的join tree) 
  |->assign_query_collations (parser/parse_collate.c) 
  
transformSelectStmt (parser/analyze.c) 
  |->if (stmt->withClause) 
  |  |*->transformWithClause (parser/parse_cte.c) 
  |->transformFromClause (parser/parse_clause.c) (处理FROM子句) 
  |->transformTargetList (parser/parse_target.c) 
  |->markTargetListOrigins (parser/parse_target.c) 
  |->transformWhereClause (parser/parse_clause.c) (处理WHERE子句) 
  |->transformWhereClause (parser/parse_clause.c) (处理HAVING子句) 
  |->transformSortClause (parser/parse_clause.c) (处理ORDER BY子句。因为GROUP BY/DISTINCT需要ORDER BY的结果,所以先处理ORDER BY) 
  |->transformGroupClause (parser/parse_clause.c) (处理GROUP BY子句) 
  |->(处理DISTINCT子句) 
  |  |*->(没有DISTINCT子句) 
  |  |   |->(设置相关的项为空) 
  |  |*->(DISTINCT子句) 
  |  |   |->transformDistinctClause (parser/parse_clause.c) 
  |  |*->(DISTINCT ON子句) 
  |      |->transformDistinctOnClause (parser/parse_clause.c) 
  |->transformLimitClause (parser/parse_clause.c) (处理OFFSET子句) 
  |->transformLimitClause (parser/parse_clause.c) (处理LIMIT子句) 
  |->transformWindowDefinitions (parser/parse_clause.c) 
  | 
  |->(设置Query的range table) 
  |->makeFromExpr (nodes/makefuncs.c) (设置Query的join tree) 
  |->(设置Query的其他项) 
  |->if (pstate->p_hasAggs || qry->groupClause || qry->havingQual) 
  |  |->parseCheckAggregates (parser/parse_agg.c) 
  |->foreach(l, stmt->lockingClause) 
  |  |->transformLockingClause (*) (处理FOR UPDATE/SHARE子句) 
  |->assign_query_collations (parser/parse_collate.c) 
  
  
transformSetOperationStmt (parser/analyze.c) 
  |->if (stmt->withClause) 
  |  |*->transformWithClause (parser/parse_cte.c) 
  |->transformSetOperationTree (*) 
  |->(找到最左边的SELECT对应的RangeTblRef) 
  |->(生成targetList) 
  |->addRangeTableEntryForJoin (parser/parse_relation.c) 
  |->addRTEtoQuery (parser/parse_relation.c) 
  |->transformSortClause (parser/parse_clause.c) 
  |->transformLimitClause (parser/parse_clause.c) (处理OFFSET子句) 
  |->transformLimitClause (parser/parse_clause.c) (处理LIMIT子句) 
  | 
  |->(设置Query的range table) 
  |->makeFromExpr (nodes/makefuncs.c) (设置Query的join tree) 
  |->(设置Query的其他项) 
  |->if (pstate->p_hasAggs || qry->groupClause || qry->havingQual) 
  |  |->parseCheckAggregates (parser/parse_agg.c) 
  |->foreach(l, stmt->lockingClause) 
  |  |->transformLockingClause (*) (处理FOR UPDATE/SHARE子句) 
  |->assign_query_collations (parser/parse_collate.c) 
  
  
transformDeclareCursorStmt (parser/analyze.c) 
  |->transformStmt (*) (transform DECLARE语句中的SELECT语句) 
  |->(检查各种无效的情况) 
  |->stmt->query = NULL; (不再需要DeclareCursorStmt中的SELECT语句) 
  |->result->utilityStmt = (Node *) stmt; (设置Query中的utilityStmt为本DeclareCursorStmt) 
  
transformExplainStmt (parser/analyze.c) 
  |->transformTopLevelStmt (*) 
  | 
  |->result = makeNode(Query); 
  |->result->commandType = CMD_UTILITY; 
  |->result->utilityStmt = (Node *) stmt; 
  
  
transformCreateTableAsStmt (parser/analyze.c) (处理CREATE TABLE AS, SELECT ... INTO, CREATE MATERIALIZED VIEW) 
  |->transformStmt (*) 
  |->if (stmt->relkind == OBJECT_MATVIEW) 
  |   |->(检查各种无效的情况) 
  |   |->stmt->into->viewQuery = copyObject(query); (把query保存到IntoClause中) 
  | 
  |->result = makeNode(Query); 
  |->result->commandType = CMD_UTILITY; 
  |->result->utilityStmt = (Node *) stmt; 
  
  
*************** 
**  rewrite  ** 
*************** 
  
QueryRewrite (rewrite/rewriteHandler.c) 
  |->RewriteQuery (*) (查询重写,获得querylist) 
  |->foreach(l, querylist) 
  |  |->fireRIRrules (*) 
  |  |->(设置queryId) 
  |->(在query list中查找并设置可以set tag的query) 
  
RewriteQuery (rewrite/rewriteHandler.c) 
  |->foreach(lc1, parsetree->cteList) (处理WITH子句中的所有CTE) 
  |  |->(如果CTE是SELECT,则直接跳过不处理) 
  |  |->RewriteQuery (*) (重写CTE中的查询) 
  |  |->(用重写后的query覆盖CTE中的查询,对CTE,当前只支持单条语句的DO INSTEAD规则,其他情况都报错) 
  |->(如果查询语句不是SELECT和UTILITY) 
  |  |->rt_fetch (parser/parsetree.h) (获得resultRelation对应的RTE) 
  |  |->heap_open (access/heap/heapam.c) 
  |  |->(对不同语句类型做分别处理:重写targetList) 
  |  |  |*->(CMD_INSERT) 
  |  |  |  |->(如果有VALUES,则获得其对应的RTE) 
  |  |  |  |->if (values_rte) 
  |  |  |     |*->(有VALUES对应的RTE) 
  |  |  |     |   |->rewriteTargetListIU (*) (重写INSERT/UPDATE的targetList) 
  |  |  |     |   |->rewriteValuesRTE (*) (重写VALUES,把DEFAULT变成缺省值表达式) 
  |  |  |     |*->rewriteTargetListIU (*) 
  |  |  |*->(CMD_UPDATE) 
  |  |  |  |->rewriteTargetListIU (*) 
  |  |  |  |->rewriteTargetListUD (*) (重写UPDATE/DELETE的targetList) 
  |  |  |*->(CMD_DELETE) 
  |  |  |  |->rewriteTargetListUD (*) 
  |  |  |*->(其他) 
  |  |     |->(报错) 
  |  |->matchLocks (*) (获得匹配的规则,规则保存在RelationData结构中的rd_rules,其类型是RuleLock(rewrite/prs2lock.h)) 
  |  |->fireRules (*) 
  |  |->if(没有INSTEAD规则,并且是个视图,该视图没有INSTEAD触发器) (该视图必须是可更新视图) 
  |  |  |->rewriteTargetView (*) (如果不是可更新视图则报错) 
  |  |  |->(把原来的query加到product_queries,加在前面或者后面) 
  |  |  |->(把instead和returning设为true) 
  |  |->if (product_queries != NIL) (product_queries是在fireRules函数中生成的所有规则的动作语句) 
  |  |  |->(首先检查规则是否递归了) 
  |  |  |->(创建rewritten_event,并添加到列表rewritten_events的开头) 
  |  |  |->foreach(n, product_queries) (重写规则中的动作语句) 
  |  |  |  |->RewriteQuery (*) 
  |  |  |  |->(把重写结果加到rewritten列表中) 
  |  |  |->(从rewritten_events的开头删除rewritten_event) 
  |  |->(如果有INSTEAD规则并且原始查询有RETURNING子句,而规则动作中没有RETURNING,则报错) 
  |  |->heap_close (access/heap/heapam.c) 
  |->if (!instead) (如果没有unqualified INSTEAD规则) 
  |  |->if (parsetree->commandType == CMD_INSERT) 
  |  |  |*->(把quad_product或者原来的query添加到rewritten列表的开头) 
  |  |  |*->(把quad_product或者原来的query添加到rewritten列表的结尾) 
  |->(如果重写结果包括多个非utility语句,并且原来的query中有CTE则报错) 
   
fireRIRrules (rewrite/rewriteHandler.c) 
  |->while (rt_index < list_length(parsetree->rtable)) (处理每个RTE) 
  | |->rt_fetch (parser/parsetree.h) 
  | |->(如果是RTE_SUBQUERY) 
  | | |->fireRIRrules (*) 
  | | |->(continue) 
  | |->(如果不是RTE_RELATION,则跳过不处理) 
  | |->(如果是物化视图,则跳过不处理) 
  | |->(跳过没有在查询中引用到的RTE) 
  | |->(跳过在ApplyRetrieveRule中新增加的RTE) 
  | |->heap_open (access/heap/heapam.c) 
  | |->(收集所有SELECT规则) 
  | |->if (locks != NIL) (收集到的SELECT规则) 
  | |  |->(检查是否有无穷递归) 
  | |  |->foreach(l, locks) (处理每个规则) 
  | |  |  |->ApplyRetrieveRule (*) 
  | |->heap_close (access/heap/heapam.c) 
  |->foreach(lc, parsetree->cteList) (处理每个CTE) 
  |  |->fireRIRrules (*) 
  |->if (parsetree->hasSubLinks) 
  |  |->query_tree_walker (nodes/nodeFuncs.c) (fireRIRonSubLink (*)) 
   
ApplyRetrieveRule (rewrite/rewriteHandler.c) 
  |->(检查各种无效情况) 
  |->if (rt_index == parsetree->resultRelation) (可更新视图,已经经过rewriteTargetView处理) 
  |  |-> 
  |->get_parse_rowmark (parser/parse_relation.c) 
  |->AcquireRewriteLocks (*) 
  |->fireRIRrules (*) 
  |->(把对rule_action的fireRIRrule的结果作为子查询挂到当前RTE下) 
  |->markQueryForLocking (*) 
  
  
************ 
**  plan  ** 
************ 
nodes/nodes.h : 包含Cost/Selectivity类型 
nodes/primnodes.h : 包含在parse/plan/execute阶段都要用到的类型 
nodes/plannodes.h : 查询计划节点类型 
nodes/relation.h : planner的内部数据结构 
  
  
planner (optimizer/plan/planner.c) 
  |->if (planner_hook) 
    |*->(*planner_hook)(...) 
    |*->standard_planner (*) 
     
standard_planner (optimizer/plan/planner.c) 
  |->(创建并初始化PlannerGlobal结构) 
  |->subquery_planner (*) 
  |->(如果是SCROLLABLE CUROSOR,并且上面生成的计划不支持向后扫描,则在上面增加一个物化计划节点) 
  |->set_plan_references (optimizer/plan/setrefs.c) 
  |->forboth(lp, glob->subplans, lr, glob->subroots) (对所有subplan执行set_plan_references) 
  |  |->set_plan_references (optimizer/plan/setrefs.c) 
  |->(创建并设置PlannedStmt,其中设置的值来自Query和PlannerGlobal) 
  
subquery_planner (optimizer/plan/planner.c) 
  |->(创建并初始化PlannerInfo结构root) 
  |->if (hasRecursion) 
  |  |*->root->wt_param_id = SS_assign_special_param(root); (optimizer/plan/subselect.c) 
  |  |*->root->wt_param_id = -1; 
  |->if (parse->cteList) 
  |  |->SS_process_ctes (optimizer/plan/subselect.c) (处理所有CTE) 
  |->if (parse->hasSubLinks) 
  |  |->pull_up_sublinks (optimizer/prep/prepjointree.c) (处理WHERE和JOIN/ON中的EXISTS和ANY SubLink,把他们变换成SEMI/ANTI-SEMI JOIN) 
  |->inline_set_returning_functions (optimizer/prep/prepjointree.c) (inline集合返回函数:就是把rtable中的RTE_FUNCTION变成RTE_SUBQUERY) 
  |  |->inline_set_returning_function (optimizer/util/clauses.c) (输入RTE_FUNCTION rte,返回函数对应的Query) 
  |->pull_up_subqueries (optimizer/prep/prepjointree.c) (处理query.jointree,上拉子查询) 
  |->if (parse->setOperations) 
  |  |->flatten_simple_union_all (optimizer/prep/prepjointree.c) (把UNION ALL变换成Append) 
  |->(遍历所有RTE,检查是否有JOIN/LATERAL/OUTER JOIN) 
  |->preprocess_rowmarks (*) (生成PlanRowMark列表,即PlannerInfo.rowMarks) 
  |->expand_inherited_tables (optimizer/prep/prepunion.c) (处理继承表,生成Append) 
  | 
  |->preprocess_expression (*) (预处理parse->targetList) 
  |->preprocess_expression (*) (预处理parse->returningList) 
  |->preprocess_qual_conditions (*) (预处理parse->jointree) 
  |->preprocess_expression (*) (预处理parse->havingQual) 
  |->foreach(l, parse->windowClause) 
  |  |->preprocess_expression (*) (预处理WindowClause子句中的startOffset) 
  |  |->preprocess_expression (*) (预处理WindowClause子句中的endOffset) 
  |->preprocess_expression (*) (预处理parse->limitOffset) 
  |->preprocess_expression (*) (预处理parse->limitCount) 
  |->preprocess_expression (*) (预处理root->append_rel_list) 
  |->foreach(l, parse->rtable) (处理RTE内的表达式,需要处理的RTE:RTE_SUBQUERY/RTE_FUNCTION/RTE_VALUES) 
  |  |->(根据RTE类型做分别处理) 
  |    |*->(RTE_SUBQUERY) 
  |    |  |->flatten_join_alias_vars (optimizer/util/var.c) (只有当有joinRTE,并且RTE是lateral的时候才处理) 
  |    |*->(RTE_FUNCTION) 
  |    |  |->preprocess_expression (*) (预处理rte->funcexpr) 
  |    |*->(RTE_VALUES) 
  |       |->preprocess_expression (*) (预处理rte->values_lists) 
  |->(处理havingQual中的每一项,分为三种情况:保留在havingQual中/移到WHERE中/移到WHERER同时保留在havingQual中) 
  |->if (hasOuterJoins) 
  |  |->reduce_outer_joins (optimizer/prep/prepjointree.c) (试图把外连接变成内连接) 
  | 
  |->if (parse->resultRelation有效并且是个父表) 
  |  |*->inheritance_planner (*) 
  |  |*->(...) 
  |     |->grouping_planner (*) 
  |     |->if (parse->commandType != CMD_SELECT) 
  |       |->make_modifytable (optimizer/plan/createplan.c) 
  |->if (list_length(glob->subplans) != num_old_subplans || root->glob->nParamExec > 0) 
  |  |->SS_finalize_plan (optimizer/plan/subselect.c) (对sublink和parameter做最后的处理) 
  | 
  
grouping_planner (optimizer/plan/planner.c) (处理group by/聚集等相关的planning,而基本的查询规划是由query_planner来处理的) 
  |->if (parse->limitCount || parse->limitOffset) 
  |  |->preprocess_limit (*) 
  |->if (parse->setOperations) 
  | |*->(...) 
  | |  |->if (parse->sortClause) 
  | |  |  |->tuple_fraction = 0.0; 
  | |  |->plan_set_operations (optimizer/prep/prepunion.c) (对集合SQL语句进行规划) 
  | |  |->make_pathkeys_for_sortclauses (optimizer/path/pathkeys.c) 
  | |  |->postprocess_setop_tlist (*) 
  | |  |->make_pathkeys_for_sortclauses (optimizer/path/pathkeys.c) 
  | |*->(...) 
  |    |->if (parse->groupClause) 
  |    |  |->preprocess_groupclause (*) 
  |    |->preprocess_targetlist (optimizer/prep/preptlist.c) 
  |    |->if (parse->hasWindowFuncs) 
  |    |  |->find_window_functions (optimizer/util/clauses.c) (找到所有的窗口函数,具有相同winref的窗口函数[也就是引用同一个窗口子句的窗口函数]保存在同一个列表中) 
  |    |  |->if (wflists->numWindowFuncs > 0) 
  |    |     |*->select_active_windows (*) (获得所有活动的窗口子句,并且把具有相同的partition_by和order_by的窗口子句放在一起) 
  |    |     |*->parse->hasWindowFuncs = false; 
  |    |->make_subplanTargetList (*) 
  |    |->if (parse->hasAggs) 
  |    |  |->count_agg_clauses (optimizer/util/clauses.c) (处理targetlist) 
  |    |  |->count_agg_clauses (optimizer/util/clauses.c) (处理havingQual) 
  |    |  |->preprocess_minmax_aggregates (optimizer/plan/planagg.c) 
  |    |->(设置standard_qp_extra结构,在standard_qp_callback函数中用到) 
  |    |->query_planner (optimizer/plan/planmain.c) 
  |    |->(...) 
  |    |  |*->if (parse->groupClause) 
  |    |  |  |->choose_hashed_grouping (*) (是否用hash来处理GROUP的代价更低) 
  |    |  |*->else if (parse->distinctClause && sorted_path && !root->hasHavingQual && !parse->hasAggs && !activeWindows) 
  |    |     |->choose_hashed_distinct (*) (是否用hash来处理DISTINCT的代价更低) 
  |    |->if (use_hashed_grouping || use_hashed_distinct || !sorted_path) 
  |    |  |*->best_path = cheapest_path; 
  |    |  |*->best_path = sorted_path; 
  |    |->result_plan = optimize_minmax_aggregates (optimizer/plan/planagg.c) (检查是否可以通过索引来优化MINMAX聚集) 
  |    |-> 
  | 
  
inheritance_planner (optimizer/plan/planner.c) 
  |-> 
  
query_planner (optimizer/plan/planmain.c) 
  |->(如果parse->jointree->fromlist为空,则直接创建一个ResultPath) 
  |->setup_simple_rel_arrays (optimizer/util/relnode.c) (初始化PlannerInfo中的simple_rel_array和simple_rte_array) 
  |->add_base_rels_to_query (optimizer/plan/initsplan.c) (对jointree中的所有base relation创建RelOptInfo,包括子表) 
  | 
  |->build_base_rel_tlists (optimizer/plan/initsplan.c) (把finalTargetList中的Var加到相应的base relation的RelOptInfo中,以及处理PlaceHolderVar) 
  |->find_placeholders_in_jointree (optimizer/util/placeholder.c) (搜索jointree中的PLV,创建相应的PlaceHolderInfo) 
  |->find_lateral_references (optimizer/plan/initsplan.c) (处理lateral RTE中的Var和PLV) 
  |->deconstruct_jointree (optimizer/plan/initsplan.c) (把jointree flatten,并且处理WHERE/JOIN ON中的qual) 
  | 
  |->reconsider_outer_join_clauses (optimizer/path/equivclass.c) () 
  |->generate_base_implied_equalities (optimizer/path/equivclass.c) () 
  |->(*qp_callback) (从EquivalenceClass生成query PathKeys) 
  |->fix_placeholder_input_needed_levels (optimizer/util/placeholder.c) () 
  |->remove_useless_joins (optimizer/plan/analyzejoins.c) (遍历root->join_info_list,找到无用的连接然后删除) 
  |->add_placeholders_to_base_rels (optimizer/util/placeholder.c) 
  |->create_lateral_join_info (optimizer/plan/initsplan.c) 
  |->(计算涉及的baserel的磁盘页的总和) 
  | 
  |->make_one_rel (optimizer/path/allpaths.c) (找到所有的path,并且返回一个最后的join对应的RelOptInfo) 
  | 
  |->(...) 
  |  |*->if (parse->groupClause) 
  |  |  |->get_sortgrouplist_exprs (optimizer/util/tlist.c) 
  |  |  |->estimate_num_groups (utils/adt/selfuncs.c) 
  |  |  |->(调整tuple_fraction) 
  |  |*->else if (parse->hasAggs || root->hasHavingQual) (有聚集但是没有group by,那么只有一个group,所以必须读取所有元组) 
  |  |  |->tuple_fraction = 0.0; 
  |  |*->else if (parse->distinctClause) (没有group by和聚集,只有distinct) 
  |  |  |->get_sortgrouplist_exprs (optimizer/util/tlist.c) 
  |  |  |->estimate_num_groups (utils/adt/selfuncs.c) 
  |  |  |->(调整tuple_fraction) 
  |  |*->else 
  |     |->(把tuple_fraction从绝对数变成比例) 
  |->get_cheapest_fractional_path_for_pathkeys (optimizer/path/pathkeys.c) 
  |->if (sortedpath) (检查如果对cheapest-total path进行排序,其结果比sorted_path还代价低,则丢弃前面获得的sorted_path) 
  |  |->if (root->query_pathkeys == NIL || pathkeys_contained_in(root->query_pathkeys,cheapestpath->pathkeys)) 
  |  |  |*->(设置sorted_path的代价和cheapest_path的代价一样) 
  |  |  |*->cost_sort (optimizer/path/costsize.c) (计算排序的代价) 
  |  |->if (compare_fractional_path_costs(sortedpath, &sort_path, tuple_fraction) > 0) 
  |     |->sortedpath = NULL; 
  |->(设置返回的cheapest_path和sorted_path) 
  
make_one_rel (optimizer/path/allpaths.c) 
  |->(生成root->all_baserels) 
  |->set_base_rel_sizes (*) (设置baserel的大小估计值:行数和行宽度) 
  |  |->for (rti = 1; rti < root->simple_rel_array_size; rti++) 
  |    |->(如果不是baserel则跳过) 
  |    |->set_rel_size (*) 
  |->set_base_rel_pathlists (*) 
  |  |->for (rti = 1; rti < root->simple_rel_array_size; rti++) 
  |    |->(如果不是baserel则跳过) 
  |    |->set_rel_pathlist (*) 
  |->make_rel_from_joinlist (*) () 
  
make_rel_from_joinlist (optimizer/path/allpaths.c) 
  |->levels_needed = list_length(joinlist); 
  |->foreach(jl, joinlist) (创建与joinlist对应的RelOptInfo列表initial_rels) 
  |  |->(...) 
  |  |  |*->if (IsA(jlnode, RangeTblRef)) 
  |  |  |  |->find_base_rel (optimizer/util/relnode.c) 
  |  |  |*->else if (IsA(jlnode, List)) 
  |  |  |  |->make_rel_from_joinlist (*) 
  |  |  |*->else 
  |  |     |->(报错) 
  |  |->initial_rels = lappend(initial_rels, thisrel); 
  |->(...) 
     |*->if (levels_needed == 1) 
     |  |->return (RelOptInfo *) linitial(initial_rels); 
     |*->else 
        |->root->initial_rels = initial_rels; 
        |->(...) 
           |*->if (join_search_hook) 
           |  |->(*join_search_hook)(...) (调用hook) 
           |*->else if (enable_geqo && levels_needed >= geqo_threshold) 
           |  |->geqo (optimizer/geqo/geqo_main.c) 
           |*->else 
              |->standard_join_search (*) 
  
standard_join_search (optimizer/path/allpaths.c) 
  |->(分配List*数组root->join_rel_level,并且设置root->join_rel_level[1] = initial_rels) 
  |->for (lev = 2; lev <= levels_needed; lev++) 
  |  |->join_search_one_level (optimizer/path/joinrels.c) 
  |  |->foreach(lc, root->join_rel_level[lev]) 
  |    |->set_cheapest (optimizer/util/pathnode.c) 
  | 
  |->rel = (RelOptInfo *) linitial(root->join_rel_level[levels_needed]); 
  |->return rel; 
  
join_search_one_level (optimizer/path/joinrels.c) 
  |->foreach(r, joinrels[level - 1]) (对于下一级的每个RelOptInfo) 
  |  |->RelOptInfo *old_rel = (RelOptInfo *) lfirst(r); 
  |  |->if (old_rel->joininfo != NIL || old_rel->has_eclass_joins || has_join_restriction(root, old_rel)) 
  |     |*->make_rels_by_clause_joins (*) 
  |     |  |->for_each_cell(l, other_rels) 
  |     |    |->if (!bms_overlap(old_rel->relids, other_rel->relids) &&  
  |     |      |    (have_relevant_joinclause(root, old_rel, other_rel) || have_join_order_restriction(root, old_rel, other_rel))) 
  |     |      |*->make_join_rel (*) 
  |     |*->make_rels_by_clauseless_joins (*) 
  |        |->for_each_cell(l, other_rels) 
  |          |->if (!bms_overlap(other_rel->relids, old_rel->relids)) 
  |            |*->make_join_rel (*) 
  |->for (k = 2;; k++) (考虑bushy join。此时不考虑笛卡尔积) 
  |  |->int other_level = level - k; 
  |  |->if (k > other_level) 
  |  |  |*->break; 
  |  |->foreach(r, joinrels[k]) 
  |     |->if (old_rel->joininfo == NIL && !old_rel->has_eclass_joins && !has_join_restriction(root, old_rel)) 
  |     |  |*->continue; 
  |     |->if (k == other_level) 
  |     |  |*->other_rels = lnext(r); 
  |     |  |*->other_rels = list_head(joinrels[other_level]); 
  |     |->for_each_cell(r2, other_rels) 
  |        |->if (!bms_overlap(old_rel->relids, new_rel->relids)) 
  |           |*->if (have_relevant_joinclause(root, old_rel, new_rel) || have_join_order_restriction(root, old_rel, new_rel)) 
  |               |*->make_join_rel (*) 
  |->if (joinrels[level] == NIL) 
  |  |->foreach(r, joinrels[level - 1]) 
  |  |  |->make_rels_by_clauseless_joins (*) 
  |  |->if (joinrels[level] == NIL && root->join_info_list == NIL && root->lateral_info_list == NIL) 
  |     |->(报错) 
  
make_join_rel (optimizer/path/joinrels.c) 
  |->join_is_legal (*) (检查正要进行的连接是否legal,如果不legal则直接返回NULL) 
  |->(如果需要,交换两边的rel) 
  |->(如果是内连接则初始化SpecialJoinInfo) 
  |->build_join_rel (optimizer/util/relnode.c) (如果joinrel已经存在则直接返回,否则创建新的) 
  |->(如果是dummy rel则返回) 
  |->switch (sjinfo->jointype) 
  |  |*->case JOIN_INNER: 
  |  |  |->if (is_dummy_rel(rel1) || is_dummy_rel(rel2) || restriction_is_constant_false(restrictlist, false)) 
  |  |  |  |->mark_dummy_rel (*) 
  |  |  |  |->break; 
  |  |  |->add_paths_to_joinrel (optimizer/path/joinpath.c) 
  |  |  |->add_paths_to_joinrel (optimizer/path/joinpath.c) 
  |  |*->case JOIN_LEFT: 
  |  |*->case JOIN_FULL: 
  |  |*->case JOIN_SEMI: 
  |  |*->case JOIN_ANTI: 
  |  |  |-> 
  |  |*->default: 
  |     |->(报错) 
  
join_is_legal (optimizer/path/joinrels.c) 
  |-> 
  
set_rel_size (optimizer/path/allpaths.c) 
  |->(...) 
    |*->if (rel->reloptkind == RELOPT_BASEREL && relation_excluded_by_constraints(root, rel, rte)) (如果通过约束检查,本表不需要扫描) 
    |  |->set_dummy_rel_pathlist (*) 
    |*->else if (rte->inh) 
    |  |->set_append_rel_size (*) 
    |*->else 
       |->switch (rel->rtekind) 
         |*->case RTE_RELATION: 
         |  |->if (rte->relkind == RELKIND_FOREIGN_TABLE) 
         |    |*->set_foreign_size (*) 
         |    |*->set_plain_rel_size (*) 
         |*->case RTE_SUBQUERY: 
         |  |->set_subquery_pathlist (*) 
         |*->case RTE_FUNCTION: 
         |  |->set_function_size_estimates (optimizer/path/costsize.c) 
         |*->case RTE_VALUES: 
         |  |->set_values_size_estimates (optimizer/path/costsize.c) 
         |*->case RTE_CTE: 
         |  |->if (rte->self_reference) 
         |    |*->set_worktable_pathlist (*) 
         |    |*->set_cte_pathlist (*) 
         |*->default: 
            |->(报错) 
  
set_rel_pathlist (optimizer/path/allpaths.c) 
  |->(...) 
    |*->if (IS_DUMMY_REL(rel)) 
    |  |->(空) 
    |*->else if (rte->inh) 
    |  |->set_append_rel_pathlist (*) 
    |*->else 
       |->switch (rel->rtekind) 
         |*->case RTE_RELATION: 
         |  |->if (rte->relkind == RELKIND_FOREIGN_TABLE) 
         |    |*->set_foreign_pathlist (*) 
         |    |  |->(rel->fdwroutine->GetForeignPaths 调用FDW中的GetForeignPaths函数来生成path) 
         |    |  |->set_cheapest (optimizer/util/pathnode.c) 
         |    |*->set_plain_rel_pathlist (*) 
         |       |->add_path (optimizer/util/pathnode.c) (把 create_seqscan_path 的结果添加到RelOptInfo的pathlist中) 
         |       |->create_index_paths (optimizer/path/indxpath.c) (创建并添加索引path) 
         |       |->create_tidscan_paths (optimizer/path/tidpath.c) (创建并添加TID path) 
         |       |->set_cheapest (optimizer/util/pathnode.c) 
         |*->case RTE_SUBQUERY: 
         |  |->(空,已经在set_rel_size里面处理了) 
         |*->case RTE_FUNCTION: 
         |  |->set_function_pathlist (*) 
         |    |->add_path (optimizer/util/pathnode.c) (把 create_functionscan_path 的结果添加到RelOptInfo的pathlist中) 
         |    |->set_cheapest (optimizer/util/pathnode.c) 
         |*->case RTE_VALUES: 
         |  |->set_values_pathlist (*) 
         |    |->add_path (optimizer/util/pathnode.c) (把 create_valuesscan_path 的结果添加到RelOptInfo的pathlist中) 
         |    |->set_cheapest (optimizer/util/pathnode.c) 
         |*->case RTE_CTE: 
         |  |->(空,已经在set_rel_size里面处理了) 
         |*->default: 
            |->(报错) 
  
**************** 
**  executor  ** 
**************** 
  
ExecutorStart (executor/execMain.c) 
  |-> 
  
  
ExecutorRun (executor/execMain.c) 
  |-> 
  
  
ExecutorFinish (xecutor/execMain.c) 
  |-> 
  
  
ExecutorEnd (xecutor/execMain.c) 
  |-> 

0 0
原创粉丝点击