溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

PostgreSQL 源碼解讀(205)- 查詢#118(數(shù)據(jù)結構RangeTblEntry)

發(fā)布時間:2020-08-16 22:16:26 來源:ITPUB博客 閱讀:554 作者:husthxd 欄目:關系型數(shù)據(jù)庫

本節(jié)簡單介紹了PostgreSQL在執(zhí)行邏輯優(yōu)化中對應Relation的數(shù)據(jù)結構:RangeTblEntry.

一、數(shù)據(jù)結構

RangeTblEntry
RTE可能是普通表/FROM中的子查詢/JOIN語句的結果等(只有顯式的JOIN語法會產生RTE,由多個FROM項生成的隱式連接則不會生成.這是因為 我們只需要RTE來處理SQL特性,比如外部連接和連接輸出列別名)


/*--------------------
 * RangeTblEntry -
 *    A range table is a List of RangeTblEntry nodes.
 *    RangeTblEntry節(jié)點鏈表
 *
 *    A range table entry may represent a plain relation, a sub-select in
 *    FROM, or the result of a JOIN clause.  (Only explicit JOIN syntax
 *    produces an RTE, not the implicit join resulting from multiple FROM
 *    items.  This is because we only need the RTE to deal with SQL features
 *    like outer joins and join-output-column aliasing.)  Other special
 *    RTE types also exist, as indicated by RTEKind.
 *    RTE可能是普通表/FROM中的子查詢/JOIN語句的結果.
 *    (只有顯示的JOIN語法會產生RTE,由多個FROM項生成的隱式連接則不會生成.這是因為
 *     我們只需要RTE來處理SQL特性,比如外部連接和連接輸出列別名)
 *
 *    Note that we consider RTE_RELATION to cover anything that has a pg_class
 *    entry.  relkind distinguishes the sub-cases.
 *    注意RTE_RELATION指代了存儲在pg_class中的relation信息.
 *
 *    alias is an Alias node representing the AS alias-clause attached to the
 *    FROM expression, or NULL if no clause.
 *    alias是FROM表達式中AS別名子句中的Alias節(jié)點.
 *
 *    eref is the table reference name and column reference names (either
 *    real or aliases).  Note that system columns (OID etc) are not included
 *    in the column list.
 *    eref->aliasname is required to be present, and should generally be used
 *    to identify the RTE for error messages etc.
 *    eref是表和列引用名稱.要注意的是系統(tǒng)列(如OID)不在列鏈表中.
 *
 *    In RELATION RTEs, the colnames in both alias and eref are indexed by
 *    physical attribute number; this means there must be colname entries for
 *    dropped columns.  When building an RTE we insert empty strings ("") for
 *    dropped columns.  Note however that a stored rule may have nonempty
 *    colnames for columns dropped since the rule was created (and for that
 *    matter the colnames might be out of date due to column renamings).
 *    The same comments apply to FUNCTION RTEs when a function's return type
 *    is a named composite type.
 *    在RELATION RTEs中,別名和eref都通過物理屬性編號來索引.
 *
 *    In JOIN RTEs, the colnames in both alias and eref are one-to-one with
 *    joinaliasvars entries.  A JOIN RTE will omit columns of its inputs when
 *    those columns are known to be dropped at parse time.  Again, however,
 *    a stored rule might contain entries for columns dropped since the rule
 *    was created.  (This is only possible for columns not actually referenced
 *    in the rule.)  When loading a stored rule, we replace the joinaliasvars
 *    items for any such columns with null pointers.  (We can't simply delete
 *    them from the joinaliasvars list, because that would affect the attnums
 *    of Vars referencing the rest of the list.)
 *    在JOIN RTEs中,不管是別名還是eref與joinaliasvars是一一對應的.
 *    JOIN RTE會省略掉在解析階段發(fā)現(xiàn)的需要drop的列.
 *    但是,已存儲的規(guī)則可能包含已drop的列.
 *
 *    inh is true for relation references that should be expanded to include
 *    inheritance children, if the rel has any.  This *must* be false for
 *    RTEs other than RTE_RELATION entries.
 *    如關系引用需要擴展用于包含繼承子關系,則inh字段為T.除了RTE_RELATION條目,其他RTEs必須為F.
 *
 *    inFromCl marks those range variables that are listed in the FROM clause.
 *    It's false for RTEs that are added to a query behind the scenes, such
 *    as the NEW and OLD variables for a rule, or the subqueries of a UNION.
 *    This flag is not used anymore during parsing, since the parser now uses
 *    a separate "namespace" data structure to control visibility, but it is
 *    needed by ruleutils.c to determine whether RTEs should be shown in
 *    decompiled queries.
 *    inFromCl標記了FROM語句包含了哪些RangeVar.
 *    在解析階段,該標記不會使用,因為解析器使用獨立的"namespace"數(shù)據(jù)結構來控制可見性,
 *      但在ruleutils.c中需要用到該標記來確定RTEs是否在反編譯查詢中顯示.
 *
 *    requiredPerms and checkAsUser specify run-time access permissions
 *    checks to be performed at query startup.  The user must have *all*
 *    of the permissions that are OR'd together in requiredPerms (zero
 *    indicates no permissions checking).  If checkAsUser is not zero,
 *    then do the permissions checks using the access rights of that user,
 *    not the current effective user ID.  (This allows rules to act as
 *    setuid gateways.)  Permissions checks only apply to RELATION RTEs.
 *    requiredPerms和checkAsUser用于表示在查詢啟動時需要檢查的運行時訪問權限.
 *
 *    For SELECT/INSERT/UPDATE permissions, if the user doesn't have
 *    table-wide permissions then it is sufficient to have the permissions
 *    on all columns identified in selectedCols (for SELECT) and/or
 *    insertedCols and/or updatedCols (INSERT with ON CONFLICT DO UPDATE may
 *    have all 3).  selectedCols, insertedCols and updatedCols are bitmapsets,
 *    which cannot have negative integer members, so we subtract
 *    FirstLowInvalidHeapAttributeNumber from column numbers before storing
 *    them in these fields.  A whole-row Var reference is represented by
 *    setting the bit for InvalidAttrNumber.
 *    對于SELECT/INSERT/UPDATE權限,如果用戶沒有表級權限,但有足夠的權限訪問在
 *    selectedCols (SELECT) and/or
 *    insertedCols and/or updatedCols (INSERT with ON CONFLICT DO UPDATE may
 *    have all 3)中定義的列.
 *
 *    updatedCols is also used in some other places, for example, to determine
 *    which triggers to fire and in FDWs to know which changed columns they
 *    need to ship off.  Generated columns that are caused to be updated by an
 *    update to a base column are collected in extraUpdatedCols.  This is not
 *    considered for permission checking, but it is useful in those places
 *    that want to know the full set of columns being updated as opposed to
 *    only the ones the user explicitly mentioned in the query.  (There is
 *    currently no need for an extraInsertedCols, but it could exist.)
 *    updatedCols可能會用于其他地方,比如用于確定哪個觸發(fā)器會被觸發(fā),在FDWs中哪些修改的列需要發(fā)送等.
 *
 *    securityQuals is a list of security barrier quals (boolean expressions),
 *    to be tested in the listed order before returning a row from the
 *    relation.  It is always NIL in parser output.  Entries are added by the
 *    rewriter to implement security-barrier views and/or row-level security.
 *    Note that the planner turns each boolean expression into an implicitly
 *    AND'ed sublist, as is its usual habit with qualification expressions.
 *    securityQuals是安全欄表達式鏈表(布爾表達式),在返回行前用于校驗.
 *--------------------
 */
