summaryrefslogtreecommitdiff
path: root/src/include/nodes/pathnodes.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/nodes/pathnodes.h')
-rw-r--r--src/include/nodes/pathnodes.h331
1 files changed, 226 insertions, 105 deletions
diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
index a42333cb92f..44ffc73f155 100644
--- a/src/include/nodes/pathnodes.h
+++ b/src/include/nodes/pathnodes.h
@@ -3,6 +3,8 @@
* pathnodes.h
* Definitions for planner's internal data structures, especially Paths.
*
+ * We don't support copying RelOptInfo, IndexOptInfo, or Path nodes.
+ * There are some subsidiary structs that are useful to copy, though.
*
* Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
@@ -85,20 +87,25 @@ typedef enum UpperRelationKind
* PlannerGlobal holds state for an entire planner invocation; this state
* is shared across all levels of sub-Queries that exist in the command being
* planned.
+ *
+ * Not all fields are printed. (In some cases, there is no print support for
+ * the field type.)
*----------
*/
typedef struct PlannerGlobal
{
+ pg_node_attr(no_copy_equal, no_read)
+
NodeTag type;
/* Param values provided to planner() */
- ParamListInfo boundParams;
+ ParamListInfo boundParams pg_node_attr(read_write_ignore);
/* Plans for SubPlan nodes */
List *subplans;
/* PlannerInfos for SubPlan nodes */
- List *subroots;
+ List *subroots pg_node_attr(read_write_ignore);
/* indices of subplans that require REWIND */
Bitmapset *rewindPlanIDs;
@@ -149,7 +156,7 @@ typedef struct PlannerGlobal
char maxParallelHazard;
/* partition descriptors */
- PartitionDirectory partition_directory;
+ PartitionDirectory partition_directory pg_node_attr(read_write_ignore);
} PlannerGlobal;
/* macro for fetching the Plan associated with a SubPlan node */
@@ -168,6 +175,9 @@ typedef struct PlannerGlobal
*
* For reasons explained in optimizer/optimizer.h, we define the typedef
* either here or in that header, whichever is read first.
+ *
+ * Not all fields are printed. (In some cases, there is no print support for
+ * the field type.)
*----------
*/
#ifndef HAVE_PLANNERINFO_TYPEDEF
@@ -177,6 +187,8 @@ typedef struct PlannerInfo PlannerInfo;
struct PlannerInfo
{
+ pg_node_attr(no_copy_equal, no_read)
+
NodeTag type;
/* the Query being planned */
@@ -189,7 +201,7 @@ struct PlannerInfo
Index query_level;
/* NULL at outermost Query */
- PlannerInfo *parent_root;
+ PlannerInfo *parent_root pg_node_attr(read_write_ignore);
/*
* plan_params contains the expressions that this query level needs to
@@ -208,16 +220,16 @@ struct PlannerInfo
* does not correspond to a base relation, such as a join RTE or an
* unreferenced view RTE; or if the RelOptInfo hasn't been made yet.
*/
- struct RelOptInfo **simple_rel_array;
+ struct RelOptInfo **simple_rel_array pg_node_attr(read_write_ignore);
/* allocated size of array */
- int simple_rel_array_size;
+ int simple_rel_array_size pg_node_attr(read_write_ignore);
/*
* simple_rte_array is the same length as simple_rel_array and holds
* pointers to the associated rangetable entries. Using this is a shade
* faster than using rt_fetch(), mostly due to fewer indirections.
*/
- RangeTblEntry **simple_rte_array;
+ RangeTblEntry **simple_rte_array pg_node_attr(read_write_ignore);
/*
* append_rel_array is the same length as the above arrays, and holds
@@ -225,7 +237,7 @@ struct PlannerInfo
* child_relid, or NULL if the rel is not an appendrel child. The array
* itself is not allocated if append_rel_list is empty.
*/
- struct AppendRelInfo **append_rel_array;
+ struct AppendRelInfo **append_rel_array pg_node_attr(read_write_ignore);
/*
* all_baserels is a Relids set of all base relids (but not "other"
@@ -253,7 +265,7 @@ struct PlannerInfo
* GEQO.
*/
List *join_rel_list;
- struct HTAB *join_rel_hash;
+ struct HTAB *join_rel_hash pg_node_attr(read_write_ignore);
/*
* When doing a dynamic-programming-style join search, join_rel_level[k]
@@ -263,7 +275,7 @@ struct PlannerInfo
* join_rel_level is NULL if not in use.
*/
/* lists of join-relation RelOptInfos */
- List **join_rel_level;
+ List **join_rel_level pg_node_attr(read_write_ignore);
/* index of list being extended */
int join_cur_level;
@@ -355,19 +367,19 @@ struct PlannerInfo
List *sort_pathkeys;
/* Canonicalised partition schemes used in the query. */
- List *part_schemes;
+ List *part_schemes pg_node_attr(read_write_ignore);
/* RelOptInfos we are now trying to join */
- List *initial_rels;
+ List *initial_rels pg_node_attr(read_write_ignore);
/*
* Upper-rel RelOptInfos. Use fetch_upper_rel() to get any particular
* upper rel.
*/
- List *upper_rels[UPPERREL_FINAL + 1];
+ List *upper_rels[UPPERREL_FINAL + 1] pg_node_attr(read_write_ignore);
/* Result tlists chosen by grouping_planner for upper-stage processing */
- struct PathTarget *upper_targets[UPPERREL_FINAL + 1];
+ struct PathTarget *upper_targets[UPPERREL_FINAL + 1] pg_node_attr(read_write_ignore);
/*
* The fully-processed targetlist is kept here. It differs from
@@ -392,12 +404,12 @@ struct PlannerInfo
* Fields filled during create_plan() for use in setrefs.c
*/
/* for GroupingFunc fixup */
- AttrNumber *grouping_map;
+ AttrNumber *grouping_map pg_node_attr(array_size(update_colnos), read_write_ignore);
/* List of MinMaxAggInfos */
List *minmax_aggs;
/* context holding PlannerInfo */
- MemoryContext planner_cxt;
+ MemoryContext planner_cxt pg_node_attr(read_write_ignore);
/* # of pages in all non-dummy tables of query */
Cardinality total_table_pages;
@@ -430,15 +442,15 @@ struct PlannerInfo
* Information about aggregates. Filled by preprocess_aggrefs().
*/
/* AggInfo structs */
- List *agginfos;
+ List *agginfos pg_node_attr(read_write_ignore);
/* AggTransInfo structs */
- List *aggtransinfos;
+ List *aggtransinfos pg_node_attr(read_write_ignore);
/* number w/ DISTINCT/ORDER BY/WITHIN GROUP */
- int numOrderedAggs;
+ int numOrderedAggs pg_node_attr(read_write_ignore);
/* does any agg not support partial mode? */
- bool hasNonPartialAggs;
+ bool hasNonPartialAggs pg_node_attr(read_write_ignore);
/* is any partial agg non-serializable? */
- bool hasNonSerialAggs;
+ bool hasNonSerialAggs pg_node_attr(read_write_ignore);
/*
* These fields are used only when hasRecursion is true:
@@ -446,7 +458,7 @@ struct PlannerInfo
/* PARAM_EXEC ID for the work table */
int wt_param_id;
/* a path for non-recursive term */
- struct Path *non_recursive_path;
+ struct Path *non_recursive_path pg_node_attr(read_write_ignore);
/*
* These fields are workspace for createplan.c
@@ -460,11 +472,11 @@ struct PlannerInfo
* These fields are workspace for setrefs.c. Each is an array
* corresponding to glob->subplans.
*/
- bool *isAltSubplan;
- bool *isUsedSubplan;
+ bool *isAltSubplan pg_node_attr(read_write_ignore);
+ bool *isUsedSubplan pg_node_attr(read_write_ignore);
/* optional private data for join_search_hook, e.g., GEQO */
- void *join_search_private;
+ void *join_search_private pg_node_attr(read_write_ignore);
/* Does this query modify any partition key columns? */
bool partColsUpdated;
@@ -721,6 +733,9 @@ typedef struct PartitionSchemeData *PartitionScheme;
* Furthermore, FULL JOINs add extra nullable_partexprs expressions
* corresponding to COALESCE expressions of the left and right join columns,
* to simplify matching join clauses to those lists.
+ *
+ * Not all fields are printed. (In some cases, there is no print support for
+ * the field type.)
*----------
*/
@@ -764,6 +779,8 @@ typedef enum RelOptKind
typedef struct RelOptInfo
{
+ pg_node_attr(no_copy_equal, no_read)
+
NodeTag type;
RelOptKind reloptkind;
@@ -829,9 +846,9 @@ typedef struct RelOptInfo
/* largest attrno of rel */
AttrNumber max_attr;
/* array indexed [min_attr .. max_attr] */
- Relids *attr_needed;
+ Relids *attr_needed pg_node_attr(read_write_ignore);
/* array indexed [min_attr .. max_attr] */
- int32 *attr_widths;
+ int32 *attr_widths pg_node_attr(read_write_ignore);
/* LATERAL Vars and PHVs referenced by rel */
List *lateral_vars;
/* rels that reference me laterally */
@@ -866,16 +883,18 @@ typedef struct RelOptInfo
/* join is only valid for current user */
bool useridiscurrent;
/* use "struct FdwRoutine" to avoid including fdwapi.h here */
- struct FdwRoutine *fdwroutine;
- void *fdw_private;
+ struct FdwRoutine *fdwroutine pg_node_attr(read_write_ignore);
+ void *fdw_private pg_node_attr(read_write_ignore);
/*
* cache space for remembering if we have proven this relation unique
+ *
+ * can't print unique_for_rels/non_unique_for_rels; BMSes aren't Nodes
*/
/* known unique for these other relid set(s) */
- List *unique_for_rels;
+ List *unique_for_rels pg_node_attr(read_write_ignore);
/* known not unique for these set(s) */
- List *non_unique_for_rels;
+ List *non_unique_for_rels pg_node_attr(read_write_ignore);
/*
* used by various scans and joins:
@@ -903,24 +922,24 @@ typedef struct RelOptInfo
* used for partitioned relations:
*/
/* Partitioning scheme */
- PartitionScheme part_scheme;
+ PartitionScheme part_scheme pg_node_attr(read_write_ignore);
/*
* Number of partitions; -1 if not yet set; in case of a join relation 0
* means it's considered unpartitioned
*/
- int nparts;
+ int nparts pg_node_attr(read_write_ignore);
/* Partition bounds */
- struct PartitionBoundInfoData *boundinfo;
+ struct PartitionBoundInfoData *boundinfo pg_node_attr(read_write_ignore);
/* True if partition bounds were created by partition_bounds_merge() */
bool partbounds_merged;
/* Partition constraint, if not the root */
- List *partition_qual;
+ List *partition_qual pg_node_attr(read_write_ignore);
/*
* Array of RelOptInfos of partitions, stored in the same order as bounds
*/
- struct RelOptInfo **part_rels;
+ struct RelOptInfo **part_rels pg_node_attr(read_write_ignore);
/*
* Bitmap with members acting as indexes into the part_rels[] array to
@@ -930,9 +949,9 @@ typedef struct RelOptInfo
/* Relids set of all partition relids */
Relids all_partrels;
/* Non-nullable partition key expressions */
- List **partexprs;
+ List **partexprs pg_node_attr(read_write_ignore);
/* Nullable partition key expressions */
- List **nullable_partexprs;
+ List **nullable_partexprs pg_node_attr(read_write_ignore);
} RelOptInfo;
/*
@@ -993,14 +1012,16 @@ typedef struct IndexOptInfo IndexOptInfo;
struct IndexOptInfo
{
+ pg_node_attr(no_copy_equal, no_read)
+
NodeTag type;
/* OID of the index relation */
Oid indexoid;
/* tablespace of index (not table) */
Oid reltablespace;
- /* back-link to index's table */
- RelOptInfo *rel;
+ /* back-link to index's table; don't print, else infinite recursion */
+ RelOptInfo *rel pg_node_attr(read_write_ignore);
/*
* index-size statistics (from pg_class and elsewhere)
@@ -1021,30 +1042,38 @@ struct IndexOptInfo
int nkeycolumns;
/*
+ * array fields aren't really worth the trouble to print
+ */
+
+ /*
* column numbers of index's attributes both key and included columns, or
* 0
*/
- int *indexkeys;
+ int *indexkeys pg_node_attr(read_write_ignore);
/* OIDs of collations of index columns */
- Oid *indexcollations;
+ Oid *indexcollations pg_node_attr(read_write_ignore);
/* OIDs of operator families for columns */
- Oid *opfamily;
+ Oid *opfamily pg_node_attr(read_write_ignore);
/* OIDs of opclass declared input data types */
- Oid *opcintype;
+ Oid *opcintype pg_node_attr(read_write_ignore);
/* OIDs of btree opfamilies, if orderable */
- Oid *sortopfamily;
+ Oid *sortopfamily pg_node_attr(read_write_ignore);
/* is sort order descending? */
- bool *reverse_sort;
+ bool *reverse_sort pg_node_attr(read_write_ignore);
/* do NULLs come first in the sort order? */
- bool *nulls_first;
+ bool *nulls_first pg_node_attr(read_write_ignore);
/* opclass-specific options for columns */
- bytea **opclassoptions;
+ bytea **opclassoptions pg_node_attr(read_write_ignore);
/* which index cols can be returned in an index-only scan? */
- bool *canreturn;
+ bool *canreturn pg_node_attr(read_write_ignore);
/* OID of the access method (in pg_am) */
Oid relam;
- /* expressions for non-simple index columns */
- List *indexprs;
+
+ /*
+ * expressions for non-simple index columns; redundant to print since we
+ * print indextlist
+ */
+ List *indexprs pg_node_attr(read_write_ignore);
/* predicate if a partial index, else NIL */
List *indpred;
@@ -1071,17 +1100,17 @@ struct IndexOptInfo
* Remaining fields are copied from the index AM's API struct
* (IndexAmRoutine)
*/
- bool amcanorderbyop;
- bool amoptionalkey;
- bool amsearcharray;
- bool amsearchnulls;
+ bool amcanorderbyop pg_node_attr(read_write_ignore);
+ bool amoptionalkey pg_node_attr(read_write_ignore);
+ bool amsearcharray pg_node_attr(read_write_ignore);
+ bool amsearchnulls pg_node_attr(read_write_ignore);
/* does AM have amgettuple interface? */
- bool amhasgettuple;
+ bool amhasgettuple pg_node_attr(read_write_ignore);
/* does AM have amgetbitmap interface? */
- bool amhasgetbitmap;
- bool amcanparallel;
+ bool amhasgetbitmap pg_node_attr(read_write_ignore);
+ bool amcanparallel pg_node_attr(read_write_ignore);
/* does AM have ammarkpos interface? */
- bool amcanmarkpos;
+ bool amcanmarkpos pg_node_attr(read_write_ignore);
/* Rather than include amapi.h here, we declare amcostestimate like this */
void (*amcostestimate) (); /* AM's cost estimator */
};
@@ -1096,6 +1125,8 @@ struct IndexOptInfo
*/
typedef struct ForeignKeyOptInfo
{
+ pg_node_attr(custom_read_write, no_copy_equal, no_read)
+
NodeTag type;
/*
@@ -1109,11 +1140,11 @@ typedef struct ForeignKeyOptInfo
/* number of columns in the foreign key */
int nkeys;
/* cols in referencing table */
- AttrNumber conkey[INDEX_MAX_KEYS];
+ AttrNumber conkey[INDEX_MAX_KEYS] pg_node_attr(array_size(nkeys));
/* cols in referenced table */
- AttrNumber confkey[INDEX_MAX_KEYS];
+ AttrNumber confkey[INDEX_MAX_KEYS] pg_node_attr(array_size(nkeys));
/* PK = FK operator OIDs */
- Oid conpfeqop[INDEX_MAX_KEYS];
+ Oid conpfeqop[INDEX_MAX_KEYS] pg_node_attr(array_size(nkeys));
/*
* Derived info about whether FK's equality conditions match the query:
@@ -1144,16 +1175,21 @@ typedef struct ForeignKeyOptInfo
*/
typedef struct StatisticExtInfo
{
+ pg_node_attr(no_copy_equal, no_read)
+
NodeTag type;
/* OID of the statistics row */
Oid statOid;
/* includes child relations */
- bool inherit;
+ bool inherit pg_node_attr(read_write_ignore);
- /* back-link to statistic's table */
- RelOptInfo *rel;
+ /*
+ * back-link to statistic's table; don't print, infinite recursion on plan
+ * tree dump
+ */
+ RelOptInfo *rel pg_node_attr(read_write_ignore);
/* statistics kind of this entry */
char kind;
@@ -1204,9 +1240,15 @@ typedef struct StatisticExtInfo
*
* NB: if ec_merged isn't NULL, this class has been merged into another, and
* should be ignored in favor of using the pointed-to class.
+ *
+ * NB: EquivalenceClasses are never copied after creation. Therefore,
+ * copyObject() copies pointers to them as pointers, and equal() compares
+ * pointers to EquivalenceClasses via pointer equality.
*/
typedef struct EquivalenceClass
{
+ pg_node_attr(custom_read_write, no_copy_equal, no_read)
+
NodeTag type;
List *ec_opfamilies; /* btree operator family OIDs */
@@ -1257,6 +1299,8 @@ typedef struct EquivalenceClass
*/
typedef struct EquivalenceMember
{
+ pg_node_attr(no_copy_equal, no_read)
+
NodeTag type;
Expr *em_expr; /* the expression represented */
@@ -1286,6 +1330,8 @@ typedef struct EquivalenceMember
*/
typedef struct PathKey
{
+ pg_node_attr(no_read)
+
NodeTag type;
EquivalenceClass *pk_eclass; /* the value that is ordered */
@@ -1299,6 +1345,8 @@ typedef struct PathKey
*/
typedef struct PathKeyInfo
{
+ pg_node_attr(no_read)
+
NodeTag type;
List *pathkeys;
List *clauses;
@@ -1341,13 +1389,15 @@ typedef enum VolatileFunctionStatus
*/
typedef struct PathTarget
{
+ pg_node_attr(no_copy_equal, no_read)
+
NodeTag type;
/* list of expressions to be computed */
List *exprs;
/* corresponding sort/group refnos, or 0 */
- Index *sortgrouprefs;
+ Index *sortgrouprefs pg_node_attr(array_size(exprs));
/* cost of evaluating the expressions */
QualCost cost;
@@ -1380,6 +1430,8 @@ typedef struct PathTarget
*/
typedef struct ParamPathInfo
{
+ pg_node_attr(no_copy_equal, no_read)
+
NodeTag type;
Relids ppi_req_outer; /* rels supplying parameters used by path */
@@ -1416,22 +1468,43 @@ typedef struct ParamPathInfo
*
* "pathkeys" is a List of PathKey nodes (see above), describing the sort
* ordering of the path's output rows.
+ *
+ * We do not support copying Path trees, mainly because the circular linkages
+ * between RelOptInfo and Path nodes can't be handled easily in a simple
+ * depth-first traversal. We also don't have read support at the moment.
*/
typedef struct Path
{
+ pg_node_attr(no_copy_equal, no_read)
+
NodeTag type;
/* tag identifying scan/join method */
NodeTag pathtype;
- /* the relation this path can build */
- RelOptInfo *parent;
+ /*
+ * the relation this path can build
+ *
+ * We do NOT print the parent, else we'd be in infinite recursion. We can
+ * print the parent's relids for identification purposes, though.
+ */
+ RelOptInfo *parent pg_node_attr(write_only_relids);
- /* list of Vars/Exprs, cost, width */
- PathTarget *pathtarget;
+ /*
+ * list of Vars/Exprs, cost, width
+ *
+ * We print the pathtarget only if it's not the default one for the rel.
+ */
+ PathTarget *pathtarget pg_node_attr(write_only_nondefault_pathtarget);
- /* parameterization info, or NULL if none */
- ParamPathInfo *param_info;
+ /*
+ * parameterization info, or NULL if none
+ *
+ * We do not print the whole of param_info, since it's printed via
+ * RelOptInfo; it's sufficient and less cluttering to print just the
+ * required outer relids.
+ */
+ ParamPathInfo *param_info pg_node_attr(write_only_req_outer);
/* engage parallel-aware logic? */
bool parallel_aware;
@@ -1539,6 +1612,8 @@ typedef struct IndexPath
*/
typedef struct IndexClause
{
+ pg_node_attr(no_copy_equal, no_read)
+
NodeTag type;
struct RestrictInfo *rinfo; /* original restriction or join clause */
List *indexquals; /* indexqual(s) derived from it */
@@ -1834,6 +1909,8 @@ typedef struct GatherMergePath
typedef struct JoinPath
{
+ pg_node_attr(abstract)
+
Path path;
JoinType jointype;
@@ -2036,6 +2113,8 @@ typedef struct AggPath
typedef struct GroupingSetData
{
+ pg_node_attr(no_copy_equal, no_read)
+
NodeTag type;
List *set; /* grouping set as list of sortgrouprefs */
Cardinality numGroups; /* est. number of result groups */
@@ -2043,6 +2122,8 @@ typedef struct GroupingSetData
typedef struct RollupData
{
+ pg_node_attr(no_copy_equal, no_read)
+
NodeTag type;
List *groupClause; /* applicable subset of parse->groupClause */
List *gsets; /* lists of integer indexes into groupClause */
@@ -2306,10 +2387,18 @@ typedef struct LimitPath
* apply only one. We mark clauses of this kind by setting parent_ec to
* point to the generating EquivalenceClass. Multiple clauses with the same
* parent_ec in the same join are redundant.
+ *
+ * Most fields are ignored for equality, since they may not be set yet, and
+ * should be derivable from the clause anyway.
+ *
+ * parent_ec, left_ec, right_ec are not printed, lest it lead to infinite
+ * recursion in plan tree dump.
*/
typedef struct RestrictInfo
{
+ pg_node_attr(no_read)
+
NodeTag type;
/* the represented clause of WHERE or JOIN */
@@ -2322,22 +2411,22 @@ typedef struct RestrictInfo
bool outerjoin_delayed;
/* see comment above */
- bool can_join;
+ bool can_join pg_node_attr(equal_ignore);
/* see comment above */
- bool pseudoconstant;
+ bool pseudoconstant pg_node_attr(equal_ignore);
/* true if known to contain no leaked Vars */
- bool leakproof;
+ bool leakproof pg_node_attr(equal_ignore);
/* to indicate if clause contains any volatile functions. */
- VolatileFunctionStatus has_volatile;
+ VolatileFunctionStatus has_volatile pg_node_attr(equal_ignore);
/* see comment above */
Index security_level;
/* The set of relids (varnos) actually referenced in the clause: */
- Relids clause_relids;
+ Relids clause_relids pg_node_attr(equal_ignore);
/* The set of relids required to evaluate the clause: */
Relids required_relids;
@@ -2352,84 +2441,89 @@ typedef struct RestrictInfo
* Relids in the left/right side of the clause. These fields are set for
* any binary opclause.
*/
- Relids left_relids;
- Relids right_relids;
+ Relids left_relids pg_node_attr(equal_ignore);
+ Relids right_relids pg_node_attr(equal_ignore);
/*
* Modified clause with RestrictInfos. This field is NULL unless clause
* is an OR clause.
*/
- Expr *orclause;
+ Expr *orclause pg_node_attr(equal_ignore);
/*
* Generating EquivalenceClass. This field is NULL unless clause is
* potentially redundant.
*/
- EquivalenceClass *parent_ec;
+ EquivalenceClass *parent_ec pg_node_attr(equal_ignore, read_write_ignore);
/*
* cache space for cost and selectivity
*/
/* eval cost of clause; -1 if not yet set */
- QualCost eval_cost;
+ QualCost eval_cost pg_node_attr(equal_ignore);
/*
* selectivity for "normal" (JOIN_INNER) semantics; -1 if not yet set; >1
* means a redundant clause
*/
- Selectivity norm_selec;
+ Selectivity norm_selec pg_node_attr(equal_ignore);
/* selectivity for outer join semantics; -1 if not yet set */
- Selectivity outer_selec;
+ Selectivity outer_selec pg_node_attr(equal_ignore);
/*
* opfamilies containing clause operator; valid if clause is
* mergejoinable, else NIL
*/
- List *mergeopfamilies;
+ List *mergeopfamilies pg_node_attr(equal_ignore);
/*
* cache space for mergeclause processing; NULL if not yet set
*/
/* EquivalenceClass containing lefthand */
- EquivalenceClass *left_ec;
+ EquivalenceClass *left_ec pg_node_attr(equal_ignore, read_write_ignore);
/* EquivalenceClass containing righthand */
- EquivalenceClass *right_ec;
+ EquivalenceClass *right_ec pg_node_attr(equal_ignore, read_write_ignore);
/* EquivalenceMember for lefthand */
- EquivalenceMember *left_em;
+ EquivalenceMember *left_em pg_node_attr(equal_ignore);
/* EquivalenceMember for righthand */
- EquivalenceMember *right_em;
- /* list of MergeScanSelCache structs */
- List *scansel_cache;
+ EquivalenceMember *right_em pg_node_attr(equal_ignore);
+
+ /*
+ * List of MergeScanSelCache structs. Those aren't Nodes, so hard to
+ * copy; instead replace with NIL. That has the effect that copying will
+ * just reset the cache. Likewise, can't compare or print them.
+ */
+ List *scansel_cache pg_node_attr(copy_as(NIL), equal_ignore, read_write_ignore);
/*
* transient workspace for use while considering a specific join path; T =
* outer var on left, F = on right
*/
- bool outer_is_left;
+ bool outer_is_left pg_node_attr(equal_ignore);
/*
* copy of clause operator; valid if clause is hashjoinable, else
* InvalidOid
*/
- Oid hashjoinoperator;
+ Oid hashjoinoperator pg_node_attr(equal_ignore);
/*
* cache space for hashclause processing; -1 if not yet set
*/
/* avg bucketsize of left side */
- Selectivity left_bucketsize;
+ Selectivity left_bucketsize pg_node_attr(equal_ignore);
/* avg bucketsize of right side */
- Selectivity right_bucketsize;
+ Selectivity right_bucketsize pg_node_attr(equal_ignore);
/* left side's most common val's freq */
- Selectivity left_mcvfreq;
+ Selectivity left_mcvfreq pg_node_attr(equal_ignore);
/* right side's most common val's freq */
- Selectivity right_mcvfreq;
+ Selectivity right_mcvfreq pg_node_attr(equal_ignore);
/* hash equality operators used for memoize nodes, else InvalidOid */
- Oid left_hasheqoperator;
- Oid right_hasheqoperator;
+ Oid left_hasheqoperator pg_node_attr(equal_ignore);
+ Oid right_hasheqoperator pg_node_attr(equal_ignore);
} RestrictInfo;
/*
@@ -2479,6 +2573,17 @@ typedef struct MergeScanSelCache
* Although the planner treats this as an expression node type, it is not
* recognized by the parser or executor, so we declare it here rather than
* in primnodes.h.
+ *
+ * We intentionally do not compare phexpr. Two PlaceHolderVars with the
+ * same ID and levelsup should be considered equal even if the contained
+ * expressions have managed to mutate to different states. This will
+ * happen during final plan construction when there are nested PHVs, since
+ * the inner PHV will get replaced by a Param in some copies of the outer
+ * PHV. Another way in which it can happen is that initplan sublinks
+ * could get replaced by differently-numbered Params when sublink folding
+ * is done. (The end result of such a situation would be some
+ * unreferenced initplans, which is annoying but not really a problem.) On
+ * the same reasoning, there is no need to examine phrels.
*/
typedef struct PlaceHolderVar
@@ -2486,10 +2591,10 @@ typedef struct PlaceHolderVar
Expr xpr;
/* the represented expression */
- Expr *phexpr;
+ Expr *phexpr pg_node_attr(equal_ignore);
/* base relids syntactically within expr src */
- Relids phrels;
+ Relids phrels pg_node_attr(equal_ignore);
/* ID for PHV (unique within planner run) */
Index phid;
@@ -2562,6 +2667,8 @@ typedef struct SpecialJoinInfo SpecialJoinInfo;
struct SpecialJoinInfo
{
+ pg_node_attr(no_read)
+
NodeTag type;
Relids min_lefthand; /* base relids in minimum LHS for join */
Relids min_righthand; /* base relids in minimum RHS for join */
@@ -2654,7 +2761,7 @@ typedef struct AppendRelInfo
* child column is dropped or doesn't exist in the parent.
*/
int num_child_cols; /* length of array */
- AttrNumber *parent_colnos;
+ AttrNumber *parent_colnos pg_node_attr(array_size(num_child_cols));
/*
* We store the parent table's OID here for inheritance, or InvalidOid for
@@ -2684,6 +2791,8 @@ typedef struct AppendRelInfo
*/
typedef struct RowIdentityVarInfo
{
+ pg_node_attr(no_copy_equal, no_read)
+
NodeTag type;
Var *rowidvar; /* Var to be evaluated (but varno=ROWID_VAR) */
@@ -2720,12 +2829,17 @@ typedef struct RowIdentityVarInfo
typedef struct PlaceHolderInfo
{
+ pg_node_attr(no_read)
+
NodeTag type;
/* ID for PH (unique within planner run) */
Index phid;
- /* copy of PlaceHolderVar tree */
+ /*
+ * copy of PlaceHolderVar tree (should be redundant for comparison, could
+ * be ignored)
+ */
PlaceHolderVar *ph_var;
/* lowest level we can evaluate value at */
@@ -2748,6 +2862,8 @@ typedef struct PlaceHolderInfo
*/
typedef struct MinMaxAggInfo
{
+ pg_node_attr(no_copy_equal, no_read)
+
NodeTag type;
/* pg_proc Oid of the aggregate */
@@ -2759,8 +2875,11 @@ typedef struct MinMaxAggInfo
/* expression we are aggregating on */
Expr *target;
- /* modified "root" for planning the subquery */
- PlannerInfo *subroot;
+ /*
+ * modified "root" for planning the subquery; not printed, too large, not
+ * interesting enough
+ */
+ PlannerInfo *subroot pg_node_attr(read_write_ignore);
/* access path for subquery */
Path *path;
@@ -2821,6 +2940,8 @@ typedef struct MinMaxAggInfo
*/
typedef struct PlannerParamItem
{
+ pg_node_attr(no_copy_equal, no_read)
+
NodeTag type;
Node *item; /* the Var, PlaceHolderVar, or Aggref */