Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/sqlalchemy/sql/operators.py: 65%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

639 statements  

1# sql/operators.py 

2# Copyright (C) 2005-2025 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 auto 

16from enum import Flag 

17from enum import IntEnum 

18from operator import add as _uncast_add 

19from operator import and_ as _uncast_and_ 

20from operator import contains as _uncast_contains 

21from operator import eq as _uncast_eq 

22from operator import floordiv as _uncast_floordiv 

23from operator import ge as _uncast_ge 

24from operator import getitem as _uncast_getitem 

25from operator import gt as _uncast_gt 

26from operator import inv as _uncast_inv 

27from operator import le as _uncast_le 

28from operator import lshift as _uncast_lshift 

29from operator import lt as _uncast_lt 

30from operator import matmul as _uncast_matmul 

31from operator import mod as _uncast_mod 

32from operator import mul as _uncast_mul 

33from operator import ne as _uncast_ne 

34from operator import neg as _uncast_neg 

35from operator import or_ as _uncast_or_ 

36from operator import pow as _uncast_pow 

37from operator import rshift as _uncast_rshift 

38from operator import sub as _uncast_sub 

39from operator import truediv as _uncast_truediv 

40import typing 

41from typing import Any 

42from typing import Callable 

43from typing import cast 

44from typing import Dict 

45from typing import Generic 

46from typing import Hashable 

47from typing import Literal 

48from typing import Optional 

49from typing import overload 

50from typing import Protocol 

51from typing import Set 

52from typing import Tuple 

53from typing import Type 

54from typing import TYPE_CHECKING 

55from typing import TypeVar 

56from typing import Union 

57 

58from .. import exc 

59from .. import util 

60 

61if typing.TYPE_CHECKING: 

62 from ._typing import ColumnExpressionArgument 

63 from .cache_key import CacheConst 

64 from .elements import ColumnElement 

65 from .type_api import TypeEngine 

66 

67_T = TypeVar("_T", bound=Any) 

68_FN = TypeVar("_FN", bound=Callable[..., Any]) 

69 

70 

71class OperatorClass(Flag): 

72 """Describes a class of SQLAlchemy built-in operators that should be 

73 available on a particular type. 

74 

75 The :class:`.OperatorClass` should be present on the 

76 :attr:`.TypeEngine.operator_classes` attribute of any particular type. 

77 

78 The enums here can be ORed together to provide sets of operators merged 

79 together. 

80 

81 .. versionadded:: 2.1 

82 

83 """ 

84 

85 UNSPECIFIED = auto() 

86 BASE = auto() 

87 BOOLEAN_ALGEBRA = auto() 

88 COMPARISON = auto() 

89 INDEXABLE = auto() # noqa: F811 

90 CONTAINS = auto() 

91 CONCATENABLE = auto() 

92 STRING_MATCH = auto() 

93 MATH = auto() 

94 BITWISE = auto() 

95 DATE_ARITHEMETIC = auto() 

96 JSON_GETITEM = auto() 

97 

98 STRING = ( 

99 BASE | COMPARISON | STRING_MATCH | CONTAINS | CONCATENABLE | INDEXABLE 

100 ) 

101 INTEGER = BASE | COMPARISON | MATH | BITWISE 

102 NUMERIC = BASE | COMPARISON | MATH | BITWISE 

103 BOOLEAN = BASE | COMPARISON | BOOLEAN_ALGEBRA | COMPARISON 

104 BINARY = BASE | COMPARISON | CONTAINS | CONCATENABLE | INDEXABLE 

105 DATETIME = BASE | COMPARISON | DATE_ARITHEMETIC 

106 JSON = BASE | COMPARISON | INDEXABLE | JSON_GETITEM 

107 ARRAY = BASE | COMPARISON | CONTAINS | CONCATENABLE | INDEXABLE 

108 TUPLE = BASE | COMPARISON | CONTAINS | CONCATENABLE | INDEXABLE 

109 

110 ANY = ( 

111 STRING 

112 | INTEGER 

113 | NUMERIC 

114 | BOOLEAN 

115 | DATETIME 

116 | BINARY 

117 | JSON 

118 | ARRAY 

119 | TUPLE 

120 ) 

121 

122 

123class OperatorType(Hashable, Protocol): 

124 """describe an op() function.""" 

125 

126 __slots__ = () 

127 

128 __name__: str 

129 

130 @overload 

131 def __call__( 

132 self, 

133 left: ColumnExpressionArgument[Any], 

134 right: Optional[Any] = None, 

135 *other: Any, 

136 **kwargs: Any, 

137 ) -> ColumnElement[Any]: ... 

138 

139 @overload 

140 def __call__( 

141 self, 

142 left: Operators, 

143 right: Optional[Any] = None, 

144 *other: Any, 

145 **kwargs: Any, 

146 ) -> Operators: ... 

147 

148 def __call__( 

149 self, 

150 left: Any, 

151 right: Optional[Any] = None, 

152 *other: Any, 

153 **kwargs: Any, 

154 ) -> Operators: ... 

155 

156 

157add = cast(OperatorType, _uncast_add) 

158and_ = cast(OperatorType, _uncast_and_) 

159contains = cast(OperatorType, _uncast_contains) 

160eq = cast(OperatorType, _uncast_eq) 

161floordiv = cast(OperatorType, _uncast_floordiv) 

162ge = cast(OperatorType, _uncast_ge) 

163getitem = cast(OperatorType, _uncast_getitem) 

164gt = cast(OperatorType, _uncast_gt) 

165inv = cast(OperatorType, _uncast_inv) 

166le = cast(OperatorType, _uncast_le) 

167lshift = cast(OperatorType, _uncast_lshift) 

168lt = cast(OperatorType, _uncast_lt) 

169matmul = cast(OperatorType, _uncast_matmul) 

170mod = cast(OperatorType, _uncast_mod) 

171mul = cast(OperatorType, _uncast_mul) 

172ne = cast(OperatorType, _uncast_ne) 

173neg = cast(OperatorType, _uncast_neg) 

174or_ = cast(OperatorType, _uncast_or_) 

175pow_ = cast(OperatorType, _uncast_pow) 

176rshift = cast(OperatorType, _uncast_rshift) 

177sub = cast(OperatorType, _uncast_sub) 

178truediv = cast(OperatorType, _uncast_truediv) 

179 

180 

181class Operators: 

182 """Base of comparison and logical operators. 

183 

184 Implements base methods 

185 :meth:`~sqlalchemy.sql.operators.Operators.operate` and 

186 :meth:`~sqlalchemy.sql.operators.Operators.reverse_operate`, as well as 

187 :meth:`~sqlalchemy.sql.operators.Operators.__and__`, 

188 :meth:`~sqlalchemy.sql.operators.Operators.__or__`, 

189 :meth:`~sqlalchemy.sql.operators.Operators.__invert__`. 

190 

191 Usually is used via its most common subclass 

192 :class:`.ColumnOperators`. 

193 

194 """ 

195 

196 __slots__ = () 

197 

198 def __and__(self, other: Any) -> Operators: 

199 """Implement the ``&`` operator. 

200 

201 When used with SQL expressions, results in an 

202 AND operation, equivalent to 

203 :func:`_expression.and_`, that is:: 

204 

205 a & b 

206 

207 is equivalent to:: 

208 

209 from sqlalchemy import and_ 

210 

211 and_(a, b) 

212 

213 Care should be taken when using ``&`` regarding 

214 operator precedence; the ``&`` operator has the highest precedence. 

215 The operands should be enclosed in parenthesis if they contain 

216 further sub expressions:: 

217 

218 (a == 2) & (b == 4) 

219 

220 """ 

221 return self.operate(and_, other) 

222 

223 def __or__(self, other: Any) -> Operators: 

224 """Implement the ``|`` operator. 

225 

226 When used with SQL expressions, results in an 

227 OR operation, equivalent to 

228 :func:`_expression.or_`, that is:: 

229 

230 a | b 

231 

232 is equivalent to:: 

233 

234 from sqlalchemy import or_ 

235 

236 or_(a, b) 

237 

238 Care should be taken when using ``|`` regarding 

239 operator precedence; the ``|`` operator has the highest precedence. 

240 The operands should be enclosed in parenthesis if they contain 

241 further sub expressions:: 

242 

243 (a == 2) | (b == 4) 

244 

245 """ 

246 return self.operate(or_, other) 

247 

248 def __invert__(self) -> Operators: 

249 """Implement the ``~`` operator. 

250 

251 When used with SQL expressions, results in a 

252 NOT operation, equivalent to 

253 :func:`_expression.not_`, that is:: 

254 

255 ~a 

256 

257 is equivalent to:: 

258 

259 from sqlalchemy import not_ 

260 

261 not_(a) 

262 

263 """ 

264 return self.operate(inv) 

265 

266 def _null_operate(self, other: Any) -> Operators: 

267 """A 'null' operation available on all types, used for testing.""" 

268 

269 return self.operate(null_op, other) 

270 

271 def op( 

272 self, 

273 opstring: str, 

274 precedence: int = 0, 

275 is_comparison: bool = False, 

276 return_type: Optional[ 

277 Union[Type[TypeEngine[Any]], TypeEngine[Any]] 

278 ] = None, 

279 python_impl: Optional[Callable[..., Any]] = None, 

280 operator_class: OperatorClass = OperatorClass.BASE, 

281 visit_name: Optional[str] = None, 

282 ) -> Callable[[Any], Operators]: 

283 """Produce a generic operator function. 

284 

285 e.g.:: 

286 

287 somecolumn.op("*")(5) 

288 

289 produces:: 

290 

291 somecolumn * 5 

292 

293 This function can also be used to make bitwise operators explicit. For 

294 example:: 

295 

296 somecolumn.op("&")(0xFF) 

297 

298 is a bitwise AND of the value in ``somecolumn``. 

299 

300 :param opstring: a string which will be output as the infix operator 

301 between this element and the expression passed to the 

302 generated function. 

303 

304 :param precedence: precedence which the database is expected to apply 

305 to the operator in SQL expressions. This integer value acts as a hint 

306 for the SQL compiler to know when explicit parenthesis should be 

307 rendered around a particular operation. A lower number will cause the 

308 expression to be parenthesized when applied against another operator 

309 with higher precedence. The default value of ``0`` is lower than all 

310 operators except for the comma (``,``) and ``AS`` operators. A value 

311 of 100 will be higher or equal to all operators, and -100 will be 

312 lower than or equal to all operators. 

313 

314 .. seealso:: 

315 

316 :ref:`faq_sql_expression_op_parenthesis` - detailed description 

317 of how the SQLAlchemy SQL compiler renders parenthesis 

318 

319 :param is_comparison: legacy; if True, the operator will be considered 

320 as a "comparison" operator, that is which evaluates to a boolean 

321 true/false value, like ``==``, ``>``, etc. This flag is provided 

322 so that ORM relationships can establish that the operator is a 

323 comparison operator when used in a custom join condition. 

324 

325 Using the ``is_comparison`` parameter is superseded by using the 

326 :meth:`.Operators.bool_op` method instead; this more succinct 

327 operator sets this parameter automatically, but also provides 

328 correct :pep:`484` typing support as the returned object will 

329 express a "boolean" datatype, i.e. ``BinaryExpression[bool]``. 

330 

331 :param return_type: a :class:`.TypeEngine` class or object that will 

332 force the return type of an expression produced by this operator 

333 to be of that type. By default, operators that specify 

334 :paramref:`.Operators.op.is_comparison` will resolve to 

335 :class:`.Boolean`, and those that do not will be of the same 

336 type as the left-hand operand. 

337 

338 :param python_impl: an optional Python function that can evaluate 

339 two Python values in the same way as this operator works when 

340 run on the database server. Useful for in-Python SQL expression 

341 evaluation functions, such as for ORM hybrid attributes, and the 

342 ORM "evaluator" used to match objects in a session after a multi-row 

343 update or delete. 

344 

345 e.g.:: 

346 

347 >>> expr = column("x").op("+", python_impl=lambda a, b: a + b)("y") 

348 

349 The operator for the above expression will also work for non-SQL 

350 left and right objects:: 

351 

352 >>> expr.operator(5, 10) 

353 15 

354 

355 .. versionadded:: 2.0 

356 

357 :param operator_class: optional :class:`.OperatorClass` which will be 

358 applied to the :class:`.custom_op` created, which provides hints 

359 as to which datatypes are appropriate for this operator. Defaults 

360 to :attr:`.OperatorClass.BASE` which is appropriate for all 

361 datatypes. 

362 

363 .. versionadded:: 2.1 

364 

365 .. seealso:: 

366 

367 :meth:`.Operators.bool_op` 

368 

369 :ref:`types_operators` 

370 

371 :ref:`relationship_custom_operator` 

372 

373 :param visit_name: string name indicating a series of methods that 

374 maybe be implemented by a :class:`.Dialect`, specifically using its 

375 :class:`.SQLCompiler` implementation. The naming scheme is 

376 ``visit_<visit_name>_op_[binary|unary]``; e.g. using the visit name 

377 ``hstore`` means that a binary expression using the operator will 

378 attempt to locate a method ``visit_hstore_op_binary()`` on the 

379 target dialect's compiler class, which can then provide a compilation 

380 string for the full binary expression. 

381 

382 .. versionadded:: 2.1 

383 

384 """ 

