Coverage Report

Created: 2026-03-15 17:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/util/bitmap_expr_calculation.h
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
#pragma once
18
#include <stack>
19
#include <string>
20
21
#include "util/bitmap_intersect.h"
22
23
namespace doris {
24
25
// Compute the intersection union difference set of two or more bitmaps
26
// Usage: orthogonal_bitmap_parse_calculate(bitmap_column, filter_column, input_string)
27
// Example: orthogonal_bitmap_expr_calculate(user_id, event, '(A|B)&(C-D)'), meaning find the intersection union difference set of user_id in all A/B/C/D 4 bitmaps
28
// Operation symbol:
29
// the operator '|' stands for union, the operator '&' stands for intersection, the operator '-' indicates the difference set, the operator '^' stands for xor
30
class BitmapExprCalculation : public BitmapIntersect<std::string> {
31
public:
32
0
    BitmapExprCalculation() = default;
33
34
0
    explicit BitmapExprCalculation(const char* src) { deserialize(src); }
35
36
0
    void bitmap_calculation_init(std::string& input_str) {
37
0
        _polish = reverse_polish(input_str);
38
0
        std::string bitmap_key;
39
0
        for (int i = 0; i < _polish.length(); i++) {
40
0
            char c = _polish.at(i);
41
0
            if (c != '&' && c != '|' && c != '^' && c != '-' && c != ' ' && c != '\\') {
42
0
                bitmap_key += c;
43
0
            } else if (i != 0 && _polish.at(i - 1) == '\\') {
44
0
                bitmap_key += c;
45
0
            } else if (c == '\\') {
46
0
                continue;
47
0
            } else {
48
0
                if (bitmap_key.length() > 0) {
49
0
                    add_key(bitmap_key);
50
0
                    bitmap_key.clear();
51
0
                }
52
0
            }
53
0
        }
54
0
        if (bitmap_key.length() > 0) {
55
0
            add_key(bitmap_key);
56
0
            bitmap_key.clear();
57
0
        }
58
0
    }
59
60
0
    BitmapValue bitmap_calculate() const {
61
0
        std::stack<BitmapValue> values;
62
0
        std::string bitmap_key;
63
0
        for (int i = 0; i < _polish.length(); i++) {
64
0
            char c = _polish.at(i);
65
0
            if (c == ' ') {
66
0
                if (bitmap_key.length() > 0) {
67
0
                    values.push(_bitmaps.at(bitmap_key));
68
0
                    bitmap_key.clear();
69
0
                }
70
0
            } else if (c != '&' && c != '|' && c != '^' && c != '-' && c != '\\') {
71
0
                bitmap_key += c;
72
0
            } else if (i != 0 && _polish.at(i - 1) == '\\') {
73
0
                bitmap_key += c;
74
0
            } else if (c == '\\') {
75
0
                continue;
76
0
            } else {
77
0
                if (bitmap_key.length() > 0) {
78
0
                    values.push(_bitmaps.at(bitmap_key));
79
0
                    bitmap_key.clear();
80
0
                }
81
0
                if (values.size() >= 2) {
82
0
                    BitmapValue op_a = values.top();
83
0
                    values.pop();
84
0
                    BitmapValue op_b = values.top();
85
0
                    values.pop();
86
0
                    BitmapValue cal_result;
87
0
                    bitmap_calculate(op_a, op_b, c, cal_result);
88
0
                    values.push(cal_result);
89
0
                }
90
0
            }
91
0
        }
92
0
        BitmapValue result;
93
0
        if (bitmap_key.length() > 0) {
94
0
            result |= _bitmaps.at(bitmap_key);
95
0
        } else if (!values.empty()) {
96
0
            result |= values.top();
97
0
        }
98
0
        return result;
99
0
    }
100
101
    // calculate the bitmap value by expr bitmap calculate
102
0
    int64_t bitmap_calculate_count() const {
103
0
        if (_bitmaps.empty()) {
104
0
            return 0;
105
0
        }
106
0
        return bitmap_calculate().cardinality();
107
0
    }
108
109
private:
110
0
    constexpr int priority(char c) {
111
0
        switch (c) {
112
0
        case '&':
113
0
            return 1;
114
0
        case '|':
115
0
            return 1;
116
0
        case '^':
117
0
            return 1;
118
0
        case '-':
119
0
            return 1;
120
0
        default:
121
0
            return 0;
122
0
        }
123
0
    }
124
125
    template <class T>
126
0
    std::string print_stack(std::stack<T>& stack) {
127
0
        std::string result;
128
0
        while (!stack.empty()) {
129
0
            result = stack.top() + result;
130
0
            stack.pop();
131
0
        }
132
0
        return result;
133
0
    }
134
135
0
    std::string reverse_polish(const std::string& input_str) {
136
0
        std::stack<char> polish;
137
0
        std::stack<char> op_stack;
138
0
        bool last_is_char = false;
139
0
        for (int i = 0; i < input_str.length(); i++) {
140
0
            char cur_char = input_str.at(i);
141
0
            if (cur_char != '&' && cur_char != '|' && cur_char != '^' && cur_char != '-' &&
142
0
                cur_char != '(' && cur_char != ')' && cur_char != ' ' && cur_char != '\t') {
143
0
                if (!last_is_char) {
144
0
                    polish.push(' ');
145
0
                }
146
0
                polish.push(cur_char);
147
0
                last_is_char = true;
148
0
                continue;
149
0
            } else if (i != 0 && input_str.at(i - 1) == '\\') {
150
0
                polish.push(cur_char);
151
0
                last_is_char = true;
152
0
                continue;
153
0
            } else if (cur_char == ' ' || cur_char == '\t') {
154
0
                last_is_char = false;
155
0
                continue;
156
0
            } else if (cur_char == '(') {
157
0
                op_stack.push(cur_char);
158
0
            } else if (!op_stack.empty() && cur_char == ')') {
159
0
                while (!op_stack.empty() && op_stack.top() != '(') {
160
0
                    polish.push(op_stack.top());
161
0
                    op_stack.pop();
162
0
                }
163
0
                op_stack.pop();
164
0
            } else {
165
0
                if (!op_stack.empty() && op_stack.top() == '(') {
166
0
                    op_stack.push(cur_char);
167
0
                } else {
168
0
                    if (!op_stack.empty() && priority(cur_char) > priority(op_stack.top())) {
169
0
                        op_stack.push(cur_char);
170
0
                    } else {
171
0
                        while (!op_stack.empty()) {
172
0
                            if (op_stack.top() == '(') {
173
0
                                break;
174
0
                            }
175
0
                            if (priority(cur_char) <= priority(op_stack.top())) {
176
0
                                polish.push(op_stack.top());
177
0
                                op_stack.pop();
178
0
                            } else {
179
0
                                break;
180
0
                            }
181
0
                        }
182
0
                        op_stack.push(cur_char);
183
0
                    }
184
0
                }
185
0
            }
186
0
            last_is_char = false;
187
0
        }
188
189
0
        while (!op_stack.empty()) {
190
0
            polish.push(op_stack.top());
191
0
            op_stack.pop();
192
0
        }
193
0
        return print_stack(polish);
194
0
    }
195
196
    void bitmap_calculate(BitmapValue& op_a, BitmapValue& op_b, char op,
197
0
                          BitmapValue& result) const {
198
0
        result |= op_b;
199
0
        switch (op) {
200
0
        case '&':
201
0
            result &= op_a;
202
0
            break;
203
0
        case '|':
204
0
            result |= op_a;
205
0
            break;
206
0
        case '-':
207
0
            result -= op_a;
208
0
            break;
209
0
        case '^':
210
0
            result ^= op_a;
211
0
            break;
212
0
        }
213
0
    }
214
215
    std::string _polish;
216
};
217
} // namespace doris