def test_polymorphic_deferred(self): email_users, users = (self.tables.email_users, self.tables.users) mapper( User, users, polymorphic_identity="user", polymorphic_on=users.c.type, ) mapper( EmailUser, email_users, inherits=User, polymorphic_identity="emailuser", ) eu = EmailUser(name="user1", email_address="*****@*****.**") sess = create_session() sess.add(eu) sess.flush() sess.expunge_all() eu = sess.query(User).first() eu2 = pickle.loads(pickle.dumps(eu)) sess2 = create_session() sess2.add(eu2) assert "email_address" not in eu2.__dict__ eq_(eu2.email_address, "*****@*****.**")
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
def test_instance_deferred_cols(self): users, addresses = (self.tables.users, self.tables.addresses) mapper( User, users, properties={"addresses": relationship(Address, backref="user")}, ) mapper(Address, addresses) sess = create_session() u1 = User(name="ed") u1.addresses.append(Address(email_address="*****@*****.**")) sess.add(u1) sess.flush() sess.expunge_all() u1 = ( sess.query(User) .options( sa.orm.defer("name"), sa.orm.defer("addresses.email_address") ) .get(u1.id) ) assert "name" not in u1.__dict__ assert "addresses" not in u1.__dict__ u2 = pickle.loads(pickle.dumps(u1)) sess2 = create_session() sess2.add(u2) eq_(u2.name, "ed") assert "addresses" not in u2.__dict__ ad = u2.addresses[0] assert "email_address" not in ad.__dict__ eq_(ad.email_address, "*****@*****.**") eq_( u2, User(name="ed", addresses=[Address(email_address="*****@*****.**")]), ) u2 = pickle.loads(pickle.dumps(u1)) sess2 = create_session() u2 = sess2.merge(u2, load=False) eq_(u2.name, "ed") assert "addresses" not in u2.__dict__ ad = u2.addresses[0] # mapper options now transmit over merge(), # new as of 0.6, so email_address is deferred. assert "email_address" not in ad.__dict__ eq_(ad.email_address, "*****@*****.**") eq_( u2, User(name="ed", addresses=[Address(email_address="*****@*****.**")]), )
def test_basic(self): Address, addresses, users, User = ( self.classes.Address, self.tables.addresses, self.tables.users, self.classes.User, ) mapper(Address, addresses) mapper( User, users, properties={"addresses": relationship(Address, lazy="immediate")}, ) sess = create_session() result = sess.query(User).filter(users.c.id == 7).all() eq_(len(sess.identity_map), 2) sess.close() eq_( [ User( id=7, addresses=[Address(id=1, email_address="*****@*****.**")], ) ], result, )
def test_join_to_join_entities(self): sess = create_session() pa = with_polymorphic(Person, [Engineer]) pa_alias = with_polymorphic(Person, [Engineer], aliased=True) eq_( [ (p1.name, type(p1), p2.name, type(p2)) for (p1, p2) in sess.query(pa, pa_alias) .join( pa_alias, or_( pa.Engineer.primary_language == pa_alias.Engineer.primary_language, and_( pa.Engineer.primary_language == None, # noqa pa_alias.Engineer.primary_language == None, pa.person_id > pa_alias.person_id, ), ), ) .order_by(pa.name, pa_alias.name) ], [ ("dilbert", Engineer, "dilbert", Engineer), ("dogbert", Manager, "pointy haired boss", Boss), ("vlad", Engineer, "vlad", Engineer), ("wally", Engineer, "wally", Engineer), ], )
def test_basic(self): users, Address, addresses, User = ( self.tables.users, self.classes.Address, self.tables.addresses, self.classes.User, ) mapper( User, users, properties={ "addresses": relationship(mapper(Address, addresses), lazy="select") }, ) sess = create_session() q = sess.query(User) eq_( [ User( id=7, addresses=[Address(id=1, email_address="*****@*****.**")], ) ], q.filter(users.c.id == 7).all(), )
def test_orderby_desc(self): Address, addresses, users, User = ( self.classes.Address, self.tables.addresses, self.tables.users, self.classes.User, ) mapper(Address, addresses) mapper( User, users, properties=dict(addresses=relationship( Address, lazy="select", order_by=[sa.desc(addresses.c.email_address)], )), ) sess = create_session() assert [ User(id=7, addresses=[Address(id=1)]), User( id=8, addresses=[ Address(id=2, email_address="*****@*****.**"), Address(id=4, email_address="*****@*****.**"), Address(id=3, email_address="*****@*****.**"), ], ), User(id=9, addresses=[Address(id=5)]), User(id=10, addresses=[]), ] == sess.query(User).all()
def test_m2o_noload(self): """test that a NULL foreign key doesn't trigger a lazy load""" users, Address, addresses, User = ( self.tables.users, self.classes.Address, self.tables.addresses, self.classes.User, ) mapper(User, users) mapper(Address, addresses, properties={"user": relationship(User)}) sess = create_session() ad1 = Address(email_address="somenewaddress", id=12) sess.add(ad1) sess.flush() sess.expunge_all() ad2 = sess.query(Address).get(1) ad3 = sess.query(Address).get(ad1.id) def go(): # one lazy load assert ad2.user.name == "jack" # no lazy load assert ad3.user is None self.assert_sql_count(testing.db, go, 1)
def test_rekey(self): class User(Base, fixtures.ComparableEntity): __tablename__ = "users" __autoload__ = True nom = Column("name", String(50), key="nom") addresses = relationship("Address", backref="user") class Address(Base, fixtures.ComparableEntity): __tablename__ = "addresses" __autoload__ = True u1 = User( nom="u1", addresses=[Address(email="one"), Address(email="two")] ) sess = create_session() sess.add(u1) sess.flush() sess.expunge_all() eq_( sess.query(User).all(), [ User( nom="u1", addresses=[Address(email="one"), Address(email="two")], ) ], ) a1 = sess.query(Address).filter(Address.email == "two").one() eq_(a1, Address(email="two")) eq_(a1.user, User(nom="u1")) assert_raises(TypeError, User, name="u3")
def test_one(self): ( Part, inherited_part, design_types, DesignType, parts, design, Design, InheritedPart, ) = ( self.classes.Part, self.tables.inherited_part, self.tables.design_types, self.classes.DesignType, self.tables.parts, self.tables.design, self.classes.Design, self.classes.InheritedPart, ) p_m = mapper(Part, parts) mapper( InheritedPart, inherited_part, properties=dict(part=relationship(Part, lazy="joined")), ) d_m = mapper( Design, design, properties=dict(inheritedParts=relationship( InheritedPart, cascade="all, delete-orphan", backref="design", )), ) mapper(DesignType, design_types) d_m.add_property( "type", relationship(DesignType, lazy="joined", backref="designs")) p_m.add_property( "design", relationship( Design, lazy="joined", backref=backref("parts", cascade="all, delete-orphan"), ), ) d = Design() sess = create_session() sess.add(d) sess.flush() sess.expunge_all() x = sess.query(Design).get(1) x.inheritedParts
def test_basic(self): ( Comment, Derived, derived, comments, DerivedII, Base, base, derivedII, ) = ( self.classes.Comment, self.classes.Derived, self.tables.derived, self.tables.comments, self.classes.DerivedII, self.classes.Base, self.tables.base, self.tables.derivedII, ) mapper(Comment, comments) baseMapper = mapper( Base, base, properties=dict(comments=relationship( Comment, lazy="joined", cascade="all, delete-orphan")), ) mapper(Derived, derived, inherits=baseMapper) mapper(DerivedII, derivedII, inherits=baseMapper) sess = create_session() d = Derived("uid1", "x", "y") d.comments = [Comment("uid1", "comment")] d2 = DerivedII("uid2", "xx", "z") d2.comments = [Comment("uid2", "comment")] sess.add_all((d, d2)) sess.flush() sess.expunge_all() # this eager load sets up an AliasedClauses for the "comment" # relationship, then stores it in clauses_by_lead_mapper[mapper for # Derived] d = sess.query(Derived).get("uid1") sess.expunge_all() assert len([c for c in d.comments]) == 1 # this eager load sets up an AliasedClauses for the "comment" # relationship, and should store it in clauses_by_lead_mapper[mapper # for DerivedII]. the bug was that the previous AliasedClause create # prevented this population from occurring. d2 = sess.query(DerivedII).get("uid2") sess.expunge_all() # object is not in the session; therefore the lazy load cant trigger # here, eager load had to succeed assert len([c for c in d2.comments]) == 1
def test_basic(self): Department, Employee, employees, departments = ( self.classes.Department, self.classes.Employee, self.tables.employees, self.tables.departments, ) mapper(Employee, employees) mapper( Department, departments, properties=dict(employees=relationship( Employee, lazy="joined", backref="department")), ) d1 = Department(name="One") for e in "Jim", "Jack", "John", "Susan": d1.employees.append(Employee(name=e)) d2 = Department(name="Two") for e in "Joe", "Bob", "Mary", "Wally": d2.employees.append(Employee(name=e)) sess = create_session() sess.add_all((d1, d2)) sess.flush() q = (sess.query(Department).join("employees").filter( Employee.name.startswith("J")).distinct().order_by( sa.desc(Department.name))) eq_(q.count(), 2) assert q[0] is d2
def test_withjoinedload(self): """ Test that an joinedload locates the correct "from" clause with which to attach to, when presented with a query that already has a complicated from clause. """ Thing, tests, options = ( self.classes.Thing, self.tables.tests, self.tables.options, ) s = create_session() q = s.query(Thing).options(sa.orm.joinedload("category")) result = q.select_from( tests.outerjoin( options, sa.and_( tests.c.id == options.c.test_id, tests.c.owner_id == options.c.owner_id, ), )).filter( sa.and_( tests.c.owner_id == 1, sa.or_( options.c.someoption == None, options.c.someoption == False, # noqa ), )) result_str = ["%d %s" % (t.id, t.category.name) for t in result] eq_(result_str, ["1 Some Category", "3 Some Category"])
def test_withoutjoinedload(self): Thing, tests, options = ( self.classes.Thing, self.tables.tests, self.tables.options, ) s = create_session() result = ( s.query(Thing).select_from( tests.outerjoin( options, sa.and_( tests.c.id == options.c.test_id, tests.c.owner_id == options.c.owner_id, ), )).filter( sa.and_( tests.c.owner_id == 1, sa.or_( options.c.someoption == None, # noqa options.c.someoption == False, ), ))) result_str = ["%d %s" % (t.id, t.category.name) for t in result] eq_(result_str, ["1 Some Category", "3 Some Category"])
def go(): class A(fixtures.ComparableEntity): pass class B(A): pass mapper( A, table1, polymorphic_on=table1.c.col2, polymorphic_identity="a", ) mapper(B, table2, inherits=A, polymorphic_identity="b") sess = create_session() a1 = A() a2 = A() b1 = B(col3="b1") b2 = B(col3="b2") for x in [a1, a2, b1, b2]: sess.add(x) sess.flush() sess.expunge_all() alist = sess.query(A).order_by(A.col1).all() eq_([A(), A(), B(col3="b1"), B(col3="b2")], alist) for a in alist: sess.delete(a) sess.flush() # don't need to clear_mappers() del B del A
def test_no_deref(self): User, Address = self._user_address_fixture( addresses_args={"backref": "user"}) session = create_session() user = User() user.name = "joe" user.fullname = "Joe User" user.password = "******" address = Address() address.email_address = "*****@*****.**" address.user = user session.add(user) session.flush() session.expunge_all() def query1(): session = create_session(testing.db) user = session.query(User).first() return user.addresses.all() def query2(): session = create_session(testing.db) return session.query(User).first().addresses.all() def query3(): session = create_session(testing.db) return session.query(User).first().addresses.all() eq_(query1(), [Address(email_address="*****@*****.**")]) eq_(query2(), [Address(email_address="*****@*****.**")]) eq_(query3(), [Address(email_address="*****@*****.**")])
def test_basic(self): class User(Base, fixtures.ComparableEntity): __tablename__ = "users" __autoload__ = True addresses = relationship("Address", backref="user") class Address(Base, fixtures.ComparableEntity): __tablename__ = "addresses" __autoload__ = True u1 = User( name="u1", addresses=[Address(email="one"), Address(email="two")] ) sess = create_session() sess.add(u1) sess.flush() sess.expunge_all() eq_( sess.query(User).all(), [ User( name="u1", addresses=[Address(email="one"), Address(email="two")], ) ], ) a1 = sess.query(Address).filter(Address.email == "two").one() eq_(a1, Address(email="two")) eq_(a1.user, User(name="u1"))
def test_basic(self): class Foo(object): def __init__(self, data=None): self.data = data def __repr__(self): return "Foo id %d, data %s" % (self.id, self.data) mapper(Foo, foo) class Bar(Foo): def __repr__(self): return "Bar id %d, data %s" % (self.id, self.data) mapper( Bar, bar, inherits=Foo, properties={ "foos": relationship(Foo, secondary=bar_foo, lazy="select") }, ) sess = create_session() b = Bar("bar #1") sess.add(b) b.foos.append(Foo("foo #1")) b.foos.append(Foo("foo #2")) sess.flush() compare = [repr(b)] + sorted([repr(o) for o in b.foos]) sess.expunge_all() result = sess.query(Bar).all() print(repr(result[0]) + repr(result[0].foos)) found = [repr(result[0])] + sorted([repr(o) for o in result[0].foos]) eq_(found, compare)
def test_replace(self): KeywordAssociation, Item, Keyword = ( self.classes.KeywordAssociation, self.classes.Item, self.classes.Keyword, ) sess = create_session() item1 = Item("item1") item1.keywords.append( KeywordAssociation(Keyword("blue"), "blue_assoc") ) item1.keywords.append(KeywordAssociation(Keyword("red"), "red_assoc")) sess.add(item1) sess.flush() red_keyword = item1.keywords[1].keyword del item1.keywords[1] item1.keywords.append(KeywordAssociation(red_keyword, "new_red_assoc")) sess.flush() saved = repr([item1]) sess.expunge_all() result = sess.query(Item).all() loaded = repr(result) eq_(saved, loaded)
def test_configured_order_by(self): addresses = self.tables.addresses User, Address = self._user_address_fixture( addresses_args={"order_by": addresses.c.email_address.desc()}) sess = create_session() u = sess.query(User).get(8) eq_( list(u.addresses), [ Address(email_address="*****@*****.**"), Address(email_address="*****@*****.**"), Address(email_address="*****@*****.**"), ], ) # test cancellation of None, replacement with something else eq_( list(u.addresses.order_by(None).order_by(Address.email_address)), [ Address(email_address="*****@*****.**"), Address(email_address="*****@*****.**"), Address(email_address="*****@*****.**"), ], ) # test cancellation of None, replacement with nothing eq_( set(u.addresses.order_by(None)), set([ Address(email_address="*****@*****.**"), Address(email_address="*****@*****.**"), Address(email_address="*****@*****.**"), ]), )
def test_orderby_secondary(self): """tests that a regular mapper select on a single table can order by a relationship to a second table""" Address, addresses, users, User = ( self.classes.Address, self.tables.addresses, self.tables.users, self.classes.User, ) mapper(Address, addresses) mapper( User, users, properties=dict(addresses=relationship(Address, lazy="select")), ) q = create_session().query(User) result = (q.filter(users.c.id == addresses.c.user_id).order_by( addresses.c.email_address).all()) assert [ User( id=8, addresses=[ Address(id=2, email_address="*****@*****.**"), Address(id=3, email_address="*****@*****.**"), Address(id=4, email_address="*****@*****.**"), ], ), User(id=9, addresses=[Address(id=5)]), User(id=7, addresses=[Address(id=1)]), ] == result
def test_dynamic_on_backref(self): users, Address, addresses, User = ( self.tables.users, self.classes.Address, self.tables.addresses, self.classes.User, ) mapper( Address, addresses, properties={ "user": relationship(User, backref=backref("addresses", lazy="dynamic")) }, ) mapper(User, users) sess = create_session() ad = sess.query(Address).get(1) def go(): ad.user = None self.assert_sql_count(testing.db, go, 0) sess.flush() u = sess.query(User).get(7) assert ad not in u.addresses
def test_no_orphan(self): """test that a lazily loaded child object is not marked as an orphan""" users, Address, addresses, User = ( self.tables.users, self.classes.Address, self.tables.addresses, self.classes.User, ) mapper( User, users, properties={ "addresses": relationship(Address, cascade="all,delete-orphan", lazy="select") }, ) mapper(Address, addresses) sess = create_session() user = sess.query(User).get(7) assert getattr(User, "addresses").hasparent(attributes.instance_state( user.addresses[0]), optimistic=True) assert not sa.orm.class_mapper(Address)._is_orphan( attributes.instance_state(user.addresses[0]))
def test_secondary_as_join(self): # test [ticket:4349] User, users = self.classes.User, self.tables.users items, orders, order_items, Item = ( self.tables.items, self.tables.orders, self.tables.order_items, self.classes.Item, ) mapper( User, users, properties={ "items": relationship(Item, secondary=order_items.join(orders), lazy="dynamic") }, ) mapper(Item, items) sess = create_session() u1 = sess.query(User).first() self.assert_compile( u1.items, "SELECT items.id AS items_id, " "items.description AS items_description " "FROM items, order_items JOIN orders " "ON orders.id = order_items.order_id " "WHERE :param_1 = orders.user_id " "AND items.id = order_items.item_id", use_default_dialect=True, )
def test_orderby(self): users, Address, addresses, User = ( self.tables.users, self.classes.Address, self.tables.addresses, self.classes.User, ) mapper( User, users, properties={ "addresses": relationship( mapper(Address, addresses), lazy="select", order_by=addresses.c.email_address, ) }, ) q = create_session().query(User) assert [ User(id=7, addresses=[Address(id=1)]), User( id=8, addresses=[ Address(id=3, email_address="*****@*****.**"), Address(id=4, email_address="*****@*****.**"), Address(id=2, email_address="*****@*****.**"), ], ), User(id=9, addresses=[Address(id=5)]), User(id=10, addresses=[]), ] == q.all()
def test_custom_query_with_custom_mixin(self): class MyAppenderMixin(AppenderMixin): def add(self, items): if isinstance(items, list): for item in items: self.append(item) else: self.append(items) class MyQuery(Query): pass class MyAppenderQuery(MyAppenderMixin, MyQuery): query_class = MyQuery User, Address = self._user_address_fixture( addresses_args={"query_class": MyAppenderQuery}) sess = create_session() u = User() sess.add(u) col = u.addresses assert isinstance(col, Query) assert isinstance(col, MyQuery) assert hasattr(col, "append") assert hasattr(col, "add") eq_(type(col).__name__, "MyAppenderQuery") q = col.limit(1) assert isinstance(q, Query) assert isinstance(q, MyQuery) assert not hasattr(q, "append") assert not hasattr(q, "add") eq_(type(q).__name__, "MyQuery")
def test_join_to_join_columns(self): sess = create_session() pa = with_polymorphic(Person, [Engineer]) pa_alias = with_polymorphic(Person, [Engineer], aliased=True) eq_( [ row for row in sess.query( pa.name, pa.Engineer.primary_language, pa_alias.name, pa_alias.Engineer.primary_language, ) .join( pa_alias, or_( pa.Engineer.primary_language == pa_alias.Engineer.primary_language, and_( pa.Engineer.primary_language == None, # noqa pa_alias.Engineer.primary_language == None, pa.person_id > pa_alias.person_id, ), ), ) .order_by(pa.name, pa_alias.name) ], [ ("dilbert", "java", "dilbert", "java"), ("dogbert", None, "pointy haired boss", None), ("vlad", "cobol", "vlad", "cobol"), ("wally", "c++", "wally", "c++"), ], )
def test_merge(self): addresses = self.tables.addresses User, Address = self._user_address_fixture( addresses_args={"order_by": addresses.c.email_address}) sess = create_session() u1 = User(name="jack") a1 = Address(email_address="a1") a2 = Address(email_address="a2") a3 = Address(email_address="a3") u1.addresses.append(a2) u1.addresses.append(a3) sess.add_all([u1, a1]) sess.flush() u1 = User(id=u1.id, name="jack") u1.addresses.append(a1) u1.addresses.append(a3) u1 = sess.merge(u1) eq_(attributes.get_history(u1, "addresses"), ([a1], [a3], [a2])) sess.flush() eq_(list(u1.addresses), [a1, a3])
def test_replace(self): self._setup(ordering_list("position")) s1 = Slide("Slide #1") s1.bullets = [Bullet("1"), Bullet("2"), Bullet("3")] self.assert_(len(s1.bullets) == 3) self.assert_(s1.bullets[2].position == 2) session = create_session() session.add(s1) session.flush() new_bullet = Bullet("new 2") self.assert_(new_bullet.position is None) # mark existing bullet as db-deleted before replacement. # session.delete(s1.bullets[1]) s1.bullets[1] = new_bullet self.assert_(new_bullet.position == 1) self.assert_(len(s1.bullets) == 3) id_ = s1.id session.flush() session.expunge_all() srt = session.query(Slide).get(id_) self.assert_(srt.bullets) self.assert_(len(srt.bullets) == 3) self.assert_(srt.bullets[1].text == "new 2") self.assert_(srt.bullets[2].text == "3")
def _backref_test(self, autoflush, saveuser): User, Address = self._user_address_fixture( addresses_args={"backref": "user"}) sess = create_session(autoflush=autoflush, autocommit=False) u = User(name="buffy") a = Address(email_address="*****@*****.**") a.user = u if saveuser: sess.add(u) else: sess.add(a) if not autoflush: sess.flush() assert u in sess assert a in sess eq_(list(u.addresses), [a]) a.user = None if not autoflush: eq_(list(u.addresses), [a]) if not autoflush: sess.flush() eq_(list(u.addresses), [])