Coverage Report

Created: 2026-04-15 12:22

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
191
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
49
191
        DCHECK_EQ(arguments.size(), 2);
50
191
        auto return_type = block.get_data_type(result);
51
52
191
        auto x_col = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[0]).column);
53
191
        auto y_col = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[1]).column);
54
55
191
        const auto size = x_col.size();
56
57
191
        auto res = ColumnString::create();
58
191
        auto null_map = ColumnUInt8::create(size, 0);
59
191
        auto& null_map_data = null_map->get_data();
60
191
        GeoPoint point;
61
191
        std::string buf;
62
533
        for (int row = 0; row < size; ++row) {
63
342
            auto cur_res = point.from_coord(x_col.value_at(row), y_col.value_at(row));
64
342
            if (cur_res != GEO_PARSE_OK) {
65
0
                null_map_data[row] = 1;
66
0
                res->insert_default();
67
0
                continue;
68
0
            }
69
342
            buf.clear();
70
342
            point.encode_to(&buf);
71
342
            res->insert_data(buf.data(), buf.size());
72
342
        }
73
74
191
        block.replace_by_position(result,
75
191
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
76
191
        return Status::OK();
77
191
    }
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
131
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
93
131
        DCHECK_EQ(arguments.size(), 1);
94
131
        auto return_type = block.get_data_type(result);
95
96
131
        auto& input = block.get_by_position(arguments[0]).column;
97
98
131
        auto size = input->size();
99
100
131
        auto res = ColumnString::create();
101
131
        auto null_map = ColumnUInt8::create(size, 0);
102
131
        auto& null_map_data = null_map->get_data();
103
104
131
        std::unique_ptr<GeoShape> shape;
105
470
        for (int row = 0; row < size; ++row) {
106
339
            auto shape_value = input->get_data_at(row);
107
339
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
108
339
            if (shape == nullptr) {
109
13
                null_map_data[row] = 1;
110
13
                res->insert_default();
111
13
                continue;
112
13
            }
113
326
            auto wkt = shape->as_wkt();
114
326
            res->insert_data(wkt.data(), wkt.size());
115
326
        }
116
131
        block.replace_by_position(result,
117
131
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
118
119
131
        return Status::OK();
120
131
    }
_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
41
        for (int row = 0; row < size; ++row) {
106
30
            auto shape_value = input->get_data_at(row);
107
30
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
108
30
            if (shape == nullptr) {
109
2
                null_map_data[row] = 1;
110
2
                res->insert_default();
111
2
                continue;
112
2
            }
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
120
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
93
120
        DCHECK_EQ(arguments.size(), 1);
94
120
        auto return_type = block.get_data_type(result);
95
96
120
        auto& input = block.get_by_position(arguments[0]).column;
97
98
120
        auto size = input->size();
99
100
120
        auto res = ColumnString::create();
101
120
        auto null_map = ColumnUInt8::create(size, 0);
102
120
        auto& null_map_data = null_map->get_data();
103
104
120
        std::unique_ptr<GeoShape> shape;
105
429
        for (int row = 0; row < size; ++row) {
106
309
            auto shape_value = input->get_data_at(row);
107
309
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
108
309
            if (shape == nullptr) {
109
11
                null_map_data[row] = 1;
110
11
                res->insert_default();
111
11
                continue;
112
11
            }
113
298
            auto wkt = shape->as_wkt();
114
298
            res->insert_data(wkt.data(), wkt.size());
115
298
        }
116
120
        block.replace_by_position(result,
117
120
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
118
119
120
        return Status::OK();
120
120
    }
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
14
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
128
14
        DCHECK_EQ(arguments.size(), 1);
129
14
        auto return_type = block.get_data_type(result);
130
131
14
        auto& input = block.get_by_position(arguments[0]).column;
132
133
14
        auto size = input->size();
134
135
14
        auto res = ColumnFloat64::create();
136
14
        auto null_map = ColumnUInt8::create(size, 0);
137
14
        auto& null_map_data = null_map->get_data();
138
14
        res->reserve(size);
139
140
14
        GeoPoint point;
141
47
        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
2
                null_map_data[row] = 1;
147
2
                res->insert_default();
148
2
                continue;
149
2
            }