typedef enum RTEKind
{
  //常規(guī)的關系引用
  RTE_RELATION,       /* ordinary relation reference */
  //FROM中的子查詢
  RTE_SUBQUERY,       /* subquery in FROM */
  //JOIN
  RTE_JOIN,         /* join */
  //FROM中的函數(shù)
  RTE_FUNCTION,       /* function in FROM */
  //TableFunc(..,列鏈表)
  RTE_TABLEFUNC,        /* TableFunc(.., column list) */
  //VALUES (<exprlist>), (<exprlist>), ...
  RTE_VALUES,         /* VALUES (<exprlist>), (<exprlist>), ... */
  //CTE
  RTE_CTE,          /* common table expr (WITH list element) */
  //tuplestore,比如AFTER觸發(fā)器
  RTE_NAMEDTUPLESTORE,    /* tuplestore, e.g. for AFTER triggers */
  //表示空的FROM語句.通過規(guī)劃器添加,在解析和重寫階段不會出現(xiàn)
  RTE_RESULT          /* RTE represents an empty FROM clause; such
                 * RTEs are added by the planner, they're not
                 * present during parsing or rewriting */
} RTEKind;
typedef struct RangeTblEntry
{
  NodeTag   type;
  //詳見上述說明
  RTEKind   rtekind;    /* see above */
  /*
   * XXX the fields applicable to only some rte kinds should be merged into
   * a union.  I didn't do this yet because the diffs would impact a lot of
   * code that is being actively worked on.  FIXME someday.
   */
  /*
   * Fields valid for a plain relation RTE (else zero):
   * 以下字段對普通關系RTE有用(其他類型的RTE,值為0)
   *
   * As a special case, RTE_NAMEDTUPLESTORE can also set relid to indicate
   * that the tuple format of the tuplestore is the same as the referenced
   * relation.  This allows plans referencing AFTER trigger transition
   * tables to be invalidated if the underlying table is altered.
   * 作為一個特例,RTE_NAMEDTUPLESTORE可設置relid,用以表示該tuple是屬于哪個relation的.
   *
   * rellockmode is really LOCKMODE, but it's declared int to avoid having
   * to include lock-related headers here.  It must be RowExclusiveLock if
   * the RTE is an INSERT/UPDATE/DELETE target, else RowShareLock if the RTE
   * is a SELECT FOR UPDATE/FOR SHARE target, else AccessShareLock.
   * rellockmode是實際的LOCKMODE,定義為int類型是為了避免包含鎖相關的頭文件.
   * 如果RTE是INSERT/UPDATE/DELETE,必須是RowExclusiveLock,
   * 如果是SELECT FOR UPDATE/FOR SHARE,是RowShareLock
   * 否則,是AccessShareLock
   *
   * Note: in some cases, rule expansion may result in RTEs that are marked
   * with RowExclusiveLock even though they are not the target of the
   * current query; this happens if a DO ALSO rule simply scans the original
   * target table.  We leave such RTEs with their original lockmode so as to
   * avoid getting an additional, lesser lock.
   */
  Oid     relid;      /* OID of the relation */
  char    relkind;    /* relation kind (see pg_class.relkind) */
  int     rellockmode;  /* lock level that query requires on the rel */
  struct TableSampleClause *tablesample;  /* sampling info, or NULL */
  /*
   * Fields valid for a subquery RTE (else NULL):
   * 用于子查詢
   */
  //子查詢
  Query    *subquery;   /* the sub-query */
  //來自于安全欄視圖?
  bool    security_barrier; /* is from security_barrier view? */
  /*
   * Fields valid for a join RTE (else NULL/zero):
   * 用于連接RTE(否則為NULL/0)
   *
   * joinaliasvars is a list of (usually) Vars corresponding to the columns
   * of the join result.  An alias Var referencing column K of the join
   * result can be replaced by the K'th element of joinaliasvars --- but to
   * simplify the task of reverse-listing aliases correctly, we do not do
   * that until planning time.  In detail: an element of joinaliasvars can
   * be a Var of one of the join's input relations, or such a Var with an
   * implicit coercion to the join's output column type, or a COALESCE
   * expression containing the two input column Vars (possibly coerced).
   * Within a Query loaded from a stored rule, it is also possible for
   * joinaliasvars items to be null pointers, which are placeholders for
   * (necessarily unreferenced) columns dropped since the rule was made.
   * Also, once planning begins, joinaliasvars items can be almost anything,
   * as a result of subquery-flattening substitutions.
   * joinaliasvars是對應join結果的Vars鏈表.
   * 引用連接結果列K的別名Var可以通過joinaliasvars中的第K個元素代替,這一步在計劃階段才去做.
   */
  JoinType  jointype;   /* type of join */
  List     *joinaliasvars;  /* list of alias-var expansions */
  /*
   * Fields valid for a function RTE (else NIL/zero):
   * 函數(shù)RTE
   *
   * When funcordinality is true, the eref->colnames list includes an alias
   * for the ordinality column.  The ordinality column is otherwise
   * implicit, and must be accounted for "by hand" in places such as
   * expandRTE().
   * funcordinality為T,則eref->colnames鏈表包含原列的別名.
   */
  List     *functions;    /* list of RangeTblFunction nodes */
  bool    funcordinality; /* is this called WITH ORDINALITY? */
  /*
   * Fields valid for a TableFunc RTE (else NULL):
   * 用于TableFunc RTE
   */
  TableFunc  *tablefunc;
  /*
   * Fields valid for a values RTE (else NIL):
   * 用于Values RTE
   */
  List     *values_lists; /* list of expression lists */
  /*
   * Fields valid for a CTE RTE (else NULL/zero):
   * 用于CTE RTE
   */
  //WITH鏈表條目名稱
  char     *ctename;    /* name of the WITH list item */
  //查詢層次編號
  Index   ctelevelsup;  /* number of query levels up */
  //是否遞歸?
  bool    self_reference; /* is this a recursive self-reference? */
  /*
   * Fields valid for CTE, VALUES, ENR, and TableFunc RTEs (else NIL):
   * 用于CTE, VALUES, ENR, and TableFunc RTEs
   *
   * We need these for CTE RTEs so that the types of self-referential
   * columns are well-defined.  For VALUES RTEs, storing these explicitly
   * saves having to re-determine the info by scanning the values_lists. For
   * ENRs, we store the types explicitly here (we could get the information
   * from the catalogs if 'relid' was supplied, but we'd still need these
   * for TupleDesc-based ENRs, so we might as well always store the type
   * info here).  For TableFuncs, these fields are redundant with data in
   * the TableFunc node, but keeping them here allows some code sharing with
   * the other cases.
   * CTE : 自引用列可被定義.
   * VALUES : 顯式存儲這些信息可以避免掃描values_lists.
   * ENRs : 顯式存儲
   * TableFuncs : 這些字段與TableFunc節(jié)點中的數(shù)據(jù)重復,用于共享信息
   *
   * For ENRs only, we have to consider the possibility of dropped columns.
   * A dropped column is included in these lists, but it will have zeroes in
   * all three lists (as well as an empty-string entry in eref).  Testing
   * for zero coltype is the standard way to detect a dropped column.
   * 對于ERNs,不得不考慮已刪除字段的可能性.
   */
  List     *coltypes;   /* OID list of column type OIDs */
  List     *coltypmods;   /* integer list of column typmods */
  List     *colcollations;  /* OID list of column collation OIDs */
  /*
   * Fields valid for ENR RTEs (else NULL/zero):
   * ENR RTEs的字段
   */
  char     *enrname;    /* name of ephemeral named relation */
  double    enrtuples;    /* estimated or actual from caller */
  /*
   * Fields valid in all RTEs:
   * 所有RTE都有的字段
   */
  //用戶自定義別名
  Alias    *alias;      /* user-written alias clause, if any */
  //已擴展的引用名
  Alias    *eref;     /* expanded reference names */
  //子查詢/函數(shù)/VALUES是LATERAL
  bool    lateral;    /* subquery, function, or values is LATERAL? */
  //是否繼承?
  bool    inh;      /* inheritance requested? */
  //在FROM中出現(xiàn)?
  bool    inFromCl;   /* present in FROM clause? */
  //訪問權限位掩碼
  AclMode   requiredPerms;  /* bitmask of required access permissions */
  //如有效,則使用此角色檢查訪問權限
  Oid     checkAsUser;  /* if valid, check access as this role */
  //需要SELECT的權限
  Bitmapset  *selectedCols; /* columns needing SELECT permission */
  Bitmapset  *insertedCols; /* columns needing INSERT permission */
  Bitmapset  *updatedCols;  /* columns needing UPDATE permission */
  //將要被update的列
  Bitmapset  *extraUpdatedCols; /* generated columns being updated */
  //需應用的安全欄
  List     *securityQuals;  /* security barrier quals to apply, if any */
} RangeTblEntry;

