Quellcode durchsuchen

HUE-1961 [metastore] Add ability to alter column name, type, comment

Jenny Kim vor 10 Jahren
Ursprung
Commit
1bee0a371b

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

@@ -213,6 +213,35 @@ class HiveServer2Dbms(object):
         return col
     return None
 
+
+  def alter_column(self, database, table_name, column_name, new_column_name, column_type, comment=None,
+                   partition_spec=None, cascade=False):
+    hql = 'ALTER TABLE `%s`.`%s`' % (database, table_name)
+
+    if partition_spec:
+      hql += ' PARTITION (%s)' % partition_spec
+
+    hql += ' CHANGE COLUMN `%s` `%s` %s' % (column_name, new_column_name, column_type.upper())
+
+    if comment:
+      hql += " COMMENT '%s'" % comment
+
+    if cascade:
+      hql += ' CASCADE'
+
+    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 column statement: %s") % hql
+      raise QueryServerException(msg)
+
+    return self.get_column(database, table_name, new_column_name)
+
+
   def execute_query(self, query, design):
     return self.execute_and_watch(query, design=design)
 

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

@@ -16,6 +16,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import json
 import logging
 import urllib
 
@@ -351,6 +352,32 @@ class TestMetastoreWithHadoop(BeeswaxSampleProvider):
     check(client, [200, 302]) # Ok
 
 
+  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)
+
+    resp = self.client.get('/metastore/table/%s/test_alter_column' % self.db_name)
+    assert_true('before_alter', resp.content)
+    assert_true('int', resp.content)
+
+    # Alter name, type and comment
+    resp = self.client.post(reverse("metastore:alter_column",
+                                    kwargs={'database': self.db_name, 'table': 'test_alter_column', 'column': 'before_alter'}),
+                            {'new_column_name': 'after_alter', 'new_column_type': 'string', 'comment': 'alter comment'})
+    json_resp = json.loads(resp.content)
+    assert_equal('after_alter', json_resp['data']['name'], json_resp)
+    assert_equal('string', json_resp['data']['type'], json_resp)
+    assert_equal('alter comment', json_resp['data']['comment'], json_resp)
+
+    # Invalid column type returns error response
+    resp = self.client.post(reverse("metastore:alter_column",
+                                    kwargs={'database': self.db_name, 'table': 'test_alter_column', 'column': 'before_alter'}),
+                            {'new_column_name': 'foo'})
+    json_resp = json.loads(resp.content)
+    assert_equal(1, json_resp['status'], json_resp)
+    assert_true('Failed to alter column' in json_resp['data'], json_resp)
+
+
 class TestParser(object):
 
   def test_parse_simple(self):

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

@@ -35,4 +35,5 @@ urlpatterns = patterns('metastore.views',
   url(r'^table/(?P<database>\w+)/(?P<table>\w+)/partitions/(?P<partition_spec>.+?)/read$', 'read_partition', name='read_partition'),
   url(r'^table/(?P<database>\w+)/(?P<table>\w+)/partitions/(?P<partition_spec>.+?)/browse$', 'browse_partition', name='browse_partition'),
   url(r'^table/(?P<database>\w+)/(?P<table>\w+)/partitions/drop$', 'drop_partition', name='drop_partition'),
+  url(r'^table/(?P<database>\w+)/(?P<table>\w+)/(?P<column>\w+)/alter', 'alter_column', name='alter_column'),
 )

+ 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_column(request, database, table, column):
+  db = dbms.get(request.user)
+  response = {'status': -1, 'data': ''}
+  try:
+    col = db.get_column(database, table, column)
+    if col:
+      new_column_name = request.POST.get('new_column_name', col.name)
+      new_column_type = request.POST.get('new_column_type', col.type)
+      comment = request.POST.get('comment', None)
+      partition_spec = request.POST.get('partition_spec', None)
+
+      column = db.alter_column(database, table, column, new_column_name, new_column_type, comment=comment, partition_spec=partition_spec)
+
+      response['status'] = 0
+      response['data'] = {
+        'name': column.name,
+        'type': column.type,
+        'comment': column.comment
+      }
+    else:
+      raise PopupException(_('Column `%s`.`%s` `%s` not found') % (database, table, column))
+  except Exception, ex:
+    response['status'] = 1
+    response['data'] = _("Failed to alter column `%s`.`%s` `%s`: %s") % (database, table, column, str(ex))
+
+  return JsonResponse(response)
+
+
 @check_has_write_access_permission
 def drop_table(request, database):
   db = dbms.get(request.user)