Skip to content

Commit

Permalink
ARROW-12479: [C++][Gandiva] Implement castBigInt, castInt, castInterv…
Browse files Browse the repository at this point in the history
…alDay and castIntervalYear extra functions

Closes #10112 from jvictorhuguenin/feature/implement-castint-cast-bigint-for-various-types and squashes the following commits:

9a3e8ad <frank400> Remove castNULLABLE unnecessary implementations
d029d12 <frank400> Change macro parameter from NAME to TYPE
33dad3a <frank400> Change alias for year_interval to month_interval
44bf1ad <frank400> Fix implicit cast
5a42c3c <frank400> Implement round method
9fc9324 <frank400> Fix unsigned minus sign
5e7a335 <frank400> Fix build problems
f52655f <frank400> Fix checkstyle
6f1f87d <frank400> Add alias for nullable functions
813d9cc <frank400> Add projector test for nullable functions
8afc3eb <frank400> Add Cast nullable functions
c284b1e <frank400> Fix year Interval type
89a2daf <frank400> Add test for implemented castINT functions
1f3e44b <frank400> Fix tests implementation
e177ebb <frank400> Fix duplicated function
5c6a7f3 <frank400> Add castINT and castBIGINT from dayinterval and yearinterval
d98af88 <frank400> Add castINT and castBIGINT for floats and doubles

Authored-by: frank400 <j.victorhuguenin2018@gmail.com>
Signed-off-by: Praveen <praveen@dremio.com>
  • Loading branch information
