Skip to content

Commit 936ddbe

Browse files
committed
Add numeric integer to double coercion for hive tables
1 parent a7eb366 commit 936ddbe

File tree

8 files changed

+229
-9
lines changed

8 files changed

+229
-9
lines changed

plugin/trino-hive/src/main/java/io/trino/plugin/hive/coercions/CoercionUtils.java

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -127,14 +127,32 @@ public static Type createTypeFromCoercer(TypeManager typeManager, HiveType fromH
127127
}
128128
return Optional.empty();
129129
}
130-
if (fromHiveType.equals(HIVE_BYTE) && (toHiveType.equals(HIVE_SHORT) || toHiveType.equals(HIVE_INT) || toHiveType.equals(HIVE_LONG))) {
131-
return Optional.of(new IntegerNumberUpscaleCoercer<>(fromType, toType));
130+
if (fromHiveType.equals(HIVE_BYTE)) {
131+
if (toHiveType.equals(HIVE_SHORT) || toHiveType.equals(HIVE_INT) || toHiveType.equals(HIVE_LONG)) {
132+
return Optional.of(new IntegerNumberUpscaleCoercer<>(fromType, toType));
133+
}
134+
if (toHiveType.equals(HIVE_DOUBLE)) {
135+
return Optional.of(new IntegerNumberToDoubleCoercer<>(fromType));
136+
}
132137
}
133-
if (fromHiveType.equals(HIVE_SHORT) && (toHiveType.equals(HIVE_INT) || toHiveType.equals(HIVE_LONG))) {
134-
return Optional.of(new IntegerNumberUpscaleCoercer<>(fromType, toType));
138+
if (fromHiveType.equals(HIVE_SHORT)) {
139+
if (toHiveType.equals(HIVE_INT) || toHiveType.equals(HIVE_LONG)) {
140+
return Optional.of(new IntegerNumberUpscaleCoercer<>(fromType, toType));
141+
}
142+
if (toHiveType.equals(HIVE_DOUBLE)) {
143+
return Optional.of(new IntegerNumberToDoubleCoercer<>(fromType));
144+
}
145+
}
146+
if (fromHiveType.equals(HIVE_INT)) {
147+
if (toHiveType.equals(HIVE_LONG)) {
148+
return Optional.of(new IntegerToBigintCoercer());
149+
}
150+
if (toHiveType.equals(HIVE_DOUBLE)) {
151+
return Optional.of(new IntegerNumberToDoubleCoercer<>(fromType));
152+
}
135153
}
136-
if (fromHiveType.equals(HIVE_INT) && toHiveType.equals(HIVE_LONG)) {
137-
return Optional.of(new IntegerToBigintCoercer());
154+
if (fromHiveType.equals(HIVE_LONG) && toHiveType.equals(HIVE_DOUBLE)) {
155+
return Optional.of(new IntegerNumberToDoubleCoercer<>(fromType));
138156
}
139157
if (fromHiveType.equals(HIVE_FLOAT) && toHiveType.equals(HIVE_DOUBLE)) {
140158
return Optional.of(new FloatToDoubleCoercer());
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
15+
package io.trino.plugin.hive.coercions;
16+
17+
import io.trino.spi.block.Block;
18+
import io.trino.spi.block.BlockBuilder;
19+
import io.trino.spi.type.DoubleType;
20+
import io.trino.spi.type.Type;
21+
22+
import static io.trino.spi.type.DoubleType.DOUBLE;
23+
24+
public class IntegerNumberToDoubleCoercer<F extends Type>
25+
extends TypeCoercer<F, DoubleType>
26+
{
27+
public IntegerNumberToDoubleCoercer(F fromType)
28+
{
29+
super(fromType, DOUBLE);
30+
}
31+
32+
@Override
33+
protected void applyCoercedValue(BlockBuilder blockBuilder, Block block, int position)
34+
{
35+
DOUBLE.writeDouble(blockBuilder, fromType.getLong(block, position));
36+
}
37+
}

plugin/trino-hive/src/main/java/io/trino/plugin/hive/orc/OrcTypeTranslator.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,33 @@
1717
import io.trino.plugin.hive.coercions.BooleanCoercer.BooleanToVarcharCoercer;
1818
import io.trino.plugin.hive.coercions.DateCoercer.VarcharToDateCoercer;
1919
import io.trino.plugin.hive.coercions.DoubleToVarcharCoercer;
20+
import io.trino.plugin.hive.coercions.IntegerNumberToDoubleCoercer;
2021
import io.trino.plugin.hive.coercions.TimestampCoercer.LongTimestampToVarcharCoercer;
2122
import io.trino.plugin.hive.coercions.TimestampCoercer.VarcharToLongTimestampCoercer;
2223
import io.trino.plugin.hive.coercions.TimestampCoercer.VarcharToShortTimestampCoercer;
2324
import io.trino.plugin.hive.coercions.TypeCoercer;
2425
import io.trino.spi.type.DateType;
26+
import io.trino.spi.type.DoubleType;
2527
import io.trino.spi.type.TimestampType;
2628
import io.trino.spi.type.Type;
2729
import io.trino.spi.type.VarcharType;
2830

2931
import java.util.Optional;
3032

3133
import static io.trino.orc.metadata.OrcType.OrcTypeKind.BOOLEAN;
34+
import static io.trino.orc.metadata.OrcType.OrcTypeKind.BYTE;
3235
import static io.trino.orc.metadata.OrcType.OrcTypeKind.DOUBLE;
36+
import static io.trino.orc.metadata.OrcType.OrcTypeKind.INT;
37+
import static io.trino.orc.metadata.OrcType.OrcTypeKind.LONG;
38+
import static io.trino.orc.metadata.OrcType.OrcTypeKind.SHORT;
3339
import static io.trino.orc.metadata.OrcType.OrcTypeKind.STRING;
3440
import static io.trino.orc.metadata.OrcType.OrcTypeKind.TIMESTAMP;
3541
import static io.trino.orc.metadata.OrcType.OrcTypeKind.VARCHAR;
42+
import static io.trino.spi.type.BigintType.BIGINT;
43+
import static io.trino.spi.type.IntegerType.INTEGER;
44+
import static io.trino.spi.type.SmallintType.SMALLINT;
3645
import static io.trino.spi.type.TimestampType.TIMESTAMP_NANOS;
46+
import static io.trino.spi.type.TinyintType.TINYINT;
3747
import static io.trino.spi.type.VarcharType.createUnboundedVarcharType;
3848

3949
public final class OrcTypeTranslator
@@ -63,6 +73,20 @@ private OrcTypeTranslator() {}
6373
if (fromOrcType == BOOLEAN && toTrinoType instanceof VarcharType varcharType) {
6474
return Optional.of(new BooleanToVarcharCoercer(varcharType));
6575
}
76+
if (toTrinoType instanceof DoubleType) {
77+
if (fromOrcType == BYTE) {
78+
return Optional.of(new IntegerNumberToDoubleCoercer<>(TINYINT));
79+
}
80+
if (fromOrcType == SHORT) {
81+
return Optional.of(new IntegerNumberToDoubleCoercer<>(SMALLINT));
82+
}
83+
if (fromOrcType == INT) {
84+
return Optional.of(new IntegerNumberToDoubleCoercer<>(INTEGER));
85+
}
86+
if (fromOrcType == LONG) {
87+
return Optional.of(new IntegerNumberToDoubleCoercer<>(BIGINT));
88+
}
89+
}
6690
return Optional.empty();
6791
}
6892

plugin/trino-hive/src/main/java/io/trino/plugin/hive/util/HiveCoercionPolicy.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,16 @@ private boolean canCoerce(HiveType fromHiveType, HiveType toHiveType, HiveTimest
8383
fromType instanceof DecimalType;
8484
}
8585
if (fromHiveType.equals(HIVE_BYTE)) {
86-
return toHiveType.equals(HIVE_SHORT) || toHiveType.equals(HIVE_INT) || toHiveType.equals(HIVE_LONG);
86+
return toHiveType.equals(HIVE_SHORT) || toHiveType.equals(HIVE_INT) || toHiveType.equals(HIVE_LONG) || toHiveType.equals(HIVE_DOUBLE);
8787
}
8888
if (fromHiveType.equals(HIVE_SHORT)) {
89-
return toHiveType.equals(HIVE_INT) || toHiveType.equals(HIVE_LONG);
89+
return toHiveType.equals(HIVE_INT) || toHiveType.equals(HIVE_LONG) || toHiveType.equals(HIVE_DOUBLE);
9090
}
9191
if (fromHiveType.equals(HIVE_INT)) {
92-
return toHiveType.equals(HIVE_LONG);
92+
return toHiveType.equals(HIVE_LONG) || toHiveType.equals(HIVE_DOUBLE);
93+
}
94+
if (fromHiveType.equals(HIVE_LONG)) {
95+
return toHiveType.equals(HIVE_DOUBLE);
9396
}
9497
if (fromHiveType.equals(HIVE_FLOAT)) {
9598
return toHiveType.equals(HIVE_DOUBLE) || toType instanceof DecimalType;
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
package io.trino.plugin.hive.coercions;
15+
16+
import io.trino.spi.block.Block;
17+
import io.trino.spi.type.Type;
18+
import org.junit.jupiter.api.Test;
19+
20+
import static io.trino.plugin.hive.HiveTimestampPrecision.DEFAULT_PRECISION;
21+
import static io.trino.plugin.hive.HiveType.toHiveType;
22+
import static io.trino.plugin.hive.coercions.CoercionUtils.createCoercer;
23+
import static io.trino.spi.predicate.Utils.blockToNativeValue;
24+
import static io.trino.spi.predicate.Utils.nativeValueToBlock;
25+
import static io.trino.spi.type.BigintType.BIGINT;
26+
import static io.trino.spi.type.DoubleType.DOUBLE;
27+
import static io.trino.spi.type.IntegerType.INTEGER;
28+
import static io.trino.spi.type.SmallintType.SMALLINT;
29+
import static io.trino.spi.type.TinyintType.TINYINT;
30+
import static io.trino.type.InternalTypeManager.TESTING_TYPE_MANAGER;
31+
import static org.assertj.core.api.Assertions.assertThat;
32+
33+
public class TestIntegerNumberToDoubleCoercer
34+
{
35+
@Test
36+
public void testTinyintToDoubleCoercion()
37+
{
38+
assertDoubleCoercion(TINYINT, 0L, 0D);
39+
assertDoubleCoercion(TINYINT, 12L, 12D);
40+
assertDoubleCoercion(TINYINT, -12L, -12D);
41+
assertDoubleCoercion(TINYINT, (long) Byte.MAX_VALUE, 127D);
42+
assertDoubleCoercion(TINYINT, (long) Byte.MIN_VALUE, -128D);
43+
}
44+
45+
@Test
46+
public void testSmallintToDoubleCoercion()
47+
{
48+
assertDoubleCoercion(SMALLINT, 0L, 0D);
49+
assertDoubleCoercion(SMALLINT, 128L, 128D);
50+
assertDoubleCoercion(SMALLINT, -128L, -128D);
51+
assertDoubleCoercion(SMALLINT, (long) Short.MAX_VALUE, 32767D);
52+
assertDoubleCoercion(SMALLINT, (long) Short.MIN_VALUE, -32768D);
53+
}
54+
55+
@Test
56+
public void testIntToDoubleCoercion()
57+
{
58+
assertDoubleCoercion(INTEGER, 0L, 0D);
59+
assertDoubleCoercion(INTEGER, 128L, 128D);
60+
assertDoubleCoercion(INTEGER, -128L, -128D);
61+
assertDoubleCoercion(INTEGER, (long) Integer.MAX_VALUE, 2147483647D);
62+
assertDoubleCoercion(INTEGER, (long) Integer.MIN_VALUE, -2147483648D);
63+
}
64+
65+
@Test
66+
public void testBigintToDoubleCoercion()
67+
{
68+
assertDoubleCoercion(BIGINT, 0L, 0D);
69+
assertDoubleCoercion(BIGINT, 128L, 128D);
70+
assertDoubleCoercion(BIGINT, -128L, -128D);
71+
assertDoubleCoercion(BIGINT, Long.MAX_VALUE, 9223372036854775807D);
72+
assertDoubleCoercion(BIGINT, Long.MIN_VALUE, -9223372036854775808D);
73+
}
74+
75+
private static void assertDoubleCoercion(Type fromType, Object valueToBeCoerced, Double expectedValue)
76+
{
77+
Block coercedValue = createCoercer(TESTING_TYPE_MANAGER, toHiveType(fromType), toHiveType(DOUBLE), new CoercionUtils.CoercionContext(DEFAULT_PRECISION, true)).orElseThrow()
78+
.apply(nativeValueToBlock(fromType, valueToBeCoerced));
79+
assertThat(blockToNativeValue(DOUBLE, coercedValue))
80+
.isEqualTo(expectedValue);
81+
}
82+
}

0 commit comments

Comments
 (0)