summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/sql')
-rw-r--r--lib/sqlalchemy/sql/expression.py72
1 files changed, 37 insertions, 35 deletions
diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py
index f59ed7afd..e9786cbe1 100644
--- a/lib/sqlalchemy/sql/expression.py
+++ b/lib/sqlalchemy/sql/expression.py
@@ -26,7 +26,8 @@ to stay the same in future releases.
"""
-import itertools, re
+import itertools
+import re
from operator import attrgetter
from .. import util, exc, inspection
@@ -1403,8 +1404,12 @@ def _labeled(element):
# there is some inconsistency here between the usage of
# inspect() vs. checking for Visitable and __clause_element__.
# Ideally all functions here would derive from inspect(),
-# this is a work in progress. In some cases performance is a concern
-# also.
+# however the inspect() versions add significant callcount
+# overhead for critical functions like _interpret_as_column_or_from().
+# Generally, the column-based functions are more performance critical
+# and are fine just checking for __clause_element__(). it's only
+# _interpret_as_from() where we'd like to be able to receive ORM entities
+# that have no defined namespace, hence inspect() is needed there.
def _column_as_key(element):
if isinstance(element, basestring):
@@ -1445,9 +1450,8 @@ def _no_literals(element):
return element
def _is_literal(element):
- insp = inspection.inspect(element, raiseerr=False)
-
- return insp is None and not isinstance(element, Visitable)
+ return not isinstance(element, Visitable) and \
+ not hasattr(element, '__clause_element__')
def _only_column_elements_or_none(element, name):
if element is None:
@@ -1456,51 +1460,49 @@ def _only_column_elements_or_none(element, name):
return _only_column_elements(element, name)
def _only_column_elements(element, name):
- insp = inspection.inspect(element, raiseerr=False)
- if insp is None or \
- not hasattr(insp, "expression") or \
- not isinstance(insp.expression, ColumnElement):
+ if hasattr(element, '__clause_element__'):
+ element = element.__clause_element__()
+ if not isinstance(element, ColumnElement):
raise exc.ArgumentError(
"Column-based expression object expected for argument "
"'%s'; got: '%s', type %s" % (name, element, type(element)))
- return insp.expression
+ return element
+
def _literal_as_binds(element, name=None, type_=None):
- insp = inspection.inspect(element, raiseerr=False)
- if insp is None:
+ if hasattr(element, '__clause_element__'):
+ return element.__clause_element__()
+ elif not isinstance(element, Visitable):
if element is None:
- return _const_expr(element)
+ return null()
else:
- return BindParameter(name, element, type_=type_, unique=True)
- elif insp.is_clause_element:
- return insp
+ return _BindParamClause(name, element, type_=type_, unique=True)
else:
- return insp.expression
+ return element
+def _interpret_as_column_or_from(element):
+ if isinstance(element, Visitable):
+ return element
+ elif hasattr(element, '__clause_element__'):
+ return element.__clause_element__()
-def _interpret_as_from(element):
insp = inspection.inspect(element, raiseerr=False)
if insp is None:
if isinstance(element, (util.NoneType, bool)):
return _const_expr(element)
- elif isinstance(element, basestring):
- return TextClause(unicode(element))
elif hasattr(insp, "selectable"):
return insp.selectable
- else:
- raise exc.ArgumentError("FROM expression expected")
-def _literal_as_column(element):
- insp = inspection.inspect(element, raiseerr=False)
- if insp is not None:
- if hasattr(insp, "expression"):
- return insp.expression
- elif hasattr(insp, "selectable"):
- return insp.selectable
- elif insp.is_clause_element:
- return insp
return literal_column(str(element))
+def _interpret_as_from(element):
+ insp = inspection.inspect(element, raiseerr=False)
+ if insp is None:
+ if isinstance(element, basestring):
+ return TextClause(unicode(element))
+ elif hasattr(insp, "selectable"):
+ return insp.selectable
+ raise exc.ArgumentError("FROM expression expected")
def _const_expr(element):
if element is None:
@@ -4911,7 +4913,7 @@ class Select(SelectBase):
if cols_present:
self._raw_columns = []
for c in columns:
- c = _literal_as_column(c)
+ c = _interpret_as_column_or_from(c)
if isinstance(c, ScalarSelect):
c = c.self_group(against=operators.comma_op)
self._raw_columns.append(c)
@@ -5238,7 +5240,7 @@ class Select(SelectBase):
self._reset_exported()
rc = []
for c in columns:
- c = _literal_as_column(c)
+ c = _interpret_as_column_or_from(c)
if isinstance(c, ScalarSelect):
c = c.self_group(against=operators.comma_op)
rc.append(c)
@@ -5382,7 +5384,7 @@ class Select(SelectBase):
"""
self._reset_exported()
- column = _literal_as_column(column)
+ column = _interpret_as_column_or_from(column)
if isinstance(column, ScalarSelect):
column = column.self_group(against=operators.comma_op)