Browse Source

PR795 [editor] Add a ClickHouse connector using jdbc (#795)

* [editor] Add a ClickHouse connector using jdbc

```
[notebook]
  [[interpreters]]
    [[[clickhouse]]]
      name=ClickHouse
      interface=jdbc
      options='{"url": "jdbc:clickhouse://localhost:8123", "driver": "ru.yandex.clickhouse.ClickHouseDriver", "user": "readonly", "password": ""}'
```

* add the ini configuration examples for ClickHouse
maiha 6 years ago
parent
commit
c78a800a0d

+ 7 - 0
desktop/conf.dist/hue.ini

@@ -935,6 +935,13 @@
     #   ## If 'user' and 'password' are omitted, they will be prompted in the UI.
     #   ## If 'user' and 'password' are omitted, they will be prompted in the UI.
     #   options='{"url": "jdbc:presto://localhost:8080/catalog/schema", "driver": "io.prestosql.jdbc.PrestoDriver", "user": "root", "password": "root"}'
     #   options='{"url": "jdbc:presto://localhost:8080/catalog/schema", "driver": "io.prestosql.jdbc.PrestoDriver", "user": "root", "password": "root"}'
 
 
+    # [[[clickhouse]]]
+    #   name=ClickHouse
+    #   interface=jdbc
+    #   ## Specific options for connecting to the ClickHouse server.
+    #   ## The JDBC driver clickhouse-jdbc.jar and its related jars need to be in the CLASSPATH environment variable.
+    #   options='{"url": "jdbc:clickhouse://localhost:8123", "driver": "ru.yandex.clickhouse.ClickHouseDriver", "user": "readonly", "password": ""}'
+
 ###########################################################################
 ###########################################################################
 # Settings to configure your Analytics Dashboards
 # Settings to configure your Analytics Dashboards
 ###########################################################################
 ###########################################################################

+ 7 - 0
desktop/conf/pseudo-distributed.ini.tmpl

@@ -936,6 +936,13 @@
     #   ## If 'user' and 'password' are omitted, they will be prompted in the UI.
     #   ## If 'user' and 'password' are omitted, they will be prompted in the UI.
     #   options='{"url": "jdbc:presto://localhost:8080/catalog/schema", "driver": "io.prestosql.jdbc.PrestoDriver", "user": "root", "password": "root"}'
     #   options='{"url": "jdbc:presto://localhost:8080/catalog/schema", "driver": "io.prestosql.jdbc.PrestoDriver", "user": "root", "password": "root"}'
 
 
+    # [[[clickhouse]]]
+    #   name=ClickHouse
+    #   interface=jdbc
+    #   ## Specific options for connecting to the ClickHouse server.
+    #   ## The JDBC driver clickhouse-jdbc.jar and its related jars need to be in the CLASSPATH environment variable.
+    #   options='{"url": "jdbc:clickhouse://localhost:8123", "driver": "ru.yandex.clickhouse.ClickHouseDriver", "user": "readonly", "password": ""}'
+
 ###########################################################################
 ###########################################################################
 # Settings to configure your Analytics Dashboards
 # Settings to configure your Analytics Dashboards
 ###########################################################################
 ###########################################################################

+ 3 - 0
desktop/libs/notebook/src/notebook/connectors/base.py

@@ -365,6 +365,9 @@ def get_api(request, snippet):
     elif interpreter['options'] and interpreter['options'].get('url', '').find('presto') >= 0:
     elif interpreter['options'] and interpreter['options'].get('url', '').find('presto') >= 0:
       from notebook.connectors.jdbc_presto import JdbcApiPresto
       from notebook.connectors.jdbc_presto import JdbcApiPresto
       return JdbcApiPresto(request.user, interpreter=interpreter)
       return JdbcApiPresto(request.user, interpreter=interpreter)
+    elif interpreter['options'] and interpreter['options'].get('url', '').find('clickhouse') >= 0:
+      from notebook.connectors.jdbc_clickhouse import JdbcApiClickhouse
+      return JdbcApiClickhouse(request.user, interpreter=interpreter)
     else:
     else:
       from notebook.connectors.jdbc import JdbcApi
       from notebook.connectors.jdbc import JdbcApi
       return JdbcApi(request.user, interpreter=interpreter)
       return JdbcApi(request.user, interpreter=interpreter)

+ 43 - 0
desktop/libs/notebook/src/notebook/connectors/jdbc_clickhouse.py

@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+# Licensed to Cloudera, Inc. under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  Cloudera, Inc. licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from librdbms.jdbc import query_and_fetch
+
+from notebook.connectors.jdbc import JdbcApi
+from notebook.connectors.jdbc import Assist
+class JdbcApiClickhouse(JdbcApi):
+
+  def _createAssist(self, db):
+    return ClickhouseAssist(db)
+
+class ClickhouseAssist(Assist):
+
+  def get_databases(self):
+    dbs, description = query_and_fetch(self.db, 'SHOW DATABASES')
+    return [db[0] and db[0].strip() for db in dbs]
+
+  def get_tables_full(self, database, table_names=[]):
+    tables, description = query_and_fetch(self.db, "SELECT name, '' FROM system.tables WHERE database='%s'" % database)
+    return [{"comment": table[1] and table[1].strip(), "type": "Table", "name": table[0] and table[0].strip()} for table in tables]
+
+  def get_columns_full(self, database, table):
+    columns, description = query_and_fetch(self.db, "SELECT name, type, '' FROM system.columns WHERE database='%s' AND table = '%s'" % (database, table))
+    return [{"comment": col[2] and col[2].strip(), "type": col[1], "name": col[0] and col[0].strip()} for col in columns]
+
+  def get_sample_data(self, database, table, column=None):
+    column = column or '*'
+    return query_and_fetch(self.db, 'SELECT %s FROM %s.%s limit 100' % (column, database, table))

+ 2 - 0
desktop/libs/notebook/src/notebook/templates/editor_components.mako

@@ -191,6 +191,7 @@ ${ sqlSyntaxDropdown.sqlSyntaxDropdown() }
                   <!-- ko case: 'kafkasql' -->Kafka SQL<!-- /ko -->
                   <!-- ko case: 'kafkasql' -->Kafka SQL<!-- /ko -->
                   <!-- ko case: 'markdown' -->Markdown<!-- /ko -->
                   <!-- ko case: 'markdown' -->Markdown<!-- /ko -->
                   <!-- ko case: 'text' -->Text<!-- /ko -->
                   <!-- ko case: 'text' -->Text<!-- /ko -->
+                  <!-- ko case: 'clickhouse' -->ClickHouse<!-- /ko -->
                   <!-- ko case: $default -->SQL<!-- /ko -->
                   <!-- ko case: $default -->SQL<!-- /ko -->
                   <!-- /ko -->
                   <!-- /ko -->
                 </span>
                 </span>
@@ -219,6 +220,7 @@ ${ sqlSyntaxDropdown.sqlSyntaxDropdown() }
                 <!-- ko case: 'kafkasql' -->Kafka SQL<!-- /ko -->
                 <!-- ko case: 'kafkasql' -->Kafka SQL<!-- /ko -->
                 <!-- ko case: 'markdown' -->Markdown<!-- /ko -->
                 <!-- ko case: 'markdown' -->Markdown<!-- /ko -->
                 <!-- ko case: 'text' -->Text<!-- /ko -->
                 <!-- ko case: 'text' -->Text<!-- /ko -->
+                <!-- ko case: 'clickhouse' -->ClickHouse<!-- /ko -->
                 <!-- ko case: $default -->SQL<!-- /ko -->
                 <!-- ko case: $default -->SQL<!-- /ko -->
               <!-- /ko -->
               <!-- /ko -->
               <!-- ko component: { name: 'hue-favorite-app', params: { hue4: IS_HUE_4, app: 'editor', interpreter: editorType() }} --><!-- /ko -->
               <!-- ko component: { name: 'hue-favorite-app', params: { hue4: IS_HUE_4, app: 'editor', interpreter: editorType() }} --><!-- /ko -->