Coverage Report

Created: 2026-04-01 06: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
187
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
49
187
        DCHECK_EQ(arguments.size(), 2);
50
187
        auto return_type = block.get_data_type(result);
51
52
187
        auto x_col = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[0]).column);
53
187
        auto y_col = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[1]).column);
54
55
187
        const auto size = x_col.size();
56
57
187
        auto res = ColumnString::create();
58
187
        auto null_map = ColumnUInt8::create(size, 0);
59
187
        auto& null_map_data = null_map->get_data();
60
187
        GeoPoint point;
61
187
        std::string buf;
62
524
        for (int row = 0; row < size; ++row) {
63
337
            auto cur_res = point.from_coord(x_col.value_at(row), y_col.value_at(row));
64
337
            if (cur_res != GEO_PARSE_OK) {
65
0
                null_map_data[row] = 1;
66
0
                res->insert_default();
67
0
                continue;
68
0
            }
69
337
            buf.clear();
70
337
            point.encode_to(&buf);
71
337
            res->insert_data(buf.data(), buf.size());
72
337
        }
73
74
187
        block.replace_by_position(result,
75
187
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
76
187
        return Status::OK();
77
187
    }
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
129
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
93
129
        DCHECK_EQ(arguments.size(), 1);
94
129
        auto return_type = block.get_data_type(result);
95
96
129
        auto& input = block.get_by_position(arguments[0]).column;
97
98
129
        auto size = input->size();
99
100
129
        auto res = ColumnString::create();
101
129
        auto null_map = ColumnUInt8::create(size, 0);
102
129
        auto& null_map_data = null_map->get_data();
103
104
129
        std::unique_ptr<GeoShape> shape;
105
464
        for (int row = 0; row < size; ++row) {
106
335
            auto shape_value = input->get_data_at(row);
107
335
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
108
335
            if (shape == nullptr) {
109
11
                null_map_data[row] = 1;
110
11
                res->insert_default();
111
11
                continue;
112
11
            }
113
324
            auto wkt = shape->as_wkt();
114
324
            res->insert_data(wkt.data(), wkt.size());
115
324
        }
116
129
        block.replace_by_position(result,
117
129
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
118
119
129
        return Status::OK();
120
129
    }
_ZN5doris8StAsTextINS_11StAsWktNameEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
92
10
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
93
10
        DCHECK_EQ(arguments.size(), 1);
94
10
        auto return_type = block.get_data_type(result);
95
96
10
        auto& input = block.get_by_position(arguments[0]).column;
97
98
10
        auto size = input->size();
99
100
10
        auto res = ColumnString::create();
101
10
        auto null_map = ColumnUInt8::create(size, 0);
102
10
        auto& null_map_data = null_map->get_data();
103
104
10
        std::unique_ptr<GeoShape> shape;
105
38
        for (int row = 0; row < size; ++row) {
106
28
            auto shape_value = input->get_data_at(row);
107
28
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
108
28
            if (shape == nullptr) {
109
1
                null_map_data[row] = 1;
110
1
                res->insert_default();
111
1
                continue;
112
1
            }
113
27
            auto wkt = shape->as_wkt();
114
27
            res->insert_data(wkt.data(), wkt.size());
115
27
        }
116
10
        block.replace_by_position(result,
117
10
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
118
119
10
        return Status::OK();
120
10
    }
_ZN5doris8StAsTextINS_12StAsTextNameEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
92
119
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
93
119
        DCHECK_EQ(arguments.size(), 1);
94
119
        auto return_type = block.get_data_type(result);
95
96
119
        auto& input = block.get_by_position(arguments[0]).column;
97
98
119
        auto size = input->size();
99
100
119
        auto res = ColumnString::create();
101
119
        auto null_map = ColumnUInt8::create(size, 0);
102
119
        auto& null_map_data = null_map->get_data();
103
104
119
        std::unique_ptr<GeoShape> shape;
