* Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
* Description: batch function test
*/
#include <string>
#include <vector>
#include "gtest/gtest.h"
#include "codegen/batch_functions/batch_mathfunctions.h"
#include "codegen/batch_functions/batch_murmur3_hash.h"
#include "codegen/batch_functions/batch_decimal_arithmetic_functions.h"
#include "codegen/batch_functions/batch_decimal_cast_functions.h"
#include "operator/execution_context.h"
#include "codegen/batch_functions/batch_stringfunctions.h"
#include "codegen/batch_functions/batch_datetime_functions.h"
#include "util/test_util.h"
using namespace omniruntime::op;
using namespace omniruntime::codegen::function;
using namespace std;
using namespace omniruntime::TestUtil;
template <typename T> bool CmpArray(T *x, T *y, int32_t rowCnt)
{
for (int i = 0; i < rowCnt; ++i) {
if (x[i] != y[i]) {
return false;
}
}
return true;
}
TEST(BatchFunctionTest, CastBasicTypes)
{
ConfigUtil::SetRoundingRule(RoundingRule::HALF_UP);
int32_t rowCnt = 2;
int32_t col1[2] = {-10, 10};
int64_t col2[2] = {-20L, 20L};
double col3[2] = {-30.0, 30.0};
bool resIsNull[2] = {false, false};
double outDouble[2];
BatchCastInt32ToDouble(col1, resIsNull, outDouble, rowCnt);
double expectDouble1[2] = {-10.0, 10.0};
EXPECT_TRUE(CmpArray<double>(outDouble, expectDouble1, rowCnt));
BatchCastInt64ToDouble(col2, resIsNull, outDouble, rowCnt);
double expectDouble2[2] = {-20.0, 20.0};
EXPECT_TRUE(CmpArray<double>(outDouble, expectDouble2, rowCnt));
int32_t outInt[2];
BatchCastInt64ToInt32(col2, resIsNull, outInt, rowCnt);
int32_t expectInt1[2] = {-20, 20};
EXPECT_TRUE(CmpArray<int32_t>(outInt, expectInt1, rowCnt));
BatchCastDoubleToInt32HalfUp(col3, resIsNull, outInt, rowCnt);
int32_t expectInt2[2] = { -30, 30 };
EXPECT_TRUE(CmpArray<int32_t>(outInt, expectInt2, rowCnt));
int64_t outLong[2];
BatchCastInt32ToInt64(col1, resIsNull, outLong, rowCnt);
int64_t expectLong1[2] = { -10L, 10L };
EXPECT_TRUE(CmpArray<int64_t>(outLong, expectLong1, rowCnt));
BatchCastDoubleToInt64HalfUp(col3, resIsNull, outLong, rowCnt);
int64_t expectLong2[2] = { -30L, 30L };
EXPECT_TRUE(CmpArray<int64_t>(outLong, expectLong2, rowCnt));
}
TEST(BatchFunctionTest, Abs)
{
int32_t rowCnt = 2;
int32_t col1[2] = { -10, 10 };
int64_t col2[2] = { -20L, 20L };
double col3[2] = { -30.0, 30.0 };
bool resIsNull[2] = { false, false };
BatchAbs<int32_t>(col1, resIsNull, col1, rowCnt);
BatchAbs<int64_t>(col2, resIsNull, col2, rowCnt);
BatchAbs<double>(col3, resIsNull, col3, rowCnt);
int32_t expectCol1[2] = { 10, 10 };
int64_t expectCol2[2] = { 20L, 20L };
double expectCol3[2] = { 30.0, 30.0 };
EXPECT_TRUE(CmpArray<int32_t>(col1, expectCol1, rowCnt));
EXPECT_TRUE(CmpArray<int64_t>(col2, expectCol2, rowCnt));
EXPECT_TRUE(CmpArray<double>(col3, expectCol3, rowCnt));
}
TEST(BatchFunctionTest, IntCmp)
{
int32_t rowCnt = 2;
int32_t left[2] = { -10, 20 };
int32_t right[2] = { -20, 10 };
bool output[2];
bool expect[2];
BatchLessThanInt32(left, right, output, rowCnt);
expect[0] = false;
expect[1] = false;
EXPECT_TRUE(CmpArray<bool>(output, expect, rowCnt));
BatchLessThanEqualInt32(left, right, output, rowCnt);
expect[0] = false;
expect[1] = false;
EXPECT_TRUE(CmpArray<bool>(output, expect, rowCnt));
BatchGreaterThanInt32(left, right, output, rowCnt);
expect[0] = true;
expect[1] = true;
EXPECT_TRUE(CmpArray<bool>(output, expect, rowCnt));
BatchGreaterThanEqualInt32(left, right, output, rowCnt);
expect[0] = true;
expect[1] = true;
EXPECT_TRUE(CmpArray<bool>(output, expect, rowCnt));
BatchEqualInt32(left, right, output, rowCnt);
expect[0] = false;
expect[1] = false;
EXPECT_TRUE(CmpArray<bool>(output, expect, rowCnt));
BatchNotEqualInt32(left, right, output, rowCnt);
expect[0] = true;
expect[1] = true;
EXPECT_TRUE(CmpArray<bool>(output, expect, rowCnt));
}
TEST(BatchFunctionTest, IntArith)
{
int32_t rowCnt = 2;
int32_t left[2] = { -10, 10 };
int32_t right[2] = { -20, 20 };
int32_t expect[2];
bool isNull[2] = { false, false };
auto context = new ExecutionContext();
int64_t contextPtr = reinterpret_cast<int64_t>(context);
expect[0] = -30;
expect[1] = 30;
BatchAddInt32(left, right, rowCnt);
EXPECT_TRUE(CmpArray<int32_t>(left, expect, rowCnt));
expect[0] = -10;
expect[1] = 10;
BatchSubtractInt32(left, right, rowCnt);
EXPECT_TRUE(CmpArray<int32_t>(left, expect, rowCnt));
expect[0] = 200;
expect[1] = 200;
BatchMultiplyInt32(left, right, rowCnt);
EXPECT_TRUE(CmpArray<int32_t>(left, expect, rowCnt));
expect[0] = -10;
expect[1] = 10;
BatchDivideInt32(contextPtr, left, right, rowCnt, isNull);
EXPECT_TRUE(CmpArray<int32_t>(left, expect, rowCnt));
expect[0] = -10;
expect[1] = 10;
BatchModulusInt32(contextPtr, left, right, rowCnt, isNull);
EXPECT_TRUE(CmpArray<int32_t>(left, expect, rowCnt));
delete context;
}
TEST(BatchFunctionTest, LongCmp)
{
int32_t rowCnt = 2;
int64_t left[2] = { -10L, 20L };
int64_t right[2] = { -20L, 10L };
bool output[2];
bool expect[2];
BatchLessThanInt64(left, right, output, rowCnt);
expect[0] = false;
expect[1] = false;
EXPECT_TRUE(CmpArray<bool>(output, expect, rowCnt));
BatchLessThanEqualInt64(left, right, output, rowCnt);
expect[0] = false;
expect[1] = false;
EXPECT_TRUE(CmpArray<bool>(output, expect, rowCnt));
BatchGreaterThanInt64(left, right, output, rowCnt);
expect[0] = true;
expect[1] = true;
EXPECT_TRUE(CmpArray<bool>(output, expect, rowCnt));
BatchGreaterThanEqualInt64(left, right, output, rowCnt);
expect[0] = true;
expect[1] = true;
EXPECT_TRUE(CmpArray<bool>(output, expect, rowCnt));
BatchEqualInt64(left, right, output, rowCnt);
expect[0] = false;
expect[1] = false;
EXPECT_TRUE(CmpArray<bool>(output, expect, rowCnt));
BatchNotEqualInt64(left, right, output, rowCnt);
expect[0] = true;
expect[1] = true;
EXPECT_TRUE(CmpArray<bool>(output, expect, rowCnt));
}
TEST(BatchFunctionTest, LongArith)
{
int32_t rowCnt = 2;
int64_t left[2] = { -10L, 10L };
int64_t right[2] = { -20L, 20L };
int64_t expect[2];
bool isNull[2] = { false, false };
auto context = new ExecutionContext();
int64_t contextPtr = reinterpret_cast<int64_t>(context);
expect[0] = -30L;
expect[1] = 30L;
BatchAddInt64(left, right, rowCnt);
EXPECT_TRUE(CmpArray<int64_t>(left, expect, rowCnt));
expect[0] = -10L;
expect[1] = 10L;
BatchSubtractInt64(left, right, rowCnt);
EXPECT_TRUE(CmpArray<int64_t>(left, expect, rowCnt));
expect[0] = 200L;
expect[1] = 200L;
BatchMultiplyInt64(left, right, rowCnt);
EXPECT_TRUE(CmpArray<int64_t>(left, expect, rowCnt));
expect[0] = -10L;
expect[1] = 10L;
BatchDivideInt64(contextPtr, left, right, rowCnt, isNull);
EXPECT_TRUE(CmpArray<int64_t>(left, expect, rowCnt));
expect[0] = -10L;
expect[1] = 10L;
BatchModulusInt64(contextPtr, left, right, rowCnt, isNull);
EXPECT_TRUE(CmpArray<int64_t>(left, expect, rowCnt));
delete context;
}
TEST(BatchFunctionTest, DoubleCmp)
{
int32_t rowCnt = 2;
double left[2] = { -10.0, 20.0 };
double right[2] = { -20.0, 10.0 };
bool output[2];
bool expect[2];
BatchLessThanDouble(left, right, output, rowCnt);
expect[0] = false;
expect[1] = false;
EXPECT_TRUE(CmpArray<bool>(output, expect, rowCnt));
BatchLessThanEqualDouble(left, right, output, rowCnt);
expect[0] = false;
expect[1] = false;
EXPECT_TRUE(CmpArray<bool>(output, expect, rowCnt));
BatchGreaterThanDouble(left, right, output, rowCnt);
expect[0] = true;
expect[1] = true;
EXPECT_TRUE(CmpArray<bool>(output, expect, rowCnt));
BatchGreaterThanEqualDouble(left, right, output, rowCnt);
expect[0] = true;
expect[1] = true;
EXPECT_TRUE(CmpArray<bool>(output, expect, rowCnt));
BatchEqualDouble(left, right, output, rowCnt);
expect[0] = false;
expect[1] = false;
EXPECT_TRUE(CmpArray<bool>(output, expect, rowCnt));
BatchNotEqualDouble(left, right, output, rowCnt);
expect[0] = true;
expect[1] = true;
EXPECT_TRUE(CmpArray<bool>(output, expect, rowCnt));
}
TEST(BatchFunctionTest, DoubleArith)
{
int32_t rowCnt = 2;
double left[2] = { -10.0, 10.0 };
double right[2] = { -20.0, 20.0 };
double expect[2];
expect[0] = -30.0;
expect[1] = 30.0;
BatchAddDouble(left, right, rowCnt);
EXPECT_TRUE(CmpArray<double>(left, expect, rowCnt));
expect[0] = -10.0;
expect[1] = 10.0;
BatchSubtractDouble(left, right, rowCnt);
EXPECT_TRUE(CmpArray<double>(left, expect, rowCnt));
expect[0] = 200.0;
expect[1] = 200.0;
BatchMultiplyDouble(left, right, rowCnt);
EXPECT_TRUE(CmpArray<double>(left, expect, rowCnt));
expect[0] = -10.0;
expect[1] = 10.0;
BatchDivideDouble(left, right, rowCnt);
EXPECT_TRUE(CmpArray<double>(left, expect, rowCnt));
expect[0] = -10.0;
expect[1] = 10.0;
BatchModulusDouble(left, right, rowCnt);
EXPECT_TRUE(CmpArray<double>(left, expect, rowCnt));
}
bool CompareDoubleBits(double d1, double d2)
{
uint64_t bits1;
uint64_t bits2;
memcpy_s(&bits1, sizeof bits1, &d1, sizeof(double));
memcpy_s(&bits2, sizeof bits2, &d2, sizeof(double));
return bits1 == bits2;
}
TEST(BatchFunctionTest, BatchNormalizeNaNAndZero)
{
const int32_t rowCnt = 3;
uint64_t nanBits = 0xFFF8000000000001L;
double nanDouble = 0;
memcpy_s(&nanDouble, sizeof nanDouble, &nanBits, sizeof(nanBits));
double value = 3.5;
double input[rowCnt] = {-0.0, nanDouble, value};
bool isAnyNull[rowCnt] = {false, false, false};
double output[rowCnt];
std::vector<double> expect = {0.0, 0.0 / 0.0, value};
BatchNormalizeNaNAndZero(input, isAnyNull, output, rowCnt);
for (int32_t i = 0; i < rowCnt; i++) {
EXPECT_TRUE(CompareDoubleBits(expect[i], output[i]));
}
EXPECT_FALSE(CompareDoubleBits(input[0], output[0]));
EXPECT_FALSE(CompareDoubleBits(input[1], output[1]));
}
TEST(BatchFunctionTest, BatchPowerDouble)
{
int32_t rowCnt = 2;
double base[2] = { -10.0, 10.0 };
double exponent[2] = { 2.0, 3.0 };
double output[2];
double expect[2] = { 100.0, 1000.0 };
BatchPowerDouble(base, exponent, output, rowCnt);
EXPECT_TRUE(CmpArray<double>(output, expect, rowCnt));
}
TEST(BatchFunctionTest, Mm3Hash)
{
int32_t rowCnt = 1;
int32_t intVal[1] = { -2147483648 };
int64_t longVal[1] = { -2147483648L };
double doubleVal[1] = { 123.456 };
int64_t decimal64Val[1] = { -2147483648L };
uint8_t *strVal[1];
bool boolVal[1] = { true };
string str = "hello world";
strVal[0] = reinterpret_cast<uint8_t *>(const_cast<char *>(str.c_str()));
int32_t strLen[1] = { 11 };
Decimal128 decimal128Val[1];
decimal128Val[0].SetValue(0, 4000);
int32_t seed[1] = { 42 };
bool isValNull[1] = { false };
bool isSeedNull[1] = { false };
bool resIsNull[1] = { false };
int32_t output[1];
BatchMm3Int32(intVal, isValNull, seed, isSeedNull, resIsNull, output, rowCnt);
EXPECT_EQ(output[0], 723455942);
BatchMm3Int64(longVal, isValNull, seed, isSeedNull, resIsNull, output, rowCnt);
EXPECT_EQ(output[0], -1889108749);
BatchMm3Double(doubleVal, isValNull, seed, isSeedNull, resIsNull, output, rowCnt);
EXPECT_EQ(output[0], -39269148);
BatchMm3String(strVal, strLen, isValNull, seed, isSeedNull, resIsNull, output, rowCnt);
EXPECT_EQ(output[0], -1528836094);
BatchMm3Decimal64(decimal64Val, 8, 2, isValNull, seed, isSeedNull, resIsNull, output, rowCnt);
EXPECT_EQ(output[0], -1889108749);
BatchMm3Decimal128(decimal128Val, 38, 20, isValNull, seed, isSeedNull, resIsNull, output, rowCnt);
EXPECT_EQ(output[0], 776638264);
BatchMm3Boolean(boolVal, isValNull, seed, isSeedNull, resIsNull, output, rowCnt);
EXPECT_EQ(output[0], -559580957);
}
TEST(BatchFunctionTest, Decimal64Cmp)
{
int32_t rowCnt = 2;
int64_t col1[2] = { 12345678L, 123456L };
int64_t col2[2] = { 12345678L, 1234567890L };
bool output[2];
BatchLessThanDecimal64(col1, 8, 2, col2, 9, 2, output, rowCnt);
EXPECT_EQ(output[0], false);
EXPECT_EQ(output[1], true);
BatchLessThanEqualDecimal64(col1, 8, 3, col2, 9, 2, output, rowCnt);
EXPECT_EQ(output[0], true);
EXPECT_EQ(output[1], true);
BatchGreaterThanDecimal64(col1, 8, 6, col2, 9, 2, output, rowCnt);
EXPECT_EQ(output[0], false);
EXPECT_EQ(output[1], false);
BatchGreaterThanEqualDecimal64(col1, 8, 2, col2, 9, 2, output, rowCnt);
EXPECT_EQ(output[0], true);
EXPECT_EQ(output[1], false);
BatchEqualDecimal64(col1, 8, 2, col2, 9, 2, output, rowCnt);
EXPECT_EQ(output[0], true);
EXPECT_EQ(output[1], false);
BatchNotEqualDecimal64(col1, 8, 2, col2, 9, 2, output, rowCnt);
EXPECT_EQ(output[0], false);
EXPECT_EQ(output[1], true);
}
TEST(BatchFunctionTest, Decimal128Cmp)
{
int32_t rowCnt = 2;
Decimal128 col1[2];
col1[0].SetValue(1234567L, UINT64_MAX);
col1[1].SetValue(123456L, UINT64_MAX);
Decimal128 col2[2];
col2[0].SetValue(-1234567L, UINT64_MAX);
col2[1].SetValue(1234567L, UINT64_MAX);
bool output[2];
BatchLessThanDecimal128(col1, 38, 2, col2, 38, 2, output, rowCnt);
EXPECT_EQ(output[0], false);
EXPECT_EQ(output[1], true);
BatchLessThanEqualDecimal128(col1, 38, 4, col2, 38, 3, output, rowCnt);
EXPECT_EQ(output[0], false);
EXPECT_EQ(output[1], true);
BatchGreaterThanDecimal128(col1, 38, 6, col2, 38, 2, output, rowCnt);
EXPECT_EQ(output[0], true);
EXPECT_EQ(output[1], false);
BatchGreaterThanEqualDecimal128(col1, 38, 2, col2, 38, 4, output, rowCnt);
EXPECT_EQ(output[0], true);
EXPECT_EQ(output[1], true);
BatchEqualDecimal128(col1, 38, 2, col2, 38, 2, output, rowCnt);
EXPECT_EQ(output[0], false);
EXPECT_EQ(output[1], false);
BatchNotEqualDecimal128(col1, 38, 2, col2, 38, 2, output, rowCnt);
EXPECT_EQ(output[0], true);
EXPECT_EQ(output[1], true);
}
TEST(BatchFunctionTest, CastDecimalToDecimal)
{
int32_t rowCnt = 2;
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
int64_t decimal64Val[2] = { 1234567L, INT64_MAX };
Decimal128 decimal128Val[2];
decimal128Val[0].SetValue(0, 1234567);
decimal128Val[1].SetValue(~0, -123456);
bool isAnyNull[2] = { false, false };
bool overflowNull[2] = { false, false };
int64_t output64[2];
Decimal128 output128[2];
BatchCastDecimal64To64(contextPtr, decimal64Val, 7, 2, isAnyNull, output64, 10, 3, rowCnt);
EXPECT_EQ(output64[0], 12345670L);
EXPECT_TRUE(context->HasError());
BatchCastDecimal64To64RetNull(overflowNull, decimal64Val, 7, 2, output64, 10, 3, rowCnt);
EXPECT_EQ(output64[0], 12345670L);
EXPECT_FALSE(overflowNull[0]);
EXPECT_TRUE(overflowNull[1]);
BatchCastDecimal128To128(contextPtr, decimal128Val, 20, 10, isAnyNull, output128, 38, 18, rowCnt);
EXPECT_EQ(output128[0].HighBits(), 0);
EXPECT_EQ(output128[0].LowBits(), 123456700000000L);
EXPECT_EQ(output128[1].HighBits(), ~0);
EXPECT_EQ(output128[1].LowBits(), -12345600000000L);
overflowNull[0] = false;
overflowNull[1] = false;
BatchCastDecimal128To128RetNull(overflowNull, decimal128Val, 20, 10, output128, 38, 18, rowCnt);
EXPECT_FALSE(overflowNull[0]);
EXPECT_FALSE(overflowNull[1]);
BatchCastDecimal64To128(contextPtr, decimal64Val, 18, 18, isAnyNull, output128, 38, 20, rowCnt);
EXPECT_EQ(output128[0].HighBits(), 0);
EXPECT_EQ(output128[0].LowBits(), 123456700L);
EXPECT_EQ(output128[1].HighBits(), 49);
EXPECT_EQ(output128[1].LowBits(), 18446744073709551516UL);
BatchCastDecimal64To128RetNull(overflowNull, decimal64Val, 18, 18, output128, 38, 15, rowCnt);
EXPECT_EQ(output128[0].HighBits(), 0);
EXPECT_EQ(output128[0].LowBits(), 1235);
EXPECT_EQ(output128[1].HighBits(), 0);
EXPECT_EQ(output128[1].LowBits(), std::round(INT64_MAX / 1000));
BatchCastDecimal128To64(contextPtr, decimal128Val, 38, 10, isAnyNull, output64, 18, 9, rowCnt);
EXPECT_EQ(output64[0], 123457);
EXPECT_EQ(output64[1], -12346);
overflowNull[0] = false;
overflowNull[1] = false;
BatchCastDecimal128To64RetNull(overflowNull, decimal128Val, 38, 3, output64, 5, 2, rowCnt);
EXPECT_TRUE(overflowNull[0]);
EXPECT_EQ(output64[1], -12346);
delete context;
}
TEST(BatchFunctionTest, CastBasicTypeToDecimal)
{
int32_t rowCnt = 1;
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
int32_t intVal[1] = { 1234567 };
int64_t longVal[1] = { INT32_MAX };
double doubleVal[1] = { 99999999.99 };
bool isAnyNull[1] = { false };
bool overflowNull[1] = { false };
int64_t output64[1];
Decimal128 output128[1];
BatchCastIntToDecimal64(contextPtr, intVal, isAnyNull, output64, 9, 2, rowCnt);
EXPECT_EQ(output64[0], 123456700);
BatchCastIntToDecimal128(contextPtr, intVal, isAnyNull, output128, 38, 9, rowCnt);
EXPECT_EQ(output128[0].HighBits(), 0);
EXPECT_EQ(output128[0].LowBits(), 1'234'567'000'000'000);
BatchCastIntToDecimal64RetNull(overflowNull, intVal, output64, 6, 0, rowCnt);
EXPECT_TRUE(overflowNull[0]);
overflowNull[0] = false;
BatchCastIntToDecimal128RetNull(overflowNull, intVal, output128, 18, 12, rowCnt);
EXPECT_TRUE(overflowNull[0]);
overflowNull[0] = false;
BatchCastLongToDecimal64(contextPtr, longVal, isAnyNull, output64, 13, 2, rowCnt);
EXPECT_EQ(output64[0], INT_MAX * 100L);
BatchCastLongToDecimal128(contextPtr, longVal, isAnyNull, output128, 38, 5, rowCnt);
EXPECT_EQ(output128[0].HighBits(), 0);
EXPECT_EQ(output128[0].LowBits(), INT_MAX * 100'000L);
BatchCastLongToDecimal64RetNull(overflowNull, longVal, output64, 9, 0, rowCnt);
EXPECT_TRUE(overflowNull[0]);
BatchCastLongToDecimal128RetNull(overflowNull, longVal, output128, 38, 6, rowCnt);
EXPECT_EQ(output128[0].HighBits(), 0);
EXPECT_EQ(output128[0].LowBits(), INT_MAX * 1000'000L);
overflowNull[0] = false;
BatchCastDoubleToDecimal64(contextPtr, doubleVal, isAnyNull, output64, 13, 2, rowCnt);
EXPECT_EQ(output64[0], 9'999'999'999L);
BatchCastDoubleToDecimal128(contextPtr, doubleVal, isAnyNull, output128, 38, 5, rowCnt);
EXPECT_EQ(output128[0].HighBits(), 0);
EXPECT_EQ(output128[0].LowBits(), 9'999'999'999L * 1000L);
BatchCastDoubleToDecimal64RetNull(overflowNull, doubleVal, output64, 12, 0, rowCnt);
EXPECT_EQ(output64[0], 100'000'000L);
BatchCastDoubleToDecimal128RetNull(overflowNull, doubleVal, output128, 19, 18, rowCnt);
EXPECT_TRUE(overflowNull[0]);
delete context;
}
TEST(BatchFunctionTest, CastDecimalToBasicType)
{
int32_t rowCnt = 1;
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
int64_t decimal64Val[1] = { 1234567 };
Decimal128 decimal128Val[1];
decimal128Val[0].SetValue(0, INT64_MAX);
int32_t outputInt[1];
int64_t outputLong[1];
double outputDouble[1];
bool isAnyNull[1] = { false };
bool overflowNull[1] = { false };
BatchCastDecimal64ToIntHalfUp(contextPtr, decimal64Val, 7, 2, isAnyNull, outputInt, rowCnt);
EXPECT_EQ(outputInt[0], 12346);
BatchCastDecimal64ToLongHalfUp(decimal64Val, 7, 2, isAnyNull, outputLong, rowCnt);
EXPECT_EQ(outputLong[0], 12346L);
BatchCastDecimal64ToDoubleHalfUp(decimal64Val, 7, 2, isAnyNull, outputDouble, rowCnt);
EXPECT_EQ(outputDouble[0], 12345.67);
BatchCastDecimal128ToInt(contextPtr, decimal128Val, 19, 2, isAnyNull, outputInt, rowCnt);
EXPECT_TRUE(context->HasError());
BatchCastDecimal128ToLong(contextPtr, decimal128Val, 19, 2, isAnyNull, outputLong, rowCnt);
EXPECT_EQ(outputLong[0], INT64_MAX / 100L);
BatchCastDecimal128ToDoubleHalfUp(decimal128Val, 19, 2, isAnyNull, outputDouble, rowCnt);
EXPECT_EQ(outputDouble[0], INT64_MAX / (double)100);
BatchCastDecimal64ToIntRetNull(overflowNull, decimal64Val, 7, 2, outputInt, rowCnt);
EXPECT_EQ(outputInt[0], 12345);
BatchCastDecimal64ToLongRetNull(overflowNull, decimal64Val, 7, 2, outputLong, rowCnt);
EXPECT_EQ(outputLong[0], 12345L);
BatchCastDecimal64ToDoubleRetNull(overflowNull, decimal64Val, 7, 2, outputDouble, rowCnt);
EXPECT_EQ(outputDouble[0], 12345.67);
BatchCastDecimal128ToIntRetNull(overflowNull, decimal128Val, 7, 2, outputInt, rowCnt);
EXPECT_EQ(outputInt[0], static_cast<int32_t>(INT64_MAX / 100L));
BatchCastDecimal128ToLongRetNull(overflowNull, decimal128Val, 7, 2, outputLong, rowCnt);
EXPECT_EQ(outputLong[0], INT64_MAX / 100L);
BatchCastDecimal128ToDoubleRetNull(overflowNull, decimal128Val, 7, 2, outputDouble, rowCnt);
EXPECT_EQ(outputDouble[0], INT64_MAX / (double)100);
delete context;
}
TEST(BatchFunctionTest, MakeDecimal)
{
int32_t rowCnt = 1;
auto context = new ExecutionContext();
int64_t contextPtr = reinterpret_cast<int64_t>(context);
int64_t col[1] = { 12345678L };
int64_t output[1];
bool isAnyNull[1] = { false };
bool overflowNull[1] = { false };
BatchUnscaledValue64(col, 7, 2, isAnyNull, output, rowCnt);
EXPECT_EQ(output[0], 12345678L);
BatchMakeDecimal64(contextPtr, col, isAnyNull, output, 7, 2, rowCnt);
EXPECT_TRUE(context->HasError());
BatchMakeDecimal64RetNull(overflowNull, col, output, 7, 2, rowCnt);
EXPECT_TRUE(overflowNull[0]);
delete context;
}
TEST(BatchFunctionTest, RoundDecimal)
{
int32_t rowCnt = 2;
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
bool isNull[2] = {false, true};
int32_t round[2] = {0, 0};
Decimal128 output128[2];
int64_t output64[2];
Decimal128 decimal128Val1[2];
decimal128Val1[0] = Decimal128("22167875302138684366688952930001319804");
decimal128Val1[1] = Decimal128("151949737170315874258868924986217725952");
BatchRoundDecimal128(contextPtr, decimal128Val1, 38, 18, round, isNull, output128, 21, 0, rowCnt);
EXPECT_EQ(output128[0].HighBits(), 1);
EXPECT_EQ(output128[0].LowBits(), 3721131228429132751L);
EXPECT_EQ(output128[1].HighBits(), 0);
EXPECT_EQ(output128[1].LowBits(), 0);
Decimal128 decimal128Val2[2];
decimal128Val2[0] = Decimal128("22167875302138684366688952930001319804");
decimal128Val2[1] = Decimal128("151949737170315874258868924986217725952");
BatchRoundDecimal128WithoutRound(contextPtr, decimal128Val2, 38, 18, isNull, output128, 21, 0, rowCnt);
EXPECT_EQ(output128[0].HighBits(), 1);
EXPECT_EQ(output128[0].LowBits(), 3721131228429132751L);
EXPECT_EQ(output128[1].HighBits(), 0);
EXPECT_EQ(output128[1].LowBits(), 0);
int64_t decimal64Val1[2] = { 463127424592162661L, 63636006298474304L};
output64[1] = 0;
BatchRoundDecimal64(contextPtr, decimal64Val1, 18, 8, round, isNull, output64, 11, 0, rowCnt);
EXPECT_EQ(output64[0], 4631274246L);
EXPECT_EQ(output64[1], 0);
int64_t decimal64Val2[2] = { 463127424592162661L, 63636006298474304L};
BatchRoundDecimal64WithoutRound(contextPtr, decimal64Val2, 18, 8, isNull, output64, 11, 0, rowCnt);
EXPECT_EQ(output64[0], 4631274246L);
EXPECT_EQ(output64[1], 0);
delete context;
}
TEST(BatchFunctionTest, DecimalAdd)
{
int32_t rowCnt = 2;
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
bool isAnyNull[2] = { false, false };
Decimal128 output128[2];
int64_t decimal64Val1[2] = { 1234567, 98765 };
int64_t decimal64Val2[2] = { 9999999, -1111111 };
BatchAddDec64Dec64Dec64ReScale(contextPtr, isAnyNull, decimal64Val1, 7, 2, decimal64Val2, 7, 2, 9, 2, rowCnt);
EXPECT_EQ(decimal64Val1[0], 11234566);
EXPECT_EQ(decimal64Val1[1], -1012346);
BatchAddDec64Dec64Dec128ReScale(contextPtr, isAnyNull, decimal64Val1, 9, 2, decimal64Val2, 7, 2, output128, 19, 9,
rowCnt);
EXPECT_EQ(output128[0].HighBits(), 0);
EXPECT_EQ(output128[0].LowBits(), 212345650000000);
EXPECT_EQ(output128[1].HighBits(), ~0);
EXPECT_EQ(output128[1].LowBits(), -21234570000000);
Decimal128 decimal128Val1[2];
decimal128Val1[0].SetValue(0, INT64_MAX);
decimal128Val1[1].SetValue(0, 99'999'999'999'999'999UL);
Decimal128 decimal128Val2[2];
decimal128Val2[0].SetValue(0, 123456789);
decimal128Val2[1].SetValue(~0, -987654321);
BatchAddDec128Dec128Dec128ReScale(contextPtr, isAnyNull, decimal128Val1, 19, 9, decimal128Val2, 19, 9, 38, 9,
rowCnt);
EXPECT_EQ(decimal128Val1[0].HighBits(), 0);
EXPECT_EQ(decimal128Val1[0].LowBits(), 9'223'372'036'978'232'596UL);
EXPECT_EQ(decimal128Val1[1].HighBits(), 0);
EXPECT_EQ(decimal128Val1[1].LowBits(), 99'999'999'012'345'678UL);
BatchAddDec64Dec128Dec128ReScale(contextPtr, isAnyNull, decimal64Val1, 8, 2, decimal128Val1, 38, 9, 38, 9, rowCnt);
EXPECT_EQ(decimal128Val1[0].HighBits(), 0);
EXPECT_EQ(decimal128Val1[0].LowBits(), 9'223'484'382'638'232'596UL);
EXPECT_EQ(decimal128Val1[1].HighBits(), 0);
EXPECT_EQ(decimal128Val1[1].LowBits(), 99'989'875'552'345'678UL);
decimal64Val1[0] = 823'484'382'638'232'596L;
BatchAddDec128Dec64Dec128ReScale(contextPtr, isAnyNull, decimal128Val1, 19, 9, decimal64Val1, 18, 9, 19, 19,
rowCnt);
EXPECT_TRUE(context->HasError());
delete context;
}
TEST(BatchFunctionTest, DecimalAddRetNull)
{
int32_t rowCnt = 2;
bool overflowNull[2] = { false };
Decimal128 output128[2];
int64_t decimal64Val1[2] = { 1234567, 98765 };
int64_t decimal64Val2[2] = { 9999999, -1111111 };
BatchAddDec64Dec64Dec64RetNull(overflowNull, decimal64Val1, 7, 2, decimal64Val2, 7, 2, 9, 2, rowCnt);
EXPECT_FALSE(overflowNull[0]);
EXPECT_EQ(decimal64Val1[0], 11234566);
EXPECT_FALSE(overflowNull[1]);
EXPECT_EQ(decimal64Val1[1], -1012346);
BatchAddDec64Dec64Dec128RetNull(overflowNull, decimal64Val1, 8, 2, decimal64Val2, 7, 2, output128, 19, 9, rowCnt);
EXPECT_FALSE(overflowNull[0]);
EXPECT_EQ(output128[0].HighBits(), 0);
EXPECT_EQ(output128[0].LowBits(), 212345650000000);
EXPECT_FALSE(overflowNull[1]);
EXPECT_EQ(output128[1].HighBits(), ~0);
EXPECT_EQ(output128[1].LowBits(), -21234570000000);
Decimal128 decimal128Val1[2];
decimal128Val1[0] = Decimal128("-9223372036854775807");
decimal128Val1[1] = Decimal128("99999999999999999");
Decimal128 decimal128Val2[2];
decimal128Val2[0] = Decimal128("123456789");
decimal128Val2[1] = Decimal128("-987654321");
BatchAddDec128Dec128Dec128RetNull(overflowNull, decimal128Val1, 19, 9, decimal128Val2, 19, 9, 38, 19, rowCnt);
EXPECT_FALSE(overflowNull[0]);
EXPECT_EQ(decimal128Val1[0], Decimal128("-92233720367313190180000000000"));
EXPECT_FALSE(overflowNull[1]);
EXPECT_EQ(decimal128Val1[1], Decimal128("999999990123456780000000000"));
BatchAddDec64Dec128Dec128RetNull(overflowNull, decimal64Val1, 9, 2, decimal128Val1, 30, 19, 30, 21, rowCnt);
EXPECT_TRUE(overflowNull[0]);
EXPECT_FALSE(overflowNull[1]);
EXPECT_EQ(decimal128Val1[1].HighBits(), 0x1'4315'AFBF);
EXPECT_EQ(decimal128Val1[1].LowBits(), 0x53A'4894'CE2A'E000);
decimal64Val1[0] = 823'484'382'638'232'596L;
decimal64Val1[1] = 999'999'999'999'999'999L;
decimal128Val1[0].SetValue(0, 9'223'484'382'638'232'596UL);
BatchAddDec128Dec64Dec128RetNull(overflowNull, decimal128Val1, 19, 9, decimal64Val1, 18, 9, 19, 19, rowCnt);
EXPECT_TRUE(overflowNull[0]);
EXPECT_TRUE(overflowNull[1]);
}
TEST(BatchFunctionTest, DecimalSubtract)
{
int32_t rowCnt = 2;
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
bool isAnyNull[2] = { false, false };
Decimal128 output128[2];
int64_t decimal64Val1[2] = { 1234567, -34567 };
int64_t decimal64Val2[2] = { 9999999, 1111111 };
BatchSubDec64Dec64Dec64ReScale(contextPtr, isAnyNull, decimal64Val1, 7, 2, decimal64Val2, 7, 2, 9, 2, rowCnt);
EXPECT_EQ(decimal64Val1[0], -8765432);
EXPECT_EQ(decimal64Val1[1], -1145678);
BatchSubDec64Dec64Dec128ReScale(contextPtr, isAnyNull, decimal64Val1, 9, 2, decimal64Val2, 7, 2, output128, 19, 9,
rowCnt);
EXPECT_EQ(output128[0].HighBits(), ~0);
EXPECT_EQ(output128[0].LowBits(), -187'654'310'000'000L);
EXPECT_EQ(output128[1].HighBits(), ~0);
EXPECT_EQ(output128[1].LowBits(), -0x1486'7F11'1880);
Decimal128 decimal128Val1[2];
decimal128Val1[0].SetValue(0, INT64_MAX);
decimal128Val1[1].SetValue(1234, 9'999'000'000);
Decimal128 decimal128Val2[2];
decimal128Val2[0].SetValue(0, 100'000);
decimal128Val2[1].SetValue(~1234, -987654321);
BatchSubDec128Dec128Dec128ReScale(contextPtr, isAnyNull, decimal128Val1, 19, 9, decimal128Val2, 30, 9, 38, 9,
rowCnt);
EXPECT_EQ(decimal128Val1[0].HighBits(), 0);
EXPECT_EQ(decimal128Val1[0].LowBits(), INT64_MAX - 100'000);
EXPECT_EQ(decimal128Val1[1].HighBits(), 0x9A4);
EXPECT_EQ(decimal128Val1[1].LowBits(), 0x0000'0002'8EDB'0A71);
BatchSubDec64Dec128Dec128ReScale(contextPtr, isAnyNull, decimal64Val1, 18, 9, decimal128Val1, 38, 9, 19, 12,
rowCnt);
EXPECT_TRUE(context->HasError());
context->ResetError();
decimal64Val1[0] = 823'484'382'638'232'596L;
decimal128Val1[0].SetValue(~0, -INT64_MAX);
BatchSubDec128Dec64Dec128ReScale(contextPtr, isAnyNull, decimal128Val1, 19, 9, decimal64Val1, 18, 9, 19, 19,
rowCnt);
EXPECT_TRUE(context->HasError());
delete context;
}
TEST(BatchFunctionTest, DecimalSubtractRetNull)
{
int32_t rowCnt = 2;
bool overflowNull[2] = { false, false };
Decimal128 output128[2];
int64_t decimal64Val1[2] = { 1234567, -34567 };
int64_t decimal64Val2[2] = { 9999999, 1111111 };
BatchSubDec64Dec64Dec64RetNull(overflowNull, decimal64Val1, 7, 2, decimal64Val2, 7, 2, 9, 2, rowCnt);
EXPECT_FALSE(overflowNull[0]);
EXPECT_EQ(decimal64Val1[0], -8765432);
EXPECT_FALSE(overflowNull[1]);
EXPECT_EQ(decimal64Val1[1], -1145678);
BatchSubDec64Dec64Dec128RetNull(overflowNull, decimal64Val1, 8, 2, decimal64Val2, 7, 2, output128, 19, 9, rowCnt);
EXPECT_FALSE(overflowNull[0]);
EXPECT_EQ(output128[0].HighBits(), ~0);
EXPECT_EQ(output128[0].LowBits(), -187'654'310'000'000UL);
EXPECT_FALSE(overflowNull[1]);
EXPECT_EQ(output128[1].HighBits(), ~0);
EXPECT_EQ(output128[1].LowBits(), -0x1486'7F11'1880);
Decimal128 decimal128Val1[2];
decimal128Val1[0].SetValue(~0, -INT64_MAX);
decimal128Val1[1].SetValue(~0, -1);
Decimal128 decimal128Val2[2];
decimal128Val2[0].SetValue(0, 100'000);
decimal128Val2[1].SetValue(~1234, -100'000);
BatchSubDec128Dec128Dec128RetNull(overflowNull, decimal128Val1, 19, 9, decimal128Val2, 19, 9, 38, 9, rowCnt);
EXPECT_FALSE(overflowNull[0]);
EXPECT_EQ(decimal128Val1[0].HighBits(), ~0);
EXPECT_EQ(decimal128Val1[0].LowBits(), -9223372036854775807UL - 100'000UL);
EXPECT_FALSE(overflowNull[1]);
EXPECT_EQ(decimal128Val1[1].HighBits(), 1234);
EXPECT_EQ(decimal128Val1[1].LowBits(), 99999);
BatchSubDec64Dec128Dec128RetNull(overflowNull, decimal64Val1, 9, 2, decimal128Val1, 38, 9, 19, 12, rowCnt);
EXPECT_TRUE(overflowNull[0]);
EXPECT_TRUE(overflowNull[1]);
decimal64Val1[0] = 823'484'382'638'232'596L;
decimal64Val1[1] = 823'484'382'638'232'596L;
decimal128Val1[0].SetValue(0, 9'223'484'382'638'232'596UL);
BatchSubDec128Dec64Dec128RetNull(overflowNull, decimal128Val1, 19, 9, decimal64Val1, 18, 9, 19, 19, rowCnt);
EXPECT_TRUE(overflowNull[0]);
EXPECT_TRUE(overflowNull[1]);
}
TEST(BatchFunctionTest, DecimalMultiply)
{
int32_t rowCnt = 2;
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
bool isAnyNull[2] = { false, false };
Decimal128 output128[2];
int64_t decimal64Val1[2] = { 1234567, -987654 };
int64_t decimal64Val2[2] = { 9999999, 1010101 };
BatchMulDec64Dec64Dec64ReScale(contextPtr, isAnyNull, decimal64Val1, 7, 2, decimal64Val2, 7, 2, 14, 2, rowCnt);
EXPECT_EQ(decimal64Val1[0], 123'456'687'654L);
EXPECT_EQ(decimal64Val1[1], -9'976'302'931L);
BatchMulDec64Dec64Dec128ReScale(contextPtr, isAnyNull, decimal64Val1, 12, 2, decimal64Val2, 7, 2, output128, 19, 4,
rowCnt);
EXPECT_EQ(output128[0].HighBits(), 0);
EXPECT_EQ(output128[0].LowBits(), 123'456'687'654L * 9999999L);
EXPECT_EQ(output128[1].HighBits(), ~0);
EXPECT_EQ(output128[1].LowBits(), -9'976'302'931L * 1010101);
Decimal128 decimal128Val1[2];
decimal128Val1[0].SetValue(0, 123456);
decimal128Val1[1].SetValue(~0, -999999);
Decimal128 decimal128Val2[2];
decimal128Val2[0].SetValue(0, 10000L);
decimal128Val2[1].SetValue(0, 314159L);
BatchMulDec128Dec128Dec128ReScale(contextPtr, isAnyNull, decimal128Val1, 20, 9, decimal128Val2, 19, 0, 38, 9,
rowCnt);
EXPECT_EQ(decimal128Val1[0].HighBits(), 0);
EXPECT_EQ(decimal128Val1[0].LowBits(), 1234560000);
EXPECT_EQ(decimal128Val1[1].HighBits(), ~0);
EXPECT_EQ(decimal128Val1[1].LowBits(), -314158685841);
decimal128Val1[0].SetValue(INT64_MAX, INT64_MAX);
BatchMulDec64Dec128Dec128ReScale(contextPtr, isAnyNull, decimal64Val1, 8, 2, decimal128Val1, 38, 9, 38, 9, rowCnt);
EXPECT_TRUE(context->HasError());
context->ResetError();
decimal64Val1[0] = 123456789;
decimal64Val1[1] = 314159;
decimal128Val1[0].SetValue(0, 823'484'382'638'232'596UL);
decimal128Val1[1].SetValue(~123, -1);
BatchMulDec128Dec64Dec128ReScale(contextPtr, isAnyNull, decimal128Val1, 19, 9, decimal64Val1, 18, 9, 38, 18,
rowCnt);
EXPECT_EQ(decimal128Val1[0].HighBits(), 0x541858);
EXPECT_EQ(decimal128Val1[0].LowBits(), 0x78F3'8F5D'A9D8'69A4);
EXPECT_EQ(decimal128Val1[1].HighBits(), ~0x24D'9F95);
EXPECT_EQ(decimal128Val1[1].LowBits(), -0x4'CB2F);
delete context;
}
TEST(BatchFunctionTest, DecimalMultiplyRetNull)
{
int32_t rowCnt = 2;
bool overflowNull[2] = { false, false };
Decimal128 output128[2];
int64_t decimal64Val1[2] = { -1234567, -314159 };
int64_t decimal64Val2[2] = { 9999999, 65432 };
BatchMulDec64Dec64Dec64RetNull(overflowNull, decimal64Val1, 7, 2, decimal64Val2, 7, 2, 14, 2, rowCnt);
EXPECT_FALSE(overflowNull[0]);
EXPECT_EQ(decimal64Val1[0], -123'456'687'654L);
EXPECT_FALSE(overflowNull[1]);
EXPECT_EQ(decimal64Val1[1], -205'560'517L);
BatchMulDec64Dec64Dec128RetNull(overflowNull, decimal64Val1, 12, 2, decimal64Val2, 7, 2, output128, 19, 4, rowCnt);
EXPECT_FALSE(overflowNull[0]);
EXPECT_EQ(output128[0].HighBits(), ~0);
EXPECT_EQ(output128[0].LowBits(), -123'456'687'654L * 9999999);
EXPECT_FALSE(overflowNull[1]);
EXPECT_EQ(output128[1].HighBits(), ~0);
EXPECT_EQ(output128[1].LowBits(), -13'450'235'748'344);
Decimal128 decimal128Val1[2];
decimal128Val1[0].SetValue(0, INT64_MAX);
decimal128Val1[1].SetValue(~1, -9999999);
Decimal128 decimal128Val2[2];
decimal128Val2[0].SetValue(0, 100);
decimal128Val2[1].SetValue(0, 31415926);
BatchMulDec128Dec128Dec128RetNull(overflowNull, decimal128Val1, 19, 9, decimal128Val2, 19, 0, 38, 9, rowCnt);
EXPECT_FALSE(overflowNull[0]);
EXPECT_EQ(decimal128Val1[0].HighBits(), 49);
EXPECT_EQ(decimal128Val1[0].LowBits(), 0xFFFFFFFFFFFFFF9C);
EXPECT_FALSE(overflowNull[1]);
EXPECT_EQ(decimal128Val1[1].HighBits(), ~0x1DF'5E76);
EXPECT_EQ(decimal128Val1[1].LowBits(), -0x0001'1DB9'E539'008A);
BatchMulDec64Dec128Dec128RetNull(overflowNull, decimal64Val1, 9, 2, decimal128Val1, 38, 9, 19, 12, rowCnt);
EXPECT_TRUE(overflowNull[0]);
EXPECT_TRUE(overflowNull[1]);
decimal64Val1[0] = 823'484'382'638'232'596L;
decimal128Val1[0].SetValue(0, 9'223'484'382'638'232'596UL);
BatchMulDec128Dec64Dec128RetNull(overflowNull, decimal128Val1, 19, 9, decimal64Val1, 18, 9, 19, 19, rowCnt);
EXPECT_TRUE(overflowNull[0]);
EXPECT_TRUE(overflowNull[1]);
}
TEST(BatchFunctionTest, DecimalDivide)
{
int32_t rowCnt = 2;
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
bool isAnyNull[2] = { false, false };
Decimal128 output128[2];
int64_t decimal64Val1[2] = { -1234567, 9999999 };
int64_t decimal64Val2[2] = { 100000, 33333 };
BatchDivDec64Dec64Dec64ReScale(contextPtr, isAnyNull, decimal64Val1, 7, 2, decimal64Val2, 7, 2, 14, 2, rowCnt);
EXPECT_EQ(decimal64Val1[0], -1235);
EXPECT_EQ(decimal64Val1[1], 30000);
Decimal128 decimal128Val1[2];
decimal128Val1[0].SetValue(0, 100000);
decimal128Val1[1].SetValue(~0, -999);
BatchDivDec64Dec128Dec64ReScale(contextPtr, isAnyNull, decimal64Val1, 7, 2, decimal128Val1, 19, 2, 14, 2, rowCnt);
EXPECT_EQ(decimal64Val1[0], -1);
EXPECT_EQ(decimal64Val1[1], -3003);
decimal128Val1[0].SetValue(~0, -INT64_MAX);
decimal128Val1[1].SetValue(0, 1234567890);
BatchDivDec128Dec64Dec64ReScale(contextPtr, isAnyNull, decimal128Val1, 20, 6, decimal64Val2, 7, 2, 18, 8, rowCnt);
EXPECT_EQ(decimal64Val2[0], -922337203685477581);
EXPECT_EQ(decimal64Val2[1], 370374071);
BatchDivDec64Dec64Dec128ReScale(contextPtr, isAnyNull, decimal64Val1, 7, 2, decimal64Val2, 18, 8, output128, 20, 2,
rowCnt);
EXPECT_EQ(output128[0].HighBits(), 0);
EXPECT_EQ(output128[0].LowBits(), 0);
EXPECT_EQ(output128[1].HighBits(), ~0);
EXPECT_EQ(output128[1].LowBits(), -811);
Decimal128 decimal128Val2[2];
decimal128Val2[0].SetValue(0, 1);
decimal128Val2[1].SetValue(123, 456);
BatchDivDec128Dec128Dec128ReScale(contextPtr, isAnyNull, decimal128Val1, 19, 2, decimal128Val2, 19, 2, 38, 6,
rowCnt);
EXPECT_EQ(decimal128Val1[0].HighBits(), ~0x7A11F);
EXPECT_EQ(decimal128Val1[0].LowBits(), -0xFFFF'FFFF'FFF0'BDC0);
EXPECT_EQ(decimal128Val1[1].HighBits(), 0);
EXPECT_EQ(decimal128Val1[1].LowBits(), 0);
decimal128Val1[0].SetValue(0, 1111111);
decimal128Val1[1].SetValue(0, 31415);
BatchDivDec64Dec128Dec128ReScale(contextPtr, isAnyNull, decimal64Val2, 18, 2, decimal128Val1, 19, 2, 19, 6, rowCnt);
EXPECT_EQ(decimal128Val1[0].HighBits(), ~0);
EXPECT_EQ(decimal128Val1[0].LowBits(), -0x0B85'1ECB'A5B9'0AB8);
EXPECT_EQ(decimal128Val1[1].HighBits(), 0);
EXPECT_EQ(decimal128Val1[1].LowBits(), 11789720548);
decimal64Val1[0] = 0;
BatchDivDec128Dec64Dec128ReScale(contextPtr, isAnyNull, decimal128Val1, 38, 2, decimal64Val1, 7, 2, 38, 2, rowCnt);
EXPECT_TRUE(context->HasError());
delete context;
}
TEST(BatchFunctionTest, DecimalDivideRetNull)
{
int32_t rowCnt = 2;
bool overflowNull[2] = { false, false };
Decimal128 output128[2];
int64_t decimal64Val1[2] = { -9999999, 3141592 };
int64_t decimal64Val2[2] = { 1234567, 1010 };
BatchDivDec64Dec64Dec64RetNull(overflowNull, decimal64Val1, 7, 2, decimal64Val2, 7, 2, 14, 2, rowCnt);
EXPECT_FALSE(overflowNull[0]);
EXPECT_EQ(decimal64Val1[0], -810);
EXPECT_FALSE(overflowNull[1]);
EXPECT_EQ(decimal64Val1[1], 311049);
BatchDivDec64Dec64Dec128RetNull(overflowNull, decimal64Val1, 7, 0, decimal64Val2, 9, 6, output128, 19, 4, rowCnt);
EXPECT_FALSE(overflowNull[0]);
EXPECT_EQ(output128[0].HighBits(), ~0);
EXPECT_EQ(output128[0].LowBits(), -6561005);
EXPECT_FALSE(overflowNull[1]);
EXPECT_EQ(output128[1].HighBits(), 0);
EXPECT_EQ(output128[1].LowBits(), 3079693069307);
decimal64Val1[0] = 123456789999;
decimal64Val1[1] = 31415926;
Decimal128 decimal128Val1[2];
decimal128Val1[0].SetValue(0, 100000);
decimal128Val1[1].SetValue(~0, -54321);
BatchDivDec64Dec128Dec64RetNull(overflowNull, decimal64Val1, 12, 2, decimal128Val1, 38, 10, 16, 0, rowCnt);
EXPECT_FALSE(overflowNull[0]);
EXPECT_EQ(decimal64Val1[0], 123'456'789'999'000UL);
EXPECT_FALSE(overflowNull[1]);
EXPECT_EQ(decimal64Val1[1], -57'833'850'629UL);
BatchDivDec128Dec64Dec64RetNull(overflowNull, decimal128Val1, 38, 0, decimal64Val2, 7, 2, 17, 4, rowCnt);
EXPECT_FALSE(overflowNull[0]);
EXPECT_EQ(decimal64Val2[0], 81000);
EXPECT_FALSE(overflowNull[1]);
EXPECT_EQ(decimal64Val2[1], -53783168);
decimal128Val1[0].SetValue(1, UINT64_MAX);
decimal128Val1[1].SetValue(0, 31415666);
Decimal128 decimal128Val2[2];
decimal128Val2[0].SetValue(0, 1);
decimal128Val2[1].SetValue(~0, -31415);
BatchDivDec128Dec128Dec128RetNull(overflowNull, decimal128Val1, 38, 0, decimal128Val2, 38, 19, 38, 0, rowCnt);
EXPECT_TRUE(overflowNull[0]);
EXPECT_FALSE(overflowNull[1]);
EXPECT_EQ(decimal128Val1[1].HighBits(), ~0x21E);
EXPECT_EQ(decimal128Val1[1].LowBits(), -0x1CD1'F72F'613F'51F0);
overflowNull[0] = false;
overflowNull[1] = false;
decimal64Val1[0] = INT64_MAX;
decimal64Val1[1] = INT64_MAX;
BatchDivDec64Dec128Dec128RetNull(overflowNull, decimal64Val1, 18, 0, decimal128Val2, 38, 19, 38, 5, rowCnt);
EXPECT_TRUE(overflowNull[0]);
EXPECT_TRUE(overflowNull[1]);
overflowNull[0] = false;
overflowNull[1] = false;
decimal64Val1[0] = 823'484'382'638'232'596L;
decimal64Val1[1] = 100000L;
decimal128Val1[0].SetValue(INT64_MAX, 9'223'484'382'638'232'596UL);
decimal128Val1[1].SetValue(0, 31415926UL);
BatchDivDec128Dec64Dec128RetNull(overflowNull, decimal128Val1, 19, 9, decimal64Val1, 18, 9, 38, 19, rowCnt);
EXPECT_TRUE(overflowNull[0]);
EXPECT_FALSE(overflowNull[1]);
EXPECT_EQ(decimal128Val1[1].HighBits(), 0xAA);
EXPECT_EQ(decimal128Val1[1].LowBits(), 0x4E5B'00D4'3BD9'8000);
}
TEST(BatchFunctionTest, DecimalModulus)
{
int32_t rowCnt = 2;
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
bool isAnyNull[2] = { false, false };
int64_t output64[2];
int64_t decimal64Val1[2] = { -1234567, 3141592 };
int64_t decimal64Val2[2] = { 100000, 10101 };
BatchModDec64Dec64Dec64ReScale(contextPtr, isAnyNull, decimal64Val1, 7, 2, decimal64Val2, 7, 2, 14, 2, rowCnt);
EXPECT_EQ(decimal64Val1[0], -34567);
EXPECT_EQ(decimal64Val1[1], 181);
Decimal128 decimal128Val1[2];
decimal128Val1[0].SetValue(12, UINT64_MAX);
decimal128Val1[1].SetValue(0, 9'999'999'999);
Decimal128 decimal128Val2[2];
decimal128Val2[0].SetValue(0, 1111111);
decimal128Val2[1].SetValue(~0, -1111111);
BatchModDec128Dec128Dec128ReScale(contextPtr, isAnyNull, decimal128Val1, 19, 2, decimal128Val2, 19, 2, 38, 2,
rowCnt);
EXPECT_EQ(decimal128Val1[0].HighBits(), 0);
EXPECT_EQ(decimal128Val1[0].LowBits(), 531573);
EXPECT_EQ(decimal128Val1[1].HighBits(), 0);
EXPECT_EQ(decimal128Val1[1].LowBits(), 999);
BatchModDec64Dec128Dec64ReScale(contextPtr, isAnyNull, decimal64Val1, 7, 2, decimal128Val1, 19, 10, 14, 10, rowCnt);
EXPECT_EQ(decimal64Val1[0], -384925);
EXPECT_EQ(decimal64Val1[1], 118);
decimal128Val1[0].SetValue(0, 0);
BatchModDec64Dec128Dec128ReScale(contextPtr, isAnyNull, decimal64Val1, 18, 2, decimal128Val1, 38, 2, 38, 2, rowCnt);
EXPECT_TRUE(context->HasError());
decimal128Val1[0].SetValue(~0, -INT64_MAX);
decimal128Val1[1].SetValue(0, 31415927);
BatchModDec128Dec64Dec64ReScale(contextPtr, isAnyNull, decimal128Val1, 20, 6, decimal64Val2, 7, 2, 18, 6, rowCnt);
EXPECT_EQ(decimal64Val2[0], -854775807);
EXPECT_EQ(decimal64Val2[1], 31415927);
BatchModDec128Dec64Dec128ReScale(contextPtr, isAnyNull, decimal128Val1, 19, 2, decimal64Val2, 9, 2, 20, 2, rowCnt);
EXPECT_EQ(decimal128Val1[0].HighBits(), ~0);
EXPECT_EQ(decimal128Val1[0].LowBits(), -698836018);
EXPECT_EQ(decimal128Val1[1].HighBits(), 0);
EXPECT_EQ(decimal128Val1[1].LowBits(), 0);
BatchModDec128Dec128Dec64ReScale(contextPtr, isAnyNull, decimal128Val1, 19, 2, decimal128Val2, 19, 2, output64, 18,
2, rowCnt);
EXPECT_EQ(output64[0], -1058310);
EXPECT_EQ(output64[1], 0);
delete context;
}
TEST(BatchFunctionTest, DecimalModulusRetNull)
{
int32_t rowCnt = 2;
bool overflowNull[2] = { false, false };
int64_t output64[2];
int64_t decimal64Val1[2] = { -1234567, 3141592 };
int64_t decimal64Val2[2] = { 100000, 10101 };
BatchModDec64Dec64Dec64RetNull(overflowNull, decimal64Val1, 7, 2, decimal64Val2, 7, 2, 14, 2, rowCnt);
EXPECT_FALSE(overflowNull[0]);
EXPECT_EQ(decimal64Val1[0], -34567);
EXPECT_FALSE(overflowNull[1]);
EXPECT_EQ(decimal64Val1[1], 181);
Decimal128 decimal128Val1[2];
decimal128Val1[0].SetValue(12, UINT64_MAX);
decimal128Val1[1].SetValue(0, 9'999'999'999);
Decimal128 decimal128Val2[2];
decimal128Val2[0].SetValue(0, 1111111);
decimal128Val2[1].SetValue(~0, -1111111);
BatchModDec128Dec128Dec128RetNull(overflowNull, decimal128Val1, 19, 2, decimal128Val2, 19, 2, 38, 2, rowCnt);
EXPECT_FALSE(overflowNull[0]);
EXPECT_EQ(decimal128Val1[0].HighBits(), 0);
EXPECT_EQ(decimal128Val1[0].LowBits(), 531573);
EXPECT_FALSE(overflowNull[1]);
EXPECT_EQ(decimal128Val1[1].HighBits(), 0);
EXPECT_EQ(decimal128Val1[1].LowBits(), 999);
BatchModDec64Dec128Dec64RetNull(overflowNull, decimal64Val1, 7, 2, decimal128Val1, 19, 10, 14, 10, rowCnt);
EXPECT_FALSE(overflowNull[0]);
EXPECT_EQ(decimal64Val1[0], -384925);
EXPECT_FALSE(overflowNull[1]);
EXPECT_EQ(decimal64Val1[1], 118);
decimal128Val1[0].SetValue(0, 0);
BatchModDec64Dec128Dec128RetNull(overflowNull, decimal64Val1, 18, 2, decimal128Val1, 38, 2, 38, 2, rowCnt);
EXPECT_TRUE(overflowNull[0]);
overflowNull[0] = false;
overflowNull[1] = false;
decimal128Val1[0].SetValue(~0, -INT64_MAX);
decimal128Val1[1].SetValue(0, 31415927);
BatchModDec128Dec64Dec64RetNull(overflowNull, decimal128Val1, 20, 6, decimal64Val2, 7, 2, 18, 6, rowCnt);
EXPECT_FALSE(overflowNull[0]);
EXPECT_EQ(decimal64Val2[0], -854775807);
EXPECT_FALSE(overflowNull[1]);
EXPECT_EQ(decimal64Val2[1], 31415927);
BatchModDec128Dec64Dec128RetNull(overflowNull, decimal128Val1, 19, 2, decimal64Val2, 7, 2, 20, 2, rowCnt);
EXPECT_FALSE(overflowNull[0]);
EXPECT_EQ(decimal128Val1[0].HighBits(), ~0);
EXPECT_EQ(decimal128Val1[0].LowBits(), -698836018);
EXPECT_FALSE(overflowNull[1]);
EXPECT_EQ(decimal128Val1[1].HighBits(), 0);
EXPECT_EQ(decimal128Val1[1].LowBits(), 0);
BatchModDec128Dec128Dec64RetNull(overflowNull, decimal128Val1, 19, 2, decimal128Val2, 19, 2, output64, 18, 2,
rowCnt);
EXPECT_FALSE(overflowNull[0]);
EXPECT_EQ(output64[0], -1058310);
EXPECT_FALSE(overflowNull[1]);
EXPECT_EQ(output64[1], 0);
}
TEST(BatchFunctionTest, CountChar)
{
std::vector<std::string> inputStr {"hello", "aAaA", "abcd", "hello", ""};
std::vector<int32_t> inputLen {5, 4, 4, 5, 0};
std::vector<std::string> targetStr {"l", "a", "e", "", "a"};
int32_t rowCnt = inputStr.size();
int64_t output[rowCnt];
std::vector<uint8_t *> strAddr(rowCnt);
std::vector<uint8_t *> targetAddr(rowCnt);
int32_t targetWidth = 10;
std::vector<int32_t> targetLen(rowCnt);
for(int32_t i = 0; i < rowCnt; i++) {
strAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(inputStr[i].c_str()));
targetAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(targetStr[i].c_str()));
targetLen[i] = static_cast<int32_t>(targetStr[i].length());
}
bool isAnyNull[] = { false, false, false, false, false};
BatchCountChar(strAddr.data(), inputLen.data(), targetAddr.data(), targetWidth, targetLen.data(), isAnyNull, output, rowCnt);
std::vector<int32_t> result(output, output + rowCnt);
std::vector<int32_t> expected { 2, 2, 0, 0, 0 };
AssertIntEquals(expected, result);
}
TEST(BatchFunctionTest, SpiltIndex)
{
std::vector<const char *> inputStr {"Jack,John,Mary", "Jack,Johnny,Mary", "Jack,John,Mary", "Jack,John,Mary",
nullptr, "Jack,John,Mary", "Jack,John,MaryPaul,Nathan"};
std::vector<int32_t> inputLen {14, 16, 14, 14, 0, 14, 14};
std::vector<const char *> targetStr {",", ",", ",", ",", ",", nullptr, ","};
int32_t index[] = {2, 1, -1, 3, 1, 1, 2};
int32_t rowCnt = inputStr.size();
int32_t targetWidth = 1;
std::vector<int32_t> targetLen {1, 1, 1, 1, 1, 0, 1};
uint8_t* output[rowCnt];
int32_t outLen[rowCnt];
std::vector<uint8_t *> strAddr(rowCnt);
std::vector<uint8_t *> targetAddr(rowCnt);
for(int32_t i = 0; i < rowCnt; i++) {
strAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(inputStr[i]));
targetAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(targetStr[i]));
}
bool isAnyNull[] = { false, false, false, false, true, true, false};
BatchSplitIndex(strAddr.data(), inputLen.data(), targetAddr.data(), targetWidth, targetLen.data(),
index, isAnyNull, output, outLen, rowCnt);
EXPECT_EQ("Mary", std::string(reinterpret_cast<char *>(output[0]), outLen[0]));
EXPECT_EQ("Johnny", std::string(reinterpret_cast<char *>(output[1]), outLen[1]));
EXPECT_TRUE(output[2] == nullptr);
EXPECT_TRUE(output[3] == nullptr);
EXPECT_TRUE(output[4] == nullptr);
EXPECT_TRUE(output[5] == nullptr);
EXPECT_EQ("Mary", std::string(reinterpret_cast<char *>(output[6]), outLen[6]));
EXPECT_EQ(4, outLen[0]);
EXPECT_EQ(6, outLen[1]);
EXPECT_EQ(0, outLen[2]);
EXPECT_EQ(0, outLen[3]);
EXPECT_EQ(0, outLen[4]);
EXPECT_EQ(0, outLen[5]);
EXPECT_EQ(4, outLen[6]);
}
TEST(BatchFunctionTest, SubstrZh)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::string str = "时欧基乌斯侧后解 hello! 回复哦黑色的and magic粉色的圣诞袜";
auto strLen = static_cast<int32_t>(str.length());
std::vector<std::string> inputStr(8, str);
std::vector<int32_t> inputLen(8, strLen);
std::vector<int32_t> startIndexs { 1, 1, 10, -5, 0, 37, -38, -37 };
std::vector<int32_t> length { 37, 5, 10, 7, 0, strLen + 5, 10, 37 };
int32_t rowCnt = inputStr.size();
std::vector<int32_t> outLen(rowCnt);
std::vector<uint8_t *> outResult(rowCnt);
std::vector<uint8_t *> strAddr(rowCnt);
for (int32_t i = 0; i < rowCnt; i++) {
strAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(inputStr[i].c_str()));
}
bool isAnyNull[] = { false, false, false, false, false, false, false, false };
BatchSubstrVarchar<int32_t, false, false>(contextPtr, strAddr.data(), inputLen.data(), startIndexs.data(),
length.data(), isAnyNull, outResult.data(), outLen.data(), rowCnt);
std::vector<std::string> expected { str, "时欧基乌斯", "hello! 回复哦", "色的圣诞袜", "", "袜", "", str };
AssertStringEquals(expected, outResult, outLen);
delete context;
}
TEST(BatchFunctionTest, SubstrZhWhenStartIndexEqualsZero)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::string str = "时欧基乌斯侧后解 hello! 回复哦黑色的and magic粉色的圣诞袜";
auto strLen = static_cast<int32_t>(str.length());
std::vector<std::string> inputStr(8, str);
std::vector<int32_t> inputLen(8, strLen);
std::vector<int32_t> startIndexs { 0, 0, 0, 0, 0, 0, 0, 0 };
std::vector<int32_t> length { 37, 5, 10, 7, 0, strLen + 5, 10, 37 };
int32_t rowCnt = inputStr.size();
std::vector<int32_t> outLen(rowCnt);
std::vector<uint8_t *> outResult(rowCnt);
std::vector<uint8_t *> strAddr(rowCnt);
for (int32_t i = 0; i < rowCnt; i++) {
strAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(inputStr[i].c_str()));
}
bool isAnyNull[] = { false, false, false, false, false, false, false, false };
BatchSubstrVarchar<int32_t, false, false>(contextPtr, strAddr.data(), inputLen.data(), startIndexs.data(),
length.data(), isAnyNull, outResult.data(), outLen.data(), rowCnt);
std::vector<std::string> expected { "", "", "", "", "", "", "", "" };
AssertStringEquals(expected, outResult, outLen);
delete context;
}
TEST(BatchFunctionTest, SubstrCharZh)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::string str = "时欧基乌斯侧后解 hello! 回复哦黑色的and magic粉色的圣诞袜";
int32_t width = 37;
int32_t strLen = str.length();
std::vector<std::string> inputStr(8, str);
std::vector<int32_t> inputLen(8, strLen);
std::vector<int32_t> startIndexs { 1, 1, 10, -5, 0, 37, -38, -37 };
std::vector<int32_t> length { 37, 5, 10, 7, 0, strLen + 5, 10, 37 };
int32_t rowCnt = inputStr.size();
std::vector<int32_t> outLen(rowCnt);
std::vector<uint8_t *> outResult(rowCnt);
std::vector<uint8_t *> strAddr(rowCnt);
for (int32_t i = 0; i < rowCnt; i++) {
strAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(inputStr[i].c_str()));
}
bool isAnyNull[] = { false, false, false, false, false, false, false, false };
BatchSubstrChar<int32_t, false, false>(contextPtr, strAddr.data(), width, inputLen.data(), startIndexs.data(),
length.data(), isAnyNull, outResult.data(), outLen.data(), rowCnt);
std::vector<std::string> expected { str, "时欧基乌斯", "hello! 回复哦", "色的圣诞袜", "", "袜", "", str };
AssertStringEquals(expected, outResult, outLen);
delete context;
}
TEST(BatchFunctionTest, SubstrCharZhWhenStartIndexEqualsZero)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::string str = "时欧基乌斯侧后解 hello! 回复哦黑色的and magic粉色的圣诞袜";
int32_t width = 37;
int32_t strLen = str.length();
std::vector<std::string> inputStr(8, str);
std::vector<int32_t> inputLen(8, strLen);
std::vector<int32_t> startIndexs { 0, 0, 0, 0, 0, 0, 0, 0 };
std::vector<int32_t> length { 37, 5, 10, 7, 0, strLen + 5, 10, 37 };
int32_t rowCnt = inputStr.size();
std::vector<int32_t> outLen(rowCnt);
std::vector<uint8_t *> outResult(rowCnt);
std::vector<uint8_t *> strAddr(rowCnt);
for (int32_t i = 0; i < rowCnt; i++) {
strAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(inputStr[i].c_str()));
}
bool isAnyNull[] = { false, false, false, false, false, false, false, false };
BatchSubstrChar<int32_t, false, false>(contextPtr, strAddr.data(), width, inputLen.data(), startIndexs.data(),
length.data(), isAnyNull, outResult.data(), outLen.data(), rowCnt);
std::vector<std::string> expected { "", "", "", "", "", "", "", "" };
AssertStringEquals(expected, outResult, outLen);
delete context;
}
TEST(BatchFunctionTest, SubstrWithStartZh)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::string str = "时欧基乌斯侧后解 hello! 回复哦黑色的and magic粉色的圣诞袜";
auto strLen = static_cast<int32_t>(str.length());
std::vector<std::string> inputStr(7, str);
std::vector<int32_t> inputLen(7, strLen);
std::vector<int32_t> startIndexs { 1, 9, -3, 0, 37, -38, -37 };
int32_t rowCnt = inputStr.size();
std::vector<int32_t> outLen(rowCnt);
std::vector<uint8_t *> outResult(rowCnt);
std::vector<uint8_t *> strAddr(rowCnt);
for (int32_t i = 0; i < rowCnt; i++) {
strAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(inputStr[i].c_str()));
}
bool isAnyNull[] = { false, false, false, false, false, false, false };
BatchSubstrVarcharWithStart<int32_t, false, false>(contextPtr, strAddr.data(), inputLen.data(), startIndexs.data(),
isAnyNull, outResult.data(), outLen.data(), rowCnt);
std::vector<std::string> expected { str, " hello! 回复哦黑色的and magic粉色的圣诞袜", "圣诞袜", "", "袜", "", str };
AssertStringEquals(expected, outResult, outLen);
delete context;
}
TEST(BatchFunctionTest, SubstrWithStartZhWhenStartIndexEqualsZero)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::string str = "时欧基乌斯侧后解 hello! 回复哦黑色的and magic粉色的圣诞袜";
auto strLen = static_cast<int32_t>(str.length());
std::vector<std::string> inputStr(7, str);
std::vector<int32_t> inputLen(7, strLen);
std::vector<int32_t> startIndexs { 0, 0, 0, 0, 0, 0, 0 };
int32_t rowCnt = inputStr.size();
std::vector<int32_t> outLen(rowCnt);
std::vector<uint8_t *> outResult(rowCnt);
std::vector<uint8_t *> strAddr(rowCnt);
for (int32_t i = 0; i < rowCnt; i++) {
strAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(inputStr[i].c_str()));
}
bool isAnyNull[] = { false, false, false, false, false, false, false };
BatchSubstrVarcharWithStart<int32_t, false, false>(contextPtr, strAddr.data(), inputLen.data(), startIndexs.data(),
isAnyNull, outResult.data(), outLen.data(), rowCnt);
std::vector<std::string> expected { "", "", "", "", "", "", "" };
AssertStringEquals(expected, outResult, outLen);
delete context;
}
TEST(BatchFunctionTest, SubstrWithStartZhForSpark)
{
ConfigUtil::SetNegativeStartIndexOutOfBoundsRule(NegativeStartIndexOutOfBoundsRule::INTERCEPT_FROM_BEYOND);
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::string str = "时欧基乌斯侧后解 h";
auto strLen = static_cast<int32_t>(str.length());
std::vector<std::string> inputStr(1, str);
std::vector<int32_t> inputLen(1, strLen);
std::vector<int32_t> outLen(inputStr.size());
std::vector<uint8_t *> outResult(inputStr.size());
std::vector<int32_t> startIndexs { -15 };
int32_t rowCnt = inputStr.size();
std::vector<uint8_t *> strAddr(rowCnt);
for (int32_t i = 0; i < rowCnt; i++) {
strAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(inputStr[i].c_str()));
}
bool isAnyNull[] = { false };
BatchSubstrVarcharWithStart<int32_t, true, false>(contextPtr, strAddr.data(), inputLen.data(), startIndexs.data(),
isAnyNull, outResult.data(), outLen.data(), rowCnt);
std::vector<std::string> expected(1, str);
AssertStringEquals(expected, outResult, outLen);
ConfigUtil::SetNegativeStartIndexOutOfBoundsRule(NegativeStartIndexOutOfBoundsRule::EMPTY_STRING);
delete context;
}
TEST(BatchFunctionTest, SubstrWithStartZhForSparkWhenStartIndexEqualsZero)
{
ConfigUtil::SetZeroStartIndexSupportRule(ZeroStartIndexSupportRule::IS_SUPPORT);
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::string str = "时欧基乌斯侧后解 h";
auto strLen = static_cast<int32_t>(str.length());
std::vector<std::string> inputStr(1, str);
std::vector<int32_t> inputLen(1, strLen);
std::vector<int32_t> outLen(inputStr.size());
std::vector<uint8_t *> outResult(inputStr.size());
std::vector<int32_t> startIndexs { 0 };
int32_t rowCnt = inputStr.size();
std::vector<uint8_t *> strAddr(rowCnt);
for (int32_t i = 0; i < rowCnt; i++) {
strAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(inputStr[i].c_str()));
}
bool isAnyNull[] = { false };
BatchSubstrVarcharWithStart<int32_t, true, true>(contextPtr, strAddr.data(), inputLen.data(), startIndexs.data(),
isAnyNull, outResult.data(), outLen.data(), rowCnt);
std::vector<std::string> expected(1, str);
AssertStringEquals(expected, outResult, outLen);
ConfigUtil::SetZeroStartIndexSupportRule(ZeroStartIndexSupportRule::IS_NOT_SUPPORT);
delete context;
}
TEST(BatchFunctionTest, SubstrWithStartEnForSpark)
{
ConfigUtil::SetNegativeStartIndexOutOfBoundsRule(NegativeStartIndexOutOfBoundsRule::INTERCEPT_FROM_BEYOND);
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::string str = "apple";
auto strLen = static_cast<int32_t>(str.length());
std::vector<std::string> inputStr(1, str);
std::vector<int32_t> inputLen(1, strLen);
std::vector<int32_t> outLen(inputStr.size());
std::vector<uint8_t *> outResult(inputStr.size());
std::vector<int32_t> startIndexs { -7 };
int32_t rowCnt = inputStr.size();
std::vector<uint8_t *> strAddr(rowCnt);
for (int32_t i = 0; i < rowCnt; i++) {
strAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(inputStr[i].c_str()));
}
bool isAnyNull[] = { false };
BatchSubstrVarcharWithStart<int32_t, true, false>(contextPtr, strAddr.data(), inputLen.data(), startIndexs.data(),
isAnyNull, outResult.data(), outLen.data(), rowCnt);
std::vector<std::string> expected(1, str);
AssertStringEquals(expected, outResult, outLen);
ConfigUtil::SetNegativeStartIndexOutOfBoundsRule(NegativeStartIndexOutOfBoundsRule::EMPTY_STRING);
delete context;
}
TEST(BatchFunctionTest, SubstrWithStartEnForSparkWhenStartIndexEqualsZero)
{
ConfigUtil::SetZeroStartIndexSupportRule(ZeroStartIndexSupportRule::IS_SUPPORT);
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::string str = "apple";
auto strLen = static_cast<int32_t>(str.length());
std::vector<std::string> inputStr(1, str);
std::vector<int32_t> inputLen(1, strLen);
std::vector<int32_t> outLen(inputStr.size());
std::vector<uint8_t *> outResult(inputStr.size());
std::vector<int32_t> startIndexs { 0 };
int32_t rowCnt = inputStr.size();
std::vector<uint8_t *> strAddr(rowCnt);
for (int32_t i = 0; i < rowCnt; i++) {
strAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(inputStr[i].c_str()));
}
bool isAnyNull[] = { false };
BatchSubstrVarcharWithStart<int32_t, true, true>(contextPtr, strAddr.data(), inputLen.data(), startIndexs.data(),
isAnyNull, outResult.data(), outLen.data(), rowCnt);
std::vector<std::string> expected(1, str);
AssertStringEquals(expected, outResult, outLen);
ConfigUtil::SetZeroStartIndexSupportRule(ZeroStartIndexSupportRule::IS_NOT_SUPPORT);
delete context;
}
TEST(BatchFunctionTest, SubstrWithZhForSpark)
{
ConfigUtil::SetNegativeStartIndexOutOfBoundsRule(NegativeStartIndexOutOfBoundsRule::INTERCEPT_FROM_BEYOND);
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::string str = "时欧基乌斯侧后解 h";
auto strLen = static_cast<int32_t>(str.length());
std::vector<std::string> inputStr(4, str);
int32_t rowCnt = inputStr.size();
std::vector<int32_t> inputLen(4, strLen);
std::vector<int32_t> outLen(inputStr.size());
std::vector<uint8_t *> outResult(inputStr.size());
std::vector<int32_t> startIndexs { -15, -15, -15, -15 };
std::vector<int32_t> length { 5, 6, 14, 20 };
std::vector<uint8_t *> strAddr(rowCnt);
for (int32_t i = 0; i < rowCnt; i++) {
strAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(inputStr[i].c_str()));
}
bool isAnyNull1[] = { false, false, false, false };
BatchSubstrVarchar<int32_t, true, false>(contextPtr, strAddr.data(), inputLen.data(), startIndexs.data(),
length.data(), isAnyNull1, outResult.data(), outLen.data(), rowCnt);
std::vector<std::string> expected { "", "时", "时欧基乌斯侧后解 ", "时欧基乌斯侧后解 h" };
AssertStringEquals(expected, outResult, outLen);
ConfigUtil::SetNegativeStartIndexOutOfBoundsRule(NegativeStartIndexOutOfBoundsRule::EMPTY_STRING);
delete context;
}
TEST(BatchFunctionTest, SubstrWithZhForSparkWhenStartIndexEqualsZero)
{
ConfigUtil::SetZeroStartIndexSupportRule(ZeroStartIndexSupportRule::IS_SUPPORT);
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::string str = "时欧基乌斯侧后解 h";
auto strLen = static_cast<int32_t>(str.length());
std::vector<std::string> inputStr(4, str);
int32_t rowCnt = inputStr.size();
std::vector<int32_t> inputLen(4, strLen);
std::vector<int32_t> outLen(inputStr.size());
std::vector<uint8_t *> outResult(inputStr.size());
std::vector<int32_t> startIndexs { 0, 0, 0, 0 };
std::vector<int32_t> length { 0, 1, 2, 5 };
std::vector<uint8_t *> strAddr(rowCnt);
for (int32_t i = 0; i < rowCnt; i++) {
strAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(inputStr[i].c_str()));
}
bool isAnyNull1[] = { false, false, false, false };
BatchSubstrVarchar<int32_t, true, true>(contextPtr, strAddr.data(), inputLen.data(), startIndexs.data(),
length.data(), isAnyNull1, outResult.data(), outLen.data(), rowCnt);
std::vector<std::string> expected { "", "时", "时欧", "时欧基乌斯" };
AssertStringEquals(expected, outResult, outLen);
ConfigUtil::SetZeroStartIndexSupportRule(ZeroStartIndexSupportRule::IS_NOT_SUPPORT);
delete context;
}
TEST(BatchFunctionTest, SubstrWithEnForSpark)
{
ConfigUtil::SetNegativeStartIndexOutOfBoundsRule(NegativeStartIndexOutOfBoundsRule::INTERCEPT_FROM_BEYOND);
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::string str = "apple";
auto strLen = static_cast<int32_t>(str.length());
std::vector<std::string> inputStr(1, str);
int32_t rowCnt = inputStr.size();
std::vector<int32_t> inputLen(1, strLen);
std::vector<int32_t> outLen(inputStr.size());
std::vector<uint8_t *> outResult(inputStr.size());
std::vector<int32_t> startIndexs { -7 };
std::vector<int32_t> length { 3 };
std::vector<uint8_t *> strAddr(rowCnt);
for (int32_t i = 0; i < rowCnt; i++) {
strAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(inputStr[i].c_str()));
}
bool isAnyNull1[] = { false };
BatchSubstrVarchar<int32_t, true, false>(contextPtr, strAddr.data(), inputLen.data(), startIndexs.data(),
length.data(), isAnyNull1, outResult.data(), outLen.data(), rowCnt);
std::vector<std::string> expected { "a" };
AssertStringEquals(expected, outResult, outLen);
ConfigUtil::SetNegativeStartIndexOutOfBoundsRule(NegativeStartIndexOutOfBoundsRule::EMPTY_STRING);
delete context;
}
TEST(BatchFunctionTest, SubstrWithEnForSparkWhenStartIndexEqualsZero)
{
ConfigUtil::SetZeroStartIndexSupportRule(ZeroStartIndexSupportRule::IS_SUPPORT);
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::string str = "apple";
auto strLen = static_cast<int32_t>(str.length());
std::vector<std::string> inputStr(1, str);
int32_t rowCnt = inputStr.size();
std::vector<int32_t> inputLen(1, strLen);
std::vector<int32_t> outLen(inputStr.size());
std::vector<uint8_t *> outResult(inputStr.size());
std::vector<int32_t> startIndexs { 0 };
std::vector<int32_t> length { 3 };
std::vector<uint8_t *> strAddr(rowCnt);
for (int32_t i = 0; i < rowCnt; i++) {
strAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(inputStr[i].c_str()));
}
bool isAnyNull1[] = { false };
BatchSubstrVarchar<int32_t, true, true>(contextPtr, strAddr.data(), inputLen.data(), startIndexs.data(),
length.data(), isAnyNull1, outResult.data(), outLen.data(), rowCnt);
std::vector<std::string> expected { "app" };
AssertStringEquals(expected, outResult, outLen);
ConfigUtil::SetZeroStartIndexSupportRule(ZeroStartIndexSupportRule::IS_NOT_SUPPORT);
delete context;
}
TEST(BatchFunctionTest, SubstrCharWithStartZh)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::string str = "时欧基乌斯侧后解 hello! 回复哦黑色的and magic粉色的圣诞袜";
auto width = static_cast<int32_t>(str.length());
int32_t strLen = str.length();
std::vector<std::string> inputStr(7, str);
std::vector<int32_t> inputLen(7, strLen);
std::vector<int32_t> outLen(inputStr.size());
std::vector<uint8_t *> outResult(inputStr.size());
std::vector<int32_t> startIndexs { 1, 9, -3, 0, 37, -38, -37 };
int32_t rowCnt = inputStr.size();
std::vector<uint8_t *> strAddr(rowCnt);
for (int32_t i = 0; i < rowCnt; i++) {
strAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(inputStr[i].c_str()));
}
bool isAnyNull[] = { false, false, false, false, false, false, false };
BatchSubstrCharWithStart<int32_t, false, false>(contextPtr, strAddr.data(), width, inputLen.data(),
startIndexs.data(), isAnyNull, outResult.data(), outLen.data(), rowCnt);
std::vector<std::string> expected { str, " hello! 回复哦黑色的and magic粉色的圣诞袜", "圣诞袜", "", "袜", "", str };
AssertStringEquals(expected, outResult, outLen);
delete context;
}
TEST(BatchFunctionTest, SubstrCharWithStartZhWhenStartIndexEqualsZero)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::string str = "时欧基乌斯侧后解 hello! 回复哦黑色的and magic粉色的圣诞袜";
auto width = static_cast<int32_t>(str.length());
int32_t strLen = str.length();
std::vector<std::string> inputStr(7, str);
std::vector<int32_t> inputLen(7, strLen);
std::vector<int32_t> outLen(inputStr.size());
std::vector<uint8_t *> outResult(inputStr.size());
std::vector<int32_t> startIndexs { 0, 0, 0, 0, 0, 0, 0 };
int32_t rowCnt = inputStr.size();
std::vector<uint8_t *> strAddr(rowCnt);
for (int32_t i = 0; i < rowCnt; i++) {
strAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(inputStr[i].c_str()));
}
bool isAnyNull[] = { false, false, false, false, false, false, false };
BatchSubstrCharWithStart<int32_t, false, false>(contextPtr, strAddr.data(), width, inputLen.data(),
startIndexs.data(), isAnyNull, outResult.data(), outLen.data(), rowCnt);
std::vector<std::string> expected { "", "", "", "", "", "", "" };
AssertStringEquals(expected, outResult, outLen);
delete context;
}
TEST(BatchFunctionTest, LengthStrZh)
{
std::string str = "时欧基乌斯侧后解 hello! 回复哦黑色的and magic粉色的圣诞袜";
int32_t strLen = str.length();
std::vector<std::string> inputStr { str, "解 hello! 回复哦黑色的" };
std::vector<int32_t> inputLen { strLen, 29 };
std::vector<int64_t> outLen(inputStr.size());
int32_t rowCnt = inputStr.size();
std::vector<uint8_t *> strAddr(rowCnt);
for (int32_t i = 0; i < rowCnt; i++) {
strAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(inputStr[i].c_str()));
}
bool isAnyNull[] = { false, false };
BatchLengthStr(strAddr.data(), inputLen.data(), isAnyNull, outLen.data(), rowCnt);
std::vector<int64_t> expected { 37, 15 };
AssertLongEquals(expected, outLen);
}
TEST(BatchFunctionTest, LikeStrZh)
{
std::string str = "时欧基乌斯侧后解 hello! 回复哦黑色的and magic粉色的圣诞袜";
int32_t strLen = str.length();
std::vector<std::string> inputStr(4, str);
std::vector<int32_t> inputLen(4, strLen);
std::vector<std::string> patternStr { "^时欧基乌斯侧后解 hello! 回复哦黑色的and magic粉色的圣诞.$",
"^时欧基乌斯侧后解 hello! 回复哦黑色的and magic粉色的圣诞..$",
"^时欧基乌斯侧后解 hello! 回复哦黑色的and magic粉色的圣.*$",
"^欧时基乌斯侧后解 hello! 回复哦黑色的and magic粉色的圣诞.*$" };
int32_t rowCnt = inputStr.size();
bool output[rowCnt];
std::vector<uint8_t *> strAddr(rowCnt);
std::vector<uint8_t *> patternAddr(rowCnt);
std::vector<int32_t> patternLen(rowCnt);
for (int32_t i = 0; i < rowCnt; i++) {
strAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(inputStr[i].c_str()));
patternAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(patternStr[i].c_str()));
patternLen[i] = static_cast<int32_t>(patternStr[i].length());
}
bool isAnyNull[] = { false, false, false, false };
BatchLikeStr(strAddr.data(), inputLen.data(), patternAddr.data(), patternLen.data(), isAnyNull, output, rowCnt);
std::vector<bool> expected { true, false, true, false };
AssertBoolEquals(expected, output);
}
TEST(BatchFunctionTest, LikeCharZh)
{
std::vector<std::string> inputStr { "时欧基乌斯侧后解 hello! 回复哦黑色的and magic粉色的圣诞袜", "时欧基乌",
"时欧基乌", "时欧基乌" };
std::vector<std::string> patternStr { "^时欧基乌斯侧后解 hello! 回复哦黑色的and magic粉色的圣诞.$", "^时欧基乌..$",
"^时欧基乌.$", "^时欧基乌.*$" };
int32_t batch = 4;
std::vector<bool> expected { true, true, false, true };
std::vector<int32_t> width { 37, 6, 6, 6 };
for (int32_t i = 0; i < batch; i++) {
int32_t rowCnt = 1;
std::vector<int32_t> inputLen { static_cast<int32_t>(inputStr[i].length()) };
bool output[rowCnt];
std::vector<uint8_t *> strAddr { reinterpret_cast<uint8_t *>(const_cast<char *>(inputStr[i].c_str())) };
std::vector<uint8_t *> patternAddr { reinterpret_cast<uint8_t *>(const_cast<char *>(patternStr[i].c_str())) };
std::vector<int32_t> patternLen { static_cast<int32_t>(patternStr[i].length()) };
bool isAnyNull[] = { false };
BatchLikeChar(strAddr.data(), width[i], inputLen.data(), patternAddr.data(), patternLen.data(), isAnyNull,
output, rowCnt);
EXPECT_EQ(output[0], expected[i]);
}
}
TEST(BatchFunctionTest, ReplaceStrStrStrZh)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> str { "apple", "粉色的圣诞袜", "粉色de圣诞袜", "粉色de圣诞袜", "粉色de圣诞袜",
"", "粉色de圣诞袜" };
std::vector<int32_t> strLen { 5, 18, 17, 17, 17, 0, 17 };
std::vector<std::string> searchStr { "", "", "", "", "de圣", "", "" };
std::vector<int32_t> searchLen { 0, 0, 0, 0, 5, 0, 0 };
std::vector<std::string> replaceStr { "*w*", "*w*", "*w*", "*的*", "*的*", "", "" };
std::vector<int32_t> replaceLen { 3, 3, 3, 5, 5, 0, 0 };
int32_t rowCnt = str.size();
std::vector<uint8_t *> output(rowCnt);
std::vector<int32_t> outLen(rowCnt);
std::vector<uint8_t *> strAddr(rowCnt);
std::vector<uint8_t *> searchStrAddr(rowCnt);
std::vector<uint8_t *> replaceStrAddr(rowCnt);
for (int32_t i = 0; i < rowCnt; i++) {
strAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(str[i].c_str()));
searchStrAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(searchStr[i].c_str()));
replaceStrAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(replaceStr[i].c_str()));
}
bool isAnyNull[] = { false, false, false, false, false, false, false };
BatchReplaceStrStrStrWithRepReplace(contextPtr, strAddr.data(), strLen.data(), searchStrAddr.data(),
searchLen.data(), replaceStrAddr.data(), replaceLen.data(), isAnyNull, output.data(), outLen.data(), rowCnt);
std::vector<std::string> expected { "*w*a*w*p*w*p*w*l*w*e*w*",
"*w*粉*w*色*w*的*w*圣*w*诞*w*袜*w*",
"*w*粉*w*色*w*d*w*e*w*圣*w*诞*w*袜*w*",
"*的*粉*的*色*的*d*的*e*的*圣*的*诞*的*袜*的*",
"粉色*的*诞袜",
"",
"粉色de圣诞袜" };
AssertStringEquals(expected, output, outLen);
delete context;
}
TEST(BatchFunctionTest, ReplaceWithoutRepZh)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> str { "apple", "apple", "粉色的圣诞袜", "粉色的圣诞袜", "粉色de圣诞袜", "粉色de圣诞袜" };
std::vector<int32_t> strLen { 5, 5, 18, 18, 17, 17 };
std::vector<std::string> searchStr { "", "pp", "", "圣诞", "", "色de" };
std::vector<int32_t> searchLen { 0, 2, 0, 6, 0, 5 };
int32_t rowCnt = str.size();
std::vector<uint8_t *> output(rowCnt);
std::vector<int32_t> outLen(rowCnt);
std::vector<uint8_t *> strAddr(rowCnt);
std::vector<uint8_t *> searchStrAddr(rowCnt);
for (int32_t i = 0; i < rowCnt; i++) {
strAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(str[i].c_str()));
searchStrAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(searchStr[i].c_str()));
}
bool isAnyNull[] = { false, false, false, false, false, false };
BatchReplaceStrStrWithoutRepNotReplace(contextPtr, strAddr.data(), strLen.data(), searchStrAddr.data(),
searchLen.data(), isAnyNull, output.data(), outLen.data(), rowCnt);
std::vector<std::string> expected {
"apple", "ale", "粉色的圣诞袜", "粉色的袜", "粉色de圣诞袜", "粉圣诞袜",
};
AssertStringEquals(expected, output, outLen);
delete context;
}
TEST(BatchFunctionTest, ConcatStrStrZh)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> ap { "你是Chinese?", "", "pink圣诞袜" };
std::vector<int32_t> apLen { 14, 0, 13 };
std::vector<std::string> bp { "Yes我是", "粉色de圣诞袜", "" };
std::vector<int32_t> bpLen { 9, 17, 0 };
int32_t rowCnt = ap.size();
std::vector<uint8_t *> output(rowCnt);
std::vector<int32_t> outLen(rowCnt);
std::vector<uint8_t *> apAddr(rowCnt);
std::vector<uint8_t *> bpAddr(rowCnt);
for (int32_t i = 0; i < rowCnt; i++) {
apAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(ap[i].c_str()));
bpAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(bp[i].c_str()));
}
bool isAnyNull[] = { false, false, false };
BatchConcatStrStr(contextPtr, apAddr.data(), apLen.data(), bpAddr.data(), bpLen.data(), isAnyNull, output.data(),
outLen.data(), rowCnt);
std::vector<std::string> expected { "你是Chinese?Yes我是", "粉色de圣诞袜", "pink圣诞袜" };
AssertStringEquals(expected, output, outLen);
delete context;
}
TEST(BatchFunctionTest, ConcatCharCharZh)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> ap { "粉色de圣诞袜", "*黑色*", "Hei你好吗", "Oh我很好",
"Hei你好吗 ", "Oh我很好 ", " Hei你好吗", " Oh我很好",
"Hei 你好吗", "Oh 我很好", " ", "Oh我很好",
"Hei你好吗", " ", "Hei你好吗", "" };
std::vector<int32_t> aWidth { 7, 8, 10, 12, 12, 5, 8, 8 };
std::vector<std::string> bp { "*黑色*", "粉色de", "Oh我很好", "Hei你好吗", "Oh我很好 ",
"Hei你好吗 ", " Oh我很好", " Hei你好吗", "Oh 我很好", "Hei 你好",
"Oh我很好 ", " ", " ", "Hei你好吗", "",
"Hei你好" };
std::vector<int32_t> bWidth { 4, 8, 8, 12, 8, 12, 5, 5 };
std::vector<std::string> expected { "粉色de圣诞袜*黑色*",
"*黑色* 粉色de",
"Hei你好吗 Oh我很好",
"Oh我很好 Hei你好吗",
"Hei你好吗 Oh我很好 ",
"Oh我很好 Hei你好吗 ",
" Hei你好吗 Oh我很好",
" Oh我很好 Hei你好吗",
"Hei 你好吗 Oh 我很好",
"Oh 我很好 Hei 你好",
" Oh我很好 ",
"Oh我很好 ",
"Hei你好吗 ",
" Hei你好吗",
"Hei你好吗",
" Hei你好" };
int32_t batch = 8;
int32_t rowCnt = 2;
for (int32_t i = 0; i < batch; i++) {
std::vector<uint8_t *> output(rowCnt);
std::vector<int32_t> outLen(rowCnt);
std::vector<int32_t> apLen(rowCnt);
std::vector<int32_t> bpLen(rowCnt);
std::vector<uint8_t *> apAddr(rowCnt);
std::vector<uint8_t *> bpAddr(rowCnt);
for (int32_t row = 0; row < rowCnt; row++) {
int32_t index = i * rowCnt + row;
apLen[row] = static_cast<int32_t>(ap[index].length());
bpLen[row] = static_cast<int32_t>(bp[index].length());
apAddr[row] = reinterpret_cast<uint8_t *>(const_cast<char *>(ap[index].c_str()));
bpAddr[row] = reinterpret_cast<uint8_t *>(const_cast<char *>(bp[index].c_str()));
}
bool isAnyNull[] = { false, false };
BatchConcatCharChar(contextPtr, apAddr.data(), aWidth[i], apLen.data(), bpAddr.data(), bWidth[i], bpLen.data(),
isAnyNull, output.data(), outLen.data(), rowCnt);
AssertStringEquals(expected, i * rowCnt, rowCnt, output, outLen);
}
delete context;
}
TEST(BatchFunctionTest, ConcatCharStrZh)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> ap { "*你是谁呢*", "我很OK", "*你是谁呢*", "我很OK", "*你是谁呢*", "" };
std::vector<int32_t> aWidth { 6, 10, 10 };
std::vector<std::string> bp { "我很OK", "*你是谁呢*", "我很OK", "*你是谁呢*", "", "*你是谁呢*" };
std::vector<std::string> expected { "*你是谁呢*我很OK", "我很OK *你是谁呢*", "*你是谁呢* 我很OK",
"我很OK *你是谁呢*", "*你是谁呢*", " *你是谁呢*" };
int32_t batch = 3;
int32_t rowCnt = 2;
for (int32_t i = 0; i < batch; i++) {
std::vector<uint8_t *> output(rowCnt);
std::vector<int32_t> outLen(rowCnt);
std::vector<int32_t> apLen(rowCnt);
std::vector<int32_t> bpLen(rowCnt);
std::vector<uint8_t *> apAddr(rowCnt);
std::vector<uint8_t *> bpAddr(rowCnt);
for (int32_t row = 0; row < rowCnt; row++) {
int32_t index = i * rowCnt + row;
apLen[row] = static_cast<int32_t>(ap[index].length());
bpLen[row] = static_cast<int32_t>(bp[index].length());
apAddr[row] = reinterpret_cast<uint8_t *>(const_cast<char *>(ap[index].c_str()));
bpAddr[row] = reinterpret_cast<uint8_t *>(const_cast<char *>(bp[index].c_str()));
}
bool isAnyNull[] = { false, false };
BatchConcatCharStr(contextPtr, apAddr.data(), aWidth[i], apLen.data(), bpAddr.data(), bpLen.data(), isAnyNull,
output.data(), outLen.data(), rowCnt);
AssertStringEquals(expected, i * rowCnt, rowCnt, output, outLen);
}
delete context;
}
TEST(BatchFunctionTest, ConcatStrCharZh)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> ap { "粉色de圣诞袜", "*黑色*", "粉色de圣诞袜", "*黑色*", "粉色de圣诞袜 ", "" };
std::vector<std::string> bp { "*黑色*", "粉色de圣诞袜", "*黑色*", "粉色de圣诞袜", "", "粉色de圣诞袜 " };
std::vector<int32_t> bWidth { 4, 6, 5 };
std::vector<std::string> expected { "粉色de圣诞袜*黑色*", "*黑色*粉色de圣诞袜", "粉色de圣诞袜*黑色*",
"*黑色*粉色de圣诞袜", "粉色de圣诞袜 ", "粉色de圣诞袜 " };
int32_t batch = 3;
int32_t rowCnt = 2;
for (int32_t i = 0; i < batch; i++) {
std::vector<uint8_t *> output(rowCnt);
std::vector<int32_t> outLen(rowCnt);
std::vector<int32_t> apLen(rowCnt);
std::vector<int32_t> bpLen(rowCnt);
std::vector<uint8_t *> apAddr(rowCnt);
std::vector<uint8_t *> bpAddr(rowCnt);
for (int32_t row = 0; row < rowCnt; row++) {
int32_t index = i * rowCnt + row;
apLen[row] = static_cast<int32_t>(ap[index].length());
bpLen[row] = static_cast<int32_t>(bp[index].length());
apAddr[row] = reinterpret_cast<uint8_t *>(const_cast<char *>(ap[index].c_str()));
bpAddr[row] = reinterpret_cast<uint8_t *>(const_cast<char *>(bp[index].c_str()));
}
bool isAnyNull[] = { false, false };
BatchConcatStrChar(contextPtr, apAddr.data(), apLen.data(), bpAddr.data(), bWidth[i], bpLen.data(), isAnyNull,
output.data(), outLen.data(), rowCnt);
AssertStringEquals(expected, i * rowCnt, rowCnt, output, outLen);
}
delete context;
}
TEST(BatchFunctionTest, ConcatStrStrRetNull)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> ap { "你是Chinese?", "", "pink圣诞袜" };
std::vector<int32_t> apLen { 14, 0, 13 };
std::vector<std::string> bp { "Yes我是", "粉色de圣诞袜", "" };
std::vector<int32_t> bpLen { 9, 17, 0 };
int32_t rowCnt = ap.size();
std::vector<uint8_t *> output(rowCnt);
std::vector<int32_t> outLen(rowCnt);
std::vector<uint8_t *> apAddr(rowCnt);
std::vector<uint8_t *> bpAddr(rowCnt);
for (int32_t i = 0; i < rowCnt; i++) {
apAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(ap[i].c_str()));
bpAddr[i] = reinterpret_cast<uint8_t *>(const_cast<char *>(bp[i].c_str()));
}
bool isNull[] = { false, false, false };
BatchConcatStrStrRetNull(isNull, contextPtr, apAddr.data(), apLen.data(), bpAddr.data(), bpLen.data(),
output.data(), outLen.data(), rowCnt);
std::vector<std::string> expected { "你是Chinese?Yes我是", "粉色de圣诞袜", "pink圣诞袜" };
AssertStringEquals(expected, output, outLen);
delete context;
}
TEST(BatchFunctionTest, ConcatCharCharRetNull)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> ap { "粉色de圣诞袜", "*黑色*", "Hei你好吗", "Oh我很好",
"Hei你好吗 ", "Oh我很好 ", " Hei你好吗", " Oh我很好",
"Hei 你好吗", "Oh 我很好", " ", "Oh我很好",
"Hei你好吗", " ", "Hei你好吗", "" };
std::vector<int32_t> aWidth { 7, 8, 10, 12, 12, 5, 8, 8 };
std::vector<std::string> bp { "*黑色*", "粉色de", "Oh我很好", "Hei你好吗", "Oh我很好 ",
"Hei你好吗 ", " Oh我很好", " Hei你好吗", "Oh 我很好", "Hei 你好",
"Oh我很好 ", " ", " ", "Hei你好吗", "",
"Hei你好" };
std::vector<int32_t> bWidth { 4, 8, 8, 12, 8, 12, 5, 5 };
std::vector<std::string> expected { "粉色de圣诞袜*黑色*",
"*黑色* 粉色de",
"Hei你好吗 Oh我很好",
"Oh我很好 Hei你好吗",
"Hei你好吗 Oh我很好 ",
"Oh我很好 Hei你好吗 ",
" Hei你好吗 Oh我很好",
" Oh我很好 Hei你好吗",
"Hei 你好吗 Oh 我很好",
"Oh 我很好 Hei 你好",
" Oh我很好 ",
"Oh我很好 ",
"Hei你好吗 ",
" Hei你好吗",
"Hei你好吗",
" Hei你好" };
int32_t batch = 8;
int32_t rowCnt = 2;
for (int32_t i = 0; i < batch; i++) {
std::vector<uint8_t *> output(rowCnt);
std::vector<int32_t> outLen(rowCnt);
std::vector<int32_t> apLen(rowCnt);
std::vector<int32_t> bpLen(rowCnt);
std::vector<uint8_t *> apAddr(rowCnt);
std::vector<uint8_t *> bpAddr(rowCnt);
for (int32_t row = 0; row < rowCnt; row++) {
int32_t index = i * rowCnt + row;
apLen[row] = static_cast<int32_t>(ap[index].length());
bpLen[row] = static_cast<int32_t>(bp[index].length());
apAddr[row] = reinterpret_cast<uint8_t *>(const_cast<char *>(ap[index].c_str()));
bpAddr[row] = reinterpret_cast<uint8_t *>(const_cast<char *>(bp[index].c_str()));
}
bool isNull[] = { false, false };
BatchConcatCharCharRetNull(isNull, contextPtr, apAddr.data(), aWidth[i], apLen.data(), bpAddr.data(), bWidth[i],
bpLen.data(), output.data(), outLen.data(), rowCnt);
AssertStringEquals(expected, i * rowCnt, rowCnt, output, outLen);
}
delete context;
}
TEST(BatchFunctionTest, ConcatCharStrRetNull)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> ap { "*你是谁呢*", "我很OK", "*你是谁呢*", "我很OK", "*你是谁呢*", "" };
std::vector<int32_t> aWidth { 6, 10, 10 };
std::vector<std::string> bp { "我很OK", "*你是谁呢*", "我很OK", "*你是谁呢*", "", "*你是谁呢*" };
std::vector<std::string> expected { "*你是谁呢*我很OK", "我很OK *你是谁呢*", "*你是谁呢* 我很OK",
"我很OK *你是谁呢*", "*你是谁呢*", " *你是谁呢*" };
int32_t batch = 3;
int32_t rowCnt = 2;
for (int32_t i = 0; i < batch; i++) {
std::vector<uint8_t *> output(rowCnt);
std::vector<int32_t> outLen(rowCnt);
std::vector<int32_t> apLen(rowCnt);
std::vector<int32_t> bpLen(rowCnt);
std::vector<uint8_t *> apAddr(rowCnt);
std::vector<uint8_t *> bpAddr(rowCnt);
for (int32_t row = 0; row < rowCnt; row++) {
int32_t index = i * rowCnt + row;
apLen[row] = static_cast<int32_t>(ap[index].length());
bpLen[row] = static_cast<int32_t>(bp[index].length());
apAddr[row] = reinterpret_cast<uint8_t *>(const_cast<char *>(ap[index].c_str()));
bpAddr[row] = reinterpret_cast<uint8_t *>(const_cast<char *>(bp[index].c_str()));
}
bool isNull[] = { false, false };
BatchConcatCharStrRetNull(isNull, contextPtr, apAddr.data(), aWidth[i], apLen.data(), bpAddr.data(),
bpLen.data(), output.data(), outLen.data(), rowCnt);
AssertStringEquals(expected, i * rowCnt, rowCnt, output, outLen);
}
delete context;
}
TEST(BatchFunctionTest, ConcatStrCharRetNull)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> ap { "粉色de圣诞袜", "*黑色*", "粉色de圣诞袜", "*黑色*", "粉色de圣诞袜 ", "" };
std::vector<std::string> bp { "*黑色*", "粉色de圣诞袜", "*黑色*", "粉色de圣诞袜", "", "粉色de圣诞袜 " };
std::vector<int32_t> bWidth { 4, 6, 5 };
std::vector<std::string> expected { "粉色de圣诞袜*黑色*", "*黑色*粉色de圣诞袜", "粉色de圣诞袜*黑色*",
"*黑色*粉色de圣诞袜", "粉色de圣诞袜 ", "粉色de圣诞袜 " };
int32_t batch = 3;
int32_t rowCnt = 2;
for (int32_t i = 0; i < batch; i++) {
std::vector<uint8_t *> output(rowCnt);
std::vector<int32_t> outLen(rowCnt);
std::vector<int32_t> apLen(rowCnt);
std::vector<int32_t> bpLen(rowCnt);
std::vector<uint8_t *> apAddr(rowCnt);
std::vector<uint8_t *> bpAddr(rowCnt);
for (int32_t row = 0; row < rowCnt; row++) {
int32_t index = i * rowCnt + row;
apLen[row] = static_cast<int32_t>(ap[index].length());
bpLen[row] = static_cast<int32_t>(bp[index].length());
apAddr[row] = reinterpret_cast<uint8_t *>(const_cast<char *>(ap[index].c_str()));
bpAddr[row] = reinterpret_cast<uint8_t *>(const_cast<char *>(bp[index].c_str()));
}
bool isNull[] = { false, false };
BatchConcatStrCharRetNull(isNull, contextPtr, apAddr.data(), apLen.data(), bpAddr.data(), bWidth[i],
bpLen.data(), output.data(), outLen.data(), rowCnt);
AssertStringEquals(expected, i * rowCnt, rowCnt, output, outLen);
}
delete context;
}
TEST(BatchFunctionTest, CastStrWithDiffWidths)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> srcStr { "cast乌s斯侧后解", "cast乌s斯解", "cast乌s斯侧后解", "cast乌s" };
std::vector<int32_t> srcWidth { 18, 18 };
std::vector<int32_t> dstWidth { 1024, 7 };
std::vector<std::string> expected { "cast乌s斯侧后解", "cast乌s斯解", "cast乌s斯", "cast乌s" };
int32_t batch = 2;
int32_t rowCnt = 2;
for (int32_t i = 0; i < batch; i++) {
std::vector<uint8_t *> output(rowCnt);
std::vector<int32_t> outLen(rowCnt);
std::vector<int32_t> strLen(rowCnt);
std::vector<uint8_t *> srcAddr(rowCnt);
for (int32_t row = 0; row < rowCnt; row++) {
int32_t index = i * rowCnt + row;
strLen[row] = static_cast<int32_t>(srcStr[index].length());
srcAddr[row] = reinterpret_cast<uint8_t *>(const_cast<char *>(srcStr[index].c_str()));
}
bool isAnyNull[] = { false, false };
BatchCastStrWithDiffWidths(contextPtr, srcAddr.data(), srcWidth[i], strLen.data(), isAnyNull, output.data(),
outLen.data(), dstWidth[i], rowCnt);
AssertStringEquals(expected, i * rowCnt, rowCnt, output, outLen);
}
delete context;
}
TEST(BatchFunctionTest, CastStrWithDiffWidthsRetNull)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> srcStr { "cast乌s斯侧后解", "cast乌s斯解", "cast乌s斯侧后解", "cast乌s" };
std::vector<int32_t> srcWidth { 18, 18 };
std::vector<int32_t> dstWidth { 1024, 7 };
std::vector<std::string> expected { "cast乌s斯侧后解", "cast乌s斯解", "cast乌s斯", "cast乌s" };
int32_t batch = 2;
int32_t rowCnt = 2;
for (int32_t i = 0; i < batch; i++) {
std::vector<uint8_t *> output(rowCnt);
std::vector<int32_t> outLen(rowCnt);
std::vector<int32_t> strLen(rowCnt);
std::vector<uint8_t *> srcAddr(rowCnt);
for (int32_t row = 0; row < rowCnt; row++) {
int32_t index = i * rowCnt + row;
strLen[row] = static_cast<int32_t>(srcStr[index].length());
srcAddr[row] = reinterpret_cast<uint8_t *>(const_cast<char *>(srcStr[index].c_str()));
}
bool isNull[] = { false, false };
BatchCastStrWithDiffWidthsRetNull(isNull, contextPtr, srcAddr.data(), srcWidth[i], strLen.data(), output.data(),
outLen.data(), dstWidth[i], rowCnt);
AssertStringEquals(expected, i * rowCnt, rowCnt, output, outLen);
}
delete context;
}
TEST(BatchFunctionTest, BatchInstr)
{
std::vector<std::string> srcStrVec { "", "", "abc", "abc", "abc", "abc", "", "abc", "" };
std::vector<std::string> subStrVec { "", "abc", "", "abcd", "bd", "bc", "ab", "", "" };
int32_t rowCnt = static_cast<int32_t>(srcStrVec.size());
char *srcStrs[rowCnt];
int32_t srcLens[rowCnt];
char *subStrs[rowCnt];
int32_t subLens[rowCnt];
bool isAnyNull[] = {true, true, true, false, false, false, false, false, false};
int32_t output[rowCnt];
for (int32_t row = 0; row < rowCnt; row++) {
srcStrs[row] = const_cast<char *>(srcStrVec[row].c_str());
srcLens[row] = srcStrVec[row].length();
subStrs[row] = const_cast<char *>(subStrVec[row].c_str());
subLens[row] = subStrVec[row].length();
}
BatchInStr(srcStrs, srcLens, subStrs, subLens, isAnyNull, output, rowCnt);
std::vector<int32_t> result(output, output + rowCnt);
std::vector<int32_t> expect { 0, 0, 0, 0, 0, 2, 0, 1, 1 };
AssertIntEquals(expect, result);
}
TEST(BatchFunctionTest, BatchStartsWithStr)
{
std::vector<std::string> srcStrVec { "", "", "abc", "abc", "abc", "abc", "", "abc", "" };
std::vector<std::string> matchStrVec { "ab", "ab", "ab", "ab", "ab", "ab", "ab", "ab", "ab" };
int32_t rowCnt = static_cast<int32_t>(srcStrVec.size());
char *srcStrs[rowCnt];
int32_t srcLens[rowCnt];
char *matchStrs[rowCnt];
int32_t matchLens[rowCnt];
bool isAnyNull[] = {true, true, false, false, false, false, false, false, false};
bool output[rowCnt];
for (int32_t row = 0; row < rowCnt; row++) {
srcStrs[row] = const_cast<char *>(srcStrVec[row].c_str());
srcLens[row] = srcStrVec[row].length();
matchStrs[row] = const_cast<char *>(matchStrVec[row].c_str());
matchLens[row] = matchStrVec[row].length();
}
BatchStartsWithStr(srcStrs, srcLens, matchStrs, matchLens, isAnyNull, output, rowCnt);
std::vector<bool> expect { false, false, true, true, true, true, false, true, false };
AssertBoolEquals(expect, output);
}
TEST(BatchFunctionTest, BatchEndsWithStr)
{
std::vector<std::string> srcStrVec { "", "", "abc", "abc", "abc", "abc", "", "abc", "" };
std::vector<std::string> matchStrVec { "bc", "bc", "bc", "bc", "bc", "bc", "bc", "bc", "bc" };
int32_t rowCnt = static_cast<int32_t>(srcStrVec.size());
char *srcStrs[rowCnt];
int32_t srcLens[rowCnt];
char *matchStrs[rowCnt];
int32_t matchLens[rowCnt];
bool isAnyNull[] = {true, true, false, false, false, false, false, false, false};
bool output[rowCnt];
for (int32_t row = 0; row < rowCnt; row++) {
srcStrs[row] = const_cast<char *>(srcStrVec[row].c_str());
srcLens[row] = srcStrVec[row].length();
matchStrs[row] = const_cast<char *>(matchStrVec[row].c_str());
matchLens[row] = matchStrVec[row].length();
}
BatchEndsWithStr(srcStrs, srcLens, matchStrs, matchLens, isAnyNull, output, rowCnt);
std::vector<bool> expect { false, false, true, true, true, true, false, true, false };
AssertBoolEquals(expect, output);
}
TEST(BatchFunctionTest, BatchJsonSplitStr)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> jsonStr { "[\"a\",\"b\"]", "invalid json", "[\"only\"]" };
std::vector<int32_t> jsonStrLen {
static_cast<int32_t>(jsonStr[0].length()),
static_cast<int32_t>(jsonStr[1].length()),
static_cast<int32_t>(jsonStr[2].length()) };
std::vector<uint8_t *> jsonStrAddr {
reinterpret_cast<uint8_t *>(const_cast<char *>(jsonStr[0].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(jsonStr[1].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(jsonStr[2].c_str())) };
int32_t rowCnt = static_cast<int32_t>(jsonStr.size());
bool jsonStrIsNull[] = { false, false, true };
bool outIsNull[] = { false, false, false };
std::vector<uint8_t *> output(rowCnt);
std::vector<int32_t> outLen(rowCnt);
BatchJsonSplitStr(contextPtr, jsonStrAddr.data(), jsonStrLen.data(), jsonStrIsNull, outIsNull, output.data(),
outLen.data(), rowCnt);
EXPECT_FALSE(outIsNull[0]);
EXPECT_EQ(std::string(reinterpret_cast<char *>(output[0]), outLen[0]), "a\r\nb");
EXPECT_TRUE(outIsNull[1]);
EXPECT_EQ(output[1], nullptr);
EXPECT_TRUE(outIsNull[2]);
EXPECT_EQ(output[2], nullptr);
delete context;
}
TEST(BatchFunctionTest, BatchJsonValue)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> jsonStr { R"({"name":"John","age":30})", R"({"name":"John"})", R"({"value":null})" };
std::vector<int32_t> jsonStrLen {
static_cast<int32_t>(jsonStr[0].length()),
static_cast<int32_t>(jsonStr[1].length()),
static_cast<int32_t>(jsonStr[2].length()) };
std::vector<uint8_t *> jsonStrAddr {
reinterpret_cast<uint8_t *>(const_cast<char *>(jsonStr[0].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(jsonStr[1].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(jsonStr[2].c_str())) };
std::vector<std::string> pathStr { "$.name", "$.age", "$.value" };
std::vector<int32_t> pathStrLen {
static_cast<int32_t>(pathStr[0].length()),
static_cast<int32_t>(pathStr[1].length()),
static_cast<int32_t>(pathStr[2].length()) };
std::vector<uint8_t *> pathStrAddr {
reinterpret_cast<uint8_t *>(const_cast<char *>(pathStr[0].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(pathStr[1].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(pathStr[2].c_str())) };
int32_t rowCnt = static_cast<int32_t>(jsonStr.size());
bool jsonStrIsNull[] = { false, false, false };
bool pathStrIsNull[] = { false, false, false };
bool outIsNull[] = { false, false, false };
std::vector<uint8_t *> output(rowCnt);
std::vector<int32_t> outLen(rowCnt);
BatchJsonValue(contextPtr, jsonStrAddr.data(), jsonStrLen.data(), jsonStrIsNull, pathStrAddr.data(), 0,
pathStrLen.data(), pathStrIsNull, outIsNull, output.data(), outLen.data(), rowCnt);
EXPECT_FALSE(outIsNull[0]);
EXPECT_EQ(std::string(reinterpret_cast<char *>(output[0]), outLen[0]), "John");
EXPECT_TRUE(outIsNull[1]);
EXPECT_EQ(output[1], nullptr);
EXPECT_TRUE(outIsNull[2]);
EXPECT_EQ(output[2], nullptr);
delete context;
}
TEST(BatchFunctionTest, BatchJsonValueWithBehaviors)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> jsonStr { R"({"name":"John"})", "invalid json" };
std::vector<int32_t> jsonStrLen {
static_cast<int32_t>(jsonStr[0].length()),
static_cast<int32_t>(jsonStr[1].length()) };
std::vector<uint8_t *> jsonStrAddr {
reinterpret_cast<uint8_t *>(const_cast<char *>(jsonStr[0].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(jsonStr[1].c_str())) };
std::vector<std::string> pathStr { "$.age", "$.name" };
std::vector<int32_t> pathStrLen {
static_cast<int32_t>(pathStr[0].length()),
static_cast<int32_t>(pathStr[1].length()) };
std::vector<uint8_t *> pathStrAddr {
reinterpret_cast<uint8_t *>(const_cast<char *>(pathStr[0].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(pathStr[1].c_str())) };
std::vector<std::string> defaultOnEmpty { "missing", "" };
std::vector<std::string> defaultOnError { "", "bad_json" };
std::vector<int32_t> defaultOnEmptyLen {
static_cast<int32_t>(defaultOnEmpty[0].length()),
static_cast<int32_t>(defaultOnEmpty[1].length()) };
std::vector<int32_t> defaultOnErrorLen {
static_cast<int32_t>(defaultOnError[0].length()),
static_cast<int32_t>(defaultOnError[1].length()) };
std::vector<uint8_t *> defaultOnEmptyAddr {
reinterpret_cast<uint8_t *>(const_cast<char *>(defaultOnEmpty[0].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(defaultOnEmpty[1].c_str())) };
std::vector<uint8_t *> defaultOnErrorAddr {
reinterpret_cast<uint8_t *>(const_cast<char *>(defaultOnError[0].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(defaultOnError[1].c_str())) };
int32_t emptyBehavior[] = { 2, 0 };
int32_t errorBehavior[] = { 0, 2 };
bool jsonStrIsNull[] = { false, false };
bool pathStrIsNull[] = { false, false };
bool emptyBehaviorIsNull[] = { false, false };
bool errorBehaviorIsNull[] = { false, false };
bool defaultOnEmptyIsNull[] = { false, true };
bool defaultOnErrorIsNull[] = { true, false };
bool outIsNull[] = { false, false };
std::vector<uint8_t *> output(2);
std::vector<int32_t> outLen(2);
BatchJsonValueWithBehaviors(contextPtr, jsonStrAddr.data(), jsonStrLen.data(), jsonStrIsNull, pathStrAddr.data(), 0,
pathStrLen.data(), pathStrIsNull, emptyBehavior, emptyBehaviorIsNull, defaultOnEmptyAddr.data(),
defaultOnEmptyLen.data(), defaultOnEmptyIsNull, errorBehavior, errorBehaviorIsNull, defaultOnErrorAddr.data(),
defaultOnErrorLen.data(), defaultOnErrorIsNull, outIsNull, output.data(), outLen.data(), 2);
EXPECT_FALSE(outIsNull[0]);
EXPECT_EQ(std::string(reinterpret_cast<char *>(output[0]), outLen[0]), "missing");
EXPECT_FALSE(outIsNull[1]);
EXPECT_EQ(std::string(reinterpret_cast<char *>(output[1]), outLen[1]), "bad_json");
delete context;
}
TEST(BatchFunctionTest, BatchJsonValueComplexTypesReturnNull)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> jsonStr { R"({"data":{"x":1}})", R"({"items":[1,2,3]})", R"({"flag":true})" };
std::vector<int32_t> jsonStrLen {
static_cast<int32_t>(jsonStr[0].length()),
static_cast<int32_t>(jsonStr[1].length()),
static_cast<int32_t>(jsonStr[2].length()) };
std::vector<uint8_t *> jsonStrAddr {
reinterpret_cast<uint8_t *>(const_cast<char *>(jsonStr[0].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(jsonStr[1].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(jsonStr[2].c_str())) };
std::vector<std::string> pathStr { "$.data", "$.items", "$.flag" };
std::vector<int32_t> pathStrLen {
static_cast<int32_t>(pathStr[0].length()),
static_cast<int32_t>(pathStr[1].length()),
static_cast<int32_t>(pathStr[2].length()) };
std::vector<uint8_t *> pathStrAddr {
reinterpret_cast<uint8_t *>(const_cast<char *>(pathStr[0].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(pathStr[1].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(pathStr[2].c_str())) };
int32_t rowCnt = static_cast<int32_t>(jsonStr.size());
bool jsonStrIsNull[] = { false, false, false };
bool pathStrIsNull[] = { false, false, false };
bool outIsNull[] = { false, false, false };
std::vector<uint8_t *> output(rowCnt);
std::vector<int32_t> outLen(rowCnt);
BatchJsonValue(contextPtr, jsonStrAddr.data(), jsonStrLen.data(), jsonStrIsNull, pathStrAddr.data(), 0,
pathStrLen.data(), pathStrIsNull, outIsNull, output.data(), outLen.data(), rowCnt);
EXPECT_TRUE(outIsNull[0]);
EXPECT_EQ(output[0], nullptr);
EXPECT_TRUE(outIsNull[1]);
EXPECT_EQ(output[1], nullptr);
EXPECT_FALSE(outIsNull[2]);
EXPECT_EQ(std::string(reinterpret_cast<char *>(output[2]), outLen[2]), "true");
delete context;
}
TEST(BatchFunctionTest, BatchJsonValueWithBehaviorsComplexTypesUseEmptyBehavior)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> jsonStr { R"({"data":{"x":1}})", R"({"items":[1,2,3]})" };
std::vector<int32_t> jsonStrLen {
static_cast<int32_t>(jsonStr[0].length()),
static_cast<int32_t>(jsonStr[1].length()) };
std::vector<uint8_t *> jsonStrAddr {
reinterpret_cast<uint8_t *>(const_cast<char *>(jsonStr[0].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(jsonStr[1].c_str())) };
std::vector<std::string> pathStr { "$.data", "$.items" };
std::vector<int32_t> pathStrLen {
static_cast<int32_t>(pathStr[0].length()),
static_cast<int32_t>(pathStr[1].length()) };
std::vector<uint8_t *> pathStrAddr {
reinterpret_cast<uint8_t *>(const_cast<char *>(pathStr[0].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(pathStr[1].c_str())) };
std::vector<std::string> defaultOnEmpty { "missing", "" };
std::vector<std::string> defaultOnError { "", "" };
std::vector<int32_t> defaultOnEmptyLen {
static_cast<int32_t>(defaultOnEmpty[0].length()),
static_cast<int32_t>(defaultOnEmpty[1].length()) };
std::vector<int32_t> defaultOnErrorLen {
static_cast<int32_t>(defaultOnError[0].length()),
static_cast<int32_t>(defaultOnError[1].length()) };
std::vector<uint8_t *> defaultOnEmptyAddr {
reinterpret_cast<uint8_t *>(const_cast<char *>(defaultOnEmpty[0].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(defaultOnEmpty[1].c_str())) };
std::vector<uint8_t *> defaultOnErrorAddr {
reinterpret_cast<uint8_t *>(const_cast<char *>(defaultOnError[0].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(defaultOnError[1].c_str())) };
int32_t emptyBehavior[] = { 2, 0 };
int32_t errorBehavior[] = { 0, 0 };
bool jsonStrIsNull[] = { false, false };
bool pathStrIsNull[] = { false, false };
bool emptyBehaviorIsNull[] = { false, false };
bool errorBehaviorIsNull[] = { false, false };
bool defaultOnEmptyIsNull[] = { false, true };
bool defaultOnErrorIsNull[] = { true, true };
bool outIsNull[] = { false, false };
std::vector<uint8_t *> output(2);
std::vector<int32_t> outLen(2);
BatchJsonValueWithBehaviors(contextPtr, jsonStrAddr.data(), jsonStrLen.data(), jsonStrIsNull, pathStrAddr.data(), 0,
pathStrLen.data(), pathStrIsNull, emptyBehavior, emptyBehaviorIsNull, defaultOnEmptyAddr.data(),
defaultOnEmptyLen.data(), defaultOnEmptyIsNull, errorBehavior, errorBehaviorIsNull, defaultOnErrorAddr.data(),
defaultOnErrorLen.data(), defaultOnErrorIsNull, outIsNull, output.data(), outLen.data(), 2);
EXPECT_FALSE(outIsNull[0]);
EXPECT_EQ(std::string(reinterpret_cast<char *>(output[0]), outLen[0]), "missing");
EXPECT_TRUE(outIsNull[1]);
EXPECT_EQ(output[1], nullptr);
delete context;
}
TEST(BatchFunctionTest, BatchJsonQuery)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> jsonStr {
R"({"roomInfos":{"id":1,"name":"A"}})",
R"({"roomInfos":{"name":"A"}})",
R"({"roomInfos":[]})" };
std::vector<int32_t> jsonStrLen {
static_cast<int32_t>(jsonStr[0].length()),
static_cast<int32_t>(jsonStr[1].length()),
static_cast<int32_t>(jsonStr[2].length()) };
std::vector<uint8_t *> jsonStrAddr {
reinterpret_cast<uint8_t *>(const_cast<char *>(jsonStr[0].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(jsonStr[1].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(jsonStr[2].c_str())) };
std::vector<std::string> pathStr { "$.roomInfos", "$.roomInfos.name", "$.missing" };
std::vector<int32_t> pathStrLen {
static_cast<int32_t>(pathStr[0].length()),
static_cast<int32_t>(pathStr[1].length()),
static_cast<int32_t>(pathStr[2].length()) };
std::vector<uint8_t *> pathStrAddr {
reinterpret_cast<uint8_t *>(const_cast<char *>(pathStr[0].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(pathStr[1].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(pathStr[2].c_str())) };
int32_t rowCnt = static_cast<int32_t>(jsonStr.size());
bool jsonStrIsNull[] = { false, false, false };
bool pathStrIsNull[] = { false, false, false };
bool outIsNull[] = { false, false, false };
std::vector<uint8_t *> output(rowCnt);
std::vector<int32_t> outLen(rowCnt);
BatchJsonQuery(contextPtr, jsonStrAddr.data(), jsonStrLen.data(), jsonStrIsNull, pathStrAddr.data(), 0,
pathStrLen.data(), pathStrIsNull, outIsNull, output.data(), outLen.data(), rowCnt);
EXPECT_FALSE(outIsNull[0]);
EXPECT_EQ(std::string(reinterpret_cast<char *>(output[0]), outLen[0]), R"({"id":1,"name":"A"})");
EXPECT_TRUE(outIsNull[1]);
EXPECT_EQ(output[1], nullptr);
EXPECT_TRUE(outIsNull[2]);
EXPECT_EQ(output[2], nullptr);
delete context;
}
TEST(BatchFunctionTest, BatchJsonQueryWithWrapperAndBehavior)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> jsonStr {
R"({"roomInfos":{"name":"A"}})",
R"({"roomInfos":[]})",
R"({"roomInfos":[]})" };
std::vector<int32_t> jsonStrLen {
static_cast<int32_t>(jsonStr[0].length()),
static_cast<int32_t>(jsonStr[1].length()),
static_cast<int32_t>(jsonStr[2].length()) };
std::vector<uint8_t *> jsonStrAddr {
reinterpret_cast<uint8_t *>(const_cast<char *>(jsonStr[0].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(jsonStr[1].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(jsonStr[2].c_str())) };
std::vector<std::string> pathStr {
"$.roomInfos.name",
"lax $.missing",
"strict $.missing" };
std::vector<int32_t> pathStrLen {
static_cast<int32_t>(pathStr[0].length()),
static_cast<int32_t>(pathStr[1].length()),
static_cast<int32_t>(pathStr[2].length()) };
std::vector<uint8_t *> pathStrAddr {
reinterpret_cast<uint8_t *>(const_cast<char *>(pathStr[0].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(pathStr[1].c_str())),
reinterpret_cast<uint8_t *>(const_cast<char *>(pathStr[2].c_str())) };
int32_t wrapperBehavior[] = { 1, 0, 0 };
int32_t emptyBehavior[] = { 0, 1, 0 };
int32_t errorBehavior[] = { 0, 0, 2 };
bool jsonStrIsNull[] = { false, false, false };
bool pathStrIsNull[] = { false, false, false };
bool wrapperBehaviorIsNull[] = { false, false, false };
bool emptyBehaviorIsNull[] = { false, false, false };
bool errorBehaviorIsNull[] = { false, false, false };
bool outIsNull[] = { false, false, false };
std::vector<uint8_t *> output(3);
std::vector<int32_t> outLen(3);
BatchJsonQueryWithWrapperAndBehavior(contextPtr, jsonStrAddr.data(), jsonStrLen.data(), jsonStrIsNull,
pathStrAddr.data(), 0, pathStrLen.data(), pathStrIsNull, wrapperBehavior, wrapperBehaviorIsNull,
emptyBehavior, emptyBehaviorIsNull, errorBehavior, errorBehaviorIsNull, outIsNull, output.data(),
outLen.data(), 3);
EXPECT_FALSE(outIsNull[0]);
EXPECT_EQ(std::string(reinterpret_cast<char *>(output[0]), outLen[0]), R"(["A"])");
EXPECT_FALSE(outIsNull[1]);
EXPECT_EQ(std::string(reinterpret_cast<char *>(output[1]), outLen[1]), "[]");
EXPECT_FALSE(outIsNull[2]);
EXPECT_EQ(std::string(reinterpret_cast<char *>(output[2]), outLen[2]), "{}");
EXPECT_FALSE(context->HasError());
delete context;
}
TEST(BatchFunctionTest, BatchJsonSplitChar)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> jsonStr { "[\"'dIPFMXtJL\"]" };
std::vector<int32_t> jsonStrLen { static_cast<int32_t>(jsonStr[0].length()) };
std::vector<uint8_t *> jsonStrAddr {
reinterpret_cast<uint8_t *>(const_cast<char *>(jsonStr[0].c_str())) };
int32_t rowCnt = 1;
bool jsonStrIsNull[] = { false };
bool outIsNull[] = { false };
std::vector<uint8_t *> output(rowCnt);
std::vector<int32_t> outLen(rowCnt);
BatchJsonSplitChar(contextPtr, jsonStrAddr.data(), 1, jsonStrLen.data(), jsonStrIsNull, outIsNull, output.data(),
outLen.data(), rowCnt);
EXPECT_FALSE(outIsNull[0]);
EXPECT_EQ(std::string(reinterpret_cast<char *>(output[0]), outLen[0]), "'dIPFMXtJL");
delete context;
}
TEST(BatchFunctionTest, BatchJsonSplitFloatFormatting)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> jsonStr { "[1.2,3.14,-2.5]" };
std::vector<int32_t> jsonStrLen { static_cast<int32_t>(jsonStr[0].length()) };
std::vector<uint8_t *> jsonStrAddr {
reinterpret_cast<uint8_t *>(const_cast<char *>(jsonStr[0].c_str())) };
bool jsonStrIsNull[] = { false };
bool outIsNull[] = { false };
std::vector<uint8_t *> output(1);
std::vector<int32_t> outLen(1);
BatchJsonSplitStr(contextPtr, jsonStrAddr.data(), jsonStrLen.data(), jsonStrIsNull, outIsNull, output.data(),
outLen.data(), 1);
EXPECT_FALSE(outIsNull[0]);
EXPECT_EQ(std::string(reinterpret_cast<char *>(output[0]), outLen[0]), "1.2\r\n3.14\r\n-2.5");
delete context;
}
TEST(BatchFunctionTest, BatchJsonSplitScientificNotationFormatting)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> jsonStr { "[1.171815966525443e+77]" };
std::vector<int32_t> jsonStrLen { static_cast<int32_t>(jsonStr[0].length()) };
std::vector<uint8_t *> jsonStrAddr {
reinterpret_cast<uint8_t *>(const_cast<char *>(jsonStr[0].c_str())) };
bool jsonStrIsNull[] = { false };
bool outIsNull[] = { false };
std::vector<uint8_t *> output(1);
std::vector<int32_t> outLen(1);
BatchJsonSplitStr(contextPtr, jsonStrAddr.data(), jsonStrLen.data(), jsonStrIsNull, outIsNull, output.data(),
outLen.data(), 1);
EXPECT_FALSE(outIsNull[0]);
EXPECT_EQ(std::string(reinterpret_cast<char *>(output[0]), outLen[0]), "1.171815966525443E+77");
delete context;
}
TEST(BatchFunctionTest, BatchCastStringToDate)
{
ConfigUtil::SetStringToDateFormatRule(StringToDateFormatRule::ALLOW_REDUCED_PRECISION);
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> srcStr { "1970-01-03", "1969-12-31", "1453-05-29", " 1453-05-29 ",
" 1 453-05-29 " };
bool isNull[] = { false, false, false, false, false };
std::vector<int32_t> expected { 2, -1, -188682, -188682, 0 };
int32_t rowCnt = 5;
std::vector<int32_t> output(rowCnt);
std::vector<int32_t> strLen(rowCnt);
std::vector<uint8_t *> srcAddr(rowCnt);
for (int32_t row = 0; row < rowCnt; row++) {
strLen[row] = static_cast<int32_t>(srcStr[row].length());
srcAddr[row] = reinterpret_cast<uint8_t *>(const_cast<char *>(srcStr[row].c_str()));
}
BatchCastStringToDateAllowReducePrecison(contextPtr, srcAddr.data(), strLen.data(), isNull, output.data(), rowCnt);
AssertIntEquals(expected, output);
BatchCastStringToDateRetNullAllowReducePrecison(isNull, srcAddr.data(), strLen.data(), output.data(), rowCnt);
AssertIntEquals(expected, output);
ConfigUtil::SetStringToDateFormatRule(StringToDateFormatRule::NOT_ALLOW_REDUCED_PRECISION);
delete context;
}
TEST(BatchFunctionTest, BatchCastStringToInt)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> srcStr = { "2147483648",
"2123123123147483648",
"-2123123123147483648",
"-2123123123147-483648",
"+45",
"-45",
"3.14159",
"31337 a",
"+12345678901",
"-12345678901",
"2147483647.2",
"2147483648.2",
" 2147483647.2 ",
" a 2147483647.2 ",
" 2147483647.2 a ",
".",
".2",
"0.",
"2.3e3",
"-1e+2",
"+.",
"-.",
"- .",
"",
" ",
" + ",
"-",
"-123.a",
"-123." };
bool isAnyNull[] = { false, false, false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, false, false, false, false,
false, false, false };
std::vector<int32_t> expected { 0, 0, 0, 0, 45, -45, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int32_t rowCnt = static_cast<int32_t>(srcStr.size());
std::vector<int32_t> output(rowCnt);
std::vector<int32_t> strLen(rowCnt);
std::vector<uint8_t *> srcAddr(rowCnt);
for (int32_t row = 0; row < rowCnt; row++) {
strLen[row] = static_cast<int32_t>(srcStr[row].length());
srcAddr[row] = reinterpret_cast<uint8_t *>(const_cast<char *>(srcStr[row].c_str()));
}
BatchCastStringToInt(contextPtr, srcAddr.data(), strLen.data(), isAnyNull, output.data(), rowCnt);
AssertIntEquals(expected, output);
EXPECT_TRUE(context->HasError());
delete context;
}
TEST(BatchFunctionTest, BatchCastStringToLong)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
std::vector<std::string> srcStr { "23423",
"100123",
"-10078",
"123.123",
"9223372036854775807",
"9223372036854775808",
"-9223372036854775808",
"-9223372036854775809" };
bool isAnyNull[] = { false, false, false, false, false, false, false, false };
std::vector<int64_t> expected { 23423, 100123, -10078, 0, INT64_MAX, 0, INT64_MIN, 0 };
int32_t rowCnt = 8;
std::vector<int64_t> output(rowCnt);
std::vector<int32_t> strLen(rowCnt);
std::vector<uint8_t *> srcAddr(rowCnt);
for (int32_t row = 0; row < rowCnt; row++) {
strLen[row] = static_cast<int32_t>(srcStr[row].length());
srcAddr[row] = reinterpret_cast<uint8_t *>(const_cast<char *>(srcStr[row].c_str()));
}
BatchCastStringToLong(contextPtr, srcAddr.data(), strLen.data(), isAnyNull, output.data(), rowCnt);
AssertLongEquals(expected, output);
delete context;
}
TEST(BatchFunctionTest, BatchCastStringToIntRetNull)
{
std::vector<std::string> srcStr = { "2147483648",
"2123123123147483648",
"-2123123123147483648",
"-2123123123147-483648",
"+45",
"-45",
"3.14159",
"31337 a",
"+12345678901",
"-12345678901",
"2147483647.2",
"2147483648.2",
" 2147483647.2 ",
" a 2147483647.2 ",
" 2147483647.2 a ",
".",
".2",
"0.",
"2.3e3",
"-1e+2",
"+.",
"-.",
"- .",
"",
" ",
" + ",
"-",
"-123.a",
"-123." };
int32_t rowCnt = static_cast<int32_t>(srcStr.size());
std::vector<int32_t> strLen(rowCnt);
std::vector<uint8_t *> srcAddr(rowCnt);
for (int32_t row = 0; row < rowCnt; row++) {
strLen[row] = static_cast<int32_t>(srcStr[row].length());
srcAddr[row] = reinterpret_cast<uint8_t *>(const_cast<char *>(srcStr[row].c_str()));
}
bool isNull[rowCnt];
std::vector<int32_t> output(rowCnt);
BatchCastStringToIntRetNull(isNull, srcAddr.data(), strLen.data(), output.data(), rowCnt);
std::vector<int32_t> expected { 0, 0, 0, 0, 45, -45, 3, 0, 0, 0, 2147483647, 0, 2147483647, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -123 };
std::vector<bool> expectedNulls { true, true, true, true, false, false, false, true, true, true,
false, true, false, true, true, false, false, false, true, true,
false, false, true, true, true, true, true, true, false };
AssertIntEquals(expected, output);
AssertBoolEquals(expectedNulls, isNull);
}
TEST(BatchFunctionTest, BatchCastStringToLongRetNull)
{
std::vector<std::string> srcStr = { "23423",
"123.123",
"2147483648",
"2a147483648",
"-10078",
std::to_string(std::numeric_limits<int64_t>::min()),
std::to_string(std::numeric_limits<int64_t>::max()),
std::to_string(std::numeric_limits<uint64_t>::max()),
"-9223372036854775808",
"9223372036854775807",
"-9223372036854775818",
"9223372036854775817",
"-2123123123147-483648",
" 2147483647.2 ",
" a 2147483647.2 ",
" 2147483647.2 a ",
".",
".2",
"0.",
"2.3e3",
"-1e+2" };
int32_t rowCnt = static_cast<int32_t>(srcStr.size());
std::vector<int32_t> strLen(rowCnt);
std::vector<uint8_t *> srcAddr(rowCnt);
for (int32_t row = 0; row < rowCnt; row++) {
strLen[row] = static_cast<int32_t>(srcStr[row].length());
srcAddr[row] = reinterpret_cast<uint8_t *>(const_cast<char *>(srcStr[row].c_str()));
}
bool isNull[rowCnt];
std::vector<int64_t> output(rowCnt);
BatchCastStringToLongRetNull(isNull, srcAddr.data(), strLen.data(), output.data(), rowCnt);
std::vector<int64_t> expected { 23423,
123,
2147483648,
0,
-10078,
std::numeric_limits<int64_t>::min(),
std::numeric_limits<int64_t>::max(),
0,
INT64_MIN,
INT64_MAX,
0,
0,
0,
2147483647,
0,
0,
0,
0,
0,
0,
0 };
std::vector<bool> expectedNulls { false, false, false, true, false, false, false, true, false, false, true,
true, true, false, true, true, false, false, false, true, true };
AssertLongEquals(expected, output);
AssertBoolEquals(expectedNulls, isNull);
}
TEST(BatchFunctionTest, BatchUnixTimestampFromStr)
{
const int32_t rowCnt = 6;
std::string timeStrs[] = {"2024-10-12", "1948-01-12", "2023-12-09", "",
"1989-07-10 11:10:09", "1985-06-29 00:04:49"};
std::string fmtStrs[] = {"%Y-%m-%d", "%Y-%m-%d", "%Y-%m-%d", "", "%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M:%S"};
std::string tzStrs[] = {"Asia/Shanghai", "Asia/Shanghai", "Asia/Shanghai", "Asia/Shanghai",
"Asia/Shanghai", "Asia/Shanghai"};
std::string policyStrs[] = {"CORRECTED", "CORRECTED", "CORRECTED", "CORRECTED", "CORRECTED", "CORRECTED"};
const char *timeStrPtrs[rowCnt];
int32_t timeLens[rowCnt];
const char *fmtStrPtrs[rowCnt];
int32_t fmtLens[rowCnt];
const char *tzStrPtrs[rowCnt];
int32_t tzLens[rowCnt];
const char *policyStrPtrs[rowCnt];
int32_t policyLens[rowCnt];
for (int32_t i = 0; i < rowCnt; i++) {
timeStrPtrs[i] = const_cast<char *>(timeStrs[i].c_str());
timeLens[i] = timeStrs[i].length();
fmtStrPtrs[i] = fmtStrs[i].c_str();
fmtLens[i] = fmtStrs[i].length();
tzStrPtrs[i] = tzStrs[i].c_str();
tzLens[i] = tzStrs[i].length();
policyStrPtrs[i] = policyStrs[i].c_str();
policyLens[i] = policyStrs[i].length();
}
bool isNullTimeStr[] = {false, false, false, true, false, false};
bool isNullFmtStr[] = {false, false, false, true, false, false};
bool isNullTzStr[] = {false, false, false, false, false, false};
bool isNullPolStr[] = {false, false, false, false, false, false};
bool retIsNull[rowCnt] = {false};
int64_t output[rowCnt];
BatchUnixTimestampFromStr(timeStrPtrs, timeLens, isNullTimeStr, fmtStrPtrs, fmtLens, isNullFmtStr, tzStrPtrs,
tzLens, isNullTzStr, policyStrPtrs, policyLens, isNullPolStr, retIsNull, output, rowCnt);
std::vector<bool> expectIsNull = {false, false, false, true, false, false};
AssertBoolEquals(expectIsNull, retIsNull);
std::vector<int64_t> result(output, output + rowCnt);
std::vector<int64_t> expect = { 1728662400, -693388800, 1702051200, 0, 616039809, 488822689 };
AssertLongEquals(expect, result);
}
TEST(BatchFunctionTest, BatchUnixTimestampFromDate)
{
const int32_t rowCnt = 3;
int32_t dates[] = {7130, 5658, 0};
std::string fmtStrs[] = {"%Y-%m-%d", "%Y-%m-%d", "%Y-%m-%d"};
std::string tzStrs[] = {"Asia/Shanghai", "Asia/Shanghai", "Asia/Shanghai"};
std::string policyStrs[] = {"CORRECTED", "CORRECTED", "CORRECTED"};
const char *fmtStrPtrs[rowCnt];
int32_t fmtLens[rowCnt];
const char *tzStrPtrs[rowCnt];
int32_t tzLens[rowCnt];
const char *policyStrPtrs[rowCnt];
int32_t policyLens[rowCnt];
for (int32_t i = 0; i < rowCnt; i++) {
fmtStrPtrs[i] = fmtStrs[i].c_str();
fmtLens[i] = fmtStrs[i].length();
tzStrPtrs[i] = tzStrs[i].c_str();
tzLens[i] = tzStrs[i].length();
policyStrPtrs[i] = policyStrs[i].c_str();
policyLens[i] = policyStrs[i].length();
}
bool isAnyNull[] = {false, false, false};
int64_t output[rowCnt];
BatchUnixTimestampFromDate(dates, fmtStrPtrs, fmtLens, tzStrPtrs, tzLens, policyStrPtrs, policyLens,
isAnyNull, output, rowCnt);
std::vector<int64_t> result(output, output + rowCnt);
std::vector<int64_t> expect = { 615999600, 488822400, -28800 };
AssertLongEquals(expect, result);
}
TEST(BatchFunctionTest, BatchFromUnixTimeRetNull)
{
const int32_t rowCnt = 4;
bool outputNull[rowCnt];
auto context = new ExecutionContext();
int64_t contextPtr = reinterpret_cast<int64_t>(context);
int64_t timestamps[rowCnt] = {615999600, 488822400, 0, -100};
std::string fmtStrs[] = {"%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M:%S"};
std::string tzStrs[] = {"Asia/Shanghai", "Asia/Shanghai", "Asia/Shanghai", "Asia/Shanghai"};
const char *fmtStrPtrs[rowCnt];
int32_t fmtLens[rowCnt];
const char *tzStrPtrs[rowCnt];
int32_t tzLens[rowCnt];
char *output[rowCnt];
int32_t outLens[rowCnt];
for (int32_t i = 0; i < rowCnt; i++) {
fmtStrPtrs[i] = fmtStrs[i].c_str();
fmtLens[i] = fmtStrs[i].length();
tzStrPtrs[i] = tzStrs[i].c_str();
tzLens[i] = tzStrs[i].length();
}
BatchFromUnixTimeRetNull(outputNull, contextPtr, timestamps, fmtStrPtrs, fmtLens, tzStrPtrs, tzLens,
output, outLens, rowCnt);
std::vector<uint8_t *> result(rowCnt);
std::vector<int32_t> resultLen(outLens, outLens + rowCnt);
for (int32_t i = 0; i < rowCnt; i++) {
result[i] = reinterpret_cast<uint8_t *>(output[i]);
}
std::vector<std::string> expect = { "1989-07-10 00:00:00", "1985-06-29 00:00:00", "1970-01-01 08:00:00",
"1970-01-01 07:58:20" };
AssertStringEquals(expect, result, resultLen);
delete context;
}
TEST(BatchFunctionTest, BatchContainsStr)
{
std::vector<std::string> srcStrVec{ "", "ab", "", "abc", "abc", "abcd", "", "ab", "" };
std::vector<std::string> matchStrVec{ "ab", "", "", "ab", "bc", "bc", "ab", "", "" };
int32_t rowCnt = static_cast<int32_t>(srcStrVec.size());
char *srcStrs[rowCnt];
int32_t srcLens[rowCnt];
char *matchStrs[rowCnt];
int32_t matchLens[rowCnt];
bool isAnyNull[] = {true, true, true, false, false, false, false, false, false};
bool output[rowCnt];
for (int32_t row = 0; row < rowCnt; row++) {
srcStrs[row] = const_cast<char *>(srcStrVec[row].c_str());
srcLens[row] = srcStrVec[row].length();
matchStrs[row] = const_cast<char *>(matchStrVec[row].c_str());
matchLens[row] = matchStrVec[row].length();
}
BatchContainsStr(srcStrs, srcLens, matchStrs, matchLens, isAnyNull, output, rowCnt);
std::vector<bool> expect{ false, false, false, true, true, true, false, true, true };
AssertBoolEquals(expect, output);
}
TEST(BatchFunctionTest, BatchGreatestStr)
{
std::vector<std::string> xStrVec{ "abc", "abcd", "abc", "", "", "abc", "", "", "1234" };
std::vector<std::string> yStrVec{ "abcd", "abc", "", "abc", "", "", "abc", "", "2" };
int32_t rowCnt = static_cast<int32_t>(xStrVec.size());
uint8_t *xStrs[rowCnt];
int32_t xLens[rowCnt];
uint8_t *yStrs[rowCnt];
int32_t yLens[rowCnt];
bool xIsNull[] = { false, false, false, false, false, false, true, true, false };
bool yIsNull[] = { false, false, false, false, false, true, false, true, false };
bool retIsNull[] = { false, false, false, false, false, false, false, false, false };
std::vector<uint8_t *> output(rowCnt);
std::vector<int32_t> outLens(rowCnt);
for (int32_t row = 0; row < rowCnt; row++) {
xStrs[row] = reinterpret_cast<uint8_t *>(const_cast<char *>(xStrVec[row].c_str()));
xLens[row] = xStrVec[row].length();
yStrs[row] = reinterpret_cast<uint8_t *>(const_cast<char *>(yStrVec[row].c_str()));
yLens[row] = yStrVec[row].length();
}
BatchGreatestStr(xStrs, xLens, xIsNull, yStrs, yLens, yIsNull, retIsNull, output.data(), outLens.data(), rowCnt);
std::vector<std::string> expect = { "abcd", "abcd", "abc", "abc", "", "abc", "abc", "", "2" };
std::vector<bool> expectRetNull{ false, false, false, false, false, false, false, true, false };
AssertStringEquals(expect, output, outLens);
AssertBoolEquals(expectRetNull, retIsNull);
}
TEST(BatchFunctionTest, BatchGreatest)
{
int32_t xValue[] = {10, 5, 0, 10, 0};
bool xIsNull[] = {false, false, true, false, true};
int32_t yValue[] = {5, 10, 10, 0, 0};
bool yIsNull[] = {false, false, false, true, true};
bool retIsNull[] = {false, false, false, false, false};
int32_t rowCnt = sizeof(xValue) / sizeof(int32_t);
int32_t output[rowCnt];
BatchGreatest<int32_t>(xValue, xIsNull, yValue, yIsNull, retIsNull, output, rowCnt);
int32_t expect[] = {10, 10, 10, 10, 0};
EXPECT_TRUE(CmpArray<int32_t>(output, expect, rowCnt));
bool expectRetNull[] = {false, false, false, false, true};
EXPECT_TRUE(CmpArray<bool>(retIsNull, expectRetNull, rowCnt));
bool xBool[] = {true, false, true, false, true, false, false};
bool xBoolIsNull[] = {false, false, false, false, false, true, true};
bool yBool[] = {false, true, true, false, false, true, false};
bool yBoolIsNull[] = {false, false, false, false, true, false, true};
bool boolRetIsNull[] = {false, false, false, false, false, false, false};
int32_t boolRowCnt = sizeof(xBool) / sizeof(bool);
bool boolOutput[boolRowCnt];
BatchGreatest<bool>(xBool, xBoolIsNull, yBool, yBoolIsNull, boolRetIsNull, boolOutput, boolRowCnt);
bool boolExpect[] = {true, true, true, false, true, true, false};
bool boolExpectRetNull[] = {false, false, false, false, false, false, true};
EXPECT_TRUE(CmpArray<bool>(boolOutput, boolExpect, boolRowCnt));
EXPECT_TRUE(CmpArray<bool>(boolRetIsNull, boolExpectRetNull, boolRowCnt));
}
TEST(BatchFunctionTest, BatchGreatestDecimal64)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
int64_t xValue[] = {127, 0, 128, 0, 12800};
bool xIsNull[] = {false, true, false, true, false};
int64_t yValue[] = {128, 128, 0, 0, 12708};
bool yIsNull[] = {false, false, true, true, false};
bool retIsNull[] = {false, false, false, false, false};
int32_t rowCnt = sizeof(xValue) / sizeof(int64_t);
int64_t output[] = {0, 0, 0, 0, 0};
BatchGreatestDecimal64(contextPtr, xValue, 18, 1, xIsNull, yValue, 18, 1, yIsNull, retIsNull, output, 18, 1,
rowCnt);
int64_t expect[] = {128, 128, 128, 0, 12800};
bool expectRetNull[] = {false, false, false, true, false};
EXPECT_TRUE(CmpArray<int64_t>(output, expect, rowCnt));
EXPECT_TRUE(CmpArray<bool>(retIsNull, expectRetNull, rowCnt));
for (int i = 0; i < rowCnt; i++) {
retIsNull[i] = false;
output[i] = 0;
}
bool overflowNull[] = {false, false, false, false, false};
BatchGreatestDecimal64RetNull(overflowNull, xValue, 18, 1, xIsNull, yValue, 18, 1, yIsNull, retIsNull, output, 18,
1, rowCnt);
int64_t expectRet[] = {128, 128, 128, 0, 12800};
bool expectRetNull2[] = {false, false, false, true, false};
bool expectOverflowNull[] = {false, false, false, false, false};
EXPECT_TRUE(CmpArray<int64_t>(output, expectRet, rowCnt));
EXPECT_TRUE(CmpArray<bool>(retIsNull, expectRetNull2, rowCnt));
EXPECT_TRUE(CmpArray<bool>(overflowNull, expectOverflowNull, rowCnt));
delete context;
}
TEST(BatchFunctionTest, BatchGreatestDecimal128)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
Decimal128 xValue[] = {Decimal128(0, 127), Decimal128(0, 0), Decimal128(0, 128), Decimal128(0, 0),
Decimal128(0, 12800)};
bool xIsNull[] = {false, true, false, true, false};
Decimal128 yValue[] = {Decimal128(0, 128), Decimal128(0, 128), Decimal128(0, 0), Decimal128(0, 0),
Decimal128(0, 12708)};
bool yIsNull[] = {false, false, true, true, false};
bool retIsNull[] = {false, false, false, false, false};
int32_t rowCnt = sizeof(xValue) / sizeof(Decimal128);
Decimal128 output[] = {Decimal128(0, 0), Decimal128(0, 0), Decimal128(0, 0), Decimal128(0, 0), Decimal128(0, 0)};
BatchGreatestDecimal128(contextPtr, xValue, 38, 1, xIsNull, yValue, 38, 1, yIsNull, retIsNull, output, 38, 1,
rowCnt);
Decimal128 expect[] = {Decimal128(0, 128), Decimal128(0, 128), Decimal128(0, 128), Decimal128(0, 0),
Decimal128(0, 12800)};
bool expectRetNull[] = {false, false, false, true, false};
EXPECT_TRUE(CmpArray<Decimal128>(output, expect, rowCnt));
EXPECT_TRUE(CmpArray<bool>(retIsNull, expectRetNull, rowCnt));
for (int i = 0; i < rowCnt; i++) {
retIsNull[i] = false;
output[i] = Decimal128(0, 0);
}
bool overflowNull[] = {false, false, false, false, false};
BatchGreatestDecimal128RetNull(overflowNull, xValue, 38, 1, xIsNull, yValue, 38, 1, yIsNull, retIsNull, output, 38,
1, rowCnt);
Decimal128 expectRet[] = {Decimal128(0, 128), Decimal128(0, 128), Decimal128(0, 128), Decimal128(0, 0),
Decimal128(0, 12800)};
bool expectRetNull2[] = {false, false, false, true, false};
bool expectOverflowNull[] = {false, false, false, false, false};
EXPECT_TRUE(CmpArray<Decimal128>(output, expectRet, rowCnt));
EXPECT_TRUE(CmpArray<bool>(retIsNull, expectRetNull2, rowCnt));
EXPECT_TRUE(CmpArray<bool>(overflowNull, expectOverflowNull, rowCnt));
delete context;
}
TEST(BatchFunctionTest, BatchEmptyToNull)
{
std::vector<std::string> inString{ "", "abc", "abc123", "", "国家" };
int32_t rowCnt = static_cast<int32_t>(inString.size());
bool isAnyNull[] = {false, false, false, false, true};
int32_t inLens[rowCnt];
std::vector<char *> strAddr(rowCnt);
for (int i = 0; i < rowCnt; ++i) {
inLens[i] = inString[i].size();
strAddr[i] = reinterpret_cast<char *>(const_cast<char *>(inString[i].c_str()));
}
strAddr[3] = nullptr;
std::vector<int32_t> outLen(rowCnt);
std::vector<char *> outResult(rowCnt);
BatchEmptyToNull(strAddr.data(), inLens, isAnyNull, outResult.data(), outLen.data(), rowCnt);
EXPECT_EQ(outResult[0], nullptr);
EXPECT_EQ(outLen[0], 0);
EXPECT_EQ("abc", std::string(outResult[1], outLen[1]));
EXPECT_EQ("abc123", std::string(outResult[2], outLen[2]));
EXPECT_EQ(outResult[3], nullptr);
EXPECT_EQ(outLen[3], 0);
}
TEST(BatchFunctionTest, BatchStaticInvokeVarcharTypeWriteSideCheck)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
int32_t limit = 4;
std::vector<std::string> srcStrVec{ "abc", "abcd", "abcde", "abc ", "abcd ", "abced ", "测试超过长度", "测试长度"};
std::vector<std::string> matchStrVec{ "abc", "abcd", "", "abc ", "abcd", "", "", "测试长度"};
int32_t rowCnt = static_cast<int32_t>(srcStrVec.size()) + 1;
char *srcStrs[rowCnt];
int32_t srcLens[rowCnt];
char *output[rowCnt];
int32_t outputLen[rowCnt];
for (int32_t row = 0; row < rowCnt - 1; ++row) {
srcStrs[row] = const_cast<char *>(srcStrVec[row].c_str());
srcLens[row] = srcStrVec[row].size();
}
srcStrs[rowCnt - 1] = nullptr;
srcLens[rowCnt - 1] = 0;
bool isAnyNull[] = {false, false, false, false, false, false, false, false, true};
BatchStaticInvokeVarcharTypeWriteSideCheck(contextPtr, srcStrs, srcLens, limit,
isAnyNull, output, outputLen, rowCnt);
for (int32_t row = 0; row < rowCnt; ++row) {
if (outputLen[row] == 0) {
EXPECT_TRUE(output[row] == nullptr);
} else {
std::string outStr (output[row], outputLen[row]);
EXPECT_EQ(outStr, matchStrVec[row]);
}
}
delete context;
}
TEST(BatchFunctionTest, BatchStaticInvokeCharReadPadding)
{
auto context = new ExecutionContext();
auto contextPtr = reinterpret_cast<int64_t>(context);
int32_t limit = 4;
std::vector<std::string> srcStrVec{ "1", "12", "123", "1234", "12345", "123456", "测试超过长度", "测试"};
std::vector<std::string> matchStrVec{ "1 ", "12 ", "123 ", "1234", "12345", "123456", "测试超过长度", "测试 "};
int32_t rowCnt = static_cast<int32_t>(srcStrVec.size()) + 1;
char *srcStrs[rowCnt];
int32_t srcLens[rowCnt];
char *matchStrs[rowCnt];
int32_t matchLens[rowCnt];
char *output[rowCnt];
int32_t outputLen[rowCnt];
for (int32_t row = 0; row < rowCnt - 1; ++row) {
srcStrs[row] = const_cast<char *>(srcStrVec[row].c_str());
srcLens[row] = srcStrVec[row].length();
matchStrs[row] = const_cast<char *>(matchStrVec[row].c_str());
matchLens[row] = matchStrVec[row].length();
}
srcStrs[rowCnt - 1] = nullptr;
srcLens[rowCnt - 1] = 0;
bool isAnyNull[] = {false, false, false, false, false, false, false, false, true};
BatchStaticInvokeCharReadPadding(contextPtr, srcStrs, srcLens, limit, isAnyNull, output, outputLen, rowCnt);
for (int32_t row = 0; row < rowCnt; ++row) {
if (outputLen[row] == 0) {
EXPECT_TRUE(output[row] == nullptr);
} else {
std::string outStr (output[row], outputLen[row]);
EXPECT_EQ(outStr, matchStrVec[row]);
}
}
delete context;
}