apache / apache/ignite

Assertion error in GridSqlQuerySplitter.normalizeExpression

Open
#10,544 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
5.1k
Forks
1.9k
Avg merge
3d 2h
Merged PRs (30d)
46

Description

An auto-generated SQL query is causing Ignite 2.14 with default h2 based SQL parser to crash with an AssertionError. I've distilled the SQL to the simplest it can be to expose the problem:
``` sql
select count(*) from (
select "dates_" from (
select "dates_" from "3a91b5ae9ccDM_FULAir_Passen_"
)
where "dates_" is not null
)
```
Result:
```
Feb 16, 2023 8:07:03 AM org.apache.ignite.logger.java.JavaLogger error
SEVERE: Runtime error caught during grid runnable execution: GridWorker [name=message-received-notify, igniteInstanceName=null, finished=false, heartbeatTs=1676534823448, hashCode=1652503014, interrupted=false, runner=client-connector-#263]
java.lang.AssertionError: 0
("dates_" IS NOT NULL)
at org.apache.ignite.internal.processors.query.h2.sql.GridSqlQuerySplitter.normalizeExpression(GridSqlQuerySplitter.java:1513)
at org.apache.ignite.internal.processors.query.h2.sql.GridSqlQuerySplitter.normalizeExpression(GridSqlQuerySplitter.java:1501)
at org.apache.ignite.internal.processors.query.h2.sql.GridSqlQuerySplitter.normalizeQuery(GridSqlQuerySplitter.java:1394)
at org.apache.ignite.internal.processors.query.h2.sql.GridSqlQuerySplitter.split0(GridSqlQuerySplitter.java:280)
at org.apache.ignite.internal.processors.query.h2.sql.GridSqlQuerySplitter.split(GridSqlQuerySplitter.java:221)
at org.apache.ignite.internal.processors.query.h2.QueryParser.parseH2(QueryParser.java:552)
at org.apache.ignite.internal.processors.query.h2.QueryParser.parse0(QueryParser.java:229)
at org.apache.ignite.internal.processors.query.h2.QueryParser.parse(QueryParser.java:142)
at org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing.querySqlFields(IgniteH2Indexing.java:984)
at org.apache.ignite.internal.processors.query.GridQueryProcessor$2.applyx(GridQueryProcessor.java:3101)
at org.apache.ignite.internal.processors.query.GridQueryProcessor$2.applyx(GridQueryProcessor.java:3074)
at org.apache.ignite.internal.util.lang.IgniteOutClosureX.apply(IgniteOutClosureX.java:36)
at org.apache.ignite.internal.processors.query.GridQueryProcessor.executeQuery(GridQueryProcessor.java:3751)
at org.apache.ignite.internal.processors.query.GridQueryProcessor.lambda$querySqlFields$3(GridQueryProcessor.java:3118)
at org.apache.ignite.internal.processors.query.GridQueryProcessor.executeQuerySafe(GridQueryProcessor.java:3190)
at org.apache.ignite.internal.processors.query.GridQueryProcessor.querySqlFields(GridQueryProcessor.java:3070)
at org.apache.ignite.internal.processors.query.GridQueryProcessor.querySqlFields(GridQueryProcessor.java:3024)
at org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequestHandler.querySqlFields(JdbcRequestHandler.java:773)
at org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequestHandler.executeQuery(JdbcRequestHandler.java:641)
at org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequestHandler.doHandle(JdbcRequestHandler.java:311)
at org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequestHandler.handle(JdbcRequestHandler.java:251)
at org.apache.ignite.internal.processors.odbc.ClientListenerNioListener.onMessage(ClientListenerNioListener.java:204)
at org.apache.ignite.internal.processors.odbc.ClientListenerNioListener.onMessage(ClientListenerNioListener.java:55)
at org.apache.ignite.internal.util.nio.GridNioFilterChain$TailFilter.onMessageReceived(GridNioFilterChain.java:279)
at org.apache.ignite.internal.util.nio.GridNioFilterAdapter.proceedMessageReceived(GridNioFilterAdapter.java:109)
at org.apache.ignite.internal.util.nio.GridNioAsyncNotifyFilter$3.body(GridNioAsyncNotifyFilter.java:97)
at org.apache.ignite.internal.util.worker.GridWorker.run(GridWorker.java:125)
at org.apache.ignite.internal.util.worker.GridWorkerPool$1.run(GridWorkerPool.java:70)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
```
Problematic code:
``` java
// Unique aliases must be generated for all the table filters already.
assert uniqueAlias != null : childIdx + "\n" + parent.getSQL();
```

Now clearly this SQL could be written as
``` sql
select count(*) from (
select "dates_" from (
select "dates_" from "3a91b5ae9ccDM_FULAir_Passen_"
where "dates_" is not null
)
)
```
which solves the problem and stops the crash. But this is a simplification of auto-generated SQL; there are cases that need the triple nested querying to work this way.

I wonder whether the assertion error is identifying a bug, or is simply a poor way of communicating missing support for a particular SQL query structure.

I have not tried it with Calcite.

Contributor guide

Open the contributing guide

Research direction

Run the nested SQL reproducer against Ignite 2.14 with the default H2-based parser, then inspect GridSqlQuerySplitter.normalizeExpression around line 1513 and the surrounding normalization flow. Done means the query no longer crashes with AssertionError while preserving support for nested query structures that require the original form.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, sql
Domain
databases
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.