diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2010-01-16 22:44:04 +0000 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2010-01-16 22:44:04 +0000 |
commit | abccc0624228def744b0382e84f01cf95e0d3aed (patch) | |
tree | fca7eb29b90211daa699da6d0358f81243c243d9 /lib/sqlalchemy/sql/expression.py | |
parent | 00df05061e7a0333022d02705c21270f9de4edab (diff) | |
download | sqlalchemy-abccc0624228def744b0382e84f01cf95e0d3aed.tar.gz |
- added "statement_options()" to Query, to so options can be
passed to the resulting statement. Currently only
Select-statements have these options, and the only option
used is "stream_results", and the only dialect which knows
"stream_results" is psycopg2.
- Query.yield_per() will set the "stream_results" statement
option automatically.
- Added "statement_options()" to Selects, which set statement
specific options. These enable e.g. dialect specific options
such as whether to enable using server side cursors, etc.
- The psycopg2 now respects the statement option
"stream_results". This option overrides the connection setting
"server_side_cursors". If true, server side cursors will be
used for the statement. If false, they will not be used, even
if "server_side_cursors" is true on the
connection. [ticket:1619]
- added a "frozendict" from http://code.activestate.com/recipes/414283/,
adding more default collections as immutable class vars on
Query, Insert, Select
Diffstat (limited to 'lib/sqlalchemy/sql/expression.py')
-rw-r--r-- | lib/sqlalchemy/sql/expression.py | 65 |
1 files changed, 43 insertions, 22 deletions
diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py index 742746cbe..2dc13ee82 100644 --- a/lib/sqlalchemy/sql/expression.py +++ b/lib/sqlalchemy/sql/expression.py @@ -2178,8 +2178,13 @@ class _TypeClause(ClauseElement): def __init__(self, type): self.type = type +class _Executable(object): + """Mark a ClauseElement as supporting execution.""" -class _TextClause(ClauseElement): + supports_execution = True + _statement_options = util.frozendict() + +class _TextClause(_Executable, ClauseElement): """Represent a literal SQL text fragment. Public constructor is the :func:`text()` function. @@ -2189,7 +2194,6 @@ class _TextClause(ClauseElement): __visit_name__ = 'textclause' _bind_params_regex = re.compile(r'(?<![:\w\x5c]):(\w+)(?!:)', re.UNICODE) - supports_execution = True @property def _select_iterable(self): @@ -2198,11 +2202,14 @@ class _TextClause(ClauseElement): _hide_froms = [] def __init__(self, text = "", bind=None, - bindparams=None, typemap=None, autocommit=PARSE_AUTOCOMMIT): + bindparams=None, typemap=None, autocommit=PARSE_AUTOCOMMIT, statement_options=None): self._bind = bind self.bindparams = {} self.typemap = typemap self._autocommit = autocommit + self._statement_options = statement_options + if self._statement_options is None: + self._statement_options = {} if typemap is not None: for key in typemap.keys(): typemap[key] = sqltypes.to_instance(typemap[key]) @@ -2792,6 +2799,7 @@ class Alias(FromClause): self.supports_execution = baseselectable.supports_execution if self.supports_execution: self._autocommit = baseselectable._autocommit + self._statement_options = baseselectable._statement_options self.element = selectable if alias is None: if self.original.named_with_column: @@ -2845,6 +2853,7 @@ class Alias(FromClause): def bind(self): return self.element.bind + class _Grouping(ColumnElement): """Represent a grouping within a column expression""" @@ -3159,11 +3168,9 @@ def _generative(fn, *args, **kw): fn(self, *args[1:], **kw) return self -class _SelectBaseMixin(object): +class _SelectBaseMixin(_Executable): """Base class for :class:`Select` and ``CompoundSelects``.""" - supports_execution = True - def __init__(self, use_labels=False, for_update=False, @@ -3172,13 +3179,17 @@ class _SelectBaseMixin(object): order_by=None, group_by=None, bind=None, - autocommit=False): + autocommit=False, + statement_options=None): self.use_labels = use_labels self.for_update = for_update self._autocommit = autocommit self._limit = limit self._offset = offset self._bind = bind + self._statement_options = statement_options + if self._statement_options is None: + self._statement_options = dict() self._order_by_clause = ClauseList(*util.to_list(order_by) or []) self._group_by_clause = ClauseList(*util.to_list(group_by) or []) @@ -3290,6 +3301,18 @@ class _SelectBaseMixin(object): def _from_objects(self): return [self] + @_generative + def statement_options(self, **kwargs): + """ Set non-SQL options for the statement, such as dialect-specific options. + + The options available are covered in the respective dialect's section. + + """ + _statement_options = self._statement_options.copy() + for key, value in kwargs.items(): + _statement_options[key] = value + self._statement_options = _statement_options + class _ScalarSelect(_Grouping): _from_objects = [] @@ -3411,7 +3434,9 @@ class Select(_SelectBaseMixin, FromClause): """ __visit_name__ = 'select' - + + _prefixes = () + def __init__(self, columns, whereclause=None, @@ -3468,9 +3493,7 @@ class Select(_SelectBaseMixin, FromClause): self._having = None if prefixes: - self._prefixes = [_literal_as_text(p) for p in prefixes] - else: - self._prefixes = [] + self._prefixes = tuple([_literal_as_text(p) for p in prefixes]) _SelectBaseMixin.__init__(self, **kwargs) @@ -3624,7 +3647,7 @@ class Select(_SelectBaseMixin, FromClause): """ clause = _literal_as_text(clause) - self._prefixes = self._prefixes + [clause] + self._prefixes = self._prefixes + (clause,) @_generative def select_from(self, fromclause): @@ -3682,7 +3705,7 @@ class Select(_SelectBaseMixin, FromClause): """ clause = _literal_as_text(clause) - self._prefixes = self._prefixes.union([clause]) + self._prefixes = self._prefixes + (clause,) def append_whereclause(self, whereclause): """append the given expression to this select() construct's WHERE criterion. @@ -3803,12 +3826,11 @@ class Select(_SelectBaseMixin, FromClause): self._bind = bind bind = property(bind, _set_bind) -class _UpdateBase(ClauseElement): +class _UpdateBase(_Executable, ClauseElement): """Form the base for ``INSERT``, ``UPDATE``, and ``DELETE`` statements.""" __visit_name__ = 'update_base' - supports_execution = True _autocommit = True def _generate(self): @@ -3924,7 +3946,9 @@ class Insert(_ValuesBase): """ __visit_name__ = 'insert' - + + _prefixes = () + def __init__(self, table, values=None, @@ -3939,9 +3963,7 @@ class Insert(_ValuesBase): self.inline = inline self._returning = returning if prefixes: - self._prefixes = [_literal_as_text(p) for p in prefixes] - else: - self._prefixes = [] + self._prefixes = tuple([_literal_as_text(p) for p in prefixes]) self.kwargs = self._process_deprecated_kw(kwargs) @@ -3964,7 +3986,7 @@ class Insert(_ValuesBase): """ clause = _literal_as_text(clause) - self._prefixes = self._prefixes + [clause] + self._prefixes = self._prefixes + (clause,) class Update(_ValuesBase): """Represent an Update construct. @@ -4061,9 +4083,8 @@ class Delete(_UpdateBase): # TODO: coverage self._whereclause = clone(self._whereclause) -class _IdentifiedClause(ClauseElement): +class _IdentifiedClause(_Executable, ClauseElement): __visit_name__ = 'identified' - supports_execution = True _autocommit = False quote = None |