二、源碼解讀

N/A

三、跟蹤分析

測試SQL語句:


-- 用于測試的查詢語句
testdb=# select * from (
testdb(# select t_dwxx.dwmc,t_grxx.grbh,t_grxx.xm,t_jfxx.ny,t_jfxx.je
testdb(# from t_dwxx inner join t_grxx on t_dwxx.dwbh = t_grxx.dwbh
testdb(# inner join t_jfxx on t_grxx.grbh = t_jfxx.grbh
testdb(# where t_dwxx.dwbh IN ('1001')
testdb(# union all
testdb(# select t_dwxx.dwmc,t_grxx.grbh,t_grxx.xm,t_jfxx.ny,t_jfxx.je
testdb(# from t_dwxx inner join t_grxx on t_dwxx.dwbh = t_grxx.dwbh
testdb(# inner join t_jfxx on t_grxx.grbh = t_jfxx.grbh
testdb(# where t_dwxx.dwbh IN ('1002') 
testdb(# ) as ret
testdb-# order by ret.grbh
testdb-# limit 4;

樣例數(shù)據(jù)如下:


...
(gdb) set $rtable=$query->rtable
(gdb) p *$rtable
$8 = {type = T_List, length = 3, head = 0x170be48, tail = 0x170f6b0}
(gdb) p *(Node *)($rtable->head->data.ptr_value)
$9 = {type = T_RangeTblEntry}
(gdb) p *(RangeTblEntry *)($rtable->head->data.ptr_value)
$10 = {type = T_RangeTblEntry, rtekind = RTE_SUBQUERY, relid = 0, relkind = 0 '\000', tablesample = 0x0, 
  subquery = 0x1667500, 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 = 0x1666d40, eref = 0x170bc18, lateral = false, inh = true, 
  inFromCl = true, requiredPerms = 2, checkAsUser = 0, selectedCols = 0x0, insertedCols = 0x0, 
  updatedCols = 0x0, securityQuals = 0x0}
(gdb) set $rte=(RangeTblEntry *)($rtable->head->data.ptr_value)
(gdb) p *$rte->subquery
$12 = {type = T_Query, commandType = CMD_SELECT, querySource = QSRC_ORIGINAL, queryId = 0, canSetTag = true, 
  utilityStmt = 0x0, resultRelation = 0, hasAggs = false, hasWindowFuncs = false, hasTargetSRFs = false, 
  hasSubLinks = false, hasDistinctOn = false, hasRecursive = false, hasModifyingCTE = false, 
  hasForUpdate = false, hasRowSecurity = false, cteList = 0x0, rtable = 0x16fe4e8, jointree = 0x170bbe8, 
  targetList = 0x170b358, override = OVERRIDING_NOT_SET, onConflict = 0x0, returningList = 0x0, 
  groupClause = 0x0, groupingSets = 0x0, havingQual = 0x0, windowClause = 0x0, distinctClause = 0x0, 
  sortClause = 0x0, limitOffset = 0x0, limitCount = 0x0, rowMarks = 0x0, setOperations = 0x1667610, 
  constraintDeps = 0x0, withCheckOptions = 0x0, stmt_location = 0, stmt_len = 0}
(gdb) p *$rte->alias
$13 = {type = T_Alias, aliasname = 0x1666d28 "ret", colnames = 0x0}
(gdb) p *$rte->eref
$14 = {type = T_Alias, aliasname = 0x170bc48 "ret", colnames = 0x170bcb8}
(gdb) p *$rte->eref->colnames
$15 = {type = T_List, length = 5, head = 0x170bc98, tail = 0x170be28}
(gdb) p *(Node *)$rte->eref->colnames->head->data.ptr_value
$16 = {type = T_String}
(gdb) p *(Value *)$rte->eref->colnames->head->data.ptr_value
$17 = {type = T_String, val = {ival = 24165472, str = 0x170bc60 "dwmc"}}
---->subquery
(gdb) p *(RangeTblEntry *)$rte->subquery->rtable->head->data.ptr_value
$26 = {type = T_RangeTblEntry, rtekind = RTE_SUBQUERY, relid = 0, relkind = 0 '\000', tablesample = 0x0, 
  subquery = 0x16faf98, 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 = 0x16fe240, eref = 0x16fe290, lateral = false, inh = false, 
  inFromCl = false, requiredPerms = 0, checkAsUser = 0, selectedCols = 0x0, insertedCols = 0x0, 
  updatedCols = 0x0, securityQuals = 0x0}
(gdb) set $rte_sq_rte=((RangeTblEntry *)$rte->subquery->rtable->head->data.ptr_value)
(gdb) p *(RangeTblEntry *)$rte_sq_rte->subquery->rtable->head->data.ptr_value
$30 = {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 = 0x16677c0, lateral = false, inh = true, inFromCl = true, 
  requiredPerms = 2, checkAsUser = 0, selectedCols = 0x16fbda8, insertedCols = 0x0, updatedCols = 0x0, 
  securityQuals = 0x0}
(gdb) set $rte_sq_rte_sq_rte=(RangeTblEntry *)$rte_sq_rte->subquery->rtable->head->data.ptr_value
(gdb) p *$rte_sq_rte_sq_rte
$42 = {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 = 0x16677c0, lateral = false, inh = true, inFromCl = true, 
  requiredPerms = 2, checkAsUser = 0, selectedCols = 0x16fbda8, insertedCols = 0x0, updatedCols = 0x0, 
  securityQuals = 0x0}
(gdb) set $rte_sq_rte_sq_rtable=$rte_sq_rte->subquery->rtable
(gdb) p *(RangeTblEntry *)($rte_sq_rte_sq_rtable->head->data.ptr_value)
$60 = {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 = 0x16677c0, lateral = false, inh = true, inFromCl = true, 
  requiredPerms = 2, checkAsUser = 0, selectedCols = 0x16fbda8, insertedCols = 0x0, updatedCols = 0x0, 
  securityQuals = 0x0}
(gdb) p *(RangeTblEntry *)($rte_sq_rte_sq_rtable->head->next->data.ptr_value)
$61 = {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 = 0x16fb4f0, lateral = false, inh = true, inFromCl = true, 
  requiredPerms = 2, checkAsUser = 0, selectedCols = 0x16fbe10, insertedCols = 0x0, updatedCols = 0x0, 
  securityQuals = 0x0}
(gdb) p *(RangeTblEntry *)($rte_sq_rte_sq_rtable->head->next->next->data.ptr_value)
$62 = {type = T_RangeTblEntry, rtekind = RTE_JOIN, relid = 0, relkind = 0 '\000', tablesample = 0x0, 
  subquery = 0x0, security_barrier = false, jointype = JOIN_INNER, joinaliasvars = 0x16fbff8, 
  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 = 0x16fc318, lateral = false, inh = false, inFromCl = true, 
  requiredPerms = 0, checkAsUser = 0, selectedCols = 0x0, insertedCols = 0x0, updatedCols = 0x0, 
  securityQuals = 0x0}
(gdb) p *(RangeTblEntry *)($rte_sq_rte_sq_rtable->head->next->next->next->data.ptr_value)
$63 = {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 = 0x16fc678, lateral = false, inh = true, inFromCl = true, 
  requiredPerms = 2, checkAsUser = 0, selectedCols = 0x16fd1d0, insertedCols = 0x0, updatedCols = 0x0, 
  securityQuals = 0x0}
(gdb) p *(RangeTblEntry *)($rte_sq_rte_sq_rtable->tail->data.ptr_value)
$64 = {type = T_RangeTblEntry, rtekind = RTE_JOIN, relid = 0, relkind = 0 '\000', tablesample = 0x0, 
  subquery = 0x0, security_barrier = false, jointype = JOIN_INNER, joinaliasvars = 0x16fd3b8, 
  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 = 0x16fd798, lateral = false, inh = false, inFromCl = true, 
  requiredPerms = 0, checkAsUser = 0, selectedCols = 0x0, insertedCols = 0x0, updatedCols = 0x0, 
  securityQuals = 0x0}

四、參考資料

N/A

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI