internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: getredash/redash

Issue:
presto query runner merges columns with same name
The query `SELECT 'foo' AS same_name, 'not foo' AS same_name` against a Presto data source generates surprising results: ('foo', 'foo') instead of ('foo', 'not foo')

The issue is in https://github.com/getredash/redash/blob/d74442184e30a8aeb19edacb39e1ca22cbb523c1/redash/query_runner/presto.py#L87. From experimenting with other data sources, it looks like redash itself supports showing result sets that have duplicated column names.



Discussion:

Resolving patch:
diff --git a/redash/query_runner/presto.py b/redash/query_runner/presto.py
--- a/redash/query_runner/presto.py
+++ b/redash/query_runner/presto.py
@@ -6,6 +6,8 @@
 import logging
 logger = logging.getLogger(__name__)
 
+from collections import defaultdict
+
 try:
     from pyhive import presto
     enabled = True
@@ -76,15 +78,12 @@ def run_query(self, query):
 
         cursor = connection.cursor()
 
+
         try:
             cursor.execute(query)
-            columns_data = [(row[0], row[1]) for row in cursor.description]
-
-            columns = [{'name': col[0],
-                'friendly_name': col[0],
-                'type': PRESTO_TYPES_MAPPING.get(col[1], None)} for col in columns_data]
-
-            rows = [dict(zip(([c[0] for c in columns_data]), r)) for i, r in enumerate(cursor.fetchall())]
+            column_tuples = [(i[0], PRESTO_TYPES_MAPPING.get(i[1], None)) for i in cursor.description]
+            columns = self.fetch_columns(column_tuples)
+            rows = [dict(zip(([c['name'] for c in columns]), r)) for i, r in enumerate(cursor.fetchall())]
             data = {'columns': columns, 'rows': rows}
             json_data = json.dumps(data, cls=JSONEncoder)
             error = None


Test patch:
Repository: getredash/redash

Issue:
Error on adding modules to python datasource
I'm trying to add a module to a python datasource, but it's failing with this traceback

```
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1475, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1461, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/usr/local/lib/python2.7/dist-packages/flask_restful/__init__.py", line 477, in wrapper
    resp = resource(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/flask_login.py", line 792, in decorated_view
    return func(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/flask/views.py", line 84, in view
    return self.dispatch_request(*args, **kwargs)
  File "/opt/redash/redash.0.9.2.b1536/redash/handlers/base.py", line 19, in dispatch_request
    return super(BaseResource, self).dispatch_request(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/flask_restful/__init__.py", line 587, in dispatch_request
    resp = meth(*args, **kwargs)
  File "/opt/redash/redash.0.9.2.b1536/redash/permissions.py", line 40, in decorated
    return fn(*args, **kwargs)
  File "/opt/redash/redash.0.9.2.b1536/redash/handlers/data_sources.py", line 38, in post
    data_source.options.update(req['options'])
  File "/opt/redash/redash.0.9.2.b1536/redash/utils/configuration.py", line 56, in update
    if k in self.schema['secret'] and v == SECRET_PLACEHOLDER:
KeyError: 'secret'
```



Discussion:

Resolving patch:
diff --git a/redash/utils/configuration.py b/redash/utils/configuration.py
--- a/redash/utils/configuration.py
+++ b/redash/utils/configuration.py
@@ -38,7 +38,7 @@ def iteritems(self):
         return self._config.iteritems()
 
     def to_dict(self, mask_secrets=False):
-        if (mask_secrets is False or 'secret' not in self.schema):
+        if mask_secrets is False or 'secret' not in self.schema:
             return self._config
 
         config = self._config.copy()
@@ -53,7 +53,7 @@ def update(self, new_config):
 
         config = {}
         for k, v in new_config.iteritems():
-            if k in self.schema['secret'] and v == SECRET_PLACEHOLDER:
+            if k in self.schema.get('secret', []) and v == SECRET_PLACEHOLDER:
                 config[k] = self[k]
             else:
                 config[k] = v


