Skip to content

Commit 749171b

Browse files
authored
Merge pull request #1746 from alexanderlz/master
[Data Sources] Add: MemSQL query runner
2 parents 40a8187 + 6b7234c commit 749171b

File tree

3 files changed

+157
-0
lines changed

3 files changed

+157
-0
lines changed

redash/query_runner/memsql_ds.py

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import json
2+
import logging
3+
import sys
4+
5+
from redash.query_runner import *
6+
from redash.utils import JSONEncoder
7+
8+
logger = logging.getLogger(__name__)
9+
10+
try:
11+
from memsql.common import database
12+
13+
enabled = True
14+
except ImportError, e:
15+
logger.warning(e)
16+
enabled = False
17+
18+
COLUMN_NAME = 0
19+
COLUMN_TYPE = 1
20+
21+
types_map = {
22+
'BIGINT': TYPE_INTEGER,
23+
'TINYINT': TYPE_INTEGER,
24+
'SMALLINT': TYPE_INTEGER,
25+
'MEDIUMINT': TYPE_INTEGER,
26+
'INT': TYPE_INTEGER,
27+
'DOUBLE': TYPE_FLOAT,
28+
'DECIMAL': TYPE_FLOAT,
29+
'FLOAT': TYPE_FLOAT,
30+
'REAL': TYPE_FLOAT,
31+
'BOOL': TYPE_BOOLEAN,
32+
'BOOLEAN': TYPE_BOOLEAN,
33+
'TIMESTAMP': TYPE_DATETIME,
34+
'DATETIME': TYPE_DATETIME,
35+
'DATE': TYPE_DATETIME,
36+
'JSON': TYPE_STRING,
37+
'CHAR': TYPE_STRING,
38+
'VARCHAR': TYPE_STRING
39+
}
40+
41+
42+
class MemSQL(BaseSQLQueryRunner):
43+
noop_query = 'SELECT 1'
44+
45+
@classmethod
46+
def configuration_schema(cls):
47+
return {
48+
"type": "object",
49+
"properties": {
50+
"host": {
51+
"type": "string"
52+
},
53+
"port": {
54+
"type": "number"
55+
},
56+
"user": {
57+
"type": "string"
58+
},
59+
"password": {
60+
"type": "string"
61+
}
62+
63+
},
64+
"required": ["host", "port"],
65+
"secret": ["password"]
66+
}
67+
68+
@classmethod
69+
def annotate_query(cls):
70+
return False
71+
72+
@classmethod
73+
def type(cls):
74+
return "memsql"
75+
76+
@classmethod
77+
def enabled(cls):
78+
return enabled
79+
80+
def __init__(self, configuration):
81+
super(MemSQL, self).__init__(configuration)
82+
83+
def _get_tables(self, schema):
84+
schemas_query = "show schemas"
85+
86+
tables_query = "show tables in %s"
87+
88+
columns_query = "show columns in %s"
89+
90+
for schema_name in filter(lambda a: len(a) > 0,
91+
map(lambda a: str(a['Database']), self._run_query_internal(schemas_query))):
92+
for table_name in filter(lambda a: len(a) > 0, map(lambda a: str(a['Tables_in_%s' % schema_name]),
93+
self._run_query_internal(
94+
tables_query % schema_name))):
95+
table_name = '.'.join((schema_name, table_name))
96+
columns = filter(lambda a: len(a) > 0, map(lambda a: str(a['Field']),
97+
self._run_query_internal(columns_query % table_name)))
98+
99+
schema[table_name] = {'name': table_name, 'columns': columns}
100+
return schema.values()
101+
102+
def run_query(self, query, user):
103+
104+
cursor = None
105+
try:
106+
cursor = database.connect(**self.configuration.to_dict())
107+
108+
res = cursor.query(query)
109+
# column_names = []
110+
# columns = []
111+
#
112+
# for column in cursor.description:
113+
# column_name = column[COLUMN_NAME]
114+
# column_names.append(column_name)
115+
#
116+
# columns.append({
117+
# 'name': column_name,
118+
# 'friendly_name': column_name,
119+
# 'type': types_map.get(column[COLUMN_TYPE], None)
120+
# })
121+
122+
rows = [dict(zip(list(row.keys()), list(row.values()))) for row in res]
123+
124+
# ====================================================================================================
125+
# temporary - until https://github.com/memsql/memsql-python/pull/8 gets merged
126+
# ====================================================================================================
127+
columns = []
128+
column_names = rows[0].keys() if rows else None
129+
130+
if column_names:
131+
for column in column_names:
132+
columns.append({
133+
'name': column,
134+
'friendly_name': column,
135+
'type': TYPE_STRING
136+
})
137+
138+
data = {'columns': columns, 'rows': rows}
139+
json_data = json.dumps(data, cls=JSONEncoder)
140+
error = None
141+
except KeyboardInterrupt:
142+
cursor.close()
143+
error = "Query cancelled by user."
144+
json_data = None
145+
except Exception as e:
146+
logging.exception(e)
147+
raise sys.exc_info()[1], None, sys.exc_info()[2]
148+
finally:
149+
if cursor:
150+
cursor.close()
151+
152+
return json_data, error
153+
154+
155+
register(MemSQL)

redash/settings.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ def all_settings():
183183
'redash.query_runner.sqlite',
184184
'redash.query_runner.dynamodb_sql',
185185
'redash.query_runner.mssql',
186+
'redash.query_runner.memsql_ds',
186187
'redash.query_runner.jql',
187188
'redash.query_runner.google_analytics',
188189
'redash.query_runner.snowflake',

requirements_all_ds.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ sasl>=0.1.3
1717
thrift>=0.8.0
1818
thrift_sasl>=0.1.0
1919
cassandra-driver==3.1.1
20+
memsql==2.16.0
2021
snowflake_connector_python==1.3.7
2122
atsd_client==2.0.12
2223
simple_salesforce==0.72.2

0 commit comments

Comments
 (0)