SQL: Fix the return type in the sign function (#64845) (#64968)

Fixes the inconsistency between the type of the object returned by the
`SIGN()/SIGNUM()` SQL functions and the specified `DataType`.

In the Class Sign, DataType is DataTypes.INTEGER. The source code is as
follows:

```
    public DataType dataType() {
        return DataTypes.INTEGER;
    }
```

But In the Class MathProcessor, the source code of SIGN((Object l),
Parameter and return value types are the same. Therefore, when using
double or float parameters to test, there is a little problem, the test
method is like the following curl :

```
curl -XPOST 127.0.0.1:9200/_sql -d "{\"query\":\"select  SIGN(1.0) \"}" \
  -H 'Content-Type: application/json'
```

The result is:

```
{"columns":[{"name":"SIGN(1.0)","type":"integer"}],"rows":[[1.0]]}
```

The result value is `1.0`, but the type is `integer`.

Signed-off-by: mantuliu <240951888@qq.com>
Co-authored-by: Marios Trivyzas <matriv@gmail.com>
(cherry picked from commits aa78301e71f, ced3c1281c7, 40e5b9b)
This commit is contained in:
Andras Palinkas 2020-11-11 17:07:17 -05:00 committed by GitHub
parent 4b1d66fc29
commit a7301065d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 17 deletions

View File

@ -77,26 +77,13 @@ public class MathProcessor implements Processor {
Randomness.get().nextDouble(), true),
SIGN((Object l) -> {
if (l instanceof Double) {
return Math.signum((Double) l);
return (int) Math.signum((Double) l);
}
if (l instanceof Float) {
return Math.signum((Float) l);
return (int) Math.signum((Float) l);
}
long lo = Long.signum(((Number) l).longValue());
if (l instanceof Integer) {
return DataTypeConverter.safeToInt(lo);
}
if (l instanceof Short) {
return DataTypeConverter.safeToShort(lo);
}
if (l instanceof Byte) {
return DataTypeConverter.safeToByte(lo);
}
//fallback to generic double
return lo;
return Long.signum(((Number) l).longValue());
}),
SIN(Math::sin),
SINH(Math::sinh),

View File

@ -10,6 +10,9 @@ import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.ql.QlIllegalArgumentException;
import org.elasticsearch.xpack.sql.expression.function.scalar.math.MathProcessor.MathOperation;
import java.util.Arrays;
import java.util.List;
public class MathOperationTests extends ESTestCase {
public void testAbsLongMax() {
@ -35,4 +38,28 @@ public class MathOperationTests extends ESTestCase {
assertEquals(42f, MathOperation.ABS.apply(-42f));
assertEquals(42d, MathOperation.ABS.apply(-42d));
}
public void testSignIntegerType() {
List<Number> negative = Arrays.asList((byte) -42, (short) -42, -42, -42L, -42.0f, -42.0d);
List<Number> zero = Arrays.asList((byte) 0, (short) 0, 0, 0L, 0.0f, 0.0d);
List<Number> positive = Arrays.asList((byte) 42, (short) 42, 42, 42L, 42.0f, 42.0d);
for (Number number : negative) {
Number result = MathOperation.SIGN.apply(number);
assertEquals(Integer.class, result.getClass());
assertEquals(-1, result);
}
for (Number number : zero) {
Number result = MathOperation.SIGN.apply(number);
assertEquals(Integer.class, result.getClass());
assertEquals(0, result);
}
for (Number number : positive) {
Number result = MathOperation.SIGN.apply(number);
assertEquals(Integer.class, result.getClass());
assertEquals(1, result);
}
}
}