def test_attribute_mapped_collection(self): users, addresses = self.tables.users, self.tables.addresses mapper( User, users, properties={ "addresses": relationship( Address, collection_class=attribute_mapped_collection( "email_address" ), ) }, ) mapper(Address, addresses) u1 = User() u1.addresses = {"email1": Address(email_address="email1")} for loads, dumps in picklers(): repickled = loads(dumps(u1)) eq_(u1.addresses, repickled.addresses) eq_(repickled.addresses["email1"], Address(email_address="email1"))
def test_pickle_protocols(self): users, addresses = (self.tables.users, self.tables.addresses) mapper( User, users, properties={"addresses": relationship(Address, backref="user")}, ) mapper(Address, addresses) sess = sessionmaker()() u1 = User(name="ed") u1.addresses.append(Address(email_address="*****@*****.**")) sess.add(u1) sess.commit() u1 = sess.query(User).first() u1.addresses for loads, dumps in picklers(): u2 = loads(dumps(u1)) eq_(u1, u2)
def setup_mappers(cls): A, B, C, D = cls.classes.A, cls.classes.B, cls.classes.C, cls.classes.D a, b, c, d = cls.tables.a, cls.tables.b, cls.tables.c, cls.tables.d mapper( A, a, properties={ "bs": relationship(B, backref="a"), "c": relationship(C, backref="as"), "ds": relationship(D, backref="a"), }, ) mapper(B, b) mapper(C, c) mapper(D, d)
def test_nested_joins(self): task, Task_Type, Joined, task_type, msg = ( self.tables.task, self.classes.Task_Type, self.classes.Joined, self.tables.task_type, self.tables.msg, ) # this is testing some subtle column resolution stuff, # concerning corresponding_column() being extremely accurate # as well as how mapper sets up its column properties mapper(Task_Type, task_type) j = sa.outerjoin(task, msg, task.c.id == msg.c.task_id) jj = sa.select( [ task.c.id.label("task_id"), sa.func.count(msg.c.id).label("props_cnt"), ], from_obj=[j], group_by=[task.c.id], ).alias("prop_c_s") jjj = sa.join(task, jj, task.c.id == jj.c.task_id) mapper( Joined, jjj, properties=dict(type=relationship(Task_Type, lazy="joined")), ) session = create_session() eq_( session.query(Joined).limit(10).offset(0).one(), Joined(id=1, title="task 1", props_cnt=0), )
def test_uses_get(self): """test that a simple many-to-one lazyload optimizes to use query.get().""" Address, addresses, users, User = ( self.classes.Address, self.tables.addresses, self.tables.users, self.classes.User, ) for pj in ( None, users.c.id == addresses.c.user_id, addresses.c.user_id == users.c.id, ): mapper( Address, addresses, properties=dict(user=relationship( mapper(User, users), lazy="select", primaryjoin=pj)), ) sess = create_session() # load address a1 = (sess.query(Address).filter_by( email_address="*****@*****.**").one()) # load user that is attached to the address u1 = sess.query(User).get(8) def go(): # lazy load of a1.user should get it from the session assert a1.user is u1 self.assert_sql_count(testing.db, go, 0) sa.orm.clear_mappers()
def test_useget_cancels_eager(self): """test that a one to many lazyload cancels the unnecessary eager many-to-one join on the other side.""" User = self.classes.User Address = self.classes.Address mapper(User, self.tables.users) mapper( Address, self.tables.addresses, properties={ "user": relationship( User, lazy="joined", backref=backref("addresses", lazy="baked_select"), ) }, ) sess = Session() u1 = sess.query(User).filter(User.id == 8).one() def go(): eq_(u1.addresses[0].user, u1) self.assert_sql_execution( testing.db, go, CompiledSQL( "SELECT addresses.id AS addresses_id, addresses.user_id AS " "addresses_user_id, addresses.email_address AS " "addresses_email_address FROM addresses WHERE :param_1 = " "addresses.user_id", {"param_1": 8}, ), )
def test_instance_lazy_relation_loaders(self): users, addresses = (self.tables.users, self.tables.addresses) mapper( User, users, properties={"addresses": relationship(Address, lazy="noload")}, ) mapper(Address, addresses) sess = Session() u1 = User(name="ed", addresses=[Address(email_address="*****@*****.**")]) sess.add(u1) sess.commit() sess.close() u1 = sess.query(User).options(lazyload(User.addresses)).first() u2 = pickle.loads(pickle.dumps(u1)) sess = Session() sess.add(u2) assert u2.addresses
def test_check_prop_type(self): edge, Edge, Point = ( self.tables.edge, self.classes.Edge, self.classes.Point, ) mapper( Edge, edge, properties={ "start": sa.orm.composite(Point, (edge.c.x1, ), edge.c.y1) }, ) assert_raises_message( sa.exc.ArgumentError, # note that we also are checking that the tuple # renders here, so the "%" operator in the string needs to # apply the tuple also r"Composite expects Column objects or mapped " r"attributes/attribute names as " r"arguments, got: \(Column", configure_mappers, )
def setup_mappers(cls): keywords, items, item_keywords, Keyword, Item = ( cls.tables.keywords, cls.tables.items, cls.tables.item_keywords, cls.classes.Keyword, cls.classes.Item, ) mapper( Item, items, properties={ "keyword": relationship( Keyword, secondary=item_keywords, uselist=False, backref=backref("item", uselist=False), ) }, ) mapper(Keyword, keywords)
def test_needs_parent(self): """test the error raised when parent object is not bound.""" 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) u = q.filter(users.c.id == 7).first() sess.expunge(u) assert_raises(orm_exc.DetachedInstanceError, getattr, u, "addresses")
def test_many_to_one(self): users, Address, addresses, User = ( self.tables.users, self.classes.Address, self.tables.addresses, self.classes.User, ) mapper( Address, addresses, properties=dict( user=relationship(mapper(User, users), lazy="select")), ) sess = create_session() q = sess.query(Address) a = q.filter(addresses.c.id == 1).one() assert a.user is not None u1 = sess.query(User).get(7) assert a.user is u1
def test_alias_pathing(self): metadata = MetaData(self.engine) a = Table( "a", metadata, Column("id", Integer, primary_key=True, test_needs_autoincrement=True), Column("bid", Integer, ForeignKey("b.id")), Column("type", String(30)), ) asub = Table( "asub", metadata, Column("id", Integer, ForeignKey("a.id"), primary_key=True), Column("data", String(30)), ) b = Table( "b", metadata, Column("id", Integer, primary_key=True, test_needs_autoincrement=True), ) mapper(A, a, polymorphic_identity="a", polymorphic_on=a.c.type) mapper(ASub, asub, inherits=A, polymorphic_identity="asub") mapper(B, b, properties={"as_": relationship(A)}) metadata.create_all() sess = Session() a1 = ASub(data="a1") a2 = ASub(data="a2") a3 = ASub(data="a3") b1 = B(as_=[a1, a2, a3]) sess.add(b1) sess.commit() del sess # sqlite has a slow enough growth here # that we have to run it more times to see the # "dip" again @profile_memory(maxtimes=120) def go(): sess = Session() sess.query(B).options(subqueryload(B.as_.of_type(ASub))).all() sess.close() try: go() finally: metadata.drop_all() clear_mappers()
def test_two(self): product_mapper = mapper( Product, products_table, polymorphic_on=products_table.c.product_type, polymorphic_identity="product", ) mapper(Detail, inherits=product_mapper, polymorphic_identity="detail") mapper( SpecLine, specification_table, properties=dict(follower=relationship( Product, foreign_keys=[specification_table.c.follower_id], primaryjoin=specification_table.c.follower_id == products_table.c.product_id, lazy="select", uselist=False, )), ) session = create_session() s = SpecLine(follower=Product(name="p1")) s2 = SpecLine(follower=Detail(name="d1")) session.add(s) session.add(s2) orig = repr([s, s2]) session.flush() session.expunge_all() new = repr(session.query(SpecLine).all()) print(orig) print(new) assert (orig == new == "[<SpecLine 1.0 <Product p1>>, " "<SpecLine 1.0 <Detail d1>>]")
def setup_mappers(cls): graphs, edges = cls.tables.graphs, cls.tables.edges class Point(cls.Comparable): def __init__(self, x, y): self.x = x self.y = y def __composite_values__(self): return [self.x, self.y] __hash__ = None def __eq__(self, other): return (isinstance(other, Point) and other.x == self.x and other.y == self.y) def __ne__(self, other): return not isinstance(other, Point) or not self.__eq__(other) class Graph(cls.Comparable): pass class Edge(cls.Comparable): def __init__(self, *args): if args: self.start, self.end = args mapper(Graph, graphs, properties={"edges": relationship(Edge)}) mapper( Edge, edges, properties={ "start": sa.orm.composite(Point, edges.c.x1, edges.c.y1), "end": sa.orm.composite(Point, edges.c.x2, edges.c.y2), }, )
def setup_mappers(cls): global WeatherLocation, Report class WeatherLocation(object): def __init__(self, continent, city): self.continent = continent self.city = city class Report(object): def __init__(self, temperature, id_=None): self.temperature = temperature if id_: self.id = id_ mapper( WeatherLocation, weather_locations, properties={ "reports": relationship(Report, backref="location"), "city": deferred(weather_locations.c.city), }, ) mapper(Report, weather_reports)
def test_many_to_many(self): keywords, items, item_keywords, Keyword, Item = ( self.tables.keywords, self.tables.items, self.tables.item_keywords, self.classes.Keyword, self.classes.Item, ) mapper(Keyword, keywords) mapper( Item, items, properties=dict(keywords=relationship( Keyword, secondary=item_keywords, lazy="select")), ) q = create_session().query(Item) assert self.static.item_keyword_result == q.all() eq_( self.static.item_keyword_result[0:2], q.join("keywords").filter(keywords.c.name == "red").all(), )
def test_advanced(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) class Blub(Bar): def __repr__(self): return "Blub id %d, data %s, bars %s, foos %s" % ( self.id, self.data, repr([b for b in self.bars]), repr([f for f in self.foos]), ) mapper( Blub, blub, inherits=Bar, properties={ "bars": relationship(Bar, secondary=blub_bar, lazy="joined"), "foos": relationship(Foo, secondary=blub_foo, lazy="joined"), }, ) sess = create_session() f1 = Foo("foo #1") b1 = Bar("bar #1") b2 = Bar("bar #2") bl1 = Blub("blub #1") for o in (f1, b1, b2, bl1): sess.add(o) bl1.foos.append(f1) bl1.bars.append(b2) sess.flush() compare = repr(bl1) blubid = bl1.id sess.expunge_all() result = sess.query(Blub).all() print(result) self.assert_(repr(result[0]) == compare) sess.expunge_all() x = sess.query(Blub).filter_by(id=blubid).one() print(x) self.assert_(repr(x) == compare)
def test_many_to_one_binds(self): Address, addresses, users, User = ( self.classes.Address, self.tables.addresses, self.tables.users, self.classes.User, ) mapper( Address, addresses, primary_key=[addresses.c.user_id, addresses.c.email_address], ) mapper( User, users, properties=dict(address=relationship( Address, uselist=False, primaryjoin=sa.and_( users.c.id == addresses.c.user_id, addresses.c.email_address == "*****@*****.**", ), )), ) q = create_session().query(User) eq_( [ User(id=7, address=None), User(id=8, address=Address(id=3)), User(id=9, address=None), User(id=10, address=None), ], list(q), )
def test_all_orm_descriptors_pep520_classical(self): class MyClass(object): pass from sqlalchemy_1_3.orm import mapper from sqlalchemy_1_3 import Table, MetaData, Column, Integer names = self._random_names() m = MetaData() t = Table("t", m, Column("id", Integer, primary_key=True), *[Column(name, Integer) for name in names]) m = mapper(MyClass, t) eq_(m.all_orm_descriptors.keys(), ["id"] + names)
def test_load_m2o_attached_to_o2(self): """ Tests eager load of a many-to-one attached to a one-to-many. this testcase illustrated the bug, which is that when the single Company is loaded, no further processing of the rows occurred in order to load the Company's second Address object. """ addresses, invoices, Company, companies, Invoice, Address = ( self.tables.addresses, self.tables.invoices, self.classes.Company, self.tables.companies, self.classes.Invoice, self.classes.Address, ) mapper(Address, addresses) mapper( Company, companies, properties={"addresses": relationship(Address, lazy="joined")}, ) mapper( Invoice, invoices, properties={"company": relationship(Company, lazy="joined")}, ) a1 = Address(address="a1 address") a2 = Address(address="a2 address") c1 = Company(company_name="company 1", addresses=[a1, a2]) i1 = Invoice(date=datetime.datetime.now(), company=c1) session = create_session() session.add(i1) session.flush() company_id = c1.company_id invoice_id = i1.invoice_id session.expunge_all() c = session.query(Company).get(company_id) session.expunge_all() i = session.query(Invoice).get(invoice_id) def go(): eq_(c, i.company) eq_(c.addresses, i.company.addresses) self.assert_sql_count(testing.db, go, 0)
def test_inheriting(self): A, B, b_table, a_table, Dest, dest_table = ( self.classes.A, self.classes.B, self.tables.b_table, self.tables.a_table, self.classes.Dest, self.tables.dest_table, ) mapper( A, a_table, properties={ "some_dest": relationship(Dest, back_populates="many_a") }, ) mapper( B, b_table, inherits=A, concrete=True, properties={ "some_dest": relationship(Dest, back_populates="many_b") }, ) mapper( Dest, dest_table, properties={ "many_a": relationship(A, back_populates="some_dest"), "many_b": relationship(B, back_populates="some_dest"), }, ) sess = sessionmaker()() dest1 = Dest(name="c1") dest2 = Dest(name="c2") a1 = A(some_dest=dest1, aname="a1") a2 = A(some_dest=dest2, aname="a2") b1 = B(some_dest=dest1, bname="b1") b2 = B(some_dest=dest1, bname="b2") assert_raises(AttributeError, setattr, b1, "aname", "foo") assert_raises(AttributeError, getattr, A, "bname") assert dest2.many_a == [a2] assert dest1.many_a == [a1] assert dest1.many_b == [b1, b2] sess.add_all([dest1, dest2]) sess.commit() assert sess.query(Dest).filter(Dest.many_a.contains(a2)).one() is dest2 assert dest2.many_a == [a2] assert dest1.many_a == [a1] assert dest1.many_b == [b1, b2] assert sess.query(B).filter(B.bname == "b1").one() is b1
def setup_mappers(cls): Category, owners, Option, tests, Thing, Owner, options, categories = ( cls.classes.Category, cls.tables.owners, cls.classes.Option, cls.tables.tests, cls.classes.Thing, cls.classes.Owner, cls.tables.options, cls.tables.categories, ) mapper(Owner, owners) mapper(Category, categories) mapper( Option, options, properties=dict( owner=relationship(Owner, viewonly=True), test=relationship(Thing, viewonly=True), ), ) mapper( Thing, tests, properties=dict( owner=relationship(Owner, backref="tests"), category=relationship(Category), owner_option=relationship( Option, primaryjoin=sa.and_( tests.c.id == options.c.test_id, tests.c.owner_id == options.c.owner_id, ), foreign_keys=[options.c.test_id, options.c.owner_id], uselist=False, ), ), )
def test_selective_relationships(self): sub, base_mtom, Related, Base, related, sub_mtom, base, Sub = ( self.tables.sub, self.tables.base_mtom, self.classes.Related, self.classes.Base, self.tables.related, self.tables.sub_mtom, self.tables.base, self.classes.Sub, ) mapper( Base, base, properties={ "related": relationship( Related, secondary=base_mtom, backref="bases", order_by=related.c.id, ) }, ) mapper( Sub, sub, inherits=Base, concrete=True, properties={ "related": relationship( Related, secondary=sub_mtom, backref="subs", order_by=related.c.id, ) }, ) mapper(Related, related) sess = sessionmaker()() b1, s1, r1, r2, r3 = Base(), Sub(), Related(), Related(), Related() b1.related.append(r1) b1.related.append(r2) s1.related.append(r2) s1.related.append(r3) sess.add_all([b1, s1]) sess.commit() eq_(s1.related, [r2, r3]) eq_(b1.related, [r1, r2])
def test_secondary_doesnt_interfere_w_join_to_fromlist(self): # tests that the "secondary" being added to the FROM # as part of [ticket:4349] does not prevent a subsequent join to # an entity that does not provide any "left side". Query right now # does not know how to join() like this unambiguously if _from_obj is # more than one element long. Order, orders = self.classes.Order, self.tables.orders items, order_items, Item = ( self.tables.items, self.tables.order_items, self.classes.Item, ) item_keywords = self.tables.item_keywords class ItemKeyword(object): pass mapper( Order, orders, properties={ "items": relationship(Item, secondary=order_items, lazy="dynamic") }, ) mapper( ItemKeyword, item_keywords, primary_key=[item_keywords.c.item_id, item_keywords.c.keyword_id], ) mapper( Item, items, properties={"item_keywords": relationship(ItemKeyword)}, ) sess = create_session() order = sess.query(Order).first() self.assert_compile( order.items.join(ItemKeyword), "SELECT items.id AS items_id, " "items.description AS items_description " "FROM order_items, items " "JOIN item_keywords ON items.id = item_keywords.item_id " "WHERE :param_1 = order_items.order_id " "AND items.id = order_items.item_id", use_default_dialect=True, )
def test_load(self): foo, bar, baz = self.tables.foo, self.tables.bar, self.tables.baz # TODO: add persistence test also testing.db.execute(foo.insert(), a="not bar", b="baz") testing.db.execute(foo.insert(), a="also not bar", b="baz") testing.db.execute(foo.insert(), a="i am bar", b="bar") testing.db.execute(foo.insert(), a="also bar", b="bar") class Foo(fixtures.ComparableEntity): pass class Bar(Foo): pass class Baz(Foo): pass mapper(Foo, foo, polymorphic_on=foo.c.b) mapper( Baz, baz, with_polymorphic=( "*", foo.join(baz, foo.c.b == "baz").alias("baz"), ), inherits=Foo, inherit_condition=(foo.c.a == baz.c.a), inherit_foreign_keys=[baz.c.a], polymorphic_identity="baz", ) mapper( Bar, bar, with_polymorphic=( "*", foo.join(bar, foo.c.b == "bar").alias("bar"), ), inherits=Foo, inherit_condition=(foo.c.a == bar.c.a), inherit_foreign_keys=[bar.c.a], polymorphic_identity="bar", ) s = Session() assert [Baz(), Baz(), Bar(), Bar()] == s.query(Foo).order_by(Foo.b.desc()).all() assert [Bar(), Bar()] == s.query(Bar).all()
def test_misc_one(self): metadata = MetaData(testing.db) node_table = Table( "node", metadata, Column("node_id", Integer, primary_key=True), Column("name_index", Integer, nullable=True), ) node_name_table = Table( "node_name", metadata, Column("node_name_id", Integer, primary_key=True), Column("node_id", Integer, ForeignKey("node.node_id")), Column("host_id", Integer, ForeignKey("host.host_id")), Column("name", String(64), nullable=False), ) host_table = Table( "host", metadata, Column("host_id", Integer, primary_key=True), Column("hostname", String(64), nullable=False, unique=True), ) metadata.create_all() try: node_table.insert().execute(node_id=1, node_index=5) class Node(object): pass class NodeName(object): pass class Host(object): pass mapper(Node, node_table) mapper(Host, host_table) mapper( NodeName, node_name_table, properties={ "node": relationship(Node, backref=backref("names")), "host": relationship(Host), }, ) sess = create_session() assert sess.query(Node).get(1).names == [] finally: metadata.drop_all()
def setup_mappers(cls): User = cls.classes.User Address = cls.classes.Address Order = cls.classes.Order mapper( User, cls.tables.users, properties={ "addresses": relationship(Address, order_by=cls.tables.addresses.c.id), "orders": relationship(Order, order_by=cls.tables.orders.c.id), }, ) mapper(Address, cls.tables.addresses) mapper(Order, cls.tables.orders)
def test_basic(self): class Principal(object): def __init__(self, **kwargs): for key, value in kwargs.items(): setattr(self, key, value) class User(Principal): pass class Group(Principal): pass mapper(Principal, principals) mapper(User, users, inherits=Principal) mapper( Group, groups, inherits=Principal, properties={ "users": relationship( User, secondary=user_group_map, lazy="select", backref="groups", ) }, ) g = Group(name="group1") g.users.append( User( name="user1", password="******", email="*****@*****.**", login_id="lg1", )) sess = create_session() sess.add(g) sess.flush()
def test_overlapping_backref_relationship(self): A, B, b_table, a_table, Dest, dest_table = ( self.classes.A, self.classes.B, self.tables.b_table, self.tables.a_table, self.classes.Dest, self.tables.dest_table, ) # test issue #3630, no error or warning is generated mapper(A, a_table) mapper(B, b_table, inherits=A, concrete=True) mapper( Dest, dest_table, properties={ "a": relationship(A, backref="dest"), "a1": relationship(B, backref="dest"), }, ) configure_mappers()
def _o2m_twolevel_fixture(self, lazy="select", **kw): User = self.classes.User Address = self.classes.Address Dingaling = self.classes.Dingaling mapper( User, self.tables.users, properties={ "addresses": relationship(Address, order_by=self.tables.addresses.c.id, lazy=lazy, **kw) }, ) mapper( Address, self.tables.addresses, properties={"dingalings": relationship(Dingaling, lazy=lazy)}, ) mapper(Dingaling, self.tables.dingalings) return User, Address, Dingaling