Skip to content

Commit 64ff71e

Browse files
committed
Don't call into the Postgres planner anymore when we take over
In the past we needed to call into the Postgres planner for permission checking on Postgres tables. This has not been needed for a while now. We were still doing it out of caution for breaking other things, but it seems like that might be causing problems by itself too. And also it's quite a waste of CPU cycles.
1 parent 6dc835c commit 64ff71e

File tree

3 files changed

+36
-30
lines changed

3 files changed

+36
-30
lines changed

src/pgduckdb_planner.cpp

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,7 @@ DuckdbRangeTableEntry(CustomScan *custom_scan) {
133133
}
134134

135135
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) {
138137
/* We need to check can we DuckDB create plan */
139138

140139
Plan *duckdb_plan = InvokeCPPFunc(CreatePlan, parse, throw_error);
@@ -152,39 +151,46 @@ DuckdbPlanNode(Query *parse, const char *query_string, int cursor_options, Param
152151
duckdb_plan = materialize_finished_plan(duckdb_plan);
153152
}
154153

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;
175181

176182
/* Put a DuckdDB RTE at the end of the rtable */
177183
RangeTblEntry *rte = DuckdbRangeTableEntry(custom_scan);
178-
postgres_plan->rtable = lappend(postgres_plan->rtable, rte);
184+
planned_stmt->rtable = lappend(planned_stmt->rtable, rte);
179185

180186
/* Update the varno of the Var nodes in the custom_scan_tlist, to point to
181187
* our new RTE. This should not be necessary anymore when we stop relying
182188
* on the standard_planner here. */
183189
foreach_node(TargetEntry, target_entry, custom_scan->custom_scan_tlist) {
184190
Var *var = castNode(Var, target_entry->expr);
185191

186-
var->varno = list_length(postgres_plan->rtable);
192+
var->varno = list_length(planned_stmt->rtable);
187193
}
188194

189-
return postgres_plan;
195+
return planned_stmt;
190196
}

test/regression/expected/non_superuser.out

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ SELECT * FROM t;
1515
-- Should fail
1616
SET ROLE user2;
1717
SELECT * FROM t;
18-
ERROR: permission denied for table t
18+
ERROR: (PGDuckDB/Duckdb_ExecCustomScan_Cpp) Executor Error: (PGDuckDB/Init) permission denied for table t
1919
-- Should fail because we're not allowed to read the internal tables by default
2020
SELECT * from duckdb.tables;
21-
ERROR: permission denied for table tables
21+
ERROR: (PGDuckDB/Duckdb_ExecCustomScan_Cpp) Executor Error: (PGDuckDB/Init) permission denied for table tables
2222
SELECT * from duckdb.extensions;
23-
ERROR: permission denied for table extensions
23+
ERROR: (PGDuckDB/Duckdb_ExecCustomScan_Cpp) Executor Error: (PGDuckDB/Init) permission denied for table extensions
2424
-- Should fail because any Postgres tables accesesd from DuckDB will have their
2525
-- permissions checked even if it happens straight from DuckDB.
2626
SET duckdb.force_execution = false;

test/regression/expected/temporary_tables.out

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ EXPLAIN VERBOSE INSERT INTO tc(c) SELECT md5('ta');
471471
QUERY PLAN
472472
------------------------------------------------------------
473473
Custom Scan (DuckDBScan) (cost=0.00..0.00 rows=0 width=0)
474-
Output: duckdb_scan."Count"
474+
Output: "Count"
475475
DuckDB Execution Plan:
476476

477477
┌───────────────────────────┐
@@ -508,7 +508,7 @@ EXPLAIN VERBOSE INSERT INTO tc(d) SELECT md5('test');
508508
QUERY PLAN
509509
------------------------------------------------------------
510510
Custom Scan (DuckDBScan) (cost=0.00..0.00 rows=0 width=0)
511-
Output: duckdb_scan."Count"
511+
Output: "Count"
512512
DuckDB Execution Plan:
513513

514514
┌───────────────────────────┐

0 commit comments

Comments
 (0)