[fix](function)return NULL rather than 'null' if path not found (#25880)

fix json_extract not return NULL but null
This commit is contained in:
Yulei-Yang
2023-10-30 14:26:44 +08:00
committed by GitHub
parent 0d956e90cf
commit 3a954cd1aa
8 changed files with 137 additions and 100 deletions

View File

@ -815,7 +815,7 @@ struct FunctionJsonExtractImpl {
}
static void execute(const std::vector<const ColumnString*>& data_columns,
ColumnString& result_column, size_t input_rows_count) {
ColumnString& result_column, NullMap& null_map, size_t input_rows_count) {
rapidjson::Document document;
rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
rapidjson::StringBuffer buf;
@ -835,11 +835,16 @@ struct FunctionJsonExtractImpl {
}
}
// write value as string
buf.Clear();
writer.Reset(buf);
value.Accept(writer);
result_column.insert_data(buf.GetString(), buf.GetSize());
if (value.IsNull()) {
null_map[row] = 1;
result_column.insert_default();
} else {
// write value as string
buf.Clear();
writer.Reset(buf);
value.Accept(writer);
result_column.insert_data(buf.GetString(), buf.GetSize());
}
}
}
};
@ -880,6 +885,37 @@ public:
}
};
template <typename Impl>
class FunctionJsonNullable : public IFunction {
public:
static constexpr auto name = Impl::name;
static FunctionPtr create() { return std::make_shared<FunctionJsonNullable<Impl>>(); }
String get_name() const override { return name; }
size_t get_number_of_arguments() const override { return 0; }
bool is_variadic() const override { return true; }
bool use_default_implementation_for_constants() const override { return true; }
DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
return make_nullable(std::make_shared<DataTypeString>());
}
Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
size_t result, size_t input_rows_count) const override {
auto result_column = ColumnString::create();
auto null_map = ColumnUInt8::create(input_rows_count, 0);
std::vector<ColumnPtr> column_ptrs; // prevent converted column destruct
std::vector<const ColumnString*> data_columns;
for (int i = 0; i < arguments.size(); i++) {
column_ptrs.push_back(
block.get_by_position(arguments[i]).column->convert_to_full_column_if_const());
data_columns.push_back(assert_cast<const ColumnString*>(column_ptrs.back().get()));
}
Impl::execute(data_columns, *assert_cast<ColumnString*>(result_column.get()),
null_map->get_data(), input_rows_count);
block.replace_by_position(
result, ColumnNullable::create(std::move(result_column), std::move(null_map)));
return Status::OK();
}
};
using FunctionGetJsonDouble = FunctionBinaryStringOperateToNullType<GetJsonDouble>;
using FunctionGetJsonInt = FunctionBinaryStringOperateToNullType<GetJsonInt>;
using FunctionGetJsonBigInt = FunctionBinaryStringOperateToNullType<GetJsonBigInt>;
@ -1476,7 +1512,7 @@ void register_function_json(SimpleFunctionFactory& factory) {
factory.register_function<FunctionJsonAlwaysNotNullable<FunctionJsonArrayImpl>>();
factory.register_function<FunctionJsonAlwaysNotNullable<FunctionJsonObjectImpl>>();
factory.register_function<FunctionJson<FunctionJsonQuoteImpl>>();
factory.register_function<FunctionJson<FunctionJsonExtractImpl>>();
factory.register_function<FunctionJsonNullable<FunctionJsonExtractImpl>>();
factory.register_function<FunctionJsonValid>();
factory.register_function<FunctionJsonContains>();