105
426
        for (int row = 0; row < size; ++row) {
106
307
            auto shape_value = input->get_data_at(row);
107
307
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
108
307
            if (shape == nullptr) {
109
10
                null_map_data[row] = 1;
110
10
                res->insert_default();
111
10
                continue;
112
10
            }
113
297
            auto wkt = shape->as_wkt();
114
297
            res->insert_data(wkt.data(), wkt.size());
115
297
        }
116
119
        block.replace_by_position(result,
117
119
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
118
119
119
        return Status::OK();
120
119
    }
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
13
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
128
13
        DCHECK_EQ(arguments.size(), 1);
129
13
        auto return_type = block.get_data_type(result);
130
131
13
        auto& input = block.get_by_position(arguments[0]).column;
132
133
13
        auto size = input->size();
134
135
13
        auto res = ColumnFloat64::create();
136
13
        auto null_map = ColumnUInt8::create(size, 0);
137
13
        auto& null_map_data = null_map->get_data();
138
13
        res->reserve(size);
139
140
13
        GeoPoint point;
141
44
        for (int row = 0; row < size; ++row) {
142
31
            auto point_value = input->get_data_at(row);
143
31
            auto pt = point.decode_from(point_value.data, point_value.size);
144
145
31
            if (!pt) {
146
1
                null_map_data[row] = 1;
147
1
                res->insert_default();
148
1
                continue;
149
1
            }
150
30
            auto x_value = point.x();
151
30
            res->insert_value(x_value);
152
30
        }
153
13
        block.replace_by_position(result,
154
13
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
155
156
13
        return Status::OK();
157
13
    }
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
12
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
165
12
        DCHECK_EQ(arguments.size(), 1);
166
12
        auto return_type = block.get_data_type(result);
167
168
12
        auto& input = block.get_by_position(arguments[0]).column;
169
170
12
        auto size = input->size();
171
172
12
        auto res = ColumnFloat64::create();
173
12
        res->reserve(size);
174
12
        auto null_map = ColumnUInt8::create(size, 0);
175
12
        auto& null_map_data = null_map->get_data();
176
177
12
        GeoPoint point;
178
42
        for (int row = 0; row < size; ++row) {
179
30
            auto point_value = input->get_data_at(row);
180
30
            auto pt = point.decode_from(point_value.data, point_value.size);
181
182
30
            if (!pt) {
183
1
                null_map_data[row] = 1;
184
1
                res->insert_default();
185
1
                continue;
186
1
            }
187
29
            auto y_value = point.y();
188
29
            res->insert_value(y_value);
189
29
        }
190
12
        block.replace_by_position(result,
191
12
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
192
193
12
        return Status::OK();
194
12
    }
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
43
        for (int row = 0; row < size; ++row) {
216
32
            double distance = 0;
217
32
            if (!GeoPoint::ComputeDistance(x_lng.value_at(row), x_lat.value_at(row),
218
32
                                           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
32
            res->insert_value(distance);
224
32
        }
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
12
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
237
12
        DCHECK_EQ(arguments.size(), 4);
238
12
        auto return_type = block.get_data_type(result);
239
240
12
        auto x_lng = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[0]).column);
241
12
        auto x_lat = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[1]).column);
242
12
        auto y_lng = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[2]).column);
243
12
        auto y_lat = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[3]).column);
244
245
12
        const auto size = x_lng.size();
246
247
12
        auto res = ColumnFloat64::create();
248
12
        res->reserve(size);
249
12
        auto null_map = ColumnUInt8::create(size, 0);
250
12
        auto& null_map_data = null_map->get_data();
251
252
45
        for (int row = 0; row < size; ++row) {
253
33
            double angle = 0;
254
33
            if (!GeoPoint::ComputeAngleSphere(x_lng.value_at(row), x_lat.value_at(row),
255
33
                                              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
33
            res->insert_value(angle);
261
33
        }
262
263
12
        block.replace_by_position(result,
264
12
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
265
12
        return Status::OK();
266
12
    }
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
9
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
274
9
        DCHECK_EQ(arguments.size(), 3);
275
9
        auto return_type = block.get_data_type(result);
276
277
9
        auto p1 = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
278
9
        auto p2 = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
279
9
        auto p3 = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[2]).column);
