Coverage Report

Created: 2026-04-01 12:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exprs/function/geo/geo_tobinary.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/geo_tobinary.h"
19
20
#include <cstddef>
21
#include <sstream>
22
#include <vector>
23
24
#include "exprs/function/geo/ByteOrderValues.h"
25
#include "exprs/function/geo/geo_common.h"
26
#include "exprs/function/geo/geo_tobinary_type.h"
27
#include "exprs/function/geo/geo_types.h"
28
#include "exprs/function/geo/machine.h"
29
#include "exprs/function/geo/wkt_parse_type.h"
30
#include "iomanip"
31
32
namespace doris {
33
34
81
bool toBinary::geo_tobinary(GeoShape* shape, std::string* result) {
35
81
    ToBinaryContext ctx;
36
81
    std::stringstream result_stream;
37
81
    ctx.outStream = &result_stream;
38
81
    if (toBinary::write(shape, &ctx)) {
39
81
        std::stringstream hex_stream;
40
81
        hex_stream << std::hex << std::setfill('0');
41
81
        result_stream.seekg(0);
42
81
        unsigned char c;
43
5.45k
        while (result_stream.read(reinterpret_cast<char*>(&c), 1)) {
44
5.37k
            hex_stream << std::setw(2) << static_cast<int>(c);
45
5.37k
        }
46
        //for compatibility with postgres
47
81
        *result = "\\x" + hex_stream.str();
48
81
        return true;
49
81
    }
50
0
    return false;
51
81
}
52
53
81
bool toBinary::write(GeoShape* shape, ToBinaryContext* ctx) {
54
81
    switch (shape->type()) {
55
29
    case GEO_SHAPE_POINT: {
56
29
        return writeGeoPoint((GeoPoint*)(shape), ctx);
57
0
    }
58
2
    case GEO_SHAPE_LINE_STRING: {
59
2
        return writeGeoLine((GeoLine*)(shape), ctx);
60
0
    }
61
50
    case GEO_SHAPE_POLYGON: {
62
50
        return writeGeoPolygon((GeoPolygon*)(shape), ctx);
63
0
    }
64
0
    default:
65
0
        return false;
66
81
    }
67
81
}
68
69
29
bool toBinary::writeGeoPoint(GeoPoint* point, ToBinaryContext* ctx) {
70
29
    writeByteOrder(ctx);
71
29
    writeGeometryType(wkbType::wkbPoint, ctx);
72
29
    GeoCoordinateList p = point->to_coords();
73
74
29
    writeCoordinateList(p, false, ctx);
75
29
    return true;
76
29
}
77
78
2
bool toBinary::writeGeoLine(GeoLine* line, ToBinaryContext* ctx) {
79
2
    writeByteOrder(ctx);
80
2
    writeGeometryType(wkbType::wkbLine, ctx);
81
2
    GeoCoordinateList p = line->to_coords();
82
83
2
    writeCoordinateList(p, true, ctx);
84
2
    return true;
85
2
}
86
87
50
bool toBinary::writeGeoPolygon(doris::GeoPolygon* polygon, ToBinaryContext* ctx) {
88
50
    writeByteOrder(ctx);
89
50
    writeGeometryType(wkbType::wkbPolygon, ctx);
90
50
    writeInt(polygon->numLoops(), ctx);
91
50
    std::unique_ptr<GeoCoordinateListList> coordss(polygon->to_coords());
92
93
100
    for (int i = 0; i < coordss->list.size(); ++i) {
94
50
        writeCoordinateList(*coordss->list[i], true, ctx);
95
50
    }
96
50
    return true;
97
50
}
98
99
81
void toBinary::writeByteOrder(ToBinaryContext* ctx) {
100
81
    ctx->byteOrder = getMachineByteOrder();
101
81
    if (ctx->byteOrder == 1) {
102
81
        ctx->buf[0] = byteOrder::wkbNDR;
103
81
    } else {
104
0
        ctx->buf[0] = byteOrder::wkbXDR;
105
0
    }
106
107
81
    ctx->outStream->write(reinterpret_cast<char*>(ctx->buf), 1);
108
81
}
109
110
81
void toBinary::writeGeometryType(int typeId, ToBinaryContext* ctx) {
111
81
    writeInt(typeId, ctx);
112
81
}
113
114
183
void toBinary::writeInt(int val, ToBinaryContext* ctx) {
115
183
    ByteOrderValues::putInt(val, ctx->buf, ctx->byteOrder);
116
183
    ctx->outStream->write(reinterpret_cast<char*>(ctx->buf), 4);
117
183
}
118
119
void toBinary::writeCoordinateList(const GeoCoordinateList& coords, bool sized,
120
81
                                   ToBinaryContext* ctx) {
121
81
    std::size_t size = coords.list.size();
122
123
81
    if (sized) {
124
52
        writeInt(static_cast<int>(size), ctx);
125
52
    }
126
366
    for (std::size_t i = 0; i < size; i++) {
127
285
        GeoCoordinate coord = coords.list[i];
128
285
        writeCoordinate(coord, ctx);
129
285
    }
130
81
}
131
132
285
void toBinary::writeCoordinate(GeoCoordinate& coords, ToBinaryContext* ctx) {
133
285
    ByteOrderValues::putDouble(coords.x, ctx->buf, ctx->byteOrder);
134
285
    ctx->outStream->write(reinterpret_cast<char*>(ctx->buf), 8);
135
285
    ByteOrderValues::putDouble(coords.y, ctx->buf, ctx->byteOrder);
136
285
    ctx->outStream->write(reinterpret_cast<char*>(ctx->buf), 8);
137
285
}
138
139
} // namespace doris