[Zope3-checkins] SVN: Zope3/branches/Zope-3.1/src/zope/app/rdb/
Merged revision 38419 from the trunk:
Dmitry Vasiliev
dima at hlabs.spb.ru
Fri Sep 9 07:43:08 EDT 2005
Log message for revision 38421:
Merged revision 38419 from the trunk:
Added custom executemany() method for cursors created through GadflyAdapter.
See http://www.zope.org/Collectors/Zope3-dev/445 for discussion.
Changed:
U Zope3/branches/Zope-3.1/src/zope/app/rdb/__init__.py
U Zope3/branches/Zope-3.1/src/zope/app/rdb/gadflyda.py
U Zope3/branches/Zope-3.1/src/zope/app/rdb/interfaces.py
U Zope3/branches/Zope-3.1/src/zope/app/rdb/tests/test_gadflyadapter.py
-=-
Modified: Zope3/branches/Zope-3.1/src/zope/app/rdb/__init__.py
===================================================================
--- Zope3/branches/Zope-3.1/src/zope/app/rdb/__init__.py 2005-09-09 11:33:32 UTC (rev 38420)
+++ Zope3/branches/Zope-3.1/src/zope/app/rdb/__init__.py 2005-09-09 11:43:08 UTC (rev 38421)
@@ -31,7 +31,7 @@
from zope.interface import implements
from zope.app.container.contained import Contained
-from zope.app.rdb.interfaces import DatabaseException
+from zope.app.rdb.interfaces import DatabaseException, DatabaseAdapterError
from zope.app.rdb.interfaces import IResultSet
from zope.app.rdb.interfaces import IZopeConnection, IZopeCursor
from zope.app.rdb.interfaces import IManageableZopeDatabaseAdapter
@@ -104,10 +104,6 @@
return cmp(len(self), len(other))
-class DatabaseAdapterError(Exception):
- pass
-
-
class ZopeDatabaseAdapter(Persistent, Contained):
implements(IManageableZopeDatabaseAdapter)
@@ -152,6 +148,8 @@
try:
self._v_connection = ZopeConnection(
self._connection_factory(), self)
+ except DatabaseException:
+ raise
# Note: I added the general Exception, since the DA can return
# implementation-specific errors. But we really want to catch all
# issues at this point, so that we can convert it to a
@@ -294,6 +292,8 @@
"""Executes an operation, registering the underlying
connection with the transaction system. """
operation, parameters = self._prepareOperation(operation, parameters)
+ # If executemany() is not defined pass parameters
+ # to execute() as defined by DB API v.1
method = getattr(self.cursor, "executemany", self.cursor.execute)
self.connection.registerForTxn()
return method(operation, parameters)
Modified: Zope3/branches/Zope-3.1/src/zope/app/rdb/gadflyda.py
===================================================================
--- Zope3/branches/Zope-3.1/src/zope/app/rdb/gadflyda.py 2005-09-09 11:33:32 UTC (rev 38420)
+++ Zope3/branches/Zope-3.1/src/zope/app/rdb/gadflyda.py 2005-09-09 11:43:08 UTC (rev 38421)
@@ -19,17 +19,39 @@
import os
from zope.app.rdb import ZopeDatabaseAdapter, parseDSN
-from zope.app.rdb import DatabaseAdapterError
+from zope.app.rdb import DatabaseException, DatabaseAdapterError
+from zope.app.rdb import ZopeConnection, ZopeCursor
GadflyError = DatabaseAdapterError
+class GadflyAdapterCursor(ZopeCursor):
+
+ def executemany(self, operation, parameters):
+ command = operation.split(None, 1)[0].lower()
+ if command not in ("insert", "update", "delete"):
+ raise DatabaseAdapterError(
+ "executemany() is not applicable for %r" % operation)
+
+ operation, parameters = self._prepareOperation(operation, parameters)
+ self.connection.registerForTxn()
+ if command == "insert":
+ self.execute(operation, parameters)
+ else:
+ for param in parameters:
+ self.execute(operation, param)
+
+class GadflyAdapterConnection(ZopeConnection):
+
+ def cursor(self):
+ return GadflyAdapterCursor(self.conn.cursor(), self)
+
class GadflyAdapter(ZopeDatabaseAdapter):
"""A Gadfly adapter for Zope3"""
# The registerable object needs to have a container
__name__ = __parent__ = None
-
+
def _connection_factory(self):
"""Create a Gadfly DBI connection based on the DSN.
@@ -59,6 +81,14 @@
return db
+ def connect(self):
+ if not self.isConnected():
+ try:
+ self._v_connection = GadflyAdapterConnection(
+ self._connection_factory(), self)
+ except gadfly.error, error:
+ raise DatabaseException(str(error))
+
_gadflyRoot = 'gadfly'
def setGadflyRoot(path='gadfly'):
@@ -66,5 +96,4 @@
_gadflyRoot = path
def getGadflyRoot():
- global _gadflyRoot
return _gadflyRoot
Modified: Zope3/branches/Zope-3.1/src/zope/app/rdb/interfaces.py
===================================================================
--- Zope3/branches/Zope-3.1/src/zope/app/rdb/interfaces.py 2005-09-09 11:33:32 UTC (rev 38420)
+++ Zope3/branches/Zope-3.1/src/zope/app/rdb/interfaces.py 2005-09-09 11:43:08 UTC (rev 38421)
@@ -93,6 +93,9 @@
def __str__(self):
return self.message
+class DatabaseAdapterError(DatabaseException):
+ pass
+
arraysize = 1 # default constant, symbolic
class IDBICursor(Interface):
Modified: Zope3/branches/Zope-3.1/src/zope/app/rdb/tests/test_gadflyadapter.py
===================================================================
--- Zope3/branches/Zope-3.1/src/zope/app/rdb/tests/test_gadflyadapter.py 2005-09-09 11:33:32 UTC (rev 38420)
+++ Zope3/branches/Zope-3.1/src/zope/app/rdb/tests/test_gadflyadapter.py 2005-09-09 11:43:08 UTC (rev 38421)
@@ -141,12 +141,82 @@
cursor = connection.cursor()
verifyObject(IZopeCursor, cursor)
+class GadflyCursorStub(object):
+ def __init__(self):
+ self.operations = []
+
+ def execute(self, operation, parameters=None):
+ self.operations.append((operation, parameters))
+
+class GadflyConnectionStub(object):
+
+ def cursor(self):
+ return GadflyCursorStub()
+
+ def commit(self):
+ pass
+
+ def rollback(self):
+ pass
+
+ def close(self):
+ pass
+
+class GadflyTestAdapter(GadflyAdapter):
+
+ def _connection_factory(self):
+ return GadflyConnectionStub()
+
+class GadflyAdapterTests(TestCase):
+
+ def setUp(self):
+ self.adapter = GadflyTestAdapter("dbi://")
+ self.connection = self.adapter()
+ self.cursor = self.connection.cursor()
+
+ def testBadExecutemanyOperations(self):
+ raises = self.assertRaises
+ for operation in [
+ "SELECT",
+ "CREATE",
+ "DROP",
+ ]:
+ raises(DatabaseAdapterError,
+ self.cursor.executemany, operation, [])
+
+ def testExecutemanyInsert(self):
+ operation = "INSERT INTO table(v1, v2) VALUES (?, ?)"
+ parameters = [(1, 2), (3, 4)]
+ self.cursor.executemany(operation, parameters)
+ self.failUnlessEqual([(operation, parameters)],
+ self.cursor.operations)
+
+ def testExecutemanyUpdate(self):
+ operation = "UPDATE table SET value=0 WHERE id=?"
+ parameters = [(1,), (2,)]
+ self.cursor.executemany(operation, parameters)
+ self.failUnlessEqual([
+ (operation, parameters[0]),
+ (operation, parameters[1]),
+ ], self.cursor.operations)
+
+ def testExecutemanyDelete(self):
+ operation = "DELETE FROM table WHERE id=?"
+ parameters = [(1,), (2,)]
+ self.cursor.executemany(operation, parameters)
+ self.failUnlessEqual([
+ (operation, parameters[0]),
+ (operation, parameters[1]),
+ ], self.cursor.operations)
+
+
def test_suite():
return TestSuite((
makeSuite(TestGadflyAdapter),
makeSuite(TestGadflyAdapterNew),
makeSuite(TestGadflyAdapterDefault),
+ makeSuite(GadflyAdapterTests),
))
if __name__=='__main__':
More information about the Zope3-Checkins
mailing list