mirror of
https://github.com/sqlalchemy/sqlalchemy.git
synced 2026-05-28 11:35:19 -04:00
772374735d
tested using pycodestyle version 2.2.0 Fixes: #3885 Change-Id: I5df43adc3aefe318f9eeab72a078247a548ec566 Pull-request: https://github.com/zzzeek/sqlalchemy/pull/343
484 lines
15 KiB
Python
484 lines
15 KiB
Python
from sqlalchemy.testing import assert_raises_message
|
|
from sqlalchemy import MetaData, Integer, ForeignKey
|
|
from sqlalchemy.testing.schema import Table
|
|
from sqlalchemy.testing.schema import Column
|
|
from sqlalchemy.orm import mapper, create_session
|
|
import sqlalchemy as sa
|
|
from sqlalchemy import testing
|
|
from sqlalchemy.testing import fixtures, eq_, engines, is_
|
|
from sqlalchemy.orm import relationship, Session, backref, sessionmaker
|
|
from test.orm import _fixtures
|
|
from sqlalchemy.testing.mock import Mock
|
|
|
|
|
|
class BindIntegrationTest(_fixtures.FixtureTest):
|
|
run_inserts = None
|
|
|
|
def test_mapped_binds(self):
|
|
Address, addresses, users, User = (self.classes.Address,
|
|
self.tables.addresses,
|
|
self.tables.users,
|
|
self.classes.User)
|
|
|
|
# ensure tables are unbound
|
|
m2 = sa.MetaData()
|
|
users_unbound = users.tometadata(m2)
|
|
addresses_unbound = addresses.tometadata(m2)
|
|
|
|
mapper(Address, addresses_unbound)
|
|
mapper(User, users_unbound, properties={
|
|
'addresses': relationship(Address,
|
|
backref=backref("user", cascade="all"),
|
|
cascade="all")})
|
|
|
|
sess = Session(binds={User: self.metadata.bind,
|
|
Address: self.metadata.bind})
|
|
|
|
u1 = User(id=1, name='ed')
|
|
sess.add(u1)
|
|
eq_(sess.query(User).filter(User.id == 1).all(),
|
|
[User(id=1, name='ed')])
|
|
|
|
# test expression binding
|
|
|
|
sess.execute(users_unbound.insert(), params=dict(id=2,
|
|
name='jack'))
|
|
eq_(sess.execute(users_unbound.select(users_unbound.c.id
|
|
== 2)).fetchall(), [(2, 'jack')])
|
|
|
|
eq_(sess.execute(users_unbound.select(User.id == 2)).fetchall(),
|
|
[(2, 'jack')])
|
|
|
|
sess.execute(users_unbound.delete())
|
|
eq_(sess.execute(users_unbound.select()).fetchall(), [])
|
|
|
|
sess.close()
|
|
|
|
def test_table_binds(self):
|
|
Address, addresses, users, User = (self.classes.Address,
|
|
self.tables.addresses,
|
|
self.tables.users,
|
|
self.classes.User)
|
|
|
|
# ensure tables are unbound
|
|
m2 = sa.MetaData()
|
|
users_unbound = users.tometadata(m2)
|
|
addresses_unbound = addresses.tometadata(m2)
|
|
|
|
mapper(Address, addresses_unbound)
|
|
mapper(User, users_unbound, properties={
|
|
'addresses': relationship(Address,
|
|
backref=backref("user", cascade="all"),
|
|
cascade="all")})
|
|
|
|
Session = sessionmaker(binds={users_unbound: self.metadata.bind,
|
|
addresses_unbound: self.metadata.bind})
|
|
sess = Session()
|
|
|
|
u1 = User(id=1, name='ed')
|
|
sess.add(u1)
|
|
eq_(sess.query(User).filter(User.id == 1).all(),
|
|
[User(id=1, name='ed')])
|
|
|
|
sess.execute(users_unbound.insert(), params=dict(id=2, name='jack'))
|
|
|
|
eq_(sess.execute(users_unbound.select(users_unbound.c.id
|
|
== 2)).fetchall(), [(2, 'jack')])
|
|
|
|
eq_(sess.execute(users_unbound.select(User.id == 2)).fetchall(),
|
|
[(2, 'jack')])
|
|
|
|
sess.execute(users_unbound.delete())
|
|
eq_(sess.execute(users_unbound.select()).fetchall(), [])
|
|
|
|
sess.close()
|
|
|
|
def test_bind_from_metadata(self):
|
|
users, User = self.tables.users, self.classes.User
|
|
|
|
mapper(User, users)
|
|
|
|
session = create_session()
|
|
session.execute(users.insert(), dict(name='Johnny'))
|
|
|
|
assert len(session.query(User).filter_by(name='Johnny').all()) == 1
|
|
|
|
session.execute(users.delete())
|
|
|
|
assert len(session.query(User).filter_by(name='Johnny').all()) == 0
|
|
session.close()
|
|
|
|
def test_bind_arguments(self):
|
|
users, Address, addresses, User = (self.tables.users,
|
|
self.classes.Address,
|
|
self.tables.addresses,
|
|
self.classes.User)
|
|
|
|
mapper(User, users)
|
|
mapper(Address, addresses)
|
|
|
|
e1 = engines.testing_engine()
|
|
e2 = engines.testing_engine()
|
|
e3 = engines.testing_engine()
|
|
|
|
sess = Session(e3)
|
|
sess.bind_mapper(User, e1)
|
|
sess.bind_mapper(Address, e2)
|
|
|
|
assert sess.connection().engine is e3
|
|
assert sess.connection(bind=e1).engine is e1
|
|
assert sess.connection(mapper=Address, bind=e1).engine is e1
|
|
assert sess.connection(mapper=Address).engine is e2
|
|
assert sess.connection(clause=addresses.select()).engine is e2
|
|
assert sess.connection(mapper=User,
|
|
clause=addresses.select()).engine is e1
|
|
assert sess.connection(mapper=User,
|
|
clause=addresses.select(),
|
|
bind=e2).engine is e2
|
|
|
|
sess.close()
|
|
|
|
def test_bind_arg(self):
|
|
sess = Session()
|
|
|
|
assert_raises_message(
|
|
sa.exc.ArgumentError,
|
|
"Not an acceptable bind target: foobar",
|
|
sess.bind_mapper, "foobar", testing.db
|
|
)
|
|
|
|
mapper(self.classes.User, self.tables.users)
|
|
u_object = self.classes.User()
|
|
|
|
assert_raises_message(
|
|
sa.exc.ArgumentError,
|
|
"Not an acceptable bind target: User()",
|
|
sess.bind_mapper, u_object, testing.db
|
|
)
|
|
|
|
@engines.close_open_connections
|
|
def test_bound_connection(self):
|
|
users, User = self.tables.users, self.classes.User
|
|
|
|
mapper(User, users)
|
|
c = testing.db.connect()
|
|
sess = create_session(bind=c)
|
|
sess.begin()
|
|
transaction = sess.transaction
|
|
u = User(name='u1')
|
|
sess.add(u)
|
|
sess.flush()
|
|
assert transaction._connection_for_bind(testing.db, None) \
|
|
is transaction._connection_for_bind(c, None) is c
|
|
|
|
assert_raises_message(sa.exc.InvalidRequestError,
|
|
'Session already has a Connection '
|
|
'associated',
|
|
transaction._connection_for_bind,
|
|
testing.db.connect(), None)
|
|
transaction.rollback()
|
|
assert len(sess.query(User).all()) == 0
|
|
sess.close()
|
|
|
|
def test_bound_connection_transactional(self):
|
|
User, users = self.classes.User, self.tables.users
|
|
|
|
mapper(User, users)
|
|
c = testing.db.connect()
|
|
|
|
sess = create_session(bind=c, autocommit=False)
|
|
u = User(name='u1')
|
|
sess.add(u)
|
|
sess.flush()
|
|
sess.close()
|
|
assert not c.in_transaction()
|
|
assert c.scalar("select count(1) from users") == 0
|
|
|
|
sess = create_session(bind=c, autocommit=False)
|
|
u = User(name='u2')
|
|
sess.add(u)
|
|
sess.flush()
|
|
sess.commit()
|
|
assert not c.in_transaction()
|
|
assert c.scalar("select count(1) from users") == 1
|
|
c.execute("delete from users")
|
|
assert c.scalar("select count(1) from users") == 0
|
|
|
|
c = testing.db.connect()
|
|
|
|
trans = c.begin()
|
|
sess = create_session(bind=c, autocommit=True)
|
|
u = User(name='u3')
|
|
sess.add(u)
|
|
sess.flush()
|
|
assert c.in_transaction()
|
|
trans.commit()
|
|
assert not c.in_transaction()
|
|
assert c.scalar("select count(1) from users") == 1
|
|
|
|
|
|
class SessionBindTest(fixtures.MappedTest):
|
|
|
|
@classmethod
|
|
def define_tables(cls, metadata):
|
|
Table('test_table', metadata,
|
|
Column('id', Integer, primary_key=True,
|
|
test_needs_autoincrement=True),
|
|
Column('data', Integer))
|
|
|
|
@classmethod
|
|
def setup_classes(cls):
|
|
class Foo(cls.Basic):
|
|
pass
|
|
|
|
@classmethod
|
|
def setup_mappers(cls):
|
|
test_table, Foo = cls.tables.test_table, cls.classes.Foo
|
|
|
|
meta = MetaData()
|
|
test_table.tometadata(meta)
|
|
|
|
assert meta.tables['test_table'].bind is None
|
|
mapper(Foo, meta.tables['test_table'])
|
|
|
|
def test_session_bind(self):
|
|
Foo = self.classes.Foo
|
|
|
|
engine = self.metadata.bind
|
|
|
|
for bind in (engine, engine.connect()):
|
|
try:
|
|
sess = create_session(bind=bind)
|
|
assert sess.bind is bind
|
|
f = Foo()
|
|
sess.add(f)
|
|
sess.flush()
|
|
assert sess.query(Foo).get(f.id) is f
|
|
finally:
|
|
if hasattr(bind, 'close'):
|
|
bind.close()
|
|
|
|
def test_session_unbound(self):
|
|
Foo = self.classes.Foo
|
|
|
|
sess = create_session()
|
|
sess.add(Foo())
|
|
assert_raises_message(
|
|
sa.exc.UnboundExecutionError,
|
|
('Could not locate a bind configured on Mapper|Foo|test_table '
|
|
'or this Session'),
|
|
sess.flush)
|
|
|
|
|
|
class GetBindTest(fixtures.MappedTest):
|
|
@classmethod
|
|
def define_tables(cls, metadata):
|
|
Table(
|
|
'base_table', metadata,
|
|
Column('id', Integer, primary_key=True)
|
|
)
|
|
Table(
|
|
'w_mixin_table', metadata,
|
|
Column('id', Integer, primary_key=True)
|
|
)
|
|
Table(
|
|
'joined_sub_table', metadata,
|
|
Column('id', ForeignKey('base_table.id'), primary_key=True)
|
|
)
|
|
Table(
|
|
'concrete_sub_table', metadata,
|
|
Column('id', Integer, primary_key=True)
|
|
)
|
|
|
|
@classmethod
|
|
def setup_classes(cls):
|
|
class MixinOne(cls.Basic):
|
|
pass
|
|
|
|
class BaseClass(cls.Basic):
|
|
pass
|
|
|
|
class ClassWMixin(MixinOne, cls.Basic):
|
|
pass
|
|
|
|
class JoinedSubClass(BaseClass):
|
|
pass
|
|
|
|
class ConcreteSubClass(BaseClass):
|
|
pass
|
|
|
|
@classmethod
|
|
def setup_mappers(cls):
|
|
mapper(cls.classes.ClassWMixin, cls.tables.w_mixin_table)
|
|
mapper(cls.classes.BaseClass, cls.tables.base_table)
|
|
mapper(
|
|
cls.classes.JoinedSubClass,
|
|
cls.tables.joined_sub_table, inherits=cls.classes.BaseClass)
|
|
mapper(
|
|
cls.classes.ConcreteSubClass,
|
|
cls.tables.concrete_sub_table, inherits=cls.classes.BaseClass,
|
|
concrete=True)
|
|
|
|
def _fixture(self, binds):
|
|
return Session(binds=binds)
|
|
|
|
def test_fallback_table_metadata(self):
|
|
session = self._fixture({})
|
|
is_(
|
|
session.get_bind(self.classes.BaseClass),
|
|
testing.db
|
|
)
|
|
|
|
def test_bind_base_table_base_class(self):
|
|
base_class_bind = Mock()
|
|
session = self._fixture({
|
|
self.tables.base_table: base_class_bind
|
|
})
|
|
|
|
is_(
|
|
session.get_bind(self.classes.BaseClass),
|
|
base_class_bind
|
|
)
|
|
|
|
def test_bind_base_table_joined_sub_class(self):
|
|
base_class_bind = Mock()
|
|
session = self._fixture({
|
|
self.tables.base_table: base_class_bind
|
|
})
|
|
|
|
is_(
|
|
session.get_bind(self.classes.BaseClass),
|
|
base_class_bind
|
|
)
|
|
is_(
|
|
session.get_bind(self.classes.JoinedSubClass),
|
|
base_class_bind
|
|
)
|
|
|
|
def test_bind_joined_sub_table_joined_sub_class(self):
|
|
base_class_bind = Mock(name='base')
|
|
joined_class_bind = Mock(name='joined')
|
|
session = self._fixture({
|
|
self.tables.base_table: base_class_bind,
|
|
self.tables.joined_sub_table: joined_class_bind
|
|
})
|
|
|
|
is_(
|
|
session.get_bind(self.classes.BaseClass),
|
|
base_class_bind
|
|
)
|
|
# joined table inheritance has to query based on the base
|
|
# table, so this is what we expect
|
|
is_(
|
|
session.get_bind(self.classes.JoinedSubClass),
|
|
base_class_bind
|
|
)
|
|
|
|
def test_bind_base_table_concrete_sub_class(self):
|
|
base_class_bind = Mock()
|
|
session = self._fixture({
|
|
self.tables.base_table: base_class_bind
|
|
})
|
|
|
|
is_(
|
|
session.get_bind(self.classes.ConcreteSubClass),
|
|
testing.db
|
|
)
|
|
|
|
def test_bind_sub_table_concrete_sub_class(self):
|
|
base_class_bind = Mock(name='base')
|
|
concrete_sub_bind = Mock(name='concrete')
|
|
|
|
session = self._fixture({
|
|
self.tables.base_table: base_class_bind,
|
|
self.tables.concrete_sub_table: concrete_sub_bind
|
|
})
|
|
|
|
is_(
|
|
session.get_bind(self.classes.BaseClass),
|
|
base_class_bind
|
|
)
|
|
is_(
|
|
session.get_bind(self.classes.ConcreteSubClass),
|
|
concrete_sub_bind
|
|
)
|
|
|
|
def test_bind_base_class_base_class(self):
|
|
base_class_bind = Mock()
|
|
session = self._fixture({
|
|
self.classes.BaseClass: base_class_bind
|
|
})
|
|
|
|
is_(
|
|
session.get_bind(self.classes.BaseClass),
|
|
base_class_bind
|
|
)
|
|
|
|
def test_bind_mixin_class_simple_class(self):
|
|
base_class_bind = Mock()
|
|
session = self._fixture({
|
|
self.classes.MixinOne: base_class_bind
|
|
})
|
|
|
|
is_(
|
|
session.get_bind(self.classes.ClassWMixin),
|
|
base_class_bind
|
|
)
|
|
|
|
def test_bind_base_class_joined_sub_class(self):
|
|
base_class_bind = Mock()
|
|
session = self._fixture({
|
|
self.classes.BaseClass: base_class_bind
|
|
})
|
|
|
|
is_(
|
|
session.get_bind(self.classes.JoinedSubClass),
|
|
base_class_bind
|
|
)
|
|
|
|
def test_bind_joined_sub_class_joined_sub_class(self):
|
|
base_class_bind = Mock(name='base')
|
|
joined_class_bind = Mock(name='joined')
|
|
session = self._fixture({
|
|
self.classes.BaseClass: base_class_bind,
|
|
self.classes.JoinedSubClass: joined_class_bind
|
|
})
|
|
|
|
is_(
|
|
session.get_bind(self.classes.BaseClass),
|
|
base_class_bind
|
|
)
|
|
is_(
|
|
session.get_bind(self.classes.JoinedSubClass),
|
|
joined_class_bind
|
|
)
|
|
|
|
def test_bind_base_class_concrete_sub_class(self):
|
|
base_class_bind = Mock()
|
|
session = self._fixture({
|
|
self.classes.BaseClass: base_class_bind
|
|
})
|
|
|
|
is_(
|
|
session.get_bind(self.classes.ConcreteSubClass),
|
|
base_class_bind
|
|
)
|
|
|
|
def test_bind_sub_class_concrete_sub_class(self):
|
|
base_class_bind = Mock(name='base')
|
|
concrete_sub_bind = Mock(name='concrete')
|
|
|
|
session = self._fixture({
|
|
self.classes.BaseClass: base_class_bind,
|
|
self.classes.ConcreteSubClass: concrete_sub_bind
|
|
})
|
|
|
|
is_(
|
|
session.get_bind(self.classes.BaseClass),
|
|
base_class_bind
|
|
)
|
|
is_(
|
|
session.get_bind(self.classes.ConcreteSubClass),
|
|
concrete_sub_bind
|
|
)
|