Coverage Report

Created: 2026-03-12 14:13

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
87
        std::stringstream hex_stream;
40
87
        hex_stream << std::hex << std::setfill('0');
41
87
        result_stream.seekg(0);
42
87
        unsigned char c;
43
5.80k
        while (result_stream.read(reinterpret_cast<char*>(&c), 1)) {
44
5.71k
            hex_stream << std::setw(2) << static_cast<int>(c);
45
5.71k
        }
46
        //for compatibility with postgres
47
87
        *result = "\\x" + hex_stream.str();
48
87
        return true;
49
87
    }
50
0
    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
52
bool toBinary::writeGeoPolygon(doris::GeoPolygon* polygon, ToBinaryContext* ctx) {
88
52
    writeByteOrder(ctx);
89
52
    writeGeometryType(wkbType::wkbPolygon, ctx);
90
52
    writeInt(polygon->numLoops(), ctx);
91
52
    std::unique_ptr<GeoCoordinateListList> coordss(polygon->to_coords());
92
93
104
    for (int i = 0; i < coordss->list.size(); ++i) {
94
52
        writeCoordinateList(*coordss->list[i], true, ctx);
95
52
    }
96
52
    return true;
97
52
}
98
99
87
void toBinary::writeByteOrder(ToBinaryContext* ctx) {
100
87
    ctx->byteOrder = getMachineByteOrder();
101
87
    if (ctx->byteOrder == 1) {
102
87
        ctx->buf[0] = byteOrder::wkbNDR;
103
87
    } else {
104
0
        ctx->buf[0] = byteOrder::wkbXDR;
105
0
    }
106
107
87
    ctx->outStream->write(reinterpret_cast<char*>(ctx->buf), 1);
108
87
}
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
87
                                   ToBinaryContext* ctx) {
121
87
    std::size_t size = coords.list.size();
122
123
87
    if (sized) {
124
56
        writeInt(static_cast<int>(size), ctx);
125
56
    }
126
390
    for (std::size_t i = 0; i < size; i++) {
127
303
        GeoCoordinate coord = coords.list[i];
128
303
        writeCoordinate(coord, ctx);
129
303
    }
130
87
}
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