summaryrefslogtreecommitdiffstats
path: root/yql/essentials/minikql/computation/mkql_custom_list.h
blob: 19eb2f2f30e8d307a026972ea580735c3497eba9 (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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#pragma once
#include <yql/essentials/minikql/computation/mkql_computation_node_impl.h>
#include <yql/essentials/minikql/computation/mkql_computation_node_holders.h>

namespace NKikimr {
namespace NMiniKQL {

class TCustomListValue: public TComputationValue<TCustomListValue> {
public:
    TCustomListValue(TMemoryUsageInfo* memInfo)
        : TComputationValue(memInfo)
        , Length(Length_)
        , HasItems(HasItems_)
    {
    }

private:
    bool HasFastListLength() const override {
        return bool(Length_);
    }

    ui64 GetListLength() const override {
        if (!Length_) {
            ui64 length = Iterator_ ? 1ULL : 0ULL;
            for (const auto it = Iterator_ ? std::move(Iterator_) : NUdf::TBoxedValueAccessor::GetListIterator(*this); it.Skip();) {
                ++length;
            }

            Length_ = length;
        }

        return *Length_;
    }

    ui64 GetEstimatedListLength() const override {
        return GetListLength();
    }

    bool HasListItems() const override {
        if (HasItems_) {
            return *HasItems_;
        }

        if (Length_) {
            HasItems_ = (*Length_ != 0);
            return *HasItems_;
        }

        auto iter = NUdf::TBoxedValueAccessor::GetListIterator(*this);
        HasItems_ = iter.Skip();
        if (*HasItems_) {
            Iterator_ = std::move(iter);
        }
        return *HasItems_;
    }

protected:
    mutable std::optional<ui64> Length_;
    mutable std::optional<bool> HasItems_;
    mutable NUdf::TUnboxedValue Iterator_;

    // FIXME Remove
    std::optional<ui64>& Length;   // NOLINT(readability-identifier-naming)
    std::optional<bool>& HasItems; // NOLINT(readability-identifier-naming)
};

class TForwardListValue: public TCustomListValue {
public:
    class TIterator: public TComputationValue<TIterator> {
    public:
        TIterator(TMemoryUsageInfo* memInfo, NUdf::TUnboxedValue&& stream);

    private:
        bool Next(NUdf::TUnboxedValue& value) override;

        const NUdf::TUnboxedValue Stream_;
    };

    TForwardListValue(TMemoryUsageInfo* memInfo, NUdf::TUnboxedValue&& stream);

private:
    NUdf::TUnboxedValue GetListIterator() const override;

    mutable NUdf::TUnboxedValue Stream_;
};

class TExtendListValue: public TCustomListValue {
public:
    class TIterator: public TComputationValue<TIterator> {
    public:
        TIterator(TMemoryUsageInfo* memInfo, TUnboxedValueVector&& iters);
        ~TIterator();

    private:
        bool Next(NUdf::TUnboxedValue& value) override;
        bool Skip() override;

        const TUnboxedValueVector Iters_;
        ui32 Index_;
    };

    TExtendListValue(TMemoryUsageInfo* memInfo, TUnboxedValueVector&& lists);

    ~TExtendListValue();

private:
    NUdf::TUnboxedValue GetListIterator() const override;
    ui64 GetListLength() const override;
    bool HasListItems() const override;

    const TUnboxedValueVector Lists_;
};

class TExtendStreamValue: public TComputationValue<TExtendStreamValue> {
public:
    using TBase = TComputationValue<TExtendStreamValue>;

    TExtendStreamValue(TMemoryUsageInfo* memInfo, TUnboxedValueVector&& lists);

    ~TExtendStreamValue();

private:
    NUdf::EFetchStatus Fetch(NUdf::TUnboxedValue& value);

    const TUnboxedValueVector Lists_;
    ui32 Index_ = 0;
};

} // namespace NMiniKQL
} // namespace NKikimr