aboutsummaryrefslogtreecommitdiffstats
path: root/keystone-moon/keystone/common/sql/core.py
diff options
context:
space:
mode:
Diffstat (limited to 'keystone-moon/keystone/common/sql/core.py')
-rw-r--r--keystone-moon/keystone/common/sql/core.py110
1 files changed, 39 insertions, 71 deletions
diff --git a/keystone-moon/keystone/common/sql/core.py b/keystone-moon/keystone/common/sql/core.py
index ebd61bb7..cb026356 100644
--- a/keystone-moon/keystone/common/sql/core.py
+++ b/keystone-moon/keystone/common/sql/core.py
@@ -18,14 +18,13 @@ Before using this module, call initialize(). This has to be done before
CONF() because it sets up configuration options.
"""
-import contextlib
import functools
from oslo_config import cfg
from oslo_db import exception as db_exception
from oslo_db import options as db_options
+from oslo_db.sqlalchemy import enginefacade
from oslo_db.sqlalchemy import models
-from oslo_db.sqlalchemy import session as db_session
from oslo_log import log
from oslo_serialization import jsonutils
import six
@@ -34,6 +33,7 @@ from sqlalchemy.ext import declarative
from sqlalchemy.orm.attributes import flag_modified, InstrumentedAttribute
from sqlalchemy import types as sql_types
+from keystone.common import driver_hints
from keystone.common import utils
from keystone import exception
from keystone.i18n import _
@@ -68,7 +68,6 @@ flag_modified = flag_modified
def initialize():
"""Initialize the module."""
-
db_options.set_defaults(
CONF,
connection="sqlite:///keystone.db")
@@ -166,77 +165,47 @@ class ModelDictMixin(object):
return {name: getattr(self, name) for name in names}
-_engine_facade = None
+_main_context_manager = None
-def _get_engine_facade():
- global _engine_facade
+def _get_main_context_manager():
+ global _main_context_manager
- if not _engine_facade:
- _engine_facade = db_session.EngineFacade.from_config(CONF)
+ if not _main_context_manager:
+ _main_context_manager = enginefacade.transaction_context()
- return _engine_facade
+ return _main_context_manager
def cleanup():
- global _engine_facade
+ global _main_context_manager
- _engine_facade = None
+ _main_context_manager = None
-def get_engine():
- return _get_engine_facade().get_engine()
+_CONTEXT = None
-def get_session(expire_on_commit=False):
- return _get_engine_facade().get_session(expire_on_commit=expire_on_commit)
+def _get_context():
+ global _CONTEXT
+ if _CONTEXT is None:
+ # NOTE(dims): Delay the `threading.local` import to allow for
+ # eventlet/gevent monkeypatching to happen
+ import threading
+ _CONTEXT = threading.local()
+ return _CONTEXT
-@contextlib.contextmanager
-def transaction(expire_on_commit=False):
- """Return a SQLAlchemy session in a scoped transaction."""
- session = get_session(expire_on_commit=expire_on_commit)
- with session.begin():
- yield session
+def session_for_read():
+ return _get_main_context_manager().reader.using(_get_context())
-def truncated(f):
- """Ensure list truncation is detected in Driver list entity methods.
+def session_for_write():
+ return _get_main_context_manager().writer.using(_get_context())
- This is designed to wrap and sql Driver list_{entity} methods in order to
- calculate if the resultant list has been truncated. Provided a limit dict
- is found in the hints list, we increment the limit by one so as to ask the
- wrapped function for one more entity than the limit, and then once the list
- has been generated, we check to see if the original limit has been
- exceeded, in which case we truncate back to that limit and set the
- 'truncated' boolean to 'true' in the hints limit dict.
- """
- @functools.wraps(f)
- def wrapper(self, hints, *args, **kwargs):
- if not hasattr(hints, 'limit'):
- raise exception.UnexpectedError(
- _('Cannot truncate a driver call without hints list as '
- 'first parameter after self '))
-
- if hints.limit is None:
- return f(self, hints, *args, **kwargs)
-
- # A limit is set, so ask for one more entry than we need
- list_limit = hints.limit['limit']
- hints.set_limit(list_limit + 1)
- ref_list = f(self, hints, *args, **kwargs)
-
- # If we got more than the original limit then trim back the list and
- # mark it truncated. In both cases, make sure we set the limit back
- # to its original value.
- if len(ref_list) > list_limit:
- hints.set_limit(list_limit, truncated=True)
- return ref_list[:list_limit]
- else:
- hints.set_limit(list_limit)
- return ref_list
- return wrapper
+def truncated(f):
+ return driver_hints.truncated(f)
class _WontMatch(Exception):
@@ -325,42 +294,41 @@ def _filter(model, query, hints):
satisfied_filters.append(filter_)
return query.filter(query_term)
- def exact_filter(model, filter_, cumulative_filter_dict):
+ def exact_filter(model, query, filter_, satisfied_filters):
"""Applies an exact filter to a query.
:param model: the table model in question
+ :param query: query to apply filters to
:param dict filter_: describes this filter
- :param dict cumulative_filter_dict: describes the set of exact filters
- built up so far
-
+ :param list satisfied_filters: filter_ will be added if it is
+ satisfied.
+ :returns query: query updated to add any exact filters we could
+ satisfy
"""
key = filter_['name']
col = getattr(model, key)
if isinstance(col.property.columns[0].type, sql.types.Boolean):
- cumulative_filter_dict[key] = (
- utils.attr_as_boolean(filter_['value']))
+ filter_val = utils.attr_as_boolean(filter_['value'])
else:
_WontMatch.check(filter_['value'], col)
- cumulative_filter_dict[key] = filter_['value']
+ filter_val = filter_['value']
+
+ satisfied_filters.append(filter_)
+ return query.filter(col == filter_val)
try:
- filter_dict = {}
satisfied_filters = []
for filter_ in hints.filters:
if filter_['name'] not in model.attributes:
continue
if filter_['comparator'] == 'equals':
- exact_filter(model, filter_, filter_dict)
- satisfied_filters.append(filter_)
+ query = exact_filter(model, query, filter_,
+ satisfied_filters)
else:
query = inexact_filter(model, query, filter_,
satisfied_filters)
- # Apply any exact filters we built up
- if filter_dict:
- query = query.filter_by(**filter_dict)
-
# Remove satisfied filters, then the caller will know remaining filters
for filter_ in satisfied_filters:
hints.filters.remove(filter_)
@@ -377,7 +345,7 @@ def _limit(query, hints):
:param query: query to apply filters to
:param hints: contains the list of filters and limit details.
- :returns updated query
+ :returns: updated query
"""
# NOTE(henry-nash): If we were to implement pagination, then we