def test_transactional(self): track = [] class TrackProxy(ConnectionProxy): def __getattribute__(self, key): fn = object.__getattribute__(self, key) def go(*arg, **kw): track.append(fn.__name__) return fn(*arg, **kw) return go engine = engines.testing_engine(options={'proxy':TrackProxy()}) conn = engine.connect() trans = conn.begin() conn.execute(select([1])) trans.rollback() trans = conn.begin() conn.execute(select([1])) trans.commit() eq_(track, [ 'begin', 'execute', 'cursor_execute', 'rollback', 'begin', 'execute', 'cursor_execute', 'commit', ])
def test_transactional_advanced(self): track = [] class TrackProxy(ConnectionProxy): def __getattribute__(self, key): fn = object.__getattribute__(self, key) def go(*arg, **kw): track.append(fn.__name__) return fn(*arg, **kw) return go engine = engines.testing_engine(options={'proxy':TrackProxy()}) conn = engine.connect() trans = conn.begin() trans2 = conn.begin_nested() conn.execute(select([1])) trans2.rollback() trans2 = conn.begin_nested() conn.execute(select([1])) trans2.commit() trans.rollback() trans = conn.begin_twophase() conn.execute(select([1])) trans.prepare() trans.commit() track = [t for t in track if t not in ('cursor_execute', 'execute')] eq_(track, ['begin', 'savepoint', 'rollback_savepoint', 'savepoint', 'release_savepoint', 'rollback', 'begin_twophase', 'prepare_twophase', 'commit_twophase'] )
def go(): engine = engines.testing_engine( options={'logging_name':'FOO', 'pool_logging_name':'BAR'} ) sess = create_session(bind=engine) a1 = A(col2="a1") a2 = A(col2="a2") a3 = A(col2="a3") a1.bs.append(B(col2="b1")) a1.bs.append(B(col2="b2")) a3.bs.append(B(col2="b3")) for x in [a1,a2,a3]: sess.add(x) sess.flush() sess.expunge_all() alist = sess.query(A).all() eq_( [ A(col2="a1", bs=[B(col2="b1"), B(col2="b2")]), A(col2="a2", bs=[]), A(col2="a3", bs=[B(col2="b3")]) ], alist) for a in alist: sess.delete(a) sess.flush() sess.close() engine.dispose()
def test_no_rowcount_on_selects_inserts(self): """assert that rowcount is only called on deletes and updates. This because cursor.rowcount can be expensive on some dialects such as Firebird. """ engine = engines.testing_engine() metadata.bind = engine t = Table('t1', metadata, Column('data', String(10))) metadata.create_all() class BreakRowcountMixin(object): @property def rowcount(self): assert False execution_ctx_cls = engine.dialect.execution_ctx_cls engine.dialect.execution_ctx_cls = type( "FakeCtx", (BreakRowcountMixin, execution_ctx_cls), {}) try: r = t.insert().execute({'data': 'd1'}, {'data': 'd2'}, {'data': 'd3'}) eq_(t.select().execute().fetchall(), [('d1', ), ('d2', ), ('d3', )]) assert_raises(AssertionError, t.update().execute, {'data': 'd4'}) assert_raises(AssertionError, t.delete().execute) finally: engine.dialect.execution_ctx_cls = execution_ctx_cls
def test_transactional(self): track = [] class TrackProxy(ConnectionProxy): def __getattribute__(self, key): fn = object.__getattribute__(self, key) def go(*arg, **kw): track.append(fn.__name__) return fn(*arg, **kw) return go engine = engines.testing_engine(options={'proxy': TrackProxy()}) conn = engine.connect() trans = conn.begin() conn.execute(select([1])) trans.rollback() trans = conn.begin() conn.execute(select([1])) trans.commit() eq_(track, [ 'begin', 'execute', 'cursor_execute', 'rollback', 'begin', 'execute', 'cursor_execute', 'commit', ])
def test_native_odbc_execute(self): t1 = Table('t1', MetaData(), Column('c1', Integer)) dbapi = MockDBAPI() engine = engines.testing_engine('mssql+mxodbc://localhost', options={ 'module': dbapi, '_initialize': False }) conn = engine.connect() # crud: uses execute conn.execute(t1.insert().values(c1='foo')) conn.execute(t1.delete().where(t1.c.c1 == 'foo')) conn.execute(t1.update().where(t1.c.c1 == 'foo').values(c1='bar')) # select: uses executedirect conn.execute(t1.select()) # manual flagging conn.execution_options(native_odbc_execute=True).\ execute(t1.select()) conn.execution_options(native_odbc_execute=False).\ execute(t1.insert().values(c1='foo' )) eq_(dbapi.log, [ 'execute', 'execute', 'execute', 'executedirect', 'execute', 'executedirect', ])
def test_explode_in_initializer(self): engine = engines.testing_engine() def broken_initialize(connection): connection.execute("select fake_stuff from _fake_table") engine.dialect.initialize = broken_initialize # raises a DBAPIError, not an AttributeError assert_raises(exc.DBAPIError, engine.connect) # dispose connections so we get a new one on # next go engine.dispose() p1 = engine.pool def is_disconnect(e): return True engine.dialect.is_disconnect = is_disconnect # invalidate() also doesn't screw up assert_raises(exc.DBAPIError, engine.connect) # pool was recreated assert engine.pool is not p1
def go(): engine = engines.testing_engine(options={ 'logging_name': 'FOO', 'pool_logging_name': 'BAR' }) sess = create_session(bind=engine) a1 = A(col2="a1") a2 = A(col2="a2") a3 = A(col2="a3") a1.bs.append(B(col2="b1")) a1.bs.append(B(col2="b2")) a3.bs.append(B(col2="b3")) for x in [a1, a2, a3]: sess.add(x) sess.flush() sess.expunge_all() alist = sess.query(A).all() eq_([ A(col2="a1", bs=[B(col2="b1"), B(col2="b2")]), A(col2="a2", bs=[]), A(col2="a3", bs=[B(col2="b3")]) ], alist) for a in alist: sess.delete(a) sess.flush() sess.close() engine.dispose()
def test_native_odbc_execute(self): t1 = Table('t1', MetaData(), Column('c1', Integer)) dbapi = MockDBAPI() engine = engines.testing_engine('mssql+mxodbc://localhost', options={'module': dbapi, '_initialize': False}) conn = engine.connect() # crud: uses execute conn.execute(t1.insert().values(c1='foo')) conn.execute(t1.delete().where(t1.c.c1 == 'foo')) conn.execute(t1.update().where(t1.c.c1 == 'foo').values(c1='bar' )) # select: uses executedirect conn.execute(t1.select()) # manual flagging conn.execution_options(native_odbc_execute=True).\ execute(t1.select()) conn.execution_options(native_odbc_execute=False).\ execute(t1.insert().values(c1='foo' )) eq_(dbapi.log, [ 'execute', 'execute', 'execute', 'executedirect', 'execute', 'executedirect', ])
def test_unnamed_logger(self): eng = engines.testing_engine(options={'echo': 'debug', 'echo_pool': 'debug'}) self._test_logger( eng, "0x...%s" % hex(id(eng))[-4:], "0x...%s" % hex(id(eng.pool))[-4:], )
def test_named_logger(self): options = {'echo':'debug', 'echo_pool':'debug', 'logging_name':'myenginename', 'pool_logging_name':'mypoolname' } eng = engines.testing_engine(options=options) self._test_logger(eng, "myenginename", "mypoolname") eng.dispose() self._test_logger(eng, "myenginename", "mypoolname")
def test_unnamed_logger(self): eng = engines.testing_engine(options={ 'echo': 'debug', 'echo_pool': 'debug' }) self._test_logger( eng, "0x...%s" % hex(id(eng))[-4:], "0x...%s" % hex(id(eng.pool))[-4:], )
def _test(self, returning): if not returning and not testing.db.dialect.implicit_returning: engine = testing.db else: engine = engines.testing_engine(options={'implicit_returning':returning}) engine.execute(t2.insert(), nextid=1) r = engine.execute(t1.insert(), data='hi') eq_([1], r.inserted_primary_key) engine.execute(t2.insert(), nextid=2) r = engine.execute(t1.insert(), data='there') eq_([2], r.inserted_primary_key)
def test_named_logger(self): options = { 'echo': 'debug', 'echo_pool': 'debug', 'logging_name': 'myenginename', 'pool_logging_name': 'mypoolname' } eng = engines.testing_engine(options=options) self._test_logger(eng, "myenginename", "mypoolname") eng.dispose() self._test_logger(eng, "myenginename", "mypoolname")
def _test(self, returning): if not returning and not testing.db.dialect.implicit_returning: engine = testing.db else: engine = engines.testing_engine( options={'implicit_returning': returning}) engine.execute(t2.insert(), nextid=1) r = engine.execute(t1.insert(), data='hi') eq_([1], r.inserted_primary_key) engine.execute(t2.insert(), nextid=2) r = engine.execute(t1.insert(), data='there') eq_([2], r.inserted_primary_key)
def test_raw_lobs(self): engine = testing_engine(options=dict(auto_convert_lobs=False)) metadata = MetaData() t = Table("z_test", metadata, Column('id', Integer, primary_key=True), Column('data', Text), Column('bindata', LargeBinary)) t.create(engine) try: engine.execute(t.insert(), id=1, data='this is text', bindata='this is binary') row = engine.execute(t.select()).first() eq_(row['data'].read(), 'this is text') eq_(row['bindata'].read(), 'this is binary') finally: t.drop(engine)
def test_engine_level_options(self): eng = engines.testing_engine(options={'execution_options' : {'foo': 'bar'}}) conn = eng.contextual_connect() eq_(conn._execution_options['foo'], 'bar') eq_(conn.execution_options(bat='hoho')._execution_options['foo' ], 'bar') eq_(conn.execution_options(bat='hoho')._execution_options['bat' ], 'hoho') eq_(conn.execution_options(foo='hoho')._execution_options['foo' ], 'hoho') eng.update_execution_options(foo='hoho') conn = eng.contextual_connect() eq_(conn._execution_options['foo'], 'hoho')
def test_seq_nonpk(self): """test sequences fire off as defaults on non-pk columns""" engine = engines.testing_engine(options={'implicit_returning': False}) result = engine.execute(sometable.insert(), name="somename") assert set(result.postfetch_cols()) == set([sometable.c.obj_id]) result = engine.execute(sometable.insert(), name="someother") assert set(result.postfetch_cols()) == set([sometable.c.obj_id]) sometable.insert().execute({'name': 'name3'}, {'name': 'name4'}) eq_(sometable.select().order_by(sometable.c.id).execute().fetchall(), [(1, "somename", 1), (2, "someother", 2), (3, "name3", 3), (4, "name4", 4)])
def test_options(self): track = [] class TrackProxy(ConnectionProxy): def __getattribute__(self, key): fn = object.__getattribute__(self, key) def go(*arg, **kw): track.append(fn.__name__) return fn(*arg, **kw) return go engine = engines.testing_engine(options={'proxy':TrackProxy()}) conn = engine.connect() c2 = conn.execution_options(foo='bar') eq_(c2._execution_options, {'foo':'bar'}) c2.execute(select([1])) c3 = c2.execution_options(bar='bat') eq_(c3._execution_options, {'foo':'bar', 'bar':'bat'}) eq_(track, ['execute', 'cursor_execute'])
def test_twophase(self): # TODO: mock up a failure condition here # to ensure a rollback succeeds mapper(User, users) mapper(Address, addresses) engine2 = engines.testing_engine() sess = create_session(autocommit=True, autoflush=False, twophase=True) sess.bind_mapper(User, testing.db) sess.bind_mapper(Address, engine2) sess.begin() u1 = User(name='u1') a1 = Address(email_address='u1@e') sess.add_all((u1, a1)) sess.commit() sess.close() engine2.dispose() assert users.count().scalar() == 1 assert addresses.count().scalar() == 1
def test_engine_level_options(self): eng = engines.testing_engine( options={'execution_options': { 'foo': 'bar' }}) conn = eng.contextual_connect() eq_(conn._execution_options['foo'], 'bar') eq_( conn.execution_options(bat='hoho')._execution_options['foo'], 'bar') eq_( conn.execution_options(bat='hoho')._execution_options['bat'], 'hoho') eq_( conn.execution_options(foo='hoho')._execution_options['foo'], 'hoho') eng.update_execution_options(foo='hoho') conn = eng.contextual_connect() eq_(conn._execution_options['foo'], 'hoho')
def test_seq_nonpk(self): """test sequences fire off as defaults on non-pk columns""" engine = engines.testing_engine(options={'implicit_returning':False}) result = engine.execute(sometable.insert(), name="somename") assert set(result.postfetch_cols()) == set([sometable.c.obj_id]) result = engine.execute(sometable.insert(), name="someother") assert set(result.postfetch_cols()) == set([sometable.c.obj_id]) sometable.insert().execute( {'name':'name3'}, {'name':'name4'}) eq_(sometable.select().order_by(sometable.c.id).execute().fetchall(), [(1, "somename", 1), (2, "someother", 2), (3, "name3", 3), (4, "name4", 4)])
def test_options(self): track = [] class TrackProxy(ConnectionProxy): def __getattribute__(self, key): fn = object.__getattribute__(self, key) def go(*arg, **kw): track.append(fn.__name__) return fn(*arg, **kw) return go engine = engines.testing_engine(options={'proxy': TrackProxy()}) conn = engine.connect() c2 = conn.execution_options(foo='bar') eq_(c2._execution_options, {'foo': 'bar'}) c2.execute(select([1])) c3 = c2.execution_options(bar='bat') eq_(c3._execution_options, {'foo': 'bar', 'bar': 'bat'}) eq_(track, ['execute', 'cursor_execute'])
def test_no_rowcount_on_selects_inserts(self): """assert that rowcount is only called on deletes and updates. This because cursor.rowcount can be expensive on some dialects such as Firebird. """ engine = engines.testing_engine() metadata.bind = engine t = Table('t1', metadata, Column('data', String(10)) ) metadata.create_all() class BreakRowcountMixin(object): @property def rowcount(self): assert False execution_ctx_cls = engine.dialect.execution_ctx_cls engine.dialect.execution_ctx_cls = type("FakeCtx", (BreakRowcountMixin, execution_ctx_cls), {}) try: r = t.insert().execute({'data': 'd1'}, {'data': 'd2'}, {'data': 'd3'}) eq_(t.select().execute().fetchall(), [('d1', ), ('d2', ), ('d3', )]) assert_raises(AssertionError, t.update().execute, {'data' : 'd4'}) assert_raises(AssertionError, t.delete().execute) finally: engine.dialect.execution_ctx_cls = execution_ctx_cls
def test_transactional_advanced(self): track = [] class TrackProxy(ConnectionProxy): def __getattribute__(self, key): fn = object.__getattribute__(self, key) def go(*arg, **kw): track.append(fn.__name__) return fn(*arg, **kw) return go engine = engines.testing_engine(options={'proxy': TrackProxy()}) conn = engine.connect() trans = conn.begin() trans2 = conn.begin_nested() conn.execute(select([1])) trans2.rollback() trans2 = conn.begin_nested() conn.execute(select([1])) trans2.commit() trans.rollback() trans = conn.begin_twophase() conn.execute(select([1])) trans.prepare() trans.commit() track = [t for t in track if t not in ('cursor_execute', 'execute')] eq_(track, [ 'begin', 'savepoint', 'rollback_savepoint', 'savepoint', 'release_savepoint', 'rollback', 'begin_twophase', 'prepare_twophase', 'commit_twophase' ])
def test_proxy(self): stmts = [] cursor_stmts = [] class MyProxy(ConnectionProxy): def execute(self, conn, execute, clauseelement, *multiparams, **params): stmts.append( (str(clauseelement), params,multiparams) ) return execute(clauseelement, *multiparams, **params) def cursor_execute(self, execute, cursor, statement, parameters, context, executemany): cursor_stmts.append( (str(statement), parameters, None) ) return execute(cursor, statement, parameters, context) def assert_stmts(expected, received): for stmt, params, posn in expected: if not received: assert False while received: teststmt, testparams, testmultiparams = received.pop(0) teststmt = re.compile(r'[\n\t ]+', re.M).sub(' ', teststmt).strip() if teststmt.startswith(stmt) and (testparams==params or testparams==posn): break for engine in ( engines.testing_engine(options=dict(implicit_returning=False, proxy=MyProxy())), engines.testing_engine(options=dict( implicit_returning=False, proxy=MyProxy(), strategy='threadlocal')) ): m = MetaData(engine) t1 = Table('t1', m, Column('c1', Integer, primary_key=True), Column('c2', String(50), default=func.lower('Foo'), primary_key=True) ) m.create_all() try: t1.insert().execute(c1=5, c2='some data') t1.insert().execute(c1=6) eq_(engine.execute("select * from t1").fetchall(), [(5, 'some data'), (6, 'foo')] ) finally: m.drop_all() engine.dispose() compiled = [ ("CREATE TABLE t1", {}, None), ("INSERT INTO t1 (c1, c2)", {'c2': 'some data', 'c1': 5}, None), ("INSERT INTO t1 (c1, c2)", {'c1': 6}, None), ("select * from t1", {}, None), ("DROP TABLE t1", {}, None) ] if not testing.against('oracle+zxjdbc'): # or engine.dialect.preexecute_pk_sequences: cursor = [ ("CREATE TABLE t1", {}, ()), ("INSERT INTO t1 (c1, c2)", {'c2': 'some data', 'c1': 5}, (5, 'some data')), ("SELECT lower", {'lower_2':'Foo'}, ('Foo',)), ("INSERT INTO t1 (c1, c2)", {'c2': 'foo', 'c1': 6}, (6, 'foo')), ("select * from t1", {}, ()), ("DROP TABLE t1", {}, ()) ] else: insert2_params = (6, 'Foo') if testing.against('oracle+zxjdbc'): from sqlalchemy.dialects.oracle.zxjdbc import ReturningParam insert2_params.append(ReturningParam(12)) cursor = [ ("CREATE TABLE t1", {}, ()), ("INSERT INTO t1 (c1, c2)", {'c2': 'some data', 'c1': 5}, (5, 'some data')), # bind param name 'lower_2' might be incorrect ("INSERT INTO t1 (c1, c2)", {'c1': 6, "lower_2":"Foo"}, insert2_params), ("select * from t1", {}, ()), ("DROP TABLE t1", {}, ()) ] assert_stmts(compiled, stmts) assert_stmts(cursor, cursor_stmts)
def _create_testing_engine(options, file_config): from sqlalchemy.test import engines, testing global db db = engines.testing_engine(db_url, db_opts) testing.db = db
def create_engine(cls): return engines.testing_engine(options=dict(strategy='threadlocal'))
def setup(self): self.sql = self.accum() opts = config.db_opts.copy() opts['strategy'] = 'mock' opts['executor'] = self.sql self.engine = engines.testing_engine(options=opts)
def test_fetch_single_arraysize(self): eng = testing_engine(options={'arraysize':1}) result = eng.execute(binary_table.select()).fetchall() eq_(result, [(i, stream) for i in range(1, 11)])
def test_proxy(self): stmts = [] cursor_stmts = [] class MyProxy(ConnectionProxy): def execute(self, conn, execute, clauseelement, *multiparams, **params): stmts.append((str(clauseelement), params, multiparams)) return execute(clauseelement, *multiparams, **params) def cursor_execute( self, execute, cursor, statement, parameters, context, executemany, ): cursor_stmts.append((str(statement), parameters, None)) return execute(cursor, statement, parameters, context) def assert_stmts(expected, received): for stmt, params, posn in expected: if not received: assert False while received: teststmt, testparams, testmultiparams = \ received.pop(0) teststmt = re.compile(r'[\n\t ]+', re.M).sub(' ', teststmt).strip() if teststmt.startswith(stmt) and (testparams == params or testparams == posn): break for engine in \ engines.testing_engine(options=dict(implicit_returning=False, proxy=MyProxy())), \ engines.testing_engine(options=dict(implicit_returning=False, proxy=MyProxy(), strategy='threadlocal')): m = MetaData(engine) t1 = Table( 't1', m, Column('c1', Integer, primary_key=True), Column('c2', String(50), default=func.lower('Foo'), primary_key=True)) m.create_all() try: t1.insert().execute(c1=5, c2='some data') t1.insert().execute(c1=6) eq_( engine.execute('select * from t1').fetchall(), [(5, 'some data'), (6, 'foo')]) finally: m.drop_all() engine.dispose() compiled = [('CREATE TABLE t1', {}, None), ('INSERT INTO t1 (c1, c2)', { 'c2': 'some data', 'c1': 5 }, None), ('INSERT INTO t1 (c1, c2)', { 'c1': 6 }, None), ('select * from t1', {}, None), ('DROP TABLE t1', {}, None)] if not testing.against('oracle+zxjdbc'): # or engine.dialect.pr # eexecute_pk_sequence # s: cursor = [ ('CREATE TABLE t1', {}, ()), ('INSERT INTO t1 (c1, c2)', { 'c2': 'some data', 'c1': 5 }, (5, 'some data')), ('SELECT lower', { 'lower_2': 'Foo' }, ('Foo', )), ('INSERT INTO t1 (c1, c2)', { 'c2': 'foo', 'c1': 6 }, (6, 'foo')), ('select * from t1', {}, ()), ('DROP TABLE t1', {}, ()), ] else: insert2_params = 6, 'Foo' if testing.against('oracle+zxjdbc'): insert2_params += (ReturningParam(12), ) cursor = [('CREATE TABLE t1', {}, ()), ('INSERT INTO t1 (c1, c2)', { 'c2': 'some data', 'c1': 5 }, (5, 'some data')), ('INSERT INTO t1 (c1, c2)', { 'c1': 6, 'lower_2': 'Foo' }, insert2_params), ('select * from t1', {}, ()), ('DROP TABLE t1', {}, ()) ] # bind param name 'lower_2' might # be incorrect assert_stmts(compiled, stmts) assert_stmts(cursor, cursor_stmts)