Refs #28643 -- Added Ord, Chr, Left, and Right database functions.

This commit is contained in:
bobort 2018-02-23 09:23:22 -06:00 committed by Tim Graham
parent c412926a2e
commit f82de6bfb1
8 changed files with 262 additions and 6 deletions

View file

@ -1,7 +1,23 @@
from django.db.models import Func, Transform, Value, fields
from django.db.models import Func, IntegerField, Transform, Value, fields
from django.db.models.functions import Coalesce
class Chr(Transform):
function = 'CHR'
lookup_name = 'chr'
def as_mysql(self, compiler, connection):
return super().as_sql(
compiler, connection, function='CHAR', template='%(function)s(%(expressions)s USING utf16)'
)
def as_oracle(self, compiler, connection):
return super().as_sql(compiler, connection, template='%(function)s(%(expressions)s USING NCHAR_CS)')
def as_sqlite(self, compiler, connection, **extra_context):
return super().as_sql(compiler, connection, function='CHAR', **extra_context)
class ConcatPair(Func):
"""
Concatenate two arguments together. This is used by `Concat` because not
@ -55,6 +71,30 @@ class Concat(Func):
return ConcatPair(expressions[0], self._paired(expressions[1:]))
class Left(Func):
function = 'LEFT'
arity = 2
def __init__(self, expression, length, **extra):
"""
expression: the name of a field, or an expression returning a string
length: the number of characters to return from the start of the string
"""
if not hasattr(length, 'resolve_expression'):
if length < 1:
raise ValueError("'length' must be greater than 0.")
super().__init__(expression, length, **extra)
def get_substr(self):
return Substr(self.source_expressions[0], Value(1), self.source_expressions[1])
def use_substr(self, compiler, connection, **extra_context):
return self.get_substr().as_oracle(compiler, connection, **extra_context)
as_oracle = use_substr
as_sqlite = use_substr
class Length(Transform):
"""Return the number of characters in the expression."""
function = 'LENGTH'
@ -70,6 +110,18 @@ class Lower(Transform):
lookup_name = 'lower'
class Ord(Transform):
function = 'ASCII'
lookup_name = 'ord'
output_field = IntegerField()
def as_mysql(self, compiler, connection, **extra_context):
return super().as_sql(compiler, connection, function='ORD', **extra_context)
def as_sqlite(self, compiler, connection, **extra_context):
return super().as_sql(compiler, connection, function='UNICODE', **extra_context)
class Replace(Func):
function = 'REPLACE'
@ -77,6 +129,13 @@ class Replace(Func):
super().__init__(expression, text, replacement, **extra)
class Right(Left):
function = 'RIGHT'
def get_substr(self):
return Substr(self.source_expressions[0], self.source_expressions[1] * Value(-1))
class StrIndex(Func):
"""
Return a positive integer corresponding to the 1-indexed position of the