Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/SQLAlchemy-1.3.25.dev0-py3.11-linux-x86_64.egg/sqlalchemy/sql/operators.py: 58%

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

310 statements  

1# sql/operators.py 

2# Copyright (C) 2005-2021 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 operator import add 

14from operator import and_ 

15from operator import contains 

16from operator import eq 

17from operator import ge 

18from operator import getitem 

19from operator import gt 

20from operator import inv 

21from operator import le 

22from operator import lshift 

23from operator import lt 

24from operator import mod 

25from operator import mul 

26from operator import ne 

27from operator import neg 

28from operator import or_ 

29from operator import rshift 

30from operator import sub 

31from operator import truediv 

32 

33from .. import util 

34 

35 

36if util.py2k: 

37 from operator import div 

38else: 

39 div = truediv 

40 

41 

42class Operators(object): 

43 """Base of comparison and logical operators. 

44 

45 Implements base methods 

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

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

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

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

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

51 

52 Usually is used via its most common subclass 

53 :class:`.ColumnOperators`. 

54 

55 """ 

56 

57 __slots__ = () 

58 

59 def __and__(self, other): 

60 """Implement the ``&`` operator. 

61 

62 When used with SQL expressions, results in an 

63 AND operation, equivalent to 

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

65 

66 a & b 

67 

68 is equivalent to:: 

69 

70 from sqlalchemy import and_ 

71 and_(a, b) 

72 

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

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

75 The operands should be enclosed in parenthesis if they contain 

76 further sub expressions:: 

77 

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

79 

80 """ 

81 return self.operate(and_, other) 

82 

83 def __or__(self, other): 

84 """Implement the ``|`` operator. 

85 

86 When used with SQL expressions, results in an 

87 OR operation, equivalent to 

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

89 

90 a | b 

91 

92 is equivalent to:: 

93 

94 from sqlalchemy import or_ 

95 or_(a, b) 

96 

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

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

99 The operands should be enclosed in parenthesis if they contain 

100 further sub expressions:: 

101 

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

103 

104 """ 

105 return self.operate(or_, other) 

106 

107 def __invert__(self): 

108 """Implement the ``~`` operator. 

109 

110 When used with SQL expressions, results in a 

111 NOT operation, equivalent to 

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

113 

114 ~a 

115 

116 is equivalent to:: 

117 

118 from sqlalchemy import not_ 

119 not_(a) 

120 

121 """ 

122 return self.operate(inv) 

123 

124 def op( 

125 self, opstring, precedence=0, is_comparison=False, return_type=None 

126 ): 

127 """Produce a generic operator function. 

128 

129 e.g.:: 

130 

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

132 

133 produces:: 

134 

135 somecolumn * 5 

136 

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

138 example:: 

139 

140 somecolumn.op('&')(0xff) 

141 

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

143 

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

145 between this element and the expression passed to the 

146 generated function. 

147 

148 :param precedence: precedence to apply to the operator, when 

149 parenthesizing expressions. A lower number will cause the expression 

150 to be parenthesized when applied against another operator with 

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

152 operators except for the comma (``,``) and ``AS`` operators. 

153 A value of 100 will be higher or equal to all operators, and -100 

154 will be lower than or equal to all operators. 

155 

156 :param is_comparison: if True, the operator will be considered as a 

157 "comparison" operator, that is which evaluates to a boolean 

158 true/false value, like ``==``, ``>``, etc. This flag should be set 

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

160 comparison operator when used in a custom join condition. 

161 

162 .. versionadded:: 0.9.2 - added the 

163 :paramref:`.Operators.op.is_comparison` flag. 

164 

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

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

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

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

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

170 type as the left-hand operand. 

171 

172 .. versionadded:: 1.2.0b3 - added the 

173 :paramref:`.Operators.op.return_type` argument. 

174 

175 .. seealso:: 

176 

177 :ref:`types_operators` 

178 

179 :ref:`relationship_custom_operator` 

180 

181 """ 

182 operator = custom_op(opstring, precedence, is_comparison, return_type) 

183 

184 def against(other): 

185 return operator(self, other) 

186 

187 return against 

188 

189 def bool_op(self, opstring, precedence=0): 