385 operator = custom_op( 

386 opstring, 

387 precedence=precedence, 

388 is_comparison=is_comparison, 

389 return_type=return_type, 

390 python_impl=python_impl, 

391 operator_class=operator_class, 

392 visit_name=visit_name, 

393 ) 

394 

395 def against(other: Any) -> Operators: 

396 return operator(self, other) 

397 

398 return against 

399 

400 def bool_op( 

401 self, 

402 opstring: str, 

403 precedence: int = 0, 

404 python_impl: Optional[Callable[..., Any]] = None, 

405 ) -> Callable[[Any], Operators]: 

406 """Return a custom boolean operator. 

407 

408 This method is shorthand for calling 

409 :meth:`.Operators.op` and passing the 

410 :paramref:`.Operators.op.is_comparison` 

411 flag with True. A key advantage to using :meth:`.Operators.bool_op` 

412 is that when using column constructs, the "boolean" nature of the 

413 returned expression will be present for :pep:`484` purposes. 

414 

415 .. seealso:: 

416 

417 :meth:`.Operators.op` 

418 

419 """ 

420 return self.op( 

421 opstring, 

422 precedence=precedence, 

423 is_comparison=True, 

424 python_impl=python_impl, 

425 ) 

426 

427 def operate( 

428 self, op: OperatorType, *other: Any, **kwargs: Any 

429 ) -> Operators: 

430 r"""Operate on an argument. 

431 

432 This is the lowest level of operation, raises 

433 :class:`NotImplementedError` by default. 

434 

435 Overriding this on a subclass can allow common 

436 behavior to be applied to all operations. 

437 For example, overriding :class:`.ColumnOperators` 

438 to apply ``func.lower()`` to the left and right 

439 side:: 

440 

441 class MyComparator(ColumnOperators): 

442 def operate(self, op, other, **kwargs): 

443 return op(func.lower(self), func.lower(other), **kwargs) 

444 

445 :param op: Operator callable. 

446 :param \*other: the 'other' side of the operation. Will 

447 be a single scalar for most operations. 

448 :param \**kwargs: modifiers. These may be passed by special 

449 operators such as :meth:`ColumnOperators.contains`. 

450 

451 

452 """ 

453 raise NotImplementedError(str(op)) 

454 

455 __sa_operate__ = operate 

456 

457 def reverse_operate( 

458 self, op: OperatorType, other: Any, **kwargs: Any 

459 ) -> Operators: 

460 """Reverse operate on an argument. 

461 

462 Usage is the same as :meth:`operate`. 

463 

464 """ 

465 raise NotImplementedError(str(op)) 

466 

467 

468class custom_op(OperatorType, Generic[_T]): 

469 """Represent a 'custom' operator. 

470 

471 :class:`.custom_op` is normally instantiated when the 

472 :meth:`.Operators.op` or :meth:`.Operators.bool_op` methods 

473 are used to create a custom operator callable. The class can also be 

474 used directly when programmatically constructing expressions. E.g. 

475 to represent the "factorial" operation:: 

476 

477 from sqlalchemy.sql import UnaryExpression 

478 from sqlalchemy.sql import operators 

479 from sqlalchemy import Numeric 

480 

481 unary = UnaryExpression( 

482 table.c.somecolumn, modifier=operators.custom_op("!"), type_=Numeric 

483 ) 

484 

485 .. seealso:: 

486 

487 :meth:`.Operators.op` 

488 

489 :meth:`.Operators.bool_op` 

490 

491 """ # noqa: E501 

492 

493 __name__ = "custom_op" 

494 

495 __slots__ = ( 

496 "opstring", 

497 "precedence", 

498 "is_comparison", 

499 "natural_self_precedent", 

500 "eager_grouping", 

501 "return_type", 

502 "python_impl", 

503 "operator_class", 

504 "visit_name", 

505 ) 

506 

507 def __init__( 

508 self, 

509 opstring: str, 

510 *, 

511 precedence: int = 0, 

512 is_comparison: bool = False, 

513 return_type: Optional[ 

514 Union[Type[TypeEngine[_T]], TypeEngine[_T]] 

515 ] = None, 

516 natural_self_precedent: bool = False, 

517 eager_grouping: bool = False, 

518 python_impl: Optional[Callable[..., Any]] = None, 

519 operator_class: OperatorClass = OperatorClass.BASE, 

520 visit_name: Optional[str] = None, 

521 ): 

522 """Create a new :class:`.custom_op`. 

523 

524 See :meth:`.Operators.op` for parameter information. 

525 

526 """ 

527 self.opstring = opstring 

528 self.precedence = precedence 

529 self.is_comparison = is_comparison 

530 self.natural_self_precedent = natural_self_precedent 

531 self.eager_grouping = eager_grouping 

532 self.return_type = ( 

533 return_type._to_instance(return_type) if return_type else None 

534 ) 

535 self.python_impl = python_impl 

536 self.operator_class = operator_class 

537 self.visit_name = visit_name 

538 

539 def __eq__(self, other: Any) -> bool: 

540 return ( 

541 isinstance(other, custom_op) 

542 and other._hash_key() == self._hash_key() 

543 ) 

544 

545 def __hash__(self) -> int: 

546 return hash(self._hash_key()) 

547 

548 def _hash_key(self) -> Union[CacheConst, Tuple[Any, ...]]: 

549 return ( 

550 self.__class__, 

551 self.opstring, 

552 self.precedence, 

553 self.is_comparison, 

554 self.natural_self_precedent, 

555 self.eager_grouping, 

556 self.return_type._static_cache_key if self.return_type else None, 

557 self.operator_class, 

558 ) 

559 

560 @overload 

561 def __call__( 

562 self, 

563 left: ColumnExpressionArgument[Any], 

564 right: Optional[Any] = None, 

565 *other: Any, 

566 **kwargs: Any, 

567 ) -> ColumnElement[Any]: ... 

568 

569 @overload 

570 def __call__( 

571 self, 

572 left: Operators, 

573 right: Optional[Any] = None, 

574 *other: Any, 

575 **kwargs: Any, 

576 ) -> Operators: ... 

577 

578 def __call__( 

579 self, 

580 left: Any, 

581 right: Optional[Any] = None, 

582 *other: Any, 

583 **kwargs: Any, 

584 ) -> Operators: 

585 if hasattr(left, "__sa_operate__"): 

586 return left.operate(self, right, *other, **kwargs) # type: ignore 

587 elif self.python_impl: 

588 return self.python_impl(left, right, *other, **kwargs) # type: ignore # noqa: E501 

589 else: 

590 raise exc.InvalidRequestError( 

591 f"Custom operator {self.opstring!r} can't be used with " 

592 "plain Python objects unless it includes the " 

593 "'python_impl' parameter." 

594 ) 

595 

596 

597class OrderingOperators(Operators): 

598 """defines ORDER BY operators, which can operate as single expressions 

599 or comma-separated lists 

600 

601 """ 

602 

603 __slots__ = () 

604 

605 if typing.TYPE_CHECKING: 

606 

607 def operate( 

608 self, op: OperatorType, *other: Any, **kwargs: Any 

609 ) -> OrderingOperators: ... 

610 

611 def reverse_operate( 

612 self, op: OperatorType, other: Any, **kwargs: Any 

613 ) -> OrderingOperators: ... 

614 

615 def desc(self) -> OrderingOperators: 

616 """Produce a :func:`_expression.desc` clause against the 

617 parent object.""" 

618 return self.operate(desc_op) 

619 

620 def asc(self) -> OrderingOperators: 

621 """Produce a :func:`_expression.asc` clause against the 

622 parent object.""" 

623 return self.operate(asc_op) 

624 

625 def nulls_first(self) -> OrderingOperators: 

626 """Produce a :func:`_expression.nulls_first` clause against the 

627 parent object. 

628 

629 .. versionchanged:: 1.4 The ``nulls_first()`` operator is 

630 renamed from ``nullsfirst()`` in previous releases. 

631 The previous name remains available for backwards compatibility. 

632 """ 

633 return self.operate(nulls_first_op) 

634 

635 # deprecated 1.4; see #5435 

636 if TYPE_CHECKING: 

637 

638 def nullsfirst(self) -> OrderingOperators: ... 

639 

640 else: 

641 nullsfirst = nulls_first 

642 

643 def nulls_last(self) -> OrderingOperators: 

644 """Produce a :func:`_expression.nulls_last` clause against the 

645 parent object. 

646 

647 .. versionchanged:: 1.4 The ``nulls_last()`` operator is 

648 renamed from ``nullslast()`` in previous releases. 

649 The previous name remains available for backwards compatibility. 

650 """ 

651 return self.operate(nulls_last_op) 

652 

653 # deprecated 1.4; see #5429 

654 if TYPE_CHECKING: 

655 

656 def nullslast(self) -> OrderingOperators: ... 

657 

658 else: 

659 nullslast = nulls_last 

660 

661 

662class ColumnOperators(OrderingOperators): 

663 """Defines boolean, comparison, and other operators for 

664 :class:`_expression.ColumnElement` expressions. 

665 

666 By default, all methods call down to 

667 :meth:`.operate` or :meth:`.reverse_operate`, 

668 passing in the appropriate operator function from the 

669 Python builtin ``operator`` module or 

670 a SQLAlchemy-specific operator function from 

671 :mod:`sqlalchemy.expression.operators`. For example 

672 the ``__eq__`` function:: 

673 

674 def __eq__(self, other): 

675 return self.operate(operators.eq, other) 

676 

677 Where ``operators.eq`` is essentially:: 

678 

679 def eq(a, b): 

680 return a == b 

681 

682 The core column expression unit :class:`_expression.ColumnElement` 

683 overrides :meth:`.Operators.operate` and others 

684 to return further :class:`_expression.ColumnElement` constructs, 

685 so that the ``==`` operation above is replaced by a clause 

686 construct. 

687 

688 .. seealso:: 

689 

690 :ref:`types_operators` 

691 

692 :attr:`.TypeEngine.comparator_factory` 

693 

694 :class:`.ColumnOperators` 

695 

696 :class:`.PropComparator` 

697 

698 """ 

699 

700 __slots__ = () 

701 

702 timetuple: Literal[None] = None 

703 """Hack, allows datetime objects to be compared on the LHS.""" 

704 

705 if typing.TYPE_CHECKING: 

706 

707 def operate( 

708 self, op: OperatorType, *other: Any, **kwargs: Any 

709 ) -> ColumnOperators: ... 

710 

711 def reverse_operate( 

712 self, op: OperatorType, other: Any, **kwargs: Any 

713 ) -> ColumnOperators: ... 

714 

715 def __lt__(self, other: Any) -> ColumnOperators: 

716 """Implement the ``<`` operator. 

717 

718 In a column context, produces the clause ``a < b``. 

719 

720 """ 

721 return self.operate(lt, other) 

722 

723 def __le__(self, other: Any) -> ColumnOperators: 

724 """Implement the ``<=`` operator. 

725 

726 In a column context, produces the clause ``a <= b``. 

727 

728 """ 

729 return self.operate(le, other) 

730 

731 # ColumnOperators defines an __eq__ so it must explicitly declare also 

732 # an hash or it's set to None by python: 

733 # https://docs.python.org/3/reference/datamodel.html#object.__hash__ 

734 if TYPE_CHECKING: 

735 

736 def __hash__(self) -> int: ... 

737 

738 else: 

739 __hash__ = Operators.__hash__ 

740 

741 def __eq__(self, other: Any) -> ColumnOperators: # type: ignore[override] 

742 """Implement the ``==`` operator. 

743 

744 In a column context, produces the clause ``a = b``. 

745 If the target is ``None``, produces ``a IS NULL``. 

746 

747 """ 

748 return self.operate(eq, other) 

749 

750 def __ne__(self, other: Any) -> ColumnOperators: # type: ignore[override] 

751 """Implement the ``!=`` operator. 

752 

753 In a column context, produces the clause ``a != b``. 

754 If the target is ``None``, produces ``a IS NOT NULL``. 

755 

756 """ 

757 return self.operate(ne, other) 

758 

759 def is_distinct_from(self, other: Any) -> ColumnOperators: 

760 """Implement the ``IS DISTINCT FROM`` operator. 

761 

762 Renders "a IS DISTINCT FROM b" on most platforms; 

763 on some such as SQLite may render "a IS NOT b". 

764 

765 """ 

766 return self.operate(is_distinct_from, other) 

767 

