[
https://issues.apache.org/jira/browse/IGNITE-24560?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Pavel Pereslegin updated IGNITE-24560:
--------------------------------------
Labels: ignite-3 (was: )
> 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
> Priority: Major
> Labels: ignite-3
>
> 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)