190 """Return a custom boolean operator. 

191 

192 This method is shorthand for calling 

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

194 :paramref:`.Operators.op.is_comparison` 

195 flag with True. 

196 

197 .. versionadded:: 1.2.0b3 

198 

199 .. seealso:: 

200 

201 :meth:`.Operators.op` 

202 

203 """ 

204 return self.op(opstring, precedence=precedence, is_comparison=True) 

205 

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

207 r"""Operate on an argument. 

208 

209 This is the lowest level of operation, raises 

210 :class:`NotImplementedError` by default. 

211 

212 Overriding this on a subclass can allow common 

213 behavior to be applied to all operations. 

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

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

216 side:: 

217 

218 class MyComparator(ColumnOperators): 

219 def operate(self, op, other): 

220 return op(func.lower(self), func.lower(other)) 

221 

222 :param op: Operator callable. 

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

224 be a single scalar for most operations. 

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

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

227 

228 

229 """ 

230 raise NotImplementedError(str(op)) 

231 

232 def reverse_operate(self, op, other, **kwargs): 

233 """Reverse operate on an argument. 

234 

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

236 

237 """ 

238 raise NotImplementedError(str(op)) 

239 

240 

241class custom_op(object): 

242 """Represent a 'custom' operator. 

243 

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

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

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

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

248 to represent the "factorial" operation:: 

249 

250 from sqlalchemy.sql import UnaryExpression 

251 from sqlalchemy.sql import operators 

252 from sqlalchemy import Numeric 

253 

254 unary = UnaryExpression(table.c.somecolumn, 

255 modifier=operators.custom_op("!"), 

256 type_=Numeric) 

257 

258 

259 .. seealso:: 

260 

261 :meth:`.Operators.op` 

262 

263 :meth:`.Operators.bool_op` 

264 

265 """ 

266 

267 __name__ = "custom_op" 

268 

269 def __init__( 

270 self, 

271 opstring, 

272 precedence=0, 

273 is_comparison=False, 

274 return_type=None, 

275 natural_self_precedent=False, 

276 eager_grouping=False, 

277 ): 

278 self.opstring = opstring 

279 self.precedence = precedence 

280 self.is_comparison = is_comparison 

281 self.natural_self_precedent = natural_self_precedent 

282 self.eager_grouping = eager_grouping 

283 self.return_type = ( 

284 return_type._to_instance(return_type) if return_type else None 

285 ) 

286 

287 def __eq__(self, other): 

288 return isinstance(other, custom_op) and other.opstring == self.opstring 

289 

290 def __hash__(self): 

291 return id(self) 

292 

293 def __call__(self, left, right, **kw): 

294 return left.operate(self, right, **kw) 

295 

296 

297class ColumnOperators(Operators): 

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

299 :class:`_expression.ColumnElement` expressions. 

300 

301 By default, all methods call down to 

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

303 passing in the appropriate operator function from the 

304 Python builtin ``operator`` module or 

305 a SQLAlchemy-specific operator function from 

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

307 the ``__eq__`` function:: 

308 

309 def __eq__(self, other): 

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

311 

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

313 

314 def eq(a, b): 

315 return a == b 

316 

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

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

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

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

321 construct. 

322 

323 .. seealso:: 

324 

325 :ref:`types_operators` 

326 

327 :attr:`.TypeEngine.comparator_factory` 

328 

329 :class:`.ColumnOperators` 

330 

331 :class:`.PropComparator` 

332 

333 """ 

334 

335 __slots__ = () 

336 

337 timetuple = None 

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

339 

340 def __lt__(self, other): 

341 """Implement the ``<`` operator. 

342 

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

344 

345 """ 

346 return self.operate(lt, other) 

347 

348 def __le__(self, other): 

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

350 

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

352 

353 """ 

354 return self.operate(le, other) 

355 

356 __hash__ = Operators.__hash__ 

357 

358 def __eq__(self, other): 

359 """Implement the ``==`` operator. 

360 

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

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

363 

364 """ 

365 return self.operate(eq, other) 

366 

367 def __ne__(self, other): 

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

369 

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

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

372 

373 """ 

374 return self.operate(ne, other) 

375 

376 def is_distinct_from(self, other): 

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

378 

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

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

381 

382 .. versionadded:: 1.1 

383 

384 """ 

385 return self.operate(is_distinct_from, other) 

386 

387 def isnot_distinct_from(self, other): 

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

389 

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

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

392 

393 .. versionadded:: 1.1 

394 

395 """ 

396 return self.operate(isnot_distinct_from, other) 

397 

398 def __gt__(self, other): 

399 """Implement the ``>`` operator. 

400 

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

402 

403 """ 

404 return self.operate(gt, other) 

405 

406 def __ge__(self, other): 

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

408 

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

410 

411 """ 

412 return self.operate(ge, other) 

413 

414 def __neg__(self): 

415 """Implement the ``-`` operator. 

416 

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

418 

419 """ 

420 return self.operate(neg) 

421 

422 def __contains__(self, other): 

423 return self.operate(contains, other) 

424 

425 def __getitem__(self, index): 

426 """Implement the [] operator. 

427 

428 This can be used by some database-specific types 

429 such as PostgreSQL ARRAY and HSTORE. 

430 

431 """ 

432 return self.operate(getitem, index) 

433 

434 def __lshift__(self, other): 

435 """implement the << operator. 

436 

437 Not used by SQLAlchemy core, this is provided 

438 for custom operator systems which want to use 

439 << as an extension point. 

440 """ 

441 return self.operate(lshift, other) 

442 

443 def __rshift__(self, other): 

444 """implement the >> operator. 

445 

446 Not used by SQLAlchemy core, this is provided 

447 for custom operator systems which want to use 

448 >> as an extension point. 

449 """ 

450 return self.operate(rshift, other) 

451 

452 def concat(self, other): 

453 """Implement the 'concat' operator. 

454 

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

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

457 

458 """ 

459 return self.operate(concat_op, other) 

460 

461 def like(self, other, escape=None): 

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

463 

464 In a column context, produces the expression:: 

465 

466 a LIKE other 

467 

468 E.g.:: 

469 

470 stmt = select([sometable]).\ 

471 where(sometable.c.column.like("%foobar%")) 

472 

473 :param other: expression to be compared 

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

475 keyword, e.g.:: 

476 

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

478 

479 .. seealso:: 

480 

481 :meth:`.ColumnOperators.ilike` 

482 

483 """ 

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

485 

486 def ilike(self, other, escape=None): 

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

488 

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

490 

491 lower(a) LIKE lower(other) 

492 

493 Or on backends that support the ILIKE operator:: 

494 

495 a ILIKE other 

496 

497 E.g.:: 

498 

499 stmt = select([sometable]).\ 

500 where(sometable.c.column.ilike("%foobar%")) 

501 

502 :param other: expression to be compared 

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

504 keyword, e.g.:: 

505 

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

507 

508 .. seealso:: 

509 

510 :meth:`.ColumnOperators.like` 

511 

512 """ 

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

514 

515 def in_(self, other): 

516 """Implement the ``in`` operator. 

517 

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

519 

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

521 

522 * A list of literal values, e.g.:: 

523 

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

525 

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

527 bound parameters the same length as the list given:: 

528 

529 WHERE COL IN (?, ?, ?) 

530 

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

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

533 

534 from sqlalchemy import tuple_ 

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

536 

537 * An empty list, e.g.:: 

538 

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

540 

541 In this calling form, the expression renders a "false" expression, 

542 e.g.:: 

543 

544 WHERE 1 != 1 

545 

546 This "false" expression has historically had different behaviors 

547 in older SQLAlchemy versions, see 

548 :paramref:`_sa.create_engine.empty_in_strategy` 

549 for behavioral options. 

550 

551 .. versionchanged:: 1.2 simplified the behavior of "empty in" 

552 expressions 

553 

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

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

556 

557 stmt.where(column.in_(bindparam('value', expanding=True))) 

558 

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

560 placeholder expression that looks like:: 

561 

562 WHERE COL IN ([EXPANDING_value]) 

563 

564 This placeholder expression is intercepted at statement execution 

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

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

567 

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

569 

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

571 

572 WHERE COL IN (?, ?, ?) 

573 

574 .. versionadded:: 1.2 added "expanding" bound parameters 

575 

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

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

578 SQLite this would be:: 

579 

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

581 

582 .. versionadded:: 1.3 "expanding" bound parameters now support 

583 empty lists 

584 

585 * a :func:`_expression.select` construct, 

586 which is usually a correlated 

587 scalar select:: 

588 

589 stmt.where( 

590 column.in_( 

591 select([othertable.c.y]). 

592 where(table.c.x == othertable.c.x) 

593 ) 

594 ) 

595 

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

597 

598 WHERE COL IN (SELECT othertable.y 

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

600 

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

602 construct, 

603 or a :func:`.bindparam` construct that includes the 

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

605 

606 """ 

