Added support for arbitary nested type of arrays for function has [#METR-18149].

This commit is contained in:
Alexey Milovidov 2016-07-09 07:39:57 +03:00
parent 27360b8166
commit e1181f2175
3 changed files with 134 additions and 16 deletions

View File

@ -879,14 +879,14 @@ public:
};
/// Для has.
/// For has.
struct IndexToOne
{
using ResultType = UInt8;
static bool apply(size_t j, ResultType & current) { current = 1; return false; }
};
/// Для indexOf.
/// For indexOf.
struct IndexIdentity
{
using ResultType = UInt64;
@ -894,7 +894,7 @@ struct IndexIdentity
static bool apply(size_t j, ResultType & current) { current = j + 1; return false; }
};
/// Для countEqual.
/// For countEqual.
struct IndexCount
{
using ResultType = UInt32;
@ -1016,6 +1016,40 @@ struct ArrayIndexStringImpl
}
};
/** Catch-all implementation for arrays of arbitary type.
*/
template <typename IndexConv, bool is_value_has_single_element_to_compare>
struct ArrayIndexGenericImpl
{
/** To compare with constant value, create non-constant column with single element,
* and pass is_value_has_single_element_to_compare = true.
*/
static void vector(
const IColumn & data, const ColumnArray::Offsets_t & offsets,
const IColumn & value,
PaddedPODArray<typename IndexConv::ResultType> & result)
{
size_t size = offsets.size();
result.resize(size);
ColumnArray::Offset_t current_offset = 0;
for (size_t i = 0; i < size; ++i)
{
size_t array_size = offsets[i] - current_offset;
typename IndexConv::ResultType current = 0;
for (size_t j = 0; j < array_size; ++j)
if (0 == data.compareAt(current_offset + j, is_value_has_single_element_to_compare ? 0 : i, value, 1))
if (!IndexConv::apply(j, current))
break;
result[i] = current;
current_offset = offsets[i];
}
}
};
template <typename IndexConv, typename Name>
class FunctionArrayIndex : public IFunction
@ -1110,6 +1144,8 @@ private:
col_nested->getOffsets(), item_arg_vector->getChars(), item_arg_vector->getOffsets(),
col_res->getData());
}
else
return false;
return true;
}
@ -1165,6 +1201,40 @@ private:
return true;
}
bool executeGeneric(Block & block, const ColumnNumbers & arguments, size_t result)
{
const ColumnArray * col_array = typeid_cast<const ColumnArray *>(block.getByPosition(arguments[0]).column.get());
if (!col_array)
return false;
const IColumn & col_nested = col_array->getData();
const IColumn & item_arg = *block.getByPosition(arguments[1]).column;
const auto col_res = std::make_shared<ResultColumnType>();
block.getByPosition(result).column = col_res;
if (item_arg.isConst())
{
ArrayIndexGenericImpl<IndexConv, true>::vector(col_nested, col_array->getOffsets(),
*item_arg.cut(0, 1)->convertToFullColumnIfConst(), col_res->getData());
}
else
{
/// If item_arg is tuple and have constants.
if (auto materialized_tuple = item_arg.convertToFullColumnIfConst())
{
ArrayIndexGenericImpl<IndexConv, false>::vector(
col_nested, col_array->getOffsets(), *materialized_tuple, col_res->getData());
}
else
ArrayIndexGenericImpl<IndexConv, false>::vector(
col_nested, col_array->getOffsets(), item_arg, col_res->getData());
}
return true;
}
public:
/// Получить имя функции.
@ -1207,12 +1277,12 @@ public:
|| executeNumber<Float32>(block, arguments, result)
|| executeNumber<Float64>(block, arguments, result)
|| executeConst(block, arguments, result)
|| executeString(block, arguments, result)))
|| executeString(block, arguments, result)
|| executeGeneric(block, arguments, result)))
throw Exception{
"Illegal column " + block.getByPosition(arguments[0]).column->getName()
+ " of first argument of function " + getName(),
ErrorCodes::ILLEGAL_COLUMN
};
ErrorCodes::ILLEGAL_COLUMN};
}
};

View File

@ -0,0 +1,24 @@
1
1
0
1
1
1
1
1
0
0
1
1
1
1
0
1
1
1
0
1
1
1
0
1

View File

@ -0,0 +1,24 @@
SELECT has([(a, b), (c, d)], (a, b)) FROM (SELECT 1 AS a, 2 AS b, 3 AS c, 4 AS d);
SELECT has([(a, b), (c, d)], (c, d)) FROM (SELECT 1 AS a, 2 AS b, 3 AS c, 4 AS d);
SELECT has([(a, b), (c, d)], (b, c)) FROM (SELECT 1 AS a, 2 AS b, 3 AS c, 4 AS d);
SELECT has([(a, b), (c, d)], (b, c)) FROM (SELECT 1 AS a, 2 AS b, 2 AS c, 2 AS d);
SELECT has([(a, b), (c, d)], (a, b)) FROM (SELECT number + 1 AS a, number + 2 AS b, number + 3 AS c, number + 4 AS d FROM system.numbers LIMIT 2);
SELECT has([(a, b), (c, d)], (c, d)) FROM (SELECT number + 1 AS a, number + 2 AS b, number + 3 AS c, number + 4 AS d FROM system.numbers LIMIT 2);
SELECT has([(a, b), (c, d)], (b, c)) FROM (SELECT number + 1 AS a, number + 2 AS b, number + 3 AS c, number + 4 AS d FROM system.numbers LIMIT 2);
SELECT has([(a, b), (c, d)], (b, c)) FROM (SELECT number + 1 AS a, number + 2 AS b, number + 2 AS c, number + 2 AS d FROM system.numbers LIMIT 2);
SELECT has([(a, b), (c, d)], (a, b)) FROM (SELECT materialize(1) AS a, 2 AS b, 3 AS c, 4 AS d);
SELECT has([(a, b), (c, d)], (c, d)) FROM (SELECT materialize(1) AS a, 2 AS b, 3 AS c, 4 AS d);
SELECT has([(a, b), (c, d)], (b, c)) FROM (SELECT materialize(1) AS a, 2 AS b, 3 AS c, 4 AS d);
SELECT has([(a, b), (c, d)], (b, c)) FROM (SELECT materialize(1) AS a, 2 AS b, 2 AS c, 2 AS d);
SELECT has([(a, b), (c, d)], (a, b)) FROM (SELECT materialize(1) AS a, 2 AS b, materialize(3) AS c, 4 AS d);
SELECT has([(a, b), (c, d)], (c, d)) FROM (SELECT materialize(1) AS a, 2 AS b, materialize(3) AS c, 4 AS d);
SELECT has([(a, b), (c, d)], (b, c)) FROM (SELECT materialize(1) AS a, 2 AS b, materialize(3) AS c, 4 AS d);
SELECT has([(a, b), (c, d)], (b, c)) FROM (SELECT materialize(1) AS a, 2 AS b, materialize(2) AS c, 2 AS d);
SELECT has([(a, b), (c, d)], (a, b)) FROM (SELECT materialize(1) AS a, materialize(2) AS b, materialize(3) AS c, 4 AS d);
SELECT has([(a, b), (c, d)], (c, d)) FROM (SELECT materialize(1) AS a, materialize(2) AS b, materialize(3) AS c, 4 AS d);
SELECT has([(a, b), (c, d)], (b, c)) FROM (SELECT materialize(1) AS a, materialize(2) AS b, materialize(3) AS c, 4 AS d);
SELECT has([(a, b), (c, d)], (b, c)) FROM (SELECT materialize(1) AS a, materialize(2) AS b, materialize(2) AS c, 2 AS d);