From 0343b57c52f4d4f6f09bf3b241e29b4f780ad9e7 Mon Sep 17 00:00:00 2001 From: baishen Date: Thu, 5 Dec 2024 01:37:06 +0800 Subject: [PATCH] feat(query): Support `st_collect` aggregate function (#16996) feat(query): Support st_collect aggregate function --- .../src/aggregates/aggregate_array_agg.rs | 11 +- .../aggregates/aggregate_function_factory.rs | 22 +- .../aggregates/aggregate_json_array_agg.rs | 6 +- .../aggregates/aggregate_json_object_agg.rs | 12 +- .../src/aggregates/aggregate_st_collect.rs | 381 ++++++++++++++++++ .../functions/src/aggregates/aggregator.rs | 3 + src/query/functions/src/aggregates/mod.rs | 2 + src/query/functions/src/scalars/geometry.rs | 53 +++ .../functions/tests/it/aggregates/agg.rs | 226 +++++++++++ .../tests/it/aggregates/testdata/agg.txt | 144 +++++++ .../it/aggregates/testdata/agg_group_by.txt | 144 +++++++ .../functions/tests/it/scalars/geometry.rs | 50 +++ .../it/scalars/testdata/function_list.txt | 4 + .../tests/it/scalars/testdata/geometry.txt | 90 +++++ .../functions/02_0060_function_geometry.test | 59 +++ 15 files changed, 1187 insertions(+), 20 deletions(-) create mode 100644 src/query/functions/src/aggregates/aggregate_st_collect.rs diff --git a/src/query/functions/src/aggregates/aggregate_array_agg.rs b/src/query/functions/src/aggregates/aggregate_array_agg.rs index 23f07b011290..28218078ea2d 100644 --- a/src/query/functions/src/aggregates/aggregate_array_agg.rs +++ b/src/query/functions/src/aggregates/aggregate_array_agg.rs @@ -15,6 +15,7 @@ use std::alloc::Layout; use std::fmt; use std::marker::PhantomData; +use std::mem; use std::sync::Arc; use borsh::BorshDeserialize; @@ -101,8 +102,9 @@ where match inner_type.remove_nullable() { DataType::Decimal(decimal_type) => { let size = decimal_type.size(); - for value in &self.values { - let val = T::upcast_scalar(value.clone()); + let values = mem::take(&mut self.values); + for value in values.into_iter() { + let val = T::upcast_scalar(value); let decimal_val = val.as_decimal().unwrap(); let new_val = match decimal_val { DecimalScalar::Decimal128(v, _) => { @@ -116,8 +118,9 @@ where } } _ => { - for value in &self.values { - let val = T::upcast_scalar(value.clone()); + let values = mem::take(&mut self.values); + for value in values.into_iter() { + let val = T::upcast_scalar(value); inner_builder.push(val.as_ref()); } } diff --git a/src/query/functions/src/aggregates/aggregate_function_factory.rs b/src/query/functions/src/aggregates/aggregate_function_factory.rs index 562fdf9494c8..e8cbd31ef2bb 100644 --- a/src/query/functions/src/aggregates/aggregate_function_factory.rs +++ b/src/query/functions/src/aggregates/aggregate_function_factory.rs @@ -26,6 +26,17 @@ use super::AggregateFunctionOrNullAdaptor; use crate::aggregates::AggregateFunctionRef; use crate::aggregates::Aggregators; +// The NULL value in the those function needs to be handled separately. +const NEED_NULL_AGGREGATE_FUNCTIONS: [&str; 7] = [ + "array_agg", + "list", + "json_array_agg", + "json_object_agg", + "group_array_moving_avg", + "group_array_moving_sum", + "st_collect", +]; + const STATE_SUFFIX: &str = "_state"; pub type AggregateFunctionCreator = @@ -172,15 +183,8 @@ impl AggregateFunctionFactory { ) -> Result { let name = name.as_ref(); let mut features = AggregateFunctionFeatures::default(); - // The NULL value in the array_agg function needs to be added to the returned array column, - // so handled separately. - if name == "array_agg" - || name == "list" - || name == "json_array_agg" - || name == "json_object_agg" - || name == "group_array_moving_avg" - || name == "group_array_moving_sum" - { + + if NEED_NULL_AGGREGATE_FUNCTIONS.contains(&name) { let agg = self.get_impl(name, params, arguments, &mut features)?; return Ok(agg); } diff --git a/src/query/functions/src/aggregates/aggregate_json_array_agg.rs b/src/query/functions/src/aggregates/aggregate_json_array_agg.rs index 33c525d56c07..0365e989f797 100644 --- a/src/query/functions/src/aggregates/aggregate_json_array_agg.rs +++ b/src/query/functions/src/aggregates/aggregate_json_array_agg.rs @@ -15,6 +15,7 @@ use std::alloc::Layout; use std::fmt; use std::marker::PhantomData; +use std::mem; use std::sync::Arc; use borsh::BorshDeserialize; @@ -102,8 +103,9 @@ where fn merge_result(&mut self, builder: &mut ColumnBuilder) -> Result<()> { let tz = TimeZone::UTC; let mut items = Vec::with_capacity(self.values.len()); - for value in &self.values { - let v = T::upcast_scalar(value.clone()); + let values = mem::take(&mut self.values); + for value in values.into_iter() { + let v = T::upcast_scalar(value); // NULL values are omitted from the output. if v == Scalar::Null { continue; diff --git a/src/query/functions/src/aggregates/aggregate_json_object_agg.rs b/src/query/functions/src/aggregates/aggregate_json_object_agg.rs index a3028cd73400..80f81e23dc82 100644 --- a/src/query/functions/src/aggregates/aggregate_json_object_agg.rs +++ b/src/query/functions/src/aggregates/aggregate_json_object_agg.rs @@ -16,6 +16,7 @@ use std::alloc::Layout; use std::collections::BTreeMap; use std::fmt; use std::marker::PhantomData; +use std::mem; use std::sync::Arc; use borsh::BorshDeserialize; @@ -166,19 +167,20 @@ where fn merge_result(&mut self, builder: &mut ColumnBuilder) -> Result<()> { let tz = TimeZone::UTC; - let mut kvs = Vec::with_capacity(self.kvs.len()); - for (key, value) in &self.kvs { - let v = V::upcast_scalar(value.clone()); + let mut values = Vec::with_capacity(self.kvs.len()); + let kvs = mem::take(&mut self.kvs); + for (key, value) in kvs.into_iter() { + let v = V::upcast_scalar(value); // NULL values are omitted from the output. if v == Scalar::Null { continue; } let mut val = vec![]; cast_scalar_to_variant(v.as_ref(), &tz, &mut val); - kvs.push((key, val)); + values.push((key, val)); } let mut data = vec![]; - jsonb::build_object(kvs.iter().map(|(k, v)| (k, &v[..])), &mut data).unwrap(); + jsonb::build_object(values.iter().map(|(k, v)| (k, &v[..])), &mut data).unwrap(); let object_value = Scalar::Variant(data); builder.push(object_value.as_ref()); diff --git a/src/query/functions/src/aggregates/aggregate_st_collect.rs b/src/query/functions/src/aggregates/aggregate_st_collect.rs new file mode 100644 index 000000000000..f3078976cdf8 --- /dev/null +++ b/src/query/functions/src/aggregates/aggregate_st_collect.rs @@ -0,0 +1,381 @@ +// Copyright 2021 Datafuse Labs +// +// Licensed 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. + +use std::alloc::Layout; +use std::fmt; +use std::marker::PhantomData; +use std::mem; +use std::sync::Arc; + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use databend_common_exception::ErrorCode; +use databend_common_exception::Result; +use databend_common_expression::types::Bitmap; +use databend_common_expression::types::DataType; +use databend_common_expression::types::GeometryType; +use databend_common_expression::types::ValueType; +use databend_common_expression::Column; +use databend_common_expression::ColumnBuilder; +use databend_common_expression::InputColumns; +use databend_common_expression::Scalar; +use databend_common_expression::ScalarRef; +use databend_common_io::ewkb_to_geo; +use databend_common_io::geo_to_ewkb; +use geo::Geometry; +use geo::GeometryCollection; +use geo::LineString; +use geo::MultiLineString; +use geo::MultiPoint; +use geo::MultiPolygon; +use geo::Point; +use geo::Polygon; +use geozero::wkb::Ewkb; + +use super::aggregate_function_factory::AggregateFunctionDescription; +use super::aggregate_scalar_state::ScalarStateFunc; +use super::borsh_deserialize_state; +use super::borsh_serialize_state; +use super::StateAddr; +use crate::aggregates::assert_unary_arguments; +use crate::aggregates::AggregateFunction; + +#[derive(BorshSerialize, BorshDeserialize, Debug)] +pub struct StCollectState +where + T: ValueType, + T::Scalar: BorshSerialize + BorshDeserialize, +{ + values: Vec, +} + +impl Default for StCollectState +where + T: ValueType, + T::Scalar: BorshSerialize + BorshDeserialize, +{ + fn default() -> Self { + Self { values: Vec::new() } + } +} + +impl ScalarStateFunc for StCollectState +where + T: ValueType, + T::Scalar: BorshSerialize + BorshDeserialize + Send + Sync, +{ + fn new() -> Self { + Self::default() + } + + fn add(&mut self, other: Option>) { + if let Some(other) = other { + self.values.push(T::to_owned_scalar(other)); + } + } + + fn add_batch(&mut self, column: &T::Column, validity: Option<&Bitmap>) -> Result<()> { + let column_len = T::column_len(column); + if column_len == 0 { + return Ok(()); + } + let column_iter = T::iter_column(column); + if let Some(validity) = validity { + for (val, valid) in column_iter.zip(validity.iter()) { + if valid { + self.values.push(T::to_owned_scalar(val)); + } + } + } else { + for val in column_iter { + self.values.push(T::to_owned_scalar(val)); + } + } + + Ok(()) + } + + fn merge(&mut self, rhs: &Self) -> Result<()> { + self.values.extend_from_slice(&rhs.values); + Ok(()) + } + + fn merge_result(&mut self, builder: &mut ColumnBuilder) -> Result<()> { + if self.values.is_empty() { + builder.push(ScalarRef::Null); + return Ok(()); + } + + let mut has_point = false; + let mut has_line_string = false; + let mut has_polygon = false; + let mut has_other = false; + + let mut srid = None; + let mut geos = Vec::with_capacity(self.values.len()); + let values = mem::take(&mut self.values); + for (i, value) in values.into_iter().enumerate() { + let val = T::upcast_scalar(value); + let v = val.as_geometry().unwrap(); + let (geo, geo_srid) = ewkb_to_geo(&mut Ewkb(v))?; + if i == 0 { + srid = geo_srid; + } else if !srid.eq(&geo_srid) { + return Err(ErrorCode::GeometryError(format!( + "Incompatible SRID: {} and {}", + srid.unwrap_or_default(), + geo_srid.unwrap_or_default() + ))); + } + match geo { + Geometry::Point(_) => { + has_point = true; + } + Geometry::LineString(_) => { + has_line_string = true; + } + Geometry::Polygon(_) => { + has_polygon = true; + } + _ => { + has_other = true; + } + } + geos.push(geo); + } + let geo = if has_point && !has_line_string && !has_polygon && !has_other { + let points: Vec = geos + .into_iter() + .map(|geo| geo.try_into().unwrap()) + .collect(); + let multi_point = MultiPoint::from_iter(points); + Geometry::MultiPoint(multi_point) + } else if !has_point && has_line_string && !has_polygon && !has_other { + let line_strings: Vec = geos + .into_iter() + .map(|geo| geo.try_into().unwrap()) + .collect(); + let multi_line_string = MultiLineString::from_iter(line_strings); + Geometry::MultiLineString(multi_line_string) + } else if !has_point && !has_line_string && has_polygon && !has_other { + let polygons: Vec = geos + .into_iter() + .map(|geo| geo.try_into().unwrap()) + .collect(); + let multi_polygon = MultiPolygon::from_iter(polygons); + Geometry::MultiPolygon(multi_polygon) + } else { + let geo_collect = GeometryCollection::from_iter(geos); + Geometry::GeometryCollection(geo_collect) + }; + + let data = geo_to_ewkb(geo, srid)?; + let geometry_value = Scalar::Geometry(data); + builder.push(geometry_value.as_ref()); + Ok(()) + } +} + +#[derive(Clone)] +pub struct AggregateStCollectFunction { + display_name: String, + return_type: DataType, + _t: PhantomData, + _state: PhantomData, +} + +impl AggregateFunction for AggregateStCollectFunction +where + T: ValueType + Send + Sync, + State: ScalarStateFunc, +{ + fn name(&self) -> &str { + "AggregateStCollectFunction" + } + + fn return_type(&self) -> Result { + Ok(self.return_type.clone()) + } + + fn init_state(&self, place: StateAddr) { + place.write(|| State::new()); + } + + fn state_layout(&self) -> Layout { + Layout::new::() + } + + fn accumulate( + &self, + place: StateAddr, + columns: InputColumns, + _validity: Option<&Bitmap>, + _input_rows: usize, + ) -> Result<()> { + let state = place.get::(); + match &columns[0] { + Column::Nullable(box nullable_column) => { + let column = T::try_downcast_column(&nullable_column.column).unwrap(); + state.add_batch(&column, Some(&nullable_column.validity)) + } + _ => { + if let Some(column) = T::try_downcast_column(&columns[0]) { + state.add_batch(&column, None) + } else { + Ok(()) + } + } + } + } + + fn accumulate_keys( + &self, + places: &[StateAddr], + offset: usize, + columns: InputColumns, + _input_rows: usize, + ) -> Result<()> { + match &columns[0] { + Column::Nullable(box nullable_column) => { + let column = T::try_downcast_column(&nullable_column.column).unwrap(); + let column_iter = T::iter_column(&column); + column_iter + .zip(nullable_column.validity.iter().zip(places.iter())) + .for_each(|(v, (valid, place))| { + let addr = place.next(offset); + let state = addr.get::(); + if valid { + state.add(Some(v.clone())) + } else { + state.add(None) + } + }); + } + _ => { + if let Some(column) = T::try_downcast_column(&columns[0]) { + let column_iter = T::iter_column(&column); + column_iter.zip(places.iter()).for_each(|(v, place)| { + let addr = place.next(offset); + let state = addr.get::(); + state.add(Some(v.clone())) + }); + } + } + } + + Ok(()) + } + + fn accumulate_row(&self, place: StateAddr, columns: InputColumns, row: usize) -> Result<()> { + let state = place.get::(); + match &columns[0] { + Column::Nullable(box nullable_column) => { + let valid = nullable_column.validity.get_bit(row); + if valid { + let column = T::try_downcast_column(&nullable_column.column).unwrap(); + let v = T::index_column(&column, row); + state.add(v); + } else { + state.add(None); + } + } + _ => { + if let Some(column) = T::try_downcast_column(&columns[0]) { + let v = T::index_column(&column, row); + state.add(v); + } + } + } + + Ok(()) + } + + fn serialize(&self, place: StateAddr, writer: &mut Vec) -> Result<()> { + let state = place.get::(); + borsh_serialize_state(writer, state) + } + + fn merge(&self, place: StateAddr, reader: &mut &[u8]) -> Result<()> { + let state = place.get::(); + let rhs: State = borsh_deserialize_state(reader)?; + + state.merge(&rhs) + } + + fn merge_states(&self, place: StateAddr, rhs: StateAddr) -> Result<()> { + let state = place.get::(); + let other = rhs.get::(); + state.merge(other) + } + + fn merge_result(&self, place: StateAddr, builder: &mut ColumnBuilder) -> Result<()> { + let state = place.get::(); + state.merge_result(builder) + } + + fn need_manual_drop_state(&self) -> bool { + true + } + + unsafe fn drop_state(&self, place: StateAddr) { + let state = place.get::(); + std::ptr::drop_in_place(state); + } +} + +impl fmt::Display for AggregateStCollectFunction { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.display_name) + } +} + +impl AggregateStCollectFunction +where + T: ValueType + Send + Sync, + State: ScalarStateFunc, +{ + fn try_create(display_name: &str, return_type: DataType) -> Result> { + let func = AggregateStCollectFunction:: { + display_name: display_name.to_string(), + return_type, + _t: PhantomData, + _state: PhantomData, + }; + Ok(Arc::new(func)) + } +} + +pub fn try_create_aggregate_st_collect_function( + display_name: &str, + _params: Vec, + argument_types: Vec, +) -> Result> { + assert_unary_arguments(display_name, argument_types.len())?; + if argument_types[0].remove_nullable() != DataType::Geometry + && argument_types[0] != DataType::Null + { + return Err(ErrorCode::BadDataValueType(format!( + "The argument of aggregate function {} must be Geometry", + display_name + ))); + } + let return_type = DataType::Nullable(Box::new(DataType::Geometry)); + + type State = StCollectState; + AggregateStCollectFunction::::try_create(display_name, return_type) +} + +pub fn aggregate_st_collect_function_desc() -> AggregateFunctionDescription { + AggregateFunctionDescription::creator(Box::new(try_create_aggregate_st_collect_function)) +} diff --git a/src/query/functions/src/aggregates/aggregator.rs b/src/query/functions/src/aggregates/aggregator.rs index e463ae7f8168..4c9c88a6e9b4 100644 --- a/src/query/functions/src/aggregates/aggregator.rs +++ b/src/query/functions/src/aggregates/aggregator.rs @@ -54,6 +54,7 @@ use crate::aggregates::aggregate_quantile_tdigest_function_desc; use crate::aggregates::aggregate_quantile_tdigest_weighted_function_desc; use crate::aggregates::aggregate_retention_function_desc; use crate::aggregates::aggregate_skewness_function_desc; +use crate::aggregates::aggregate_st_collect_function_desc; use crate::aggregates::aggregate_string_agg_function_desc; use crate::aggregates::aggregate_sum_function_desc; @@ -144,6 +145,8 @@ impl Aggregators { factory.register("histogram", aggregate_histogram_function_desc()); factory.register("mode", aggregate_mode_function_desc()); + + factory.register("st_collect", aggregate_st_collect_function_desc()); } pub fn register_combinator(factory: &mut AggregateFunctionFactory) { diff --git a/src/query/functions/src/aggregates/mod.rs b/src/query/functions/src/aggregates/mod.rs index 86fff42b0309..a24d642ff76f 100644 --- a/src/query/functions/src/aggregates/mod.rs +++ b/src/query/functions/src/aggregates/mod.rs @@ -43,6 +43,7 @@ mod aggregate_quantile_tdigest_weighted; mod aggregate_retention; mod aggregate_scalar_state; mod aggregate_skewness; +mod aggregate_st_collect; mod aggregate_stddev; mod aggregate_string_agg; mod aggregate_sum; @@ -75,6 +76,7 @@ pub use aggregate_quantile_tdigest::*; pub use aggregate_quantile_tdigest_weighted::*; pub use aggregate_retention::*; pub use aggregate_skewness::*; +pub use aggregate_st_collect::*; pub use aggregate_string_agg::*; pub use aggregate_sum::*; pub use aggregate_unary::*; diff --git a/src/query/functions/src/scalars/geometry.rs b/src/query/functions/src/scalars/geometry.rs index 0a0998d95cb8..a4018319adaa 100644 --- a/src/query/functions/src/scalars/geometry.rs +++ b/src/query/functions/src/scalars/geometry.rs @@ -46,8 +46,10 @@ use databend_common_io::Axis; use databend_common_io::Extremum; use geo::coord; use geo::dimensions::Dimensions; +use geo::Area; use geo::BoundingRect; use geo::Contains; +use geo::ConvexHull; use geo::Coord; use geo::EuclideanDistance; use geo::EuclideanLength; @@ -442,6 +444,57 @@ pub fn register(registry: &mut FunctionRegistry) { ), ); + registry.register_passthrough_nullable_1_arg::, _, _>( + "st_area", + |_, _| FunctionDomain::MayThrow, + vectorize_with_builder_1_arg::>(|ewkb, builder, ctx| { + if let Some(validity) = &ctx.validity { + if !validity.get_bit(builder.len()) { + builder.push(F64::from(0_f64)); + return; + } + } + + match ewkb_to_geo(&mut Ewkb(ewkb)) { + Ok((geo, _)) => { + let area = geo.unsigned_area(); + let area = (area * 1_000_000_000_f64).round() / 1_000_000_000_f64; + builder.push(area.into()); + } + Err(e) => { + ctx.set_error(builder.len(), e.to_string()); + builder.push(F64::from(0_f64)); + } + } + }), + ); + + registry.register_passthrough_nullable_1_arg::( + "st_convexhull", + |_, _| FunctionDomain::MayThrow, + vectorize_with_builder_1_arg::(|ewkb, builder, ctx| { + if let Some(validity) = &ctx.validity { + if !validity.get_bit(builder.len()) { + builder.commit_row(); + return; + } + } + + match ewkb_to_geo(&mut Ewkb(ewkb)).and_then(|(geo, srid)| { + let polygon = geo.convex_hull(); + geo_to_ewkb(Geometry::from(polygon), srid) + }) { + Ok(ewkb) => { + builder.put_slice(ewkb.as_slice()); + } + Err(e) => { + ctx.set_error(builder.len(), e.to_string()); + } + } + builder.commit_row(); + }), + ); + registry.register_combine_nullable_1_arg::( "st_endpoint", |_, _| FunctionDomain::MayThrow, diff --git a/src/query/functions/tests/it/aggregates/agg.rs b/src/query/functions/tests/it/aggregates/agg.rs index 969e4ecc9348..fd4bc22e50e6 100644 --- a/src/query/functions/tests/it/aggregates/agg.rs +++ b/src/query/functions/tests/it/aggregates/agg.rs @@ -73,6 +73,7 @@ fn test_agg() { test_agg_json_array_agg(file, eval_aggr); test_agg_json_object_agg(file, eval_aggr); test_agg_mode(file, eval_aggr); + test_agg_st_collect(file, eval_aggr); } #[test] @@ -113,6 +114,7 @@ fn test_agg_group_by() { test_agg_json_array_agg(file, eval_aggr); test_agg_json_object_agg(file, eval_aggr); test_agg_mode(file, simulate_two_groups_group_by); + test_agg_st_collect(file, eval_aggr); } fn gen_bitmap_data() -> Column { @@ -194,6 +196,130 @@ fn get_example() -> Vec<(&'static str, Column)> { ] } +fn get_geometry_example() -> Vec<(&'static str, Column)> { + vec![ + ( + "point", + StringType::from_data(vec!["POINT(1 1)", "POINT(2 2)", "POINT(3 3)", "POINT(4 4)"]), + ), + ( + "point_null", + StringType::from_data_with_validity( + vec!["POINT(1 1)", "", "POINT(3 3)", "POINT(4 4)"], + vec![true, false, true, true], + ), + ), + ( + "line_string", + StringType::from_data(vec![ + "LINESTRING(0 0, 1 1)", + "LINESTRING(1 1, 2 2)", + "LINESTRING(2 2, 3 3)", + "LINESTRING(3 3, 4 4)", + ]), + ), + ( + "line_string_null", + StringType::from_data_with_validity( + vec![ + "LINESTRING(0 0, 1 1)", + "", + "LINESTRING(2 2, 3 3)", + "LINESTRING(3 3, 4 4)", + ], + vec![true, false, true, true], + ), + ), + ( + "polygon", + StringType::from_data(vec![ + "POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))", + "POLYGON((1 1, 2 1, 2 2, 1 2, 1 1))", + "POLYGON((2 2, 3 2, 3 3, 2 3, 2 2))", + "POLYGON((3 3, 4 3, 4 4, 3 4, 3 3))", + ]), + ), + ( + "mixed_geom", + StringType::from_data(vec![ + "POINT(0 0)", + "LINESTRING(1 1, 2 2)", + "POLYGON((2 2, 3 2, 3 3, 2 3, 2 2))", + "POINT(4 4)", + ]), + ), + ( + "mixed_geom_null", + StringType::from_data_with_validity( + vec![ + "POINT(0 0)", + "", + "POLYGON((2 2, 3 2, 3 3, 2 3, 2 2))", + "POINT(4 4)", + ], + vec![true, false, true, true], + ), + ), + ( + "point_4326", + StringType::from_data(vec![ + "SRID=4326;POINT(116.3 39.9)", + "SRID=4326;POINT(121.4 31.2)", + "SRID=4326;POINT(113.2 23.1)", + "SRID=4326;POINT(114.1 22.5)", + ]), + ), + ( + "line_string_4326", + StringType::from_data(vec![ + "SRID=4326;LINESTRING(116.3 39.9, 121.4 31.2)", + "SRID=4326;LINESTRING(121.4 31.2, 113.2 23.1)", + "SRID=4326;LINESTRING(113.2 23.1, 114.1 22.5)", + "SRID=4326;LINESTRING(114.1 22.5, 116.3 39.9)", + ]), + ), + ( + "polygon_4326", + StringType::from_data(vec![ + "SRID=4326;POLYGON((116 39, 117 39, 117 40, 116 40, 116 39))", + "SRID=4326;POLYGON((121 31, 122 31, 122 32, 121 32, 121 31))", + "SRID=4326;POLYGON((113 23, 114 23, 114 24, 113 24, 113 23))", + "SRID=4326;POLYGON((114 22, 115 22, 115 23, 114 23, 114 22))", + ]), + ), + ( + "mixed_3857", + StringType::from_data(vec![ + "SRID=3857;POINT(12947889.3 4852834.1)", + "SRID=3857;LINESTRING(13515330.8 3642091.4, 12600089.2 2632873.5)", + "SRID=3857;POLYGON((12700000 2600000, 12800000 2600000, 12800000 2700000, 12700000 2700000, 12700000 2600000))", + "SRID=3857;POINT(12959772.9 2551529.8)", + ]), + ), + ( + "mixed_srid", + StringType::from_data(vec![ + "SRID=4326;POINT(116.3 39.9)", + "SRID=3857;POINT(12947889.3 4852834.1)", + "SRID=4326;LINESTRING(121.4 31.2, 113.2 23.1)", + "SRID=3857;POLYGON((12700000 2600000, 12800000 2600000, 12800000 2700000, 12700000 2700000, 12700000 2600000))", + ]), + ), + ( + "mixed_srid_null", + StringType::from_data_with_validity( + vec![ + "SRID=4326;POINT(116.3 39.9)", + "", + "SRID=4326;LINESTRING(121.4 31.2, 113.2 23.1)", + "SRID=3857;POLYGON((12700000 2600000, 12800000 2600000, 12800000 2700000, 12700000 2700000, 12700000 2600000))", + ], + vec![true, false, true, true], + ), + ), + ] +} + fn test_count(file: &mut impl Write, simulator: impl AggregationSimulator) { run_agg_ast(file, "count(1)", get_example().as_slice(), simulator); run_agg_ast(file, "count()", get_example().as_slice(), simulator); @@ -892,3 +1018,103 @@ fn test_agg_mode(file: &mut impl Write, simulator: impl AggregationSimulator) { run_agg_ast(file, "mode(d)", get_example().as_slice(), simulator); run_agg_ast(file, "mode(all_null)", get_example().as_slice(), simulator); } + +fn test_agg_st_collect(file: &mut impl Write, simulator: impl AggregationSimulator) { + run_agg_ast( + file, + "st_collect(to_geometry('point(10 20)'))", + get_geometry_example().as_slice(), + simulator, + ); + run_agg_ast( + file, + "st_collect(to_geometry('srid=4326;linestring(10 20, 40 50)'))", + get_geometry_example().as_slice(), + simulator, + ); + run_agg_ast( + file, + "st_collect(NULL)", + get_geometry_example().as_slice(), + simulator, + ); + + run_agg_ast( + file, + "st_collect(to_geometry(point))", + get_geometry_example().as_slice(), + simulator, + ); + run_agg_ast( + file, + "st_collect(to_geometry(point_null))", + get_geometry_example().as_slice(), + simulator, + ); + run_agg_ast( + file, + "st_collect(to_geometry(line_string))", + get_geometry_example().as_slice(), + simulator, + ); + run_agg_ast( + file, + "st_collect(to_geometry(line_string_null))", + get_geometry_example().as_slice(), + simulator, + ); + run_agg_ast( + file, + "st_collect(to_geometry(polygon))", + get_geometry_example().as_slice(), + simulator, + ); + run_agg_ast( + file, + "st_collect(to_geometry(mixed_geom))", + get_geometry_example().as_slice(), + simulator, + ); + run_agg_ast( + file, + "st_collect(to_geometry(mixed_geom_null))", + get_geometry_example().as_slice(), + simulator, + ); + run_agg_ast( + file, + "st_collect(to_geometry(point_4326))", + get_geometry_example().as_slice(), + simulator, + ); + run_agg_ast( + file, + "st_collect(to_geometry(line_string_4326))", + get_geometry_example().as_slice(), + simulator, + ); + run_agg_ast( + file, + "st_collect(to_geometry(polygon_4326))", + get_geometry_example().as_slice(), + simulator, + ); + run_agg_ast( + file, + "st_collect(to_geometry(mixed_3857))", + get_geometry_example().as_slice(), + simulator, + ); + run_agg_ast( + file, + "st_collect(to_geometry(mixed_srid))", + get_geometry_example().as_slice(), + simulator, + ); + run_agg_ast( + file, + "st_collect(to_geometry(mixed_srid_null))", + get_geometry_example().as_slice(), + simulator, + ); +} diff --git a/src/query/functions/tests/it/aggregates/testdata/agg.txt b/src/query/functions/tests/it/aggregates/testdata/agg.txt index 3f2f302db43a..b3aa2c3cd21e 100644 --- a/src/query/functions/tests/it/aggregates/testdata/agg.txt +++ b/src/query/functions/tests/it/aggregates/testdata/agg.txt @@ -1532,3 +1532,147 @@ evaluation (internal): +----------+-------------------------------------------------------------------------+ +ast: st_collect(to_geometry('point(10 20)')) +evaluation (internal): ++--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| point | StringColumn[POINT(1 1), POINT(2 2), POINT(3 3), POINT(4 4)] | +| Output | NullableColumn { column: BinaryColumn { data: 0x010400000004000000010100000000000000000024400000000000003440010100000000000000000024400000000000003440010100000000000000000024400000000000003440010100000000000000000024400000000000003440, offsets: [0, 93] }, validity: [0b_______1] } | ++--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast: st_collect(to_geometry('srid=4326;linestring(10 20, 40 50)')) +evaluation (internal): ++--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| point | StringColumn[POINT(1 1), POINT(2 2), POINT(3 3), POINT(4 4)] | +| Output | NullableColumn { column: BinaryColumn { data: 0x0105000020e6100000040000000102000000020000000000000000002440000000000000344000000000000044400000000000004940010200000002000000000000000000244000000000000034400000000000004440000000000000494001020000000200000000000000000024400000000000003440000000000000444000000000000049400102000000020000000000000000002440000000000000344000000000000044400000000000004940, offsets: [0, 177] }, validity: [0b_______1] } | ++--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast: st_collect(NULL) +evaluation (internal): ++--------+-----------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+-----------------------------------------------------------------------------------------------+ +| point | StringColumn[POINT(1 1), POINT(2 2), POINT(3 3), POINT(4 4)] | +| Output | NullableColumn { column: BinaryColumn { data: 0x, offsets: [0, 0] }, validity: [0b_______0] } | ++--------+-----------------------------------------------------------------------------------------------+ + + +ast: st_collect(to_geometry(point)) +evaluation (internal): ++--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| point | StringColumn[POINT(1 1), POINT(2 2), POINT(3 3), POINT(4 4)] | +| Output | NullableColumn { column: BinaryColumn { data: 0x0104000000040000000101000000000000000000f03f000000000000f03f010100000000000000000000400000000000000040010100000000000000000008400000000000000840010100000000000000000010400000000000001040, offsets: [0, 93] }, validity: [0b_______1] } | ++--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast: st_collect(to_geometry(point_null)) +evaluation (internal): ++------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| point_null | NullableColumn { column: StringColumn[POINT(1 1), , POINT(3 3), POINT(4 4)], validity: [0b____1101] } | +| Output | NullableColumn { column: BinaryColumn { data: 0x0104000000030000000101000000000000000000f03f000000000000f03f010100000000000000000008400000000000000840010100000000000000000010400000000000001040, offsets: [0, 72] }, validity: [0b_______1] } | ++------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast: st_collect(to_geometry(line_string)) +evaluation (internal): ++-------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++-------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| line_string | StringColumn[LINESTRING(0 0, 1 1), LINESTRING(1 1, 2 2), LINESTRING(2 2, 3 3), LINESTRING(3 3, 4 4)] | +| Output | NullableColumn { column: BinaryColumn { data: 0x01050000000400000001020000000200000000000000000000000000000000000000000000000000f03f000000000000f03f010200000002000000000000000000f03f000000000000f03f0000000000000040000000000000004001020000000200000000000000000000400000000000000040000000000000084000000000000008400102000000020000000000000000000840000000000000084000000000000010400000000000001040, offsets: [0, 173] }, validity: [0b_______1] } | ++-------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast: st_collect(to_geometry(line_string_null)) +evaluation (internal): ++------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| line_string_null | NullableColumn { column: StringColumn[LINESTRING(0 0, 1 1), , LINESTRING(2 2, 3 3), LINESTRING(3 3, 4 4)], validity: [0b____1101] } | +| Output | NullableColumn { column: BinaryColumn { data: 0x01050000000300000001020000000200000000000000000000000000000000000000000000000000f03f000000000000f03f01020000000200000000000000000000400000000000000040000000000000084000000000000008400102000000020000000000000000000840000000000000084000000000000010400000000000001040, offsets: [0, 132] }, validity: [0b_______1] } | ++------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast: st_collect(to_geometry(polygon)) +evaluation (internal): ++---------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++---------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| polygon | StringColumn[POLYGON((0 0, 1 0, 1 1, 0 1, 0 0)), POLYGON((1 1, 2 1, 2 2, 1 2, 1 1)), POLYGON((2 2, 3 2, 3 3, 2 3, 2 2)), POLYGON((3 3, 4 3, 4 4, 3 4, 3 3))] | +| Output | NullableColumn { column: BinaryColumn { data: 0x0106000000040000000103000000010000000500000000000000000000000000000000000000000000000000f03f0000000000000000000000000000f03f000000000000f03f0000000000000000000000000000f03f0000000000000000000000000000000001030000000100000005000000000000000000f03f000000000000f03f0000000000000040000000000000f03f00000000000000400000000000000040000000000000f03f0000000000000040000000000000f03f000000000000f03f010300000001000000050000000000000000000040000000000000004000000000000008400000000000000040000000000000084000000000000008400000000000000040000000000000084000000000000000400000000000000040010300000001000000050000000000000000000840000000000000084000000000000010400000000000000840000000000000104000000000000010400000000000000840000000000000104000000000000008400000000000000840, offsets: [0, 381] }, validity: [0b_______1] } | ++---------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast: st_collect(to_geometry(mixed_geom)) +evaluation (internal): ++------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| mixed_geom | StringColumn[POINT(0 0), LINESTRING(1 1, 2 2), POLYGON((2 2, 3 2, 3 3, 2 3, 2 2)), POINT(4 4)] | +| Output | NullableColumn { column: BinaryColumn { data: 0x010700000004000000010100000000000000000000000000000000000000010200000002000000000000000000f03f000000000000f03f00000000000000400000000000000040010300000001000000050000000000000000000040000000000000004000000000000008400000000000000040000000000000084000000000000008400000000000000040000000000000084000000000000000400000000000000040010100000000000000000010400000000000001040, offsets: [0, 185] }, validity: [0b_______1] } | ++------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast: st_collect(to_geometry(mixed_geom_null)) +evaluation (internal): ++-----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++-----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| mixed_geom_null | NullableColumn { column: StringColumn[POINT(0 0), , POLYGON((2 2, 3 2, 3 3, 2 3, 2 2)), POINT(4 4)], validity: [0b____1101] } | +| Output | NullableColumn { column: BinaryColumn { data: 0x010700000003000000010100000000000000000000000000000000000000010300000001000000050000000000000000000040000000000000004000000000000008400000000000000040000000000000084000000000000008400000000000000040000000000000084000000000000000400000000000000040010100000000000000000010400000000000001040, offsets: [0, 144] }, validity: [0b_______1] } | ++-----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast: st_collect(to_geometry(point_4326)) +evaluation (internal): ++------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| point_4326 | StringColumn[SRID=4326;POINT(116.3 39.9), SRID=4326;POINT(121.4 31.2), SRID=4326;POINT(113.2 23.1), SRID=4326;POINT(114.1 22.5)] | +| Output | NullableColumn { column: BinaryColumn { data: 0x0104000020e61000000400000001010000003333333333135d403333333333f3434001010000009a99999999595e403333333333333f400101000000cdcccccccc4c5c409a9999999919374001010000006666666666865c400000000000803640, offsets: [0, 97] }, validity: [0b_______1] } | ++------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast: st_collect(to_geometry(line_string_4326)) +evaluation (internal): ++------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| line_string_4326 | StringColumn[SRID=4326;LINESTRING(116.3 39.9, 121.4 31.2), SRID=4326;LINESTRING(121.4 31.2, 113.2 23.1), SRID=4326;LINESTRING(113.2 23.1, 114.1 22.5), SRID=4326;LINESTRING(114.1 22.5, 116.3 39.9)] | +| Output | NullableColumn { column: BinaryColumn { data: 0x0105000020e6100000040000000102000000020000003333333333135d403333333333f343409a99999999595e403333333333333f400102000000020000009a99999999595e403333333333333f40cdcccccccc4c5c409a99999999193740010200000002000000cdcccccccc4c5c409a999999991937406666666666865c4000000000008036400102000000020000006666666666865c4000000000008036403333333333135d403333333333f34340, offsets: [0, 177] }, validity: [0b_______1] } | ++------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast: st_collect(to_geometry(polygon_4326)) +evaluation (internal): ++--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| polygon_4326 | StringColumn[SRID=4326;POLYGON((116 39, 117 39, 117 40, 116 40, 116 39)), SRID=4326;POLYGON((121 31, 122 31, 122 32, 121 32, 121 31)), SRID=4326;POLYGON((113 23, 114 23, 114 24, 113 24, 113 23)), SRID=4326;POLYGON((114 22, 115 22, 115 23, 114 23, 114 22))] | +| Output | NullableColumn { column: BinaryColumn { data: 0x0106000020e610000004000000010300000001000000050000000000000000005d4000000000008043400000000000405d4000000000008043400000000000405d4000000000000044400000000000005d4000000000000044400000000000005d400000000000804340010300000001000000050000000000000000405e400000000000003f400000000000805e400000000000003f400000000000805e4000000000000040400000000000405e4000000000000040400000000000405e400000000000003f40010300000001000000050000000000000000405c4000000000000037400000000000805c4000000000000037400000000000805c4000000000000038400000000000405c4000000000000038400000000000405c400000000000003740010300000001000000050000000000000000805c4000000000000036400000000000c05c4000000000000036400000000000c05c4000000000000037400000000000805c4000000000000037400000000000805c400000000000003640, offsets: [0, 385] }, validity: [0b_______1] } | ++--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast: st_collect(to_geometry(mixed_3857)) +evaluation (internal): ++------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| mixed_3857 | StringColumn[SRID=3857;POINT(12947889.3 4852834.1), SRID=3857;LINESTRING(13515330.8 3642091.4, 12600089.2 2632873.5), SRID=3857;POLYGON((12700000 2600000, 12800000 2600000, 12800000 2700000, 12700000 2700000, 12700000 2600000)), SRID=3857;POINT(12959772.9 2551529.8)] | +| Output | NullableColumn { column: BinaryColumn { data: 0x0107000020110f00000400000001010000009a99992936b2684166666686188352410102000000020000009a99995948c76941333333b375c94b416666662663086841000000c05416444101030000000100000005000000000000002c3968410000000020d6434100000000006a68410000000020d6434100000000006a68410000000070994441000000002c3968410000000070994441000000002c3968410000000020d643410101000000cdcccc9c03b86841666666e674774341, offsets: [0, 189] }, validity: [0b_______1] } | ++------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +error: Incompatible SRID: 4326 and 3857 + +error: Incompatible SRID: 4326 and 3857 + diff --git a/src/query/functions/tests/it/aggregates/testdata/agg_group_by.txt b/src/query/functions/tests/it/aggregates/testdata/agg_group_by.txt index 8195a1b83138..8d595d04bd8b 100644 --- a/src/query/functions/tests/it/aggregates/testdata/agg_group_by.txt +++ b/src/query/functions/tests/it/aggregates/testdata/agg_group_by.txt @@ -1470,3 +1470,147 @@ evaluation (internal): +----------+-------------------------------------------------------------------------+ +ast: st_collect(to_geometry('point(10 20)')) +evaluation (internal): ++--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| point | StringColumn[POINT(1 1), POINT(2 2), POINT(3 3), POINT(4 4)] | +| Output | NullableColumn { column: BinaryColumn { data: 0x010400000004000000010100000000000000000024400000000000003440010100000000000000000024400000000000003440010100000000000000000024400000000000003440010100000000000000000024400000000000003440, offsets: [0, 93] }, validity: [0b_______1] } | ++--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast: st_collect(to_geometry('srid=4326;linestring(10 20, 40 50)')) +evaluation (internal): ++--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| point | StringColumn[POINT(1 1), POINT(2 2), POINT(3 3), POINT(4 4)] | +| Output | NullableColumn { column: BinaryColumn { data: 0x0105000020e6100000040000000102000000020000000000000000002440000000000000344000000000000044400000000000004940010200000002000000000000000000244000000000000034400000000000004440000000000000494001020000000200000000000000000024400000000000003440000000000000444000000000000049400102000000020000000000000000002440000000000000344000000000000044400000000000004940, offsets: [0, 177] }, validity: [0b_______1] } | ++--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast: st_collect(NULL) +evaluation (internal): ++--------+-----------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+-----------------------------------------------------------------------------------------------+ +| point | StringColumn[POINT(1 1), POINT(2 2), POINT(3 3), POINT(4 4)] | +| Output | NullableColumn { column: BinaryColumn { data: 0x, offsets: [0, 0] }, validity: [0b_______0] } | ++--------+-----------------------------------------------------------------------------------------------+ + + +ast: st_collect(to_geometry(point)) +evaluation (internal): ++--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| point | StringColumn[POINT(1 1), POINT(2 2), POINT(3 3), POINT(4 4)] | +| Output | NullableColumn { column: BinaryColumn { data: 0x0104000000040000000101000000000000000000f03f000000000000f03f010100000000000000000000400000000000000040010100000000000000000008400000000000000840010100000000000000000010400000000000001040, offsets: [0, 93] }, validity: [0b_______1] } | ++--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast: st_collect(to_geometry(point_null)) +evaluation (internal): ++------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| point_null | NullableColumn { column: StringColumn[POINT(1 1), , POINT(3 3), POINT(4 4)], validity: [0b____1101] } | +| Output | NullableColumn { column: BinaryColumn { data: 0x0104000000030000000101000000000000000000f03f000000000000f03f010100000000000000000008400000000000000840010100000000000000000010400000000000001040, offsets: [0, 72] }, validity: [0b_______1] } | ++------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast: st_collect(to_geometry(line_string)) +evaluation (internal): ++-------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++-------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| line_string | StringColumn[LINESTRING(0 0, 1 1), LINESTRING(1 1, 2 2), LINESTRING(2 2, 3 3), LINESTRING(3 3, 4 4)] | +| Output | NullableColumn { column: BinaryColumn { data: 0x01050000000400000001020000000200000000000000000000000000000000000000000000000000f03f000000000000f03f010200000002000000000000000000f03f000000000000f03f0000000000000040000000000000004001020000000200000000000000000000400000000000000040000000000000084000000000000008400102000000020000000000000000000840000000000000084000000000000010400000000000001040, offsets: [0, 173] }, validity: [0b_______1] } | ++-------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast: st_collect(to_geometry(line_string_null)) +evaluation (internal): ++------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| line_string_null | NullableColumn { column: StringColumn[LINESTRING(0 0, 1 1), , LINESTRING(2 2, 3 3), LINESTRING(3 3, 4 4)], validity: [0b____1101] } | +| Output | NullableColumn { column: BinaryColumn { data: 0x01050000000300000001020000000200000000000000000000000000000000000000000000000000f03f000000000000f03f01020000000200000000000000000000400000000000000040000000000000084000000000000008400102000000020000000000000000000840000000000000084000000000000010400000000000001040, offsets: [0, 132] }, validity: [0b_______1] } | ++------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast: st_collect(to_geometry(polygon)) +evaluation (internal): ++---------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++---------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| polygon | StringColumn[POLYGON((0 0, 1 0, 1 1, 0 1, 0 0)), POLYGON((1 1, 2 1, 2 2, 1 2, 1 1)), POLYGON((2 2, 3 2, 3 3, 2 3, 2 2)), POLYGON((3 3, 4 3, 4 4, 3 4, 3 3))] | +| Output | NullableColumn { column: BinaryColumn { data: 0x0106000000040000000103000000010000000500000000000000000000000000000000000000000000000000f03f0000000000000000000000000000f03f000000000000f03f0000000000000000000000000000f03f0000000000000000000000000000000001030000000100000005000000000000000000f03f000000000000f03f0000000000000040000000000000f03f00000000000000400000000000000040000000000000f03f0000000000000040000000000000f03f000000000000f03f010300000001000000050000000000000000000040000000000000004000000000000008400000000000000040000000000000084000000000000008400000000000000040000000000000084000000000000000400000000000000040010300000001000000050000000000000000000840000000000000084000000000000010400000000000000840000000000000104000000000000010400000000000000840000000000000104000000000000008400000000000000840, offsets: [0, 381] }, validity: [0b_______1] } | ++---------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast: st_collect(to_geometry(mixed_geom)) +evaluation (internal): ++------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| mixed_geom | StringColumn[POINT(0 0), LINESTRING(1 1, 2 2), POLYGON((2 2, 3 2, 3 3, 2 3, 2 2)), POINT(4 4)] | +| Output | NullableColumn { column: BinaryColumn { data: 0x010700000004000000010100000000000000000000000000000000000000010200000002000000000000000000f03f000000000000f03f00000000000000400000000000000040010300000001000000050000000000000000000040000000000000004000000000000008400000000000000040000000000000084000000000000008400000000000000040000000000000084000000000000000400000000000000040010100000000000000000010400000000000001040, offsets: [0, 185] }, validity: [0b_______1] } | ++------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast: st_collect(to_geometry(mixed_geom_null)) +evaluation (internal): ++-----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++-----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| mixed_geom_null | NullableColumn { column: StringColumn[POINT(0 0), , POLYGON((2 2, 3 2, 3 3, 2 3, 2 2)), POINT(4 4)], validity: [0b____1101] } | +| Output | NullableColumn { column: BinaryColumn { data: 0x010700000003000000010100000000000000000000000000000000000000010300000001000000050000000000000000000040000000000000004000000000000008400000000000000040000000000000084000000000000008400000000000000040000000000000084000000000000000400000000000000040010100000000000000000010400000000000001040, offsets: [0, 144] }, validity: [0b_______1] } | ++-----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast: st_collect(to_geometry(point_4326)) +evaluation (internal): ++------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| point_4326 | StringColumn[SRID=4326;POINT(116.3 39.9), SRID=4326;POINT(121.4 31.2), SRID=4326;POINT(113.2 23.1), SRID=4326;POINT(114.1 22.5)] | +| Output | NullableColumn { column: BinaryColumn { data: 0x0104000020e61000000400000001010000003333333333135d403333333333f3434001010000009a99999999595e403333333333333f400101000000cdcccccccc4c5c409a9999999919374001010000006666666666865c400000000000803640, offsets: [0, 97] }, validity: [0b_______1] } | ++------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast: st_collect(to_geometry(line_string_4326)) +evaluation (internal): ++------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| line_string_4326 | StringColumn[SRID=4326;LINESTRING(116.3 39.9, 121.4 31.2), SRID=4326;LINESTRING(121.4 31.2, 113.2 23.1), SRID=4326;LINESTRING(113.2 23.1, 114.1 22.5), SRID=4326;LINESTRING(114.1 22.5, 116.3 39.9)] | +| Output | NullableColumn { column: BinaryColumn { data: 0x0105000020e6100000040000000102000000020000003333333333135d403333333333f343409a99999999595e403333333333333f400102000000020000009a99999999595e403333333333333f40cdcccccccc4c5c409a99999999193740010200000002000000cdcccccccc4c5c409a999999991937406666666666865c4000000000008036400102000000020000006666666666865c4000000000008036403333333333135d403333333333f34340, offsets: [0, 177] }, validity: [0b_______1] } | ++------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast: st_collect(to_geometry(polygon_4326)) +evaluation (internal): ++--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| polygon_4326 | StringColumn[SRID=4326;POLYGON((116 39, 117 39, 117 40, 116 40, 116 39)), SRID=4326;POLYGON((121 31, 122 31, 122 32, 121 32, 121 31)), SRID=4326;POLYGON((113 23, 114 23, 114 24, 113 24, 113 23)), SRID=4326;POLYGON((114 22, 115 22, 115 23, 114 23, 114 22))] | +| Output | NullableColumn { column: BinaryColumn { data: 0x0106000020e610000004000000010300000001000000050000000000000000005d4000000000008043400000000000405d4000000000008043400000000000405d4000000000000044400000000000005d4000000000000044400000000000005d400000000000804340010300000001000000050000000000000000405e400000000000003f400000000000805e400000000000003f400000000000805e4000000000000040400000000000405e4000000000000040400000000000405e400000000000003f40010300000001000000050000000000000000405c4000000000000037400000000000805c4000000000000037400000000000805c4000000000000038400000000000405c4000000000000038400000000000405c400000000000003740010300000001000000050000000000000000805c4000000000000036400000000000c05c4000000000000036400000000000c05c4000000000000037400000000000805c4000000000000037400000000000805c400000000000003640, offsets: [0, 385] }, validity: [0b_______1] } | ++--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +ast: st_collect(to_geometry(mixed_3857)) +evaluation (internal): ++------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Column | Data | ++------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| mixed_3857 | StringColumn[SRID=3857;POINT(12947889.3 4852834.1), SRID=3857;LINESTRING(13515330.8 3642091.4, 12600089.2 2632873.5), SRID=3857;POLYGON((12700000 2600000, 12800000 2600000, 12800000 2700000, 12700000 2700000, 12700000 2600000)), SRID=3857;POINT(12959772.9 2551529.8)] | +| Output | NullableColumn { column: BinaryColumn { data: 0x0107000020110f00000400000001010000009a99992936b2684166666686188352410102000000020000009a99995948c76941333333b375c94b416666662663086841000000c05416444101030000000100000005000000000000002c3968410000000020d6434100000000006a68410000000020d6434100000000006a68410000000070994441000000002c3968410000000070994441000000002c3968410000000020d643410101000000cdcccc9c03b86841666666e674774341, offsets: [0, 189] }, validity: [0b_______1] } | ++------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +error: Incompatible SRID: 4326 and 3857 + +error: Incompatible SRID: 4326 and 3857 + diff --git a/src/query/functions/tests/it/scalars/geometry.rs b/src/query/functions/tests/it/scalars/geometry.rs index 372fd79937d6..cdb3f9d5d9dd 100644 --- a/src/query/functions/tests/it/scalars/geometry.rs +++ b/src/query/functions/tests/it/scalars/geometry.rs @@ -64,6 +64,8 @@ fn test_geometry() { test_st_disjoint(file); test_st_within(file); test_st_equals(file); + test_st_area(file); + test_st_convexhull(file); } fn test_haversine(file: &mut impl Write) { @@ -760,3 +762,51 @@ fn test_st_equals(file: &mut impl Write) { &[], ); } + +fn test_st_area(file: &mut impl Write) { + run_ast( + file, + "ST_AREA(TO_GEOMETRY('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))'))", + &[], + ); + run_ast( + file, + "ST_AREA(TO_GEOMETRY('POLYGON((0 0, 0 4, 4 4, 4 0, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1))'))", + &[], + ); + run_ast( + file, + "ST_AREA(TO_GEOMETRY('MULTIPOLYGON(((0 0, 0 2, 2 2, 2 0, 0 0)), ((3 0, 3 2, 5 2, 5 0, 3 0)))'))", + &[], + ); + run_ast(file, "ST_AREA(TO_GEOMETRY('POINT(0 0)'))", &[]); + run_ast( + file, + "ST_AREA(TO_GEOMETRY('LINESTRING(0 0, 1 1, 2 2)'))", + &[], + ); +} + +fn test_st_convexhull(file: &mut impl Write) { + run_ast(file, "ST_CONVEXHULL(TO_GEOMETRY('POINT(1 1)'))", &[]); + run_ast( + file, + "ST_CONVEXHULL(TO_GEOMETRY('MULTIPOINT((1 1), (0 0), (2 2), (1 2), (2 1))'))", + &[], + ); + run_ast( + file, + "ST_CONVEXHULL(TO_GEOMETRY('LINESTRING(0 0, 1 1, 0 2, 2 1)'))", + &[], + ); + run_ast( + file, + "ST_CONVEXHULL(TO_GEOMETRY('POLYGON((0 0, 0 2, 1 1, 2 2, 2 0, 0 0))'))", + &[], + ); + run_ast( + file, + "ST_CONVEXHULL(TO_GEOMETRY('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(1 1, 2 2), POLYGON((3 0, 3 3, 6 3, 6 0, 3 0)))'))", + &[], + ); +} diff --git a/src/query/functions/tests/it/scalars/testdata/function_list.txt b/src/query/functions/tests/it/scalars/testdata/function_list.txt index 11a0695c73cc..c5878d026d5e 100644 --- a/src/query/functions/tests/it/scalars/testdata/function_list.txt +++ b/src/query/functions/tests/it/scalars/testdata/function_list.txt @@ -3625,6 +3625,8 @@ Functions overloads: 17 sqrt(Float32 NULL) :: Float64 NULL 18 sqrt(Float64) :: Float64 19 sqrt(Float64 NULL) :: Float64 NULL +0 st_area(Geometry) :: Float64 +1 st_area(Geometry NULL) :: Float64 NULL 0 st_asewkb(Geometry) :: Binary 1 st_asewkb(Geometry NULL) :: Binary NULL 0 st_asewkt(Geometry) :: String @@ -3637,6 +3639,8 @@ Functions overloads: 1 st_aswkt(Geometry NULL) :: String NULL 0 st_contains(Geometry, Geometry) :: Boolean 1 st_contains(Geometry NULL, Geometry NULL) :: Boolean NULL +0 st_convexhull(Geometry) :: Geometry +1 st_convexhull(Geometry NULL) :: Geometry NULL 0 st_dimension(Geometry) :: Int32 NULL 1 st_dimension(Geometry NULL) :: Int32 NULL 0 st_disjoint(Geometry, Geometry) :: Boolean diff --git a/src/query/functions/tests/it/scalars/testdata/geometry.txt b/src/query/functions/tests/it/scalars/testdata/geometry.txt index 03ec23e22726..582132490ea5 100644 --- a/src/query/functions/tests/it/scalars/testdata/geometry.txt +++ b/src/query/functions/tests/it/scalars/testdata/geometry.txt @@ -1370,3 +1370,93 @@ output domain : {TRUE} output : true +ast : ST_AREA(TO_GEOMETRY('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))')) +raw expr : ST_AREA(TO_GEOMETRY('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))')) +checked expr : st_area(to_geometry("POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))")) +optimized expr : 1_f64 +output type : Float64 +output domain : {1..=1} +output : 1 + + +ast : ST_AREA(TO_GEOMETRY('POLYGON((0 0, 0 4, 4 4, 4 0, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1))')) +raw expr : ST_AREA(TO_GEOMETRY('POLYGON((0 0, 0 4, 4 4, 4 0, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1))')) +checked expr : st_area(to_geometry("POLYGON((0 0, 0 4, 4 4, 4 0, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1))")) +optimized expr : 15_f64 +output type : Float64 +output domain : {15..=15} +output : 15 + + +ast : ST_AREA(TO_GEOMETRY('MULTIPOLYGON(((0 0, 0 2, 2 2, 2 0, 0 0)), ((3 0, 3 2, 5 2, 5 0, 3 0)))')) +raw expr : ST_AREA(TO_GEOMETRY('MULTIPOLYGON(((0 0, 0 2, 2 2, 2 0, 0 0)), ((3 0, 3 2, 5 2, 5 0, 3 0)))')) +checked expr : st_area(to_geometry("MULTIPOLYGON(((0 0, 0 2, 2 2, 2 0, 0 0)), ((3 0, 3 2, 5 2, 5 0, 3 0)))")) +optimized expr : 8_f64 +output type : Float64 +output domain : {8..=8} +output : 8 + + +ast : ST_AREA(TO_GEOMETRY('POINT(0 0)')) +raw expr : ST_AREA(TO_GEOMETRY('POINT(0 0)')) +checked expr : st_area(to_geometry("POINT(0 0)")) +optimized expr : 0_f64 +output type : Float64 +output domain : {0..=0} +output : 0 + + +ast : ST_AREA(TO_GEOMETRY('LINESTRING(0 0, 1 1, 2 2)')) +raw expr : ST_AREA(TO_GEOMETRY('LINESTRING(0 0, 1 1, 2 2)')) +checked expr : st_area(to_geometry("LINESTRING(0 0, 1 1, 2 2)")) +optimized expr : 0_f64 +output type : Float64 +output domain : {0..=0} +output : 0 + + +ast : ST_CONVEXHULL(TO_GEOMETRY('POINT(1 1)')) +raw expr : ST_CONVEXHULL(TO_GEOMETRY('POINT(1 1)')) +checked expr : st_convexhull(to_geometry("POINT(1 1)")) +optimized expr : "POLYGON((1 1,1 1))" +output type : Geometry +output domain : Undefined +output : 'POLYGON((1 1,1 1))' + + +ast : ST_CONVEXHULL(TO_GEOMETRY('MULTIPOINT((1 1), (0 0), (2 2), (1 2), (2 1))')) +raw expr : ST_CONVEXHULL(TO_GEOMETRY('MULTIPOINT((1 1), (0 0), (2 2), (1 2), (2 1))')) +checked expr : st_convexhull(to_geometry("MULTIPOINT((1 1), (0 0), (2 2), (1 2), (2 1))")) +optimized expr : "POLYGON((2 1,2 2,1 2,0 0,2 1))" +output type : Geometry +output domain : Undefined +output : 'POLYGON((2 1,2 2,1 2,0 0,2 1))' + + +ast : ST_CONVEXHULL(TO_GEOMETRY('LINESTRING(0 0, 1 1, 0 2, 2 1)')) +raw expr : ST_CONVEXHULL(TO_GEOMETRY('LINESTRING(0 0, 1 1, 0 2, 2 1)')) +checked expr : st_convexhull(to_geometry("LINESTRING(0 0, 1 1, 0 2, 2 1)")) +optimized expr : "POLYGON((2 1,0 2,0 0,2 1))" +output type : Geometry +output domain : Undefined +output : 'POLYGON((2 1,0 2,0 0,2 1))' + + +ast : ST_CONVEXHULL(TO_GEOMETRY('POLYGON((0 0, 0 2, 1 1, 2 2, 2 0, 0 0))')) +raw expr : ST_CONVEXHULL(TO_GEOMETRY('POLYGON((0 0, 0 2, 1 1, 2 2, 2 0, 0 0))')) +checked expr : st_convexhull(to_geometry("POLYGON((0 0, 0 2, 1 1, 2 2, 2 0, 0 0))")) +optimized expr : "POLYGON((2 0,2 2,0 2,0 0,2 0))" +output type : Geometry +output domain : Undefined +output : 'POLYGON((2 0,2 2,0 2,0 0,2 0))' + + +ast : ST_CONVEXHULL(TO_GEOMETRY('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(1 1, 2 2), POLYGON((3 0, 3 3, 6 3, 6 0, 3 0)))')) +raw expr : ST_CONVEXHULL(TO_GEOMETRY('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(1 1, 2 2), POLYGON((3 0, 3 3, 6 3, 6 0, 3 0)))')) +checked expr : st_convexhull(to_geometry("GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(1 1, 2 2), POLYGON((3 0, 3 3, 6 3, 6 0, 3 0)))")) +optimized expr : "POLYGON((6 0,6 3,3 3,0 0,6 0))" +output type : Geometry +output domain : Undefined +output : 'POLYGON((6 0,6 3,3 3,0 0,6 0))' + + diff --git a/tests/sqllogictests/suites/query/functions/02_0060_function_geometry.test b/tests/sqllogictests/suites/query/functions/02_0060_function_geometry.test index e66be9111ff7..e07908a0b76b 100644 --- a/tests/sqllogictests/suites/query/functions/02_0060_function_geometry.test +++ b/tests/sqllogictests/suites/query/functions/02_0060_function_geometry.test @@ -676,6 +676,65 @@ SELECT st_equals(st_geomfromtext('SRID=4326;POLYGON((-87.906471 43.038902, -95.9 ---- 0 +statement ok +CREATE OR REPLACE TABLE collect_test (g GEOMETRY); + +statement ok +INSERT INTO collect_test VALUES + ('POINT(1 2)'), + ('POINT(3 4)'), + ('LINESTRING(0 0, 1 1)'), + ('POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))'); + +query T +SELECT ST_ASWKT(ST_COLLECT(g)) FROM collect_test; +---- +GEOMETRYCOLLECTION(POINT(1 2),POINT(3 4),LINESTRING(0 0,1 1),POLYGON((0 0,1 0,1 1,0 1,0 0))) + +query T +SELECT ST_AREA(TO_GEOMETRY('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))')); +---- +1.0 + +query T +SELECT ST_AREA(TO_GEOMETRY('MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)), ((2 2, 2 3, 3 3, 3 2, 2 2)))')); +---- +2.0 + +query T +SELECT ST_AREA(TO_GEOMETRY('POINT(0 0)')); +---- +0.0 + +query T +SELECT ST_AREA(g) FROM collect_test; +---- +0.0 +0.0 +0.0 +1.0 + +query T +SELECT ST_ASWKT(ST_CONVEXHULL(TO_GEOMETRY('MULTIPOINT(0 0, 1 0, 1 1, 0 1, 0.5 0.5)'))); +---- +POLYGON((1 0,1 1,0 1,0 0,1 0)) + +query T +SELECT ST_ASWKT(ST_CONVEXHULL(TO_GEOMETRY('LINESTRING(0 0, 1 1, 0 2)'))); +---- +POLYGON((0 0,1 1,0 2,0 0)) + +query T +SELECT ST_ASWKT(ST_CONVEXHULL(g)) FROM collect_test; +---- +POLYGON((1 2,1 2)) +POLYGON((3 4,3 4)) +POLYGON((0 0,1 1,0 0)) +POLYGON((1 0,1 1,0 1,0 0,1 0)) + +statement ok +DROP TABLE collect_test; + statement ok SET enable_geo_create_table=0