浏览代码

HUE-7738 [editor] Add function description in autocomplete API

Hive only.

e.g.

$.post("/notebook/api/autocomplete/trunc", {
      "snippet": ko.mapping.toJSON({
          type: "41"
      }),
      "operation": "function"
    }, function(data) {
      console.log(ko.mapping.toJSON(data));
    });

{"status":0,"message":"","function":{"name":"trunc","signature":"trunc(date, fmt)","description":"Returns returns date with the time portion of the day truncated to the unit specified by the format model fmt. If you omit fmt, then date is truncated to the nearest day. It now only supports 'MONTH'/'MON'/'MM' and 'YEAR'/'YYYY'/'YY' as format.\ndate is a string in the format 'yyyy-MM-dd HH:mm:ss' or 'yyyy-MM-dd'. The time part of date is ignored.\nExample:\n  > SELECT trunc('2009-02-12', 'MM');\nOK\n '2009-02-01'\n > SELECT trunc('2015-10-27', 'YEAR');\nOK\n '2015-01-01'"}}
Romain 5 年之前
父节点
当前提交
6ff04f3c57

+ 22 - 0
apps/beeswax/src/beeswax/api.py

@@ -109,6 +109,8 @@ def _autocomplete(db, database=None, table=None, column=None, nested=None, query
   try:
     if operation == 'functions':
       response['functions'] = _get_functions(db, database)
+    elif operation == 'function':
+      response['function'] = _get_function(db, database)
     elif database is None:
       response['databases'] = db.get_databases()
     elif table is None:
@@ -198,6 +200,26 @@ def _get_functions(db, database=None):
   return data
 
 
+def _get_function(db, name):
+  data = {}
+
+  if db.client.query_server['dialect'] == 'hive':
+    functions = db.get_function(name=name)
+    rows = escape_rows(functions, nulls_only=True)
+
+    full_description = '\n'.join([col for row in rows for col in row])
+    signature, description = full_description.split(' - ', 1)
+    name = name.split('(', 1)[0]
+
+    data = {
+      'name': name,
+      'signature': signature,
+      'description': description,
+    }
+
+  return data
+
+
 @error_handler
 def parameters(request, design_id=None):
   response = {'status': -1, 'message': ''}

+ 34 - 0
apps/beeswax/src/beeswax/api_tests.py

@@ -91,9 +91,43 @@ class TestApi():
       _get_functions.return_value = [
         {'name': 'f1'}, {'name': 'f2'}, {'name': 'f3'}
       ]
+
       resp = _autocomplete(db, database='default', operation='functions')
 
       assert_equal(
         resp['functions'],
         [{'name': 'f1'}, {'name': 'f2'}, {'name': 'f3'}]
       )
+
+
+  def test_get_function(self):
+    db = Mock()
+    db.client = Mock(query_server = {'dialect': 'hive'})
+    db.get_function = Mock(
+      return_value = [
+        ['floor_month(param) - Returns the timestamp at a month granularity'],
+        ['param needs to be a timestamp value'],
+        ['Example:'],
+        ["> SELECT floor_month(CAST('yyyy-MM-dd HH:mm:ss' AS TIMESTAMP)) FROM src;"],
+        ['yyyy-MM-01 00:00:00']
+      ]
+    )
+
+    data = _autocomplete(db, database='floor_month', operation='function')
+
+    assert_equal(
+      data['function'],
+      {
+        'name': 'floor_month',
+        'signature': 'floor_month(param)',
+        'description':
+            'Returns the timestamp at a month granularity\nparam needs to be a timestamp value\nExample:\n'
+            '> SELECT floor_month(CAST(\'yyyy-MM-dd HH:mm:ss\' AS TIMESTAMP)) FROM src;\nyyyy-MM-01 00:00:00'
+      }
+    )
+
+
+    db.client = Mock(query_server = {'dialect': 'impala'})
+    data = _autocomplete(db, operation='function')
+
+    assert_equal(data['function'], {})

+ 15 - 0
apps/beeswax/src/beeswax/server/dbms.py

@@ -1125,6 +1125,21 @@ class HiveServer2Dbms(object):
     return rows
 
 
+  def get_function(self, name):
+    hql = 'DESCRIBE FUNCTION EXTENDED `%(name)s`' % {
+      'name': name,
+    }
+
+    query = hql_query(hql)
+    handle = self.execute_and_wait(query, timeout_sec=5.0)
+
+    if handle:
+      rows = self.fetch(handle, rows=100).rows()
+      self.close(handle)
+
+    return rows
+
+
   def get_query_metadata(self, query):
     hql = 'SELECT * FROM ( %(query)s ) t LIMIT 0' % {'query': query.strip(';')}
 

+ 26 - 0
docs/designs/sql/autocomplete_udfs.md

@@ -0,0 +1,26 @@
+HUE-7738 [editor] Add function listing in autocomplete API
+
+This is a first pass before v1. See the documentation for usage.
+
+Note:
+- only Hive can provide detailed function info
+- by default Hive only provides function names
+
+Still need to add:
+
+Both:
+- add other fields when possible, e.g. return type, signature, binary
+type, is persistent
+- show aggregate functions;
+- show analytic functions;
+
+Hive:
+- DESCRIBE FUNCTION EXTENDED trunc
+
+Impala
+- include _impala_builtins per default
+- include the active database
+
+Other SQL
+- TODO: either errors or try to return columns
+- MySql e.g. show function status (or better check with SqlAlchemy)

+ 12 - 0
docs/docs-site/content/developer/api/_index.md

@@ -379,6 +379,18 @@ For a specific database:
     });
 
 
+For a specific function/UDF details (e.g. trunc):
+
+    $.post("/notebook/api/autocomplete/<function_name>", {
+      "snippet": ko.mapping.toJSON({
+          type: "hive"
+      }),
+      "operation": "function"
+    }, function(data) {
+      console.log(ko.mapping.toJSON(data));
+    });
+
+
 ### SQL Risk Optimization
 ### Data Browsing
 ### Workflow scheduling