Fixed segment fault of arrayIntersect and add a test

This commit is contained in:
qianlixiang 2019-03-31 11:44:05 +08:00
parent bdb420cdfd
commit a1d2732d4c
3 changed files with 104 additions and 2 deletions

View File

@ -56,6 +56,7 @@ private:
struct UnpackedArrays struct UnpackedArrays
{ {
size_t base_rows = 0;
std::vector<char> is_const; std::vector<char> is_const;
std::vector<const NullMap *> null_maps; std::vector<const NullMap *> null_maps;
std::vector<const ColumnArray::ColumnOffsets::Container *> offsets; std::vector<const ColumnArray::ColumnOffsets::Container *> offsets;
@ -246,6 +247,8 @@ FunctionArrayIntersect::UnpackedArrays FunctionArrayIntersect::prepareArrays(con
arrays.offsets.resize(columns_number); arrays.offsets.resize(columns_number);
arrays.nested_columns.resize(columns_number); arrays.nested_columns.resize(columns_number);
bool all_const = true;
for (auto i : ext::range(0, columns_number)) for (auto i : ext::range(0, columns_number))
{ {
auto argument_column = columns[i].get(); auto argument_column = columns[i].get();
@ -257,6 +260,9 @@ FunctionArrayIntersect::UnpackedArrays FunctionArrayIntersect::prepareArrays(con
if (auto argument_column_array = typeid_cast<const ColumnArray *>(argument_column)) if (auto argument_column_array = typeid_cast<const ColumnArray *>(argument_column))
{ {
if (!arrays.is_const[i])
all_const = false;
arrays.offsets[i] = &argument_column_array->getOffsets(); arrays.offsets[i] = &argument_column_array->getOffsets();
arrays.nested_columns[i] = &argument_column_array->getData(); arrays.nested_columns[i] = &argument_column_array->getData();
if (auto column_nullable = typeid_cast<const ColumnNullable *>(arrays.nested_columns[i])) if (auto column_nullable = typeid_cast<const ColumnNullable *>(arrays.nested_columns[i]))
@ -269,6 +275,24 @@ FunctionArrayIntersect::UnpackedArrays FunctionArrayIntersect::prepareArrays(con
throw Exception{"Arguments for function " + getName() + " must be arrays.", ErrorCodes::LOGICAL_ERROR}; throw Exception{"Arguments for function " + getName() + " must be arrays.", ErrorCodes::LOGICAL_ERROR};
} }
if (all_const)
{
arrays.base_rows = arrays.offsets.front()->size();
}
else
{
for (auto i : ext::range(0, columns_number))
{
if (arrays.is_const[i]) continue;
size_t rows = arrays.offsets[i]->size();
if (arrays.base_rows == 0 && rows > 0)
arrays.base_rows = rows;
else if (arrays.base_rows != rows)
throw Exception("Non-const array columns in function " + getName() + "should have same rows", ErrorCodes::LOGICAL_ERROR);
}
}
return arrays; return arrays;
} }
@ -352,7 +376,7 @@ template <typename Map, typename ColumnType, bool is_numeric_column>
ColumnPtr FunctionArrayIntersect::execute(const UnpackedArrays & arrays, MutableColumnPtr result_data_ptr) ColumnPtr FunctionArrayIntersect::execute(const UnpackedArrays & arrays, MutableColumnPtr result_data_ptr)
{ {
auto args = arrays.nested_columns.size(); auto args = arrays.nested_columns.size();
auto rows = arrays.offsets.front()->size(); auto rows = arrays.base_rows;
bool all_nullable = true; bool all_nullable = true;
@ -392,11 +416,14 @@ ColumnPtr FunctionArrayIntersect::execute(const UnpackedArrays & arrays, Mutable
for (auto arg : ext::range(0, args)) for (auto arg : ext::range(0, args))
{ {
bool current_has_nullable = false; bool current_has_nullable = false;
size_t off = (*arrays.offsets[arg])[row];
size_t off;
// const array has only one row // const array has only one row
bool const_arg = arrays.is_const[arg]; bool const_arg = arrays.is_const[arg];
if (const_arg) if (const_arg)
off = (*arrays.offsets[arg])[0]; off = (*arrays.offsets[arg])[0];
else
off = (*arrays.offsets[arg])[row];
for (auto i : ext::range(prev_off[arg], off)) for (auto i : ext::range(prev_off[arg], off))
{ {

View File

@ -0,0 +1,48 @@
[]
[1,2]
[1]
[1,2]
[]
[]
[]
[]
[]
[]
[]
[]
[1,2]
[1]
[1,2]
[]
[1,2]
[1,2]
[1,2]
[1,2]
[]
[]
[]
[]
[1,2]
[1,2]
[1]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[1,2]
[1,2]
[1]
[]
[1,2]
[1,2]
[1,2]
[1,2]
[]
[]
[]
[]

View File

@ -0,0 +1,27 @@
drop table if exists test.array_intersect;
create table test.array_intersect (date Date, arr Array(UInt8)) engine=MergeTree partition by date order by date;
insert into test.array_intersect values ('2019-01-01', [1,2,3]);
insert into test.array_intersect values ('2019-01-01', [1,2]);
insert into test.array_intersect values ('2019-01-01', [1]);
insert into test.array_intersect values ('2019-01-01', []);
select arrayIntersect(arr, [1,2]) from test.array_intersect;
select arrayIntersect(arr, []) from test.array_intersect;
select arrayIntersect([], arr) from test.array_intersect;
select arrayIntersect([1,2], arr) from test.array_intersect;
select arrayIntersect([1,2], [1,2,3,4]) from test.array_intersect;
select arrayIntersect([], []) from test.array_intersect;
optimize table test.array_intersect;
select arrayIntersect(arr, [1,2]) from test.array_intersect;
select arrayIntersect(arr, []) from test.array_intersect;
select arrayIntersect([], arr) from test.array_intersect;
select arrayIntersect([1,2], arr) from test.array_intersect;
select arrayIntersect([1,2], [1,2,3,4]) from test.array_intersect;
select arrayIntersect([], []) from test.array_intersect;
drop table if exists test.array_intersect;