summaryrefslogtreecommitdiff
path: root/oslo_db
diff options
context:
space:
mode:
authorKevin Benton <kevin@benton.pub>2017-01-16 14:09:36 -0800
committerKevin Benton <kevin@benton.pub>2017-01-17 12:48:45 -0800
commitadeaa7bdcc6f5af18b0a8016864f5cbbc08d92f0 (patch)
treeae99ee21abc9c02eaa459656cce885803d6ce4ac /oslo_db
parent5095c7c16c90df3fc6d3eb1ee31b6ac291b77df6 (diff)
downloadoslo-db-adeaa7bdcc6f5af18b0a8016864f5cbbc08d92f0.tar.gz
Coerce booleans to integer values in paginate_query
This will avoid a traceback resulting from using > or < on a boolean value (example in bug report). Change-Id: I4b90f18737e62bb35bacf75ad7a85603fb7b45cc Closes-Bug: #1656947
Diffstat (limited to 'oslo_db')
-rw-r--r--oslo_db/sqlalchemy/utils.py11
-rw-r--r--oslo_db/tests/sqlalchemy/test_utils.py21
2 files changed, 29 insertions, 3 deletions
diff --git a/oslo_db/sqlalchemy/utils.py b/oslo_db/sqlalchemy/utils.py
index 5adbd22..97a28c6 100644
--- a/oslo_db/sqlalchemy/utils.py
+++ b/oslo_db/sqlalchemy/utils.py
@@ -38,6 +38,7 @@ from sqlalchemy import Index
from sqlalchemy import inspect
from sqlalchemy import Integer
from sqlalchemy import MetaData
+from sqlalchemy.sql.expression import cast
from sqlalchemy.sql.expression import literal_column
from sqlalchemy.sql import text
from sqlalchemy import String
@@ -236,11 +237,15 @@ def paginate_query(query, model, limit, sort_keys, marker=None,
crit_attrs.append((model_attr == marker_values[j]))
model_attr = getattr(model, sort_keys[i])
+ val = marker_values[i]
+ # sqlalchemy doesn't like booleans in < >. bug/1656947
+ if isinstance(model_attr.type, Boolean):
+ val = int(val)
+ model_attr = cast(model_attr, Integer)
if sort_dirs[i].startswith('desc'):
- crit_attrs.append((model_attr < marker_values[i]))
+ crit_attrs.append((model_attr < val))
else:
- crit_attrs.append((model_attr > marker_values[i]))
-
+ crit_attrs.append((model_attr > val))
criteria = sqlalchemy.sql.and_(*crit_attrs)
criteria_list.append(criteria)
diff --git a/oslo_db/tests/sqlalchemy/test_utils.py b/oslo_db/tests/sqlalchemy/test_utils.py
index c88ac10..40a7ea2 100644
--- a/oslo_db/tests/sqlalchemy/test_utils.py
+++ b/oslo_db/tests/sqlalchemy/test_utils.py
@@ -32,6 +32,7 @@ from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import mapper
from sqlalchemy.orm import Session
+from sqlalchemy.sql.expression import cast
from sqlalchemy.sql import select
from sqlalchemy.types import UserDefinedType, NullType
from sqlalchemy.dialects.postgresql import psycopg2
@@ -77,6 +78,7 @@ class FakeTable(Base):
project_id = Column(String(50))
snapshot_id = Column(String(50))
updated_at = Column(DateTime, nullable=True)
+ enabled = Column(Boolean, default=True)
# mox is comparing in some awkward way that
# in this case requires the same identity of object
@@ -450,6 +452,25 @@ class TestGetUniqueKeys(test_base.BaseTestCase):
class TestPaginateQueryActualSQL(test_base.BaseTestCase):
+ def test_paginate_with_boolean_sort(self):
+ s = Session()
+ q = s.query(FakeTable)
+ q = utils.paginate_query(q, FakeTable, 5, ['enabled'],
+ sort_dirs=['asc'],
+ marker=FakeTable(user_id='hello',
+ enabled=False))
+ expected_core_sql = (
+ select([FakeTable]).
+ order_by(sqlalchemy.asc(FakeTable.enabled)).
+ where(cast(FakeTable.enabled, Integer) > 0).
+ limit(5)
+ )
+
+ self.assertEqual(
+ str(expected_core_sql.compile()),
+ str(q.statement.compile())
+ )
+
def test_paginate_on_hybrid_assert_stmt(self):
s = Session()
q = s.query(FakeTable)