280
9
        const auto size = p1.size();
281
9
        auto res = ColumnFloat64::create();
282
9
        res->reserve(size);
283
9
        auto null_map = ColumnUInt8::create(size, 0);
284
9
        auto& null_map_data = null_map->get_data();
285
286
9
        GeoPoint point1;
287
9
        GeoPoint point2;
288
9
        GeoPoint point3;
289
290
30
        for (int row = 0; row < size; ++row) {
291
21
            auto shape_value1 = p1.value_at(row);
292
21
            auto pt1 = point1.decode_from(shape_value1.data, shape_value1.size);
293
21
            if (!pt1) {
294
1
                null_map_data[row] = 1;
295
1
                res->insert_default();
296
1
                continue;
297
1
            }
298
299
20
            auto shape_value2 = p2.value_at(row);
300
20
            auto pt2 = point2.decode_from(shape_value2.data, shape_value2.size);
301
20
            if (!pt2) {
302
1
                null_map_data[row] = 1;
303
1
                res->insert_default();
304
1
                continue;
305
1
            }
306
19
            auto shape_value3 = p3.value_at(row);
307
19
            auto pt3 = point3.decode_from(shape_value3.data, shape_value3.size);
308
19
            if (!pt3) {
309
1
                null_map_data[row] = 1;
310
1
                res->insert_default();
311
1
                continue;
312
1
            }
313
314
18
            double angle = 0;
315
18
            if (!GeoPoint::ComputeAngle(&point1, &point2, &point3, &angle)) {
316
2
                null_map_data[row] = 1;
317
2
                res->insert_default();
318
2
                continue;
319
2
            }
320
16
            res->insert_value(angle);
321
16
        }
322
9
        block.replace_by_position(result,
323
9
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
324
9
        return Status::OK();
325
9
    }
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
11
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
333
11
        DCHECK_EQ(arguments.size(), 2);
334
11
        auto return_type = block.get_data_type(result);
335
336
11
        auto left_col = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
337
11
        auto right_col =
338
11
                ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
339
340
11
        const auto size = left_col.size();
341
11
        auto res = ColumnFloat64::create();
342
11
        res->reserve(size);
343
11
        auto null_map = ColumnUInt8::create(size, 0);
344
11
        auto& null_map_data = null_map->get_data();
345
11
        GeoPoint point1;
346
11
        GeoPoint point2;
347
33
        for (int row = 0; row < size; ++row) {
348
22
            auto shape_value1 = left_col.value_at(row);
349
22
            auto pt1 = point1.decode_from(shape_value1.data, shape_value1.size);
350
22
            auto shape_value2 = right_col.value_at(row);
351
22
            auto pt2 = point2.decode_from(shape_value2.data, shape_value2.size);
352
353
22
            if (!(pt1 && pt2)) {
354
2
                null_map_data[row] = 1;
355
2
                res->insert_default();
356
2
                continue;
357
2
            }
358
359
20
            double angle = 0;
360
20
            if (!GeoPoint::ComputeAzimuth(&point1, &point2, &angle)) {
361
2
                null_map_data[row] = 1;
362
2
                res->insert_default();
363
2
                continue;
364
2
            }
365
18
            res->insert_value(angle);
366
18
        }
367
11
        block.replace_by_position(result,
368
11
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
369
11
        return Status::OK();
370
11
    }
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
19
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
378
19
        DCHECK_EQ(arguments.size(), 1);
379
19
        auto return_type = block.get_data_type(result);
380
381
19
        auto col = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
382
19
        const auto size = col->size();
383
19
        auto res = ColumnFloat64::create();
384
19
        res->reserve(size);
385
19
        auto null_map = ColumnUInt8::create(size, 0);
386
19
        auto& null_map_data = null_map->get_data();
387
19
        std::unique_ptr<GeoShape> shape;
388
389
73
        for (int row = 0; row < size; ++row) {
390
54
            auto shape_value = col->get_data_at(row);
391
54
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
392
54
            if (!shape) {
393
2
                null_map_data[row] = 1;
394
2
                res->insert_default();
395
2
                continue;
396
2
            }
397
398
52
            double area = 0;
399
52
            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
52
            res->insert_value(area);
405
52
        }
406
407
19
        block.replace_by_position(result,
408
19
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
409
19
        return Status::OK();
410
19
    }
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
19
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
418
19
        DCHECK_EQ(arguments.size(), 1);
419
19
        auto return_type = block.get_data_type(result);
420
421
19
        auto col = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
422
19
        const auto size = col->size();
423
19
        auto res = ColumnFloat64::create();
424
19
        res->reserve(size);
425
19
        auto null_map = ColumnUInt8::create(size, 0);
426
19
        auto& null_map_data = null_map->get_data();
427
428
19
        std::unique_ptr<GeoShape> shape;
429
430
73
        for (int row = 0; row < size; ++row) {
431
54
            auto shape_value = col->get_data_at(row);
432
54
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
433
54
            if (!shape) {
434
2
                null_map_data[row] = 1;
435
2
                res->insert_default();
436
2
                continue;
437
2
            }
438
439
52
            double area = 0;
440
52
            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
52
            res->insert_value(area);
447
52
        }
448
449
19
        block.replace_by_position(result,
450
19
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
451
19
        return Status::OK();
452
19
    }
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
117
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
460
117
        DCHECK_EQ(arguments.size(), 3);
461
117
        auto return_type = block.get_data_type(result);
462
117
        auto center_lng =
463
117
                ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[0]).column);
464
117
        auto center_lat =
465
117
                ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[1]).column);
466
117
        auto radius = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[2]).column);
467
468
117
        const auto size = center_lng.size();
469
470
117
        auto res = ColumnString::create();
471
472
117
        auto null_map = ColumnUInt8::create(size, 0);
473
117
        auto& null_map_data = null_map->get_data();
474
475
117
        GeoCircle circle;
476
117
        std::string buf;
477
288
        for (int row = 0; row < size; ++row) {
478
171
            auto lng_value = center_lng.value_at(row);
479
171
            auto lat_value = center_lat.value_at(row);
480
171
            auto radius_value = radius.value_at(row);
481
482
171
            auto value = circle.init(lng_value, lat_value, radius_value);
483
171
            if (value != GEO_PARSE_OK) {
484
0
                null_map_data[row] = 1;
485
0
                res->insert_default();
486
0
                continue;
487
0
            }
488
171
            buf.clear();
489
171
            circle.encode_to(&buf);
490
171
            res->insert_data(buf.data(), buf.size());
491
171
        }
492
117
        block.replace_by_position(result,
493
117
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
494
117
        return Status::OK();
495
117
    }
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
255
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
505
255
        DCHECK_EQ(arguments.size(), 2);
506
255
        auto return_type = block.get_data_type(result);
507
255
        auto left_col = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
508
255
        auto right_col =
509
255
                ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
510
511
255
        const auto size = left_col.size();
512
513
255
        auto res = ColumnUInt8::create(size, 0);
514
255
        auto null_map = ColumnUInt8::create(size, 0);
515
255
        auto& null_map_data = null_map->get_data();
516
517
530
        for (int row = 0; row < size; ++row) {
518
275
            auto lhs_value = left_col.value_at(row);
519
275
            auto rhs_value = right_col.value_at(row);
520
521
275
            std::unique_ptr<GeoShape> shape1(
522
275
                    GeoShape::from_encoded(lhs_value.data, lhs_value.size));
523
275
            std::unique_ptr<GeoShape> shape2(
524
275
                    GeoShape::from_encoded(rhs_value.data, rhs_value.size));
525
526
275
            if (!shape1 || !shape2) {
527
3
                null_map_data[row] = 1;
528
3
                continue;
529
3
            }
530
272
            auto relation_value = Func::evaluate(shape1.get(), shape2.get());
531
272
            res->get_data()[row] = relation_value;
532
272
        }
