1 /*------------------------------------------------------------------------- 2 * 3 * distributed_planner.h 4 * General Citus planner code. 5 * 6 * Copyright (c) Citus Data, Inc. 7 *------------------------------------------------------------------------- 8 */ 9 10 #ifndef DISTRIBUTED_PLANNER_H 11 #define DISTRIBUTED_PLANNER_H 12 13 #include "postgres.h" 14 15 #include "distributed/pg_version_constants.h" 16 17 #include "nodes/plannodes.h" 18 19 #include "nodes/pathnodes.h" 20 21 #include "distributed/citus_nodes.h" 22 #include "distributed/errormessage.h" 23 #include "distributed/log_utils.h" 24 25 26 /* values used by jobs and tasks which do not require identifiers */ 27 #define INVALID_JOB_ID 0 28 #define INVALID_TASK_ID 0 29 30 #define CURSOR_OPT_FORCE_DISTRIBUTED 0x080000 31 32 33 /* level of planner calls */ 34 extern int PlannerLevel; 35 36 37 typedef struct RelationRestrictionContext 38 { 39 bool allReferenceTables; 40 List *relationRestrictionList; 41 } RelationRestrictionContext; 42 43 44 typedef struct RootPlanParams 45 { 46 PlannerInfo *root; 47 48 /* 49 * Copy of root->plan_params. root->plan_params is not preserved in 50 * relation_restriction_equivalence, so we need to create a copy. 51 */ 52 List *plan_params; 53 } RootPlanParams; 54 55 typedef struct RelationRestriction 56 { 57 Index index; 58 Oid relationId; 59 bool distributedRelation; 60 RangeTblEntry *rte; 61 RelOptInfo *relOptInfo; 62 PlannerInfo *plannerInfo; 63 64 /* list of RootPlanParams for all outer nodes */ 65 List *outerPlanParamsList; 66 67 /* list of translated vars, this is copied from postgres since it gets deleted on postgres*/ 68 List *translatedVars; 69 } RelationRestriction; 70 71 typedef struct JoinRestrictionContext 72 { 73 List *joinRestrictionList; 74 bool hasSemiJoin; 75 } JoinRestrictionContext; 76 77 typedef struct JoinRestriction 78 { 79 JoinType joinType; 80 List *joinRestrictInfoList; 81 PlannerInfo *plannerInfo; 82 Relids innerrelRelids; 83 Relids outerrelRelids; 84 } JoinRestriction; 85 86 typedef struct FastPathRestrictionContext 87 { 88 bool fastPathRouterQuery; 89 90 /* 91 * While calculating fastPathRouterQuery, we could sometimes be 92 * able to extract the distribution key value as well (such as when 93 * there are no prepared statements). Could be NULL when the distribution 94 * key contains parameter, so check for it before using. 95 */ 96 Const *distributionKeyValue; 97 98 /* 99 * Set to true when distKey = Param; in the queryTree 100 */ 101 bool distributionKeyHasParam; 102 }FastPathRestrictionContext; 103 104 typedef struct PlannerRestrictionContext 105 { 106 RelationRestrictionContext *relationRestrictionContext; 107 JoinRestrictionContext *joinRestrictionContext; 108 109 /* 110 * When the query is qualified for fast path, we don't have 111 * the RelationRestrictionContext and JoinRestrictionContext 112 * since those are dependent to calling standard_planner. 113 * Instead, we keep this struct to pass some extra information. 114 */ 115 FastPathRestrictionContext *fastPathRestrictionContext; 116 MemoryContext memoryContext; 117 } PlannerRestrictionContext; 118 119 typedef struct RelationShard 120 { 121 CitusNode type; 122 Oid relationId; 123 uint64 shardId; 124 } RelationShard; 125 126 typedef struct RelationRowLock 127 { 128 CitusNode type; 129 Oid relationId; 130 LockClauseStrength rowLockStrength; 131 } RelationRowLock; 132 133 134 /* 135 * Parameters to be set according to range table entries of a query. 136 */ 137 typedef struct RTEListProperties 138 { 139 bool hasPostgresLocalTable; 140 141 bool hasReferenceTable; 142 bool hasCitusLocalTable; 143 144 /* includes hash, append and range partitioned tables */ 145 bool hasDistributedTable; 146 147 /* union of hasReferenceTable, hasCitusLocalTable and hasDistributedTable */ 148 bool hasCitusTable; 149 150 bool hasMaterializedView; 151 } RTEListProperties; 152 153 154 typedef struct DistributedPlanningContext 155 { 156 /* The parsed query that is given to the planner. It is a slightly modified 157 * to work with the standard_planner */ 158 Query *query; 159 160 /* A copy of the original parsed query that is given to the planner. This 161 * doesn't contain most of the changes that are made to parse. There's one 162 * that change that is made for non fast path router queries though, which 163 * is the assigning of RTE identities using AssignRTEIdentities. This is 164 * NULL for non distributed plans, since those don't need it. */ 165 Query *originalQuery; 166 167 /* the cursor options given to the planner */ 168 int cursorOptions; 169 170 /* the ParamListInfo that is given to the planner */ 171 ParamListInfo boundParams; 172 173 /* Plan created either by standard_planner or by FastPathPlanner */ 174 PlannedStmt *plan; 175 176 /* Our custom restriction context */ 177 PlannerRestrictionContext *plannerRestrictionContext; 178 } DistributedPlanningContext; 179 180 181 /* 182 * CitusCustomScanPath is injected into the planner during the combine query planning 183 * phase of the logical planner. 184 * 185 * We call out to the standard planner to plan the combine query part for the output of 186 * the logical planner. This makes it easier to implement new sql features into the 187 * logical planner by not having to manually implement the plan creation for the combine 188 * query on the coordinator.. 189 */ 190 typedef struct CitusCustomScanPath 191 { 192 CustomPath custom_path; 193 194 /* 195 * Custom scan node computed by the citus planner that will produce the tuples for the 196 * path we are injecting during the planning of the combine query 197 */ 198 CustomScan *remoteScan; 199 } CitusCustomScanPath; 200 201 202 #if PG_VERSION_NUM >= PG_VERSION_13 203 extern PlannedStmt * distributed_planner(Query *parse, 204 const char *query_string, 205 int cursorOptions, 206 ParamListInfo boundParams); 207 #else 208 extern PlannedStmt * distributed_planner(Query *parse, 209 int cursorOptions, 210 ParamListInfo boundParams); 211 #endif 212 213 214 /* 215 * Common hint message to workaround using postgres local and citus local tables 216 * in distributed queries 217 */ 218 #define LOCAL_TABLE_SUBQUERY_CTE_HINT \ 219 "Use CTE's or subqueries to select from local tables and use them in joins" 220 221 extern List * ExtractRangeTableEntryList(Query *query); 222 extern bool NeedsDistributedPlanning(Query *query); 223 extern List * TranslatedVarsForRteIdentity(int rteIdentity); 224 extern struct DistributedPlan * GetDistributedPlan(CustomScan *node); 225 extern void multi_relation_restriction_hook(PlannerInfo *root, RelOptInfo *relOptInfo, 226 Index restrictionIndex, RangeTblEntry *rte); 227 extern void multi_join_restriction_hook(PlannerInfo *root, 228 RelOptInfo *joinrel, 229 RelOptInfo *outerrel, 230 RelOptInfo *innerrel, 231 JoinType jointype, 232 JoinPathExtraData *extra); 233 extern bool HasUnresolvedExternParamsWalker(Node *expression, ParamListInfo boundParams); 234 extern bool IsModifyCommand(Query *query); 235 extern void EnsurePartitionTableNotReplicated(Oid relationId); 236 extern Node * ResolveExternalParams(Node *inputNode, ParamListInfo boundParams); 237 extern bool IsMultiTaskPlan(struct DistributedPlan *distributedPlan); 238 extern RangeTblEntry * RemoteScanRangeTableEntry(List *columnNameList); 239 extern int GetRTEIdentity(RangeTblEntry *rte); 240 extern bool GetOriginalInh(RangeTblEntry *rte); 241 extern LOCKMODE GetQueryLockMode(Query *query); 242 extern int32 BlessRecordExpression(Expr *expr); 243 extern void DissuadePlannerFromUsingPlan(PlannedStmt *plan); 244 extern PlannedStmt * FinalizePlan(PlannedStmt *localPlan, 245 struct DistributedPlan *distributedPlan); 246 extern RTEListProperties * GetRTEListPropertiesForQuery(Query *query); 247 248 249 extern struct DistributedPlan * CreateDistributedPlan(uint64 planId, Query *originalQuery, 250 Query *query, ParamListInfo 251 boundParams, bool 252 hasUnresolvedParams, 253 PlannerRestrictionContext * 254 plannerRestrictionContext); 255 256 #endif /* DISTRIBUTED_PLANNER_H */ 257