Coverage Report

Created: 2026-03-18 12:42

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