768 def is_not_distinct_from(self, other: Any) -> ColumnOperators: 

769 """Implement the ``IS NOT DISTINCT FROM`` operator. 

770 

771 Renders "a IS NOT DISTINCT FROM b" on most platforms; 

772 on some such as SQLite may render "a IS b". 

773 

774 .. versionchanged:: 1.4 The ``is_not_distinct_from()`` operator is 

775 renamed from ``isnot_distinct_from()`` in previous releases. 

776 The previous name remains available for backwards compatibility. 

777 

778 """ 

779 return self.operate(is_not_distinct_from, other) 

780 

781 # deprecated 1.4; see #5435 

782 if TYPE_CHECKING: 

783 

784 def isnot_distinct_from(self, other: Any) -> ColumnOperators: ... 

785 

786 else: 

787 isnot_distinct_from = is_not_distinct_from 

788 

789 def __gt__(self, other: Any) -> ColumnOperators: 

790 """Implement the ``>`` operator. 

791 

792 In a column context, produces the clause ``a > b``. 

793 

794 """ 

795 return self.operate(gt, other) 

796 

797 def __ge__(self, other: Any) -> ColumnOperators: 

798 """Implement the ``>=`` operator. 

799 

800 In a column context, produces the clause ``a >= b``. 

801 

802 """ 

803 return self.operate(ge, other) 

804 

805 def __neg__(self) -> ColumnOperators: 

806 """Implement the ``-`` operator. 

807 

808 In a column context, produces the clause ``-a``. 

809 

810 """ 

811 return self.operate(neg) 

812 

813 def __contains__(self, other: Any) -> ColumnOperators: 

814 return self.operate(contains, other) 

815 

816 def __getitem__(self, index: Any) -> ColumnOperators: 

817 """Implement the [] operator. 

818 

819 This can be used by some database-specific types 

820 such as PostgreSQL ARRAY and HSTORE. 

821 

822 """ 

823 return self.operate(getitem, index) 

824 

825 def __lshift__(self, other: Any) -> ColumnOperators: 

826 """Implement the ``<<`` operator. 

827 

828 Not used by SQLAlchemy core, this is provided 

829 for custom operator systems which want to use 

830 << as an extension point. 

831 """ 

832 return self.operate(lshift, other) 

833 

834 def __rlshift__(self, other: Any) -> ColumnOperators: 

835 """Implement the ``<<`` operator in reverse. 

836 

837 Not used by SQLAlchemy core, this is provided 

838 for custom operator systems which want to use 

839 << as an extension point. 

840 """ 

841 return self.reverse_operate(lshift, other) 

842 

843 def __rshift__(self, other: Any) -> ColumnOperators: 

844 """Implement the ``>>`` operator. 

845 

846 Not used by SQLAlchemy core, this is provided 

847 for custom operator systems which want to use 

848 >> as an extension point. 

849 """ 

850 return self.operate(rshift, other) 

851 

852 def __rrshift__(self, other: Any) -> ColumnOperators: 

853 """Implement the ``>>`` operator in reverse. 

854 

855 Not used by SQLAlchemy core, this is provided 

856 for custom operator systems which want to use 

857 >> as an extension point. 

858 """ 

859 return self.reverse_operate(rshift, other) 

860 

861 def __matmul__(self, other: Any) -> ColumnOperators: 

862 """Implement the ``@`` operator. 

863 

864 Not used by SQLAlchemy core, this is provided 

865 for custom operator systems which want to use 

866 @ as an extension point. 

867 """ 

868 return self.operate(matmul, other) 

869 

870 def __rmatmul__(self, other: Any) -> ColumnOperators: 

871 """Implement the ``@`` operator in reverse. 

872 

873 Not used by SQLAlchemy core, this is provided 

874 for custom operator systems which want to use 

875 @ as an extension point. 

876 """ 

877 return self.reverse_operate(matmul, other) 

878 

879 def concat(self, other: Any) -> ColumnOperators: 

880 """Implement the 'concat' operator. 

881 

882 In a column context, produces the clause ``a || b``, 

883 or uses the ``concat()`` operator on MySQL. 

884 

885 """ 

886 return self.operate(concat_op, other) 

887 

888 def _rconcat(self, other: Any) -> ColumnOperators: 

889 """Implement an 'rconcat' operator. 

890 

891 this is for internal use at the moment 

892 

893 .. versionadded:: 1.4.40 

894 

895 """ 

896 return self.reverse_operate(concat_op, other) 

897 

898 def like( 

899 self, other: Any, escape: Optional[str] = None 

900 ) -> ColumnOperators: 

901 r"""Implement the ``like`` operator. 

902 

903 In a column context, produces the expression: 

904 

905 .. sourcecode:: sql 

906 

907 a LIKE other 

908 

909 E.g.:: 

910 

911 stmt = select(sometable).where(sometable.c.column.like("%foobar%")) 

912 

913 :param other: expression to be compared 

914 :param escape: optional escape character, renders the ``ESCAPE`` 

915 keyword, e.g.:: 

916 

917 somecolumn.like("foo/%bar", escape="/") 

918 

919 .. seealso:: 

920 

921 :meth:`.ColumnOperators.ilike` 

922 

923 """ 

924 return self.operate(like_op, other, escape=escape) 

925 

926 def ilike( 

927 self, other: Any, escape: Optional[str] = None 

928 ) -> ColumnOperators: 

929 r"""Implement the ``ilike`` operator, e.g. case insensitive LIKE. 

930 

931 In a column context, produces an expression either of the form: 

932 

933 .. sourcecode:: sql 

934 

935 lower(a) LIKE lower(other) 

936 

937 Or on backends that support the ILIKE operator: 

938 

939 .. sourcecode:: sql 

940 

941 a ILIKE other 

942 

943 E.g.:: 

944 

945 stmt = select(sometable).where(sometable.c.column.ilike("%foobar%")) 

946 

947 :param other: expression to be compared 

948 :param escape: optional escape character, renders the ``ESCAPE`` 

949 keyword, e.g.:: 

950 

951 somecolumn.ilike("foo/%bar", escape="/") 

952 

953 .. seealso:: 

954 

955 :meth:`.ColumnOperators.like` 

956 

957 """ # noqa: E501 

958 return self.operate(ilike_op, other, escape=escape) 

959 

960 def bitwise_xor(self, other: Any) -> ColumnOperators: 

961 """Produce a bitwise XOR operation, typically via the ``^`` 

962 operator, or ``#`` for PostgreSQL. 

963 

964 .. versionadded:: 2.0.2 

965 

966 .. seealso:: 

967 

968 :ref:`operators_bitwise` 

969 

970 """ 

971 

972 return self.operate(bitwise_xor_op, other) 

973 

974 def bitwise_or(self, other: Any) -> ColumnOperators: 

975 """Produce a bitwise OR operation, typically via the ``|`` 

976 operator. 

977 

978 .. versionadded:: 2.0.2 

979 

980 .. seealso:: 

981 

982 :ref:`operators_bitwise` 

983 

984 """ 

985 

986 return self.operate(bitwise_or_op, other) 

987 

988 def bitwise_and(self, other: Any) -> ColumnOperators: 

989 """Produce a bitwise AND operation, typically via the ``&`` 

990 operator. 

991 

992 .. versionadded:: 2.0.2 

993 

994 .. seealso:: 

995 

996 :ref:`operators_bitwise` 

997 

998 """ 

999 

1000 return self.operate(bitwise_and_op, other) 

1001 

1002 def bitwise_not(self) -> ColumnOperators: 

1003 """Produce a bitwise NOT operation, typically via the ``~`` 

1004 operator. 

1005 

1006 .. versionadded:: 2.0.2 

1007 

1008 .. seealso:: 

1009 

1010 :ref:`operators_bitwise` 

1011 

1012 """ 

1013 

1014 return self.operate(bitwise_not_op) 

1015 

1016 def bitwise_lshift(self, other: Any) -> ColumnOperators: 

1017 """Produce a bitwise LSHIFT operation, typically via the ``<<`` 

1018 operator. 

1019 

1020 .. versionadded:: 2.0.2 

1021 

1022 .. seealso:: 

1023 

1024 :ref:`operators_bitwise` 

1025 

1026 """ 

1027 

1028 return self.operate(bitwise_lshift_op, other) 

1029 

1030 def bitwise_rshift(self, other: Any) -> ColumnOperators: 

1031 """Produce a bitwise RSHIFT operation, typically via the ``>>`` 

1032 operator. 

1033 

1034 .. versionadded:: 2.0.2 

1035 

1036 .. seealso:: 

1037 

1038 :ref:`operators_bitwise` 

1039 

1040 """ 

1041 

1042 return self.operate(bitwise_rshift_op, other) 

1043 

1044 def in_(self, other: Any) -> ColumnOperators: 

1045 """Implement the ``in`` operator. 

1046 

1047 In a column context, produces the clause ``column IN <other>``. 

1048 

1049 The given parameter ``other`` may be: 

1050 

1051 * A list of literal values, 

1052 e.g.:: 

1053 

1054 stmt.where(column.in_([1, 2, 3])) 

1055 

1056 In this calling form, the list of items is converted to a set of 

1057 bound parameters the same length as the list given: 

1058 

1059 .. sourcecode:: sql 

1060 

1061 WHERE COL IN (?, ?, ?) 

1062 

1063 * A list of tuples may be provided if the comparison is against a 

1064 :func:`.tuple_` containing multiple expressions:: 

1065 

1066 from sqlalchemy import tuple_ 

1067 

1068 stmt.where(tuple_(col1, col2).in_([(1, 10), (2, 20), (3, 30)])) 

1069 

1070 * An empty list, 

1071 e.g.:: 

1072 

1073 stmt.where(column.in_([])) 

1074 

1075 In this calling form, the expression renders an "empty set" 

1076 expression. These expressions are tailored to individual backends 

1077 and are generally trying to get an empty SELECT statement as a 

1078 subquery. Such as on SQLite, the expression is: 

1079 

1080 .. sourcecode:: sql 

1081 

1082 WHERE col IN (SELECT 1 FROM (SELECT 1) WHERE 1!=1) 

1083 

1084 .. versionchanged:: 1.4 empty IN expressions now use an 

1085 execution-time generated SELECT subquery in all cases. 

1086 

1087 * A bound parameter, e.g. :func:`.bindparam`, may be used if it 

1088 includes the :paramref:`.bindparam.expanding` flag:: 

1089 

1090 stmt.where(column.in_(bindparam("value", expanding=True))) 

1091 

1092 In this calling form, the expression renders a special non-SQL 

1093 placeholder expression that looks like: 

1094 

1095 .. sourcecode:: sql 

1096 

1097 WHERE COL IN ([EXPANDING_value]) 

1098 

1099 This placeholder expression is intercepted at statement execution 

1100 time to be converted into the variable number of bound parameter 

1101 form illustrated earlier. If the statement were executed as:: 

1102 

1103 connection.execute(stmt, {"value": [1, 2, 3]}) 

1104 

1105 The database would be passed a bound parameter for each value: 

1106 

1107 .. sourcecode:: sql 

1108 

1109 WHERE COL IN (?, ?, ?) 

1110 

1111 If an empty list is passed, a special "empty list" expression, 

1112 which is specific to the database in use, is rendered. On 

1113 SQLite this would be: 

1114 

1115 .. sourcecode:: sql 

1116 

1117 WHERE COL IN (SELECT 1 FROM (SELECT 1) WHERE 1!=1) 

1118 

1119 * a :func:`_expression.select` construct, which is usually a 

1120 correlated scalar select:: 

1121 

1122 stmt.where( 

1123 column.in_(select(othertable.c.y).where(table.c.x == othertable.c.x)) 

1124 ) 

1125 

1126 In this calling form, :meth:`.ColumnOperators.in_` renders as given: 

1127 

1128 .. sourcecode:: sql 

1129 

1130 WHERE COL IN (SELECT othertable.y 

1131 FROM othertable WHERE othertable.x = table.x) 

1132 

1133 :param other: a list of literals, a :func:`_expression.select` 

1134 construct, or a :func:`.bindparam` construct that includes the 

1135 :paramref:`.bindparam.expanding` flag set to True. 

1136 

1137 """ # noqa: E501 

1138 return self.operate(in_op, other) 

1139 

1140 def not_in(self, other: Any) -> ColumnOperators: 

1141 """implement the ``NOT IN`` operator. 

1142 

1143 This is equivalent to using negation with 

1144 :meth:`.ColumnOperators.in_`, i.e. ``~x.in_(y)``. 

1145 

1146 In the case that ``other`` is an empty sequence, the compiler 

1147 produces an "empty not in" expression. This defaults to the 

1148 expression "1 = 1" to produce true in all cases. The 

1149 :paramref:`_sa.create_engine.empty_in_strategy` may be used to 

1150 alter this behavior. 

1151 

1152 .. versionchanged:: 1.4 The ``not_in()`` operator is renamed from 

1153 ``notin_()`` in previous releases. The previous name remains 

1154 available for backwards compatibility. 

1155 

1156 .. seealso:: 

1157 

1158 :meth:`.ColumnOperators.in_` 

1159 

1160 """ 

