Coverage Report

Created: 2026-05-16 21:52

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
3
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
51
3
        DCHECK_EQ(arguments.size(), 2);
52
3
        auto return_type = block.get_data_type(result);
53
54
3
        auto x_col = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[0]).column);
55
3
        auto y_col = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[1]).column);
56
57
3
        const auto size = x_col.size();
58
59
3
        auto res = ColumnString::create();
60
3
        auto null_map = ColumnUInt8::create(size, 0);
61
3
        auto& null_map_data = null_map->get_data();
62
3
        GeoPoint point;
63
3
        std::string buf;
64
8
        for (int row = 0; row < size; ++row) {
65
5
            auto cur_res = point.from_coord(x_col.value_at(row), y_col.value_at(row));
66
5
            if (cur_res != GEO_PARSE_OK) {
67
0
                null_map_data[row] = 1;
68
0
                res->insert_default();
69
0
                continue;
70
0
            }
71
5
            buf.clear();
72
5
            point.encode_to(&buf);
73
5
            res->insert_data(buf.data(), buf.size());
74
5
        }
75
76
3
        block.replace_by_position(result,
77
3
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
78
3
        return Status::OK();
79
3
    }
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
2
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
95
2
        DCHECK_EQ(arguments.size(), 1);
96
2
        auto return_type = block.get_data_type(result);
97
98
2
        auto& input = block.get_by_position(arguments[0]).column;
99
100
2
        auto size = input->size();
101
102
2
        auto res = ColumnString::create();
103
2
        auto null_map = ColumnUInt8::create(size, 0);
104
2
        auto& null_map_data = null_map->get_data();
105
106
2
        std::unique_ptr<GeoShape> shape;
107
6
        for (int row = 0; row < size; ++row) {
108
4
            auto shape_value = input->get_data_at(row);
109
4
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
110
4
            if (shape == nullptr) {
111
2
                null_map_data[row] = 1;
112
2
                res->insert_default();
113
2
                continue;
114
2
            }
115
2
            auto wkt = shape->as_wkt();
116
2
            res->insert_data(wkt.data(), wkt.size());
117
2
        }
118
2
        block.replace_by_position(result,
119
2
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
120
121
2
        return Status::OK();
122
2
    }
_ZN5doris8StAsTextINS_11StAsWktNameEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
94
1
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
95
1
        DCHECK_EQ(arguments.size(), 1);
96
1
        auto return_type = block.get_data_type(result);
97
98
1
        auto& input = block.get_by_position(arguments[0]).column;
99
100
1
        auto size = input->size();
101
102
1
        auto res = ColumnString::create();
103
1
        auto null_map = ColumnUInt8::create(size, 0);
104
1
        auto& null_map_data = null_map->get_data();
105
106
1
        std::unique_ptr<GeoShape> shape;
107
3
        for (int row = 0; row < size; ++row) {
108
2
            auto shape_value = input->get_data_at(row);
109
2
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
110
2
            if (shape == nullptr) {
111
1
                null_map_data[row] = 1;
112
1
                res->insert_default();
113
1
                continue;
114
1
            }
115
1
            auto wkt = shape->as_wkt();
116
1
            res->insert_data(wkt.data(), wkt.size());
117
1
        }
118
1
        block.replace_by_position(result,
119
1
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
120
121
1
        return Status::OK();
122
1
    }
_ZN5doris8StAsTextINS_12StAsTextNameEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
94
1
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
95
1
        DCHECK_EQ(arguments.size(), 1);
96
1
        auto return_type = block.get_data_type(result);
97
98
1
        auto& input = block.get_by_position(arguments[0]).column;
99
100
1
        auto size = input->size();
101
102
1
        auto res = ColumnString::create();
103
1
        auto null_map = ColumnUInt8::create(size, 0);
104
1
        auto& null_map_data = null_map->get_data();
105
106
1
        std::unique_ptr<GeoShape> shape;
107
3
        for (int row = 0; row < size; ++row) {
108
2
            auto shape_value = input->get_data_at(row);
109
2
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
110
2
            if (shape == nullptr) {
111
1
                null_map_data[row] = 1;
112
1
                res->insert_default();
113
1
                continue;
114
1
            }
115
1
            auto wkt = shape->as_wkt();
116
1
            res->insert_data(wkt.data(), wkt.size());
117
1
        }
118
1
        block.replace_by_position(result,
119
1
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
120
121
1
        return Status::OK();
122
1
    }
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
1
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
130
1
        DCHECK_EQ(arguments.size(), 1);
131
1
        auto return_type = block.get_data_type(result);
132
133
1
        auto& input = block.get_by_position(arguments[0]).column;
134
135
1
        auto size = input->size();
136
137
1
        auto res = ColumnFloat64::create();
138
1
        auto null_map = ColumnUInt8::create(size, 0);
139
1
        auto& null_map_data = null_map->get_data();
140
1
        res->reserve(size);
141
142
1
        GeoPoint point;
143
3
        for (int row = 0; row < size; ++row) {
144
2
            auto point_value = input->get_data_at(row);
145
2
            auto pt = point.decode_from(point_value.data, point_value.size);
146
147
2
            if (!pt) {
148
1
                null_map_data[row] = 1;
149
1
                res->insert_default();
150
1
                continue;
151
1
            }
152
1
            auto x_value = point.x();
153
1
            res->insert_value(x_value);
154
1
        }
