github-actions[bot] commented on code in PR #69032:
URL: https://github.com/apache/doris/pull/69032#discussion_r4269360799
##########
be/src/format_v2/parquet/native_schema_desc.cpp:
##########
@@ -844,8 +845,19 @@ std::pair<DataTypePtr, bool>
NativeFieldDescriptor::convert_to_doris_type(
tparquet::LogicalType logicalType, bool nullable) {
std::pair<DataTypePtr, bool> ans = {std::make_shared<DataTypeNothing>(),
false};
bool& is_type_compatibility = ans.second;
- if (logicalType.__isset.STRING || logicalType.__isset.ENUM ||
logicalType.__isset.JSON ||
- logicalType.__isset.BSON) {
+ if (logicalType.__isset.GEOMETRY) {
+ const std::string crs =
+ logicalType.GEOMETRY.__isset.crs ? logicalType.GEOMETRY.crs :
"OGC:CRS84";
+ ans.first = std::make_shared<DataTypeSpatial>(TYPE_GEOMETRY, crs);
Review Comment:
[P1] Preserve nullability when constructing spatial file types
For an OPTIONAL annotated GEOMETRY/GEOGRAPHY field, these branches ignore
`nullable` and return a bare `DataTypeSpatial`. `build_native_node_schema`
consequently sets `nullable_definition_level` to 0. The public schema is
wrapped as Nullable, so `COUNT(shape)` pushdown remains admissible, but
`count_loaded_non_null_values` counts NULL definition level 0 as a value. An
annotated Iceberg column containing `[POINT(1 2), NULL]` therefore returns 2
instead of 1 with FileScannerV2 and COUNT pushdown enabled. Honor `nullable`
here and in the parallel v1 branches, and cover COUNT on actual optional
spatial files.
##########
fe/fe-type/src/main/java/org/apache/doris/catalog/PrimitiveType.java:
##########
@@ -83,7 +83,9 @@ public enum PrimitiveType {
VARIANT("VARIANT", 24, TPrimitiveType.VARIANT, false),
TEMPLATE("TEMPLATE", -1, TPrimitiveType.INVALID_TYPE, false),
// Unsupported scalar types.
- BINARY("BINARY", -1, TPrimitiveType.BINARY, false);
+ BINARY("BINARY", -1, TPrimitiveType.BINARY, false),
+ GEOMETRY("GEOMETRY", 16, TPrimitiveType.GEOMETRY, false),
Review Comment:
[P2] Mark spatial MySQL results as binary WKB
These new types inherit the Varbinary SerDe and send raw WKB, but
`toMysqlType` falls through to `MYSQL_TYPE_STRING` and `MysqlSerializer` only
assigns binary charset/flags to VARBINARY. Thus `SELECT
ST_GeometryFromWKBTyped('0101000000000000000000F03F0000000000000040')`
advertises UTF-8 text containing bytes `F0 3F`; default Unicode PyMySQL
decoding raises `UnicodeDecodeError` instead of returning the value. Its
[result
decoder](https://github.com/PyMySQL/PyMySQL/blob/main/pymysql/connections.py)
uses the advertised charset to decide whether to decode bytes. Extend spatial
result metadata to the existing binary contract, including charset 63, with
direct-result coverage for both kinds.
##########
fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java:
##########
@@ -5391,6 +5382,21 @@ public DataType
visitAggStateDataType(AggStateDataTypeContext ctx) {
});
}
+ @Override
+ public DataType visitSpatialDataType(SpatialDataTypeContext ctx) {
+ return ParserUtils.withOrigin(ctx, () -> {
+ String crs = ctx.crs == null ? "OGC:CRS84" :
stripQuotes(ctx.crs.getText());
Review Comment:
[P2] Unescape spatial parameters as SQL string literals
`stripQuotes` removes only delimiters, whereas `ScalarType.toSql` escapes
apostrophes by doubling them. A CRS such as `projjson:custom'crs` renders as
`GEOMETRY('projjson:custom''crs')` and reparses with two apostrophes, changing
CRS identity and the referenced property; SHOW CREATE/recreate doubles it
again. The [Iceberg CRS contract](https://iceberg.apache.org/spec/#crs) permits
unique strings and table-property references. Use the normal
`SqlLiteralUtils.parseStringLiteral` path, as `visitStringLiteral` does, and
cover an escaped CRS round trip.
##########
be/src/exprs/function/geo/functions_geo.cpp:
##########
@@ -360,7 +527,7 @@ struct StAzimuth {
}
double angle = 0;
- if (!GeoPoint::ComputeAzimuth(&point1, &point2, &angle)) {
+ if (!GeoPoint::ComputeAzimuth(pt1, pt2, &angle)) {
Review Comment:
[P2] Use a correct spherical bearing path for typed Geography
New Geography points reach `ComputeAzimuth -> ComputeAngle`, which calls
`S2LatLng::FromDegrees(x,y)` although x is longitude and [S2 expects latitude
first](https://github.com/google/s2geometry/blob/master/src/s2/s2latlng.h).
This also turns `north(0,90)` into latitude 0/longitude 90. For `POINT(10 45)
-> POINT(10 46)`, the source formula yields about 0.173449 radians instead of
due north's 0. Simply swapping axes still leaves `b-a` opposite the [clockwise
bearing
convention](https://doris.apache.org/docs/4.x/sql-manual/sql-functions/scalar-functions/spatial-functions/st-azimuth/):
east `(0 0)->(1 0)` would yield 3pi/2 instead of pi/2. Use the correct
spherical clockwise bearing/angle computation and test non-equatorial cardinal
directions; `ST_Angle` shares this helper.
##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StWithin.java:
##########
@@ -70,6 +70,12 @@ public List<FunctionSignature> getSignatures() {
return SIGNATURES;
}
+ @Override
+ public FunctionSignature searchSignature(List<FunctionSignature>
signatures) {
+ FunctionSignature signature =
SpatialFunctionSignature.binary(child(0), child(1), BooleanType.INSTANCE);
Review Comment:
[P2] Reject unimplemented Geography containment pairs
The new signature admits identical nonempty Geography points, but
`ST_Within(p,p)` reaches `GeoShape::within -> rhs->contains(this)`; `GeoPoint`
and `GeoLine` do not override `contains`, so the base method returns false
without testing containment. Thus `ST_Intersects(p,p)` is true while
`ST_Within`/`ST_Contains(p,p)` are false, and the new golden locks in that
result. [Within is reflexive](https://postgis.net/docs/ST_Within.html), and the
PR requires unsupported combinations to fail explicitly. Implement the
supported typed pairs, or return `NotSupported` for unimplemented combinations,
and correct the self-point golden.
##########
be/src/exprs/function/geo/functions_geo.cpp:
##########
@@ -507,24 +692,32 @@ struct StRelationFunction {
static Status execute(Block& block, const ColumnNumbers& arguments, size_t
result) {
DCHECK_EQ(arguments.size(), 2);
auto return_type = block.get_data_type(result);
- auto left_col =
ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[0]).column);
- auto right_col =
-
ColumnView<TYPE_STRING>::create(block.get_by_position(arguments[1]).column);
+ const auto& left_col = block.get_by_position(arguments[0]).column;
+ const auto& right_col = block.get_by_position(arguments[1]).column;
+ const auto& left_type = block.get_data_type(arguments[0]);
+ const auto& right_type = block.get_data_type(arguments[1]);
+ RETURN_IF_ERROR(validate_geography_semantics(left_type, NAME));
+ RETURN_IF_ERROR(validate_geography_semantics(right_type, NAME));
- const auto size = left_col.size();
+ const auto size = left_col->size();
auto res = ColumnUInt8::create(size, 0);
auto null_map = ColumnUInt8::create(size, 0);
auto& null_map_data = null_map->get_data();
- for (int row = 0; row < size; ++row) {
- auto lhs_value = left_col.value_at(row);
- auto rhs_value = right_col.value_at(row);
-
- std::unique_ptr<GeoShape> shape1(
- GeoShape::from_encoded(lhs_value.data, lhs_value.size));
- std::unique_ptr<GeoShape> shape2(
- GeoShape::from_encoded(rhs_value.data, rhs_value.size));
+ for (size_t row = 0; row < size; ++row) {
+ // Propagate NULL before using nested placeholders; a NULL
geometry has an
+ // empty payload, not a WKB shape.
+ if (any_geo_argument_is_null(block, arguments, row)) {
+ null_map_data[row] = 1;
+ continue;
+ }
+ std::unique_ptr<GeoShape> shape1;
+ RETURN_IF_ERROR(
+ decode_calculation_shape(left_col->get_data_at(row),
left_type, &shape1, NAME));
Review Comment:
[P2] Use spherical predicates throughout typed Geography dispatch
This newly accepts `GEOGRAPHY(OGC:CRS84, spherical)`, but
`GeoLine::intersects` projects latitude/longitude onto a Cartesian segment
using only vertices 0/1. Accepted `LINESTRING(170 0,-170 0)` and `POINT(180 0)`
give distance 10 and `ST_Intersects=false`/`ST_Disjoint=true`, although the
point lies on the spherical date-line edge. Later line segments are also
ignored. The parallel polygon/point helper uses planar ray crossing: a polygon
spanning longitudes +/-170 and latitudes +/-10 falsely intersects `POINT(0 0)`
instead of respecting its small spherical interior at the date line. The
[Geography
contract](https://iceberg.apache.org/spec/#edge-interpolation-algorithm)
requires geodesic edges. Use complete spherical operations across admitted
shape pairs, or explicitly reject unsupported pairs; fixing only the line
helper leaves the polygon path wrong.
##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StIntersects.java:
##########
@@ -70,6 +70,12 @@ public List<FunctionSignature> getSignatures() {
return SIGNATURES;
}
+ @Override
+ public FunctionSignature searchSignature(List<FunctionSignature>
signatures) {
+ FunctionSignature signature =
SpatialFunctionSignature.binary(child(0), child(1), BooleanType.INSTANCE);
Review Comment:
[P2] Keep an open Geography line open in polygon intersection
The new typed signature admits a default Geography polygon covering the
square `[-0.5,0.5]^2` and the disjoint open `LINESTRING(-2 0,-2 2,2 2,2 0)`.
`GeoPolygon::intersects` gets an empty S2 polyline intersection, then its
fallback loops through all vertices using `(i+1)%num_vertices`. That invents a
last-to-first edge `(2 0)->(-2 0)` across the square and returns true.
Reversing operands uses `S2Polygon::Intersects` directly and returns false.
This is separate from the planar-helper problem: the nonexistent closing edge
is wrong even with a spherical edge test. Iterate only real consecutive line
edges, reserve wraparound for polygon rings, and cover both operand orders.
##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StDisjoint.java:
##########
@@ -70,6 +70,12 @@ public List<FunctionSignature> getSignatures() {
return SIGNATURES;
}
+ @Override
+ public FunctionSignature searchSignature(List<FunctionSignature>
signatures) {
+ FunctionSignature signature =
SpatialFunctionSignature.binary(child(0), child(1), BooleanType.INSTANCE);
Review Comment:
[P2] Canonicalize equivalent Geography points for relation comparisons
The new typed overload accepts default Geography `POINT(180 0)` and
`POINT(-180 0)`, which denote the same date-line point. Both pass the inclusive
coordinate bounds, but `to_s2point` converts them without canonicalization and
`GeoPoint::intersects` compares their S2 vectors exactly. The pinned [S2
ToPoint
formula](https://github.com/google/s2geometry/blob/v0.10.0/src/s2/s2latlng.cc)
produces opposite nonzero sine roundoff at +pi/-pi, so `ST_Intersects` returns
false and `ST_Disjoint` true for these equivalent locations. This is separate
from the line/polygon planar-helper issue. Preserve raw WKB, but canonicalize
equivalent longitude/pole representations for calculations or compare positions
under spherical semantics, and cover date-line/pole aliases.
##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StAsBinary.java:
##########
@@ -68,6 +68,12 @@ public List<FunctionSignature> getSignatures() {
return SIGNATURES;
}
+ @Override
+ public FunctionSignature searchSignature(List<FunctionSignature>
signatures) {
+ FunctionSignature signature = SpatialFunctionSignature.unary(child(0),
VarcharType.SYSTEM_DEFAULT);
Review Comment:
[P2] Return a binary carrier for typed ST_AsBinary
This typed overload returns VARCHAR, while its BE branch copies raw WKB into
`ColumnString`. The recommended Flight projection `SELECT
ST_AsBinary(ST_GeometryFromWKBTyped('0101000000000000000000F03F0000000000000040'))`
therefore maps to Arrow UTF8 and appends bytes `F0 3F` unchanged. The
inspected builder path does not validate UTF8, and [PyArrow
StringScalar](https://github.com/apache/arrow/blob/apache-arrow-24.0.0/python/pyarrow/scalar.pxi)
decodes those bytes in `as_py`/`to_pylist`, raising `UnicodeDecodeError`
instead of returning WKB bytes. Spatial MySQL metadata changes cannot fix this
accessor's VARCHAR result. Give the typed overload a binary return type with
matching BE column/result handling, and cover its Arrow schema directly;
`hex(ST_AsBinary(...))` masks the defect.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]