Coverage Report

Created: 2026-06-02 13:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exprs/function/geo/functions_geo.cpp
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
18
#include "exprs/function/geo/functions_geo.h"
19
20
#include <glog/logging.h>
21
22
#include <algorithm>
23
#include <boost/iterator/iterator_facade.hpp>
24
#include <utility>
25
26
#include "common/compiler_util.h"
27
#include "core/assert_cast.h"
28
#include "core/block/block.h"
29
#include "core/block/column_with_type_and_name.h"
30
#include "core/column/column.h"
31
#include "core/column/column_array.h"
32
#include "core/column/column_execute_util.h"
33
#include "core/column/column_nullable.h"
34
#include "core/data_type/data_type_array.h"
35
#include "core/data_type/data_type_nullable.h"
36
#include "core/data_type/data_type_number.h"
37
#include "core/data_type/data_type_string.h"
38
#include "core/data_type/define_primitive_type.h"
39
#include "core/string_ref.h"
40
#include "exprs/function/geo/geo_common.h"
41
#include "exprs/function/geo/geo_types.h"
42
#include "exprs/function/simple_function_factory.h"
43
44
namespace doris {
45
46
struct StPoint {
47
    static constexpr auto NAME = "st_point";
48
    static const size_t NUM_ARGS = 2;
49
    using Type = DataTypeString;
50
124
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
51
124
        DCHECK_EQ(arguments.size(), 2);
52
124
        auto return_type = block.get_data_type(result);
53
54
124
        auto x_col = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[0]).column);
55
124
        auto y_col = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[1]).column);
56
57
124
        const auto size = x_col.size();
58
59
124
        auto res = ColumnString::create();
60
124
        auto null_map = ColumnUInt8::create(size, 0);
61
124
        auto& null_map_data = null_map->get_data();
62
124
        GeoPoint point;
63
124
        std::string buf;
64
250
        for (int row = 0; row < size; ++row) {
65
126
            auto cur_res = point.from_coord(x_col.value_at(row), y_col.value_at(row));
66
126
            if (cur_res != GEO_PARSE_OK) {
67
0
                null_map_data[row] = 1;
68
0
                res->insert_default();
69
0
                continue;
70
0
            }
71
126
            buf.clear();
72
126
            point.encode_to(&buf);
73
126
            res->insert_data(buf.data(), buf.size());
74
126
        }
75
76
124
        block.replace_by_position(result,
77
124
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
78
124
        return Status::OK();
79
124
    }
80
};
81
82
struct StAsTextName {
83
    static constexpr auto NAME = "st_astext";
84
};
85
struct StAsWktName {
86
    static constexpr auto NAME = "st_aswkt";
87
};
88
89
template <typename FunctionName>
90
struct StAsText {
91
    static constexpr auto NAME = FunctionName::NAME;
92
    static const size_t NUM_ARGS = 1;
93
    using Type = DataTypeString;
94
37
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
95
37
        DCHECK_EQ(arguments.size(), 1);
96
37
        auto return_type = block.get_data_type(result);
97
98
37
        auto& input = block.get_by_position(arguments[0]).column;
99
100
37
        auto size = input->size();
101
102
37
        auto res = ColumnString::create();
103
37
        auto null_map = ColumnUInt8::create(size, 0);
104
37
        auto& null_map_data = null_map->get_data();
105
106
37
        std::unique_ptr<GeoShape> shape;
107
76
        for (int row = 0; row < size; ++row) {
108
39
            auto shape_value = input->get_data_at(row);
109
39
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
110
39
            if (shape == nullptr) {
111
2
                null_map_data[row] = 1;
112
2
                res->insert_default();
113
2
                continue;
114
2
            }
115
37
            auto wkt = shape->as_wkt();
116
37
            res->insert_data(wkt.data(), wkt.size());
117
37
        }
118
37
        block.replace_by_position(result,
119
37
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
120
121
37
        return Status::OK();
122
37
    }
_ZN5doris8StAsTextINS_11StAsWktNameEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
94
2
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
95
2
        DCHECK_EQ(arguments.size(), 1);
96
2
        auto return_type = block.get_data_type(result);
97
98
2
        auto& input = block.get_by_position(arguments[0]).column;
99
100
2
        auto size = input->size();
101
102
2
        auto res = ColumnString::create();
103
2
        auto null_map = ColumnUInt8::create(size, 0);
104
2
        auto& null_map_data = null_map->get_data();
105
106
2
        std::unique_ptr<GeoShape> shape;
107
5
        for (int row = 0; row < size; ++row) {
108
3
            auto shape_value = input->get_data_at(row);
109
3
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
110
3
            if (shape == nullptr) {
111
1
                null_map_data[row] = 1;
112
1
                res->insert_default();
113
1
                continue;
114
1
            }
115
2
            auto wkt = shape->as_wkt();
116
2
            res->insert_data(wkt.data(), wkt.size());
117
2
        }
118
2
        block.replace_by_position(result,
119
2
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
120
121
2
        return Status::OK();
122
2
    }
_ZN5doris8StAsTextINS_12StAsTextNameEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
94
35
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
95
35
        DCHECK_EQ(arguments.size(), 1);
96
35
        auto return_type = block.get_data_type(result);
97
98
35
        auto& input = block.get_by_position(arguments[0]).column;
99
100
35
        auto size = input->size();
101
102
35
        auto res = ColumnString::create();
103
35
        auto null_map = ColumnUInt8::create(size, 0);
104
35
        auto& null_map_data = null_map->get_data();
105
106
35
        std::unique_ptr<GeoShape> shape;
107
71
        for (int row = 0; row < size; ++row) {
108
36
            auto shape_value = input->get_data_at(row);
109
36
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
110
36
            if (shape == nullptr) {
111
1
                null_map_data[row] = 1;
112
1
                res->insert_default();
113
1
                continue;
114
1
            }
115
35
            auto wkt = shape->as_wkt();
116
35
            res->insert_data(wkt.data(), wkt.size());
117
35
        }
118
35
        block.replace_by_position(result,
119
35
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
120
121
35
        return Status::OK();
122
35
    }
123
};
124
125
struct StX {
126
    static constexpr auto NAME = "st_x";
127
    static const size_t NUM_ARGS = 1;
128
    using Type = DataTypeFloat64;
129
5
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
130
5
        DCHECK_EQ(arguments.size(), 1);
131
5
        auto return_type = block.get_data_type(result);
132
133
5
        auto& input = block.get_by_position(arguments[0]).column;
134
135
5
        auto size = input->size();
136
137
5
        auto res = ColumnFloat64::create();
138
5
        auto null_map = ColumnUInt8::create(size, 0);
139
5
        auto& null_map_data = null_map->get_data();
140
5
        res->reserve(size);
141
142
5
        GeoPoint point;
143
11
        for (int row = 0; row < size; ++row) {
144
6
            auto point_value = input->get_data_at(row);
145
6
            auto pt = point.decode_from(point_value.data, point_value.size);
146
147
6
            if (!pt) {
148
1
                null_map_data[row] = 1;
149
1
                res->insert_default();
150
1
                continue;
151
1
            }
152
5
            auto x_value = point.x();
153
5
            res->insert_value(x_value);
154
5
        }
155
5
        block.replace_by_position(result,
156
5
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
157
158
5
        return Status::OK();
159
5
    }
160
};
161
162
struct StY {
163
    static constexpr auto NAME = "st_y";
164
    static const size_t NUM_ARGS = 1;
165
    using Type = DataTypeFloat64;
166
4
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
167
4
        DCHECK_EQ(arguments.size(), 1);
168
4
        auto return_type = block.get_data_type(result);
169
170
4
        auto& input = block.get_by_position(arguments[0]).column;
171
172
4
        auto size = input->size();
173
174
4
        auto res = ColumnFloat64::create();
175
4
        res->reserve(size);
176
4
        auto null_map = ColumnUInt8::create(size, 0);
177
4
        auto& null_map_data = null_map->get_data();
178
179
4
        GeoPoint point;
180
9
        for (int row = 0; row < size; ++row) {
181
5
            auto point_value = input->get_data_at(row);
182
5
            auto pt = point.decode_from(point_value.data, point_value.size);
183
184
5
            if (!pt) {
185
1
                null_map_data[row] = 1;
186
1
                res->insert_default();
187
1
                continue;
188
1
            }
189
4
            auto y_value = point.y();
190
4
            res->insert_value(y_value);
191
4
        }
192
4
        block.replace_by_position(result,
193
4
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
194
195
4
        return Status::OK();
196
4
    }
197
};
198
199
struct StDistanceSphere {
200
    static constexpr auto NAME = "st_distance_sphere";
201
    static const size_t NUM_ARGS = 4;
202
    using Type = DataTypeFloat64;
203
3
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
204
3
        DCHECK_EQ(arguments.size(), 4);
205
3
        auto return_type = block.get_data_type(result);
206
207
3
        auto x_lng = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[0]).column);
