summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/engine
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2017-03-14 12:00:56 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2017-03-14 17:01:07 -0400
commitf3b6f4f8da5223fae0a1dd948d4266b2e49e317c (patch)
tree9cae69a0b1680161a5e6604371a17b5766c3dc34 /lib/sqlalchemy/engine
parent596e322543df6ff380243c9cb0cf9997252329f6 (diff)
downloadsqlalchemy-f3b6f4f8da5223fae0a1dd948d4266b2e49e317c.tar.gz
Add "empty in" strategies; default to "static"
The longstanding behavior of the :meth:`.Operators.in_` and :meth:`.Operators.not_in_` operators emitting a warning when the right-hand condition is an empty sequence has been revised; a new flag :paramref:`.create_engine.empty_in_strategy` allows an empty "IN" expression to generate a simple boolean expression, or to invoke the previous behavior of dis-equating the expression to itself, with or without a warning. The default behavior is now to emit the simple boolean expression, allowing an empty IN to be evaulated without any performance penalty. Change-Id: I65cc37f2d7cf65a59bf217136c42fee446929352 Fixes: #3907
Diffstat (limited to 'lib/sqlalchemy/engine')
-rw-r--r--lib/sqlalchemy/engine/__init__.py18
-rw-r--r--lib/sqlalchemy/engine/default.py12
2 files changed, 30 insertions, 0 deletions
diff --git a/lib/sqlalchemy/engine/__init__.py b/lib/sqlalchemy/engine/__init__.py
index 2a6c68d66..bd8b7e68a 100644
--- a/lib/sqlalchemy/engine/__init__.py
+++ b/lib/sqlalchemy/engine/__init__.py
@@ -192,6 +192,24 @@ def create_engine(*args, **kwargs):
:ref:`dbengine_logging` for information on how to configure logging
directly.
+ :param empty_in_strategy: The SQL compilation strategy to use when
+ rendering an IN or NOT IN expression for :meth:`.ColumnOperators.in_`
+ where the right-hand side
+ is an empty set. This is a string value that may be one of
+ ``static``, ``dynamic``, or ``dynamic_warn``. The ``static``
+ strategy is the default, and an IN comparison to an empty set
+ will generate a simple false expression "1 != 1". The ``dynamic``
+ strategy behaves like that of SQLAlchemy 1.1 and earlier, emitting
+ a false expression of the form "expr != expr", which has the effect
+ of evaluting to NULL in the case of a null expression.
+ ``dynamic_warn`` is the same as ``dynamic``, however also emits a
+ warning when an empty set is encountered; this because the "dynamic"
+ comparison is typically poorly performing on most databases.
+
+ .. versionadded:: 1.2 Added the ``empty_in_strategy`` setting and
+ additionally defaulted the behavior for empty-set IN comparisons
+ to a static boolean expression.
+
:param encoding: Defaults to ``utf-8``. This is the string
encoding used by SQLAlchemy for string encode/decode
operations which occur within SQLAlchemy, **outside of
diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py
index 18c3276f8..b8c2d2845 100644
--- a/lib/sqlalchemy/engine/default.py
+++ b/lib/sqlalchemy/engine/default.py
@@ -178,6 +178,7 @@ class DefaultDialect(interfaces.Dialect):
supports_right_nested_joins=None,
case_sensitive=True,
supports_native_boolean=None,
+ empty_in_strategy='static',
label_length=None, **kwargs):
if not getattr(self, 'ported_sqla_06', True):
@@ -207,6 +208,17 @@ class DefaultDialect(interfaces.Dialect):
self.supports_native_boolean = supports_native_boolean
self.case_sensitive = case_sensitive
+ self.empty_in_strategy = empty_in_strategy
+ if empty_in_strategy == 'static':
+ self._use_static_in = True
+ elif empty_in_strategy in ('dynamic', 'dynamic_warn'):
+ self._use_static_in = False
+ self._warn_on_empty_in = empty_in_strategy == 'dynamic_warn'
+ else:
+ raise exc.ArgumentError(
+ "empty_in_strategy may be 'static', "
+ "'dynamic', or 'dynamic_warn'")
+
if label_length and label_length > self.max_identifier_length:
raise exc.ArgumentError(
"Label length of %d is greater than this dialect's"