Repository: getredash/redash

Issue:
Columns with same name (on different tables) are messing up the results
If we have two columns with the same name in the same query the result is overridden. In this query I also found another bug: the `COUNT` and the `GROUP_CONCAT` does not show results if they don't have an alias.

``` sql
SELECT s.name,
       t.name,
       count(tg.id),
       group_concat(tg.taggable_id
                    ORDER BY tg.taggable_id ASC separator ', ')
FROM taggings tg,
     tags t,
     questions q,
     subgroups s
WHERE t.id = tg.tag_id
  AND tg.taggable_id = q.id
  AND tg.taggable_type = 'Question'
  AND q.year >= 2009
  AND s.id = q.subgroup_id
GROUP BY s.name,
         t.id
```

Result:
![screen shot 2015-09-22 at 2 07 53 pm](https://cloud.githubusercontent.com/assets/501867/10025613/803d60b6-6133-11e5-8dc4-2c5f202b9f6c.png)

Should be:
![screen shot 2015-09-22 at 2 08 52 pm](https://cloud.githubusercontent.com/assets/501867/10025622/829eaf5e-6133-11e5-8daa-751fc53162a6.png)

Adding an alias to all columns fixes it.



Discussion:
I've implemented a [solution](https://github.com/EverythingMe/redash/blob/master/redash/query_runner/pg.py#L134-L136) for this in the PostgreSQL query runner, but never generalized it for the other query runners.

Which one are you using?

@arikfr  I'm using mysql. Should I implement the solution for mysql or try to generalize it?


Resolving patch:
diff --git a/redash/query_runner/__init__.py b/redash/query_runner/__init__.py
--- a/redash/query_runner/__init__.py
+++ b/redash/query_runner/__init__.py
@@ -67,6 +67,24 @@ def configuration_schema(cls):
     def run_query(self, query):
         raise NotImplementedError()
 
+    def fetch_columns(self, columns):
+        column_names = []
+        duplicates_counter = 1
+        new_columns = []
+
+        for col in columns:
+            column_name = col[0]
+            if column_name in column_names:
+                column_name = "{}{}".format(column_name, duplicates_counter)
+                duplicates_counter += 1
+
+            column_names.append(column_name)
+            new_columns.append({'name': column_name,
+                                'friendly_name': column_name,
+                                'type': col[1]})
+
+        return new_columns
+
     def get_schema(self):
         return []
 
diff --git a/redash/query_runner/mysql.py b/redash/query_runner/mysql.py
--- a/redash/query_runner/mysql.py
+++ b/redash/query_runner/mysql.py
@@ -119,13 +119,8 @@ def run_query(self, query):
 
             # TODO - very similar to pg.py
             if cursor.description is not None:
-                columns_data = [(i[0], i[1]) for i in cursor.description]
-
-                rows = [dict(zip((c[0] for c in columns_data), row)) for row in data]
-
-                columns = [{'name': col[0],
-                            'friendly_name': col[0],
-                            'type': types_map.get(col[1], None)} for col in columns_data]
+                columns = self.fetch_columns([(i[0], types_map.get(i[1], None)) for i in cursor.description])
+                rows = [dict(zip((c['name'] for c in columns), row)) for row in data]
 
                 data = {'columns': columns, 'rows': rows}
                 json_data = json.dumps(data, cls=JSONEncoder)
@@ -149,4 +144,4 @@ def run_query(self, query):
 
         return json_data, error
 
-register(Mysql)
\ No newline at end of file
+register(Mysql)
diff --git a/redash/query_runner/pg.py b/redash/query_runner/pg.py
--- a/redash/query_runner/pg.py
+++ b/redash/query_runner/pg.py
@@ -121,29 +121,9 @@ def run_query(self, query):
             cursor.execute(query)
             _wait(connection)
 
-            # While set would be more efficient here, it sorts the data which is not what we want, but due to the small
-            # size of the data we can assume it's ok.
-            column_names = []
-            columns = []
-            duplicates_counter = 1
-
             if cursor.description is not None:
-                for column in cursor.description:
-                    # TODO: this deduplication needs to be generalized and reused in all query runners.
-                    column_name = column.name
-                    if column_name in column_names:
-                        column_name += str(duplicates_counter)
-                        duplicates_counter += 1
-
-                    column_names.append(column_name)
-
-                    columns.append({
-                        'name': column_name,
-                        'friendly_name': column_name,
-                        'type': types_map.get(column.type_code, None)
-                    })
-
-                rows = [dict(zip(column_names, row)) for row in cursor]
+                columns = self.fetch_columns([(i[0], types_map.get(i[1], None)) for i in cursor.description])
+                rows = [dict(zip((c['name'] for c in columns), row)) for row in cursor]
 
                 data = {'columns': columns, 'rows': rows}
                 error = None
@@ -170,4 +150,4 @@ def run_query(self, query):
 
         return json_data, error
 
-register(PostgreSQL)
\ No newline at end of file
+register(PostgreSQL)


Test patch: