From b56bd8541ee3d063001b065bd5c3a7336226d7f9 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Wed, 23 Aug 2023 11:20:26 +0200 Subject: [PATCH] Devices: Fix bulk edit query (#3541) --- src/pretix/control/views/organizer.py | 4 ++-- src/pretix/helpers/database.py | 20 ++++++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/pretix/control/views/organizer.py b/src/pretix/control/views/organizer.py index 4d9758dcf4..7ee590c02f 100644 --- a/src/pretix/control/views/organizer.py +++ b/src/pretix/control/views/organizer.py @@ -1054,8 +1054,8 @@ class DeviceBulkUpdateView(DeviceQueryMixin, OrganizerDetailViewMixin, Organizer limit_events_list=Subquery( Device.limit_events.through.objects.filter( device_id=OuterRef('pk') - ).order_by('device_id', 'event_id').values('device_id').annotate( - g=GroupConcat('event_id', separator=',') + ).order_by().values('device_id').annotate( + g=GroupConcat('event_id', separator=',', ordered=True) ).values('g') ) ) diff --git a/src/pretix/helpers/database.py b/src/pretix/helpers/database.py index c676ff98a7..92e11abc87 100644 --- a/src/pretix/helpers/database.py +++ b/src/pretix/helpers/database.py @@ -66,18 +66,26 @@ class GroupConcat(Aggregate): function = 'group_concat' template = '%(function)s(%(field)s, "%(separator)s")' - def __init__(self, *expressions, **extra): + def __init__(self, *expressions, ordered=False, **extra): + self.ordered = ordered if 'separator' not in extra: # For PostgreSQL separator is an obligatory extra.update({'separator': ','}) super().__init__(*expressions, **extra) def as_postgresql(self, compiler, connection): - return super().as_sql( - compiler, connection, - function='string_agg', - template="%(function)s(%(field)s::text, '%(separator)s')", - ) + if self.ordered: + return super().as_sql( + compiler, connection, + function='string_agg', + template="%(function)s(%(field)s::text, '%(separator)s' ORDER BY %(field)s ASC)", + ) + else: + return super().as_sql( + compiler, connection, + function='string_agg', + template="%(function)s(%(field)s::text, '%(separator)s')", + ) class ReplicaRouter: