Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
5b2ae44
Add unsigned_long type support to QL
bpintea Nov 17, 2020
56b6e3d
style fixes
bpintea Nov 17, 2020
0b648ae
Merge remote-tracking branch 'upstream/master' into feat/unsigned_long
bpintea Nov 19, 2020
9eda683
Make JDBC QA tests version aware
bpintea Nov 19, 2020
dced577
Disable UL for 7.11 till after merging it in
bpintea Nov 19, 2020
30360f4
Merge remote-tracking branch 'upstream/master' into feat/unsigned_long
bpintea Nov 19, 2020
e2a2363
Refactor UL gating based on version
bpintea Nov 22, 2020
ab5eaa0
Merge remote-tracking branch 'upstream/master' into feat/unsigned_long
bpintea Nov 22, 2020
672df32
Minor clean-ups
bpintea Nov 23, 2020
93ece7c
Merge remote-tracking branch 'upstream/master' into feat/unsigned_long
bpintea Nov 23, 2020
cbcb148
Merge remote-tracking branch 'upstream/master' into feat/unsigned_long
bpintea Nov 27, 2020
85447c1
Address reivew comments
bpintea Nov 27, 2020
6a8ac44
Merge branch 'master' into feat/unsigned_long
elasticmachine Nov 30, 2020
6801bd5
Remove stale comment
bpintea Nov 30, 2020
9210138
Merge remote-tracking branch 'upstream/master' into feat/unsigned_long
bpintea Nov 30, 2020
c9bfffd
Filter out UL from * expansion. Drop client check
bpintea Nov 30, 2020
2d64608
Revert FieldExtractorTestCase: no float to UL
bpintea Nov 30, 2020
754d026
Address review comments
bpintea Dec 8, 2020
6119fd3
Merge remote-tracking branch 'upstream/master' into feat/unsigned_long
bpintea Dec 8, 2020
d89513c
Merge remote-tracking branch 'upstream/master' into feat/unsigned_long
bpintea Dec 16, 2020
46a072e
Add 'SHOW COLUMNS' tests
bpintea Dec 16, 2020
0897d8e
Switch UNSIGNED_LONG to NUMERIC xDBC type
bpintea Dec 16, 2020
1b906ec
Update test
bpintea Dec 16, 2020
346b566
Merge branch 'master' into feat/unsigned_long
elasticmachine Dec 16, 2020
f99eeec
Style fix
bpintea Dec 16, 2020
a8c586b
Merge remote-tracking branch 'upstream/master' into feat/unsigned_long
bpintea Jan 13, 2021
0799d72
Merge remote-tracking branch 'upstream/master' into feat/unsigned_long
bpintea May 27, 2021
f5be346
Merge remote-tracking branch 'upstream/master' into feat/unsigned_long
bpintea May 27, 2021
9664e23
License header fix
bpintea May 27, 2021
91bd1d6
Merge branch 'master' into feat/unsigned_long
bpintea Jul 21, 2021
f8c20db
Update target release.Update test to 4-dig. years
bpintea Jul 21, 2021
c1718b5
Merge branch 'master' into feat/unsigned_long
bpintea Jul 21, 2021
9b5bc54
Merge branch 'master' into feat/unsigned_long
bpintea Aug 17, 2021
71e707b
Merge branch 'master' into feat/unsigned_long
bpintea Sep 1, 2021
51a4f84
Add Painless-driven testing
bpintea Sep 2, 2021
c6a170c
Merge branch 'master' into feat/unsigned_long
bpintea Sep 2, 2021
38b1450
Merge branch 'master' into feat/unsigned_long
bpintea Dec 2, 2021
d398757
Merge branch 'master' into feat/unsigned_long
elasticmachine Dec 2, 2021
bbfcd93
Merge branch 'master' into feat/unsigned_long
bpintea Dec 14, 2021
509892c
Extend value extraction as unsigned long
bpintea Dec 23, 2021
d03cb1d
Address review comments
bpintea Dec 23, 2021
35149d8
Merge branch 'master' into feat/unsigned_long
bpintea Dec 23, 2021
0943d4b
Remove ShowColumns UL version-dep filtering
bpintea Dec 23, 2021
8ebfad1
Extract mapping reading out of loops
bpintea Dec 23, 2021
64f02f7
Resolve UL fields to unsupported in resolver
bpintea Jan 4, 2022
95d8c02
Merge branch 'master' into feat/unsigned_long
bpintea Jan 4, 2022
67d38aa
Merge branch 'master' into feat/unsigned_long
bpintea Jan 10, 2022
41be569
Merge branch 'master' into feat/unsigned_long
bpintea Jan 31, 2022
f6c3a8e
Address review comments
bpintea Jan 31, 2022
abda408
Update docs/changelog/65145.yaml
Jan 31, 2022
c14a41f
Merge branch 'master' into feat/unsigned_long
bpintea Feb 2, 2022
5302100
Extract UL to Unsupported map transf. to own class
bpintea Feb 2, 2022
fba1d65
Move compat filtering out of the Analyzer
bpintea Feb 2, 2022
80c79d4
Merge branch 'master' into feat/unsigned_long
bpintea Feb 3, 2022
6ce3a1e
Apply review comments. Bump UL intro version
bpintea Feb 3, 2022
4ef30c1
Merge branch 'master' into feat/unsigned_long
elasticmachine Feb 3, 2022
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
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import org.elasticsearch.xpack.ql.type.DataTypes;
import org.elasticsearch.xpack.ql.util.StringUtils;