208
3
        auto x_lat = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[1]).column);
209
3
        auto y_lng = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[2]).column);
210
3
        auto y_lat = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[3]).column);
211
212
3
        const auto size = x_lng.size();
213
3
        auto res = ColumnFloat64::create();
214
3
        res->reserve(size);
215
3
        auto null_map = ColumnUInt8::create(size, 0);
216
3
        auto& null_map_data = null_map->get_data();
217
10
        for (int row = 0; row < size; ++row) {
218
7
            double distance = 0;
219
7
            if (!GeoPoint::ComputeDistance(x_lng.value_at(row), x_lat.value_at(row),
220
7
                                           y_lng.value_at(row), y_lat.value_at(row), &distance)) {
221
0
                null_map_data[row] = 1;
222
0
                res->insert_default();
223
0
                continue;
224
0
            }
225
7
            res->insert_value(distance);
226
7
        }
227
228
3
        block.replace_by_position(result,
229
3
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
230
3
        return Status::OK();
231
3
    }
232
};
233
234
struct StAngleSphere {
235
    static constexpr auto NAME = "st_angle_sphere";
236
    static const size_t NUM_ARGS = 4;
237
    using Type = DataTypeFloat64;
238
4
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
239
4
        DCHECK_EQ(arguments.size(), 4);
240
4
        auto return_type = block.get_data_type(result);
241
242
4
        auto x_lng = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[0]).column);
243
4
        auto x_lat = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[1]).column);
244
4
        auto y_lng = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[2]).column);
245
4
        auto y_lat = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[3]).column);
246
247
4
        const auto size = x_lng.size();
248
249
4
        auto res = ColumnFloat64::create();
250
4
        res->reserve(size);
251
4
        auto null_map = ColumnUInt8::create(size, 0);
252
4
        auto& null_map_data = null_map->get_data();
253
254
12
        for (int row = 0; row < size; ++row) {
255
8
            double angle = 0;
256
8
            if (!GeoPoint::ComputeAngleSphere(x_lng.value_at(row), x_lat.value_at(row),
257
8
                                              y_lng.value_at(row), y_lat.value_at(row), &angle)) {
258
0
                null_map_data[row] = 1;
259
0
                res->insert_default();
260
0
                continue;
261
0
            }
262
8
            res->insert_value(angle);
263
8
        }
264
265
4
        block.replace_by_position(result,
266
4
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
267
4
        return Status::OK();
268
4
    }
269
};
270
271
struct StAngle {
272
    static constexpr auto NAME = "st_angle";
273
    static const size_t NUM_ARGS = 3;
274
    using Type = DataTypeFloat64;
275
5
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
276
5
        DCHECK_EQ(arguments.size(), 3);
277
5
        auto return_type = block.get_data_type(result);
278
279
5
        auto p1 = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
280
5
        auto p2 = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
281
5
        auto p3 = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[2]).column);
282
5
        const auto size = p1.size();
283
5
        auto res = ColumnFloat64::create();
284
5
        res->reserve(size);
285
5
        auto null_map = ColumnUInt8::create(size, 0);
286
5
        auto& null_map_data = null_map->get_data();
287
288
5
        GeoPoint point1;
289
5
        GeoPoint point2;
290
5
        GeoPoint point3;
291
292
13
        for (int row = 0; row < size; ++row) {
293
8
            auto shape_value1 = p1.value_at(row);
294
8
            auto pt1 = point1.decode_from(shape_value1.data, shape_value1.size);
295
8
            if (!pt1) {
296
1
                null_map_data[row] = 1;
297
1
                res->insert_default();
298
1
                continue;
299
1
            }
300
301
7
            auto shape_value2 = p2.value_at(row);
302
7
            auto pt2 = point2.decode_from(shape_value2.data, shape_value2.size);
303
7
            if (!pt2) {
304
1
                null_map_data[row] = 1;
305
1
                res->insert_default();
306
1
                continue;
307
1
            }
308
6
            auto shape_value3 = p3.value_at(row);
309
6
            auto pt3 = point3.decode_from(shape_value3.data, shape_value3.size);
310
6
            if (!pt3) {
311
1
                null_map_data[row] = 1;
312
1
                res->insert_default();
313
1
                continue;
314
1
            }
315
316
5
            double angle = 0;
317
5
            if (!GeoPoint::ComputeAngle(&point1, &point2, &point3, &angle)) {
318
1
                null_map_data[row] = 1;
319
1
                res->insert_default();
320
1
                continue;
321
1
            }
322
4
            res->insert_value(angle);
323
4
        }
324
5
        block.replace_by_position(result,
325
5
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
326
5
        return Status::OK();
327
5
    }
