[function](json) Json unquote (#18037)
This commit is contained in:
@ -933,11 +933,81 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class FunctionJsonUnquote : public IFunction {
|
||||
public:
|
||||
static constexpr auto name = "json_unquote";
|
||||
static FunctionPtr create() { return std::make_shared<FunctionJsonUnquote>(); }
|
||||
|
||||
String get_name() const override { return name; }
|
||||
|
||||
size_t get_number_of_arguments() const override { return 1; }
|
||||
|
||||
DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
|
||||
return make_nullable(std::make_shared<DataTypeString>());
|
||||
}
|
||||
|
||||
bool use_default_implementation_for_nulls() const override { return false; }
|
||||
|
||||
bool use_default_implementation_for_constants() const override { return true; }
|
||||
|
||||
Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
|
||||
size_t result, size_t input_rows_count) override {
|
||||
const IColumn& col_from = *(block.get_by_position(arguments[0]).column);
|
||||
|
||||
auto null_map = ColumnUInt8::create(input_rows_count, 0);
|
||||
|
||||
const ColumnString* col_from_string = check_and_get_column<ColumnString>(col_from);
|
||||
if (auto* nullable = check_and_get_column<ColumnNullable>(col_from)) {
|
||||
col_from_string =
|
||||
check_and_get_column<ColumnString>(*nullable->get_nested_column_ptr());
|
||||
}
|
||||
|
||||
if (!col_from_string) {
|
||||
return Status::RuntimeError("Illegal column {} should be ColumnString",
|
||||
col_from.get_name());
|
||||
}
|
||||
|
||||
auto col_to = ColumnString::create();
|
||||
col_to->reserve(input_rows_count);
|
||||
|
||||
// parser can be reused for performance
|
||||
rapidjson::Document document;
|
||||
for (size_t i = 0; i < input_rows_count; ++i) {
|
||||
if (col_from.is_null_at(i)) {
|
||||
null_map->get_data()[i] = 1;
|
||||
col_to->insert_data(nullptr, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto& json_str = col_from_string->get_data_at(i);
|
||||
if (json_str.size < 2 || json_str.data[0] != '"' ||
|
||||
json_str.data[json_str.size - 1] != '"') {
|
||||
// non-quoted string
|
||||
col_to->insert_data(json_str.data, json_str.size);
|
||||
} else {
|
||||
document.Parse(json_str.data, json_str.size);
|
||||
if (document.HasParseError() || !document.IsString()) {
|
||||
return Status::RuntimeError(
|
||||
fmt::format("Invalid JSON text in argument 1 to function {}: {}", name,
|
||||
std::string_view(json_str.data, json_str.size)));
|
||||
}
|
||||
col_to->insert_data(document.GetString(), document.GetStringLength());
|
||||
}
|
||||
}
|
||||
|
||||
block.replace_by_position(result,
|
||||
ColumnNullable::create(std::move(col_to), std::move(null_map)));
|
||||
|
||||
return Status::OK();
|
||||
}
|
||||
};
|
||||
|
||||
void register_function_json(SimpleFunctionFactory& factory) {
|
||||
factory.register_function<FunctionGetJsonInt>();
|
||||
factory.register_function<FunctionGetJsonBigInt>();
|
||||
factory.register_function<FunctionGetJsonDouble>();
|
||||
factory.register_function<FunctionGetJsonString>();
|
||||
factory.register_function<FunctionJsonUnquote>();
|
||||
|
||||
factory.register_function<FunctionJsonAlwaysNotNullable<FunctionJsonArrayImpl>>();
|
||||
factory.register_function<FunctionJsonAlwaysNotNullable<FunctionJsonObjectImpl>>();
|
||||
|
||||
Reference in New Issue
Block a user