Skip to content

Commit 9fa4aee

Browse files
elbinpallimalilibmtdcmeehan
authored andcommitted
Add cast functions for char datatype to numeric types
1 parent 48f0a0c commit 9fa4aee

File tree

4 files changed

+119
-6
lines changed

4 files changed

+119
-6
lines changed

presto-main/src/main/java/com/facebook/presto/type/CharOperators.java

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import com.facebook.presto.common.block.Block;
1717
import com.facebook.presto.common.type.StandardTypes;
18+
import com.facebook.presto.spi.PrestoException;
1819
import com.facebook.presto.spi.function.BlockIndex;
1920
import com.facebook.presto.spi.function.BlockPosition;
2021
import com.facebook.presto.spi.function.IsNull;
@@ -26,6 +27,7 @@
2627
import io.airlift.slice.XxHash64;
2728

2829
import static com.facebook.presto.common.function.OperatorType.BETWEEN;
30+
import static com.facebook.presto.common.function.OperatorType.CAST;
2931
import static com.facebook.presto.common.function.OperatorType.EQUAL;
3032
import static com.facebook.presto.common.function.OperatorType.GREATER_THAN;
3133
import static com.facebook.presto.common.function.OperatorType.GREATER_THAN_OR_EQUAL;
@@ -37,6 +39,8 @@
3739
import static com.facebook.presto.common.function.OperatorType.NOT_EQUAL;
3840
import static com.facebook.presto.common.function.OperatorType.XX_HASH_64;
3941
import static com.facebook.presto.common.type.Chars.compareChars;
42+
import static com.facebook.presto.spi.StandardErrorCode.INVALID_CAST_ARGUMENT;
43+
import static java.lang.String.format;
4044

