Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
f36e610
Use ascending on MvMedian doubles
ivancea Aug 19, 2024
a1b958d
Initial function and tests
ivancea Aug 19, 2024
ad31847
Fixed unsigned long ascending
ivancea Aug 20, 2024
0c1d49a
Merge branch 'main' into mv-median-absolute-deviation-function
ivancea Aug 20, 2024
adfab05
Added overflow test cases, and double overflow fixes
ivancea Aug 20, 2024
1c4c381
Added overflow checks and extra tests for them
ivancea Aug 21, 2024
990ef6c
Minor refactor
ivancea Aug 21, 2024
c5cbd0c
Update docs/changelog/112055.yaml
ivancea Aug 21, 2024
25f05cc
Format
ivancea Aug 21, 2024
a4ce26f
Merge branch 'main' into mv-median-absolute-deviation-function
ivancea Aug 28, 2024
8c57086
Merge branch 'main' into mv-median-absolute-deviation-function
ivancea Aug 29, 2024
557c62f
Fix overflows by using the next bigger number type for MAD (in -> lon…
ivancea Aug 29, 2024
60b698b
Ensure exact conversions in longs
ivancea Aug 29, 2024
880f310
Avoid using BigIntegers for unsigned longs
ivancea Aug 29, 2024
0da4f14
Added function to registry, and updated failing tests
ivancea Aug 29, 2024
5254fee
Added CSV tests and docs
ivancea Aug 29, 2024
f4c312c
Added csv tests for all types and using an index
ivancea Aug 29, 2024
8096654
Assert doubles median is finite
ivancea Aug 29, 2024
8009502
Surrogate in aggregation
ivancea Aug 29, 2024
348eb9b
Merge branch 'main' into mv-median-absolute-deviation-function
ivancea Sep 3, 2024
0ca55ec
Extra cases for FROM test
ivancea Sep 3, 2024
47965c1
Improved function documentation
ivancea Sep 3, 2024
a07c58f
Moved MAD agg csv tests to its own file and updated meta tests
ivancea Sep 3, 2024
f123a2a
Merge branch 'main' into mv-median-absolute-deviation-function
ivancea Sep 6, 2024
09b1f31
Added missing ascending case for doubles, fixed doubles infinites bug…
ivancea Sep 6, 2024
f11a707
Simplified ints calculation by removing long overflow safeguards
ivancea Sep 6, 2024
a0a61ca
Add required capability to agg test
ivancea Sep 6, 2024
42377ce
Improved docs on `ascending` functions
ivancea Sep 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/changelog/112055.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pr: 112055
summary: "ESQL: `mv_median_absolute_deviation` function"
area: ES|QL
type: feature
issues:
- 111590

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions docs/reference/esql/functions/mv-functions.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* <<esql-mv_last>>
* <<esql-mv_max>>
* <<esql-mv_median>>
* <<esql-mv_median_absolute_deviation>>
* <<esql-mv_min>>
* <<esql-mv_pseries_weighted_sum>>
* <<esql-mv_sort>>
Expand All @@ -34,6 +35,7 @@ include::layout/mv_first.asciidoc[]
include::layout/mv_last.asciidoc[]
include::layout/mv_max.asciidoc[]
include::layout/mv_median.asciidoc[]
include::layout/mv_median_absolute_deviation.asciidoc[]
include::layout/mv_min.asciidoc[]
include::layout/mv_pseries_weighted_sum.asciidoc[]
include::layout/mv_slice.asciidoc[]
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,18 @@ public static Number unsignedLongAsNumber(long l) {
return l < 0 ? twosComplement(l) : LONG_MAX_PLUS_ONE_AS_BIGINTEGER.add(BigInteger.valueOf(l));
}

/**
* Converts an unsigned long value "encoded" into a (signed) long.
* In case of overflow, an ArithmeticException is thrown.
*/
public static long unsignedLongAsLongExact(long l) {
if (l < 0) {
return twosComplement(l);
}

throw new ArithmeticException(UNSIGNED_LONG_OVERFLOW);
}

public static BigInteger unsignedLongAsBigInteger(long l) {
return l < 0 ? BigInteger.valueOf(twosComplement(l)) : LONG_MAX_PLUS_ONE_AS_BIGINTEGER.add(BigInteger.valueOf(l));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public MvEvaluatorImplementer(
this.resultType = TypeName.get(processFunction.getReturnType());
}
this.singleValueFunction = SingleValueFunction.from(declarationType, singleValueMethodName, resultType, fieldType);
this.ascendingFunction = AscendingFunction.from(this, declarationType, ascendingMethodName);
this.ascendingFunction = AscendingFunction.from(this, declarationType, workType, ascendingMethodName);
this.warnExceptions = warnExceptions;
this.implementation = ClassName.get(
elements.getPackageOf(declarationType).toString(),
Expand Down Expand Up @@ -511,7 +511,7 @@ private void call(MethodSpec.Builder builder) {
* Function handling blocks of ascending values.
*/
private class AscendingFunction {
static AscendingFunction from(MvEvaluatorImplementer impl, TypeElement declarationType, String name) {
static AscendingFunction from(MvEvaluatorImplementer impl, TypeElement declarationType, TypeName workType, String name) {
if (name.equals("")) {
return null;
}
Expand All @@ -523,26 +523,41 @@ static AscendingFunction from(MvEvaluatorImplementer impl, TypeElement declarati
m -> m.getParameters().size() == 1 && m.getParameters().get(0).asType().getKind() == TypeKind.INT
);
if (fn != null) {
return impl.new AscendingFunction(fn, false);
return impl.new AscendingFunction(fn, false, false);
}
// Block mode without work parameter
fn = findMethod(
declarationType,
new String[] { name },
m -> m.getParameters().size() == 3
&& m.getParameters().get(1).asType().getKind() == TypeKind.INT
&& m.getParameters().get(2).asType().getKind() == TypeKind.INT
);
if (fn == null) {
throw new IllegalArgumentException("Couldn't find " + declarationType + "#" + name + "(block, int, int)");
if (fn != null) {
return impl.new AscendingFunction(fn, true, false);
}
return impl.new AscendingFunction(fn, true);
// Block mode with work parameter
fn = findMethod(
declarationType,
new String[] { name },
m -> m.getParameters().size() == 4
&& TypeName.get(m.getParameters().get(0).asType()).equals(workType)
&& m.getParameters().get(2).asType().getKind() == TypeKind.INT
&& m.getParameters().get(3).asType().getKind() == TypeKind.INT
);
if (fn != null) {
return impl.new AscendingFunction(fn, true, true);
}
throw new IllegalArgumentException("Couldn't find " + declarationType + "#" + name + "(block, int, int)");
}

private final List<Object> invocationArgs = new ArrayList<>();
private final boolean blockMode;
private final boolean withWorkParameter;

private AscendingFunction(ExecutableElement fn, boolean blockMode) {
private AscendingFunction(ExecutableElement fn, boolean blockMode, boolean withWorkParameter) {
this.blockMode = blockMode;
this.withWorkParameter = withWorkParameter;
if (blockMode) {
invocationArgs.add(resultType);
}
Expand All @@ -552,7 +567,11 @@ private AscendingFunction(ExecutableElement fn, boolean blockMode) {

private void call(MethodSpec.Builder builder) {
if (blockMode) {
builder.addStatement("$T result = $T.$L(v, first, valueCount)", invocationArgs.toArray());
if (withWorkParameter) {
builder.addStatement("$T result = $T.$L(work, v, first, valueCount)", invocationArgs.toArray());
} else {
builder.addStatement("$T result = $T.$L(v, first, valueCount)", invocationArgs.toArray());
}
} else {
builder.addStatement("int idx = $T.$L(valueCount)", invocationArgs.toArray());
fetch(builder, "result", resultType, "first + idx", workType.equals(fieldType) ? "firstScratch" : "valueScratch");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
medianAbsoluteDeviation
// tag::median-absolute-deviation[]
FROM employees
| STATS MEDIAN(salary), MEDIAN_ABSOLUTE_DEVIATION(salary)
// end::median-absolute-deviation[]
;

// tag::median-absolute-deviation-result[]
MEDIAN(salary):double | MEDIAN_ABSOLUTE_DEVIATION(salary):double
47003 | 10096.5
// end::median-absolute-deviation-result[]
;

medianAbsoluteDeviationFold
required_capability: fn_mv_median_absolute_deviation
ROW x = [0, 2, 5, 6]
| STATS
int_constant = MEDIAN_ABSOLUTE_DEVIATION([0, 2, 5, 6]::integer),
int_var = MEDIAN_ABSOLUTE_DEVIATION(x::integer),
long_constant = MEDIAN_ABSOLUTE_DEVIATION([0, 2, 5, 6]::long),
long_var = MEDIAN_ABSOLUTE_DEVIATION(x::long),
double_constant = MEDIAN_ABSOLUTE_DEVIATION([0, 2, 5, 6]::double),
double_var = MEDIAN_ABSOLUTE_DEVIATION(x::double)
;

int_constant:double | int_var:double | long_constant:double | long_var:double | double_constant:double | double_var:double
2 | 2 | 2 | 2 | 2 | 2
;

docsStatsMADNestedExpression#[skip:-8.12.99,reason:supported in 8.13+]
// tag::docsStatsMADNestedExpression[]
FROM employees
| STATS m_a_d_max_salary_change = MEDIAN_ABSOLUTE_DEVIATION(MV_MAX(salary_change))
// end::docsStatsMADNestedExpression[]
;

// tag::docsStatsMADNestedExpression-result[]
m_a_d_max_salary_change:double
5.69
// end::docsStatsMADNestedExpression-result[]
;
Loading