Test patch:
diff --git a/tests/test_configuration.py b/tests/test_configuration.py
--- a/tests/test_configuration.py
+++ b/tests/test_configuration.py
@@ -74,3 +74,10 @@ def test_doesnt_leave_leftovers(self):
         self.assertEqual(container['a'], 1)
         self.assertEqual('test', container['b'])
         self.assertNotIn('e', container)
+
+    def test_works_for_schema_without_secret(self):
+        secretless = configuration_schema.copy()
+        secretless.pop('secret')
+        container = ConfigurationContainer({'a': 1, 'b': 'test', 'e': 3}, secretless)
+        container.update({'a': 2})
+        self.assertEqual(container['a'], 2)
Repository: getredash/redash

Issue:
Vertica doesn't show schema
Vertica query runner returns error due to incompatible get_schema method

Vertica doesn't show schema
Vertica query runner returns error due to incompatible get_schema method



Discussion:

Resolving patch:
diff --git a/redash/query_runner/sqlite.py b/redash/query_runner/sqlite.py
--- a/redash/query_runner/sqlite.py
+++ b/redash/query_runner/sqlite.py
@@ -3,14 +3,14 @@
 import sqlite3
 import sys
 
-from redash.query_runner import BaseQueryRunner
+from redash.query_runner import BaseSQLQueryRunner
 from redash.query_runner import register
 
 from redash.utils import JSONEncoder
 
 logger = logging.getLogger(__name__)
 
-class Sqlite(BaseQueryRunner):
+class Sqlite(BaseSQLQueryRunner):
     @classmethod
     def configuration_schema(cls):
         return {
@@ -33,7 +33,7 @@ def __init__(self, configuration):
 
         self._dbpath = self.configuration['dbpath']
 
-    def get_schema(self):
+    def _get_tables(self, schema):
         query_table = "select tbl_name from sqlite_master where type='table'"
         query_columns = "PRAGMA table_info(%s)"
 
@@ -44,7 +44,6 @@ def get_schema(self):
 
         results = json.loads(results)
 
-        schema = {}
         for row in results['rows']:
             table_name = row['tbl_name']
             schema[table_name] = {'name': table_name, 'columns': []}
diff --git a/redash/query_runner/vertica.py b/redash/query_runner/vertica.py
--- a/redash/query_runner/vertica.py
+++ b/redash/query_runner/vertica.py
@@ -28,7 +28,7 @@
 }
 
 
