mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-24 16:42:05 +00:00
Added support for arbitary nested type of arrays for function has [#METR-18149].
This commit is contained in:
parent
27360b8166
commit
e1181f2175
@ -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};
|
||||
}
|
||||
};
|
||||
|
||||
|
24
dbms/tests/queries/0_stateless/00347_has_tuple.reference
Normal file
24
dbms/tests/queries/0_stateless/00347_has_tuple.reference
Normal 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
|
24
dbms/tests/queries/0_stateless/00347_has_tuple.sql
Normal file
24
dbms/tests/queries/0_stateless/00347_has_tuple.sql
Normal 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);
|
Loading…
Reference in New Issue
Block a user