[ https://issues.apache.org/jira/browse/IGNITE-24560?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Pavel Pereslegin updated IGNITE-24560: -------------------------------------- Affects Version/s: 3.0 > 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 > Components: sql > Affects Versions: 3.0 > 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)