diff options
author | vitalyisaev <vitalyisaev@ydb.tech> | 2023-11-14 09:58:56 +0300 |
---|---|---|
committer | vitalyisaev <vitalyisaev@ydb.tech> | 2023-11-14 10:20:20 +0300 |
commit | c2b2dfd9827a400a8495e172a56343462e3ceb82 (patch) | |
tree | cd4e4f597d01bede4c82dffeb2d780d0a9046bd0 /contrib/clickhouse/src/Interpreters/ComparisonTupleEliminationVisitor.cpp | |
parent | d4ae8f119e67808cb0cf776ba6e0cf95296f2df7 (diff) | |
download | ydb-c2b2dfd9827a400a8495e172a56343462e3ceb82.tar.gz |
YQ Connector: move tests from yql to ydb (OSS)
Перенос папки с тестами на Коннектор из папки yql в папку ydb (синхронизируется с github).
Diffstat (limited to 'contrib/clickhouse/src/Interpreters/ComparisonTupleEliminationVisitor.cpp')
-rw-r--r-- | contrib/clickhouse/src/Interpreters/ComparisonTupleEliminationVisitor.cpp | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/contrib/clickhouse/src/Interpreters/ComparisonTupleEliminationVisitor.cpp b/contrib/clickhouse/src/Interpreters/ComparisonTupleEliminationVisitor.cpp new file mode 100644 index 0000000000..4f06f345b9 --- /dev/null +++ b/contrib/clickhouse/src/Interpreters/ComparisonTupleEliminationVisitor.cpp @@ -0,0 +1,100 @@ +#include <Interpreters/ComparisonTupleEliminationVisitor.h> +#include <Parsers/ASTSelectQuery.h> +#include <Parsers/ASTFunction.h> +#include <Parsers/ASTLiteral.h> + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int LOGICAL_ERROR; +} + +namespace +{ + +ASTs splitTuple(const ASTPtr & node) +{ + if (const auto * func = node->as<ASTFunction>(); func && func->name == "tuple") + return func->arguments->children; + + if (const auto * literal = node->as<ASTLiteral>(); literal && literal->value.getType() == Field::Types::Tuple) + { + ASTs result; + const auto & tuple = literal->value.get<const Tuple &>(); + for (const auto & child : tuple) + result.emplace_back(std::make_shared<ASTLiteral>(child)); + return result; + } + + return {}; +} + +ASTPtr concatWithAnd(const ASTs & nodes) +{ + if (nodes.empty()) + throw Exception(ErrorCodes::LOGICAL_ERROR, "Cannot concat empty list of nodes"); + + if (nodes.size() == 1) + return nodes[0]; + + auto result = makeASTFunction("and"); + result->arguments->children = nodes; + return result; +} + +class SplitTupleComparsionExpressionMatcher +{ +public: + using Data = ComparisonTupleEliminationMatcher::Data; + + static bool needChildVisit(const ASTPtr &, const ASTPtr &) { return true; } + static void visit(ASTPtr & ast, Data &) + { + auto * func = ast->as<ASTFunction>(); + if (!func || func->arguments->children.size() != 2) + return; + + if (func->name != "equals" && func->name != "notEquals") + return; + + auto lhs = splitTuple(func->arguments->children[0]); + auto rhs = splitTuple(func->arguments->children[1]); + if (lhs.size() != rhs.size() || lhs.empty()) + return; + + ASTs new_args; + new_args.reserve(lhs.size()); + for (size_t i = 0; i < lhs.size(); ++i) + { + new_args.emplace_back(makeASTFunction("equals", lhs[i], rhs[i])); + } + + if (func->name == "notEquals") + ast = makeASTFunction("not", concatWithAnd(new_args)); + else + ast = concatWithAnd(new_args); + } +}; + +using SplitTupleComparsionExpressionVisitor = InDepthNodeVisitor<SplitTupleComparsionExpressionMatcher, true>; + +} + +bool ComparisonTupleEliminationMatcher::needChildVisit(ASTPtr &, const ASTPtr &) +{ + return true; +} + +void ComparisonTupleEliminationMatcher::visit(ASTPtr & ast, Data & data) +{ + auto * select_ast = ast->as<ASTSelectQuery>(); + if (!select_ast || !select_ast->where()) + return; + + if (select_ast->where()) + SplitTupleComparsionExpressionVisitor(data).visit(select_ast->refWhere()); +} + +} |