Fix sort_query handling of polymorphic inheritance

This commit is contained in:
Konsta Vesterinen
2014-07-31 10:11:15 +03:00
parent 06579c323d
commit 2614d388ae
3 changed files with 102 additions and 35 deletions

View File

@@ -4,6 +4,12 @@ Changelog
Here you can see the full list of changes between each SQLAlchemy-Utils release. Here you can see the full list of changes between each SQLAlchemy-Utils release.
0.26.8 (2014-07-30)
^^^^^^^^^^^^^^^^^^^
- Fixed order by column property handling in sort_query when using polymorphic inheritance
0.26.7 (2014-07-29) 0.26.7 (2014-07-29)
^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^

View File

@@ -46,12 +46,10 @@ class QuerySorter(object):
property_ = properties[attr] property_ = properties[attr]
if isinstance(property_, ColumnProperty): if isinstance(property_, ColumnProperty):
if isinstance(property_.columns[0], Label): if isinstance(property_.columns[0], Label):
expr = property_.columns[0].name return getattr(entity, property_.key)
else: else:
expr = get_expr_attr(entity, property_.key) return get_expr_attr(entity, property_.key)
return expr return
else:
return
mapper = sa.inspect(entity) mapper = sa.inspect(entity)
@@ -81,6 +79,7 @@ class QuerySorter(object):
self.query = query self.query = query
self.labels = query_labels(query) self.labels = query_labels(query)
self.entities = query_entities(query) self.entities = query_entities(query)
for sort in args: for sort in args:
if not sort: if not sort:
continue continue

View File

