You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ariatosca.apache.org by em...@apache.org on 2017/04/05 15:58:25 UTC
[5/6] incubator-ariatosca git commit:
ARIA-137-Support-for-predicate-based-queries-in-the-SQL-mapi
ARIA-137-Support-for-predicate-based-queries-in-the-SQL-mapi
Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/422574e0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/422574e0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/422574e0
Branch: refs/heads/ARIA-134-populate-workflows
Commit: 422574e03174e5dff57888af2519ed62048ce3fa
Parents: e7ffc73
Author: max-orlov <ma...@gigaspaces.com>
Authored: Tue Apr 4 20:41:59 2017 +0300
Committer: max-orlov <ma...@gigaspaces.com>
Committed: Wed Apr 5 16:02:04 2017 +0300
----------------------------------------------------------------------
aria/storage/sql_mapi.py | 28 +++++++++++++++-
tests/storage/test_model_storage.py | 57 ++++++++++++++++++++++++++++++++
2 files changed, 84 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/422574e0/aria/storage/sql_mapi.py
----------------------------------------------------------------------
diff --git a/aria/storage/sql_mapi.py b/aria/storage/sql_mapi.py
index 59e1896..8d34bb4 100644
--- a/aria/storage/sql_mapi.py
+++ b/aria/storage/sql_mapi.py
@@ -31,6 +31,13 @@ from . import (
exceptions,
)
+_predicates = {'ge': '__ge__',
+ 'gt': '__gt__',
+ 'lt': '__lt__',
+ 'le': '__le__',
+ 'eq': '__eq__',
+ 'ne': '__ne__'}
+
class SQLAlchemyModelAPI(api.ModelAPI):
"""
@@ -243,7 +250,10 @@ class SQLAlchemyModelAPI(api.ModelAPI):
@staticmethod
def _add_value_filter(query, filters):
for column, value in filters.items():
- if isinstance(value, (list, tuple)):
+ if isinstance(value, dict):
+ for predicate, operand in value.items():
+ query = query.filter(getattr(column, predicate)(operand))
+ elif isinstance(value, (list, tuple)):
query = query.filter(column.in_(value))
else:
query = query.filter(column == value)
@@ -269,12 +279,28 @@ class SQLAlchemyModelAPI(api.ModelAPI):
include, filters, sort, joins = self._get_joins_and_converted_columns(
include, filters, sort
)
+ filters = self._convert_operands(filters)
query = self._get_base_query(include, joins)
query = self._filter_query(query, filters)
query = self._sort_query(query, sort)
return query
+ @staticmethod
+ def _convert_operands(filters):
+ for column, conditions in filters.items():
+ if isinstance(conditions, dict):
+ for predicate, operand in conditions.items():
+ if predicate not in _predicates:
+ raise exceptions.StorageError(
+ "{0} is not a valid predicate for filtering. Valid predicates are {1}"
+ .format(predicate, ', '.join(_predicates.keys())))
+ del filters[column][predicate]
+ filters[column][_predicates[predicate]] = operand
+
+
+ return filters
+
def _get_joins_and_converted_columns(self,
include,
filters,
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/422574e0/tests/storage/test_model_storage.py
----------------------------------------------------------------------
diff --git a/tests/storage/test_model_storage.py b/tests/storage/test_model_storage.py
index e4f3eba..4dabfaf 100644
--- a/tests/storage/test_model_storage.py
+++ b/tests/storage/test_model_storage.py
@@ -15,6 +15,12 @@
import pytest
+from sqlalchemy import (
+ Column,
+ Integer,
+ Text
+)
+
from aria import (
application_model_storage,
modeling
@@ -150,3 +156,54 @@ def test_mapi_include(context):
assert_include(service1)
assert_include(service2)
+
+
+class MockModel(modeling.models.aria_declarative_base, modeling.mixins.ModelMixin): #pylint: disable=abstract-method
+ __tablename__ = 'op_mock_model'
+
+ name = Column(Text)
+ value = Column(Integer)
+
+
+class TestFilterOperands(object):
+
+ @pytest.fixture()
+ def storage(self):
+ model_storage = application_model_storage(
+ sql_mapi.SQLAlchemyModelAPI, initiator=tests_storage.init_inmemory_model_storage)
+ model_storage.register(MockModel)
+ for value in (1, 2, 3, 4):
+ model_storage.op_mock_model.put(MockModel(value=value))
+ yield model_storage
+ tests_storage.release_sqlite_storage(model_storage)
+
+ def test_gt(self, storage):
+ assert len(storage.op_mock_model.list(filters=dict(value=dict(gt=3)))) == 1
+ assert len(storage.op_mock_model.list(filters=dict(value=dict(gt=4)))) == 0
+
+ def test_ge(self, storage):
+ assert len(storage.op_mock_model.list(filters=dict(value=dict(ge=3)))) == 2
+ assert len(storage.op_mock_model.list(filters=dict(value=dict(ge=5)))) == 0
+
+ def test_lt(self, storage):
+ assert len(storage.op_mock_model.list(filters=dict(value=dict(lt=2)))) == 1
+ assert len(storage.op_mock_model.list(filters=dict(value=dict(lt=1)))) == 0
+
+ def test_le(self, storage):
+ assert len(storage.op_mock_model.list(filters=dict(value=dict(le=2)))) == 2
+ assert len(storage.op_mock_model.list(filters=dict(value=dict(le=0)))) == 0
+
+ def test_eq(self, storage):
+ assert len(storage.op_mock_model.list(filters=dict(value=dict(eq=2)))) == 1
+ assert len(storage.op_mock_model.list(filters=dict(value=dict(eq=0)))) == 0
+
+ def test_neq(self, storage):
+ assert len(storage.op_mock_model.list(filters=dict(value=dict(ne=2)))) == 3
+
+ def test_gt_and_lt(self, storage):
+ assert len(storage.op_mock_model.list(filters=dict(value=dict(gt=1, lt=3)))) == 1
+ assert len(storage.op_mock_model.list(filters=dict(value=dict(gt=2, lt=2)))) == 0
+
+ def test_eq_and_ne(self, storage):
+ assert len(storage.op_mock_model.list(filters=dict(value=dict(eq=1, ne=3)))) == 1
+ assert len(storage.op_mock_model.list(filters=dict(value=dict(eq=1, ne=1)))) == 0