aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/clickhouse/src/Parsers/makeASTForLogicalFunction.cpp
blob: fd9b78a5f52ae347463f8cd9d9de229e8b797577 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <Parsers/makeASTForLogicalFunction.h>
#include <Parsers/ASTLiteral.h>
#include <Parsers/ASTFunction.h>
#include <Parsers/ASTExpressionList.h>
#include <Common/FieldVisitorConvertToNumber.h>
#include <boost/range/algorithm_ext/erase.hpp>


namespace DB
{

ASTPtr makeASTForLogicalAnd(ASTs && arguments)
{
    bool partial_result = true;
    boost::range::remove_erase_if(arguments, [&](const ASTPtr & argument) -> bool
    {
        bool b;
        if (!tryGetLiteralBool(argument.get(), b))
            return false;
        partial_result &= b;
        return true;
    });

    if (!partial_result)
        return std::make_shared<ASTLiteral>(Field{static_cast<UInt8>(0)});
    if (arguments.empty())
        return std::make_shared<ASTLiteral>(Field{static_cast<UInt8>(1)});
    if (arguments.size() == 1)
        return arguments[0];

    auto function = std::make_shared<ASTFunction>();
    auto exp_list = std::make_shared<ASTExpressionList>();
    function->name = "and";
    function->arguments = exp_list;
    function->children.push_back(exp_list);
    exp_list->children = std::move(arguments);
    return function;
}


ASTPtr makeASTForLogicalOr(ASTs && arguments)
{
    bool partial_result = false;
    boost::range::remove_erase_if(arguments, [&](const ASTPtr & argument) -> bool
    {
        bool b;
        if (!tryGetLiteralBool(argument.get(), b))
            return false;
        partial_result |= b;
        return true;
    });

    if (partial_result)
        return std::make_shared<ASTLiteral>(Field{static_cast<UInt8>(1)});
    if (arguments.empty())
        return std::make_shared<ASTLiteral>(Field{static_cast<UInt8>(0)});
    if (arguments.size() == 1)
        return arguments[0];

    auto function = std::make_shared<ASTFunction>();
    auto exp_list = std::make_shared<ASTExpressionList>();
    function->name = "or";
    function->arguments = exp_list;
    function->children.push_back(exp_list);
    exp_list->children = std::move(arguments);
    return function;
}


bool tryGetLiteralBool(const IAST * ast, bool & value)
{
    if (!ast)
        return false;

    try
    {
        if (const ASTLiteral * literal = ast->as<ASTLiteral>())
        {
            value = !literal->value.isNull() && applyVisitor(FieldVisitorConvertToNumber<bool>(), literal->value);
            return true;
        }
        return false;
    }
    catch (...)
    {
        return false;
    }
}

}