533
255
        block.replace_by_position(result,
534
255
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
535
255
        return Status::OK();
536
255
    }
_ZN5doris18StRelationFunctionINS_14StContainsFuncEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
504
69
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
505
69
        DCHECK_EQ(arguments.size(), 2);
506
69
        auto return_type = block.get_data_type(result);
507
69
        auto left_col = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
508
69
        auto right_col =
509
69
                ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
510
511
69
        const auto size = left_col.size();
512
513
69
        auto res = ColumnUInt8::create(size, 0);
514
69
        auto null_map = ColumnUInt8::create(size, 0);
515
69
        auto& null_map_data = null_map->get_data();
516
517
158
        for (int row = 0; row < size; ++row) {
518
89
            auto lhs_value = left_col.value_at(row);
519
89
            auto rhs_value = right_col.value_at(row);
520
521
89
            std::unique_ptr<GeoShape> shape1(
522
89
                    GeoShape::from_encoded(lhs_value.data, lhs_value.size));
523
89
            std::unique_ptr<GeoShape> shape2(
524
89
                    GeoShape::from_encoded(rhs_value.data, rhs_value.size));
525
526
89
            if (!shape1 || !shape2) {
527
3
                null_map_data[row] = 1;
528
3
                continue;
529
3
            }
530
86
            auto relation_value = Func::evaluate(shape1.get(), shape2.get());
531
86
            res->get_data()[row] = relation_value;
532
86
        }
533
69
        block.replace_by_position(result,
534
69
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
535
69
        return Status::OK();
536
69
    }
_ZN5doris18StRelationFunctionINS_16StIntersectsFuncEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
504
62
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
505
62
        DCHECK_EQ(arguments.size(), 2);
506
62
        auto return_type = block.get_data_type(result);
507
62
        auto left_col = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
508
62
        auto right_col =
509
62
                ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
510
511
62
        const auto size = left_col.size();
512
513
62
        auto res = ColumnUInt8::create(size, 0);
514
62
        auto null_map = ColumnUInt8::create(size, 0);
515
62
        auto& null_map_data = null_map->get_data();
516
517
124
        for (int row = 0; row < size; ++row) {
518
62
            auto lhs_value = left_col.value_at(row);
519
62
            auto rhs_value = right_col.value_at(row);
520
521
62
            std::unique_ptr<GeoShape> shape1(
522
62
                    GeoShape::from_encoded(lhs_value.data, lhs_value.size));
523
62
            std::unique_ptr<GeoShape> shape2(
524
62
                    GeoShape::from_encoded(rhs_value.data, rhs_value.size));
525
526
62
            if (!shape1 || !shape2) {
527
0
                null_map_data[row] = 1;
528
0
                continue;
529
0
            }
530
62
            auto relation_value = Func::evaluate(shape1.get(), shape2.get());
531
62
            res->get_data()[row] = relation_value;
532
62
        }
533
62
        block.replace_by_position(result,
534
62
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
535
62
        return Status::OK();
536
62
    }
_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
69
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
505
69
        DCHECK_EQ(arguments.size(), 2);
506
69
        auto return_type = block.get_data_type(result);
507
69
        auto left_col = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
508
69
        auto right_col =
509
69
                ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
510
511
69
        const auto size = left_col.size();
512
513
69
        auto res = ColumnUInt8::create(size, 0);
514
69
        auto null_map = ColumnUInt8::create(size, 0);
515
69
        auto& null_map_data = null_map->get_data();
