Skip to content

Conversation

@paleolimbot
Copy link
Member

@paleolimbot paleolimbot commented Jan 20, 2026

This PR integrates Item Crs inputs and outputs into ST_Transform, which now has a rather complicated signature with respect to what can happen:

  • (Geometry or ItemCrs) + (String or Integer constant to) -> Geometery (type-level CRS)
  • (Geometry or ItemCrs) + (String or integer from) + (String or Integer constant to) -> Geometery (type-level CRS)
  • (Geometry or ItemCrs) + (String or Integer array/column to) -> Item CRS
  • (Geometry or ItemCrs) + (String or integer from) + (String or Integer array/column to) -> Item CRS

There's probably no great way to implement all of that cleanly but I did try to reduce repetition as much as possible.

import pandas as pd
import sedona.db

sd = sedona.db.connect()

df = pd.DataFrame({"wkt": ["POINT (0 1)", "POINT (2 3)"], "srid_from": [4326, 3857], "srid_to": [3857, 4326]})
sd.create_data_frame(df).to_view("foofy")

# Array -> Array
sd.sql("SELECT ST_Transform(ST_GeomFromWKT(wkt), srid_from, srid_to) as g FROM foofy").show()
#> ┌───────────────────────────────────────────────────────────────────────────────┐
#> │                                       g                                       │
#> │                                     struct                                    │
#> ╞═══════════════════════════════════════════════════════════════════════════════╡
#> │ {item: POINT(0 111325.1428663851), crs: EPSG:3857}                            │
#> ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
#> │ {item: POINT(0.000017966305682390428 0.00002694945852358465), crs: EPSG:4326} │
#> └───────────────────────────────────────────────────────────────────────────────┘

# Array -> Scalar
sd.sql("SELECT ST_Transform(ST_GeomFromWKT(wkt), srid_from, 4326) as g FROM foofy").show()
#> ┌───────────────────────────────────────────────────────┐
#> │                           g                           │
#> │                        geometry                       │
#> ╞═══════════════════════════════════════════════════════╡
#> │ POINT(0 1)                                            │
#> ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
#> │ POINT(0.000017966305682390428 0.00002694945852358465) │
#> └───────────────────────────────────────────────────────┘

# Scalar -> Array
sd.sql("SELECT ST_Transform(ST_GeomFromWKT(wkt), 4326, srid_to) as g FROM foofy").show()
#> ┌────────────────────────────────────────────────────┐
#> │                          g                         │
#> │                       struct                       │
#> ╞════════════════════════════════════════════════════╡
#> │ {item: POINT(0 111325.1428663851), crs: EPSG:3857} │
#> ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
#> │ {item: POINT(2 3), crs: EPSG:4326}                 │
#> └────────────────────────────────────────────────────┘

# ItemCrs -> Array
sd.sql("SELECT ST_Transform(ST_SetSRID(ST_GeomFromWKT(wkt), srid_from), srid_to) as g FROM foofy").show()
#> ┌───────────────────────────────────────────────────────────────────────────────┐
#> │                                       g                                       │
#> │                                     struct                                    │
#> ╞═══════════════════════════════════════════════════════════════════════════════╡
#> │ {item: POINT(0 111325.1428663851), crs: EPSG:3857}                            │
#> ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
#> │ {item: POINT(0.000017966305682390428 0.00002694945852358465), crs: EPSG:4326} │
#> └───────────────────────────────────────────────────────────────────────────────┘

# ItemCrs -> Scalar
sd.sql("SELECT ST_Transform(ST_SetSRID(ST_GeomFromWKT(wkt), srid_from), 4326) as g FROM foofy").show()
#> ┌───────────────────────────────────────────────────────┐
#> │                           g                           │
#> │                        geometry                       │
#> ╞═══════════════════════════════════════════════════════╡
#> │ POINT(0 1)                                            │
#> ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
#> │ POINT(0.000017966305682390428 0.00002694945852358465) │
#> └───────────────────────────────────────────────────────┘

@paleolimbot paleolimbot force-pushed the item-crs-st-transform branch from 9570f39 to 3c13875 Compare January 20, 2026 22:14
@paleolimbot paleolimbot requested a review from Copilot January 20, 2026 22:58
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements item-level CRS (Coordinate Reference System) support for the ST_Transform function, enabling transformations where the target CRS varies per row rather than being fixed at the type level.

Changes:

  • Adds support for item-level CRS input/output in ST_Transform, allowing per-row CRS specifications
  • Refactors argument handling to support both scalar and array CRS inputs with appropriate return type determination
  • Optimizes transformation by caching when both source and target CRS are constant across all rows

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 7 comments.

File Description
rust/sedona-testing/src/testers.rs Updates invoke method to compute return types with scalar arguments
rust/sedona-functions/src/executor.rs Adds support for iterating over item-crs struct arrays by extracting geometry from the "item" field
c/sedona-proj/src/st_transform.rs Major refactor to support item-crs inputs/outputs with new argument pattern matching and transformation logic
c/sedona-proj/Cargo.toml Adds sedona-common dependency

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

let maybe_from_crs = deserialize_crs(from_crs_str)?;
let maybe_to_crs = deserialize_crs(to_crs_str)?;

if let Some(crs_output) = &mut maybe_crs_ouput {
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'ouput' to 'output'.

Copilot uses AI. Check for mistakes.
paleolimbot and others added 3 commits January 20, 2026 17:03
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@paleolimbot paleolimbot marked this pull request as ready for review January 20, 2026 23:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant