Repository: getredash/redash

Issue:
API - result data in json from query id
Today, in order to get query results in json form, the url references the query_data_id, which is retrieved in a separate query data request by query_id.

So, in order to avoid 2 requests, plz allow getting the results by query_id (like is done with the csv format)

https://redash.host.com/api/queries/1234/results.json



Discussion:

Resolving patch:
diff --git a/redash/controllers.py b/redash/controllers.py
--- a/redash/controllers.py
+++ b/redash/controllers.py
@@ -414,48 +414,52 @@ def post(self):
 
 
 class QueryResultAPI(BaseResource):
-    @require_permission('view_query')
-    def get(self, query_result_id):
-        query_result = models.QueryResult.get_by_id(query_result_id)
-        if query_result:
-            data = json.dumps({'query_result': query_result.to_dict()}, cls=utils.JSONEncoder)
-            return make_response(data, 200, cache_headers)
-        else:
-            abort(404)
+    @staticmethod
+    def csv_response(query_result):
+        s = cStringIO.StringIO()
+
+        query_data = json.loads(query_result.data)
+        writer = csv.DictWriter(s, fieldnames=[col['name'] for col in query_data['columns']])
+        writer.writer = utils.UnicodeWriter(s)
+        writer.writeheader()
+        for row in query_data['rows']:
+            for k, v in row.iteritems():
+                if isinstance(v, numbers.Number) and (v > 1000 * 1000 * 1000 * 100):
+                    row[k] = datetime.datetime.fromtimestamp(v/1000.0)
+
+            writer.writerow(row)
 
+        headers = {'Content-Type': "text/csv; charset=UTF-8"}
+        headers.update(cache_headers)
+        return make_response(s.getvalue(), 200, headers)
 
-class CsvQueryResultsAPI(BaseResource):
     @require_permission('view_query')
-    def get(self, query_id, query_result_id=None):
-        if not query_result_id:
+    def get(self, query_id=None, query_result_id=None, filetype='json'):
+        if query_result_id is None and query_id is not None:
             query = models.Query.get(models.Query.id == query_id)
             if query:
                 query_result_id = query._data['latest_query_data']
 
-        query_result = query_result_id and models.QueryResult.get_by_id(query_result_id)
-        if query_result:
-            s = cStringIO.StringIO()
-
-            query_data = json.loads(query_result.data)
-            writer = csv.DictWriter(s, fieldnames=[col['name'] for col in query_data['columns']])
-            writer.writer = utils.UnicodeWriter(s)
-            writer.writeheader()
-            for row in query_data['rows']:
-                for k, v in row.iteritems():
-                    if isinstance(v, numbers.Number) and (v > 1000 * 1000 * 1000 * 100):
-                        row[k] = datetime.datetime.fromtimestamp(v/1000.0)
+        if query_result_id:
+            query_result = models.QueryResult.get_by_id(query_result_id)
 
-                writer.writerow(row)
+        if query_result:
+            if filetype == 'json':
+                data = json.dumps({'query_result': query_result.to_dict()}, cls=utils.JSONEncoder)
+                return make_response(data, 200, cache_headers)
+            else:
+                return self.csv_response(query_result)
 
-            return make_response(s.getvalue(), 200, {'Content-Type': "text/csv; charset=UTF-8"})
         else:
             abort(404)
 
-api.add_resource(CsvQueryResultsAPI, '/api/queries/<query_id>/results/<query_result_id>.csv',
-                 '/api/queries/<query_id>/results.csv',
-                 endpoint='csv_query_results')
+
 api.add_resource(QueryResultListAPI, '/api/query_results', endpoint='query_results')
-api.add_resource(QueryResultAPI, '/api/query_results/<query_result_id>', endpoint='query_result')
+api.add_resource(QueryResultAPI,
+                 '/api/query_results/<query_result_id>',
+                 '/api/queries/<query_id>/results.<filetype>',
+                 '/api/queries/<query_id>/results/<query_result_id>.<filetype>',
+                 endpoint='query_result')
 
 
 class JobAPI(BaseResource):


Test patch: