diff --git a/be/src/exprs/function/geo/functions_geo.cpp b/be/src/exprs/function/geo/functions_geo.cpp index 6a191f133e542a..b8fce612d24cfb 100644 --- a/be/src/exprs/function/geo/functions_geo.cpp +++ b/be/src/exprs/function/geo/functions_geo.cpp @@ -28,8 +28,10 @@ #include "core/block/block.h" #include "core/block/column_with_type_and_name.h" #include "core/column/column.h" +#include "core/column/column_array.h" #include "core/column/column_execute_util.h" #include "core/column/column_nullable.h" +#include "core/data_type/data_type_array.h" #include "core/data_type/data_type_nullable.h" #include "core/data_type/data_type_number.h" #include "core/data_type/data_type_string.h" @@ -917,6 +919,167 @@ struct StDistance { } }; +struct StNumGeometries { + static constexpr auto NAME = "st_numgeometries"; + static const size_t NUM_ARGS = 1; + using Type = DataTypeInt64; + + 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 = ColumnInt64::create(); + res->reserve(size); + + auto null_map = ColumnUInt8::create(size, 0); + auto& null_map_data = null_map->get_data(); + + for (int row = 0; row < size; ++row) { + auto value = col->get_data_at(row); + auto shape = GeoShape::from_encoded(value.data, value.size); + if (!shape) { + null_map_data[row] = 1; + res->insert_default(); + continue; + } + + res->insert_value(shape->num_geometries()); + } + + block.replace_by_position(result, + ColumnNullable::create(std::move(res), std::move(null_map))); + return Status::OK(); + } +}; + +struct StGeometries { + static constexpr auto NAME = "st_geometries"; + static const size_t NUM_ARGS = 1; + + 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 nested_data = ColumnString::create(); + auto offsets_col = ColumnArray::ColumnOffsets::create(); + auto& offsets = offsets_col->get_data(); + offsets.reserve(size); + + auto null_map = ColumnUInt8::create(size, 0); + auto& null_map_data = null_map->get_data(); + + size_t current_offset = 0; + std::string buf; + + for (size_t row = 0; row < size; ++row) { + auto shape_value = col->get_data_at(row); + auto shape = GeoShape::from_encoded(shape_value.data, shape_value.size); + + if (!shape) { + null_map_data[row] = 1; + offsets.push_back(current_offset); + continue; + } + + if (shape->type() == GEO_SHAPE_MULTI_POLYGON) { + auto* multi_polygon = static_cast(shape.get()); + const auto& polygons = multi_polygon->polygons(); + + if (polygons.empty()) { + null_map_data[row] = 1; + offsets.push_back(current_offset); + continue; + } + + for (const auto& polygon : polygons) { + DCHECK(polygon != nullptr); + buf.clear(); + polygon->encode_to(&buf); + nested_data->insert_data(buf.data(), buf.size()); + ++current_offset; + } + } else { + nested_data->insert_data(shape_value.data, shape_value.size); + ++current_offset; + } + + offsets.push_back(current_offset); + } + + auto nested_null_map = ColumnUInt8::create(nested_data->size(), 0); + auto nested_nullable = + ColumnNullable::create(std::move(nested_data), std::move(nested_null_map)); + auto array_col = ColumnArray::create(std::move(nested_nullable), std::move(offsets_col)); + + block.replace_by_position( + result, ColumnNullable::create(std::move(array_col), std::move(null_map))); + + return Status::OK(); + } +}; + +class FunctionStGeometries final : public IFunction { +public: + static constexpr auto name = StGeometries::NAME; + + static FunctionPtr create() { return std::make_shared(); } + + String get_name() const override { return name; } + + size_t get_number_of_arguments() const override { return StGeometries::NUM_ARGS; } + + bool is_variadic() const override { return false; } + + DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { + return make_nullable( + std::make_shared(make_nullable(std::make_shared()))); + } + + Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, + uint32_t result, size_t input_rows_count) const override { + return StGeometries::execute(block, arguments, result); + } +}; + +struct StNumPoints { + static constexpr auto NAME = "st_numpoints"; + static const size_t NUM_ARGS = 1; + using Type = DataTypeInt64; + + 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 = ColumnInt64::create(); + res->reserve(size); + + auto null_map = ColumnUInt8::create(size, 0); + auto& null_map_data = null_map->get_data(); + + for (int row = 0; row < size; ++row) { + auto value = col->get_data_at(row); + auto shape = GeoShape::from_encoded(value.data, value.size); + if (!shape) { + null_map_data[row] = 1; + res->insert_default(); + continue; + } + + res->insert_value(shape->num_points()); + } + + block.replace_by_position(result, + ColumnNullable::create(std::move(res), std::move(null_map))); + return Status::OK(); + } +}; + void register_function_geo(SimpleFunctionFactory& factory) { factory.register_function>(); factory.register_function>>(); @@ -947,6 +1110,9 @@ void register_function_geo(SimpleFunctionFactory& factory) { factory.register_function>(); factory.register_function>(); factory.register_function>(); + factory.register_function>(); + factory.register_function>(); + factory.register_function(); } } // namespace doris diff --git a/be/src/exprs/function/geo/geo_types.cpp b/be/src/exprs/function/geo/geo_types.cpp index 03dd5c080c398a..c084e5e272de25 100644 --- a/be/src/exprs/function/geo/geo_types.cpp +++ b/be/src/exprs/function/geo/geo_types.cpp @@ -1929,6 +1929,27 @@ double GeoMultiPolygon::Distance(const GeoShape* rhs) const { return (min_distance == std::numeric_limits::max()) ? -1.0 : min_distance; } +int GeoPolygon::num_points() const { + int total = 0; + for (int i = 0; i < numLoops(); ++i) { + auto* loop = getLoop(i); + DCHECK(loop != nullptr); + total += loop->num_vertices() + 1; + } + return total; +} + +int GeoMultiPolygon::num_points() const { + int total = 0; + for (const auto& polygon : _polygons) { + DCHECK(polygon != nullptr); + int point_count = polygon->num_points(); + DCHECK_GE(point_count, 0); + total += point_count; + } + return total; +} + double GeoCircle::Distance(const GeoShape* rhs) const { // Both rhs and self are guaranteed to be valid by StDistance (functions_geo.cpp) double circle_radius = S2Earth::ToMeters(_cap->radius()); diff --git a/be/src/exprs/function/geo/geo_types.h b/be/src/exprs/function/geo/geo_types.h index f6d8e04e0182fa..146ebf2a847603 100644 --- a/be/src/exprs/function/geo/geo_types.h +++ b/be/src/exprs/function/geo/geo_types.h @@ -81,6 +81,9 @@ class GeoShape { static bool ComputeArea(GeoShape* rhs, double* angle, std::string square_unit); + virtual int num_geometries() const { return 1; } + virtual int num_points() const { return -1; } + protected: virtual void encode(std::string* buf) = 0; virtual bool decode(const void* data, size_t size) = 0; @@ -125,6 +128,9 @@ class GeoPoint : public GeoShape { double x() const; double y() const; + int num_geometries() const override { return 1; } + int num_points() const override { return 1; } + protected: void encode(std::string* buf) override; bool decode(const void* data, size_t size) override; @@ -161,6 +167,9 @@ class GeoLine : public GeoShape { int numPoint() const; const S2Point* getPoint(int i) const; + int num_geometries() const override { return 1; } + int num_points() const override { return numPoint(); } + protected: void encode(std::string* buf) override; bool decode(const void* data, size_t size) override; @@ -199,6 +208,9 @@ class GeoPolygon : public GeoShape { double Distance(const GeoShape* rhs) const override; S2Loop* getLoop(int i) const; + int num_geometries() const override { return 1; } + int num_points() const override; + protected: void encode(std::string* buf) override; bool decode(const void* data, size_t size) override; @@ -232,6 +244,9 @@ class GeoMultiPolygon : public GeoShape { double Length() const override; double Distance(const GeoShape* rhs) const override; + int num_geometries() const override { return static_cast(_polygons.size()); } + int num_points() const override; + protected: void encode(std::string* buf) override; bool decode(const void* data, size_t size) override; 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 dd35df6831507a..6becce0a15d91e 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 @@ -479,6 +479,7 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.StDistance; 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.StGeometries; import org.apache.doris.nereids.trees.expressions.functions.scalar.StGeometryFromWKB; import org.apache.doris.nereids.trees.expressions.functions.scalar.StGeometryType; import org.apache.doris.nereids.trees.expressions.functions.scalar.StGeometryfromtext; @@ -487,6 +488,8 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.StLength; import org.apache.doris.nereids.trees.expressions.functions.scalar.StLinefromtext; import org.apache.doris.nereids.trees.expressions.functions.scalar.StLinestringfromtext; +import org.apache.doris.nereids.trees.expressions.functions.scalar.StNumGeometries; +import org.apache.doris.nereids.trees.expressions.functions.scalar.StNumPoints; import org.apache.doris.nereids.trees.expressions.functions.scalar.StPoint; import org.apache.doris.nereids.trees.expressions.functions.scalar.StPolyfromtext; import org.apache.doris.nereids.trees.expressions.functions.scalar.StPolygon; @@ -1056,6 +1059,9 @@ public class BuiltinScalarFunctions implements FunctionHelper { scalar(StTouches.class, "st_touches"), scalar(StLength.class, "st_length"), scalar(StGeometryType.class, "st_geometrytype"), + scalar(StNumGeometries.class, "st_numgeometries"), + scalar(StGeometries.class, "st_geometries"), + scalar(StNumPoints.class, "st_numpoints"), 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/StGeometries.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StGeometries.java new file mode 100644 index 00000000000000..e48d6919702e63 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StGeometries.java @@ -0,0 +1,69 @@ +// 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.ArrayType; +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_geometries'. + */ +public class StGeometries extends ScalarFunction + implements UnaryExpression, ExplicitlyCastableSignature, AlwaysNullable, PropagateNullLiteral { + + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(ArrayType.of(VarcharType.SYSTEM_DEFAULT, true)) + .args(VarcharType.SYSTEM_DEFAULT) + ); + + public StGeometries(Expression arg0) { + super("st_geometries", arg0); + } + + private StGeometries(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public StGeometries withChildren(List children) { + Preconditions.checkArgument(children.size() == 1); + return new StGeometries(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitStGeometries(this, context); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StNumGeometries.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StNumGeometries.java new file mode 100644 index 00000000000000..0dcdb2c8a2703f --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StNumGeometries.java @@ -0,0 +1,68 @@ +// 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.BigIntType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * Scalar function 'st_numgeometries'. This class is generated by GenerateFunction. + */ +public class StNumGeometries extends ScalarFunction + implements UnaryExpression, ExplicitlyCastableSignature, AlwaysNullable, PropagateNullLiteral { + + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(BigIntType.INSTANCE).args(VarcharType.SYSTEM_DEFAULT) + ); + + public StNumGeometries(Expression arg0) { + super("st_numgeometries", arg0); + } + + private StNumGeometries(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public StNumGeometries withChildren(List children) { + Preconditions.checkArgument(children.size() == 1); + return new StNumGeometries(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitStNumGeometries(this, context); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StNumPoints.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StNumPoints.java new file mode 100644 index 00000000000000..15fa580016e6b2 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StNumPoints.java @@ -0,0 +1,68 @@ +// 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.BigIntType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * Scalar function 'st_numpoints'. This class is generated by GenerateFunction. + */ +public class StNumPoints extends ScalarFunction + implements UnaryExpression, ExplicitlyCastableSignature, AlwaysNullable, PropagateNullLiteral { + + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(BigIntType.INSTANCE).args(VarcharType.SYSTEM_DEFAULT) + ); + + public StNumPoints(Expression arg0) { + super("st_numpoints", arg0); + } + + private StNumPoints(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public StNumPoints withChildren(List children) { + Preconditions.checkArgument(children.size() == 1); + return new StNumPoints(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitStNumPoints(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 f02579c4326c1a..b3ff1fef25336e 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 @@ -499,6 +499,7 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.StDistance; 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.StGeometries; import org.apache.doris.nereids.trees.expressions.functions.scalar.StGeometryFromWKB; import org.apache.doris.nereids.trees.expressions.functions.scalar.StGeometryType; import org.apache.doris.nereids.trees.expressions.functions.scalar.StGeometryfromtext; @@ -507,6 +508,8 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.StLength; import org.apache.doris.nereids.trees.expressions.functions.scalar.StLinefromtext; import org.apache.doris.nereids.trees.expressions.functions.scalar.StLinestringfromtext; +import org.apache.doris.nereids.trees.expressions.functions.scalar.StNumGeometries; +import org.apache.doris.nereids.trees.expressions.functions.scalar.StNumPoints; import org.apache.doris.nereids.trees.expressions.functions.scalar.StPoint; import org.apache.doris.nereids.trees.expressions.functions.scalar.StPolyfromtext; import org.apache.doris.nereids.trees.expressions.functions.scalar.StPolygon; @@ -2378,6 +2381,18 @@ default R visitStGeometryType(StGeometryType stGeometryType, C context) { return visitScalarFunction(stGeometryType, context); } + default R visitStNumGeometries(StNumGeometries stNumGeometries, C context) { + return visitScalarFunction(stNumGeometries, context); + } + + default R visitStNumPoints(StNumPoints stNumPoints, C context) { + return visitScalarFunction(stNumPoints, context); + } + + default R visitStGeometries(StGeometries stGeometries, C context) { + return visitScalarFunction(stGeometries, context); + } + default R visitStDistance(StDistance stDistance, C context) { return visitScalarFunction(stDistance, context); } diff --git a/regression-test/data/query_p0/sql_functions/spatial_functions/test_st_num_geometries_num_points_and_geometries.out b/regression-test/data/query_p0/sql_functions/spatial_functions/test_st_num_geometries_num_points_and_geometries.out new file mode 100644 index 00000000000000..e46ccc9c72b009 --- /dev/null +++ b/regression-test/data/query_p0/sql_functions/spatial_functions/test_st_num_geometries_num_points_and_geometries.out @@ -0,0 +1,304 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !st_numpoints_point_constructor -- +1 + +-- !st_numpoints_point_wkt -- +1 + +-- !st_numpoints_linestring_two_points -- +2 + +-- !st_numpoints_linestring_three_points -- +3 + +-- !st_numpoints_linestring_four_points -- +4 + +-- !st_numpoints_triangle_polygon -- +4 + +-- !st_numpoints_square_polygon -- +5 + +-- !st_numpoints_polygon_with_one_hole -- +10 + +-- !st_numpoints_polygon_with_two_holes -- +15 + +-- !st_numpoints_multipolygon_one_polygon -- +5 + +-- !st_numpoints_multipolygon_two_polygons -- +10 + +-- !st_numpoints_multipolygon_three_polygons -- +14 + +-- !st_numpoints_multipolygon_with_hole -- +15 + +-- !st_numpoints_circle -- +-1 + +-- !st_numgeometries_point_constructor -- +1 + +-- !st_numgeometries_point_wkt -- +1 + +-- !st_numgeometries_linestring -- +1 + +-- !st_numgeometries_polygon -- +1 + +-- !st_numgeometries_polygon_with_hole -- +1 + +-- !st_numgeometries_multipolygon_one_polygon -- +1 + +-- !st_numgeometries_multipolygon_two_polygons -- +2 + +-- !st_numgeometries_multipolygon_three_polygons -- +3 + +-- !st_numgeometries_multipolygon_with_hole -- +2 + +-- !st_numgeometries_circle -- +1 + +-- !st_geometries_point_size -- +1 + +-- !st_geometries_point_element_type -- +ST_POINT + +-- !st_geometries_point_element_text -- +POINT (1 2) + +-- !st_geometries_linestring_size -- +1 + +-- !st_geometries_linestring_element_type -- +ST_LINESTRING + +-- !st_geometries_linestring_element_text -- +LINESTRING (0 0, 1 1, 2 2) + +-- !st_geometries_polygon_size -- +1 + +-- !st_geometries_polygon_element_type -- +ST_POLYGON + +-- !st_geometries_polygon_element_text -- +POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0)) + +-- !st_geometries_polygon_with_hole_size -- +1 + +-- !st_geometries_polygon_with_hole_element_type -- +ST_POLYGON + +-- !st_geometries_multipolygon_one_polygon_size -- +1 + +-- !st_geometries_multipolygon_one_polygon_element_1_type -- +ST_POLYGON + +-- !st_geometries_multipolygon_two_polygons_size -- +2 + +-- !st_geometries_multipolygon_two_polygons_element_1_type -- +ST_POLYGON + +-- !st_geometries_multipolygon_two_polygons_element_2_type -- +ST_POLYGON + +-- !st_geometries_multipolygon_two_polygons_element_1_text -- +POLYGON ((1 0, 1 1, 0 1, 0 0, 1 0)) + +-- !st_geometries_multipolygon_two_polygons_element_2_text -- +POLYGON ((3 2, 3 3, 2 3, 2 2, 3 2)) + +-- !st_geometries_multipolygon_two_polygons_element_3_out_of_bound -- +\N + +-- !st_geometries_multipolygon_three_polygons_size -- +3 + +-- !st_geometries_multipolygon_three_polygons_element_3_type -- +ST_POLYGON + +-- !st_geometries_multipolygon_with_hole_size -- +2 + +-- !st_geometries_multipolygon_with_hole_element_1_type -- +ST_POLYGON + +-- !st_geometries_multipolygon_with_hole_element_2_type -- +ST_POLYGON + +-- !st_geometries_circle_size -- +1 + +-- !st_geometries_circle_element_type -- +ST_CIRCLE + +-- !st_geometries_circle_element_2_out_of_bound -- +\N + +-- !st_numpoints_null_literal -- +\N + +-- !st_numgeometries_null_literal -- +\N + +-- !st_geometries_null_literal_size -- +\N + +-- !st_numpoints_geomfromtext_null -- +\N + +-- !st_numgeometries_geomfromtext_null -- +\N + +-- !st_geometries_geomfromtext_null_size -- +\N + +-- !st_numpoints_invalid_encoded_string -- +\N + +-- !st_numgeometries_invalid_encoded_string -- +\N + +-- !st_geometries_invalid_encoded_string_size -- +\N + +-- !st_numpoints_invalid_wkt -- +\N + +-- !st_numgeometries_invalid_wkt -- +\N + +-- !st_geometries_invalid_wkt_size -- +\N + +-- !st_numpoints_invalid_polygon_not_closed -- +\N + +-- !st_numgeometries_invalid_polygon_not_closed -- +\N + +-- !st_geometries_invalid_polygon_not_closed_size -- +\N + +-- !st_numpoints_lowercase_name -- +3 + +-- !st_numgeometries_lowercase_name -- +2 + +-- !st_geometries_lowercase_name_size -- +2 + +-- !st_numpoints_geometryfromtext_alias -- +4 + +-- !st_numgeometries_geometryfromtext_alias -- +1 + +-- !st_geometries_geometryfromtext_alias_element_2_type -- +ST_POLYGON + +-- !st_num_points_table_ordered -- +1 1 +2 2 +3 4 +4 5 +5 10 +6 5 +7 10 +8 15 +9 \N + +-- !st_num_geometries_table_ordered -- +1 1 +2 1 +3 1 +4 1 +5 1 +6 1 +7 2 +8 2 +9 \N + +-- !st_geometries_table_size_ordered -- +1 1 +2 1 +3 1 +4 1 +5 1 +6 1 +7 2 +8 2 +9 \N + +-- !st_geometries_table_first_element_type_ordered -- +1 ST_POINT +2 ST_LINESTRING +3 ST_LINESTRING +4 ST_POLYGON +5 ST_POLYGON +6 ST_POLYGON +7 ST_POLYGON +8 ST_POLYGON +9 \N + +-- !st_geometries_table_second_element_type_ordered -- +1 \N +2 \N +3 \N +4 \N +5 \N +6 \N +7 ST_POLYGON +8 ST_POLYGON +9 \N + +-- !st_all_three_functions_table_summary_ordered -- +1 ST_POINT 1 1 1 ST_POINT \N +2 ST_LINESTRING 2 1 1 ST_LINESTRING \N +3 ST_LINESTRING 4 1 1 ST_LINESTRING \N +4 ST_POLYGON 5 1 1 ST_POLYGON \N +5 ST_POLYGON 10 1 1 ST_POLYGON \N +6 ST_MULTIPOLYGON 5 1 1 ST_POLYGON \N +7 ST_MULTIPOLYGON 10 2 2 ST_POLYGON ST_POLYGON +8 ST_MULTIPOLYGON 15 2 2 ST_POLYGON ST_POLYGON +9 \N \N \N \N \N \N + +-- !st_numpoints_arithmetic -- +13 + +-- !st_numgeometries_arithmetic -- +12 + +-- !st_numpoints_predicate -- +4 +5 +6 +7 +8 + +-- !st_numgeometries_predicate -- +7 +8 + +-- !st_geometries_predicate -- +7 +8 + diff --git a/regression-test/suites/query_p0/sql_functions/spatial_functions/test_st_num_geometries_num_points_and_geometries.groovy b/regression-test/suites/query_p0/sql_functions/spatial_functions/test_st_num_geometries_num_points_and_geometries.groovy new file mode 100644 index 00000000000000..7e2ac9310817dc --- /dev/null +++ b/regression-test/suites/query_p0/sql_functions/spatial_functions/test_st_num_geometries_num_points_and_geometries.groovy @@ -0,0 +1,504 @@ +// 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. + +suite("test_st_num_geometries_num_points_and_geometries", "arrow_flight_sql") { + sql "set batch_size = 4096;" + + // ---------------------------------------------------------------------- + // ST_NumPoints: simple geometry inputs + // ---------------------------------------------------------------------- + + qt_st_numpoints_point_constructor """ + select ST_NumPoints(ST_Point(1, 2)); + """ + + qt_st_numpoints_point_wkt """ + select ST_NumPoints(ST_GeomFromText('POINT(1 2)')); + """ + + qt_st_numpoints_linestring_two_points """ + select ST_NumPoints(ST_GeomFromText('LINESTRING(0 0, 1 1)')); + """ + + qt_st_numpoints_linestring_three_points """ + select ST_NumPoints(ST_GeomFromText('LINESTRING(0 0, 1 1, 2 2)')); + """ + + qt_st_numpoints_linestring_four_points """ + select ST_NumPoints(ST_GeomFromText('LINESTRING(0 0, 1 0, 1 1, 0 1)')); + """ + + qt_st_numpoints_triangle_polygon """ + select ST_NumPoints(ST_GeomFromText('POLYGON((0 0, 1 0, 0 1, 0 0))')); + """ + + qt_st_numpoints_square_polygon """ + select ST_NumPoints(ST_GeomFromText('POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))')); + """ + + qt_st_numpoints_polygon_with_one_hole """ + select ST_NumPoints(ST_GeomFromText( + 'POLYGON((0 0, 4 0, 4 4, 0 4, 0 0), (1 1, 1 3, 3 3, 3 1, 1 1))' + )); + """ + + qt_st_numpoints_polygon_with_two_holes """ + select ST_NumPoints(ST_GeomFromText( + 'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1), (7 7, 7 8, 8 8, 8 7, 7 7))' + )); + """ + + qt_st_numpoints_multipolygon_one_polygon """ + select ST_NumPoints(ST_GeomFromText( + 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)))' + )); + """ + + qt_st_numpoints_multipolygon_two_polygons """ + select ST_NumPoints(ST_GeomFromText( + 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)), ((2 2, 2 3, 3 3, 3 2, 2 2)))' + )); + """ + + qt_st_numpoints_multipolygon_three_polygons """ + select ST_NumPoints(ST_GeomFromText( + 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)), ((2 2, 2 3, 3 3, 3 2, 2 2)), ((5 5, 6 5, 5 6, 5 5)))' + )); + """ + + qt_st_numpoints_multipolygon_with_hole """ + select ST_NumPoints(ST_GeomFromText( + 'MULTIPOLYGON(((0 0, 0 10, 10 10, 10 0, 0 0), (2 2, 2 8, 8 8, 8 2, 2 2)), ((20 20, 20 21, 21 21, 21 20, 20 20)))' + )); + """ + + qt_st_numpoints_circle """ + select ST_NumPoints(ST_Circle(0, 0, 1000)); + """ + + // ---------------------------------------------------------------------- + // ST_NumGeometries: simple geometry and multi geometry inputs + // ---------------------------------------------------------------------- + + qt_st_numgeometries_point_constructor """ + select ST_NumGeometries(ST_Point(1, 2)); + """ + + qt_st_numgeometries_point_wkt """ + select ST_NumGeometries(ST_GeomFromText('POINT(1 2)')); + """ + + qt_st_numgeometries_linestring """ + select ST_NumGeometries(ST_GeomFromText('LINESTRING(0 0, 1 1, 2 2)')); + """ + + qt_st_numgeometries_polygon """ + select ST_NumGeometries(ST_GeomFromText('POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))')); + """ + + qt_st_numgeometries_polygon_with_hole """ + select ST_NumGeometries(ST_GeomFromText( + 'POLYGON((0 0, 4 0, 4 4, 0 4, 0 0), (1 1, 1 3, 3 3, 3 1, 1 1))' + )); + """ + + qt_st_numgeometries_multipolygon_one_polygon """ + select ST_NumGeometries(ST_GeomFromText( + 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)))' + )); + """ + + qt_st_numgeometries_multipolygon_two_polygons """ + select ST_NumGeometries(ST_GeomFromText( + 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)), ((2 2, 2 3, 3 3, 3 2, 2 2)))' + )); + """ + + qt_st_numgeometries_multipolygon_three_polygons """ + select ST_NumGeometries(ST_GeomFromText( + 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)), ((2 2, 2 3, 3 3, 3 2, 2 2)), ((5 5, 6 5, 5 6, 5 5)))' + )); + """ + + qt_st_numgeometries_multipolygon_with_hole """ + select ST_NumGeometries(ST_GeomFromText( + 'MULTIPOLYGON(((0 0, 0 10, 10 10, 10 0, 0 0), (2 2, 2 8, 8 8, 8 2, 2 2)), ((20 20, 20 21, 21 21, 21 20, 20 20)))' + )); + """ + + qt_st_numgeometries_circle """ + select ST_NumGeometries(ST_Circle(0, 0, 1000)); + """ + + // ---------------------------------------------------------------------- + // ST_Geometries: simple geometry should return array with one element + // ---------------------------------------------------------------------- + + qt_st_geometries_point_size """ + select ARRAY_SIZE(ST_Geometries(ST_Point(1, 2))); + """ + + qt_st_geometries_point_element_type """ + select ST_GeometryType(ELEMENT_AT(ST_Geometries(ST_Point(1, 2)), 1)); + """ + + qt_st_geometries_point_element_text """ + select ST_AsText(ELEMENT_AT(ST_Geometries(ST_Point(1, 2)), 1)); + """ + + qt_st_geometries_linestring_size """ + select ARRAY_SIZE(ST_Geometries(ST_GeomFromText('LINESTRING(0 0, 1 1, 2 2)'))); + """ + + qt_st_geometries_linestring_element_type """ + select ST_GeometryType(ELEMENT_AT(ST_Geometries(ST_GeomFromText('LINESTRING(0 0, 1 1, 2 2)')), 1)); + """ + + qt_st_geometries_linestring_element_text """ + select ST_AsText(ELEMENT_AT(ST_Geometries(ST_GeomFromText('LINESTRING(0 0, 1 1, 2 2)')), 1)); + """ + + qt_st_geometries_polygon_size """ + select ARRAY_SIZE(ST_Geometries(ST_GeomFromText('POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))'))); + """ + + qt_st_geometries_polygon_element_type """ + select ST_GeometryType(ELEMENT_AT(ST_Geometries(ST_GeomFromText('POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))')), 1)); + """ + + qt_st_geometries_polygon_element_text """ + select ST_AsText(ELEMENT_AT(ST_Geometries(ST_GeomFromText('POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))')), 1)); + """ + + qt_st_geometries_polygon_with_hole_size """ + select ARRAY_SIZE(ST_Geometries(ST_GeomFromText( + 'POLYGON((0 0, 4 0, 4 4, 0 4, 0 0), (1 1, 1 3, 3 3, 3 1, 1 1))' + ))); + """ + + qt_st_geometries_polygon_with_hole_element_type """ + select ST_GeometryType(ELEMENT_AT(ST_Geometries(ST_GeomFromText( + 'POLYGON((0 0, 4 0, 4 4, 0 4, 0 0), (1 1, 1 3, 3 3, 3 1, 1 1))' + )), 1)); + """ + + // ---------------------------------------------------------------------- + // ST_Geometries: multipolygon should be split into polygon elements + // ---------------------------------------------------------------------- + + qt_st_geometries_multipolygon_one_polygon_size """ + select ARRAY_SIZE(ST_Geometries(ST_GeomFromText( + 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)))' + ))); + """ + + qt_st_geometries_multipolygon_one_polygon_element_1_type """ + select ST_GeometryType(ELEMENT_AT(ST_Geometries(ST_GeomFromText( + 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)))' + )), 1)); + """ + + qt_st_geometries_multipolygon_two_polygons_size """ + select ARRAY_SIZE(ST_Geometries(ST_GeomFromText( + 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)), ((2 2, 2 3, 3 3, 3 2, 2 2)))' + ))); + """ + + qt_st_geometries_multipolygon_two_polygons_element_1_type """ + select ST_GeometryType(ELEMENT_AT(ST_Geometries(ST_GeomFromText( + 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)), ((2 2, 2 3, 3 3, 3 2, 2 2)))' + )), 1)); + """ + + qt_st_geometries_multipolygon_two_polygons_element_2_type """ + select ST_GeometryType(ELEMENT_AT(ST_Geometries(ST_GeomFromText( + 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)), ((2 2, 2 3, 3 3, 3 2, 2 2)))' + )), 2)); + """ + + qt_st_geometries_multipolygon_two_polygons_element_1_text """ + select ST_AsText(ELEMENT_AT(ST_Geometries(ST_GeomFromText( + 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)), ((2 2, 2 3, 3 3, 3 2, 2 2)))' + )), 1)); + """ + + qt_st_geometries_multipolygon_two_polygons_element_2_text """ + select ST_AsText(ELEMENT_AT(ST_Geometries(ST_GeomFromText( + 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)), ((2 2, 2 3, 3 3, 3 2, 2 2)))' + )), 2)); + """ + + qt_st_geometries_multipolygon_two_polygons_element_3_out_of_bound """ + select ST_AsText(ELEMENT_AT(ST_Geometries(ST_GeomFromText( + 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)), ((2 2, 2 3, 3 3, 3 2, 2 2)))' + )), 3)); + """ + + qt_st_geometries_multipolygon_three_polygons_size """ + select ARRAY_SIZE(ST_Geometries(ST_GeomFromText( + 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)), ((2 2, 2 3, 3 3, 3 2, 2 2)), ((5 5, 6 5, 5 6, 5 5)))' + ))); + """ + + qt_st_geometries_multipolygon_three_polygons_element_3_type """ + select ST_GeometryType(ELEMENT_AT(ST_Geometries(ST_GeomFromText( + 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)), ((2 2, 2 3, 3 3, 3 2, 2 2)), ((5 5, 6 5, 5 6, 5 5)))' + )), 3)); + """ + + qt_st_geometries_multipolygon_with_hole_size """ + select ARRAY_SIZE(ST_Geometries(ST_GeomFromText( + 'MULTIPOLYGON(((0 0, 0 10, 10 10, 10 0, 0 0), (2 2, 2 8, 8 8, 8 2, 2 2)), ((20 20, 20 21, 21 21, 21 20, 20 20)))' + ))); + """ + + qt_st_geometries_multipolygon_with_hole_element_1_type """ + select ST_GeometryType(ELEMENT_AT(ST_Geometries(ST_GeomFromText( + 'MULTIPOLYGON(((0 0, 0 10, 10 10, 10 0, 0 0), (2 2, 2 8, 8 8, 8 2, 2 2)), ((20 20, 20 21, 21 21, 21 20, 20 20)))' + )), 1)); + """ + + qt_st_geometries_multipolygon_with_hole_element_2_type """ + select ST_GeometryType(ELEMENT_AT(ST_Geometries(ST_GeomFromText( + 'MULTIPOLYGON(((0 0, 0 10, 10 10, 10 0, 0 0), (2 2, 2 8, 8 8, 8 2, 2 2)), ((20 20, 20 21, 21 21, 21 20, 20 20)))' + )), 2)); + """ + + // ---------------------------------------------------------------------- + // ST_Geometries: circle behavior + // Circle is a Doris-specific shape. It should be treated as one geometry. + // ---------------------------------------------------------------------- + + qt_st_geometries_circle_size """ + select ARRAY_SIZE(ST_Geometries(ST_Circle(0, 0, 1000))); + """ + + qt_st_geometries_circle_element_type """ + select ST_GeometryType(ELEMENT_AT(ST_Geometries(ST_Circle(0, 0, 1000)), 1)); + """ + + qt_st_geometries_circle_element_2_out_of_bound """ + select ST_GeometryType(ELEMENT_AT(ST_Geometries(ST_Circle(0, 0, 1000)), 2)); + """ + + // ---------------------------------------------------------------------- + // NULL and invalid inputs + // ---------------------------------------------------------------------- + + qt_st_numpoints_null_literal """ + select ST_NumPoints(null); + """ + + qt_st_numgeometries_null_literal """ + select ST_NumGeometries(null); + """ + + qt_st_geometries_null_literal_size """ + select ARRAY_SIZE(ST_Geometries(null)); + """ + + qt_st_numpoints_geomfromtext_null """ + select ST_NumPoints(ST_GeomFromText(null)); + """ + + qt_st_numgeometries_geomfromtext_null """ + select ST_NumGeometries(ST_GeomFromText(null)); + """ + + qt_st_geometries_geomfromtext_null_size """ + select ARRAY_SIZE(ST_Geometries(ST_GeomFromText(null))); + """ + + qt_st_numpoints_invalid_encoded_string """ + select ST_NumPoints('abc'); + """ + + qt_st_numgeometries_invalid_encoded_string """ + select ST_NumGeometries('abc'); + """ + + qt_st_geometries_invalid_encoded_string_size """ + select ARRAY_SIZE(ST_Geometries('abc')); + """ + + qt_st_numpoints_invalid_wkt """ + select ST_NumPoints(ST_GeomFromText('INVALID(0 0)')); + """ + + qt_st_numgeometries_invalid_wkt """ + select ST_NumGeometries(ST_GeomFromText('INVALID(0 0)')); + """ + + qt_st_geometries_invalid_wkt_size """ + select ARRAY_SIZE(ST_Geometries(ST_GeomFromText('INVALID(0 0)'))); + """ + + qt_st_numpoints_invalid_polygon_not_closed """ + select ST_NumPoints(ST_GeomFromText('POLYGON((0 0, 1 0, 1 1, 0 1))')); + """ + + qt_st_numgeometries_invalid_polygon_not_closed """ + select ST_NumGeometries(ST_GeomFromText('POLYGON((0 0, 1 0, 1 1, 0 1))')); + """ + + qt_st_geometries_invalid_polygon_not_closed_size """ + select ARRAY_SIZE(ST_Geometries(ST_GeomFromText('POLYGON((0 0, 1 0, 1 1, 0 1))'))); + """ + + // ---------------------------------------------------------------------- + // Lowercase function names and ST_GeometryFromText alias coverage + // ---------------------------------------------------------------------- + + qt_st_numpoints_lowercase_name """ + select st_numpoints(ST_GeomFromText('LINESTRING(0 0, 1 1, 2 2)')); + """ + + qt_st_numgeometries_lowercase_name """ + select st_numgeometries(ST_GeomFromText( + 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)), ((2 2, 2 3, 3 3, 3 2, 2 2)))' + )); + """ + + qt_st_geometries_lowercase_name_size """ + select ARRAY_SIZE(st_geometries(ST_GeomFromText( + 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)), ((2 2, 2 3, 3 3, 3 2, 2 2)))' + ))); + """ + + qt_st_numpoints_geometryfromtext_alias """ + select ST_NumPoints(ST_GeometryFromText('LINESTRING(0 0, 1 1, 2 2, 3 3)')); + """ + + qt_st_numgeometries_geometryfromtext_alias """ + select ST_NumGeometries(ST_GeometryFromText('POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))')); + """ + + qt_st_geometries_geometryfromtext_alias_element_2_type """ + select ST_GeometryType(ELEMENT_AT(ST_Geometries(ST_GeometryFromText( + 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)), ((2 2, 2 3, 3 3, 3 2, 2 2)))' + )), 2)); + """ + + // ---------------------------------------------------------------------- + // Table-driven tests: column input, ordering, NULL row, mixed geometry types + // ---------------------------------------------------------------------- + + sql "drop table if exists test_st_geometry_component_functions_cases" + sql """ + CREATE TABLE test_st_geometry_component_functions_cases ( + `id` int NOT NULL, + `wkt` varchar(2048) NULL + ) ENGINE=OLAP + UNIQUE KEY(`id`) + COMMENT 'OLAP' + DISTRIBUTED BY HASH(`id`) BUCKETS 4 + PROPERTIES ( + "replication_allocation" = "tag.location.default: 1" + ); + """ + + sql """ + insert into test_st_geometry_component_functions_cases values + (1, 'POINT(0 0)'), + (2, 'LINESTRING(0 0, 0 1)'), + (3, 'LINESTRING(0 0, 1 0, 1 1, 0 1)'), + (4, 'POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))'), + (5, 'POLYGON((0 0, 4 0, 4 4, 0 4, 0 0), (1 1, 1 3, 3 3, 3 1, 1 1))'), + (6, 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)))'), + (7, 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)), ((2 2, 2 3, 3 3, 3 2, 2 2)))'), + (8, 'MULTIPOLYGON(((0 0, 0 10, 10 10, 10 0, 0 0), (2 2, 2 8, 8 8, 8 2, 2 2)), ((20 20, 20 21, 21 21, 21 20, 20 20)))'), + (9, null); + """ + + qt_st_num_points_table_ordered """ + select id, ST_NumPoints(ST_GeomFromText(wkt)) + from test_st_geometry_component_functions_cases + order by id; + """ + + qt_st_num_geometries_table_ordered """ + select id, ST_NumGeometries(ST_GeomFromText(wkt)) + from test_st_geometry_component_functions_cases + order by id; + """ + + qt_st_geometries_table_size_ordered """ + select id, ARRAY_SIZE(ST_Geometries(ST_GeomFromText(wkt))) + from test_st_geometry_component_functions_cases + order by id; + """ + + qt_st_geometries_table_first_element_type_ordered """ + select id, ST_GeometryType(ELEMENT_AT(ST_Geometries(ST_GeomFromText(wkt)), 1)) + from test_st_geometry_component_functions_cases + order by id; + """ + + qt_st_geometries_table_second_element_type_ordered """ + select id, ST_GeometryType(ELEMENT_AT(ST_Geometries(ST_GeomFromText(wkt)), 2)) + from test_st_geometry_component_functions_cases + order by id; + """ + + qt_st_all_three_functions_table_summary_ordered """ + select + id, + ST_GeometryType(ST_GeomFromText(wkt)), + ST_NumPoints(ST_GeomFromText(wkt)), + ST_NumGeometries(ST_GeomFromText(wkt)), + ARRAY_SIZE(ST_Geometries(ST_GeomFromText(wkt))), + ST_GeometryType(ELEMENT_AT(ST_Geometries(ST_GeomFromText(wkt)), 1)), + ST_GeometryType(ELEMENT_AT(ST_Geometries(ST_GeomFromText(wkt)), 2)) + from test_st_geometry_component_functions_cases + order by id; + """ + + // ---------------------------------------------------------------------- + // Return values used in arithmetic and predicates + // ---------------------------------------------------------------------- + + qt_st_numpoints_arithmetic """ + select ST_NumPoints(ST_GeomFromText('LINESTRING(0 0, 1 1, 2 2)')) + 10; + """ + + qt_st_numgeometries_arithmetic """ + select ST_NumGeometries(ST_GeomFromText( + 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)), ((2 2, 2 3, 3 3, 3 2, 2 2)))' + )) + 10; + """ + + qt_st_numpoints_predicate """ + select id + from test_st_geometry_component_functions_cases + where ST_NumPoints(ST_GeomFromText(wkt)) >= 5 + order by id; + """ + + qt_st_numgeometries_predicate """ + select id + from test_st_geometry_component_functions_cases + where ST_NumGeometries(ST_GeomFromText(wkt)) >= 2 + order by id; + """ + + qt_st_geometries_predicate """ + select id + from test_st_geometry_component_functions_cases + where ARRAY_SIZE(ST_Geometries(ST_GeomFromText(wkt))) >= 2 + order by id; + """ +}