150
31
            auto x_value = point.x();
151
31
            res->insert_value(x_value);
152
31
        }
153
14
        block.replace_by_position(result,
154
14
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
155
156
14
        return Status::OK();
157
14
    }
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
13
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
165
13
        DCHECK_EQ(arguments.size(), 1);
166
13
        auto return_type = block.get_data_type(result);
167
168
13
        auto& input = block.get_by_position(arguments[0]).column;
169
170
13
        auto size = input->size();
171
172
13
        auto res = ColumnFloat64::create();
173
13
        res->reserve(size);
174
13
        auto null_map = ColumnUInt8::create(size, 0);
175
13
        auto& null_map_data = null_map->get_data();
176
177
13
        GeoPoint point;
178
45
        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
2
                null_map_data[row] = 1;
184
2
                res->insert_default();
185
2
                continue;
186
2
            }
187
30
            auto y_value = point.y();
188
30
            res->insert_value(y_value);
189
30
        }
190
13
        block.replace_by_position(result,
191
13
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
192
193
13
        return Status::OK();
194
13
    }
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
12
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
202
12
        DCHECK_EQ(arguments.size(), 4);
203
12
        auto return_type = block.get_data_type(result);
204
205
12
        auto x_lng = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[0]).column);
206
12
        auto x_lat = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[1]).column);
207
12
        auto y_lng = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[2]).column);
208
12
        auto y_lat = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[3]).column);
209
210
12
        const auto size = x_lng.size();
211
12
        auto res = ColumnFloat64::create();
212
12
        res->reserve(size);
213
12
        auto null_map = ColumnUInt8::create(size, 0);
214
12
        auto& null_map_data = null_map->get_data();
215
49
        for (int row = 0; row < size; ++row) {
216
37
            double distance = 0;
217
37
            if (!GeoPoint::ComputeDistance(x_lng.value_at(row), x_lat.value_at(row),
218
37
                                           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
37
            res->insert_value(distance);
224
37
        }
225
226
12
        block.replace_by_position(result,
227
12
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
228
12
        return Status::OK();
229
12
    }
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
51
        for (int row = 0; row < size; ++row) {
253
38
            double angle = 0;
254
38
            if (!GeoPoint::ComputeAngleSphere(x_lng.value_at(row), x_lat.value_at(row),
255
38
                                              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
38
            res->insert_value(angle);
261
38
        }
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
10
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
274
10
        DCHECK_EQ(arguments.size(), 3);
275
10
        auto return_type = block.get_data_type(result);
276
277
10
        auto p1 = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
278
10
        auto p2 = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
279
10
        auto p3 = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[2]).column);
280
10
        const auto size = p1.size();
281
10
        auto res = ColumnFloat64::create();
282
10
        res->reserve(size);
283
10
        auto null_map = ColumnUInt8::create(size, 0);
284
10
        auto& null_map_data = null_map->get_data();
285
286
10
        GeoPoint point1;
287
10
        GeoPoint point2;
288
10
        GeoPoint point3;
289
290
35
        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
2
                null_map_data[row] = 1;
295
2
                res->insert_default();
296
2
                continue;
297
2
            }
298
299
23
            auto shape_value2 = p2.value_at(row);
300
23
            auto pt2 = point2.decode_from(shape_value2.data, shape_value2.size);
301
23
            if (!pt2) {
302
2
                null_map_data[row] = 1;
303
2
                res->insert_default();
304
2
                continue;
305
2
            }
306
21
            auto shape_value3 = p3.value_at(row);
307
21
            auto pt3 = point3.decode_from(shape_value3.data, shape_value3.size);
308
21
            if (!pt3) {
309
2
                null_map_data[row] = 1;
310
2
                res->insert_default();
311
2
                continue;
312
2
            }
313
314
19
            double angle = 0;
315
19
            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
17
            res->insert_value(angle);
321
17
        }