jvictorhuguenin authored and praveenbingo committed Aug 4, 2021
1 parent c4e53e0 commit 87e0252
Show file tree
Hide file tree
Showing 10 changed files with 351 additions and 2 deletions.
14 changes: 12 additions & 2 deletions cpp/src/gandiva/function_registry_arithmetic.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,13 @@ namespace gandiva {
#define BINARY_RELATIONAL_BOOL_DATE_FN(name, ALIASES) \
NUMERIC_DATE_TYPES(BINARY_RELATIONAL_SAFE_NULL_IF_NULL, name, ALIASES)

#define UNARY_CAST_TO_FLOAT64(name) UNARY_SAFE_NULL_IF_NULL(castFLOAT8, {}, name, float64)
#define UNARY_CAST_TO_FLOAT64(type) UNARY_SAFE_NULL_IF_NULL(castFLOAT8, {}, type, float64)

#define UNARY_CAST_TO_FLOAT32(name) UNARY_SAFE_NULL_IF_NULL(castFLOAT4, {}, name, float32)
#define UNARY_CAST_TO_FLOAT32(type) UNARY_SAFE_NULL_IF_NULL(castFLOAT4, {}, type, float32)

#define UNARY_CAST_TO_INT32(type) UNARY_SAFE_NULL_IF_NULL(castINT, {}, type, int32)

#define UNARY_CAST_TO_INT64(type) UNARY_SAFE_NULL_IF_NULL(castBIGINT, {}, type, int64)

std::vector<NativeFunction> GetArithmeticFunctionRegistry() {
static std::vector<NativeFunction> arithmetic_fn_registry_ = {
Expand All @@ -44,6 +48,12 @@ std::vector<NativeFunction> GetArithmeticFunctionRegistry() {
UNARY_CAST_TO_FLOAT32(int32), UNARY_CAST_TO_FLOAT32(int64),
UNARY_CAST_TO_FLOAT32(float64),

// cast to int32
UNARY_CAST_TO_INT32(float32), UNARY_CAST_TO_INT32(float64),

// cast to int64
UNARY_CAST_TO_INT64(float32), UNARY_CAST_TO_INT64(float64),

// cast to float64
UNARY_CAST_TO_FLOAT64(int32), UNARY_CAST_TO_FLOAT64(int64),
UNARY_CAST_TO_FLOAT64(float32), UNARY_CAST_TO_FLOAT64(decimal128),
Expand Down
1 change: 1 addition & 0 deletions cpp/src/gandiva/function_registry_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ using arrow::int16;
using arrow::int32;
using arrow::int64;
using arrow::int8;
using arrow::month_interval;
using arrow::uint16;
using arrow::uint32;
using arrow::uint64;
Expand Down
26 changes: 26 additions & 0 deletions cpp/src/gandiva/function_registry_datetime.cc
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,32 @@ std::vector<NativeFunction> GetDateTimeFunctionRegistry() {
NativeFunction("castBIGINT", {}, DataTypeVector{day_time_interval()}, int64(),
kResultNullIfNull, "castBIGINT_daytimeinterval"),

NativeFunction("castINT", {"castNULLABLEINT"}, DataTypeVector{month_interval()},
int32(), kResultNullIfNull, "castINT_year_interval",
NativeFunction::kCanReturnErrors),

NativeFunction("castBIGINT", {"castNULLABLEBIGINT"},
DataTypeVector{month_interval()}, int64(), kResultNullIfNull,
"castBIGINT_year_interval", NativeFunction::kCanReturnErrors),

NativeFunction("castNULLABLEINTERVALYEAR", {"castINTERVALYEAR"},
DataTypeVector{int32()}, month_interval(), kResultNullIfNull,
"castNULLABLEINTERVALYEAR_int32",
NativeFunction::kNeedsContext | NativeFunction::kCanReturnErrors),

NativeFunction("castNULLABLEINTERVALYEAR", {"castINTERVALYEAR"},
DataTypeVector{int64()}, month_interval(), kResultNullIfNull,
"castNULLABLEINTERVALYEAR_int64",
NativeFunction::kNeedsContext | NativeFunction::kCanReturnErrors),

NativeFunction("castNULLABLEINTERVALDAY", {"castINTERVALDAY"},
DataTypeVector{int32()}, day_time_interval(), kResultNullIfNull,
"castNULLABLEINTERVALDAY_int32"),

NativeFunction("castNULLABLEINTERVALDAY", {"castINTERVALDAY"},
DataTypeVector{int64()}, day_time_interval(), kResultNullIfNull,
"castNULLABLEINTERVALDAY_int64"),

NativeFunction("extractDay", {}, DataTypeVector{day_time_interval()}, int64(),
kResultNullIfNull, "extractDay_daytimeinterval"),

Expand Down
1 change: 1 addition & 0 deletions cpp/src/gandiva/gdv_function_stubs.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ using gdv_timestamp = int64_t;
using gdv_utf8 = char*;
using gdv_binary = char*;
using gdv_day_time_interval = int64_t;
using gdv_month_interval = int32_t;

#ifdef GANDIVA_UNIT_TEST
// unit tests may be compiled without O2, so inlining may not happen.
Expand Down
15 changes: 15 additions & 0 deletions cpp/src/gandiva/precompiled/arithmetic_ops.cc
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,21 @@ CAST_UNARY(castFLOAT4, float64, float32)

#undef CAST_UNARY

// cast float types to int types.
#define CAST_INT_FLOAT(NAME, IN_TYPE, OUT_TYPE) \
FORCE_INLINE \
gdv_##OUT_TYPE NAME##_##IN_TYPE(gdv_##IN_TYPE in) { \
gdv_##OUT_TYPE out = static_cast<gdv_##OUT_TYPE>(round(in)); \
return out; \
}

CAST_INT_FLOAT(castBIGINT, float32, int64)
CAST_INT_FLOAT(castBIGINT, float64, int64)
CAST_INT_FLOAT(castINT, float32, int32)
CAST_INT_FLOAT(castINT, float64, int32)

#undef CAST_INT_FLOAT

// simple nullable functions, result value = fn(input validity)
#define VALIDITY_OP(NAME, TYPE, OP) \
FORCE_INLINE \
Expand Down
40 changes: 40 additions & 0 deletions cpp/src/gandiva/precompiled/arithmetic_ops_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,44 @@ TEST(TestArithmeticOps, TestBitwiseOps) {
EXPECT_EQ(bitwise_not_int64(0x0000000000000000), 0xFFFFFFFFFFFFFFFF);
}

TEST(TestArithmeticOps, TestIntCastFloatDouble) {
// castINT from floats
EXPECT_EQ(castINT_float32(6.6f), 7);
EXPECT_EQ(castINT_float32(-6.6f), -7);
EXPECT_EQ(castINT_float32(-6.3f), -6);
EXPECT_EQ(castINT_float32(0.0f), 0);
EXPECT_EQ(castINT_float32(-0), 0);

// castINT from doubles
EXPECT_EQ(castINT_float64(6.6), 7);
EXPECT_EQ(castINT_float64(-6.6), -7);
EXPECT_EQ(castINT_float64(-6.3), -6);
EXPECT_EQ(castINT_float64(0.0), 0);
EXPECT_EQ(castINT_float64(-0), 0);
EXPECT_EQ(castINT_float64(999999.99999999999999999999999), 1000000);
EXPECT_EQ(castINT_float64(-999999.99999999999999999999999), -1000000);
EXPECT_EQ(castINT_float64(INT32_MAX), 2147483647);
EXPECT_EQ(castINT_float64(-2147483647), -2147483647);
}

TEST(TestArithmeticOps, TestBigIntCastFloatDouble) {
// castINT from floats
EXPECT_EQ(castBIGINT_float32(6.6f), 7);
EXPECT_EQ(castBIGINT_float32(-6.6f), -7);
EXPECT_EQ(castBIGINT_float32(-6.3f), -6);
EXPECT_EQ(castBIGINT_float32(0.0f), 0);
EXPECT_EQ(castBIGINT_float32(-0), 0);

// castINT from doubles
EXPECT_EQ(castBIGINT_float64(6.6), 7);
EXPECT_EQ(castBIGINT_float64(-6.6), -7);
EXPECT_EQ(castBIGINT_float64(-6.3), -6);
EXPECT_EQ(castBIGINT_float64(0.0), 0);
EXPECT_EQ(castBIGINT_float64(-0), 0);
EXPECT_EQ(castBIGINT_float64(999999.99999999999999999999999), 1000000);
EXPECT_EQ(castBIGINT_float64(-999999.99999999999999999999999), -1000000);
EXPECT_EQ(castBIGINT_float64(INT32_MAX), 2147483647);
EXPECT_EQ(castBIGINT_float64(-2147483647), -2147483647);
}

} // namespace gandiva
31 changes: 31 additions & 0 deletions cpp/src/gandiva/precompiled/time.cc
Original file line number Diff line number Diff line change
Expand Up @@ -860,4 +860,35 @@ NUMERIC_TYPES(TO_TIMESTAMP)

NUMERIC_TYPES(TO_TIME)

#define CAST_INT_YEAR_INTERVAL(TYPE, OUT_TYPE) \
FORCE_INLINE \
gdv_##OUT_TYPE TYPE##_year_interval(gdv_month_interval in) { \
return static_cast<gdv_##OUT_TYPE>(in / 12.0); \
}

CAST_INT_YEAR_INTERVAL(castBIGINT, int64)
CAST_INT_YEAR_INTERVAL(castINT, int32)

#define CAST_NULLABLE_INTERVAL_DAY(TYPE) \
FORCE_INLINE \
gdv_day_time_interval castNULLABLEINTERVALDAY_##TYPE(gdv_##TYPE in) { \
return static_cast<gdv_day_time_interval>(in); \
}

CAST_NULLABLE_INTERVAL_DAY(int32)
CAST_NULLABLE_INTERVAL_DAY(int64)

#define CAST_NULLABLE_INTERVAL_YEAR(TYPE) \
FORCE_INLINE \
gdv_month_interval castNULLABLEINTERVALYEAR_##TYPE(int64_t context, gdv_##TYPE in) { \
gdv_month_interval value = static_cast<gdv_month_interval>(in); \
if (value != in) { \
gdv_fn_context_set_error_msg(context, "Integer overflow"); \
} \
return value; \
}

