Coverage Report

Created: 2026-03-23 17:10

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
68
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
49
68
        DCHECK_EQ(arguments.size(), 2);
50
68
        auto return_type = block.get_data_type(result);
51
52
68
        auto x_col = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[0]).column);
53
68
        auto y_col = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[1]).column);
54
55
68
        const auto size = x_col.size();
56
57
68
        auto res = ColumnString::create();
58
68
        auto null_map = ColumnUInt8::create(size, 0);
59
68
        auto& null_map_data = null_map->get_data();
60
68
        GeoPoint point;
61
68
        std::string buf;
62
138
        for (int row = 0; row < size; ++row) {
63
70
            auto cur_res = point.from_coord(x_col.value_at(row), y_col.value_at(row));
64
70
            if (cur_res != GEO_PARSE_OK) {
65
0
                null_map_data[row] = 1;
66
0
                res->insert_default();
67
0
                continue;
68
0
            }
69
70
            buf.clear();
70
70
            point.encode_to(&buf);
71
70
            res->insert_data(buf.data(), buf.size());
72
70
        }
73
74
68
        block.replace_by_position(result,
75
68
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
76
68
        return Status::OK();
77
68
    }
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
24
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
93
24
        DCHECK_EQ(arguments.size(), 1);
94
24
        auto return_type = block.get_data_type(result);
95
96
24
        auto& input = block.get_by_position(arguments[0]).column;
97
98
24
        auto size = input->size();
99
100
24
        auto res = ColumnString::create();
101
24
        auto null_map = ColumnUInt8::create(size, 0);
102
24
        auto& null_map_data = null_map->get_data();
103
104
24
        std::unique_ptr<GeoShape> shape;
105
50
        for (int row = 0; row < size; ++row) {
106
26
            auto shape_value = input->get_data_at(row);
107
26
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
108
26
            if (shape == nullptr) {
109
2
                null_map_data[row] = 1;
110
2
                res->insert_default();
111
2
                continue;
112
2
            }
113
24
            auto wkt = shape->as_wkt();
114
24
            res->insert_data(wkt.data(), wkt.size());
115
24
        }
116
24
        block.replace_by_position(result,
117
24
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
118
119
24
        return Status::OK();
120
24
    }
_ZN5doris8StAsTextINS_11StAsWktNameEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
92
2
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
93
2
        DCHECK_EQ(arguments.size(), 1);
94
2
        auto return_type = block.get_data_type(result);
95
96
2
        auto& input = block.get_by_position(arguments[0]).column;
97
98
2
        auto size = input->size();
99
100
2
        auto res = ColumnString::create();
101
2
        auto null_map = ColumnUInt8::create(size, 0);
102
2
        auto& null_map_data = null_map->get_data();
103
104
2
        std::unique_ptr<GeoShape> shape;
105
5
        for (int row = 0; row < size; ++row) {
106
3
            auto shape_value = input->get_data_at(row);
107
3
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
108
3
            if (shape == nullptr) {
109
1
                null_map_data[row] = 1;
110
1
                res->insert_default();
111
1
                continue;
112
1
            }
113
2
            auto wkt = shape->as_wkt();
114
2
            res->insert_data(wkt.data(), wkt.size());
115
2
        }
116
2
        block.replace_by_position(result,
117
2
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
118
119
2
        return Status::OK();
120
2
    }
_ZN5doris8StAsTextINS_12StAsTextNameEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
92
22
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
93
22
        DCHECK_EQ(arguments.size(), 1);
94
22
        auto return_type = block.get_data_type(result);
95
96
22
        auto& input = block.get_by_position(arguments[0]).column;
97
98
22
        auto size = input->size();
99
100
22
        auto res = ColumnString::create();
101
22
        auto null_map = ColumnUInt8::create(size, 0);
102
22
        auto& null_map_data = null_map->get_data();
103
104
22
        std::unique_ptr<GeoShape> shape;
105
45
        for (int row = 0; row < size; ++row) {
106
23
            auto shape_value = input->get_data_at(row);
107
23
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
108
23
            if (shape == nullptr) {
109
1
                null_map_data[row] = 1;
110
1
                res->insert_default();
111
1
                continue;
112
1
            }
113
22
            auto wkt = shape->as_wkt();
114
22
            res->insert_data(wkt.data(), wkt.size());
115
22
        }
116
22
        block.replace_by_position(result,
117
22
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
118
119
22
        return Status::OK();
120
22
    }
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
5
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
128
5
        DCHECK_EQ(arguments.size(), 1);
129
5
        auto return_type = block.get_data_type(result);
130
131
5
        auto& input = block.get_by_position(arguments[0]).column;
132
133
5
        auto size = input->size();
134
135
5
        auto res = ColumnFloat64::create();
136
5
        auto null_map = ColumnUInt8::create(size, 0);
137
5
        auto& null_map_data = null_map->get_data();
138
5
        res->reserve(size);
139
140
5
        GeoPoint point;
141
11
        for (int row = 0; row < size; ++row) {
142
6
            auto point_value = input->get_data_at(row);
143
6
            auto pt = point.decode_from(point_value.data, point_value.size);
144
145
6
            if (!pt) {
146
1
                null_map_data[row] = 1;
147
1
                res->insert_default();
148
1
                continue;
149
1
            }
150
5
            auto x_value = point.x();
151
5
            res->insert_value(x_value);
152
5
        }
153
5
        block.replace_by_position(result,
154
5
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
155
156
5
        return Status::OK();
157
5
    }
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
4
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
165
4
        DCHECK_EQ(arguments.size(), 1);
166
4
        auto return_type = block.get_data_type(result);
167
168
4
        auto& input = block.get_by_position(arguments[0]).column;
169
170
4
        auto size = input->size();
171
172
4
        auto res = ColumnFloat64::create();
173
4
        res->reserve(size);
174
4
        auto null_map = ColumnUInt8::create(size, 0);
175
4
        auto& null_map_data = null_map->get_data();
176
177
4
        GeoPoint point;
178
9
        for (int row = 0; row < size; ++row) {
179
5
            auto point_value = input->get_data_at(row);
180
5
            auto pt = point.decode_from(point_value.data, point_value.size);
181
182
5
            if (!pt) {
183
1
                null_map_data[row] = 1;
184
1
                res->insert_default();
185
1
                continue;
186
1
            }
187
4
            auto y_value = point.y();
188
4
            res->insert_value(y_value);
189
4
        }
190
4
        block.replace_by_position(result,
191
4
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
192
193
4
        return Status::OK();
194
4
    }
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
2
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
202
2
        DCHECK_EQ(arguments.size(), 4);
203
2
        auto return_type = block.get_data_type(result);
204
205
2
        auto x_lng = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[0]).column);
206
2
        auto x_lat = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[1]).column);
207
2
        auto y_lng = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[2]).column);
208
2
        auto y_lat = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[3]).column);
209
210
2
        const auto size = x_lng.size();
211
2
        auto res = ColumnFloat64::create();
212
2
        res->reserve(size);
213
2
        auto null_map = ColumnUInt8::create(size, 0);
214
2
        auto& null_map_data = null_map->get_data();
215
8
        for (int row = 0; row < size; ++row) {
216
6
            double distance = 0;
217
6
            if (!GeoPoint::ComputeDistance(x_lng.value_at(row), x_lat.value_at(row),
218
6
                                           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
6
            res->insert_value(distance);
224
6
        }
225
226
2
        block.replace_by_position(result,
227
2
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
228
2
        return Status::OK();
229
2
    }
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
3
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
237
3
        DCHECK_EQ(arguments.size(), 4);
238
3
        auto return_type = block.get_data_type(result);
239
240
3
        auto x_lng = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[0]).column);
241
3
        auto x_lat = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[1]).column);
242
3
        auto y_lng = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[2]).column);
243
3
        auto y_lat = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[3]).column);
244
245
3
        const auto size = x_lng.size();
246
247
3
        auto res = ColumnFloat64::create();
248
3
        res->reserve(size);
249
3
        auto null_map = ColumnUInt8::create(size, 0);
250
3
        auto& null_map_data = null_map->get_data();
251
252
10
        for (int row = 0; row < size; ++row) {
253
7
            double angle = 0;
254
7
            if (!GeoPoint::ComputeAngleSphere(x_lng.value_at(row), x_lat.value_at(row),
255
7
                                              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
7
            res->insert_value(angle);
261
7
        }
262
263
3
        block.replace_by_position(result,
264
3
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
265
3
        return Status::OK();
266
3
    }
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
5
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
274
5
        DCHECK_EQ(arguments.size(), 3);
275
5
        auto return_type = block.get_data_type(result);
276
277
5
        auto p1 = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
278
5
        auto p2 = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
279
5
        auto p3 = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[2]).column);
280
5
        const auto size = p1.size();
281
5
        auto res = ColumnFloat64::create();
282
5
        res->reserve(size);
283
5
        auto null_map = ColumnUInt8::create(size, 0);
284
5
        auto& null_map_data = null_map->get_data();
285
286
5
        GeoPoint point1;
287
5
        GeoPoint point2;
288
5
        GeoPoint point3;
289
290
13
        for (int row = 0; row < size; ++row) {
291
8
            auto shape_value1 = p1.value_at(row);
292
8
            auto pt1 = point1.decode_from(shape_value1.data, shape_value1.size);
293
8
            if (!pt1) {
294
1
                null_map_data[row] = 1;
295
1
                res->insert_default();
296
1
                continue;
297
1
            }
298
299
7
            auto shape_value2 = p2.value_at(row);
300
7
            auto pt2 = point2.decode_from(shape_value2.data, shape_value2.size);
301
7
            if (!pt2) {
302
1
                null_map_data[row] = 1;
303
1
                res->insert_default();
304
1
                continue;
305
1
            }
306
6
            auto shape_value3 = p3.value_at(row);
307
6
            auto pt3 = point3.decode_from(shape_value3.data, shape_value3.size);
308
6
            if (!pt3) {
309
1
                null_map_data[row] = 1;
310
1
                res->insert_default();
311
1
                continue;
312
1
            }
313
314
5
            double angle = 0;
315
5
            if (!GeoPoint::ComputeAngle(&point1, &point2, &point3, &angle)) {
316
1
                null_map_data[row] = 1;
317
1
                res->insert_default();
318
1
                continue;
319
1
            }
320
4
            res->insert_value(angle);
321
4
        }
322
5
        block.replace_by_position(result,
323
5
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
324
5
        return Status::OK();
325
5
    }
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
7
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
333
7
        DCHECK_EQ(arguments.size(), 2);
334
7
        auto return_type = block.get_data_type(result);
335
336
7
        auto left_col = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
337
7
        auto right_col =
338
7
                ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
339
340
7
        const auto size = left_col.size();
341
7
        auto res = ColumnFloat64::create();
342
7
        res->reserve(size);
343
7
        auto null_map = ColumnUInt8::create(size, 0);
344
7
        auto& null_map_data = null_map->get_data();
345
7
        GeoPoint point1;
346
7
        GeoPoint point2;
347
16
        for (int row = 0; row < size; ++row) {
348
9
            auto shape_value1 = left_col.value_at(row);
349
9
            auto pt1 = point1.decode_from(shape_value1.data, shape_value1.size);
350
9
            auto shape_value2 = right_col.value_at(row);
351
9
            auto pt2 = point2.decode_from(shape_value2.data, shape_value2.size);
352
353
9
            if (!(pt1 && pt2)) {
354
2
                null_map_data[row] = 1;
355
2
                res->insert_default();
356
2
                continue;
357
2
            }
358
359
7
            double angle = 0;
360
7
            if (!GeoPoint::ComputeAzimuth(&point1, &point2, &angle)) {
361
1
                null_map_data[row] = 1;
362
1
                res->insert_default();
363
1
                continue;
364
1
            }
365
6
            res->insert_value(angle);
366
6
        }
367
7
        block.replace_by_position(result,
368
7
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
369
7
        return Status::OK();
370
7
    }
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
3
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
378
3
        DCHECK_EQ(arguments.size(), 1);
379
3
        auto return_type = block.get_data_type(result);
380
381
3
        auto col = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
382
3
        const auto size = col->size();
383
3
        auto res = ColumnFloat64::create();
384
3
        res->reserve(size);
385
3
        auto null_map = ColumnUInt8::create(size, 0);
386
3
        auto& null_map_data = null_map->get_data();
387
3
        std::unique_ptr<GeoShape> shape;
388
389
7
        for (int row = 0; row < size; ++row) {
390
4
            auto shape_value = col->get_data_at(row);
391
4
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
392
4
            if (!shape) {
393
1
                null_map_data[row] = 1;
394
1
                res->insert_default();
395
1
                continue;
396
1
            }
397
398
3
            double area = 0;
399
3
            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
3
            res->insert_value(area);
405
3
        }
406
407
3
        block.replace_by_position(result,
408
3
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
409
3
        return Status::OK();
410
3
    }
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
3
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
418
3
        DCHECK_EQ(arguments.size(), 1);
419
3
        auto return_type = block.get_data_type(result);
420
421
3
        auto col = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
422
3
        const auto size = col->size();
423
3
        auto res = ColumnFloat64::create();
424
3
        res->reserve(size);
425
3
        auto null_map = ColumnUInt8::create(size, 0);
426
3
        auto& null_map_data = null_map->get_data();
427
428
3
        std::unique_ptr<GeoShape> shape;
429
430
7
        for (int row = 0; row < size; ++row) {
431
4
            auto shape_value = col->get_data_at(row);
432
4
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
433
4
            if (!shape) {
434
1
                null_map_data[row] = 1;
435
1
                res->insert_default();
436
1
                continue;
437
1
            }
438
439
3
            double area = 0;
440
3
            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
3
            res->insert_value(area);
447
3
        }
448
449
3
        block.replace_by_position(result,
450
3
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
451
3
        return Status::OK();
452
3
    }
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
37
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
460
37
        DCHECK_EQ(arguments.size(), 3);
461
37
        auto return_type = block.get_data_type(result);
462
37
        auto center_lng =
463
37
                ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[0]).column);
464
37
        auto center_lat =
465
37
                ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[1]).column);
466
37
        auto radius = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[2]).column);
467
468
37
        const auto size = center_lng.size();
469
470
37
        auto res = ColumnString::create();
471
472
37
        auto null_map = ColumnUInt8::create(size, 0);
473
37
        auto& null_map_data = null_map->get_data();
474
475
37
        GeoCircle circle;
476
37
        std::string buf;
477
77
        for (int row = 0; row < size; ++row) {
478
40
            auto lng_value = center_lng.value_at(row);
479
40
            auto lat_value = center_lat.value_at(row);
480
40
            auto radius_value = radius.value_at(row);
481
482
40
            auto value = circle.init(lng_value, lat_value, radius_value);
483
40
            if (value != GEO_PARSE_OK) {
484
0
                null_map_data[row] = 1;
485
0
                res->insert_default();
486
0
                continue;
487
0
            }
488
40
            buf.clear();
489
40
            circle.encode_to(&buf);
490
40
            res->insert_data(buf.data(), buf.size());
491
40
        }
492
37
        block.replace_by_position(result,
493
37
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
494
37
        return Status::OK();
495
37
    }
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
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
141
        for (int row = 0; row < size; ++row) {
518
72
            auto lhs_value = left_col.value_at(row);
519
72
            auto rhs_value = right_col.value_at(row);
520
521
72
            std::unique_ptr<GeoShape> shape1(
522
72
                    GeoShape::from_encoded(lhs_value.data, lhs_value.size));
523
72
            std::unique_ptr<GeoShape> shape2(
524
72
                    GeoShape::from_encoded(rhs_value.data, rhs_value.size));
525
526
72
            if (!shape1 || !shape2) {
527
2
                null_map_data[row] = 1;
528
2
                continue;
529
2
            }
530
70
            auto relation_value = Func::evaluate(shape1.get(), shape2.get());
531
70
            res->get_data()[row] = relation_value;
532
70
        }
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_14StContainsFuncEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
504
7
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
505
7
        DCHECK_EQ(arguments.size(), 2);
506
7
        auto return_type = block.get_data_type(result);
507
7
        auto left_col = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
508
7
        auto right_col =
509
7
                ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
510
511
7
        const auto size = left_col.size();
512
513
7
        auto res = ColumnUInt8::create(size, 0);
514
7
        auto null_map = ColumnUInt8::create(size, 0);
515
7
        auto& null_map_data = null_map->get_data();
516
517
17
        for (int row = 0; row < size; ++row) {
518
10
            auto lhs_value = left_col.value_at(row);
519
10
            auto rhs_value = right_col.value_at(row);
520
521
10
            std::unique_ptr<GeoShape> shape1(
522
10
                    GeoShape::from_encoded(lhs_value.data, lhs_value.size));
523
10
            std::unique_ptr<GeoShape> shape2(
524
10
                    GeoShape::from_encoded(rhs_value.data, rhs_value.size));
525
526
10
            if (!shape1 || !shape2) {
527
2
                null_map_data[row] = 1;
528
2
                continue;
529
2
            }
530
8
            auto relation_value = Func::evaluate(shape1.get(), shape2.get());
531
8
            res->get_data()[row] = relation_value;
532
8
        }
533
7
        block.replace_by_position(result,
534
7
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
535
7
        return Status::OK();
536
7
    }
_ZN5doris18StRelationFunctionINS_16StIntersectsFuncEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
504
31
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
505
31
        DCHECK_EQ(arguments.size(), 2);
506
31
        auto return_type = block.get_data_type(result);
507
31
        auto left_col = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
508
31
        auto right_col =
509
31
                ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
510
511
31
        const auto size = left_col.size();
512
513
31
        auto res = ColumnUInt8::create(size, 0);
514
31
        auto null_map = ColumnUInt8::create(size, 0);
515
31
        auto& null_map_data = null_map->get_data();
516
517
62
        for (int row = 0; row < size; ++row) {
518
31
            auto lhs_value = left_col.value_at(row);
519
31
            auto rhs_value = right_col.value_at(row);
520
521
31
            std::unique_ptr<GeoShape> shape1(
522
31
                    GeoShape::from_encoded(lhs_value.data, lhs_value.size));
523
31
            std::unique_ptr<GeoShape> shape2(
524
31
                    GeoShape::from_encoded(rhs_value.data, rhs_value.size));
525
526
31
            if (!shape1 || !shape2) {
527
0
                null_map_data[row] = 1;
528
0
                continue;
529
0
            }
530
31
            auto relation_value = Func::evaluate(shape1.get(), shape2.get());
531
31
            res->get_data()[row] = relation_value;
532
31
        }
533
31
        block.replace_by_position(result,
534
31
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
535
31
        return Status::OK();
536
31
    }
Unexecuted instantiation: _ZN5doris18StRelationFunctionINS_14StDisjointFuncEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
_ZN5doris18StRelationFunctionINS_13StTouchesFuncEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
504
31
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
505
31
        DCHECK_EQ(arguments.size(), 2);
506
31
        auto return_type = block.get_data_type(result);
507
31
        auto left_col = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
508
31
        auto right_col =
509
31
                ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
510
511
31
        const auto size = left_col.size();
512
513
31
        auto res = ColumnUInt8::create(size, 0);
514
31
        auto null_map = ColumnUInt8::create(size, 0);
515
31
        auto& null_map_data = null_map->get_data();
516
517
62
        for (int row = 0; row < size; ++row) {
518
31
            auto lhs_value = left_col.value_at(row);
519
31
            auto rhs_value = right_col.value_at(row);
520
521
31
            std::unique_ptr<GeoShape> shape1(
522
31
                    GeoShape::from_encoded(lhs_value.data, lhs_value.size));
523
31
            std::unique_ptr<GeoShape> shape2(
524
31
                    GeoShape::from_encoded(rhs_value.data, rhs_value.size));
525
526
31
            if (!shape1 || !shape2) {
527
0
                null_map_data[row] = 1;
528
0
                continue;
529
0
            }
530
31
            auto relation_value = Func::evaluate(shape1.get(), shape2.get());
531
31
            res->get_data()[row] = relation_value;
532
31
        }
533
31
        block.replace_by_position(result,
534
31
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
535
31
        return Status::OK();
536
31
    }
