PostgreSQL 原始碼解讀(21)- 查詢語句#6(PlannedStmt詳解-跟蹤分析)
本文簡單介紹了PG根據查詢樹生成的執行計劃的詳細結構,生成執行計劃的輸入是上一節介紹的查詢樹Query。
一、PlannedStmt結構
生成執行計劃在函式pg_plan_queries中實現,返回的是連結串列plantree_list,連結串列中的元素是PlannedStmt.
PlannedStmt結構:
/* ---------------- * PlannedStmt node * * The output of the planner is a Plan tree headed by a PlannedStmt node. * PlannedStmt holds the "one time" information needed by the executor. * * For simplicity in APIs, we also wrap utility statements in PlannedStmt * nodes; in such cases, commandType == CMD_UTILITY, the statement itself * is in the utilityStmt field, and the rest of the struct is mostly dummy. * (We do use canSetTag, stmt_location, stmt_len, and possibly queryId.) * ---------------- */ typedef struct PlannedStmt { NodeTag type; CmdType commandType; /* select|insert|update|delete|utility */ uint64 queryId; /* query identifier (copied from Query) */ bool hasReturning; /* is it insert|update|delete RETURNING? */ bool hasModifyingCTE; /* has insert|update|delete in WITH? */ bool canSetTag; /* do I set the command result tag? */ bool transientPlan; /* redo plan when TransactionXmin changes? */ bool dependsOnRole; /* is plan specific to current role? */ bool parallelModeNeeded; /* parallel mode required to execute? */ int jitFlags; /* which forms of JIT should be performed */ struct Plan *planTree; /* tree of Plan nodes */ List *rtable; /* list of RangeTblEntry nodes */ /* rtable indexes of target relations for INSERT/UPDATE/DELETE */ List *resultRelations; /* integer list of RT indexes, or NIL */ /* * rtable indexes of non-leaf target relations for UPDATE/DELETE on all * the partitioned tables mentioned in the query. */ List *nonleafResultRelations; /* * rtable indexes of root target relations for UPDATE/DELETE; this list * maintains a subset of the RT indexes in nonleafResultRelations, * indicating the roots of the respective partition hierarchies. */ List *rootResultRelations; List *subplans; /* Plan trees for SubPlan expressions; note * that some could be NULL */ Bitmapset *rewindPlanIDs; /* indices of subplans that require REWIND */ List *rowMarks; /* a list of PlanRowMark's */ List *relationOids; /* OIDs of relations the plan depends on */ List *invalItems; /* other dependencies, as PlanInvalItems */ List *paramExecTypes; /* type OIDs for PARAM_EXEC Params */ Node *utilityStmt; /* non-null if this is utility stmt */ /* statement location in source string (copied from Query) */ int stmt_location; /* start location, or -1 if unknown */ int stmt_len; /* length in bytes; 0 means "rest of string" */ } PlannedStmt; /* macro for fetching the Plan associated with a SubPlan node */ #define exec_subplan_get_plan(plannedstmt, subplan) \ ((Plan *) list_nth((plannedstmt)->subplans, (subplan)->plan_id - 1))
SQL語句:
select t_dwxx.dwmc,t_grxx.grbh,t_grxx.xm,t_jfxx.ny,t_jfxx.je from t_dwxx,t_grxx,t_jfxx where t_dwxx.dwbh = t_grxx.dwbh and t_grxx.grbh = t_jfxx.grbh and t_dwxx.dwbh IN ('1001','1002') order by t_grxx.grbh limit 8; select * from ( select t_dwxx.dwmc,t_grxx.grbh,t_grxx.xm,t_jfxx.ny,t_jfxx.je from t_dwxx inner join t_grxx on t_dwxx.dwbh = t_grxx.dwbh inner join t_jfxx on t_grxx.grbh = t_jfxx.grbh where t_dwxx.dwbh IN ('1001') union all select t_dwxx.dwmc,t_grxx.grbh,t_grxx.xm,t_jfxx.ny,t_jfxx.je from t_dwxx inner join t_grxx on t_dwxx.dwbh = t_grxx.dwbh inner join t_jfxx on t_grxx.grbh = t_jfxx.grbh where t_dwxx.dwbh IN ('1002') ) as ret order by ret.grbh limit 4;
跟蹤分析:
(gdb) b exec_simple_query Breakpoint 1 at 0x84cad8: file postgres.c, line 893. (gdb) c Continuing. Breakpoint 1, exec_simple_query ( query_string=0x12b3ef0 "select * from (\nselect t_dwxx.dwmc,t_grxx.grbh,t_grxx.xm,t_jfxx.ny,t_jfxx.je\nfrom t_dwxx inner join t_grxx on t_dwxx.dwbh = t_grxx.dwbh\ninner join t_jfxx on t_grxx.grbh = t_jfxx.grbh\nwhere t_dwxx.dwbh"...) at postgres.c:893 893 CommandDest dest = whereToSendOutput; 1050 plantree_list = pg_plan_queries(querytree_list, (gdb) 1054 if (snapshot_set) (gdb) p (PlannedStmt *)plantree_list->head->data.ptr_value $3 = (PlannedStmt *) 0x7f1a23ea74c8 (gdb) p *(PlannedStmt *)plantree_list->head->data.ptr_value $4 = {type = T_PlannedStmt, commandType = CMD_SELECT, queryId = 0, hasReturning = false, hasModifyingCTE = false, canSetTag = true, transientPlan = false, dependsOnRole = false, parallelModeNeeded = false, jitFlags = 0, planTree = 0x7f1a23ea27f8, rtable = 0x7f1a23ea29b8, resultRelations = 0x0, nonleafResultRelations = 0x0, rootResultRelations = 0x0, subplans = 0x0, rewindPlanIDs = 0x0, rowMarks = 0x0, relationOids = 0x7f1a23ea3968, invalItems = 0x0, paramExecTypes = 0x0, utilityStmt = 0x0, stmt_location = 0, stmt_len = 455} (gdb) set $pstmt=(PlannedStmt *)plantree_list->head->data.ptr_value (gdb) p *$pstmt->rtable $5 = {type = T_List, length = 13, head = 0x7f1a23ea2998, tail = 0x7f1a23ea5cb8} (gdb) p *(Node *)$pstmt->rtable->head->data.ptr_value $6 = {type = T_RangeTblEntry} (gdb) p *(RangeTblEntry *)$pstmt->rtable->head->data.ptr_value $7 = {type = T_RangeTblEntry, rtekind = RTE_SUBQUERY, relid = 0, relkind = 0 '\000', tablesample = 0x0, subquery = 0x0, security_barrier = false, jointype = JOIN_INNER, joinaliasvars = 0x0, functions = 0x0, funcordinality = false, tablefunc = 0x0, values_lists = 0x0, ctename = 0x0, ctelevelsup = 0, self_reference = false, coltypes = 0x0, coltypmods = 0x0, colcollations = 0x0, enrname = 0x0, enrtuples = 0, alias = 0x12d8d40, eref = 0x13abb08, lateral = false, inh = true, inFromCl = true, requiredPerms = 2, checkAsUser = 0, selectedCols = 0x0, insertedCols = 0x0, updatedCols = 0x0, securityQuals = 0x0} (gdb) p *((RangeTblEntry *)$pstmt->rtable->head->data.ptr_value)->alias $8 = {type = T_Alias, aliasname = 0x12d8d28 "ret", colnames = 0x0} (gdb) p *((RangeTblEntry *)$pstmt->rtable->head->data.ptr_value)->eref $9 = {type = T_Alias, aliasname = 0x13abb38 "ret", colnames = 0x13abba8} (gdb) p *(RangeTblEntry *)$pstmt->rtable->head->next->data.ptr_value $10 = {type = T_RangeTblEntry, rtekind = RTE_SUBQUERY, relid = 0, relkind = 0 '\000', tablesample = 0x0, subquery = 0x0, security_barrier = false, jointype = JOIN_INNER, joinaliasvars = 0x0, functions = 0x0, funcordinality = false, tablefunc = 0x0, values_lists = 0x0, ctename = 0x0, ctelevelsup = 0, self_reference = false, coltypes = 0x0, coltypmods = 0x0, colcollations = 0x0, enrname = 0x0, enrtuples = 0, alias = 0x137ee90, eref = 0x137eee0, lateral = false, inh = false, inFromCl = false, requiredPerms = 0, checkAsUser = 0, selectedCols = 0x0, insertedCols = 0x0, updatedCols = 0x0, securityQuals = 0x0} (gdb) p *((RangeTblEntry *)$pstmt->rtable->head->next->data.ptr_value)->alias $11 = {type = T_Alias, aliasname = 0x137eec0 "*SELECT* 1", colnames = 0x0} (gdb) p *(RangeTblEntry *)$pstmt->rtable->head->next->next->data.ptr_value $12 = {type = T_RangeTblEntry, rtekind = RTE_SUBQUERY, relid = 0, relkind = 0 '\000', tablesample = 0x0, subquery = 0x0, security_barrier = false, jointype = JOIN_INNER, joinaliasvars = 0x0, functions = 0x0, funcordinality = false, tablefunc = 0x0, values_lists = 0x0, ctename = 0x0, ctelevelsup = 0, self_reference = false, coltypes = 0x0, coltypmods = 0x0, colcollations = 0x0, enrname = 0x0, enrtuples = 0, alias = 0x13818d8, eref = 0x1381928, lateral = false, inh = false, inFromCl = false, requiredPerms = 0, checkAsUser = 0, selectedCols = 0x0, insertedCols = 0x0, updatedCols = 0x0, securityQuals = 0x0} (gdb) p *((RangeTblEntry *)$pstmt->rtable->head->next->next->data.ptr_value)->alias $13 = {type = T_Alias, aliasname = 0x1381908 "*SELECT* 2", colnames = 0x0} $14 = {type = T_RangeTblEntry, rtekind = RTE_RELATION, relid = 26754, relkind = 114 'r', tablesample = 0x0, subquery = 0x0, security_barrier = false, jointype = JOIN_INNER, joinaliasvars = 0x0, functions = 0x0, funcordinality = false, tablefunc = 0x0, values_lists = 0x0, ctename = 0x0, ctelevelsup = 0, self_reference = false, coltypes = 0x0, coltypmods = 0x0, colcollations = 0x0, enrname = 0x0, enrtuples = 0, alias = 0x0, eref = 0x1384418, lateral = false, inh = false, inFromCl = true, requiredPerms = 2, checkAsUser = 0, selectedCols = 0x1384598, insertedCols = 0x0, updatedCols = 0x0, securityQuals = 0x0} (gdb) p *(RangeTblEntry *)$pstmt->rtable->head->next->next->next->next->data.ptr_value $15 = {type = T_RangeTblEntry, rtekind = RTE_RELATION, relid = 26757, relkind = 114 'r', tablesample = 0x0, subquery = 0x0, security_barrier = false, jointype = JOIN_INNER, joinaliasvars = 0x0, functions = 0x0, funcordinality = false, tablefunc = 0x0, values_lists = 0x0, ctename = 0x0, ctelevelsup = 0, self_reference = false, coltypes = 0x0, coltypmods = 0x0, colcollations = 0x0, enrname = 0x0, enrtuples = 0, alias = 0x0, eref = 0x13846e0, lateral = false, inh = false, inFromCl = true, requiredPerms = 2, checkAsUser = 0, selectedCols = 0x13848b8, insertedCols = 0x0, updatedCols = 0x0, securityQuals = 0x0} (gdb) p *(RangeTblEntry *)$pstmt->rtable->head->next->next->next->next->next->data.ptr_value $16 = {type = T_RangeTblEntry, rtekind = RTE_JOIN, relid = 0, relkind = 0 '\000', tablesample = 0x0, subquery = 0x0, security_barrier = false, jointype = JOIN_INNER, joinaliasvars = 0x0, functions = 0x0, funcordinality = false, tablefunc = 0x0, values_lists = 0x0, ctename = 0x0, ctelevelsup = 0, self_reference = false, coltypes = 0x0, coltypmods = 0x0, colcollations = 0x0, enrname = 0x0, enrtuples = 0, alias = 0x0, eref = 0x1384d40, lateral = false, inh = false, inFromCl = true, requiredPerms = 0, checkAsUser = 0, selectedCols = 0x0, insertedCols = 0x0, updatedCols = 0x0, securityQuals = 0x0} (gdb) p *((RangeTblEntry *)$pstmt->rtable->head->next->next->next->next->next->data.ptr_value)->eref $17 = {type = T_Alias, aliasname = 0x1384d70 "unnamed_join", colnames = 0x1384d90} (gdb) p *(RangeTblEntry *)$pstmt->rtable->head->next->next->next->next->next->next->data.ptr_value $18 = {type = T_RangeTblEntry, rtekind = RTE_RELATION, relid = 26760, relkind = 114 'r', tablesample = 0x0, subquery = 0x0, security_barrier = false, jointype = JOIN_INNER, joinaliasvars = 0x0, functions = 0x0, funcordinality = false, tablefunc = 0x0, values_lists = 0x0, ctename = 0x0, ctelevelsup = 0, self_reference = false, coltypes = 0x0, coltypmods = 0x0, colcollations = 0x0, enrname = 0x0, enrtuples = 0, alias = 0x0, eref = 0x1385158, lateral = false, inh = false, inFromCl = true, requiredPerms = 2, checkAsUser = 0, selectedCols = 0x13852d8, insertedCols = 0x0, updatedCols = 0x0, securityQuals = 0x0} (gdb) p *((RangeTblEntry *)$pstmt->rtable->head->next->next->next->next->next->next->data.ptr_value)->eref $19 = {type = T_Alias, aliasname = 0x1385188 "t_jfxx", colnames = 0x13851a0} (gdb) p *(RangeTblEntry *)$pstmt->rtable->head->next->next->next->next->next->next->next->data.ptr_value $20 = {type = T_RangeTblEntry, rtekind = RTE_JOIN, relid = 0, relkind = 0 '\000', tablesample = 0x0, subquery = 0x0, security_barrier = false, jointype = JOIN_INNER, joinaliasvars = 0x0, functions = 0x0, funcordinality = false, tablefunc = 0x0, values_lists = 0x0, ctename = 0x0, ctelevelsup = 0, self_reference = false, coltypes = 0x0, coltypmods = 0x0, colcollations = 0x0, enrname = 0x0, enrtuples = 0, alias = 0x0, eref = 0x13858b0, lateral = false, inh = false, inFromCl = true, requiredPerms = 0, checkAsUser = 0, selectedCols = 0x0, insertedCols = 0x0, updatedCols = 0x0, securityQuals = 0x0} (gdb) p *(RangeTblEntry *)$pstmt->rtable->head->next->next->next->next->next->next->next->next->data.ptr_value $21 = {type = T_RangeTblEntry, rtekind = RTE_RELATION, relid = 26754, relkind = 114 'r', tablesample = 0x0, subquery = 0x0, security_barrier = false, jointype = JOIN_INNER, joinaliasvars = 0x0, functions = 0x0, funcordinality = false, tablefunc = 0x0, values_lists = 0x0, ctename = 0x0, ctelevelsup = 0, self_reference = false, coltypes = 0x0, coltypmods = 0x0, colcollations = 0x0, enrname = 0x0, enrtuples = 0, alias = 0x0, eref = 0x7f1a23e95308, lateral = false, inh = false, inFromCl = true, requiredPerms = 2, checkAsUser = 0, selectedCols = 0x7f1a23e95458, insertedCols = 0x0, updatedCols = 0x0, securityQuals = 0x0} (gdb) p *((RangeTblEntry *)$pstmt->rtable->head->next->next->next->next->next->next->next->next->data.ptr_value)->eref $22 = {type = T_Alias, aliasname = 0x138bf90 "t_dwxx", colnames = 0x7f1a23e95338} (gdb) p *(RangeTblEntry *)$pstmt->rtable->head->next->next->next->next->next->next->next->next->next->data.ptr_value $23 = {type = T_RangeTblEntry, rtekind = RTE_RELATION, relid = 26757, relkind = 114 'r', tablesample = 0x0, subquery = 0x0, security_barrier = false, jointype = JOIN_INNER, joinaliasvars = 0x0, functions = 0x0, funcordinality = false, tablefunc = 0x0, values_lists = 0x0, ctename = 0x0, ctelevelsup = 0, self_reference = false, coltypes = 0x0, coltypmods = 0x0, colcollations = 0x0, enrname = 0x0, enrtuples = 0, alias = 0x0, eref = 0x7f1a23e955a0, lateral = false, inh = false, inFromCl = true, requiredPerms = 2, checkAsUser = 0, selectedCols = 0x7f1a23e95778, insertedCols = 0x0, updatedCols = 0x0, securityQuals = 0x0} (gdb) p *(RangeTblEntry *)$pstmt->rtable->head->next->next->next->next->next->next->next->next->next->data.ptr_value $24 = {type = T_RangeTblEntry, rtekind = RTE_RELATION, relid = 26757, relkind = 114 'r', tablesample = 0x0, subquery = 0x0, security_barrier = false, jointype = JOIN_INNER, joinaliasvars = 0x0, functions = 0x0, funcordinality = false, tablefunc = 0x0, values_lists = 0x0, ctename = 0x0, ctelevelsup = 0, self_reference = false, coltypes = 0x0, coltypmods = 0x0, colcollations = 0x0, enrname = 0x0, enrtuples = 0, alias = 0x0, eref = 0x7f1a23e955a0, lateral = false, inh = false, inFromCl = true, requiredPerms = 2, checkAsUser = 0, selectedCols = 0x7f1a23e95778, insertedCols = 0x0, updatedCols = 0x0, securityQuals = 0x0} #--->planTree:Limit (gdb) p $pstmt->planTree $25 = (struct Plan *) 0x7f1a23ea27f8 (gdb) p *$pstmt->planTree $26 = {type = T_Limit, startup_cost = 96.799999999999983, total_cost = 96.809999999999988, plan_rows = 4, plan_width = 360, parallel_aware = false, parallel_safe = true, plan_node_id = 0, targetlist = 0x7f1a23ea2d08, qual = 0x0, lefttree = 0x7f1a23ea2488, righttree = 0x0, initPlan = 0x0, extParam = 0x0, allParam = 0x0} (gdb) p *$pstmt->relationOids $45 = {type = T_OidList, length = 6, head = 0x7f1a23ea3948, tail = 0x7f1a23ea5b88} (gdb) p *$pstmt->relationOids->head $46 = {data = {ptr_value = 0x6882, int_value = 26754, oid_value = 26754}, next = 0x7f1a23ea3ac8} #--->planTree->lefttree:Sort (gdb) p *$pstmt->planTree->lefttree $52 = {type = T_Sort, startup_cost = 96.799999999999983, total_cost = 96.83499999999998, plan_rows = 14, plan_width = 360, parallel_aware = false, parallel_safe = true, plan_node_id = 1, targetlist = 0x7f1a23ea30f8, qual = 0x0, lefttree = 0x7f1a23e9d078, righttree = 0x0, initPlan = 0x0, extParam = 0x0, allParam = 0x0} (gdb) p *(Sort *)$pstmt->planTree->lefttree $53 = {plan = {type = T_Sort, startup_cost = 96.799999999999983, total_cost = 96.83499999999998, plan_rows = 14, plan_width = 360, parallel_aware = false, parallel_safe = true, plan_node_id = 1, targetlist = 0x7f1a23ea30f8, qual = 0x0, lefttree = 0x7f1a23e9d078, righttree = 0x0, initPlan = 0x0, extParam = 0x0, allParam = 0x0}, numCols = 1, sortColIdx = 0x7f1a23e9dae8, sortOperators = 0x7f1a23ea2440, collations = 0x7f1a23ea2458, nullsFirst = 0x7f1a23ea2470} (gdb) set $sort=(Sort *)$pstmt->planTree->lefttree (gdb) p *$sort->plan.lefttree $59 = {type = T_Append, startup_cost = 16.149999999999999, total_cost = 96.589999999999989, plan_rows = 14, plan_width = 360, parallel_aware = false, parallel_safe = true, plan_node_id = 2, targetlist = 0x7f1a23ea34e8, qual = 0x0, lefttree = 0x0, righttree = 0x0, initPlan = 0x0, extParam = 0x0, allParam = 0x0} (gdb) p *(Append *)$sort->plan.lefttree $60 = {plan = {type = T_Append, startup_cost = 16.149999999999999, total_cost = 96.589999999999989, plan_rows = 14, plan_width = 360, parallel_aware = false, parallel_safe = true, plan_node_id = 2, targetlist = 0x7f1a23ea34e8, qual = 0x0, lefttree = 0x0, righttree = 0x0, initPlan = 0x0, extParam = 0x0, allParam = 0x0}, appendplans = 0x7f1a23ea1030, first_partial_plan = 2, partitioned_rels = 0x0, part_prune_infos = 0x0} ##--->planTree->lefttree->plan.lefttree:Append (gdb)set $append=(Append *)$sort->plan.lefttree (gdb) p *$append.appendplans $64 = {type = T_List, length = 2, head = 0x7f1a23ea1010, tail = 0x7f1a23ea2420} (gdb) p *(Node *)$append.appendplans->head->data.ptr_value $65 = {type = T_NestLoop} (gdb) p *(NestLoop *)$append.appendplans->head->data.ptr_value $73 = {join = {plan = {type = T_NestLoop, startup_cost = 16.149999999999999, total_cost = 48.189999999999998, plan_rows = 7, plan_width = 360, parallel_aware = false, parallel_safe = true, plan_node_id = 4, targetlist = 0x7f1a23ea3ff8, qual = 0x0, lefttree = 0x7f1a23e9f9a0, righttree = 0x7f1a23ea0e60, initPlan = 0x0, extParam = 0x0, allParam = 0x0}, jointype = JOIN_INNER, inner_unique = false, joinqual = 0x0}, nestParams = 0x0} (gdb) set $nl1=(NestLoop *)$append.appendplans->head->data.ptr_value (gdb) set $nl2=(NestLoop *)$append.appendplans->head->next->data.ptr_value (gdb) p *$nl1->join->plan->lefttree $79 = {type = T_SeqScan, startup_cost = 0, total_cost = 12, plan_rows = 1, plan_width = 256, parallel_aware = false, parallel_safe = true, plan_node_id = 5, targetlist = 0x7f1a23ea4348, qual = 0x7f1a23ea46c8, lefttree = 0x0, righttree = 0x0, initPlan = 0x0, extParam = 0x0, allParam = 0x0} (gdb) p *(SeqScan *)$nl1->join->plan->lefttree $80 = {plan = {type = T_SeqScan, startup_cost = 0, total_cost = 12, plan_rows = 1, plan_width = 256, parallel_aware = false, parallel_safe = true, plan_node_id = 5, targetlist = 0x7f1a23ea4348, qual = 0x7f1a23ea46c8, lefttree = 0x0, righttree = 0x0, initPlan = 0x0, extParam = 0x0, allParam = 0x0}, scanrelid = 4} (gdb) p *(SeqScan *)$nl1->join->plan->lefttree->qual $81 = {plan = {type = T_List, startup_cost = 6.9045796748682899e-310, total_cost = 6.9045796748682899e-310, plan_rows = 0, plan_width = 64, parallel_aware = false, parallel_safe = false, plan_node_id = 19611104, targetlist = 0x700000067, qual = 0x41300000001, lefttree = 0x640000000e, righttree = 0x700000000, initPlan = 0xffffffff00000001, extParam = 0x0, allParam = 0x0}, scanrelid = 0} (gdb) p *(Node *)$nl1->join->plan->lefttree->qual $82 = {type = T_List} (gdb) p *(List *)$nl1->join->plan->lefttree->qual $83 = {type = T_List, length = 1, head = 0x7f1a23ea46a8, tail = 0x7f1a23ea46a8} (gdb) p *(Node *)$nl1->join->plan->lefttree->qual->head->data.ptr_value $84 = {type = T_OpExpr} (gdb) p *(OpExpr *)$nl1->join->plan->lefttree->qual->head->data.ptr_value $85 = {xpr = {type = T_OpExpr}, opno = 98, opfuncid = 67, opresulttype = 16, opretset = false, opcollid = 0, inputcollid = 100, args = 0x7f1a23ea4608, location = -1} (gdb) set $opexpr=(OpExpr *)$nl1->join->plan->lefttree->qual->head->data.ptr_value (gdb) p *$opexpr->args $86 = {type = T_List, length = 2, head = 0x7f1a23ea45e8, tail = 0x7f1a23ea4688} (gdb) p *(Node *)$opexpr->args->head->data.ptr_value $87 = {type = T_RelabelType} (gdb) p *(RelabelType *)$opexpr->args->head->data.ptr_value $88 = {xpr = {type = T_RelabelType}, arg = 0x7f1a23ea4598, resulttype = 25, resulttypmod = -1, resultcollid = 100, relabelformat = COERCE_IMPLICIT_CAST, location = -1} (gdb) p *((RelabelType *)$opexpr->args->head->data.ptr_value)->arg $89 = {type = T_Var} (gdb) p *(Var *)((RelabelType *)$opexpr->args->head->data.ptr_value)->arg $90 = {xpr = {type = T_Var}, varno = 4, varattno = 2, vartype = 1043, vartypmod = 14, varcollid = 100, varlevelsup = 0, varnoold = 4, varoattno = 2, location = 110} (gdb) p *(RelabelType *)$opexpr->args->tail->data.ptr_value $91 = {xpr = {type = T_Const}, arg = 0x64ffffffff, resulttype = 4294967295, resulttypmod = 0, resultcollid = 20488992, relabelformat = COERCE_EXPLICIT_CALL, location = 0} (gdb) p *(Const *)$opexpr->args->tail->data.ptr_value $92 = {xpr = {type = T_Const}, consttype = 25, consttypmod = -1, constcollid = 100, constlen = -1, constvalue = 20488992, constisnull = false, constbyval = false, location = 205} #其他類似 #DONE!
最終的計劃樹結構如下:
二、資料結構
Plan
/* ---------------- * Plan node * * All plan nodes "derive" from the Plan structure by having the * Plan structure as the first field. This ensures that everything works * when nodes are cast to Plan's. (node pointers are frequently cast to Plan* * when passed around generically in the executor) * * We never actually instantiate any Plan nodes; this is just the common * abstract superclass for all Plan-type nodes. * ---------------- */ typedef struct Plan { NodeTag type; /* * estimated execution costs for plan (see costsize.c for more info) */ Cost startup_cost; /* cost expended before fetching any tuples */ Cost total_cost; /* total cost (assuming all tuples fetched) */ /* * planner's estimate of result size of this plan step */ double plan_rows; /* number of rows plan is expected to emit */ int plan_width; /* average row width in bytes */ /* * information needed for parallel query */ bool parallel_aware; /* engage parallel-aware logic? */ bool parallel_safe; /* OK to use as part of parallel plan? */ /* * Common structural data for all Plan types. */ int plan_node_id; /* unique across entire final plan tree */ List *targetlist; /* target list to be computed at this node */ List *qual; /* implicitly-ANDed qual conditions */ struct Plan *lefttree; /* input plan tree(s) */ struct Plan *righttree; List *initPlan; /* Init Plan nodes (un-correlated expr * subselects) */ /* * Information for management of parameter-change-driven rescanning * * extParam includes the paramIDs of all external PARAM_EXEC params * affecting this plan node or its children. setParam params from the * node's initPlans are not included, but their extParams are. * * allParam includes all the extParam paramIDs, plus the IDs of local * params that affect the node (i.e., the setParams of its initplans). * These are _all_ the PARAM_EXEC params that affect this node. */ Bitmapset *extParam; Bitmapset *allParam; } Plan;
Limit
/* ---------------- * limit node * * Note: as of Postgres 8.2, the offset and count expressions are expected * to yield int8, rather than int4 as before. * ---------------- */ typedef struct Limit { Plan plan; Node *limitOffset; /* OFFSET parameter, or NULL if none */ Node *limitCount; /* COUNT parameter, or NULL if none */ } Limit;
Sort
/* ---------------- * sort node * ---------------- */ typedef struct Sort { Plan plan; int numCols; /* number of sort-key columns */ AttrNumber *sortColIdx; /* their indexes in the target list */ Oid *sortOperators; /* OIDs of operators to sort them by */ Oid *collations; /* OIDs of collations */ bool *nullsFirst; /* NULLS FIRST/LAST directions */ } Sort;
Append
/* ---------------- * Append node - * Generate the concatenation of the results of sub-plans. * ---------------- */ typedef struct Append { Plan plan; List *appendplans; /* * All 'appendplans' preceding this index are non-partial plans. All * 'appendplans' from this index onwards are partial plans. */ int first_partial_plan; /* RT indexes of non-leaf tables in a partition tree */ List *partitioned_rels; /* Info for run-time subplan pruning; NULL if we're not doing that */ struct PartitionPruneInfo *part_prune_info; } Append;
NestLoop
/* ---------------- * nest loop join node * * The nestParams list identifies any executor Params that must be passed * into execution of the inner subplan carrying values from the current row * of the outer subplan. Currently we restrict these values to be simple * Vars, but perhaps someday that'd be worth relaxing. (Note: during plan * creation, the paramval can actually be a PlaceHolderVar expression; but it * must be a Var with varno OUTER_VAR by the time it gets to the executor.) * ---------------- */ typedef struct NestLoop { Join join; List *nestParams; /* list of NestLoopParam nodes */ } NestLoop; typedef struct NestLoopParam { NodeTag type; int paramno; /* number of the PARAM_EXEC Param to set */ Var *paramval; /* outer-relation Var to assign to Param */ } NestLoopParam; /* * ========== * Join nodes * ========== */ /* ---------------- * merge join node * * The expected ordering of each mergeable column is described by a btree * opfamily OID, a collation OID, a direction (BTLessStrategyNumber or * BTGreaterStrategyNumber) and a nulls-first flag. Note that the two sides * of each mergeclause may be of different datatypes, but they are ordered the * same way according to the common opfamily and collation. The operator in * each mergeclause must be an equality operator of the indicated opfamily. * ---------------- */ typedef struct MergeJoin { Join join; bool skip_mark_restore; /* Can we skip mark/restore calls? */ List *mergeclauses; /* mergeclauses as expression trees */ /* these are arrays, but have the same length as the mergeclauses list: */ Oid *mergeFamilies; /* per-clause OIDs of btree opfamilies */ Oid *mergeCollations; /* per-clause OIDs of collations */ int *mergeStrategies; /* per-clause ordering (ASC or DESC) */ bool *mergeNullsFirst; /* per-clause nulls ordering */ } MergeJoin; /* ---------------- * hash join node * ---------------- */ typedef struct HashJoin { Join join; List *hashclauses; } HashJoin; /* ---------------- * Join node * * jointype: rule for joining tuples from left and right subtrees * inner_unique each outer tuple can match to no more than one inner tuple * joinqual: qual conditions that came from JOIN/ON or JOIN/USING * (plan.qual contains conditions that came from WHERE) * * When jointype is INNER, joinqual and plan.qual are semantically * interchangeable. For OUTER jointypes, the two are *not* interchangeable; * only joinqual is used to determine whether a match has been found for * the purpose of deciding whether to generate null-extended tuples. * (But plan.qual is still applied before actually returning a tuple.) * For an outer join, only joinquals are allowed to be used as the merge * or hash condition of a merge or hash join. * * inner_unique is set if the joinquals are such that no more than one inner * tuple could match any given outer tuple. This allows the executor to * skip searching for additional matches. (This must be provable from just * the joinquals, ignoring plan.qual, due to where the executor tests it.) * ---------------- */ typedef struct Join { Plan plan; JoinType jointype; bool inner_unique; List *joinqual; /* JOIN quals (in addition to plan.qual) */ } Join;
SeqScan
/* * ========== * Scan nodes * ========== */ typedef struct Scan { Plan plan; Index scanrelid; /* relid is index into the range table */ } Scan; /* ---------------- * sequential scan node * ---------------- */ typedef Scan SeqScan;
三、小結
1、PlannedStmt:這是已規劃的SQL語句,可用於Executor執行;
2、重要的資料結構:計劃的基礎結構Plan,“繼承“的結構Limit、Sort等。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/6906/viewspace-2374895/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- PostgreSQL 原始碼解讀(22)- 查詢語句#7(PlannedStmt結構詳解-日誌分析)SQL原始碼
- PostgreSQL 原始碼解讀(23)- 查詢語句#8(PlannedStmt與QUERY P...SQL原始碼
- PostgreSQL 原始碼解讀(19)- 查詢語句#4(ParseTree詳解)SQL原始碼
- PostgreSQL 原始碼解讀(20)- 查詢語句#5(查詢樹Query詳解)SQL原始碼
- PostgreSQL 原始碼解讀(36)- 查詢語句#21(查詢優化-消除外連線)SQL原始碼優化
- PostgreSQL 原始碼解讀(14)- Insert語句(如何構造PlannedStmt)SQL原始碼
- PostgreSQL 原始碼解讀(24)- 查詢語句#9(查詢重寫)SQL原始碼
- PostgreSQL 原始碼解讀(18)- 查詢語句#3(SQL Parse)SQL原始碼
- PostgreSQL 原始碼解讀(15)- Insert語句(執行過程跟蹤)SQL原始碼
- PostgreSQL 原始碼解讀(45)- 查詢語句#30(query_planner函式#6)SQL原始碼函式
- PostgreSQL 原始碼解讀(71)- 查詢語句#56(make_one_rel函式#21-...SQL原始碼函式
- PostgreSQL 原始碼解讀(83)- 查詢語句#68(PortalStart函式)SQL原始碼函式
- PostgreSQL 原始碼解讀(42)- 查詢語句#27(等價類)SQL原始碼
- PostgreSQL 原始碼解讀(74)- 查詢語句#59(Review - subquery_...SQL原始碼View
- PostgreSQL 原始碼解讀(75)- 查詢語句#60(Review - standard_...SQL原始碼View
- PostgreSQL 原始碼解讀(25)- 查詢語句#10(查詢優化概覽)SQL原始碼優化
- PostgreSQL 原始碼解讀(17)- 查詢語句#2(查詢優化基礎)SQL原始碼優化
- PostgreSQL 原始碼解讀(29)- 查詢語句#14(查詢優化-上拉子查詢)SQL原始碼優化
- PostgreSQL 原始碼解讀(90)- 查詢語句#75(ExecHashJoin函式#1)SQL原始碼函式
- PostgreSQL 原始碼解讀(91)- 查詢語句#76(ExecHashJoin函式#2)SQL原始碼函式
- PostgreSQL 原始碼解讀(93)- 查詢語句#77(ExecHashJoin函式#3)SQL原始碼函式
- PostgreSQL 原始碼解讀(81)- 查詢語句#66(Review - exec_simp...SQL原始碼View
- PostgreSQL 原始碼解讀(84)- 查詢語句#69(PortalStart->InitP...SQL原始碼
- PostgreSQL 原始碼解讀(85)- 查詢語句#70(PortalRun->InitPla...SQL原始碼
- PostgreSQL 原始碼解讀(86)- 查詢語句#71(PortalRun->PortalR...SQL原始碼
- PostgreSQL 原始碼解讀(50)- 查詢語句#35(Optimizer Review#1)SQL原始碼View
- PostgreSQL 原始碼解讀(51)- 查詢語句#36(Optimizer Review#2)SQL原始碼View
- PostgreSQL 原始碼解讀(37)- 查詢語句#22(查詢優化-grouping_plan...SQL原始碼優化
- PostgreSQL 原始碼解讀(87)- 查詢語句#72(PortalRunSelect->E...SQL原始碼
- PostgreSQL 原始碼解讀(56)- 查詢語句#41(make_one_rel函式#6-索...SQL原始碼函式
- PostgreSQL 原始碼解讀(16)- 查詢語句#1(基礎:關係代數)SQL原始碼
- PostgreSQL 原始碼解讀(95)- 查詢語句#78(ExecHashJoin函式#4-H...SQL原始碼函式
- PostgreSQL 原始碼解讀(97)- 查詢語句#79(ExecHashJoin函式#5-H...SQL原始碼函式
- PostgreSQL 原始碼解讀(88)- 查詢語句#73(SeqNext函式#1)SQL原始碼函式
- PostgreSQL 原始碼解讀(89)- 查詢語句#74(SeqNext函式#2)SQL原始碼函式
- PostgreSQL 原始碼解讀(46)- 查詢語句#31(query_planner函式#7)SQL原始碼函式
- PostgreSQL 原始碼解讀(47)- 查詢語句#32(query_planner函式#8)SQL原始碼函式
- PostgreSQL 原始碼解讀(48)- 查詢語句#33(query_planner函式#9)SQL原始碼函式