from sqlalchemy import ForeignKey
from sqlalchemy import func
from sqlalchemy import Integer
from sqlalchemy import select
from sqlalchemy import String
from sqlalchemy.orm import relationship
from sqlalchemy.testing import eq_
from sqlalchemy.testing import fixtures
from sqlalchemy.testing.fixtures import fixture_session
from sqlalchemy.testing.schema import Column
from sqlalchemy.testing.schema import Table
class AssociationTest(fixtures.MappedTest):
run_setup_classes = "once"
run_setup_mappers = "once"
@classmethod
def define_tables(cls, metadata):
Table(
"items",
metadata,
Column(
"item_id",
Integer,
primary_key=True,
test_needs_autoincrement=True,
),
Column("name", String(40)),
)
Table(
"item_keywords",
metadata,
Column("item_id", Integer, ForeignKey("items.item_id")),
Column("keyword_id", Integer, ForeignKey("keywords.keyword_id")),
Column("data", String(40)),
)
Table(
"keywords",
metadata,
Column(
"keyword_id",
Integer,
primary_key=True,
test_needs_autoincrement=True,
),
Column("name", String(40)),
)
@classmethod
def setup_classes(cls):
class Item(cls.Basic):
def __init__(self, name):
self.name = name
def __repr__(self):
return "Item id=%d name=%s keywordassoc=%r" % (
self.item_id,
self.name,
self.keywords,
)
class Keyword(cls.Basic):
def __init__(self, name):
self.name = name
def __repr__(self):
return "Keyword id=%d name=%s" % (self.keyword_id, self.name)
class KeywordAssociation(cls.Basic):
def __init__(self, keyword, data):
self.keyword = keyword
self.data = data
def __repr__(self):
return "KeywordAssociation itemid=%d keyword=%r data=%s" % (
self.item_id,
self.keyword,
self.data,
)
@classmethod
def setup_mappers(cls):
KeywordAssociation, Item, Keyword = (
cls.classes.KeywordAssociation,
cls.classes.Item,
cls.classes.Keyword,
)
items, item_keywords, keywords = cls.tables.get_all(
"items", "item_keywords", "keywords"
)
cls.mapper_registry.map_imperatively(Keyword, keywords)
cls.mapper_registry.map_imperatively(
KeywordAssociation,
item_keywords,
properties={"keyword": relationship(Keyword, lazy="joined")},
primary_key=[item_keywords.c.item_id, item_keywords.c.keyword_id],
)
cls.mapper_registry.map_imperatively(
Item,
items,
properties={
"keywords": relationship(
KeywordAssociation,
order_by=item_keywords.c.data,
cascade="all, delete-orphan",
)
},
)
def test_insert(self):
KeywordAssociation, Item, Keyword = (
self.classes.KeywordAssociation,
self.classes.Item,
self.classes.Keyword,
)
sess = fixture_session()
item1 = Item("item1")
item2 = Item("item2")
item1.keywords.append(
KeywordAssociation(Keyword("blue"), "blue_assoc")
)
item1.keywords.append(KeywordAssociation(Keyword("red"), "red_assoc"))
item2.keywords.append(
KeywordAssociation(Keyword("green"), "green_assoc")
)
sess.add_all((item1, item2))
sess.flush()
saved = repr([item1, item2])
sess.expunge_all()
result = sess.query(Item).all()
loaded = repr(result)
eq_(saved, loaded)
def test_replace(self):
KeywordAssociation, Item, Keyword = (
self.classes.KeywordAssociation,
self.classes.Item,
self.classes.Keyword,
)
sess = fixture_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_modify(self):
KeywordAssociation, Item, Keyword = (
self.classes.KeywordAssociation,
self.classes.Item,
self.classes.Keyword,
)
sess = fixture_session()
item1 = Item("item1")
item2 = Item("item2")
item1.keywords.append(
KeywordAssociation(Keyword("blue"), "blue_assoc")
)
item1.keywords.append(KeywordAssociation(Keyword("red"), "red_assoc"))
item2.keywords.append(
KeywordAssociation(Keyword("green"), "green_assoc")
)
sess.add_all((item1, item2))
sess.flush()
red_keyword = item1.keywords[1].keyword
del item1.keywords[0]
del item1.keywords[0]
purple_keyword = Keyword("purple")
item1.keywords.append(KeywordAssociation(red_keyword, "new_red_assoc"))
item2.keywords.append(
KeywordAssociation(purple_keyword, "purple_item2_assoc")
)
item1.keywords.append(
KeywordAssociation(purple_keyword, "purple_item1_assoc")
)
item1.keywords.append(
KeywordAssociation(Keyword("yellow"), "yellow_assoc")
)
sess.flush()
saved = repr([item1, item2])
sess.expunge_all()
result = sess.query(Item).all()
loaded = repr(result)
eq_(saved, loaded)
def test_delete(self):
KeywordAssociation = self.classes.KeywordAssociation
Item = self.classes.Item
item_keywords = self.tables.item_keywords
Keyword = self.classes.Keyword
sess = fixture_session()
item1 = Item("item1")
item2 = Item("item2")
item1.keywords.append(
KeywordAssociation(Keyword("blue"), "blue_assoc")
)
item1.keywords.append(KeywordAssociation(Keyword("red"), "red_assoc"))
item2.keywords.append(
KeywordAssociation(Keyword("green"), "green_assoc")
)
sess.add_all((item1, item2))
sess.flush()
eq_(
sess.connection().scalar(
select(func.count("*")).select_from(item_keywords)
),
3,
)
sess.delete(item1)
sess.delete(item2)
sess.flush()
eq_(
sess.connection().scalar(
select(func.count("*")).select_from(item_keywords)
),
0,
)