-
Notifications
You must be signed in to change notification settings - Fork 25k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SQL: Introduce Coalesce function #35253
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// | ||
// Null expressions | ||
// | ||
|
||
dateTimeOverNull | ||
SELECT YEAR(CAST(NULL AS DATE)) d; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @matriv notice that now |
||
|
||
d:i | ||
null | ||
; | ||
|
||
addOfNull | ||
SELECT CAST(NULL AS INT) + CAST(NULL AS FLOAT) AS n; | ||
|
||
n:d | ||
null | ||
; | ||
|
||
|
||
divOfNull | ||
SELECT 5 / CAST(NULL AS FLOAT) + 10 AS n; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because I want to check that the a cast preserve the null value and its associated type. I've renamed the test and added a basic one without cast. |
||
|
||
n:d | ||
null | ||
; | ||
|
||
coalesceJustWithNull | ||
SELECT COALESCE(null, null, null) AS c; | ||
|
||
c | ||
null | ||
; | ||
|
||
coalesceWithFirstNullOfString | ||
SELECT COALESCE(null, 'first') AS c; | ||
|
||
c:s | ||
first | ||
; | ||
|
||
coalesceWithFirstNullOfNumber | ||
SELECT COALESCE(null, 123) AS c; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would also add a test where all values are There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm... my bad, not sure why I haven't seen that. |
||
c:i | ||
123 | ||
; | ||
|
||
coalesceMixed | ||
SELECT COALESCE(null, 123, null, 321) AS c; | ||
|
||
c:i | ||
123 | ||
; | ||
|
||
coalesceScalar | ||
SELECT COALESCE(null, ABS(123) + 1) AS c; | ||
|
||
c:i | ||
124 | ||
; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add a test where the first value is non-null? (all tests with COALESCE assume there is at least one null value before the first non-null) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added (there's an optimization test that tries that but anyway). |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
// | ||
// Null expressions | ||
// | ||
|
||
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; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there is no having condition here. can we add one? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, can you add a test when COALESCE is used in the WHERE filter (no aggregations). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done. |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -82,6 +82,7 @@ | |
import org.elasticsearch.xpack.sql.expression.function.scalar.string.Space; | ||
import org.elasticsearch.xpack.sql.expression.function.scalar.string.Substring; | ||
import org.elasticsearch.xpack.sql.expression.function.scalar.string.UCase; | ||
import org.elasticsearch.xpack.sql.expression.predicate.conditional.Coalesce; | ||
import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Mod; | ||
import org.elasticsearch.xpack.sql.parser.ParsingException; | ||
import org.elasticsearch.xpack.sql.tree.Location; | ||
|
@@ -142,6 +143,8 @@ private void defineDefaultFunctions() { | |
def(Skewness.class, Skewness::new), | ||
def(Kurtosis.class, Kurtosis::new)); | ||
// Scalar functions | ||
// conditional | ||
addToMap(def(Coalesce.class, Coalesce::new)); | ||
// Date | ||
addToMap(def(DayName.class, DayName::new, "DAYNAME"), | ||
def(DayOfMonth.class, DayOfMonth::new, "DAYOFMONTH", "DAY", "DOM"), | ||
|
@@ -310,6 +313,26 @@ static <T extends Function> FunctionDefinition def(Class<T> function, | |
return def(function, builder, false, aliases); | ||
} | ||
|
||
/** | ||
* Build a {@linkplain FunctionDefinition} for multi-arg function that | ||
* is not aware of time zone and does not support {@code DISTINCT}. | ||
*/ | ||
@SuppressWarnings("overloads") // These are ambiguous if you aren't using ctor references but we always do | ||
static <T extends Function> FunctionDefinition def(Class<T> function, | ||
MultiFunctionBuilder<T> ctorRef, String... aliases) { | ||
FunctionBuilder builder = (location, children, distinct, tz) -> { | ||
if (distinct) { | ||
throw new IllegalArgumentException("does not support DISTINCT yet it was specified"); | ||
} | ||
return ctorRef.build(location, children); | ||
}; | ||
return def(function, builder, false, aliases); | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Really really minor: can you remove the empty line or add it to the other places between the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, I've added it to the rest (the source wasn't consistent). |
||
interface MultiFunctionBuilder<T> { | ||
T build(Location location, List<Expression> children); | ||
} | ||
|
||
/** | ||
* Build a {@linkplain FunctionDefinition} for a unary function that is not | ||
* aware of time zone but does support {@code DISTINCT}. | ||
|
@@ -325,6 +348,7 @@ static <T extends Function> FunctionDefinition def(Class<T> function, | |
}; | ||
return def(function, builder, false, aliases); | ||
} | ||
|
||
interface DistinctAwareUnaryFunctionBuilder<T> { | ||
T build(Location location, Expression target, boolean distinct); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
package org.elasticsearch.xpack.sql.expression.gen.pipeline; | ||
|
||
import org.elasticsearch.xpack.sql.expression.Expression; | ||
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor; | ||
import org.elasticsearch.xpack.sql.tree.Location; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
public abstract class MultiPipe extends Pipe { | ||
|
||
protected MultiPipe(Location location, Expression expression, List<Pipe> children) { | ||
super(location, expression, children); | ||
} | ||
|
||
@Override | ||
public Processor asProcessor() { | ||
List<Processor> procs = new ArrayList<>(); | ||
for (Pipe pipe : children()) { | ||
procs.add(pipe.asProcessor()); | ||
} | ||
|
||
return asProcessor(procs); | ||
} | ||
|
||
public abstract Processor asProcessor(List<Processor> procs); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't we need There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, because this check already exists. From
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah ok, overlooked that! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hack to get jdbc-csv to support null. /cc @matriv