/[papo]/gnue/common/src/dbdrivers/_pgsql/DBdriver.py
ViewVC logotype

Diff of /gnue/common/src/dbdrivers/_pgsql/DBdriver.py

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

revision 1.12 by apronotti, Wed Sep 25 17:23:28 2002 UTC revision 1.13 by styxman, Fri Nov 15 15:32:55 2002 UTC
# Line 1  Line 1 
1  #  #
2  # This file is part of GNU Enterprise.  # This file is part of GNU Enterprise.
3  #  #
4  # GNU Enterprise is free software; you can redistribute it  # GNU Enterprise is free software; you can redistribute it
5  # and/or modify it under the terms of the GNU General Public  # and/or modify it under the terms of the GNU General Public
6  # License as published by the Free Software Foundation; either  # License as published by the Free Software Foundation; either
7  # version 2, or(at your option) any later version.  # version 2, or(at your option) any later version.
8  #  #
9  # GNU Enterprise is distributed in the hope that it will be  # GNU Enterprise is distributed in the hope that it will be
10  # useful, but WITHOUT ANY WARRANTY; without even the implied  # useful, but WITHOUT ANY WARRANTY; without even the implied
11  # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR  # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12  # PURPOSE. See the GNU General Public License for more details.  # PURPOSE. See the GNU General Public License for more details.
13  #  #
14  # You should have received a copy of the GNU General Public  # You should have received a copy of the GNU General Public
15  # License along with program; see the file COPYING. If not,  # License along with program; see the file COPYING. If not,
16  # write to the Free Software Foundation, Inc., 59 Temple Place  # write to the Free Software Foundation, Inc., 59 Temple Place
17  # - Suite 330, Boston, MA 02111-1307, USA.  # - Suite 330, Boston, MA 02111-1307, USA.
18  #  #
19  # Copyright 2000, 2001 Free Software Foundation  # Copyright 2000-2002 Free Software Foundation
20  #  #
21  # FILE:  # FILE:
22  # _pgsql/DBdriver.py  # _pgsql/DBdriver.py
23  #  #
24  # DESCRIPTION:  # DESCRIPTION:
25  # A core Postgresql implementation of dbdriver the other  # A core Postgresql dbdriver that the other (specific)
26  # postgresql drivers can extend  # postgresql drivers can extend
27  #  #
28  # NOTES:  # NOTES:
29  #  #
30    
   
 from string import lower, join  
 import sys  
31  import string  import string
32    from string import lower, join, split
33    import sys
34  from gnue.common import GDebug, GDataObjects  from gnue.common import GDebug, GDataObjects
35  from gnue.common.dbdrivers._dbsig.DBdriver \  from gnue.common.dbdrivers._dbsig.DBdriver \
36     import DBSIG_RecordSet, DBSIG_ResultSet, DBSIG_DataObject, \     import DBSIG_RecordSet, DBSIG_ResultSet, DBSIG_DataObject
           DBSIG_DataObject_Object  
37    
38  #from gnue.common.dbdrivers._dbsig.DBdriver import DBSIG_DataObject_Object as PGSQL_DataObject_Object  from gnue.common.dbdrivers._dbsig.DBdriver import DBSIG_DataObject_Object as PGSQL_DataObject_Object
39  from gnue.common.dbdrivers._dbsig.DBdriver import DBSIG_DataObject_SQL as PGSQL_DataObject_SQL  from gnue.common.dbdrivers._dbsig.DBdriver import DBSIG_DataObject_SQL as PGSQL_DataObject_SQL
40    
41    
42  class PGSQL_RecordSet(DBSIG_RecordSet):  class PGSQL_RecordSet(DBSIG_RecordSet):
43     pass    def _buildUpdateStatement(self):
44  #   def _buildUpdateStatement(self, table):      updates = []
45  #     updates = []      for field in self._modifiedFlags.keys():
46  #     for field in self._modifiedFlags.keys():  ##    # To convert date from format '2002-12-31 23:59:59,99'
47  #       a = len (field.split ('.'))  ##    # into '2002-12-31 23:59:59' format.
48  #       if (a == 2):  ##    # We have to determine whether given string is date\time
49  #         [auxTable, auxField]= field.split ('.')  ##    # maybe it's the most stupid way, but it should work.
50  #         if string.count(self._parent._dataObject.table,',') and (auxTable != table):  ##    # TODO: if in ANY other field data of this format and comma in
51  #           continue  ##    # place will exist, the remaining string from first ',' will be
52  #       elif (a == 1):  ##    # eaten.
53  #         auxField= field  ##    # If you know better decision - please, modify this code.
54  #       else:  ##
55  #         # raise  ## This should have been submitted as a patch for peer review.
56  #         pass  ## For starters, it can break non-date fields w/commas.
57    ## Secondly, such checks belong in _toSqlString!
58  #       updates.append ("%s=%s" % (auxField,  ## -- jcater
59  #                                  self._parent._dataObject._toSqlString(self._fields[field])))  ##
60    ##      tmpDate = self._fields[field]
61  #     where = []  ##      if ((len(tmpDate)==22) and (tmpDate[-3]==',')):
62        ##        tmpDate = tmpDate.split(',')
63  #     if updates:  ##        tmpDate = tmpDate[0]
64  #       if self._parent._dataObject._primaryKeys:  ##      updates.append ("%s=%s" % (field,
65  #         for iterTable in self._parent._dataObject._primaryKeys.keys():  ##        self._parent._dataObject._toSqlString(tmpDate)))
66  #           if iterTable != table: continue  
67  #           for iterField in self._parent._dataObject._primaryKeys[iterTable]:        updates.append ("%s=%s" % (field,
68  #             auxWhere = "%s = '%s'"          self._parent._dataObject._toSqlString(self._fields[field])))
69  #             where.append(auxWhere % (iterField,self._initialData[table+"."+iterField]))  
70  #       else:      if self._parent._dataObject._primaryIdField:
71  #         for field in self._initialData.keys():        where = [self._parent._dataObject._primaryIdFormat % \
72  #           a = len (field.split ('.'))            self._initialData[self._parent._dataObject._primaryIdField]  ]
73  #           if (a == 2):      else:
74  #             [auxTable, auxField]= field.split ('.')        where = []
75  #             if string.count(self._parent._dataObject.table,',') and (auxTable != table):        for field in self._initialData.keys():
76  #               continue          if self._initialData[field] == None:
77  #           elif (a == 1):            where.append ("%s IS NULL" % field)
78  #             auxField= field          else:
79  #           else:            where.append ("%s=%s" % (field, self._parent._dataObject._toSqlString(self._initialData[field])))
80  #             # raise      return "UPDATE %s SET %s WHERE %s" % \
81  #             pass         (self._parent._dataObject.table, string.join(updates,','), \
82            string.join(where,' AND ') )
 #           if self._initialData[field] == None:  
 #             where.append ("%s IS NULL" % auxField)  
 #           else:  
 #             where.append ("%s=%s" % (auxField, self._parent._dataObject._toSqlString(self._initialData[field])))  
   
 #     updateStmt = "BEGIN; SELECT %s FROM %s WHERE %s FOR UPDATE; " % \  
 #                  (string.join(updates,','), table, \  
 #                   string.join(where,' AND ') ) + \  
 #                  "UPDATE %s SET %s WHERE %s" % \  
 #                  (table, string.join(updates,','), \  
 #                   string.join(where,' AND ') ) + "; COMMIT;"  
83    
 #     return updateStmt  