328
};
329
330
struct StAzimuth {
331
    static constexpr auto NAME = "st_azimuth";
332
    static const size_t NUM_ARGS = 2;
333
    using Type = DataTypeFloat64;
334
7
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
335
7
        DCHECK_EQ(arguments.size(), 2);
336
7
        auto return_type = block.get_data_type(result);
337
338
7
        auto left_col = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
339
7
        auto right_col =
340
7
                ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
341
342
7
        const auto size = left_col.size();
343
7
        auto res = ColumnFloat64::create();
344
7
        res->reserve(size);
345
7
        auto null_map = ColumnUInt8::create(size, 0);
346
7
        auto& null_map_data = null_map->get_data();
347
7
        GeoPoint point1;
348
7
        GeoPoint point2;
349
16
        for (int row = 0; row < size; ++row) {
350
9
            auto shape_value1 = left_col.value_at(row);
351
9
            auto pt1 = point1.decode_from(shape_value1.data, shape_value1.size);
352
9
            auto shape_value2 = right_col.value_at(row);
353
9
            auto pt2 = point2.decode_from(shape_value2.data, shape_value2.size);
354
355
9
            if (!(pt1 && pt2)) {
356
2
                null_map_data[row] = 1;
357
2
                res->insert_default();
358
2
                continue;
359
2
            }
360
361
7
            double angle = 0;
362
7
            if (!GeoPoint::ComputeAzimuth(&point1, &point2, &angle)) {
363
1
                null_map_data[row] = 1;
364
1
                res->insert_default();
365
1
                continue;
366
1
            }
367
6
            res->insert_value(angle);
368
6
        }
369
7
        block.replace_by_position(result,
370
7
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
371
7
        return Status::OK();
372
7
    }
373
};
374
375
struct StAreaSquareMeters {
376
    static constexpr auto NAME = "st_area_square_meters";
377
    static const size_t NUM_ARGS = 1;
378
    using Type = DataTypeFloat64;
379
3
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
380
3
        DCHECK_EQ(arguments.size(), 1);
381
3
        auto return_type = block.get_data_type(result);
382
383
3
        auto col = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
384
3
        const auto size = col->size();
385
3
        auto res = ColumnFloat64::create();
386
3
        res->reserve(size);
387
3
        auto null_map = ColumnUInt8::create(size, 0);
388
3
        auto& null_map_data = null_map->get_data();
389
3
        std::unique_ptr<GeoShape> shape;
390
391
7
        for (int row = 0; row < size; ++row) {
392
4
            auto shape_value = col->get_data_at(row);
393
4
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
394
4
            if (!shape) {
395
1
                null_map_data[row] = 1;
396
1
                res->insert_default();
397
1
                continue;
398
1
            }
399
400
3
            double area = 0;
401
3
            if (!GeoShape::ComputeArea(shape.get(), &area, "square_meters")) {
402
0
                null_map_data[row] = 1;
403
0
                res->insert_default();
404
0
                continue;
405
0
            }
406
3
            res->insert_value(area);
407
3
        }
408
409
3
        block.replace_by_position(result,
410
3
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
411
3
        return Status::OK();
412
3
    }
413
};
414
415
struct StAreaSquareKm {
416
    static constexpr auto NAME = "st_area_square_km";
417
    static const size_t NUM_ARGS = 1;
418
    using Type = DataTypeFloat64;
419
3
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
420
3
        DCHECK_EQ(arguments.size(), 1);
421
3
        auto return_type = block.get_data_type(result);
422
423
3
        auto col = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
424
3
        const auto size = col->size();
425
3
        auto res = ColumnFloat64::create();
426
3
        res->reserve(size);
427
3
        auto null_map = ColumnUInt8::create(size, 0);
428
3
        auto& null_map_data = null_map->get_data();
429
430
3
        std::unique_ptr<GeoShape> shape;
431
432
7
        for (int row = 0; row < size; ++row) {
433
4
            auto shape_value = col->get_data_at(row);
434
4
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
435
4
            if (!shape) {
436
1
                null_map_data[row] = 1;
437
1
                res->insert_default();
438
1
                continue;
439
1
            }
440
441
3
            double area = 0;
442
3
            if (!GeoShape::ComputeArea(shape.get(), &area, "square_km")) {
443
0
                null_map_data[row] = 1;
444
0
                res->insert_default();
445
0
                ;
446
0
                continue;
447
0
            }
448
3
            res->insert_value(area);
449
3
        }
450
451
3
        block.replace_by_position(result,
452
3
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
453
3
        return Status::OK();
454
3
    }
455
};
456
457
struct StCircle {
458
    static constexpr auto NAME = "st_circle";
459
    static const size_t NUM_ARGS = 3;
460
    using Type = DataTypeString;
461
98
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
462
98
        DCHECK_EQ(arguments.size(), 3);
463
98
        auto return_type = block.get_data_type(result);
464
98
        auto center_lng =
465
98
                ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[0]).column);
466
98
        auto center_lat =
467
98
                ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[1]).column);
468
98
        auto radius = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[2]).column);
469
470
98
        const auto size = center_lng.size();
471
472
98
        auto res = ColumnString::create();
473
474
98
        auto null_map = ColumnUInt8::create(size, 0);
475
98
        auto& null_map_data = null_map->get_data();
476
477
98
        GeoCircle circle;
478
98
        std::string buf;
479
199
        for (int row = 0; row < size; ++row) {
480
101
            auto lng_value = center_lng.value_at(row);
481
101
            auto lat_value = center_lat.value_at(row);
482
101
            auto radius_value = radius.value_at(row);
483
484
101
            auto value = circle.init(lng_value, lat_value, radius_value);
485
101
            if (value != GEO_PARSE_OK) {
486
0
                null_map_data[row] = 1;
487
0
                res->insert_default();
488
0
                continue;
489
0
            }
490
101
            buf.clear();
491
101
            circle.encode_to(&buf);
492
101
            res->insert_data(buf.data(), buf.size());
493
101
        }
494
98
        block.replace_by_position(result,
495
98
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
496
98
        return Status::OK();
497
98
    }
