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:
parent
9ac4ee9c44
commit
b2e85d5639
|
@ -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()))) {
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue