diff options
author | Hannes Ljungberg <hannes@5monkeys.se> | 2020-06-14 20:50:39 +0200 |
---|---|---|
committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2020-06-16 08:16:14 +0200 |
commit | 0d6d4e78b17d7500e1a503fd2b02fdcf822d9d3c (patch) | |
tree | 5490caec4e52639d2629d5af0141556438a503a4 /django/contrib/postgres/constraints.py | |
parent | dcb4d79ef719d824431a8b3ff8ada879bbab21cc (diff) | |
download | django-0d6d4e78b17d7500e1a503fd2b02fdcf822d9d3c.tar.gz |
Fixed #31709 -- Added support for opclasses in ExclusionConstraint.
Diffstat (limited to 'django/contrib/postgres/constraints.py')
-rw-r--r-- | django/contrib/postgres/constraints.py | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/django/contrib/postgres/constraints.py b/django/contrib/postgres/constraints.py index cdb238c405..2ae72c402e 100644 --- a/django/contrib/postgres/constraints.py +++ b/django/contrib/postgres/constraints.py @@ -12,7 +12,7 @@ class ExclusionConstraint(BaseConstraint): def __init__( self, *, name, expressions, index_type=None, condition=None, - deferrable=None, include=None, + deferrable=None, include=None, opclasses=(), ): if index_type and index_type.lower() not in {'gist', 'spgist'}: raise ValueError( @@ -48,20 +48,37 @@ class ExclusionConstraint(BaseConstraint): raise ValueError( 'Covering exclusion constraints only support GiST indexes.' ) + if not isinstance(opclasses, (list, tuple)): + raise ValueError( + 'ExclusionConstraint.opclasses must be a list or tuple.' + ) + if opclasses and len(expressions) != len(opclasses): + raise ValueError( + 'ExclusionConstraint.expressions and ' + 'ExclusionConstraint.opclasses must have the same number of ' + 'elements.' + ) self.expressions = expressions self.index_type = index_type or 'GIST' self.condition = condition self.deferrable = deferrable self.include = tuple(include) if include else () + self.opclasses = opclasses super().__init__(name=name) def _get_expression_sql(self, compiler, connection, query): expressions = [] - for expression, operator in self.expressions: + for idx, (expression, operator) in enumerate(self.expressions): if isinstance(expression, str): expression = F(expression) expression = expression.resolve_expression(query=query) sql, params = expression.as_sql(compiler, connection) + try: + opclass = self.opclasses[idx] + if opclass: + sql = '%s %s' % (sql, opclass) + except IndexError: + pass expressions.append('%s WITH %s' % (sql % params, operator)) return expressions @@ -119,6 +136,8 @@ class ExclusionConstraint(BaseConstraint): kwargs['deferrable'] = self.deferrable if self.include: kwargs['include'] = self.include + if self.opclasses: + kwargs['opclasses'] = self.opclasses return path, args, kwargs def __eq__(self, other): @@ -129,16 +148,18 @@ class ExclusionConstraint(BaseConstraint): self.expressions == other.expressions and self.condition == other.condition and self.deferrable == other.deferrable and - self.include == other.include + self.include == other.include and + self.opclasses == other.opclasses ) return super().__eq__(other) def __repr__(self): - return '<%s: index_type=%s, expressions=%s%s%s%s>' % ( + return '<%s: index_type=%s, expressions=%s%s%s%s%s>' % ( self.__class__.__qualname__, self.index_type, self.expressions, '' if self.condition is None else ', condition=%s' % self.condition, '' if self.deferrable is None else ', deferrable=%s' % self.deferrable, '' if not self.include else ', include=%s' % repr(self.include), + '' if not self.opclasses else ', opclasses=%s' % repr(self.opclasses), ) |