1161 return self.operate(not_in_op, other) 

1162 

1163 # deprecated 1.4; see #5429 

1164 if TYPE_CHECKING: 

1165 

1166 def notin_(self, other: Any) -> ColumnOperators: ... 

1167 

1168 else: 

1169 notin_ = not_in 

1170 

1171 def not_like( 

1172 self, other: Any, escape: Optional[str] = None 

1173 ) -> ColumnOperators: 

1174 """implement the ``NOT LIKE`` operator. 

1175 

1176 This is equivalent to using negation with 

1177 :meth:`.ColumnOperators.like`, i.e. ``~x.like(y)``. 

1178 

1179 .. versionchanged:: 1.4 The ``not_like()`` operator is renamed from 

1180 ``notlike()`` in previous releases. The previous name remains 

1181 available for backwards compatibility. 

1182 

1183 .. seealso:: 

1184 

1185 :meth:`.ColumnOperators.like` 

1186 

1187 """ 

1188 return self.operate(not_like_op, other, escape=escape) 

1189 

1190 # deprecated 1.4; see #5435 

1191 if TYPE_CHECKING: 

1192 

1193 def notlike( 

1194 self, other: Any, escape: Optional[str] = None 

1195 ) -> ColumnOperators: ... 

1196 

1197 else: 

1198 notlike = not_like 

1199 

1200 def not_ilike( 

1201 self, other: Any, escape: Optional[str] = None 

1202 ) -> ColumnOperators: 

1203 """implement the ``NOT ILIKE`` operator. 

1204 

1205 This is equivalent to using negation with 

1206 :meth:`.ColumnOperators.ilike`, i.e. ``~x.ilike(y)``. 

1207 

1208 .. versionchanged:: 1.4 The ``not_ilike()`` operator is renamed from 

1209 ``notilike()`` in previous releases. The previous name remains 

1210 available for backwards compatibility. 

1211 

1212 .. seealso:: 

1213 

1214 :meth:`.ColumnOperators.ilike` 

1215 

1216 """ 

1217 return self.operate(not_ilike_op, other, escape=escape) 

1218 

1219 # deprecated 1.4; see #5435 

1220 if TYPE_CHECKING: 

1221 

1222 def notilike( 

1223 self, other: Any, escape: Optional[str] = None 

1224 ) -> ColumnOperators: ... 

1225 

1226 else: 

1227 notilike = not_ilike 

1228 

1229 def is_(self, other: Any) -> ColumnOperators: 

1230 """Implement the ``IS`` operator. 

1231 

1232 Normally, ``IS`` is generated automatically when comparing to a 

1233 value of ``None``, which resolves to ``NULL``. However, explicit 

1234 usage of ``IS`` may be desirable if comparing to boolean values 

1235 on certain platforms. 

1236 

1237 .. seealso:: :meth:`.ColumnOperators.is_not` 

1238 

1239 """ 

1240 return self.operate(is_, other) 

1241 

1242 def is_not(self, other: Any) -> ColumnOperators: 

1243 """Implement the ``IS NOT`` operator. 

1244 

1245 Normally, ``IS NOT`` is generated automatically when comparing to a 

1246 value of ``None``, which resolves to ``NULL``. However, explicit 

1247 usage of ``IS NOT`` may be desirable if comparing to boolean values 

1248 on certain platforms. 

1249 

1250 .. versionchanged:: 1.4 The ``is_not()`` operator is renamed from 

1251 ``isnot()`` in previous releases. The previous name remains 

1252 available for backwards compatibility. 

1253 

1254 .. seealso:: :meth:`.ColumnOperators.is_` 

1255 

1256 """ 

1257 return self.operate(is_not, other) 

1258 

1259 # deprecated 1.4; see #5429 

1260 if TYPE_CHECKING: 

1261 

1262 def isnot(self, other: Any) -> ColumnOperators: ... 

1263 

1264 else: 

1265 isnot = is_not 

1266 

1267 def startswith( 

1268 self, 

1269 other: Any, 

1270 escape: Optional[str] = None, 

1271 autoescape: bool = False, 

1272 ) -> ColumnOperators: 

1273 r"""Implement the ``startswith`` operator. 

1274 

1275 Produces a LIKE expression that tests against a match for the start 

1276 of a string value: 

1277 

1278 .. sourcecode:: sql 

1279 

1280 column LIKE <other> || '%' 

1281 

1282 E.g.:: 

1283 

1284 stmt = select(sometable).where(sometable.c.column.startswith("foobar")) 

1285 

1286 Since the operator uses ``LIKE``, wildcard characters 

1287 ``"%"`` and ``"_"`` that are present inside the <other> expression 

1288 will behave like wildcards as well. For literal string 

1289 values, the :paramref:`.ColumnOperators.startswith.autoescape` flag 

1290 may be set to ``True`` to apply escaping to occurrences of these 

1291 characters within the string value so that they match as themselves 

1292 and not as wildcard characters. Alternatively, the 

1293 :paramref:`.ColumnOperators.startswith.escape` parameter will establish 

1294 a given character as an escape character which can be of use when 

1295 the target expression is not a literal string. 

1296 

1297 :param other: expression to be compared. This is usually a plain 

1298 string value, but can also be an arbitrary SQL expression. LIKE 

1299 wildcard characters ``%`` and ``_`` are not escaped by default unless 

1300 the :paramref:`.ColumnOperators.startswith.autoescape` flag is 

1301 set to True. 

1302 

1303 :param autoescape: boolean; when True, establishes an escape character 

1304 within the LIKE expression, then applies it to all occurrences of 

1305 ``"%"``, ``"_"`` and the escape character itself within the 

1306 comparison value, which is assumed to be a literal string and not a 

1307 SQL expression. 

1308 

1309 An expression such as:: 

1310 

1311 somecolumn.startswith("foo%bar", autoescape=True) 

1312 

1313 Will render as: 

1314 

1315 .. sourcecode:: sql 

1316 

1317 somecolumn LIKE :param || '%' ESCAPE '/' 

1318 

1319 With the value of ``:param`` as ``"foo/%bar"``. 

1320 

1321 :param escape: a character which when given will render with the 

1322 ``ESCAPE`` keyword to establish that character as the escape 

1323 character. This character can then be placed preceding occurrences 

1324 of ``%`` and ``_`` to allow them to act as themselves and not 

1325 wildcard characters. 

1326 

1327 An expression such as:: 

1328 

1329 somecolumn.startswith("foo/%bar", escape="^") 

1330 

1331 Will render as: 

1332 

1333 .. sourcecode:: sql 

1334 

1335 somecolumn LIKE :param || '%' ESCAPE '^' 

1336 

1337 The parameter may also be combined with 

1338 :paramref:`.ColumnOperators.startswith.autoescape`:: 

1339 

1340 somecolumn.startswith("foo%bar^bat", escape="^", autoescape=True) 

1341 

1342 Where above, the given literal parameter will be converted to 

1343 ``"foo^%bar^^bat"`` before being passed to the database. 

1344 

1345 .. seealso:: 

1346 

1347 :meth:`.ColumnOperators.endswith` 

1348 

1349 :meth:`.ColumnOperators.contains` 

1350 

1351 :meth:`.ColumnOperators.like` 

1352 

1353 """ # noqa: E501 

1354 return self.operate( 

1355 startswith_op, other, escape=escape, autoescape=autoescape 

1356 ) 

1357 

1358 def istartswith( 

1359 self, 

1360 other: Any, 

1361 escape: Optional[str] = None, 

1362 autoescape: bool = False, 

1363 ) -> ColumnOperators: 

1364 r"""Implement the ``istartswith`` operator, e.g. case insensitive 

1365 version of :meth:`.ColumnOperators.startswith`. 

1366 

1367 Produces a LIKE expression that tests against an insensitive 

1368 match for the start of a string value: 

1369 

1370 .. sourcecode:: sql 

1371 

1372 lower(column) LIKE lower(<other>) || '%' 

1373 

1374 E.g.:: 

1375 

1376 stmt = select(sometable).where(sometable.c.column.istartswith("foobar")) 

1377 

1378 Since the operator uses ``LIKE``, wildcard characters 

1379 ``"%"`` and ``"_"`` that are present inside the <other> expression 

1380 will behave like wildcards as well. For literal string 

1381 values, the :paramref:`.ColumnOperators.istartswith.autoescape` flag 

1382 may be set to ``True`` to apply escaping to occurrences of these 

1383 characters within the string value so that they match as themselves 

1384 and not as wildcard characters. Alternatively, the 

1385 :paramref:`.ColumnOperators.istartswith.escape` parameter will 

1386 establish a given character as an escape character which can be of 

1387 use when the target expression is not a literal string. 

1388 

1389 :param other: expression to be compared. This is usually a plain 

1390 string value, but can also be an arbitrary SQL expression. LIKE 

1391 wildcard characters ``%`` and ``_`` are not escaped by default unless 

1392 the :paramref:`.ColumnOperators.istartswith.autoescape` flag is 

1393 set to True. 

1394 

1395 :param autoescape: boolean; when True, establishes an escape character 

1396 within the LIKE expression, then applies it to all occurrences of 

1397 ``"%"``, ``"_"`` and the escape character itself within the 

1398 comparison value, which is assumed to be a literal string and not a 

1399 SQL expression. 

1400 

1401 An expression such as:: 

1402 

1403 somecolumn.istartswith("foo%bar", autoescape=True) 

1404 

1405 Will render as: 

1406 

1407 .. sourcecode:: sql 

1408 

1409 lower(somecolumn) LIKE lower(:param) || '%' ESCAPE '/' 

1410 

1411 With the value of ``:param`` as ``"foo/%bar"``. 

1412 

1413 :param escape: a character which when given will render with the 

1414 ``ESCAPE`` keyword to establish that character as the escape 

1415 character. This character can then be placed preceding occurrences 

1416 of ``%`` and ``_`` to allow them to act as themselves and not 

1417 wildcard characters. 

1418 

1419 An expression such as:: 

1420 

1421 somecolumn.istartswith("foo/%bar", escape="^") 

1422 

1423 Will render as: 

1424 

1425 .. sourcecode:: sql 

1426 

1427 lower(somecolumn) LIKE lower(:param) || '%' ESCAPE '^' 

1428 

1429 The parameter may also be combined with 

1430 :paramref:`.ColumnOperators.istartswith.autoescape`:: 

1431 

1432 somecolumn.istartswith("foo%bar^bat", escape="^", autoescape=True) 

1433 

1434 Where above, the given literal parameter will be converted to 

1435 ``"foo^%bar^^bat"`` before being passed to the database. 

1436 

1437 .. seealso:: 

1438 

1439 :meth:`.ColumnOperators.startswith` 

1440 """ # noqa: E501 

1441 return self.operate( 

1442 istartswith_op, other, escape=escape, autoescape=autoescape 

1443 ) 

1444 

1445 def endswith( 

1446 self, 

1447 other: Any, 

1448 escape: Optional[str] = None, 

1449 autoescape: bool = False, 

1450 ) -> ColumnOperators: 

1451 r"""Implement the 'endswith' operator. 

1452 

1453 Produces a LIKE expression that tests against a match for the end 

1454 of a string value: 

1455 

1456 .. sourcecode:: sql 

1457 

1458 column LIKE '%' || <other> 

1459 

1460 E.g.:: 

1461 

1462 stmt = select(sometable).where(sometable.c.column.endswith("foobar")) 

1463 

1464 Since the operator uses ``LIKE``, wildcard characters 

1465 ``"%"`` and ``"_"`` that are present inside the <other> expression 

1466 will behave like wildcards as well. For literal string 

1467 values, the :paramref:`.ColumnOperators.endswith.autoescape` flag 

1468 may be set to ``True`` to apply escaping to occurrences of these 

1469 characters within the string value so that they match as themselves 

1470 and not as wildcard characters. Alternatively, the 

1471 :paramref:`.ColumnOperators.endswith.escape` parameter will establish 

1472 a given character as an escape character which can be of use when 

1473 the target expression is not a literal string. 

1474 

1475 :param other: expression to be compared. This is usually a plain 

1476 string value, but can also be an arbitrary SQL expression. LIKE 

1477 wildcard characters ``%`` and ``_`` are not escaped by default unless 

1478 the :paramref:`.ColumnOperators.endswith.autoescape` flag is 

1479 set to True. 

1480 

1481 :param autoescape: boolean; when True, establishes an escape character 

1482 within the LIKE expression, then applies it to all occurrences of 

1483 ``"%"``, ``"_"`` and the escape character itself within the 

1484 comparison value, which is assumed to be a literal string and not a 

1485 SQL expression. 

1486 

1487 An expression such as:: 

1488 

1489 somecolumn.endswith("foo%bar", autoescape=True) 

1490 

1491 Will render as: 

1492 

1493 .. sourcecode:: sql 

1494 

1495 somecolumn LIKE '%' || :param ESCAPE '/' 

1496 

1497 With the value of ``:param`` as ``"foo/%bar"``. 

1498 

1499 :param escape: a character which when given will render with the 

1500 ``ESCAPE`` keyword to establish that character as the escape 

1501 character. This character can then be placed preceding occurrences 

1502 of ``%`` and ``_`` to allow them to act as themselves and not 

1503 wildcard characters. 

1504 

1505 An expression such as:: 

1506 

1507 somecolumn.endswith("foo/%bar", escape="^") 

1508 

1509 Will render as: 

1510 

1511 .. sourcecode:: sql 

1512 

1513 somecolumn LIKE '%' || :param ESCAPE '^' 

1514 

1515 The parameter may also be combined with 

1516 :paramref:`.ColumnOperators.endswith.autoescape`:: 

1517 

1518 somecolumn.endswith("foo%bar^bat", escape="^", autoescape=True) 

1519 

1520 Where above, the given literal parameter will be converted to 

1521 ``"foo^%bar^^bat"`` before being passed to the database. 

1522 

1523 .. seealso:: 

1524 

1525 :meth:`.ColumnOperators.startswith` 

1526 

1527 :meth:`.ColumnOperators.contains` 

1528 

1529 :meth:`.ColumnOperators.like` 

1530 

1531 """ # noqa: E501 

