[Featureserver] PostGis w/o OGR
Josh Livni
mailing_lists at umbrellaconsulting.com
Tue Dec 11 13:16:30 EST 2007
I recently had the need to remove the OGR dependency from PostGIS.py,
which is nice if you want to run FeatureServer with PostGIS on a box
where installing OGR could be a hassle.
If anyone else would find this simple modification helpful, please feel
free to make use of the attached patch.
Note: I've tested the patch with simple and multi geometries, on tables
with mixed simple and multi geometries. As far as I can tell I've got
it so it returns the same thing it used to (eg it strips out all but the
first geometry in a multigeometry situation), however it's extremely
possible that I missed a case in there somewhere.
If anyone else wants to test this patch so Chris might feel extra
comfortable committing it (as he noted, it could be considered a
regression going from OGR parsing to kludgy string manipulation), please
test away and post results. Either way, hopefully someone finds it useful.
Cheers,
-Josh
-------------- next part --------------
Index: PostGIS.py
===================================================================
--- PostGIS.py (revision 359)
+++ PostGIS.py (working copy)
@@ -1,13 +1,12 @@
from FeatureServer.DataSource import DataSource, Feature
-from FeatureServer.DataSource.OGR import OGR
-import psycopg, copy, re, ogr
+import psycopg, copy, re
class PostGIS (DataSource):
"""PostGIS datasource. Setting up the table is beyond the scope of
FeatureServer."""
wkt_linestring_match = re.compile(r'\(([^()]+)\)')
- def __init__(self, name, srid = 4326, fid = "ogc_fid", geometry = "wkb_geometry", order = "", writable = True, **args):
+ def __init__(self, name, srid = 4326, fid = "ogc_fid", geometry = "the_geom", order = "", writable = True, **args):
DataSource.__init__(self, name, **args)
self.table = args["layer"]
self.fid_col = fid
@@ -77,13 +76,6 @@
else:
raise Exception("Couldn't create WKT from geometry of type %s (%s). Only Point, Line, Polygon are supported." % (geom['type'], geom))
- def from_wkb (self, geom):
- try:
- ogrgeom = ogr.CreateGeometryFromWkb(geom)
- return OGR.freeze_geometry(ogrgeom)
- except:
- return None
-
def from_wkt (self, geom):
coords = []
for line in self.wkt_linestring_match.findall(geom):
@@ -99,9 +91,21 @@
coords = coords[0]
elif geom.startswith("POLYGON"):
geomtype = "Polygon"
+ elif geom.startswith("MULTIPOINT"):
+ #return just the 1st point
+ return self.from_wkt('POINT' + geom[10:14] + ')')
+ elif geom.startswith("MULTILINESTRING"):
+ #test to see if it's really a multilinestring, or just pretending:
+ if geom.find(',(') >= 0:
+ return self.from_wkt('LINESTRING' + geom[11:geom.index(',(')])
+ else:
+ return self.from_wkt('LINESTRING' + geom[11:])
+ elif geom.startswith("MULTIPOLYGON"):
+ #return only the first polygon, like ogr does
+ return self.from_wkt('POLYGON' + geom[13:geom.index(',((')])
else:
geomtype = geom[:geom.index["("]]
- raise Error("Unsupported geometry type %s" % geomtype)
+ raise Exception("Unsupported geometry type %s" % geomtype)
return {"type": geomtype, "coordinates": coords}
def id_sequence (self):
@@ -142,7 +146,7 @@
cursor = self.db.cursor()
if action.id:
- sql = "SELECT AsBinary(%s) as fs_binary_geom_col, * FROM \"%s\" WHERE %s = %%(%s)d" % (
+ sql = "SELECT AsText(%s) as fs_text_geom, * FROM \"%s\" WHERE %s = %%(%s)d" % (
self.geom_col, self.table, self.fid_col, self.fid_col )
cursor.execute(str(sql), {self.fid_col: action.id})
result = [cursor.fetchone()]
@@ -157,7 +161,7 @@
filters = self.feature_predicates(match)
attrs = action.attributes
- sql = "SELECT AsBinary(%s) as fs_binary_geom_col, * FROM \"%s\"" % (self.geom_col, self.table)
+ sql = "SELECT AsText(%s) as fs_text_geom, * FROM \"%s\"" % (self.geom_col, self.table)
if filters:
sql += " WHERE " + " AND ".join(filters)
if self.order:
@@ -175,13 +179,13 @@
features = []
for row in result:
props = dict(zip(columns, row))
- geom = self.from_wkb(props['fs_binary_geom_col'])
+ geom = self.from_wkt(props['fs_text_geom'])
id = props[self.fid_col]
- del props[self.fid_col]
+ del props[self.fid_col]
del props[self.geom_col]
- del props['fs_binary_geom_col']
+ del props['fs_text_geom']
for key, value in props.items():
- if isinstance(value, str): props[key] = unicode(value, "utf-8")
- if (geom):
- features.append( Feature( id, geom, props ) )
+ if isinstance(value, str): props[key] = unicode(value, "utf-8")
+ if (geom):
+ features.append( Feature( id, geom, props ) )
return features
More information about the Featureserver
mailing list