Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specific process for geometries with Z or M coordinate with SpatiaLite dialect #506

Merged
merged 12 commits into from
Apr 23, 2024
Merged
2 changes: 1 addition & 1 deletion doc/spatialite_tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Declare a Mapping
Now that we have a working connection we can go ahead and create a mapping between
a Python class and a database table::

>>> from sqlalchemy.ext.declarative import declarative_base
>>> from sqlalchemy.orm import declarative_base
>>> from sqlalchemy import Column, Integer, String
>>> from geoalchemy2 import Geometry
>>>
Expand Down
9 changes: 8 additions & 1 deletion geoalchemy2/types/dialects/sqlite.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,16 @@ def bind_processor_process(spatial_type, bindvalue):
else:
return "SRID=%d;%s" % (bindvalue.srid, bindvalue.data)
sdp5 marked this conversation as resolved.
Show resolved Hide resolved
elif isinstance(bindvalue, WKBElement):
if bindvalue.srid == -1:
bindvalue.srid = spatial_type.srid
sdp5 marked this conversation as resolved.
Show resolved Hide resolved
# With SpatiaLite we use Shapely to convert the WKBElement to an EWKT string
shape = to_shape(bindvalue)
return "SRID=%d;%s" % (bindvalue.srid, shape.wkt)
result = "SRID=%d;%s" % (bindvalue.srid, shape.wkt)
if shape.has_z:
# shapely.wkb.loads returns geom_type with a 'Z', for example, 'LINESTRING Z'
# which is a limitation with SpatiaLite. Hence, a temporary fix.
result = result.replace("Z ", "")
return result
elif isinstance(bindvalue, RasterElement):
return "%s" % (bindvalue.data)
else:
Expand Down
35 changes: 35 additions & 0 deletions tests/test_functional_sqlite.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,41 @@ def test_explicit_schema(self, conn):
# Drop the table
t.drop(bind=conn)

def test_3d_geometry(self, conn, metadata):
sdp5 marked this conversation as resolved.
Show resolved Hide resolved
# Define the table
col = Column(
"geom",
Geometry(geometry_type=None, srid=4326, spatial_index=False),
nullable=False,
)
t = Table(
"3d_geom_type",
metadata,
Column("id", Integer, primary_key=True),
col,
)

# Create the table
t.create(bind=conn)

# Should be 'LINESTRING Z (0 0 0, 1 1 1)'
# Read comments at geoalchemy2/types/dialects/sqlite.py#L22
elements = {"geom": "SRID=4326;LINESTRING (0 0 0, 1 1 1)"}
conn.execute(t.insert(), elements)

with pytest.raises((IntegrityError, OperationalError)):
with conn.begin_nested():
# This returns a NULL for the geom field.
conn.execute(t.insert(), [{"geom": "SRID=4326;LINESTRING Z (0 0 0, 1 1 1)"}])

results = conn.execute(t.select())
rows = results.fetchall()

assert len(rows) == 1

# Drop the table
t.drop(bind=conn)


class TestIndex:
@pytest.fixture
Expand Down