forked from huawei/openGauss-server
1404 lines
51 KiB
C
1404 lines
51 KiB
C
/* -------------------------------------------------------------------------
|
|
*
|
|
* plannodes.h
|
|
* definitions for query plan nodes
|
|
*
|
|
*
|
|
* Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
* src/include/nodes/plannodes.h
|
|
*
|
|
* -------------------------------------------------------------------------
|
|
*/
|
|
#ifndef PLANNODES_H
|
|
#define PLANNODES_H
|
|
|
|
#include "access/sdir.h"
|
|
#include "foreign/foreign.h"
|
|
#include "nodes/bitmapset.h"
|
|
#include "nodes/primnodes.h"
|
|
#include "utils/partitionmap.h"
|
|
#include "utils/partitionmap_gs.h"
|
|
#include "optimizer/pruning.h"
|
|
#include "pgxc/locator.h"
|
|
#include "pgxc/nodemgr.h"
|
|
#include "bulkload/dist_fdw.h"
|
|
#include "utils/bloom_filter.h"
|
|
|
|
#define MAX_SPECIAL_BUCKETMAP_NUM 2
|
|
#define BUCKETMAP_DEFAULT_INDEX -1
|
|
|
|
/*
|
|
* Determines if query has to be launched
|
|
* on Coordinators only (SEQUENCE DDL),
|
|
* on Datanodes (normal Remote Queries),
|
|
* or on all Postgres-XC nodes (Utilities and DDL).
|
|
*/
|
|
typedef enum
|
|
{
|
|
EXEC_ON_DATANODES,
|
|
EXEC_ON_COORDS,
|
|
EXEC_ON_ALL_NODES,
|
|
EXEC_ON_NONE
|
|
} RemoteQueryExecType;
|
|
|
|
#define EXEC_CONTAIN_COORDINATOR(exec_type) \
|
|
((exec_type) == EXEC_ON_ALL_NODES || (exec_type) == EXEC_ON_COORDS)
|
|
|
|
#define EXEC_CONTAIN_DATANODE(exec_type) \
|
|
((exec_type) == EXEC_ON_ALL_NODES || (exec_type) == EXEC_ON_DATANODES)
|
|
|
|
/*
|
|
* Determines the position where the RemoteQuery node will run.
|
|
*/
|
|
typedef enum { GATHER, PLAN_ROUTER, SCAN_GATHER } RemoteQueryType;
|
|
|
|
/*
|
|
* @hdfs
|
|
* Determines the optimization mode base on informational constraint.
|
|
* Currently, join Scan and foreign scan about on HDFS foreign table
|
|
* would be optimized.
|
|
*/
|
|
typedef enum { INVALID_MODE, SCAN_OPTIMIZE_MODE, JOIN_OPTIMIZE_MODE } OptimizedMode;
|
|
/* ----------------------------------------------------------------
|
|
* node definitions
|
|
* ----------------------------------------------------------------
|
|
*/
|
|
|
|
typedef struct NodeGroupQueryMem {
|
|
Oid ng_oid;
|
|
char nodegroup[NAMEDATALEN];
|
|
|
|
int query_mem[2]; /* memory in kb */
|
|
} NodeGroupQueryMem;
|
|
|
|
/* ----------------
|
|
* 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.
|
|
* ----------------
|
|
*/
|
|
typedef struct PlannedStmt {
|
|
NodeTag type;
|
|
|
|
CmdType commandType; /* select|insert|update|delete */
|
|
|
|
uint64 queryId; /* query identifier, uniquely indicate this plan in Runtime (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? */
|
|
|
|
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 */
|
|
|
|
Node* utilityStmt; /* non-null if this is DECLARE CURSOR */
|
|
|
|
List* subplans; /* Plan trees for SubPlan expressions */
|
|
|
|
Bitmapset* rewindPlanIDs; /* indices of subplans that require REWIND */
|
|
|
|
List* rowMarks; /* a list of PlanRowMark's */
|
|
|
|
/*
|
|
* Notice: be careful to use relationOids as it may contain non-table OID
|
|
* in some scenarios, e.g. assignment of relationOids in fix_expr_common.
|
|
*/
|
|
List* relationOids; /* contain OIDs of relations the plan depends on */
|
|
|
|
List* invalItems; /* other dependencies, as PlanInvalItems */
|
|
|
|
int nParamExec; /* number of PARAM_EXEC Params used */
|
|
|
|
int num_streams; /* number of stream exist in plan tree */
|
|
|
|
int max_push_sql_num; /* number of split sql want push DN execute */
|
|
|
|
int gather_count; /* gather_count in query */
|
|
|
|
int num_nodes; /* number of data nodes */
|
|
|
|
NodeDefinition* nodesDefinition; /* all data nodes' defination */
|
|
|
|
int instrument_option; /* used for collect instrument data */
|
|
|
|
int num_plannodes; /* how many plan node in this planstmt */
|
|
|
|
int query_mem[2]; /* how many memory the query can use , memory in kb */
|
|
|
|
int assigned_query_mem[2]; /* how many memory the query is assigned */
|
|
|
|
bool is_dynmaic_smp;
|
|
|
|
int dynsmp_max_cpu; /* max avaliable cpu for this dn */
|
|
|
|
int dynsmp_avail_cpu; /* max avaliable cpu for this dn */
|
|
|
|
int dynsmp_cpu_util;
|
|
|
|
int dynsmp_active_statement;
|
|
|
|
double dynsmp_query_estimate_cpu_usge;
|
|
|
|
int dynsmp_plan_optimal_dop; /* the final optimized dop for the plan */
|
|
|
|
int dynsmp_plan_original_dop;
|
|
|
|
int dynsmp_dop_mem_limit; /* memory will put a limit on dop */
|
|
|
|
int dynsmp_min_non_spill_dop; /* optimal dop cannot greater than this */
|
|
|
|
int num_bucketmaps; /* Num of special-bucketmap stored in plannedstmt */
|
|
|
|
uint2* bucketMap[MAX_SPECIAL_BUCKETMAP_NUM]; /* the map information need to be get */
|
|
|
|
char* query_string; /* convey the query string to backend/stream thread of DataNode for debug purpose */
|
|
|
|
List* subplan_ids; /* in which plan id subplan should be inited */
|
|
|
|
List* initPlan; /* initplan in top plan node */
|
|
/* data redistribution for DFS table.
|
|
* dataDestRelIndex is index into the range table. This variable
|
|
* will take effect on data redistribution state.
|
|
*/
|
|
Index dataDestRelIndex;
|
|
|
|
int MaxBloomFilterNum;
|
|
|
|
int query_dop; /* Dop of current query. */
|
|
|
|
double plannertime; /* planner execute time */
|
|
|
|
/* set true in do_query_for_planrouter() for PlannedStmt sent to
|
|
* the compute pool
|
|
*/
|
|
bool in_compute_pool;
|
|
|
|
/* true if there is/are ForeignScan node(s) of OBS foreign table
|
|
* in plantree.
|
|
*/
|
|
bool has_obsrel;
|
|
|
|
List* plan_hint_warning; /* hint warning during plan generation, only used in CN */
|
|
|
|
List* noanalyze_rellist; /* relations and attributes that have no statistics, only used in CN */
|
|
|
|
int ng_num; /* nodegroup number */
|
|
NodeGroupQueryMem* ng_queryMem; /* each nodegroup's query mem */
|
|
bool ng_use_planA; /* true means I am a planA, default false */
|
|
|
|
bool isRowTriggerShippable; /* true if all row triggers are shippable. */
|
|
bool is_stream_plan;
|
|
bool multi_node_hint;
|
|
|
|
uint64 uniqueSQLId;
|
|
} PlannedStmt;
|
|
|
|
typedef struct NodeGroupInfoContext {
|
|
Oid groupOids[MAX_SPECIAL_BUCKETMAP_NUM];
|
|
uint2* bucketMap[MAX_SPECIAL_BUCKETMAP_NUM];
|
|
int num_bucketmaps;
|
|
} NodeGroupInfoContext;
|
|
|
|
/*
|
|
* Determine if this plan step needs excution on current dn
|
|
* RestoreMode is always considered as 'have to' execute
|
|
*/
|
|
#define NeedExecute(plan) \
|
|
(isRestoreMode ? true \
|
|
: (plan->exec_nodes == NULL || plan->exec_nodes->nodeList == NULL || \
|
|
list_member_int((plan)->exec_nodes->nodeList, u_sess->pgxc_cxt.PGXCNodeId)))
|
|
|
|
/* 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))
|
|
|
|
/* ----------------
|
|
* 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;
|
|
|
|
int plan_node_id; /* node id */
|
|
int parent_node_id; /* parent node id */
|
|
RemoteQueryExecType exec_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 global rows plan is expected to emit */
|
|
double multiple;
|
|
int plan_width; /* average row width in bytes */
|
|
int dop; /* degree of parallelism of current plan */
|
|
|
|
/*
|
|
* machine learning model estimations
|
|
*/
|
|
double pred_rows;
|
|
double pred_startup_time;
|
|
double pred_total_time;
|
|
long pred_max_memory;
|
|
/*
|
|
* MPPDB Recursive-Union Support
|
|
*
|
|
* - @recursive_union_plan_nodeid
|
|
* Pointing to its belonging RecursiveUnion's plan node id to indate if we are
|
|
* under RecursiveUnion
|
|
*
|
|
* - @recursive_union_controller
|
|
* Indicate if current Plan node is controller node in recursive-union steps
|
|
*
|
|
* - @control_plan_nodeid
|
|
* Normally, set on the top-plan node of a producer thread, to indicate which
|
|
* control-plan we need syn-up with
|
|
*
|
|
* - @is_sync_planode
|
|
* Indicate the current producer thread is the sync-up thread in recursive union,
|
|
* normally set on produer's top plan node
|
|
*
|
|
* Please note the above four variables is meaningless if a plan node is not under
|
|
* recursive-union's recursive part
|
|
*/
|
|
/*
|
|
* plan node id of RecursiveUnion node where current plan node belongs to, 0 for
|
|
* not under recursive-union
|
|
*/
|
|
int recursive_union_plan_nodeid;
|
|
|
|
/* flag to indicate if it is controller plan node */
|
|
bool recursive_union_controller;
|
|
|
|
/* plan node id of Controller plan node, 0 for not in control */
|
|
int control_plan_nodeid;
|
|
|
|
/* flag indicate if the current plan node is the sync node (for multi-stream case) */
|
|
bool is_sync_plannode;
|
|
|
|
/*
|
|
* Common structural data for all Plan types.
|
|
*/
|
|
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;
|
|
|
|
bool ispwj; /* is it special for partitionwisejoin? */
|
|
int paramno; /* the partition'sn that it is scaning */
|
|
|
|
List* initPlan; /* Init Plan nodes (un-correlated expr
|
|
* subselects) */
|
|
|
|
List* distributed_keys; /* distributed on which key */
|
|
ExecNodes* exec_nodes; /* List of Datanodes where to execute this plan */
|
|
|
|
/*
|
|
* 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;
|
|
|
|
// For vectorized engine, plan produce vector output
|
|
//
|
|
bool vec_output;
|
|
/*
|
|
* @hdfs
|
|
* Mark the foreign scan whether has unique results on one of its
|
|
* output columns.
|
|
*/
|
|
bool hasUniqueResults;
|
|
/*
|
|
* Mark the plan whether includes delta table or not.
|
|
*/
|
|
bool isDeltaTable;
|
|
|
|
/* used to replace work_mem, maxmem in [0], and minmem in [1] */
|
|
int operatorMemKB[2];
|
|
/* allowed max mem after spread */
|
|
int operatorMaxMem;
|
|
|
|
bool parallel_enabled; /* Is it run in parallel? */
|
|
bool hasHashFilter; /* true for this plan has a hashfilter */
|
|
|
|
List* var_list; /* Need bloom filter var list. */
|
|
List* filterIndexList; /* Need used bloomfilter array index. */
|
|
|
|
/* used to replace work_mem */
|
|
int** ng_operatorMemKBArray; /* for multiple logic cluster */
|
|
int ng_num;
|
|
double innerdistinct; /* join inner rel distinct estimation value */
|
|
double outerdistinct; /* join outer rel distinct estimation value */
|
|
} Plan;
|
|
|
|
/* ----------------
|
|
* these are defined to avoid confusion problems with "left"
|
|
* and "right" and "inner" and "outer". The convention is that
|
|
* the "left" plan is the "outer" plan and the "right" plan is
|
|
* the inner plan, but these make the code more readable.
|
|
* ----------------
|
|
*/
|
|
#define innerPlan(node) (((Plan*)(node))->righttree)
|
|
#define outerPlan(node) (((Plan*)(node))->lefttree)
|
|
|
|
/* ----------------
|
|
* Result node -
|
|
* If no outer plan, evaluate a variable-free targetlist.
|
|
* If outer plan, return tuples from outer plan (after a level of
|
|
* projection as shown by targetlist).
|
|
*
|
|
* If resconstantqual isn't NULL, it represents a one-time qualification
|
|
* test (i.e., one that doesn't depend on any variables from the outer plan,
|
|
* so needs to be evaluated only once).
|
|
* ----------------
|
|
*/
|
|
typedef struct BaseResult {
|
|
Plan plan;
|
|
Node* resconstantqual;
|
|
} BaseResult;
|
|
|
|
typedef struct VecResult : public BaseResult {
|
|
} VecResult;
|
|
|
|
/* ----------------
|
|
* ModifyTable node -
|
|
* Apply rows produced by subplan(s) to result table(s),
|
|
* by inserting, updating, or deleting.
|
|
*
|
|
* Note that rowMarks and epqParam are presumed to be valid for all the
|
|
* subplan(s); they can't contain any info that varies across subplans.
|
|
* ----------------
|
|
*/
|
|
typedef struct ModifyTable {
|
|
Plan plan;
|
|
CmdType operation; /* INSERT, UPDATE, or DELETE */
|
|
bool canSetTag; /* do we set the command tag/es_processed? */
|
|
List* resultRelations; /* integer list of RT indexes */
|
|
int resultRelIndex; /* index of first resultRel in plan's list */
|
|
List* plans; /* plan(s) producing source data */
|
|
List* returningLists; /* per-target-table RETURNING tlists */
|
|
List* fdwPrivLists; /* per-target-table FDW private data lists */
|
|
List* rowMarks; /* PlanRowMarks (non-locking only) */
|
|
int epqParam; /* ID of Param for EvalPlanQual re-eval */
|
|
bool partKeyUpdated; /* when update on a partitioned table,true: part key column
|
|
is to be updated,false: no part key column is to updated */
|
|
#ifdef PGXC
|
|
List* remote_plans; /* per-target-table remote node */
|
|
List* remote_insert_plans;
|
|
List* remote_update_plans;
|
|
List* remote_delete_plans;
|
|
#endif
|
|
bool is_dist_insertselect;
|
|
|
|
ErrorCacheEntry* cacheEnt; /* Error record cache */
|
|
|
|
Index mergeTargetRelation; /* RT index of the merge target */
|
|
List* mergeSourceTargetList;
|
|
List* mergeActionList; /* actions for MERGE */
|
|
|
|
UpsertAction upsertAction; /* DUPLICATE KEY UPDATE action */
|
|
List* updateTlist; /* List of UPDATE target */
|
|
List* exclRelTlist; /* target list of the EXECLUDED pseudo relation */
|
|
Index exclRelRTIndex; /* RTI of the EXCLUDED pseudo relation */
|
|
bool partKeyUpsert;
|
|
|
|
OpMemInfo mem_info; /* Memory info for modify node */
|
|
} ModifyTable;
|
|
|
|
/* ----------------
|
|
* Append node -
|
|
* Generate the concatenation of the results of sub-plans.
|
|
* ----------------
|
|
*/
|
|
typedef struct Append {
|
|
Plan plan;
|
|
List* appendplans;
|
|
} Append;
|
|
|
|
typedef struct VecAppend : public Append {
|
|
} VecAppend;
|
|
/* ----------------
|
|
* MergeAppend node -
|
|
* Merge the results of pre-sorted sub-plans to preserve the ordering.
|
|
* ----------------
|
|
*/
|
|
typedef struct MergeAppend {
|
|
Plan plan;
|
|
List* mergeplans;
|
|
/* remaining fields are just like the sort-key info in struct Sort */
|
|
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 */
|
|
} MergeAppend;
|
|
|
|
/* ----------------
|
|
* RecursiveUnion node -
|
|
* Generate a recursive union of two subplans.
|
|
*
|
|
* The "outer" subplan is always the non-recursive term, and the "inner"
|
|
* subplan is the recursive term.
|
|
* ----------------
|
|
*/
|
|
typedef struct RecursiveUnion {
|
|
Plan plan;
|
|
int wtParam; /* ID of Param representing work table */
|
|
/* Remaining fields are zero/null in UNION ALL case */
|
|
int numCols; /* number of columns to check for
|
|
* duplicate-ness */
|
|
AttrNumber* dupColIdx; /* their indexes in the target list */
|
|
Oid* dupOperators; /* equality operators to compare with */
|
|
long numGroups; /* estimated number of groups in input */
|
|
bool has_inner_stream; /* indicate the underlaying plan node has stream operator (on recursive-term) */
|
|
bool has_outer_stream; /* indicate the underlaying plan node has stream operator (on none-recursive side) */
|
|
bool is_used;
|
|
bool is_correlated; /* indicate if the recursive union contains correlated term,
|
|
* in case of correlated term involved, we need broadcast data
|
|
* to one datanode to execute the recursive CTE in one-DN mode */
|
|
} RecursiveUnion;
|
|
|
|
/* ----------------
|
|
* BitmapAnd node -
|
|
* Generate the intersection of the results of sub-plans.
|
|
*
|
|
* The subplans must be of types that yield tuple bitmaps. The targetlist
|
|
* and qual fields of the plan are unused and are always NIL.
|
|
* ----------------
|
|
*/
|
|
typedef struct BitmapAnd {
|
|
Plan plan;
|
|
List* bitmapplans;
|
|
} BitmapAnd;
|
|
|
|
/* ----------------
|
|
* BitmapOr node -
|
|
* Generate the union of the results of sub-plans.
|
|
*
|
|
* The subplans must be of types that yield tuple bitmaps. The targetlist
|
|
* and qual fields of the plan are unused and are always NIL.
|
|
* ----------------
|
|
*/
|
|
typedef struct BitmapOr {
|
|
Plan plan;
|
|
List* bitmapplans;
|
|
} BitmapOr;
|
|
|
|
/*
|
|
* ==========
|
|
* Scan nodes
|
|
* ==========
|
|
*/
|
|
typedef struct Scan {
|
|
Plan plan;
|
|
Index scanrelid; /* relid is index into the range table */
|
|
bool isPartTbl; /* Does it scan a partitioned table */
|
|
int itrs; /* table partition's number for scan */
|
|
PruningResult* pruningInfo; /* pruning result for where-clause */
|
|
BucketInfo* bucketInfo; /* pruning result for buckets */
|
|
ScanDirection partScanDirection; /* specifies the scan ordering */
|
|
/*
|
|
* @hdfs
|
|
* If we use the informational constarint, the following variables will be seted as true.
|
|
* If scan_qual_optimized is true, it means that foreign scan will be optimized by using
|
|
* scan qual in executor phase.
|
|
* If predicate_pushdown_optimized is true, it means that predicate is pushed down and
|
|
* foreign scan will be optimized in the executor phase by using the predicate.
|
|
*/
|
|
bool scan_qual_optimized;
|
|
bool predicate_pushdown_optimized;
|
|
|
|
/* use struct pointer to avoid including parsenodes.h here */
|
|
TableSampleClause* tablesample;
|
|
|
|
/* Memory info for scan node, now it just used on indexscan, indexonlyscan, bitmapscan, dfsindexscan */
|
|
OpMemInfo mem_info;
|
|
|
|
/* use vector engine to execute this scan */
|
|
bool executeBatch;
|
|
} Scan;
|
|
|
|
/* ----------------
|
|
* sequential scan node
|
|
* ----------------
|
|
*/
|
|
typedef Scan SeqScan;
|
|
|
|
/*
|
|
* ==========
|
|
* Column Store Scan nodes
|
|
* ==========
|
|
*/
|
|
typedef struct CStoreScan : public Scan {
|
|
/* Some optimization information */
|
|
double selectionRatio; /* row output / rows scanned */
|
|
List* cstorequal; /* push predicate down to cstorescan */
|
|
List* minMaxInfo; /* min/max information, mark get this column min or max value. */
|
|
RelstoreType relStoreLocation; /* The store position information. */
|
|
bool is_replica_table; /* Is a replication table? */
|
|
} CStoreScan;
|
|
|
|
/*
|
|
* ==========
|
|
* Dfs Store Scan nodes. When the relation is CU format, we use CstoreScan
|
|
* to scan data.
|
|
* ==========
|
|
*/
|
|
typedef struct DfsScan : public Scan {
|
|
RelstoreType relStoreLocation;
|
|
char* storeFormat; /* The store format, the ORC format only is supported for dfsScan. */
|
|
List* privateData; /* Private data. */
|
|
} DfsScan;
|
|
|
|
/*
|
|
* ==========
|
|
* Time Series Store Scan nodes
|
|
* ==========
|
|
*/
|
|
typedef struct TsStoreScan: public Scan {
|
|
/* Some optimization information */
|
|
double selectionRatio; /* row output / rows scanned */
|
|
List *tsstorequal; /* push predicate down to tsstorescan */
|
|
List *minMaxInfo; /* min/max information, mark get this column min or max value.*/
|
|
RelstoreType relStoreLocation; /* The store position information. */
|
|
bool is_replica_table; /* Is a replication table? */
|
|
AttrNumber sort_by_time_colidx; /* If is sort by tstime limit n */
|
|
int limit; /* If is limit n */
|
|
bool is_simple_scan; /* If is sort by tstime limit n */
|
|
bool has_sort; /* If is have sort node */
|
|
int series_func_calls; /* series function calls time */
|
|
int top_key_func_arg; /* second arg of top_key function */
|
|
} TsStoreScan;
|
|
|
|
/* ----------------
|
|
* index scan node
|
|
*
|
|
* indexqualorig is an implicitly-ANDed list of index qual expressions, each
|
|
* in the same form it appeared in the query WHERE condition. Each should
|
|
* be of the form (indexkey OP comparisonval) or (comparisonval OP indexkey).
|
|
* The indexkey is a Var or expression referencing column(s) of the index's
|
|
* base table. The comparisonval might be any expression, but it won't use
|
|
* any columns of the base table. The expressions are ordered by index
|
|
* column position (but items referencing the same index column can appear
|
|
* in any order). indexqualorig is used at runtime only if we have to recheck
|
|
* a lossy indexqual.
|
|
*
|
|
* indexqual has the same form, but the expressions have been commuted if
|
|
* necessary to put the indexkeys on the left, and the indexkeys are replaced
|
|
* by Var nodes identifying the index columns (their varno is INDEX_VAR and
|
|
* their varattno is the index column number).
|
|
*
|
|
* indexorderbyorig is similarly the original form of any ORDER BY expressions
|
|
* that are being implemented by the index, while indexorderby is modified to
|
|
* have index column Vars on the left-hand side. Here, multiple expressions
|
|
* must appear in exactly the ORDER BY order, and this is not necessarily the
|
|
* index column order. Only the expressions are provided, not the auxiliary
|
|
* sort-order information from the ORDER BY SortGroupClauses; it's assumed
|
|
* that the sort ordering is fully determinable from the top-level operators.
|
|
* indexorderbyorig is unused at run time, but is needed for EXPLAIN.
|
|
* (Note these fields are used for amcanorderbyop cases, not amcanorder cases.)
|
|
*
|
|
* indexorderdir specifies the scan ordering, for indexscans on amcanorder
|
|
* indexes (for other indexes it should be "don't care").
|
|
* ----------------
|
|
*/
|
|
typedef struct IndexScan {
|
|
Scan scan;
|
|
Oid indexid; /* OID of index to scan */
|
|
char* indexname; /* Index name of index to scan */
|
|
List* indexqual; /* list of index quals (usually OpExprs) */
|
|
List* indexqualorig; /* the same in original form */
|
|
List* indexorderby; /* list of index ORDER BY exprs */
|
|
List* indexorderbyorig; /* the same in original form */
|
|
ScanDirection indexorderdir; /* forward or backward or don't care */
|
|
bool usecstoreindex; /* mark the column store index */
|
|
Index indexscan_relid; /* Hack for column store index, treat the index as normal relation */
|
|
List* idx_cstorequal; /* For column store, this contains only quals pushdownable to
|
|
storage engine */
|
|
List* cstorequal; /* quals that can be pushdown to cstore base table */
|
|
List* targetlist; /* Hack for column store index, target list to be computed at this node */
|
|
bool index_only_scan;
|
|
} IndexScan;
|
|
|
|
/* ----------------
|
|
* index-only scan node
|
|
*
|
|
* IndexOnlyScan is very similar to IndexScan, but it specifies an
|
|
* index-only scan, in which the data comes from the index not the heap.
|
|
* Because of this, *all* Vars in the plan node's targetlist, qual, and
|
|
* index expressions reference index columns and have varno = INDEX_VAR.
|
|
* Hence we do not need separate indexqualorig and indexorderbyorig lists,
|
|
* since their contents would be equivalent to indexqual and indexorderby.
|
|
*
|
|
* To help EXPLAIN interpret the index Vars for display, we provide
|
|
* indextlist, which represents the contents of the index as a targetlist
|
|
* with one TLE per index column. Vars appearing in this list reference
|
|
* the base table, and this is the only field in the plan node that may
|
|
* contain such Vars.
|
|
* ----------------
|
|
*/
|
|
typedef struct IndexOnlyScan {
|
|
Scan scan;
|
|
Oid indexid; /* OID of index to scan */
|
|
List* indexqual; /* list of index quals (usually OpExprs) */
|
|
List* indexorderby; /* list of index ORDER BY exprs */
|
|
List* indextlist; /* TargetEntry list describing index's cols */
|
|
ScanDirection indexorderdir; /* forward or backward or don't care */
|
|
} IndexOnlyScan;
|
|
|
|
/* ----------------
|
|
* bitmap index scan node
|
|
*
|
|
* BitmapIndexScan delivers a bitmap of potential tuple locations;
|
|
* it does not access the heap itself. The bitmap is used by an
|
|
* ancestor BitmapHeapScan node, possibly after passing through
|
|
* intermediate BitmapAnd and/or BitmapOr nodes to combine it with
|
|
* the results of other BitmapIndexScans.
|
|
*
|
|
* The fields have the same meanings as for IndexScan, except we don't
|
|
* store a direction flag because direction is uninteresting.
|
|
*
|
|
* In a BitmapIndexScan plan node, the targetlist and qual fields are
|
|
* not used and are always NIL. The indexqualorig field is unused at
|
|
* run time too, but is saved for the benefit of EXPLAIN.
|
|
* ----------------
|
|
*/
|
|
typedef struct BitmapIndexScan {
|
|
Scan scan;
|
|
Oid indexid; /* OID of index to scan */
|
|
char* indexname; /* name of index to scan */
|
|
List* indexqual; /* list of index quals (OpExprs) */
|
|
List* indexqualorig; /* the same in original form */
|
|
} BitmapIndexScan;
|
|
|
|
/* ----------------
|
|
* bitmap sequential scan node
|
|
*
|
|
* This needs a copy of the qual conditions being used by the input index
|
|
* scans because there are various cases where we need to recheck the quals;
|
|
* for example, when the bitmap is lossy about the specific rows on a page
|
|
* that meet the index condition.
|
|
* ----------------
|
|
*/
|
|
typedef struct BitmapHeapScan {
|
|
Scan scan;
|
|
List* bitmapqualorig; /* index quals, in standard expr form */
|
|
} BitmapHeapScan;
|
|
|
|
/* ----------------
|
|
* Column Store index scan node
|
|
*
|
|
* ----------------
|
|
*/
|
|
typedef struct CStoreIndexScan {
|
|
Scan scan;
|
|
Oid indexid; /* OID of index to scan */
|
|
List* indexqual; /* list of index quals (usually OpExprs) */
|
|
List* indexqualorig; /* the same in original form */
|
|
List* indexorderby; /* list of index ORDER BY exprs */
|
|
List* indexorderbyorig; /* the same in original form */
|
|
ScanDirection indexorderdir; /* forward or backward or don't care */
|
|
|
|
List* baserelcstorequal; /* for base relation of index */
|
|
List* cstorequal; /* quals that can be pushdown to cstore base table */
|
|
List* indextlist;
|
|
RelstoreType relStoreLocation; /* The store position information. */
|
|
bool indexonly; /* flag indicates index only scan */
|
|
} CStoreIndexScan;
|
|
|
|
typedef struct CStoreIndexCtidScan : public BitmapIndexScan {
|
|
List* indextlist;
|
|
List* cstorequal;
|
|
} CStoreIndexCtidScan;
|
|
|
|
typedef struct CStoreIndexHeapScan : public BitmapHeapScan {
|
|
} CStoreIndexHeapScan;
|
|
|
|
typedef struct CStoreIndexAnd : public BitmapAnd {
|
|
} CStoreIndexAnd;
|
|
|
|
typedef struct CStoreIndexOr : public BitmapOr {
|
|
} CStoreIndexOr;
|
|
|
|
/* ----------------
|
|
* DFS Store index scan node
|
|
*/
|
|
typedef struct DfsIndexScan {
|
|
Scan scan;
|
|
Oid indexid; /* OID of index to scan */
|
|
List* indextlist; /* list of index target entry which represents the column of base-relation */
|
|
List* indexqual; /* list of index quals (usually OpExprs) */
|
|
List* indexqualorig; /* the same in original form */
|
|
List* indexorderby; /* list of index ORDER BY exprs */
|
|
List* indexorderbyorig; /* the same in original form */
|
|
ScanDirection indexorderdir; /* forward or backward or don't care */
|
|
RelstoreType relStoreLocation; /* The store position information. */
|
|
List* cstorequal; /* quals that can be pushdown to cstore base table */
|
|
List* indexScantlist; /* list of target column for scanning on index table */
|
|
DfsScan* dfsScan; /* the inner object for scanning the base-relation */
|
|
bool indexonly; /* flag indicates index only scan */
|
|
} DfsIndexScan;
|
|
|
|
/* ----------------
|
|
* tid scan node
|
|
*
|
|
* tidquals is an implicitly OR'ed list of qual expressions of the form
|
|
* "CTID = pseudoconstant" or "CTID = ANY(pseudoconstant_array)".
|
|
* ----------------
|
|
*/
|
|
typedef struct TidScan {
|
|
Scan scan;
|
|
List* tidquals; /* qual(s) involving CTID = something */
|
|
} TidScan;
|
|
|
|
/* ----------------
|
|
* subquery scan node
|
|
*
|
|
* SubqueryScan is for scanning the output of a sub-query in the range table.
|
|
* We often need an extra plan node above the sub-query's plan to perform
|
|
* expression evaluations (which we can't push into the sub-query without
|
|
* risking changing its semantics). Although we are not scanning a physical
|
|
* relation, we make this a descendant of Scan anyway for code-sharing
|
|
* purposes.
|
|
*
|
|
* Note: we store the sub-plan in the type-specific subplan field, not in
|
|
* the generic lefttree field as you might expect. This is because we do
|
|
* not want plan-tree-traversal routines to recurse into the subplan without
|
|
* knowing that they are changing Query contexts.
|
|
* ----------------
|
|
*/
|
|
typedef struct SubqueryScan {
|
|
Scan scan;
|
|
Plan* subplan;
|
|
} SubqueryScan;
|
|
|
|
typedef struct VecSubqueryScan : public SubqueryScan {
|
|
} VecSubqueryScan;
|
|
|
|
/* ----------------
|
|
* FunctionScan node
|
|
* ----------------
|
|
*/
|
|
typedef struct FunctionScan {
|
|
Scan scan;
|
|
Node* funcexpr; /* expression tree for func call */
|
|
List* funccolnames; /* output column names (string Value nodes) */
|
|
List* funccoltypes; /* OID list of column type OIDs */
|
|
List* funccoltypmods; /* integer list of column typmods */
|
|
List* funccolcollations; /* OID list of column collation OIDs */
|
|
} FunctionScan;
|
|
|
|
/* ----------------
|
|
* ValuesScan node
|
|
* ----------------
|
|
*/
|
|
typedef struct ValuesScan {
|
|
Scan scan;
|
|
List* values_lists; /* list of expression lists */
|
|
} ValuesScan;
|
|
|
|
/* ----------------
|
|
* CteScan node
|
|
* ----------------
|
|
*/
|
|
typedef struct CteScan {
|
|
Scan scan;
|
|
int ctePlanId; /* ID of init SubPlan for CTE */
|
|
int cteParam; /* ID of Param representing CTE output */
|
|
RecursiveUnion* subplan; /* subplan of CteScan, must be RecursiveUnion */
|
|
} CteScan;
|
|
|
|
/* ----------------
|
|
* WorkTableScan node
|
|
* ----------------
|
|
*/
|
|
typedef struct WorkTableScan {
|
|
Scan scan;
|
|
int wtParam; /* ID of Param representing work table */
|
|
} WorkTableScan;
|
|
|
|
/* ----------------
|
|
* ForeignScan node
|
|
*
|
|
* fdw_exprs and fdw_private are both under the control of the foreign-data
|
|
* wrapper, but fdw_exprs is presumed to contain expression trees and will
|
|
* be post-processed accordingly by the planner; fdw_private won't be.
|
|
* Note that everything in both lists must be copiable by copyObject().
|
|
* One way to store an arbitrary blob of bytes is to represent it as a bytea
|
|
* Const. Usually, though, you'll be better off choosing a representation
|
|
* that can be dumped usefully by nodeToString().
|
|
* ----------------
|
|
*/
|
|
typedef struct ForeignScan {
|
|
Scan scan;
|
|
|
|
Oid scan_relid; /* Oid of the scan relation */
|
|
List* fdw_exprs; /* expressions that FDW may evaluate */
|
|
List* fdw_private; /* private data for FDW */
|
|
bool fsSystemCol; /* true if any "system column" is needed */
|
|
|
|
bool needSaveError;
|
|
ErrorCacheEntry* errCache; /* Error record cache */
|
|
|
|
/* This is used in hdfs foreign scan to store prunning information. */
|
|
List* prunningResult;
|
|
|
|
RelationMetaData* rel; /* the meta data of the foreign table */
|
|
ForeignOptions* options; /* the configuration options */
|
|
|
|
/* number of files(objects) to be scanned. just valid for planner */
|
|
int64 objectNum;
|
|
BloomFilterSet** bloomFilterSet;
|
|
int bfNum; /* the number of bloomfilter object. */
|
|
|
|
/* set true in do_query_for_planrouter() for ForeignScan sent to
|
|
* the compute pool
|
|
*/
|
|
bool in_compute_pool;
|
|
bool not_use_bloomfilter; /* set true in ExecInitXXXX() of planrouter node */
|
|
} ForeignScan;
|
|
|
|
/* ----------------
|
|
* ExtensiblePlan node
|
|
*
|
|
* The comments for ForeignScan's fdw_exprs, fdw_private, fdw_scan_tlist,
|
|
* and fs_relids fields apply equally to ExtensiblePlan's extensible_exprs,
|
|
* extensible_data, extensible_plan_tlist, and extensible_relids fields. The
|
|
* convention of setting scan.scanrelid to zero for joins applies as well.
|
|
*
|
|
* Note that since Plan trees can be copied, extensible scan providers *must*
|
|
* fit all plan data they need into those fields; embedding ExtensiblePlan in
|
|
* a larger struct will not work.
|
|
* ----------------
|
|
*/
|
|
struct ExtensiblePlan;
|
|
|
|
typedef struct ExtensiblePlanMethods {
|
|
char* ExtensibleName;
|
|
|
|
/* Create execution state (ExtensiblePlanState) from a ExtensiblePlan plan node */
|
|
Node* (*CreateExtensiblePlanState)(struct ExtensiblePlan* cscan);
|
|
} ExtensiblePlanMethods;
|
|
|
|
typedef struct ExtensiblePlan {
|
|
Scan scan;
|
|
|
|
uint32 flags; /* mask of EXTENSIBLEPATH_* flags, see relation.h */
|
|
|
|
List* extensible_plans; /* list of Plan nodes, if any */
|
|
|
|
List* extensible_exprs; /* expressions that extensible code may evaluate */
|
|
|
|
List* extensible_private; /* private data for extensible code */
|
|
|
|
List* extensible_plan_tlist; /* optional tlist describing scan
|
|
* tuple */
|
|
Bitmapset* extensible_relids; /* RTIs generated by this scan */
|
|
|
|
ExtensiblePlanMethods* methods;
|
|
} ExtensiblePlan;
|
|
/*
|
|
* ==========
|
|
* Join nodes
|
|
* ==========
|
|
*/
|
|
|
|
/* ----------------
|
|
* Join node
|
|
*
|
|
* jointype: rule for joining tuples from left and right subtrees
|
|
* 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.
|
|
* ----------------
|
|
*/
|
|
typedef struct Join {
|
|
Plan plan;
|
|
JoinType jointype;
|
|
List* joinqual; /* JOIN quals (in addition to plan.qual) */
|
|
/*
|
|
* @hdfs
|
|
* This flag will be set as true if we use informational constraint
|
|
* in order to optimize join plan.
|
|
*/
|
|
bool optimizable;
|
|
List* nulleqqual;
|
|
|
|
uint32 skewoptimize;
|
|
} Join;
|
|
|
|
/* ----------------
|
|
* 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 */
|
|
bool materialAll;
|
|
} NestLoop;
|
|
|
|
typedef struct VecNestLoop : public NestLoop {
|
|
} VecNestLoop;
|
|
|
|
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;
|
|
|
|
/* ----------------
|
|
* 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;
|
|
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;
|
|
|
|
typedef struct VecMergeJoin : public MergeJoin {
|
|
} VecMergeJoin;
|
|
/* ----------------
|
|
* hash join node
|
|
* ----------------
|
|
*/
|
|
typedef struct HashJoin {
|
|
Join join;
|
|
List* hashclauses;
|
|
bool streamBothSides;
|
|
bool transferFilterFlag;
|
|
bool rebuildHashTable;
|
|
bool isSonicHash;
|
|
OpMemInfo mem_info; /* Memory info for inner hash table */
|
|
} HashJoin;
|
|
|
|
/* ----------------
|
|
* materialization node
|
|
* ----------------
|
|
*/
|
|
typedef struct Material {
|
|
Plan plan;
|
|
bool materialize_all; /* if all data should be materialized at the first time */
|
|
OpMemInfo mem_info; /* Memory info for material */
|
|
} Material;
|
|
|
|
typedef struct VecMaterial : public Material {
|
|
} VecMaterial;
|
|
|
|
/* ----------------
|
|
* 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 */
|
|
#ifdef PGXC
|
|
bool srt_start_merge; /* No need to create the sorted runs. The
|
|
* underlying plan provides those runs. Merge
|
|
* them.
|
|
*/
|
|
#endif /* PGXC */
|
|
OpMemInfo mem_info; /* Memory info for sort */
|
|
} Sort;
|
|
|
|
typedef struct VecSort : public Sort {
|
|
} VecSort;
|
|
|
|
/* ---------------
|
|
* group node -
|
|
* Used for queries with GROUP BY (but no aggregates) specified.
|
|
* The input must be presorted according to the grouping columns.
|
|
* ---------------
|
|
*/
|
|
typedef struct Group {
|
|
Plan plan;
|
|
int numCols; /* number of grouping columns */
|
|
AttrNumber* grpColIdx; /* their indexes in the target list */
|
|
Oid* grpOperators; /* equality operators to compare with */
|
|
} Group;
|
|
|
|
typedef struct VecGroup : public Group {
|
|
} VecGroup;
|
|
/* ---------------
|
|
* aggregate node
|
|
*
|
|
* An Agg node implements plain or grouped aggregation. For grouped
|
|
* aggregation, we can work with presorted input or unsorted input;
|
|
* the latter strategy uses an internal hashtable.
|
|
*
|
|
* Notice the lack of any direct info about the aggregate functions to be
|
|
* computed. They are found by scanning the node's tlist and quals during
|
|
* executor startup. (It is possible that there are no aggregate functions;
|
|
* this could happen if they get optimized away by constant-folding, or if
|
|
* we are using the Agg node to implement hash-based grouping.)
|
|
* ---------------
|
|
*/
|
|
typedef enum AggStrategy {
|
|
AGG_PLAIN, /* simple agg across all input rows */
|
|
AGG_SORTED, /* grouped agg, input must be sorted */
|
|
AGG_HASHED /* grouped agg, use internal hashtable */
|
|
} AggStrategy;
|
|
|
|
#ifdef STREAMPLAN
|
|
typedef enum SAggMethod {
|
|
OPTIMAL_AGG, /* 0. chose the optimal hash agg plan according to costs. */
|
|
DN_AGG_CN_AGG, /* 1. */
|
|
DN_REDISTRIBUTE_AGG, /* 2. */
|
|
DN_AGG_REDISTRIBUTE_AGG, /* 3. */
|
|
DN_REDISTRIBUTE_AGG_CN_AGG, /* 1+. according to DN_AGG_CN_AGG */
|
|
DN_REDISTRIBUTE_AGG_REDISTRIBUTE_AGG /* 3+. according to DN_AGG_REDISTRIBUTE_AGG */
|
|
} SAggMethod;
|
|
|
|
/* flags bits for SAggMethod choose */
|
|
#define ALLOW_ALL_AGG 0X00 /* Any AggMethod may be selected */
|
|
#define DISALLOW_CN_AGG 0x01 /* disallow DN_AGG_CN_AGG, DN_REDISTRIBUTE_AGG_CN_AGG */
|
|
#define FOREC_SLVL_AGG 0x02 /* force single level agg, actually disallow CN_AGG meanwhile */
|
|
|
|
#endif
|
|
|
|
typedef struct Agg {
|
|
Plan plan;
|
|
AggStrategy aggstrategy;
|
|
int numCols; /* number of grouping columns */
|
|
AttrNumber* grpColIdx; /* their indexes in the target list */
|
|
Oid* grpOperators; /* equality operators to compare with */
|
|
long numGroups; /* estimated number of groups in input */
|
|
List* groupingSets; /* grouping sets to use */
|
|
List* chain; /* chained Agg/Sort nodes */
|
|
#ifdef PGXC
|
|
bool is_final; /* apply final agg directly on the data received from remote Datanodes */
|
|
bool single_node; /* We can finalise the aggregates on the datanode/s */
|
|
#endif /* PGXC */
|
|
Bitmapset* aggParams; /* IDs of Params used in Aggref inputs */
|
|
OpMemInfo mem_info; /* Memory info for hashagg */
|
|
bool is_sonichash; /* allowed to use sonic hash routine or not */
|
|
bool is_dummy; /* just for coop analysis, if true, agg node does nothing */
|
|
uint32 skew_optimize; /* skew optimize method for agg */
|
|
bool unique_check; /* we will report an error when meet duplicate in unique check mode */
|
|
} Agg;
|
|
|
|
/* ----------------
|
|
* window aggregate node
|
|
* ----------------
|
|
*/
|
|
typedef struct WindowAgg {
|
|
Plan plan;
|
|
Index winref; /* ID referenced by window functions */
|
|
int partNumCols; /* number of columns in partition clause */
|
|
AttrNumber* partColIdx; /* their indexes in the target list */
|
|
Oid* partOperators; /* equality operators for partition columns */
|
|
int ordNumCols; /* number of columns in ordering clause */
|
|
AttrNumber* ordColIdx; /* their indexes in the target list */
|
|
Oid* ordOperators; /* equality operators for ordering columns */
|
|
int frameOptions; /* frame_clause options, see WindowDef */
|
|
Node* startOffset; /* expression for starting bound, if any */
|
|
Node* endOffset; /* expression for ending bound, if any */
|
|
OpMemInfo mem_info; /* Memory info for window agg with agg func */
|
|
} WindowAgg;
|
|
|
|
typedef struct VecWindowAgg : public WindowAgg {
|
|
} VecWindowAgg;
|
|
/* ----------------
|
|
* unique node
|
|
* ----------------
|
|
*/
|
|
typedef struct Unique {
|
|
Plan plan;
|
|
int numCols; /* number of columns to check for uniqueness */
|
|
AttrNumber* uniqColIdx; /* their indexes in the target list */
|
|
Oid* uniqOperators; /* equality operators to compare with */
|
|
} Unique;
|
|
|
|
/* ----------------
|
|
* hash build node
|
|
*
|
|
* If the executor is supposed to try to apply skew join optimization, then
|
|
* skewTable/skewColumn/skewInherit identify the outer relation's join key
|
|
* column, from which the relevant MCV statistics can be fetched. Also, its
|
|
* type information is provided to save a lookup.
|
|
* ----------------
|
|
*/
|
|
typedef struct Hash {
|
|
Plan plan;
|
|
Oid skewTable; /* outer join key's table OID, or InvalidOid */
|
|
AttrNumber skewColumn; /* outer join key's column #, or zero */
|
|
bool skewInherit; /* is outer join rel an inheritance tree? */
|
|
Oid skewColType; /* datatype of the outer key column */
|
|
int32 skewColTypmod; /* typmod of the outer key column */
|
|
/* all other info is in the parent HashJoin node */
|
|
} Hash;
|
|
|
|
/* ----------------
|
|
* setop node
|
|
* ----------------
|
|
*/
|
|
typedef enum SetOpCmd { SETOPCMD_INTERSECT, SETOPCMD_INTERSECT_ALL, SETOPCMD_EXCEPT, SETOPCMD_EXCEPT_ALL } SetOpCmd;
|
|
|
|
typedef enum SetOpStrategy {
|
|
SETOP_SORTED, /* input must be sorted */
|
|
SETOP_HASHED /* use internal hashtable */
|
|
} SetOpStrategy;
|
|
|
|
typedef struct SetOp {
|
|
Plan plan;
|
|
SetOpCmd cmd; /* what to do */
|
|
SetOpStrategy strategy; /* how to do it */
|
|
int numCols; /* number of columns to check for
|
|
* duplicate-ness */
|
|
AttrNumber* dupColIdx; /* their indexes in the target list */
|
|
Oid* dupOperators; /* equality operators to compare with */
|
|
AttrNumber flagColIdx; /* where is the flag column, if any */
|
|
int firstFlag; /* flag value for first input relation */
|
|
long numGroups; /* estimated number of groups in input */
|
|
OpMemInfo mem_info; /* Memory info for hashagg set op */
|
|
} SetOp;
|
|
|
|
/* ----------------
|
|
* lock-rows node
|
|
*
|
|
* rowMarks identifies the rels to be locked by this node; it should be
|
|
* a subset of the rowMarks listed in the top-level PlannedStmt.
|
|
* epqParam is a Param that all scan nodes below this one must depend on.
|
|
* It is used to force re-evaluation of the plan during EvalPlanQual.
|
|
* ----------------
|
|
*/
|
|
typedef struct LockRows {
|
|
Plan plan;
|
|
List* rowMarks; /* a list of PlanRowMark's */
|
|
int epqParam; /* ID of Param for EvalPlanQual re-eval */
|
|
} LockRows;
|
|
|
|
/* ----------------
|
|
* 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;
|
|
|
|
typedef struct VecLimit : public Limit {
|
|
} VecLimit;
|
|
|
|
/*
|
|
* RowMarkType -
|
|
* enums for types of row-marking operations
|
|
*
|
|
* When doing UPDATE, DELETE, or SELECT FOR UPDATE/SHARE, we have to uniquely
|
|
* identify all the source rows, not only those from the target relations, so
|
|
* that we can perform EvalPlanQual rechecking at need. For plain tables we
|
|
* can just fetch the TID, the same as for a target relation. Otherwise (for
|
|
* example for VALUES or FUNCTION scans) we have to copy the whole row value.
|
|
* The latter is pretty inefficient but fortunately the case is not
|
|
* performance-critical in practice.
|
|
*/
|
|
typedef enum RowMarkType {
|
|
ROW_MARK_EXCLUSIVE, /* obtain exclusive tuple lock */
|
|
ROW_MARK_SHARE, /* obtain shared tuple lock */
|
|
ROW_MARK_REFERENCE, /* just fetch the TID */
|
|
ROW_MARK_COPY, /* physically copy the row value */
|
|
ROW_MARK_COPY_DATUM /* physically copy the datum of every row column */
|
|
} RowMarkType;
|
|
|
|
#define RowMarkRequiresRowShareLock(marktype) ((marktype) <= ROW_MARK_SHARE)
|
|
|
|
/*
|
|
* PlanRowMark -
|
|
* plan-time representation of FOR UPDATE/SHARE clauses
|
|
*
|
|
* When doing UPDATE, DELETE, or SELECT FOR UPDATE/SHARE, we create a separate
|
|
* PlanRowMark node for each non-target relation in the query. Relations that
|
|
* are not specified as FOR UPDATE/SHARE are marked ROW_MARK_REFERENCE (if
|
|
* real tables) or ROW_MARK_COPY (if not).
|
|
*
|
|
* Initially all PlanRowMarks have rti == prti and isParent == false.
|
|
* When the planner discovers that a relation is the root of an inheritance
|
|
* tree, it sets isParent true, and adds an additional PlanRowMark to the
|
|
* list for each child relation (including the target rel itself in its role
|
|
* as a child). The child entries have rti == child rel's RT index and
|
|
* prti == parent's RT index, and can therefore be recognized as children by
|
|
* the fact that prti != rti.
|
|
*
|
|
* The planner also adds resjunk output columns to the plan that carry
|
|
* information sufficient to identify the locked or fetched rows. For
|
|
* tables (markType != ROW_MARK_COPY), these columns are named
|
|
* tableoid%u OID of table
|
|
* ctid%u TID of row
|
|
* The tableoid column is only present for an inheritance hierarchy.
|
|
* When markType == ROW_MARK_COPY, there is instead a single column named
|
|
* wholerow%u whole-row value of relation
|
|
* In all three cases, %u represents the rowmark ID number (rowmarkId).
|
|
* This number is unique within a plan tree, except that child relation
|
|
* entries copy their parent's rowmarkId. (Assigning unique numbers
|
|
* means we needn't renumber rowmarkIds when flattening subqueries, which
|
|
* would require finding and renaming the resjunk columns as well.)
|
|
* Note this means that all tables in an inheritance hierarchy share the
|
|
* same resjunk column names. However, in an inherited UPDATE/DELETE the
|
|
* columns could have different physical column numbers in each subplan.
|
|
*/
|
|
typedef struct PlanRowMark {
|
|
NodeTag type;
|
|
Index rti; /* range table index of markable relation */
|
|
Index prti; /* range table index of parent relation */
|
|
Index rowmarkId; /* unique identifier for resjunk columns */
|
|
RowMarkType markType; /* see enum above */
|
|
bool noWait; /* NOWAIT option */
|
|
bool isParent; /* true if this is a "dummy" parent entry */
|
|
int numAttrs; /* number of attributes in subplan */
|
|
Bitmapset* bms_nodeids;
|
|
} PlanRowMark;
|
|
|
|
/*
|
|
* Plan invalidation info
|
|
*
|
|
* We track the objects on which a PlannedStmt depends in two ways:
|
|
* relations are recorded as a simple list of OIDs, and everything else
|
|
* is represented as a list of PlanInvalItems. A PlanInvalItem is designed
|
|
* to be used with the syscache invalidation mechanism, so it identifies a
|
|
* system catalog entry by cache ID and hash value.
|
|
*/
|
|
typedef struct PlanInvalItem {
|
|
NodeTag type;
|
|
int cacheId; /* a syscache ID, see utils/syscache.h */
|
|
uint32 hashValue; /* hash value of object's cache lookup key */
|
|
} PlanInvalItem;
|
|
/*
|
|
* Target : data partition
|
|
* Brief : structure definition about partition iteration
|
|
*/
|
|
typedef struct PartIteratorParam {
|
|
NodeTag type;
|
|
int paramno;
|
|
} PartIteratorParam;
|
|
|
|
typedef struct PartIterator {
|
|
Plan plan;
|
|
PartitionType partType; /* partition type, range or interval? */
|
|
int itrs; /* the number of the partitions */
|
|
ScanDirection direction;
|
|
PartIteratorParam* param;
|
|
/*
|
|
* Below three variables are used to record starting partition id, ending partition id and number of
|
|
* partitions.
|
|
*/
|
|
int startPartitionId; /* Used in parallel execution to record smp worker starting partition id. */
|
|
int endPartitionId; /* Used in parallel execution to record smp worker ending partition id. */
|
|
} PartIterator;
|
|
typedef struct GlobalPartIterator {
|
|
int curItrs;
|
|
PruningResult* pruningResult;
|
|
} GlobalPartIterator;
|
|
|
|
typedef struct VecPartIterator : public PartIterator {
|
|
} VecPartIterator;
|
|
/*
|
|
* Vector Plan Nodes.
|
|
*
|
|
*/
|
|
|
|
/* ----------------
|
|
* vector hash join node
|
|
* ----------------
|
|
*/
|
|
|
|
// comment to avoid g++ warning
|
|
// vector aggregation.
|
|
|
|
typedef struct HashJoin VecHashJoin;
|
|
typedef struct Agg VecAgg;
|
|
typedef struct SetOp VecSetOp;
|
|
typedef struct Unique VecUnique;
|
|
|
|
typedef struct RowToVec {
|
|
Plan plan;
|
|
} RowToVec;
|
|
|
|
typedef struct VecToRow {
|
|
Plan plan;
|
|
} VecToRow;
|
|
|
|
inline bool IsVecOutput(Plan* p)
|
|
{
|
|
return p && p->vec_output;
|
|
}
|
|
|
|
typedef struct VecForeignScan : public ForeignScan {
|
|
} VecForeignScan;
|
|
|
|
typedef struct VecModifyTable : public ModifyTable {
|
|
} VecModifyTable;
|
|
|
|
static inline bool IsJoinPlan(Node* node)
|
|
{
|
|
return IsA(node, Join) || IsA(node, NestLoop) || IsA(node, VecNestLoop) || IsA(node, MergeJoin) ||
|
|
IsA(node, VecMergeJoin) || IsA(node, HashJoin) || IsA(node, VecHashJoin);
|
|
}
|
|
|
|
#endif /* PLANNODES_H */
|
|
|