84    
85  class PGSQL_ResultSet(DBSIG_ResultSet):  class PGSQL_ResultSet(DBSIG_ResultSet):
86    def __init__(self, dataObject, cursor=None, defaultValues={}, masterRecordSet=None, fieldNames=None):    def __init__(self, dataObject, cursor=None, defaultValues={}, masterRecordSet=None, fieldNames=None):
# Line 102  class PGSQL_ResultSet(DBSIG_ResultSet): Line 89  class PGSQL_ResultSet(DBSIG_ResultSet):
89      self._recordSetClass = PGSQL_RecordSet      self._recordSetClass = PGSQL_RecordSet
90    
91  class PGSQL_DataObject(DBSIG_DataObject):  class PGSQL_DataObject(DBSIG_DataObject):
92    
93      schema2nativeTypes={"auto":"int4",
94                          "int":"int",
95                          "number":"int",
96                          "float":"float",
97                          "decimal":"decimal",
98                          "varchar":"varchar",
99                          "char":"char",
100                          "blob":"text",
101                          "text":"text",
102                          "longtext":"text",
103                          "date":"date",
104                          "datetime":"datetime",
105                          "timestamp":"timestamp"}
106    
107    def __init__(self, pgdriver=None, pgresultset=None):    def __init__(self, pgdriver=None, pgresultset=None):
108      DBSIG_DataObject.__init__(self)      DBSIG_DataObject.__init__(self)
109      self._connectString = 'host=%s dbname=%s user=%s password=%s port=%s'      self._connectString = 'host=%s dbname=%s user=%s password=%s port=%s'
110      self._escapeSingleQuote = '\\'      self._escapeSingleQuote = '\\'
111        # date/time format
112        self._dateTimeFormat = "'%Y-%m-%d %H:%M:%S'"
113    
114      if pgdriver:      if pgdriver:
115        self._pgdriver = pgdriver        self._pgdriver = pgdriver
116        self._DatabaseError = self._pgdriver.DatabaseError        self._DatabaseError = self._pgdriver.DatabaseError
117      if pgresultset:      if pgresultset:
118        self._resultSetClass = pgresultset        self._resultSetClass = pgresultset
119        
120    def connect(self, connectData={}):    def connect(self, connectData={}):
121      GDebug.printMesg(1,"Postgresql database driver initializing")      GDebug.printMesg(1,"Postgresql database driver initializing")
122      try:      try:
 #  
 #  Ugly dneighbo hack as no python studs to ask questions for  
 #  
123        try:        try:
124          port = connectData['port']          port = connectData['port']
125        except:        except:
126          port  = '5432'          port  = '5432'
127    
 #  
 #  End hack (note port variable used below and defined in __init above)  
 #  
