[Checkins] SVN: z3c.zalchemy/trunk/src/z3c/zalchemy/ The ISQLAlchemyContainer interface needs to derive from IContainerNamesContainer to ensure that the name-choosing field does not pop up.

Michael Bernstein webmaven at cox.net
Sun Jan 14 17:58:42 EST 2007


Log message for revision 72037:
  The ISQLAlchemyContainer interface needs to derive from IContainerNamesContainer to ensure that the name-choosing field does not pop up.
  
  Both the SQLAlchemyNameChooser and SQLAlchemyContainer classes need to flush the entire session when an object is added, not just the added object. This is because a SQLAlchemy mapper can attach dependent objects (via FK relationships), whose changes will be lost if only the added object itself is flushed before the session is committed.
  
  Here is some non-Zope example code that demonstrates the problem. If you run it once, the PK in the data table is set to 0 (instead of 1 via th FK relationship with metadata), and on a second run, the code will fail because it tries to set data.id to 0 again, which it can't because it is a unique primary key.
  
  --8<------------------------------------------------------------
  
  from sqlalchemy import *
  
  global_connect('mysql://root:root@localhost/helloworld')
  
  metadata = Table('metadata',
      Column('id', Integer, Sequence('metadata_seq'), primary_key=True),
      )
  
  data = Table('data',
      Column('id', Integer, ForeignKey(metadata.c.id), primary_key=True),
      )
  
  class Data(object):
      def __init__(self):
          self.rdc = MetaData()
  class MetaData(object): pass
  
  metadata_mapper = mapper(MetaData, metadata)
  data_mapper = mapper(Data, data)
  data_mapper.add_property('rdc', relation(MetaData))
  
  metadata.create(checkfirst=True)
  data.create(checkfirst=True)
  session = create_session()
  trans = session.create_transaction()
  d = Data()
  session.save(d)
  session.flush([d])
  trans.commit()
  
  --8<------------------------------------------------------------
  
  Changing session.flush([d]) to session.flush() fixes the problem.
  
  While there may be situations where you want to flush a single object (or a list) instead of the whole session, those would be the exception, not the rule.
  
  

Changed:
  U   z3c.zalchemy/trunk/src/z3c/zalchemy/container.py
  U   z3c.zalchemy/trunk/src/z3c/zalchemy/interfaces.py

-=-
Modified: z3c.zalchemy/trunk/src/z3c/zalchemy/container.py
===================================================================
--- z3c.zalchemy/trunk/src/z3c/zalchemy/container.py	2007-01-14 22:00:29 UTC (rev 72036)
+++ z3c.zalchemy/trunk/src/z3c/zalchemy/container.py	2007-01-14 22:58:42 UTC (rev 72037)
@@ -76,7 +76,7 @@
         # flush the object to make sure it contains an id
         session = z3c.zalchemy.getSession()
         session.save(obj)
-        session.flush([obj])
+        session.flush()
         return self.context._toStringIdentifier(obj)
 
 
@@ -148,7 +148,7 @@
     def __setitem__(self, name, item):
         session = z3c.zalchemy.getSession()
         session.save(item)
-        session.flush([item])
+        session.flush()
 
     def _toStringIdentifier(self, obj):
         session = z3c.zalchemy.getSession()

Modified: z3c.zalchemy/trunk/src/z3c/zalchemy/interfaces.py
===================================================================
--- z3c.zalchemy/trunk/src/z3c/zalchemy/interfaces.py	2007-01-14 22:00:29 UTC (rev 72036)
+++ z3c.zalchemy/trunk/src/z3c/zalchemy/interfaces.py	2007-01-14 22:58:42 UTC (rev 72037)
@@ -13,7 +13,7 @@
 ##############################################################################
 from zope import interface
 from zope import schema
-from zope.app.container.interfaces import IContainer
+from zope.app.container.interfaces import IContainerNamesContainer
 from zope.app.container.constraints import contains, containers
 
 
@@ -22,7 +22,7 @@
     """
 
 
-class ISQLAlchemyContainer(IContainer):
+class ISQLAlchemyContainer(IContainerNamesContainer):
     """A zope container containing sqlalchemy objects.
     """
     className = schema.TextLine(



More information about the Checkins mailing list