Add validation of array data

This commit is contained in:
alesapin 2018-10-29 16:18:41 +03:00
parent 713c44c3db
commit 444b6e1e43

View File

@ -2,6 +2,7 @@
#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>
@ -29,6 +30,20 @@ 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)
{
@ -116,14 +131,15 @@ 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());
if (value.isNull())
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)))
{
/// Check that we are indeed allowed to insert a NULL.
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};
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);