4145
public final class CharOperators
4246
{
@@ -167,4 +171,82 @@ public static boolean indeterminate(@SqlType("char(x)") Slice value, @IsNull boo
167171
{
168172
return isNull;
169173
}
174+
175+
@LiteralParameters("x")
176+
@ScalarOperator(CAST)
177+
@SqlType(StandardTypes.DOUBLE)
178+
public static double castToDouble(@SqlType("char(x)") Slice slice)
179+
{
180+
try {
181+
return Double.parseDouble(slice.toStringUtf8());
182+
}
183+
catch (Exception e) {
184+
throw new PrestoException(INVALID_CAST_ARGUMENT, format("Cannot cast '%s' to DOUBLE", slice.toStringUtf8()));
185+
}
186+
}
187+
188+
@LiteralParameters("x")
189+
@ScalarOperator(CAST)
190+
@SqlType(StandardTypes.REAL)
191+
public static long castToFloat(@SqlType("char(x)") Slice slice)
192+
{
193+
try {
194+
return Float.floatToIntBits(Float.parseFloat(slice.toStringUtf8()));
195+
}
196+
catch (Exception e) {
197+
throw new PrestoException(INVALID_CAST_ARGUMENT, format("Cannot cast '%s' to REAL", slice.toStringUtf8()));
198+
}
199+
}
200+
201+
@LiteralParameters("x")
202+
@ScalarOperator(CAST)
203+
@SqlType(StandardTypes.BIGINT)
204+
public static long castToBigint(@SqlType("char(x)") Slice slice)
205+
{
206+
try {
207+
return Long.parseLong(slice.toStringUtf8().trim());
208+
}
209+
catch (Exception e) {
210+
throw new PrestoException(INVALID_CAST_ARGUMENT, format("Cannot cast '%s' to BIGINT", slice.toStringUtf8()));
211+
}
212+
}
213+
214+
@LiteralParameters("x")
215+
@ScalarOperator(CAST)
216+
@SqlType(StandardTypes.INTEGER)
217+
public static long castToInteger(@SqlType("char(x)") Slice slice)
218+
{
219+
try {
220+
return Integer.parseInt(slice.toStringUtf8().trim());
221+
}
222+
catch (Exception e) {
223+
throw new PrestoException(INVALID_CAST_ARGUMENT, format("Cannot cast '%s' to INT", slice.toStringUtf8()));
224+
}
225+
}
226+
227+
@LiteralParameters("x")
228+
@ScalarOperator(CAST)
229+
@SqlType(StandardTypes.SMALLINT)
230+
public static long castToSmallint(@SqlType("char(x)") Slice slice)
231+
{
232+
try {
233+
return Short.parseShort(slice.toStringUtf8().trim());
234+
}
235+
catch (Exception e) {
236+
throw new PrestoException(INVALID_CAST_ARGUMENT, format("Cannot cast '%s' to SMALLINT", slice.toStringUtf8()));
237+
}
238+
}
239+
240+
@LiteralParameters("x")
241+
@ScalarOperator(CAST)
242+
@SqlType(StandardTypes.TINYINT)
243+
public static long castToTinyint(@SqlType("char(x)") Slice slice)
244+
{
245+
try {
246+
return Byte.parseByte(slice.toStringUtf8().trim());
247+
}
248+
catch (Exception e) {
249+
throw new PrestoException(INVALID_CAST_ARGUMENT, format("Cannot cast '%s' to TINYINT", slice.toStringUtf8()));
250+
}
251+
}
170252
}

presto-main/src/test/java/com/facebook/presto/operator/scalar/AbstractTestFunctions.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@ protected void assertFunction(String projection, Type expectedType, Object expec
112112
functionAssertions.assertFunction(projection, expectedType, expected);
113113
}
114114

115+
protected void assertFunctionString(String projection, Type expectedType, String expected)
116+
{
117+
functionAssertions.assertFunctionString(projection, expectedType, expected);
118+
}
119+
115120
protected void assertFunctionWithError(String projection, Type expectedType, Double expected)
116121
{
117122
if (expected == null) {

presto-main/src/test/java/com/facebook/presto/operator/scalar/TestDateTimeFunctionsBase.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import com.facebook.presto.common.type.TimeType;
2525
import com.facebook.presto.common.type.TimeZoneKey;
2626
import com.facebook.presto.common.type.TimestampType;
27-
import com.facebook.presto.common.type.Type;
2827
import com.facebook.presto.spi.StandardErrorCode;
2928
import com.facebook.presto.spi.security.ConnectorIdentity;
3029
import com.facebook.presto.testing.TestingConnectorSession;
@@ -1175,11 +1174,6 @@ public void testIntervalDayToSecondToMilliseconds()
11751174
assertFunction("to_milliseconds(parse_duration('1d'))", BigintType.BIGINT, DAYS.toMillis(1));
11761175
}
11771176

1178-
private void assertFunctionString(String projection, Type expectedType, String expected)
1179-
{
1180-
functionAssertions.assertFunctionString(projection, expectedType, expected);
1181-
}
1182-
11831177
private static SqlDate toDate(LocalDate localDate)
11841178
{
11851179
return new SqlDate(toIntExact(localDate.toEpochDay()));

presto-main/src/test/java/com/facebook/presto/type/TestCharOperators.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,13 @@
1717
import org.testng.annotations.Test;
1818

1919
import static com.facebook.presto.common.function.OperatorType.INDETERMINATE;
20+
import static com.facebook.presto.common.type.BigintType.BIGINT;
2021
import static com.facebook.presto.common.type.BooleanType.BOOLEAN;
22+
import static com.facebook.presto.common.type.DoubleType.DOUBLE;
23+
import static com.facebook.presto.common.type.IntegerType.INTEGER;
24+
import static com.facebook.presto.common.type.RealType.REAL;
25+
import static com.facebook.presto.common.type.SmallintType.SMALLINT;
26+
import static com.facebook.presto.common.type.TinyintType.TINYINT;
2127

2228
public class TestCharOperators
2329
extends AbstractTestFunctions
@@ -192,4 +198,30 @@ public void testIndeterminate()
192198
assertOperator(INDETERMINATE, "CAST(null AS CHAR(3))", BOOLEAN, true);
193199
assertOperator(INDETERMINATE, "CHAR '123'", BOOLEAN, false);
194200
}
201+
202+
@Test
203+
public void testCharCast()
204+
{
205+
assertFunction("CAST(CAST('78.95' AS CHAR(5)) AS DOUBLE)", DOUBLE, 78.95);
206+
assertFunction("CAST(CAST(' 45.58 ' AS CHAR(10)) AS DOUBLE)", DOUBLE, 45.58);
207+
assertInvalidCast("CAST(CAST(' Z56 ' AS CHAR(20)) AS DOUBLE)");
208+
assertFunction("CAST(CAST('45.783' AS CHAR(6)) AS REAL)", REAL, 45.783f);
209+
assertFunction("CAST(CAST(' 45.783 ' AS CHAR(10)) AS REAL)", REAL, 45.783f);
210+
assertInvalidCast("CAST(CAST(' Z56 ' AS CHAR(20)) AS REAL)");
211+
assertFunctionString("CAST(CAST('6.40282346638528860e+70' AS CHAR(60)) AS REAL)", REAL, "Infinity");
212+
assertFunction("CAST(CAST('45' AS CHAR(2)) AS BIGINT)", BIGINT, 45L);
213+
assertFunction("CAST(CAST(' 45 ' AS CHAR(10)) AS BIGINT)", BIGINT, 45L);
214+
assertInvalidCast("CAST(CAST(' Z56 ' AS CHAR(20)) AS BIGINT)");
215+
assertFunction("CAST(CAST('45' AS CHAR(2)) AS INTEGER)", INTEGER, 45);
216+
assertFunction("CAST(CAST('2147483647' AS CHAR(10)) AS INTEGER)", INTEGER, 2147483647);
217+
assertFunction("CAST(CAST(' 45 ' AS CHAR(10)) AS INTEGER)", INTEGER, 45);
218+
assertInvalidCast("CAST(CAST(' Z56 ' AS CHAR(20)) AS INTEGER)");
219+
assertInvalidCast("CAST(CAST('2147483648' AS CHAR(10)) AS INTEGER)"); // 1 over the max range of integer
220+
assertFunction("CAST(CAST('45' AS CHAR(2)) AS SMALLINT)", SMALLINT, (short) 45);
221+
assertFunction("CAST(CAST(' 45 ' AS CHAR(10)) AS SMALLINT)", SMALLINT, (short) 45);
222+
assertInvalidCast("CAST(CAST(' Z56 ' AS CHAR(20)) AS SMALLINT)");
223+
assertFunction("CAST(CAST('123' AS CHAR(3)) AS TINYINT)", TINYINT, (byte) 123);
224+
assertFunction("CAST(CAST(' 123 ' AS CHAR(10)) AS TINYINT)", TINYINT, (byte) 123);
225+
assertInvalidCast("CAST(CAST(' Z56 ' AS CHAR(20)) AS TINYINT)");
226+
}
195227
}

0 commit comments

Comments
 (0)