SQL: Do not resolve self-referencing aliases (#62382)

Prevent the analyzer for trying to resolve aliases on expressions that
reference themselves (or fields within themselves) as that causes
infinite recursion.

Fix #62296

(cherry picked from commit 021d27815b03e92e02859bc9c0c8eec78f30c72e)
This commit is contained in:
Costin Leau 2020-09-15 20:46:13 +03:00 committed by Costin Leau
parent 9ac4ee9c44
commit b2e85d5639
2 changed files with 25 additions and 2 deletions

View File

@ -867,7 +867,7 @@ public class Analyzer extends RuleExecutor<LogicalPlan> {
boolean qualified = u.qualifier() != null; boolean qualified = u.qualifier() != null;
for (Alias alias : aliases) { for (Alias alias : aliases) {
// don't replace field with their own aliases (it creates infinite cycles) // don't replace field with their own aliases (it creates infinite cycles)
if (u != alias.child() && if (alias.anyMatch(e -> e == u) == false &&
(qualified ? (qualified ?
Objects.equals(alias.qualifiedName(), u.qualifiedName()) : Objects.equals(alias.qualifiedName(), u.qualifiedName()) :
Objects.equals(alias.name(), u.name()))) { Objects.equals(alias.name(), u.name()))) {

View File

@ -5,7 +5,6 @@
*/ */
package org.elasticsearch.xpack.sql.analysis.analyzer; package org.elasticsearch.xpack.sql.analysis.analyzer;
import java.util.stream.Collectors;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.ql.QlIllegalArgumentException; import org.elasticsearch.xpack.ql.QlIllegalArgumentException;
import org.elasticsearch.xpack.ql.expression.Alias; import org.elasticsearch.xpack.ql.expression.Alias;
@ -29,6 +28,7 @@ import org.elasticsearch.xpack.sql.stats.Metrics;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
import static org.elasticsearch.xpack.ql.type.DataTypes.BOOLEAN; import static org.elasticsearch.xpack.ql.type.DataTypes.BOOLEAN;
import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD;
@ -277,4 +277,27 @@ public class FieldAttributeTests extends ESTestCase {
+ "matches any of [line 1:37 [m], line 1:55 [m]]", + "matches any of [line 1:37 [m], line 1:55 [m]]",
ex.getMessage()); ex.getMessage());
} }
public void testFunctionOverNonExistingFieldAsArgumentAndSameAlias() throws Exception {
Map<String, EsField> mapping = TypesTests.loadMapping("mapping-basic.json");
EsIndex index = new EsIndex("test", mapping);
getIndexResult = IndexResolution.valid(index);
analyzer = new Analyzer(SqlTestUtils.TEST_CFG, functionRegistry, getIndexResult, verifier);
VerificationException ex = expectThrows(VerificationException.class, () ->
plan("SELECT sum(missing) AS missing FROM test WHERE missing = 0"));
assertEquals("Found 1 problem\nline 1:12: Unknown column [missing]", ex.getMessage());
}
public void testFunctionWithExpressionOverNonExistingFieldAsArgumentAndSameAlias() throws Exception {
Map<String, EsField> mapping = TypesTests.loadMapping("mapping-basic.json");
EsIndex index = new EsIndex("test", mapping);
getIndexResult = IndexResolution.valid(index);
analyzer = new Analyzer(SqlTestUtils.TEST_CFG, functionRegistry, getIndexResult, verifier);
VerificationException ex = expectThrows(VerificationException.class, () ->
plan("SELECT LENGTH(CONCAT(missing, 'x')) + 1 AS missing FROM test WHERE missing = 0"));
assertEquals("Found 1 problem\nline 1:22: Unknown column [missing]", ex.getMessage());
}
} }