@@ -5,24 +5,31 @@ from sqlalchemy_utils.functions import QuerySorterException
from tests import TestCase from tests import TestCase
def assert_contains(clause, query):
# Test that query executes
query.all()
assert clause in str(query)
class TestSortQuery(TestCase): class TestSortQuery(TestCase):
def test_without_sort_param_returns_the_query_object_untouched(self): def test_without_sort_param_returns_the_query_object_untouched(self):
query = self.session.query(self.Article) query = self.session.query(self.Article)
sorted_query = sort_query(query, '') query = sort_query(query, '')
assert query == sorted_query assert query == query
def test_column_ascending(self): def test_column_ascending(self):
query = sort_query(self.session.query(self.Article), 'name') query = sort_query(self.session.query(self.Article), 'name')
assert 'ORDER BY article.name ASC' in str(query) assert_contains('ORDER BY article.name ASC', query)
def test_column_descending(self): def test_column_descending(self):
query = sort_query(self.session.query(self.Article), '-name') query = sort_query(self.session.query(self.Article), '-name')
assert 'ORDER BY article.name DESC' in str(query) assert_contains('ORDER BY article.name DESC', query)
def test_skips_unknown_columns(self): def test_skips_unknown_columns(self):
query = self.session.query(self.Article) query = self.session.query(self.Article)
sorted_query = sort_query(query, '-unknown') query = sort_query(query, '-unknown')
assert query == sorted_query assert query == query
def test_non_silent_mode(self): def test_non_silent_mode(self):
query = self.session.query(self.Article) query = self.session.query(self.Article)
@@ -35,21 +42,21 @@ class TestSortQuery(TestCase):
.join(self.Article.category) .join(self.Article.category)
) )
query = sort_query(query, 'name', silent=False) query = sort_query(query, 'name', silent=False)
assert 'ORDER BY article.name ASC' in str(query) assert_contains('ORDER BY article.name ASC', query)
def test_calculated_value_ascending(self): def test_calculated_value_ascending(self):
query = self.session.query( query = self.session.query(
self.Category, sa.func.count(self.Article.id).label('articles') self.Category, sa.func.count(self.Article.id).label('articles')
) )
query = sort_query(query, 'articles') query = sort_query(query, 'articles')
assert 'ORDER BY articles ASC' in str(query) assert_contains('ORDER BY articles ASC', query)
def test_calculated_value_descending(self): def test_calculated_value_descending(self):
query = self.session.query( query = self.session.query(
self.Category, sa.func.count(self.Article.id).label('articles') self.Category, sa.func.count(self.Article.id).label('articles')
) )
query = sort_query(query, '-articles') query = sort_query(query, '-articles')
assert 'ORDER BY articles DESC' in str(query) assert_contains('ORDER BY articles DESC', query)
def test_subqueried_scalar(self): def test_subqueried_scalar(self):
article_count = ( article_count = (
@@ -65,7 +72,7 @@ class TestSortQuery(TestCase):
self.Category, article_count.label('articles') self.Category, article_count.label('articles')
) )
query = sort_query(query, '-articles') query = sort_query(query, '-articles')
assert 'ORDER BY articles DESC' in str(query) assert_contains('ORDER BY articles DESC', query)
def test_aliased_joined_entity(self): def test_aliased_joined_entity(self):
alias = sa.orm.aliased(self.Category, name='categories') alias = sa.orm.aliased(self.Category, name='categories')
@@ -75,17 +82,17 @@ class TestSortQuery(TestCase):
alias, self.Article.category alias, self.Article.category
) )
query = sort_query(query, '-categories-name') query = sort_query(query, '-categories-name')
assert 'ORDER BY categories.name DESC' in str(query) assert_contains('ORDER BY categories.name DESC', query)
def test_joined_table_column(self): def test_joined_table_column(self):
query = self.session.query(self.Article).join(self.Article.category) query = self.session.query(self.Article).join(self.Article.category)
sorted_query = sort_query(query, 'category-name') query = sort_query(query, 'category-name')
assert 'category.name ASC' in str(sorted_query) assert_contains('category.name ASC', query)
def test_multiple_columns(self): def test_multiple_columns(self):
query = self.session.query(self.Article) query = self.session.query(self.Article)
sorted_query = sort_query(query, 'name', 'id') query = sort_query(query, 'name', 'id')
assert 'article.name ASC, article.id ASC' in str(sorted_query) assert_contains('article.name ASC, article.id ASC', query)
def test_column_property(self): def test_column_property(self):
self.Category.article_count = sa.orm.column_property( self.Category.article_count = sa.orm.column_property(
@@ -95,8 +102,8 @@ class TestSortQuery(TestCase):
) )
query = self.session.query(self.Category) query = self.session.query(self.Category)
sorted_query = sort_query(query, 'article_count') query = sort_query(query, 'article_count')
assert 'article_count ASC' in str(sorted_query) assert_contains('article_count ASC', query)
def test_column_property_descending(self): def test_column_property_descending(self):
self.Category.article_count = sa.orm.column_property( self.Category.article_count = sa.orm.column_property(
@@ -106,8 +113,8 @@ class TestSortQuery(TestCase):
) )
query = self.session.query(self.Category) query = self.session.query(self.Category)
sorted_query = sort_query(query, '-article_count') query = sort_query(query, '-article_count')
assert 'article_count DESC' in str(sorted_query) assert_contains('article_count DESC', query)
def test_relationship_property(self): def test_relationship_property(self):
query = self.session.query(self.Category) query = self.session.query(self.Category)
@@ -122,19 +129,20 @@ class TestSortQuery(TestCase):
def test_synonym_property(self): def test_synonym_property(self):
query = self.session.query(self.Category) query = self.session.query(self.Category)
query = sort_query(query, 'name_synonym') query = sort_query(query, 'name_synonym')
assert 'ORDER BY name DESC' assert_contains('ORDER BY name DESC', query)
def test_hybrid_property(self): def test_hybrid_property(self):
query = self.session.query(self.Category) query = self.session.query(self.Category)
query = sort_query(query, 'articles_count') query = sort_query(query, 'articles_count')
assert 'ORDER BY (SELECT count(article.id) AS count_1' in str(query) assert_contains('ORDER BY (SELECT count(article.id) AS count_1', query)
def test_hybrid_property_descending(self): def test_hybrid_property_descending(self):
query = self.session.query(self.Category) query = self.session.query(self.Category)
query = sort_query(query, '-articles_count') query = sort_query(query, '-articles_count')
assert ( assert_contains(
'ORDER BY (SELECT count(article.id) AS count_1' 'ORDER BY (SELECT count(article.id) AS count_1',
) in str(query) query
)
assert ' DESC' in str(query) assert ' DESC' in str(query)
def test_assigned_hybrid_property(self): def test_assigned_hybrid_property(self):
@@ -146,16 +154,22 @@ class TestSortQuery(TestCase):
) )
query = self.session.query(self.Article) query = self.session.query(self.Article)
query = sort_query(query, 'some_hybrid') query = sort_query(query, 'some_hybrid')
assert 'ORDER BY article.name ASC' in str(query) assert_contains('ORDER BY article.name ASC', query)
class TestSortQueryRelationshipCounts(TestCase):
"""
Currently this doesn't work with SQLite
"""
dns = 'postgres://postgres@localhost/sqlalchemy_utils_test'
def test_relation_hybrid_property(self): def test_relation_hybrid_property(self):
query = ( query = (
self.session.query(self.Article) self.session.query(self.Article)
.join(self.Article.category) .join(self.Article.category)
.correlate(self.Article.__table__) ).group_by(self.Article.id)
)
query = sort_query(query, '-category-articles_count') query = sort_query(query, '-category-articles_count')
assert 'ORDER BY (SELECT count(article.id) AS count_1' in str(query) assert_contains('ORDER BY (SELECT count(article.id) AS count_1', query)
def test_aliased_hybrid_property(self): def test_aliased_hybrid_property(self):
alias = sa.orm.aliased( alias = sa.orm.aliased(
@@ -168,6 +182,54 @@ class TestSortQuery(TestCase):
.options( .options(
sa.orm.contains_eager(self.Article.category, alias=alias) sa.orm.contains_eager(self.Article.category, alias=alias)
) )
) ).group_by(alias.id, self.Article.id)
query = sort_query(query, '-categories-articles_count') query = sort_query(query, '-categories-articles_count')
assert 'ORDER BY (SELECT count(article.id) AS count_1' in str(query) assert_contains('ORDER BY (SELECT count(article.id) AS count_1', query)
class TestSortQueryWithPolymorphicInheritance(TestCase):
"""
Currently this doesn't work with SQLite
"""
dns = 'postgres://postgres@localhost/sqlalchemy_utils_test'
def create_models(self):
class TextItem(self.Base):
__tablename__ = 'text_item'
id = sa.Column(sa.Integer, primary_key=True)
type = sa.Column(sa.Unicode(255))
__mapper_args__ = {
'polymorphic_on': type,
'with_polymorphic': '*'
}
class Article(TextItem):
__tablename__ = 'article'
id = sa.Column(
sa.Integer, sa.ForeignKey(TextItem.id), primary_key=True
)
__mapper_args__ = {
'polymorphic_identity': u'article'
}
self.TextItem = TextItem
self.Article = Article
def test_column_property(self):
self.TextItem.item_count = sa.orm.column_property(
sa.select(
[
sa.func.count('1')
],
)
.select_from(self.TextItem.__table__)
.label('item_count')
)
query = sort_query(
self.session.query(self.TextItem),
'item_count'
)
assert_contains('ORDER BY (SELECT count(:param_2) AS count_2', query)