diff options
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r-- | lib/sqlalchemy/sql/coercions.py | 7 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/compiler.py | 22 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/elements.py | 19 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/lambdas.py | 2 |
4 files changed, 26 insertions, 24 deletions
diff --git a/lib/sqlalchemy/sql/coercions.py b/lib/sqlalchemy/sql/coercions.py index 820fc1bf1..517bfd57d 100644 --- a/lib/sqlalchemy/sql/coercions.py +++ b/lib/sqlalchemy/sql/coercions.py @@ -561,9 +561,10 @@ class InElementImpl(RoleImpl): return element.self_group(against=operator) elif isinstance(element, elements.BindParameter): - # previously we were adding expanding flags here but - # we now do this in the compiler where we have more context - # see compiler.py -> _render_in_expr_w_bindparam + element = element._clone(maintain_key=True) + element.expanding = True + element.expand_op = operator + return element else: return element diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index dedd75f5c..734e65492 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -1904,32 +1904,14 @@ class SQLCompiler(Compiled): binary, override_operator=operators.match_op ) - def visit_in_op_binary(self, binary, operator, **kw): - return self._render_in_expr_w_bindparam(binary, operator, **kw) - def visit_not_in_op_binary(self, binary, operator, **kw): # The brackets are required in the NOT IN operation because the empty # case is handled using the form "(col NOT IN (null) OR 1 = 1)". # The presence of the OR makes the brackets required. - return "(%s)" % self._render_in_expr_w_bindparam( - binary, operator, **kw + return "(%s)" % self._generate_generic_binary( + binary, OPERATORS[operator], **kw ) - def _render_in_expr_w_bindparam(self, binary, operator, **kw): - opstring = OPERATORS[operator] - - if isinstance(binary.right, elements.BindParameter): - if not binary.right.expanding or not binary.right.expand_op: - # note that by cloning here, we rely upon the - # _cache_key_bind_match dictionary to resolve - # clones of bindparam() objects to the ones that are - # present in our cache key. - binary.right = binary.right._clone(maintain_key=True) - binary.right.expanding = True - binary.right.expand_op = operator - - return self._generate_generic_binary(binary, opstring, **kw) - def visit_empty_set_op_expr(self, type_, expand_op): if expand_op is operators.not_in_op: if len(type_) > 1: diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py index 416a4e82e..cdb1dbca8 100644 --- a/lib/sqlalchemy/sql/elements.py +++ b/lib/sqlalchemy/sql/elements.py @@ -256,6 +256,15 @@ class ClauseElement( return c + def _negate_in_binary(self, negated_op, original_op): + """a hook to allow the right side of a binary expression to respond + to a negation of the binary expression. + + Used for the special case of expanding bind parameter with IN. + + """ + return self + def _with_binary_element_type(self, type_): """in the context of binary expression, convert the type of this object to the one given. @@ -1510,6 +1519,14 @@ class BindParameter(roles.InElementRole, ColumnElement): literal_execute=True, ) + def _negate_in_binary(self, negated_op, original_op): + if self.expand_op is original_op: + bind = self._clone() + bind.expand_op = negated_op + return bind + else: + return self + def _with_binary_element_type(self, type_): c = ClauseElement._clone(self) c.type = type_ @@ -3729,7 +3746,7 @@ class BinaryExpression(ColumnElement): if self.negate is not None: return BinaryExpression( self.left, - self.right, + self.right._negate_in_binary(self.negate, self.operator), self.negate, negate=self.operator, type_=self.type, diff --git a/lib/sqlalchemy/sql/lambdas.py b/lib/sqlalchemy/sql/lambdas.py index ddc4774db..b3f47252a 100644 --- a/lib/sqlalchemy/sql/lambdas.py +++ b/lib/sqlalchemy/sql/lambdas.py @@ -270,6 +270,8 @@ class LambdaElement(elements.ClauseElement): bind = bindparam_lookup[thing.key] if thing.expanding: bind.expanding = True + bind.expand_op = thing.expand_op + bind.type = thing.type return bind if self._rec.is_sequence: |