Эх сурвалжийг харах

HUE-3073 [metastore] Add ability to alter table name and comment

Jenny Kim 10 жил өмнө
parent
commit
20759b1

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

@@ -206,6 +206,30 @@ class HiveServer2Dbms(object):
     return self.client.get_table(database, table_name)
 
 
+  def alter_table(self, database, table_name, new_table_name=None, comment=None, tblproperties=None):
+    hql = 'ALTER TABLE `%s`.`%s`' % (database, table_name)
+
+    if new_table_name:
+      table_name = new_table_name
+      hql += ' RENAME TO `%s`' % table_name
+    elif comment:
+      hql += " SET TBLPROPERTIES ('comment' = '%s')" % comment
+    elif tblproperties:
+      hql += " SET TBLPROPERTIES (%s)" % ' ,'.join("'%s' = '%s'" % (k, v) for k, v in tblproperties.items())
+
+    timeout = SERVER_CONN_TIMEOUT.get()
+    query = hql_query(hql)
+    handle = self.execute_and_wait(query, timeout_sec=timeout)
+
+    if handle:
+      self.close(handle)
+    else:
+      msg = _("Failed to execute alter table statement: %s") % hql
+      raise QueryServerException(msg)
+
+    return self.client.get_table(database, table_name)
+
+
   def get_column(self, database, table_name, column_name):
     table = self.client.get_table(database, table_name)
     for col in table.cols:

+ 31 - 0
apps/metastore/src/metastore/tests.py

@@ -352,6 +352,37 @@ class TestMetastoreWithHadoop(BeeswaxSampleProvider):
     check(client, [200, 302]) # Ok
 
 
+  def test_alter_table(self):
+    resp = _make_query(self.client, "CREATE TABLE test_alter_table (a int) COMMENT 'Before Alter';", database=self.db_name)
+    resp = wait_for_query_to_finish(self.client, resp, max=30.0)
+
+    resp = self.client.get('/metastore/table/%s/test_alter_table' % self.db_name)
+    assert_true('test_alter_table', resp.content)
+    assert_true('Before Alter', resp.content)
+
+    # Alter name
+    resp = self.client.post(reverse("metastore:alter_table",
+                                    kwargs={'database': self.db_name, 'table': 'test_alter_table'}),
+                            {'new_table_name': 'table_altered'})
+    json_resp = json.loads(resp.content)
+    assert_equal('table_altered', json_resp['data']['name'], json_resp)
+
+    # Alter comment
+    resp = self.client.post(reverse("metastore:alter_table",
+                                    kwargs={'database': self.db_name, 'table': 'table_altered'}),
+                            {'comment': 'After Alter'})
+    json_resp = json.loads(resp.content)
+    assert_equal('After Alter', json_resp['data']['comment'], json_resp)
+
+    # Invalid table name returns error response
+    resp = self.client.post(reverse("metastore:alter_table",
+                                    kwargs={'database': self.db_name, 'table': 'table_altered'}),
+                            {'new_table_name': 'bad name'})
+    json_resp = json.loads(resp.content)
+    assert_equal(1, json_resp['status'], json_resp)
+    assert_true('Failed to alter table' in json_resp['data'], json_resp)
+
+
   def test_alter_column(self):
     resp = _make_query(self.client, 'CREATE TABLE test_alter_column (before_alter int);', database=self.db_name)
     resp = wait_for_query_to_finish(self.client, resp, max=30.0)

+ 1 - 0
apps/metastore/src/metastore/urls.py

@@ -27,6 +27,7 @@ urlpatterns = patterns('metastore.views',
   url(r'^tables/(?P<database>\w+)?$', 'show_tables', name='show_tables'),
   url(r'^tables/drop/(?P<database>\w+)$', 'drop_table', name='drop_table'),
   url(r'^table/(?P<database>\w+)/(?P<table>\w+)$', 'describe_table', name='describe_table'),
+  url(r'^table/(?P<database>\w+)/(?P<table>\w+)/alter', 'alter_table', name='alter_table'),
   url(r'^table/(?P<database>\w+)/(?P<table>\w+)/metadata$', 'get_table_metadata', name='get_table_metadata'),
   url(r'^table/(?P<database>\w+)/(?P<table>\w+)/load$', 'load_table', name='load_table'),
   url(r'^table/(?P<database>\w+)/(?P<table>\w+)/read$', 'read_table', name='read_table'),

+ 30 - 0
apps/metastore/src/metastore/views.py

@@ -261,6 +261,36 @@ def describe_table(request, database, table):
   })
 
 
+@check_has_write_access_permission
+@require_http_methods(["POST"])
+def alter_table(request, database, table):
+  db = dbms.get(request.user)
+  response = {'status': -1, 'data': ''}
+  try:
+    new_table_name = request.POST.get('new_table_name', None)
+    comment = request.POST.get('comment', None)
+
+    # Cannot modify both name and comment at same time, name will get precedence
+    if new_table_name and comment:
+      LOG.warn('Cannot alter both table name and comment at the same time, will perform rename.')
+
+    table_obj = db.alter_table(database, table, new_table_name=new_table_name, comment=comment)
+
+    response['status'] = 0
+    response['data'] = {
+      'name': table_obj.name,
+      'comment': table_obj.comment,
+      'is_view': table_obj.is_view,
+      'location': table_obj.path_location,
+      'properties': table_obj.properties
+    }
+  except Exception, ex:
+    response['status'] = 1
+    response['data'] = _("Failed to alter table `%s`.`%s`: %s") % (database, table, str(ex))
+
+  return JsonResponse(response)
+
+
 @check_has_write_access_permission
 @require_http_methods(["POST"])
 def alter_column(request, database, table):