[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