CAST_NULLABLE_INTERVAL_YEAR(int32)
CAST_NULLABLE_INTERVAL_YEAR(int64)

} // extern "C"
44 changes: 44 additions & 0 deletions cpp/src/gandiva/precompiled/time_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -869,4 +869,48 @@ TEST(TestTime, TestToTimeNumeric) {
EXPECT_EQ(expected_output, to_time_float64(3601.500));
}

TEST(TestTime, TestCastIntDayInterval) {
EXPECT_EQ(castBIGINT_daytimeinterval(10), 864000000);
EXPECT_EQ(castBIGINT_daytimeinterval(-100), -8640000001);
EXPECT_EQ(castBIGINT_daytimeinterval(-0), 0);
}

TEST(TestTime, TestCastIntYearInterval) {
EXPECT_EQ(castINT_year_interval(24), 2);
EXPECT_EQ(castINT_year_interval(-24), -2);
EXPECT_EQ(castINT_year_interval(-23), -1);

EXPECT_EQ(castBIGINT_year_interval(24), 2);
EXPECT_EQ(castBIGINT_year_interval(-24), -2);
EXPECT_EQ(castBIGINT_year_interval(-23), -1);
}

TEST(TestTime, TestCastNullableInterval) {
ExecutionContext context;
auto context_ptr = reinterpret_cast<int64_t>(&context);
// Test castNULLABLEINTERVALDAY for int and bigint
EXPECT_EQ(castNULLABLEINTERVALDAY_int32(1), 1);
EXPECT_EQ(castNULLABLEINTERVALDAY_int32(12), 12);
EXPECT_EQ(castNULLABLEINTERVALDAY_int32(-55), -55);
EXPECT_EQ(castNULLABLEINTERVALDAY_int32(-1201), -1201);
EXPECT_EQ(castNULLABLEINTERVALDAY_int64(1), 1);
EXPECT_EQ(castNULLABLEINTERVALDAY_int64(12), 12);
EXPECT_EQ(castNULLABLEINTERVALDAY_int64(-55), -55);
EXPECT_EQ(castNULLABLEINTERVALDAY_int64(-1201), -1201);

// Test castNULLABLEINTERVALYEAR for int and bigint
EXPECT_EQ(castNULLABLEINTERVALYEAR_int32(context_ptr, 1), 1);
EXPECT_EQ(castNULLABLEINTERVALYEAR_int32(context_ptr, 12), 12);
EXPECT_EQ(castNULLABLEINTERVALYEAR_int32(context_ptr, 55), 55);
EXPECT_EQ(castNULLABLEINTERVALYEAR_int32(context_ptr, 1201), 1201);
EXPECT_EQ(castNULLABLEINTERVALYEAR_int64(context_ptr, 1), 1);
EXPECT_EQ(castNULLABLEINTERVALYEAR_int64(context_ptr, 12), 12);
EXPECT_EQ(castNULLABLEINTERVALYEAR_int64(context_ptr, 55), 55);
EXPECT_EQ(castNULLABLEINTERVALYEAR_int64(context_ptr, 1201), 1201);
// validate overflow error when using bigint as input
castNULLABLEINTERVALYEAR_int64(context_ptr, INT64_MAX);
EXPECT_EQ(context.get_error(), "Integer overflow");
context.Reset();
}

} // namespace gandiva
22 changes: 22 additions & 0 deletions cpp/src/gandiva/precompiled/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -543,4 +543,26 @@ float castFLOAT4_utf8(int64_t context, const char* data, int32_t len);

double castFLOAT8_utf8(int64_t context, const char* data, int32_t len);

int32_t castINT_float32(gdv_float32 value);

int32_t castINT_float64(gdv_float64 value);

int64_t castBIGINT_float32(gdv_float32 value);

int64_t castBIGINT_float64(gdv_float64 value);

int64_t castBIGINT_daytimeinterval(gdv_day_time_interval in);

int32_t castINT_year_interval(gdv_month_interval in);

int64_t castBIGINT_year_interval(gdv_month_interval in);

gdv_day_time_interval castNULLABLEINTERVALDAY_int32(gdv_int32 in);

gdv_day_time_interval castNULLABLEINTERVALDAY_int64(gdv_int64 in);

gdv_month_interval castNULLABLEINTERVALYEAR_int32(int64_t context, gdv_int32 in);

gdv_month_interval castNULLABLEINTERVALYEAR_int64(int64_t context, gdv_int64 in);

} // extern "C"
Loading

0 comments on commit 87e0252

Please sign in to comment.