Fixed error [#METR-18149].

This commit is contained in:
Alexey Milovidov 2016-07-10 10:24:24 +03:00
parent b10177ed69
commit 003d63023b
10 changed files with 76 additions and 19 deletions

View File

@ -289,6 +289,9 @@ public:
/** Преобразование из константы в полноценный столбец */
ColumnPtr convertToFullColumn() const override;
/** Create ColumnTuple of constant columns as elements. */
ColumnPtr convertToTupleOfConstants() const;
void getExtremes(Field & min, Field & max) const override;
};

View File

@ -17,7 +17,6 @@ namespace ErrorCodes
/** Column, that is just group of few another columns.
*
* Nested columns must not be constant.
* For constant Tuples, see ColumnConstTuple.
* Mixed constant/non-constant columns is prohibited in tuple
* for implementation simplicity.

View File

@ -672,8 +672,27 @@ private:
* x >= y: x1 > y1 || (x1 == y1 && (x2 > y2 || (x2 == y2 ... && xn >= yn))
*/
auto x_const = typeid_cast<const ColumnConstTuple *>(c0);
auto y_const = typeid_cast<const ColumnConstTuple *>(c1);
ColumnPtr x_tuple_of_consts;
ColumnPtr y_tuple_of_consts;
auto x = static_cast<const ColumnTuple *>(c0);
auto y = static_cast<const ColumnTuple *>(c1);
if (x_const)
{
x_tuple_of_consts = x_const->convertToTupleOfConstants();
x = static_cast<const ColumnTuple *>(x_tuple_of_consts.get());
}
if (y_const)
{
y_tuple_of_consts = y_const->convertToTupleOfConstants();
y = static_cast<const ColumnTuple *>(y_tuple_of_consts.get());
}
const size_t tuple_size = x->getData().columns();
if (0 == tuple_size)
@ -866,7 +885,7 @@ public:
+ " of first argument of function " + getName(),
ErrorCodes::ILLEGAL_COLUMN);
}
else if (typeid_cast<const ColumnTuple *>(col_left_untyped))
else if (typeid_cast<const DataTypeTuple *>(col_with_name_and_type_left.type.get()))
executeTuple(block, result, col_left_untyped, col_right_untyped);
else if (!left_is_num && !right_is_num)
executeString(block, result, col_left_untyped, col_right_untyped);

View File

@ -1269,12 +1269,26 @@ private:
const ColumnWithTypeAndName & arg1 = block.getByPosition(arguments[1]);
const ColumnWithTypeAndName & arg2 = block.getByPosition(arguments[2]);
const ColumnTuple * col1 = static_cast<const ColumnTuple *>(arg1.column.get());
const ColumnTuple * col2 = static_cast<const ColumnTuple *>(arg2.column.get());
ColumnPtr col1_holder;
ColumnPtr col2_holder;
if (!col1 || !col2)
if (typeid_cast<const ColumnTuple *>(arg1.column.get()))
col1_holder = arg1.column;
else if (const ColumnConstTuple * const_tuple = typeid_cast<const ColumnConstTuple *>(arg1.column.get()))
col1_holder = const_tuple->convertToTupleOfConstants();
else
return false;
if (typeid_cast<const ColumnTuple *>(arg2.column.get()))
col2_holder = arg2.column;
else if (const ColumnConstTuple * const_tuple = typeid_cast<const ColumnConstTuple *>(arg2.column.get()))
col2_holder = const_tuple->convertToTupleOfConstants();
else
return false;
const ColumnTuple * col1 = static_cast<const ColumnTuple *>(col1_holder.get());
const ColumnTuple * col2 = static_cast<const ColumnTuple *>(col2_holder.get());
const DataTypeTuple & type1 = static_cast<const DataTypeTuple &>(*arg1.type);
const DataTypeTuple & type2 = static_cast<const DataTypeTuple &>(*arg2.type);

View File

@ -1652,7 +1652,7 @@ private:
if (const auto column_tuple = typeid_cast<const ColumnTuple *>(col))
element_block = column_tuple->getData();
else if (const auto column_const_tuple = typeid_cast<const ColumnConstTuple *>(col))
element_block = static_cast<const ColumnTuple &>(*column_const_tuple->convertToFullColumn()).getData();
element_block = static_cast<const ColumnTuple &>(*column_const_tuple->convertToTupleOfConstants()).getData();
/// create columns for converted elements
for (const auto & to_element_type : to_element_types)

View File

