Sean Broeder created CALCITE-7792:
-------------------------------------
Summary: AbstractNamespace.validate() sets status VALID even after
validateImpl() throws
Key: CALCITE-7792
URL: https://issues.apache.org/jira/browse/CALCITE-7792
Project: Calcite
Issue Type: Bug
Components: core
Affects Versions: 1.42.0
Reporter: Sean Broeder
Assignee: Sean Broeder
AbstractNamespace.validate()'s finally block sets status = VALID even when
validateImpl() throws, leaving rowType null. A subsequent getRowType() call on
that same namespace then recurses forever rather than resurfacing the original
error. It sees rowType == null and calls validateNamespace(), which calls
namespace.validate(...) and since status is already VALID, it calls
namespace.getType() -> getRowType() again, ending in a StackOverflowError.
example:
{code:java}
select * from (select bad_col from emp) as t
{code}
Validating this throws "Column 'BAD_COL' not found in any table" the first
time, as expected. But a second, independent getRowType() call on the inner
SELECT's namespace then throws StackOverflowError instead of re-surfacing that
error.
Reachability: this isn't triggered by ordinary correlated SQL through a single
top-level validate() call — I checked a CTE referenced twice via correlated
EXISTS clauses and two independently-correlated subqueries over the same
derived-table. Both surface the clean underlying error, not this bug. Calcite's
own internal re-entrant validate()/getRowType() calls only land on namespaces
that haven't failed yet, and a genuine failure aborts the whole top-level
validate() call before anything gets a second look at that same namespace.
The bug needs something that catches an exception from probing a namespace and
keeps going. In my case, this is a validator extension that speculatively
resolves an identifier against several candidate scopes and treats a resolution
failure as "not a match" rather than a hard error. An external caller that
revalidates the same parsed query or asks for a namespace's type again after an
earlier validation attempt on it would also hit the issue.
This problem can be mitigated if status is set conditionally in the finally
block and I see no impact on standard Calcite users in doing so, so I am hoping
this is agreeable.
{code:java}
status = succeeded ? SqlValidatorImpl.Status.VALID :
SqlValidatorImpl.Status.UNVALIDATED;
{code}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)