summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/sql')
-rw-r--r--lib/sqlalchemy/sql/compiler.py6
-rw-r--r--lib/sqlalchemy/sql/elements.py21
-rw-r--r--lib/sqlalchemy/sql/operators.py6
-rw-r--r--lib/sqlalchemy/sql/selectable.py1
4 files changed, 32 insertions, 2 deletions
diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py
index 5fbc7d87f..e45db428a 100644
--- a/lib/sqlalchemy/sql/compiler.py
+++ b/lib/sqlalchemy/sql/compiler.py
@@ -1019,13 +1019,15 @@ class SQLCompiler(Compiled):
"Unary expression has no operator or modifier")
def visit_istrue_unary_operator(self, element, operator, **kw):
- if self.dialect.supports_native_boolean:
+ if element._is_implicitly_boolean or \
+ self.dialect.supports_native_boolean:
return self.process(element.element, **kw)
else:
return "%s = 1" % self.process(element.element, **kw)
def visit_isfalse_unary_operator(self, element, operator, **kw):
- if self.dialect.supports_native_boolean:
+ if element._is_implicitly_boolean or \
+ self.dialect.supports_native_boolean:
return "NOT %s" % self.process(element.element, **kw)
else:
return "%s = 0" % self.process(element.element, **kw)
diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py
index 2e8c39f3b..2a6fa323c 100644
--- a/lib/sqlalchemy/sql/elements.py
+++ b/lib/sqlalchemy/sql/elements.py
@@ -641,6 +641,8 @@ class ColumnElement(operators.ColumnOperators, ClauseElement):
"""A flag that can be flipped to prevent a column from being resolvable
by string label name."""
+ _is_implicitly_boolean = False
+
_alt_names = ()
def self_group(self, against=None):
@@ -1229,6 +1231,7 @@ class TextClause(Executable, ClauseElement):
_execution_options = \
Executable._execution_options.union(
{'autocommit': PARSE_AUTOCOMMIT})
+ _is_implicitly_boolean = False
@property
def _select_iterable(self):
@@ -1813,6 +1816,7 @@ class ClauseList(ClauseElement):
self.clauses = [
text_converter(clause)
for clause in clauses]
+ self._is_implicitly_boolean = operators.is_boolean(self.operator)
def __iter__(self):
return iter(self.clauses)
@@ -1915,6 +1919,7 @@ class BooleanClauseList(ClauseList, ColumnElement):
self.operator = operator
self.group_contents = True
self.type = type_api.BOOLEANTYPE
+ self._is_implicitly_boolean = True
return self
@classmethod
@@ -2923,6 +2928,7 @@ class AsBoolean(UnaryExpression):
self.negate = negate
self.modifier = None
self.wraps_column_expression = True
+ self._is_implicitly_boolean = element._is_implicitly_boolean
def self_group(self, against=None):
return self
@@ -2950,6 +2956,12 @@ class BinaryExpression(ColumnElement):
__visit_name__ = 'binary'
+ _is_implicitly_boolean = True
+ """Indicates that any database will know this is a boolean expression
+ even if the database does not have an explicit boolean datatype.
+
+ """
+
def __init__(self, left, right, operator, type_=None,
negate=None, modifiers=None):
# allow compatibility with libraries that
@@ -2962,6 +2974,7 @@ class BinaryExpression(ColumnElement):
self.operator = operator
self.type = type_api.to_instance(type_)
self.negate = negate
+ self._is_implicitly_boolean = operators.is_boolean(operator)
if modifiers is None:
self.modifiers = {}
@@ -3066,6 +3079,10 @@ class Grouping(ColumnElement):
def self_group(self, against=None):
return self
+ @util.memoized_property
+ def _is_implicitly_boolean(self):
+ return self.element._is_implicitly_boolean
+
@property
def _key_label(self):
return self._label
@@ -3551,6 +3568,10 @@ class Label(ColumnElement):
return self.__class__, (self.name, self._element, self._type)
@util.memoized_property
+ def _is_implicitly_boolean(self):
+ return self.element._is_implicitly_boolean
+
+ @util.memoized_property
def _allow_label_resolve(self):
return self.element._allow_label_resolve
diff --git a/lib/sqlalchemy/sql/operators.py b/lib/sqlalchemy/sql/operators.py
index fd65979c5..a9f4e3e3e 100644
--- a/lib/sqlalchemy/sql/operators.py
+++ b/lib/sqlalchemy/sql/operators.py
@@ -1315,6 +1315,12 @@ def is_natural_self_precedent(op):
return op in _natural_self_precedent or \
isinstance(op, custom_op) and op.natural_self_precedent
+_booleans = (inv, istrue, isfalse, and_, or_)
+
+
+def is_boolean(op):
+ return is_comparison(op) or op in _booleans
+
_mirror = {
gt: lt,
ge: le,
diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py
index 04f6c086d..5b665829b 100644
--- a/lib/sqlalchemy/sql/selectable.py
+++ b/lib/sqlalchemy/sql/selectable.py
@@ -3576,6 +3576,7 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect):
class ScalarSelect(Generative, Grouping):
_from_objects = []
_is_from_container = True
+ _is_implicitly_boolean = False
def __init__(self, element):
self.element = element