2021-08-09 18:21:43 +00:00
|
|
|
#include <Functions/IFunction.h>
|
|
|
|
#include <Functions/FunctionFactory.h>
|
|
|
|
#include <Functions/FunctionHelpers.h>
|
|
|
|
#include <DataTypes/IDataType.h>
|
|
|
|
#include <DataTypes/DataTypeTuple.h>
|
|
|
|
#include <DataTypes/DataTypeArray.h>
|
|
|
|
#include <DataTypes/DataTypeString.h>
|
|
|
|
#include <Columns/ColumnTuple.h>
|
|
|
|
#include <Columns/ColumnArray.h>
|
|
|
|
#include <Columns/ColumnString.h>
|
|
|
|
#include <Columns/ColumnsNumber.h>
|
|
|
|
#include <Common/assert_cast.h>
|
|
|
|
#include <memory>
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
|
2021-08-10 20:47:56 +00:00
|
|
|
/** Transform a named tuple into an array of pairs, where the first element
|
|
|
|
* of the pair corresponds to the tuple field name and the second one to the
|
|
|
|
* tuple value.
|
2021-08-09 18:21:43 +00:00
|
|
|
*/
|
2021-08-10 20:33:24 +00:00
|
|
|
class FunctionTupleToNameValuePairs : public IFunction
|
2021-08-09 18:21:43 +00:00
|
|
|
{
|
|
|
|
public:
|
2021-08-10 20:33:24 +00:00
|
|
|
static constexpr auto name = "tupleToNameValuePairs";
|
2021-08-09 18:21:43 +00:00
|
|
|
static FunctionPtr create(ContextPtr)
|
|
|
|
{
|
2021-08-10 20:33:24 +00:00
|
|
|
return std::make_shared<FunctionTupleToNameValuePairs>();
|
2021-08-09 18:21:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
String getName() const override
|
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t getNumberOfArguments() const override
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool useDefaultImplementationForConstants() const override
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-08-13 13:34:16 +00:00
|
|
|
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-08-09 18:21:43 +00:00
|
|
|
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
|
|
|
{
|
|
|
|
// get the type of all the fields in the tuple
|
|
|
|
const IDataType * col = arguments[0].type.get();
|
|
|
|
const DataTypeTuple * tuple = checkAndGetDataType<DataTypeTuple>(col);
|
|
|
|
|
|
|
|
if (!tuple)
|
2021-08-10 20:47:56 +00:00
|
|
|
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
|
|
|
|
"First argument for function {} must be a tuple.",
|
|
|
|
getName());
|
2021-08-09 18:21:43 +00:00
|
|
|
|
2021-08-11 23:09:06 +00:00
|
|
|
const auto & element_types = tuple->getElements();
|
2021-08-09 21:45:16 +00:00
|
|
|
|
2021-08-11 23:09:06 +00:00
|
|
|
if (element_types.empty())
|
2021-08-10 20:47:56 +00:00
|
|
|
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
|
|
|
|
"The argument tuple for function {} must not be empty.",
|
|
|
|
getName());
|
2021-08-09 18:21:43 +00:00
|
|
|
|
2021-08-11 23:09:06 +00:00
|
|
|
const auto & first_element_type = element_types[0];
|
2021-08-09 18:21:43 +00:00
|
|
|
|
2021-08-11 23:09:06 +00:00
|
|
|
bool all_value_types_equal = std::all_of(element_types.begin() + 1,
|
|
|
|
element_types.end(),
|
|
|
|
[&](const auto &other)
|
|
|
|
{
|
|
|
|
return first_element_type->equals(*other);
|
|
|
|
});
|
2021-08-09 21:45:16 +00:00
|
|
|
|
2021-08-11 23:09:06 +00:00
|
|
|
if (!all_value_types_equal)
|
2021-08-09 18:21:43 +00:00
|
|
|
{
|
2021-08-10 20:47:56 +00:00
|
|
|
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
|
|
|
|
"The argument tuple for function {} must contain just one type.",
|
|
|
|
getName());
|
2021-08-09 18:21:43 +00:00
|
|
|
}
|
|
|
|
|
2021-08-11 23:09:06 +00:00
|
|
|
DataTypePtr tuple_name_type = std::make_shared<DataTypeString>();
|
|
|
|
DataTypes item_data_types = {tuple_name_type,
|
|
|
|
first_element_type};
|
2021-08-09 18:21:43 +00:00
|
|
|
|
2021-08-11 23:09:06 +00:00
|
|
|
auto item_data_type = std::make_shared<DataTypeTuple>(item_data_types);
|
2021-08-09 21:45:16 +00:00
|
|
|
|
2021-08-11 23:09:06 +00:00
|
|
|
return std::make_shared<DataTypeArray>(item_data_type);
|
2021-08-09 18:21:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
|
|
|
{
|
2021-08-10 20:47:56 +00:00
|
|
|
const IColumn * tuple_col = arguments[0].column.get();
|
2021-08-09 18:21:43 +00:00
|
|
|
const DataTypeTuple * tuple = checkAndGetDataType<DataTypeTuple>(arguments[0].type.get());
|
2021-08-12 10:25:31 +00:00
|
|
|
const auto * tuple_col_concrete = assert_cast<const ColumnTuple*>(tuple_col);
|
2021-08-09 18:21:43 +00:00
|
|
|
|
2021-08-10 22:19:50 +00:00
|
|
|
auto keys = ColumnString::create();
|
2021-08-09 18:21:43 +00:00
|
|
|
MutableColumnPtr values = tuple_col_concrete->getColumn(0).cloneEmpty();
|
|
|
|
auto offsets = ColumnVector<UInt64>::create();
|
|
|
|
for (size_t row = 0; row < tuple_col_concrete->size(); ++row)
|
|
|
|
{
|
|
|
|
for (size_t col = 0; col < tuple_col_concrete->tupleSize(); ++col)
|
|
|
|
{
|
2021-08-10 20:47:56 +00:00
|
|
|
const std::string & key = tuple->getElementNames()[col];
|
2021-08-11 23:09:06 +00:00
|
|
|
const IColumn & value_column = tuple_col_concrete->getColumn(col);
|
2021-08-09 18:21:43 +00:00
|
|
|
|
2021-08-11 23:09:06 +00:00
|
|
|
values->insertFrom(value_column, row);
|
2021-08-09 18:21:43 +00:00
|
|
|
keys->insertData(key.data(), key.size());
|
|
|
|
}
|
|
|
|
offsets->insertValue(tuple_col_concrete->tupleSize() * (row + 1));
|
|
|
|
}
|
|
|
|
|
2021-08-11 23:09:06 +00:00
|
|
|
std::vector<ColumnPtr> tuple_columns = { std::move(keys), std::move(values) };
|
|
|
|
auto tuple_column = ColumnTuple::create(std::move(tuple_columns));
|
|
|
|
return ColumnArray::create(std::move(tuple_column), std::move(offsets));
|
2021-08-09 18:21:43 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-08-10 20:33:24 +00:00
|
|
|
void registerFunctionTupleToNameValuePairs(FunctionFactory & factory)
|
2021-08-09 18:21:43 +00:00
|
|
|
{
|
2021-08-10 20:33:24 +00:00
|
|
|
factory.registerFunction<FunctionTupleToNameValuePairs>();
|
2021-08-09 18:21:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|