155
1
        block.replace_by_position(result,
156
1
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
157
158
1
        return Status::OK();
159
1
    }
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
1
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
167
1
        DCHECK_EQ(arguments.size(), 1);
168
1
        auto return_type = block.get_data_type(result);
169
170
1
        auto& input = block.get_by_position(arguments[0]).column;
171
172
1
        auto size = input->size();
173
174
1
        auto res = ColumnFloat64::create();
175
1
        res->reserve(size);
176
1
        auto null_map = ColumnUInt8::create(size, 0);
177
1
        auto& null_map_data = null_map->get_data();
178
179
1
        GeoPoint point;
180
3
        for (int row = 0; row < size; ++row) {
181
2
            auto point_value = input->get_data_at(row);
182
2
            auto pt = point.decode_from(point_value.data, point_value.size);
183
184
2
            if (!pt) {
185
1
                null_map_data[row] = 1;
186
1
                res->insert_default();
187
1
                continue;
188
1
            }
189
1
            auto y_value = point.y();
190
1
            res->insert_value(y_value);
191
1
        }
192
1
        block.replace_by_position(result,
193
1
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
194
195
1
        return Status::OK();
196
1
    }
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
1
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
204
1
        DCHECK_EQ(arguments.size(), 4);
205
1
        auto return_type = block.get_data_type(result);
206
207
1
        auto x_lng = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[0]).column);
208
1
        auto x_lat = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[1]).column);
209
1
        auto y_lng = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[2]).column);
210
1
        auto y_lat = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[3]).column);
211
212
1
        const auto size = x_lng.size();
213
1
        auto res = ColumnFloat64::create();
214
1
        res->reserve(size);
215
1
        auto null_map = ColumnUInt8::create(size, 0);
216
1
        auto& null_map_data = null_map->get_data();
217
6
        for (int row = 0; row < size; ++row) {
218
5
            double distance = 0;
219
5
            if (!GeoPoint::ComputeDistance(x_lng.value_at(row), x_lat.value_at(row),
220
5
                                           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
5
            res->insert_value(distance);
226
5
        }
227
228
1
        block.replace_by_position(result,
229
1
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
230
1
        return Status::OK();
231
1
    }
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
1
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
239
1
        DCHECK_EQ(arguments.size(), 4);
240
1
        auto return_type = block.get_data_type(result);
241
242
1
        auto x_lng = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[0]).column);
243
1
        auto x_lat = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[1]).column);
244
1
        auto y_lng = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[2]).column);
245
1
        auto y_lat = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[3]).column);
246
247
1
        const auto size = x_lng.size();
248
249
1
        auto res = ColumnFloat64::create();
250
1
        res->reserve(size);
251
1
        auto null_map = ColumnUInt8::create(size, 0);
252
1
        auto& null_map_data = null_map->get_data();
253
254
6
        for (int row = 0; row < size; ++row) {
255
5
            double angle = 0;
256
5
            if (!GeoPoint::ComputeAngleSphere(x_lng.value_at(row), x_lat.value_at(row),
257
5
                                              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
5
            res->insert_value(angle);
263
5
        }
264
265
1
        block.replace_by_position(result,
266
1
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
267
1
        return Status::OK();
268
1
    }
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
1
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
276
1
        DCHECK_EQ(arguments.size(), 3);
277
1
        auto return_type = block.get_data_type(result);
278
279
1
        auto p1 = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
280
1
        auto p2 = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
281
1
        auto p3 = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[2]).column);
282
1
        const auto size = p1.size();
283
1
        auto res = ColumnFloat64::create();
284
1
        res->reserve(size);
285
1
        auto null_map = ColumnUInt8::create(size, 0);
286
1
        auto& null_map_data = null_map->get_data();
287
288
1
        GeoPoint point1;
289
1
        GeoPoint point2;
290
1
        GeoPoint point3;
291
292
5
        for (int row = 0; row < size; ++row) {
293
4
            auto shape_value1 = p1.value_at(row);
294
4
            auto pt1 = point1.decode_from(shape_value1.data, shape_value1.size);
295
4
            if (!pt1) {
296
1
                null_map_data[row] = 1;
297
1
                res->insert_default();
298
1
                continue;
299
1
            }
300
301
3
            auto shape_value2 = p2.value_at(row);
302
3
            auto pt2 = point2.decode_from(shape_value2.data, shape_value2.size);
303
3
            if (!pt2) {
304
1
                null_map_data[row] = 1;
305
1
                res->insert_default();
306
1
                continue;
307
1
            }
308
2
            auto shape_value3 = p3.value_at(row);
309
2
            auto pt3 = point3.decode_from(shape_value3.data, shape_value3.size);
310
2
            if (!pt3) {
311
1
                null_map_data[row] = 1;
312
1
                res->insert_default();
313
1
                continue;
314
1
            }
315
316
1
            double angle = 0;
317
1
            if (!GeoPoint::ComputeAngle(&point1, &point2, &point3, &angle)) {
318
0
                null_map_data[row] = 1;
319
0
                res->insert_default();
320
0
                continue;
321
0
            }
322
1
            res->insert_value(angle);
323
1
        }