1532 return self.operate( 

1533 endswith_op, other, escape=escape, autoescape=autoescape 

1534 ) 

1535 

1536 def iendswith( 

1537 self, 

1538 other: Any, 

1539 escape: Optional[str] = None, 

1540 autoescape: bool = False, 

1541 ) -> ColumnOperators: 

1542 r"""Implement the ``iendswith`` operator, e.g. case insensitive 

1543 version of :meth:`.ColumnOperators.endswith`. 

1544 

1545 Produces a LIKE expression that tests against an insensitive match 

1546 for the end of a string value: 

1547 

1548 .. sourcecode:: sql 

1549 

1550 lower(column) LIKE '%' || lower(<other>) 

1551 

1552 E.g.:: 

1553 

1554 stmt = select(sometable).where(sometable.c.column.iendswith("foobar")) 

1555 

1556 Since the operator uses ``LIKE``, wildcard characters 

1557 ``"%"`` and ``"_"`` that are present inside the <other> expression 

1558 will behave like wildcards as well. For literal string 

1559 values, the :paramref:`.ColumnOperators.iendswith.autoescape` flag 

1560 may be set to ``True`` to apply escaping to occurrences of these 

1561 characters within the string value so that they match as themselves 

1562 and not as wildcard characters. Alternatively, the 

1563 :paramref:`.ColumnOperators.iendswith.escape` parameter will establish 

1564 a given character as an escape character which can be of use when 

1565 the target expression is not a literal string. 

1566 

1567 :param other: expression to be compared. This is usually a plain 

1568 string value, but can also be an arbitrary SQL expression. LIKE 

1569 wildcard characters ``%`` and ``_`` are not escaped by default unless 

1570 the :paramref:`.ColumnOperators.iendswith.autoescape` flag is 

1571 set to True. 

1572 

1573 :param autoescape: boolean; when True, establishes an escape character 

1574 within the LIKE expression, then applies it to all occurrences of 

1575 ``"%"``, ``"_"`` and the escape character itself within the 

1576 comparison value, which is assumed to be a literal string and not a 

1577 SQL expression. 

1578 

1579 An expression such as:: 

1580 

1581 somecolumn.iendswith("foo%bar", autoescape=True) 

1582 

1583 Will render as: 

1584 

1585 .. sourcecode:: sql 

1586 

1587 lower(somecolumn) LIKE '%' || lower(:param) ESCAPE '/' 

1588 

1589 With the value of ``:param`` as ``"foo/%bar"``. 

1590 

1591 :param escape: a character which when given will render with the 

1592 ``ESCAPE`` keyword to establish that character as the escape 

1593 character. This character can then be placed preceding occurrences 

1594 of ``%`` and ``_`` to allow them to act as themselves and not 

1595 wildcard characters. 

1596 

1597 An expression such as:: 

1598 

1599 somecolumn.iendswith("foo/%bar", escape="^") 

1600 

1601 Will render as: 

1602 

1603 .. sourcecode:: sql 

1604 

1605 lower(somecolumn) LIKE '%' || lower(:param) ESCAPE '^' 

1606 

1607 The parameter may also be combined with 

1608 :paramref:`.ColumnOperators.iendswith.autoescape`:: 

1609 

1610 somecolumn.endswith("foo%bar^bat", escape="^", autoescape=True) 

1611 

1612 Where above, the given literal parameter will be converted to 

1613 ``"foo^%bar^^bat"`` before being passed to the database. 

1614 

1615 .. seealso:: 

1616 

1617 :meth:`.ColumnOperators.endswith` 

1618 """ # noqa: E501 

1619 return self.operate( 

1620 iendswith_op, other, escape=escape, autoescape=autoescape 

1621 ) 

1622 

1623 def contains(self, other: Any, **kw: Any) -> ColumnOperators: 

1624 r"""Implement the 'contains' operator. 

1625 

1626 Produces a LIKE expression that tests against a match for the middle 

1627 of a string value: 

1628 

1629 .. sourcecode:: sql 

1630 

1631 column LIKE '%' || <other> || '%' 

1632 

1633 E.g.:: 

1634 

1635 stmt = select(sometable).where(sometable.c.column.contains("foobar")) 

1636 

1637 Since the operator uses ``LIKE``, wildcard characters 

1638 ``"%"`` and ``"_"`` that are present inside the <other> expression 

1639 will behave like wildcards as well. For literal string 

1640 values, the :paramref:`.ColumnOperators.contains.autoescape` flag 

1641 may be set to ``True`` to apply escaping to occurrences of these 

1642 characters within the string value so that they match as themselves 

1643 and not as wildcard characters. Alternatively, the 

1644 :paramref:`.ColumnOperators.contains.escape` parameter will establish 

1645 a given character as an escape character which can be of use when 

1646 the target expression is not a literal string. 

1647 

1648 :param other: expression to be compared. This is usually a plain 

1649 string value, but can also be an arbitrary SQL expression. LIKE 

1650 wildcard characters ``%`` and ``_`` are not escaped by default unless 

1651 the :paramref:`.ColumnOperators.contains.autoescape` flag is 

1652 set to True. 

1653 

1654 :param autoescape: boolean; when True, establishes an escape character 

1655 within the LIKE expression, then applies it to all occurrences of 

1656 ``"%"``, ``"_"`` and the escape character itself within the 

1657 comparison value, which is assumed to be a literal string and not a 

1658 SQL expression. 

1659 

1660 An expression such as:: 

1661 

1662 somecolumn.contains("foo%bar", autoescape=True) 

1663 

1664 Will render as: 

1665 

1666 .. sourcecode:: sql 

1667 

1668 somecolumn LIKE '%' || :param || '%' ESCAPE '/' 

1669 

1670 With the value of ``:param`` as ``"foo/%bar"``. 

1671 

1672 :param escape: a character which when given will render with the 

1673 ``ESCAPE`` keyword to establish that character as the escape 

1674 character. This character can then be placed preceding occurrences 

1675 of ``%`` and ``_`` to allow them to act as themselves and not 

1676 wildcard characters. 

1677 

1678 An expression such as:: 

1679 

1680 somecolumn.contains("foo/%bar", escape="^") 

1681 

1682 Will render as: 

1683 

1684 .. sourcecode:: sql 

1685 

1686 somecolumn LIKE '%' || :param || '%' ESCAPE '^' 

1687 

1688 The parameter may also be combined with 

1689 :paramref:`.ColumnOperators.contains.autoescape`:: 

1690 

1691 somecolumn.contains("foo%bar^bat", escape="^", autoescape=True) 

1692 

1693 Where above, the given literal parameter will be converted to 

1694 ``"foo^%bar^^bat"`` before being passed to the database. 

1695 

1696 .. seealso:: 

1697 

1698 :meth:`.ColumnOperators.startswith` 

1699 

1700 :meth:`.ColumnOperators.endswith` 

1701 

1702 :meth:`.ColumnOperators.like` 

1703 

1704 

1705 """ # noqa: E501 

1706 return self.operate(contains_op, other, **kw) 

1707 

1708 def icontains(self, other: Any, **kw: Any) -> ColumnOperators: 

1709 r"""Implement the ``icontains`` operator, e.g. case insensitive 

1710 version of :meth:`.ColumnOperators.contains`. 

1711 

1712 Produces a LIKE expression that tests against an insensitive match 

1713 for the middle of a string value: 

1714 

1715 .. sourcecode:: sql 

1716 

1717 lower(column) LIKE '%' || lower(<other>) || '%' 

1718 

1719 E.g.:: 

1720 

1721 stmt = select(sometable).where(sometable.c.column.icontains("foobar")) 

1722 

1723 Since the operator uses ``LIKE``, wildcard characters 

1724 ``"%"`` and ``"_"`` that are present inside the <other> expression 

1725 will behave like wildcards as well. For literal string 

1726 values, the :paramref:`.ColumnOperators.icontains.autoescape` flag 

1727 may be set to ``True`` to apply escaping to occurrences of these 

1728 characters within the string value so that they match as themselves 

1729 and not as wildcard characters. Alternatively, the 

1730 :paramref:`.ColumnOperators.icontains.escape` parameter will establish 

1731 a given character as an escape character which can be of use when 

1732 the target expression is not a literal string. 

1733 

1734 :param other: expression to be compared. This is usually a plain 

1735 string value, but can also be an arbitrary SQL expression. LIKE 

1736 wildcard characters ``%`` and ``_`` are not escaped by default unless 

1737 the :paramref:`.ColumnOperators.icontains.autoescape` flag is 

1738 set to True. 

1739 

1740 :param autoescape: boolean; when True, establishes an escape character 

1741 within the LIKE expression, then applies it to all occurrences of 

1742 ``"%"``, ``"_"`` and the escape character itself within the 

1743 comparison value, which is assumed to be a literal string and not a 

1744 SQL expression. 

1745 

1746 An expression such as:: 

1747 

1748 somecolumn.icontains("foo%bar", autoescape=True) 

1749 

1750 Will render as: 

1751 

1752 .. sourcecode:: sql 

1753 

1754 lower(somecolumn) LIKE '%' || lower(:param) || '%' ESCAPE '/' 

1755 

1756 With the value of ``:param`` as ``"foo/%bar"``. 

1757 

1758 :param escape: a character which when given will render with the 

1759 ``ESCAPE`` keyword to establish that character as the escape 

1760 character. This character can then be placed preceding occurrences 

1761 of ``%`` and ``_`` to allow them to act as themselves and not 

1762 wildcard characters. 

1763 

1764 An expression such as:: 

1765 

1766 somecolumn.icontains("foo/%bar", escape="^") 

1767 

1768 Will render as: 

1769 

1770 .. sourcecode:: sql 

1771 

1772 lower(somecolumn) LIKE '%' || lower(:param) || '%' ESCAPE '^' 

1773 

1774 The parameter may also be combined with 

1775 :paramref:`.ColumnOperators.contains.autoescape`:: 

1776 

1777 somecolumn.icontains("foo%bar^bat", escape="^", autoescape=True) 

1778 

1779 Where above, the given literal parameter will be converted to 

1780 ``"foo^%bar^^bat"`` before being passed to the database. 

1781 

1782 .. seealso:: 

1783 

1784 :meth:`.ColumnOperators.contains` 

1785 

1786 """ # noqa: E501 

1787 return self.operate(icontains_op, other, **kw) 

1788 

1789 def match(self, other: Any, **kwargs: Any) -> ColumnOperators: 

1790 """Implements a database-specific 'match' operator. 

1791 

1792 :meth:`_sql.ColumnOperators.match` attempts to resolve to 

1793 a MATCH-like function or operator provided by the backend. 

1794 Examples include: 

1795 

1796 * PostgreSQL - renders ``x @@ plainto_tsquery(y)`` 

1797 

1798 .. versionchanged:: 2.0 ``plainto_tsquery()`` is used instead 

1799 of ``to_tsquery()`` for PostgreSQL now; for compatibility with 

1800 other forms, see :ref:`postgresql_match`. 

1801 

1802 

1803 * MySQL - renders ``MATCH (x) AGAINST (y IN BOOLEAN MODE)`` 

1804 

1805 .. seealso:: 

1806 

1807 :class:`_mysql.match` - MySQL specific construct with 

1808 additional features. 

1809 

1810 * Oracle Database - renders ``CONTAINS(x, y)`` 

1811 * other backends may provide special implementations. 

1812 * Backends without any special implementation will emit 

1813 the operator as "MATCH". This is compatible with SQLite, for 

1814 example. 

1815 

1816 """ 

1817 return self.operate(match_op, other, **kwargs) 

1818 

1819 def regexp_match( 

1820 self, pattern: Any, flags: Optional[str] = None 

1821 ) -> ColumnOperators: 

1822 """Implements a database-specific 'regexp match' operator. 

1823 

1824 E.g.:: 

1825 

1826 stmt = select(table.c.some_column).where( 

1827 table.c.some_column.regexp_match("^(b|c)") 

1828 ) 

1829 

1830 :meth:`_sql.ColumnOperators.regexp_match` attempts to resolve to 

1831 a REGEXP-like function or operator provided by the backend, however 

1832 the specific regular expression syntax and flags available are 

1833 **not backend agnostic**. 

1834 

1835 Examples include: 

1836 

1837 * PostgreSQL - renders ``x ~ y`` or ``x !~ y`` when negated. 

1838 * Oracle Database - renders ``REGEXP_LIKE(x, y)`` 

1839 * SQLite - uses SQLite's ``REGEXP`` placeholder operator and calls into 

1840 the Python ``re.match()`` builtin. 

1841 * other backends may provide special implementations. 

1842 * Backends without any special implementation will emit 

1843 the operator as "REGEXP" or "NOT REGEXP". This is compatible with 

1844 SQLite and MySQL, for example. 

1845 

1846 Regular expression support is currently implemented for Oracle 

1847 Database, PostgreSQL, MySQL and MariaDB. Partial support is available 

1848 for SQLite. Support among third-party dialects may vary. 

1849 

1850 :param pattern: The regular expression pattern string or column 

1851 clause. 

1852 :param flags: Any regular expression string flags to apply, passed as 

1853 plain Python string only. These flags are backend specific. 

1854 Some backends, like PostgreSQL and MariaDB, may alternatively 

1855 specify the flags as part of the pattern. 

1856 When using the ignore case flag 'i' in PostgreSQL, the ignore case 

1857 regexp match operator ``~*`` or ``!~*`` will be used. 

1858 

1859 .. versionadded:: 1.4 

1860 

1861 .. versionchanged:: 1.4.48, 2.0.18 Note that due to an implementation 

1862 error, the "flags" parameter previously accepted SQL expression 

1863 objects such as column expressions in addition to plain Python 

1864 strings. This implementation did not work correctly with caching 

1865 and was removed; strings only should be passed for the "flags" 

1866 parameter, as these flags are rendered as literal inline values 

1867 within SQL expressions. 

1868 

1869 .. seealso:: 

1870 

1871 :meth:`_sql.ColumnOperators.regexp_replace` 

1872 

1873 

1874 """ 

1875 return self.operate(regexp_match_op, pattern, flags=flags) 

1876 

1877 def regexp_replace( 

1878 self, pattern: Any, replacement: Any, flags: Optional[str] = None 

1879 ) -> ColumnOperators: 

1880 """Implements a database-specific 'regexp replace' operator. 

1881 

1882 E.g.:: 

1883 

1884 stmt = select( 

1885 table.c.some_column.regexp_replace("b(..)", "X\1Y", flags="g") 

1886 ) 

1887 

1888 :meth:`_sql.ColumnOperators.regexp_replace` attempts to resolve to 

1889 a REGEXP_REPLACE-like function provided by the backend, that 

1890 usually emit the function ``REGEXP_REPLACE()``. However, 

1891 the specific regular expression syntax and flags available are 

1892 **not backend agnostic**. 

1893 

1894 Regular expression replacement support is currently implemented for 

1895 Oracle Database, PostgreSQL, MySQL 8 or greater and MariaDB. Support 

1896 among third-party dialects may vary. 

1897 

1898 :param pattern: The regular expression pattern string or column 

1899 clause. 

1900 :param pattern: The replacement string or column clause. 

1901 :param flags: Any regular expression string flags to apply, passed as 

1902 plain Python string only. These flags are backend specific. 

1903 Some backends, like PostgreSQL and MariaDB, may alternatively 

1904 specify the flags as part of the pattern. 

1905 

1906 .. versionadded:: 1.4 

1907 

1908 .. versionchanged:: 1.4.48, 2.0.18 Note that due to an implementation 

1909 error, the "flags" parameter previously accepted SQL expression 

1910 objects such as column expressions in addition to plain Python 

1911 strings. This implementation did not work correctly with caching 

1912 and was removed; strings only should be passed for the "flags" 

1913 parameter, as these flags are rendered as literal inline values 

1914 within SQL expressions. 

1915 

1916 

1917 .. seealso:: 

1918 

1919 :meth:`_sql.ColumnOperators.regexp_match` 

1920 

1921 """ 

1922 return self.operate( 

1923 regexp_replace_op, 

1924 pattern, 

1925 replacement=replacement, 

1926 flags=flags, 

1927 ) 

1928 

1929 def collate(self, collation: str) -> ColumnOperators: 

1930 """Produce a :func:`_expression.collate` clause against 

1931 the parent object, given the collation string. 

1932 

1933 .. seealso:: 

1934 

1935 :func:`_expression.collate` 

1936 

1937 """ 

1938 return self.operate(collate, collation) 

1939 

1940 def __radd__(self, other: Any) -> ColumnOperators: 

1941 """Implement the ``+`` operator in reverse. 

1942 

1943 See :meth:`.ColumnOperators.__add__`. 

1944 

1945 """ 

1946 return self.reverse_operate(add, other) 

1947 

1948 def __rsub__(self, other: Any) -> ColumnOperators: 

1949 """Implement the ``-`` operator in reverse. 

1950 

1951 See :meth:`.ColumnOperators.__sub__`. 

1952 

1953 """ 

1954 return self.reverse_operate(sub, other) 

1955 

1956 def __rmul__(self, other: Any) -> ColumnOperators: 

1957 """Implement the ``*`` operator in reverse. 

1958 

1959 See :meth:`.ColumnOperators.__mul__`. 

1960 

1961 """ 

1962 return self.reverse_operate(mul, other) 

1963 

1964 def __rmod__(self, other: Any) -> ColumnOperators: 

1965 """Implement the ``%`` operator in reverse. 

1966 

1967 See :meth:`.ColumnOperators.__mod__`. 

1968 

1969 """ 

1970 return self.reverse_operate(mod, other) 

1971 

1972 def between( 

1973 self, cleft: Any, cright: Any, symmetric: bool = False 

1974 ) -> ColumnOperators: 

1975 """Produce a :func:`_expression.between` clause against 

1976 the parent object, given the lower and upper range. 

1977 

1978 """ 

1979 return self.operate(between_op, cleft, cright, symmetric=symmetric) 

1980 

1981 def distinct(self) -> ColumnOperators: 

1982 """Produce a :func:`_expression.distinct` clause against the 

1983 parent object. 

1984 

1985 """ 

1986 return self.operate(distinct_op) 

1987 

1988 def any_(self) -> ColumnOperators: 

1989 """Produce an :func:`_expression.any_` clause against the 

1990 parent object. 

1991 

1992 See the documentation for :func:`_sql.any_` for examples. 

1993 

1994 .. note:: be sure to not confuse the newer 

1995 :meth:`_sql.ColumnOperators.any_` method with the **legacy** 

1996 version of this method, the :meth:`_types.ARRAY.Comparator.any` 

1997 method that's specific to :class:`_types.ARRAY`, which uses a 

1998 different calling style. 

1999 

2000 """ 

2001 return self.operate(any_op) 

2002 

2003 def all_(self) -> ColumnOperators: 

2004 """Produce an :func:`_expression.all_` clause against the 

2005 parent object. 

2006 

2007 See the documentation for :func:`_sql.all_` for examples. 

2008 

2009 .. note:: be sure to not confuse the newer 

2010 :meth:`_sql.ColumnOperators.all_` method with the **legacy** 

2011 version of this method, the :meth:`_types.ARRAY.Comparator.all` 

2012 method that's specific to :class:`_types.ARRAY`, which uses a 

2013 different calling style. 

2014 

2015 """ 

2016 return self.operate(all_op) 

2017 

2018 def __add__(self, other: Any) -> ColumnOperators: 

2019 """Implement the ``+`` operator. 

2020 

2021 In a column context, produces the clause ``a + b`` 

2022 if the parent object has non-string affinity. 

2023 If the parent object has a string affinity, 

2024 produces the concatenation operator, ``a || b`` - 

2025 see :meth:`.ColumnOperators.concat`. 

2026 

2027 """ 

2028 return self.operate(add, other) 

2029 

2030 def __sub__(self, other: Any) -> ColumnOperators: 

2031 """Implement the ``-`` operator. 

2032 

2033 In a column context, produces the clause ``a - b``. 

2034 

2035 """ 

2036 return self.operate(sub, other) 

2037 

2038 def __mul__(self, other: Any) -> ColumnOperators: 

2039 """Implement the ``*`` operator. 

2040 

2041 In a column context, produces the clause ``a * b``. 

2042 

2043 """ 

2044 return self.operate(mul, other) 

2045 

2046 def __mod__(self, other: Any) -> ColumnOperators: 

2047 """Implement the ``%`` operator. 

2048 

2049 In a column context, produces the clause ``a % b``. 

2050 

2051 """ 

2052 return self.operate(mod, other) 

2053 

2054 def __truediv__(self, other: Any) -> ColumnOperators: 

2055 """Implement the ``/`` operator. 

2056 

2057 In a column context, produces the clause ``a / b``, and 

2058 considers the result type to be numeric. 

2059 

2060 .. versionchanged:: 2.0 The truediv operator against two integers 

2061 is now considered to return a numeric value. Behavior on specific 

2062 backends may vary. 

2063 

2064 """ 

2065 return self.operate(truediv, other) 

2066 

2067 def __rtruediv__(self, other: Any) -> ColumnOperators: 

2068 """Implement the ``/`` operator in reverse. 

2069 

2070 See :meth:`.ColumnOperators.__truediv__`. 

2071 

2072 """ 

2073 return self.reverse_operate(truediv, other) 

2074 

2075 def __floordiv__(self, other: Any) -> ColumnOperators: 

2076 """Implement the ``//`` operator. 

2077 

2078 In a column context, produces the clause ``a / b``, 

2079 which is the same as "truediv", but considers the result 

2080 type to be integer. 

2081 

2082 .. versionadded:: 2.0 

2083 

2084 """ 

2085 return self.operate(floordiv, other) 

2086 

2087 def __rfloordiv__(self, other: Any) -> ColumnOperators: 

2088 """Implement the ``//`` operator in reverse. 

2089 

2090 See :meth:`.ColumnOperators.__floordiv__`. 

2091 

2092 """ 

2093 return self.reverse_operate(floordiv, other) 

2094 

2095 def __pow__(self, other: Any) -> ColumnOperators: 

2096 """Implement the ``**`` operator. 

2097 

2098 In a column context, produces the clause ``pow(a, b)``, or a similar 

2099 dialect-specific expression. 

2100 

2101 .. versionadded:: 2.1 

2102 

2103 """ 

2104 return self.operate(pow_, other) 

2105 

2106 def __rpow__(self, other: Any) -> ColumnOperators: 

2107 """Implement the ``**`` operator in reverse. 

2108 

2109 .. seealso:: 

2110 

2111 :meth:`.ColumnOperators.__pow__`. 

2112 

2113 .. versionadded:: 2.1 

2114 

2115 """ 

2116 return self.reverse_operate(pow_, other) 

2117 

2118 

2119_commutative: Set[Any] = {eq, ne, add, mul} 

2120_comparison: Set[Any] = {eq, ne, lt, gt, ge, le} 

2121 

2122 

2123def _operator_fn(fn: Callable[..., Any]) -> OperatorType: 

2124 return cast(OperatorType, fn) 

2125 

2126 

2127def commutative_op(fn: _FN) -> _FN: 

2128 _commutative.add(fn) 

2129 return fn 

2130 

2131 

2132def comparison_op(fn: _FN) -> _FN: 

2133 _comparison.add(fn) 

2134 return fn 

2135 

2136 

2137@_operator_fn 

2138def from_() -> Any: 

2139 raise NotImplementedError() 

2140 

2141 

2142@_operator_fn 

2143@comparison_op 

2144def function_as_comparison_op() -> Any: 

2145 raise NotImplementedError() 

2146 

2147 

2148@_operator_fn 

2149def as_() -> Any: 

2150 raise NotImplementedError() 

2151 

2152 

2153@_operator_fn 

2154def exists() -> Any: 

2155 raise NotImplementedError() 

2156 

2157 

2158@_operator_fn 

2159def is_true(a: Any) -> Any: 

2160 raise NotImplementedError() 

2161 

2162 

2163# 1.4 deprecated; see #5435 

2164if TYPE_CHECKING: 

2165 

2166 @_operator_fn 

2167 def istrue(a: Any) -> Any: ... 

2168 

2169else: 

2170 istrue = is_true 

2171 

2172 

2173@_operator_fn 

2174def is_false(a: Any) -> Any: 

2175 raise NotImplementedError() 

2176 

2177 

2178# 1.4 deprecated; see #5435 

2179if TYPE_CHECKING: 

2180 

2181 @_operator_fn 

2182 def isfalse(a: Any) -> Any: ... 

2183 

2184else: 

2185 isfalse = is_false 

2186 

2187 

2188@comparison_op 

2189@_operator_fn 

2190def is_distinct_from(a: Any, b: Any) -> Any: 

2191 return a.is_distinct_from(b) 

2192 

2193 

2194@comparison_op 

2195@_operator_fn 

2196def is_not_distinct_from(a: Any, b: Any) -> Any: 

2197 return a.is_not_distinct_from(b) 

2198 

2199 

2200# deprecated 1.4; see #5435 

2201if TYPE_CHECKING: 

2202 

2203 @_operator_fn 

2204 def isnot_distinct_from(a: Any, b: Any) -> Any: ... 

2205 

2206else: 

2207 isnot_distinct_from = is_not_distinct_from 

2208 

2209 

2210@comparison_op 

2211@_operator_fn 

2212def is_(a: Any, b: Any) -> Any: 

2213 return a.is_(b) 

2214 

2215 

2216@comparison_op 

2217@_operator_fn 

2218def is_not(a: Any, b: Any) -> Any: 

2219 return a.is_not(b) 

2220 

2221 

2222# 1.4 deprecated; see #5429 

2223if TYPE_CHECKING: 

2224 

2225 @_operator_fn 

2226 def isnot(a: Any, b: Any) -> Any: ... 

2227 

2228else: 

2229 isnot = is_not 

2230 

2231 

2232@_operator_fn 

2233def collate(a: Any, b: Any) -> Any: 

2234 return a.collate(b) 

2235 

2236 

2237@_operator_fn 

2238def op(a: Any, opstring: str, b: Any) -> Any: 

2239 return a.op(opstring)(b) 

2240 

2241 

2242@comparison_op 

2243@_operator_fn 

2244def like_op(a: Any, b: Any, escape: Optional[str] = None) -> Any: 

2245 return a.like(b, escape=escape) 

2246 

2247 

2248@comparison_op 

2249@_operator_fn 

2250def not_like_op(a: Any, b: Any, escape: Optional[str] = None) -> Any: 

2251 return a.notlike(b, escape=escape) 

2252 

2253 

2254# 1.4 deprecated; see #5435 

2255if TYPE_CHECKING: 

2256 

2257 @_operator_fn 

2258 def notlike_op(a: Any, b: Any, escape: Optional[str] = None) -> Any: ... 

2259 

2260else: 

2261 notlike_op = not_like_op 

2262 

2263 

2264@comparison_op 

2265@_operator_fn 

2266def ilike_op(a: Any, b: Any, escape: Optional[str] = None) -> Any: 

2267 return a.ilike(b, escape=escape) 

2268 

2269 

2270@comparison_op 

2271@_operator_fn 

2272def not_ilike_op(a: Any, b: Any, escape: Optional[str] = None) -> Any: 

2273 return a.not_ilike(b, escape=escape) 

2274 

2275 

2276# 1.4 deprecated; see #5435 

2277if TYPE_CHECKING: 

2278 

2279 @_operator_fn 

2280 def notilike_op(a: Any, b: Any, escape: Optional[str] = None) -> Any: ... 

2281 

2282else: 

2283 notilike_op = not_ilike_op 

2284 

2285 

2286@comparison_op 

2287@_operator_fn 

2288def between_op(a: Any, b: Any, c: Any, symmetric: bool = False) -> Any: 

2289 return a.between(b, c, symmetric=symmetric) 

2290 

2291 

2292@comparison_op 

2293@_operator_fn 

2294def not_between_op(a: Any, b: Any, c: Any, symmetric: bool = False) -> Any: 

2295 return ~a.between(b, c, symmetric=symmetric) 

2296 

2297 

2298# 1.4 deprecated; see #5435 

2299if TYPE_CHECKING: 

2300 

2301 @_operator_fn 

2302 def notbetween_op( 

2303 a: Any, b: Any, c: Any, symmetric: bool = False 

2304 ) -> Any: ... 

2305 

2306else: 

2307 notbetween_op = not_between_op 

2308 

2309 

2310@comparison_op 

2311@_operator_fn 

2312def in_op(a: Any, b: Any) -> Any: 

2313 return a.in_(b) 

2314 

2315 

2316@comparison_op 

2317@_operator_fn 

2318def not_in_op(a: Any, b: Any) -> Any: 

2319 return a.not_in(b) 

2320 

2321 

2322# 1.4 deprecated; see #5429 

2323if TYPE_CHECKING: 

2324 

2325 @_operator_fn 

2326 def notin_op(a: Any, b: Any) -> Any: ... 

2327 

2328else: 

2329 notin_op = not_in_op 

2330 

2331 

2332@_operator_fn 

2333def distinct_op(a: Any) -> Any: 

2334 return a.distinct() 

2335 

2336 

2337@_operator_fn 

2338def any_op(a: Any) -> Any: 

2339 return a.any_() 

2340 

2341 

2342@_operator_fn 

2343def all_op(a: Any) -> Any: 

2344 return a.all_() 

2345 

2346 

2347def _escaped_like_impl( 

2348 fn: Callable[..., Any], other: Any, escape: Optional[str], autoescape: bool 

2349) -> Any: 

2350 if autoescape: 

2351 if autoescape is not True: 

2352 util.warn( 

2353 "The autoescape parameter is now a simple boolean True/False" 

2354 ) 

2355 if escape is None: 

2356 escape = "/" 

2357 

2358 if not isinstance(other, str): 

2359 raise TypeError("String value expected when autoescape=True") 

2360 

2361 if escape not in ("%", "_"): 

2362 other = other.replace(escape, escape + escape) 

2363 

2364 other = other.replace("%", escape + "%").replace("_", escape + "_") 

2365 

2366 return fn(other, escape=escape) 

2367 

2368 

2369@comparison_op 

2370@_operator_fn 

2371def startswith_op( 

2372 a: Any, b: Any, escape: Optional[str] = None, autoescape: bool = False 

2373) -> Any: 

2374 return _escaped_like_impl(a.startswith, b, escape, autoescape) 

2375 

2376 

2377@comparison_op 

2378@_operator_fn 

2379def not_startswith_op( 

2380 a: Any, b: Any, escape: Optional[str] = None, autoescape: bool = False 

2381) -> Any: 

2382 return ~_escaped_like_impl(a.startswith, b, escape, autoescape) 

2383 

2384 

2385# 1.4 deprecated; see #5435 

2386if TYPE_CHECKING: 

2387 

2388 @_operator_fn 

2389 def notstartswith_op( 

2390 a: Any, b: Any, escape: Optional[str] = None, autoescape: bool = False 

2391 ) -> Any: ... 

2392 

2393else: 

2394 notstartswith_op = not_startswith_op 

2395 

2396 

2397@comparison_op 

2398@_operator_fn 

2399def istartswith_op( 

2400 a: Any, b: Any, escape: Optional[str] = None, autoescape: bool = False 

2401) -> Any: 

2402 return _escaped_like_impl(a.istartswith, b, escape, autoescape) 

2403 

2404 

2405@comparison_op 

2406@_operator_fn 

2407def not_istartswith_op( 

2408 a: Any, b: Any, escape: Optional[str] = None, autoescape: bool = False 

2409) -> Any: 

2410 return ~_escaped_like_impl(a.istartswith, b, escape, autoescape) 

2411 

2412 

2413@comparison_op 

2414@_operator_fn 

2415def endswith_op( 

2416 a: Any, b: Any, escape: Optional[str] = None, autoescape: bool = False 

2417) -> Any: 

2418 return _escaped_like_impl(a.endswith, b, escape, autoescape) 

2419 

2420 

2421@comparison_op 

2422@_operator_fn 

2423def not_endswith_op( 

2424 a: Any, b: Any, escape: Optional[str] = None, autoescape: bool = False 

2425) -> Any: 

2426 return ~_escaped_like_impl(a.endswith, b, escape, autoescape) 

2427 

2428 

2429# 1.4 deprecated; see #5435 

2430if TYPE_CHECKING: 

2431 

2432 @_operator_fn 

2433 def notendswith_op( 

2434 a: Any, b: Any, escape: Optional[str] = None, autoescape: bool = False 

2435 ) -> Any: ... 

2436 

2437else: 

2438 notendswith_op = not_endswith_op 

2439 

2440 

2441@comparison_op 

2442@_operator_fn 

2443def iendswith_op( 

2444 a: Any, b: Any, escape: Optional[str] = None, autoescape: bool = False 

2445) -> Any: 

2446 return _escaped_like_impl(a.iendswith, b, escape, autoescape) 

2447 

2448 

2449@comparison_op 

2450@_operator_fn 

2451def not_iendswith_op( 

2452 a: Any, b: Any, escape: Optional[str] = None, autoescape: bool = False 

2453) -> Any: 

2454 return ~_escaped_like_impl(a.iendswith, b, escape, autoescape) 

2455 

2456 

2457@comparison_op 

2458@_operator_fn 

2459def contains_op( 

2460 a: Any, b: Any, escape: Optional[str] = None, autoescape: bool = False 

2461) -> Any: 

2462 return _escaped_like_impl(a.contains, b, escape, autoescape) 

2463 

2464 

2465@comparison_op 

2466@_operator_fn 

2467def not_contains_op( 

2468 a: Any, b: Any, escape: Optional[str] = None, autoescape: bool = False 

2469) -> Any: 

2470 return ~_escaped_like_impl(a.contains, b, escape, autoescape) 

2471 

2472 

2473# 1.4 deprecated; see #5435 

2474if TYPE_CHECKING: 

2475 

2476 @_operator_fn 

2477 def notcontains_op( 

2478 a: Any, b: Any, escape: Optional[str] = None, autoescape: bool = False 

2479 ) -> Any: ... 

2480 

2481else: 

2482 notcontains_op = not_contains_op 

2483 

2484 

2485@comparison_op 

2486@_operator_fn 

2487def icontains_op( 

2488 a: Any, b: Any, escape: Optional[str] = None, autoescape: bool = False 

2489) -> Any: 

2490 return _escaped_like_impl(a.icontains, b, escape, autoescape) 

2491 

2492 

2493@comparison_op 

2494@_operator_fn 

2495def not_icontains_op( 

2496 a: Any, b: Any, escape: Optional[str] = None, autoescape: bool = False 

2497) -> Any: 

2498 return ~_escaped_like_impl(a.icontains, b, escape, autoescape) 

2499 

2500 

2501@comparison_op 

2502@_operator_fn 

2503def match_op(a: Any, b: Any, **kw: Any) -> Any: 

2504 return a.match(b, **kw) 

2505 

2506 

2507@comparison_op 

2508@_operator_fn 

2509def regexp_match_op(a: Any, b: Any, flags: Optional[str] = None) -> Any: 

2510 return a.regexp_match(b, flags=flags) 

2511 

2512 

2513@comparison_op 

2514@_operator_fn 

2515def not_regexp_match_op(a: Any, b: Any, flags: Optional[str] = None) -> Any: 

2516 return ~a.regexp_match(b, flags=flags) 

2517 

2518 

2519@_operator_fn 

2520def regexp_replace_op( 

2521 a: Any, b: Any, replacement: Any, flags: Optional[str] = None 

2522) -> Any: 

2523 return a.regexp_replace(b, replacement=replacement, flags=flags) 

2524 

2525 

2526@comparison_op 

2527@_operator_fn 

2528def not_match_op(a: Any, b: Any, **kw: Any) -> Any: 

2529 return ~a.match(b, **kw) 

2530 

2531 

2532# 1.4 deprecated; see #5429 

2533if TYPE_CHECKING: 

2534 

2535 @_operator_fn 

2536 def notmatch_op(a: Any, b: Any, **kw: Any) -> Any: ... 

2537 

2538else: 

2539 notmatch_op = not_match_op 

2540 

2541 

2542@_operator_fn 

2543def comma_op(a: Any, b: Any) -> Any: 

2544 raise NotImplementedError() 

2545 

2546 

2547@_operator_fn 

2548def filter_op(a: Any, b: Any) -> Any: 

2549 raise NotImplementedError() 

2550 

2551 

2552@_operator_fn 

2553def concat_op(a: Any, b: Any) -> Any: 

2554 try: 

2555 concat = a.concat 

2556 except AttributeError: 

2557 return b._rconcat(a) 

2558 else: 

2559 return concat(b) 

2560 

2561 

2562@_operator_fn 

2563def desc_op(a: Any) -> Any: 

2564 return a.desc() 

2565 

