summaryrefslogtreecommitdiff
path: root/examples/postgis/postgis.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2012-08-17 18:35:25 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2012-08-17 18:35:25 -0400
commita2468c8a31c8308cdb5740f2401e9dedd003836e (patch)
treee4cc3eb17c59f678ea2919ecd0880f1df7854b6e /examples/postgis/postgis.py
parent20fa7fe2b85d356e3da08191f01d7528ded42033 (diff)
downloadsqlalchemy-a2468c8a31c8308cdb5740f2401e9dedd003836e.tar.gz
- [feature] To complement [ticket:2547], types
can now provide "bind expressions" and "column expressions" which allow compile-time injection of SQL expressions into statements on a per-column or per-bind level. This is to suit the use case of a type which needs to augment bind- and result- behavior at the SQL level, as opposed to in the Python level. Allows for schemes like transparent encryption/ decryption, usage of Postgis functions, etc. [ticket:1534] - update postgis example fully. - still need to repair the result map propagation here to be transparent for cases like "labeled column".
Diffstat (limited to 'examples/postgis/postgis.py')
-rw-r--r--examples/postgis/postgis.py31
1 files changed, 13 insertions, 18 deletions
diff --git a/examples/postgis/postgis.py b/examples/postgis/postgis.py
index 1239d66a4..77fcacba1 100644
--- a/examples/postgis/postgis.py
+++ b/examples/postgis/postgis.py
@@ -38,7 +38,6 @@ class TextualGisElement(GisElement, expression.Function):
"""
def __init__(self, desc, srid=-1):
- assert isinstance(desc, basestring)
self.desc = desc
expression.Function.__init__(self, "ST_GeomFromText", desc, srid)
@@ -63,21 +62,30 @@ class Geometry(UserDefinedType):
# override the __eq__() operator
def __eq__(self, other):
- return self.op('~=')(_to_postgis(other))
+ return self.op('~=')(other)
# add a custom operator
def intersects(self, other):
- return self.op('&&')(_to_postgis(other))
+ return self.op('&&')(other)
# any number of GIS operators can be overridden/added here
# using the techniques above.
+ def _coerce_compared_value(self, op, value):
+ return self
+
def get_col_spec(self):
return self.name
+ def bind_expression(self, bindvalue):
+ return TextualGisElement(bindvalue)
+
+ def column_expression(self, col):
+ return func.ST_AsText(col, type_=self)
+
def bind_processor(self, dialect):
def process(value):
- if value is not None:
+ if isinstance(value, GisElement):
return value.desc
else:
return value
@@ -165,8 +173,6 @@ def setup_ddl_events():
table.columns = table.info.pop('_saved_columns')
setup_ddl_events()
-# ORM integration
-
def _to_postgis(value):
"""Interpret a value as a GIS-compatible construct.
@@ -188,17 +194,6 @@ def _to_postgis(value):
else:
raise Exception("Invalid type")
-# without importing "orm", the "attribute_instrument"
-# event isn't even set up.
-from sqlalchemy import orm
-
-@event.listens_for(type, "attribute_instrument")
-def attribute_instrument(cls, key, inst):
- type_ = getattr(inst, "type", None)
- if isinstance(type_, Geometry):
- @event.listens_for(inst, "set", retval=True)
- def set_value(state, value, oldvalue, initiator):
- return _to_postgis(value)
# illustrate usage
@@ -245,7 +240,7 @@ if __name__ == '__main__':
session.commit()
# after flush and/or commit, all the TextualGisElements become PersistentGisElements.
- assert str(r.road_geom) == "01020000000200000000000000B832084100000000E813104100000000283208410000000088601041"
+ assert str(r.road_geom) == "LINESTRING(198231 263418,198213 268322)"
r1 = session.query(Road).filter(Road.road_name=='Graeme Ave').one()