codekingpro/portable-devtools
115k
1# sql/operators.py
2# Copyright (C) 2005-2026 the SQLAlchemy authors and contributors
3# <see AUTHORS file>
4#
5# This module is part of SQLAlchemy and is released under
6# the MIT License: https://www.opensource.org/licenses/mit-license.php
7
8# This module is part of SQLAlchemy and is released under
9# the MIT License: https://www.opensource.org/licenses/mit-license.php
10
11"""Defines operators used in SQL expressions."""
12
13from __future__ import annotations
14
15from enum import IntEnum
16from operator import add as _uncast_add
17from operator import and_ as _uncast_and_
18from operator import contains as _uncast_contains
19from operator import eq as _uncast_eq
20from operator import floordiv as _uncast_floordiv
21from operator import ge as _uncast_ge
22from operator import getitem as _uncast_getitem
23from operator import gt as _uncast_gt
24from operator import inv as _uncast_inv
25from operator import le as _uncast_le
26from operator import lshift as _uncast_lshift
27from operator import lt as _uncast_lt
28from operator import mod as _uncast_mod
29from operator import mul as _uncast_mul
30from operator import ne as _uncast_ne
31from operator import neg as _uncast_neg
32from operator import or_ as _uncast_or_
33from operator import rshift as _uncast_rshift
34from operator import sub as _uncast_sub
35from operator import truediv as _uncast_truediv
36import typing
37from typing import Any
38from typing import Callable
39from typing import cast
40from typing import Dict
41from typing import Generic
42from typing import Optional
43from typing import overload
44from typing import Set
45from typing import Tuple
46from typing import Type
47from typing import TYPE_CHECKING
48from typing import TypeVar
49from typing import Union
50
51from .. import exc
52from .. import util
53from ..util.typing import Literal
54from ..util.typing import Protocol
55
56if typing.TYPE_CHECKING:
57 from ._typing import ColumnExpressionArgument
58 from .cache_key import CacheConst
59 from .elements import ColumnElement
60 from .type_api import TypeEngine
61
62_T = TypeVar("_T", bound=Any)
63_FN = TypeVar("_FN", bound=Callable[..., Any])
64
65
66class OperatorType(Protocol):
67 """describe an op() function."""
68
69 __slots__ = ()
70
71 __name__: str
72
73 @overload
74 def __call__(
75 self,
76 left: ColumnExpressionArgument[Any],
77 right: Optional[Any] = None,
78 *other: Any,
79 **kwargs: Any,
80 ) -> ColumnElement[Any]: ...
81
82 @overload
83 def __call__(
84 self,
85 left: Operators,
86 right: Optional[Any] = None,
87 *other: Any,
88 **kwargs: Any,
89 ) -> Operators: ...
90
91 def __call__(
92 self,
93 left: Any,
94 right: Optional[Any] = None,
95 *other: Any,
96 **kwargs: Any,
97 ) -> Operators: ...
98
99
100add = cast(OperatorType, _uncast_add)
101and_ = cast(OperatorType, _uncast_and_)
102contains = cast(OperatorType, _uncast_contains)
103eq = cast(OperatorType, _uncast_eq)
104floordiv = cast(OperatorType, _uncast_floordiv)
105ge = cast(OperatorType, _uncast_ge)
106getitem = cast(OperatorType, _uncast_getitem)
107gt = cast(OperatorType, _uncast_gt)
108inv = cast(OperatorType, _uncast_inv)
109le = cast(OperatorType, _uncast_le)
110lshift = cast(OperatorType, _uncast_lshift)
111lt = cast(OperatorType, _uncast_lt)
112mod = cast(OperatorType, _uncast_mod)
113mul = cast(OperatorType, _uncast_mul)
114ne = cast(OperatorType, _uncast_ne)
115neg = cast(OperatorType, _uncast_neg)
116or_ = cast(OperatorType, _uncast_or_)
117rshift = cast(OperatorType, _uncast_rshift)
118sub = cast(OperatorType, _uncast_sub)
119truediv = cast(OperatorType, _uncast_truediv)
120
121
122class Operators:
123 """Base of comparison and logical operators.
124
125 Implements base methods
126 :meth:`~sqlalchemy.sql.operators.Operators.operate` and
127 :meth:`~sqlalchemy.sql.operators.Operators.reverse_operate`, as well as
128 :meth:`~sqlalchemy.sql.operators.Operators.__and__`,
129 :meth:`~sqlalchemy.sql.operators.Operators.__or__`,
130 :meth:`~sqlalchemy.sql.operators.Operators.__invert__`.
131
132 Usually is used via its most common subclass
133 :class:`.ColumnOperators`.
134
135 """
136
137 __slots__ = ()
138
139 def __and__(self, other: Any) -> Operators:
140 """Implement the ``&`` operator.
141
142 When used with SQL expressions, results in an
143 AND operation, equivalent to
144 :func:`_expression.and_`, that is::
145
146 a & b
147
148 is equivalent to::
149
150 from sqlalchemy import and_
151
152 and_(a, b)
153
154 Care should be taken when using ``&`` regarding
155 operator precedence; the ``&`` operator has the highest precedence.
156 The operands should be enclosed in parenthesis if they contain
157 further sub expressions::
158
159 (a == 2) & (b == 4)
160
161 """
162 return self.operate(and_, other)
163
164 def __or__(self, other: Any) -> Operators:
165 """Implement the ``|`` operator.
166
167 When used with SQL expressions, results in an
168 OR operation, equivalent to
169 :func:`_expression.or_`, that is::
170
171 a | b
172
173 is equivalent to::
174
175 from sqlalchemy import or_
176
177 or_(a, b)
178
179 Care should be taken when using ``|`` regarding
180 operator precedence; the ``|`` operator has the highest precedence.
181 The operands should be enclosed in parenthesis if they contain
182 further sub expressions::
183
184 (a == 2) | (b == 4)
185
186 """
187 return self.operate(or_, other)
188
189 def __invert__(self) -> Operators:
190 """Implement the ``~`` operator.
191
192 When used with SQL expressions, results in a
193 NOT operation, equivalent to
194 :func:`_expression.not_`, that is::
195
196 ~a
197
198 is equivalent to::
199
200 from sqlalchemy import not_
201
202 not_(a)
203
204 """
205 return self.operate(inv)
206
207 def op(
208 self,
209 opstring: str,
210 precedence: int = 0,
211 is_comparison: bool = False,
212 return_type: Optional[
213 Union[Type[TypeEngine[Any]], TypeEngine[Any]]
214 ] = None,
215 python_impl: Optional[Callable[..., Any]] = None,
216 ) -> Callable[[Any], Operators]:
217 """Produce a generic operator function.
218
219 e.g.::
220
221 somecolumn.op("*")(5)
222
223 produces::
224
225 somecolumn * 5
226
227 This function can also be used to make bitwise operators explicit. For
228 example::
229
230 somecolumn.op("&")(0xFF)
231
232 is a bitwise AND of the value in ``somecolumn``.
233
234 :param opstring: a string which will be output as the infix operator
235 between this element and the expression passed to the
236 generated function.
237
238 :param precedence: precedence which the database is expected to apply
239 to the operator in SQL expressions. This integer value acts as a hint
240 for the SQL compiler to know when explicit parenthesis should be
241 rendered around a particular operation. A lower number will cause the
242 expression to be parenthesized when applied against another operator
243 with higher precedence. The default value of ``0`` is lower than all
244 operators except for the comma (``,``) and ``AS`` operators. A value
245 of 100 will be higher or equal to all operators, and -100 will be
246 lower than or equal to all operators.
247
248 .. seealso::
249
250 :ref:`faq_sql_expression_op_parenthesis` - detailed description
251 of how the SQLAlchemy SQL compiler renders parenthesis
252
253 :param is_comparison: legacy; if True, the operator will be considered
254 as a "comparison" operator, that is which evaluates to a boolean
255 true/false value, like ``==``, ``>``, etc. This flag is provided
256 so that ORM relationships can establish that the operator is a
257 comparison operator when used in a custom join condition.
258
259 Using the ``is_comparison`` parameter is superseded by using the
260 :meth:`.Operators.bool_op` method instead; this more succinct
261 operator sets this parameter automatically, but also provides
262 correct :pep:`484` typing support as the returned object will
263 express a "boolean" datatype, i.e. ``BinaryExpression[bool]``.
264
265 :param return_type: a :class:`.TypeEngine` class or object that will
266 force the return type of an expression produced by this operator
267 to be of that type. By default, operators that specify
268 :paramref:`.Operators.op.is_comparison` will resolve to
269 :class:`.Boolean`, and those that do not will be of the same
270 type as the left-hand operand.
271
272 :param python_impl: an optional Python function that can evaluate
273 two Python values in the same way as this operator works when
274 run on the database server. Useful for in-Python SQL expression
275 evaluation functions, such as for ORM hybrid attributes, and the
276 ORM "evaluator" used to match objects in a session after a multi-row
277 update or delete.
278
279 e.g.::
280
281 >>> expr = column("x").op("+", python_impl=lambda a, b: a + b)("y")
282
283 The operator for the above expression will also work for non-SQL
284 left and right objects::
285
286 >>> expr.operator(5, 10)
287 15
288
289 .. versionadded:: 2.0
290
291
292 .. seealso::
293
294 :meth:`.Operators.bool_op`
295
296 :ref:`types_operators`
297
298 :ref:`relationship_custom_operator`
299
300 """
301 operator = custom_op(
302 opstring,
303 precedence,
304 is_comparison,
305 return_type,
306 python_impl=python_impl,
307 )
308
309 def against(other: Any) -> Operators:
310 return operator(self, other)
311
312 return against
313
314 def bool_op(
315 self,
316 opstring: str,
317 precedence: int = 0,
318 python_impl: Optional[Callable[..., Any]] = None,
319 ) -> Callable[[Any], Operators]:
320 """Return a custom boolean operator.
321
322 This method is shorthand for calling
323 :meth:`.Operators.op` and passing the
324 :paramref:`.Operators.op.is_comparison`
325 flag with True. A key advantage to using :meth:`.Operators.bool_op`
326 is that when using column constructs, the "boolean" nature of the
327 returned expression will be present for :pep:`484` purposes.
328
329 .. seealso::
330
331 :meth:`.Operators.op`
332
333 """
334 return self.op(
335 opstring,
336 precedence=precedence,
337 is_comparison=True,
338 python_impl=python_impl,
339 )
340
341 def operate(
342 self, op: OperatorType, *other: Any, **kwargs: Any
343 ) -> Operators:
344 r"""Operate on an argument.
345
346 This is the lowest level of operation, raises
347 :class:`NotImplementedError` by default.
348
349 Overriding this on a subclass can allow common
350 behavior to be applied to all operations.
351 For example, overriding :class:`.ColumnOperators`
352 to apply ``func.lower()`` to the left and right
353 side::
354
355 class MyComparator(ColumnOperators):
356 def operate(self, op, other, **kwargs):
357 return op(func.lower(self), func.lower(other), **kwargs)
358
359 :param op: Operator callable.
360 :param \*other: the 'other' side of the operation. Will
361 be a single scalar for most operations.
362 :param \**kwargs: modifiers. These may be passed by special
363 operators such as :meth:`ColumnOperators.contains`.
364
365
366 """
367 raise NotImplementedError(str(op))
368
369 __sa_operate__ = operate
370
371 def reverse_operate(
372 self, op: OperatorType, other: Any, **kwargs: Any
373 ) -> Operators:
374 """Reverse operate on an argument.
375
376 Usage is the same as :meth:`operate`.
377
378 """
379 raise NotImplementedError(str(op))
380
381
382class custom_op(OperatorType, Generic[_T]):
383 """Represent a 'custom' operator.
384
385 :class:`.custom_op` is normally instantiated when the
386 :meth:`.Operators.op` or :meth:`.Operators.bool_op` methods
387 are used to create a custom operator callable. The class can also be
388 used directly when programmatically constructing expressions. E.g.
389 to represent the "factorial" operation::
390
391 from sqlalchemy.sql import UnaryExpression
392 from sqlalchemy.sql import operators
393 from sqlalchemy import Numeric
394
395 unary = UnaryExpression(
396 table.c.somecolumn, modifier=operators.custom_op("!"), type_=Numeric
397 )
398
399 .. seealso::
400
401 :meth:`.Operators.op`
402
403 :meth:`.Operators.bool_op`
404
405 """ # noqa: E501
406
407 __name__ = "custom_op"
408
409 __slots__ = (
410 "opstring",
411 "precedence",
412 "is_comparison",
413 "natural_self_precedent",
414 "eager_grouping",
415 "return_type",
416 "python_impl",
417 )
418
419 def __init__(
420 self,
421 opstring: str,
422 precedence: int = 0,
423 is_comparison: bool = False,
424 return_type: Optional[
425 Union[Type[TypeEngine[_T]], TypeEngine[_T]]
426 ] = None,
427 natural_self_precedent: bool = False,
428 eager_grouping: bool = False,
429 python_impl: Optional[Callable[..., Any]] = None,
430 ):
431 self.opstring = opstring
432 self.precedence = precedence
433 self.is_comparison = is_comparison
434 self.natural_self_precedent = natural_self_precedent
435 self.eager_grouping = eager_grouping
436 self.return_type = (
437 return_type._to_instance(return_type) if return_type else None
438 )
439 self.python_impl = python_impl
440
441 def __eq__(self, other: Any) -> bool:
442 return (
443 isinstance(other, custom_op)
444 and other._hash_key() == self._hash_key()
445 )
446
447 def __hash__(self) -> int:
448 return hash(self._hash_key())
449
450 def _hash_key(self) -> Union[CacheConst, Tuple[Any, ...]]:
451 return (
452 self.__class__,
453 self.opstring,
454 self.precedence,
455 self.is_comparison,
456 self.natural_self_precedent,
457 self.eager_grouping,
458 self.return_type._static_cache_key if self.return_type else None,
459 )
460
461 @overload
462 def __call__(
463 self,
464 left: ColumnExpressionArgument[Any],
465 right: Optional[Any] = None,
466 *other: Any,
467 **kwargs: Any,
468 ) -> ColumnElement[Any]: ...
469
470 @overload
471 def __call__(
472 self,
473 left: Operators,
474 right: Optional[Any] = None,
475 *other: Any,
476 **kwargs: Any,
477 ) -> Operators: ...
478
479 def __call__(
480 self,
481 left: Any,
482 right: Optional[Any] = None,
483 *other: Any,
484 **kwargs: Any,
485 ) -> Operators:
486 if hasattr(left, "__sa_operate__"):
487 return left.operate(self, right, *other, **kwargs) # type: ignore
488 elif self.python_impl:
489 return self.python_impl(left, right, *other, **kwargs) # type: ignore # noqa: E501
490 else:
491 raise exc.InvalidRequestError(
492 f"Custom operator {self.opstring!r} can't be used with "
493 "plain Python objects unless it includes the "
494 "'python_impl' parameter."
495 )
496
497
498class ColumnOperators(Operators):
499 """Defines boolean, comparison, and other operators for
500 :class:`_expression.ColumnElement` expressions.
501
502 By default, all methods call down to
503 :meth:`.operate` or :meth:`.reverse_operate`,
504 passing in the appropriate operator function from the
505 Python builtin ``operator`` module or
506 a SQLAlchemy-specific operator function from
507 :mod:`sqlalchemy.expression.operators`. For example
508 the ``__eq__`` function::
509
510 def __eq__(self, other):
511 return self.operate(operators.eq, other)
512
513 Where ``operators.eq`` is essentially::
514
515 def eq(a, b):
516 return a == b
517
518 The core column expression unit :class:`_expression.ColumnElement`
519 overrides :meth:`.Operators.operate` and others
520 to return further :class:`_expression.ColumnElement` constructs,
521 so that the ``==`` operation above is replaced by a clause
522 construct.
523
524 .. seealso::
525
526 :ref:`types_operators`
527
528 :attr:`.TypeEngine.comparator_factory`
529
530 :class:`.ColumnOperators`
531
532 :class:`.PropComparator`
533
534 """
535
536 __slots__ = ()
537
538 timetuple: Literal[None] = None
539 """Hack, allows datetime objects to be compared on the LHS."""
540
541 if typing.TYPE_CHECKING:
542
543 def operate(
544 self, op: OperatorType, *other: Any, **kwargs: Any
545 ) -> ColumnOperators: ...
546
547 def reverse_operate(
548 self, op: OperatorType, other: Any, **kwargs: Any
549 ) -> ColumnOperators: ...
550
551 def __lt__(self, other: Any) -> ColumnOperators:
552 """Implement the ``<`` operator.
553
554 In a column context, produces the clause ``a < b``.
555
556 """
557 return self.operate(lt, other)
558
559 def __le__(self, other: Any) -> ColumnOperators:
560 """Implement the ``<=`` operator.
561
562 In a column context, produces the clause ``a <= b``.
563
564 """
565 return self.operate(le, other)
566
567 # ColumnOperators defines an __eq__ so it must explicitly declare also
568 # an hash or it's set to None by python:
569 # https://docs.python.org/3/reference/datamodel.html#object.__hash__
570 if TYPE_CHECKING:
571
572 def __hash__(self) -> int: ...
573
574 else:
575 __hash__ = Operators.__hash__
576
577 def __eq__(self, other: Any) -> ColumnOperators: # type: ignore[override]
578 """Implement the ``==`` operator.
579
580 In a column context, produces the clause ``a = b``.
581 If the target is ``None``, produces ``a IS NULL``.
582
583 """
584 return self.operate(eq, other)
585
586 def __ne__(self, other: Any) -> ColumnOperators: # type: ignore[override]
587 """Implement the ``!=`` operator.
588
589 In a column context, produces the clause ``a != b``.
590 If the target is ``None``, produces ``a IS NOT NULL``.
591
592 """
593 return self.operate(ne, other)
594
595 def is_distinct_from(self, other: Any) -> ColumnOperators:
596 """Implement the ``IS DISTINCT FROM`` operator.
597
598 Renders "a IS DISTINCT FROM b" on most platforms;
599 on some such as SQLite may render "a IS NOT b".
600
601 """
602 return self.operate(is_distinct_from, other)
603
604 def is_not_distinct_from(self, other: Any) -> ColumnOperators:
605 """Implement the ``IS NOT DISTINCT FROM`` operator.
606
607 Renders "a IS NOT DISTINCT FROM b" on most platforms;
608 on some such as SQLite may render "a IS b".
609
610 .. versionchanged:: 1.4 The ``is_not_distinct_from()`` operator is
611 renamed from ``isnot_distinct_from()`` in previous releases.
612 The previous name remains available for backwards compatibility.
613
614 """
615 return self.operate(is_not_distinct_from, other)
616
617 # deprecated 1.4; see #5435
618 if TYPE_CHECKING:
619
620 def isnot_distinct_from(self, other: Any) -> ColumnOperators: ...
621
622 else:
623 isnot_distinct_from = is_not_distinct_from
624
625 def __gt__(self, other: Any) -> ColumnOperators:
626 """Implement the ``>`` operator.
627
628 In a column context, produces the clause ``a > b``.
629
630 """
631 return self.operate(gt, other)
632
633 def __ge__(self, other: Any) -> ColumnOperators:
634 """Implement the ``>=`` operator.
635
636 In a column context, produces the clause ``a >= b``.
637
638 """
639 return self.operate(ge, other)
640
641 def __neg__(self) -> ColumnOperators:
642 """Implement the ``-`` operator.
643
644 In a column context, produces the clause ``-a``.
645
646 """
647 return self.operate(neg)
648
649 def __contains__(self, other: Any) -> ColumnOperators:
650 return self.operate(contains, other)
651
652 def __getitem__(self, index: Any) -> ColumnOperators:
653 """Implement the [] operator.
654
655 This can be used by some database-specific types
656 such as PostgreSQL ARRAY and HSTORE.
657
658 """
659 return self.operate(getitem, index)
660
661 def __lshift__(self, other: Any) -> ColumnOperators:
662 """implement the << operator.
663
664 Not used by SQLAlchemy core, this is provided
665 for custom operator systems which want to use
666 << as an extension point.
667 """
668 return self.operate(lshift, other)
669
670 def __rshift__(self, other: Any) -> ColumnOperators:
671 """implement the >> operator.
672
673 Not used by SQLAlchemy core, this is provided
674 for custom operator systems which want to use
675 >> as an extension point.
676 """
677 return self.operate(rshift, other)
678
679 def concat(self, other: Any) -> ColumnOperators:
680 """Implement the 'concat' operator.
681
682 In a column context, produces the clause ``a || b``,
683 or uses the ``concat()`` operator on MySQL.
684
685 """
686 return self.operate(concat_op, other)
687
688 def _rconcat(self, other: Any) -> ColumnOperators:
689 """Implement an 'rconcat' operator.
690
691 this is for internal use at the moment
692
693 .. versionadded:: 1.4.40
694
695 """
696 return self.reverse_operate(concat_op, other)
697
698 def like(
699 self, other: Any, escape: Optional[str] = None
700 ) -> ColumnOperators:
701 r"""Implement the ``like`` operator.
702
703 In a column context, produces the expression:
704
705 .. sourcecode:: sql
706
707 a LIKE other
708
709 E.g.::
710
711 stmt = select(sometable).where(sometable.c.column.like("%foobar%"))
712
713 :param other: expression to be compared
714 :param escape: optional escape character, renders the ``ESCAPE``
715 keyword, e.g.::
716
717 somecolumn.like("foo/%bar", escape="/")
718
719 .. seealso::
720
721 :meth:`.ColumnOperators.ilike`
722
723 """
724 return self.operate(like_op, other, escape=escape)
725
726 def ilike(
727 self, other: Any, escape: Optional[str] = None
728 ) -> ColumnOperators:
729 r"""Implement the ``ilike`` operator, e.g. case insensitive LIKE.
730
731 In a column context, produces an expression either of the form:
732
733 .. sourcecode:: sql
734
735 lower(a) LIKE lower(other)
736
737 Or on backends that support the ILIKE operator:
738
739 .. sourcecode:: sql
740
741 a ILIKE other
742
743 E.g.::
744
745 stmt = select(sometable).where(sometable.c.column.ilike("%foobar%"))
746
747 :param other: expression to be compared
748 :param escape: optional escape character, renders the ``ESCAPE``
749 keyword, e.g.::
750
751 somecolumn.ilike("foo/%bar", escape="/")
752
753 .. seealso::
754
755 :meth:`.ColumnOperators.like`
756
757 """ # noqa: E501
758 return self.operate(ilike_op, other, escape=escape)
759
760 def bitwise_xor(self, other: Any) -> ColumnOperators:
761 """Produce a bitwise XOR operation, typically via the ``^``
762 operator, or ``#`` for PostgreSQL.
763
764 .. versionadded:: 2.0.2
765
766 .. seealso::
767
768 :ref:`operators_bitwise`
769
770 """
771
772 return self.operate(bitwise_xor_op, other)
773
774 def bitwise_or(self, other: Any) -> ColumnOperators:
775 """Produce a bitwise OR operation, typically via the ``|``
776 operator.
777
778 .. versionadded:: 2.0.2
779
780 .. seealso::
781
782 :ref:`operators_bitwise`
783
784 """
785
786 return self.operate(bitwise_or_op, other)
787
788 def bitwise_and(self, other: Any) -> ColumnOperators:
789 """Produce a bitwise AND operation, typically via the ``&``
790 operator.
791
792 .. versionadded:: 2.0.2
793
794 .. seealso::
795
796 :ref:`operators_bitwise`
797
798 """
799
800 return self.operate(bitwise_and_op, other)
801
802 def bitwise_not(self) -> ColumnOperators:
803 """Produce a bitwise NOT operation, typically via the ``~``
804 operator.
805
806 .. versionadded:: 2.0.2
807
808 .. seealso::
809
810 :ref:`operators_bitwise`
811
812 """
813
814 return self.operate(bitwise_not_op)
815
816 def bitwise_lshift(self, other: Any) -> ColumnOperators:
817 """Produce a bitwise LSHIFT operation, typically via the ``<<``
818 operator.
819
820 .. versionadded:: 2.0.2
821
822 .. seealso::
823
824 :ref:`operators_bitwise`
825
826 """
827
828 return self.operate(bitwise_lshift_op, other)
829
830 def bitwise_rshift(self, other: Any) -> ColumnOperators:
831 """Produce a bitwise RSHIFT operation, typically via the ``>>``
832 operator.
833
834 .. versionadded:: 2.0.2
835
836 .. seealso::
837
838 :ref:`operators_bitwise`
839
840 """
841
842 return self.operate(bitwise_rshift_op, other)
843
844 def in_(self, other: Any) -> ColumnOperators:
845 """Implement the ``in`` operator.
846
847 In a column context, produces the clause ``column IN <other>``.
848
849 The given parameter ``other`` may be:
850
851 * A list of literal values,
852 e.g.::
853
854 stmt.where(column.in_([1, 2, 3]))
855
856 In this calling form, the list of items is converted to a set of
857 bound parameters the same length as the list given:
858
859 .. sourcecode:: sql
860
861 WHERE COL IN (?, ?, ?)
862
863 * A list of tuples may be provided if the comparison is against a
864 :func:`.tuple_` containing multiple expressions::
865
866 from sqlalchemy import tuple_
867
868 stmt.where(tuple_(col1, col2).in_([(1, 10), (2, 20), (3, 30)]))
869
870 * An empty list,
871 e.g.::
872
873 stmt.where(column.in_([]))
874
875 In this calling form, the expression renders an "empty set"
876 expression. These expressions are tailored to individual backends
877 and are generally trying to get an empty SELECT statement as a
878 subquery. Such as on SQLite, the expression is:
879
880 .. sourcecode:: sql
881
882 WHERE col IN (SELECT 1 FROM (SELECT 1) WHERE 1!=1)
883
884 .. versionchanged:: 1.4 empty IN expressions now use an
885 execution-time generated SELECT subquery in all cases.
886
887 * A bound parameter, e.g. :func:`.bindparam`, may be used if it
888 includes the :paramref:`.bindparam.expanding` flag::
889
890 stmt.where(column.in_(bindparam("value", expanding=True)))
891
892 In this calling form, the expression renders a special non-SQL
893 placeholder expression that looks like:
894
895 .. sourcecode:: sql
896
897 WHERE COL IN ([EXPANDING_value])
898
899 This placeholder expression is intercepted at statement execution
900 time to be converted into the variable number of bound parameter
901 form illustrated earlier. If the statement were executed as::
902
903 connection.execute(stmt, {"value": [1, 2, 3]})
904
905 The database would be passed a bound parameter for each value:
906
907 .. sourcecode:: sql
908
909 WHERE COL IN (?, ?, ?)
910
911 .. versionadded:: 1.2 added "expanding" bound parameters
912
913 If an empty list is passed, a special "empty list" expression,
914 which is specific to the database in use, is rendered. On
915 SQLite this would be:
916
917 .. sourcecode:: sql
918
919 WHERE COL IN (SELECT 1 FROM (SELECT 1) WHERE 1!=1)
920
921 .. versionadded:: 1.3 "expanding" bound parameters now support
922 empty lists
923
924 * a :func:`_expression.select` construct, which is usually a
925 correlated scalar select::
926
927 stmt.where(
928 column.in_(select(othertable.c.y).where(table.c.x == othertable.c.x))
929 )
930
931 In this calling form, :meth:`.ColumnOperators.in_` renders as given:
932
933 .. sourcecode:: sql
934
935 WHERE COL IN (SELECT othertable.y
936 FROM othertable WHERE othertable.x = table.x)
937
938 :param other: a list of literals, a :func:`_expression.select`
939 construct, or a :func:`.bindparam` construct that includes the
940 :paramref:`.bindparam.expanding` flag set to True.
941
942 """ # noqa: E501
943 return self.operate(in_op, other)
944
945 def not_in(self, other: Any) -> ColumnOperators:
946 """implement the ``NOT IN`` operator.
947
948 This is equivalent to using negation with
949 :meth:`.ColumnOperators.in_`, i.e. ``~x.in_(y)``.
950
951 In the case that ``other`` is an empty sequence, the compiler
952 produces an "empty not in" expression. This defaults to the
953 expression "1 = 1" to produce true in all cases. The
954 :paramref:`_sa.create_engine.empty_in_strategy` may be used to
955 alter this behavior.
956
957 .. versionchanged:: 1.4 The ``not_in()`` operator is renamed from
958 ``notin_()`` in previous releases. The previous name remains
959 available for backwards compatibility.
960
961 .. versionchanged:: 1.2 The :meth:`.ColumnOperators.in_` and
962 :meth:`.ColumnOperators.not_in` operators
963 now produce a "static" expression for an empty IN sequence
964 by default.
965
966 .. seealso::
967
968 :meth:`.ColumnOperators.in_`
969
970 """
971 return self.operate(not_in_op, other)
972
973 # deprecated 1.4; see #5429
974 if TYPE_CHECKING:
975
976 def notin_(self, other: Any) -> ColumnOperators: ...
977
978 else:
979 notin_ = not_in
980
981 def not_like(
982 self, other: Any, escape: Optional[str] = None
983 ) -> ColumnOperators:
984 """implement the ``NOT LIKE`` operator.
985
986 This is equivalent to using negation with
987 :meth:`.ColumnOperators.like`, i.e. ``~x.like(y)``.
988
989 .. versionchanged:: 1.4 The ``not_like()`` operator is renamed from
990 ``notlike()`` in previous releases. The previous name remains
991 available for backwards compatibility.
992
993 .. seealso::
994
995 :meth:`.ColumnOperators.like`
996
997 """
998 return self.operate(not_like_op, other, escape=escape)
999
1000 # deprecated 1.4; see #5435
1001 if TYPE_CHECKING:
1002
1003 def notlike(
1004 self, other: Any, escape: Optional[str] = None
1005 ) -> ColumnOperators: ...
1006
1007 else:
1008 notlike = not_like
1009
1010 def not_ilike(
1011 self, other: Any, escape: Optional[str] = None
1012 ) -> ColumnOperators:
1013 """implement the ``NOT ILIKE`` operator.
1014
1015 This is equivalent to using negation with
1016 :meth:`.ColumnOperators.ilike`, i.e. ``~x.ilike(y)``.
1017
1018 .. versionchanged:: 1.4 The ``not_ilike()`` operator is renamed from
1019 ``notilike()`` in previous releases. The previous name remains
1020 available for backwards compatibility.
1021
1022 .. seealso::
1023
1024 :meth:`.ColumnOperators.ilike`
1025
1026 """
1027 return self.operate(not_ilike_op, other, escape=escape)
1028
1029 # deprecated 1.4; see #5435
1030 if TYPE_CHECKING:
1031
1032 def notilike(
1033 self, other: Any, escape: Optional[str] = None
1034 ) -> ColumnOperators: ...
1035
1036 else:
1037 notilike = not_ilike
1038
1039 def is_(self, other: Any) -> ColumnOperators:
1040 """Implement the ``IS`` operator.
1041
1042 Normally, ``IS`` is generated automatically when comparing to a
1043 value of ``None``, which resolves to ``NULL``. However, explicit
1044 usage of ``IS`` may be desirable if comparing to boolean values
1045 on certain platforms.
1046
1047 .. seealso:: :meth:`.ColumnOperators.is_not`
1048
1049 """
1050 return self.operate(is_, other)
1051
1052 def is_not(self, other: Any) -> ColumnOperators:
1053 """Implement the ``IS NOT`` operator.
1054
1055 Normally, ``IS NOT`` is generated automatically when comparing to a
1056 value of ``None``, which resolves to ``NULL``. However, explicit
1057 usage of ``IS NOT`` may be desirable if comparing to boolean values
1058 on certain platforms.
1059
1060 .. versionchanged:: 1.4 The ``is_not()`` operator is renamed from
1061 ``isnot()`` in previous releases. The previous name remains
1062 available for backwards compatibility.
1063
1064 .. seealso:: :meth:`.ColumnOperators.is_`
1065
1066 """
1067 return self.operate(is_not, other)
1068
1069 # deprecated 1.4; see #5429
1070 if TYPE_CHECKING:
1071
1072 def isnot(self, other: Any) -> ColumnOperators: ...
1073
1074 else:
1075 isnot = is_not
1076
1077 def startswith(
1078 self,
1079 other: Any,
1080 escape: Optional[str] = None,
1081 autoescape: bool = False,
1082 ) -> ColumnOperators:
1083 r"""Implement the ``startswith`` operator.
1084
1085 Produces a LIKE expression that tests against a match for the start
1086 of a string value:
1087
1088 .. sourcecode:: sql
1089
1090 column LIKE <other> || '%'
1091
1092 E.g.::
1093
1094 stmt = select(sometable).where(sometable.c.column.startswith("foobar"))
1095
1096 Since the operator uses ``LIKE``, wildcard characters
1097 ``"%"`` and ``"_"`` that are present inside the <other> expression
1098 will behave like wildcards as well. For literal string
1099 values, the :paramref:`.ColumnOperators.startswith.autoescape` flag
1100 may be set to ``True`` to apply escaping to occurrences of these
1101 characters within the string value so that they match as themselves
1102 and not as wildcard characters. Alternatively, the
1103 :paramref:`.ColumnOperators.startswith.escape` parameter will establish
1104 a given character as an escape character which can be of use when
1105 the target expression is not a literal string.
1106
1107 :param other: expression to be compared. This is usually a plain
1108 string value, but can also be an arbitrary SQL expression. LIKE
1109 wildcard characters ``%`` and ``_`` are not escaped by default unless
1110 the :paramref:`.ColumnOperators.startswith.autoescape` flag is
1111 set to True.
1112
1113 :param autoescape: boolean; when True, establishes an escape character
1114 within the LIKE expression, then applies it to all occurrences of
1115 ``"%"``, ``"_"`` and the escape character itself within the
1116 comparison value, which is assumed to be a literal string and not a
1117 SQL expression.
1118
1119 An expression such as::
1120
1121 somecolumn.startswith("foo%bar", autoescape=True)
1122
1123 Will render as:
1124
1125 .. sourcecode:: sql
1126
1127 somecolumn LIKE :param || '%' ESCAPE '/'
1128
1129 With the value of ``:param`` as ``"foo/%bar"``.
1130
1131 :param escape: a character which when given will render with the
1132 ``ESCAPE`` keyword to establish that character as the escape
1133 character. This character can then be placed preceding occurrences
1134 of ``%`` and ``_`` to allow them to act as themselves and not
1135 wildcard characters.
1136
1137 An expression such as::
1138
1139 somecolumn.startswith("foo/%bar", escape="^")
1140
1141 Will render as:
1142
1143 .. sourcecode:: sql
1144
1145 somecolumn LIKE :param || '%' ESCAPE '^'
1146
1147 The parameter may also be combined with
1148 :paramref:`.ColumnOperators.startswith.autoescape`::
1149
1150 somecolumn.startswith("foo%bar^bat", escape="^", autoescape=True)
1151
1152 Where above, the given literal parameter will be converted to
1153 ``"foo^%bar^^bat"`` before being passed to the database.
1154
1155 .. seealso::
1156
1157 :meth:`.ColumnOperators.endswith`
1158
1159 :meth:`.ColumnOperators.contains`
1160
1161 :meth:`.ColumnOperators.like`
1162
1163 """ # noqa: E501
1164 return self.operate(
1165 startswith_op, other, escape=escape, autoescape=autoescape
1166 )
1167
1168 def istartswith(
1169 self,
1170 other: Any,
1171 escape: Optional[str] = None,
1172 autoescape: bool = False,
1173 ) -> ColumnOperators:
1174 r"""Implement the ``istartswith`` operator, e.g. case insensitive
1175 version of :meth:`.ColumnOperators.startswith`.
1176
1177 Produces a LIKE expression that tests against an insensitive
1178 match for the start of a string value:
1179
1180 .. sourcecode:: sql
1181
1182 lower(column) LIKE lower(<other>) || '%'
1183
1184 E.g.::
1185
1186 stmt = select(sometable).where(sometable.c.column.istartswith("foobar"))
1187
1188 Since the operator uses ``LIKE``, wildcard characters
1189 ``"%"`` and ``"_"`` that are present inside the <other> expression
1190 will behave like wildcards as well. For literal string
1191 values, the :paramref:`.ColumnOperators.istartswith.autoescape` flag
1192 may be set to ``True`` to apply escaping to occurrences of these
1193 characters within the string value so that they match as themselves
1194 and not as wildcard characters. Alternatively, the
1195 :paramref:`.ColumnOperators.istartswith.escape` parameter will
1196 establish a given character as an escape character which can be of
1197 use when the target expression is not a literal string.
1198
1199 :param other: expression to be compared. This is usually a plain
1200 string value, but can also be an arbitrary SQL expression. LIKE
