Ticket #26617: 26617.patch

File 26617.patch, 3.5 KB (added by Rustam Kashapov, 9 years ago)
  • django/contrib/postgres/aggregates/general.py

    diff --git a/django/contrib/postgres/aggregates/general.py b/django/contrib/postgres/aggregates/general.py
    index 1dda69c..6ff6727 100644
    a b class BoolOr(Aggregate):  
    3232
    3333class StringAgg(Aggregate):
    3434    function = 'STRING_AGG'
    35     template = "%(function)s(%(expressions)s, '%(delimiter)s')"
     35    template = "%(function)s(%(distinct)s%(expressions)s, '%(delimiter)s')"
    3636
    37     def __init__(self, expression, delimiter, **extra):
    38         super(StringAgg, self).__init__(expression, delimiter=delimiter, **extra)
     37    def __init__(self, expression, delimiter, distinct=False, **extra):
     38        distinct = 'DISTINCT ' if distinct else ''
     39        super(StringAgg, self).__init__(expression, delimiter=delimiter, distinct=distinct, **extra)
    3940
    4041    def convert_value(self, value, expression, connection, context):
    4142        if not value:
  • docs/ref/contrib/postgres/aggregates.txt

    diff --git a/docs/ref/contrib/postgres/aggregates.txt b/docs/ref/contrib/postgres/aggregates.txt
    index 3097498..ba912cb 100644
    a b General-purpose aggregation functions  
    6363``StringAgg``
    6464-------------
    6565
    66 .. class:: StringAgg(expression, delimiter)
     66.. class:: StringAgg(expression, delimiter, distinct=False)
    6767
    6868    Returns the input values concatenated into a string, separated by
    6969    the ``delimiter`` string.
    General-purpose aggregation functions  
    7272
    7373        Required argument. Needs to be a string.
    7474
     75    .. attribute:: distinct
     76
     77        .. versionadded: 1.10
     78
     79        This is a optional boolean argument.
     80
     81        If ``True``, a concatenated values will be distinct.
     82        Default is ``False``.
     83
    7584Aggregate functions for statistics
    7685==================================
    7786
  • tests/postgres_tests/test_aggregates.py

    diff --git a/tests/postgres_tests/test_aggregates.py b/tests/postgres_tests/test_aggregates.py
    index 07e4ea0..7714c73 100644
    a b class TestGeneralAggregate(PostgreSQLTestCase):  
    110110        values = AggregateTestModel.objects.aggregate(stringagg=StringAgg('char_field', delimiter=';'))
    111111        self.assertEqual(values, {'stringagg': ''})
    112112
     113    def test_string_agg_distinct_false(self):
     114        AggregateTestModel.objects.all().delete()
     115        AggregateTestModel.objects.create(char_field='Foo')
     116        AggregateTestModel.objects.create(char_field='Foo')
     117        AggregateTestModel.objects.create(char_field='Bar')
     118        models = AggregateTestModel.objects.order_by('char_field')
     119        values = models.aggregate(stringagg=StringAgg('char_field', delimiter=' ', distinct=False))
     120        aggregates = values['stringagg']
     121        self.assertEqual(aggregates.count('Foo'), 2)
     122        self.assertEqual(aggregates.count('Bar'), 1)
     123
     124    def test_string_agg_distinct_true(self):
     125        AggregateTestModel.objects.all().delete()
     126        AggregateTestModel.objects.create(char_field='Foo')
     127        AggregateTestModel.objects.create(char_field='Foo')
     128        AggregateTestModel.objects.create(char_field='Bar')
     129        models = AggregateTestModel.objects.order_by('char_field')
     130        values = models.aggregate(stringagg=StringAgg('char_field', delimiter=' ', distinct=True))
     131        aggregates = values['stringagg']
     132        self.assertEqual(aggregates.count('Foo'), 1)
     133        self.assertEqual(aggregates.count('Bar'), 1)
     134
    113135
    114136class TestStatisticsAggregate(PostgreSQLTestCase):
    115137    @classmethod
Back to Top