dabo Commit
Revision 3314
Date: 2007-08-19 12:07:48 -0700 (Sun, 19 Aug 2007)
Author: Ed
Trac: http://svn.dabodev.com/trac/dabo/changeset/3314
Changed:
U trunk/dabo/biz/dAutoBizobj.py
U trunk/dabo/biz/dBizobj.py
U trunk/dabo/biz/test/test_dBizobj.py
U trunk/dabo/dApp.py
U trunk/dabo/dPref.py
U trunk/dabo/db/dBackend.py
U trunk/dabo/db/dCursorMixin.py
U trunk/dabo/db/dbFirebird.py
U trunk/dabo/db/dbMySQL.py
U trunk/dabo/db/dbPostgreSQL.py
U trunk/dabo/db/dbSQLite.py
U trunk/dabo/db/test/test_dCursorMixin.py
Log:
Major re-write to the way that transactions are handled in the bizobj and
database layers.
These changes are designed to work within the entire framework; i.e.,
applications, forms, bizobjs and cursors. If you use any single piece of the
framework separately, such as a raw cursor, you will have to manage
transactions yourself.
Transactions now happen happen by default when calling biz.save()/saveAll() and
biz.delete()/deleteAll(). If for some reason you do not want transactions, you
must call them with the parameter startTransaction=False.
Only one bizobj will begin and commit/rollback. All others do not touch
transactions, as they are within the current transaction. Upon a save or delete
method being called, the bizobj will request the transaction 'token' from the
app. If no other bizobj has started a transaction, it will have True returned
from the request, and the bizobj will handle the transaction. If there are
related bizobjs who in turn have their save/delete methods called, their
requests for the token will be denied, so they will not do anything regarding
transactions. When the process is completed in the initial method that
requested the token, either a commit or rollback will be called, and the token
released.
This design eliminates the problem with nested and chained bizobjs starting
and/or ending multiple transactions. Only the original bizobj in the process
can manage transactions, and only from the method that was originally called.
The 'AutoCommit' property has been removed. Defaulting transactions to being
used by default will handle the call to commit(). Again, if you deal with
cursors directly (as is done in dPref.py), the commit calls must also be
handled manually.
Diff:
Modified: trunk/dabo/biz/dAutoBizobj.py
===================================================================
--- trunk/dabo/biz/dAutoBizobj.py 2007-08-14 21:57:09 UTC (rev 3313)
+++ trunk/dabo/biz/dAutoBizobj.py 2007-08-19 19:07:48 UTC (rev 3314)
@@ -43,12 +43,8 @@
g._toExc = {}
for biz in g._AutoTables.values():
- ac = biz.AutoCommit
- biz.AutoCommit = True
- biz.CreateTable()
+ biz.createTable()
- biz.AutoCommit = ac
-
if g._toExc:
if dabo.dAppRef is not None:
class DbAdminLogin(dabo.ui.dDialog):
@@ -138,7 +134,7 @@
tempConn =
dabo.db.dConnection(ci)
except dException.DBNoAccessException:
dabo.ui.stop(_("Could not
access the database with the given username and password."))
- _WriteQueriesToFile(g._toExc)
+ _writeQueriesToFile(g._toExc)
raise
dException.DBNoAccessException
else:
cur = tempConn.getDaboCursor()
@@ -149,20 +145,20 @@
cur.execute(query)
except
dException.DBNoAccessExeption:
dabo.ui.stop(_("Could not setup the database. Access was denied."))
-
_WriteQueriesToFile(g._toExc)
+
_writeQueriesToFile(g._toExc)
raise
dException.DBNoAccessException
else:
login.release()
- _WriteQueriesToFile(g._toExc)
+ _writeQueriesToFile(g._toExc)
raise dException.DBNoAccessException
else:
- _WriteQueriesToFile(g._toExc)
+ _writeQueriesToFile(g._toExc)
raise dException.DBNoAccessException
-def _WriteQueriesToFile(queries):
+def _writeQueriesToFile(queries):
f = open("queries.sql", "w")
for k in queries.keys():
f.write(_("#Queries for DB '%s' on host '%s':\n") %
(k.ConnectInfo.Database, k.ConnectInfo.Host))
@@ -171,6 +167,8 @@
f.close()
+
+
class dAutoBizobj(dBizobj):
"""This class is just like bBizobj but is supports the auto creation of
the table by setting the table property.
@@ -244,7 +242,7 @@
#Override in subclass
- def CreateTable(self):
+ def createTable(self):
"""Create the tables that has been asigned to this bizobj."""
if self._table is None:
raise dException.dException(_("No table has been
defined for this bizobj."))
Modified: trunk/dabo/biz/dBizobj.py
===================================================================
--- trunk/dabo/biz/dBizobj.py 2007-08-14 21:57:09 UTC (rev 3313)
+++ trunk/dabo/biz/dBizobj.py 2007-08-19 19:07:48 UTC (rev 3314)
@@ -60,7 +60,6 @@
self._restorePositionOnRequery = True
# Various attributes used for Properties
- self._autoCommit = False
self._caption = ""
self._dataSource = ""
self._nonUpdateFields = []
@@ -166,7 +165,6 @@
crs.AutoQuoteNames = self.AutoQuoteNames
crs.BackendObject = cf.getBackendObject()
crs.sqlManager = self.SqlManager
- crs.AutoCommit = self.AutoCommit
crs._bizobj = self
if self.RequeryOnLoad:
crs.requery()
@@ -262,45 +260,49 @@
self.afterLast()
- def saveAll(self, startTransaction=False, topLevel=True):
+ def saveAll(self, startTransaction=True):
"""Saves all changes to the bizobj and children."""
- useTransact = startTransaction or topLevel
cursor = self._CurrentCursor
current_row = self.RowNumber
+ app = self.Application
+ isTransactionManager = False
+ if startTransaction:
+ isTransactionManager = app.getTransactionToken(self)
+ if isTransactionManager:
+ cursor.beginTransaction()
- if useTransact:
- # Tell the cursor to begin a transaction, if needed.
- cursor.beginTransaction()
-
try:
self.scanChangedRows(self.save,
includeNewUnchanged=self.SaveNewUnchanged,
- startTransaction=False, topLevel=False)
+ startTransaction=False)
+ if isTransactionManager:
+ cursor.commitTransaction()
+ app.releaseTransactionToken(self)
+
except dException.ConnectionLostException, e:
self.RowNumber = current_row
raise dException.ConnectionLostException, e
except dException.DBQueryException, e:
# Something failed; reset things.
- if useTransact:
+ if isTransactionManager:
cursor.rollbackTransaction()
+ app.releaseTransactionToken(self)
# Pass the exception to the UI
self.RowNumber = current_row
raise dException.DBQueryException, e
except dException.dException, e:
- if useTransact:
+ if isTransactionManager:
cursor.rollbackTransaction()
+ app.releaseTransactionToken(self)
self.RowNumber = current_row
raise
- if useTransact:
- cursor.commitTransaction()
-
if current_row >= 0:
try:
self.RowNumber = current_row
except: pass
- def save(self, startTransaction=False, topLevel=True):
+ def save(self, startTransaction=True):
"""Save any changes that have been made in the current row.
If the save is successful, the saveAll() of all child bizobjs
will be
@@ -318,10 +320,12 @@
# validation, an Exception will be raised.
self._validate()
- useTransact = startTransaction or topLevel
- if useTransact:
- # Tell the cursor to begin a transaction, if needed.
- cursor.beginTransaction()
+ app = self.Application
+ isTransactionManager = False
+ if startTransaction:
+ isTransactionManager = app.getTransactionToken(self)
+ if isTransactionManager:
+ cursor.beginTransaction()
# Save to the Database, but first save the IsAdding flag as the
save() call
# will reset it to False:
@@ -337,11 +341,12 @@
# No need to start another transaction. And
since this is a child bizobj,
# we need to save all rows that have changed.
if child.RowCount > 0:
- child.saveAll(startTransaction=False,
topLevel=False)
+ child.saveAll(startTransaction=False)
# Finish the transaction, and requery the children if
needed.
- if useTransact:
+ if isTransactionManager:
cursor.commitTransaction()
+ app.releaseTransactionToken(self)
if self.RequeryChildOnSave:
self.requeryAllChildren()
@@ -353,22 +358,20 @@
except dException.DBQueryException, e:
# Something failed; reset things.
- if useTransact:
+ if isTransactionManager:
cursor.rollbackTransaction()
+ app.releaseTransactionToken(self)
# Pass the exception to the UI
raise dException.DBQueryException, e
except dException.dException, e:
# Something failed; reset things.
- if useTransact:
+ if isTransactionManager:
cursor.rollbackTransaction()
+ app.releaseTransactionToken(self)
# Pass the exception to the UI
raise
- # Some backends (Firebird particularly) need to be told to write
- # their changes even if no explicit transaction was started.
- cursor.flush()
-
# Two hook methods: one specific to Save(), and one which is
called after any change
# to the data (either save() or delete()).
self.afterChange()
@@ -404,37 +407,45 @@
self.afterCancel()
- def deleteAllChildren(self, startTransaction=False):
+ def deleteAllChildren(self, startTransaction=True):
"""Delete all children associated with the current record
without
deleting the current record in this bizobj.
"""
cursor = self._CurrentCursor
+ app = self.Application
errMsg = self.beforeDeleteAllChildren()
if errMsg:
raise dException.BusinessRuleViolation, errMsg
+ isTransactionManager = False
if startTransaction:
- cursor.beginTransaction()
+ isTransactionManager = app.getTransactionToken(self)
+ if isTransactionManager:
+ cursor.beginTransaction()
try:
for child in self.__children:
child.deleteAll(startTransaction=False)
- if startTransaction:
+ if isTransactionManager:
cursor.commitTransaction()
- self.afterDeleteAllChildren()
+ app.releaseTransactionToken(self)
except dException.DBQueryException, e:
- if startTransaction:
+ if isTransactionManager:
cursor.rollbackTransaction()
+ app.releaseTransactionToken(self)
raise dException.DBQueryException, e
except StandardError, e:
- if startTransaction:
+ if isTransactionManager:
cursor.rollbackTransaction()
+ app.releaseTransactionToken(self)
raise StandardError, e
+ self.afterDeleteAllChildren()
- def delete(self, startTransaction=False):
+ def delete(self, startTransaction=True, inLoop=False):
"""Delete the current row of the data set."""
+ app = self.Application
cursor = self._CurrentCursor
errMsg = self.beforeDelete()
if not errMsg:
@@ -451,8 +462,11 @@
if child.RowCount > 0:
raise dException.dException,
_("Deletion prohibited - there are related child records.")
+ isTransactionManager = False
if startTransaction:
- cursor.beginTransaction()
+ isTransactionManager = app.getTransactionToken(self)
+ if isTransactionManager:
+ cursor.beginTransaction()
try:
cursor.delete()
@@ -469,33 +483,56 @@
child.cancelAll()
child.requery()
- if startTransaction:
+ if isTransactionManager:
cursor.commitTransaction()
+ app.releaseTransactionToken(self)
- # Some backends (Firebird particularly) need to be told
to write
- # their changes even if no explicit transaction was
started.
- cursor.flush()
+ if not inLoop:
+ self.afterPointerMove()
+ self.afterChange()
+ self.afterDelete()
+ except dException.DBQueryException, e:
+ if isTransactionManager:
+ cursor.rollbackTransaction()
+ app.releaseTransactionToken(self)
+ raise dException.DBQueryException, e
+ except StandardError, e:
+ if isTransactionManager:
+ cursor.rollbackTransaction()
+ app.releaseTransactionToken(self)
+ raise StandardError, e
+
+ def deleteAll(self, startTransaction=True):
+ """ Delete all rows in the data set."""
+ isTransactionManager = False
+ if startTransaction:
+ isTransactionManager = app.getTransactionToken(self)
+ if isTransactionManager:
+ cursor.beginTransaction()
+ try:
+ while self.RowCount > 0:
+ self.first()
+ ret = self.delete(startTransaction=False,
inLoop=True)
+ if isTransactionManager:
+ cursor.commitTransaction()
+ app.releaseTransactionToken(self)
+
self.afterPointerMove()
self.afterChange()
self.afterDelete()
except dException.DBQueryException, e:
- if startTransaction:
+ if isTransactionManager:
cursor.rollbackTransaction()
+ app.releaseTransactionToken(self)
raise dException.DBQueryException, e
except StandardError, e:
- if startTransaction:
+ if isTransactionManager:
cursor.rollbackTransaction()
+ app.releaseTransactionToken(self)
raise StandardError, e
- def deleteAll(self, startTransaction=False):
- """ Delete all rows in the data set."""
- while self.RowCount > 0:
- self.first()
- ret = self.delete(startTransaction)
-
-
def execute(self, sql):
"""Execute the sql on the cursor. Dangerous. Use executeSafe
instead."""
self._syncWithCursors()
@@ -758,19 +795,14 @@
raise dException.ConnectionLostException, e
except dException.DBQueryException, e:
- # Something failed; reset things.
- cursor.rollbackTransaction()
# Pass the exception to the UI
raise dException.DBQueryException, e
except dException.NoRecordsException:
- # No need to abort the transaction because of this, but
- # we still need to pass the exception to the UI
+ # Pass the exception to the UI
uiException = dException.NoRecordsException
except dException.dException, e:
- # Something failed; reset things.
- cursor.rollbackTransaction()
# Pass the exception to the UI
raise dException.dException, e
@@ -1467,7 +1499,6 @@
such cursors are in sync with the bizobj.
"""
for crs in self.__cursors.values():
- crs.AutoCommit = self._autoCommit
crs.AutoPopulatePK = self._autoPopulatePK
crs.AutoQuoteNames = self._autoQuoteNames
crs.Table = self._dataSource
@@ -1477,14 +1508,7 @@
crs.setNonUpdateFields(self._nonUpdateFields)
- def _getAutoCommit(self):
- return self._CurrentCursor.AutoCommit
-
- def _setAutoCommit(self, val):
- self._autoCommit = val
- self._syncWithCursors()
-
-
+ ## Property getter/setter methods ##
def _getAutoPopulatePK(self):
try:
return self._autoPopulatePK
@@ -1841,9 +1865,6 @@
### -------------- Property Definitions ------------------ ##
- AutoCommit = property(_getAutoCommit, _setAutoCommit, None,
- _("Do we need explicit begin/commit/rollback commands
for transactions? (bool)"))
-
AutoPopulatePK = property(_getAutoPopulatePK, _setAutoPopulatePK, None,
_("Determines if we are using a table that
auto-generates its PKs. (bool)"))
Modified: trunk/dabo/biz/test/test_dBizobj.py
===================================================================
--- trunk/dabo/biz/test/test_dBizobj.py 2007-08-14 21:57:09 UTC (rev 3313)
+++ trunk/dabo/biz/test/test_dBizobj.py 2007-08-19 19:07:48 UTC (rev 3314)
@@ -44,12 +44,6 @@
""" % self.temp_table_name)
## - Begin property unit tests -
- def test_AutoCommit(self):
- biz = self.biz
- self.assertEqual(biz.AutoCommit, False)
- biz.AutoCommit = True
- self.assertEqual(biz.AutoCommit, True)
-
def test_AutoSQL(self):
biz = self.biz
self.assertEqual(biz.AutoSQL, "select *\n from %s\n limit
1000" % self.temp_table_name)
Modified: trunk/dabo/dApp.py
===================================================================
--- trunk/dabo/dApp.py 2007-08-14 21:57:09 UTC (rev 3313)
+++ trunk/dabo/dApp.py 2007-08-19 19:07:48 UTC (rev 3314)
@@ -186,6 +186,9 @@
self.getTempFile = self._tempFileHolder.getTempFile
# Create the framework-level preference manager
self._frameworkPrefs = dabo.dPref(key="dabo_framework")
+ # Hold a reference to the bizobj, if any, controlling the
current
+ # database transaction
+ self._transactionBizobj = None
# List of form classes to open on App Startup
self.formsToOpen = []
@@ -397,7 +400,7 @@
except:
vers = -1
localVers = self._currentUpdateVersion()
- ret = localVers < vers
+ ret = (localVers != vers)
prf.setValue("last_check", now)
return ret
@@ -708,6 +711,35 @@
self.dbConnectionNameToFiles[k] = connFile
+ def getTransactionToken(self, biz):
+ """Only one bizobj at a time can begin and end transactions.
This allows the bizobj
+ to query the app for the 'token', which is simply an
acknowledgement that there
+ is no other transaction pending. If the bizobj gets the token,
further requests for the
+ token will receive a reply of False, meaning that they should
not be handling the transaction.
+ """
+ print "TOKEN REQUEST", biz
+ if self._transactionBizobj is None:
+ print "TOKEN SET TO ", biz
+ self._transactionBizobj = biz
+ return True
+ else:
+ print "TOKEN DENIED; holder=", self._transactionBizobj
+ return False
+
+
+ def releaseTransactionToken(self, biz):
+ """When a process that would normally close a transaction
happens, the bizobj that is
+ holding the transaction token calls this message to return the
token. A check is run to
+ ensure that the releasing bizobj is the one currently holding
the token; if it is, the
+ internal attribute is reset.
+ """
+ print "APP RELEASE TOKEN FROM:", biz,
+ if biz is self._transactionBizobj:
+ self._transactionBizobj = None
+ print "RELEASED",
+ print ""
+
+
def setLanguage(self, lang, charset=None):
"""Allows you to change the language used for localization. If
the language
passed is not one for which there is a translation file, an
IOError exception
Modified: trunk/dabo/dPref.py
===================================================================
--- trunk/dabo/dPref.py 2007-08-14 21:57:09 UTC (rev 3313)
+++ trunk/dabo/dPref.py 2007-08-19 19:07:48 UTC (rev 3314)
@@ -72,11 +72,10 @@
# Make sure that the table exists
if not "daboprefs" in self._cursor.getTables():
self._cursor.execute("create table daboprefs
(ckey text not null, ctype text not null, cvalue text not null)")
+ self._cursor.commitTransaction()
else:
self._cursor = crs
self._cxn = cxn
- if self._cursor:
- self._cursor.AutoCommit = True
def __getattr__(self, att):
@@ -220,6 +219,7 @@
sql = "insert into daboprefs (ckey, ctype, cvalue)
values (?, ?, ?)"
prm = (key, typ, val)
crs.execute(sql, prm)
+ self._cursor.commitTransaction()
def persist(self):
@@ -234,6 +234,7 @@
for key in self._deletionCache.keys():
self._cursor.execute("delete from daboprefs where ckey
like ? ", (key, ))
self._deletionCache = {}
+ self._cursor.commitTransaction()
def deletePref(self, att, nested=False):
@@ -260,7 +261,8 @@
self._deletionCache[key] = None
if self._cache.has_key(att):
del self._cache[att]
-
+ self._cursor.commitTransaction()
+
def deleteAllPrefs(self):
"""Deletes all preferences for this object, and all sub-prefs
as well."""
@@ -281,7 +283,8 @@
# Update the caches
self._cache = {}
self._deletionCache[key] = None
-
+ self._cursor.commitTransaction()
+
def flushCache(self):
"""Clear the cache, forcing fresh reads from the database."""
@@ -376,6 +379,7 @@
sql = "insert into daboprefs (ckey, ctype, cvalue) values (?,
?, ?)"
prm = (key, newTyp, val)
self._cursor.execute(sql, prm)
+ self._cursor.commitTransaction()
def setValue(self, key, val):
Modified: trunk/dabo/db/dBackend.py
===================================================================
--- trunk/dabo/db/dBackend.py 2007-08-14 21:57:09 UTC (rev 3313)
+++ trunk/dabo/db/dBackend.py 2007-08-19 19:07:48 UTC (rev 3314)
@@ -25,9 +25,6 @@
def __init__(self):
self._baseClass = dBackend
- self._autoCommit = False
- # This forces the setting on the connection
- self.AutoCommit = False
super(dBackend, self).__init__()
self.dbModuleName = None
self._connection = None
@@ -196,31 +193,16 @@
return tuple([(d[0], self.getDaboFieldType(d[1]), None) for d
in cursorDescription])
- def getAutoCommitStatus(self, cursor):
- return self._autoCommit
-
-
- def setAutoCommitStatus(self, cursor, val):
- if hasattr(self._connection, "autocommit"):
- self._connection.autocommit(val)
- self._autoCommit = val
- else:
- # Without an autocommit method, assume no autocommit.
- self._autoCommit = False
- if val:
- raise ValueError, "Can't set AutoCommit to True
for this backend."
-
-
def beginTransaction(self, cursor):
""" Begin a SQL transaction. Override in subclasses if
needed."""
- pass
+ self._connection.begin()
+ dabo.dbActivityLog.write("SQL: begin")
def commitTransaction(self, cursor):
""" Commit a SQL transaction."""
- if not cursor.AutoCommit:
- self._connection.commit()
- dabo.dbActivityLog.write("SQL: commit")
+ self._connection.commit()
+ dabo.dbActivityLog.write("SQL: commit")
def rollbackTransaction(self, cursor):
Modified: trunk/dabo/db/dCursorMixin.py
===================================================================
--- trunk/dabo/db/dCursorMixin.py 2007-08-14 21:57:09 UTC (rev 3313)
+++ trunk/dabo/db/dCursorMixin.py 2007-08-19 19:07:48 UTC (rev 3314)
@@ -352,7 +352,6 @@
# Redundant!
return
ac = self.AuxCursor
- ac.AutoCommit = self.AutoCommit
ac.AutoPopulatePK = self.AutoPopulatePK
ac.AutoQuoteNames = self.AutoQuoteNames
ac.DataStructure = self.DataStructure
@@ -1056,7 +1055,7 @@
raise dException.NoRecordsException, _("No records in
data set")
- def save(self, allRows=False, useTransaction=False):
+ def save(self, allRows=False):
""" Save any changes to the data back to the data store."""
# Make sure that there is data to save
if self.RowCount <= 0:
@@ -1068,26 +1067,20 @@
try:
self.__saverow(row)
except dException.DBQueryException, e:
- # Error was raised. Exit and rollback the
changes if
- # this object started the transaction.
+ # Error was encountered. Raise an exception so
that the
+ # calling bizobj can rollback the transaction
if necessary
dabo.dbActivityLog.write(_("DBQueryException
encountered in save(): %s") % e)
- if useTransaction:
- self.rollbackTransaction()
raise dException.DBQueryException, e
except StandardError, e:
if "connect" in str(e).lower():
dabo.dbActivityLog.write(_("Connection
Lost exception encountered in saverow(): %s") % e)
raise
dException.ConnectionLostException, e
else:
- # Error was raised. Exit and rollback
the changes if
- # this object started the transaction.
- if useTransaction:
- self.rollbackTransaction()
+ # Error was encountered. Raise an
exception so that the
+ # calling bizobj can rollback the
transaction if necessary
raise
self._syncAuxProperties()
- if useTransaction:
- self.beginTransaction()
# Faster to deal with 2 specific cases: all rows or just
current row
if allRows:
@@ -1100,10 +1093,7 @@
if pk in self._mementos.keys():
saverow(self.RowNumber)
- if useTransaction:
- self.commitTransaction()
-
def __saverow(self, row):
rec = self._records[row]
recKey = self.pkExpression(rec)
@@ -1726,8 +1716,7 @@
""" Begin a SQL transaction."""
ret = None
if self.BackendObject:
- if not self.AutoCommit:
- ret =
self.BackendObject.beginTransaction(self.AuxCursor)
+ ret =
self.BackendObject.beginTransaction(self.AuxCursor)
return ret
@@ -1735,8 +1724,7 @@
""" Commit a SQL transaction."""
ret = None
if self.BackendObject:
- if not self.AutoCommit:
- ret =
self.BackendObject.commitTransaction(self.AuxCursor)
+ ret =
self.BackendObject.commitTransaction(self.AuxCursor)
return ret
@@ -2014,14 +2002,6 @@
## Property getter/setter methods ##
- def _getAutoCommit(self):
- return self.BackendObject.getAutoCommitStatus(self)
-
-
- def _setAutoCommit(self, val):
- self.BackendObject.setAutoCommitStatus(self, val)
-
-
def _getAutoSQL(self):
return self.getSQL()
@@ -2252,9 +2232,6 @@
self._virtualFields = val
- AutoCommit = property(_getAutoCommit, _setAutoCommit, None,
- _("Do we need explicit begin/commit/rollback commands
for transactions? (bool)"))
-
AutoPopulatePK = property(_getAutoPopulatePK, _setAutoPopulatePK, None,
_("When inserting a new record, does the backend
populate the PK field?"))
Modified: trunk/dabo/db/dbFirebird.py
===================================================================
--- trunk/dabo/db/dbFirebird.py 2007-08-14 21:57:09 UTC (rev 3313)
+++ trunk/dabo/db/dbFirebird.py 2007-08-19 19:07:48 UTC (rev 3314)
@@ -193,8 +193,8 @@
def beginTransaction(self, cursor):
""" Begin a SQL transaction."""
- if not cursor.connection._has_transaction():
- cursor.connection.begin()
+ if not self._connection._has_transaction():
+ self._connection.begin()
dabo.dbActivityLog.write("SQL: begin")
@@ -202,7 +202,7 @@
""" Firebird requires an explicit commit in order to have
changes
to the database written to disk.
"""
- cursor.connection.commit()
+ self._connection.commit()
dabo.dbActivityLog.write("SQL: commit")
Modified: trunk/dabo/db/dbMySQL.py
===================================================================
--- trunk/dabo/db/dbMySQL.py 2007-08-14 21:57:09 UTC (rev 3313)
+++ trunk/dabo/db/dbMySQL.py 2007-08-19 19:07:48 UTC (rev 3314)
@@ -4,6 +4,7 @@
import decimal
except ImportError:
decimal = None
+import dabo
from dabo.dLocalize import _
from dBackend import dBackend
import dabo.dException as dException
@@ -60,6 +61,24 @@
return cursors.DictCursor
+ def beginTransaction(self, cursor):
+ """ Begin a SQL transaction."""
+ cursor.execute("START TRANSACTION")
+ dabo.dbActivityLog.write("SQL: begin")
+
+
+ def commitTransaction(self, cursor):
+ """ Commit a SQL transaction."""
+ cursor.execute("COMMIT")
+ dabo.dbActivityLog.write("SQL: commit")
+
+
+ def rollbackTransaction(self, cursor):
+ """ Rollback a SQL transaction."""
+ cursor.execute("ROLLBACK")
+ dabo.dbActivityLog.write("SQL: rollback")
+
+
def escQuote(self, val):
# escape backslashes and single quotes, and
# wrap the result in single quotes
Modified: trunk/dabo/db/dbPostgreSQL.py
===================================================================
--- trunk/dabo/db/dbPostgreSQL.py 2007-08-14 21:57:09 UTC (rev 3313)
+++ trunk/dabo/db/dbPostgreSQL.py 2007-08-19 19:07:48 UTC (rev 3314)
@@ -13,7 +13,6 @@
#self.dbModuleName = "pgdb"
#self.dbModuleName = "PgSQL"
self.dbModuleName = "psycopg"
- self.useTransactions = True # this does not appear to be
required
self.conn_user = ''
@@ -222,7 +221,8 @@
to the database written to disk.
"""
self.commitTransaction(cursor)
-
+
+
def getLastInsertID(self, cursor):
""" Return the ID of the last inserted row, or None.
Modified: trunk/dabo/db/dbSQLite.py
===================================================================
--- trunk/dabo/db/dbSQLite.py 2007-08-14 21:57:09 UTC (rev 3313)
+++ trunk/dabo/db/dbSQLite.py 2007-08-19 19:07:48 UTC (rev 3314)
@@ -2,7 +2,9 @@
import sys
import os
import re
+import dabo
from dabo.dLocalize import _
+from dabo.dException import dException
from dBackend import dBackend
from dNoEscQuoteStr import dNoEscQuoteStr as dNoEQ
from dCursorMixin import dCursorMixin
@@ -69,25 +71,35 @@
return qt + val.replace(sl, sl+sl).replace(qt, qt+qt) + qt
- def setAutoCommitStatus(self, cursor, val):
- """SQLite doesn't use an 'autocommit()' method. Instead,
- set the isolation_level property of the connection.
- """
- if val:
- self._connection.isolation_level = None
- else:
- self._connection.isolation_level = ""
- self._autoCommit = val
-
-
def beginTransaction(self, cursor):
""" Begin a SQL transaction. Since pysqlite does an implicit
- 'begin' even when not using autocommit, simply do nothing.
+ 'begin' all the time, simply do nothing.
"""
+ dabo.dbActivityLog.write("SQL: begin (implicit, nothing done)")
pass
+
+
+ def commitTransaction(self, cursor):
+ """ Commit a SQL transaction."""
+ try:
+ cursor.execute("COMMIT")
+ dabo.dbActivityLog.write("SQL: commit")
+ except Exception, e:
+ if "no transaction is active" in str(e):
+ pass
+ else:
+ dabo.dbActivityLog.write("SQL: commit failed:
%s" % e)
+ raise dException.DBQueryException, e
+
+
+ def rollbackTransaction(self, cursor):
+ """ Rollback a SQL transaction."""
+ cursor.execute("ROLLBACK")
+ dabo.dbActivityLog.write("SQL: rollback")
+
-
def flush(self, crs):
+ dabo.dbActivityLog.write("SQL: flush")
self._connection.commit()
Modified: trunk/dabo/db/test/test_dCursorMixin.py
===================================================================
--- trunk/dabo/db/test/test_dCursorMixin.py 2007-08-14 21:57:09 UTC (rev
3313)
+++ trunk/dabo/db/test/test_dCursorMixin.py 2007-08-19 19:07:48 UTC (rev
3314)
@@ -45,16 +45,6 @@
return ""
## - Begin property unit tests -
- def test_AutoCommit(self):
- cur = self.cur
- self.assertEqual(cur.AutoCommit, False)
- try:
- cur.AutoCommit = True
- self.assertEqual(cur.AutoCommit, True)
- except ValueError:
- # Okay; this db didn't allow the setting of AutoCommit.
- self.assertEqual(cur.AutoCommit, False)
-
def test_AutoSQL(self):
cur = self.cur
self.assertEqual(cur.AutoSQL, "select *\n from %s\n limit
1000" % self.temp_table_name)
_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://leafe.com/mailman/listinfo/dabo-dev
Searchable Archives: http://leafe.com/archives/search/dabo-dev
This message: http://leafe.com/archives/byMID/dabo-dev/[EMAIL PROTECTED]