516
517
138
        for (int row = 0; row < size; ++row) {
518
69
            auto lhs_value = left_col.value_at(row);
519
69
            auto rhs_value = right_col.value_at(row);
520
521
69
            std::unique_ptr<GeoShape> shape1(
522
69
                    GeoShape::from_encoded(lhs_value.data, lhs_value.size));
523
69
            std::unique_ptr<GeoShape> shape2(
524
69
                    GeoShape::from_encoded(rhs_value.data, rhs_value.size));
525
526
69
            if (!shape1 || !shape2) {
527
0
                null_map_data[row] = 1;
528
0
                continue;
529
0
            }
530
69
            auto relation_value = Func::evaluate(shape1.get(), shape2.get());
531
69
            res->get_data()[row] = relation_value;
532
69
        }
533
69
        block.replace_by_position(result,
534
69
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
535
69
        return Status::OK();
536
69
    }
537
};
538
539
struct StContainsFunc {
540
    static constexpr auto NAME = "st_contains";
541
86
    static bool evaluate(GeoShape* shape1, GeoShape* shape2) { return shape1->contains(shape2); }
542
};
543
544
struct StIntersectsFunc {
545
    static constexpr auto NAME = "st_intersects";
546
62
    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
69
    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
559
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
600
559
        DCHECK_EQ(arguments.size(), 1);
601
559
        auto return_type = block.get_data_type(result);
602
559
        auto& geo = block.get_by_position(arguments[0]).column;
603
604
559
        const auto size = geo->size();
605
559
        auto res = ColumnString::create();
606
559
        auto null_map = ColumnUInt8::create(size, 0);
607
559
        auto& null_map_data = null_map->get_data();
608
559
        GeoParseStatus status;
609
559
        std::string buf;
610
1.34k
        for (int row = 0; row < size; ++row) {
611
784
            auto value = geo->get_data_at(row);
612
784
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
613
784
            if (shape == nullptr || status != GEO_PARSE_OK ||
614
784
                (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
760
            buf.clear();
620
760
            shape->encode_to(&buf);
621
760
            res->insert_data(buf.data(), buf.size());
622
760
        }
623
559
        block.replace_by_position(result,
624
559
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
625
559
        return Status::OK();
626
559
    }
_ZN5doris13StGeoFromTextINS_18StGeometryFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
599
167
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
600
167
        DCHECK_EQ(arguments.size(), 1);
601
167
        auto return_type = block.get_data_type(result);
602
167
        auto& geo = block.get_by_position(arguments[0]).column;
603
604
167
        const auto size = geo->size();
605
167
        auto res = ColumnString::create();
606
167
        auto null_map = ColumnUInt8::create(size, 0);
607
167
        auto& null_map_data = null_map->get_data();
608
167
        GeoParseStatus status;
609
167
        std::string buf;
610
352
        for (int row = 0; row < size; ++row) {
611
185
            auto value = geo->get_data_at(row);
612
185
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
613
185
            if (shape == nullptr || status != GEO_PARSE_OK ||
614
185
                (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
181
            buf.clear();
620
181
            shape->encode_to(&buf);
621
181
            res->insert_data(buf.data(), buf.size());
622
181
        }
623
167
        block.replace_by_position(result,
624
167
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
625
167
        return Status::OK();
626
167
    }
_ZN5doris13StGeoFromTextINS_14StGeomFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
599
142
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
600
142
        DCHECK_EQ(arguments.size(), 1);
601
142
        auto return_type = block.get_data_type(result);
602
142
        auto& geo = block.get_by_position(arguments[0]).column;
603
604
142
        const auto size = geo->size();
605
142
        auto res = ColumnString::create();
606
142
        auto null_map = ColumnUInt8::create(size, 0);
607
142
        auto& null_map_data = null_map->get_data();
608
142
        GeoParseStatus status;
609
142
        std::string buf;
610
315
        for (int row = 0; row < size; ++row) {
611
173
            auto value = geo->get_data_at(row);
612
173
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
613
173
            if (shape == nullptr || status != GEO_PARSE_OK ||
614
173
                (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
166
            buf.clear();
620
166
            shape->encode_to(&buf);
621
166
            res->insert_data(buf.data(), buf.size());
622
166
        }
623
142
        block.replace_by_position(result,
624
142
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
625
142
        return Status::OK();
626
142
    }
_ZN5doris13StGeoFromTextINS_14StLineFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
599
92
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
600
92
        DCHECK_EQ(arguments.size(), 1);
601
92
        auto return_type = block.get_data_type(result);
602
92
        auto& geo = block.get_by_position(arguments[0]).column;
603
604
92
        const auto size = geo->size();
605
92
        auto res = ColumnString::create();
606
92
        auto null_map = ColumnUInt8::create(size, 0);
607
92
        auto& null_map_data = null_map->get_data();
608
92
        GeoParseStatus status;
609
92
        std::string buf;
610
202
        for (int row = 0; row < size; ++row) {
611
110
            auto value = geo->get_data_at(row);
612
110
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
613
110
            if (shape == nullptr || status != GEO_PARSE_OK ||
614
110
                (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
108
            buf.clear();
620
108
            shape->encode_to(&buf);
621
108
            res->insert_data(buf.data(), buf.size());
622
108
        }
623
92
        block.replace_by_position(result,
624
92
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
625
92
        return Status::OK();
626
92
    }
_ZN5doris13StGeoFromTextINS_20StLineStringFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
599
8
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
600
8
        DCHECK_EQ(arguments.size(), 1);
601
8
        auto return_type = block.get_data_type(result);
602
8
        auto& geo = block.get_by_position(arguments[0]).column;
603
604
8
        const auto size = geo->size();
605
8
        auto res = ColumnString::create();
606
8
        auto null_map = ColumnUInt8::create(size, 0);
607
8
        auto& null_map_data = null_map->get_data();
608
8
        GeoParseStatus status;
609
8
        std::string buf;
610
34
        for (int row = 0; row < size; ++row) {
611
26
            auto value = geo->get_data_at(row);
612
26
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
613
26
            if (shape == nullptr || status != GEO_PARSE_OK ||
614
26
                (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
25
            buf.clear();
620
25
            shape->encode_to(&buf);
621
25
            res->insert_data(buf.data(), buf.size());
622
25
        }
623
8
        block.replace_by_position(result,
624
8
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
625
8
        return Status::OK();
626
8
    }
_ZN5doris13StGeoFromTextINS_9StPolygonEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
599
116
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
600
116
        DCHECK_EQ(arguments.size(), 1);
601
116
        auto return_type = block.get_data_type(result);
602
116
        auto& geo = block.get_by_position(arguments[0]).column;
603
604
116
        const auto size = geo->size();
605
116
        auto res = ColumnString::create();
606
116
        auto null_map = ColumnUInt8::create(size, 0);
607
116
        auto& null_map_data = null_map->get_data();
608
116
        GeoParseStatus status;
609
116
        std::string buf;
610
302
        for (int row = 0; row < size; ++row) {
611
186
            auto value = geo->get_data_at(row);
612
186
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
613
186
            if (shape == nullptr || status != GEO_PARSE_OK ||
614
186
                (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
181
            buf.clear();
620
181
            shape->encode_to(&buf);
621
181
            res->insert_data(buf.data(), buf.size());
622
181
        }
623
116
        block.replace_by_position(result,
624
116
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
625
116
        return Status::OK();
626
116
    }
_ZN5doris13StGeoFromTextINS_17StPolygonFromTextEE7executeERNS_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
38
        for (int row = 0; row < size; ++row) {
611
28
            auto value = geo->get_data_at(row);
612
28
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
613
28
            if (shape == nullptr || status != GEO_PARSE_OK ||
614
28
                (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
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_14StPolyFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
599
24
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
600
24
        DCHECK_EQ(arguments.size(), 1);
601
24
        auto return_type = block.get_data_type(result);
602
24
        auto& geo = block.get_by_position(arguments[0]).column;
603
604
24
        const auto size = geo->size();
605
24
        auto res = ColumnString::create();
606
24
        auto null_map = ColumnUInt8::create(size, 0);
607
24
        auto& null_map_data = null_map->get_data();
608
24
        GeoParseStatus status;
609
24
        std::string buf;
610
100
        for (int row = 0; row < size; ++row) {
611
76
            auto value = geo->get_data_at(row);
612
76
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
613
76
            if (shape == nullptr || status != GEO_PARSE_OK ||
614
76
                (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
73
            buf.clear();
620
73
            shape->encode_to(&buf);
621
73
            res->insert_data(buf.data(), buf.size());
622
73
        }
623
24
        block.replace_by_position(result,
624
24
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
625
24
        return Status::OK();
626
24
    }
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
25
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
645
25
        DCHECK_EQ(arguments.size(), 1);
646
25
        auto return_type = block.get_data_type(result);
647
25
        auto& geo = block.get_by_position(arguments[0]).column;
648
649
25
        const auto size = geo->size();
650
25
        auto res = ColumnString::create();
651
25
        auto null_map = ColumnUInt8::create(size, 0);
652
25
        auto& null_map_data = null_map->get_data();
653
25
        GeoParseStatus status;
654
25
        std::string buf;
655
84
        for (int row = 0; row < size; ++row) {
656
59
            auto value = geo->get_data_at(row);
657
59
            std::unique_ptr<GeoShape> shape = GeoShape::from_wkb(value.data, value.size, status);
658
59
            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
57
            buf.clear();
664
57
            shape->encode_to(&buf);
665
57
            res->insert_data(buf.data(), buf.size());
666
57
        }
667
25
        block.replace_by_position(result,
668
25
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
669
25
        return Status::OK();
670
25
    }
_ZN5doris12StGeoFromWkbINS_17StGeometryFromWKBEE7executeERNS_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
    }
_ZN5doris12StGeoFromWkbINS_13StGeomFromWKBEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
644
11
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
645
11
        DCHECK_EQ(arguments.size(), 1);
646
11
        auto return_type = block.get_data_type(result);
647
11
        auto& geo = block.get_by_position(arguments[0]).column;
648
649
11
        const auto size = geo->size();
650
11
        auto res = ColumnString::create();
651
11
        auto null_map = ColumnUInt8::create(size, 0);
652
11
        auto& null_map_data = null_map->get_data();
653
11
        GeoParseStatus status;
654
11
        std::string buf;
655
39
        for (int row = 0; row < size; ++row) {
656
28
            auto value = geo->get_data_at(row);
657
28
            std::unique_ptr<GeoShape> shape = GeoShape::from_wkb(value.data, value.size, status);
658
28
            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
27
            buf.clear();
664
27
            shape->encode_to(&buf);
665
27
            res->insert_data(buf.data(), buf.size());
666
27
        }
667
11
        block.replace_by_position(result,
668
11
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
669
11
        return Status::OK();
670
11
    }
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
32
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
678
32
        DCHECK_EQ(arguments.size(), 1);
679
32
        auto return_type = block.get_data_type(result);
680
32
        auto res = ColumnString::create();
681
682
32
        auto col = block.get_by_position(arguments[0]).column;
683
32
        const auto size = col->size();
684
32
        auto null_map = ColumnUInt8::create(size, 0);
685
32
        auto& null_map_data = null_map->get_data();
686
32
        std::unique_ptr<GeoShape> shape;
687
688
115
        for (int row = 0; row < size; ++row) {
689
83
            auto shape_value = col->get_data_at(row);
690
83
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
691
83
            if (!shape) {
692
2
                null_map_data[row] = 1;
693
2
                res->insert_default();
694
2
                continue;
695
2
            }
696
697
81
            std::string binary = GeoShape::as_binary(shape.get());
698
81
            if (binary.empty()) {
699
0
                null_map_data[row] = 1;
700
0
                res->insert_default();
701
0
                continue;
702
0
            }
703
81
            res->insert_data(binary.data(), binary.size());
704
81
        }
705
706
32
        block.replace_by_position(result,
707
32
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
708
32
        return Status::OK();
709
32
    }
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