607 return self.operate(in_op, other) 

608 

609 def notin_(self, other): 

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

611 

612 This is equivalent to using negation with 

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

614 

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

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

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

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

619 alter this behavior. 

620 

621 .. versionchanged:: 1.2 The :meth:`.ColumnOperators.in_` and 

622 :meth:`.ColumnOperators.notin_` operators 

623 now produce a "static" expression for an empty IN sequence 

624 by default. 

625 

626 .. seealso:: 

627 

628 :meth:`.ColumnOperators.in_` 

629 

630 """ 

631 return self.operate(notin_op, other) 

632 

633 def notlike(self, other, escape=None): 

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

635 

636 This is equivalent to using negation with 

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

638 

639 .. seealso:: 

640 

641 :meth:`.ColumnOperators.like` 

642 

643 """ 

644 return self.operate(notlike_op, other, escape=escape) 

645 

646 def notilike(self, other, escape=None): 

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

648 

649 This is equivalent to using negation with 

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

651 

652 .. seealso:: 

653 

654 :meth:`.ColumnOperators.ilike` 

655 

656 """ 

657 return self.operate(notilike_op, other, escape=escape) 

658 

659 def is_(self, other): 

660 """Implement the ``IS`` operator. 

661 

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

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

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

665 on certain platforms. 

666 

667 .. seealso:: :meth:`.ColumnOperators.isnot` 

668 

669 """ 

670 return self.operate(is_, other) 

671 

672 def isnot(self, other): 

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

674 

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

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

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

678 on certain platforms. 

679 

680 .. seealso:: :meth:`.ColumnOperators.is_` 

681 

682 """ 

683 return self.operate(isnot, other) 

684 

685 def startswith(self, other, **kwargs): 

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

687 

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

689 of a string value:: 

690 

691 column LIKE <other> || '%' 

692 

693 E.g.:: 

694 

695 stmt = select([sometable]).\ 

696 where(sometable.c.column.startswith("foobar")) 

697 

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

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

700 will behave like wildcards as well. For literal string 

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

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

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

704 and not as wildcard characters. Alternatively, the 

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

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

707 the target expression is not a literal string. 

708 

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

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

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

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

713 set to True. 

714 

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

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

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

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

719 SQL expression. 

720 

721 An expression such as:: 

722 

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

724 

725 Will render as:: 

726 

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

728 

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

730 

731 .. versionadded:: 1.2 

732 

733 .. versionchanged:: 1.2.0 The 

734 :paramref:`.ColumnOperators.startswith.autoescape` parameter is 

735 now a simple boolean rather than a character; the escape 

736 character itself is also escaped, and defaults to a forwards 

737 slash, which itself can be customized using the 

738 :paramref:`.ColumnOperators.startswith.escape` parameter. 

739 

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

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

742 character. This character can then be placed preceding occurrences 

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

744 wildcard characters. 

745 

746 An expression such as:: 

747 

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

749 

750 Will render as:: 

751 

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

753 

754 The parameter may also be combined with 

755 :paramref:`.ColumnOperators.startswith.autoescape`:: 

756 

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

758 

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

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

761 

762 .. seealso:: 

763 

764 :meth:`.ColumnOperators.endswith` 

765 

766 :meth:`.ColumnOperators.contains` 

767 

768 :meth:`.ColumnOperators.like` 

769 

