@@ -133,8 +133,7 @@ DuckdbRangeTableEntry(CustomScan *custom_scan) {
133
133
}
134
134
135
135
PlannedStmt *
136
- DuckdbPlanNode (Query *parse, const char *query_string, int cursor_options, ParamListInfo bound_params,
137
- bool throw_error) {
136
+ DuckdbPlanNode (Query *parse, int cursor_options, bool throw_error) {
138
137
/* We need to check can we DuckDB create plan */
139
138
140
139
Plan *duckdb_plan = InvokeCPPFunc (CreatePlan, parse, throw_error);
@@ -152,39 +151,46 @@ DuckdbPlanNode(Query *parse, const char *query_string, int cursor_options, Param
152
151
duckdb_plan = materialize_finished_plan (duckdb_plan);
153
152
}
154
153
155
- /*
156
- * We let postgres generate a basic plan, but then completely overwrite the
157
- * actual plan with our CustomScan node. This is useful to get the correct
158
- * values for all the other many fields of the PlannedStmt.
159
- *
160
- * XXX: The primary reason we did this in the past is so that Postgres
161
- * filled in permInfos and rtable correctly. Those are needed for postgres
162
- * to do its permission checks on the used tables. We do these checks
163
- * inside DuckDB as well, so that's not really necessary anymore. We still
164
- * do this though to get all the other fields filled in correctly. Possibly
165
- * we don't need to do this anymore.
166
- *
167
- * FIXME: For some reason this needs an additional query copy to allow
168
- * re-planning of the query later during execution. But I don't really
169
- * understand why this is needed.
170
- */
171
- Query *copied_query = (Query *)copyObjectImpl (parse);
172
- PlannedStmt *postgres_plan = standard_planner (copied_query, query_string, cursor_options, bound_params);
173
-
174
- postgres_plan->planTree = duckdb_plan;
154
+ PlannedStmt *planned_stmt = makeNode (PlannedStmt);
155
+ planned_stmt->commandType = parse->commandType ;
156
+ planned_stmt->queryId = parse->queryId ;
157
+ planned_stmt->hasReturning = (parse->returningList != NIL);
158
+ planned_stmt->hasModifyingCTE = parse->hasModifyingCTE ;
159
+ planned_stmt->canSetTag = parse->canSetTag ;
160
+ planned_stmt->transientPlan = false ;
161
+ planned_stmt->dependsOnRole = false ;
162
+ planned_stmt->parallelModeNeeded = false ;
163
+ planned_stmt->planTree = duckdb_plan;
164
+ planned_stmt->rtable = NULL ;
165
+ #if PG_VERSION_NUM >= 160000
166
+ planned_stmt->permInfos = NULL ;
167
+ #endif
168
+ planned_stmt->resultRelations = NULL ;
169
+ planned_stmt->appendRelations = NULL ;
170
+ planned_stmt->subplans = NIL;
171
+ planned_stmt->rewindPlanIDs = NULL ;
172
+ planned_stmt->rowMarks = NIL;
173
+ planned_stmt->relationOids = NIL;
174
+ planned_stmt->invalItems = NIL;
175
+ planned_stmt->paramExecTypes = NIL;
176
+
177
+ /* utilityStmt should be null, but we might as well copy it */
178
+ planned_stmt->utilityStmt = parse->utilityStmt ;
179
+ planned_stmt->stmt_location = parse->stmt_location ;
180
+ planned_stmt->stmt_len = parse->stmt_len ;
175
181
176
182
/* Put a DuckdDB RTE at the end of the rtable */
177
183
RangeTblEntry *rte = DuckdbRangeTableEntry (custom_scan);
178
- postgres_plan ->rtable = lappend (postgres_plan ->rtable , rte);
184
+ planned_stmt ->rtable = lappend (planned_stmt ->rtable , rte);
179
185
180
186
/* Update the varno of the Var nodes in the custom_scan_tlist, to point to
181
187
* our new RTE. This should not be necessary anymore when we stop relying
182
188
* on the standard_planner here. */
183
189
foreach_node (TargetEntry, target_entry, custom_scan->custom_scan_tlist ) {
184
190
Var *var = castNode (Var, target_entry->expr );
185
191
186
- var->varno = list_length (postgres_plan ->rtable );
192
+ var->varno = list_length (planned_stmt ->rtable );
187
193
}
188
194
189
- return postgres_plan ;
195
+ return planned_stmt ;
190
196
}
0 commit comments