/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/Model/postgisdb.py
ViewVC logotype

Diff of /branches/WIP-pyshapelib-bramz/Thuban/Model/postgisdb.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1605 by bh, Tue Aug 19 11:00:40 2003 UTC revision 1660 by bh, Tue Aug 26 12:54:45 2003 UTC
# Line 20  import wellknowntext Line 20  import wellknowntext
20    
21  from data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, SHAPETYPE_POINT, RAW_WKT  from data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, SHAPETYPE_POINT, RAW_WKT
22    
23    def has_postgis_support():
24        """Return whether this Thuban instance supports PostGIS connections
25    
26        Having PostGIS support means that the psycopg module can be
27        imported.
28        """
29        return psycopg is not None
30    
31    def psycopg_version():
32        return psycopg.__version__
33    
34  if psycopg is not None:  if psycopg is not None:
35      type_map = [(psycopg.STRING, table.FIELDTYPE_STRING),      type_map = [(psycopg.STRING, table.FIELDTYPE_STRING),
36                  (psycopg.INTEGER, table.FIELDTYPE_INT),                  (psycopg.INTEGER, table.FIELDTYPE_INT),
37                  (psycopg.FLOAT, table.FIELDTYPE_DOUBLE)]                  (psycopg.FLOAT, table.FIELDTYPE_DOUBLE)]
38    
39    
40    class ConnectionError(Exception):
41    
42        """Class for exceptions occurring when establishing a Databse connection"""
43    
44    
45  class PostGISConnection:  class PostGISConnection:
46    
47      """Represent a PostGIS database      """Represent a PostGIS database
# Line 48  class PostGISConnection: Line 64  class PostGISConnection:
64          self.user = user          self.user = user
65          self.password = password          self.password = password
66          self.dbtype = dbtype          self.dbtype = dbtype
67            self.connect()
68    
69        def connect(self):
70            """Internal: Establish the database connection"""
71          params = []          params = []
72          for name in ("host", "port", "dbname", "user", "password"):          for name in ("host", "port", "dbname", "user", "password"):
73              val = getattr(self, name)              val = getattr(self, name)
74              if val:              if val:
75                  params.append("%s=%s" % (name, val))                  params.append("%s=%s" % (name, val))
76          self.connection = psycopg.connect(" ".join(params))          try:
77                self.connection = psycopg.connect(" ".join(params))
78            except psycopg.OperationalError, val:
79                raise ConnectionError(str(val))
80    
81          # determine the OID for the geometry type. This is PostGIS          # determine the OID for the geometry type. This is PostGIS
82          # specific.          # specific.
# Line 67  class PostGISConnection: Line 90  class PostGISConnection:
90          else:          else:
91              raise ValueError("Can't determine postgres type of geometries")              raise ValueError("Can't determine postgres type of geometries")
92    
93        def BriefDescription(self):
94            """Return a brief, one-line description of the connection
95    
96            The return value is suitable for a list box of all database
97            connections.
98            """
99            return ("postgis://%(user)s@%(host)s:%(port)s/%(dbname)s"
100                    % self.__dict__)
101    
102      def Close(self):      def Close(self):
103          """Close the database connection"""          """Close the database connection"""
104          self.connection.close()          self.connection.close()
# Line 140  class PostGISTable: Line 172  class PostGISTable:
172                             % (", ".join([col.name for col in self.columns]),                             % (", ".join([col.name for col in self.columns]),
173                                self.tablename))                                self.tablename))
174    
175        def DBConnection(self):
176            """Return the dbconnection used by the table"""
177            return self.db
178    
179        def TableName(self):
180            """Return the name of the table in the database"""
181            return self.tablename
182    
183        def Title(self):
184            """Return the title of the table.
185    
186            The title is currently fixed and equal to the tablename
187            """
188            return self.tablename
189    
190      def Dependencies(self):      def Dependencies(self):
191          """Return an empty tuple because a PostGISTable depends on nothing else          """Return an empty tuple because a PostGISTable depends on nothing else
192          """          """
# Line 247  class PostGISShape: Line 294  class PostGISShape:
294    
295    
296  shapetype_map = {"POLYGON": SHAPETYPE_POLYGON,  shapetype_map = {"POLYGON": SHAPETYPE_POLYGON,
297                     "MULTIPOLYGON": SHAPETYPE_POLYGON,
298                   "MULTILINESTRING": SHAPETYPE_ARC,                   "MULTILINESTRING": SHAPETYPE_ARC,
299                   "POINT": SHAPETYPE_POINT}                   "POINT": SHAPETYPE_POINT}
300    
# Line 292  class PostGISShapeStore(PostGISTable): Line 340  class PostGISShapeStore(PostGISTable):
340          y=[]          y=[]
341          cursor = self.db.cursor()          cursor = self.db.cursor()
342          try:          try:
343              stmt = ("SELECT AsText(Envelope(%s)) FROM %s;"              # Using the extent function is postgis specific. An OGC
344                      % (self.geometry_column, self.tablename))              # Simple Features compliant solution would be to use a query
345              cursor.execute(stmt)              # like "SELECT AsText(Envelope(the_geom)) FROM mytable;" and
346                # calculate the bounding box by hand from that
347                cursor.execute("SELECT extent(%s) FROM %s;"
348                               % (self.geometry_column, self.tablename))
349              result = cursor.fetchone()              result = cursor.fetchone()
350              while result:              if result:
351                  result = result[0]                  (minx, miny), (maxx, maxy) \
352                  # Here we must do some parsing through the result string                        = wellknowntext.parse_wkt_thuban(result[0])[0]
353                  # to get the points out of the polygon which representes                  return (minx, miny, maxx, maxy)
                 # the bounding box The first and the last point of a  
                 # polygon are identical  
                 result = result.split("(")[2]  
                 result = result.split(")")[0]  
                 points = result.split(",")  
                 del points[4] # Remove the last point  
                 for point in points:  
                     px, py = point.split()  
                     x.append(float(px))  
                     y.append(float(py))  
                 result = cursor.fetchone()  
354          finally:          finally:
355              cursor.close()              cursor.close()
         if not x:  
             # Empty table  
             return None  
         return (min(x), min(y), max(x), max(y))  
356    
357      def Shape(self, shapeid):      def Shape(self, shapeid):
358          cursor = self.db.cursor()          cursor = self.db.cursor()
# Line 326  class PostGISShapeStore(PostGISTable): Line 362  class PostGISShapeStore(PostGISTable):
362          cursor.close()          cursor.close()
363          return PostGISShape(shapeid, wkt)          return PostGISShape(shapeid, wkt)
364    
365        def AllShapes(self):
366            cursor = self.db.cursor()
367            cursor.execute("SELECT gid, AsText(%s) FROM %s ORDER BY gid"
368                           % (self.geometry_column, self.tablename))
369            while 1:
370                result = cursor.fetchone()
371                if result is None:
372                    return
373                yield PostGISShape(result[0], result[1])
374    
375    
376      def ShapesInRegion(self, bbox):      def ShapesInRegion(self, bbox):
377          """Generate all shapes overlapping the region given by bbox."""          """Generate all shapes overlapping the region given by bbox."""
378          # IMPORTANT:This will work for PostGIS < 0.8          # IMPORTANT:This will work for PostGIS < 0.8
# Line 341  class PostGISShapeStore(PostGISTable): Line 388  class PostGISShapeStore(PostGISTable):
388          while 1:          while 1:
389              result = cursor.fetchone()              result = cursor.fetchone()
390              if result is None:              if result is None:
391                  raise StopIteration                  return
392              yield PostGISShape(result[0], result[1])              yield PostGISShape(result[0], result[1])

Legend:
Removed from v.1605  
changed lines
  Added in v.1660

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26