770 """ 

771 return self.operate(startswith_op, other, **kwargs) 

772 

773 def endswith(self, other, **kwargs): 

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

775 

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

777 of a string value:: 

778 

779 column LIKE '%' || <other> 

780 

781 E.g.:: 

782 

783 stmt = select([sometable]).\ 

784 where(sometable.c.column.endswith("foobar")) 

785 

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

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

788 will behave like wildcards as well. For literal string 

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

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

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

792 and not as wildcard characters. Alternatively, the 

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

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

795 the target expression is not a literal string. 

796 

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

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

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

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

801 set to True. 

802 

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

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

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

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

807 SQL expression. 

808 

809 An expression such as:: 

810 

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

812 

813 Will render as:: 

814 

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

816 

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

818 

819 .. versionadded:: 1.2 

820 

821 .. versionchanged:: 1.2.0 The 

822 :paramref:`.ColumnOperators.endswith.autoescape` parameter is 

823 now a simple boolean rather than a character; the escape 

824 character itself is also escaped, and defaults to a forwards 

825 slash, which itself can be customized using the 

826 :paramref:`.ColumnOperators.endswith.escape` parameter. 

827 

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

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

830 character. This character can then be placed preceding occurrences 

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

832 wildcard characters. 

833 

834 An expression such as:: 

835 

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

837 

838 Will render as:: 

839 

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

841 

842 The parameter may also be combined with 

843 :paramref:`.ColumnOperators.endswith.autoescape`:: 

844 

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

846 

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

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

849 

850 .. seealso:: 

851 

852 :meth:`.ColumnOperators.startswith` 

853 

854 :meth:`.ColumnOperators.contains` 

855 

856 :meth:`.ColumnOperators.like` 

857 

858 """ 

859 return self.operate(endswith_op, other, **kwargs) 

860 

861 def contains(self, other, **kwargs): 

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

863 

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

865 of a string value:: 

866 

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

868 

869 E.g.:: 

870 

871 stmt = select([sometable]).\ 

872 where(sometable.c.column.contains("foobar")) 

873 

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

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

876 will behave like wildcards as well. For literal string 

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

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

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

880 and not as wildcard characters. Alternatively, the 

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

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

883 the target expression is not a literal string. 

884 

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

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

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

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

889 set to True. 

890 

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

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

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

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

895 SQL expression. 

896 

897 An expression such as:: 

898 

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

900 

901 Will render as:: 

902 

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

904 

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

906 

907 .. versionadded:: 1.2 

908 

909 .. versionchanged:: 1.2.0 The 

910 :paramref:`.ColumnOperators.contains.autoescape` parameter is 

911 now a simple boolean rather than a character; the escape 

912 character itself is also escaped, and defaults to a forwards 

913 slash, which itself can be customized using the 

914 :paramref:`.ColumnOperators.contains.escape` parameter. 

915 

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

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

918 character. This character can then be placed preceding occurrences 

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

920 wildcard characters. 

921 

922 An expression such as:: 

923 

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

925 

926 Will render as:: 

927 

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

929 

930 The parameter may also be combined with 

931 :paramref:`.ColumnOperators.contains.autoescape`:: 

932 

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

934 

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

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

937 

938 .. seealso:: 

939 

940 :meth:`.ColumnOperators.startswith` 

941 

942 :meth:`.ColumnOperators.endswith` 

943 

944 :meth:`.ColumnOperators.like` 

945 

946 

947 """ 

948 return self.operate(contains_op, other, **kwargs) 

949 

950 def match(self, other, **kwargs): 

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

952 

953 :meth:`~.ColumnOperators.match` attempts to resolve to 

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

955 Examples include: 

956 

957 * PostgreSQL - renders ``x @@ to_tsquery(y)`` 

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

959 * Oracle - renders ``CONTAINS(x, y)`` 

960 * other backends may provide special implementations. 

961 * Backends without any special implementation will emit 

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

963 example. 

964 

965 """ 

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

967 

968 def desc(self): 

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

970 parent object.""" 

971 return self.operate(desc_op) 

972 

973 def asc(self): 

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

975 parent object.""" 

976 return self.operate(asc_op) 

977 

978 def nullsfirst(self): 

979 """Produce a :func:`_expression.nullsfirst` clause against the 

980 parent object.""" 

981 return self.operate(nullsfirst_op) 

982 

983 def nullslast(self): 

984 """Produce a :func:`_expression.nullslast` clause against the 

985 parent object.""" 

986 return self.operate(nullslast_op) 

987 

988 def collate(self, collation): 

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

990 the parent object, given the collation string. 

991 

992 .. seealso:: 

993 

994 :func:`_expression.collate` 

995 

996 """ 

997 return self.operate(collate, collation) 

998 

999 def __radd__(self, other): 

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

1001 

1002 See :meth:`.ColumnOperators.__add__`. 

1003 

1004 """ 

1005 return self.reverse_operate(add, other) 

1006 

1007 def __rsub__(self, other): 

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

1009 

1010 See :meth:`.ColumnOperators.__sub__`. 

1011 

1012 """ 

1013 return self.reverse_operate(sub, other) 

1014 

1015 def __rmul__(self, other): 

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

1017 

1018 See :meth:`.ColumnOperators.__mul__`. 

1019 

1020 """ 

1021 return self.reverse_operate(mul, other) 

1022 

1023 def __rdiv__(self, other): 

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

1025 

1026 See :meth:`.ColumnOperators.__div__`. 

1027 

1028 """ 

1029 return self.reverse_operate(div, other) 

1030 

1031 def __rmod__(self, other): 

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

1033 

1034 See :meth:`.ColumnOperators.__mod__`. 

1035 

1036 """ 

1037 return self.reverse_operate(mod, other) 

1038 

1039 def between(self, cleft, cright, symmetric=False): 

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

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

1042 

1043 """ 

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

1045 

1046 def distinct(self): 

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

1048 parent object. 

1049 

1050 """ 

1051 return self.operate(distinct_op) 

1052 

1053 def any_(self): 

1054 """Produce a :func:`_expression.any_` clause against the 

1055 parent object. 

1056 

1057 This operator is only appropriate against a scalar subquery 

1058 object, or for some backends an column expression that is 

1059 against the ARRAY type, e.g.:: 

1060 

1061 # postgresql '5 = ANY (somearray)' 

1062 expr = 5 == mytable.c.somearray.any_() 

1063 

1064 # mysql '5 = ANY (SELECT value FROM table)' 

1065 expr = 5 == select([table.c.value]).as_scalar().any_() 

1066 

1067 .. seealso:: 

1068 

1069 :func:`_expression.any_` - standalone version 

1070 

1071 :func:`_expression.all_` - ALL operator 

1072 

1073 .. versionadded:: 1.1 

1074 

1075 """ 

1076 return self.operate(any_op) 

1077 

1078 def all_(self): 

1079 """Produce a :func:`_expression.all_` clause against the 

1080 parent object. 

1081 

1082 This operator is only appropriate against a scalar subquery 

1083 object, or for some backends an column expression that is 

1084 against the ARRAY type, e.g.:: 

1085 

1086 # postgresql '5 = ALL (somearray)' 

1087 expr = 5 == mytable.c.somearray.all_() 

1088 

1089 # mysql '5 = ALL (SELECT value FROM table)' 

1090 expr = 5 == select([table.c.value]).as_scalar().all_() 

1091 

1092 .. seealso:: 

1093 

1094 :func:`_expression.all_` - standalone version 

1095 

1096 :func:`_expression.any_` - ANY operator 

1097 

1098 .. versionadded:: 1.1 

1099 

1100 """ 

1101 return self.operate(all_op) 

1102 

1103 def __add__(self, other): 

1104 """Implement the ``+`` operator. 

1105 

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

1107 if the parent object has non-string affinity. 

1108 If the parent object has a string affinity, 

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

1110 see :meth:`.ColumnOperators.concat`. 

1111 

1112 """ 

1113 return self.operate(add, other) 

1114 

1115 def __sub__(self, other): 

1116 """Implement the ``-`` operator. 

1117 

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

1119 

1120 """ 

1121 return self.operate(sub, other) 

1122 

1123 def __mul__(self, other): 

1124 """Implement the ``*`` operator. 

1125 

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

1127 

1128 """ 

1129 return self.operate(mul, other) 

1130 

1131 def __div__(self, other): 

1132 """Implement the ``/`` operator. 

1133 

1134 In a column context, produces the clause ``a / b``. 

1135 

1136 """ 

1137 return self.operate(div, other) 

1138 

1139 def __mod__(self, other): 

1140 """Implement the ``%`` operator. 

1141 

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

1143 

1144 """ 

1145 return self.operate(mod, other) 

1146 

1147 def __truediv__(self, other): 

1148 """Implement the ``//`` operator. 

1149 

1150 In a column context, produces the clause ``a / b``. 

1151 

1152 """ 

1153 return self.operate(truediv, other) 

1154 

1155 def __rtruediv__(self, other): 

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

1157 

1158 See :meth:`.ColumnOperators.__truediv__`. 

1159 