322
10
        block.replace_by_position(result,
323
10
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
324
10
        return Status::OK();
325
10
    }
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
14
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
333
14
        DCHECK_EQ(arguments.size(), 2);
334
14
        auto return_type = block.get_data_type(result);
335
336
14
        auto left_col = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
337
14
        auto right_col =
338
14
                ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
339
340
14
        const auto size = left_col.size();
341
14
        auto res = ColumnFloat64::create();
342
14
        res->reserve(size);
343
14
        auto null_map = ColumnUInt8::create(size, 0);
344
14
        auto& null_map_data = null_map->get_data();
345
14
        GeoPoint point1;
346
14
        GeoPoint point2;
347
41
        for (int row = 0; row < size; ++row) {
348
27
            auto shape_value1 = left_col.value_at(row);
349
27
            auto pt1 = point1.decode_from(shape_value1.data, shape_value1.size);
350
27
            auto shape_value2 = right_col.value_at(row);
351
27
            auto pt2 = point2.decode_from(shape_value2.data, shape_value2.size);
352
353
27
            if (!(pt1 && pt2)) {
354
4
                null_map_data[row] = 1;
355
4
                res->insert_default();
356
4
                continue;
357
4
            }
358
359
23
            double angle = 0;
360
23
            if (!GeoPoint::ComputeAzimuth(&point1, &point2, &angle)) {
361
2
                null_map_data[row] = 1;
362
2
                res->insert_default();
363
2
                continue;
364
2
            }
365
21
            res->insert_value(angle);
366
21
        }
367
14
        block.replace_by_position(result,
368
14
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
369
14
        return Status::OK();
370
14
    }
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
20
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
378
20
        DCHECK_EQ(arguments.size(), 1);
379
20
        auto return_type = block.get_data_type(result);
380
381
20
        auto col = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
382
20
        const auto size = col->size();
383
20
        auto res = ColumnFloat64::create();
384
20
        res->reserve(size);
385
20
        auto null_map = ColumnUInt8::create(size, 0);
386
20
        auto& null_map_data = null_map->get_data();
387
20
        std::unique_ptr<GeoShape> shape;
388
389
76
        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
3
                null_map_data[row] = 1;
394
3
                res->insert_default();
395
3
                continue;
396
3
            }
397
398
53
            double area = 0;
399
53
            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
53
            res->insert_value(area);
405
53
        }
406
407
20
        block.replace_by_position(result,
408
20
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
409
20
        return Status::OK();
410
20
    }
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
20
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
418
20
        DCHECK_EQ(arguments.size(), 1);
419
20
        auto return_type = block.get_data_type(result);
420
421
20
        auto col = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
422
20
        const auto size = col->size();
423
20
        auto res = ColumnFloat64::create();
424
20
        res->reserve(size);
425
20
        auto null_map = ColumnUInt8::create(size, 0);
426
20
        auto& null_map_data = null_map->get_data();
427
428
20
        std::unique_ptr<GeoShape> shape;
429
430
76
        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
3
                null_map_data[row] = 1;
435
3
                res->insert_default();
436
3
                continue;
437
3
            }
438
439
53
            double area = 0;
440
53
            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
53
            res->insert_value(area);
447
53
        }
448
449
20
        block.replace_by_position(result,
450
20
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
451
20
        return Status::OK();
452
20
    }
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
118
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
460
118
        DCHECK_EQ(arguments.size(), 3);
461
118
        auto return_type = block.get_data_type(result);
462
118
        auto center_lng =
463
118
                ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[0]).column);
464
118
        auto center_lat =
465
118
                ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[1]).column);
466
118
        auto radius = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[2]).column);
467
468
118
        const auto size = center_lng.size();
469
470
118
        auto res = ColumnString::create();
471
472
118
        auto null_map = ColumnUInt8::create(size, 0);
