summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql/compiler.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2012-08-27 19:40:12 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2012-08-27 19:40:12 -0400
commit7d6c1c4a95596d5d83d9187d823f88fdc46f35b6 (patch)
tree1899e61ed65a2e5e44698bf06a3342aa1e89b422 /lib/sqlalchemy/sql/compiler.py
parent3a2d617f7f4232ae6f0e256e6b4327e48118ffbf (diff)
downloadsqlalchemy-7d6c1c4a95596d5d83d9187d823f88fdc46f35b6.tar.gz
- [feature] Reworked the startswith(), endswith(),
contains() operators to do a better job with negation (NOT LIKE), and also to assemble them at compilation time so that their rendered SQL can be altered, such as in the case for Firebird STARTING WITH [ticket:2470] - [feature] firebird - The "startswith()" operator renders as "STARTING WITH", "~startswith()" renders as "NOT STARTING WITH", using FB's more efficient operator. [ticket:2470]
Diffstat (limited to 'lib/sqlalchemy/sql/compiler.py')
-rw-r--r--lib/sqlalchemy/sql/compiler.py46
1 files changed, 45 insertions, 1 deletions
diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py
index 8e4f0288f..297cd9adb 100644
--- a/lib/sqlalchemy/sql/compiler.py
+++ b/lib/sqlalchemy/sql/compiler.py
@@ -24,7 +24,7 @@ To generate user-defined SQL strings, see
import re
import sys
-from .. import schema, engine, util, exc
+from .. import schema, engine, util, exc, types
from . import (
operators, functions, util as sql_util, visitors, expression as sql
)
@@ -670,6 +670,50 @@ class SQLCompiler(engine.Compiled):
def _generate_generic_unary_modifier(self, unary, opstring, **kw):
return unary.element._compiler_dispatch(self, **kw) + opstring
+ @util.memoized_property
+ def _like_percent_literal(self):
+ return sql.literal_column("'%'", type_=types.String())
+
+ def visit_contains_op_binary(self, binary, operator, **kw):
+ binary = binary._clone()
+ percent = self._like_percent_literal
+ binary.right = percent.__add__(binary.right).__add__(percent)
+ return self.visit_like_op_binary(binary, operator, **kw)
+
+ def visit_notcontains_op_binary(self, binary, operator, **kw):
+ binary = binary._clone()
+ percent = self._like_percent_literal
+ binary.right = percent.__add__(binary.right).__add__(percent)
+ return self.visit_notlike_op_binary(binary, operator, **kw)
+
+ def visit_startswith_op_binary(self, binary, operator, **kw):
+ binary = binary._clone()
+ percent = self._like_percent_literal
+ binary.right = percent.__radd__(
+ binary.right
+ )
+ return self.visit_like_op_binary(binary, operator, **kw)
+
+ def visit_notstartswith_op_binary(self, binary, operator, **kw):
+ binary = binary._clone()
+ percent = self._like_percent_literal
+ binary.right = percent.__radd__(
+ binary.right
+ )
+ return self.visit_notlike_op_binary(binary, operator, **kw)
+
+ def visit_endswith_op_binary(self, binary, operator, **kw):
+ binary = binary._clone()
+ percent = self._like_percent_literal
+ binary.right = percent.__add__(binary.right)
+ return self.visit_like_op_binary(binary, operator, **kw)
+
+ def visit_notendswith_op_binary(self, binary, operator, **kw):
+ binary = binary._clone()
+ percent = self._like_percent_literal
+ binary.right = percent.__add__(binary.right)
+ return self.visit_notlike_op_binary(binary, operator, **kw)
+
def visit_like_op_binary(self, binary, operator, **kw):
escape = binary.modifiers.get("escape", None)
return '%s LIKE %s' % (