mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-22 07:31:57 +00:00
Merge pull request #3503 from yandex/check_array_value_null
Better code for check on null values inside array IN expression
This commit is contained in:
commit
121f04522e
@ -2,7 +2,6 @@
|
||||
#include <Interpreters/evaluateConstantExpression.h>
|
||||
#include <Interpreters/Context.h>
|
||||
#include <Interpreters/convertFieldToType.h>
|
||||
#include <DataTypes/DataTypeArray.h>
|
||||
#include <Parsers/TokenIterator.h>
|
||||
#include <Parsers/ExpressionListParsers.h>
|
||||
#include <Formats/ValuesRowInputStream.h>
|
||||
@ -30,20 +29,6 @@ namespace ErrorCodes
|
||||
}
|
||||
|
||||
|
||||
bool is_array_type_compatible(const DataTypeArray & type, const Field & value)
|
||||
{
|
||||
if (type.getNestedType()->isNullable())
|
||||
return true;
|
||||
|
||||
const Array & array = DB::get<const Array &>(value);
|
||||
size_t size = array.size();
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
if (array[i].isNull())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ValuesRowInputStream::ValuesRowInputStream(ReadBuffer & istr_, const Block & header_, const Context & context_, const FormatSettings & format_settings)
|
||||
: istr(istr_), header(header_), context(std::make_unique<Context>(context_)), format_settings(format_settings)
|
||||
{
|
||||
@ -131,15 +116,14 @@ bool ValuesRowInputStream::read(MutableColumns & columns)
|
||||
std::pair<Field, DataTypePtr> value_raw = evaluateConstantExpression(ast, *context);
|
||||
Field value = convertFieldToType(value_raw.first, type, value_raw.second.get());
|
||||
|
||||
const auto * array_type = typeid_cast<const DataTypeArray *>(&type);
|
||||
|
||||
/// Check that we are indeed allowed to insert a NULL.
|
||||
if ((value.isNull() && !type.isNullable()) || (array_type && !is_array_type_compatible(*array_type, value)))
|
||||
if (value.isNull())
|
||||
{
|
||||
throw Exception{"Expression returns value " + applyVisitor(FieldVisitorToString(), value)
|
||||
+ ", that is out of range of type " + type.getName()
|
||||
+ ", at: " + String(prev_istr_position, std::min(SHOW_CHARS_ON_SYNTAX_ERROR, istr.buffer().end() - prev_istr_position)),
|
||||
ErrorCodes::VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE};
|
||||
if (!type.isNullable())
|
||||
throw Exception{"Expression returns value " + applyVisitor(FieldVisitorToString(), value)
|
||||
+ ", that is out of range of type " + type.getName()
|
||||
+ ", at: " + String(prev_istr_position, std::min(SHOW_CHARS_ON_SYNTAX_ERROR, istr.buffer().end() - prev_istr_position)),
|
||||
ErrorCodes::VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE};
|
||||
}
|
||||
|
||||
columns[i]->insert(value);
|
||||
|
@ -218,7 +218,12 @@ Field convertFieldToTypeImpl(const Field & src, const IDataType & type, const ID
|
||||
|
||||
Array res(src_arr_size);
|
||||
for (size_t i = 0; i < src_arr_size; ++i)
|
||||
{
|
||||
res[i] = convertFieldToType(src_arr[i], *nested_type);
|
||||
if (res[i].isNull() && !type_array->getNestedType()->isNullable())
|
||||
throw Exception("Type mismatch of array elements in IN or VALUES section. Expected: " + type_array->getNestedType()->getName()
|
||||
+ ". Got NULL in position " + toString(i + 1), ErrorCodes::TYPE_MISMATCH);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
['aaaaa','bbbbb','ccccc']
|
@ -0,0 +1,11 @@
|
||||
DROP TABLE IF EXISTS test.arraytest;
|
||||
|
||||
CREATE TABLE test.arraytest ( created_date Date DEFAULT toDate(created_at), created_at DateTime DEFAULT now(), strings Array(String) DEFAULT emptyArrayString()) ENGINE = MergeTree(created_date, cityHash64(created_at), (created_date, cityHash64(created_at)), 8192);
|
||||
|
||||
INSERT INTO test.arraytest (created_at, strings) VALUES (now(), ['aaaaa', 'bbbbb', 'ccccc']);
|
||||
INSERT INTO test.arraytest (created_at, strings) VALUES (now(), ['aaaaa', 'bbbbb', null]); -- { clientError 53 }
|
||||
|
||||
SELECT strings from test.arraytest;
|
||||
|
||||
DROP TABLE IF EXISTS test.arraytest;
|
||||
|
Loading…
Reference in New Issue
Block a user