import six
from django.db.models.expressions import (
F as FBase, Value as ValueBase, Func, Expression)
class OperatorMixin(object):
CAT = '||'
REPLACE = '#='
DELETE = '#-'
KEY = '->'
KEYTEXT = '->>'
PATH = '#>'
PATHTEXT = '#>>'
def cat(self, other):
return self._combine(other, self.CAT, False)
def replace(self, other):
return self._combine(other, self.REPLACE, False)
def delete(self, other):
return self._combine(other, self.DELETE, False)
def key(self, other):
return self._combine(other, self.KEY, False)
def keytext(self, other):
return self._combine(other, self.KEYTEXT, False)
def path(self, other):
return self._combine(other, self.PATH, False)
def pathtext(self, other):
return self._combine(other, self.PATHTEXT, False)
class F(FBase, OperatorMixin):
pass
class Value(ValueBase, OperatorMixin):
def as_sql(self, compiler, connection):
if self._output_field and any(self._output_field.get_internal_type() == fieldname for fieldname in
['ArrayField', 'MultiReferenceArrayField']):
base_field = self._output_field.base_field
return '%s::%s[]' % ('%s', base_field.db_type(connection)), [self.value]
return super(Value, self).as_sql(compiler, connection)
class SimpleFunc(Func):
def __init__(self, field, *values, **extra):
if not isinstance(field, Expression):
field = F(field)
if values and not isinstance(values[0], Expression):
values = [Value(v) for v in values]
super(SimpleFunc, self).__init__(field, *values, **extra)
class ArrayAppend(SimpleFunc):
function = 'ARRAY_APPEND'
class ArrayPrepend(Func):
function = 'ARRAY_PREPEND'
def __init__(self, value, field, **extra):
if not isinstance(value, Expression):
value = Value(value)
field = F(field)
super(ArrayPrepend, self).__init__(value, field, **extra)
class ArrayRemove(SimpleFunc):
function = 'ARRAY_REMOVE'
class ArrayReplace(SimpleFunc):
function = 'ARRAY_REPLACE'
class ArrayPosition(SimpleFunc):
function = 'ARRAY_POSITION'
class ArrayPositions(SimpleFunc):
function = 'ARRAY_POSITIONS'
class ArrayCat(Func):
function = 'ARRAY_CAT'
def __init__(
self, field, value, prepend=False, output_field=None, **extra):
if not isinstance(field, Expression):
field = F(field)
if not isinstance(value, Expression):
if isinstance(value, six.string_types):
value = F(value)
elif output_field:
value = Value(value, output_field=output_field)
else:
value = Value(value)
if prepend:
super(ArrayCat, self).__init__(value, field, **extra)
else:
super(ArrayCat, self).__init__(field, value, **extra)
class ArrayLength(SimpleFunc):
function = 'ARRAY_LENGTH'
class ArrayDims(SimpleFunc):
function = 'ARRAY_DIMS'
class ArrayUpper(SimpleFunc):
function = 'ARRAY_UPPER'
class ArrayLower(SimpleFunc):
function = 'ARRAY_LOWER'
class Cardinality(SimpleFunc):
function = 'CARDINALITY'