/* Distributed planner hook */ PlannedStmt * multi_planner(Query *parse, int cursorOptions, ParamListInfo boundParams) { PlannedStmt *result = NULL; /* * First call into standard planner. This is required because the Citus * planner relies on parse tree transformations made by postgres' planner. */ result = standard_planner(parse, cursorOptions, boundParams); if (NeedsDistributedPlanning(parse)) { MultiPlan *physicalPlan = CreatePhysicalPlan(parse); /* store required data into the planned statement */ result = MultiQueryContainerNode(result, physicalPlan); } return result; }
/* Distributed planner hook */ PlannedStmt * multi_planner(Query *parse, int cursorOptions, ParamListInfo boundParams) { PlannedStmt *result = NULL; bool needsDistributedPlanning = NeedsDistributedPlanning(parse); Query *originalQuery = NULL; RelationRestrictionContext *restrictionContext = NULL; /* * standard_planner scribbles on it's input, but for deparsing we need the * unmodified form. So copy once we're sure it's a distributed query. */ if (needsDistributedPlanning) { originalQuery = copyObject(parse); /* * We implement INSERT INTO .. SELECT by pushing down the SELECT to * each shard. To compute that we use the router planner, by adding * an "uninstantiated" constraint that the partition column be equal to a * certain value. standard_planner() distributes that constraint to * the baserestrictinfos to all the tables where it knows how to push * the restriction safely. An example is that the tables that are * connected via equi joins. * * The router planner then iterates over the target table's shards, * for each we replace the "uninstantiated" restriction, with one that * PruneShardList() handles, and then generate a query for that * individual shard. If any of the involved tables don't prune down * to a single shard, or if the pruned shards aren't colocated, * we error out. */ if (InsertSelectQuery(parse)) { AddUninstantiatedPartitionRestriction(parse); } } /* create a restriction context and put it at the end if context list */ restrictionContext = CreateAndPushRestrictionContext(); PG_TRY(); { /* * First call into standard planner. This is required because the Citus * planner relies on parse tree transformations made by postgres' planner. */ result = standard_planner(parse, cursorOptions, boundParams); if (needsDistributedPlanning) { MultiPlan *physicalPlan = CreatePhysicalPlan(originalQuery, parse, restrictionContext); /* store required data into the planned statement */ result = MultiQueryContainerNode(result, physicalPlan); } } PG_CATCH(); { PopRestrictionContext(); PG_RE_THROW(); } PG_END_TRY(); /* remove the context from the context list */ PopRestrictionContext(); return result; }