summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-02-12 19:54:49 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2010-02-12 19:54:49 +0000
commitd0d5f792404126f2f3f62cb850e6b887c246178e (patch)
tree05d7718d9500c6bcd43e6f74b9365e895f609191 /lib/sqlalchemy/sql
parent85d335b01bf64a27e99cee915205afd99e7191b5 (diff)
downloadsqlalchemy-d0d5f792404126f2f3f62cb850e6b887c246178e.tar.gz
- Made sqlalchemy.sql.expressions.Executable part of public
API, used for any expression construct that can be sent to execute(). FunctionElement now inherits Executable so that it gains execution_options(), which are also propagated to the select() that's generated within execute(). Executable in turn subclasses _Generative which marks any ClauseElement that supports the @_generative decorator - these may also become "public" for the benefit of the compiler extension at some point.
Diffstat (limited to 'lib/sqlalchemy/sql')
-rw-r--r--lib/sqlalchemy/sql/expression.py54
1 files changed, 32 insertions, 22 deletions
diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py
index 1ae706999..0f55ac097 100644
--- a/lib/sqlalchemy/sql/expression.py
+++ b/lib/sqlalchemy/sql/expression.py
@@ -2208,7 +2208,20 @@ class _TypeClause(ClauseElement):
def __init__(self, type):
self.type = type
-class _Executable(object):
+
+class _Generative(object):
+ """Allow a ClauseElement to generate itself via the
+ @_generative decorator.
+
+ """
+
+ def _generate(self):
+ s = self.__class__.__new__(self.__class__)
+ s.__dict__ = self.__dict__.copy()
+ return s
+
+
+class Executable(_Generative):
"""Mark a ClauseElement as supporting execution."""
supports_execution = True
@@ -2240,8 +2253,10 @@ class _Executable(object):
"""
self._execution_options = self._execution_options.union(kw)
+# legacy, some outside users may be calling this
+_Executable = Executable
-class _TextClause(_Executable, ClauseElement):
+class _TextClause(Executable, ClauseElement):
"""Represent a literal SQL text fragment.
Public constructor is the :func:`text()` function.
@@ -2251,7 +2266,7 @@ class _TextClause(_Executable, ClauseElement):
__visit_name__ = 'textclause'
_bind_params_regex = re.compile(r'(?<![:\w\x5c]):(\w+)(?!:)', re.UNICODE)
- _execution_options = _Executable._execution_options.union({'autocommit':PARSE_AUTOCOMMIT})
+ _execution_options = Executable._execution_options.union({'autocommit':PARSE_AUTOCOMMIT})
@property
def _select_iterable(self):
@@ -2293,11 +2308,6 @@ class _TextClause(_Executable, ClauseElement):
else:
return None
- def _generate(self):
- s = self.__class__.__new__(self.__class__)
- s.__dict__ = self.__dict__.copy()
- return s
-
def _copy_internals(self, clone=_clone):
self.bindparams = dict((b.key, clone(b))
for b in self.bindparams.values())
@@ -2483,7 +2493,7 @@ class _Case(ColumnElement):
def _from_objects(self):
return list(itertools.chain(*[x._from_objects for x in self.get_children()]))
-class FunctionElement(ColumnElement, FromClause):
+class FunctionElement(Executable, ColumnElement, FromClause):
"""Base for SQL function-oriented constructs."""
def __init__(self, *clauses, **kwargs):
@@ -2514,13 +2524,16 @@ class FunctionElement(ColumnElement, FromClause):
util.reset_memoized(self, 'clauses')
def select(self):
- return select([self])
+ s = select([self])
+ if self._execution_options:
+ s = s.execution_options(**self._execution_options)
+ return s
def scalar(self):
- return select([self]).execute().scalar()
+ return self.select().execute().scalar()
def execute(self):
- return select([self]).execute()
+ return self.select().execute()
def _bind_param(self, obj):
return _BindParamClause(None, obj, _fallback_type=self.type, unique=True)
@@ -3243,7 +3256,7 @@ class TableClause(_Immutable, FromClause):
def _from_objects(self):
return [self]
-class _SelectBaseMixin(_Executable):
+class _SelectBaseMixin(Executable):
"""Base class for :class:`Select` and ``CompoundSelects``."""
def __init__(self,
@@ -3312,6 +3325,8 @@ class _SelectBaseMixin(_Executable):
self._execution_options = self._execution_options.union({'autocommit':True})
def _generate(self):
+ """Override the default _generate() method to also clear out exported collections."""
+
s = self.__class__.__new__(self.__class__)
s.__dict__ = self.__dict__.copy()
s._reset_exported()
@@ -3889,19 +3904,14 @@ class Select(_SelectBaseMixin, FromClause):
self._bind = bind
bind = property(bind, _set_bind)
-class _UpdateBase(_Executable, ClauseElement):
+class _UpdateBase(Executable, ClauseElement):
"""Form the base for ``INSERT``, ``UPDATE``, and ``DELETE`` statements."""
__visit_name__ = 'update_base'
- _execution_options = _Executable._execution_options.union({'autocommit':True})
+ _execution_options = Executable._execution_options.union({'autocommit':True})
kwargs = util.frozendict()
- def _generate(self):
- s = self.__class__.__new__(self.__class__)
- s.__dict__ = self.__dict__.copy()
- return s
-
def _process_colparams(self, parameters):
if isinstance(parameters, (list, tuple)):
pp = {}
@@ -4151,9 +4161,9 @@ class Delete(_UpdateBase):
# TODO: coverage
self._whereclause = clone(self._whereclause)
-class _IdentifiedClause(_Executable, ClauseElement):
+class _IdentifiedClause(Executable, ClauseElement):
__visit_name__ = 'identified'
- _execution_options = _Executable._execution_options.union({'autocommit':False})
+ _execution_options = Executable._execution_options.union({'autocommit':False})
quote = None
def __init__(self, ident):