498
};
499
500
template <typename Func>
501
struct StRelationFunction {
502
    static constexpr auto NAME = Func::NAME;
503
    static const size_t NUM_ARGS = 2;
504
    using Type = DataTypeUInt8;
505
506
247
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
507
247
        DCHECK_EQ(arguments.size(), 2);
508
247
        auto return_type = block.get_data_type(result);
509
247
        auto left_col = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
510
247
        auto right_col =
511
247
                ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
512
513
247
        const auto size = left_col.size();
514
515
247
        auto res = ColumnUInt8::create(size, 0);
516
247
        auto null_map = ColumnUInt8::create(size, 0);
517
247
        auto& null_map_data = null_map->get_data();
518
519
497
        for (int row = 0; row < size; ++row) {
520
250
            auto lhs_value = left_col.value_at(row);
521
250
            auto rhs_value = right_col.value_at(row);
522
523
250
            std::unique_ptr<GeoShape> shape1(
524
250
                    GeoShape::from_encoded(lhs_value.data, lhs_value.size));
525
250
            std::unique_ptr<GeoShape> shape2(
526
250
                    GeoShape::from_encoded(rhs_value.data, rhs_value.size));
527
528
250
            if (!shape1 || !shape2) {
529
2
                null_map_data[row] = 1;
530
2
                continue;
531
2
            }
532
248
            auto relation_value = Func::evaluate(shape1.get(), shape2.get());
533
248
            res->get_data()[row] = relation_value;
534
248
        }
535
247
        block.replace_by_position(result,
536
247
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
537
247
        return Status::OK();
538
247
    }
_ZN5doris18StRelationFunctionINS_14StContainsFuncEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
506
61
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
507
61
        DCHECK_EQ(arguments.size(), 2);
508
61
        auto return_type = block.get_data_type(result);
509
61
        auto left_col = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
510
61
        auto right_col =
511
61
                ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
512
513
61
        const auto size = left_col.size();
514
515
61
        auto res = ColumnUInt8::create(size, 0);
516
61
        auto null_map = ColumnUInt8::create(size, 0);
517
61
        auto& null_map_data = null_map->get_data();
518
519
125
        for (int row = 0; row < size; ++row) {
520
64
            auto lhs_value = left_col.value_at(row);
521
64
            auto rhs_value = right_col.value_at(row);
522
523
64
            std::unique_ptr<GeoShape> shape1(
524
64
                    GeoShape::from_encoded(lhs_value.data, lhs_value.size));
525
64
            std::unique_ptr<GeoShape> shape2(
526
64
                    GeoShape::from_encoded(rhs_value.data, rhs_value.size));
527
528
64
            if (!shape1 || !shape2) {
529
2
                null_map_data[row] = 1;
530
2
                continue;
531
2
            }
532
62
            auto relation_value = Func::evaluate(shape1.get(), shape2.get());
533
62
            res->get_data()[row] = relation_value;
534
62
        }
535
61
        block.replace_by_position(result,
536
61
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
537
61
        return Status::OK();
538
61
    }
_ZN5doris18StRelationFunctionINS_16StIntersectsFuncEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
506
62
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
507
62
        DCHECK_EQ(arguments.size(), 2);
508
62
        auto return_type = block.get_data_type(result);
509
62
        auto left_col = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
510
62
        auto right_col =
511
62
                ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
512
513
62
        const auto size = left_col.size();
514
515
62
        auto res = ColumnUInt8::create(size, 0);
516
62
        auto null_map = ColumnUInt8::create(size, 0);
517
62
        auto& null_map_data = null_map->get_data();
518
519
124
        for (int row = 0; row < size; ++row) {
520
62
            auto lhs_value = left_col.value_at(row);
521
62
            auto rhs_value = right_col.value_at(row);
522
523
62
            std::unique_ptr<GeoShape> shape1(
524
62
                    GeoShape::from_encoded(lhs_value.data, lhs_value.size));
525
62
            std::unique_ptr<GeoShape> shape2(
526
62
                    GeoShape::from_encoded(rhs_value.data, rhs_value.size));
527
528
62
            if (!shape1 || !shape2) {
529
0
                null_map_data[row] = 1;
530
0
                continue;
531
0
            }
532
62
            auto relation_value = Func::evaluate(shape1.get(), shape2.get());
533
62
            res->get_data()[row] = relation_value;
534
62
        }
535
62
        block.replace_by_position(result,
536
62
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
537
62
        return Status::OK();
538
62
    }
_ZN5doris18StRelationFunctionINS_14StDisjointFuncEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
506
55
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
507
55
        DCHECK_EQ(arguments.size(), 2);
508
55
        auto return_type = block.get_data_type(result);
509
55
        auto left_col = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
510
55
        auto right_col =
511
55
                ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
512
513
55
        const auto size = left_col.size();
514
515
55
        auto res = ColumnUInt8::create(size, 0);
516
55
        auto null_map = ColumnUInt8::create(size, 0);
517
55
        auto& null_map_data = null_map->get_data();
518
519
110
        for (int row = 0; row < size; ++row) {
520
55
            auto lhs_value = left_col.value_at(row);
521
55
            auto rhs_value = right_col.value_at(row);
522
523
55
            std::unique_ptr<GeoShape> shape1(
524
55
                    GeoShape::from_encoded(lhs_value.data, lhs_value.size));
525
55
            std::unique_ptr<GeoShape> shape2(
526
55
                    GeoShape::from_encoded(rhs_value.data, rhs_value.size));
527
528
55
            if (!shape1 || !shape2) {
529
0
                null_map_data[row] = 1;
530
0
                continue;
531
0
            }
532
55
            auto relation_value = Func::evaluate(shape1.get(), shape2.get());
533
55
            res->get_data()[row] = relation_value;
534
55
        }
535
55
        block.replace_by_position(result,
536
55
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
537
55
        return Status::OK();
538
55
    }
_ZN5doris18StRelationFunctionINS_13StTouchesFuncEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
506
69
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
507
69
        DCHECK_EQ(arguments.size(), 2);
508
69
        auto return_type = block.get_data_type(result);
509
69
        auto left_col = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
510
69
        auto right_col =
511
69
                ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
512
513
69
        const auto size = left_col.size();
514
515
69
        auto res = ColumnUInt8::create(size, 0);
516
69
        auto null_map = ColumnUInt8::create(size, 0);
517
69
        auto& null_map_data = null_map->get_data();
518
519
138
        for (int row = 0; row < size; ++row) {
520
69
            auto lhs_value = left_col.value_at(row);
521
69
            auto rhs_value = right_col.value_at(row);
522
523
69
            std::unique_ptr<GeoShape> shape1(
524
69
                    GeoShape::from_encoded(lhs_value.data, lhs_value.size));
525
69
            std::unique_ptr<GeoShape> shape2(
526
69
                    GeoShape::from_encoded(rhs_value.data, rhs_value.size));
527
528
69
            if (!shape1 || !shape2) {
529
0
                null_map_data[row] = 1;
530
0
                continue;
531
0
            }
532
69
            auto relation_value = Func::evaluate(shape1.get(), shape2.get());
533
69
            res->get_data()[row] = relation_value;
534
69
        }
535
69
        block.replace_by_position(result,
536
69
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
537
69
        return Status::OK();
538
69
    }
539
};
540
541
struct StContainsFunc {
542
    static constexpr auto NAME = "st_contains";
543
62
    static bool evaluate(GeoShape* shape1, GeoShape* shape2) { return shape1->contains(shape2); }
544
};
545
546
struct StIntersectsFunc {
547
    static constexpr auto NAME = "st_intersects";
548
62
    static bool evaluate(GeoShape* shape1, GeoShape* shape2) { return shape1->intersects(shape2); }
549
};
550
551
struct StDisjointFunc {
552
    static constexpr auto NAME = "st_disjoint";
553
55
    static bool evaluate(GeoShape* shape1, GeoShape* shape2) { return shape1->disjoint(shape2); }
554
};
555
556
struct StTouchesFunc {
557
    static constexpr auto NAME = "st_touches";
558
69
    static bool evaluate(GeoShape* shape1, GeoShape* shape2) { return shape1->touches(shape2); }
559
};
560
561
struct StGeometryFromText {
562
    static constexpr auto NAME = "st_geometryfromtext";
563
    static constexpr GeoShapeType shape_type = GEO_SHAPE_ANY;
564
};
565
566
struct StGeomFromText {
567
    static constexpr auto NAME = "st_geomfromtext";
568
    static constexpr GeoShapeType shape_type = GEO_SHAPE_ANY;
569
};
570
571
struct StLineFromText {
572
    static constexpr auto NAME = "st_linefromtext";
573
    static constexpr GeoShapeType shape_type = GEO_SHAPE_LINE_STRING;
574
};
575
576
struct StLineStringFromText {
577
    static constexpr auto NAME = "st_linestringfromtext";
578
    static constexpr GeoShapeType shape_type = GEO_SHAPE_LINE_STRING;
579
};
580
581
struct StPolygon {
582
    static constexpr auto NAME = "st_polygon";
583
    static constexpr GeoShapeType shape_type = GEO_SHAPE_POLYGON;
584
};
585
586
struct StPolyFromText {
587
    static constexpr auto NAME = "st_polyfromtext";
588
    static constexpr GeoShapeType shape_type = GEO_SHAPE_POLYGON;
589
};
590
591
struct StPolygonFromText {
592
    static constexpr auto NAME = "st_polygonfromtext";
593
    static constexpr GeoShapeType shape_type = GEO_SHAPE_POLYGON;
594
};
595
596
template <typename Impl>
597
struct StGeoFromText {
598
    static constexpr auto NAME = Impl::NAME;
599
    static const size_t NUM_ARGS = 1;
600
    using Type = DataTypeString;
601
539
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
602
539
        DCHECK_EQ(arguments.size(), 1);
603
539
        auto return_type = block.get_data_type(result);
604
539
        auto& geo = block.get_by_position(arguments[0]).column;
605
606
539
        const auto size = geo->size();
607
539
        auto res = ColumnString::create();
608
539
        auto null_map = ColumnUInt8::create(size, 0);
609
539
        auto& null_map_data = null_map->get_data();
610
539
        GeoParseStatus status;
611
539
        std::string buf;
612
1.12k
        for (int row = 0; row < size; ++row) {
613
581
            auto value = geo->get_data_at(row);
614
581
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
615
581
            if (shape == nullptr || status != GEO_PARSE_OK ||
616
581
                (Impl::shape_type != GEO_SHAPE_ANY && shape->type() != Impl::shape_type)) {
617
23
                null_map_data[row] = 1;
618
23
                res->insert_default();
619
23
                continue;
620
23
            }
621
558
            buf.clear();
622
558
            shape->encode_to(&buf);
623
558
            res->insert_data(buf.data(), buf.size());
624
558
        }
625
539
        block.replace_by_position(result,
626
539
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
627
539
        return Status::OK();
628
539
    }
_ZN5doris13StGeoFromTextINS_18StGeometryFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
601
162
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
602
162
        DCHECK_EQ(arguments.size(), 1);
603
162
        auto return_type = block.get_data_type(result);
604
162
        auto& geo = block.get_by_position(arguments[0]).column;
605
606
162
        const auto size = geo->size();
607
162
        auto res = ColumnString::create();
608
162
        auto null_map = ColumnUInt8::create(size, 0);
609
162
        auto& null_map_data = null_map->get_data();
610
162
        GeoParseStatus status;
611
162
        std::string buf;
612
325
        for (int row = 0; row < size; ++row) {
613
163
            auto value = geo->get_data_at(row);
614
163
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
615
163
            if (shape == nullptr || status != GEO_PARSE_OK ||
616
163
                (Impl::shape_type != GEO_SHAPE_ANY && shape->type() != Impl::shape_type)) {
617
3
                null_map_data[row] = 1;
618
3
                res->insert_default();
619
3
                continue;
620
3
            }
621
160
            buf.clear();
622
160
            shape->encode_to(&buf);
623
160
            res->insert_data(buf.data(), buf.size());
624
160
        }
625
162
        block.replace_by_position(result,
626
162
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
627
162
        return Status::OK();
628
162
    }
_ZN5doris13StGeoFromTextINS_14StGeomFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
601
204
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
602
204
        DCHECK_EQ(arguments.size(), 1);
603
204
        auto return_type = block.get_data_type(result);
604
204
        auto& geo = block.get_by_position(arguments[0]).column;
605
606
204
        const auto size = geo->size();
607
204
        auto res = ColumnString::create();
608
204
        auto null_map = ColumnUInt8::create(size, 0);
609
204
        auto& null_map_data = null_map->get_data();
610
204
        GeoParseStatus status;
611
204
        std::string buf;
612
446
        for (int row = 0; row < size; ++row) {
613
242
            auto value = geo->get_data_at(row);
614
242
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
615
242
            if (shape == nullptr || status != GEO_PARSE_OK ||
616
242
                (Impl::shape_type != GEO_SHAPE_ANY && shape->type() != Impl::shape_type)) {
617
17
                null_map_data[row] = 1;
618
17
                res->insert_default();
619
17
                continue;
620
17
            }
621
225
            buf.clear();
622
225
            shape->encode_to(&buf);
623
225
            res->insert_data(buf.data(), buf.size());
624
225
        }
625
204
        block.replace_by_position(result,
626
204
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
627
204
        return Status::OK();
628
204
    }
_ZN5doris13StGeoFromTextINS_14StLineFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
601
84
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
602
84
        DCHECK_EQ(arguments.size(), 1);
603
84
        auto return_type = block.get_data_type(result);
604
84
        auto& geo = block.get_by_position(arguments[0]).column;
605
606
84
        const auto size = geo->size();
607
84
        auto res = ColumnString::create();
608
84
        auto null_map = ColumnUInt8::create(size, 0);
609
84
        auto& null_map_data = null_map->get_data();
610
84
        GeoParseStatus status;
611
84
        std::string buf;
612
169
        for (int row = 0; row < size; ++row) {
613
85
            auto value = geo->get_data_at(row);
614
85
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
615
85
            if (shape == nullptr || status != GEO_PARSE_OK ||
616
85
                (Impl::shape_type != GEO_SHAPE_ANY && shape->type() != Impl::shape_type)) {
617
1
                null_map_data[row] = 1;
618
1
                res->insert_default();
619
1
                continue;
620
1
            }
621
84
            buf.clear();
622
84
            shape->encode_to(&buf);
623
84
            res->insert_data(buf.data(), buf.size());
624
84
        }
625
84
        block.replace_by_position(result,
626
84
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
627
84
        return Status::OK();
628
84
    }
_ZN5doris13StGeoFromTextINS_20StLineStringFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
601
1
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
602
1
        DCHECK_EQ(arguments.size(), 1);
603
1
        auto return_type = block.get_data_type(result);
604
1
        auto& geo = block.get_by_position(arguments[0]).column;
605
606
1
        const auto size = geo->size();
607
1
        auto res = ColumnString::create();
608
1
        auto null_map = ColumnUInt8::create(size, 0);
609
1
        auto& null_map_data = null_map->get_data();
610
1
        GeoParseStatus status;
611
1
        std::string buf;
612
2
        for (int row = 0; row < size; ++row) {
613
1
            auto value = geo->get_data_at(row);
614
1
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
615
1
            if (shape == nullptr || status != GEO_PARSE_OK ||
616
1
                (Impl::shape_type != GEO_SHAPE_ANY && shape->type() != Impl::shape_type)) {
617
0
                null_map_data[row] = 1;
618
0
                res->insert_default();
619
0
                continue;
620
0
            }
621
1
            buf.clear();
622
1
            shape->encode_to(&buf);
623
1
            res->insert_data(buf.data(), buf.size());
624
1
        }
625
1
        block.replace_by_position(result,
626
1
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
627
1
        return Status::OK();
628
1
    }
_ZN5doris13StGeoFromTextINS_9StPolygonEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
601
85
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
602
85
        DCHECK_EQ(arguments.size(), 1);
603
85
        auto return_type = block.get_data_type(result);
604
85
        auto& geo = block.get_by_position(arguments[0]).column;
605
606
85
        const auto size = geo->size();
607
85
        auto res = ColumnString::create();
608
85
        auto null_map = ColumnUInt8::create(size, 0);
609
85
        auto& null_map_data = null_map->get_data();
610
85
        GeoParseStatus status;
611
85
        std::string buf;
612
171
        for (int row = 0; row < size; ++row) {
613
86
            auto value = geo->get_data_at(row);
614
86
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
615
86
            if (shape == nullptr || status != GEO_PARSE_OK ||
616
86
                (Impl::shape_type != GEO_SHAPE_ANY && shape->type() != Impl::shape_type)) {
617
1
                null_map_data[row] = 1;
618
1
                res->insert_default();
619
1
                continue;
620
1
            }
621
85
            buf.clear();
622
85
            shape->encode_to(&buf);
623
85
            res->insert_data(buf.data(), buf.size());
624
85
        }
625
85
        block.replace_by_position(result,
626
85
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
627
85
        return Status::OK();
628
85
    }
_ZN5doris13StGeoFromTextINS_17StPolygonFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
601
2
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
602
2
        DCHECK_EQ(arguments.size(), 1);
603
2
        auto return_type = block.get_data_type(result);
604
2
        auto& geo = block.get_by_position(arguments[0]).column;
605
606
2
        const auto size = geo->size();
607
2
        auto res = ColumnString::create();
608
2
        auto null_map = ColumnUInt8::create(size, 0);
609
2
        auto& null_map_data = null_map->get_data();
610
2
        GeoParseStatus status;
611
2
        std::string buf;
612
5
        for (int row = 0; row < size; ++row) {
613
3
            auto value = geo->get_data_at(row);
614
3
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
615
3
            if (shape == nullptr || status != GEO_PARSE_OK ||
616
3
                (Impl::shape_type != GEO_SHAPE_ANY && shape->type() != Impl::shape_type)) {
617
1
                null_map_data[row] = 1;
618
1
                res->insert_default();
619
1
                continue;
620
1
            }
621
2
            buf.clear();
622
2
            shape->encode_to(&buf);
623
2
            res->insert_data(buf.data(), buf.size());
624
2
        }
625
2
        block.replace_by_position(result,
626
2
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
627
2
        return Status::OK();
628
2
    }
_ZN5doris13StGeoFromTextINS_14StPolyFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
601
1
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
602
1
        DCHECK_EQ(arguments.size(), 1);
603
1
        auto return_type = block.get_data_type(result);
604
1
        auto& geo = block.get_by_position(arguments[0]).column;
605
606
1
        const auto size = geo->size();
607
1
        auto res = ColumnString::create();
608
1
        auto null_map = ColumnUInt8::create(size, 0);
609
1
        auto& null_map_data = null_map->get_data();
610
1
        GeoParseStatus status;
611
1
        std::string buf;
612
2
        for (int row = 0; row < size; ++row) {
613
1
            auto value = geo->get_data_at(row);
614
1
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
615
1
            if (shape == nullptr || status != GEO_PARSE_OK ||
616
1
                (Impl::shape_type != GEO_SHAPE_ANY && shape->type() != Impl::shape_type)) {
617
0
                null_map_data[row] = 1;
618
0
                res->insert_default();
619
0
                continue;
620
0
            }
621
1
            buf.clear();
622
1
            shape->encode_to(&buf);
623
1
            res->insert_data(buf.data(), buf.size());
624
1
        }
625
1
        block.replace_by_position(result,
626
1
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
627
1
        return Status::OK();
628
1
    }
629
};
630
631
struct StGeometryFromWKB {
632
    static constexpr auto NAME = "st_geometryfromwkb";
633
    static constexpr GeoShapeType shape_type = GEO_SHAPE_ANY;
634
};
635
636
struct StGeomFromWKB {
637
    static constexpr auto NAME = "st_geomfromwkb";
638
    static constexpr GeoShapeType shape_type = GEO_SHAPE_ANY;
639
};
640
641
template <typename Impl>
642
struct StGeoFromWkb {
643
    static constexpr auto NAME = Impl::NAME;
644
    static const size_t NUM_ARGS = 1;
645
    using Type = DataTypeString;
646
9
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
647
9
        DCHECK_EQ(arguments.size(), 1);
648
9
        auto return_type = block.get_data_type(result);
649
9
        auto& geo = block.get_by_position(arguments[0]).column;
650
651
9
        const auto size = geo->size();
652
9
        auto res = ColumnString::create();
653
9
        auto null_map = ColumnUInt8::create(size, 0);
654
9
        auto& null_map_data = null_map->get_data();
655
9
        GeoParseStatus status;
656
9
        std::string buf;
657
18
        for (int row = 0; row < size; ++row) {
658
9
            auto value = geo->get_data_at(row);
659
9
            std::unique_ptr<GeoShape> shape = GeoShape::from_wkb(value.data, value.size, status);
660
9
            if (shape == nullptr || status != GEO_PARSE_OK) {
661
0
                null_map_data[row] = 1;
662
0
                res->insert_default();
663
0
                continue;
664
0
            }
665
9
            buf.clear();
666
9
            shape->encode_to(&buf);
667
9
            res->insert_data(buf.data(), buf.size());
668
9
        }
669
9
        block.replace_by_position(result,
670
9
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
671
9
        return Status::OK();
672
9
    }
_ZN5doris12StGeoFromWkbINS_17StGeometryFromWKBEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
646
6
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
647
6
        DCHECK_EQ(arguments.size(), 1);
648
6
        auto return_type = block.get_data_type(result);
649
6
        auto& geo = block.get_by_position(arguments[0]).column;
650
651
6
        const auto size = geo->size();
652
6
        auto res = ColumnString::create();
653
6
        auto null_map = ColumnUInt8::create(size, 0);
654
6
        auto& null_map_data = null_map->get_data();
655
6
        GeoParseStatus status;
656
6
        std::string buf;
657
12
        for (int row = 0; row < size; ++row) {
658
6
            auto value = geo->get_data_at(row);
659
6
            std::unique_ptr<GeoShape> shape = GeoShape::from_wkb(value.data, value.size, status);
660
6
            if (shape == nullptr || status != GEO_PARSE_OK) {
661
0
                null_map_data[row] = 1;
662
0
                res->insert_default();
663
0
                continue;
664
0
            }
665
6
            buf.clear();
666
6
            shape->encode_to(&buf);
667
6
            res->insert_data(buf.data(), buf.size());
668
6
        }
669
6
        block.replace_by_position(result,
670
6
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
671
6
        return Status::OK();
672
6
    }
_ZN5doris12StGeoFromWkbINS_13StGeomFromWKBEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
646
3
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
647
3
        DCHECK_EQ(arguments.size(), 1);
648
3
        auto return_type = block.get_data_type(result);
649
3
        auto& geo = block.get_by_position(arguments[0]).column;
650
651
3
        const auto size = geo->size();
652
3
        auto res = ColumnString::create();
653
3
        auto null_map = ColumnUInt8::create(size, 0);
654
3
        auto& null_map_data = null_map->get_data();
655
3
        GeoParseStatus status;
656
3
        std::string buf;
657
6
        for (int row = 0; row < size; ++row) {
658
3
            auto value = geo->get_data_at(row);
659
3
            std::unique_ptr<GeoShape> shape = GeoShape::from_wkb(value.data, value.size, status);
660
3
            if (shape == nullptr || status != GEO_PARSE_OK) {
661
0
                null_map_data[row] = 1;
662
0
                res->insert_default();
663
0
                continue;
664
0
            }
665
3
            buf.clear();
666
3
            shape->encode_to(&buf);
667
3
            res->insert_data(buf.data(), buf.size());
668
3
        }
669
3
        block.replace_by_position(result,
670
3
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
671
3
        return Status::OK();
672
3
    }
673
};
674
675
struct StAsBinary {
676
    static constexpr auto NAME = "st_asbinary";
677
    static const size_t NUM_ARGS = 1;
678
    using Type = DataTypeString;
679
8
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
680
8
        DCHECK_EQ(arguments.size(), 1);
681
8
        auto return_type = block.get_data_type(result);
682
8
        auto res = ColumnString::create();
683
684
8
        auto col = block.get_by_position(arguments[0]).column;
685
8
        const auto size = col->size();
686
8
        auto null_map = ColumnUInt8::create(size, 0);
687
8
        auto& null_map_data = null_map->get_data();
688
8
        std::unique_ptr<GeoShape> shape;
689
690
16
        for (int row = 0; row < size; ++row) {
691
8
            auto shape_value = col->get_data_at(row);
692
8
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
693
8
            if (!shape) {
694
0
                null_map_data[row] = 1;
695
0
                res->insert_default();
696
0
                continue;
697
0
            }
698
699
8
            std::string binary = GeoShape::as_binary(shape.get());
700
8
            if (binary.empty()) {
701
0
                null_map_data[row] = 1;
702
0
                res->insert_default();
703
0
                continue;
704
0
            }
705
8
            res->insert_data(binary.data(), binary.size());
706
8
        }
707
708
8
        block.replace_by_position(result,
709
8
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
710
8
        return Status::OK();
711
8
    }
712
};
713
714
struct StLength {
715
    static constexpr auto NAME = "st_length";
716
    static const size_t NUM_ARGS = 1;
717
    using Type = DataTypeFloat64;
718
15
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
719
15
        DCHECK_EQ(arguments.size(), 1);
720
15
        auto return_type = block.get_data_type(result);
721
722
15
        auto col = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
723
15
        const auto size = col->size();
724
15
        auto res = ColumnFloat64::create();
725
15
        res->reserve(size);
726
15
        auto null_map = ColumnUInt8::create(size, 0);
727
15
        auto& null_map_data = null_map->get_data();
728
729
15
        std::unique_ptr<GeoShape> shape;
730
33
        for (int row = 0; row < size; ++row) {
731
18
            auto shape_value = col->get_data_at(row);
732
18
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
733
18
            if (!shape) {
734
1
                null_map_data[row] = 1;
735
1
                res->insert_default();
736
1
                continue;
737
1
            }
738
739
17
            double length = shape->Length();
740
17
            res->insert_value(length);
741
17
        }
742
743
15
        block.replace_by_position(result,
744
15
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
745
15
        return Status::OK();
746
15
    }
747
};
748
749
struct StGeometryType {
750
    static constexpr auto NAME = "st_geometrytype";
751
    static const size_t NUM_ARGS = 1;
752
    using Type = DataTypeString;
753
28
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
754
28
        DCHECK_EQ(arguments.size(), 1);
755
28
        auto return_type = block.get_data_type(result);
756
757
28
        auto col = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
758
28
        const auto size = col->size();
759
28
        auto res = ColumnString::create();
760
28
        auto null_map = ColumnUInt8::create(size, 0);
761
28
        auto& null_map_data = null_map->get_data();
762
763
28
        std::unique_ptr<GeoShape> shape;
764
67
        for (int row = 0; row < size; ++row) {
765
39
            auto shape_value = col->get_data_at(row);
766
39
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
767
39
            if (!shape) {
768
5
                null_map_data[row] = 1;
769
5
                res->insert_default();
770
5
                continue;
771
5
            }
772
773
34
            auto geo_type = shape->GeometryType();
774
34
            res->insert_data(geo_type.data(), geo_type.size());
775
34
        }
776
777
28
        block.replace_by_position(result,
778
28
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
779
28
        return Status::OK();
780
28
    }
781
};
782
783
struct StDistance {
784
    static constexpr auto NAME = "st_distance";
785
    static const size_t NUM_ARGS = 2;
786
    using Type = DataTypeFloat64;
787
788
47
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
789
47
        DCHECK_EQ(arguments.size(), 2);
790
47
        auto return_type = block.get_data_type(result);
791
47
        const auto& [left_column, left_const] =
792
47
                unpack_if_const(block.get_by_position(arguments[0]).column);
793
47
        const auto& [right_column, right_const] =
794
47
                unpack_if_const(block.get_by_position(arguments[1]).column);
795
796
47
        const auto size = std::max(left_column->size(), right_column->size());
797
798
47
        auto res = ColumnFloat64::create();
799
47
        res->reserve(size);
800
47
        auto null_map = ColumnUInt8::create(size, 0);
801
47
        auto& null_map_data = null_map->get_data();
802
803
47
        if (left_const) {
804
0
            const_vector(left_column, right_column, res, null_map_data, size);
805
47
        } else if (right_const) {
806
0
            vector_const(left_column, right_column, res, null_map_data, size);
807
47
        } else {
808
47
            vector_vector(left_column, right_column, res, null_map_data, size);
809
47
        }
810
47
        block.replace_by_position(result,
811
47
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
812
47
        return Status::OK();
813
47
    }
814
815
private:
816
99
    static bool decode_shape(const StringRef& value, std::unique_ptr<GeoShape>& shape) {
817
99
        shape = GeoShape::from_encoded(value.data, value.size);
818
99
        return static_cast<bool>(shape);
819
99
    }
820
821
    static void loop_do(StringRef& lhs_value, StringRef& rhs_value,
822
                        std::vector<std::unique_ptr<GeoShape>>& shapes,
823
50
                        ColumnFloat64::MutablePtr& res, NullMap& null_map, int row) {
824
50
        StringRef* strs[2] = {&lhs_value, &rhs_value};
825
148
        for (int i = 0; i < 2; ++i) {
826
99
            if (!decode_shape(*strs[i], shapes[i])) {
827
1
                null_map[row] = 1;
828
1
                res->insert_default();
829
1
                return;
830
1
            }
831
99
        }
832
49
        double distance = shapes[0]->Distance(shapes[1].get());
833
49
        if (UNLIKELY(distance < 0)) {
834
0
            null_map[row] = 1;
835
0
            res->insert_default();
836
0
            return;
837
0
        }
838
49
        res->insert_value(distance);
839
49
    }
840
841
    static void const_vector(const ColumnPtr& left_column, const ColumnPtr& right_column,
842
0
                             ColumnFloat64::MutablePtr& res, NullMap& null_map, const size_t size) {
843
0
        const auto* left_string = assert_cast<const ColumnString*>(left_column.get());
844
0
        const auto* right_string = assert_cast<const ColumnString*>(right_column.get());
845
846
0
        auto lhs_value = left_string->get_data_at(0);
847
0
        std::unique_ptr<GeoShape> lhs_shape;
848
0
        if (!decode_shape(lhs_value, lhs_shape)) {
849
0
            for (int row = 0; row < size; ++row) {
850
0
                null_map[row] = 1;
851
0
                res->insert_default();
852
0
            }
853
0
            return;
854
0
        }
855
856
0
        std::unique_ptr<GeoShape> rhs_shape;
857
0
        for (int row = 0; row < size; ++row) {
858
0
            auto rhs_value = right_string->get_data_at(row);
859
0
            if (!decode_shape(rhs_value, rhs_shape)) {
860
0
                null_map[row] = 1;
861
0
                res->insert_default();
862
0
                continue;
863
0
            }
864
0
            double distance = lhs_shape->Distance(rhs_shape.get());
865
0
            if (UNLIKELY(distance < 0)) {
866
0
                null_map[row] = 1;
867
0
                res->insert_default();
868
0
                continue;
869
0
            }
870
0
            res->insert_value(distance);
871
0
        }
872
0
    }
873
874
    static void vector_const(const ColumnPtr& left_column, const ColumnPtr& right_column,
875
0
                             ColumnFloat64::MutablePtr& res, NullMap& null_map, const size_t size) {
876
0
        const auto* left_string = assert_cast<const ColumnString*>(left_column.get());
877
0
        const auto* right_string = assert_cast<const ColumnString*>(right_column.get());
878
879
0
        auto rhs_value = right_string->get_data_at(0);
880
0
        std::unique_ptr<GeoShape> rhs_shape;
881
0
        if (!decode_shape(rhs_value, rhs_shape)) {
882
0
            for (int row = 0; row < size; ++row) {
883
0
                null_map[row] = 1;
884
0
                res->insert_default();
885
0
            }
886
0
            return;
887
0
        }
888
889
0
        std::unique_ptr<GeoShape> lhs_shape;
890
0
        for (int row = 0; row < size; ++row) {
891
0
            auto lhs_value = left_string->get_data_at(row);
892
0
            if (!decode_shape(lhs_value, lhs_shape)) {
893
0
                null_map[row] = 1;
894
0
                res->insert_default();
895
0
                continue;
896
0
            }
897
0
            double distance = lhs_shape->Distance(rhs_shape.get());
898
0
            if (UNLIKELY(distance < 0)) {
899
0
                null_map[row] = 1;
900
0
                res->insert_default();
901
0
                continue;
902
0
            }
903
0
            res->insert_value(distance);
904
0
        }
905
0
    }
906
907
    static void vector_vector(const ColumnPtr& left_column, const ColumnPtr& right_column,
908
                              ColumnFloat64::MutablePtr& res, NullMap& null_map,
909
47
                              const size_t size) {
910
47
        const auto* left_string = assert_cast<const ColumnString*>(left_column.get());
911
47
        const auto* right_string = assert_cast<const ColumnString*>(right_column.get());
912
913
47
        std::vector<std::unique_ptr<GeoShape>> shapes(2);
914
97
        for (int row = 0; row < size; ++row) {
915
50
            auto lhs_value = left_string->get_data_at(row);
916
50
            auto rhs_value = right_string->get_data_at(row);
917
50
            loop_do(lhs_value, rhs_value, shapes, res, null_map, row);
918
50
        }
919
47
    }
920
};
921
922
struct StNumGeometries {
923
    static constexpr auto NAME = "st_numgeometries";
924
    static const size_t NUM_ARGS = 1;
925
    using Type = DataTypeInt64;
926
927
22
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
928
22
        DCHECK_EQ(arguments.size(), 1);
929
930
22
        auto col = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
931
22
        const auto size = col.size();
932
933
22
        auto res = ColumnInt64::create();
934
22
        res->reserve(size);
935
936
22
        auto null_map = ColumnUInt8::create(size, 0);
937
22
        auto& null_map_data = null_map->get_data();
938
939
50
        for (int row = 0; row < size; ++row) {
940
28
            auto value = col.value_at(row);
941
28
            auto shape = GeoShape::from_encoded(value.data, value.size);
942
28
            if (!shape) {
943
4
                null_map_data[row] = 1;
944
4
                res->insert_default();
945
4
                continue;
946
4
            }
947
948
24
            res->insert_value(shape->num_geometries());
949
24
        }
950
951
22
        block.replace_by_position(result,
952
22
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
953
22
        return Status::OK();
954
22
    }
955
};
956
957
class FunctionStGeometries final : public IFunction {
958
public:
959
    static constexpr auto name = "st_geometries";
960
961
49
    static FunctionPtr create() { return std::make_shared<FunctionStGeometries>(); }
962
963
1
    String get_name() const override { return name; }
964
965
40
    size_t get_number_of_arguments() const override { return 1; }
966
967
41
    bool is_variadic() const override { return false; }
968
969
40
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
970
40
        return make_nullable(
971
40
                std::make_shared<DataTypeArray>(make_nullable(std::make_shared<DataTypeString>())));
972
40
    }