324
1
        block.replace_by_position(result,
325
1
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
326
1
        return Status::OK();
327
1
    }
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
3
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
335
3
        DCHECK_EQ(arguments.size(), 2);
336
3
        auto return_type = block.get_data_type(result);
337
338
3
        auto left_col = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
339
3
        auto right_col =
340
3
                ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
341
342
3
        const auto size = left_col.size();
343
3
        auto res = ColumnFloat64::create();
344
3
        res->reserve(size);
345
3
        auto null_map = ColumnUInt8::create(size, 0);
346
3
        auto& null_map_data = null_map->get_data();
347
3
        GeoPoint point1;
348
3
        GeoPoint point2;
349
8
        for (int row = 0; row < size; ++row) {
350
5
            auto shape_value1 = left_col.value_at(row);
351
5
            auto pt1 = point1.decode_from(shape_value1.data, shape_value1.size);
352
5
            auto shape_value2 = right_col.value_at(row);
353
5
            auto pt2 = point2.decode_from(shape_value2.data, shape_value2.size);
354
355
5
            if (!(pt1 && pt2)) {
356
2
                null_map_data[row] = 1;
357
2
                res->insert_default();
358
2
                continue;
359
2
            }
360
361
3
            double angle = 0;
362
3
            if (!GeoPoint::ComputeAzimuth(&point1, &point2, &angle)) {
363
0
                null_map_data[row] = 1;
364
0
                res->insert_default();
365
0
                continue;
366
0
            }
367
3
            res->insert_value(angle);
368
3
        }
369
3
        block.replace_by_position(result,
370
3
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
371
3
        return Status::OK();
372
3
    }
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
1
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
380
1
        DCHECK_EQ(arguments.size(), 1);
381
1
        auto return_type = block.get_data_type(result);
382
383
1
        auto col = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
384
1
        const auto size = col->size();
385
1
        auto res = ColumnFloat64::create();
386
1
        res->reserve(size);
387
1
        auto null_map = ColumnUInt8::create(size, 0);
388
1
        auto& null_map_data = null_map->get_data();
389
1
        std::unique_ptr<GeoShape> shape;
390
391
3
        for (int row = 0; row < size; ++row) {
392
2
            auto shape_value = col->get_data_at(row);
393
2
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
394
2
            if (!shape) {
395
1
                null_map_data[row] = 1;
396
1
                res->insert_default();
397
1
                continue;
398
1
            }
399
400
1
            double area = 0;
401
1
            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
1
            res->insert_value(area);
407
1
        }
408
409
1
        block.replace_by_position(result,
410
1
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
411
1
        return Status::OK();
412
1
    }
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
1
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
420
1
        DCHECK_EQ(arguments.size(), 1);
421
1
        auto return_type = block.get_data_type(result);
422
423
1
        auto col = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
424
1
        const auto size = col->size();
425
1
        auto res = ColumnFloat64::create();
426
1
        res->reserve(size);
427
1
        auto null_map = ColumnUInt8::create(size, 0);
428
1
        auto& null_map_data = null_map->get_data();
429
430
1
        std::unique_ptr<GeoShape> shape;
431
432
3
        for (int row = 0; row < size; ++row) {
433
2
            auto shape_value = col->get_data_at(row);
434
2
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
435
2
            if (!shape) {
436
1
                null_map_data[row] = 1;
437
1
                res->insert_default();
438
1
                continue;
439
1
            }
440
441
1
            double area = 0;
442
1
            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
1
            res->insert_value(area);
449
1
        }
450
451
1
        block.replace_by_position(result,
452
1
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
453
1
        return Status::OK();
454
1
    }
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
1
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
462
1
        DCHECK_EQ(arguments.size(), 3);
463
1
        auto return_type = block.get_data_type(result);
464
1
        auto center_lng =
465
1
                ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[0]).column);
466
1
        auto center_lat =
467
1
                ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[1]).column);
468
1
        auto radius = ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[2]).column);
469
470
1
        const auto size = center_lng.size();
471
472
1
        auto res = ColumnString::create();
473
474
1
        auto null_map = ColumnUInt8::create(size, 0);
475
1
        auto& null_map_data = null_map->get_data();
476
477
1
        GeoCircle circle;
478
1
        std::string buf;
479
5
        for (int row = 0; row < size; ++row) {
480
4
            auto lng_value = center_lng.value_at(row);
481
4
            auto lat_value = center_lat.value_at(row);
482
4
            auto radius_value = radius.value_at(row);
483
484
4
            auto value = circle.init(lng_value, lat_value, radius_value);
485
4
            if (value != GEO_PARSE_OK) {
486
0
                null_map_data[row] = 1;
487
0
                res->insert_default();
488
0
                continue;
489
0
            }
490
4
            buf.clear();
491
4
            circle.encode_to(&buf);
492
4
            res->insert_data(buf.data(), buf.size());
493
4
        }
494
1
        block.replace_by_position(result,
495
1
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
496
1
        return Status::OK();
497
1
    }
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
5
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
507
5
        DCHECK_EQ(arguments.size(), 2);
508
5
        auto return_type = block.get_data_type(result);
509
5
        auto left_col = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
510
5
        auto right_col =
511
5
                ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
512
513
5
        const auto size = left_col.size();