1160 """ 

1161 return self.reverse_operate(truediv, other) 

1162 

1163 

1164_commutative = {eq, ne, add, mul} 

1165_comparison = {eq, ne, lt, gt, ge, le} 

1166 

1167 

1168def commutative_op(fn): 

1169 _commutative.add(fn) 

1170 return fn 

1171 

1172 

1173def comparison_op(fn): 

1174 _comparison.add(fn) 

1175 return fn 

1176 

1177 

1178def from_(): 

1179 raise NotImplementedError() 

1180 

1181 

1182@comparison_op 

1183def function_as_comparison_op(): 

1184 raise NotImplementedError() 

1185 

1186 

1187def as_(): 

1188 raise NotImplementedError() 

1189 

1190 

1191def exists(): 

1192 raise NotImplementedError() 

1193 

1194 

1195def istrue(a): 

1196 raise NotImplementedError() 

1197 

1198 

1199def isfalse(a): 

1200 raise NotImplementedError() 

1201 

1202 

1203@comparison_op 

1204def is_distinct_from(a, b): 

1205 return a.is_distinct_from(b) 

1206 

1207 

1208@comparison_op 

1209def isnot_distinct_from(a, b): 

1210 return a.isnot_distinct_from(b) 

1211 

1212 

1213@comparison_op 

1214def is_(a, b): 

1215 return a.is_(b) 

1216 

1217 

1218@comparison_op 

1219def isnot(a, b): 

1220 return a.isnot(b) 

1221 

1222 

1223def collate(a, b): 

1224 return a.collate(b) 

1225 

1226 

1227def op(a, opstring, b): 

1228 return a.op(opstring)(b) 

1229 

1230 

1231@comparison_op 

1232def like_op(a, b, escape=None): 

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

1234 

1235 

1236@comparison_op 

1237def notlike_op(a, b, escape=None): 

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

1239 

1240 

1241@comparison_op 

1242def ilike_op(a, b, escape=None): 

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

1244 

1245 

1246@comparison_op 

1247def notilike_op(a, b, escape=None): 

1248 return a.notilike(b, escape=escape) 

1249 

1250 

1251@comparison_op 

1252def between_op(a, b, c, symmetric=False): 

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

1254 

1255 

1256@comparison_op 

1257def notbetween_op(a, b, c, symmetric=False): 

1258 return a.notbetween(b, c, symmetric=symmetric) 

1259 

1260 

1261@comparison_op 

1262def in_op(a, b): 

1263 return a.in_(b) 

1264 

1265 

1266@comparison_op 

1267def notin_op(a, b): 

1268 return a.notin_(b) 

1269 

1270 

1271def distinct_op(a): 

1272 return a.distinct() 

1273 

1274 

1275def any_op(a): 

1276 return a.any_() 

1277 

1278 

1279def all_op(a): 

1280 return a.all_() 

1281 

1282 

1283def _escaped_like_impl(fn, other, escape, autoescape): 

1284 if autoescape: 

1285 if autoescape is not True: 

1286 util.warn( 

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

1288 ) 

1289 if escape is None: 

1290 escape = "/" 

1291 

1292 if not isinstance(other, util.compat.string_types): 

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

1294 

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

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

1297 

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

1299 

1300 return fn(other, escape=escape) 

1301 

1302 

1303@comparison_op 

1304def startswith_op(a, b, escape=None, autoescape=False): 

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

1306 

1307 

1308@comparison_op 

1309def notstartswith_op(a, b, escape=None, autoescape=False): 

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

1311 

1312 

1313@comparison_op 

1314def endswith_op(a, b, escape=None, autoescape=False): 

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

1316 

1317 

1318@comparison_op 

1319def notendswith_op(a, b, escape=None, autoescape=False): 

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

1321 

1322 

1323@comparison_op 

1324def contains_op(a, b, escape=None, autoescape=False): 

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

1326 

1327 

1328@comparison_op 

1329def notcontains_op(a, b, escape=None, autoescape=False): 

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

1331 

1332 

1333@comparison_op 

1334def match_op(a, b, **kw): 

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

1336 

1337 

1338@comparison_op 

1339def notmatch_op(a, b, **kw): 

1340 return a.notmatch(b, **kw) 

1341 

1342 

1343def comma_op(a, b): 

1344 raise NotImplementedError() 

1345 

1346 

1347@comparison_op 

1348def empty_in_op(a, b): 

1349 raise NotImplementedError() 

1350 

1351 

1352@comparison_op 

1353def empty_notin_op(a, b): 

1354 raise NotImplementedError() 

1355 

1356 

1357def filter_op(a, b): 

1358 raise NotImplementedError() 

1359 

1360 

1361def concat_op(a, b): 

1362 return a.concat(b) 

1363 

1364 

1365def desc_op(a): 

1366 return a.desc() 

1367 

1368 

1369def asc_op(a): 

1370 return a.asc() 

1371 

1372 

1373def nullsfirst_op(a): 

1374 return a.nullsfirst() 

1375 

1376 

1377def nullslast_op(a): 

1378 return a.nullslast() 

1379 

1380 

1381def json_getitem_op(a, b): 

1382 raise NotImplementedError() 

1383 

1384 

1385def json_path_getitem_op(a, b): 

1386 raise NotImplementedError() 

1387 

1388 

1389def is_comparison(op): 

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

1391 

1392 

1393def is_commutative(op): 

1394 return op in _commutative 

1395 

1396 

1397def is_ordering_modifier(op): 

1398 return op in (asc_op, desc_op, nullsfirst_op, nullslast_op) 

1399 

1400 

1401def is_natural_self_precedent(op): 

1402 return ( 

1403 op in _natural_self_precedent 

1404 or isinstance(op, custom_op) 

1405 and op.natural_self_precedent 

1406 ) 

1407 

1408 

1409_booleans = (inv, istrue, isfalse, and_, or_) 

1410 

1411 

1412def is_boolean(op): 

1413 return is_comparison(op) or op in _booleans 

1414 

1415 

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

1417 

1418 

1419def mirror(op): 

1420 """rotate a comparison operator 180 degrees. 