import java.math.BigInteger;
import java.time.ZoneId;
import java.util.List;

Expand Down Expand Up @@ -207,10 +208,9 @@ public Literal visitIntegerLiteral(EqlBaseParser.IntegerLiteralContext ctx) {
Source source = source(ctx);
String text = ctx.getText();

long value;

Number value;
try {
value = Long.valueOf(StringUtils.parseLong(text));
value = StringUtils.parseInteger(text);
} catch (QlIllegalArgumentException siae) {
// if it's too large, then quietly try to parse as a float instead
try {
Expand All @@ -221,15 +221,20 @@ public Literal visitIntegerLiteral(EqlBaseParser.IntegerLiteralContext ctx) {
throw new ParsingException(source, siae.getMessage());
}

Object val = Long.valueOf(value);
DataType type = DataTypes.LONG;

// try to downsize to int if possible (since that's the most common type)
if ((int) value == value) {
type = DataTypes.INTEGER;
val = Integer.valueOf((int) value);
DataType type;
if (value instanceof BigInteger) {
type = DataTypes.UNSIGNED_LONG;
} else {
assert value instanceof Long : "Expected value [" + value + "] of type Long but got: " + value.getClass();
// try to downsize to int if possible (since that's the most common type)
if (value.longValue() == value.intValue()) {
type = DataTypes.INTEGER;
value = Integer.valueOf(value.intValue());
} else {
type = DataTypes.LONG;
}
}
return new Literal(source, val, type);
return new Literal(source, value, type);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ public void testAliasErrors() {
// Test all elasticsearch numeric field types
public void testNumeric() {
final IndexResolution idxr = loadIndexResolution("mapping-numeric.json");
accept(idxr, "foo where unsigned_long_field == 0");
accept(idxr, "foo where long_field == 0");
accept(idxr, "foo where integer_field == 0");
accept(idxr, "foo where short_field == 0");
Expand Down
3 changes: 3 additions & 0 deletions x-pack/plugin/eql/src/test/resources/mapping-numeric.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
"@timestamp" : {
"type" : "date"
},
"unsigned_long_field" : {
"type": "unsigned_long"
},
"long_field" : {
"type" : "long"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.elasticsearch.xpack.ql.type.DataTypes;

import java.io.IOException;
import java.math.BigInteger;
import java.time.ZoneId;
import java.util.ArrayDeque;
import java.util.Deque;
Expand All @@ -31,6 +32,8 @@
import static org.elasticsearch.xpack.ql.type.DataTypes.DATETIME;
import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD;
import static org.elasticsearch.xpack.ql.type.DataTypes.SCALED_FLOAT;
import static org.elasticsearch.xpack.ql.type.DataTypes.UNSIGNED_LONG;

/**
* Extractor for ES fields. Works for both 'normal' fields but also nested ones (which require hitName to be set).
* The latter is used as metadata in assembling the results in the tabular response.
Expand Down Expand Up @@ -182,25 +185,16 @@ protected Object unwrapMultiValue(Object values) {
return values;
}
if (dataType.isNumeric() && isFromDocValuesOnly(dataType) == false) {
if (dataType == DataTypes.DOUBLE || dataType == DataTypes.FLOAT || dataType == DataTypes.HALF_FLOAT) {
Number result = null;
try {
result = numberType(dataType).parse(values, true);
} catch(IllegalArgumentException iae) {
return null;
}
// docvalue_fields is always returning a Double value even if the underlying floating point data type is not Double
// even if we don't extract from docvalue_fields anymore, the behavior should be consistent
return result.doubleValue();
} else {
Number result = null;
try {
result = numberType(dataType).parse(values, true);
} catch(IllegalArgumentException iae) {
return null;
}
return result;
Number result = null;
try {
// TODO: don't mapper modules expose _source parsing methods? should the _source be (re)validated?
result = dataType == UNSIGNED_LONG ? new BigInteger(values.toString()) : numberType(dataType).parse(values, true);
} catch(IllegalArgumentException iae) {
return null;
}
// docvalue_fields is always returning a Double value even if the underlying floating point data type is not Double
// even if we don't extract from docvalue_fields anymore, the behavior should be consistent
return dataType.isRational() ? result.doubleValue() : result;
} else if (DataTypes.isString(dataType)) {
return values.toString();
} else {
Expand All @@ -215,7 +209,7 @@ protected boolean isFromDocValuesOnly(DataType dataType) {
|| dataType == DATETIME
|| dataType == SCALED_FLOAT; // because of scaling_factor
}

private static NumberType numberType(DataType dataType) {
return NumberType.valueOf(dataType.esType().toUpperCase(Locale.ROOT));
}
Expand Down Expand Up @@ -339,4 +333,4 @@ public boolean equals(Object obj) {
public int hashCode() {
return Objects.hash(fieldName, useDocValue, hitName, arrayLeniency);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@

import org.elasticsearch.xpack.ql.QlIllegalArgumentException;

import java.math.BigInteger;
import java.util.function.BiFunction;

import static org.elasticsearch.xpack.ql.util.Check.isUnsignedLong;

/**
* Arithmetic operation using the type widening rules of the JLS 5.6.2 namely
* widen to double or float or long or int in this order.
Expand All @@ -31,6 +34,22 @@ default Object wrap(Object l, Object r) {
}
}

private static BigInteger unsignedLongOperation(Number l, Number r, BiFunction<BigInteger, BigInteger, BigInteger> op) {
BigInteger biLeft, biRight;
if (l instanceof BigInteger) {
biLeft = (BigInteger) l;
biRight = BigInteger.valueOf(r.longValue());
} else if (r instanceof BigInteger) {
biLeft = BigInteger.valueOf(l.longValue());
biRight = (BigInteger) r;
} else {
return null;
}
BigInteger bi = op.apply(biLeft, biRight);
isUnsignedLong(bi);
return bi;
}

public static Number add(Number l, Number r) {
if (l == null || r == null) {
return null;
Expand All @@ -42,6 +61,10 @@ public static Number add(Number l, Number r) {
if (l instanceof Float || r instanceof Float) {
return Float.valueOf(l.floatValue() + r.floatValue());
}
BigInteger bi = unsignedLongOperation(l, r, BigInteger::add);
if (bi != null) {
return bi;
}
if (l instanceof Long || r instanceof Long) {
return Long.valueOf(Math.addExact(l.longValue(), r.longValue()));
}
Expand All @@ -60,6 +83,10 @@ public static Number sub(Number l, Number r) {
if (l instanceof Float || r instanceof Float) {
return Float.valueOf(l.floatValue() - r.floatValue());
}
BigInteger bi = unsignedLongOperation(l, r, BigInteger::subtract);
if (bi != null) {
return bi;
}
if (l instanceof Long || r instanceof Long) {
return Long.valueOf(Math.subtractExact(l.longValue(), r.longValue()));
}
Expand All @@ -78,6 +105,16 @@ public static Number mul(Number l, Number r) {
if (l instanceof Float || r instanceof Float) {
return Float.valueOf(l.floatValue() * r.floatValue());
}
// Note: in case of unsigned_long overflow (or underflow, with negative fixed point numbers), the exception is thrown.
// This is unlike the way some other traditional RDBMS that support unsigned types work, which simply promote the result to a
// floating point type, but in line with how our implementation treats other fixed point type operations (i.e. Math#xxExact()).
// The reason for our behavior is (prolly) the need to establish a schema based on an index mapping. Noteworthy however is also
// that we're not strictly consistent with the returned type: a `SUM(field)` aggregation can return a floating point, for example.
// TODO: document this last point or address it?
BigInteger bi = unsignedLongOperation(l, r, BigInteger::multiply);
if (bi != null) {
return bi;
}
if (l instanceof Long || r instanceof Long) {
return Long.valueOf(Math.multiplyExact(l.longValue(), r.longValue()));
}
Expand All @@ -96,6 +133,10 @@ public static Number div(Number l, Number r) {
if (l instanceof Float || r instanceof Float) {
return l.floatValue() / r.floatValue();
}
BigInteger bi = unsignedLongOperation(l, r, BigInteger::divide);
if (bi != null) {
return bi;
}
if (l instanceof Long || r instanceof Long) {
return l.longValue() / r.longValue();
}
Expand All @@ -114,6 +155,10 @@ public static Number mod(Number l, Number r) {
if (l instanceof Float || r instanceof Float) {
return Float.valueOf(l.floatValue() % r.floatValue());
}
BigInteger bi = unsignedLongOperation(l, r, BigInteger::remainder);
if (bi != null) {
return bi;
}
if (l instanceof Long || r instanceof Long) {
return Long.valueOf(l.longValue() % r.longValue());
}
Expand All @@ -140,10 +185,16 @@ static Number negate(Number n) {
}
return Float.valueOf(-n.floatValue());
}
if (n instanceof BigInteger) {
if (((BigInteger) n).signum() != 0) {
throw new ArithmeticException("unsigned_long overflow");
}
return n;
}
if (n instanceof Long) {
return Long.valueOf(Math.negateExact(n.longValue()));
}

return Integer.valueOf(Math.negateExact(n.intValue()));
}
}
}
Loading