Repository: getredash/redash

Issue:
Add Databricks query runner
<!--
#####################################################################
#
# Need support? USE THE FORUM! https://discuss.redash.io/c/support.
#
# Don't have steps to reproduce and actually not sure it's a bug?
# Use the forum! https://discuss.redash.io/c/support.
#
#####################################################################

**Got an idea for a new feature?** Check if it isn't on the roadmap already: http://bit.ly/redash-roadmap and start a new discussion in the features category: https://discuss.redash.io/c/feature-requests 🌟.

Found a bug? Please fill out the sections below... thank you 👍
-->

### Issue Summary

[Databricks](https://databricks.com/) offers a [Hive-like API](https://docs.databricks.com/user-guide/bi/jdbc-odbc-bi.html) that could be used to connect Redash to it to query tables over there.

### Steps to Reproduce

Mozilla has worked on a [POC code based on the existing Hive query runner](https://gist.github.com/robotblake/d0eff602664ab62959772dbb4f0cca22
) (curtesy of @robotblake) that could be the base for the code.


Discussion:

Resolving patch:
diff --git a/redash/query_runner/databricks.py b/redash/query_runner/databricks.py
new file mode 100644
--- /dev/null
+++ b/redash/query_runner/databricks.py
@@ -0,0 +1,22 @@
+import base64
+from .hive_ds import Hive
+
+try:
+    from pyhive import hive
+    from thrift.transport import THttpClient
+    enabled = True
+except ImportError:
+    enabled = False
+
+
+class DataBricks(Hive):
+
+    @classmethod
+    def type(cls):
+        return "databricks"
+
+    @classmethod
+    def enabled(cls):
+        return enabled
+
+register(DataBricks)
diff --git a/redash/query_runner/hive_ds.py b/redash/query_runner/hive_ds.py
--- a/redash/query_runner/hive_ds.py
+++ b/redash/query_runner/hive_ds.py
@@ -1,6 +1,7 @@
 import json
 import logging
 import sys
+import base64
 
 from redash.query_runner import *
 from redash.utils import JSONEncoder
@@ -53,7 +54,24 @@ def configuration_schema(cls):
                 },
                 "username": {
                     "type": "string"
-                }
+                },
+                "use_http": {
+                    "type": "boolean",
+                    "title": "Use HTTP transport"
+                },
+                "http_scheme": {
+                    "type": "string",
+                    "title": "Scheme when using HTTP transport",
+                    "default": "https"
+                },
+                "http_path": {
+                    "type": "string",
+                    "title": "Path when using HTTP transport"
+                },
+                "http_password": {
+                    "type": "string",
+                    "title": "Password when using HTTP transport"
+                },
             },
             "required": ["host"]
         }
@@ -97,7 +115,43 @@ def run_query(self, query, user):
 
         connection = None
         try:
-            connection = hive.connect(**self.configuration.to_dict())
+            host = self.configuration['host']
+
+            if self.configuration.get('use_http', False):
+                # default to https
+                scheme = self.configuration.get('http_scheme', 'https')
+
+                # if path is set but is missing initial slash, append it
+                path = self.configuration.get('http_path', '')
+                if path and path[0] != '/':
+                    path = '/' + path
+
+                # if port is set prepend colon
+                port = self.configuration.get('port', '')
+                if port:
+                    port = ':' + port
+
+                http_uri = "{}://{}{}{}".format(scheme, host, port, path)
+
+                # create transport
+                transport = THttpClient.THttpClient(http_uri)
+
+                # if username or password is set, add Authorization header
+                username = self.configuration.get('username', '')
+                password = self.configuration.get('http_password', '')
+                if username | password:
+                    auth = base64.b64encode(username + ':' + password)
+                    transport.setCustomHeaders({'Authorization': 'Basic ' + auth})
+
+                # create connection
+                connection = hive.connect(thrift_transport=transport)
+            else:
+                connection = hive.connect(
+                    host=host,
+                    port=self.configuration.get('port', None),
+                    database=self.configuration.get('database', 'default'),
+                    username=self.configuration.get('username', None),
+                )
 
             cursor = connection.cursor()
 


Test patch: