1# sql/operators.py 2# Copyright (C) 2005-2018 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: http://www.opensource.org/licenses/mit-license.php 7 8# This module is part of SQLAlchemy and is released under 9# the MIT License: http://www.opensource.org/licenses/mit-license.php 10 11"""Defines operators used in SQL expressions.""" 12 13from .. import util 14 15from operator import ( 16 and_, or_, inv, add, mul, sub, mod, truediv, lt, le, ne, gt, ge, eq, neg, 17 getitem, lshift, rshift, contains 18) 19 20if util.py2k: 21 from operator import div 22else: 23 div = truediv 24 25 26class Operators(object): 27 """Base of comparison and logical operators. 28 29 Implements base methods 30 :meth:`~sqlalchemy.sql.operators.Operators.operate` and 31 :meth:`~sqlalchemy.sql.operators.Operators.reverse_operate`, as well as 32 :meth:`~sqlalchemy.sql.operators.Operators.__and__`, 33 :meth:`~sqlalchemy.sql.operators.Operators.__or__`, 34 :meth:`~sqlalchemy.sql.operators.Operators.__invert__`. 35 36 Usually is used via its most common subclass 37 :class:`.ColumnOperators`. 38 39 """ 40 __slots__ = () 41 42 def __and__(self, other): 43 """Implement the ``&`` operator. 44 45 When used with SQL expressions, results in an 46 AND operation, equivalent to 47 :func:`~.expression.and_`, that is:: 48 49 a & b 50 51 is equivalent to:: 52 53 from sqlalchemy import and_ 54 and_(a, b) 55 56 Care should be taken when using ``&`` regarding 57 operator precedence; the ``&`` operator has the highest precedence. 58 The operands should be enclosed in parenthesis if they contain 59 further sub expressions:: 60 61 (a == 2) & (b == 4) 62 63 """ 64 return self.operate(and_, other) 65 66 def __or__(self, other): 67 """Implement the ``|`` operator. 68 69 When used with SQL expressions, results in an 70 OR operation, equivalent to 71 :func:`~.expression.or_`, that is:: 72 73 a | b 74 75 is equivalent to:: 76 77 from sqlalchemy import or_ 78 or_(a, b) 79 80 Care should be taken when using ``|`` regarding 81 operator precedence; the ``|`` operator has the highest precedence. 82 The operands should be enclosed in parenthesis if they contain 83 further sub expressions:: 84 85 (a == 2) | (b == 4) 86 87 """ 88 return self.operate(or_, other) 89 90 def __invert__(self): 91 """Implement the ``~`` operator. 92 93 When used with SQL expressions, results in a 94 NOT operation, equivalent to 95 :func:`~.expression.not_`, that is:: 96 97 ~a 98 99 is equivalent to:: 100 101 from sqlalchemy import not_ 102 not_(a) 103 104 """ 105 return self.operate(inv) 106 107 def op(self, opstring, precedence=0, is_comparison=False): 108 """produce a generic operator function. 109 110 e.g.:: 111 112 somecolumn.op("*")(5) 113 114 produces:: 115 116 somecolumn * 5 117 118 This function can also be used to make bitwise operators explicit. For 119 example:: 120 121 somecolumn.op('&')(0xff) 122 123 is a bitwise AND of the value in ``somecolumn``. 124 125 :param operator: a string which will be output as the infix operator 126 between this element and the expression passed to the 127 generated function. 128 129 :param precedence: precedence to apply to the operator, when 130 parenthesizing expressions. A lower number will cause the expression 131 to be parenthesized when applied against another operator with 132 higher precedence. The default value of ``0`` is lower than all 133 operators except for the comma (``,``) and ``AS`` operators. 134 A value of 100 will be higher or equal to all operators, and -100 135 will be lower than or equal to all operators. 136 137 .. versionadded:: 0.8 - added the 'precedence' argument. 138 139 :param is_comparison: if True, the operator will be considered as a 140 "comparison" operator, that is which evaluates to a boolean 141 true/false value, like ``==``, ``>``, etc. This flag should be set 142 so that ORM relationships can establish that the operator is a 143 comparison operator when used in a custom join condition. 144 145 .. versionadded:: 0.9.2 - added the 146 :paramref:`.Operators.op.is_comparison` flag. 147 148 .. seealso:: 149 150 :ref:`types_operators` 151 152 :ref:`relationship_custom_operator` 153 154 """ 155 operator = custom_op(opstring, precedence, is_comparison) 156 157 def against(other): 158 return operator(self, other) 159 return against 160 161 def operate(self, op, *other, **kwargs): 162 r"""Operate on an argument. 163 164 This is the lowest level of operation, raises 165 :class:`NotImplementedError` by default. 166 167 Overriding this on a subclass can allow common 168 behavior to be applied to all operations. 169 For example, overriding :class:`.ColumnOperators` 170 to apply ``func.lower()`` to the left and right 171 side:: 172 173 class MyComparator(ColumnOperators): 174 def operate(self, op, other): 175 return op(func.lower(self), func.lower(other)) 176 177 :param op: Operator callable. 178 :param \*other: the 'other' side of the operation. Will 179 be a single scalar for most operations. 180 :param \**kwargs: modifiers. These may be passed by special 181 operators such as :meth:`ColumnOperators.contains`. 182 183 184 """ 185 raise NotImplementedError(str(op)) 186 187 def reverse_operate(self, op, other, **kwargs): 188 """Reverse operate on an argument. 189 190 Usage is the same as :meth:`operate`. 191 192 """ 193 raise NotImplementedError(str(op)) 194 195 196class custom_op(object): 197 """Represent a 'custom' operator. 198 199 :class:`.custom_op` is normally instantitated when the 200 :meth:`.ColumnOperators.op` method is used to create a 201 custom operator callable. The class can also be used directly 202 when programmatically constructing expressions. E.g. 203 to represent the "factorial" operation:: 204 205 from sqlalchemy.sql import UnaryExpression 206 from sqlalchemy.sql import operators 207 from sqlalchemy import Numeric 208 209 unary = UnaryExpression(table.c.somecolumn, 210 modifier=operators.custom_op("!"), 211 type_=Numeric) 212 213 """ 214 __name__ = 'custom_op' 215 216 def __init__( 217 self, opstring, precedence=0, is_comparison=False, 218 natural_self_precedent=False, eager_grouping=False): 219 self.opstring = opstring 220 self.precedence = precedence 221 self.is_comparison = is_comparison 222 self.natural_self_precedent = natural_self_precedent 223 self.eager_grouping = eager_grouping 224 225 def __eq__(self, other): 226 return isinstance(other, custom_op) and \ 227 other.opstring == self.opstring 228 229 def __hash__(self): 230 return id(self) 231 232 def __call__(self, left, right, **kw): 233 return left.operate(self, right, **kw) 234 235 236class ColumnOperators(Operators): 237 """Defines boolean, comparison, and other operators for 238 :class:`.ColumnElement` expressions. 239 240 By default, all methods call down to 241 :meth:`.operate` or :meth:`.reverse_operate`, 242 passing in the appropriate operator function from the 243 Python builtin ``operator`` module or 244 a SQLAlchemy-specific operator function from 245 :mod:`sqlalchemy.expression.operators`. For example 246 the ``__eq__`` function:: 247 248 def __eq__(self, other): 249 return self.operate(operators.eq, other) 250 251 Where ``operators.eq`` is essentially:: 252 253 def eq(a, b): 254 return a == b 255 256 The core column expression unit :class:`.ColumnElement` 257 overrides :meth:`.Operators.operate` and others 258 to return further :class:`.ColumnElement` constructs, 259 so that the ``==`` operation above is replaced by a clause 260 construct. 261 262 See also: 263 264 :ref:`types_operators` 265 266 :attr:`.TypeEngine.comparator_factory` 267 268 :class:`.ColumnOperators` 269 270 :class:`.PropComparator` 271 272 """ 273 274 __slots__ = () 275 276 timetuple = None 277 """Hack, allows datetime objects to be compared on the LHS.""" 278 279 def __lt__(self, other): 280 """Implement the ``<`` operator. 281 282 In a column context, produces the clause ``a < b``. 283 284 """ 285 return self.operate(lt, other) 286 287 def __le__(self, other): 288 """Implement the ``<=`` operator. 289 290 In a column context, produces the clause ``a <= b``. 291 292 """ 293 return self.operate(le, other) 294 295 __hash__ = Operators.__hash__ 296 297 def __eq__(self, other): 298 """Implement the ``==`` operator. 299 300 In a column context, produces the clause ``a = b``. 301 If the target is ``None``, produces ``a IS NULL``. 302 303 """ 304 return self.operate(eq, other) 305 306 def __ne__(self, other): 307 """Implement the ``!=`` operator. 308 309 In a column context, produces the clause ``a != b``. 310 If the target is ``None``, produces ``a IS NOT NULL``. 311 312 """ 313 return self.operate(ne, other) 314 315 def is_distinct_from(self, other): 316 """Implement the ``IS DISTINCT FROM`` operator. 317 318 Renders "a IS DISTINCT FROM b" on most platforms; 319 on some such as SQLite may render "a IS NOT b". 320 321 .. versionadded:: 1.1 322 323 """ 324 return self.operate(is_distinct_from, other) 325 326 def isnot_distinct_from(self, other): 327 """Implement the ``IS NOT DISTINCT FROM`` operator. 328 329 Renders "a IS NOT DISTINCT FROM b" on most platforms; 330 on some such as SQLite may render "a IS b". 331 332 .. versionadded:: 1.1 333 334 """ 335 return self.operate(isnot_distinct_from, other) 336 337 def __gt__(self, other): 338 """Implement the ``>`` operator. 339 340 In a column context, produces the clause ``a > b``. 341 342 """ 343 return self.operate(gt, other) 344 345 def __ge__(self, other): 346 """Implement the ``>=`` operator. 347 348 In a column context, produces the clause ``a >= b``. 349 350 """ 351 return self.operate(ge, other) 352 353 def __neg__(self): 354 """Implement the ``-`` operator. 355 356 In a column context, produces the clause ``-a``. 357 358 """ 359 return self.operate(neg) 360 361 def __contains__(self, other): 362 return self.operate(contains, other) 363 364 def __getitem__(self, index): 365 """Implement the [] operator. 366 367 This can be used by some database-specific types 368 such as PostgreSQL ARRAY and HSTORE. 369 370 """ 371 return self.operate(getitem, index) 372 373 def __lshift__(self, other): 374 """implement the << operator. 375 376 Not used by SQLAlchemy core, this is provided 377 for custom operator systems which want to use 378 << as an extension point. 379 """ 380 return self.operate(lshift, other) 381 382 def __rshift__(self, other): 383 """implement the >> operator. 384 385 Not used by SQLAlchemy core, this is provided 386 for custom operator systems which want to use 387 >> as an extension point. 388 """ 389 return self.operate(rshift, other) 390 391 def concat(self, other): 392 """Implement the 'concat' operator. 393 394 In a column context, produces the clause ``a || b``, 395 or uses the ``concat()`` operator on MySQL. 396 397 """ 398 return self.operate(concat_op, other) 399 400 def like(self, other, escape=None): 401 r"""Implement the ``like`` operator. 402 403 In a column context, produces the expression:: 404 405 a LIKE other 406 407 E.g.:: 408 409 stmt = select([sometable]).\ 410 where(sometable.c.column.like("%foobar%")) 411 412 :param other: expression to be compared 413 :param escape: optional escape character, renders the ``ESCAPE`` 414 keyword, e.g.:: 415 416 somecolumn.like("foo/%bar", escape="/") 417 418 .. seealso:: 419 420 :meth:`.ColumnOperators.ilike` 421 422 """ 423 return self.operate(like_op, other, escape=escape) 424 425 def ilike(self, other, escape=None): 426 r"""Implement the ``ilike`` operator, e.g. case insensitive LIKE. 427 428 In a column context, produces an expression either of the form:: 429 430 lower(a) LIKE lower(other) 431 432 Or on backends that support the ILIKE operator:: 433 434 a ILIKE other 435 436 E.g.:: 437 438 stmt = select([sometable]).\ 439 where(sometable.c.column.ilike("%foobar%")) 440 441 :param other: expression to be compared 442 :param escape: optional escape character, renders the ``ESCAPE`` 443 keyword, e.g.:: 444 445 somecolumn.ilike("foo/%bar", escape="/") 446 447 .. seealso:: 448 449 :meth:`.ColumnOperators.like` 450 451 """ 452 return self.operate(ilike_op, other, escape=escape) 453 454 def in_(self, other): 455 """Implement the ``in`` operator. 456 457 In a column context, produces the clause ``a IN other``. 458 "other" may be a tuple/list of column expressions, 459 or a :func:`~.expression.select` construct. 460 461 """ 462 return self.operate(in_op, other) 463 464 def notin_(self, other): 465 """implement the ``NOT IN`` operator. 466 467 This is equivalent to using negation with 468 :meth:`.ColumnOperators.in_`, i.e. ``~x.in_(y)``. 469 470 .. versionadded:: 0.8 471 472 .. seealso:: 473 474 :meth:`.ColumnOperators.in_` 475 476 """ 477 return self.operate(notin_op, other) 478 479 def notlike(self, other, escape=None): 480 """implement the ``NOT LIKE`` operator. 481 482 This is equivalent to using negation with 483 :meth:`.ColumnOperators.like`, i.e. ``~x.like(y)``. 484 485 .. versionadded:: 0.8 486 487 .. seealso:: 488 489 :meth:`.ColumnOperators.like` 490 491 """ 492 return self.operate(notlike_op, other, escape=escape) 493 494 def notilike(self, other, escape=None): 495 """implement the ``NOT ILIKE`` operator. 496 497 This is equivalent to using negation with 498 :meth:`.ColumnOperators.ilike`, i.e. ``~x.ilike(y)``. 499 500 .. versionadded:: 0.8 501 502 .. seealso:: 503 504 :meth:`.ColumnOperators.ilike` 505 506 """ 507 return self.operate(notilike_op, other, escape=escape) 508 509 def is_(self, other): 510 """Implement the ``IS`` operator. 511 512 Normally, ``IS`` is generated automatically when comparing to a 513 value of ``None``, which resolves to ``NULL``. However, explicit 514 usage of ``IS`` may be desirable if comparing to boolean values 515 on certain platforms. 516 517 .. versionadded:: 0.7.9 518 519 .. seealso:: :meth:`.ColumnOperators.isnot` 520 521 """ 522 return self.operate(is_, other) 523 524 def isnot(self, other): 525 """Implement the ``IS NOT`` operator. 526 527 Normally, ``IS NOT`` is generated automatically when comparing to a 528 value of ``None``, which resolves to ``NULL``. However, explicit 529 usage of ``IS NOT`` may be desirable if comparing to boolean values 530 on certain platforms. 531 532 .. versionadded:: 0.7.9 533 534 .. seealso:: :meth:`.ColumnOperators.is_` 535 536 """ 537 return self.operate(isnot, other) 538 539 def startswith(self, other, **kwargs): 540 """Implement the ``startwith`` operator. 541 542 In a column context, produces the clause ``LIKE '<other>%'`` 543 544 """ 545 return self.operate(startswith_op, other, **kwargs) 546 547 def endswith(self, other, **kwargs): 548 """Implement the 'endswith' operator. 549 550 In a column context, produces the clause ``LIKE '%<other>'`` 551 552 """ 553 return self.operate(endswith_op, other, **kwargs) 554 555 def contains(self, other, **kwargs): 556 """Implement the 'contains' operator. 557 558 In a column context, produces the clause ``LIKE '%<other>%'`` 559 560 """ 561 return self.operate(contains_op, other, **kwargs) 562 563 def match(self, other, **kwargs): 564 """Implements a database-specific 'match' operator. 565 566 :meth:`~.ColumnOperators.match` attempts to resolve to 567 a MATCH-like function or operator provided by the backend. 568 Examples include: 569 570 * PostgreSQL - renders ``x @@ to_tsquery(y)`` 571 * MySQL - renders ``MATCH (x) AGAINST (y IN BOOLEAN MODE)`` 572 * Oracle - renders ``CONTAINS(x, y)`` 573 * other backends may provide special implementations. 574 * Backends without any special implementation will emit 575 the operator as "MATCH". This is compatible with SQlite, for 576 example. 577 578 """ 579 return self.operate(match_op, other, **kwargs) 580 581 def desc(self): 582 """Produce a :func:`~.expression.desc` clause against the 583 parent object.""" 584 return self.operate(desc_op) 585 586 def asc(self): 587 """Produce a :func:`~.expression.asc` clause against the 588 parent object.""" 589 return self.operate(asc_op) 590 591 def nullsfirst(self): 592 """Produce a :func:`~.expression.nullsfirst` clause against the 593 parent object.""" 594 return self.operate(nullsfirst_op) 595 596 def nullslast(self): 597 """Produce a :func:`~.expression.nullslast` clause against the 598 parent object.""" 599 return self.operate(nullslast_op) 600 601 def collate(self, collation): 602 """Produce a :func:`~.expression.collate` clause against 603 the parent object, given the collation string.""" 604 return self.operate(collate, collation) 605 606 def __radd__(self, other): 607 """Implement the ``+`` operator in reverse. 608 609 See :meth:`.ColumnOperators.__add__`. 610 611 """ 612 return self.reverse_operate(add, other) 613 614 def __rsub__(self, other): 615 """Implement the ``-`` operator in reverse. 616 617 See :meth:`.ColumnOperators.__sub__`. 618 619 """ 620 return self.reverse_operate(sub, other) 621 622 def __rmul__(self, other): 623 """Implement the ``*`` operator in reverse. 624 625 See :meth:`.ColumnOperators.__mul__`. 626 627 """ 628 return self.reverse_operate(mul, other) 629 630 def __rdiv__(self, other): 631 """Implement the ``/`` operator in reverse. 632 633 See :meth:`.ColumnOperators.__div__`. 634 635 """ 636 return self.reverse_operate(div, other) 637 638 def __rmod__(self, other): 639 """Implement the ``%`` operator in reverse. 640 641 See :meth:`.ColumnOperators.__mod__`. 642 643 """ 644 return self.reverse_operate(mod, other) 645 646 def between(self, cleft, cright, symmetric=False): 647 """Produce a :func:`~.expression.between` clause against 648 the parent object, given the lower and upper range. 649 650 """ 651 return self.operate(between_op, cleft, cright, symmetric=symmetric) 652 653 def distinct(self): 654 """Produce a :func:`~.expression.distinct` clause against the 655 parent object. 656 657 """ 658 return self.operate(distinct_op) 659 660 def any_(self): 661 """Produce a :func:`~.expression.any_` clause against the 662 parent object. 663 664 This operator is only appropriate against a scalar subquery 665 object, or for some backends an column expression that is 666 against the ARRAY type, e.g.:: 667 668 # postgresql '5 = ANY (somearray)' 669 expr = 5 == mytable.c.somearray.any_() 670 671 # mysql '5 = ANY (SELECT value FROM table)' 672 expr = 5 == select([table.c.value]).as_scalar().any_() 673 674 .. seealso:: 675 676 :func:`~.expression.any_` - standalone version 677 678 :func:`~.expression.all_` - ALL operator 679 680 .. versionadded:: 1.1 681 682 """ 683 return self.operate(any_op) 684 685 def all_(self): 686 """Produce a :func:`~.expression.all_` clause against the 687 parent object. 688 689 This operator is only appropriate against a scalar subquery 690 object, or for some backends an column expression that is 691 against the ARRAY type, e.g.:: 692 693 # postgresql '5 = ALL (somearray)' 694 expr = 5 == mytable.c.somearray.all_() 695 696 # mysql '5 = ALL (SELECT value FROM table)' 697 expr = 5 == select([table.c.value]).as_scalar().all_() 698 699 .. seealso:: 700 701 :func:`~.expression.all_` - standalone version 702 703 :func:`~.expression.any_` - ANY operator 704 705 .. versionadded:: 1.1 706 707 """ 708 return self.operate(all_op) 709 710 def __add__(self, other): 711 """Implement the ``+`` operator. 712 713 In a column context, produces the clause ``a + b`` 714 if the parent object has non-string affinity. 715 If the parent object has a string affinity, 716 produces the concatenation operator, ``a || b`` - 717 see :meth:`.ColumnOperators.concat`. 718 719 """ 720 return self.operate(add, other) 721 722 def __sub__(self, other): 723 """Implement the ``-`` operator. 724 725 In a column context, produces the clause ``a - b``. 726 727 """ 728 return self.operate(sub, other) 729 730 def __mul__(self, other): 731 """Implement the ``*`` operator. 732 733 In a column context, produces the clause ``a * b``. 734 735 """ 736 return self.operate(mul, other) 737 738 def __div__(self, other): 739 """Implement the ``/`` operator. 740 741 In a column context, produces the clause ``a / b``. 742 743 """ 744 return self.operate(div, other) 745 746 def __mod__(self, other): 747 """Implement the ``%`` operator. 748 749 In a column context, produces the clause ``a % b``. 750 751 """ 752 return self.operate(mod, other) 753 754 def __truediv__(self, other): 755 """Implement the ``//`` operator. 756 757 In a column context, produces the clause ``a / b``. 758 759 """ 760 return self.operate(truediv, other) 761 762 def __rtruediv__(self, other): 763 """Implement the ``//`` operator in reverse. 764 765 See :meth:`.ColumnOperators.__truediv__`. 766 767 """ 768 return self.reverse_operate(truediv, other) 769 770 771def from_(): 772 raise NotImplementedError() 773 774 775def as_(): 776 raise NotImplementedError() 777 778 779def exists(): 780 raise NotImplementedError() 781 782 783def istrue(a): 784 raise NotImplementedError() 785 786 787def isfalse(a): 788 raise NotImplementedError() 789 790 791def is_distinct_from(a, b): 792 return a.is_distinct_from(b) 793 794 795def isnot_distinct_from(a, b): 796 return a.isnot_distinct_from(b) 797 798 799def is_(a, b): 800 return a.is_(b) 801 802 803def isnot(a, b): 804 return a.isnot(b) 805 806 807def collate(a, b): 808 return a.collate(b) 809 810 811def op(a, opstring, b): 812 return a.op(opstring)(b) 813 814 815def like_op(a, b, escape=None): 816 return a.like(b, escape=escape) 817 818 819def notlike_op(a, b, escape=None): 820 return a.notlike(b, escape=escape) 821 822 823def ilike_op(a, b, escape=None): 824 return a.ilike(b, escape=escape) 825 826 827def notilike_op(a, b, escape=None): 828 return a.notilike(b, escape=escape) 829 830 831def between_op(a, b, c, symmetric=False): 832 return a.between(b, c, symmetric=symmetric) 833 834 835def notbetween_op(a, b, c, symmetric=False): 836 return a.notbetween(b, c, symmetric=symmetric) 837 838 839def in_op(a, b): 840 return a.in_(b) 841 842 843def notin_op(a, b): 844 return a.notin_(b) 845 846 847def distinct_op(a): 848 return a.distinct() 849 850 851def any_op(a): 852 return a.any_() 853 854 855def all_op(a): 856 return a.all_() 857 858 859def startswith_op(a, b, escape=None): 860 return a.startswith(b, escape=escape) 861 862 863def notstartswith_op(a, b, escape=None): 864 return ~a.startswith(b, escape=escape) 865 866 867def endswith_op(a, b, escape=None): 868 return a.endswith(b, escape=escape) 869 870 871def notendswith_op(a, b, escape=None): 872 return ~a.endswith(b, escape=escape) 873 874 875def contains_op(a, b, escape=None): 876 return a.contains(b, escape=escape) 877 878 879def notcontains_op(a, b, escape=None): 880 return ~a.contains(b, escape=escape) 881 882 883def match_op(a, b, **kw): 884 return a.match(b, **kw) 885 886 887def notmatch_op(a, b, **kw): 888 return a.notmatch(b, **kw) 889 890 891def comma_op(a, b): 892 raise NotImplementedError() 893 894 895def concat_op(a, b): 896 return a.concat(b) 897 898 899def desc_op(a): 900 return a.desc() 901 902 903def asc_op(a): 904 return a.asc() 905 906 907def nullsfirst_op(a): 908 return a.nullsfirst() 909 910 911def nullslast_op(a): 912 return a.nullslast() 913 914 915def json_getitem_op(a, b): 916 raise NotImplementedError() 917 918 919def json_path_getitem_op(a, b): 920 raise NotImplementedError() 921 922 923_commutative = set([eq, ne, add, mul]) 924 925_comparison = set([eq, ne, lt, gt, ge, le, between_op, like_op]) 926 927 928def is_comparison(op): 929 return op in _comparison or \ 930 isinstance(op, custom_op) and op.is_comparison 931 932 933def is_commutative(op): 934 return op in _commutative 935 936 937def is_ordering_modifier(op): 938 return op in (asc_op, desc_op, 939 nullsfirst_op, nullslast_op) 940 941 942def is_natural_self_precedent(op): 943 return op in _natural_self_precedent or \ 944 isinstance(op, custom_op) and op.natural_self_precedent 945 946_mirror = { 947 gt: lt, 948 ge: le, 949 lt: gt, 950 le: ge 951} 952 953 954def mirror(op): 955 """rotate a comparison operator 180 degrees. 956 957 Note this is not the same as negation. 958 959 """ 960 return _mirror.get(op, op) 961 962 963_associative = _commutative.union([concat_op, and_, or_]).difference([eq, ne]) 964 965_natural_self_precedent = _associative.union([ 966 getitem, json_getitem_op, json_path_getitem_op]) 967"""Operators where if we have (a op b) op c, we don't want to 968parenthesize (a op b). 969 970""" 971 972 973_asbool = util.symbol('_asbool', canonical=-10) 974_smallest = util.symbol('_smallest', canonical=-100) 975_largest = util.symbol('_largest', canonical=100) 976 977_PRECEDENCE = { 978 from_: 15, 979 any_op: 15, 980 all_op: 15, 981 getitem: 15, 982 json_getitem_op: 15, 983 json_path_getitem_op: 15, 984 985 mul: 8, 986 truediv: 8, 987 div: 8, 988 mod: 8, 989 neg: 8, 990 add: 7, 991 sub: 7, 992 993 concat_op: 6, 994 match_op: 6, 995 notmatch_op: 6, 996 997 ilike_op: 6, 998 notilike_op: 6, 999 like_op: 6, 1000 notlike_op: 6, 1001 in_op: 6, 1002 notin_op: 6, 1003 1004 is_: 6, 1005 isnot: 6, 1006 1007 eq: 5, 1008 ne: 5, 1009 is_distinct_from: 5, 1010 isnot_distinct_from: 5, 1011 gt: 5, 1012 lt: 5, 1013 ge: 5, 1014 le: 5, 1015 1016 between_op: 5, 1017 notbetween_op: 5, 1018 distinct_op: 5, 1019 inv: 5, 1020 istrue: 5, 1021 isfalse: 5, 1022 and_: 3, 1023 or_: 2, 1024 comma_op: -1, 1025 1026 desc_op: 3, 1027 asc_op: 3, 1028 collate: 4, 1029 1030 as_: -1, 1031 exists: 0, 1032 1033 _asbool: -10, 1034 _smallest: _smallest, 1035 _largest: _largest 1036} 1037 1038 1039def is_precedent(operator, against): 1040 if operator is against and is_natural_self_precedent(operator): 1041 return False 1042 else: 1043 return (_PRECEDENCE.get(operator, 1044 getattr(operator, 'precedence', _smallest)) <= 1045 _PRECEDENCE.get(against, 1046 getattr(against, 'precedence', _largest))) 1047