This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# sql/operators.py
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2023 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
@@ -77,7 +77,8 @@ class OperatorType(Protocol):
|
||||
right: Optional[Any] = None,
|
||||
*other: Any,
|
||||
**kwargs: Any,
|
||||
) -> ColumnElement[Any]: ...
|
||||
) -> ColumnElement[Any]:
|
||||
...
|
||||
|
||||
@overload
|
||||
def __call__(
|
||||
@@ -86,7 +87,8 @@ class OperatorType(Protocol):
|
||||
right: Optional[Any] = None,
|
||||
*other: Any,
|
||||
**kwargs: Any,
|
||||
) -> Operators: ...
|
||||
) -> Operators:
|
||||
...
|
||||
|
||||
def __call__(
|
||||
self,
|
||||
@@ -94,7 +96,8 @@ class OperatorType(Protocol):
|
||||
right: Optional[Any] = None,
|
||||
*other: Any,
|
||||
**kwargs: Any,
|
||||
) -> Operators: ...
|
||||
) -> Operators:
|
||||
...
|
||||
|
||||
|
||||
add = cast(OperatorType, _uncast_add)
|
||||
@@ -148,7 +151,6 @@ class Operators:
|
||||
is equivalent to::
|
||||
|
||||
from sqlalchemy import and_
|
||||
|
||||
and_(a, b)
|
||||
|
||||
Care should be taken when using ``&`` regarding
|
||||
@@ -173,7 +175,6 @@ class Operators:
|
||||
is equivalent to::
|
||||
|
||||
from sqlalchemy import or_
|
||||
|
||||
or_(a, b)
|
||||
|
||||
Care should be taken when using ``|`` regarding
|
||||
@@ -198,7 +199,6 @@ class Operators:
|
||||
is equivalent to::
|
||||
|
||||
from sqlalchemy import not_
|
||||
|
||||
not_(a)
|
||||
|
||||
"""
|
||||
@@ -227,7 +227,7 @@ class Operators:
|
||||
This function can also be used to make bitwise operators explicit. For
|
||||
example::
|
||||
|
||||
somecolumn.op("&")(0xFF)
|
||||
somecolumn.op('&')(0xff)
|
||||
|
||||
is a bitwise AND of the value in ``somecolumn``.
|
||||
|
||||
@@ -278,7 +278,7 @@ class Operators:
|
||||
|
||||
e.g.::
|
||||
|
||||
>>> expr = column("x").op("+", python_impl=lambda a, b: a + b)("y")
|
||||
>>> expr = column('x').op('+', python_impl=lambda a, b: a + b)('y')
|
||||
|
||||
The operator for the above expression will also work for non-SQL
|
||||
left and right objects::
|
||||
@@ -392,9 +392,10 @@ class custom_op(OperatorType, Generic[_T]):
|
||||
from sqlalchemy.sql import operators
|
||||
from sqlalchemy import Numeric
|
||||
|
||||
unary = UnaryExpression(
|
||||
table.c.somecolumn, modifier=operators.custom_op("!"), type_=Numeric
|
||||
)
|
||||
unary = UnaryExpression(table.c.somecolumn,
|
||||
modifier=operators.custom_op("!"),
|
||||
type_=Numeric)
|
||||
|
||||
|
||||
.. seealso::
|
||||
|
||||
@@ -402,7 +403,7 @@ class custom_op(OperatorType, Generic[_T]):
|
||||
|
||||
:meth:`.Operators.bool_op`
|
||||
|
||||
""" # noqa: E501
|
||||
"""
|
||||
|
||||
__name__ = "custom_op"
|
||||
|
||||
@@ -465,7 +466,8 @@ class custom_op(OperatorType, Generic[_T]):
|
||||
right: Optional[Any] = None,
|
||||
*other: Any,
|
||||
**kwargs: Any,
|
||||
) -> ColumnElement[Any]: ...
|
||||
) -> ColumnElement[Any]:
|
||||
...
|
||||
|
||||
@overload
|
||||
def __call__(
|
||||
@@ -474,7 +476,8 @@ class custom_op(OperatorType, Generic[_T]):
|
||||
right: Optional[Any] = None,
|
||||
*other: Any,
|
||||
**kwargs: Any,
|
||||
) -> Operators: ...
|
||||
) -> Operators:
|
||||
...
|
||||
|
||||
def __call__(
|
||||
self,
|
||||
@@ -542,11 +545,13 @@ class ColumnOperators(Operators):
|
||||
|
||||
def operate(
|
||||
self, op: OperatorType, *other: Any, **kwargs: Any
|
||||
) -> ColumnOperators: ...
|
||||
) -> ColumnOperators:
|
||||
...
|
||||
|
||||
def reverse_operate(
|
||||
self, op: OperatorType, other: Any, **kwargs: Any
|
||||
) -> ColumnOperators: ...
|
||||
) -> ColumnOperators:
|
||||
...
|
||||
|
||||
def __lt__(self, other: Any) -> ColumnOperators:
|
||||
"""Implement the ``<`` operator.
|
||||
@@ -569,7 +574,8 @@ class ColumnOperators(Operators):
|
||||
# https://docs.python.org/3/reference/datamodel.html#object.__hash__
|
||||
if TYPE_CHECKING:
|
||||
|
||||
def __hash__(self) -> int: ...
|
||||
def __hash__(self) -> int:
|
||||
...
|
||||
|
||||
else:
|
||||
__hash__ = Operators.__hash__
|
||||
@@ -617,7 +623,8 @@ class ColumnOperators(Operators):
|
||||
# deprecated 1.4; see #5435
|
||||
if TYPE_CHECKING:
|
||||
|
||||
def isnot_distinct_from(self, other: Any) -> ColumnOperators: ...
|
||||
def isnot_distinct_from(self, other: Any) -> ColumnOperators:
|
||||
...
|
||||
|
||||
else:
|
||||
isnot_distinct_from = is_not_distinct_from
|
||||
@@ -700,15 +707,14 @@ class ColumnOperators(Operators):
|
||||
) -> ColumnOperators:
|
||||
r"""Implement the ``like`` operator.
|
||||
|
||||
In a column context, produces the expression:
|
||||
|
||||
.. sourcecode:: sql
|
||||
In a column context, produces the expression::
|
||||
|
||||
a LIKE other
|
||||
|
||||
E.g.::
|
||||
|
||||
stmt = select(sometable).where(sometable.c.column.like("%foobar%"))
|
||||
stmt = select(sometable).\
|
||||
where(sometable.c.column.like("%foobar%"))
|
||||
|
||||
:param other: expression to be compared
|
||||
:param escape: optional escape character, renders the ``ESCAPE``
|
||||
@@ -728,21 +734,18 @@ class ColumnOperators(Operators):
|
||||
) -> ColumnOperators:
|
||||
r"""Implement the ``ilike`` operator, e.g. case insensitive LIKE.
|
||||
|
||||
In a column context, produces an expression either of the form:
|
||||
|
||||
.. sourcecode:: sql
|
||||
In a column context, produces an expression either of the form::
|
||||
|
||||
lower(a) LIKE lower(other)
|
||||
|
||||
Or on backends that support the ILIKE operator:
|
||||
|
||||
.. sourcecode:: sql
|
||||
Or on backends that support the ILIKE operator::
|
||||
|
||||
a ILIKE other
|
||||
|
||||
E.g.::
|
||||
|
||||
stmt = select(sometable).where(sometable.c.column.ilike("%foobar%"))
|
||||
stmt = select(sometable).\
|
||||
where(sometable.c.column.ilike("%foobar%"))
|
||||
|
||||
:param other: expression to be compared
|
||||
:param escape: optional escape character, renders the ``ESCAPE``
|
||||
@@ -754,7 +757,7 @@ class ColumnOperators(Operators):
|
||||
|
||||
:meth:`.ColumnOperators.like`
|
||||
|
||||
""" # noqa: E501
|
||||
"""
|
||||
return self.operate(ilike_op, other, escape=escape)
|
||||
|
||||
def bitwise_xor(self, other: Any) -> ColumnOperators:
|
||||
@@ -848,15 +851,12 @@ class ColumnOperators(Operators):
|
||||
|
||||
The given parameter ``other`` may be:
|
||||
|
||||
* A list of literal values,
|
||||
e.g.::
|
||||
* A list of literal values, e.g.::
|
||||
|
||||
stmt.where(column.in_([1, 2, 3]))
|
||||
|
||||
In this calling form, the list of items is converted to a set of
|
||||
bound parameters the same length as the list given:
|
||||
|
||||
.. sourcecode:: sql
|
||||
bound parameters the same length as the list given::
|
||||
|
||||
WHERE COL IN (?, ?, ?)
|
||||
|
||||
@@ -864,20 +864,16 @@ class ColumnOperators(Operators):
|
||||
:func:`.tuple_` containing multiple expressions::
|
||||
|
||||
from sqlalchemy import tuple_
|
||||
|
||||
stmt.where(tuple_(col1, col2).in_([(1, 10), (2, 20), (3, 30)]))
|
||||
|
||||
* An empty list,
|
||||
e.g.::
|
||||
* An empty list, e.g.::
|
||||
|
||||
stmt.where(column.in_([]))
|
||||
|
||||
In this calling form, the expression renders an "empty set"
|
||||
expression. These expressions are tailored to individual backends
|
||||
and are generally trying to get an empty SELECT statement as a
|
||||
subquery. Such as on SQLite, the expression is:
|
||||
|
||||
.. sourcecode:: sql
|
||||
subquery. Such as on SQLite, the expression is::
|
||||
|
||||
WHERE col IN (SELECT 1 FROM (SELECT 1) WHERE 1!=1)
|
||||
|
||||
@@ -887,12 +883,10 @@ class ColumnOperators(Operators):
|
||||
* A bound parameter, e.g. :func:`.bindparam`, may be used if it
|
||||
includes the :paramref:`.bindparam.expanding` flag::
|
||||
|
||||
stmt.where(column.in_(bindparam("value", expanding=True)))
|
||||
stmt.where(column.in_(bindparam('value', expanding=True)))
|
||||
|
||||
In this calling form, the expression renders a special non-SQL
|
||||
placeholder expression that looks like:
|
||||
|
||||
.. sourcecode:: sql
|
||||
placeholder expression that looks like::
|
||||
|
||||
WHERE COL IN ([EXPANDING_value])
|
||||
|
||||
@@ -902,9 +896,7 @@ class ColumnOperators(Operators):
|
||||
|
||||
connection.execute(stmt, {"value": [1, 2, 3]})
|
||||
|
||||
The database would be passed a bound parameter for each value:
|
||||
|
||||
.. sourcecode:: sql
|
||||
The database would be passed a bound parameter for each value::
|
||||
|
||||
WHERE COL IN (?, ?, ?)
|
||||
|
||||
@@ -912,9 +904,7 @@ class ColumnOperators(Operators):
|
||||
|
||||
If an empty list is passed, a special "empty list" expression,
|
||||
which is specific to the database in use, is rendered. On
|
||||
SQLite this would be:
|
||||
|
||||
.. sourcecode:: sql
|
||||
SQLite this would be::
|
||||
|
||||
WHERE COL IN (SELECT 1 FROM (SELECT 1) WHERE 1!=1)
|
||||
|
||||
@@ -925,12 +915,13 @@ class ColumnOperators(Operators):
|
||||
correlated scalar select::
|
||||
|
||||
stmt.where(
|
||||
column.in_(select(othertable.c.y).where(table.c.x == othertable.c.x))
|
||||
column.in_(
|
||||
select(othertable.c.y).
|
||||
where(table.c.x == othertable.c.x)
|
||||
)
|
||||
)
|
||||
|
||||
In this calling form, :meth:`.ColumnOperators.in_` renders as given:
|
||||
|
||||
.. sourcecode:: sql
|
||||
In this calling form, :meth:`.ColumnOperators.in_` renders as given::
|
||||
|
||||
WHERE COL IN (SELECT othertable.y
|
||||
FROM othertable WHERE othertable.x = table.x)
|
||||
@@ -939,7 +930,7 @@ class ColumnOperators(Operators):
|
||||
construct, or a :func:`.bindparam` construct that includes the
|
||||
:paramref:`.bindparam.expanding` flag set to True.
|
||||
|
||||
""" # noqa: E501
|
||||
"""
|
||||
return self.operate(in_op, other)
|
||||
|
||||
def not_in(self, other: Any) -> ColumnOperators:
|
||||
@@ -973,7 +964,8 @@ class ColumnOperators(Operators):
|
||||
# deprecated 1.4; see #5429
|
||||
if TYPE_CHECKING:
|
||||
|
||||
def notin_(self, other: Any) -> ColumnOperators: ...
|
||||
def notin_(self, other: Any) -> ColumnOperators:
|
||||
...
|
||||
|
||||
else:
|
||||
notin_ = not_in
|
||||
@@ -1002,7 +994,8 @@ class ColumnOperators(Operators):
|
||||
|
||||
def notlike(
|
||||
self, other: Any, escape: Optional[str] = None
|
||||
) -> ColumnOperators: ...
|
||||
) -> ColumnOperators:
|
||||
...
|
||||
|
||||
else:
|
||||
notlike = not_like
|
||||
@@ -1031,7 +1024,8 @@ class ColumnOperators(Operators):
|
||||
|
||||
def notilike(
|
||||
self, other: Any, escape: Optional[str] = None
|
||||
) -> ColumnOperators: ...
|
||||
) -> ColumnOperators:
|
||||
...
|
||||
|
||||
else:
|
||||
notilike = not_ilike
|
||||
@@ -1069,7 +1063,8 @@ class ColumnOperators(Operators):
|
||||
# deprecated 1.4; see #5429
|
||||
if TYPE_CHECKING:
|
||||
|
||||
def isnot(self, other: Any) -> ColumnOperators: ...
|
||||
def isnot(self, other: Any) -> ColumnOperators:
|
||||
...
|
||||
|
||||
else:
|
||||
isnot = is_not
|
||||
@@ -1083,15 +1078,14 @@ class ColumnOperators(Operators):
|
||||
r"""Implement the ``startswith`` operator.
|
||||
|
||||
Produces a LIKE expression that tests against a match for the start
|
||||
of a string value:
|
||||
|
||||
.. sourcecode:: sql
|
||||
of a string value::
|
||||
|
||||
column LIKE <other> || '%'
|
||||
|
||||
E.g.::
|
||||
|
||||
stmt = select(sometable).where(sometable.c.column.startswith("foobar"))
|
||||
stmt = select(sometable).\
|
||||
where(sometable.c.column.startswith("foobar"))
|
||||
|
||||
Since the operator uses ``LIKE``, wildcard characters
|
||||
``"%"`` and ``"_"`` that are present inside the <other> expression
|
||||
@@ -1120,9 +1114,7 @@ class ColumnOperators(Operators):
|
||||
|
||||
somecolumn.startswith("foo%bar", autoescape=True)
|
||||
|
||||
Will render as:
|
||||
|
||||
.. sourcecode:: sql
|
||||
Will render as::
|
||||
|
||||
somecolumn LIKE :param || '%' ESCAPE '/'
|
||||
|
||||
@@ -1138,9 +1130,7 @@ class ColumnOperators(Operators):
|
||||
|
||||
somecolumn.startswith("foo/%bar", escape="^")
|
||||
|
||||
Will render as:
|
||||
|
||||
.. sourcecode:: sql
|
||||
Will render as::
|
||||
|
||||
somecolumn LIKE :param || '%' ESCAPE '^'
|
||||
|
||||
@@ -1160,7 +1150,7 @@ class ColumnOperators(Operators):
|
||||
|
||||
:meth:`.ColumnOperators.like`
|
||||
|
||||
""" # noqa: E501
|
||||
"""
|
||||
return self.operate(
|
||||
startswith_op, other, escape=escape, autoescape=autoescape
|
||||
)
|
||||
@@ -1175,15 +1165,14 @@ class ColumnOperators(Operators):
|
||||
version of :meth:`.ColumnOperators.startswith`.
|
||||
|
||||
Produces a LIKE expression that tests against an insensitive
|
||||
match for the start of a string value:
|
||||
|
||||
.. sourcecode:: sql
|
||||
match for the start of a string value::
|
||||
|
||||
lower(column) LIKE lower(<other>) || '%'
|
||||
|
||||
E.g.::
|
||||
|
||||
stmt = select(sometable).where(sometable.c.column.istartswith("foobar"))
|
||||
stmt = select(sometable).\
|
||||
where(sometable.c.column.istartswith("foobar"))
|
||||
|
||||
Since the operator uses ``LIKE``, wildcard characters
|
||||
``"%"`` and ``"_"`` that are present inside the <other> expression
|
||||
@@ -1212,9 +1201,7 @@ class ColumnOperators(Operators):
|
||||
|
||||
somecolumn.istartswith("foo%bar", autoescape=True)
|
||||
|
||||
Will render as:
|
||||
|
||||
.. sourcecode:: sql
|
||||
Will render as::
|
||||
|
||||
lower(somecolumn) LIKE lower(:param) || '%' ESCAPE '/'
|
||||
|
||||
@@ -1230,9 +1217,7 @@ class ColumnOperators(Operators):
|
||||
|
||||
somecolumn.istartswith("foo/%bar", escape="^")
|
||||
|
||||
Will render as:
|
||||
|
||||
.. sourcecode:: sql
|
||||
Will render as::
|
||||
|
||||
lower(somecolumn) LIKE lower(:param) || '%' ESCAPE '^'
|
||||
|
||||
@@ -1247,7 +1232,7 @@ class ColumnOperators(Operators):
|
||||
.. seealso::
|
||||
|
||||
:meth:`.ColumnOperators.startswith`
|
||||
""" # noqa: E501
|
||||
"""
|
||||
return self.operate(
|
||||
istartswith_op, other, escape=escape, autoescape=autoescape
|
||||
)
|
||||
@@ -1261,15 +1246,14 @@ class ColumnOperators(Operators):
|
||||
r"""Implement the 'endswith' operator.
|
||||
|
||||
Produces a LIKE expression that tests against a match for the end
|
||||
of a string value:
|
||||
|
||||
.. sourcecode:: sql
|
||||
of a string value::
|
||||
|
||||
column LIKE '%' || <other>
|
||||
|
||||
E.g.::
|
||||
|
||||
stmt = select(sometable).where(sometable.c.column.endswith("foobar"))
|
||||
stmt = select(sometable).\
|
||||
where(sometable.c.column.endswith("foobar"))
|
||||
|
||||
Since the operator uses ``LIKE``, wildcard characters
|
||||
``"%"`` and ``"_"`` that are present inside the <other> expression
|
||||
@@ -1298,9 +1282,7 @@ class ColumnOperators(Operators):
|
||||
|
||||
somecolumn.endswith("foo%bar", autoescape=True)
|
||||
|
||||
Will render as:
|
||||
|
||||
.. sourcecode:: sql
|
||||
Will render as::
|
||||
|
||||
somecolumn LIKE '%' || :param ESCAPE '/'
|
||||
|
||||
@@ -1316,9 +1298,7 @@ class ColumnOperators(Operators):
|
||||
|
||||
somecolumn.endswith("foo/%bar", escape="^")
|
||||
|
||||
Will render as:
|
||||
|
||||
.. sourcecode:: sql
|
||||
Will render as::
|
||||
|
||||
somecolumn LIKE '%' || :param ESCAPE '^'
|
||||
|
||||
@@ -1338,7 +1318,7 @@ class ColumnOperators(Operators):
|
||||
|
||||
:meth:`.ColumnOperators.like`
|
||||
|
||||
""" # noqa: E501
|
||||
"""
|
||||
return self.operate(
|
||||
endswith_op, other, escape=escape, autoescape=autoescape
|
||||
)
|
||||
@@ -1353,15 +1333,14 @@ class ColumnOperators(Operators):
|
||||
version of :meth:`.ColumnOperators.endswith`.
|
||||
|
||||
Produces a LIKE expression that tests against an insensitive match
|
||||
for the end of a string value:
|
||||
|
||||
.. sourcecode:: sql
|
||||
for the end of a string value::
|
||||
|
||||
lower(column) LIKE '%' || lower(<other>)
|
||||
|
||||
E.g.::
|
||||
|
||||
stmt = select(sometable).where(sometable.c.column.iendswith("foobar"))
|
||||
stmt = select(sometable).\
|
||||
where(sometable.c.column.iendswith("foobar"))
|
||||
|
||||
Since the operator uses ``LIKE``, wildcard characters
|
||||
``"%"`` and ``"_"`` that are present inside the <other> expression
|
||||
@@ -1390,9 +1369,7 @@ class ColumnOperators(Operators):
|
||||
|
||||
somecolumn.iendswith("foo%bar", autoescape=True)
|
||||
|
||||
Will render as:
|
||||
|
||||
.. sourcecode:: sql
|
||||
Will render as::
|
||||
|
||||
lower(somecolumn) LIKE '%' || lower(:param) ESCAPE '/'
|
||||
|
||||
@@ -1408,9 +1385,7 @@ class ColumnOperators(Operators):
|
||||
|
||||
somecolumn.iendswith("foo/%bar", escape="^")
|
||||
|
||||
Will render as:
|
||||
|
||||
.. sourcecode:: sql
|
||||
Will render as::
|
||||
|
||||
lower(somecolumn) LIKE '%' || lower(:param) ESCAPE '^'
|
||||
|
||||
@@ -1425,7 +1400,7 @@ class ColumnOperators(Operators):
|
||||
.. seealso::
|
||||
|
||||
:meth:`.ColumnOperators.endswith`
|
||||
""" # noqa: E501
|
||||
"""
|
||||
return self.operate(
|
||||
iendswith_op, other, escape=escape, autoescape=autoescape
|
||||
)
|
||||
@@ -1434,15 +1409,14 @@ class ColumnOperators(Operators):
|
||||
r"""Implement the 'contains' operator.
|
||||
|
||||
Produces a LIKE expression that tests against a match for the middle
|
||||
of a string value:
|
||||
|
||||
.. sourcecode:: sql
|
||||
of a string value::
|
||||
|
||||
column LIKE '%' || <other> || '%'
|
||||
|
||||
E.g.::
|
||||
|
||||
stmt = select(sometable).where(sometable.c.column.contains("foobar"))
|
||||
stmt = select(sometable).\
|
||||
where(sometable.c.column.contains("foobar"))
|
||||
|
||||
Since the operator uses ``LIKE``, wildcard characters
|
||||
``"%"`` and ``"_"`` that are present inside the <other> expression
|
||||
@@ -1471,9 +1445,7 @@ class ColumnOperators(Operators):
|
||||
|
||||
somecolumn.contains("foo%bar", autoescape=True)
|
||||
|
||||
Will render as:
|
||||
|
||||
.. sourcecode:: sql
|
||||
Will render as::
|
||||
|
||||
somecolumn LIKE '%' || :param || '%' ESCAPE '/'
|
||||
|
||||
@@ -1489,9 +1461,7 @@ class ColumnOperators(Operators):
|
||||
|
||||
somecolumn.contains("foo/%bar", escape="^")
|
||||
|
||||
Will render as:
|
||||
|
||||
.. sourcecode:: sql
|
||||
Will render as::
|
||||
|
||||
somecolumn LIKE '%' || :param || '%' ESCAPE '^'
|
||||
|
||||
@@ -1512,7 +1482,7 @@ class ColumnOperators(Operators):
|
||||
:meth:`.ColumnOperators.like`
|
||||
|
||||
|
||||
""" # noqa: E501
|
||||
"""
|
||||
return self.operate(contains_op, other, **kw)
|
||||
|
||||
def icontains(self, other: Any, **kw: Any) -> ColumnOperators:
|
||||
@@ -1520,15 +1490,14 @@ class ColumnOperators(Operators):
|
||||
version of :meth:`.ColumnOperators.contains`.
|
||||
|
||||
Produces a LIKE expression that tests against an insensitive match
|
||||
for the middle of a string value:
|
||||
|
||||
.. sourcecode:: sql
|
||||
for the middle of a string value::
|
||||
|
||||
lower(column) LIKE '%' || lower(<other>) || '%'
|
||||
|
||||
E.g.::
|
||||
|
||||
stmt = select(sometable).where(sometable.c.column.icontains("foobar"))
|
||||
stmt = select(sometable).\
|
||||
where(sometable.c.column.icontains("foobar"))
|
||||
|
||||
Since the operator uses ``LIKE``, wildcard characters
|
||||
``"%"`` and ``"_"`` that are present inside the <other> expression
|
||||
@@ -1557,9 +1526,7 @@ class ColumnOperators(Operators):
|
||||
|
||||
somecolumn.icontains("foo%bar", autoescape=True)
|
||||
|
||||
Will render as:
|
||||
|
||||
.. sourcecode:: sql
|
||||
Will render as::
|
||||
|
||||
lower(somecolumn) LIKE '%' || lower(:param) || '%' ESCAPE '/'
|
||||
|
||||
@@ -1575,9 +1542,7 @@ class ColumnOperators(Operators):
|
||||
|
||||
somecolumn.icontains("foo/%bar", escape="^")
|
||||
|
||||
Will render as:
|
||||
|
||||
.. sourcecode:: sql
|
||||
Will render as::
|
||||
|
||||
lower(somecolumn) LIKE '%' || lower(:param) || '%' ESCAPE '^'
|
||||
|
||||
@@ -1593,7 +1558,7 @@ class ColumnOperators(Operators):
|
||||
|
||||
:meth:`.ColumnOperators.contains`
|
||||
|
||||
""" # noqa: E501
|
||||
"""
|
||||
return self.operate(icontains_op, other, **kw)
|
||||
|
||||
def match(self, other: Any, **kwargs: Any) -> ColumnOperators:
|
||||
@@ -1617,7 +1582,7 @@ class ColumnOperators(Operators):
|
||||
:class:`_mysql.match` - MySQL specific construct with
|
||||
additional features.
|
||||
|
||||
* Oracle Database - renders ``CONTAINS(x, y)``
|
||||
* Oracle - renders ``CONTAINS(x, y)``
|
||||
* other backends may provide special implementations.
|
||||
* Backends without any special implementation will emit
|
||||
the operator as "MATCH". This is compatible with SQLite, for
|
||||
@@ -1634,7 +1599,7 @@ class ColumnOperators(Operators):
|
||||
E.g.::
|
||||
|
||||
stmt = select(table.c.some_column).where(
|
||||
table.c.some_column.regexp_match("^(b|c)")
|
||||
table.c.some_column.regexp_match('^(b|c)')
|
||||
)
|
||||
|
||||
:meth:`_sql.ColumnOperators.regexp_match` attempts to resolve to
|
||||
@@ -1645,7 +1610,7 @@ class ColumnOperators(Operators):
|
||||
Examples include:
|
||||
|
||||
* PostgreSQL - renders ``x ~ y`` or ``x !~ y`` when negated.
|
||||
* Oracle Database - renders ``REGEXP_LIKE(x, y)``
|
||||
* Oracle - renders ``REGEXP_LIKE(x, y)``
|
||||
* SQLite - uses SQLite's ``REGEXP`` placeholder operator and calls into
|
||||
the Python ``re.match()`` builtin.
|
||||
* other backends may provide special implementations.
|
||||
@@ -1653,9 +1618,9 @@ class ColumnOperators(Operators):
|
||||
the operator as "REGEXP" or "NOT REGEXP". This is compatible with
|
||||
SQLite and MySQL, for example.
|
||||
|
||||
Regular expression support is currently implemented for Oracle
|
||||
Database, PostgreSQL, MySQL and MariaDB. Partial support is available
|
||||
for SQLite. Support among third-party dialects may vary.
|
||||
Regular expression support is currently implemented for Oracle,
|
||||
PostgreSQL, MySQL and MariaDB. Partial support is available for
|
||||
SQLite. Support among third-party dialects may vary.
|
||||
|
||||
:param pattern: The regular expression pattern string or column
|
||||
clause.
|
||||
@@ -1692,7 +1657,11 @@ class ColumnOperators(Operators):
|
||||
E.g.::
|
||||
|
||||
stmt = select(
|
||||
table.c.some_column.regexp_replace("b(..)", "X\1Y", flags="g")
|
||||
table.c.some_column.regexp_replace(
|
||||
'b(..)',
|
||||
'X\1Y',
|
||||
flags='g'
|
||||
)
|
||||
)
|
||||
|
||||
:meth:`_sql.ColumnOperators.regexp_replace` attempts to resolve to
|
||||
@@ -1702,8 +1671,8 @@ class ColumnOperators(Operators):
|
||||
**not backend agnostic**.
|
||||
|
||||
Regular expression replacement support is currently implemented for
|
||||
Oracle Database, PostgreSQL, MySQL 8 or greater and MariaDB. Support
|
||||
among third-party dialects may vary.
|
||||
Oracle, PostgreSQL, MySQL 8 or greater and MariaDB. Support among
|
||||
third-party dialects may vary.
|
||||
|
||||
:param pattern: The regular expression pattern string or column
|
||||
clause.
|
||||
@@ -1759,7 +1728,8 @@ class ColumnOperators(Operators):
|
||||
# deprecated 1.4; see #5435
|
||||
if TYPE_CHECKING:
|
||||
|
||||
def nullsfirst(self) -> ColumnOperators: ...
|
||||
def nullsfirst(self) -> ColumnOperators:
|
||||
...
|
||||
|
||||
else:
|
||||
nullsfirst = nulls_first
|
||||
@@ -1777,7 +1747,8 @@ class ColumnOperators(Operators):
|
||||
# deprecated 1.4; see #5429
|
||||
if TYPE_CHECKING:
|
||||
|
||||
def nullslast(self) -> ColumnOperators: ...
|
||||
def nullslast(self) -> ColumnOperators:
|
||||
...
|
||||
|
||||
else:
|
||||
nullslast = nulls_last
|
||||
@@ -1848,10 +1819,10 @@ class ColumnOperators(Operators):
|
||||
See the documentation for :func:`_sql.any_` for examples.
|
||||
|
||||
.. note:: be sure to not confuse the newer
|
||||
:meth:`_sql.ColumnOperators.any_` method with the **legacy**
|
||||
version of this method, the :meth:`_types.ARRAY.Comparator.any`
|
||||
method that's specific to :class:`_types.ARRAY`, which uses a
|
||||
different calling style.
|
||||
:meth:`_sql.ColumnOperators.any_` method with its older
|
||||
:class:`_types.ARRAY`-specific counterpart, the
|
||||
:meth:`_types.ARRAY.Comparator.any` method, which a different
|
||||
calling syntax and usage pattern.
|
||||
|
||||
"""
|
||||
return self.operate(any_op)
|
||||
@@ -1863,10 +1834,10 @@ class ColumnOperators(Operators):
|
||||
See the documentation for :func:`_sql.all_` for examples.
|
||||
|
||||
.. note:: be sure to not confuse the newer
|
||||
:meth:`_sql.ColumnOperators.all_` method with the **legacy**
|
||||
version of this method, the :meth:`_types.ARRAY.Comparator.all`
|
||||
method that's specific to :class:`_types.ARRAY`, which uses a
|
||||
different calling style.
|
||||
:meth:`_sql.ColumnOperators.all_` method with its older
|
||||
:class:`_types.ARRAY`-specific counterpart, the
|
||||
:meth:`_types.ARRAY.Comparator.all` method, which a different
|
||||
calling syntax and usage pattern.
|
||||
|
||||
"""
|
||||
return self.operate(all_op)
|
||||
@@ -1997,7 +1968,8 @@ def is_true(a: Any) -> Any:
|
||||
if TYPE_CHECKING:
|
||||
|
||||
@_operator_fn
|
||||
def istrue(a: Any) -> Any: ...
|
||||
def istrue(a: Any) -> Any:
|
||||
...
|
||||
|
||||
else:
|
||||
istrue = is_true
|
||||
@@ -2012,7 +1984,8 @@ def is_false(a: Any) -> Any:
|
||||
if TYPE_CHECKING:
|
||||
|
||||
@_operator_fn
|
||||
def isfalse(a: Any) -> Any: ...
|
||||
def isfalse(a: Any) -> Any:
|
||||
...
|
||||
|
||||
else:
|
||||
isfalse = is_false
|
||||
@@ -2034,7 +2007,8 @@ def is_not_distinct_from(a: Any, b: Any) -> Any:
|
||||
if TYPE_CHECKING:
|
||||
|
||||
@_operator_fn
|
||||
def isnot_distinct_from(a: Any, b: Any) -> Any: ...
|
||||
def isnot_distinct_from(a: Any, b: Any) -> Any:
|
||||
...
|
||||
|
||||
else:
|
||||
isnot_distinct_from = is_not_distinct_from
|
||||
@@ -2056,7 +2030,8 @@ def is_not(a: Any, b: Any) -> Any:
|
||||
if TYPE_CHECKING:
|
||||
|
||||
@_operator_fn
|
||||
def isnot(a: Any, b: Any) -> Any: ...
|
||||
def isnot(a: Any, b: Any) -> Any:
|
||||
...
|
||||
|
||||
else:
|
||||
isnot = is_not
|
||||
@@ -2088,7 +2063,8 @@ def not_like_op(a: Any, b: Any, escape: Optional[str] = None) -> Any:
|
||||
if TYPE_CHECKING:
|
||||
|
||||
@_operator_fn
|
||||
def notlike_op(a: Any, b: Any, escape: Optional[str] = None) -> Any: ...
|
||||
def notlike_op(a: Any, b: Any, escape: Optional[str] = None) -> Any:
|
||||
...
|
||||
|
||||
else:
|
||||
notlike_op = not_like_op
|
||||
@@ -2110,7 +2086,8 @@ def not_ilike_op(a: Any, b: Any, escape: Optional[str] = None) -> Any:
|
||||
if TYPE_CHECKING:
|
||||
|
||||
@_operator_fn
|
||||
def notilike_op(a: Any, b: Any, escape: Optional[str] = None) -> Any: ...
|
||||
def notilike_op(a: Any, b: Any, escape: Optional[str] = None) -> Any:
|
||||
...
|
||||
|
||||
else:
|
||||
notilike_op = not_ilike_op
|
||||
@@ -2132,9 +2109,8 @@ def not_between_op(a: Any, b: Any, c: Any, symmetric: bool = False) -> Any:
|
||||
if TYPE_CHECKING:
|
||||
|
||||
@_operator_fn
|
||||
def notbetween_op(
|
||||
a: Any, b: Any, c: Any, symmetric: bool = False
|
||||
) -> Any: ...
|
||||
def notbetween_op(a: Any, b: Any, c: Any, symmetric: bool = False) -> Any:
|
||||
...
|
||||
|
||||
else:
|
||||
notbetween_op = not_between_op
|
||||
@@ -2156,7 +2132,8 @@ def not_in_op(a: Any, b: Any) -> Any:
|
||||
if TYPE_CHECKING:
|
||||
|
||||
@_operator_fn
|
||||
def notin_op(a: Any, b: Any) -> Any: ...
|
||||
def notin_op(a: Any, b: Any) -> Any:
|
||||
...
|
||||
|
||||
else:
|
||||
notin_op = not_in_op
|
||||
@@ -2221,7 +2198,8 @@ if TYPE_CHECKING:
|
||||
@_operator_fn
|
||||
def notstartswith_op(
|
||||
a: Any, b: Any, escape: Optional[str] = None, autoescape: bool = False
|
||||
) -> Any: ...
|
||||
) -> Any:
|
||||
...
|
||||
|
||||
else:
|
||||
notstartswith_op = not_startswith_op
|
||||
@@ -2265,7 +2243,8 @@ if TYPE_CHECKING:
|
||||
@_operator_fn
|
||||
def notendswith_op(
|
||||
a: Any, b: Any, escape: Optional[str] = None, autoescape: bool = False
|
||||
) -> Any: ...
|
||||
) -> Any:
|
||||
...
|
||||
|
||||
else:
|
||||
notendswith_op = not_endswith_op
|
||||
@@ -2309,7 +2288,8 @@ if TYPE_CHECKING:
|
||||
@_operator_fn
|
||||
def notcontains_op(
|
||||
a: Any, b: Any, escape: Optional[str] = None, autoescape: bool = False
|
||||
) -> Any: ...
|
||||
) -> Any:
|
||||
...
|
||||
|
||||
else:
|
||||
notcontains_op = not_contains_op
|
||||
@@ -2366,7 +2346,8 @@ def not_match_op(a: Any, b: Any, **kw: Any) -> Any:
|
||||
if TYPE_CHECKING:
|
||||
|
||||
@_operator_fn
|
||||
def notmatch_op(a: Any, b: Any, **kw: Any) -> Any: ...
|
||||
def notmatch_op(a: Any, b: Any, **kw: Any) -> Any:
|
||||
...
|
||||
|
||||
else:
|
||||
notmatch_op = not_match_op
|
||||
@@ -2411,7 +2392,8 @@ def nulls_first_op(a: Any) -> Any:
|
||||
if TYPE_CHECKING:
|
||||
|
||||
@_operator_fn
|
||||
def nullsfirst_op(a: Any) -> Any: ...
|
||||
def nullsfirst_op(a: Any) -> Any:
|
||||
...
|
||||
|
||||
else:
|
||||
nullsfirst_op = nulls_first_op
|
||||
@@ -2426,7 +2408,8 @@ def nulls_last_op(a: Any) -> Any:
|
||||
if TYPE_CHECKING:
|
||||
|
||||
@_operator_fn
|
||||
def nullslast_op(a: Any) -> Any: ...
|
||||
def nullslast_op(a: Any) -> Any:
|
||||
...
|
||||
|
||||
else:
|
||||
nullslast_op = nulls_last_op
|
||||
@@ -2518,12 +2501,6 @@ def is_associative(op: OperatorType) -> bool:
|
||||
return op in _associative
|
||||
|
||||
|
||||
def is_order_by_modifier(op: Optional[OperatorType]) -> bool:
|
||||
return op in _order_by_modifier
|
||||
|
||||
|
||||
_order_by_modifier = {desc_op, asc_op, nulls_first_op, nulls_last_op}
|
||||
|
||||
_natural_self_precedent = _associative.union(
|
||||
[getitem, json_getitem_op, json_path_getitem_op]
|
||||
)
|
||||
@@ -2605,13 +2582,9 @@ _PRECEDENCE: Dict[OperatorType, int] = {
|
||||
}
|
||||
|
||||
|
||||
def is_precedent(
|
||||
operator: OperatorType, against: Optional[OperatorType]
|
||||
) -> bool:
|
||||
def is_precedent(operator: OperatorType, against: OperatorType) -> bool:
|
||||
if operator is against and is_natural_self_precedent(operator):
|
||||
return False
|
||||
elif against is None:
|
||||
return True
|
||||
else:
|
||||
return bool(
|
||||
_PRECEDENCE.get(
|
||||
|
||||
Reference in New Issue
Block a user