Skip to content

Commit

Permalink
feat(geospatial): add support for duckdb operations on literals (#8570)
Browse files Browse the repository at this point in the history
  • Loading branch information
ncclementi authored Mar 8, 2024
1 parent 306cdad commit b4c4369
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 0 deletions.
4 changes: 4 additions & 0 deletions ibis/backends/duckdb/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1178,6 +1178,10 @@ def _run_pre_execute_hooks(self, expr: ir.Expr) -> None:
)
elif started is False:
self._record_batch_readers_consumed[t.name] = True

if expr.op().find((ops.GeoSpatialUnOp, ops.GeoSpatialBinOp)):
self.load_extension("spatial")

super()._run_pre_execute_hooks(expr)

def to_pyarrow_batches(
Expand Down
28 changes: 28 additions & 0 deletions ibis/backends/duckdb/tests/test_geospatial.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,3 +306,31 @@ def test_literal_geospatial_inferred(con, shp, expected, snapshot):
def test_load_geo_example(con):
t = ibis.examples.zones.fetch(backend=con)
assert t.geom.type().is_geospatial()


# For the next two tests we really want to ensure that
# load_extenstion("spatial") hasn't been run yet. So we create a new connection
# instead of using the con fixture.

# geospatial literal object,
geo_line_lit = ibis.literal(
shapely.LineString([[0, 0], [1, 0], [1, 1]]), type="geometry"
)


@pytest.mark.parametrize("geo_line_lit", [geo_line_lit])
def test_geo_unop_geo_literals(geo_line_lit):
# GeoSpatialUnOp operation on a geospatial literal
con = ibis.duckdb.connect()
expr = geo_line_lit.length()

assert con.execute(expr) == 2


@pytest.mark.parametrize("geo_line_lit", [geo_line_lit])
def test_geo_binop_geo_literals(geo_line_lit):
# GeoSpatialBinOp operation on a geospatial literal
con = ibis.duckdb.connect()
expr = geo_line_lit.distance(shapely.Point(0, 0))

assert con.execute(expr) == 0

0 comments on commit b4c4369

Please sign in to comment.