You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@ignite.apache.org by "Pavel Pereslegin (Jira)" <ji...@apache.org> on 2025/02/19 07:38:00 UTC
[jira] [Created] (IGNITE-24560) Sql. Result of script parsing with single statement is cached incorrectly
Pavel Pereslegin created IGNITE-24560:
-----------------------------------------
Summary: Sql. Result of script parsing with single statement is cached incorrectly
Key: IGNITE-24560
URL: https://issues.apache.org/jira/browse/IGNITE-24560
Project: Ignite
Issue Type: Bug
Reporter: Pavel Pereslegin
Reproducer
{code;Java}
@Test
public void testScriptSingleStatement() {
sql("create table test(id int primary key, val int)");
igniteSql().executeScript("select * from test;");
sql("alter table test drop column val");
igniteSql().executeScript("select * from test;"); // Column 'VAL' not found in table 'TEST
}
{code}
Error output
{noformat}
Caused by: org.apache.calcite.runtime.CalciteContextException: At line 1, column 8: Column 'VAL' not found in table 'TEST'
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at org.apache.calcite.runtime.Resources$ExInstWithCause.ex(Resources.java:511)
at org.apache.calcite.sql.SqlUtil.newContextException(SqlUtil.java:952)
at org.apache.calcite.sql.SqlUtil.newContextException(SqlUtil.java:937)
at org.apache.calcite.sql.validate.SqlValidatorImpl.newValidationError(SqlValidatorImpl.java:5899)
at org.apache.ignite.internal.sql.engine.prepare.IgniteSqlValidator.newValidationError(IgniteSqlValidator.java:291)
at org.apache.calcite.sql.validate.DelegatingScope.fullyQualify(DelegatingScope.java:473)
at org.apache.calcite.sql.validate.SqlValidatorImpl$Expander.visit(SqlValidatorImpl.java:7105)
at org.apache.calcite.sql.validate.SqlValidatorImpl$SelectExpander.visit(SqlValidatorImpl.java:7276)
at org.apache.calcite.sql.validate.SqlValidatorImpl$SelectExpander.visit(SqlValidatorImpl.java:7261)
at org.apache.calcite.sql.SqlIdentifier.accept(SqlIdentifier.java:324)
at org.apache.calcite.sql.validate.SqlValidatorImpl$Expander.go(SqlValidatorImpl.java:7094)
at org.apache.calcite.sql.validate.SqlValidatorImpl.expandSelectExpr(SqlValidatorImpl.java:6665)
at org.apache.calcite.sql.validate.SqlValidatorImpl.expandSelectItem(SqlValidatorImpl.java:481)
at org.apache.calcite.sql.validate.SqlValidatorImpl.validateSelectList(SqlValidatorImpl.java:5015)
at org.apache.calcite.sql.validate.SqlValidatorImpl.validateSelect(SqlValidatorImpl.java:4096)
at org.apache.ignite.internal.sql.engine.prepare.IgniteSqlValidator.validateSelect(IgniteSqlValidator.java:684)
at org.apache.calcite.sql.validate.SelectNamespace.validateImpl(SelectNamespace.java:62)
at org.apache.calcite.sql.validate.AbstractNamespace.validate(AbstractNamespace.java:95)
at org.apache.calcite.sql.validate.SqlValidatorImpl.validateNamespace(SqlValidatorImpl.java:1206)
at org.apache.calcite.sql.validate.SqlValidatorImpl.validateQuery(SqlValidatorImpl.java:1177)
at org.apache.calcite.sql.SqlSelect.validate(SqlSelect.java:282)
at org.apache.calcite.sql.validate.SqlValidatorImpl.validateScopedExpression(SqlValidatorImpl.java:1143)
at org.apache.calcite.sql.validate.SqlValidatorImpl.validate(SqlValidatorImpl.java:849)
at org.apache.ignite.internal.sql.engine.prepare.IgniteSqlValidator.validate(IgniteSqlValidator.java:194)
at org.apache.ignite.internal.sql.engine.prepare.IgnitePlanner.validateAndGetTypeMetadata(IgnitePlanner.java:303)
at org.apache.ignite.internal.sql.engine.prepare.PrepareServiceImpl.lambda$prepareQuery$3(PrepareServiceImpl.java:389)
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run$$$capture(CompletableFuture.java:1700)
{noformat}
This happened because we redirect the script execution workflow to normal execution (not multi-statement), but the AST tree in the cache remains a modified after validation.
E.g.
for single statement execution we generating AST each time.
{code:Java}
ParsedResult result = new ParsedResultImpl(
queryType,
query,
normalizedQuery,
parsedStatement.dynamicParamsCount(),
() -> {
// Descendants of SqlNode class are mutable, thus we must use every
// syntax node only once to avoid problem. But we already parsed the
// query once to get normalized result. An `unparse` operation is known
// to be safe, so let's reuse result of parsing for the first invocation
// of `parsedTree` method to avoid double-parsing for one time queries.
SqlNode ast = holder.getAndSet(null);
if (ast != null) {
return ast;
}
return IgniteSqlParser.parse(query, StatementParseResult.MODE).statement();
}
{code}
but for multi-statement (currently) we using the same ast node
{code:Java}
results.add(new ParsedResultImpl(
queryType,
normalizedQuery,
normalizedQuery,
result.dynamicParamsCount(),
() -> parsedTree
));
{code}
And this is ok, but not for the case when the parsing result is placed in the cache.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)