Преглед изворни кода

HUE-1939 [beeswax] CTAS redirects to the default database in the metastore

Support saving all the CTAS use cases, e.g.
  - from current DB to current DB
  - from current DB to another DB
  - from DBA to current DB
  - from DBA.TABLE1 to DBB.TABLE2
Romain Rigaux пре 11 година
родитељ
комит
747add1

+ 4 - 3
apps/beeswax/src/beeswax/api.py

@@ -403,7 +403,8 @@ def save_results(request, query_history_id):
       data['target_dir'] = request.POST.get('path', None)
 
     db = dbms.get(request.user, query_history.get_query_server_config())
-    form = beeswax.forms.SaveResultsForm(data, db=db, fs=request.fs)
+    database = query_history.design.get_design().query.get('database', 'default')
+    form = beeswax.forms.SaveResultsForm(data, db=db, fs=request.fs, database=database)
 
     if form.is_valid():
       try:
@@ -425,12 +426,12 @@ def save_results(request, query_history_id):
           response['success_url'] = '/filebrowser/view%s' % target_dir
           response['watch_url'] = reverse(get_app_name(request) + ':api_watch_query_refresh_json', kwargs={'id': query_history.id})
         elif form.cleaned_data['save_target'] == form.SAVE_TYPE_TBL:
-          query_history = db.create_table_as_a_select(request, query_history, form.cleaned_data['target_table'], result_meta)
+          query_history = db.create_table_as_a_select(request, query_history, form.target_database, form.cleaned_data['target_table'], result_meta)
           response['id'] = query_history.id
           response['query'] = query_history.query
           response['type'] = 'hive-table'
           response['path'] = form.cleaned_data['target_table']
-          response['success_url'] = reverse('metastore:describe_table', kwargs={'database': 'default', 'table': form.cleaned_data['target_table']})
+          response['success_url'] = reverse('metastore:describe_table', kwargs={'database': form.target_database, 'table': form.cleaned_data['target_table']})
           response['watch_url'] = reverse(get_app_name(request) + ':api_watch_query_refresh_json', kwargs={'id': query_history.id})
       except Exception, ex:
         error_msg, log = expand_exception(ex, db)

+ 10 - 10
apps/beeswax/src/beeswax/forms.py

@@ -88,7 +88,7 @@ class SaveResultsForm(DependencyAwareForm):
   target_table = common.HiveIdentifierField(
                                   label=_t("Table Name"),
                                   required=False,
-                                  help_text=_t("Name of the new table"))
+                                  help_text=_t("Name of the new table")) # Can also contain a DB prefixed table name, e.g. DB_NAME.TABLE_NAME
   target_dir = PathField(label=_t("Results Location"),
                          required=False,
                          help_text=_t("Empty directory in HDFS to store results."))
@@ -100,6 +100,7 @@ class SaveResultsForm(DependencyAwareForm):
   def __init__(self, *args, **kwargs):
     self.db = kwargs.pop('db', None)
     self.fs = kwargs.pop('fs', None)
+    self.target_database = kwargs.pop('database', 'default')
     super(SaveResultsForm, self).__init__(*args, **kwargs)
 
   def clean(self):
@@ -107,20 +108,19 @@ class SaveResultsForm(DependencyAwareForm):
 
     if cleaned_data:
       if cleaned_data.get('save_target') == SaveResultsForm.SAVE_TYPE_TBL:
-        tbl = cleaned_data.get('target_table')
-        if tbl:
+        target_table = cleaned_data.get('target_table')
+        if target_table:
           try:
             if self.db is not None:
-              db_name = 'default'
-              name_parts = tbl.split(".")
+              name_parts = target_table.split(".")
               if len(name_parts) == 1:
-                tbl_name = tbl
+                pass
               elif len(name_parts) == 2:
-                db_name, tbl_name = name_parts
+                self.target_database, target_table = name_parts
               else:
-                self._errors['target_table'] = self.error_class([_('Invalid table name')])
-
-              self.db.get_table(db_name, tbl_name)
+                self._errors['target_table'] = self.error_class([_('Invalid table prefix name')])
+              cleaned_data['target_table'] = target_table # Update table name without the DB prefix
+              self.db.get_table(self.target_database, target_table)
             self._errors['target_table'] = self.error_class([_('Table already exists')])
             del cleaned_data['target_table']
           except Exception:

+ 2 - 6
apps/beeswax/src/beeswax/server/dbms.py

@@ -242,19 +242,15 @@ class HiveServer2Dbms(object):
     return self.execute_statement(hql)
 
 
-  def create_table_as_a_select(self, request, query_history, target_table, result_meta):
+  def create_table_as_a_select(self, request, query_history, target_database, target_table, result_meta):
     design = query_history.design.get_design()
     database = design.query['database']
 
-    name_parts = target_table.split(".")
-    if len(name_parts) == 2:
-      database, target_table = name_parts
-
     # Case 1: Hive Server 2 backend or results straight from an existing table
     if result_meta.in_tablename:
       self.use(database)
 
-      hql = 'CREATE TABLE `%s.%s` AS %s' % (database, target_table, design.query['query'])
+      hql = 'CREATE TABLE `%s.%s` AS %s' % (target_database, target_table, design.query['query'])
       query_history = self.execute_statement(hql)
     else:
       # Case 2: The results are in some temporary location

+ 1 - 1
apps/beeswax/src/beeswax/templates/execute.mako

@@ -601,7 +601,7 @@ ${layout.menubar(section='query')}
                ${ _('In a new table') }
             </label>
             <span data-bind="visible: $root.design.results.save.type() == 'hive-table'">
-              <input data-bind="value: $root.design.results.save.path" type="text" name="target_table" placeholder="${_('Table name')}">
+              <input data-bind="value: $root.design.results.save.path" type="text" name="target_table" class="span4" placeholder="${_('Table name or <database name>.<table name>')}">
             </span>
           </div>
         </div>

+ 4 - 0
apps/beeswax/src/beeswax/tests.py

@@ -935,6 +935,10 @@ for x in sys.stdin:
     resp = _make_query(self.client, hql, wait=True, local=False, max=180.0)
     save_and_verify(resp, TARGET_TBL_ROOT + '_2')
 
+    # Save to another DB
+    hql = "SELECT * FROM test"
+    resp = _make_query(self.client, hql, wait=True, local=False, max=180.0)
+    save_and_verify(resp, 'other_db.' + TARGET_TBL_ROOT)
 
   def test_install_examples(self):
     assert_true(not beeswax.models.MetaInstall.get().installed_example)