PostgreSQL 源码解读(205)- 查询#118(数据结构RangeTblEntry)

本节简单介绍了PostgreSQL在执行逻辑优化中对应Relation的数据结构:RangeTblEntry.

一、数据结构

RangeTblEntry 
RTE可能是普通表/FROM中的子查询/JOIN语句的结果等(只有显式的JOIN语法会产生RTE,由多个FROM项生成的隐式连接则不会生成.这是因为 我们只需要RTE来处理SQL特性,比如外部连接和连接输出列别名)

/*-------------------- * RangeTblEntry - *    A range table is a List of RangeTblEntry nodes. *    RangeTblEntry节点链表 * *    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节点. * *    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是表和列引用名称.要注意的是系统列(如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会省略掉在解析阶段发现的需要drop的列. *    但是,已存储的规则可能包含已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"数据结构来控制可见性, *      但在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可能会用于其他地方,比如用于确定哪个触发器会被触发,在FDWs中哪些修改的列需要发送等. * *    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{  //常规的关系引用  RTE_RELATION,       /* ordinary relation reference */  //FROM中的子查询  RTE_SUBQUERY,       /* subquery in FROM */  //JOIN  RTE_JOIN,         /* join */  //FROM中的函数  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触发器  RTE_NAMEDTUPLESTORE,    /* tuplestore, e.g. for AFTER triggers */  //表示空的FROM语句.通过规划器添加,在解析和重写阶段不会出现  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):   * 函数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节点中的数据重复,用于共享信息   *   * 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 */  //子查询/函数/VALUES是LATERAL  bool    lateral;    /* subquery, function, or values is LATERAL? */  //是否继承?  bool    inh;      /* inheritance requested? */  //在FROM中出现?  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语句:

郑州妇科医院:http://jbk.39.net/yiyuanzaixian/sysdfkyy/

-- 用于测试的查询语句testdb=# select * from (testdb(# select t_dwxx.dwmc,t_grxx.grbh,t_grxx.xm,t_jfxx.ny,t_jfxx.jetestdb(# from t_dwxx inner join t_grxx on t_dwxx.dwbh = t_grxx.dwbhtestdb(# inner join t_jfxx on t_grxx.grbh = t_jfxx.grbhtestdb(# where t_dwxx.dwbh IN ('1001')testdb(# union alltestdb(# select t_dwxx.dwmc,t_grxx.grbh,t_grxx.xm,t_jfxx.ny,t_jfxx.jetestdb(# from t_dwxx inner join t_grxx on t_dwxx.dwbh = t_grxx.dwbhtestdb(# inner join t_jfxx on t_grxx.grbh = t_jfxx.grbhtestdb(# where t_dwxx.dwbh IN ('1002') testdb(# ) as rettestdb-# order by ret.grbhtestdb-# limit 4;

样例数据如下:

...(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


猜你喜欢

转载自blog.51cto.com/14393794/2412096