1421 

1422 Note this is not the same as negation. 

1423 

1424 """ 

1425 return _mirror.get(op, op) 

1426 

1427 

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

1429 

1430_natural_self_precedent = _associative.union( 

1431 [getitem, json_getitem_op, json_path_getitem_op] 

1432) 

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

1434parenthesize (a op b). 

1435 

1436""" 

1437 

1438 

1439_asbool = util.symbol("_asbool", canonical=-10) 

1440_smallest = util.symbol("_smallest", canonical=-100) 

1441_largest = util.symbol("_largest", canonical=100) 

1442 

1443_PRECEDENCE = { 

1444 from_: 15, 

1445 function_as_comparison_op: 15, 

1446 any_op: 15, 

1447 all_op: 15, 

1448 getitem: 15, 

1449 json_getitem_op: 15, 

1450 json_path_getitem_op: 15, 

1451 mul: 8, 

1452 truediv: 8, 

1453 div: 8, 

1454 mod: 8, 

1455 neg: 8, 

1456 add: 7, 

1457 sub: 7, 

1458 concat_op: 6, 

1459 filter_op: 6, 

1460 match_op: 5, 

1461 notmatch_op: 5, 

1462 ilike_op: 5, 

1463 notilike_op: 5, 

1464 like_op: 5, 

1465 notlike_op: 5, 

1466 in_op: 5, 

1467 notin_op: 5, 

1468 is_: 5, 

1469 isnot: 5, 

1470 eq: 5, 

1471 ne: 5, 

1472 is_distinct_from: 5, 

1473 isnot_distinct_from: 5, 

1474 empty_in_op: 5, 

1475 empty_notin_op: 5, 

1476 gt: 5, 

1477 lt: 5, 

1478 ge: 5, 

1479 le: 5, 

1480 between_op: 5, 

1481 notbetween_op: 5, 

1482 distinct_op: 5, 

1483 inv: 5, 

1484 istrue: 5, 

1485 isfalse: 5, 

1486 and_: 3, 

1487 or_: 2, 

1488 comma_op: -1, 

1489 desc_op: 3, 

1490 asc_op: 3, 

1491 collate: 4, 

1492 as_: -1, 

1493 exists: 0, 

1494 _asbool: -10, 

1495 _smallest: _smallest, 

1496 _largest: _largest, 

1497} 

1498 

1499 

1500def is_precedent(operator, against): 

1501 if operator is against and is_natural_self_precedent(operator): 

1502 return False 

1503 else: 

1504 return _PRECEDENCE.get( 

1505 operator, getattr(operator, "precedence", _smallest) 

1506 ) <= _PRECEDENCE.get(against, getattr(against, "precedence", _largest))