Jelajahi Sumber

HUE-1486 [hbase] Bulk upload support

Kevin Wang 12 tahun lalu
induk
melakukan
b0b25c0

+ 23 - 0
apps/hbase/src/hbase/api.py

@@ -21,6 +21,7 @@ except ImportError:
   import simplejson as json
 import logging
 import re
+import csv
 
 from django.core.urlresolvers import reverse
 from django.http import HttpResponse
@@ -178,3 +179,25 @@ class HbaseApi(object):
       scanner = client.scannerOpenWithScan(tableName, scan, None)
       aggregate_data += client.scannerGetList(scanner, query['scan_length'])
     return aggregate_data
+
+  def bulkUpload(self, cluster, tableName, data):
+    client = self.connectCluster(cluster)
+    BatchMutation = get_thrift_type('BatchMutation')
+    Mutation = get_thrift_type('Mutation')
+    columns = []
+    data = data.read()
+    dialect = csv.Sniffer().sniff(data)
+    reader = csv.reader(data.splitlines(), delimiter=dialect.delimiter)
+    columns = reader.next()
+    batches = []
+    for row in reader:
+      row_key = row[0]
+      row_data = {}
+      mutations = []
+      for column_index in range(1, len(row)):
+        if str(row[column_index]) != "":
+          mutations.append(Mutation(column=smart_str(columns[column_index]), value=smart_str(row[column_index])))
+      batches += [BatchMutation(row=row_key, mutations=mutations)]
+    client.mutateRows(tableName, batches, None)
+    return True
+

+ 1 - 0
apps/hbase/src/hbase/templates/app.mako

@@ -256,6 +256,7 @@ ${ commonheader(None, "hbase", user) | n,unicode }
             % if user.is_superuser:
               <button class="btn" data-bind="enable: views.tabledata.selected().length > 0, click: views.tabledata.dropSelected"><i class="icon-trash"></i> ${_('Drop Rows')}</button>
             % endif
+            <button id="bulk-upload-btn" class="btn fileChooserBtn" data-toggle="tooltip" title="${_('.CSV, .TSV, etc...')}" aria-hidden="true"><i class="icon-upload"></i> ${_('Bulk Upload')}</button>
             <a href="#new_row_modal" data-bind="click:function(){app.focusModel(app.views.tabledata);logGA('new_row_modal');}" role="button" class="btn btn-primary" data-callback="" data-toggle="modal"><i class='icon-plus-sign'></i> ${_('New Row')}</a>
           </span>
         </div>

+ 1 - 1
apps/hbase/src/hbase/views.py

@@ -61,7 +61,7 @@ def api_router(request, url): #on split, deserialize anything
     return data
   url_params = [safe_json_load((arg, request.POST.get(arg[0:16], arg))[arg[0:15] == 'hbase-post-key-']) for arg in re.split(r'(?<!\\)/', url.strip('/'))] #deserialize later
   if request.POST.get('dest', False):
-    url_params += [request.FILES.get(request.POST.get('dest'))]
+    url_params += [request.FILES.get(request.REQUEST.get('dest'))]
   return api_dump(HbaseApi().query(*url_params))
 
 def api_dump(response):

+ 4 - 2
apps/hbase/static/css/hbase.css

@@ -156,6 +156,7 @@ ul#hbase-breadcrumbs li a {
 }
 .smartview ul.smartview-cells > li:hover a.corner-btn {
 	display: block;
+	height: 12px !important;
 }
 .smartview ul.smartview-cells > li:hover a.corner-btn:hover {
 	color:#000;
@@ -555,8 +556,9 @@ textarea {
 	border-radius: 1.5em;
 	border-bottom-left-radius: 0px;
 	border-top-left-radius: 0px;
-	padding: .5em 1em .5em .8em;
-	margin-left:-1px;
+	height: auto;
+	display: inline-block;
+	padding: 3px 12px 3px 8px;
 }
 
 .add-on i

+ 1 - 1
apps/hbase/static/js/base.js

@@ -98,7 +98,7 @@ var ListViewModel = function(options) {
     confirm("Confirm Delete", "Are you sure you want to drop the selected items? (WARNING: This cannot be undone!)", function() {
       self.batchSelected(function() {
         var s = this;
-        if(s.enabled()) {
+        if(s.enabled && s.enabled()) {
           self.isLoading(true);
           return s.disable(function() {
             s.drop(true);

+ 0 - 1
apps/hbase/static/js/controls.js

@@ -262,7 +262,6 @@ var SmartViewModel = function(options) {
       for(var i=0;i<keys.length;i++) {
         self.columnFamilies.push(new ColumnFamily({name:keys[i], enabled:false}));
       }
-      self.reload();
       if(callback!=null)
         callback();
     });

+ 13 - 0
apps/hbase/static/js/nav.js

@@ -25,6 +25,19 @@ var Router = {
     app.pageTitle(cluster + ' / ' + table);
     app.views.tabledata.name(table);
     app.focusModel(app.views.tabledata);
+
+    var bulkUploader = new qq.FileUploaderBasic({
+      button: document.getElementById("bulk-upload-btn"),
+      action: '/hbase/api/bulkUpload/"' + app.cluster() + '"/"' + app.views.tabledata.name() + '"',
+      fileFieldLabel: 'hbase_file',
+      multiple: false,
+      onComplete: function (id, fileName, response) {
+        if(response.response != null)
+          $.jHueNotify.error($(response.response).find('.alert strong').text());
+        else
+          app.views.tabledata.reload();
+      }
+    });
   },
   setCluster: function(cluster) {
     app.cluster(cluster);

+ 1 - 1
desktop/core/static/ext/js/fileuploader.js

@@ -1259,7 +1259,7 @@ qq.extend(qq.UploadHandlerXhr.prototype, {
             this._options.onComplete(id, name, response);
 
         } else {
-            this._options.onComplete(id, name, {});
+            this._options.onComplete(id, name, xhr);
         }
 
         this._files[id] = null;