-class Vertica(BaseQueryRunner):
+class Vertica(BaseSQLQueryRunner):
     @classmethod
     def configuration_schema(cls):
         return {
@@ -68,7 +68,7 @@ def enabled(cls):
     def __init__(self, configuration):
         super(Vertica, self).__init__(configuration)
 
-    def get_schema(self):
+    def _get_tables(self, schema):
         query = """
         Select table_schema, table_name, column_name from columns where is_system_table=false;
         """
@@ -80,7 +80,6 @@ def get_schema(self):
 
         results = json.loads(results)
 
-        schema = {}
         for row in results['rows']:
             table_name = '{}.{}'.format(row['table_schema'], row['table_name'])
 


Test patch:
Repository: getredash/redash

Issue:
Embed query description appearing larger than vizualization name
The query description is appearing larger then the visualization name:

![image](https://cloud.githubusercontent.com/assets/7199904/14591358/6bf74f9e-0553-11e6-91c4-70912b25025b.png)



Discussion:

Resolving patch:
diff --git a/redash/handlers/embed.py b/redash/handlers/embed.py
--- a/redash/handlers/embed.py
+++ b/redash/handlers/embed.py
@@ -41,7 +41,6 @@ def embed(query_id, visualization_id, org_slug=None):
     vis['query'] = project(vis['query'], ('created_at', 'description', 'name', 'id', 'latest_query_data_id', 'name', 'updated_at'))
 
     return render_template("embed.html",
-
                            client_config=json_dumps(client_config),
                            visualization=json_dumps(vis),
                            query_result=json_dumps(qr))


Test patch:
Repository: getredash/redash

Issue:
Getting duplicates in the search box even 
Even though there is only one query, the query box is showing duplicates when adding query to a dashboard or creating a new alert. 



Discussion:
Seeing this behaviour also http://puu.sh/omMLA/079c209fa1.png

I think it's because of the join with `DataSourceGroup` [here](https://github.com/getredash/redash/blob/master/redash/models.py#L653).


Resolving patch:
diff --git a/redash/models.py b/redash/models.py
--- a/redash/models.py
+++ b/redash/models.py
@@ -649,11 +649,13 @@ def search(cls, term, groups):
 
         where &= cls.is_archived == False
 
-        return cls.select()\
-                  .join(DataSourceGroup, on=(Query.data_source==DataSourceGroup.data_source)) \
-                  .where(where) \
-                  .where(DataSourceGroup.group << groups)\
-                  .order_by(cls.created_at.desc())
+        query_ids = cls.select(peewee.fn.Distinct(cls.id))\
+            .join(DataSourceGroup, on=(Query.data_source==DataSourceGroup.data_source)) \
+            .where(where) \
+            .where(DataSourceGroup.group << groups)
+
+        return cls.select().where(cls.id << query_ids)
+
 
     @classmethod
     def recent(cls, groups, user_id=None, limit=20):


Test patch:
diff --git a/tests/test_models.py b/tests/test_models.py
--- a/tests/test_models.py
+++ b/tests/test_models.py
@@ -90,6 +90,18 @@ def test_search_respects_groups(self):
         self.assertNotIn(q2, queries)
         self.assertNotIn(q3, queries)
 
+    def test_returns_each_query_only_once(self):
+        other_group = self.factory.create_group()
+        second_group = self.factory.create_group()
+        ds = self.factory.create_data_source(group=other_group)
+        ds.add_group(second_group, False)
+
+        q1 = self.factory.create_query(description="Testing search", data_source=ds)
+
+        queries = list(models.Query.search("Testing", [self.factory.default_group, other_group, second_group]))
+
+        self.assertEqual(1, len(queries))
+
     def test_save_creates_default_visualization(self):
         q = self.factory.create_query()
         self.assertEquals(q.visualizations.count(), 1)
Repository: getredash/redash

Issue:
Feature request: refresh button on the chart
![chart_refresh_button](https://cloud.githubusercontent.com/assets/16562082/12780895/db830522-ca81-11e5-9ea2-befdadf5c2f8.png)



Discussion:

Resolving patch:
diff --git a/migrations/0024_add_options_to_query.py b/migrations/0024_add_options_to_query.py
new file mode 100644
--- /dev/null
+++ b/migrations/0024_add_options_to_query.py
@@ -0,0 +1,10 @@
+from redash.models import db, Query
+from playhouse.migrate import PostgresqlMigrator, migrate
+
+if __name__ == '__main__':
+    migrator = PostgresqlMigrator(db.database)
+
+    with db.database.transaction():
+        migrate(
+            migrator.add_column('queries', 'options', Query.options),
+        )
diff --git a/redash/handlers/queries.py b/redash/handlers/queries.py
--- a/redash/handlers/queries.py
+++ b/redash/handlers/queries.py
@@ -86,8 +86,6 @@ def post(self, query_id):
         for field in ['id', 'created_at', 'api_key', 'visualizations', 'latest_query_data', 'user', 'last_modified_by', 'org']:
             query_def.pop(field, None)
 
-        # TODO(@arikfr): after running a query it updates all relevant queries with the new result. So is this really
-        # needed?
         if 'latest_query_data_id' in query_def:
             query_def['latest_query_data'] = query_def.pop('latest_query_data_id')
 
diff --git a/redash/models.py b/redash/models.py
--- a/redash/models.py
+++ b/redash/models.py
@@ -72,6 +72,8 @@ def db_value(self, value):
         return json.dumps(value)
 
     def python_value(self, value):
+        if not value:
+            return value
         return json.loads(value)
 
 
@@ -585,11 +587,11 @@ class Query(ModelTimestampsMixin, BaseModel, BelongsToOrgMixin):
     query = peewee.TextField()
     query_hash = peewee.CharField(max_length=32)
     api_key = peewee.CharField(max_length=40)
-    user_email = peewee.CharField(max_length=360, null=True)
     user = peewee.ForeignKeyField(User)
     last_modified_by = peewee.ForeignKeyField(User, null=True, related_name="modified_queries")
     is_archived = peewee.BooleanField(default=False, index=True)
     schedule = peewee.CharField(max_length=10, null=True)
+    options = JSONField(default={})
 
     class Meta:
         db_table = 'queries'
@@ -607,7 +609,8 @@ def to_dict(self, with_stats=False, with_visualizations=False, with_user=True, w
             'is_archived': self.is_archived,
             'updated_at': self.updated_at,
             'created_at': self.created_at,
-            'data_source_id': self.data_source_id
+            'data_source_id': self.data_source_id,
+            'options': self.options
         }
 
         if with_user:
@@ -833,7 +836,6 @@ class Dashboard(ModelTimestampsMixin, BaseModel, BelongsToOrgMixin):
     org = peewee.ForeignKeyField(Organization, related_name="dashboards")
     slug = peewee.CharField(max_length=140, index=True)
     name = peewee.CharField(max_length=100)
-    user_email = peewee.CharField(max_length=360, null=True)
     user = peewee.ForeignKeyField(User)
     layout = peewee.TextField()
     dashboard_filters_enabled = peewee.BooleanField(default=False)


Test patch:
Repository: getredash/redash

Issue:
Duplicate alerts
### Issue Summary

Alerts are duplicated when listing them in the UI. Maybe related to https://github.com/getredash/redash/issues/986?
### Steps to Reproduce
1. Create a user who belongs to multiple groups
2. Create an alert

Screenshot: http://puu.sh/oMLK5/9cfc8c6134.png (only 2 records are present in the DB)
### Technical details:
- Redash Version: 0.10.0+b1774
- Browser/OS: Latest Chrome / OS X
- How did you install Redash: AMI



Discussion:

Resolving patch:
diff --git a/redash/models.py b/redash/models.py
--- a/redash/models.py
+++ b/redash/models.py
@@ -755,7 +755,8 @@ def all(cls, groups):
             .join(DataSourceGroup, on=(Query.data_source==DataSourceGroup.data_source))\
             .where(DataSourceGroup.group << groups)\
             .switch(Alert)\
-            .join(User)
+            .join(User)\
+            .group_by(Alert, User, Query)
 
     @classmethod
     def get_by_id_and_org(cls, id, org):


Test patch:
diff --git a/tests/models/test_alerts.py b/tests/models/test_alerts.py
--- a/tests/models/test_alerts.py
+++ b/tests/models/test_alerts.py
@@ -25,3 +25,13 @@ def test_returns_all_alerts_for_given_groups(self):
         alerts = Alert.all(groups=[group])
         self.assertNotIn(alert1, alerts)
         self.assertIn(alert2, alerts)
+
+    def test_return_each_alert_only_once(self):
+        group = self.factory.create_group()
+        self.factory.data_source.add_group(group)
+
+        alert = self.factory.create_alert()
+
+        alerts = Alert.all(groups=[self.factory.default_group, group])
+        self.assertEqual(1, len(list(alerts)))
+        self.assertIn(alert, alerts)
Repository: getredash/redash

Issue:
Support for UUID type in MSSQL query runner
Currently it fails on serializing to JSON (need to add fallback in the serializer to cast into string).



Discussion:

Resolving patch:
diff --git a/redash/query_runner/mssql.py b/redash/query_runner/mssql.py
--- a/redash/query_runner/mssql.py
+++ b/redash/query_runner/mssql.py
@@ -1,6 +1,7 @@
 import json
 import logging
 import sys
+import uuid
 
 from redash.query_runner import *
 from redash.utils import JSONEncoder
@@ -22,6 +23,12 @@
     5: TYPE_FLOAT,
 }
 
+class MSSQLJSONEncoder(JSONEncoder):
+    def default(self, o):
+        if isinstance(o, uuid.UUID):
+            return str(o)
+        return super(MSSQLJSONEncoder, self).default(o)
+
 class SqlServer(BaseSQLQueryRunner):
     @classmethod
     def configuration_schema(cls):
@@ -123,7 +130,7 @@ def run_query(self, query):
                 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)
+                json_data = json.dumps(data, cls=MSSQLJSONEncoder)
                 error = None
             else:
                 error = "No data was returned."


Test patch:
Repository: getredash/redash

Issue:
Mixed view_only in multiple data_source_groups blocks query executions
A user belonging to multiple groups that have access to one data source but with different access levels can not execute queries on that data source.

For example, if a user belongs to built-in `default` group and you have set `view_only` for all data sources in this group to true, adding this user to a new group to allow full access to one of the data sources will not work.

This is caused by `group_level` definition in `def has_access()` in [permissions.py](https://github.com/getredash/redash/blob/master/redash/permissions.py):

```
required_level = 1 if need_view_only else 2
group_level = 1 if any(flatten([object_groups[group] for group in matching_groups])) else 2

return required_level <= group_level
```



Discussion:

Resolving patch:
diff --git a/redash/permissions.py b/redash/permissions.py
--- a/redash/permissions.py
+++ b/redash/permissions.py
@@ -17,7 +17,8 @@ def has_access(object_groups, user, need_view_only):
         return False
 
     required_level = 1 if need_view_only else 2
-    group_level = 1 if any(flatten([object_groups[group] for group in matching_groups])) else 2
+
+    group_level = 1 if all(flatten([object_groups[group] for group in matching_groups])) else 2
 
     return required_level <= group_level
 


Test patch:
diff --git a/tests/test_permissions.py b/tests/test_permissions.py
--- a/tests/test_permissions.py
+++ b/tests/test_permissions.py
@@ -24,6 +24,14 @@ def test_allows_if_user_member_in_group_with_full_access(self):
 
         self.assertTrue(has_access({1: not view_only}, user, not view_only))
 
+    def test_allows_if_user_member_in_multiple_groups(self):
+        user = MockUser([], [1, 2, 3])
+
+        self.assertTrue(has_access({1: not view_only, 2: view_only}, user, not view_only))
+        self.assertFalse(has_access({1: view_only, 2: view_only}, user, not view_only))
+        self.assertTrue(has_access({1: view_only, 2: view_only}, user, view_only))
+        self.assertTrue(has_access({1: not view_only, 2: not view_only}, user, view_only))
+
     def test_not_allows_if_not_enough_permission(self):
         user = MockUser([], [1])
Repository: getredash/redash

Issue:
When archiving a query, delete related alerts
Related: #731 .

When archiving a query, delete related alerts
Related: #731 .



Discussion:

Resolving patch:
diff --git a/redash/models.py b/redash/models.py
--- a/redash/models.py
+++ b/redash/models.py
@@ -641,6 +641,9 @@ def archive(self):
             for w in vis.widgets:
                 w.delete_instance()
 
+        for alert in self.alerts:
+            alert.delete_instance(recursive=True)
+
         self.save()
 
     @classmethod


Test patch:
diff --git a/tests/factories.py b/tests/factories.py
--- a/tests/factories.py
+++ b/tests/factories.py
@@ -185,6 +185,14 @@ def create_alert(self, **kwargs):
         args.update(**kwargs)
         return alert_factory.create(**args)
 
+    def create_alert_subscription(self, **kwargs):
+        args = {
+            'user': self.user
+        }
+
+        args.update(**kwargs)
+        return alert_subscription_factory.create(**args)
+
     def create_data_source(self, **kwargs):
         args = {
             'org': self.org
@@ -274,6 +282,3 @@ def create_api_key(self, **kwargs):
 
     def create_destination(self, **kwargs):
         return destination_factory.create(**kwargs)
-
-    def create_alert_subscription(self, **kwargs):
-        return alert_subscription_factory.create(**kwargs)
diff --git a/tests/test_models.py b/tests/test_models.py
--- a/tests/test_models.py
+++ b/tests/test_models.py
@@ -276,6 +276,16 @@ def test_removes_scheduling(self):
 
         self.assertEqual(None, query.schedule)
 
+    def test_deletes_alerts(self):
+        subscription = self.factory.create_alert_subscription()
+        query = subscription.alert.query
+
+        query.archive()
+
+        self.assertRaises(models.Alert.DoesNotExist, models.Alert.get_by_id, subscription.alert.id)
+        self.assertRaises(models.AlertSubscription.DoesNotExist, models.AlertSubscription.get_by_id, subscription.id)
+
+
 class DataSourceTest(BaseTestCase):
     def test_get_schema(self):
         return_value = [{'name': 'table', 'columns': []}]
Repository: getredash/redash

Issue:
User should be able to delete an Alert
Can't remove Alert with UI.

Directly run sql as below.

``` sql
delete from alerts where id = 〜
```



Discussion:
+1

+1

+1


Resolving patch:
diff --git a/redash/handlers/alerts.py b/redash/handlers/alerts.py
--- a/redash/handlers/alerts.py
+++ b/redash/handlers/alerts.py
@@ -34,6 +34,11 @@ def post(self, alert_id):
 
         return alert.to_dict()
 
+    def delete(self, alert_id):
+        alert = get_object_or_404(models.Alert.get_by_id_and_org, alert_id, self.current_org)
+        require_admin_or_owner(alert.user.id)
+        alert.delete_instance(recursive=True)
+
 
 class AlertListResource(BaseResource):
     def post(self):


Test patch:
diff --git a/tests/factories.py b/tests/factories.py
--- a/tests/factories.py
+++ b/tests/factories.py
@@ -187,7 +187,8 @@ def create_alert(self, **kwargs):
 
     def create_alert_subscription(self, **kwargs):
         args = {
-            'user': self.user
+            'user': self.user,
+            'alert': self.create_alert()
         }
 
         args.update(**kwargs)
diff --git a/tests/handlers/test_alerts.py b/tests/handlers/test_alerts.py
--- a/tests/handlers/test_alerts.py
+++ b/tests/handlers/test_alerts.py
@@ -1,8 +1,5 @@
 from tests import BaseTestCase
-from tests.factories import org_factory
-from tests.handlers import authenticated_user, json_request
-from redash.wsgi import app
-from redash.models import AlertSubscription
+from redash.models import AlertSubscription, Alert
 
 
 class TestAlertResourceGet(BaseTestCase):
@@ -30,6 +27,36 @@ def test_returns_404_if_admin_from_another_org(self):
         self.assertEqual(rv.status_code, 404)
 
 
+class TestAlertResourceDelete(BaseTestCase):
+    def test_removes_alert_and_subscriptions(self):
+        subscription = self.factory.create_alert_subscription()
+        alert = subscription.alert
+
+        rv = self.make_request('delete', "/api/alerts/{}".format(alert.id))
+        self.assertEqual(rv.status_code, 200)
+
+        self.assertRaises(Alert.DoesNotExist, Alert.get_by_id, subscription.alert.id)
+        self.assertRaises(AlertSubscription.DoesNotExist, AlertSubscription.get_by_id, subscription.id)
+
+    def test_returns_403_if_not_allowed(self):
+        alert = self.factory.create_alert()
+
+        user = self.factory.create_user()
+        rv = self.make_request('delete', "/api/alerts/{}".format(alert.id), user=user)
+        self.assertEqual(rv.status_code, 403)
+
+        rv = self.make_request('delete', "/api/alerts/{}".format(alert.id), user=self.factory.create_admin())
+        self.assertEqual(rv.status_code, 200)
+
+    def test_returns_404_for_unauthorized_users(self):
+        alert = self.factory.create_alert()
+
+        second_org = self.factory.create_org()
+        second_org_admin = self.factory.create_admin(org=second_org)
+        rv = self.make_request('delete', "/api/alerts/{}".format(alert.id), user=second_org_admin)
+        self.assertEqual(rv.status_code, 404)
+
+
 class TestAlertListPost(BaseTestCase):
     def test_returns_200_if_has_access_to_query(self):
         query = self.factory.create_query()