2566 

2567@_operator_fn 

2568def asc_op(a: Any) -> Any: 

2569 return a.asc() 

2570 

2571 

2572@_operator_fn 

2573def nulls_first_op(a: Any) -> Any: 

2574 return a.nulls_first() 

2575 

2576 

2577# 1.4 deprecated; see #5435 

2578if TYPE_CHECKING: 

2579 

2580 @_operator_fn 

2581 def nullsfirst_op(a: Any) -> Any: ... 

2582 

2583else: 

2584 nullsfirst_op = nulls_first_op 

2585 

2586 

2587@_operator_fn 

2588def nulls_last_op(a: Any) -> Any: 

2589 return a.nulls_last() 

2590 

2591 

2592# 1.4 deprecated; see #5435 

2593if TYPE_CHECKING: 

2594 

2595 @_operator_fn 

2596 def nullslast_op(a: Any) -> Any: ... 

2597 

2598else: 

2599 nullslast_op = nulls_last_op 

2600 

2601 

2602@_operator_fn 

2603def json_getitem_op(a: Any, b: Any) -> Any: 

2604 raise NotImplementedError() 

2605 

2606 

2607@_operator_fn 

2608def json_path_getitem_op(a: Any, b: Any) -> Any: 

2609 raise NotImplementedError() 

2610 

2611 

2612@_operator_fn 

2613def bitwise_xor_op(a: Any, b: Any) -> Any: 

2614 return a.bitwise_xor(b) 

2615 

2616 

2617@_operator_fn 

2618def bitwise_or_op(a: Any, b: Any) -> Any: 

2619 return a.bitwise_or(b) 

2620 

2621 

2622@_operator_fn 

2623def bitwise_and_op(a: Any, b: Any) -> Any: 

2624 return a.bitwise_and(b) 

2625 

2626 

2627@_operator_fn 

2628def bitwise_not_op(a: Any) -> Any: 

2629 return a.bitwise_not() 

2630 

2631 

2632@_operator_fn 

2633def bitwise_lshift_op(a: Any, b: Any) -> Any: 

2634 return a.bitwise_lshift(b) 

2635 

2636 

2637@_operator_fn 

2638def bitwise_rshift_op(a: Any, b: Any) -> Any: 

2639 return a.bitwise_rshift(b) 

2640 

2641 

2642@_operator_fn 

2643def null_op(a: Any, b: Any) -> Any: 

2644 """a 'null' operator that provides a boolean operation. 

2645 

2646 Does not compile in a SQL context, used for testing operators only. 

2647 

2648 .. versionadded:: 2.1 

2649 

2650 """ 

2651 return a._null_operate(b) 

2652 

2653 

2654def is_comparison(op: OperatorType) -> bool: 

2655 return op in _comparison or isinstance(op, custom_op) and op.is_comparison 

2656 

2657 

2658def is_commutative(op: OperatorType) -> bool: 

2659 return op in _commutative 

2660 

2661 

2662def is_ordering_modifier(op: OperatorType) -> bool: 

2663 return op in (asc_op, desc_op, nulls_first_op, nulls_last_op) 

2664 

2665 

2666def is_natural_self_precedent(op: OperatorType) -> bool: 

2667 return ( 

2668 op in _natural_self_precedent 

2669 or isinstance(op, custom_op) 

2670 and op.natural_self_precedent 

2671 ) 

2672 

2673 

2674_booleans = (inv, is_true, is_false, and_, or_) 

2675 

2676 

2677def is_boolean(op: OperatorType) -> bool: 

2678 return is_comparison(op) or op in _booleans 

2679 

2680 

2681_mirror = {gt: lt, ge: le, lt: gt, le: ge} 

2682 

2683 

2684def mirror(op: OperatorType) -> OperatorType: 

2685 """rotate a comparison operator 180 degrees. 

2686 

2687 Note this is not the same as negation. 

2688 

2689 """ 

2690 return _mirror.get(op, op) 

2691 

2692 

2693_associative = _commutative.union([concat_op, and_, or_]).difference([eq, ne]) 

2694 

2695 

2696def is_associative(op: OperatorType) -> bool: 

2697 return op in _associative 

2698 

2699 

2700def is_order_by_modifier(op: Optional[OperatorType]) -> bool: 

2701 return op in _order_by_modifier 

2702 

2703 

2704_order_by_modifier = {desc_op, asc_op, nulls_first_op, nulls_last_op} 

2705 

2706_natural_self_precedent = _associative.union( 

2707 [getitem, json_getitem_op, json_path_getitem_op] 

2708) 

2709"""Operators where if we have (a op b) op c, we don't want to 

2710parenthesize (a op b). 

2711 

2712""" 

2713 

2714 

2715@_operator_fn 

2716def _asbool(a: Any) -> Any: 

2717 raise NotImplementedError() 

2718 

2719 

2720class _OpLimit(IntEnum): 

2721 _smallest = -100 

2722 _largest = 100 

2723 

2724 

2725_PRECEDENCE: Dict[OperatorType, int] = { 

2726 from_: 15, 

2727 function_as_comparison_op: 15, 

2728 any_op: 15, 

2729 all_op: 15, 

2730 getitem: 15, 

2731 json_getitem_op: 15, 

2732 json_path_getitem_op: 15, 

2733 pow_: 15, 

2734 mul: 8, 

2735 truediv: 8, 

2736 floordiv: 8, 

2737 mod: 8, 

2738 neg: 8, 

2739 bitwise_not_op: 8, 

2740 add: 7, 

2741 sub: 7, 

2742 bitwise_xor_op: 7, 

2743 bitwise_or_op: 7, 

2744 bitwise_and_op: 7, 

2745 bitwise_lshift_op: 7, 

2746 bitwise_rshift_op: 7, 

2747 null_op: 7, 

2748 filter_op: 6, 

2749 concat_op: 5, 

2750 match_op: 5, 

2751 not_match_op: 5, 

2752 regexp_match_op: 5, 

2753 not_regexp_match_op: 5, 

2754 regexp_replace_op: 5, 

2755 ilike_op: 5, 

2756 not_ilike_op: 5, 

2757 like_op: 5, 

2758 not_like_op: 5, 

2759 in_op: 5, 

2760 not_in_op: 5, 

2761 is_: 5, 

2762 is_not: 5, 

2763 eq: 5, 

2764 ne: 5, 

2765 is_distinct_from: 5, 

2766 is_not_distinct_from: 5, 

2767 gt: 5, 

2768 lt: 5, 

2769 ge: 5, 

2770 le: 5, 

2771 between_op: 5, 

2772 not_between_op: 5, 

2773 distinct_op: 5, 

2774 inv: 5, 

2775 is_true: 5, 

2776 is_false: 5, 

2777 and_: 3, 

2778 or_: 2, 

2779 comma_op: -1, 

2780 desc_op: 3, 

2781 asc_op: 3, 

2782 collate: 4, 

2783 as_: -1, 

2784 exists: 0, 

2785 _asbool: -10, 

2786} 

2787 

2788 

2789# Mapping of OperatorType objects to their corresponding OperatorClass 

2790# Derived from unified_operator_lookup in default_comparator.py 

2791_OPERATOR_CLASSES: util.immutabledict[OperatorType, OperatorClass] = ( 

2792 util.immutabledict( 

2793 { 

2794 # BASE operators 

2795 null_op: OperatorClass.BASE, 

2796 # COMPARISON operators 

2797 lt: OperatorClass.COMPARISON, 

2798 le: OperatorClass.COMPARISON, 

2799 ne: OperatorClass.COMPARISON, 

2800 gt: OperatorClass.COMPARISON, 

2801 ge: OperatorClass.COMPARISON, 

2802 eq: OperatorClass.COMPARISON, 

2803 is_distinct_from: OperatorClass.COMPARISON, 

2804 is_not_distinct_from: OperatorClass.COMPARISON, 

2805 in_op: OperatorClass.COMPARISON, 

2806 not_in_op: OperatorClass.COMPARISON, 

2807 is_: OperatorClass.COMPARISON, 

2808 is_not: OperatorClass.COMPARISON, 

2809 between_op: OperatorClass.COMPARISON, 

2810 not_between_op: OperatorClass.COMPARISON, 

2811 desc_op: OperatorClass.COMPARISON, 

2812 asc_op: OperatorClass.COMPARISON, 

2813 nulls_first_op: OperatorClass.COMPARISON, 

2814 nulls_last_op: OperatorClass.COMPARISON, 

2815 distinct_op: OperatorClass.COMPARISON, 

2816 any_op: OperatorClass.COMPARISON, 

2817 all_op: OperatorClass.COMPARISON, 

2818 # BOOLEAN_ALGEBRA operators 

2819 and_: OperatorClass.BOOLEAN_ALGEBRA, 

2820 or_: OperatorClass.BOOLEAN_ALGEBRA, 

2821 inv: OperatorClass.BOOLEAN_ALGEBRA | OperatorClass.BITWISE, 

2822 # CONCATENABLE | MATH | DATE_ARITHMETIC | BITWISE operators 

2823 add: OperatorClass.CONCATENABLE 

2824 | OperatorClass.MATH 

2825 | OperatorClass.DATE_ARITHEMETIC 

2826 | OperatorClass.BITWISE, 

2827 # CONCATENABLE | BITWISE operators 

2828 concat_op: OperatorClass.CONCATENABLE | OperatorClass.BITWISE, 

2829 # INDEXABLE operators 

2830 getitem: OperatorClass.INDEXABLE, 

2831 # CONTAINS operators 

2832 contains_op: OperatorClass.CONTAINS, 

2833 icontains_op: OperatorClass.CONTAINS, 

2834 contains: OperatorClass.CONTAINS, 

2835 not_contains_op: OperatorClass.CONTAINS, 

2836 not_icontains_op: OperatorClass.CONTAINS, 

2837 # STRING_MATCH operators 

2838 like_op: OperatorClass.STRING_MATCH, 

2839 ilike_op: OperatorClass.STRING_MATCH, 

2840 not_like_op: OperatorClass.STRING_MATCH, 

2841 not_ilike_op: OperatorClass.STRING_MATCH, 

2842 startswith_op: OperatorClass.STRING_MATCH, 

2843 istartswith_op: OperatorClass.STRING_MATCH, 

2844 endswith_op: OperatorClass.STRING_MATCH, 

2845 iendswith_op: OperatorClass.STRING_MATCH, 

2846 not_startswith_op: OperatorClass.STRING_MATCH, 

2847 not_istartswith_op: OperatorClass.STRING_MATCH, 

2848 not_endswith_op: OperatorClass.STRING_MATCH, 

2849 not_iendswith_op: OperatorClass.STRING_MATCH, 

2850 collate: OperatorClass.STRING_MATCH, 

2851 match_op: OperatorClass.STRING_MATCH, 

2852 not_match_op: OperatorClass.STRING_MATCH, 

2853 regexp_match_op: OperatorClass.STRING_MATCH, 

2854 not_regexp_match_op: OperatorClass.STRING_MATCH, 

2855 regexp_replace_op: OperatorClass.STRING_MATCH, 

2856 # BITWISE operators 

2857 lshift: OperatorClass.BITWISE, 

2858 rshift: OperatorClass.BITWISE, 

2859 bitwise_xor_op: OperatorClass.BITWISE, 

2860 bitwise_or_op: OperatorClass.BITWISE, 

2861 bitwise_and_op: OperatorClass.BITWISE, 

2862 bitwise_not_op: OperatorClass.BITWISE, 

2863 bitwise_lshift_op: OperatorClass.BITWISE, 

2864 bitwise_rshift_op: OperatorClass.BITWISE, 

2865 # MATH operators 

2866 matmul: OperatorClass.MATH, 

2867 pow_: OperatorClass.MATH, 

2868 neg: OperatorClass.MATH, 

2869 mul: OperatorClass.MATH, 

2870 sub: OperatorClass.MATH | OperatorClass.DATE_ARITHEMETIC, 

2871 truediv: OperatorClass.MATH, 

2872 floordiv: OperatorClass.MATH, 

2873 mod: OperatorClass.MATH, 

2874 # JSON_GETITEM operators 

2875 json_path_getitem_op: OperatorClass.JSON_GETITEM, 

2876 json_getitem_op: OperatorClass.JSON_GETITEM, 

2877 } 

2878 ) 

2879) 

2880 

2881 

2882def is_precedent( 

2883 operator: OperatorType, against: Optional[OperatorType] 

2884) -> bool: 

2885 if operator is against and is_natural_self_precedent(operator): 

2886 return False 

2887 elif against is None: 

2888 return True 

2889 else: 

2890 return bool( 

2891 _PRECEDENCE.get( 

2892 operator, getattr(operator, "precedence", _OpLimit._smallest) 

2893 ) 

2894 <= _PRECEDENCE.get( 

2895 against, getattr(against, "precedence", _OpLimit._largest) 

2896 ) 

2897 )