On Aug 13, 2010, at 10:22 PM, Peter Hansen wrote:

> On Jun 24, 1:23 pm, Michael Bayer <mike...@zzzcomputing.com> wrote:
>> On Jun 24, 2010, at 12:35 PM, Torsten Landschoff wrote:
>>> That's what I thought but it does not cure my problem.
>>> e.raw_connect().isolation_levelis in fact None, but the rollback is not
>>> done anyway. :-(
>> 
>> its passing it through.....dont know what else we can do there
> 
> I ran into this myself today and after struggling for a few hours I
> came across this thread.  I then ended up creating a test case to
> reproduce the problem and it suggests the problem stems from some
> behaviour of transactions or of the engine.base.Connection class.  I
> don't quite know what to make of it yet, but I think it shows that the
> effect of "passing it through" is being counteracted by something
> else.  I ran this on Python 2.6.5 with SA 0.6.3 on Windows.

Postgresql and MS-SQL support transactional DDL, and I use this feature all the 
time with SQLAlchemy which does nothing special to support them.   

In addition, isolation_level=None with pysqlite disables the DBAPIs entire 
transactional system.  SQLAlchemy relies upon this system to handle proper 
transactional behavior.  Per their documentation, some statements will fail if 
executed in a transaction - SQLAlchemy does not want to be involved in 
reorganizing how the DBAPI wants to approach things, emitting manual 'begin' 
and 'commit' strings, etc.

So I consider this a pysqlite bug, and they should offer a mode by which there 
is no implicit commit for CREATE TABLE.

See http://docs.python.org/library/sqlite3.html#controlling-transactions 




> 
> '''Test showing unexpected behaviour with sqlalchemy and sqlite3 and
> isolation_level settings.  The test creates one table outside of
> a transaction (to detect potential problems with the test not
> executing
> properly) then creates a second table inside a transaction which it
> immediately rolls back.
> 
> test01() fails basically as expected, since the sqlite3 DBAPI layer
> appears to need isolation_level==None to properly roll back DDL
> statements.

> 
> test02() succeeds because isolation_level==None now.  This test and
> test01()
> both use a connection from engine.raw_connection(), which is a
> sqlalchemy.pool._ConnectionFairy() object.
> 
> test03() tries again with isolation_level==None but using a
> transaction
> created from a connection returned by engine.connect(), which is a
> sqlalchemy.engine.base.Connection() object.  This test fails in spite
> of the isolation_level setting.
> '''
> 
> import unittest
> from sqlalchemy import create_engine
> 
> DBPATH = 'sqlite://'
> DDL = 'create table %s (id integer primary key)'
> 
> class TestCase(unittest.TestCase):
>    def setup(self, **kwargs):
>        self.engine = create_engine(DBPATH, **kwargs)
>        self.engine.execute(DDL % 'foo')
> 
>    def rollback_raw(self):
>        conn = self.engine.raw_connection()
>        try:
>            conn.execute('begin')
>            conn.execute(DDL % 'bar')
>            raise ValueError
>        except ValueError:
>            conn.rollback()
> 
>    def rollback_txn(self):
>        conn = self.engine.connect()
>        try:
>            txn = conn.begin()
>            conn.execute(DDL % 'bar')
>            raise ValueError
>        except ValueError:
>            txn.rollback()
> 
>    def get_table_names(self):
>        conn = self.engine.raw_connection()
>        return [x[0] for x in conn.execute('select name from
> sqlite_master')]
> 
>    def test01(self):
>        '''use engine with default isolation_level'''
>        self.setup()
>        self.rollback_raw()
>        self.assertEqual(['foo'], self.get_table_names())
> 
>    def test02(self):
>        '''use raw_connection with isolation_level None'''
>        self.setup(connect_args={'isolation_level': None})
>        self.rollback_raw()
>        self.assertEqual(['foo'], self.get_table_names())
> 
>    def test03(self):
>        '''use transaction with isolation_level None'''
>        self.setup(connect_args={'isolation_level': None})
>        self.rollback_txn()
>        self.assertEqual(['foo'], self.get_table_names())
> 
> if __name__ == '__main__':
>    unittest.main()
> 
> 
> --
> Peter Hansen
> Engenuity Corporation
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To post to this group, send email to sqlalch...@googlegroups.com.
> To unsubscribe from this group, send email to 
> sqlalchemy+unsubscr...@googlegroups.com.
> For more options, visit this group at 
> http://groups.google.com/group/sqlalchemy?hl=en.
> 

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to