Make the GROUP_CONCAT aggregate function not repeat values (closes #3223975)
authorJulien Cristau <julien.cristau@logilab.fr>
Thu, 14 Nov 2013 12:26:29 +0100
changeset 9364 73bd5012336f
parent 9363 d773589b6d46
child 9365 71c12e778162
Make the GROUP_CONCAT aggregate function not repeat values (closes #3223975) Work on sets instead of arrays, so if the same value appears twice it's not repeated in the concatenated output. This patch handles the postgresql and sqlite backends, mysql is left alone at this point (seems doable, but I don't have time or motivation to fix and test it).
schemas/_regproc.postgres.sql
server/sqlutils.py
--- a/schemas/_regproc.postgres.sql	Tue Jan 07 15:48:31 2014 +0100
+++ b/schemas/_regproc.postgres.sql	Thu Nov 14 12:26:29 2013 +0100
@@ -10,10 +10,15 @@
     SELECT array_to_string($1, ', ')
 $$ LANGUAGE SQL;;
 
+
+CREATE FUNCTION cw_array_append_unique (anyarray, anyelement) RETURNS anyarray AS $$
+    SELECT array_append($1, (SELECT $2 WHERE $2 <> ALL($1)))
+$$ LANGUAGE SQL
+
 DROP AGGREGATE IF EXISTS group_concat (anyelement) CASCADE;
 CREATE AGGREGATE group_concat (
   basetype = anyelement,
-  sfunc = array_append,
+  sfunc = cw_array_append_unique,
   stype = anyarray,
   finalfunc = comma_join,
   initcond = '{}'
--- a/server/sqlutils.py	Tue Jan 07 15:48:31 2014 +0100
+++ b/server/sqlutils.py	Thu Nov 14 12:26:29 2013 +0100
@@ -327,10 +327,10 @@
 
     class group_concat(object):
         def __init__(self):
-            self.values = []
+            self.values = set()
         def step(self, value):
             if value is not None:
-                self.values.append(value)
+                self.values.add(value)
         def finalize(self):
             return ', '.join(unicode(v) for v in self.values)