Fix nullable processing in JSONFunctions

This commit is contained in:
Amos Bird 2021-10-02 12:20:56 +08:00
parent a391b64f57
commit a34a08268b
No known key found for this signature in database
GPG Key ID: 80D430DCBECFEDB4
3 changed files with 27 additions and 9 deletions

View File

@ -282,8 +282,8 @@ class ExecutableFunctionJSON : public IExecutableFunction, WithContext
{ {
public: public:
explicit ExecutableFunctionJSON(const NullPresence & null_presence_, bool allow_simdjson_) explicit ExecutableFunctionJSON(const NullPresence & null_presence_, bool allow_simdjson_, const DataTypePtr & json_return_type_)
: null_presence(null_presence_), allow_simdjson(allow_simdjson_) : null_presence(null_presence_), allow_simdjson(allow_simdjson_), json_return_type(json_return_type_)
{ {
} }
@ -297,7 +297,7 @@ public:
return result_type->createColumnConstWithDefaultValue(input_rows_count); return result_type->createColumnConstWithDefaultValue(input_rows_count);
ColumnsWithTypeAndName temporary_columns = null_presence.has_nullable ? createBlockWithNestedColumns(arguments) : arguments; ColumnsWithTypeAndName temporary_columns = null_presence.has_nullable ? createBlockWithNestedColumns(arguments) : arguments;
ColumnPtr temporary_result = chooseAndRunJSONParser(temporary_columns, result_type, input_rows_count); ColumnPtr temporary_result = chooseAndRunJSONParser(temporary_columns, json_return_type, input_rows_count);
if (null_presence.has_nullable) if (null_presence.has_nullable)
return wrapInNullable(temporary_result, arguments, result_type, input_rows_count); return wrapInNullable(temporary_result, arguments, result_type, input_rows_count);
return temporary_result; return temporary_result;
@ -322,6 +322,7 @@ private:
NullPresence null_presence; NullPresence null_presence;
bool allow_simdjson; bool allow_simdjson;
DataTypePtr json_return_type;
}; };
@ -330,11 +331,16 @@ class FunctionBaseFunctionJSON : public IFunctionBase
{ {
public: public:
explicit FunctionBaseFunctionJSON( explicit FunctionBaseFunctionJSON(
const NullPresence & null_presence_, bool allow_simdjson_, DataTypes argument_types_, DataTypePtr return_type_) const NullPresence & null_presence_,
bool allow_simdjson_,
DataTypes argument_types_,
DataTypePtr return_type_,
DataTypePtr json_return_type_)
: null_presence(null_presence_) : null_presence(null_presence_)
, allow_simdjson(allow_simdjson_) , allow_simdjson(allow_simdjson_)
, argument_types(std::move(argument_types_)) , argument_types(std::move(argument_types_))
, return_type(std::move(return_type_)) , return_type(std::move(return_type_))
, json_return_type(std::move(json_return_type_))
{ {
} }
@ -354,7 +360,7 @@ public:
ExecutableFunctionPtr prepare(const ColumnsWithTypeAndName &) const override ExecutableFunctionPtr prepare(const ColumnsWithTypeAndName &) const override
{ {
return std::make_unique<ExecutableFunctionJSON<Name, Impl>>(null_presence, allow_simdjson); return std::make_unique<ExecutableFunctionJSON<Name, Impl>>(null_presence, allow_simdjson, json_return_type);
} }
private: private:
@ -362,6 +368,7 @@ private:
bool allow_simdjson; bool allow_simdjson;
DataTypes argument_types; DataTypes argument_types;
DataTypePtr return_type; DataTypePtr return_type;
DataTypePtr json_return_type;
}; };
@ -388,21 +395,25 @@ public:
FunctionBasePtr build(const ColumnsWithTypeAndName & arguments) const override FunctionBasePtr build(const ColumnsWithTypeAndName & arguments) const override
{ {
DataTypePtr json_return_type = Impl<DummyJSONParser>::getReturnType(Name::name, createBlockWithNestedColumns(arguments));
NullPresence null_presence = getNullPresense(arguments); NullPresence null_presence = getNullPresense(arguments);
DataTypePtr return_type; DataTypePtr return_type;
if (null_presence.has_null_constant) if (null_presence.has_null_constant)
return_type = makeNullable(std::make_shared<DataTypeNothing>()); return_type = makeNullable(std::make_shared<DataTypeNothing>());
else if (null_presence.has_nullable) else if (null_presence.has_nullable)
return_type = makeNullable(Impl<DummyJSONParser>::getReturnType(Name::name, createBlockWithNestedColumns(arguments))); return_type = makeNullable(json_return_type);
else else
return_type = Impl<DummyJSONParser>::getReturnType(Name::name, arguments); return_type = json_return_type;
/// Top-level LowCardinality columns are processed outside JSON parser.
json_return_type = removeLowCardinality(json_return_type);
DataTypes argument_types; DataTypes argument_types;
argument_types.reserve(arguments.size()); argument_types.reserve(arguments.size());
for (const auto & argument : arguments) for (const auto & argument : arguments)
argument_types.emplace_back(argument.type); argument_types.emplace_back(argument.type);
return std::make_unique<FunctionBaseFunctionJSON<Name, Impl>>( return std::make_unique<FunctionBaseFunctionJSON<Name, Impl>>(
null_presence, getContext()->getSettingsRef().allow_simdjson, argument_types, return_type); null_presence, getContext()->getSettingsRef().allow_simdjson, argument_types, return_type, json_return_type);
} }
}; };

View File

@ -1,6 +1,12 @@
\N Nullable(String) \N Nullable(String)
String String
\N Nullable(String) \N Nullable(String)
\N Nullable(String) Nullable(String)
\N Nullable(Nothing) \N Nullable(Nothing)
\N Nullable(Nothing) \N Nullable(Nothing)
b
\N
c

View File

@ -6,3 +6,4 @@ SELECT JSONExtract(toNullable('{"string_value":null}'), 'string_value', 'Nullabl
SELECT JSONExtract(toNullable('{"string_value":null}'), 'string_value', 'String') as x, toTypeName(x); SELECT JSONExtract(toNullable('{"string_value":null}'), 'string_value', 'String') as x, toTypeName(x);
SELECT JSONExtract(NULL, 'string_value', 'Nullable(String)') as x, toTypeName(x); SELECT JSONExtract(NULL, 'string_value', 'Nullable(String)') as x, toTypeName(x);
SELECT JSONExtract(NULL, 'string_value', 'String') as x, toTypeName(x); SELECT JSONExtract(NULL, 'string_value', 'String') as x, toTypeName(x);
SELECT JSONExtractString('["a", "b", "c", "d", "e"]', idx) FROM (SELECT arrayJoin([2, NULL, 2147483646, 65535, 65535, 3]) AS idx);