/*------------------------------------------------------------------------- * * distributed_planner.h * General Citus planner code. * * Copyright (c) Citus Data, Inc. *------------------------------------------------------------------------- */ #ifndef DISTRIBUTED_PLANNER_H #define DISTRIBUTED_PLANNER_H #include "postgres.h" #include "distributed/pg_version_constants.h" #include "nodes/plannodes.h" #if PG_VERSION_NUM >= PG_VERSION_12 #include "nodes/pathnodes.h" #else #include "nodes/relation.h" #endif #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 distributedRelation; RangeTblEntry *rte; RelOptInfo *relOptInfo; PlannerInfo *plannerInfo; List *prunedShardIntervalList; /* list of RootPlanParams for all outer nodes */ List *outerPlanParamsList; } RelationRestriction; typedef struct JoinRestrictionContext { List *joinRestrictionList; bool hasSemiJoin; } 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; }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, append and range partitioned tables */ bool hasDistributedTable; /* 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; #if PG_VERSION_NUM >= PG_VERSION_13 extern PlannedStmt * distributed_planner(Query *parse, const char *query_string, int cursorOptions, ParamListInfo boundParams); #else extern PlannedStmt * distributed_planner(Query *parse, int cursorOptions, ParamListInfo boundParams); #endif /* * 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 struct DistributedPlan * GetDistributedPlan(CustomScan *node); extern void multi_relation_restriction_hook(PlannerInfo *root, RelOptInfo *relOptInfo, Index restrictionIndex, RangeTblEntry *rte); 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 LOCKMODE GetQueryLockMode(Query *query); extern int32 BlessRecordExpression(Expr *expr); extern void DissuadePlannerFromUsingPlan(PlannedStmt *plan); extern PlannedStmt * FinalizePlan(PlannedStmt *localPlan, struct DistributedPlan *distributedPlan); extern RTEListProperties * GetRTEListPropertiesForQuery(Query *query); extern struct DistributedPlan * CreateDistributedPlan(uint64 planId, Query *originalQuery, Query *query, ParamListInfo boundParams, bool hasUnresolvedParams, PlannerRestrictionContext * plannerRestrictionContext); #endif /* DISTRIBUTED_PLANNER_H */