Repository: getredash/redash

Issue:
Azure Data Warehouse through MS SQL (ODBC) runner doesn't work on a default docker image
### Issue Summary

[Default docker image](https://github.com/getredash/redash/blob/v8.0.0/Dockerfile) has neither pyodbc nor Microsoft ODBC Driver installed, so you can't query Azure Data Warehouse with default docker image, even if you enable pyodbc.

### Steps to Reproduce

1. Have Redash running in docker 
2. Enable mssql_odbc query runner through env: `REDASH_ADDITIONAL_QUERY_RUNNERS: "redash.query_runner.mssql_odbc"`
3. It doesn't get registered:
`[2019-11-13 13:29:19,823][PID:10][DEBUG][redash.query_runner] Microsoft SQL Server (ODBC) query runner enabled but not supported, not registering. Either disable or install missing dependencies.`
4. I found out why: 
a) `pyodbc==4.0.27` pypi package is missing in `requirements_all_ds.txt`
b) Even if you put it in `requirements_all_ds.txt` , it can't be downloaded & built by pip because you don't have `g++ unixodbc-dev` package installed
c) Even if you get `g++ unixodbc-dev`, you still need Microsoft ODBC Driver installed: `msodbcsql17`
5. this line in Dockerfile fixes packages, you also have to add `pyodbc` to `requirements_all_ds.txt`:
```Dockerfile
RUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - && curl https://packages.microsoft.com/config/debian/10/prod.list > /etc/apt/sources.list.d/mssql-release.list && apt-get update && ACCEPT_EULA=Y apt-get install -y msodbcsql17 g++ unixodbc-dev
```

So I see the main problem as:
* You can't query Azure SQL/Data Warehouse straight out of the box

Is it even possible to package all these dependencies into standard Redash docker image and make it work without apt-get and pyodbc troubles? That means accepting Microsoft's EULA, and some native dependencies, e.g. pyodbc builds itself from source. I haven't measured image size increase but `apt-get` writes `After this operation, 15.8 MB of additional disk space will be used`

```bash
The license terms for this product can be downloaded from
https://aka.ms/odbc131eula and found in
/usr/share/doc/msodbcsql/LICENSE.TXT . By entering 'YES',
you indicate that you accept the license terms.
```

The runner itself(#1906) works. I just had to spend 30 minutes to make it run in docker.

### Technical details:

* Redash Version: 8

Thanks for the awesome v8 release!


Discussion:
The EULA seems reasonable and the size increasing as well. We can even offset it by dropping `FreeTDS` and `pymssql` from our default packages -- this supposed to cover the same databases and be even better supported, right?
I fear this could break compatibility? There were two datasources, now there would be one - existing queries will fail.
Or we can do it in v9? I can make PR to master.

Resolving patch:
diff --git a/redash/query_runner/mssql_odbc.py b/redash/query_runner/mssql_odbc.py
--- a/redash/query_runner/mssql_odbc.py
+++ b/redash/query_runner/mssql_odbc.py
@@ -25,24 +25,31 @@ def configuration_schema(cls):
         return {
             "type": "object",
             "properties": {
+                "server": {"type": "string"},
+                "port": {"type": "number", "default": 1433},
                 "user": {"type": "string"},
                 "password": {"type": "string"},
-                "server": {"type": "string", "default": "127.0.0.1"},
-                "port": {"type": "number", "default": 1433},
+                "db": {"type": "string", "title": "Database Name"},
                 "charset": {
                     "type": "string",
                     "default": "UTF-8",
                     "title": "Character Set",
                 },
-                "db": {"type": "string", "title": "Database Name"},
-                "driver": {
-                    "type": "string",
-                    "title": "Driver Identifier",
-                    "default": "{ODBC Driver 13 for SQL Server}",
+                "use_ssl": {
+                    "type": "boolean",
+                    "title": "Use SSL",
+                    "default": False,
+                },
+                "verify_ssl": {
+                    "type": "boolean",
+                    "title": "Verify SSL certificate",
+                    "default": True,
                 },
             },
-            "required": ["db"],
+            "order": ["server", "port", "user", "password", "db", "charset", "use_ssl", "verify_ssl"],
+            "required": ["host", "user", "password", "db"],
             "secret": ["password"],
+            "extra_options": ["verify_ssl", "use_ssl"],
         }
 
     @classmethod
@@ -91,20 +98,26 @@ def run_query(self, query, user):
         connection = None
 
         try:
-            server = self.configuration.get("server", "")
+            server = self.configuration.get("server")
             user = self.configuration.get("user", "")
             password = self.configuration.get("password", "")
             db = self.configuration["db"]
             port = self.configuration.get("port", 1433)
             charset = self.configuration.get("charset", "UTF-8")
-            driver = self.configuration.get("driver", "{ODBC Driver 13 for SQL Server}")
 
             connection_string_fmt = (
-                "DRIVER={};PORT={};SERVER={};DATABASE={};UID={};PWD={}"
+                "DRIVER={{ODBC Driver 17 for SQL Server}};PORT={};SERVER={};DATABASE={};UID={};PWD={}"
             )
             connection_string = connection_string_fmt.format(
-                driver, port, server, db, user, password
+                port, server, db, user, password
             )
+
+            if self.configuration.get('use_ssl', False):
+                connection_string += ";Encrypt=YES"
+
+                if not self.configuration.get('verify_ssl'):
+                    connection_string += ";TrustServerCertificate=YES"
+
             connection = pyodbc.connect(connection_string)
             cursor = connection.cursor()
             logger.debug("SQLServerODBC running query: %s", query)
diff --git a/redash/settings/__init__.py b/redash/settings/__init__.py
--- a/redash/settings/__init__.py
+++ b/redash/settings/__init__.py
@@ -332,6 +332,7 @@ def email_server_is_configured():
     "redash.query_runner.sqlite",
     "redash.query_runner.dynamodb_sql",
     "redash.query_runner.mssql",
+    "redash.query_runner.mssql_odbc",
     "redash.query_runner.memsql_ds",
     "redash.query_runner.mapd",
     "redash.query_runner.jql",


Test patch: