Coverage Report

Created: 2026-05-26 17:00

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