473
118
        auto& null_map_data = null_map->get_data();
474
475
118
        GeoCircle circle;
476
118
        std::string buf;
477
293
        for (int row = 0; row < size; ++row) {
478
175
            auto lng_value = center_lng.value_at(row);
479
175
            auto lat_value = center_lat.value_at(row);
480
175
            auto radius_value = radius.value_at(row);
481
482
175
            auto value = circle.init(lng_value, lat_value, radius_value);
483
175
            if (value != GEO_PARSE_OK) {
484
0
                null_map_data[row] = 1;
485
0
                res->insert_default();
486
0
                continue;
487
0
            }
488
175
            buf.clear();
489
175
            circle.encode_to(&buf);
490
175
            res->insert_data(buf.data(), buf.size());
491
175
        }
492
118
        block.replace_by_position(result,
493
118
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
494
118
        return Status::OK();
495
118
    }
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
260
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
505
260
        DCHECK_EQ(arguments.size(), 2);
506
260
        auto return_type = block.get_data_type(result);
507
260
        auto left_col = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
508
260
        auto right_col =
509
260
                ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
510
511
260
        const auto size = left_col.size();
512
513
260
        auto res = ColumnUInt8::create(size, 0);
514
260
        auto null_map = ColumnUInt8::create(size, 0);
515
260
        auto& null_map_data = null_map->get_data();
516
517
543
        for (int row = 0; row < size; ++row) {
518
283
            auto lhs_value = left_col.value_at(row);
519
283
            auto rhs_value = right_col.value_at(row);
520
521
283
            std::unique_ptr<GeoShape> shape1(
522
283
                    GeoShape::from_encoded(lhs_value.data, lhs_value.size));
523
283
            std::unique_ptr<GeoShape> shape2(
524
283
                    GeoShape::from_encoded(rhs_value.data, rhs_value.size));
525
526
283
            if (!shape1 || !shape2) {
527
5
                null_map_data[row] = 1;
528
5
                continue;
529
5
            }
530
278
            auto relation_value = Func::evaluate(shape1.get(), shape2.get());
531
278
            res->get_data()[row] = relation_value;
532
278
        }
533
260
        block.replace_by_position(result,
534
260
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
535
260
        return Status::OK();
536
260
    }
_ZN5doris18StRelationFunctionINS_14StContainsFuncEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
504
74
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
505
74
        DCHECK_EQ(arguments.size(), 2);
506
74
        auto return_type = block.get_data_type(result);
507
74
        auto left_col = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
508
74
        auto right_col =
509
74
                ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
510
511
74
        const auto size = left_col.size();
512
513
74
        auto res = ColumnUInt8::create(size, 0);
514
74
        auto null_map = ColumnUInt8::create(size, 0);
515
74
        auto& null_map_data = null_map->get_data();
516
517
171
        for (int row = 0; row < size; ++row) {
518
97
            auto lhs_value = left_col.value_at(row);
519
97
            auto rhs_value = right_col.value_at(row);
520
521
97
            std::unique_ptr<GeoShape> shape1(
522
97
                    GeoShape::from_encoded(lhs_value.data, lhs_value.size));
523
97
            std::unique_ptr<GeoShape> shape2(
524
97
                    GeoShape::from_encoded(rhs_value.data, rhs_value.size));
525
526
97
            if (!shape1 || !shape2) {
527
5
                null_map_data[row] = 1;
528
5
                continue;
529
5
            }
530
92
            auto relation_value = Func::evaluate(shape1.get(), shape2.get());
531
92
            res->get_data()[row] = relation_value;
532
92
        }
533
74
        block.replace_by_position(result,
534
74
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
535
74
        return Status::OK();
536
74
    }
_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
92
    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
568
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
600
568
        DCHECK_EQ(arguments.size(), 1);
601
568
        auto return_type = block.get_data_type(result);
602
568
        auto& geo = block.get_by_position(arguments[0]).column;
603
604
568
        const auto size = geo->size();
