Update of /cvsroot/webware/Webware/MiddleKit/Run
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18056
Modified Files:
PostgreSQLObjectStore.py SQLObjectStore.py
Log Message:
Refactored _insertObject to support databases like PostgreSQL with which we
can determine the next serial number for a table in advance.
Modified sqlInsertStmt and insertSQLStart to allow setting the id column
at the point the object is added.
Index: PostgreSQLObjectStore.py
===================================================================
RCS file: /cvsroot/webware/Webware/MiddleKit/Run/PostgreSQLObjectStore.py,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** PostgreSQLObjectStore.py 16 Sep 2004 19:33:27 -0000 1.5
--- PostgreSQLObjectStore.py 17 Sep 2004 15:21:20 -0000 1.6
***************
*** 44,67 ****
return conn.cursor()
! def _insertObject(self, object, unknownSerialNums):
! # basically the same as the SQLObjectStore-
! # version but modified to retrieve the
! # serialNum via the oid (for which we need
! # class-name, unfortunately)
! object.klass
! seqname = "%s_%s_seq" % (object.klass().name(), object.klass().sqlSerialColumnName())
conn, curs = self.executeSQL("select nextval('%s')" % seqname)
id = curs.fetchone()[0]
assert id, "Didn't get next id value from sequence"
!
! sql = object.sqlInsertStmt(unknownSerialNums,id=id)
! conn, curs = self.executeSQL(sql,conn)
! conn.commit()
!
! object.setSerialNum(id)
! object.setKey(ObjectKey().initFromObject(object))
! object.setChanged(0)
!
! self._objects[object.key()] = object
def dbapiModule(self):
--- 44,53 ----
return conn.cursor()
! def retrieveNextInsertId(self, klass):
! seqname = "%s_%s_seq" % (klass.name(), klass.sqlSerialColumnName())
conn, curs = self.executeSQL("select nextval('%s')" % seqname)
id = curs.fetchone()[0]
assert id, "Didn't get next id value from sequence"
! return id
def dbapiModule(self):
***************
*** 93,149 ****
- class Klass:
-
- def insertSQLStart(self):
- """
- We override this so that the id column is always specified explicitly.
- """
- if self._insertSQLStart is None:
- res = ['insert into %s (' % self.sqlTableName()]
- attrs = self.allDataAttrs()
- attrs = [attr for attr in attrs if attr.hasSQLColumn()]
- fieldNames = [self.sqlSerialColumnName()] + [attr.sqlColumnName() for attr in attrs]
- if len(fieldNames)==0:
- fieldNames = [self.sqlSerialColumnName()]
- res.append(','.join(fieldNames))
- res.append(') values (')
- self._insertSQLStart = ''.join(res)
- self._sqlAttrs = attrs
- return self._insertSQLStart, self._sqlAttrs
-
- class MiddleObjectMixIn:
-
-
- def sqlInsertStmt(self, unknowns, id):
- """
- We override this so that the id column is always specified explicitly.
- """
- klass = self.klass()
- insertSQLStart, sqlAttrs = klass.insertSQLStart()
- values = []
- append = values.append
- extend = values.extend
- append(str(id))
- for attr in sqlAttrs:
- try:
- value = attr.sqlValue(self.valueForAttr(attr))
- except UnknownSerialNumberError, exc:
- exc.info.sourceObject = self
- unknowns.append(exc.info)
- value = 'NULL'
- if isinstance(value, str):
- append(value)
- else:
- extend(value) # value could be sequence for attrs that require multiple SQL columns
- if len(values)==0:
- values = ['0']
- values = ','.join(values)
- return insertSQLStart+values+');'
-
- MixIn(MiddleObject, MiddleObjectMixIn)
- # Normally we don't have to invoke MixIn()--it's done automatically.
- # However, that only works when augmenting MiddleKit.Core classes
- # (MiddleObject belongs to MiddleKit.Run).
-
class StringAttr:
def sqlForNonNone(self, value):
--- 79,82 ----
Index: SQLObjectStore.py
===================================================================
RCS file: /cvsroot/webware/Webware/MiddleKit/Run/SQLObjectStore.py,v
retrieving revision 1.70
retrieving revision 1.71
diff -C2 -d -r1.70 -r1.71
*** SQLObjectStore.py 27 Aug 2004 01:16:17 -0000 1.70
--- SQLObjectStore.py 17 Sep 2004 15:21:21 -0000 1.71
***************
*** 227,236 ****
assert object.serialNum()<1, 'object=%s' % rep
# SQL insert
! sql = object.sqlInsertStmt(unknownSerialNums)
conn, cur = self.executeSQL(sql)
# Get new id/serial num
! idNum = self.retrieveLastInsertId(conn, cur)
# Update object
--- 227,240 ----
assert object.serialNum()<1, 'object=%s' % rep
+ # try to get the next ID (if database supports this)
+ idNum = self.retrieveNextInsertId(object.klass())
+
# SQL insert
! sql = object.sqlInsertStmt(unknownSerialNums, idNum)
conn, cur = self.executeSQL(sql)
# Get new id/serial num
! if idNum is None:
! idNum = self.retrieveLastInsertId(conn, cur)
# Update object
***************
*** 242,245 ****
--- 246,255 ----
self._objects[object.key()] = object
+ def retrieveNextInsertId(self, klass):
+ """ Returns the id for the next new object of this class. Databases which cannot determine
+ the id until the object has been added return None, signifying that retrieveLastInsertId
+ should be called to get the id after the insert has been made. """
+ return None
+
def retrieveLastInsertId(self, conn, cur):
""" Returns the id (typically a 32-bit int) of the last INSERT operation by this connection. Used by commitInserts() to get the correct serial number for the last inserted object.
***************
*** 596,600 ****
return objRefJoin(self.klass().id(), self.serialNum())
! def sqlInsertStmt(self, unknowns):
"""
Returns the SQL insert statements for MySQL (as a tuple) in the form:
--- 606,610 ----
return objRefJoin(self.klass().id(), self.serialNum())
! def sqlInsertStmt(self, unknowns, id=None):
"""
Returns the SQL insert statements for MySQL (as a tuple) in the form:
***************
*** 605,612 ****
"""
klass = self.klass()
! insertSQLStart, sqlAttrs = klass.insertSQLStart()
values = []
append = values.append
extend = values.extend
for attr in sqlAttrs:
try:
--- 615,624 ----
"""
klass = self.klass()
! insertSQLStart, sqlAttrs = klass.insertSQLStart(includeSerialColumn=id)
values = []
append = values.append
extend = values.extend
+ if id is not None:
+ append(str(id))
for attr in sqlAttrs:
try:
***************
*** 703,707 ****
return self._fetchSQLStart
! def insertSQLStart(self):
"""
Returns a tuple of insertSQLStart (a string) and sqlAttrs (a list).
--- 715,719 ----
return self._fetchSQLStart
! def insertSQLStart(self, includeSerialColumn=False):
"""
Returns a tuple of insertSQLStart (a string) and sqlAttrs (a list).
***************
*** 712,717 ****
attrs = [attr for attr in attrs if attr.hasSQLColumn()]
fieldNames = [attr.sqlColumnName() for attr in attrs]
! if len(fieldNames)==0:
! fieldNames = [self.sqlSerialColumnName()]
res.append(','.join(fieldNames))
res.append(') values (')
--- 724,729 ----
attrs = [attr for attr in attrs if attr.hasSQLColumn()]
fieldNames = [attr.sqlColumnName() for attr in attrs]
! if includeSerialColumn or len(fieldNames) == 0:
! fieldNames.insert(0, self.sqlSerialColumnName())
res.append(','.join(fieldNames))
res.append(') values (')
|