summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql/expression.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2008-04-03 16:34:03 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2008-04-03 16:34:03 +0000
commitabb10856dcea07ca4d38d28df4e493d11d8fd345 (patch)
tree3936f0a7a9ddf7560928b6e21c4fd4a8669c337a /lib/sqlalchemy/sql/expression.py
parenta27d6be28a0beb35da2e3eb1dfed7ab7460d7654 (diff)
downloadsqlalchemy-abb10856dcea07ca4d38d28df4e493d11d8fd345.tar.gz
- case() interprets the "THEN" expressions
as values by default, meaning case([(x==y, "foo")]) will interpret "foo" as a bound value, not a SQL expression. use text(expr) for literal SQL expressions in this case. For the criterion itself, these may be literal strings only if the "value" keyword is present, otherwise SA will force explicit usage of either text() or literal().
Diffstat (limited to 'lib/sqlalchemy/sql/expression.py')
-rw-r--r--lib/sqlalchemy/sql/expression.py47
1 files changed, 38 insertions, 9 deletions
diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py
index cc97227a7..39a2ae3eb 100644
--- a/lib/sqlalchemy/sql/expression.py
+++ b/lib/sqlalchemy/sql/expression.py
@@ -392,7 +392,7 @@ def not_(clause):
result.
"""
- return operators.inv(clause)
+ return operators.inv(_literal_as_binds(clause))
def distinct(expr):
"""Return a ``DISTINCT`` clause."""
@@ -416,24 +416,45 @@ def case(whens, value=None, else_=None):
"""Produce a ``CASE`` statement.
whens
- A sequence of pairs or a dict to be translated into "when / then" clauses.
+ A sequence of pairs, or alternatively a dict,
+ to be translated into "WHEN / THEN" clauses.
value
- Optional for simple case statements.
+ Optional for simple case statements, produces
+ a column expression as in "CASE <expr> WHEN ..."
else\_
- Optional as well, for case defaults.
+ Optional as well, for case defaults produces
+ the "ELSE" portion of the "CASE" statement.
+
+ The expressions used for THEN and ELSE,
+ when specified as strings, will be interpreted
+ as bound values. To specify textual SQL expressions
+ for these, use the text(<string>) construct.
+
+ The expressions used for the WHEN criterion
+ may only be literal strings when "value" is
+ present, i.e. CASE table.somecol WHEN "x" THEN "y".
+ Otherwise, literal strings are not accepted
+ in this position, and either the text(<string>)
+ or literal(<string>) constructs must be used to
+ interpret raw string values.
+
"""
-
try:
whens = util.dictlike_iteritems(whens)
except TypeError:
pass
-
- whenlist = [ClauseList('WHEN', c, 'THEN', r, operator=None)
+
+ if value:
+ crit_filter = _literal_as_binds
+ else:
+ crit_filter = _no_literals
+
+ whenlist = [ClauseList('WHEN', crit_filter(c), 'THEN', _literal_as_binds(r), operator=None)
for (c,r) in whens]
- if not else_ is None:
- whenlist.append(ClauseList('ELSE', else_, operator=None))
+ if else_ is not None:
+ whenlist.append(ClauseList('ELSE', _literal_as_binds(else_), operator=None))
if whenlist:
type = list(whenlist[-1])[-1].type
else:
@@ -842,6 +863,14 @@ def _literal_as_binds(element, name=None, type_=None):
else:
return element
+def _no_literals(element):
+ if isinstance(element, Operators):
+ return element.expression_element()
+ elif _is_literal(element):
+ raise exceptions.ArgumentError("Ambiguous literal: %r. Use the 'text()' function to indicate a SQL expression literal, or 'literal()' to indicate a bound value." % element)
+ else:
+ return element
+
def _corresponding_column_or_error(fromclause, column, require_embedded=False):
c = fromclause.corresponding_column(column, require_embedded=require_embedded)
if not c: