Skip to content

Commit

Permalink
Merge a7505cc into 3b40416
Browse files Browse the repository at this point in the history
  • Loading branch information
elemoine committed Apr 26, 2019
2 parents 3b40416 + a7505cc commit eb52529
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 13 deletions.
22 changes: 22 additions & 0 deletions geoalchemy2/types.py
Expand Up @@ -13,6 +13,13 @@
from sqlalchemy.dialects import postgresql
from sqlalchemy.dialects.postgresql.base import ischema_names

try:
from .shape import to_shape
SHAPELY = True
except ImportError:
SHAPELY = False


from .comparator import BaseComparator, Comparator
from .elements import WKBElement, WKTElement, RasterElement, CompositeElement
from .exc import ArgumentError
Expand Down Expand Up @@ -147,6 +154,21 @@ def process(bindvalue):
return '%s' % (bindvalue.data)
else:
return 'SRID=%d;%s' % (bindvalue.srid, bindvalue.data)
elif isinstance(bindvalue, WKBElement):
if dialect.name == 'sqlite' or not bindvalue.extended:
# With SpatiaLite or when the WKBElement includes a WKB value rather
# than a EWKB value we use Shapely to convert the WKBElement to an
# EWKT string
if not SHAPELY:
raise ArgumentError('Shapely is required for handling WKBElement bind '
'values when using SpatiaLite or when the bind value '
'is a WKB rather than an EWKB')
shape = to_shape(bindvalue)
return 'SRID=%d;%s' % (bindvalue.srid, shape.wkt)
else:
# PostGIS ST_GeomFromEWKT works with EWKT strings as well
# as EWKB hex strings
return bindvalue.desc
else:
return bindvalue
return process
Expand Down
58 changes: 50 additions & 8 deletions tests/test_functional.py
Expand Up @@ -8,7 +8,7 @@
compat.register()
del compat

from sqlalchemy import create_engine, Table, MetaData, Column, Integer
from sqlalchemy import create_engine, Table, MetaData, Column, Integer, bindparam
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.engine import reflection
Expand Down Expand Up @@ -148,16 +148,13 @@ def teardown(self):
def test_insert(self):
conn = self.conn

# Issue two inserts using DBAPI's executemany() method. This tests
# the Geometry type's bind_processor and bind_expression functions.
# Issue inserts using DBAPI's executemany() method. This tests the
# Geometry type's bind_processor and bind_expression functions.
conn.execute(Lake.__table__.insert(), [
{'geom': 'SRID=4326;LINESTRING(0 0,1 1)'},
{'geom': WKTElement('LINESTRING(0 0,2 2)', srid=4326)},
{'geom': WKTElement('SRID=4326;LINESTRING(0 0,2 2)', extended=True)}

# Having WKBElement objects as bind values is not supported, so
# the following does not work:
# {'geom': from_shape(LineString([[0, 0], [3, 3]], srid=4326)}
{'geom': WKTElement('SRID=4326;LINESTRING(0 0,2 2)', extended=True)},
{'geom': from_shape(LineString([[0, 0], [3, 3]]), srid=4326)}
])

results = conn.execute(Lake.__table__.select())
Expand All @@ -184,6 +181,51 @@ def test_insert(self):
srid = session.execute(row[1].ST_SRID()).scalar()
assert srid == 4326

row = rows[3]
assert isinstance(row[1], WKBElement)
wkt = session.execute(row[1].ST_AsText()).scalar()
assert wkt == 'LINESTRING(0 0,3 3)'
srid = session.execute(row[1].ST_SRID()).scalar()
assert srid == 4326


class TestSelectBindParam():

def setup(self):
metadata.drop_all(checkfirst=True)
metadata.create_all()
self.conn = engine.connect()
self.conn.execute(Lake.__table__.insert(), {'geom': 'SRID=4326;LINESTRING(0 0,1 1)'})

def teardown(self):
self.conn.close()
metadata.drop_all()

def test_select_bindparam(self):
s = Lake.__table__.select().where(Lake.__table__.c.geom == bindparam('geom'))
results = self.conn.execute(s, geom='SRID=4326;LINESTRING(0 0,1 1)')
rows = results.fetchall()

row = rows[0]
assert isinstance(row[1], WKBElement)
wkt = session.execute(row[1].ST_AsText()).scalar()
assert wkt == 'LINESTRING(0 0,1 1)'
srid = session.execute(row[1].ST_SRID()).scalar()
assert srid == 4326

def test_select_bindparam_WKBElement(self):
s = Lake.__table__.select().where(Lake.__table__.c.geom == bindparam('geom'))
wkbelement = from_shape(LineString([[0, 0], [1, 1]]), srid=4326)
results = self.conn.execute(s, geom=wkbelement)
rows = results.fetchall()

row = rows[0]
assert isinstance(row[1], WKBElement)
wkt = session.execute(row[1].ST_AsText()).scalar()
assert wkt == 'LINESTRING(0 0,1 1)'
srid = session.execute(row[1].ST_SRID()).scalar()
assert srid == 4326


class TestInsertionORM():

Expand Down
14 changes: 9 additions & 5 deletions tests/test_functional_spatialite.py
Expand Up @@ -72,11 +72,8 @@ def test_insert(self):
# the Geometry type's bind_processor and bind_expression functions.
conn.execute(Lake.__table__.insert(), [
{'geom': 'SRID=4326;LINESTRING(0 0,1 1)'},
{'geom': WKTElement('LINESTRING(0 0,2 2)', srid=4326)}

# Having WKBElement objects as bind values is not supported, so
# the following does not work:
# {'geom': from_shape(LineString([[0, 0], [3, 3]], srid=4326)}
{'geom': WKTElement('LINESTRING(0 0,2 2)', srid=4326)},
{'geom': from_shape(LineString([[0, 0], [3, 3]]), srid=4326)}
])

results = conn.execute(Lake.__table__.select())
Expand All @@ -96,6 +93,13 @@ def test_insert(self):
srid = session.execute(row[1].ST_SRID()).scalar()
assert srid == 4326

row = rows[2]
assert isinstance(row[1], WKBElement)
wkt = session.execute(row[1].ST_AsText()).scalar()
assert wkt == 'LINESTRING(0 0, 3 3)'
srid = session.execute(row[1].ST_SRID()).scalar()
assert srid == 4326


class TestInsertionORM():

Expand Down

0 comments on commit eb52529

Please sign in to comment.