Skip to content

Commit b981d2d

Browse files
authored
Merge pull request ClickHouse#62287 from ClickHouse/vdimir/internal_functions_fix
Fix __actionName, add tests for internal functions direct call
2 parents 5849aeb + 4ea2b5e commit b981d2d

File tree

5 files changed

+77
-2
lines changed

5 files changed

+77
-2
lines changed

src/Functions/identity.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66
namespace DB
77
{
88

9+
namespace ErrorCodes
10+
{
11+
extern const int BAD_ARGUMENTS;
12+
}
13+
914
template<typename Name>
1015
class FunctionIdentityBase : public IFunction
1116
{
@@ -53,7 +58,24 @@ class FunctionActionName : public FunctionIdentityBase<ActionNameName>
5358
using FunctionIdentityBase::FunctionIdentityBase;
5459
static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionActionName>(); }
5560
size_t getNumberOfArguments() const override { return 2; }
56-
ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {1}; }
61+
ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {0, 1}; }
62+
63+
/// Do not allow any argument to have type other than String
64+
bool useDefaultImplementationForNulls() const override { return false; }
65+
bool useDefaultImplementationForNothing() const override { return false; }
66+
bool useDefaultImplementationForLowCardinalityColumns() const override { return false; }
67+
68+
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
69+
{
70+
for (const auto & arg : arguments)
71+
{
72+
if (WhichDataType(arg).isString())
73+
continue;
74+
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Function __actionName is internal nad should not be used directly");
75+
}
76+
77+
return FunctionIdentityBase<ActionNameName>::getReturnTypeImpl(arguments);
78+
}
5779
};
5880

5981
}

src/Planner/PlannerActionsVisitor.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,17 @@ class ActionNodeNameHelper
160160
const auto & function_node = node->as<FunctionNode &>();
161161
if (function_node.getFunctionName() == "__actionName")
162162
{
163-
result = toString(function_node.getArguments().getNodes().at(1)->as<ConstantNode>()->getValue());
163+
/// Perform sanity check, because user may call this function with unexpected arguments
164+
const auto & function_argument_nodes = function_node.getArguments().getNodes();
165+
if (function_argument_nodes.size() == 2)
166+
{
167+
if (const auto * second_argument = function_argument_nodes.at(1)->as<ConstantNode>())
168+
result = toString(second_argument->getValue());
169+
}
170+
171+
/// Empty node name is not allowed and leads to logical errors
172+
if (result.empty())
173+
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Function __actionName is internal nad should not be used directly");
164174
break;
165175
}
166176

src/Processors/Transforms/MergeJoinTransform.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,8 @@ static void prepareChunk(Chunk & chunk)
338338

339339
void MergeJoinAlgorithm::initialize(Inputs inputs)
340340
{
341+
LOG_DEBUG(&Poco::Logger::get("XXXX"), "{}:{}: {} - '{}'", __FILE__, __LINE__, 0, inputs[0].chunk.dumpStructure());
342+
LOG_DEBUG(&Poco::Logger::get("XXXX"), "{}:{}: {} - '{}'", __FILE__, __LINE__, 1, inputs[1].chunk.dumpStructure());
341343
if (inputs.size() != 2)
342344
throw Exception(ErrorCodes::LOGICAL_ERROR, "Two inputs are required, got {}", inputs.size());
343345

@@ -349,6 +351,8 @@ void MergeJoinAlgorithm::initialize(Inputs inputs)
349351

350352
void MergeJoinAlgorithm::consume(Input & input, size_t source_num)
351353
{
354+
LOG_DEBUG(&Poco::Logger::get("XXXX"), "{}:{}: {} - '{}'", __FILE__, __LINE__, source_num, input.chunk.dumpStructure());
355+
352356
if (input.skip_last_row)
353357
throw Exception(ErrorCodes::NOT_IMPLEMENTED, "skip_last_row is not supported");
354358

@@ -812,8 +816,17 @@ IMergingAlgorithm::Status MergeJoinAlgorithm::merge()
812816
if (!cursors[1]->cursor.isValid() && !cursors[1]->fullyCompleted())
813817
return Status(1);
814818

819+
for (size_t i = 0; i < 2; ++i)
820+
{
821+
LOG_DEBUG(&Poco::Logger::get("XXXX"), "{}:{}: sampleColumns {} '{}'", __FILE__, __LINE__, i, cursors[i]->sampleBlock().dumpStructure());
822+
}
823+
824+
815825
if (auto result = handleAllJoinState())
826+
{
827+
LOG_DEBUG(&Poco::Logger::get("XXXX"), "{}:{}: '{}'", __FILE__, __LINE__, result ? result->chunk.dumpStructure() : "NA");
816828
return std::move(*result);
829+
}
817830

818831
if (cursors[0]->fullyCompleted() || cursors[1]->fullyCompleted())
819832
{
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
aaa
2+
(1,1) (1,1)
3+
1
4+
a1 1
5+
1
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
-- This functions should not be called directly, only for internal use.
2+
-- However, we cannot completely forbid it (becasue query can came from another server, for example)
3+
-- Check that usage of these functions does not lead to crash or logical error
4+
5+
SELECT __actionName(); -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }
6+
SELECT __actionName('aaa', 'aaa', 'aaa'); -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }
7+
SELECT __actionName('aaa', '') SETTINGS allow_experimental_analyzer = 1; -- { serverError BAD_ARGUMENTS }
8+
SELECT __actionName('aaa', materialize('aaa')); -- { serverError BAD_ARGUMENTS,ILLEGAL_COLUMN }
9+
SELECT __actionName(materialize('aaa'), 'aaa'); -- { serverError ILLEGAL_COLUMN }
10+
SELECT __actionName('aaa', 'aaa');
11+
12+
SELECT concat(__actionName('aaa', toNullable('x')), '1') GROUP BY __actionName('aaa', 'x'); -- { serverError BAD_ARGUMENTS }
13+
14+
SELECT __getScalar('aaa'); -- { serverError BAD_ARGUMENTS }
15+
SELECT __getScalar(); -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }
16+
SELECT __getScalar(1); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
17+
SELECT __getScalar(materialize('1')); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
18+
19+
WITH ( SELECT (1,1) ) as a SELECT materialize(a), __getScalar('17789833925953107877_7493841889429261611') SETTINGS allow_experimental_analyzer = 1;
20+
21+
SELECT __scalarSubqueryResult('1');
22+
SELECT 'a' || __scalarSubqueryResult(a), materialize('1') as a;
23+
SELECT __scalarSubqueryResult(a, a), materialize('1') as a; -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }
24+
25+
SELECT 1 as `__grouping_set`;

0 commit comments

Comments
 (0)