Skip to content

Commit

Permalink
Fix reading from DuckDB with only geometry column (#625)
Browse files Browse the repository at this point in the history
Follow up for #623 and #622, based on input from
#619 (reply in thread)
  • Loading branch information
kylebarron authored Sep 3, 2024
1 parent 09c0005 commit 3f0780d
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 3 deletions.
13 changes: 11 additions & 2 deletions lonboard/_geoarrow/_duckdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,10 @@ def _from_geometry(
crs: Optional[Union[str, pyproj.CRS]] = None,
) -> Table:
other_col_names = [name for i, name in enumerate(rel.columns) if i != geom_col_idx]
non_geo_table = Table.from_arrow(rel.select(*other_col_names).arrow())
if other_col_names:
non_geo_table = Table.from_arrow(rel.select(*other_col_names).arrow())
else:
non_geo_table = None
geom_col_name = rel.columns[geom_col_idx]

# A poor-man's string interpolation check
Expand Down Expand Up @@ -142,7 +145,13 @@ def _from_geometry(

metadata = _make_geoarrow_field_metadata(EXTENSION_NAME.WKB, crs)
geom_field = geom_table.schema.field(0).with_metadata(metadata)
return non_geo_table.append_column(geom_field, geom_table.column(0))
if non_geo_table is not None:
return non_geo_table.append_column(geom_field, geom_table.column(0))
else:
# Need to set geospatial metadata onto the Arrow table, because the table
# returned from duckdb has none.
new_schema = geom_table.schema.set(0, geom_field)
return geom_table.with_schema(new_schema)


def _from_geoarrow(
Expand Down
18 changes: 17 additions & 1 deletion tests/test_duckdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,6 @@ def test_create_table_as_custom_con():


def test_geometry_only_column():
# https://github.com/developmentseed/lonboard/issues/622
con = duckdb.connect()
sql = f"""
INSTALL spatial;
Expand All @@ -222,3 +221,20 @@ def test_geometry_only_column():

m = viz(con.table("data"), con=con)
assert isinstance(m.layers[0], ScatterplotLayer)


def test_geometry_only_column_type_geometry():
# For WKB parsing
pytest.importorskip("shapely")

# https://github.com/developmentseed/lonboard/issues/622
con = duckdb.connect()
sql = f"""
INSTALL spatial;
LOAD spatial;
SELECT geom FROM ST_Read("{cities_gdal_path}");
"""
query = con.sql(sql)

# Should create layer without erroring
_layer = ScatterplotLayer.from_duckdb(query, con)

0 comments on commit 3f0780d

Please sign in to comment.