514
515
5
        auto res = ColumnUInt8::create(size, 0);
516
5
        auto null_map = ColumnUInt8::create(size, 0);
517
5
        auto& null_map_data = null_map->get_data();
518
519
13
        for (int row = 0; row < size; ++row) {
520
8
            auto lhs_value = left_col.value_at(row);
521
8
            auto rhs_value = right_col.value_at(row);
522
523
8
            std::unique_ptr<GeoShape> shape1(
524
8
                    GeoShape::from_encoded(lhs_value.data, lhs_value.size));
525
8
            std::unique_ptr<GeoShape> shape2(
526
8
                    GeoShape::from_encoded(rhs_value.data, rhs_value.size));
527
528
8
            if (!shape1 || !shape2) {
529
2
                null_map_data[row] = 1;
530
2
                continue;
531
2
            }
532
6
            auto relation_value = Func::evaluate(shape1.get(), shape2.get());
533
6
            res->get_data()[row] = relation_value;
534
6
        }
535
5
        block.replace_by_position(result,
536
5
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
537
5
        return Status::OK();
538
5
    }
_ZN5doris18StRelationFunctionINS_14StContainsFuncEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
506
5
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
507
5
        DCHECK_EQ(arguments.size(), 2);
508
5
        auto return_type = block.get_data_type(result);
509
5
        auto left_col = ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
510
5
        auto right_col =
511
5
                ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
512
513
5
        const auto size = left_col.size();
514
515
5
        auto res = ColumnUInt8::create(size, 0);
516
5
        auto null_map = ColumnUInt8::create(size, 0);
517
5
        auto& null_map_data = null_map->get_data();
518
519
13
        for (int row = 0; row < size; ++row) {
520
8
            auto lhs_value = left_col.value_at(row);
521
8
            auto rhs_value = right_col.value_at(row);
522
523
8
            std::unique_ptr<GeoShape> shape1(
524
8
                    GeoShape::from_encoded(lhs_value.data, lhs_value.size));
525
8
            std::unique_ptr<GeoShape> shape2(
526
8
                    GeoShape::from_encoded(rhs_value.data, rhs_value.size));
527
528
8
            if (!shape1 || !shape2) {
529
2
                null_map_data[row] = 1;
530
2
                continue;
531
2
            }
532
6
            auto relation_value = Func::evaluate(shape1.get(), shape2.get());
533
6
            res->get_data()[row] = relation_value;
534
6
        }
535
5
        block.replace_by_position(result,
536
5
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
537
5
        return Status::OK();
538
5
    }
