From 5fbd37689e16d5af387557fde4afb59526f2dc5c Mon Sep 17 00:00:00 2001 From: Andrey Sokolov Date: Sat, 25 Oct 2025 20:53:34 +0300 Subject: [PATCH 1/5] Don't try to use Orca for queries that it doesn't support On translating to DXL we can find out that the query is unsupported. The better time to make this decision is analyse stage, because in this case we can run Postgres planner without trying to run Orca and, as a consequence, significantly reduce planning time. Orca doesn't support gp_dist_random, queries on master-only tables, and function exec locations except for any. It's easy to detect on analyse stage, that a query contains these unsupported query properties. The number of unsupported query properties to check before translating to DXL will be increased later. --- src/backend/optimizer/plan/planner.c | 1 + src/backend/parser/analyze.c | 2 ++ src/backend/parser/parse_clause.c | 2 ++ src/backend/parser/parse_func.c | 4 ++++ src/backend/parser/parse_relation.c | 4 ++++ src/include/nodes/parsenodes.h | 1 + src/include/parser/parse_node.h | 2 ++ 7 files changed, 16 insertions(+) diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index a6920be46e4..d02eed04ee6 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -231,6 +231,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams) * PARALLEL RETRIEVE CURSOR is not supported by ORCA yet. */ if (optimizer && + !parse->usePostgresPlanner && GP_ROLE_DISPATCH == Gp_role && IS_QUERY_DISPATCHER() && (cursorOptions & CURSOR_OPT_PARALLEL_RETRIEVE) == 0) diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index a5666f90148..a13b01b141c 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -355,6 +355,8 @@ transformStmt(ParseState *pstate, Node *parseTree) if (pstate->p_hasDynamicFunction) result->hasDynamicFunctions = true; + result->usePostgresPlanner = pstate->usePostgresPlanner; + return result; } diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 36be42a4f8d..53d610aad61 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -840,6 +840,8 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r) /* Now we set our special attribute in the rte. */ rte->forceDistRandom = true; + /* Orca doesn't support gp_dist_random */ + pstate->usePostgresPlanner = true; return rte; } diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index 267f5ebbbe7..dffa3695fb7 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -316,6 +316,10 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, errmsg("OVER specified, but %s is not a window function nor an aggregate function", NameListToString(funcname)), parser_errposition(pstate, location))); + + /* Orca supports only the any exec location */ + if (func_exec_location(funcid) != PROEXECLOCATION_ANY) + pstate->usePostgresPlanner = true; } else if (fdresult == FUNCDETAIL_AGGREGATE) { diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index 2ebb07b1224..32698b4dbc1 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -1029,6 +1029,10 @@ parserOpenTable(ParseState *pstate, const RangeVar *relation, } } + /* Orca doesn't support queries on master-only tables */ + if (rel->rd_cdbpolicy == NULL) + pstate->usePostgresPlanner = true; + cancel_parser_errposition_callback(&pcbstate); return rel; } diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index da212dc560a..04a91f8efcc 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -215,6 +215,7 @@ typedef struct Query */ ParentStmtType parentStmtType; bool expandMatViews; /* force expansion of materialized views during rewrite to treat as views */ + bool usePostgresPlanner; /* don't try to plan the query using Orca */ } Query; /**************************************************************************** diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h index d89088d7677..ed47ee61da8 100644 --- a/src/include/parser/parse_node.h +++ b/src/include/parser/parse_node.h @@ -177,6 +177,8 @@ struct ParseState ParseParamRefHook p_paramref_hook; CoerceParamHook p_coerce_param_hook; void *p_ref_hook_state; /* common passthrough link for above */ + bool usePostgresPlanner; /* parse analysis found out that Orca + doesn't support the query */ }; /* From c53e55c75312665fa45ccbe487d7a4fab231b3b8 Mon Sep 17 00:00:00 2001 From: Alena Rybakina Date: Wed, 3 Jun 2026 05:44:59 +0300 Subject: [PATCH 2/5] Don't try to use Orca for lateral queries too Orca doesn't support LATERAL, so a query using it is handed to Orca only to fail during DXL translation and fall back to the Postgres planner. As with the other unsupported properties detected at parse analysis in the previous commit, recognize LATERAL there as well and set usePostgresPlanner, so the Postgres planner runs directly without the wasted Orca attempt. --- src/backend/parser/parse_relation.c | 12 ++++++++++++ src/test/regress/expected/aggregates_optimizer.out | 4 ---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index 32698b4dbc1..58523a8f9b3 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -1264,6 +1264,10 @@ addRangeTableEntryForSubquery(ParseState *pstate, rte->inh = false; /* never true for subqueries */ rte->inFromCl = inFromCl; + /* Orca doesn't support LATERAL */ + if (pstate != NULL && lateral) + pstate->usePostgresPlanner = true; + rte->requiredPerms = 0; rte->checkAsUser = InvalidOid; rte->selectedCols = NULL; @@ -1638,6 +1642,10 @@ addRangeTableEntryForFunction(ParseState *pstate, rte->inh = false; /* never true for functions */ rte->inFromCl = inFromCl; + /* Orca doesn't support LATERAL */ + if (pstate != NULL && lateral) + pstate->usePostgresPlanner = true; + rte->requiredPerms = 0; rte->checkAsUser = InvalidOid; rte->selectedCols = NULL; @@ -1710,6 +1718,10 @@ addRangeTableEntryForValues(ParseState *pstate, rte->inh = false; /* never true for values RTEs */ rte->inFromCl = inFromCl; + /* Orca doesn't support LATERAL */ + if (pstate != NULL && lateral) + pstate->usePostgresPlanner = true; + rte->requiredPerms = 0; rte->checkAsUser = InvalidOid; rte->selectedCols = NULL; diff --git a/src/test/regress/expected/aggregates_optimizer.out b/src/test/regress/expected/aggregates_optimizer.out index 1c9fde10903..0b7fa04650f 100644 --- a/src/test/regress/expected/aggregates_optimizer.out +++ b/src/test/regress/expected/aggregates_optimizer.out @@ -386,8 +386,6 @@ from generate_series(1, 3) s1, lateral (select s2, sum(s1 + s2) sm from generate_series(1, 3) s2 group by s2) ss order by 1, 2; -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: LATERAL QUERY PLAN ------------------------------------------------------------------------ Sort @@ -414,8 +412,6 @@ from generate_series(1, 3) s1, lateral (select s2, sum(s1 + s2) sm from generate_series(1, 3) s2 group by s2) ss order by 1, 2; -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: LATERAL s1 | s2 | sm ----+----+---- 1 | 1 | 2 From b16620f21516c6186cf12b35395c2ca4a6013c4f Mon Sep 17 00:00:00 2001 From: Alena Rybakina Date: Wed, 3 Jun 2026 06:15:15 +0300 Subject: [PATCH 3/5] Don't treat views as master-only tables when choosing the planner The master-only detection fires on a NULL distribution policy, which views have too, so every query over a view was needlessly pushed onto the Postgres planner. That path keeps the view's range table entry for permission checks, which made pgaudit emit an extra OBJECT record for the view. A view is expanded into its base relations before planning, so Orca never scans the view itself. Exclude views (RELKIND_VIEW) from the check. --- src/backend/parser/parse_relation.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index 58523a8f9b3..2d9baee3353 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -1029,8 +1029,13 @@ parserOpenTable(ParseState *pstate, const RangeVar *relation, } } - /* Orca doesn't support queries on master-only tables */ - if (rel->rd_cdbpolicy == NULL) + /* + * Orca doesn't support queries on master-only tables. A view also has + * no distribution policy, but it is expanded into its base relations + * before planning, so exclude it -- otherwise every query over a view is + * needlessly forced onto the Postgres planner. + */ + if (rel->rd_cdbpolicy == NULL && rel->rd_rel->relkind != RELKIND_VIEW) pstate->usePostgresPlanner = true; cancel_parser_errposition_callback(&pcbstate); From 66f9bf1cb320d30b6007768ce429d578c6522a7e Mon Sep 17 00:00:00 2001 From: Alena Rybakina Date: Wed, 3 Jun 2026 07:50:22 +0300 Subject: [PATCH 4/5] Copy usePostgresPlanner when copying a Query usePostgresPlanner was added to Query but never registered in the node support functions, so copyObject() on a Query silently dropped it. EXPLAIN copies the query before planning, so an EXPLAIN of a query that set the lost it and was still handed to Orca - which then failed and fell back, defeating the optimization. --- src/backend/nodes/copyfuncs.c | 1 + src/backend/nodes/equalfuncs.c | 1 + src/backend/nodes/outfuncs.c | 1 + src/backend/nodes/readfuncs.c | 1 + 4 files changed, 4 insertions(+) diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index c38fccfad41..aeca2e22a4a 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -3195,6 +3195,7 @@ _copyQuery(const Query *from) COPY_NODE_FIELD(constraintDeps); COPY_NODE_FIELD(intoPolicy); COPY_SCALAR_FIELD(parentStmtType); + COPY_SCALAR_FIELD(usePostgresPlanner); return newnode; } diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index d85c4f1150c..bb12a2d47e5 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -933,6 +933,7 @@ _equalQuery(const Query *a, const Query *b) return false; COMPARE_SCALAR_FIELD(parentStmtType); + COMPARE_SCALAR_FIELD(usePostgresPlanner); return true; } diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 7c0ee2eed62..123a9317569 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -3837,6 +3837,7 @@ _outQuery(StringInfo str, const Query *node) WRITE_NODE_FIELD(setOperations); WRITE_NODE_FIELD(constraintDeps); WRITE_BOOL_FIELD(parentStmtType); + WRITE_BOOL_FIELD(usePostgresPlanner); /* Don't serialize policy */ } diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 1b673158570..b935c05f287 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -404,6 +404,7 @@ _readQuery(void) READ_NODE_FIELD(setOperations); READ_NODE_FIELD(constraintDeps); READ_BOOL_FIELD(parentStmtType); + READ_BOOL_FIELD(usePostgresPlanner); local_node->intoPolicy = NULL; From dd1f6e09d35987b05743e081e4453d50afbb2562 Mon Sep 17 00:00:00 2001 From: Alena Rybakina Date: Wed, 3 Jun 2026 08:51:45 +0300 Subject: [PATCH 5/5] Update expected output for the master-only Orca fallback --- .../regress/expected/bfv_cte_optimizer.out | 2 -- .../expected/bfv_statistic_optimizer.out | 2 -- .../regress/expected/gporca_optimizer.out | 4 --- .../expected/olap_window_seq_optimizer.out | 32 ------------------- .../expected/qp_with_clause_optimizer.out | 16 ---------- 5 files changed, 56 deletions(-) diff --git a/src/test/regress/expected/bfv_cte_optimizer.out b/src/test/regress/expected/bfv_cte_optimizer.out index a82cc2ec619..4c89d928f85 100644 --- a/src/test/regress/expected/bfv_cte_optimizer.out +++ b/src/test/regress/expected/bfv_cte_optimizer.out @@ -519,8 +519,6 @@ create view cte_view as -- to pick a plan that would crash before this fix set allow_system_table_mods=true; update pg_class set relpages = 1::int, reltuples = 12.0::real where relname = 'a_table'; -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: Queries on master-only tables reset allow_system_table_mods; explain select * from a_table join cte_view on a_table.a = (select a from cte_view) where cte_view.a = 2024; NOTICE: One or more columns in the following table(s) do not have statistics: a_table diff --git a/src/test/regress/expected/bfv_statistic_optimizer.out b/src/test/regress/expected/bfv_statistic_optimizer.out index 4d8ebfb5770..e30f0af1e96 100644 --- a/src/test/regress/expected/bfv_statistic_optimizer.out +++ b/src/test/regress/expected/bfv_statistic_optimizer.out @@ -463,8 +463,6 @@ SET reltuples = 10000000000.0::real, relallvisible = 0::int WHERE relname = 'tiny_freq' AND relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'bfv_statistic'); -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: Queries on master-only tables INSERT INTO pg_statistic VALUES ( 'bfv_statistic.tiny_freq'::regclass, 1::smallint, diff --git a/src/test/regress/expected/gporca_optimizer.out b/src/test/regress/expected/gporca_optimizer.out index 78b4cfcf0b1..e2c1fbd62c1 100644 --- a/src/test/regress/expected/gporca_optimizer.out +++ b/src/test/regress/expected/gporca_optimizer.out @@ -9845,11 +9845,7 @@ with x as (select * from foo_missing_stats) select count(*) from x x1, x x2 wher set allow_system_table_mods=true; delete from pg_statistic where starelid='foo_missing_stats'::regclass; -NOTICE: One or more columns in the following table(s) do not have statistics: pg_statistic -HINT: For non-partitioned tables, run analyze (). For partitioned tables, run analyze rootpartition (). See log for columns missing statistics. delete from pg_statistic where starelid='bar_missing_stats'::regclass; -NOTICE: One or more columns in the following table(s) do not have statistics: pg_statistic -HINT: For non-partitioned tables, run analyze (). For partitioned tables, run analyze rootpartition (). See log for columns missing statistics. set allow_system_table_mods=false; select count(*) from foo_missing_stats where a = 10; NOTICE: One or more columns in the following table(s) do not have statistics: foo_missing_stats diff --git a/src/test/regress/expected/olap_window_seq_optimizer.out b/src/test/regress/expected/olap_window_seq_optimizer.out index 3aa7f092250..49e0210d1d8 100644 --- a/src/test/regress/expected/olap_window_seq_optimizer.out +++ b/src/test/regress/expected/olap_window_seq_optimizer.out @@ -7394,22 +7394,6 @@ create view v1 as select dt, sum(cn) over(order by grouping(cn) range grouping(cn) preceding) from sale group by rollup(cn,dt); \d+ v1 -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: Queries on master-only tables -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: Queries on master-only tables -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: Queries on master-only tables -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: Queries on master-only tables -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: Queries on master-only tables -CONTEXT: SQL function "col_description" during startup -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: Queries on master-only tables -CONTEXT: SQL statement "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_class = $1 AND rulename = $2" -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: Queries on master-only tables View "olap_window_seq.v1" Column | Type | Modifiers | Storage | Description --------+--------+-----------+---------+------------- @@ -8992,22 +8976,6 @@ ERROR: DISTINCT is supported only for single-argument window aggregates -- Test deparsing (for \d+ and pg_dump) create view distinct_windowagg_view as select sum(distinct g/2) OVER (partition by g/4) from generate_series (1, 5) g; \d+ distinct_windowagg_view -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: Queries on master-only tables -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: Queries on master-only tables -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: Queries on master-only tables -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: Queries on master-only tables -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: Queries on master-only tables -CONTEXT: SQL function "col_description" during startup -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: Queries on master-only tables -CONTEXT: SQL statement "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_class = $1 AND rulename = $2" -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: Queries on master-only tables View "olap_window_seq.distinct_windowagg_view" Column | Type | Modifiers | Storage | Description --------+--------+-----------+---------+------------- diff --git a/src/test/regress/expected/qp_with_clause_optimizer.out b/src/test/regress/expected/qp_with_clause_optimizer.out index eb398f2e6b1..8b7c5b3d9ae 100644 --- a/src/test/regress/expected/qp_with_clause_optimizer.out +++ b/src/test/regress/expected/qp_with_clause_optimizer.out @@ -9532,22 +9532,6 @@ where longlivingregions.region = denseregions.region and allcountrystats.code = and country.indepyear > 1900 ); \d+ view_with_shared_scans; -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: Queries on master-only tables -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: Queries on master-only tables -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: Queries on master-only tables -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: Queries on master-only tables -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: Queries on master-only tables -CONTEXT: SQL function "col_description" during startup -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: Queries on master-only tables -CONTEXT: SQL statement "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_class = $1 AND rulename = $2" -INFO: GPORCA failed to produce a plan, falling back to planner -DETAIL: Feature not supported: Queries on master-only tables View "qp_with_clause.view_with_shared_scans" Column | Type | Modifiers | Storage | Description ---------------------+------------------+-----------+----------+-------------