973
974
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
975
45
                        uint32_t result, size_t input_rows_count) const override {
976
45
        DCHECK_EQ(arguments.size(), 1);
977
978
45
        auto col = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
979
45
        const auto size = col.size();
980
981
45
        auto nested_data = ColumnString::create();
982
45
        auto offsets_col = ColumnArray::ColumnOffsets::create();
983
45
        auto& offsets = offsets_col->get_data();
984
45
        offsets.reserve(size);
985
986
45
        auto null_map = ColumnUInt8::create(size, 0);
987
45
        auto& null_map_data = null_map->get_data();
988
989
45
        size_t current_offset = 0;
990
45
        std::string buf;
991
992
105
        for (size_t row = 0; row < size; ++row) {
993
60
            auto shape_value = col.value_at(row);
994
60
            auto shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
995
996
60
            if (!shape) {
997
5
                null_map_data[row] = 1;
998
5
                offsets.push_back(current_offset);
999
5
                continue;
1000
5
            }
1001
1002
55
            if (shape->type() == GEO_SHAPE_MULTI_POLYGON) {
1003
24
                auto* multi_polygon = static_cast<GeoMultiPolygon*>(shape.get());
1004
24
                const auto& polygons = multi_polygon->polygons();
1005
1006
24
                if (polygons.empty()) {
1007
0
                    null_map_data[row] = 1;
1008
0
                    offsets.push_back(current_offset);
1009
0
                    continue;
1010
0
                }
1011
1012
46
                for (const auto& polygon : polygons) {
1013
46
                    DCHECK(polygon != nullptr);
1014
46
                    buf.clear();
1015
46
                    polygon->encode_to(&buf);
1016
46
                    nested_data->insert_data(buf.data(), buf.size());
1017
46
                    ++current_offset;
1018
46
                }
1019
31
            } else {
1020
31
                nested_data->insert_data(shape_value.data, shape_value.size);
1021
31
                ++current_offset;
1022
31
            }
1023
1024
55
            offsets.push_back(current_offset);
1025
55
        }
1026
1027
45
        auto nested_null_map = ColumnUInt8::create(nested_data->size(), 0);
1028
45
        auto nested_nullable =
1029
45
                ColumnNullable::create(std::move(nested_data), std::move(nested_null_map));
1030
45
        auto array_col = ColumnArray::create(std::move(nested_nullable), std::move(offsets_col));
1031
1032
45
        block.replace_by_position(
1033
45
                result, ColumnNullable::create(std::move(array_col), std::move(null_map)));
1034
1035
45
        return Status::OK();
1036
45
    }
