From 9b2c1f3fa08d4af4c60c8b42a53ba566ae4a98aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Batuhan=20Ya=C4=9Fmur?= Date: Tue, 17 Mar 2026 18:47:47 +0300 Subject: [PATCH 1/2] [Feature] Add ST_CoordDim and ST_Dimension geo functions Add two new geo scalar functions: - ST_CoordDim: Returns coordinate dimension of geometry (always 2 for 2D) - ST_Dimension: Returns topological dimension (Point=0, Line=1, Polygon=2) FE: Added expression classes, registered in BuiltinScalarFunctions, added visitor methods in ScalarFunctionVisitor. BE: Added struct implementations and registered in functions_geo.cpp. --- be/src/exprs/function/geo/functions_geo.cpp | 74 ++++++++++++++++++ .../doris/catalog/BuiltinScalarFunctions.java | 4 + .../functions/scalar/StCoordDim.java | 76 +++++++++++++++++++ .../functions/scalar/StDimension.java | 76 +++++++++++++++++++ .../visitor/ScalarFunctionVisitor.java | 10 +++ 5 files changed, 240 insertions(+) create mode 100644 fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StCoordDim.java create mode 100644 fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StDimension.java diff --git a/be/src/exprs/function/geo/functions_geo.cpp b/be/src/exprs/function/geo/functions_geo.cpp index 6a191f133e542a..50ad4ff2e55bcf 100644 --- a/be/src/exprs/function/geo/functions_geo.cpp +++ b/be/src/exprs/function/geo/functions_geo.cpp @@ -778,6 +778,78 @@ struct StGeometryType { } }; +struct StCoordDim { + static constexpr auto NAME = "st_coorddim"; + static const size_t NUM_ARGS = 1; + using Type = DataTypeInt32; + static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) { + DCHECK_EQ(arguments.size(), 1); + auto col = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const(); + const auto size = col->size(); + auto res = ColumnInt32::create(); + res->reserve(size); + auto null_map = ColumnUInt8::create(size, 0); + auto& null_map_data = null_map->get_data(); + + std::unique_ptr shape; + for (int row = 0; row < size; ++row) { + auto shape_value = col->get_data_at(row); + shape = GeoShape::from_encoded(shape_value.data, shape_value.size); + if (!shape) { + null_map_data[row] = 1; + res->insert_default(); + continue; + } + // All geometries in Doris are 2D (x, y) + res->insert_value(2); + } + block.replace_by_position(result, + ColumnNullable::create(std::move(res), std::move(null_map))); + return Status::OK(); + } +}; + +struct StDimension { + static constexpr auto NAME = "st_dimension"; + static const size_t NUM_ARGS = 1; + using Type = DataTypeInt32; + static Status execute(Block& block, const ColumnNumbers& arguments, size_t result) { + DCHECK_EQ(arguments.size(), 1); + auto col = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const(); + const auto size = col->size(); + auto res = ColumnInt32::create(); + res->reserve(size); + auto null_map = ColumnUInt8::create(size, 0); + auto& null_map_data = null_map->get_data(); + + std::unique_ptr shape; + for (int row = 0; row < size; ++row) { + auto shape_value = col->get_data_at(row); + shape = GeoShape::from_encoded(shape_value.data, shape_value.size); + if (!shape) { + null_map_data[row] = 1; + res->insert_default(); + continue; + } + int dim = -1; + switch (shape->type()) { + case GEO_SHAPE_POINT: dim = 0; break; + case GEO_SHAPE_LINE_STRING: dim = 1; break; + case GEO_SHAPE_POLYGON: + case GEO_SHAPE_MULTI_POLYGON: dim = 2; break; + default: + null_map_data[row] = 1; + res->insert_default(); + continue; + } + res->insert_value(dim); + } + block.replace_by_position(result, + ColumnNullable::create(std::move(res), std::move(null_map))); + return Status::OK(); + } +}; + struct StDistance { static constexpr auto NAME = "st_distance"; static const size_t NUM_ARGS = 2; @@ -946,6 +1018,8 @@ void register_function_geo(SimpleFunctionFactory& factory) { factory.register_function>(); factory.register_function>(); factory.register_function>(); + factory.register_function>(); + factory.register_function>(); factory.register_function>(); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java index c8719dbaeb5832..022bc4d4c7d0de 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java @@ -477,6 +477,8 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.StDistanceSphere; import org.apache.doris.nereids.trees.expressions.functions.scalar.StGeomFromWKB; import org.apache.doris.nereids.trees.expressions.functions.scalar.StGeometryFromWKB; +import org.apache.doris.nereids.trees.expressions.functions.scalar.StCoordDim; +import org.apache.doris.nereids.trees.expressions.functions.scalar.StDimension; import org.apache.doris.nereids.trees.expressions.functions.scalar.StGeometryType; import org.apache.doris.nereids.trees.expressions.functions.scalar.StGeometryfromtext; import org.apache.doris.nereids.trees.expressions.functions.scalar.StGeomfromtext; @@ -1050,6 +1052,8 @@ public class BuiltinScalarFunctions implements FunctionHelper { scalar(StTouches.class, "st_touches"), scalar(StLength.class, "st_length"), scalar(StGeometryType.class, "st_geometrytype"), + scalar(StCoordDim.class, "st_coorddim"), + scalar(StDimension.class, "st_dimension"), scalar(StDistance.class, "st_distance"), scalar(StDistanceSphere.class, "st_distance_sphere"), scalar(StAngleSphere.class, "st_angle_sphere"), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StCoordDim.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StCoordDim.java new file mode 100644 index 00000000000000..fb31bb992db875 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StCoordDim.java @@ -0,0 +1,76 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.AlwaysNullable; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullLiteral; +import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'st_coorddim'. Returns the coordinate dimension of the geometry. + * For all geometries in Doris (2D), this always returns 2. + */ +public class StCoordDim extends ScalarFunction + implements UnaryExpression, ExplicitlyCastableSignature, AlwaysNullable, PropagateNullLiteral { + + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(IntegerType.INSTANCE).args(VarcharType.SYSTEM_DEFAULT) + ); + + /** + * constructor with 1 argument. + */ + public StCoordDim(Expression arg0) { + super("st_coorddim", arg0); + } + + /** constructor for withChildren and reuse signature */ + private StCoordDim(ScalarFunctionParams functionParams) { + super(functionParams); + } + + /** + * withChildren. + */ + @Override + public StCoordDim withChildren(List children) { + Preconditions.checkArgument(children.size() == 1); + return new StCoordDim(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitStCoordDim(this, context); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StDimension.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StDimension.java new file mode 100644 index 00000000000000..ad32c7cf4a9f11 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StDimension.java @@ -0,0 +1,76 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.AlwaysNullable; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullLiteral; +import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'st_dimension'. Returns the topological dimension of the geometry. + * Point = 0, Line = 1, Polygon = 2. + */ +public class StDimension extends ScalarFunction + implements UnaryExpression, ExplicitlyCastableSignature, AlwaysNullable, PropagateNullLiteral { + + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(IntegerType.INSTANCE).args(VarcharType.SYSTEM_DEFAULT) + ); + + /** + * constructor with 1 argument. + */ + public StDimension(Expression arg0) { + super("st_dimension", arg0); + } + + /** constructor for withChildren and reuse signature */ + private StDimension(ScalarFunctionParams functionParams) { + super(functionParams); + } + + /** + * withChildren. + */ + @Override + public StDimension withChildren(List children) { + Preconditions.checkArgument(children.size() == 1); + return new StDimension(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitStDimension(this, context); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java index c32d2157d50c50..a2273eab31fff7 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java @@ -498,6 +498,8 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.StDistanceSphere; import org.apache.doris.nereids.trees.expressions.functions.scalar.StGeomFromWKB; import org.apache.doris.nereids.trees.expressions.functions.scalar.StGeometryFromWKB; +import org.apache.doris.nereids.trees.expressions.functions.scalar.StCoordDim; +import org.apache.doris.nereids.trees.expressions.functions.scalar.StDimension; import org.apache.doris.nereids.trees.expressions.functions.scalar.StGeometryType; import org.apache.doris.nereids.trees.expressions.functions.scalar.StGeometryfromtext; import org.apache.doris.nereids.trees.expressions.functions.scalar.StGeomfromtext; @@ -2368,6 +2370,14 @@ default R visitStGeometryType(StGeometryType stGeometryType, C context) { return visitScalarFunction(stGeometryType, context); } + default R visitStCoordDim(StCoordDim stCoordDim, C context) { + return visitScalarFunction(stCoordDim, context); + } + + default R visitStDimension(StDimension stDimension, C context) { + return visitScalarFunction(stDimension, context); + } + default R visitStDistance(StDistance stDistance, C context) { return visitScalarFunction(stDistance, context); } From a1ca73849b4794fc0c679959658fc46fda9e50cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Batuhan=20Ya=C4=9Fmur?= Date: Tue, 17 Mar 2026 19:28:27 +0300 Subject: [PATCH 2/2] [Fix] Apply clang-format to functions_geo.cpp --- be/src/exprs/function/geo/functions_geo.cpp | 24 +++++++++++++-------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/be/src/exprs/function/geo/functions_geo.cpp b/be/src/exprs/function/geo/functions_geo.cpp index 50ad4ff2e55bcf..a2344875a885a3 100644 --- a/be/src/exprs/function/geo/functions_geo.cpp +++ b/be/src/exprs/function/geo/functions_geo.cpp @@ -833,14 +833,20 @@ struct StDimension { } int dim = -1; switch (shape->type()) { - case GEO_SHAPE_POINT: dim = 0; break; - case GEO_SHAPE_LINE_STRING: dim = 1; break; - case GEO_SHAPE_POLYGON: - case GEO_SHAPE_MULTI_POLYGON: dim = 2; break; - default: - null_map_data[row] = 1; - res->insert_default(); - continue; + case GEO_SHAPE_POINT: + dim = 0; + break; + case GEO_SHAPE_LINE_STRING: + dim = 1; + break; + case GEO_SHAPE_POLYGON: + case GEO_SHAPE_MULTI_POLYGON: + dim = 2; + break; + default: + null_map_data[row] = 1; + res->insert_default(); + continue; } res->insert_value(dim); } @@ -1018,7 +1024,7 @@ void register_function_geo(SimpleFunctionFactory& factory) { factory.register_function>(); factory.register_function>(); factory.register_function>(); - factory.register_function>(); + factory.register_function>(); factory.register_function>(); factory.register_function>(); }