diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2008-04-03 16:34:03 +0000 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2008-04-03 16:34:03 +0000 |
commit | abb10856dcea07ca4d38d28df4e493d11d8fd345 (patch) | |
tree | 3936f0a7a9ddf7560928b6e21c4fd4a8669c337a /lib/sqlalchemy/sql/expression.py | |
parent | a27d6be28a0beb35da2e3eb1dfed7ab7460d7654 (diff) | |
download | sqlalchemy-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.py | 47 |
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: |