Coverage Report

Created: 2026-03-16 16:23

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