summaryrefslogtreecommitdiff
path: root/test/orm/test_query.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/orm/test_query.py')
-rw-r--r--test/orm/test_query.py632
1 files changed, 43 insertions, 589 deletions
diff --git a/test/orm/test_query.py b/test/orm/test_query.py
index 0973dc357..fea2337ca 100644
--- a/test/orm/test_query.py
+++ b/test/orm/test_query.py
@@ -19,7 +19,7 @@ from sqlalchemy.testing.assertions import eq_, assert_raises, assert_raises_mess
from sqlalchemy.testing import AssertsCompiledSQL
from test.orm import _fixtures
from sqlalchemy.testing import fixtures, engines
-
+from sqlalchemy.orm import Bundle
from sqlalchemy.orm.util import join, outerjoin, with_parent
class QueryTest(_fixtures.FixtureTest):
@@ -74,6 +74,7 @@ class RowTupleTest(QueryTest):
address_alias = aliased(Address, name='aalias')
fn = func.count(User.id)
name_label = User.name.label('uname')
+ bundle = Bundle('b1', User.id, User.name)
for q, asserted in [
(
sess.query(User),
@@ -112,6 +113,15 @@ class RowTupleTest(QueryTest):
'expr':fn
},
]
+ ),
+ (
+ sess.query(bundle),
+ [
+ {'aliased': False,
+ 'expr': bundle,
+ 'type': Bundle,
+ 'name': 'b1'}
+ ]
)
]:
eq_(
@@ -119,6 +129,7 @@ class RowTupleTest(QueryTest):
asserted
)
+
def test_unhashable_type(self):
from sqlalchemy.types import TypeDecorator, Integer
from sqlalchemy.sql import type_coerce
@@ -216,10 +227,13 @@ class RawSelectTest(QueryTest, AssertsCompiledSQL):
where(uu.id == Address.user_id).\
correlate(uu).as_scalar()
]),
- # curious, "address.user_id = uu.id" is reversed here
+ # for a long time, "uu.id = address.user_id" was reversed;
+ # this was resolved as of #2872 and had to do with
+ # InstrumentedAttribute.__eq__() taking precedence over
+ # QueryableAttribute.__eq__()
"SELECT uu.name, addresses.id, "
"(SELECT count(addresses.id) AS count_1 "
- "FROM addresses WHERE addresses.user_id = uu.id) AS anon_1 "
+ "FROM addresses WHERE uu.id = addresses.user_id) AS anon_1 "
"FROM users AS uu, addresses"
)
@@ -688,6 +702,7 @@ class InvalidGenerationsTest(QueryTest, AssertsCompiledSQL):
meth, q, *arg, **kw
)
+
class OperatorTest(QueryTest, AssertsCompiledSQL):
"""test sql.Comparator implementation for MapperProperties"""
@@ -1325,7 +1340,6 @@ class FilterTest(QueryTest, AssertsCompiledSQL):
assert [User(id=10)] == sess.query(User).outerjoin("addresses", aliased=True).filter(~User.addresses.any()).all()
- @testing.crashes('maxdb', 'can dump core')
def test_has(self):
Dingaling, User, Address = (self.classes.Dingaling,
self.classes.User,
@@ -1726,16 +1740,37 @@ class AggregateTest(QueryTest):
class ExistsTest(QueryTest, AssertsCompiledSQL):
+ __dialect__ = 'default'
def test_exists(self):
User = self.classes.User
sess = create_session()
- q1 = sess.query(User).filter(User.name == 'fred')
+
+ q1 = sess.query(User)
self.assert_compile(sess.query(q1.exists()),
'SELECT EXISTS ('
+ 'SELECT 1 FROM users'
+ ') AS anon_1'
+ )
+
+ q2 = sess.query(User).filter(User.name == 'fred')
+ self.assert_compile(sess.query(q2.exists()),
+ 'SELECT EXISTS ('
'SELECT 1 FROM users WHERE users.name = :name_1'
- ') AS anon_1',
- dialect=default.DefaultDialect()
+ ') AS anon_1'
+ )
+
+ def test_exists_col_warning(self):
+ User = self.classes.User
+ Address = self.classes.Address
+ sess = create_session()
+
+ q1 = sess.query(User, Address).filter(User.id == Address.user_id)
+ self.assert_compile(sess.query(q1.exists()),
+ 'SELECT EXISTS ('
+ 'SELECT 1 FROM users, addresses '
+ 'WHERE users.id = addresses.user_id'
+ ') AS anon_1'
)
@@ -1955,7 +1990,7 @@ class HintsTest(QueryTest, AssertsCompiledSQL):
"SELECT users.id AS users_id, users.name AS users_name, "
"users_1.id AS users_1_id, users_1.name AS users_1_name "
"FROM users INNER JOIN users AS users_1 USE INDEX (col1_index,col2_index) "
- "ON users.id < users_1.id",
+ "ON users_1.id > users.id",
dialect=dialect
)
@@ -2443,584 +2478,3 @@ class ExecutionOptionsTest(QueryTest):
q1.all()
-class OptionsTest(QueryTest):
- """Test the _process_paths() method of PropertyOption."""
-
- def _option_fixture(self, *arg):
- from sqlalchemy.orm import interfaces
- class Opt(interfaces.PropertyOption):
- pass
- return Opt(arg)
-
- def _make_path(self, path):
- r = []
- for i, item in enumerate(path):
- if i % 2 == 0:
- if isinstance(item, type):
- item = class_mapper(item)
- else:
- if isinstance(item, str):
- item = inspect(r[-1]).mapper.attrs[item]
- r.append(item)
- return tuple(r)
-
- def _make_path_registry(self, path):
- return orm_util.PathRegistry.coerce(self._make_path(path))
-
- def _assert_path_result(self, opt, q, paths):
- q._attributes = q._attributes.copy()
- assert_paths = opt._process_paths(q, False)
- eq_(
- [p.path for p in assert_paths],
- [self._make_path(p) for p in paths]
- )
-
- def test_get_path_one_level_string(self):
- User = self.classes.User
-
- sess = Session()
- q = sess.query(User)
-
- opt = self._option_fixture("addresses")
- self._assert_path_result(opt, q, [(User, 'addresses')])
-
- def test_get_path_one_level_attribute(self):
- User = self.classes.User
-
- sess = Session()
- q = sess.query(User)
-
- opt = self._option_fixture(User.addresses)
- self._assert_path_result(opt, q, [(User, 'addresses')])
-
- def test_path_on_entity_but_doesnt_match_currentpath(self):
- User, Address = self.classes.User, self.classes.Address
-
- # ensure "current path" is fully consumed before
- # matching against current entities.
- # see [ticket:2098]
- sess = Session()
- q = sess.query(User)
- opt = self._option_fixture('email_address', 'id')
- q = sess.query(Address)._with_current_path(
- orm_util.PathRegistry.coerce([inspect(User),
- inspect(User).attrs.addresses])
- )
- self._assert_path_result(opt, q, [])
-
- def test_get_path_one_level_with_unrelated(self):
- Order = self.classes.Order
-
- sess = Session()
- q = sess.query(Order)
- opt = self._option_fixture("addresses")
- self._assert_path_result(opt, q, [])
-
- def test_path_multilevel_string(self):
- Item, User, Order = (self.classes.Item,
- self.classes.User,
- self.classes.Order)
-
- sess = Session()
- q = sess.query(User)
-
- opt = self._option_fixture("orders.items.keywords")
- self._assert_path_result(opt, q, [
- (User, 'orders'),
- (User, 'orders', Order, 'items'),
- (User, 'orders', Order, 'items', Item, 'keywords')
- ])
-
- def test_path_multilevel_attribute(self):
- Item, User, Order = (self.classes.Item,
- self.classes.User,
- self.classes.Order)
-
- sess = Session()
- q = sess.query(User)
-
- opt = self._option_fixture(User.orders, Order.items, Item.keywords)
- self._assert_path_result(opt, q, [
- (User, 'orders'),
- (User, 'orders', Order, 'items'),
- (User, 'orders', Order, 'items', Item, 'keywords')
- ])
-
- def test_with_current_matching_string(self):
- Item, User, Order = (self.classes.Item,
- self.classes.User,
- self.classes.Order)
-
- sess = Session()
- q = sess.query(Item)._with_current_path(
- self._make_path_registry([User, 'orders', Order, 'items'])
- )
-
- opt = self._option_fixture("orders.items.keywords")
- self._assert_path_result(opt, q, [
- (Item, 'keywords')
- ])
-
- def test_with_current_matching_attribute(self):
- Item, User, Order = (self.classes.Item,
- self.classes.User,
- self.classes.Order)
-
- sess = Session()
- q = sess.query(Item)._with_current_path(
- self._make_path_registry([User, 'orders', Order, 'items'])
- )
-
- opt = self._option_fixture(User.orders, Order.items, Item.keywords)
- self._assert_path_result(opt, q, [
- (Item, 'keywords')
- ])
-
- def test_with_current_nonmatching_string(self):
- Item, User, Order = (self.classes.Item,
- self.classes.User,
- self.classes.Order)
-
- sess = Session()
- q = sess.query(Item)._with_current_path(
- self._make_path_registry([User, 'orders', Order, 'items'])
- )
-
- opt = self._option_fixture("keywords")
- self._assert_path_result(opt, q, [])
-
- opt = self._option_fixture("items.keywords")
- self._assert_path_result(opt, q, [])
-
- def test_with_current_nonmatching_attribute(self):
- Item, User, Order = (self.classes.Item,
- self.classes.User,
- self.classes.Order)
-
- sess = Session()
- q = sess.query(Item)._with_current_path(
- self._make_path_registry([User, 'orders', Order, 'items'])
- )
-
- opt = self._option_fixture(Item.keywords)
- self._assert_path_result(opt, q, [])
-
- opt = self._option_fixture(Order.items, Item.keywords)
- self._assert_path_result(opt, q, [])
-
- def test_from_base_to_subclass_attr(self):
- Dingaling, Address = self.classes.Dingaling, self.classes.Address
-
- sess = Session()
- class SubAddr(Address):
- pass
- mapper(SubAddr, inherits=Address, properties={
- 'flub': relationship(Dingaling)
- })
-
- q = sess.query(Address)
- opt = self._option_fixture(SubAddr.flub)
-
- self._assert_path_result(opt, q, [(SubAddr, 'flub')])
-
- def test_from_subclass_to_subclass_attr(self):
- Dingaling, Address = self.classes.Dingaling, self.classes.Address
-
- sess = Session()
- class SubAddr(Address):
- pass
- mapper(SubAddr, inherits=Address, properties={
- 'flub': relationship(Dingaling)
- })
-
- q = sess.query(SubAddr)
- opt = self._option_fixture(SubAddr.flub)
-
- self._assert_path_result(opt, q, [(SubAddr, 'flub')])
-
- def test_from_base_to_base_attr_via_subclass(self):
- Dingaling, Address = self.classes.Dingaling, self.classes.Address
-
- sess = Session()
- class SubAddr(Address):
- pass
- mapper(SubAddr, inherits=Address, properties={
- 'flub': relationship(Dingaling)
- })
-
- q = sess.query(Address)
- opt = self._option_fixture(SubAddr.user)
-
- self._assert_path_result(opt, q,
- [(Address, inspect(Address).attrs.user)])
-
- def test_of_type(self):
- User, Address = self.classes.User, self.classes.Address
-
- sess = Session()
- class SubAddr(Address):
- pass
- mapper(SubAddr, inherits=Address)
-
- q = sess.query(User)
- opt = self._option_fixture(User.addresses.of_type(SubAddr), SubAddr.user)
-
- u_mapper = inspect(User)
- a_mapper = inspect(Address)
- self._assert_path_result(opt, q, [
- (u_mapper, u_mapper.attrs.addresses),
- (u_mapper, u_mapper.attrs.addresses, a_mapper, a_mapper.attrs.user)
- ])
-
- def test_of_type_plus_level(self):
- Dingaling, User, Address = (self.classes.Dingaling,
- self.classes.User,
- self.classes.Address)
-
- sess = Session()
- class SubAddr(Address):
- pass
- mapper(SubAddr, inherits=Address, properties={
- 'flub': relationship(Dingaling)
- })
-
- q = sess.query(User)
- opt = self._option_fixture(User.addresses.of_type(SubAddr), SubAddr.flub)
-
- u_mapper = inspect(User)
- sa_mapper = inspect(SubAddr)
- self._assert_path_result(opt, q, [
- (u_mapper, u_mapper.attrs.addresses),
- (u_mapper, u_mapper.attrs.addresses, sa_mapper, sa_mapper.attrs.flub)
- ])
-
- def test_aliased_single(self):
- User = self.classes.User
-
- sess = Session()
- ualias = aliased(User)
- q = sess.query(ualias)
- opt = self._option_fixture(ualias.addresses)
- self._assert_path_result(opt, q, [(inspect(ualias), 'addresses')])
-
- def test_with_current_aliased_single(self):
- User, Address = self.classes.User, self.classes.Address
-
- sess = Session()
- ualias = aliased(User)
- q = sess.query(ualias)._with_current_path(
- self._make_path_registry([Address, 'user'])
- )
- opt = self._option_fixture(Address.user, ualias.addresses)
- self._assert_path_result(opt, q, [(inspect(ualias), 'addresses')])
-
- def test_with_current_aliased_single_nonmatching_option(self):
- User, Address = self.classes.User, self.classes.Address
-
- sess = Session()
- ualias = aliased(User)
- q = sess.query(User)._with_current_path(
- self._make_path_registry([Address, 'user'])
- )
- opt = self._option_fixture(Address.user, ualias.addresses)
- self._assert_path_result(opt, q, [])
-
- def test_with_current_aliased_single_nonmatching_entity(self):
- User, Address = self.classes.User, self.classes.Address
-
- sess = Session()
- ualias = aliased(User)
- q = sess.query(ualias)._with_current_path(
- self._make_path_registry([Address, 'user'])
- )
- opt = self._option_fixture(Address.user, User.addresses)
- self._assert_path_result(opt, q, [])
-
- def test_multi_entity_opt_on_second(self):
- Item = self.classes.Item
- Order = self.classes.Order
- opt = self._option_fixture(Order.items)
- sess = Session()
- q = sess.query(Item, Order)
- self._assert_path_result(opt, q, [(Order, "items")])
-
- def test_multi_entity_opt_on_string(self):
- Item = self.classes.Item
- Order = self.classes.Order
- opt = self._option_fixture("items")
- sess = Session()
- q = sess.query(Item, Order)
- self._assert_path_result(opt, q, [])
-
- def test_multi_entity_no_mapped_entities(self):
- Item = self.classes.Item
- Order = self.classes.Order
- opt = self._option_fixture("items")
- sess = Session()
- q = sess.query(Item.id, Order.id)
- self._assert_path_result(opt, q, [])
-
- def test_path_exhausted(self):
- User = self.classes.User
- Item = self.classes.Item
- Order = self.classes.Order
- opt = self._option_fixture(User.orders)
- sess = Session()
- q = sess.query(Item)._with_current_path(
- self._make_path_registry([User, 'orders', Order, 'items'])
- )
- self._assert_path_result(opt, q, [])
-
-class OptionsNoPropTest(_fixtures.FixtureTest):
- """test the error messages emitted when using property
- options in conjunection with column-only entities, or
- for not existing options
-
- """
-
- run_create_tables = False
- run_inserts = None
- run_deletes = None
-
- def test_option_with_mapper_basestring(self):
- Item = self.classes.Item
-
- self._assert_option([Item], 'keywords')
-
- def test_option_with_mapper_PropCompatator(self):
- Item = self.classes.Item
-
- self._assert_option([Item], Item.keywords)
-
- def test_option_with_mapper_then_column_basestring(self):
- Item = self.classes.Item
-
- self._assert_option([Item, Item.id], 'keywords')
-
- def test_option_with_mapper_then_column_PropComparator(self):
- Item = self.classes.Item
-
- self._assert_option([Item, Item.id], Item.keywords)
-
- def test_option_with_column_then_mapper_basestring(self):
- Item = self.classes.Item
-
- self._assert_option([Item.id, Item], 'keywords')
-
- def test_option_with_column_then_mapper_PropComparator(self):
- Item = self.classes.Item
-
- self._assert_option([Item.id, Item], Item.keywords)
-
- def test_option_with_column_basestring(self):
- Item = self.classes.Item
-
- message = \
- "Query has only expression-based entities - "\
- "can't find property named 'keywords'."
- self._assert_eager_with_just_column_exception(Item.id,
- 'keywords', message)
-
- def test_option_with_column_PropComparator(self):
- Item = self.classes.Item
-
- self._assert_eager_with_just_column_exception(Item.id,
- Item.keywords,
- "Query has only expression-based entities "
- "- can't find property named 'keywords'."
- )
-
- def test_option_against_nonexistent_PropComparator(self):
- Item = self.classes.Item
- Keyword = self.classes.Keyword
- self._assert_eager_with_entity_exception(
- [Keyword],
- (joinedload(Item.keywords), ),
- r"Can't find property 'keywords' on any entity specified "
- r"in this Query. Note the full path from root "
- r"\(Mapper\|Keyword\|keywords\) to target entity must be specified."
- )
-
- def test_option_against_nonexistent_basestring(self):
- Item = self.classes.Item
- self._assert_eager_with_entity_exception(
- [Item],
- (joinedload("foo"), ),
- r"Can't find property named 'foo' on the mapped "
- r"entity Mapper\|Item\|items in this Query."
- )
-
- def test_option_against_nonexistent_twolevel_basestring(self):
- Item = self.classes.Item
- self._assert_eager_with_entity_exception(
- [Item],
- (joinedload("keywords.foo"), ),
- r"Can't find property named 'foo' on the mapped entity "
- r"Mapper\|Keyword\|keywords in this Query."
- )
-
- def test_option_against_nonexistent_twolevel_all(self):
- Item = self.classes.Item
- self._assert_eager_with_entity_exception(
- [Item],
- (joinedload_all("keywords.foo"), ),
- r"Can't find property named 'foo' on the mapped entity "
- r"Mapper\|Keyword\|keywords in this Query."
- )
-
- @testing.fails_if(lambda:True,
- "PropertyOption doesn't yet check for relation/column on end result")
- def test_option_against_non_relation_basestring(self):
- Item = self.classes.Item
- Keyword = self.classes.Keyword
- self._assert_eager_with_entity_exception(
- [Keyword, Item],
- (joinedload_all("keywords"), ),
- r"Attribute 'keywords' of entity 'Mapper\|Keyword\|keywords' "
- "does not refer to a mapped entity"
- )
-
- @testing.fails_if(lambda:True,
- "PropertyOption doesn't yet check for relation/column on end result")
- def test_option_against_multi_non_relation_basestring(self):
- Item = self.classes.Item
- Keyword = self.classes.Keyword
- self._assert_eager_with_entity_exception(
- [Keyword, Item],
- (joinedload_all("keywords"), ),
- r"Attribute 'keywords' of entity 'Mapper\|Keyword\|keywords' "
- "does not refer to a mapped entity"
- )
-
- def test_option_against_wrong_entity_type_basestring(self):
- Item = self.classes.Item
- self._assert_eager_with_entity_exception(
- [Item],
- (joinedload_all("id", "keywords"), ),
- r"Attribute 'id' of entity 'Mapper\|Item\|items' does not "
- r"refer to a mapped entity"
- )
-
- def test_option_against_multi_non_relation_twolevel_basestring(self):
- Item = self.classes.Item
- Keyword = self.classes.Keyword
- self._assert_eager_with_entity_exception(
- [Keyword, Item],
- (joinedload_all("id", "keywords"), ),
- r"Attribute 'id' of entity 'Mapper\|Keyword\|keywords' "
- "does not refer to a mapped entity"
- )
-
- def test_option_against_multi_nonexistent_basestring(self):
- Item = self.classes.Item
- Keyword = self.classes.Keyword
- self._assert_eager_with_entity_exception(
- [Keyword, Item],
- (joinedload_all("description"), ),
- r"Can't find property named 'description' on the mapped "
- r"entity Mapper\|Keyword\|keywords in this Query."
- )
-
- def test_option_against_multi_no_entities_basestring(self):
- Item = self.classes.Item
- Keyword = self.classes.Keyword
- self._assert_eager_with_entity_exception(
- [Keyword.id, Item.id],
- (joinedload_all("keywords"), ),
- r"Query has only expression-based entities - can't find property "
- "named 'keywords'."
- )
-
- def test_option_against_wrong_multi_entity_type_attr_one(self):
- Item = self.classes.Item
- Keyword = self.classes.Keyword
- self._assert_eager_with_entity_exception(
- [Keyword, Item],
- (joinedload_all(Keyword.id, Item.keywords), ),
- r"Attribute 'Keyword.id' of entity 'Mapper\|Keyword\|keywords' "
- "does not refer to a mapped entity"
- )
-
- def test_option_against_wrong_multi_entity_type_attr_two(self):
- Item = self.classes.Item
- Keyword = self.classes.Keyword
- self._assert_eager_with_entity_exception(
- [Keyword, Item],
- (joinedload_all(Keyword.keywords, Item.keywords), ),
- r"Attribute 'Keyword.keywords' of entity 'Mapper\|Keyword\|keywords' "
- "does not refer to a mapped entity"
- )
-
- def test_option_against_wrong_multi_entity_type_attr_three(self):
- Item = self.classes.Item
- Keyword = self.classes.Keyword
- self._assert_eager_with_entity_exception(
- [Keyword.id, Item.id],
- (joinedload_all(Keyword.keywords, Item.keywords), ),
- r"Query has only expression-based entities - "
- "can't find property named 'keywords'."
- )
-
- def test_wrong_type_in_option(self):
- Item = self.classes.Item
- Keyword = self.classes.Keyword
- self._assert_eager_with_entity_exception(
- [Item],
- (joinedload_all(Keyword), ),
- r"mapper option expects string key or list of attributes"
- )
-
- def test_non_contiguous_all_option(self):
- User = self.classes.User
- self._assert_eager_with_entity_exception(
- [User],
- (joinedload_all(User.addresses, User.orders), ),
- r"Attribute 'User.orders' does not link "
- "from element 'Mapper|Address|addresses'"
- )
-
- @classmethod
- def setup_mappers(cls):
- users, User, addresses, Address, orders, Order = (
- cls.tables.users, cls.classes.User,
- cls.tables.addresses, cls.classes.Address,
- cls.tables.orders, cls.classes.Order)
- mapper(User, users, properties={
- 'addresses': relationship(Address),
- 'orders': relationship(Order)
- })
- mapper(Address, addresses)
- mapper(Order, orders)
- keywords, items, item_keywords, Keyword, Item = (cls.tables.keywords,
- cls.tables.items,
- cls.tables.item_keywords,
- cls.classes.Keyword,
- cls.classes.Item)
- mapper(Keyword, keywords, properties={
- "keywords": column_property(keywords.c.name + "some keyword")
- })
- mapper(Item, items,
- properties=dict(keywords=relationship(Keyword,
- secondary=item_keywords)))
-
- def _assert_option(self, entity_list, option):
- Item = self.classes.Item
-
- q = create_session().query(*entity_list).\
- options(joinedload(option))
- key = ('loaderstrategy', (inspect(Item), inspect(Item).attrs.keywords))
- assert key in q._attributes
-
- def _assert_eager_with_entity_exception(self, entity_list, options,
- message):
- assert_raises_message(sa.exc.ArgumentError,
- message,
- create_session().query(*entity_list).options,
- *options)
-
- def _assert_eager_with_just_column_exception(self, column,
- eager_option, message):
- assert_raises_message(sa.exc.ArgumentError, message,
- create_session().query(column).options,
- joinedload(eager_option))
-