Files
sqlalchemy/test/orm/test_selectable.py
T
Mike Bayer 8c0e82238c - Fixed bug regarding calculation of "from" list
for a select() element.  The "from" calc is now
delayed, so that if the construct uses a Column
object that is not yet attached to a Table,
but is later associated with a Table, it generates
SQL using the table as a FROM.   This change
impacted fairly deeply the mechanics of how
the FROM list as well as the "correlates" collection
is calculated, as some "clause adaption" schemes
(these are used very heavily in the ORM)
were relying upon the fact that the "froms"
collection would typically be cached before the
adaption completed.   The rework allows it
such that the "froms" collection can be cleared
and re-generated at any time.  [ticket:2261]
- RelationshipProperty.Comparator._criterion_exists()
adds an "_orm_adapt" annotation to the correlates target,
to work with the change in [ticket:2261].   It's not clear
if the change to correlation+adaption mechanics will affect end user
code yet.
- FromClause now uses group_expirable_memoized_property for
late-generated values like primary key, _columns, etc.
The Select class adds some tokens to this object and has the
nice effect that FromClause doesn't need to know about
Select's names anymore.   An additional change might be to
have Select use a different group_expirable_memoized_property
so that it's collection of attribute names are specific to
Select though this isn't really necessary right now.
2011-09-05 19:12:12 -04:00

77 lines
2.4 KiB
Python

"""Generic mapping to Select statements"""
from test.lib.testing import assert_raises, assert_raises_message
import sqlalchemy as sa
from test.lib import testing
from sqlalchemy import String, Integer, select
from test.lib.schema import Table, Column
from sqlalchemy.orm import mapper, Session
from test.lib.testing import eq_, AssertsCompiledSQL
from test.lib import fixtures
# TODO: more tests mapping to selects
class SelectableNoFromsTest(fixtures.MappedTest, AssertsCompiledSQL):
@classmethod
def define_tables(cls, metadata):
Table('common', metadata,
Column('id', Integer, primary_key=True, test_needs_autoincrement=True),
Column('data', Integer),
Column('extra', String(45)))
@classmethod
def setup_classes(cls):
class Subset(cls.Comparable):
pass
def test_no_tables(self):
Subset = self.classes.Subset
selectable = select(["x", "y", "z"]).alias()
mapper(Subset, selectable, primary_key=[selectable.c.x])
self.assert_compile(
Session().query(Subset),
"SELECT anon_1.x, anon_1.y, anon_1.z FROM (SELECT x, y, z) AS anon_1",
use_default_dialect=True
)
def test_no_table_needs_pl(self):
Subset = self.classes.Subset
selectable = select(["x", "y", "z"]).alias()
assert_raises_message(
sa.exc.ArgumentError,
"could not assemble any primary key columns",
mapper, Subset, selectable
)
def test_no_selects(self):
Subset, common = self.classes.Subset, self.tables.common
subset_select = select([common.c.id, common.c.data])
assert_raises(sa.exc.InvalidRequestError, mapper, Subset, subset_select)
def test_basic(self):
Subset, common = self.classes.Subset, self.tables.common
subset_select = select([common.c.id, common.c.data]).alias()
subset_mapper = mapper(Subset, subset_select)
sess = Session(bind=testing.db)
sess.add(Subset(data=1))
sess.flush()
sess.expunge_all()
eq_(sess.query(Subset).all(), [Subset(data=1)])
eq_(sess.query(Subset).filter(Subset.data==1).one(), Subset(data=1))
eq_(sess.query(Subset).filter(Subset.data!=1).first(), None)
subset_select = sa.orm.class_mapper(Subset).mapped_table
eq_(sess.query(Subset).filter(subset_select.c.data==1).one(),
Subset(data=1))