diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2018-08-15 17:11:14 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2018-08-15 17:15:24 -0400 |
| commit | 462ccd9ff18d2e428b20ec3f596391a275472140 (patch) | |
| tree | 45367cbdecf3f3d7928d43dcf556a9703bc55a4a /lib/sqlalchemy/sql/elements.py | |
| parent | dfa47b454a1d873b5746263f638d757c70edd3e1 (diff) | |
| download | sqlalchemy-462ccd9ff18d2e428b20ec3f596391a275472140.tar.gz | |
Add concept of "implicit boolean", treat as native
Fixed issue that is closely related to :ticket:`3639` where an expression
rendered in a boolean context on a non-native boolean backend would
be compared to 1/0 even though it is already an implcitly boolean
expression, when :meth:`.ColumnElement.self_group` were used. While this
does not affect the user-friendly backends (MySQL, SQLite) it was not
handled by Oracle (and possibly SQL Server). Whether or not the
expression is implicitly boolean on any database is now determined
up front as an additional check to not generate the integer comparison
within the compliation of the statement.
Fixes: #4320
Change-Id: Iae0a65e5c01bd576e64733c3651e1e1a1a1b240c
Diffstat (limited to 'lib/sqlalchemy/sql/elements.py')
| -rw-r--r-- | lib/sqlalchemy/sql/elements.py | 21 |
1 files changed, 21 insertions, 0 deletions
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 |
