summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql/elements.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2019-12-09 18:05:00 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2019-12-22 11:31:13 -0500
commit60e7034a7423955cd89d5624f8769d3804ca6d82 (patch)
tree027fd963fc073970b9ab62ae7f389e61192b1992 /lib/sqlalchemy/sql/elements.py
parentc6554ac52bfb7ce9ecd30ec777ce90adfe7861d2 (diff)
downloadsqlalchemy-60e7034a7423955cd89d5624f8769d3804ca6d82.tar.gz
Use expanding IN for all literal value IN expressions
The "expanding IN" feature, which generates IN expressions at query execution time which are based on the particular parameters associated with the statement execution, is now used for all IN expressions made against lists of literal values. This allows IN expressions to be fully cacheable independently of the list of values being passed, and also includes support for empty lists. For any scenario where the IN expression contains non-literal SQL expressions, the old behavior of pre-rendering for each position in the IN is maintained. The change also completes support for expanding IN with tuples, where previously type-specific bind processors weren't taking effect. As part of this change, a more explicit separation between "literal execute" and "post compile" bound parameters is being made; as the "ansi bind rules" feature is rendering bound parameters inline, as we now support "postcompile" generically, these should be used here, however we have to render literal values at execution time even for "expanding" parameters. new test fixtures etc. are added to assert everything goes to the right place. Fixes: #4645 Change-Id: Iaa2b7bfbfaaf5b80799ee17c9b8507293cba6ed1
Diffstat (limited to 'lib/sqlalchemy/sql/elements.py')
-rw-r--r--lib/sqlalchemy/sql/elements.py44
1 files changed, 27 insertions, 17 deletions
diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py
index 464c2a4d6..7d857d4fe 100644
--- a/lib/sqlalchemy/sql/elements.py
+++ b/lib/sqlalchemy/sql/elements.py
@@ -759,7 +759,7 @@ class ColumnElement(
def reverse_operate(self, op, other, **kwargs):
return op(other, self.comparator, **kwargs)
- def _bind_param(self, operator, obj, type_=None):
+ def _bind_param(self, operator, obj, type_=None, expanding=False):
return BindParameter(
None,
obj,
@@ -767,6 +767,7 @@ class ColumnElement(
type_=type_,
_compared_to_type=self.type,
unique=True,
+ expanding=expanding,
)
@property
@@ -1281,7 +1282,6 @@ class BindParameter(roles.InElementRole, ColumnElement):
self.required = required
self.expanding = expanding
self.literal_execute = literal_execute
-
if type_ is None:
if _compared_to_type is not None:
self.type = _compared_to_type.coerce_compared_value(
@@ -2282,20 +2282,29 @@ class Tuple(ClauseList, ColumnElement):
def _select_iterable(self):
return (self,)
- def _bind_param(self, operator, obj, type_=None):
- return Tuple(
- *[
- BindParameter(
- None,
- o,
- _compared_to_operator=operator,
- _compared_to_type=compared_to_type,
- unique=True,
- type_=type_,
- )
- for o, compared_to_type in zip(obj, self._type_tuple)
- ]
- ).self_group()
+ def _bind_param(self, operator, obj, type_=None, expanding=False):
+ if expanding:
+ return BindParameter(
+ None,
+ value=obj,
+ _compared_to_operator=operator,
+ unique=True,
+ expanding=True,
+ )._with_expanding_in_types(self._type_tuple)
+ else:
+ return Tuple(
+ *[
+ BindParameter(
+ None,
+ o,
+ _compared_to_operator=operator,
+ _compared_to_type=compared_to_type,
+ unique=True,
+ type_=type_,
+ )
+ for o, compared_to_type in zip(obj, self._type_tuple)
+ ]
+ ).self_group()
class Case(ColumnElement):
@@ -4240,7 +4249,7 @@ class ColumnClause(
else:
return name
- def _bind_param(self, operator, obj, type_=None):
+ def _bind_param(self, operator, obj, type_=None, expanding=False):
return BindParameter(
self.key,
obj,
@@ -4248,6 +4257,7 @@ class ColumnClause(
_compared_to_type=self.type,
type_=type_,
unique=True,
+ expanding=expanding,
)
def _make_proxy(