Skip to content

Commit

Permalink
Remove functions for individual types and rely on implicit casting to…
Browse files Browse the repository at this point in the history
… string
  • Loading branch information
PhictionalOne committed May 29, 2024
1 parent 2e7c556 commit 7bb90e4
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 387 deletions.
96 changes: 6 additions & 90 deletions extension/json/json_functions/json_array_append.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
namespace duckdb {

//! Append String or JSON value to an array
yyjson_mut_val *ArrayAppendStringOrJSON(yyjson_mut_val *arr, yyjson_mut_doc *doc, string_t element, yyjson_alc *alc,
Vector &result) {
yyjson_mut_val *ArrayAppendJSON(yyjson_mut_val *arr, yyjson_mut_doc *doc, string_t element, yyjson_alc *alc,
Vector &result) {
if (!yyjson_mut_is_arr(arr)) {
throw InvalidInputException("JSON input not an JSON Array");
}
Expand All @@ -16,108 +16,24 @@ yyjson_mut_val *ArrayAppendStringOrJSON(yyjson_mut_val *arr, yyjson_mut_doc *doc
return arr;
}

//! Append boolean value to an array
yyjson_mut_val *ArrayAppendBoolean(yyjson_mut_val *arr, yyjson_mut_doc *doc, bool element, yyjson_alc *alc,
Vector &result) {
if (!yyjson_mut_is_arr(arr)) {
throw InvalidInputException("JSON input not a JSON Array");
}

yyjson_mut_arr_add_bool(doc, arr, element);
return arr;
}

//! Append unsigned Integers to an array
yyjson_mut_val *ArrayAppendUnsignedIntegers(yyjson_mut_val *arr, yyjson_mut_doc *doc, uint64_t element, yyjson_alc *alc,
Vector &result) {
if (!yyjson_mut_is_arr(arr)) {
throw InvalidInputException("JSON input not a JSON Array");
}

yyjson_mut_arr_add_uint(doc, arr, element);
return arr;
}

//! Append signed Integers to an array
yyjson_mut_val *ArrayAppendSignedIntegers(yyjson_mut_val *arr, yyjson_mut_doc *doc, int64_t element, yyjson_alc *alc,
Vector &result) {
if (!yyjson_mut_is_arr(arr)) {
throw InvalidInputException("JSON input not a JSON Array");
}

yyjson_mut_arr_add_int(doc, arr, element);
return arr;
}

//! Append floating values to an array
yyjson_mut_val *ArrayAppendFloating(yyjson_mut_val *arr, yyjson_mut_doc *doc, double element, yyjson_alc *alc,
Vector &result) {
if (!yyjson_mut_is_arr(arr)) {
throw InvalidInputException("JSON input not a JSON Array");
}

yyjson_mut_arr_add_real(doc, arr, element);
return arr;
}

//! Append function wrapper
static void ArrayAppendFunction(DataChunk &args, ExpressionState &state, Vector &result) {
auto left_type = args.data[0].GetType();
D_ASSERT(left_type == LogicalType::VARCHAR || left_type == LogicalType::JSON());

auto right_type = args.data[1].GetType();
D_ASSERT(right_type == LogicalType::VARCHAR || right_type == LogicalType::JSON());

switch (right_type.id()) {
case LogicalType::VARCHAR:
JSONExecutors::BinaryMutExecute<string_t>(args, state, result, ArrayAppendStringOrJSON);
break;
case LogicalType::BOOLEAN:
JSONExecutors::BinaryMutExecute<bool>(args, state, result, ArrayAppendBoolean);
break;
case LogicalType::UBIGINT:
JSONExecutors::BinaryMutExecute<uint64_t>(args, state, result, ArrayAppendUnsignedIntegers);
break;
case LogicalType::BIGINT:
JSONExecutors::BinaryMutExecute<int64_t>(args, state, result, ArrayAppendSignedIntegers);
break;
case LogicalType::DOUBLE:
JSONExecutors::BinaryMutExecute<double>(args, state, result, ArrayAppendFloating);
break;
default:
// Shouldn't be thrown except implicit casting changes
throw InvalidInputException("Not a valid input type");
}
JSONExecutors::BinaryMutExecute<string_t>(args, state, result, ArrayAppendJSON);
}

static void GetArrayAppendFunctionInternal(ScalarFunctionSet &set, const LogicalType &lhs, const LogicalType &rhs) {
set.AddFunction(ScalarFunction("json_array_append", {lhs, rhs}, LogicalType::JSON(), ArrayAppendFunction,
nullptr, nullptr, nullptr, JSONFunctionLocalState::Init));
set.AddFunction(ScalarFunction("json_array_append", {lhs, rhs}, LogicalType::JSON(), ArrayAppendFunction, nullptr,
nullptr, nullptr, JSONFunctionLocalState::Init));
}

ScalarFunctionSet JSONFunctions::GetArrayAppendFunction() {
ScalarFunctionSet set("json_array_append");

// Use different executor for these
// Allows booleans directly
// GetArrayAppendFunctionInternal(set, LogicalType::JSON(), LogicalType::BOOLEAN);

// Allows for Integer types
// TINYINT, SMALLINT, INTEGER, UTINYINT, USMALLINT, UINTEGER are captured by UBIGINT and BIGINT respecively
// relies on consistant casting strategy upfront

// unsigned
// GetArrayAppendFunctionInternal(set, LogicalType::JSON(), LogicalType::UBIGINT);

// signed
// GetArrayAppendFunctionInternal(set, LogicalType::JSON(), LogicalType::BIGINT);

// Allows for floating types
// FLOAT is covered by automatic upfront casting to double
// GetArrayAppendFunctionInternal(set, LogicalType::JSON(), LogicalType::DOUBLE);

// Allows for json and string values
GetArrayAppendFunctionInternal(set, LogicalType::JSON(), LogicalType::JSON());
GetArrayAppendFunctionInternal(set, LogicalType::JSON(), LogicalType::VARCHAR);

return set;
}
Expand Down
73 changes: 5 additions & 68 deletions extension/json/json_functions/json_array_insert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
namespace duckdb {

//! Insert String or JSON value to an array
yyjson_mut_val *ArrayInsertStringOrJSON(yyjson_mut_val *arr, yyjson_mut_doc *doc, string_t element, int64_t idx,
yyjson_alc *alc, Vector &result) {
yyjson_mut_val *ArrayInsertJSON(yyjson_mut_val *arr, yyjson_mut_doc *doc, string_t element, int64_t idx,
yyjson_alc *alc, Vector &result) {
if (!yyjson_mut_is_arr(arr)) {
throw InvalidInputException("JSON input not an JSON Array");
}
Expand All @@ -22,58 +22,16 @@ yyjson_mut_val *ArrayInsertStringOrJSON(yyjson_mut_val *arr, yyjson_mut_doc *doc
return arr;
}

//! Insert any yyjson_mut_ELEMENT_TYPE type and function
template <class ELEMENT_TYPE>
std::function<yyjson_mut_val *(yyjson_mut_val *, yyjson_mut_doc *, ELEMENT_TYPE, int64_t, yyjson_alc *, Vector &)>
ArrayInsert(std::function<yyjson_mut_val *(yyjson_mut_doc *, ELEMENT_TYPE)> fconvert) {
return [&](yyjson_mut_val *arr, yyjson_mut_doc *doc, ELEMENT_TYPE element, int64_t idx, yyjson_alc *alc,
Vector &result) {
if (!yyjson_mut_is_arr(arr)) {
throw InvalidInputException("JSON input not a JSON Array");
}

size_t index = DetermineArrayIndex(arr, idx);

// Fill remaining indeces with null until element index
for (size_t entries = yyjson_mut_arr_size(arr); entries < index; ++entries) {
yyjson_mut_arr_add_null(doc, arr);
}
auto mut_value = fconvert(doc, element);
yyjson_mut_arr_insert(arr, mut_value, index);
return arr;
};
}

//! Insert function wrapper
static void ArrayInsertFunction(DataChunk &args, ExpressionState &state, Vector &result) {
auto json_type = args.data[0].GetType();
D_ASSERT(json_type == LogicalType::VARCHAR || json_type == LogicalType::JSON());
auto element_type = args.data[1].GetType();
D_ASSERT(element_type == LogicalType::VARCHAR || element_type == LogicalType::JSON());
auto idx_type = args.data[2].GetType();
D_ASSERT(idx_type == LogicalType::BIGINT);

auto element_type = args.data[1].GetType();

switch (element_type.id()) {
case LogicalType::VARCHAR:
JSONExecutors::TernaryMutExecute<string_t, int64_t>(args, state, result, ArrayInsertStringOrJSON);
break;
case LogicalType::BOOLEAN:
JSONExecutors::TernaryMutExecute<bool, int64_t>(args, state, result, ArrayInsert<bool>(yyjson_mut_bool));
break;
case LogicalType::UBIGINT:
JSONExecutors::TernaryMutExecute<uint64_t, int64_t>(args, state, result,
ArrayInsert<uint64_t>(yyjson_mut_uint));
break;
case LogicalType::BIGINT:
JSONExecutors::TernaryMutExecute<int64_t, int64_t>(args, state, result, ArrayInsert<int64_t>(yyjson_mut_sint));
break;
case LogicalType::DOUBLE:
JSONExecutors::TernaryMutExecute<double, int64_t>(args, state, result, ArrayInsert<double>(yyjson_mut_real));
break;
default:
// Shouldn't be thrown except implicit casting changes
throw InvalidInputException("Not a valid input type");
}
JSONExecutors::TernaryMutExecute<string_t, int64_t>(args, state, result, ArrayInsertJSON);
}

static void GetArrayInsertFunctionInternal(ScalarFunctionSet &set, const LogicalType &fst, const LogicalType &snd,
Expand All @@ -84,28 +42,7 @@ static void GetArrayInsertFunctionInternal(ScalarFunctionSet &set, const Logical

ScalarFunctionSet JSONFunctions::GetArrayInsertFunction() {
ScalarFunctionSet set("json_array_insert");

// Use different executor for these
// Allows booleans directly
// GetArrayInsertFunctionInternal(set, LogicalType::JSON(), LogicalType::BOOLEAN, LogicalType::BIGINT);

// Allows for Integer types
// TINYINT, SMALLINT, INTEGER, UTINYINT, USMALLINT, UINTEGER are captured by UBIGINT and BIGINT respecively
// relies on consistant casting strategy upfront

// unsigned
// GetArrayInsertFunctionInternal(set, LogicalType::JSON(), LogicalType::UBIGINT, LogicalType::BIGINT);

// signed
// GetArrayInsertFunctionInternal(set, LogicalType::JSON(), LogicalType::BIGINT, LogicalType::BIGINT);

// Allows for floating types
// FLOAT is covered by automatic upfront casting to double
// GetArrayInsertFunctionInternal(set, LogicalType::JSON(), LogicalType::DOUBLE, LogicalType::BIGINT);

// Allows for json and string values
GetArrayInsertFunctionInternal(set, LogicalType::JSON(), LogicalType::JSON(), LogicalType::BIGINT);
GetArrayInsertFunctionInternal(set, LogicalType::JSON(), LogicalType::VARCHAR, LogicalType::BIGINT);

return set;
}
Expand Down
102 changes: 7 additions & 95 deletions extension/json/json_functions/json_array_prepend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
namespace duckdb {

//! Prepend String or JSON value to an array
yyjson_mut_val *ArrayPrependStringOrJSON(yyjson_mut_val *arr, yyjson_mut_doc *doc, string_t element, yyjson_alc *alc,
Vector &result) {
yyjson_mut_val *ArrayPrependJSON(yyjson_mut_val *arr, yyjson_mut_doc *doc, string_t element, yyjson_alc *alc,
Vector &result) {
if (!yyjson_mut_is_arr(arr)) {
throw InvalidInputException("JSON input not an JSON Array");
}
Expand All @@ -16,112 +16,24 @@ yyjson_mut_val *ArrayPrependStringOrJSON(yyjson_mut_val *arr, yyjson_mut_doc *do
return arr;
}

//! Prepend boolean value to an array
yyjson_mut_val *ArrayPrependBoolean(yyjson_mut_val *arr, yyjson_mut_doc *doc, bool element, yyjson_alc *alc,
Vector &result) {
if (!yyjson_mut_is_arr(arr)) {
throw InvalidInputException("JSON input not a JSON Array");
}

auto mut_value = yyjson_mut_bool(doc, element);
yyjson_mut_arr_prepend(arr, mut_value);
return arr;
}

//! Prepend unsigned Integers to an array
yyjson_mut_val *ArrayPrependUnsignedIntegers(yyjson_mut_val *arr, yyjson_mut_doc *doc, uint64_t element,
yyjson_alc *alc, Vector &result) {
if (!yyjson_mut_is_arr(arr)) {
throw InvalidInputException("JSON input not a JSON Array");
}

auto mut_value = yyjson_mut_uint(doc, element);
yyjson_mut_arr_prepend(arr, mut_value);
return arr;
}

//! Prepend signed Integers to an array
yyjson_mut_val *ArrayPrependSignedIntegers(yyjson_mut_val *arr, yyjson_mut_doc *doc, int64_t element, yyjson_alc *alc,
Vector &result) {
if (!yyjson_mut_is_arr(arr)) {
throw InvalidInputException("JSON input not a JSON Array");
}

auto mut_value = yyjson_mut_sint(doc, element);
yyjson_mut_arr_prepend(arr, mut_value);
return arr;
}

//! Prepend floating values to an array
yyjson_mut_val *ArrayPrependFloating(yyjson_mut_val *arr, yyjson_mut_doc *doc, double element, yyjson_alc *alc,
Vector &result) {
if (!yyjson_mut_is_arr(arr)) {
throw InvalidInputException("JSON input not a JSON Array");
}

auto mut_value = yyjson_mut_real(doc, element);
yyjson_mut_arr_prepend(arr, mut_value);
return arr;
}

//! Prepend function wrapper
static void ArrayPrependFunction(DataChunk &args, ExpressionState &state, Vector &result) {
auto left_type = args.data[0].GetType();
D_ASSERT(left_type == LogicalType::VARCHAR || left_type == LogicalType::JSON());
auto right_type = args.data[1].GetType();
D_ASSERT(right_type == LogicalType::VARCHAR || right_type == LogicalType::JSON());

auto left_type = args.data[0].GetType();

switch (left_type.id()) {
case LogicalType::VARCHAR:
JSONExecutors::BinaryMutExecuteFlip<string_t>(args, state, result, ArrayPrependStringOrJSON);
break;
case LogicalType::BOOLEAN:
JSONExecutors::BinaryMutExecuteFlip<bool>(args, state, result, ArrayPrependBoolean);
break;
case LogicalType::UBIGINT:
JSONExecutors::BinaryMutExecuteFlip<uint64_t>(args, state, result, ArrayPrependUnsignedIntegers);
break;
case LogicalType::BIGINT:
JSONExecutors::BinaryMutExecuteFlip<int64_t>(args, state, result, ArrayPrependSignedIntegers);
break;
case LogicalType::DOUBLE:
JSONExecutors::BinaryMutExecuteFlip<double>(args, state, result, ArrayPrependFloating);
break;
default:
// Shouldn't be thrown except implicit casting changes
throw InvalidInputException("Not a valid input type");
}
JSONExecutors::BinaryMutExecuteFlip<string_t>(args, state, result, ArrayPrependJSON);
}

static void GetArrayPrependFunctionInternal(ScalarFunctionSet &set, const LogicalType &lhs, const LogicalType &rhs) {
set.AddFunction(ScalarFunction("json_array_prepend", {lhs, rhs}, LogicalType::JSON(), ArrayPrependFunction,
nullptr, nullptr, nullptr, JSONFunctionLocalState::Init));
set.AddFunction(ScalarFunction("json_array_prepend", {lhs, rhs}, LogicalType::JSON(), ArrayPrependFunction, nullptr,
nullptr, nullptr, JSONFunctionLocalState::Init));
}

ScalarFunctionSet JSONFunctions::GetArrayPrependFunction() {
ScalarFunctionSet set("json_array_prepend");

// Use different executor for these
// Allows booleans directly
// GetArrayPrependFunctionInternal(set, LogicalType::BOOLEAN, LogicalType::JSON());

// Allows for Integer types
// TINYINT, SMALLINT, INTEGER, UTINYINT, USMALLINT, UINTEGER are captured by UBIGINT and BIGINT respecively
// relies on consistant casting strategy upfront

// unsigned
// GetArrayPrependFunctionInternal(set, LogicalType::UBIGINT, LogicalType::JSON());

// signed
// GetArrayPrependFunctionInternal(set, LogicalType::BIGINT, LogicalType::JSON());

// Allows for floating types
// FLOAT is covered by automatic upfront casting to double
// GetArrayPrependFunctionInternal(set, LogicalType::DOUBLE, LogicalType::JSON());

// Allows for json and string values
GetArrayPrependFunctionInternal(set, LogicalType::JSON(), LogicalType::JSON());
GetArrayPrependFunctionInternal(set, LogicalType::VARCHAR, LogicalType::JSON());

return set;
}
Expand Down
4 changes: 2 additions & 2 deletions extension/json/json_functions/json_array_remove.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ static void GetArrayRemoveElementFunctionInternal(ScalarFunctionSet &set, const

static void GetArrayRemoveRangeFunctionInternal(ScalarFunctionSet &set, const LogicalType &fst, const LogicalType &snd,
const LogicalType &thrd) {
set.AddFunction(ScalarFunction("json_array_remove", {fst, snd, thrd}, LogicalType::JSON(),
ArrayRemoveRangeFunction, nullptr, nullptr, nullptr, JSONFunctionLocalState::Init));
set.AddFunction(ScalarFunction("json_array_remove", {fst, snd, thrd}, LogicalType::JSON(), ArrayRemoveRangeFunction,
nullptr, nullptr, nullptr, JSONFunctionLocalState::Init));
}

ScalarFunctionSet JSONFunctions::GetArrayRemoveFunction() {
Expand Down
4 changes: 2 additions & 2 deletions extension/json/json_functions/json_array_rotate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ static void ArrayRotateFunction(DataChunk &args, ExpressionState &state, Vector
}

static void GetArrayRotateFunctionInternal(ScalarFunctionSet &set, const LogicalType &fst, const LogicalType &snd) {
set.AddFunction(ScalarFunction("json_array_rotate", {fst, snd}, LogicalType::JSON(), ArrayRotateFunction,
nullptr, nullptr, nullptr, JSONFunctionLocalState::Init));
set.AddFunction(ScalarFunction("json_array_rotate", {fst, snd}, LogicalType::JSON(), ArrayRotateFunction, nullptr,
nullptr, nullptr, JSONFunctionLocalState::Init));
}

ScalarFunctionSet JSONFunctions::GetArrayRotateFunction() {
Expand Down
Loading

0 comments on commit 7bb90e4

Please sign in to comment.