If for Nullable types: additions [#CLICKHOUSE-2873].

This commit is contained in:
Alexey Milovidov 2017-03-07 23:42:01 +03:00
parent e20441eee6
commit fe24bb25a0
3 changed files with 37 additions and 12 deletions

View File

@ -85,6 +85,7 @@ public:
/// map of the result column of a function taking one or more nullable /// map of the result column of a function taking one or more nullable
/// columns. /// columns.
void applyNullValuesByteMap(const ColumnNullable & other); void applyNullValuesByteMap(const ColumnNullable & other);
void applyNullValuesByteMap(const ColumnUInt8 & map);
private: private:
ColumnPtr nested_column; ColumnPtr nested_column;

View File

@ -1315,8 +1315,8 @@ private:
bool executeForNullableCondition(Block & block, const ColumnNumbers & arguments, size_t result) bool executeForNullableCondition(Block & block, const ColumnNumbers & arguments, size_t result)
{ {
const ColumnWithTypeAndName & arg_cond = block.safeGetByPosition(arguments[0]); const ColumnWithTypeAndName & arg_cond = block.safeGetByPosition(arguments[0]);
bool cond_is_null = typeid_cast<const ColumnNull *>(arg_cond.column.get()); bool cond_is_null = arg_cond.column->isNull();
bool cond_is_nullable = typeid_cast<const ColumnNullable *>(arg_cond.column.get()); bool cond_is_nullable = arg_cond.column->isNullable();
if (cond_is_null) if (cond_is_null)
{ {
@ -1399,8 +1399,8 @@ private:
const ColumnWithTypeAndName & arg_then = block.safeGetByPosition(arguments[1]); const ColumnWithTypeAndName & arg_then = block.safeGetByPosition(arguments[1]);
const ColumnWithTypeAndName & arg_else = block.safeGetByPosition(arguments[2]); const ColumnWithTypeAndName & arg_else = block.safeGetByPosition(arguments[2]);
bool then_is_null = typeid_cast<const ColumnNull *>(arg_then.column.get()); bool then_is_null = arg_then.column->isNull();
bool else_is_null = typeid_cast<const ColumnNull *>(arg_else.column.get()); bool else_is_null = arg_else.column->isNull();
if (!then_is_null && !else_is_null) if (!then_is_null && !else_is_null)
return false; return false;
@ -1414,13 +1414,22 @@ private:
const ColumnUInt8 * cond_col = typeid_cast<const ColumnUInt8 *>(arg_cond.column.get()); const ColumnUInt8 * cond_col = typeid_cast<const ColumnUInt8 *>(arg_cond.column.get());
const ColumnConst<UInt8> * cond_const_col = typeid_cast<const ColumnConst<UInt8> *>(arg_cond.column.get()); const ColumnConst<UInt8> * cond_const_col = typeid_cast<const ColumnConst<UInt8> *>(arg_cond.column.get());
/// If then is NULL, we create Nullable column with condition as null mask. /// If then is NULL, we create Nullable column with null mask OR-ed with condition.
if (then_is_null) if (then_is_null)
{ {
if (cond_col) if (cond_col)
{ {
block.safeGetByPosition(result).column = std::make_shared<ColumnNullable>( if (arg_else.column->isNullable())
materializeColumnIfConst(arg_else.column), arg_cond.column->clone()); {
auto result_column = arg_else.column->clone();
static_cast<ColumnNullable &>(*result_column).applyNullValuesByteMap(static_cast<const ColumnUInt8 &>(*arg_cond.column));
block.safeGetByPosition(result).column = result_column;
}
else
{
block.safeGetByPosition(result).column = std::make_shared<ColumnNullable>(
materializeColumnIfConst(arg_else.column), arg_cond.column->clone());
}
} }
else if (cond_const_col) else if (cond_const_col)
{ {
@ -1435,7 +1444,7 @@ private:
return true; return true;
} }
/// If else is NULL, we create Nullable column with negated condition as null mask. /// If else is NULL, we create Nullable column with null mask OR-ed with negated condition.
if (else_is_null) if (else_is_null)
{ {
if (cond_col) if (cond_col)
@ -1450,8 +1459,17 @@ private:
for (size_t i = 0; i < size; ++i) for (size_t i = 0; i < size; ++i)
negated_null_map_data[i] = !null_map_data[i]; negated_null_map_data[i] = !null_map_data[i];
block.safeGetByPosition(result).column = std::make_shared<ColumnNullable>( if (arg_then.column->isNullable())
materializeColumnIfConst(arg_then.column), negated_null_map); {
auto result_column = arg_then.column->clone();
static_cast<ColumnNullable &>(*result_column).applyNullValuesByteMap(static_cast<const ColumnUInt8 &>(*arg_cond.column));
block.safeGetByPosition(result).column = result_column;
}
else
{
block.safeGetByPosition(result).column = std::make_shared<ColumnNullable>(
materializeColumnIfConst(arg_then.column), negated_null_map);
}
} }
else if (cond_const_col) else if (cond_const_col)
{ {

View File

@ -365,10 +365,10 @@ ColumnPtr ColumnNullable::replicate(const Offsets_t & offsets) const
} }
void ColumnNullable::applyNullValuesByteMap(const ColumnNullable & other) void ColumnNullable::applyNullValuesByteMap(const ColumnUInt8 & map)
{ {
NullValuesByteMap & arr1 = getNullMap(); NullValuesByteMap & arr1 = getNullMap();
const NullValuesByteMap & arr2 = other.getNullMap(); const NullValuesByteMap & arr2 = map.getData();
if (arr1.size() != arr2.size()) if (arr1.size() != arr2.size())
throw Exception{"Inconsistent sizes of ColumnNullable objects", ErrorCodes::LOGICAL_ERROR}; throw Exception{"Inconsistent sizes of ColumnNullable objects", ErrorCodes::LOGICAL_ERROR};
@ -377,4 +377,10 @@ void ColumnNullable::applyNullValuesByteMap(const ColumnNullable & other)
arr1[i] |= arr2[i]; arr1[i] |= arr2[i];
} }
void ColumnNullable::applyNullValuesByteMap(const ColumnNullable & other)
{
applyNullValuesByteMap(other.getNullMapConcreteColumn());
}
} }