@ -885,17 +885,19 @@ private:
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH};
const auto key_col_with_type = block.getByPosition(arguments[1]);
if (const ColumnTuple * key_col = typeid_cast<const ColumnTuple *>(key_col_with_type.column.get()))
if (typeid_cast<const ColumnTuple *>(key_col_with_type.column.get())
|| typeid_cast<const ColumnConstTuple *>(key_col_with_type.column.get()))
{
/// Функции у внешних словарей поддерживают только полноценные (не константные) столбцы с ключами.
const ColumnPtr key_col_materialized = key_col->convertToFullColumnIfConst();
const ColumnPtr key_col_materialized = key_col_with_type.column->convertToFullColumnIfConst();
const auto key_columns = ext::map<ConstColumnPlainPtrs>(
static_cast<const ColumnTuple &>(*key_col_materialized.get()).getColumns(), [](const ColumnPtr & ptr) { return ptr.get(); });
static_cast<const ColumnTuple &>(*key_col_materialized.get()).getColumns(),
[](const ColumnPtr & ptr) { return ptr.get(); });
const auto & key_types = static_cast<const DataTypeTuple &>(*key_col_with_type.type).getElements();
const auto out = std::make_shared<ColumnUInt8>(key_col->size());
const auto out = std::make_shared<ColumnUInt8>(key_col_with_type.column->size());
block.getByPosition(result).column = out;
dict->has(key_columns, key_types, out->getData());
@ -1064,12 +1066,14 @@ private:
const auto & attr_name = attr_name_col->getData();
const auto key_col_with_type = block.getByPosition(arguments[2]);
if (const auto key_col = typeid_cast<const ColumnTuple *>(key_col_with_type.column.get()))
if (typeid_cast<const ColumnTuple *>(key_col_with_type.column.get())
|| typeid_cast<const ColumnConstTuple *>(key_col_with_type.column.get()))
{
const ColumnPtr key_col_materialized = key_col->convertToFullColumnIfConst();
const ColumnPtr key_col_materialized = key_col_with_type.column->convertToFullColumnIfConst();
const auto key_columns = ext::map<ConstColumnPlainPtrs>(
static_cast<const ColumnTuple &>(*key_col_materialized.get()).getColumns(), [](const ColumnPtr & ptr) { return ptr.get(); });
static_cast<const ColumnTuple &>(*key_col_materialized.get()).getColumns(),
[](const ColumnPtr & ptr) { return ptr.get(); });
const auto & key_types = static_cast<const DataTypeTuple &>(*key_col_with_type.type).getElements();
@ -1635,12 +1639,14 @@ private:
const auto & attr_name = attr_name_col->getData();
const auto key_col_with_type = block.getByPosition(arguments[2]);
if (const auto key_col = typeid_cast<const ColumnTuple *>(key_col_with_type.column.get()))
if (typeid_cast<const ColumnTuple *>(key_col_with_type.column.get())
|| typeid_cast<const ColumnConstTuple *>(key_col_with_type.column.get()))
{
const ColumnPtr key_col_materialized = key_col->convertToFullColumnIfConst();
const ColumnPtr key_col_materialized = key_col_with_type.column->convertToFullColumnIfConst();
const auto key_columns = ext::map<ConstColumnPlainPtrs>(
static_cast<const ColumnTuple &>(*key_col_materialized.get()).getColumns(), [](const ColumnPtr & ptr) { return ptr.get(); });
static_cast<const ColumnTuple &>(*key_col_materialized.get()).getColumns(),
[](const ColumnPtr & ptr) { return ptr.get(); });
const auto & key_types = static_cast<const DataTypeTuple &>(*key_col_with_type.type).getElements();

View File

@ -571,6 +571,11 @@ private:
executeForArgument(col.type.get(), col.column.get(), vec_to, is_first);
}
}
else if (const ColumnConstTuple * tuple = typeid_cast<const ColumnConstTuple *>(column))
{
ColumnPtr tuple_of_constants = tuple->convertToTupleOfConstants();
executeForArgument(type, tuple_of_constants.get(), vec_to, is_first);
}
else
{
if (is_first)

View File

@ -108,6 +108,11 @@ StringRef ColumnConst<Array>::getDataAtWithTerminatingZero(size_t n) const
ColumnPtr ColumnConst<Tuple>::convertToFullColumn() const
{
return convertToTupleOfConstants()->convertToFullColumnIfConst();
}
ColumnPtr ColumnConst<Tuple>::convertToTupleOfConstants() const
{
if (!data_type)
throw Exception("No data type specified for ColumnConstTuple", ErrorCodes::LOGICAL_ERROR);
@ -123,7 +128,7 @@ ColumnPtr ColumnConst<Tuple>::convertToFullColumn() const
for (size_t i = 0; i < tuple_size; ++i)
block.insert(ColumnWithTypeAndName{
element_types[i]->createConstColumn(s, static_cast<const TupleBackend &>(*data)[i])->convertToFullColumnIfConst(),
element_types[i]->createConstColumn(s, static_cast<const TupleBackend &>(*data)[i]),
element_types[i],
""});

View File

@ -349,12 +349,13 @@ void FunctionVisibleWidth::execute(Block & block, const ColumnNumbers & argument
block.getByPosition(result).column = nested_result_column;
}
else if (const ColumnConstArray * col = typeid_cast<const ColumnConstArray *>(column.get()))
else if (typeid_cast<const ColumnConstArray *>(column.get())
|| typeid_cast<const ColumnConstTuple *>(column.get()))
{
String s;
{
WriteBufferFromString wb(s);
type->serializeTextEscaped(*col->convertToFullColumn(), 0, wb);
type->serializeTextEscaped(*column->cut(0, 1)->convertToFullColumnIfConst(), 0, wb);
}
block.getByPosition(result).column = std::make_shared<ColumnConstUInt64>(rows, s.size());

View File

@ -1262,6 +1262,11 @@ void ExpressionAnalyzer::makeExplicitSet(ASTFunction * node, const Block & sampl
ASTFunction * left_arg_tuple = typeid_cast<ASTFunction *>(left_arg.get());
/** NOTE If tuple in left hand side specified non-explicitly
* Example: identity((a, b)) IN ((1, 2), (3, 4))
* instead of (a, b)) IN ((1, 2), (3, 4))
* then set creation of set doesn't work correctly.
*/
if (left_arg_tuple && left_arg_tuple->name == "tuple")
{
for (const auto & arg : left_arg_tuple->arguments->children)