Replace null fields in tuple during parsing with default values

This commit is contained in:
Maksim Kita 2021-02-15 21:53:24 +03:00
parent 6946514c0b
commit 8520fc3e4c
2 changed files with 43 additions and 0 deletions

View File

@ -36,6 +36,7 @@ namespace ErrorCodes
{ {
extern const int LOGICAL_ERROR; extern const int LOGICAL_ERROR;
extern const int SYNTAX_ERROR; extern const int SYNTAX_ERROR;
extern const int TYPE_MISMATCH;
} }
@ -209,6 +210,14 @@ private:
if (map.size() % 2) if (map.size() % 2)
return false; return false;
} }
else if (literal->value.getType() == Field::Types::Tuple)
{
const Tuple & tuple = literal->value.get<Tuple>();
for (const auto & value : tuple)
if (value.isNull())
return true;
}
String column_name = "_dummy_" + std::to_string(replaced_literals.size()); String column_name = "_dummy_" + std::to_string(replaced_literals.size());
replaced_literals.emplace_back(literal, column_name, force_nullable); replaced_literals.emplace_back(literal, column_name, force_nullable);

View File

@ -12,6 +12,7 @@
#include <common/find_symbols.h> #include <common/find_symbols.h>
#include <Parsers/ASTLiteral.h> #include <Parsers/ASTLiteral.h>
#include <DataTypes/DataTypeNullable.h> #include <DataTypes/DataTypeNullable.h>
#include <DataTypes/DataTypeTuple.h>
namespace DB namespace DB
@ -181,6 +182,35 @@ bool ValuesBlockInputFormat::tryReadValue(IColumn & column, size_t column_idx)
} }
} }
namespace
{
void tryToReplaceNullFieldsInTupleWithDefaultValues(Field & value, const IDataType & type)
{
const DataTypeTuple * type_tuple = typeid_cast<const DataTypeTuple *>(&type);
if (!type_tuple || value.getType() != Field::Types::Tuple)
return;
Tuple & tuple_value = value.get<Tuple>();
size_t src_tuple_size = tuple_value.size();
size_t dst_tuple_size = type_tuple->getElements().size();
if (src_tuple_size != dst_tuple_size)
throw Exception("Bad size of tuple. Expected size: " + std::to_string(src_tuple_size) + ", actual size: " + std::to_string(dst_tuple_size), ErrorCodes::TYPE_MISMATCH);
for (size_t i = 0; i < src_tuple_size; ++i)
{
const auto & element_type = *(type_tuple->getElements()[i]);
if (tuple_value[i].isNull() && !element_type.isNullable())
tuple_value[i] = element_type.getDefault();
tryToReplaceNullFieldsInTupleWithDefaultValues(tuple_value[i], element_type);
}
}
}
bool ValuesBlockInputFormat::parseExpression(IColumn & column, size_t column_idx) bool ValuesBlockInputFormat::parseExpression(IColumn & column, size_t column_idx)
{ {
const Block & header = getPort().getHeader(); const Block & header = getPort().getHeader();
@ -298,6 +328,10 @@ bool ValuesBlockInputFormat::parseExpression(IColumn & column, size_t column_idx
buf.position() = const_cast<char *>(token_iterator->begin); buf.position() = const_cast<char *>(token_iterator->begin);
std::pair<Field, DataTypePtr> value_raw = evaluateConstantExpression(ast, *context); std::pair<Field, DataTypePtr> value_raw = evaluateConstantExpression(ast, *context);
if (format_settings.null_as_default)
tryToReplaceNullFieldsInTupleWithDefaultValues(value_raw.first, type);
Field value = convertFieldToType(value_raw.first, type, value_raw.second.get()); Field value = convertFieldToType(value_raw.first, type, value_raw.second.get());
/// Check that we are indeed allowed to insert a NULL. /// Check that we are indeed allowed to insert a NULL.