aboutsummaryrefslogtreecommitdiffstats
path: root/yql/essentials/minikql/comp_nodes/ut/mkql_block_exists_ut.cpp
blob: 67cf2acc490611b3f0e8aeade5b82637604a0355 (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
#include "mkql_computation_node_ut.h"

#include <yql/essentials/minikql/computation/mkql_computation_node_holders.h>
#include <yql/essentials/minikql/computation/mkql_block_builder.h>

namespace NKikimr {
namespace NMiniKQL {

namespace {

void DoBlockExistsOffset(size_t length, size_t offset) {
    TSetup<false> setup;
    TProgramBuilder& pb = *setup.PgmBuilder;

    const auto ui64Type    = pb.NewDataType(NUdf::TDataType<ui64>::Id);
    const auto optui64Type = pb.NewOptionalType(ui64Type);
    const auto boolType   = pb.NewDataType(NUdf::TDataType<bool>::Id);

    const auto inputTupleType  = pb.NewTupleType({ui64Type, optui64Type, optui64Type, optui64Type});
    const auto outputTupleType = pb.NewTupleType({ui64Type, boolType, boolType, boolType});

    TRuntimeNode::TList input;
    TVector<bool> isNull;
    static_assert(MaxBlockSizeInBytes % 4 == 0);

    const auto drng = CreateDeterministicRandomProvider(std::time(nullptr));

    for (size_t i = 0; i < length; i++) {
        const ui64 randomValue = drng->GenRand();
        const auto maybeNull = (randomValue % 2)
            ? pb.NewOptional(pb.NewDataLiteral<ui64>(randomValue / 2))
            : pb.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui64>::Id);

        const auto inputTuple = pb.NewTuple(inputTupleType, {
            pb.NewDataLiteral<ui64>(i),
            maybeNull,
            pb.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui64>::Id),
            pb.NewOptional(pb.NewDataLiteral<ui64>(i))
        });

        input.push_back(inputTuple);
        isNull.push_back((randomValue % 2) != 0);
    }

    const auto list = pb.NewList(inputTupleType, std::move(input));

    auto node = pb.ToFlow(list);
    node = pb.ExpandMap(node, [&](TRuntimeNode item) -> TRuntimeNode::TList {
        return {
            pb.Nth(item, 0),
            pb.Nth(item, 1),
            pb.Nth(item, 2),
            pb.Nth(item, 3)
        };
    });
    node = pb.WideToBlocks(node);
    if (offset > 0) {
        node = pb.WideSkipBlocks(node, pb.NewDataLiteral<ui64>(offset));
    }
    node = pb.WideMap(node, [&](TRuntimeNode::TList items) -> TRuntimeNode::TList {
        return {
            items[0],
            pb.BlockExists(items[1]),
            pb.BlockExists(items[2]),
            pb.BlockExists(items[3]),
            items[4],
        };
    });
    node = pb.WideFromBlocks(node);
    node = pb.NarrowMap(node, [&](TRuntimeNode::TList items) -> TRuntimeNode {
        return pb.NewTuple(outputTupleType, {items[0], items[1], items[2], items[3]});
    });

    const auto pgmReturn = pb.Collect(node);
    const auto graph = setup.BuildGraph(pgmReturn);
    const auto iterator = graph->GetValue().GetListIterator();

    for (size_t i = 0; i < length; i++) {
        if (i < offset) {
            continue;
        }

        NUdf::TUnboxedValue outputTuple;
        UNIT_ASSERT(iterator.Next(outputTuple));
        const ui32 key = outputTuple.GetElement(0).Get<ui64>();
        const bool maybeNull = outputTuple.GetElement(1).Get<bool>();
        const bool alwaysNull = outputTuple.GetElement(2).Get<bool>();
        const bool neverNull = outputTuple.GetElement(3).Get<bool>();

        UNIT_ASSERT_VALUES_EQUAL(key, i);
        UNIT_ASSERT_VALUES_EQUAL(maybeNull, isNull[i]);
        UNIT_ASSERT_VALUES_EQUAL(alwaysNull, false);
        UNIT_ASSERT_VALUES_EQUAL(neverNull, true);
    }

    NUdf::TUnboxedValue outputTuple;
    UNIT_ASSERT(!iterator.Next(outputTuple));
    UNIT_ASSERT(!iterator.Next(outputTuple));
}

} //namespace

Y_UNIT_TEST_SUITE(TMiniKQLBlockExistsTest) {

Y_UNIT_TEST(ExistsWithOffset) {
    const size_t length = 20;
    for (size_t offset = 0; offset < length; offset++) {
        DoBlockExistsOffset(length, offset);
    }
}

} // Y_UNIT_TEST_SUITE

} // namespace NMiniKQL
} // namespace NKikimr