128        self._dataConnection = self._pgdriver.connect(self._connectString %        self._dataConnection = self._pgdriver.connect(self._connectString %
129                                                      (connectData['host'],                                                      (connectData['host'],
130                                                       connectData['dbname'],                                                       connectData['dbname'],
# Line 144  class PGSQL_DataObject(DBSIG_DataObject) Line 143  class PGSQL_DataObject(DBSIG_DataObject)
143        raise GDataObjects.LoginError, value        raise GDataObjects.LoginError, value
144    
145      try:      try:
146        encoding = connectData['encoding']        encoding = ""
147        GDebug.printMesg(1,'Setting postgresql client_encoding to %s' % encoding)        try:
148        cursor = self._dataConnection.cursor()          encoding = connectData['encoding']
149        cursor.execute("SET CLIENT_ENCODING TO '%s'" % encoding)        except KeyError:
150        cursor.close()          # if encoding is not defined in connectData use gnue.conf setting instead
151      except KeyError:          try:
152        pass            encoding = gConfig('encoding')
153      except self._DatabaseError:          except:
154        try:            pass
155    
156          if encoding!="":
157            GDebug.printMesg(1,'Setting postgresql client_encoding to %s' % encoding)
158            cursor = self._dataConnection.cursor()
159            cursor.execute("SET CLIENT_ENCODING TO '%s'" % encoding)
160            cursor.close()
161    
162        except self._DatabaseError:
163          try:
164          cursor.close()          cursor.close()
165        except:        except:
166          pass          pass
167    
168        if connectData.has_key('datetimeformat'):
169          self._dateTimeFormat = "'%s'" % connectData['datetimeformat']
170    
171    
172      self._postConnect()      self._postConnect()
173    
174    def _postConnect(self):    def _postConnect(self):
# Line 193  class PGSQL_DataObject(DBSIG_DataObject) Line 205  class PGSQL_DataObject(DBSIG_DataObject)
205      list = []      list = []
206      for rs in cursor.fetchall():      for rs in cursor.fetchall():
207        list.append(GDataObjects.Schema(attrs={'id':rs[2], 'name':rs[0],        list.append(GDataObjects.Schema(attrs={'id':rs[2], 'name':rs[0],
208                           'type':rs[1] == 'v' and 'view' or 'table'},                           'type':rs[1] == 'v' and 'view' or 'table',
209                             'primarykey': self.__getPrimaryKey(cursor, rs[2])},
210                           getChildSchema=self.__getFieldSchema))                           getChildSchema=self.__getFieldSchema))
211    
212      cursor.close()      cursor.close()
# Line 211  class PGSQL_DataObject(DBSIG_DataObject) Line 224  class PGSQL_DataObject(DBSIG_DataObject)
224      rs = cursor.fetchone()      rs = cursor.fetchone()
225      if rs:      if rs:
226        schema = GDataObjects.Schema(attrs={'id':rs[2], 'name':rs[0],        schema = GDataObjects.Schema(attrs={'id':rs[2], 'name':rs[0],
227                             'type':rs[1] == 'v' and 'view' or 'table'},                             'type':rs[1] == 'v' and 'view' or 'table',
228                               'primarykey': self.__getPrimaryKey(cursor, rs[2]) },
229                             getChildSchema=self.__getFieldSchema)                             getChildSchema=self.__getFieldSchema)
230      else:      else:
231        schema = None        schema = None
# Line 219  class PGSQL_DataObject(DBSIG_DataObject) Line 233  class PGSQL_DataObject(DBSIG_DataObject)
233      cursor.close()      cursor.close()
234      return schema      return schema
235    
236      def __getPrimaryKey(self, cursor, oid):
237        cursor = self._dataConnection.cursor()
238        cursor.execute("select indkey from pg_index where indrelid=%d" % oid)
239        rs = cursor.fetchone()
240        statement = "select attname from pg_attribute " \
241                    "where attrelid = %d and attnum = %%d" % oid
242        if rs:
243          pks = []
244          for indpos in string.split(rs[0]):
245            cursor.execute(statement % int(indpos))
246            pks.append(cursor.fetchone()[0])
247          cursor.close()
248          return tuple(pks)
249        else:
250          cursor.close()
251          return None
252    
253    # Get fields for a table    # Get fields for a table
254    def __getFieldSchema(self, parent):    def __getFieldSchema(self, parent):
255    
256      statement = "select attname, pg_type.oid, typname, " + \      statement = "select attname, pg_type.oid, typname, " + \
257              " attnotnull, atthasdef, atttypmod " + \              " attnotnull, atthasdef, atttypmod, attnum, attlen " + \
258              "from pg_attribute, pg_type " + \              "from pg_attribute, pg_type " + \
259              "where attrelid = %d and " % (parent.id) + \              "where attrelid = %d and " % (parent.id) + \
260              "pg_type.oid = atttypid and attnum >= 0" + \              "pg_type.oid = atttypid and attnum >= 0" + \
# Line 239  class PGSQL_DataObject(DBSIG_DataObject) Line 270  class PGSQL_DataObject(DBSIG_DataObject)
270               'type':'field', 'nativetype': rs[2],               'type':'field', 'nativetype': rs[2],
271               'required': rs[3] and not rs[4]}               'required': rs[3] and not rs[4]}
272    
273        if rs[2] in ('int8','int2','int4','numeric',        if rs[2] in ('numeric','float4','float8','money','bool','int8','int2','int4'):
                    'float4','float8','money','bool'):  
274          attrs['datatype']='number'          attrs['datatype']='number'
275        elif rs[2] in ('date','time','timestamp','abstime','reltime'):        elif rs[2] in ('date','time','timestamp','abstime','reltime'):
276          attrs['datatype']='date'          attrs['datatype']='date'
277        else:        else:
278          attrs['datatype']='text'          attrs['datatype']='text'
279    
280        if rs[5] != -1:        if rs[7] > 0:
281          attrs['length'] = rs[5]          attrs['length'] = rs[7]
282          else:
283            attrs['length'] = rs[5] - 4
284    
285    
286          # Find any default values
287          if rs[4]:
288            cursor.execute("select adsrc " + \
289                           "from pg_attrdef " + \
290                           "where adrelid = %d and adnum = %d" % (parent.id, rs[6]))
291            defrs = cursor.fetchone()
292            if defrs:
293              dflt = defrs[0]
294              if dflt[:8] == 'nextval(':
295                attrs['defaulttype'] = 'sequence'
296                attrs['defaultval'] = split(dflt,"'")[1]
297              elif dflt == 'now()':
298                attrs['defaulttype'] = 'system'
299                attrs['defaultval'] = 'timestamp'
300              else:
301                attrs['defaulttype'] = 'constant'
302                attrs['defaultval'] = dflt
303    
304        list.append(GDataObjects.Schema(attrs=attrs))        list.append(GDataObjects.Schema(attrs=attrs))
305    

Legend:
Removed from v.1.12  
changed lines
  Added in v.1.13

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26