dbmanager: be sure to close db cursors (fix #7679)

This commit is contained in:
Giuseppe Sucameli 2013-10-24 23:26:02 +02:00
parent 86ddc49acf
commit 5f5cd4cca9

View File

@ -66,22 +66,22 @@ class PostGisDBConnector(DBConnector):
def _checkSpatial(self):
""" check whether postgis_version is present in catalog """
c = self._get_cursor()
self._execute(c, u"SELECT COUNT(*) FROM pg_proc WHERE proname = 'postgis_version'")
self.has_spatial = c.fetchone()[0] > 0
c = self._execute(None, u"SELECT COUNT(*) FROM pg_proc WHERE proname = 'postgis_version'")
self.has_spatial = self._fetchone(c)[0] > 0
self._close_cursor(c)
return self.has_spatial
def _checkRaster(self):
""" check whether postgis_version is present in catalog """
c = self._get_cursor()
self._execute(c, u"SELECT COUNT(*) FROM pg_proc WHERE proname = 'postgis_raster_lib_version'")
self.has_raster = c.fetchone()[0] > 0
c = self._execute(None, u"SELECT COUNT(*) FROM pg_proc WHERE proname = 'postgis_raster_lib_version'")
self.has_raster = self._fetchone(c)[0] > 0
self._close_cursor(c)
return self.has_raster
def _checkGeometryColumnsTable(self):
c = self._get_cursor()
self._execute(c, u"SELECT relkind = 'v' FROM pg_class WHERE relname = 'geometry_columns' AND relkind IN ('v', 'r')")
res = c.fetchone()
c = self._execute(None, u"SELECT relkind = 'v' FROM pg_class WHERE relname = 'geometry_columns' AND relkind IN ('v', 'r')")
res = self._fetchone(c)
self._close_cursor(c)
self.has_geometry_columns = (res != None and len(res) != 0)
if not self.has_geometry_columns:
@ -94,9 +94,9 @@ class PostGisDBConnector(DBConnector):
return self.has_geometry_columns
def _checkRasterColumnsTable(self):
c = self._get_cursor()
self._execute(c, u"SELECT relkind = 'v' FROM pg_class WHERE relname = 'raster_columns' AND relkind IN ('v', 'r')")
res = c.fetchone()
c = self._execute(None, u"SELECT relkind = 'v' FROM pg_class WHERE relname = 'raster_columns' AND relkind IN ('v', 'r')")
res = self._fetchone(c)
self._close_cursor(c)
self.has_raster_columns = (res != None and len(res) != 0)
if not self.has_raster_columns:
@ -108,9 +108,10 @@ class PostGisDBConnector(DBConnector):
return self.has_raster_columns
def getInfo(self):
c = self._get_cursor()
self._execute(c, u"SELECT version()")
return c.fetchone()
c = self._execute(None, u"SELECT version()")
res = self._fetchone(c)
self._close_cursor(c)
return res
def getSpatialInfo(self):
""" returns tuple about postgis support:
@ -123,13 +124,13 @@ class PostGisDBConnector(DBConnector):
if not self.has_spatial:
return
c = self._get_cursor()
try:
self._execute(c, u"SELECT postgis_lib_version(), postgis_geos_version(), postgis_proj_version(), postgis_scripts_installed(), postgis_scripts_released()")
c = self._execute(None, u"SELECT postgis_lib_version(), postgis_geos_version(), postgis_proj_version(), postgis_scripts_installed(), postgis_scripts_released()")
except DbError:
return
return c.fetchone()
res = self._fetchone(c)
self._close_cursor(c)
return res
def hasSpatialSupport(self):
return self.has_spatial
@ -159,17 +160,19 @@ class PostGisDBConnector(DBConnector):
def getDatabasePrivileges(self):
""" db privileges: (can create schemas, can create temp. tables) """
sql = u"SELECT has_database_privilege(%(d)s, 'CREATE'), has_database_privilege(%(d)s, 'TEMP')" % { 'd' : self.quoteString(self.dbname) }
c = self._get_cursor()
self._execute(c, sql)
return c.fetchone()
c = self._execute(None, sql)
res = self._fetchone(c)
self._close_cursor(c)
return res
def getSchemaPrivileges(self, schema):
""" schema privileges: (can create new objects, can access objects in schema) """
schema = 'current_schema()' if schema == None else self.quoteString(schema)
sql = u"SELECT has_schema_privilege(%(s)s, 'CREATE'), has_schema_privilege(%(s)s, 'USAGE')" % { 's' : schema }
c = self._get_cursor()
self._execute(c, sql)
return c.fetchone()
c = self._execute(None, sql)
res = self._fetchone(c)
self._close_cursor(c)
return res
def getTablePrivileges(self, table):
""" table privileges: (select, insert, update, delete) """
@ -182,17 +185,20 @@ class PostGisDBConnector(DBConnector):
t = self.quoteId( table )
sql = u"""SELECT has_table_privilege(%(t)s, 'SELECT'), has_table_privilege(%(t)s, 'INSERT'),
has_table_privilege(%(t)s, 'UPDATE'), has_table_privilege(%(t)s, 'DELETE')""" % { 't': self.quoteString(t) }
c = self._get_cursor()
self._execute(c, sql)
return c.fetchone()
c = self._execute(None, sql)
res = self._fetchone(c)
self._close_cursor(c)
return res
def getSchemas(self):
""" get list of schemas in tuples: (oid, name, owner, perms) """
c = self._get_cursor()
sql = u"SELECT oid, nspname, pg_get_userbyid(nspowner), nspacl, pg_catalog.obj_description(oid) FROM pg_namespace WHERE nspname !~ '^pg_' AND nspname != 'information_schema' ORDER BY nspname"
self._execute(c, sql)
return c.fetchall()
c = self._execute(None, sql)
res = self._fetchall(c)
self._close_cursor(c)
return res
def getTables(self, schema=None):
""" get list of tables """
@ -222,8 +228,6 @@ class PostGisDBConnector(DBConnector):
except DbError:
pass
c = self._get_cursor()
sys_tables = [ "spatial_ref_sys", "geography_columns", "geometry_columns",
"raster_columns", "raster_overviews" ]
@ -242,13 +246,13 @@ class PostGisDBConnector(DBConnector):
WHERE cla.relkind IN ('v', 'r') """ + schema_where + """
ORDER BY nsp.nspname, cla.relname"""
self._execute(c, sql)
for tbl in c.fetchall():
c = self._execute(None, sql)
for tbl in self._fetchall(c):
if tablenames.count( (tbl[1], tbl[0]) ) <= 0:
item = list(tbl)
item.insert(0, Table.TableType)
items.append( item )
self._close_cursor(c)
return sorted( items, cmp=lambda x,y: cmp((x[2],x[1]), (y[2],y[1])) )
@ -272,8 +276,6 @@ class PostGisDBConnector(DBConnector):
if not self.has_spatial:
return []
c = self._get_cursor()
if schema:
schema_where = u" AND nspname = %s " % self.quoteString(schema)
else:
@ -313,13 +315,14 @@ class PostGisDBConnector(DBConnector):
WHERE cla.relkind IN ('v', 'r') """ + schema_where + """
ORDER BY nsp.nspname, cla.relname, att.attname"""
self._execute(c, sql)
items = []
for i, tbl in enumerate(c.fetchall()):
c = self._execute(None, sql)
for i, tbl in enumerate(self._fetchall(c)):
item = list(tbl)
item.insert(0, Table.VectorType)
items.append( item )
self._close_cursor(c)
return items
@ -345,8 +348,6 @@ class PostGisDBConnector(DBConnector):
if not self.has_raster:
return []
c = self._get_cursor()
if schema:
schema_where = u" AND nspname = %s " % self.quoteString(schema)
else:
@ -387,25 +388,26 @@ class PostGisDBConnector(DBConnector):
WHERE cla.relkind IN ('v', 'r') """ + schema_where + """
ORDER BY nsp.nspname, cla.relname, att.attname"""
self._execute(c, sql)
items = []
for i, tbl in enumerate(c.fetchall()):
c = self._execute(None, sql)
for i, tbl in enumerate(self._fetchall(c)):
item = list(tbl)
item.insert(0, Table.RasterType)
items.append( item )
self._close_cursor(c)
return items
def getTableRowCount(self, table):
c = self._get_cursor()
self._execute( c, u"SELECT COUNT(*) FROM %s" % self.quoteId(table) )
return c.fetchone()[0]
c = self._execute(None, u"SELECT COUNT(*) FROM %s" % self.quoteId(table))
res = self._fetchone(c)[0]
self._close_cursor(c)
return res
def getTableFields(self, table):
""" return list of columns in table """
c = self._get_cursor()
schema, tablename = self.getSchemaTableName(table)
schema_where = u" AND nspname=%s " % self.quoteString(schema) if schema is not None else ""
@ -428,8 +430,10 @@ class PostGisDBConnector(DBConnector):
a.attnum > 0 AND c.relname=%s %s
ORDER BY a.attnum""" % (self.quoteString(tablename), schema_where)
self._execute(c, sql)
return c.fetchall()
c = self._execute(None, sql)
res = self._fetchall(c)
self._close_cursor(c)
return res
def getTableIndexes(self, table):
""" get info about table's indexes. ignore primary key constraint index, they get listed in constaints """
@ -442,13 +446,13 @@ class PostGisDBConnector(DBConnector):
JOIN pg_namespace nsp ON pg_class.relnamespace = nsp.oid
WHERE pg_class.relname=%s %s
AND indisprimary != 't' """ % (self.quoteString(tablename), schema_where)
c = self._get_cursor()
self._execute(c, sql)
return c.fetchall()
c = self._execute(None, sql)
res = self._fetchall(c)
self._close_cursor(c)
return res
def getTableConstraints(self, table):
c = self._get_cursor()
schema, tablename = self.getSchemaTableName(table)
schema_where = u" AND nspname=%s " % self.quoteString(schema) if schema is not None else ""
@ -460,12 +464,13 @@ class PostGisDBConnector(DBConnector):
JOIN pg_namespace nsp ON t.relnamespace = nsp.oid
WHERE t.relname = %s %s """ % (self.quoteString(tablename), schema_where)
self._execute(c, sql)
return c.fetchall()
c = self._execute(None, sql)
res = self._fetchall(c)
self._close_cursor(c)
return res
def getTableTriggers(self, table):
c = self._get_cursor()
schema, tablename = self.getSchemaTableName(table)
schema_where = u" AND nspname=%s " % self.quoteString(schema) if schema is not None else ""
@ -476,8 +481,10 @@ class PostGisDBConnector(DBConnector):
JOIN pg_namespace nsp ON t.relnamespace = nsp.oid
WHERE t.relname = %s %s """ % (self.quoteString(tablename), schema_where)
self._execute(c, sql)
return c.fetchall()
c = self._execute(None, sql)
res = self._fetchall(c)
self._close_cursor(c)
return res
def enableAllTableTriggers(self, enable, table):
""" enable or disable all triggers on table """
@ -496,7 +503,6 @@ class PostGisDBConnector(DBConnector):
def getTableRules(self, table):
c = self._get_cursor()
schema, tablename = self.getSchemaTableName(table)
schema_where = u" AND schemaname=%s " % self.quoteString(schema) if schema is not None else ""
@ -504,8 +510,10 @@ class PostGisDBConnector(DBConnector):
sql = u"""SELECT rulename, definition FROM pg_rules
WHERE tablename=%s %s """ % (self.quoteString(tablename), schema_where)
self._execute(c, sql)
return c.fetchall()
c = self._execute(None, sql)
res = self._fetchall(c)
self._close_cursor(c)
return res
def deleteTableRule(self, rule, table):
""" delete rule on table """
@ -515,28 +523,33 @@ class PostGisDBConnector(DBConnector):
def getTableExtent(self, table, geom):
""" find out table extent """
c = self._get_cursor()
subquery = u"SELECT st_extent(%s) AS extent FROM %s" % ( self.quoteId(geom), self.quoteId(table) )
sql = u"SELECT st_xmin(extent), st_ymin(extent), st_xmax(extent), st_ymax(extent) FROM (%s) AS subquery" % subquery
self._execute(c, sql)
return c.fetchone()
c = self._execute(None, sql)
res = self._fetchone(c)
self._close_cursor(c)
return res
def getTableEstimatedExtent(self, table, geom):
""" find out estimated extent (from the statistics) """
if self.isRasterTable(table):
return
c = self._get_cursor()
schema, tablename = self.getSchemaTableName(table)
schema_part = u"%s," % self.quoteString(schema) if schema is not None else ""
subquery = u"SELECT st_estimated_extent(%s%s,%s) AS extent" % (schema_part, self.quoteString(tablename), self.quoteString(geom))
sql = u"""SELECT st_xmin(extent), st_ymin(extent), st_xmax(extent), st_ymax(extent) FROM (%s) AS subquery """ % subquery
try:
self._execute(c, sql)
c = self._execute(None, sql)
except DbError, e: # no statistics for the current table
return
return c.fetchone()
res = self._fetchone(c)
self._close_cursor(c)
return res
def getViewDefinition(self, view):
""" returns definition of the view """
@ -547,8 +560,10 @@ class PostGisDBConnector(DBConnector):
sql = u"""SELECT pg_get_viewdef(c.oid) FROM pg_class c
JOIN pg_namespace nsp ON c.relnamespace = nsp.oid
WHERE relname=%s %s AND relkind='v' """ % (self.quoteString(tablename), schema_where)
c = self._execute(None, sql)
res = c.fetchone()
res = self._fetchone(c)
self._close_cursor(c)
return res[0] if res is not None else None
def getSpatialRefInfo(self, srid):
@ -556,37 +571,44 @@ class PostGisDBConnector(DBConnector):
return
try:
c = self._get_cursor()
self._execute(c, "SELECT srtext FROM spatial_ref_sys WHERE srid = '%d'" % srid)
sr = c.fetchone()
if sr == None:
return
srtext = sr[0]
# try to extract just SR name (should be quoted in double quotes)
regex = QRegExp( '"([^"]+)"' )
if regex.indexIn( srtext ) > -1:
srtext = regex.cap(1)
return srtext
c = self._execute(None, "SELECT srtext FROM spatial_ref_sys WHERE srid = '%d'" % srid)
except DbError, e:
return
sr = self._fetchone(c)
self._close_cursor(c)
if sr == None:
return
srtext = sr[0]
# try to extract just SR name (should be quoted in double quotes)
regex = QRegExp( '"([^"]+)"' )
if regex.indexIn( srtext ) > -1:
srtext = regex.cap(1)
return srtext
def isVectorTable(self, table):
if self.has_geometry_columns and self.has_geometry_columns_access:
schema, tablename = self.getSchemaTableName(table)
sql = u"SELECT count(*) FROM geometry_columns WHERE f_table_schema = %s AND f_table_name = %s" % (self.quoteString(schema), self.quoteString(tablename))
c = self._execute(None, sql)
res = c.fetchone()
res = self._fetchone(c)
self._close_cursor(c)
return res != None and res[0] > 0
return False
def isRasterTable(self, table):
if self.has_raster_columns and self.has_raster_columns_access:
schema, tablename = self.getSchemaTableName(table)
sql = u"SELECT count(*) FROM raster_columns WHERE r_table_schema = %s AND r_table_name = %s" % (self.quoteString(schema), self.quoteString(tablename))
c = self._execute(None, sql)
res = c.fetchone()
res = self._fetchone(c)
self._close_cursor(c)
return res != None and res[0] > 0
return False
@ -631,6 +653,7 @@ class PostGisDBConnector(DBConnector):
schema, tablename = self.getSchemaTableName(table)
if new_table == tablename:
return
c = self._get_cursor()
sql = u"ALTER TABLE %s RENAME TO %s" % (self.quoteId(table), self.quoteId(new_table))
@ -648,6 +671,7 @@ class PostGisDBConnector(DBConnector):
schema, tablename = self.getSchemaTableName(table)
if new_schema == schema:
return
c = self._get_cursor()
sql = u"ALTER TABLE %s SET SCHEMA %s" % (self.quoteId(table), self.quoteId(new_schema))
@ -729,9 +753,9 @@ class PostGisDBConnector(DBConnector):
""" run vacuum analyze on a table """
# vacuum analyze must be run outside transaction block - we have to change isolation level
self.connection.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
c = self._get_cursor()
sql = u"VACUUM ANALYZE %s" % self.quoteId(table)
self._execute(c, sql)
c = self._execute(None, sql)
self._commit()
self.connection.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_READ_COMMITTED)
@ -808,14 +832,16 @@ class PostGisDBConnector(DBConnector):
def isGeometryColumn(self, table, column):
c = self._get_cursor()
schema, tablename = self.getSchemaTableName(table)
schema_where = u" f_table_schema=%s AND " % self.quoteString(schema) if schema is not None else ""
sql = u"SELECT count(*) > 0 FROM geometry_columns WHERE %s f_table_name=%s AND f_geometry_column=%s" % (schema_where, self.quoteString(tablename), self.quoteString(column))
self._execute(c, sql)
return c.fetchone()[0] == 't'
c = self._execute(None, sql)
res = self._fetchone(c)[0] == 't'
self._close_cursor(c)
return res
def addGeometryColumn(self, table, geom_column='geom', geom_type='POINT', srid=-1, dim=2):
schema, tablename = self.getSchemaTableName(table)
@ -914,8 +940,9 @@ class PostGisDBConnector(DBConnector):
UNION SELECT relname FROM pg_class WHERE relkind IN ('v', 'r')
UNION SELECT attname FROM pg_attribute WHERE attnum > 0"""
c = self._execute(None, sql)
for row in c.fetchall():
for row in self._fetchall(c):
items.append( row[0] )
self._close_cursor(c)
sql_dict["identifier"] = items
return sql_dict