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)

Reply via email to