Permalink
Browse files

[Data Sources] Add: Snowflake query runner

  • Loading branch information...
1 parent 9e5944d commit a781d312c0af6fbeec7dfbc206ffb3b9810d4e9f @arikfr arikfr committed Dec 25, 2016
Showing with 107 additions and 1 deletion.
  1. +104 −0 redash/query_runner/snowflake.py
  2. +2 −1 redash/settings.py
  3. +1 −0 requirements_all_ds.txt
@@ -0,0 +1,104 @@
+from __future__ import absolute_import
+import json
+
+import snowflake.connector
+
+from redash.query_runner import BaseQueryRunner, register
+from redash.query_runner import TYPE_STRING, TYPE_DATE, TYPE_DATETIME, TYPE_INTEGER, TYPE_FLOAT, TYPE_BOOLEAN
+from redash.utils import json_dumps
+
+TYPES_MAP = {
+ 0: TYPE_INTEGER,
+ 1: TYPE_FLOAT,
+ 2: TYPE_STRING,
+ 3: TYPE_DATE,
+ 4: TYPE_DATETIME,
+ 5: TYPE_STRING,
+ 6: TYPE_DATETIME,
+ 13: TYPE_BOOLEAN
+}
+
+
+class Snowflake(BaseQueryRunner):
+ noop_query = "SELECT 1"
+
+ @classmethod
+ def configuration_schema(cls):
+ return {
+ "type": "object",
+ "properties": {
+ "account": {
+ "type": "string"
+ },
+ "user": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ },
+ "warehouse": {
+ "type": "string"
+ },
+ "database": {
+ "type": "string"
+ }
+ },
+ "required": ["user", "password", "account", "database", "warehouse"],
+ "secret": ["password"]
+ }
+
+ def run_query(self, query, user):
+ connection = snowflake.connector.connect(
+ user=self.configuration['user'],
+ password=self.configuration['password'],
+ account=self.configuration['account'],
+ )
+
+ cursor = connection.cursor()
+
+ try:
+ cursor.execute("USE WAREHOUSE {}".format(self.configuration['warehouse']))
+ cursor.execute("USE {}".format(self.configuration['database']))
+
+ cursor.execute(query)
+
+ 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
+ json_data = json_dumps(data)
+ finally:
+ cursor.close()
+ connection.close()
+
+ return json_data, error
+
+ def get_schema(self, get_stats=False):
+ query = """
+ SELECT col.table_schema,
+ col.table_name,
+ col.column_name
+ FROM {database}.information_schema.columns col
+ WHERE col.table_schema <> 'INFORMATION_SCHEMA'
+ """.format(database=self.configuration['database'])
+
+ results, error = self.run_query(query, None)
+
+ if error is not None:
+ raise Exception("Failed getting schema.")
+
+ schema = {}
+ results = json.loads(results)
+
+ for row in results['rows']:
+ table_name = '{}.{}'.format(row['TABLE_SCHEMA'], row['TABLE_NAME'])
+
+ if table_name not in schema:
+ schema[table_name] = {'name': table_name, 'columns': []}
+
+ schema[table_name]['columns'].append(row['COLUMN_NAME'])
+
+ return schema.values()
+
+register(Snowflake)
View
@@ -184,7 +184,8 @@ def all_settings():
'redash.query_runner.dynamodb_sql',
'redash.query_runner.mssql',
'redash.query_runner.jql',
- 'redash.query_runner.google_analytics'
+ 'redash.query_runner.google_analytics',
+ 'redash.query_runner.snowflake'
]
enabled_query_runners = array_from_string(os.environ.get("REDASH_ENABLED_QUERY_RUNNERS", ",".join(default_query_runners)))
@@ -17,5 +17,6 @@ sasl>=0.1.3
thrift>=0.8.0
thrift_sasl>=0.1.0
cassandra-driver==3.1.1
+snowflake_connector_python==1.3.7
# certifi is needed to support MongoDB and SSL:
certifi

0 comments on commit a781d31

Please sign in to comment.