diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-11-28 12:37:15 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-11-28 12:37:15 -0500 |
commit | bb60a8ad946dd331f546f06a156b7ebb87d1709d (patch) | |
tree | d530604307af524dc87355811fd103718114c258 /lib/sqlalchemy/sql/selectable.py | |
parent | 106e793d0573b5bcd1ddee549bca1a546aa13972 (diff) | |
download | sqlalchemy-bb60a8ad946dd331f546f06a156b7ebb87d1709d.tar.gz |
- work in progress, will squash
Diffstat (limited to 'lib/sqlalchemy/sql/selectable.py')
-rw-r--r-- | lib/sqlalchemy/sql/selectable.py | 141 |
1 files changed, 130 insertions, 11 deletions
diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py index 99b2fbefc..e49c10001 100644 --- a/lib/sqlalchemy/sql/selectable.py +++ b/lib/sqlalchemy/sql/selectable.py @@ -14,7 +14,7 @@ from .elements import ClauseElement, TextClause, ClauseList, \ from .elements import _clone, \ _literal_as_text, _interpret_as_column_or_from, _expand_cloned,\ _select_iterables, _anonymous_label, _clause_element_as_expr,\ - _cloned_intersection, _cloned_difference, True_ + _cloned_intersection, _cloned_difference, True_, _only_column_elements from .base import Immutable, Executable, _generative, \ ColumnCollection, ColumnSet, _from_objects, Generative from . import type_api @@ -1151,6 +1151,68 @@ class TableClause(Immutable, FromClause): return [self] +class ForUpdateArg(object): + + @classmethod + def parse_legacy_select(self, arg): + """Parse the for_update arugment of :func:`.select`. + + :param mode: Defines the lockmode to use. + + ``None`` - translates to no lockmode + + ``'update'`` - translates to ``FOR UPDATE`` + (standard SQL, supported by most dialects) + + ``'nowait'`` - translates to ``FOR UPDATE NOWAIT`` + (supported by Oracle, PostgreSQL 8.1 upwards) + + ``'read'`` - translates to ``LOCK IN SHARE MODE`` (for MySQL), + and ``FOR SHARE`` (for PostgreSQL) + + ``'read_nowait'`` - translates to ``FOR SHARE NOWAIT`` + (supported by PostgreSQL). ``FOR SHARE`` and + ``FOR SHARE NOWAIT`` (PostgreSQL). + + """ + if arg is None: + return None + + nowait = read = False + if arg == 'nowait': + nowait = True + elif arg == 'read': + read = True + elif arg == 'read_nowait': + read = nowait = True + + return ForUpdateArg(read=read, nowait=nowait) + + @property + def legacy_for_update_value(self): + if self.read and not self.nowait: + return "read" + elif self.read and self.nowait: + return "read_nowait" + elif self.nowait: + return "update_nowait" + else: + return "update" + + def __init__(self, nowait=False, read=False, of=None): + """Represents arguments specified to :meth:`.Select.for_update`. + + .. versionadded:: 0.9.0b2 + """ + + self.nowait = nowait + self.read = read + if of is not None: + self.of = [_only_column_elements(of, "of") + for elem in util.to_list(of)] + else: + self.of = None + class SelectBase(Executable, FromClause): """Base class for :class:`.Select` and :class:`.CompoundSelect`.""" @@ -1158,6 +1220,7 @@ class SelectBase(Executable, FromClause): _group_by_clause = ClauseList() _limit = None _offset = None + _for_update_arg = None def __init__(self, use_labels=False, @@ -1169,7 +1232,10 @@ class SelectBase(Executable, FromClause): bind=None, autocommit=None): self.use_labels = use_labels - self.for_update = for_update + + if for_update is not False: + self._for_update_arg = ForUpdateArg.parse_legacy_select(for_update) + if autocommit is not None: util.warn_deprecated('autocommit on select() is ' 'deprecated. Use .execution_options(a' @@ -1188,6 +1254,46 @@ class SelectBase(Executable, FromClause): if group_by is not None: self._group_by_clause = ClauseList(*util.to_list(group_by)) + @property + def for_update(self): + """Provide legacy dialect support for the ``for_update`` attribute + as a getter. + + """ + if self._for_update_arg is not None: + return self._for_update_arg.legacy_for_update_value + else: + return None + + @_generative + def with_for_update(self, nowait=False, read=False, of=None): + """apply FOR UPDATE to this :class:`.SelectBase`. + + E.g.:: + + stmt = select([table]).with_for_update(nowait=True) + + Additional keyword arguments are provided for common database-specific + variants. + + :param nowait: boolean; will render ``FOR UPDATE NOWAIT`` on Oracle and + Postgresql dialects. + + :param read: boolean; will render ``LOCK IN SHARE MODE`` on MySQL, + ``FOR SHARE`` on Postgresql. On Postgresql, when combined with + ``nowait``, will render ``FOR SHARE NOWAIT``. + + :param of: SQL expression or list of SQL expression elements which + will render into a ``FOR UPDATE OF`` clause; supported by PostgreSQL + and Oracle. May render as a table or as a column depending on + backend. + + + .. versionadded:: 0.9.0b2 + + """ + self._for_update_arg = ForUpdateArg(nowait=nowait, read=read, of=of) + def as_scalar(self): """return a 'scalar' representation of this selectable, which can be used as a column expression. @@ -1724,6 +1830,8 @@ class HasPrefixes(object): self._prefixes = self._prefixes + tuple( [(_literal_as_text(p), dialect) for p in prefixes]) + + class Select(HasPrefixes, SelectBase): """Represents a ``SELECT`` statement. @@ -1828,17 +1936,28 @@ class Select(HasPrefixes, SelectBase): when ``True``, applies ``FOR UPDATE`` to the end of the resulting statement. - Certain database dialects also support - alternate values for this parameter: + .. deprecated:: 0.9.0 - use :meth:`.SelectBase.with_for_update` + to specify for update arguments. + + Additional values are accepted here, including: + + ``None`` - translates to no lockmode + + ``'update'`` - translates to ``FOR UPDATE`` + (standard SQL, supported by most dialects) + + ``'update_nowait'`` - translates to ``FOR UPDATE NOWAIT`` + (supported by Oracle, PostgreSQL 8.1 upwards) + + ``'read'`` - translates to ``LOCK IN SHARE MODE`` (for MySQL), + and ``FOR SHARE`` (for PostgreSQL) - * With the MySQL dialect, the value ``"read"`` translates to - ``LOCK IN SHARE MODE``. - * With the Oracle and Postgresql dialects, the value ``"nowait"`` - translates to ``FOR UPDATE NOWAIT``. - * With the Postgresql dialect, the values "read" and ``"read_nowait"`` - translate to ``FOR SHARE`` and ``FOR SHARE NOWAIT``, respectively. + ``'read_nowait'`` - translates to ``FOR SHARE NOWAIT`` + (supported by PostgreSQL). ``FOR SHARE`` and + ``FOR SHARE NOWAIT`` (PostgreSQL). - .. versionadded:: 0.7.7 + The :meth:`.SelectBase.with_for_update` method should be preferred as + a means to specify FOR UPDATE more simply. :param group_by: a list of :class:`.ClauseElement` objects which will comprise the |