citus/src/include/distributed/distributed_planner.h

277 lines
7.9 KiB
C

/*-------------------------------------------------------------------------
*
* distributed_planner.h
* General Citus planner code.
*
* Copyright (c) Citus Data, Inc.
*-------------------------------------------------------------------------
*/
#ifndef DISTRIBUTED_PLANNER_H
#define DISTRIBUTED_PLANNER_H
#include "postgres.h"
#include "nodes/pathnodes.h"
#include "nodes/plannodes.h"
#include "pg_version_constants.h"
#include "distributed/citus_nodes.h"
#include "distributed/errormessage.h"
#include "distributed/log_utils.h"
/* values used by jobs and tasks which do not require identifiers */
#define INVALID_JOB_ID 0
#define INVALID_TASK_ID 0
#define CURSOR_OPT_FORCE_DISTRIBUTED 0x080000
/* level of planner calls */
extern int PlannerLevel;
typedef struct RelationRestrictionContext
{
bool allReferenceTables;
List *relationRestrictionList;
} RelationRestrictionContext;
typedef struct RootPlanParams
{
PlannerInfo *root;
/*
* Copy of root->plan_params. root->plan_params is not preserved in
* relation_restriction_equivalence, so we need to create a copy.
*/
List *plan_params;
} RootPlanParams;
typedef struct RelationRestriction
{
Index index;
Oid relationId;
bool citusTable;
RangeTblEntry *rte;
RelOptInfo *relOptInfo;
PlannerInfo *plannerInfo;
/* list of RootPlanParams for all outer nodes */
List *outerPlanParamsList;
/* list of translated vars, this is copied from postgres since it gets deleted on postgres*/
List *translatedVars;
} RelationRestriction;
typedef struct JoinRestrictionContext
{
List *joinRestrictionList;
bool hasSemiJoin;
bool hasOuterJoin;
} JoinRestrictionContext;
typedef struct JoinRestriction
{
JoinType joinType;
List *joinRestrictInfoList;
PlannerInfo *plannerInfo;
Relids innerrelRelids;
Relids outerrelRelids;
} JoinRestriction;
typedef struct FastPathRestrictionContext
{
bool fastPathRouterQuery;
/*
* While calculating fastPathRouterQuery, we could sometimes be
* able to extract the distribution key value as well (such as when
* there are no prepared statements). Could be NULL when the distribution
* key contains parameter, so check for it before using.
*/
Const *distributionKeyValue;
/*
* Set to true when distKey = Param; in the queryTree
*/
bool distributionKeyHasParam;
/*
* Indicates to hold off on callning the fast path planner until its
* known if the shard is local
*/
bool delayFastPathPlanning;
/*
* Range table entry for the table we're querying
*/
RangeTblEntry *distTableRte;
} FastPathRestrictionContext;
typedef struct PlannerRestrictionContext
{
RelationRestrictionContext *relationRestrictionContext;
JoinRestrictionContext *joinRestrictionContext;
/*
* When the query is qualified for fast path, we don't have
* the RelationRestrictionContext and JoinRestrictionContext
* since those are dependent to calling standard_planner.
* Instead, we keep this struct to pass some extra information.
*/
FastPathRestrictionContext *fastPathRestrictionContext;
MemoryContext memoryContext;
} PlannerRestrictionContext;
typedef struct RelationShard
{
CitusNode type;
Oid relationId;
uint64 shardId;
} RelationShard;
typedef struct RelationRowLock
{
CitusNode type;
Oid relationId;
LockClauseStrength rowLockStrength;
} RelationRowLock;
/*
* Parameters to be set according to range table entries of a query.
*/
typedef struct RTEListProperties
{
bool hasPostgresLocalTable;
bool hasReferenceTable;
bool hasCitusLocalTable;
/* includes hash, single-shard, append and range partitioned tables */
bool hasDistributedTable;
/*
* Effectively, hasDistributedTable is equal to
* "hasDistTableWithShardKey || hasSingleShardDistTable".
*
* We provide below two for the callers that want to know what kind of
* distributed tables that given query has references to.
*/
bool hasDistTableWithShardKey;
bool hasSingleShardDistTable;
/* union of hasReferenceTable, hasCitusLocalTable and hasDistributedTable */
bool hasCitusTable;
bool hasMaterializedView;
} RTEListProperties;
typedef struct DistributedPlanningContext
{
/* The parsed query that is given to the planner. It is a slightly modified
* to work with the standard_planner */
Query *query;
/* A copy of the original parsed query that is given to the planner. This
* doesn't contain most of the changes that are made to parse. There's one
* that change that is made for non fast path router queries though, which
* is the assigning of RTE identities using AssignRTEIdentities. This is
* NULL for non distributed plans, since those don't need it. */
Query *originalQuery;
/* the cursor options given to the planner */
int cursorOptions;
/* the ParamListInfo that is given to the planner */
ParamListInfo boundParams;
/* Plan created either by standard_planner or by FastPathPlanner */
PlannedStmt *plan;
/* Our custom restriction context */
PlannerRestrictionContext *plannerRestrictionContext;
} DistributedPlanningContext;
/*
* CitusCustomScanPath is injected into the planner during the combine query planning
* phase of the logical planner.
*
* We call out to the standard planner to plan the combine query part for the output of
* the logical planner. This makes it easier to implement new sql features into the
* logical planner by not having to manually implement the plan creation for the combine
* query on the coordinator..
*/
typedef struct CitusCustomScanPath
{
CustomPath custom_path;
/*
* Custom scan node computed by the citus planner that will produce the tuples for the
* path we are injecting during the planning of the combine query
*/
CustomScan *remoteScan;
} CitusCustomScanPath;
extern PlannedStmt * distributed_planner(Query *parse,
const char *query_string,
int cursorOptions,
ParamListInfo boundParams);
/*
* Common hint message to workaround using postgres local and citus local tables
* in distributed queries
*/
#define LOCAL_TABLE_SUBQUERY_CTE_HINT \
"Use CTE's or subqueries to select from local tables and use them in joins"
extern List * ExtractRangeTableEntryList(Query *query);
extern bool NeedsDistributedPlanning(Query *query);
extern List * TranslatedVarsForRteIdentity(int rteIdentity);
extern struct DistributedPlan * GetDistributedPlan(CustomScan *node);
extern void multi_relation_restriction_hook(PlannerInfo *root, RelOptInfo *relOptInfo,
Index restrictionIndex, RangeTblEntry *rte);
extern void multi_get_relation_info_hook(PlannerInfo *root, Oid relationObjectId, bool
inhparent, RelOptInfo *rel);
extern void multi_join_restriction_hook(PlannerInfo *root,
RelOptInfo *joinrel,
RelOptInfo *outerrel,
RelOptInfo *innerrel,
JoinType jointype,
JoinPathExtraData *extra);
extern bool HasUnresolvedExternParamsWalker(Node *expression, ParamListInfo boundParams);
extern bool IsModifyCommand(Query *query);
extern void EnsurePartitionTableNotReplicated(Oid relationId);
extern Node * ResolveExternalParams(Node *inputNode, ParamListInfo boundParams);
extern bool IsMultiTaskPlan(struct DistributedPlan *distributedPlan);
extern RangeTblEntry * RemoteScanRangeTableEntry(List *columnNameList);
extern int GetRTEIdentity(RangeTblEntry *rte);
extern bool GetOriginalInh(RangeTblEntry *rte);
extern LOCKMODE GetQueryLockMode(Query *query);
extern int32 BlessRecordExpression(Expr *expr);
extern void DissuadePlannerFromUsingPlan(PlannedStmt *plan);
extern PlannedStmt * FinalizePlan(PlannedStmt *localPlan,
struct DistributedPlan *distributedPlan);
extern bool ContainsSingleShardTable(Query *query);
extern RTEListProperties * GetRTEListPropertiesForQuery(Query *query);
extern struct DistributedPlan * CreateDistributedPlan(uint64 planId,
bool allowRecursivePlanning,
Query *originalQuery,
Query *query,
ParamListInfo boundParams,
bool hasUnresolvedParams,
PlannerRestrictionContext *
plannerRestrictionContext);
#endif /* DISTRIBUTED_PLANNER_H */