summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql/operators.py
Commit message (Collapse)AuthorAgeFilesLines
* update flake8 noqa skips with proper syntaxFederico Caselli2022-04-111-1/+1
| | | | Change-Id: I42ed77f559e3ee5b8c600d98457ee37803ef0ea6
* pep-484 - SQL column operationsMike Bayer2022-03-151-157/+206
| | | | | | | | | note we are taking out the ColumnOperartors[SQLCoreOperations] thing; not really clear why that was needed and at the moment it seems I was likely confused. Change-Id: I834b75f9b44f91b97e29f2e1a7b1029bd910e0a1
* pep484 + abc bases for assocaitionproxyMike Bayer2022-03-011-9/+5
| | | | | | | | | | went to this one next as it was going to be hard, and also exercises the ORM expression hierarchy a bit. made some adjustments to SQLCoreOperations etc. Change-Id: Ie5dde9218dc1318252826b766d3e70b17dd24ea7 References: #6810 References: #7774
* pep-484 for sqlalchemy.event; use future annotationsMike Bayer2022-02-151-0/+2
| | | | | | | | | | __future__.annotations mode allows us to use non-string annotations for argument and return types in most cases, but more importantly it removes a large amount of runtime overhead that would be spent in evaluating the annotations. Change-Id: I2f5b6126fe0019713fc50001be3627b664019ede References: #6810
* Fix overlapping slots, base classes without slotsArie Bovenberg2022-02-011-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Some `__slots__` were not in order. Fixes #7527 ### Description I'm fixing two types of slots mistakes: - [x] remove overlapping slots (i.e. slots already defined on a base class) - [x] fix broken inheritance (i.e. slots class inheriting from a non-slots class) - [x] slots added to base class `TransactionalContext`. It seemed to use two attributes, which I've added as slots. - [x] empty slots removed from `ORMOption`. Its base class explicitly makes use of `__dict__` so empty slots don't add anything. - [x] empty slots added to `PostLoader`. It doesn't appear to use any slots not already defined on its base classes. - [x] empty slots added to `IterateMappersMixin`. It doesn't appear to use any slots not already defined on its subclasses. - [x] empty slots added to `ImmutableContainer`. It doesn't use any fields. - [x] empty slots added to `OperatorType`. It's a protocol. - [x] empty slots added to `InternalTraversal`, `_HasTraversalDispatch`. They don't seem to use attributes on their own. ### Checklist This pull request is: - [x] A short code fix - please include the issue number, and create an issue if none exists, which must include a complete example of the issue. one line code fixes without an issue and demonstration will not be accepted. - Please include: `Fixes: #<issue number>` in the commit message - please include tests. one line code fixes without tests will not be accepted. **Have a nice day!** Closes: #7589 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/7589 Pull-request-sha: 70a9c4d46916b7c6907eb1d3ad4f7033ec964191 Change-Id: I6c6e3e69c3c34d0f3bdda7f0684849834fdd1863
* initial reorganize for static typingMike Bayer2022-01-121-101/+250
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | start applying foundational annotations to key elements. two main elements addressed here: 1. removal of public_factory() and replacement with explicit functions. this just works much better with typing. 2. typing support for column expressions and operators. The biggest part of this involves stubbing out all the ColumnOperators methods under ColumnElement in a TYPE_CHECKING section. Took me a while to see this method vs. much more complicated things I thought I needed. Also for this version implementing #7519, ColumnElement types against the Python type and not TypeEngine. it is hoped this leads to easier transferrence between ORM/Core as well as eventual support for result set typing. Not clear yet how well this approach will work and what new issues it may introduce. given the current approach we now get full, rich typing for scenarios like this: from sqlalchemy import column, Integer, String, Boolean c1 = column('a', String) c2 = column('a', Integer) expr1 = c2.in_([1, 2, 3]) expr2 = c2 / 5 expr3 = -c2 expr4_a = ~(c2 == 5) expr4_b = ~column('q', Boolean) expr5 = c1 + 'x' expr6 = c2 + 10 Fixes: #7519 Fixes: #6810 Change-Id: I078d9f57955549f6f7868314287175f6c61c44cb
* happy new year 2022Mike Bayer2022-01-061-1/+1
| | | | Change-Id: I49abf2607e0eb0623650efdf0091b1fb3db737ea
* implement python_impl to custom_op for basic ORM evaluator extensibilityMike Bayer2022-01-041-5/+65
| | | | | | | | | | | | | | | Added new parameter :paramref:`_sql.Operators.op.python_impl`, available from :meth:`_sql.Operators.op` and also when using the :class:`_sql.Operators.custom_op` constructor directly, which allows an in-Python evaluation function to be provided along with the custom SQL operator. This evaluation function becomes the implementation used when the operator object is used given plain Python objects as operands on both sides, and in particular is compatible with the ``synchronize_session='evaluate'`` option used with :ref:`orm_expression_update_delete`. Fixes: #3162 Change-Id: If46ba6a0e303e2180a177ba418a8cafe9b42608e
* consider truediv as truediv; support floordiv operatorMike Bayer2021-12-261-1/+28
| | | | | | | | | | | | | | | | | | | | | Implemented full support for "truediv" and "floordiv" using the "/" and "//" operators. A "truediv" operation between two expressions using :class:`_types.Integer` now considers the result to be :class:`_types.Numeric`, and the dialect-level compilation will cast the right operand to a numeric type on a dialect-specific basis to ensure truediv is achieved. For floordiv, conversion is also added for those databases that don't already do floordiv by default (MySQL, Oracle) and the ``FLOOR()`` function is rendered in this case, as well as for cases where the right operand is not an integer (needed for PostgreSQL, others). The change resolves issues both with inconsistent behavior of the division operator on different backends and also fixes an issue where integer division on Oracle would fail to be able to fetch a result due to inappropriate outputtypehandlers. Fixes: #4926 Change-Id: Id54cc018c1fb7a49dd3ce1216d68d40f43fe2659
* Clean up most py3k compatFederico Caselli2021-11-241-1/+1
| | | | Change-Id: I8172fdcc3103ff92aa049827728484c8779af6b7
* Remove object in class definitionFederico Caselli2021-11-221-2/+2
| | | | | References: #4600 Change-Id: I2a62ddfe00bc562720f0eae700a497495d7a987a
* First round of removal of python 2Federico Caselli2021-11-011-25/+2
| | | | | References: #4600 Change-Id: I61e35bc93fe95610ae75b31c18a3282558cd4ffe
* repair any_() / all_() "implicit flip" behavior for NoneMike Bayer2021-10-041-29/+14
| | | | | | | | | | | | | | Fixed an inconsistency in the any_() / all_() functions / methods where the special behavior these functions have of "flipping" the expression such that the "ANY" / "ALL" expression is always on the right side would not function if the comparison were against the None value, that is, "column.any_() == None" should produce the same SQL expression as "null() == column.any_()". Added more docs to clarify this as well, plus mentions that any_() / all_() generally supersede the ARRAY version "any()" / "all()". Fixes: #7140 Change-Id: Ia5d55414ba40eb3fbda3598931fdd24c9b4a4411
* Replace all http:// links to https://Federico Caselli2021-07-041-2/+2
| | | | | | Also replace http://pypi.python.org/pypi with https://pypi.org/project Change-Id: I84b5005c39969a82140706472989f2a30b0c7685
* Implement MySQL-specific MATCHAnton Kovalevich2021-06-211-0/+6
| | | | | | | | | | | | | Added new construct :class:`_mysql.match`, which provides for the full range of MySQL's MATCH operator including multiple column support and modifiers. Pull request courtesy Anton Kovalevich. Fixes: #6132 Closes: #6133 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/6133 Pull-request-sha: dc6842f13688849a848e2ecbb81600e6edf8b3a9 Change-Id: I66bbfd7947aa2e43a031772e9b5ae238d94e5223
* Fix many spell glitches in docstrings and commentsLele Gaifax2021-01-241-1/+1
| | | | | | | | | | These were revealed by running `pylint --disable all --enable spelling --spelling-dict en_US` over all sources. Closes: #5868 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/5868 Pull-request-sha: bb249195d92e3b806e81ecf1192d5a1b3cd5db48 Change-Id: I96080ec93a9fbd20ce21e9e16265b3c77f22bb14
* happy new yearMike Bayer2021-01-041-1/+1
| | | | Change-Id: Ic5bb19ca8be3cb47c95a0d3315d84cb484bac47c
* Apply underscore naming to several more operatorsjonathan vanasco2020-10-301-40/+124
| | | | | | | | | | | | | | | | | | | | | | | | | | The operator changes are: * `isfalse` is now `is_false` * `isnot_distinct_from` is now `is_not_distinct_from` * `istrue` is now `is_true` * `notbetween` is now `not_between` * `notcontains` is now `not_contains` * `notendswith` is now `not_endswith` * `notilike` is now `not_ilike` * `notlike` is now `not_like` * `notmatch` is now `not_match` * `notstartswith` is now `not_startswith` * `nullsfirst` is now `nulls_first` * `nullslast` is now `nulls_last` Because these are core operators, the internal migration strategy for this change is to support legacy terms for an extended period of time -- if not indefinitely -- but update all documentation, tutorials, and internal usage to the new terms. The new terms are used to define the functions, and the legacy terms have been deprecated into aliases of the new terms. Fixes: #5435 Change-Id: Ifbd7cb1cdda5981990243c4fc4b4ff467dc132ac
* Rename Core expression isnot, not_in_jonathan vanasco2020-09-141-12/+35
| | | | | | | | | | | | | | | | | | | Several operators are renamed to achieve more consistent naming across SQLAlchemy. The operator changes are: * `isnot` is now `is_not` * `not_in_` is now `not_in` Because these are core operators, the internal migration strategy for this change is to support legacy terms for an extended period of time -- if not indefinitely -- but update all documentation, tutorials, and internal usage to the new terms. The new terms are used to define the functions, and the legacy terms have been deprecated into aliases of the new terms. Fixes: #5429 Change-Id: Ia1e66e7a50ac35d3f6260d8bf6ba3ce8087cbad2
* Update select usage to use the new 1.4 formatFederico Caselli2020-09-081-8/+8
| | | | | | | | | | | | | | | | This change includes mainly that the bracketed use within select() is moved to positional, and keyword arguments are removed from calls to the select() function. it does not yet fully address other issues such as keyword arguments passed to the table.select(). Additionally, allows False / None to both be considered as "disable" for all of select.correlate(), select.correlate_except(), query.correlate(), which establishes consistency with passing of ``False`` for the legact select(correlate=False) argument. Change-Id: Ie6c6e6abfbd3d75d4c8de504c0cf0159e6999108
* Add support for regular expression on supported backend.Federico Caselli2020-08-271-1/+108
| | | | | | | | | | | | Two operations have been defined: * :meth:`~.ColumnOperators.regexp_match` implementing a regular expression match like function. * :meth:`~.ColumnOperators.regexp_replace` implementing a regular expression string replace function. Fixes: #1390 Change-Id: I44556846e4668ccf329023613bd26861d5c674e6
* Fix typosKarthikeyan Singaravelan2020-08-091-1/+1
|
* Convert remaining ORM APIs to support 2.0 styleMike Bayer2020-07-111-32/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is kind of a mixed bag of all kinds to help get us to 1.4 betas. The documentation stuff is a work in progress. Lots of other relatively small changes to APIs and things. More commits will follow to continue improving the documentation and transitioning to the 1.4/2.0 hybrid documentation. In particular some refinements to Session usage models so that it can match Engine's scoping / transactional patterns, and a decision to start moving away from "subtransactions" completely. * add select().from_statement() to produce FromStatement in an ORM context * begin referring to select() that has "plugins" for the few edge cases where select() will have ORM-only behaviors * convert dynamic.AppenderQuery to its own object that can use select(), though at the moment it uses Query to support legacy join calling forms. * custom query classes for AppenderQuery are replaced by do_orm_execute() hooks for custom actions, a separate gerrit will document this * add Session.get() to replace query.get() * Deprecate session.begin->subtransaction. propose within the test suite a hypothetical recipe for apps that rely on this pattern * introduce Session construction level context manager, sessionmaker context manager, rewrite the whole top of the session_transaction.rst documentation. Establish context manager patterns for Session that are identical to engine * ensure same begin_nested() / commit() behavior as engine * devise all new "join into an external transaction" recipe, add test support for it, add rules into Session so it just works, write new docs. need to ensure this doesn't break anything * vastly reduce the verbosity of lots of session docs as I dont think people read this stuff and it's difficult to keep current in any case * constructs like case(), with_only_columns() really need to move to *columns, add a coercion rule to just change these. * docs need changes everywhere I look. in_() is not in the Core tutorial? how do people even know about it? Remove tons of cruft from Select docs, etc. * build a system for common ORM options like populate_existing and autoflush to populate from execution options. * others? Change-Id: Ia4bea0f804250e54d90b3884cf8aab8b66b82ecf
* Fix a wide variety of typos and broken linksaplatkouski2020-06-251-4/+4
| | | | | | | | | | | | Note the PR has a few remaining doc linking issues listed in the comment that must be addressed separately. Signed-off-by: aplatkouski <5857672+aplatkouski@users.noreply.github.com> Closes: #5371 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/5371 Pull-request-sha: 7e7d233cf3a0c66980c27db0fcdb3c7d93bc2510 Change-Id: I9c36e8d8804483950db4b42c38ee456e384c59e3
* Set up absolute references for create_engine and relatedMike Bayer2020-04-141-1/+1
| | | | | | | includes more replacements for create_engine(), Connection, disambiguation of Result from future/baked Change-Id: Icb60a79ee7a6c45ea9056c211ffd1be110da3b5e
* Run search and replace of symbolic module namesMike Bayer2020-04-141-22/+22
| | | | | | | | Replaces a wide array of Sphinx-relative doc references with an abbreviated absolute form now supported by zzzeeksphinx. Change-Id: I94bffcc3f37885ffdde6238767224296339698a2
* Correct ambiguous func / class linksMike Bayer2020-03-251-4/+4
| | | | | | | | | :func:`.sql.expression.select`, :func:`.sql.expression.insert` and :class:`.sql.expression.Insert` were hitting many ambiguous symbol errors, due to future.select, as well as the PG/MySQL variants of Insert. Change-Id: Iac862bfc172a7f7f0cbba5353a83dc203bed376c
* happy new yearMike Bayer2020-01-011-1/+1
| | | | Change-Id: I08440dc25e40ea1ccea1778f6ee9e28a00808235
* Use expanding IN for all literal value IN expressionsMike Bayer2019-12-221-21/+7
| | | | | | | | | | | | | | | | | | | | | | | | 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
* Add note on the use of tuple_() for the IN operator in the docsStepland2019-09-161-0/+6
| | | | | | | | Closes: #4861 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/4861 Pull-request-sha: c7379d390752d0c10d6488872b163b06ee30d952 Change-Id: I223008f720fe64951e2a0bf95aab955ece22516b
* self_group() for FunctionFilterMike Bayer2019-07-121-0/+5
| | | | | | | | | Fixed issue where the :class:`.array_agg` construct in combination with :meth:`.FunctionElement.filter` would not produce the correct operator precedence between the FILTER keyword and the array index operator. Fixes: #4760 Change-Id: Ic662cd3da3330554ec673bafd80495b3f1506098
* Implement new ClauseElement role and coercion systemMike Bayer2019-05-181-2/+2
| | | | | | | | | | | | | | | | | | | | A major refactoring of all the functions handle all detection of Core argument types as well as perform coercions into a new class hierarchy based on "roles", each of which identify a syntactical location within a SQL statement. In contrast to the ClauseElement hierarchy that identifies "what" each object is syntactically, the SQLRole hierarchy identifies the "where does it go" of each object syntactically. From this we define a consistent type checking and coercion system that establishes well defined behviors. This is a breakout of the patch that is reorganizing select() constructs to no longer be in the FromClause hierarchy. Also includes a rename of as_scalar() into scalar_subquery(); deprecates automatic coercion to scalar_subquery(). Partially-fixes: #4617 Change-Id: I26f1e78898693c6b99ef7ea2f4e7dfd0e8e1a1bd
* Reimplement .compare() in terms of a visitorMike Bayer2019-04-291-0/+5
| | | | | | | | | | | | Reworked the :meth:`.ClauseElement.compare` methods in terms of a new visitor-based approach, and additionally added test coverage ensuring that all :class:`.ClauseElement` subclasses can be accurately compared against each other in terms of structure. Structural comparison capability is used to a small degree within the ORM currently, however it also may form the basis for new caching features. Fixes: #4336 Change-Id: I581b667d8e1642a6c27165cc9f4aded1c66effc6
* Fix many spell glitchesLele Gaifax2019-01-251-4/+4
| | | | | | | | | | | | This affects mostly docstrings, except in orm/events.py::dispose_collection() where one parameter gets renamed: given that the method is empty, it seemed reasonable to me to fix that too. Closes: #4440 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/4440 Pull-request-sha: 779ed75acb6142e1f1daac467b5b14134529bb4b Change-Id: Ic0553fe97853054b09c2453af76d96363de6eb0e
* Convert most "See also" phrases into .. seealso::Mike Bayer2019-01-151-5/+5
| | | | | Change-Id: Ie32598b895c1c5f5bce7c8e1573abbcfe9d434a8 (cherry picked from commit e81d3815abb36c52b0019dee6e4f67990e3d1c7d)
* Remove version directives for 0.6, 0.7, 0.8Mike Bayer2019-01-151-10/+0
| | | | | | | | | - fix a few "seealso"s - ComparableProprerty's "superseded in 0.7" becomes deprecated in 0.7 Backport to currently maintained doc versions 1.2, 1.1 Change-Id: Ib1fcb2df8673dbe5c4ffc47f3896a60d1dfcb4b2
* happy new yearMike Bayer2019-01-111-1/+1
| | | | Change-Id: I6a71f4924d046cf306961c58dffccf21e9c03911
* Post black reformattingMike Bayer2019-01-061-21/+20
| | | | | | | | | | | | | Applied on top of a pure run of black -l 79 in I7eda77fed3d8e73df84b3651fd6cfcfe858d4dc9, this set of changes resolves all remaining flake8 conditions for those codes we have enabled in setup.cfg. Included are resolutions for all remaining flake8 issues including shadowed builtins, long lines, import order, unused imports, duplicate imports, and docstring issues. Change-Id: I4f72d3ba1380dd601610ff80b8fb06a2aff8b0fe
* Run black -l 79 against all source filesMike Bayer2019-01-061-49/+60
| | | | | | | | | | | | | | This is a straight reformat run using black as is, with no edits applied at all. The black run will format code consistently, however in some cases that are prevalent in SQLAlchemy code it produces too-long lines. The too-long lines will be resolved in the following commit that will resolve all remaining flake8 issues including shadowed builtins, long lines, import order, unused imports, duplicate imports, and docstring issues. Change-Id: I7eda77fed3d8e73df84b3651fd6cfcfe858d4dc9
* document expanding bound parameters, in_(), and baked query use casesMike Bayer2018-08-271-12/+76
| | | | Change-Id: I09ccd73ebabbea4b5098ba5b170786ac065444c8
* Add concept of "implicit boolean", treat as nativeMike Bayer2018-08-151-0/+6
| | | | | | | | | | | | | | | 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
* Add all "like", "between", "is" operators as comparison operatorsMike Bayer2018-07-101-7/+36
| | | | | | | | | | | Added "like" based operators as "comparison" operators, including :meth:`.ColumnOperators.startswith` :meth:`.ColumnOperators.endswith` :meth:`.ColumnOperators.ilike` :meth:`.ColumnOperators.notilike` among many others, so that all of these operators can be the basis for an ORM "primaryjoin" condition. Change-Id: Idb13961f0c74462a139fc3444626e042f798ff08 Fixes: #4302
* support functions "as binary comparison"Mike Bayer2018-07-091-1/+7
| | | | | | | | | Added new feature :meth:`.FunctionElement.as_comparison` which allows a SQL function to act as a binary comparison operation that can work within the ORM. Change-Id: I07018e2065d09775c0406cabdd35fc38cc0da699 Fixes: #3831
* happy new yearMike Bayer2018-01-121-1/+1
| | | | Change-Id: I3ef36bfd0cb0ba62b3123c8cf92370a43156cf8f
* - call this 1.2.0Mike Bayer2017-12-261-3/+3
| | | | Change-Id: If8d60e5d44f387eba97fd9bb1dfa85947ce7f42f
* Rework autoescape to be a simple boolean; escape the escape characterMike Bayer2017-10-241-81/+247
| | | | | | | | | | | | Reworked the new "autoescape" feature introduced in :ref:`change_2694` in 1.2.0b2 to be fully automatic; the escape character now defaults to a forwards slash ``"/"`` and is applied to percent, underscore, as well as the escape character itself, for fully automatic escaping. The character can also be changed using the "escape" parameter. Change-Id: I74894a2576983c0f6eb89480c9e5727f49fa9c25 Fixes: #2694
* Support method form of any_(), all_()Mike Bayer2017-09-271-0/+32
| | | | | | | | | | | | Fixed bug where the recently added :meth:`.ColumnOperators.any_` and :meth:`.ColumnOperators.all_` methods didn't work when called as methods, as opposed to using the standalone functions :func:`~.expression.any_` and :func:`~.expression.all_`. Also added documentation examples for these relatively unintuitive SQL operators. Change-Id: I3e56b463e9fd146a077b9970624f50cba27f9811 Fixes: #4093
* Ensure custom ops have consistent typing behavior, boolean supportMike Bayer2017-09-011-6/+46
| | | | | | | | | | | | | | Refined the behavior of :meth:`.Operators.op` such that in all cases, if the :paramref:`.Operators.op.is_comparison` flag is set to True, the return type of the resulting expression will be :class:`.Boolean`, and if the flag is False, the return type of the resulting expression will be the same type as that of the left-hand expression, which is the typical default behavior of other operators. Also added a new parameter :paramref:`.Operators.op.return_type` as well as a helper method :meth:`.Operators.bool_op`. Change-Id: Ifc8553cd4037d741b84b70a9702cbd530f1a9de0 Fixes: #4063
* Flatten operator precedence for comparison operatorsMichael Birtwell2017-05-251-12/+13
| | | | | | | | | | | | | | | The operator precedence for all comparison operators such as LIKE, IS, IN, MATCH, equals, greater than, less than, etc. has all been merged into one level, so that expressions which make use of these against each other will produce parentheses between them. This suits the stated operator precedence of databases like Oracle, MySQL and others which place all of these operators as equal precedence, as well as Postgresql as of 9.5 which has also flattened its operator precendence. Co-authored-by: Mike Bayer <mike_mp@zzzcomputing.com> Fixes: #3999 Change-Id: I3f3d5124a64af0d376361cdf15a97e2e703be56f Pull-request: https://github.com/zzzeek/sqlalchemy/pull/367
* Enforce boolean result type for all eq_, is_, isnot, comparisonMike Bayer2017-04-271-1/+2
| | | | | | | | | | | | Repaired issue where the type of an expression that used :meth:`.ColumnOperators.is_` or similar would not be a "boolean" type, instead the type would be "nulltype", as well as when using custom comparison operators against an untyped expression. This typing can impact how the expression behaves in larger contexts as well as in result-row-handling. Change-Id: Ib810ff686de500d8db26ae35a51005fab29603b6 Fixes: #3873