mirror of https://github.com/citusdata/citus.git
277 lines
7.9 KiB
C
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 */
|