diff --git a/x-pack/plugin/sql/qa/src/main/resources/null.csv-spec b/x-pack/plugin/sql/qa/src/main/resources/null.csv-spec index 377b356ed29e7..474fceaed4612 100644 --- a/x-pack/plugin/sql/qa/src/main/resources/null.csv-spec +++ b/x-pack/plugin/sql/qa/src/main/resources/null.csv-spec @@ -17,13 +17,20 @@ null ; -divOfNull +divOfCastedNull SELECT 5 / CAST(NULL AS FLOAT) + 10 AS n; n:d null ; +divNoNull +SELECT 5 / null + 1 AS n; + +n:i +null +; + coalesceJustWithNull SELECT COALESCE(null, null, null) AS c; @@ -31,6 +38,14 @@ c null ; +coalesceFirstNotNull +SELECT COALESCE(123) AS c; + +c +123 +; + + coalesceWithFirstNullOfString SELECT COALESCE(null, 'first') AS c; diff --git a/x-pack/plugin/sql/qa/src/main/resources/null.sql-spec b/x-pack/plugin/sql/qa/src/main/resources/null.sql-spec index 95c5052f2837a..8976c8d8a5ea9 100644 --- a/x-pack/plugin/sql/qa/src/main/resources/null.sql-spec +++ b/x-pack/plugin/sql/qa/src/main/resources/null.sql-spec @@ -6,4 +6,7 @@ coalesceField SELECT COALESCE(null, ABS(emp_no) + 1) AS c FROM test_emp ORDER BY emp_no LIMIT 5; coalesceHaving -SELECT COALESCE(languages, 0) c FROM test_emp GROUP BY languages ORDER BY languages; +SELECT COALESCE(null, ABS(MAX(emp_no)) + 1, 123) AS c FROM test_emp GROUP BY languages HAVING c > 100 ORDER BY languages LIMIT 5; + +coalesceWhere +SELECT COALESCE(null, ABS(emp_no) + 1, 123) AS c FROM test_emp WHERE COALESCE(null, ABS(emp_no) + 1, 123, 321) > 100 ORDER BY emp_no NULLS FIRST LIMIT 5; diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/FunctionRegistry.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/FunctionRegistry.java index c11a565f0aa54..70c9c18a5a4c0 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/FunctionRegistry.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/FunctionRegistry.java @@ -371,6 +371,7 @@ static FunctionDefinition def(Class function, }; return def(function, builder, true, aliases); } + interface DatetimeUnaryFunctionBuilder { T build(Location location, Expression target, TimeZone tz); } @@ -397,6 +398,7 @@ static FunctionDefinition def(Class function, }; return def(function, builder, false, aliases); } + interface BinaryFunctionBuilder { T build(Location location, Expression lhs, Expression rhs); } @@ -415,6 +417,7 @@ private static FunctionDefinition def(Class function, Functi }; return new FunctionDefinition(primaryName, unmodifiableList(Arrays.asList(aliases)), function, datetime, realBuilder); } + private interface FunctionBuilder { Function build(Location location, List children, boolean distinct, TimeZone tz); } @@ -474,6 +477,7 @@ private static FunctionDefinition def(Class function, ctorRef.build(location, children.get(0), children.get(0).dataType()); return def(function, builder, false, aliases); } + private interface CastFunctionBuilder { T build(Location location, Expression expression, DataType dataType); } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/Coalesce.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/Coalesce.java index 9f93866d0b70b..8a2ddc4d10564 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/Coalesce.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/Coalesce.java @@ -75,7 +75,7 @@ public ScriptTemplate asScript() { templates.add(asScript(ex)); } - StringJoiner template = new StringJoiner(",", "{sql}.coalesce(", ")"); + StringJoiner template = new StringJoiner(",", "{sql}.coalesce([", "])"); ParamsBuilder params = paramsBuilder(); for (ScriptTemplate scriptTemplate : templates) { diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java index 4786cf0367b32..e78115639d64d 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java @@ -35,7 +35,6 @@ import org.elasticsearch.xpack.sql.expression.function.scalar.string.Ascii; import org.elasticsearch.xpack.sql.expression.function.scalar.string.Repeat; import org.elasticsearch.xpack.sql.expression.predicate.BinaryOperator; -import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.In; import org.elasticsearch.xpack.sql.expression.predicate.Range; import org.elasticsearch.xpack.sql.expression.predicate.conditional.Coalesce; import org.elasticsearch.xpack.sql.expression.predicate.logical.And; @@ -50,6 +49,7 @@ import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.Equals; import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.GreaterThan; import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.GreaterThanOrEqual; +import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.In; import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.LessThan; import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.LessThanOrEqual; import org.elasticsearch.xpack.sql.expression.predicate.regex.Like; @@ -79,6 +79,7 @@ import org.elasticsearch.xpack.sql.tree.NodeInfo; import org.elasticsearch.xpack.sql.type.DataType; import org.elasticsearch.xpack.sql.type.EsField; +import org.elasticsearch.xpack.sql.util.CollectionUtils; import java.util.Arrays; import java.util.Collections; @@ -408,6 +409,25 @@ public void testSimplifyCoalesceNulls() { assertEquals(0, e.children().size()); } + public void testSimplifyCoalesceRandomNulls() { + Expression e = new SimplifyCoalesce().rule(new Coalesce(EMPTY, randomListOfNulls())); + assertEquals(Coalesce.class, e.getClass()); + assertEquals(0, e.children().size()); + } + + public void testSimplifyCoalesceRandomNullsWithValue() { + Expression e = new SimplifyCoalesce().rule(new Coalesce(EMPTY, + CollectionUtils.combine( + CollectionUtils.combine(randomListOfNulls(), Literal.TRUE, Literal.FALSE, Literal.TRUE), + randomListOfNulls()))); + assertEquals(1, e.children().size()); + assertEquals(Literal.TRUE, e.children().get(0)); + } + + private List randomListOfNulls() { + return asList(randomArray(1, 10, i -> new Literal[i], () -> Literal.NULL)); + } + public void testSimplifyCoalesceFirstLiteral() { Expression e = new SimplifyCoalesce() .rule(new Coalesce(EMPTY,