aboutsummaryrefslogtreecommitdiffstats
path: root/yql/essentials/minikql/comp_nodes/mkql_contains.cpp
blob: 148eff3c04da64b45bd9054e8cea05b496724c83 (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
#include "mkql_contains.h"
#include <yql/essentials/minikql/computation/mkql_computation_node_codegen.h>  // Y_IGNORE
#include <yql/essentials/minikql/mkql_node_cast.h>

namespace NKikimr {
namespace NMiniKQL {

namespace {

class TContainsWrapper : public TMutableCodegeneratorNode<TContainsWrapper> {
    typedef TMutableCodegeneratorNode<TContainsWrapper> TBaseComputation;
public:
    TContainsWrapper(TComputationMutables& mutables, IComputationNode* dict, IComputationNode* key)
        : TBaseComputation(mutables, EValueRepresentation::Embedded)
        , Dict(dict)
        , Key(key)
    {
    }

    NUdf::TUnboxedValuePod DoCalculate(TComputationContext& compCtx) const {
        return NUdf::TUnboxedValuePod(Dict->GetValue(compCtx).Contains(Key->GetValue(compCtx)));
    }

#ifndef MKQL_DISABLE_CODEGEN
    Value* DoGenerateGetValue(const TCodegenContext& ctx, BasicBlock*& block) const {
        auto& context = ctx.Codegen.GetContext();
        const auto valueType = Type::getInt128Ty(context);

        const auto dict = GetNodeValue(Dict, ctx, block);

        const auto keyp = *Stateless || ctx.AlwaysInline ?
            new AllocaInst(valueType, 0U, "key", &ctx.Func->getEntryBlock().back()):
            new AllocaInst(valueType, 0U, "key", block);
        GetNodeValue(keyp, Key, ctx, block);
        const auto cont = CallBoxedValueVirtualMethod<NUdf::TBoxedValueAccessor::EMethod::Contains>(Type::getInt1Ty(context), dict, ctx.Codegen, block, keyp);

        ValueUnRef(Key->GetRepresentation(), keyp, ctx, block);
        if (Dict->IsTemporaryValue())
            CleanupBoxed(dict, ctx, block);
        return MakeBoolean(cont, context, block);
    }
#endif
private:
    void RegisterDependencies() const final {
        DependsOn(Dict);
        DependsOn(Key);
    }

    IComputationNode* const Dict;
    IComputationNode* const Key;
};

}

IComputationNode* WrapContains(TCallable& callable, const TComputationNodeFactoryContext& ctx) {
    MKQL_ENSURE(callable.GetInputsCount() == 2, "Expected 2 args");

    const auto dict = LocateNode(ctx.NodeLocator, callable, 0);
    const auto key = LocateNode(ctx.NodeLocator, callable, 1);
    return new TContainsWrapper(ctx.Mutables, dict, key);
}

}
}