mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-10 09:32:06 +00:00
Forbid Nullable for JSONExtract* (JSONExtract() still supports Nullable)
Only JSONExtract() can support Nullable, others JSONExtract* (JSONExtractString and similar) does not. And right now this file is pretty complex already, so adding support of Nullable for others will make it even more complex. CI: https://clickhouse-test-reports.s3.yandex.net/29680/d0fc26f91a0141b56a0550741219c3dc43630e03/fuzzer_ubsan/report.html#fail1
This commit is contained in:
parent
613b814e24
commit
20e706766c
@ -304,19 +304,32 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
template <class Parser>
|
||||||
|
ColumnPtr
|
||||||
|
chooseAndRunJSONParserOne(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const
|
||||||
|
{
|
||||||
|
/// Only implementations with prepare() can handle NULL.
|
||||||
|
///
|
||||||
|
/// (and right now this file is pretty complex already, and adding
|
||||||
|
/// support of Nullable for others will make it even more complex)
|
||||||
|
if (null_presence.has_nullable && !Impl<Parser>::supportNullable())
|
||||||
|
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "{} does not support Nullable", Name::name);
|
||||||
|
|
||||||
|
return FunctionJSONHelpers::Executor<Name, Impl, Parser>::run(arguments, result_type, input_rows_count);
|
||||||
|
}
|
||||||
|
|
||||||
ColumnPtr
|
ColumnPtr
|
||||||
chooseAndRunJSONParser(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const
|
chooseAndRunJSONParser(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const
|
||||||
{
|
{
|
||||||
#if USE_SIMDJSON
|
#if USE_SIMDJSON
|
||||||
if (allow_simdjson)
|
if (allow_simdjson)
|
||||||
return FunctionJSONHelpers::Executor<Name, Impl, SimdJSONParser>::run(arguments, result_type, input_rows_count);
|
return chooseAndRunJSONParserOne<SimdJSONParser>(arguments, result_type, input_rows_count);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if USE_RAPIDJSON
|
#if USE_RAPIDJSON
|
||||||
return FunctionJSONHelpers::Executor<Name, Impl, RapidJSONParser>::run(arguments, result_type, input_rows_count);
|
return chooseAndRunJSONParserOne<RapidJSONParser>(arguments, result_type, input_rows_count);
|
||||||
#else
|
#else
|
||||||
return FunctionJSONHelpers::Executor<Name, Impl, DummyJSONParser>::run(arguments, result_type, input_rows_count);
|
return chooseAndRunJSONParserOne<DummyJSONParser>(arguments, result_type, input_rows_count);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -433,6 +446,7 @@ public:
|
|||||||
static DataTypePtr getReturnType(const char *, const ColumnsWithTypeAndName &) { return std::make_shared<DataTypeUInt8>(); }
|
static DataTypePtr getReturnType(const char *, const ColumnsWithTypeAndName &) { return std::make_shared<DataTypeUInt8>(); }
|
||||||
|
|
||||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
||||||
|
static bool supportNullable() { return false; }
|
||||||
|
|
||||||
static bool insertResultToColumn(IColumn & dest, const Element &, const std::string_view &)
|
static bool insertResultToColumn(IColumn & dest, const Element &, const std::string_view &)
|
||||||
{
|
{
|
||||||
@ -461,6 +475,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName &) { return 0; }
|
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName &) { return 0; }
|
||||||
|
static bool supportNullable() { return false; }
|
||||||
|
|
||||||
static bool insertResultToColumn(IColumn & dest, const Element &, const std::string_view &)
|
static bool insertResultToColumn(IColumn & dest, const Element &, const std::string_view &)
|
||||||
{
|
{
|
||||||
@ -485,6 +500,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
||||||
|
static bool supportNullable() { return false; }
|
||||||
|
|
||||||
static bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
static bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
||||||
{
|
{
|
||||||
@ -515,6 +531,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
||||||
|
static bool supportNullable() { return false; }
|
||||||
|
|
||||||
static bool insertResultToColumn(IColumn & dest, const Element &, const std::string_view & last_key)
|
static bool insertResultToColumn(IColumn & dest, const Element &, const std::string_view & last_key)
|
||||||
{
|
{
|
||||||
@ -549,6 +566,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
||||||
|
static bool supportNullable() { return false; }
|
||||||
|
|
||||||
static bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
static bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
||||||
{
|
{
|
||||||
@ -591,6 +609,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
||||||
|
static bool supportNullable() { return false; }
|
||||||
|
|
||||||
static bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
static bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
||||||
{
|
{
|
||||||
@ -666,6 +685,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
||||||
|
static bool supportNullable() { return false; }
|
||||||
|
|
||||||
static bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
static bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
||||||
{
|
{
|
||||||
@ -691,6 +711,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
||||||
|
static bool supportNullable() { return false; }
|
||||||
|
|
||||||
static bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
static bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
||||||
{
|
{
|
||||||
@ -1090,6 +1111,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 2; }
|
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 2; }
|
||||||
|
static bool supportNullable() { return true; }
|
||||||
|
|
||||||
void prepare(const char * function_name, const ColumnsWithTypeAndName &, const DataTypePtr & result_type)
|
void prepare(const char * function_name, const ColumnsWithTypeAndName &, const DataTypePtr & result_type)
|
||||||
{
|
{
|
||||||
@ -1131,6 +1153,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 2; }
|
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 2; }
|
||||||
|
static bool supportNullable() { return true; }
|
||||||
|
|
||||||
void prepare(const char * function_name, const ColumnsWithTypeAndName &, const DataTypePtr & result_type)
|
void prepare(const char * function_name, const ColumnsWithTypeAndName &, const DataTypePtr & result_type)
|
||||||
{
|
{
|
||||||
@ -1182,6 +1205,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
||||||
|
static bool supportNullable() { return false; }
|
||||||
|
|
||||||
static bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
static bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
||||||
{
|
{
|
||||||
@ -1286,6 +1310,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
||||||
|
static bool supportNullable() { return false; }
|
||||||
|
|
||||||
static bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
static bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
||||||
{
|
{
|
||||||
@ -1318,6 +1343,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
||||||
|
static bool supportNullable() { return false; }
|
||||||
|
|
||||||
bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
||||||
{
|
{
|
||||||
|
19
tests/queries/0_stateless/02045_json_extract_null.reference
Normal file
19
tests/queries/0_stateless/02045_json_extract_null.reference
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
-- { echoOn }
|
||||||
|
SELECT JSONExtractInt('[1]', toNullable(1)); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
|
||||||
|
SELECT JSONExtractUInt('[1]', toNullable(1)); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
|
||||||
|
SELECT JSONExtractBool('[1]', toNullable(1)); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
|
||||||
|
SELECT JSONExtractFloat('[1]', toNullable(1)); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
|
||||||
|
SELECT JSONExtractString('["a"]', toNullable(1)); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
|
||||||
|
SELECT JSONExtractArrayRaw('["1"]', toNullable(1)); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
|
||||||
|
SELECT JSONExtractKeysAndValuesRaw('["1"]', toNullable(1)); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
|
||||||
|
SELECT JSONExtractKeysAndValues('["1"]', toNullable(1)); -- { serverError ILLEGAL_COLUMN }
|
||||||
|
SELECT JSONExtract('[1]', toNullable(1), 'Nullable(Int)');
|
||||||
|
1
|
||||||
|
SELECT JSONExtract('[1]', toNullable(1), 'Nullable(UInt8)');
|
||||||
|
1
|
||||||
|
SELECT JSONExtract('[1]', toNullable(1), 'Nullable(Bool)');
|
||||||
|
1
|
||||||
|
SELECT JSONExtract('[1]', toNullable(1), 'Nullable(Float)');
|
||||||
|
1
|
||||||
|
SELECT JSONExtract('["a"]', toNullable(1), 'Nullable(String)');
|
||||||
|
a
|
21
tests/queries/0_stateless/02045_json_extract_null.sql
Normal file
21
tests/queries/0_stateless/02045_json_extract_null.sql
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
-- Tags: no-fasttest
|
||||||
|
|
||||||
|
-- to avoid merging Tags and echoOn
|
||||||
|
SELECT 1 FORMAT Null;
|
||||||
|
|
||||||
|
-- { echoOn }
|
||||||
|
SELECT JSONExtractInt('[1]', toNullable(1)); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
|
||||||
|
SELECT JSONExtractUInt('[1]', toNullable(1)); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
|
||||||
|
SELECT JSONExtractBool('[1]', toNullable(1)); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
|
||||||
|
SELECT JSONExtractFloat('[1]', toNullable(1)); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
|
||||||
|
SELECT JSONExtractString('["a"]', toNullable(1)); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
|
||||||
|
|
||||||
|
SELECT JSONExtractArrayRaw('["1"]', toNullable(1)); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
|
||||||
|
SELECT JSONExtractKeysAndValuesRaw('["1"]', toNullable(1)); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
|
||||||
|
SELECT JSONExtractKeysAndValues('["1"]', toNullable(1)); -- { serverError ILLEGAL_COLUMN }
|
||||||
|
|
||||||
|
SELECT JSONExtract('[1]', toNullable(1), 'Nullable(Int)');
|
||||||
|
SELECT JSONExtract('[1]', toNullable(1), 'Nullable(UInt8)');
|
||||||
|
SELECT JSONExtract('[1]', toNullable(1), 'Nullable(Bool)');
|
||||||
|
SELECT JSONExtract('[1]', toNullable(1), 'Nullable(Float)');
|
||||||
|
SELECT JSONExtract('["a"]', toNullable(1), 'Nullable(String)');
|
Loading…
Reference in New Issue
Block a user