1037
};
1038
1039
struct StNumPoints {
1040
    static constexpr auto NAME = "st_numpoints";
1041
    static const size_t NUM_ARGS = 1;
1042
    using Type = DataTypeInt64;
1043
1044
26
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
1045
26
        DCHECK_EQ(arguments.size(), 1);
1046
1047
26
        auto col = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
1048
26
        const auto size = col.size();
1049
1050
26
        auto res = ColumnInt64::create();
1051
26
        res->reserve(size);
1052
1053
26
        auto null_map = ColumnUInt8::create(size, 0);
1054
26
        auto& null_map_data = null_map->get_data();
1055
1056
58
        for (int row = 0; row < size; ++row) {
1057
32
            auto value = col.value_at(row);
1058
32
            auto shape = GeoShape::from_encoded(value.data, value.size);
1059
32
            if (!shape) {
1060
4
                null_map_data[row] = 1;
1061
4
                res->insert_default();
1062
4
                continue;
1063
4
            }
1064
1065
28
            auto num_points = shape->num_points();
1066
28
            if (num_points < 0) {
1067
1
                null_map_data[row] = 1;
1068
1
                res->insert_default();
1069
1
                continue;
1070
1
            }
1071
1072
27
            res->insert_value(num_points);
1073
27
        }
1074
1075
26
        block.replace_by_position(result,
1076
26
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
1077
26
        return Status::OK();
1078
26
    }
1079
};
1080
1081
8
void register_function_geo(SimpleFunctionFactory& factory) {
1082
8
    factory.register_function<GeoFunction<StPoint>>();
1083
8
    factory.register_function<GeoFunction<StAsText<StAsWktName>>>();
1084
8
    factory.register_function<GeoFunction<StAsText<StAsTextName>>>();
1085
8
    factory.register_function<GeoFunction<StX>>();
1086
8
    factory.register_function<GeoFunction<StY>>();
1087
8
    factory.register_function<GeoFunction<StDistanceSphere>>();
1088
8
    factory.register_function<GeoFunction<StAngleSphere>>();
1089
8
    factory.register_function<GeoFunction<StAngle>>();
1090
8
    factory.register_function<GeoFunction<StAzimuth>>();
1091
8
    factory.register_function<GeoFunction<StRelationFunction<StContainsFunc>>>();
1092
8
    factory.register_function<GeoFunction<StRelationFunction<StIntersectsFunc>>>();
1093
8
    factory.register_function<GeoFunction<StRelationFunction<StDisjointFunc>>>();
1094
8
    factory.register_function<GeoFunction<StRelationFunction<StTouchesFunc>>>();
1095
8
    factory.register_function<GeoFunction<StCircle>>();
1096
8
    factory.register_function<GeoFunction<StGeoFromText<StGeometryFromText>>>();
1097
8
    factory.register_function<GeoFunction<StGeoFromText<StGeomFromText>>>();
1098
8
    factory.register_function<GeoFunction<StGeoFromText<StLineFromText>>>();
1099
8
    factory.register_function<GeoFunction<StGeoFromText<StLineStringFromText>>>();
1100
8
    factory.register_function<GeoFunction<StGeoFromText<StPolygon>>>();
1101
8
    factory.register_function<GeoFunction<StGeoFromText<StPolygonFromText>>>();
1102
8
    factory.register_function<GeoFunction<StGeoFromText<StPolyFromText>>>();
1103
8
    factory.register_function<GeoFunction<StAreaSquareMeters>>();
1104
8
    factory.register_function<GeoFunction<StAreaSquareKm>>();
1105
8
    factory.register_function<GeoFunction<StGeoFromWkb<StGeometryFromWKB>>>();
1106
8
    factory.register_function<GeoFunction<StGeoFromWkb<StGeomFromWKB>>>();
1107
8
    factory.register_function<GeoFunction<StAsBinary>>();
1108
8
    factory.register_function<GeoFunction<StLength>>();
1109
8
    factory.register_function<GeoFunction<StGeometryType>>();
1110
8
    factory.register_function<GeoFunction<StDistance>>();
1111
8
    factory.register_function<GeoFunction<StNumGeometries>>();
1112
8
    factory.register_function<GeoFunction<StNumPoints>>();
1113
8
    factory.register_alias("st_numpoints", "st_npoints");
1114
8
    factory.register_function<FunctionStGeometries>();
1115
8
}
1116
1117
} // namespace doris