Repository navigation
Conversation
| { | ||
| continue; | ||
| } | ||
| GPOS_ASSERT(IsA(join_alias_node, Var) || |
There was a problem hiding this comment.
Hi! Thank you for working on it!
Removing the assertion does not fully fix coerced USING columns. NormalizeQuery does not flatten join aliases in WHERE or JOIN ... ON conditions: flatten_join_alias_var_optimizer intentionally skips quals.
For RelabelType, the translator allocates a new colid and records it in the mapping, but only CoalesceExpr is added to the computed projection. A condition can therefore reference a column that is never computed, causing GPORCA to fall back with: DXL-to-Expr Translation: Attribute number 21 not found in project list
Bug reproduction:
SET optimizer = on;
SET optimizer_trace_fallback = on;
CREATE TABLE using_coerce_t1(k varchar(10), f2 int)
DISTRIBUTED BY (f2);
CREATE TABLE using_coerce_t2(k text, f2 oid)
DISTRIBUTED BY (f2);
INSERT INTO using_coerce_t1 VALUES ('a', 1), ('b', 2);
INSERT INTO using_coerce_t2 VALUES ('a', 1), ('c', 3);
EXPLAIN (COSTS OFF)
SELECT k
FROM using_coerce_t1
LEFT JOIN using_coerce_t2 USING (k)
WHERE k = 'a';
output:
pr2148=# SET optimizer = on;
SET
pr2148=# SET optimizer_trace_fallback = on;
SET
pr2148=# EXPLAIN (COSTS OFF)
pr2148# SELECT k
pr2148# FROM using_coerce_t1
pr2148# LEFT JOIN using_coerce_t2 USING (k)
pr2148# WHERE k = 'a';
INFO: GPORCA failed to produce a plan, falling back to Postgres-based planner
DETAIL: DXL-to-Expr Translation: Attribute number 21 not found in project list
QUERY PLAN
---------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3)
-> Nested Loop Left Join
-> Seq Scan on using_coerce_t1
Filter: ((k)::text = 'a'::text)
-> Materialize
-> Broadcast Motion 3:3 (slice2; segments: 3)
-> Seq Scan on using_coerce_t2
Filter: (k = 'a'::text)
Optimizer: Postgres query optimizer
(9 rows)
There was a problem hiding this comment.
Thanks, you are right — and it is worse than the RelabelType case: the same hole already exists on main for FuncExpr.
TranslateExprToDXLProject reuses the input colid only for a plain Var; every other expression gets a fresh colid from m_colid_counter. LoadProjectElements then records that colid for <query level, rtindex, attno>, but only the CoalesceExpr branch pushed the proj element into project_list_computed_cols_dxlnode. So for any coerced merged column the mapping points at a column nothing produces, and as you say flatten_join_alias_var_optimizer deliberately skips quals, so a predicate on the merged column reaches it.
Pre-existing repro on main, no RelabelType involved (int vs bigint ⇒ FuncExpr):
CREATE TABLE uf1(k int, v int) DISTRIBUTED BY (v);
CREATE TABLE uf2(k bigint, v int) DISTRIBUTED BY (v);
EXPLAIN (COSTS OFF) SELECT k FROM uf1 LEFT JOIN uf2 USING (k) WHERE k = 1;
INFO: GPORCA failed to produce a plan, falling back to Postgres-based planner
DETAIL: DXL-to-Expr Translation: Attribute number 21 not found in project listFixed in 59f8233 by making the computed-columns projection cover every non-Var join alias instead of enumerating node tags:
if (!IsA(join_alias_node, Var))
{
project_elem_dxlnode->AddRef();
project_list_computed_cols_dxlnode->AddChild(project_elem_dxlnode);
}Both of your queries and the int/bigint shape now plan in GPORCA:
Gather Motion 3:1 (slice1; segments: 3)
-> Hash Left Join
Hash Cond: ((using_coerce_t1.k)::text = using_coerce_t2.k)
-> Seq Scan on using_coerce_t1
Filter: ((k)::text = 'a'::text)
-> Hash
-> Broadcast Motion 3:3 (slice2; segments: 3)
-> Seq Scan on using_coerce_t2
Optimizer: GPORCA
join_gp is extended with predicates on the merged column for the varchar/text, int/oid and int/bigint shapes, and passes with optimizer=on and optimizer=off.
The merged column of a USING join is the left input coerced to the common type when the two input types differ. For binary-compatible types such as varchar vs text or int vs oid the parser emits a RelabelType, which CTranslatorQueryToDXL::TranslateJoinExprInFromToDXL rejected with an assertion that only allowed Var, FuncExpr and CoalesceExpr. On assert-enabled builds every such query fell back to the Postgres planner: CTranslatorQueryToDXL.cpp:4145: Failed assertion: IsA(join_alias_node, Var) || IsA(join_alias_node, FuncExpr) || IsA(join_alias_node, CoalesceExpr) References to join alias columns are flattened by CQueryMutators::NormalizeQuery before the join itself is translated, which is why the FuncExpr case already worked without any special handling. The projection element only has to be an expression the scalar translator understands, so drop the enumeration. Nodes the scalar translator does not support still raise the regular unsupported-feature exception and fall back cleanly. Add a regression case to join_gp covering varchar/text and int/oid USING columns, including the nested left join shape from the aggregates test.
TranslateJoinExprInFromToDXL only added the CoalesceExpr flavour of a merged USING column to the computed-columns project list, but TranslateExprToDXLProject allocates a fresh colid for every join alias var that is not a plain Var. The <query level, varno, varattno> mapping loaded right below therefore pointed at a column no operator produced for the coercion flavours (FuncExpr, RelabelType, ...). Target list references were unaffected because flatten_join_alias_var_optimizer rewrites them to the base relation columns, but it deliberately leaves quals alone, so a predicate on the merged column still goes through the mapping and ORCA bailed out with DXL-to-Expr Translation: Attribute number 21 not found in project list This is a pre-existing bug for the FuncExpr case (int vs bigint USING columns) and would newly be reachable for RelabelType. Add the project element for any non-Var join alias instead of enumerating node tags. Extend the join_gp cases with predicates on the merged column for both the RelabelType (varchar/text, int/oid) and the FuncExpr (int/bigint) shapes. Reported-by: Alena Rybakina
59f8233 to
c52e695
Compare
The merged column of a USING join is the left input coerced to the common type when the two input types differ. For binary-compatible types such as varchar vs text or int vs oid the parser emits a RelabelType, which CTranslatorQueryToDXL::TranslateJoinExprInFromToDXL rejected with an assertion that only allowed Var, FuncExpr and CoalesceExpr. On assert-enabled builds every such query fell back to the Postgres planner:
CTranslatorQueryToDXL.cpp:4145: Failed assertion:
IsA(join_alias_node, Var) || IsA(join_alias_node, FuncExpr) ||
IsA(join_alias_node, CoalesceExpr)
References to join alias columns are flattened by
CQueryMutators::NormalizeQuery before the join itself is translated, which is why the FuncExpr case already worked without any special handling. The projection element only has to be an expression the scalar translator understands, so drop the enumeration. Nodes the scalar translator does not support still raise the regular unsupported-feature exception and fall back cleanly.
Add a regression case to join_gp covering varchar/text and int/oid USING columns, including the nested left join shape from the aggregates test.
Fixes #ISSUE_Number
What does this PR do?
Type of Change
Breaking Changes
Test Plan
make installcheckmake -C src/test installcheck-cbdb-parallelImpact
Performance:
User-facing changes:
Dependencies:
Checklist
Additional Context
CI Skip Instructions