537
};
538
539
struct StContainsFunc {
540
    static constexpr auto NAME = "st_contains";
541
8
    static bool evaluate(GeoShape* shape1, GeoShape* shape2) { return shape1->contains(shape2); }
542
};
543
544
struct StIntersectsFunc {
545
    static constexpr auto NAME = "st_intersects";
546
31
    static bool evaluate(GeoShape* shape1, GeoShape* shape2) { return shape1->intersects(shape2); }
547
};
548
549
struct StDisjointFunc {
550
    static constexpr auto NAME = "st_disjoint";
551
0
    static bool evaluate(GeoShape* shape1, GeoShape* shape2) { return shape1->disjoint(shape2); }
552
};
553
554
struct StTouchesFunc {
555
    static constexpr auto NAME = "st_touches";
556
31
    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
84
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
600
84
        DCHECK_EQ(arguments.size(), 1);
601
84
        auto return_type = block.get_data_type(result);
602
84
        auto& geo = block.get_by_position(arguments[0]).column;
603
604
84
        const auto size = geo->size();
605
84
        auto res = ColumnString::create();
606
84
        auto null_map = ColumnUInt8::create(size, 0);
607
84
        auto& null_map_data = null_map->get_data();
608
84
        GeoParseStatus status;
609
84
        std::string buf;
610
173
        for (int row = 0; row < size; ++row) {
611
89
            auto value = geo->get_data_at(row);
612
89
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
613
89
            if (shape == nullptr || status != GEO_PARSE_OK ||
614
89
                (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
84
            buf.clear();
620
84
            shape->encode_to(&buf);
621
84
            res->insert_data(buf.data(), buf.size());
622
84
        }
623
84
        block.replace_by_position(result,
624
84
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
625
84
        return Status::OK();
626
84
    }
_ZN5doris13StGeoFromTextINS_18StGeometryFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
599
4
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
600
4
        DCHECK_EQ(arguments.size(), 1);
601
4
        auto return_type = block.get_data_type(result);
602
4
        auto& geo = block.get_by_position(arguments[0]).column;
603
604
4
        const auto size = geo->size();
605
4
        auto res = ColumnString::create();
606
4
        auto null_map = ColumnUInt8::create(size, 0);
607
4
        auto& null_map_data = null_map->get_data();
608
4
        GeoParseStatus status;
609
4
        std::string buf;
610
9
        for (int row = 0; row < size; ++row) {
611
5
            auto value = geo->get_data_at(row);
612
5
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
613
5
            if (shape == nullptr || status != GEO_PARSE_OK ||
614
5
                (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
4
            buf.clear();
620
4
            shape->encode_to(&buf);
621
4
            res->insert_data(buf.data(), buf.size());
622
4
        }
623
4
        block.replace_by_position(result,
624
4
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
625
4
        return Status::OK();
626
4
    }
_ZN5doris13StGeoFromTextINS_14StGeomFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
599
2
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
600
2
        DCHECK_EQ(arguments.size(), 1);
601
2
        auto return_type = block.get_data_type(result);
602
2
        auto& geo = block.get_by_position(arguments[0]).column;
603
604
2
        const auto size = geo->size();
605
2
        auto res = ColumnString::create();
606
2
        auto null_map = ColumnUInt8::create(size, 0);
607
2
        auto& null_map_data = null_map->get_data();
608
2
        GeoParseStatus status;
609
2
        std::string buf;
610
5
        for (int row = 0; row < size; ++row) {
611
3
            auto value = geo->get_data_at(row);
612
3
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
613
3
            if (shape == nullptr || status != GEO_PARSE_OK ||
614
3
                (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
2
            buf.clear();
620
2
            shape->encode_to(&buf);
621
2
            res->insert_data(buf.data(), buf.size());
622
2
        }
623
2
        block.replace_by_position(result,
624
2
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
625
2
        return Status::OK();
626
2
    }
_ZN5doris13StGeoFromTextINS_14StLineFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
599
28
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
600
28
        DCHECK_EQ(arguments.size(), 1);
601
28
        auto return_type = block.get_data_type(result);
602
28
        auto& geo = block.get_by_position(arguments[0]).column;
603
604
28
        const auto size = geo->size();
605
28
        auto res = ColumnString::create();
606
28
        auto null_map = ColumnUInt8::create(size, 0);
607
28
        auto& null_map_data = null_map->get_data();
608
28
        GeoParseStatus status;
609
28
        std::string buf;
610
57
        for (int row = 0; row < size; ++row) {
611
29
            auto value = geo->get_data_at(row);
612
29
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
613
29
            if (shape == nullptr || status != GEO_PARSE_OK ||
614
29
                (Impl::shape_type != GEO_SHAPE_ANY && shape->type() != Impl::shape_type)) {
615
1
                null_map_data[row] = 1;
616
1
                res->insert_default();
617
1
                continue;
618
1
            }
619
28
            buf.clear();
620
28
            shape->encode_to(&buf);
621
28
            res->insert_data(buf.data(), buf.size());
622
28
        }
623
28
        block.replace_by_position(result,
624
28
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
625
28
        return Status::OK();
626
28
    }
_ZN5doris13StGeoFromTextINS_20StLineStringFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
599
1
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
600
1
        DCHECK_EQ(arguments.size(), 1);
601
1
        auto return_type = block.get_data_type(result);
602
1
        auto& geo = block.get_by_position(arguments[0]).column;
603
604
1
        const auto size = geo->size();
605
1
        auto res = ColumnString::create();
606
1
        auto null_map = ColumnUInt8::create(size, 0);
607
1
        auto& null_map_data = null_map->get_data();
608
1
        GeoParseStatus status;
609
1
        std::string buf;
610
2
        for (int row = 0; row < size; ++row) {
611
1
            auto value = geo->get_data_at(row);
612
1
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
613
1
            if (shape == nullptr || status != GEO_PARSE_OK ||
614
1
                (Impl::shape_type != GEO_SHAPE_ANY && shape->type() != Impl::shape_type)) {
615
0
                null_map_data[row] = 1;
616
0
                res->insert_default();
617
0
                continue;
618
0
            }
619
1
            buf.clear();
620
1
            shape->encode_to(&buf);
621
1
            res->insert_data(buf.data(), buf.size());
622
1
        }
623
1
        block.replace_by_position(result,
624
1
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
625
1
        return Status::OK();
626
1
    }
_ZN5doris13StGeoFromTextINS_9StPolygonEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
599
46
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
600
46
        DCHECK_EQ(arguments.size(), 1);
601
46
        auto return_type = block.get_data_type(result);
602
46
        auto& geo = block.get_by_position(arguments[0]).column;
603
604
46
        const auto size = geo->size();
605
46
        auto res = ColumnString::create();
606
46
        auto null_map = ColumnUInt8::create(size, 0);
607
46
        auto& null_map_data = null_map->get_data();
608
46
        GeoParseStatus status;
609
46
        std::string buf;
610
93
        for (int row = 0; row < size; ++row) {
611
47
            auto value = geo->get_data_at(row);
612
47
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
613
47
            if (shape == nullptr || status != GEO_PARSE_OK ||
614
47
                (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
46
            buf.clear();
620
46
            shape->encode_to(&buf);
621
46
            res->insert_data(buf.data(), buf.size());
622
46
        }
623
46
        block.replace_by_position(result,
624
46
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
625
46
        return Status::OK();
626
46
    }
_ZN5doris13StGeoFromTextINS_17StPolygonFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
599
2
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
600
2
        DCHECK_EQ(arguments.size(), 1);
601
2
        auto return_type = block.get_data_type(result);
602
2
        auto& geo = block.get_by_position(arguments[0]).column;
603
604
2
        const auto size = geo->size();
605
2
        auto res = ColumnString::create();
606
2
        auto null_map = ColumnUInt8::create(size, 0);
607
2
        auto& null_map_data = null_map->get_data();
608
2
        GeoParseStatus status;
609
2
        std::string buf;
610
5
        for (int row = 0; row < size; ++row) {
611
3
            auto value = geo->get_data_at(row);
612
3
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
613
3
            if (shape == nullptr || status != GEO_PARSE_OK ||
614
3
                (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
2
            buf.clear();
620
2
            shape->encode_to(&buf);
621
2
            res->insert_data(buf.data(), buf.size());
622
2
        }
623
2
        block.replace_by_position(result,
624
2
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
625
2
        return Status::OK();
626
2
    }
_ZN5doris13StGeoFromTextINS_14StPolyFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
599
1
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
600
1
        DCHECK_EQ(arguments.size(), 1);
601
1
        auto return_type = block.get_data_type(result);
602
1
        auto& geo = block.get_by_position(arguments[0]).column;
603
604
1
        const auto size = geo->size();
605
1
        auto res = ColumnString::create();
606
1
        auto null_map = ColumnUInt8::create(size, 0);
607
1
        auto& null_map_data = null_map->get_data();
608
1
        GeoParseStatus status;
609
1
        std::string buf;
610
2
        for (int row = 0; row < size; ++row) {
611
1
            auto value = geo->get_data_at(row);
612
1
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
613
1
            if (shape == nullptr || status != GEO_PARSE_OK ||
614
1
                (Impl::shape_type != GEO_SHAPE_ANY && shape->type() != Impl::shape_type)) {
615
0
                null_map_data[row] = 1;
616
0
                res->insert_default();
617
0
                continue;
618
0
            }
619
1
            buf.clear();
620
1
            shape->encode_to(&buf);
621
1
            res->insert_data(buf.data(), buf.size());
622
1
        }
623
1
        block.replace_by_position(result,
624
1
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
625
1
        return Status::OK();
626
1
    }
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
9
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
645
9
        DCHECK_EQ(arguments.size(), 1);
646
9
        auto return_type = block.get_data_type(result);
647
9
        auto& geo = block.get_by_position(arguments[0]).column;
648
649
9
        const auto size = geo->size();
650
9
        auto res = ColumnString::create();
651
9
        auto null_map = ColumnUInt8::create(size, 0);
652
9
        auto& null_map_data = null_map->get_data();
653
9
        GeoParseStatus status;
654
9
        std::string buf;
655
18
        for (int row = 0; row < size; ++row) {
656
9
            auto value = geo->get_data_at(row);
657
9
            std::unique_ptr<GeoShape> shape = GeoShape::from_wkb(value.data, value.size, status);
658
9
            if (shape == nullptr || status != GEO_PARSE_OK) {
659
0
                null_map_data[row] = 1;
660
0
                res->insert_default();
661
0
                continue;
662
0
            }
663
9
            buf.clear();
664
9
            shape->encode_to(&buf);
665
9
            res->insert_data(buf.data(), buf.size());
666
9
        }
667
9
        block.replace_by_position(result,
668
9
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
669
9
        return Status::OK();
670
9
    }
_ZN5doris12StGeoFromWkbINS_17StGeometryFromWKBEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
644
6
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
645
6
        DCHECK_EQ(arguments.size(), 1);
646
6
        auto return_type = block.get_data_type(result);
647
6
        auto& geo = block.get_by_position(arguments[0]).column;
648
649
6
        const auto size = geo->size();
650
6
        auto res = ColumnString::create();
651
6
        auto null_map = ColumnUInt8::create(size, 0);
652
6
        auto& null_map_data = null_map->get_data();
653
6
        GeoParseStatus status;
654
6
        std::string buf;
655
12
        for (int row = 0; row < size; ++row) {
656
6
            auto value = geo->get_data_at(row);
657
6
            std::unique_ptr<GeoShape> shape = GeoShape::from_wkb(value.data, value.size, status);
658
6
            if (shape == nullptr || status != GEO_PARSE_OK) {
659
0
                null_map_data[row] = 1;
660
0
                res->insert_default();
661
0
                continue;
662
0
            }
663
6
            buf.clear();
664
6
            shape->encode_to(&buf);
665
6
            res->insert_data(buf.data(), buf.size());
666
6
        }
667
6
        block.replace_by_position(result,
668
6
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
669
6
        return Status::OK();
670
6
    }
_ZN5doris12StGeoFromWkbINS_13StGeomFromWKBEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
644
3
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
645
3
        DCHECK_EQ(arguments.size(), 1);
646
3
        auto return_type = block.get_data_type(result);
647
3
        auto& geo = block.get_by_position(arguments[0]).column;
648
649
3
        const auto size = geo->size();
650
3
        auto res = ColumnString::create();
651
3
        auto null_map = ColumnUInt8::create(size, 0);
652
3
        auto& null_map_data = null_map->get_data();
653
3
        GeoParseStatus status;
654
3
        std::string buf;
655
6
        for (int row = 0; row < size; ++row) {
656
3
            auto value = geo->get_data_at(row);
657
3
            std::unique_ptr<GeoShape> shape = GeoShape::from_wkb(value.data, value.size, status);
658
3
            if (shape == nullptr || status != GEO_PARSE_OK) {
659
0
                null_map_data[row] = 1;
660
0
                res->insert_default();
661
0
                continue;
662
0
            }
663
3
            buf.clear();
664
3
            shape->encode_to(&buf);
665
3
            res->insert_data(buf.data(), buf.size());
666
3
        }
667
3
        block.replace_by_position(result,
668
3
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
669
3
        return Status::OK();
670
3
    }
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
8
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
678
8
        DCHECK_EQ(arguments.size(), 1);
679
8
        auto return_type = block.get_data_type(result);
680
8
        auto res = ColumnString::create();
681
682
8
        auto col = block.get_by_position(arguments[0]).column;
683
8
        const auto size = col->size();
684
8
        auto null_map = ColumnUInt8::create(size, 0);
685
8
        auto& null_map_data = null_map->get_data();
686
8
        std::unique_ptr<GeoShape> shape;
687
688
16
        for (int row = 0; row < size; ++row) {
689
8
            auto shape_value = col->get_data_at(row);
690
8
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
691
8
            if (!shape) {
692
0
                null_map_data[row] = 1;
693
0
                res->insert_default();
694
0
                continue;
695
0
            }
696
697
8
            std::string binary = GeoShape::as_binary(shape.get());
698
8
            if (binary.empty()) {
699
0
                null_map_data[row] = 1;
700
0
                res->insert_default();
701
0
                continue;
702
0
            }
703
8
            res->insert_data(binary.data(), binary.size());
704
8
        }
705
706
8
        block.replace_by_position(result,
707
8
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
708
8
        return Status::OK();
709
8
    }
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
0
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
717
0
        DCHECK_EQ(arguments.size(), 1);
718
0
        auto return_type = block.get_data_type(result);
719
720
0
        auto col = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
721
0
        const auto size = col->size();
722
0
        auto res = ColumnFloat64::create();
723
0
        res->reserve(size);
724
0
        auto null_map = ColumnUInt8::create(size, 0);
725
0
        auto& null_map_data = null_map->get_data();
726
727
0
        std::unique_ptr<GeoShape> shape;
728
0
        for (int row = 0; row < size; ++row) {
729
0
            auto shape_value = col->get_data_at(row);
730
0
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
731
0
            if (!shape) {
732
0
                null_map_data[row] = 1;
733
0
                res->insert_default();
734
0
                continue;
735
0
            }
736
737
0
            double length = shape->Length();
738
0
            res->insert_value(length);
739
0
        }
740
741
0
        block.replace_by_position(result,
742
0
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
743
0
        return Status::OK();
744
0
    }
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
0
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
752
0
        DCHECK_EQ(arguments.size(), 1);
753
0
        auto return_type = block.get_data_type(result);
754
755
0
        auto col = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
756
0
        const auto size = col->size();
757
0
        auto res = ColumnString::create();
758
0
        auto null_map = ColumnUInt8::create(size, 0);
759
0
        auto& null_map_data = null_map->get_data();
760
761
0
        std::unique_ptr<GeoShape> shape;
762
0
        for (int row = 0; row < size; ++row) {
763
0
            auto shape_value = col->get_data_at(row);
764
0
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
765
0
            if (!shape) {
766
0
                null_map_data[row] = 1;
767
0
                res->insert_default();
768
0
                continue;
769
0
            }
770
771
0
            auto geo_type = shape->GeometryType();
772
0
            res->insert_data(geo_type.data(), geo_type.size());
773
0
        }
774
775
0
        block.replace_by_position(result,
776
0
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
777
0
        return Status::OK();
778
0
    }
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
0
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
787
0
        DCHECK_EQ(arguments.size(), 2);
788
0
        auto return_type = block.get_data_type(result);
789
0
        const auto& [left_column, left_const] =
790
0
                unpack_if_const(block.get_by_position(arguments[0]).column);
791
0
        const auto& [right_column, right_const] =
792
0
                unpack_if_const(block.get_by_position(arguments[1]).column);
793
794
0
        const auto size = std::max(left_column->size(), right_column->size());
795
796
0
        auto res = ColumnFloat64::create();
797
0
        res->reserve(size);
798
0
        auto null_map = ColumnUInt8::create(size, 0);
799
0
        auto& null_map_data = null_map->get_data();
800
801
0
        if (left_const) {
802
0
            const_vector(left_column, right_column, res, null_map_data, size);
803
0
        } else if (right_const) {
804
0
            vector_const(left_column, right_column, res, null_map_data, size);
805
0
        } else {
806
0
            vector_vector(left_column, right_column, res, null_map_data, size);
807
0
        }
808
0
        block.replace_by_position(result,
809
0
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
810
0
        return Status::OK();
811
0
    }
812
813
private:
814
0
    static bool decode_shape(const StringRef& value, std::unique_ptr<GeoShape>& shape) {
815
0
        shape = GeoShape::from_encoded(value.data, value.size);
816
0
        return static_cast<bool>(shape);
817
0
    }
818
819
    static void loop_do(StringRef& lhs_value, StringRef& rhs_value,
820
                        std::vector<std::unique_ptr<GeoShape>>& shapes,
821
0
                        ColumnFloat64::MutablePtr& res, NullMap& null_map, int row) {
822
0
        StringRef* strs[2] = {&lhs_value, &rhs_value};
823
0
        for (int i = 0; i < 2; ++i) {
824
0
            if (!decode_shape(*strs[i], shapes[i])) {
825
0
                null_map[row] = 1;
826
0
                res->insert_default();
827
0
                return;
828
0
            }
829
0
        }
830
0
        double distance = shapes[0]->Distance(shapes[1].get());
831
0
        if (UNLIKELY(distance < 0)) {
832
0
            null_map[row] = 1;
833
0
            res->insert_default();
834
0
            return;
835
0
        }
836
0
        res->insert_value(distance);
837
0
    }
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
0
                              const size_t size) {
908
0
        const auto* left_string = assert_cast<const ColumnString*>(left_column.get());
909
0
        const auto* right_string = assert_cast<const ColumnString*>(right_column.get());
910
911
0
        std::vector<std::unique_ptr<GeoShape>> shapes(2);
912
0
        for (int row = 0; row < size; ++row) {
913
0
            auto lhs_value = left_string->get_data_at(row);
914
0
            auto rhs_value = right_string->get_data_at(row);
915
0
            loop_do(lhs_value, rhs_value, shapes, res, null_map, row);
916
0
        }
917
0
    }
918
};
919
920
7
void register_function_geo(SimpleFunctionFactory& factory) {
921
7
    factory.register_function<GeoFunction<StPoint>>();
922
7
    factory.register_function<GeoFunction<StAsText<StAsWktName>>>();
923
7
    factory.register_function<GeoFunction<StAsText<StAsTextName>>>();
924
7
    factory.register_function<GeoFunction<StX>>();
925
7
    factory.register_function<GeoFunction<StY>>();
926
7
    factory.register_function<GeoFunction<StDistanceSphere>>();
927
7
    factory.register_function<GeoFunction<StAngleSphere>>();
928
7
    factory.register_function<GeoFunction<StAngle>>();
929
7
    factory.register_function<GeoFunction<StAzimuth>>();
930
7
    factory.register_function<GeoFunction<StRelationFunction<StContainsFunc>>>();
931
7
    factory.register_function<GeoFunction<StRelationFunction<StIntersectsFunc>>>();
932
7
    factory.register_function<GeoFunction<StRelationFunction<StDisjointFunc>>>();
933
7
    factory.register_function<GeoFunction<StRelationFunction<StTouchesFunc>>>();
934
7
    factory.register_function<GeoFunction<StCircle>>();
935
7
    factory.register_function<GeoFunction<StGeoFromText<StGeometryFromText>>>();
936
7
    factory.register_function<GeoFunction<StGeoFromText<StGeomFromText>>>();
937
7
    factory.register_function<GeoFunction<StGeoFromText<StLineFromText>>>();
938
7
    factory.register_function<GeoFunction<StGeoFromText<StLineStringFromText>>>();
939
7
    factory.register_function<GeoFunction<StGeoFromText<StPolygon>>>();
940
7
    factory.register_function<GeoFunction<StGeoFromText<StPolygonFromText>>>();
941
7
    factory.register_function<GeoFunction<StGeoFromText<StPolyFromText>>>();
942
7
    factory.register_function<GeoFunction<StAreaSquareMeters>>();
943
7
    factory.register_function<GeoFunction<StAreaSquareKm>>();
944
7
    factory.register_function<GeoFunction<StGeoFromWkb<StGeometryFromWKB>>>();
945
7
    factory.register_function<GeoFunction<StGeoFromWkb<StGeomFromWKB>>>();
946
7
    factory.register_function<GeoFunction<StAsBinary>>();
947
7
    factory.register_function<GeoFunction<StLength>>();
948
7
    factory.register_function<GeoFunction<StGeometryType>>();
949
7
    factory.register_function<GeoFunction<StDistance>>();
950
7
}
951
952
} // namespace doris