605
568
        auto res = ColumnString::create();
606
568
        auto null_map = ColumnUInt8::create(size, 0);
607
568
        auto& null_map_data = null_map->get_data();
608
568
        GeoParseStatus status;
609
568
        std::string buf;
610
1.36k
        for (int row = 0; row < size; ++row) {
611
794
            auto value = geo->get_data_at(row);
612
794
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
613
794
            if (shape == nullptr || status != GEO_PARSE_OK ||
614
794
                (Impl::shape_type != GEO_SHAPE_ANY && shape->type() != Impl::shape_type)) {
615
29
                null_map_data[row] = 1;
616
29
                res->insert_default();
617
29
                continue;
618
29
            }
619
765
            buf.clear();
620
765
            shape->encode_to(&buf);
621
765
            res->insert_data(buf.data(), buf.size());
622
765
        }
623
568
        block.replace_by_position(result,
624
568
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
625
568
        return Status::OK();
626
568
    }
_ZN5doris13StGeoFromTextINS_18StGeometryFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
599
168
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
600
168
        DCHECK_EQ(arguments.size(), 1);
601
168
        auto return_type = block.get_data_type(result);
602
168
        auto& geo = block.get_by_position(arguments[0]).column;
603
604
168
        const auto size = geo->size();
605
168
        auto res = ColumnString::create();
606
168
        auto null_map = ColumnUInt8::create(size, 0);
607
168
        auto& null_map_data = null_map->get_data();
608
168
        GeoParseStatus status;
609
168
        std::string buf;