Unexecuted instantiation: _ZN5doris18StRelationFunctionINS_16StIntersectsFuncEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Unexecuted instantiation: _ZN5doris18StRelationFunctionINS_14StDisjointFuncEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Unexecuted instantiation: _ZN5doris18StRelationFunctionINS_13StTouchesFuncEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
539
};
540
541
struct StContainsFunc {
542
    static constexpr auto NAME = "st_contains";
543
6
    static bool evaluate(GeoShape* shape1, GeoShape* shape2) { return shape1->contains(shape2); }
544
};
545
546
struct StIntersectsFunc {
547
    static constexpr auto NAME = "st_intersects";
548
0
    static bool evaluate(GeoShape* shape1, GeoShape* shape2) { return shape1->intersects(shape2); }
549
};
550
551
struct StDisjointFunc {
552
    static constexpr auto NAME = "st_disjoint";
553
0
    static bool evaluate(GeoShape* shape1, GeoShape* shape2) { return shape1->disjoint(shape2); }
554
};
555
556
struct StTouchesFunc {
557
    static constexpr auto NAME = "st_touches";
558
0
    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
5
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
602
5
        DCHECK_EQ(arguments.size(), 1);
603
5
        auto return_type = block.get_data_type(result);
604
5
        auto& geo = block.get_by_position(arguments[0]).column;
605
606
5
        const auto size = geo->size();
607
5
        auto res = ColumnString::create();
608
5
        auto null_map = ColumnUInt8::create(size, 0);
609
5
        auto& null_map_data = null_map->get_data();
610
5
        GeoParseStatus status;
611
5
        std::string buf;
612
15
        for (int row = 0; row < size; ++row) {
613
10
            auto value = geo->get_data_at(row);
614
10
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
615
10
            if (shape == nullptr || status != GEO_PARSE_OK ||
616
10
                (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
5
            buf.clear();
622
5
            shape->encode_to(&buf);
623
5
            res->insert_data(buf.data(), buf.size());
624
5
        }
625
5
        block.replace_by_position(result,
626
5
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
627
5
        return Status::OK();
628
5
    }
_ZN5doris13StGeoFromTextINS_18StGeometryFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
601
1
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
602
1
        DCHECK_EQ(arguments.size(), 1);
603
1
        auto return_type = block.get_data_type(result);
604
1
        auto& geo = block.get_by_position(arguments[0]).column;
605
606
1
        const auto size = geo->size();
607
1
        auto res = ColumnString::create();
608
1
        auto null_map = ColumnUInt8::create(size, 0);
609
1
        auto& null_map_data = null_map->get_data();
610
1
        GeoParseStatus status;
611
1
        std::string buf;
612
3
        for (int row = 0; row < size; ++row) {
613
2
            auto value = geo->get_data_at(row);
614
2
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
615
2
            if (shape == nullptr || status != GEO_PARSE_OK ||
616
2
                (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
1
            buf.clear();
622
1
            shape->encode_to(&buf);
623
1
            res->insert_data(buf.data(), buf.size());
624
1
        }
625
1
        block.replace_by_position(result,
626
1
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
627
1
        return Status::OK();
628
1
    }
_ZN5doris13StGeoFromTextINS_14StGeomFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
601
1
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
602
1
        DCHECK_EQ(arguments.size(), 1);
603
1
        auto return_type = block.get_data_type(result);
604
1
        auto& geo = block.get_by_position(arguments[0]).column;
605
606
1
        const auto size = geo->size();
607
1
        auto res = ColumnString::create();
608
1
        auto null_map = ColumnUInt8::create(size, 0);
609
1
        auto& null_map_data = null_map->get_data();
610
1
        GeoParseStatus status;
611
1
        std::string buf;
612
3
        for (int row = 0; row < size; ++row) {
613
2
            auto value = geo->get_data_at(row);
614
2
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
615
2
            if (shape == nullptr || status != GEO_PARSE_OK ||
616
2
                (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
1
            buf.clear();
622
1
            shape->encode_to(&buf);
623
1
            res->insert_data(buf.data(), buf.size());
624
1
        }
625
1
        block.replace_by_position(result,
626
1
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
627
1
        return Status::OK();
628
1
    }
_ZN5doris13StGeoFromTextINS_14StLineFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
601
1
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
602
1
        DCHECK_EQ(arguments.size(), 1);
603
1
        auto return_type = block.get_data_type(result);
604
1
        auto& geo = block.get_by_position(arguments[0]).column;
605
606
1
        const auto size = geo->size();
607
1
        auto res = ColumnString::create();
608
1
        auto null_map = ColumnUInt8::create(size, 0);
609
1
        auto& null_map_data = null_map->get_data();
610
1
        GeoParseStatus status;
611
1
        std::string buf;
612
3
        for (int row = 0; row < size; ++row) {
613
2
            auto value = geo->get_data_at(row);
614
2
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
615
2
            if (shape == nullptr || status != GEO_PARSE_OK ||
616
2
                (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
1
            buf.clear();
622
1
            shape->encode_to(&buf);
623
1
            res->insert_data(buf.data(), buf.size());
624
1
        }
625
1
        block.replace_by_position(result,
626
1
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
627
1
        return Status::OK();
628
1
    }
Unexecuted instantiation: _ZN5doris13StGeoFromTextINS_20StLineStringFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
_ZN5doris13StGeoFromTextINS_9StPolygonEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
601
1
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
602
1
        DCHECK_EQ(arguments.size(), 1);
603
1
        auto return_type = block.get_data_type(result);
604
1
        auto& geo = block.get_by_position(arguments[0]).column;
605
606
1
        const auto size = geo->size();
607
1
        auto res = ColumnString::create();
608
1
        auto null_map = ColumnUInt8::create(size, 0);
609
1
        auto& null_map_data = null_map->get_data();
610
1
        GeoParseStatus status;
611
1
        std::string buf;
612
3
        for (int row = 0; row < size; ++row) {
613
2
            auto value = geo->get_data_at(row);
614
2
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
615
2
            if (shape == nullptr || status != GEO_PARSE_OK ||
616
2
                (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
1
            buf.clear();
622
1
            shape->encode_to(&buf);
623
1
            res->insert_data(buf.data(), buf.size());
624
1
        }
625
1
        block.replace_by_position(result,
626
1
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
627
1
        return Status::OK();
628
1
    }
_ZN5doris13StGeoFromTextINS_17StPolygonFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Line
Count
Source
601
1
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
602
1
        DCHECK_EQ(arguments.size(), 1);
603
1
        auto return_type = block.get_data_type(result);
604
1
        auto& geo = block.get_by_position(arguments[0]).column;
605
606
1
        const auto size = geo->size();
607
1
        auto res = ColumnString::create();
608
1
        auto null_map = ColumnUInt8::create(size, 0);
609
1
        auto& null_map_data = null_map->get_data();
610
1
        GeoParseStatus status;
611
1
        std::string buf;
612
3
        for (int row = 0; row < size; ++row) {
613
2
            auto value = geo->get_data_at(row);
614
2
            auto shape = GeoShape::from_wkt(value.data, value.size, status);
615
2
            if (shape == nullptr || status != GEO_PARSE_OK ||
616
2
                (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
1
            buf.clear();
622
1
            shape->encode_to(&buf);
623
1
            res->insert_data(buf.data(), buf.size());
624
1
        }
625
1
        block.replace_by_position(result,
626
1
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
627
1
        return Status::OK();
628
1
    }
Unexecuted instantiation: _ZN5doris13StGeoFromTextINS_14StPolyFromTextEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
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
0
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
647
0
        DCHECK_EQ(arguments.size(), 1);
648
0
        auto return_type = block.get_data_type(result);
649
0
        auto& geo = block.get_by_position(arguments[0]).column;
650
651
0
        const auto size = geo->size();
652
0
        auto res = ColumnString::create();
653
0
        auto null_map = ColumnUInt8::create(size, 0);
654
0
        auto& null_map_data = null_map->get_data();
655
0
        GeoParseStatus status;
656
0
        std::string buf;
657
0
        for (int row = 0; row < size; ++row) {
658
0
            auto value = geo->get_data_at(row);
659
0
            std::unique_ptr<GeoShape> shape = GeoShape::from_wkb(value.data, value.size, status);
660
0
            if (shape == nullptr || status != GEO_PARSE_OK) {
661
0
                null_map_data[row] = 1;
662
0
                res->insert_default();
663
0
                continue;
664
0
            }
665
0
            buf.clear();
666
0
            shape->encode_to(&buf);
667
0
            res->insert_data(buf.data(), buf.size());
668
0
        }
669
0
        block.replace_by_position(result,
670
0
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
671
0
        return Status::OK();
672
0
    }
Unexecuted instantiation: _ZN5doris12StGeoFromWkbINS_17StGeometryFromWKBEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
Unexecuted instantiation: _ZN5doris12StGeoFromWkbINS_13StGeomFromWKBEE7executeERNS_5BlockERKSt6vectorIjSaIjEEm
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
0
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
680
0
        DCHECK_EQ(arguments.size(), 1);
681
0
        auto return_type = block.get_data_type(result);
682
0
        auto res = ColumnString::create();
683
684
0
        auto col = block.get_by_position(arguments[0]).column;
685
0
        const auto size = col->size();
686
0
        auto null_map = ColumnUInt8::create(size, 0);
687
0
        auto& null_map_data = null_map->get_data();
688
0
        std::unique_ptr<GeoShape> shape;
689
690
0
        for (int row = 0; row < size; ++row) {
691
0
            auto shape_value = col->get_data_at(row);
692
0
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
693
0
            if (!shape) {
694
0
                null_map_data[row] = 1;
695
0
                res->insert_default();
696
0
                continue;
697
0
            }
698
699
0
            std::string binary = GeoShape::as_binary(shape.get());
700
0
            if (binary.empty()) {
701
0
                null_map_data[row] = 1;
702
0
                res->insert_default();
703
0
                continue;
704
0
            }
705
0
            res->insert_data(binary.data(), binary.size());
706
0
        }
707
708
0
        block.replace_by_position(result,
709
0
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
710
0
        return Status::OK();
711
0
    }
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
0
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
719
0
        DCHECK_EQ(arguments.size(), 1);
720
0
        auto return_type = block.get_data_type(result);
721
722
0
        auto col = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
723
0
        const auto size = col->size();
724
0
        auto res = ColumnFloat64::create();
725
0
        res->reserve(size);
726
0
        auto null_map = ColumnUInt8::create(size, 0);
727
0
        auto& null_map_data = null_map->get_data();
728
729
0
        std::unique_ptr<GeoShape> shape;
730
0
        for (int row = 0; row < size; ++row) {
731
0
            auto shape_value = col->get_data_at(row);
732
0
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
733
0
            if (!shape) {
734
0
                null_map_data[row] = 1;
735
0
                res->insert_default();
736
0
                continue;
737
0
            }
738
739
0
            double length = shape->Length();
740
0
            res->insert_value(length);
741
0
        }
742
743
0
        block.replace_by_position(result,
744
0
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
745
0
        return Status::OK();
746
0
    }
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
0
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
754
0
        DCHECK_EQ(arguments.size(), 1);
755
0
        auto return_type = block.get_data_type(result);
756
757
0
        auto col = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
758
0
        const auto size = col->size();
759
0
        auto res = ColumnString::create();
760
0
        auto null_map = ColumnUInt8::create(size, 0);
761
0
        auto& null_map_data = null_map->get_data();
762
763
0
        std::unique_ptr<GeoShape> shape;
764
0
        for (int row = 0; row < size; ++row) {
765
0
            auto shape_value = col->get_data_at(row);
766
0
            shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
767
0
            if (!shape) {
768
0
                null_map_data[row] = 1;
769
0
                res->insert_default();
770
0
                continue;
771
0
            }
772
773
0
            auto geo_type = shape->GeometryType();
774
0
            res->insert_data(geo_type.data(), geo_type.size());
775
0
        }
776
777
0
        block.replace_by_position(result,
778
0
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
779
0
        return Status::OK();
780
0
    }
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
0
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
789
0
        DCHECK_EQ(arguments.size(), 2);
790
0
        auto return_type = block.get_data_type(result);
791
0
        const auto& [left_column, left_const] =
792
0
                unpack_if_const(block.get_by_position(arguments[0]).column);
793
0
        const auto& [right_column, right_const] =
794
0
                unpack_if_const(block.get_by_position(arguments[1]).column);
795
796
0
        const auto size = std::max(left_column->size(), right_column->size());
797
798
0
        auto res = ColumnFloat64::create();
799
0
        res->reserve(size);
800
0
        auto null_map = ColumnUInt8::create(size, 0);
801
0
        auto& null_map_data = null_map->get_data();
802
803
0
        if (left_const) {
804
0
            const_vector(left_column, right_column, res, null_map_data, size);
805
0
        } else if (right_const) {
806
0
            vector_const(left_column, right_column, res, null_map_data, size);
807
0
        } else {
808
0
            vector_vector(left_column, right_column, res, null_map_data, size);
809
0
        }
810
0
        block.replace_by_position(result,
811
0
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
812
0
        return Status::OK();
813
0
    }
814
815
private:
816
0
    static bool decode_shape(const StringRef& value, std::unique_ptr<GeoShape>& shape) {
817
0
        shape = GeoShape::from_encoded(value.data, value.size);
818
0
        return static_cast<bool>(shape);
819
0
    }
820
821
    static void loop_do(StringRef& lhs_value, StringRef& rhs_value,
822
                        std::vector<std::unique_ptr<GeoShape>>& shapes,
823
0
                        ColumnFloat64::MutablePtr& res, NullMap& null_map, int row) {
824
0
        StringRef* strs[2] = {&lhs_value, &rhs_value};
825
0
        for (int i = 0; i < 2; ++i) {
826
0
            if (!decode_shape(*strs[i], shapes[i])) {
827
0
                null_map[row] = 1;
828
0
                res->insert_default();
829
0
                return;
830
0
            }
831
0
        }
832
0
        double distance = shapes[0]->Distance(shapes[1].get());
833
0
        if (UNLIKELY(distance < 0)) {
834
0
            null_map[row] = 1;
835
0
            res->insert_default();
836
0
            return;
837
0
        }
838
0
        res->insert_value(distance);
839
0
    }
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
0
                              const size_t size) {
910
0
        const auto* left_string = assert_cast<const ColumnString*>(left_column.get());
911
0
        const auto* right_string = assert_cast<const ColumnString*>(right_column.get());
912
913
0
        std::vector<std::unique_ptr<GeoShape>> shapes(2);
914
0
        for (int row = 0; row < size; ++row) {
915
0
            auto lhs_value = left_string->get_data_at(row);
916
0
            auto rhs_value = right_string->get_data_at(row);
917
0
            loop_do(lhs_value, rhs_value, shapes, res, null_map, row);
918
0
        }
919
0
    }
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
0
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
928
0
        DCHECK_EQ(arguments.size(), 1);
929
930
0
        auto col = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
931
0
        const auto size = col->size();
932
933
0
        auto res = ColumnInt64::create();
934
0
        res->reserve(size);
935
936
0
        auto null_map = ColumnUInt8::create(size, 0);
937
0
        auto& null_map_data = null_map->get_data();
938
939
0
        for (int row = 0; row < size; ++row) {
940
0
            auto value = col->get_data_at(row);
941
0
            auto shape = GeoShape::from_encoded(value.data, value.size);
942
0
            if (!shape) {
943
0
                null_map_data[row] = 1;
944
0
                res->insert_default();
945
0
                continue;
946
0
            }
947
948
0
            res->insert_value(shape->num_geometries());
949
0
        }
950
951
0
        block.replace_by_position(result,
952
0
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
953
0
        return Status::OK();
954
0
    }
955
};
956
957
struct StGeometries {
958
    static constexpr auto NAME = "st_geometries";
959
    static const size_t NUM_ARGS = 1;
960
961
0
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
962
0
        DCHECK_EQ(arguments.size(), 1);
963
964
0
        auto col = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
965
0
        const auto size = col->size();
966
967
0
        auto nested_data = ColumnString::create();
968
0
        auto offsets_col = ColumnArray::ColumnOffsets::create();
969
0
        auto& offsets = offsets_col->get_data();
970
0
        offsets.reserve(size);
971
972
0
        auto null_map = ColumnUInt8::create(size, 0);
973
0
        auto& null_map_data = null_map->get_data();
974
975
0
        size_t current_offset = 0;
976
0
        std::string buf;
977
978
0
        for (size_t row = 0; row < size; ++row) {
979
0
            auto shape_value = col->get_data_at(row);
980
0
            auto shape = GeoShape::from_encoded(shape_value.data, shape_value.size);
981
982
0
            if (!shape) {
983
0
                null_map_data[row] = 1;
984
0
                offsets.push_back(current_offset);
985
0
                continue;
986
0
            }
987
988
0
            if (shape->type() == GEO_SHAPE_MULTI_POLYGON) {
989
0
                auto* multi_polygon = static_cast<GeoMultiPolygon*>(shape.get());
990
0
                const auto& polygons = multi_polygon->polygons();
991
992
0
                if (polygons.empty()) {
993
0
                    null_map_data[row] = 1;
994
0
                    offsets.push_back(current_offset);
995
0
                    continue;
996
0
                }
997
998
0
                for (const auto& polygon : polygons) {
999
0
                    DCHECK(polygon != nullptr);
1000
0
                    buf.clear();
1001
0
                    polygon->encode_to(&buf);
1002
0
                    nested_data->insert_data(buf.data(), buf.size());
1003
0
                    ++current_offset;
1004
0
                }
1005
0
            } else {
1006
0
                nested_data->insert_data(shape_value.data, shape_value.size);
1007
0
                ++current_offset;
1008
0
            }
1009
1010
0
            offsets.push_back(current_offset);
1011
0
        }
1012
1013
0
        auto nested_null_map = ColumnUInt8::create(nested_data->size(), 0);
1014
0
        auto nested_nullable =
1015
0
                ColumnNullable::create(std::move(nested_data), std::move(nested_null_map));
1016
0
        auto array_col = ColumnArray::create(std::move(nested_nullable), std::move(offsets_col));
1017
1018
0
        block.replace_by_position(
1019
0
                result, ColumnNullable::create(std::move(array_col), std::move(null_map)));
1020
1021
0
        return Status::OK();
1022
0
    }
1023
};
1024
1025
class FunctionStGeometries final : public IFunction {
1026
public:
1027
    static constexpr auto name = StGeometries::NAME;
1028
1029
2
    static FunctionPtr create() { return std::make_shared<FunctionStGeometries>(); }
1030
1031
1
    String get_name() const override { return name; }
1032
1033
0
    size_t get_number_of_arguments() const override { return StGeometries::NUM_ARGS; }
1034
1035
1
    bool is_variadic() const override { return false; }
1036
1037
0
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
1038
0
        return make_nullable(
1039
0
                std::make_shared<DataTypeArray>(make_nullable(std::make_shared<DataTypeString>())));
1040
0
    }
1041
1042
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
1043
0
                        uint32_t result, size_t input_rows_count) const override {
1044
0
        return StGeometries::execute(block, arguments, result);
1045
0
    }
1046
};
1047
1048
struct StNumPoints {
1049
    static constexpr auto NAME = "st_numpoints";
1050
    static const size_t NUM_ARGS = 1;
1051
    using Type = DataTypeInt64;
1052
1053
0
    static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) {
1054
0
        DCHECK_EQ(arguments.size(), 1);
1055
1056
0
        auto col = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
1057
0
        const auto size = col->size();
1058
1059
0
        auto res = ColumnInt64::create();
1060
0
        res->reserve(size);
1061
1062
0
        auto null_map = ColumnUInt8::create(size, 0);
1063
0
        auto& null_map_data = null_map->get_data();
1064
1065
0
        for (int row = 0; row < size; ++row) {
1066
0
            auto value = col->get_data_at(row);
1067
0
            auto shape = GeoShape::from_encoded(value.data, value.size);
1068
0
            if (!shape) {
1069
0
                null_map_data[row] = 1;
1070
0
                res->insert_default();
1071
0
                continue;
1072
0
            }
1073
1074
0
            res->insert_value(shape->num_points());
1075
0
        }
1076
1077
0
        block.replace_by_position(result,
1078
0
                                  ColumnNullable::create(std::move(res), std::move(null_map)));
1079
0
        return Status::OK();
1080
0
    }
1081
};
1082
1083
1
void register_function_geo(SimpleFunctionFactory& factory) {
1084
1
    factory.register_function<GeoFunction<StPoint>>();
1085
1
    factory.register_function<GeoFunction<StAsText<StAsWktName>>>();
1086
1
    factory.register_function<GeoFunction<StAsText<StAsTextName>>>();
1087
1
    factory.register_function<GeoFunction<StX>>();
1088
1
    factory.register_function<GeoFunction<StY>>();
1089
1
    factory.register_function<GeoFunction<StDistanceSphere>>();
1090
1
    factory.register_function<GeoFunction<StAngleSphere>>();
1091
1
    factory.register_function<GeoFunction<StAngle>>();
1092
1
    factory.register_function<GeoFunction<StAzimuth>>();
1093
1
    factory.register_function<GeoFunction<StRelationFunction<StContainsFunc>>>();
1094
1
    factory.register_function<GeoFunction<StRelationFunction<StIntersectsFunc>>>();
1095
1
    factory.register_function<GeoFunction<StRelationFunction<StDisjointFunc>>>();
1096
1
    factory.register_function<GeoFunction<StRelationFunction<StTouchesFunc>>>();
1097
1
    factory.register_function<GeoFunction<StCircle>>();
1098
1
    factory.register_function<GeoFunction<StGeoFromText<StGeometryFromText>>>();
1099
1
    factory.register_function<GeoFunction<StGeoFromText<StGeomFromText>>>();
1100
1
    factory.register_function<GeoFunction<StGeoFromText<StLineFromText>>>();
1101
1
    factory.register_function<GeoFunction<StGeoFromText<StLineStringFromText>>>();
1102
1
    factory.register_function<GeoFunction<StGeoFromText<StPolygon>>>();
1103
1
    factory.register_function<GeoFunction<StGeoFromText<StPolygonFromText>>>();
1104
1
    factory.register_function<GeoFunction<StGeoFromText<StPolyFromText>>>();
1105
1
    factory.register_function<GeoFunction<StAreaSquareMeters>>();
1106
1
    factory.register_function<GeoFunction<StAreaSquareKm>>();
1107
1
    factory.register_function<GeoFunction<StGeoFromWkb<StGeometryFromWKB>>>();
1108
1
    factory.register_function<GeoFunction<StGeoFromWkb<StGeomFromWKB>>>();
1109
1
    factory.register_function<GeoFunction<StAsBinary>>();
1110
1
    factory.register_function<GeoFunction<StLength>>();
1111
1
    factory.register_function<GeoFunction<StGeometryType>>();
1112
1
    factory.register_function<GeoFunction<StDistance>>();
1113
1
    factory.register_function<GeoFunction<StNumGeometries>>();
1114
1
    factory.register_function<GeoFunction<StNumPoints>>();
1115
1
    factory.register_function<FunctionStGeometries>();
1116
1
}
1117
1118
} // namespace doris