From 3848c6fe1d0adeba6a9892a5d5c9f781231ee789 Mon Sep 17 00:00:00 2001 From: Fan Yang Date: Thu, 4 Jul 2024 11:34:43 +0800 Subject: [PATCH] HAVERSINE Signed-off-by: Fan Yang --- src/query/functions/src/scalars/geometry.rs | 12 ++++++++++++ src/query/functions/tests/it/scalars/geometry.rs | 6 ++++++ .../tests/it/scalars/testdata/function_list.txt | 2 ++ .../functions/tests/it/scalars/testdata/geometry.txt | 9 +++++++++ .../query/functions/02_0060_function_geometry.test | 5 +++++ 5 files changed, 34 insertions(+) diff --git a/src/query/functions/src/scalars/geometry.rs b/src/query/functions/src/scalars/geometry.rs index 216998a1b3602..6dbc9ab614a3b 100644 --- a/src/query/functions/src/scalars/geometry.rs +++ b/src/query/functions/src/scalars/geometry.rs @@ -23,6 +23,7 @@ use databend_common_expression::types::VariantType; use databend_common_expression::types::F64; use databend_common_expression::vectorize_with_builder_1_arg; use databend_common_expression::vectorize_with_builder_2_arg; +use databend_common_expression::vectorize_with_builder_4_arg; use databend_common_expression::FunctionDomain; use databend_common_expression::FunctionRegistry; use databend_common_io::geometry_format; @@ -34,6 +35,7 @@ use databend_common_io::GeometryDataType; use geo::dimensions::Dimensions; use geo::BoundingRect; use geo::HasDimensions; +use geo::HaversineDistance; use geo::Point; use geo_types::Polygon; use geohash::decode_bbox; @@ -77,6 +79,16 @@ pub fn register(registry: &mut FunctionRegistry) { ]); // functions + registry.register_passthrough_nullable_4_arg::, NumberType, NumberType, NumberType, NumberType, _, _>( + "haversine", + |_, _, _, _, _| FunctionDomain::Full, + vectorize_with_builder_4_arg::, NumberType, NumberType, NumberType, NumberType,>(|lat1, lon1, lat2, lon2, builder, ctx| { + let p1 = Point::new(lon1, lat1); + let p2 = Point::new(lon2, lat2); + builder.push(p1.haversine_distance(&p2) * 0.001); + }), + ); + registry.register_passthrough_nullable_1_arg::( "st_asgeojson", |_, _| FunctionDomain::MayThrow, diff --git a/src/query/functions/tests/it/scalars/geometry.rs b/src/query/functions/tests/it/scalars/geometry.rs index 5c5c2ee7d4944..314205e1592e3 100644 --- a/src/query/functions/tests/it/scalars/geometry.rs +++ b/src/query/functions/tests/it/scalars/geometry.rs @@ -26,6 +26,7 @@ use crate::scalars::run_ast; fn test_geometry() { let mut mint = Mint::new("tests/it/scalars/testdata"); let file = &mut mint.new_goldenfile("geometry.txt").unwrap(); + test_haversine(file); test_st_asewkb(file); test_st_aswkb(file); test_st_asewkt(file); @@ -56,6 +57,11 @@ fn test_geometry() { // test_st_transform(file); } +fn test_haversine(file: &mut impl Write) { + run_ast(file, "haversine(40.7127, -74.0059, 34.0500, -118.2500)", &[ + ]); +} + fn test_st_asewkb(file: &mut impl Write) { run_ast( file, 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 ffe376857eb55..a1669acb00a88 100644 --- a/src/query/functions/tests/it/scalars/testdata/function_list.txt +++ b/src/query/functions/tests/it/scalars/testdata/function_list.txt @@ -2187,6 +2187,8 @@ Functions overloads: 1 h3_to_string(UInt64 NULL) :: String NULL 0 h3_unidirectional_edge_is_valid(UInt64) :: Boolean 1 h3_unidirectional_edge_is_valid(UInt64 NULL) :: Boolean NULL +0 haversine(Float64, Float64, Float64, Float64) :: Float64 +1 haversine(Float64 NULL, Float64 NULL, Float64 NULL, Float64 NULL) :: Float64 NULL 0 humanize_number(Float64) :: String 1 humanize_number(Float64 NULL) :: String NULL 0 humanize_size(Float64) :: String diff --git a/src/query/functions/tests/it/scalars/testdata/geometry.txt b/src/query/functions/tests/it/scalars/testdata/geometry.txt index cc4cd0fa0cb3d..66299ee6a9ea4 100644 --- a/src/query/functions/tests/it/scalars/testdata/geometry.txt +++ b/src/query/functions/tests/it/scalars/testdata/geometry.txt @@ -1,3 +1,12 @@ +ast : haversine(40.7127, -74.0059, 34.0500, -118.2500) +raw expr : haversine(40.7127, minus(74.0059), 34.0500, minus(118.2500)) +checked expr : haversine(to_float64(40.7127_d128(6,4)), to_float64(minus(74.0059_d128(6,4))), to_float64(34.0500_d128(6,4)), to_float64(minus(118.2500_d128(7,4)))) +optimized expr : 4911678.33444826_f64 +output type : Float64 +output domain : {4911678.33444826..=4911678.33444826} +output : 4911678.33444826 + + ast : st_asewkb(to_geometry('SRID=4326;POINT(-122.35 37.55)')) raw expr : st_asewkb(to_geometry('SRID=4326;POINT(-122.35 37.55)')) checked expr : st_asewkb(to_geometry("SRID=4326;POINT(-122.35 37.55)")) 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 981591af887da..9dd5c4e407e11 100644 --- a/tests/sqllogictests/suites/query/functions/02_0060_function_geometry.test +++ b/tests/sqllogictests/suites/query/functions/02_0060_function_geometry.test @@ -1,6 +1,11 @@ statement ok DROP TABLE IF EXISTS t1 +query T +SELECT haversine(40.7127, -74.0059, 34.0500, -118.2500); +---- +3936.3905335559616 + statement ok SET geometry_output_format='EWKT'