Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed "arrayWithConstant" function #4322

Merged
merged 5 commits into from Feb 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
70 changes: 70 additions & 0 deletions dbms/src/Functions/arrayWithConstant.cpp
@@ -0,0 +1,70 @@
#include <Functions/IFunction.h>
#include <Functions/FunctionHelpers.h>
#include <Functions/FunctionFactory.h>
#include <DataTypes/DataTypeArray.h>
#include <DataTypes/DataTypesNumber.h>
#include <Columns/ColumnArray.h>


namespace DB
{

namespace ErrorCodes
{
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
}

/* arrayWithConstant(num, const) - make array of constants with length num.
* arrayWithConstant(3, 'hello') = ['hello', 'hello', 'hello']
* arrayWithConstant(1, 'hello') = ['hello']
* arrayWithConstant(0, 'hello') = []
*/

class FunctionArrayWithConstant : public IFunction
{
public:
static constexpr auto name = "arrayWithConstant";

static FunctionPtr create(const Context &) { return std::make_shared<FunctionArrayWithConstant>(); }

String getName() const override { return name; }
size_t getNumberOfArguments() const override { return 2; }

DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
{
if (!isNumber(arguments[0]))
throw Exception("Illegal type " + arguments[0]->getName() +
" of argument of function " + getName() +
", expected Integer", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
return std::make_shared<DataTypeArray>(arguments[1]);
}

bool useDefaultImplementationForConstants() const override { return true; }
bool useDefaultImplementationForNulls() const override { return false; }

void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t num_rows) override
{
const auto * col_num = block.getByPosition(arguments[0]).column.get();
const auto * col_value = block.getByPosition(arguments[1]).column.get();

auto offsets_col = ColumnArray::ColumnOffsets::create();
ColumnArray::Offsets & offsets = offsets_col->getData();
offsets.reserve(num_rows);

ColumnArray::Offset offset = 0;
for (size_t i = 0; i < num_rows; ++i)
{
offset += col_num->getUInt(i);
offsets.push_back(offset);
}

block.getByPosition(result).column = ColumnArray::create(col_value->replicate(offsets), std::move(offsets_col));
}
};

void registerFunctionArrayWithConstant(FunctionFactory & factory)
{
factory.registerFunction<FunctionArrayWithConstant>();
}

}
2 changes: 2 additions & 0 deletions dbms/src/Functions/registerFunctionsArray.cpp
Expand Up @@ -28,6 +28,7 @@ void registerFunctionArrayEnumerateUniq(FunctionFactory &);
void registerFunctionArrayEnumerateDense(FunctionFactory &);
void registerFunctionArrayUniq(FunctionFactory &);
void registerFunctionArrayDistinct(FunctionFactory &);
void registerFunctionArrayWithConstant(FunctionFactory &);

void registerFunctionsArray(FunctionFactory & factory)
{
Expand Down Expand Up @@ -56,6 +57,7 @@ void registerFunctionsArray(FunctionFactory & factory)
registerFunctionArrayEnumerateDense(factory);
registerFunctionArrayUniq(factory);
registerFunctionArrayDistinct(factory);
registerFunctionArrayWithConstant(factory);
}

}
Expand Down
@@ -0,0 +1 @@
['qwerty','qwerty'] [] [1]
@@ -0,0 +1 @@
select arrayWithConstant(2, 'qwerty'), arrayWithConstant(0, -1), arrayWithConstant(1, 1)
@@ -0,0 +1,40 @@
[0,0,0]
[1,1,1]
[2,2,2]
[3,3,3]
[4,4,4]
[5,5,5]
[6,6,6]
[7,7,7]
[8,8,8]
[9,9,9]
[]
['Hello']
['Hello','Hello']
['Hello','Hello','Hello']
['Hello','Hello','Hello','Hello']
['Hello','Hello','Hello','Hello','Hello']
['Hello','Hello','Hello','Hello','Hello','Hello']
['Hello','Hello','Hello','Hello','Hello','Hello','Hello']
['Hello','Hello','Hello','Hello','Hello','Hello','Hello','Hello']
['Hello','Hello','Hello','Hello','Hello','Hello','Hello','Hello','Hello']
[]
['Hello']
[NULL,NULL]
[]
[NULL]
['Hello','Hello']
[]
['Hello']
[NULL,NULL]
[]
[]
[[]]
[[],[]]
[[],[],[]]
[[],[],[],[]]
[[],[],[],[],[]]
[[],[],[],[],[],[]]
[[],[],[],[],[],[],[]]
[[],[],[],[],[],[],[],[]]
[[],[],[],[],[],[],[],[],[]]
@@ -0,0 +1,4 @@
SELECT arrayWithConstant(3, number) FROM numbers(10);
SELECT arrayWithConstant(number, 'Hello') FROM numbers(10);
SELECT arrayWithConstant(number % 3, number % 2 ? 'Hello' : NULL) FROM numbers(10);
SELECT arrayWithConstant(number, []) FROM numbers(10);