610
355
        for (int row = 0; row < size; ++row) {
611
187
            auto value = geo->get_data_at(row);
612
187
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
613
187
            if (shape == nullptr || status != GEO_PARSE_OK ||
614
187
                (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
182
            buf.clear();
620
182
            shape->encode_to(&buf);
621
182
            res->insert_data(buf.data(), buf.size());
622
182
        }
623
168
        block.replace_by_position(result,
624
168
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
625
168
        return Status::OK();
626
168
    }
_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
319
        for (int row = 0; row < size; ++row) {
611
175
            auto value = geo->get_data_at(row);
612
175
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
613
175
            if (shape == nullptr || status != GEO_PARSE_OK ||
614
175
                (Impl::shape_type != GEO_SHAPE_ANY && shape->type() != Impl::shape_type)) {
615
8
                null_map_data[row] = 1;
616
8
                res->insert_default();
617
8
                continue;
618
8
            }
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
93
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
600
93
        DCHECK_EQ(arguments.size(), 1);
601
93
        auto return_type = block.get_data_type(result);
602
93
        auto& geo = block.get_by_position(arguments[0]).column;
603
604
93
        const auto size = geo->size();
605
93
        auto res = ColumnString::create();
606
93
        auto null_map = ColumnUInt8::create(size, 0);
607
93
        auto& null_map_data = null_map->get_data();
608
93
        GeoParseStatus status;
609
93
        std::string buf;
610
205
        for (int row = 0; row < size; ++row) {
611
112
            auto value = geo->get_data_at(row);
612
112
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
613
112
            if (shape == nullptr || status != GEO_PARSE_OK ||
614
112
                (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
109
            buf.clear();
620
109
            shape->encode_to(&buf);
621
109
            res->insert_data(buf.data(), buf.size());
622
109
        }
623
93
        block.replace_by_position(result,
624
93
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
625
93
        return Status::OK();
626
93
    }
_ZN5doris13StGeoFromTextINS_20StLineStringFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
599
9
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
600
9
        DCHECK_EQ(arguments.size(), 1);
601
9
        auto return_type = block.get_data_type(result);
602
9
        auto& geo = block.get_by_position(arguments[0]).column;
603
604
9
        const auto size = geo->size();
605
9
        auto res = ColumnString::create();
606
9
        auto null_map = ColumnUInt8::create(size, 0);
607
9
        auto& null_map_data = null_map->get_data();
608
9
        GeoParseStatus status;
609
9
        std::string buf;
610
35
        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
9
        block.replace_by_position(result,
624
9
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
625
9
        return Status::OK();
626
9
    }
_ZN5doris13StGeoFromTextINS_9StPolygonEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
599
118
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
600
118
        DCHECK_EQ(arguments.size(), 1);
601
118
        auto return_type = block.get_data_type(result);
602
118
        auto& geo = block.get_by_position(arguments[0]).column;
603
604
118
        const auto size = geo->size();
605
118
        auto res = ColumnString::create();
606
118
        auto null_map = ColumnUInt8::create(size, 0);
607
118
        auto& null_map_data = null_map->get_data();
608
118
        GeoParseStatus status;
609
118
        std::string buf;
610
306
        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
6
                null_map_data[row] = 1;
616
6
                res->insert_default();
617
6
                continue;
618
6
            }
619
182
            buf.clear();
620
182
            shape->encode_to(&buf);
621
182
            res->insert_data(buf.data(), buf.size());
622
182
        }
623
118
        block.replace_by_position(result,
624
118
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
625
118
        return Status::OK();
626
118
    }
_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
41
        for (int row = 0; row < size; ++row) {
611
30
            auto value = geo->get_data_at(row);
612
30
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
613
30
            if (shape == nullptr || status != GEO_PARSE_OK ||
614
30
                (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
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
101
        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
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
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
9
void register_function_geo(SimpleFunctionFactory& factory) {
921
9
    factory.register_function<GeoFunction<StPoint>>();
922
9
    factory.register_function<GeoFunction<StAsText<StAsWktName>>>();
923
9
    factory.register_function<GeoFunction<StAsText<StAsTextName>>>();
924
9
    factory.register_function<GeoFunction<StX>>();
925
9
    factory.register_function<GeoFunction<StY>>();
926
9
    factory.register_function<GeoFunction<StDistanceSphere>>();
927
9
    factory.register_function<GeoFunction<StAngleSphere>>();
928
9
    factory.register_function<GeoFunction<StAngle>>();
929
9
    factory.register_function<GeoFunction<StAzimuth>>();
930
9
    factory.register_function<GeoFunction<StRelationFunction<StContainsFunc>>>();
931
9
    factory.register_function<GeoFunction<StRelationFunction<StIntersectsFunc>>>();
932
9
    factory.register_function<GeoFunction<StRelationFunction<StDisjointFunc>>>();
933
9
    factory.register_function<GeoFunction<StRelationFunction<StTouchesFunc>>>();
934
9
    factory.register_function<GeoFunction<StCircle>>();
935
9
    factory.register_function<GeoFunction<StGeoFromText<StGeometryFromText>>>();
936
9
    factory.register_function<GeoFunction<StGeoFromText<StGeomFromText>>>();
937
9
    factory.register_function<GeoFunction<StGeoFromText<StLineFromText>>>();
938
9
    factory.register_function<GeoFunction<StGeoFromText<StLineStringFromText>>>();
939
9
    factory.register_function<GeoFunction<StGeoFromText<StPolygon>>>();
940
9
    factory.register_function<GeoFunction<StGeoFromText<StPolygonFromText>>>();
941
9
    factory.register_function<GeoFunction<StGeoFromText<StPolyFromText>>>();
942
9
    factory.register_function<GeoFunction<StAreaSquareMeters>>();
943
9
    factory.register_function<GeoFunction<StAreaSquareKm>>();
944
9
    factory.register_function<GeoFunction<StGeoFromWkb<StGeometryFromWKB>>>();
945
9
    factory.register_function<GeoFunction<StGeoFromWkb<StGeomFromWKB>>>();
946
9
    factory.register_function<GeoFunction<StAsBinary>>();
947
9
    factory.register_function<GeoFunction<StLength>>();
948
9
    factory.register_function<GeoFunction<StGeometryType>>();
949
9
    factory.register_function<GeoFunction<StDistance>>();
950
9
}
951
952
} // namespace doris