summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/sqlalchemy/sql/operators.py99
1 files changed, 92 insertions, 7 deletions
diff --git a/lib/sqlalchemy/sql/operators.py b/lib/sqlalchemy/sql/operators.py
index da3576466..6ba4605a6 100644
--- a/lib/sqlalchemy/sql/operators.py
+++ b/lib/sqlalchemy/sql/operators.py
@@ -197,7 +197,7 @@ class Operators(object):
class custom_op(object):
"""Represent a 'custom' operator.
- :class:`.custom_op` is normally instantitated when the
+ :class:`.custom_op` is normally instantiated when the
:meth:`.ColumnOperators.op` method is used to create a
custom operator callable. The class can also be used directly
when programmatically constructing expressions. E.g.
@@ -506,6 +506,29 @@ class ColumnOperators(Operators):
In a column context, produces the clause ``LIKE '<other>%'``
+ E.g.::
+
+ select([sometable]).where(sometable.c.column.startswith("foobar"))
+
+ :param other: expression to be compared, with SQL wildcard
+ matching (``%`` and ``_``) enabled, e.g.::
+
+ somecolumn.startswith("foo%bar")
+
+ :param escape: optional escape character, renders the ``ESCAPE``
+ keyword allowing that escape character to be used to manually
+ disable SQL wildcard matching (``%`` and ``_``) in the expression,
+ e.g.::
+
+ somecolumn.startswith("foo/%bar", escape="/")
+
+ :param autoescape: optional escape character, renders the ``ESCAPE``
+ keyword and uses that escape character to auto escape the
+ expression, disabling all SQL wildcard matching (``%`` and ``_``),
+ e.g.::
+
+ somecolumn.startswith("foo%bar", autoescape="/")
+
"""
return self.operate(startswith_op, other, **kwargs)
@@ -514,6 +537,29 @@ class ColumnOperators(Operators):
In a column context, produces the clause ``LIKE '%<other>'``
+ E.g.::
+
+ select([sometable]).where(sometable.c.column.endswith("foobar"))
+
+ :param other: expression to be compared, with SQL wildcard
+ matching (``%`` and ``_``) enabled, e.g.::
+
+ somecolumn.endswith("foo%bar")
+
+ :param escape: optional escape character, renders the ``ESCAPE``
+ keyword allowing that escape character to be used to manually
+ disable SQL wildcard matching (``%`` and ``_``) in the expression,
+ e.g.::
+
+ somecolumn.endswith("foo/%bar", escape="/")
+
+ :param autoescape: optional escape character, renders the ``ESCAPE``
+ keyword and uses that escape character to auto escape the
+ expression, disabling all SQL wildcard matching (``%`` and ``_``),
+ e.g.::
+
+ somecolumn.endswith("foo%bar", autoescape="/")
+
"""
return self.operate(endswith_op, other, **kwargs)
@@ -522,6 +568,29 @@ class ColumnOperators(Operators):
In a column context, produces the clause ``LIKE '%<other>%'``
+ E.g.::
+
+ select([sometable]).where(sometable.c.column.contains("foobar"))
+
+ :param other: expression to compare, with SQL wildcard
+ matching (``%`` and ``_``) enabled, e.g.::
+
+ somecolumn.contains("foo%bar")
+
+ :param escape: optional escape character, renders the ``ESCAPE``
+ keyword allowing that escape character to be used to manually
+ disable SQL wildcard matching (``%`` and ``_``) in the expression,
+ e.g.::
+
+ somecolumn.contains("foo/%bar", escape="/")
+
+ :param autoescape: optional escape character, renders the ``ESCAPE``
+ keyword and uses that escape character to auto escape the
+ expression, disabling all SQL wildcard matching (``%`` and ``_``),
+ e.g.::
+
+ somecolumn.contains("foo%bar", autoescape="/")
+
"""
return self.operate(contains_op, other, **kwargs)
@@ -701,6 +770,10 @@ class ColumnOperators(Operators):
return self.reverse_operate(truediv, other)
+def _escaped(value, escape):
+ return value.replace('%', escape + '%').replace('_', escape + '_')
+
+
def from_():
raise NotImplementedError()
@@ -781,27 +854,39 @@ def all_op(a):
return a.all_()
-def startswith_op(a, b, escape=None):
+def startswith_op(a, b, escape=None, autoescape=None):
+ if autoescape:
+ return a.startswith(_escaped(b, autoescape), escape=autoescape)
return a.startswith(b, escape=escape)
-def notstartswith_op(a, b, escape=None):
+def notstartswith_op(a, b, escape=None, autoescape=None):
+ if autoescape:
+ return ~a.startswith(_escaped(b, autoescape), escape=autoescape)
return ~a.startswith(b, escape=escape)
-def endswith_op(a, b, escape=None):
+def endswith_op(a, b, escape=None, autoescape=None):
+ if autoescape:
+ return a.endswith(_escaped(b, autoescape), escape=autoescape)
return a.endswith(b, escape=escape)
-def notendswith_op(a, b, escape=None):
+def notendswith_op(a, b, escape=None, autoescape=None):
+ if autoescape:
+ return ~a.endswith(_escaped(b, autoescape), escape=autoescape)
return ~a.endswith(b, escape=escape)
-def contains_op(a, b, escape=None):
+def contains_op(a, b, escape=None, autoescape=None):
+ if autoescape:
+ return a.contains(_escaped(b, autoescape), escape=autoescape)
return a.contains(b, escape=escape)
-def notcontains_op(a, b, escape=None):
+def notcontains_op(a, b, escape=None, autoescape=None):
+ if autoescape:
+ return ~a.contains(_escaped(b, autoescape), escape=autoescape)
return ~a.contains(b, escape=escape)