Răsfoiți Sursa

[core] Move the active database to the assist helper

This moves the active database observable to the assist helper, keeping the page-wide database in one place (as opposed to keeping multiple instances in sync). Before this change more than one components kept track of the active database, by using pub/sub events they were all kept in sync.

As the assist panel is a ko component we were required to use timeouts to make sure the panel was active before certain events were fired, this is not a very robust approach. By just keeping one observable there's no longer any need to have the events and all changes are instant.
Johan Ahlen 10 ani în urmă
părinte
comite
f17468b

+ 3 - 29
apps/beeswax/src/beeswax/static/beeswax/js/beeswax.vm.js

@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // See the License for the specific language governing permissions and
 // limitations under the License.
 // limitations under the License.
 
 
-function BeeswaxViewModel(server) {
+function BeeswaxViewModel(server, assistHelper) {
   var self = this;
   var self = this;
 
 
   var DESIGN_DEFAULTS = {
   var DESIGN_DEFAULTS = {
@@ -72,6 +72,8 @@ function BeeswaxViewModel(server) {
     'isRedacted': false
     'isRedacted': false
   };
   };
 
 
+  self.database = assistHelper.activeDatabase;
+
   self.design = ko.mapping.fromJS(DESIGN_DEFAULTS);
   self.design = ko.mapping.fromJS(DESIGN_DEFAULTS);
 
 
   self.design.inlineErrors = ko.computed(function() {
   self.design.inlineErrors = ko.computed(function() {
@@ -93,8 +95,6 @@ function BeeswaxViewModel(server) {
   self.chartData = ko.observableArray();
   self.chartData = ko.observableArray();
 
 
   self.server = ko.observable(server);
   self.server = ko.observable(server);
-  self.databases = ko.observableArray();
-  self.selectedDatabase = ko.observable(0);
   self.isReady = ko.observable(false);
   self.isReady = ko.observable(false);
   // Use a view model attribute so that we don't have to override KO.
   // Use a view model attribute so that we don't have to override KO.
   // This allows Hue to disable the execute button until the query placeholder dies.
   // This allows Hue to disable the execute button until the query placeholder dies.
@@ -125,22 +125,6 @@ function BeeswaxViewModel(server) {
     return (self.design.results.save.errors() && 'target_file' in self.design.results.save.errors()) ? self.design.results.save.errors()['target_file'] : null;
     return (self.design.results.save.errors() && 'target_file' in self.design.results.save.errors()) ? self.design.results.save.errors()['target_file'] : null;
   });
   });
 
 
-  self.database = ko.computed({
-    'read': function() {
-      if (self.databases()) {
-        return self.databases()[self.selectedDatabase()];
-      } else{
-        return "";
-      }
-    },
-    'write': function(databaseName) {
-      if (databaseName) {
-        self.selectedDatabase(self.databases.indexOf(databaseName));
-      }
-    },
-    'deferEvaluation': true
-  });
-
   self.hasParametersFilled = ko.computed(function() {
   self.hasParametersFilled = ko.computed(function() {
     var hasBlank = false;
     var hasBlank = false;
     $.each(self.design.parameters(), function(index, element) {
     $.each(self.design.parameters(), function(index, element) {
@@ -180,16 +164,6 @@ function BeeswaxViewModel(server) {
     }
     }
   };
   };
 
 
-  self.updateDatabases = function(databases) {
-    if (databases) {
-      var i = databases.indexOf("_impala_builtins"); // Blacklist of system databases
-      if (i != -1) {
-        databases.splice(i, 1);
-      }
-      self.databases(databases);
-    }
-  };
-
   self.updateDesign = function(design) {
   self.updateDesign = function(design) {
     self.design.query.value(design.query);
     self.design.query.value(design.query);
     self.design.id(design.id);
     self.design.id(design.id);

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

@@ -2570,12 +2570,6 @@ function loadDesign(design_id) {
   setupCodeMirrorSubscription();
   setupCodeMirrorSubscription();
 }
 }
 
 
-huePubSub.subscribe('hue.assist.databaseChanged', function(name) {
-  if (name !== viewModel.database()) {
-    viewModel.database(name);
-  }
-});
-
 function loadQueryHistory(query_history_id) {
 function loadQueryHistory(query_history_id) {
   viewModel.design.history.id(query_history_id);
   viewModel.design.history.id(query_history_id);
   viewModel.fetchQueryHistory();
   viewModel.fetchQueryHistory();
@@ -2598,7 +2592,7 @@ function setupCodeMirrorSubscription() {
 }
 }
 
 
 // Knockout
 // Knockout
-viewModel = new BeeswaxViewModel("${app_name}");
+viewModel = new BeeswaxViewModel("${app_name}", assistHelper);
 ko.applyBindings(viewModel, $("#beeswax-execute")[0]);
 ko.applyBindings(viewModel, $("#beeswax-execute")[0]);
 
 
 shareViewModel = initSharing("#documentShareModal");
 shareViewModel = initSharing("#documentShareModal");

+ 1 - 0
apps/spark/src/spark/templates/editor_components.mako

@@ -445,6 +445,7 @@ from desktop.views import _ko
           extraCompleters: completers,
           extraCompleters: completers,
           errors: errors,
           errors: errors,
           autocompleter: aceAutocompleter,
           autocompleter: aceAutocompleter,
+          assistHelper: assistHelper,
           openIt: '${ _ko("Double click to open it") }',
           openIt: '${ _ko("Double click to open it") }',
           placeholder: $root.snippetPlaceholders[type()] }"></div>
           placeholder: $root.snippetPlaceholders[type()] }"></div>
       </div>
       </div>

+ 17 - 12
desktop/core/src/desktop/static/desktop/js/assistHelper.js

@@ -26,6 +26,11 @@ var TIME_TO_LIVE_IN_MILLIS = 86400000; // 1 day
 function AssistHelper (options) {
 function AssistHelper (options) {
   var self = this;
   var self = this;
   self.options = options;
   self.options = options;
+
+  self.activeDatabase = ko.observable();
+  if (typeof options.db !== "undefined") {
+    self.activeDatabase(options.db)
+  }
 }
 }
 
 
 AssistHelper.prototype.hasExpired = function (timestamp) {
 AssistHelper.prototype.hasExpired = function (timestamp) {
@@ -44,10 +49,10 @@ AssistHelper.prototype.getTotalStorageUserPrefix = function () {
   return app;
   return app;
 };
 };
 
 
-AssistHelper.prototype.fetchTableHtmlPreview = function(databaseName, tableName, successCallback, errorCallback) {
+AssistHelper.prototype.fetchTableHtmlPreview = function(tableName, successCallback, errorCallback) {
   var self = this;
   var self = this;
   $.ajax({
   $.ajax({
-    url: "/" + self.options.app + "/api/table/" + databaseName + "/" + tableName,
+    url: "/" + self.options.app + "/api/table/" + self.activeDatabase() + "/" + tableName,
     data: {"sample": true},
     data: {"sample": true},
     beforeSend: function (xhr) {
     beforeSend: function (xhr) {
       xhr.setRequestHeader("X-Requested-With", "Hue");
       xhr.setRequestHeader("X-Requested-With", "Hue");
@@ -58,7 +63,7 @@ AssistHelper.prototype.fetchTableHtmlPreview = function(databaseName, tableName,
   });
   });
 };
 };
 
 
-AssistHelper.prototype.refreshTableStats = function(databaseName, tableName, successCallback, errorCallback) {
+AssistHelper.prototype.refreshTableStats = function(tableName, successCallback, errorCallback) {
   var self = this;
   var self = this;
   var pollRefresh = function (url) {
   var pollRefresh = function (url) {
     $.post(url, function (data) {
     $.post(url, function (data) {
@@ -74,7 +79,7 @@ AssistHelper.prototype.refreshTableStats = function(databaseName, tableName, suc
     }).fail(errorCallback);
     }).fail(errorCallback);
   };
   };
 
 
-  $.post("/" + self.options.app + "/api/analyze/" + databaseName + "/" + tableName + "/", function (data) {
+  $.post("/" + self.options.app + "/api/analyze/" + self.activeDatabase() + "/" + tableName + "/", function (data) {
     if (data.status == 0 && data.watch_url) {
     if (data.status == 0 && data.watch_url) {
       pollRefresh(data.watch_url);
       pollRefresh(data.watch_url);
     } else {
     } else {
@@ -83,10 +88,10 @@ AssistHelper.prototype.refreshTableStats = function(databaseName, tableName, suc
   }).fail(errorCallback);
   }).fail(errorCallback);
 };
 };
 
 
-AssistHelper.prototype.fetchStats = function(databaseName, tableName, columnName, successCallback, errorCallback) {
+AssistHelper.prototype.fetchStats = function(tableName, columnName, successCallback, errorCallback) {
   var self = this;
   var self = this;
   $.ajax({
   $.ajax({
-    url: "/" + self.options.app + "/api/table/" + databaseName + "/" + tableName + "/stats/" + (columnName || ""),
+    url: "/" + self.options.app + "/api/table/" + self.activeDatabase() + "/" + tableName + "/stats/" + (columnName || ""),
     data: {},
     data: {},
     beforeSend: function (xhr) {
     beforeSend: function (xhr) {
       xhr.setRequestHeader("X-Requested-With", "Hue");
       xhr.setRequestHeader("X-Requested-With", "Hue");
@@ -97,10 +102,10 @@ AssistHelper.prototype.fetchStats = function(databaseName, tableName, columnName
   });
   });
 };
 };
 
 
-AssistHelper.prototype.fetchTerms = function(databaseName, tableName, columnName, prefixFilter, successCallback, errorCallback) {
+AssistHelper.prototype.fetchTerms = function(tableName, columnName, prefixFilter, successCallback, errorCallback) {
   var self = this;
   var self = this;
   $.ajax({
   $.ajax({
-    url: "/" + self.options.app + "/api/table/" + databaseName + "/" + tableName + "/terms/" + columnName + "/" + (prefixFilter || ""),
+    url: "/" + self.options.app + "/api/table/" + self.activeDatabase() + "/" + tableName + "/terms/" + columnName + "/" + (prefixFilter || ""),
     data: {},
     data: {},
     beforeSend: function (xhr) {
     beforeSend: function (xhr) {
       xhr.setRequestHeader("X-Requested-With", "Hue");
       xhr.setRequestHeader("X-Requested-With", "Hue");
@@ -120,16 +125,16 @@ AssistHelper.prototype.fetchDatabases = function(successCallback, errorCallback)
   }, errorCallback);
   }, errorCallback);
 };
 };
 
 
-AssistHelper.prototype.fetchTables = function(databaseName, successCallback, errorCallback) {
+AssistHelper.prototype.fetchTables = function(successCallback, errorCallback) {
   var self = this;
   var self = this;
-  self.fetchAssistData("/" + self.options.app + "/api/autocomplete/" + databaseName, successCallback, errorCallback);
+  self.fetchAssistData("/" + self.options.app + "/api/autocomplete/" + self.activeDatabase(), successCallback, errorCallback);
 };
 };
 
 
-AssistHelper.prototype.fetchFields = function(databaseName, tableName, fields, successCallback, errorCallback) {
+AssistHelper.prototype.fetchFields = function(tableName, fields, successCallback, errorCallback) {
   var self = this;
   var self = this;
 
 
   var fieldPart = fields.length > 0 ? "/" + fields.join("/") : "";
   var fieldPart = fields.length > 0 ? "/" + fields.join("/") : "";
-  self.fetchAssistData("/" + self.options.app + "/api/autocomplete/" + databaseName + "/" + tableName + fieldPart, successCallback, errorCallback);
+  self.fetchAssistData("/" + self.options.app + "/api/autocomplete/" + self.activeDatabase() + "/" + tableName + fieldPart, successCallback, errorCallback);
 };
 };
 
 
 AssistHelper.prototype.clearCache = function() {
 AssistHelper.prototype.clearCache = function() {

+ 5 - 10
desktop/core/src/desktop/static/desktop/js/autocomplete.js

@@ -29,17 +29,12 @@ function Autocompleter(options) {
   var self = this;
   var self = this;
   self.options = options;
   self.options = options;
   self.assistHelper = options.assistHelper;
   self.assistHelper = options.assistHelper;
-  self.currentDb = options.db;
   if (typeof options.mode === "undefined" || options.mode === null || options.mode === "beeswax") {
   if (typeof options.mode === "undefined" || options.mode === null || options.mode === "beeswax") {
     self.currentMode = "hive";
     self.currentMode = "hive";
   } else {
   } else {
     self.currentMode = options.mode;
     self.currentMode = options.mode;
   }
   }
 
 
-  huePubSub.subscribe('hue.assist.databaseChanged', function (db) {
-    self.currentDb = db;
-  });
-
   huePubSub.subscribe('hue.ace.activeMode', function(mode) {
   huePubSub.subscribe('hue.ace.activeMode', function(mode) {
     self.currentMode = mode.split("/").pop();
     self.currentMode = mode.split("/").pop();
   })
   })
@@ -96,9 +91,9 @@ Autocompleter.prototype.extractFields = function (data, valuePrefix, includeStar
 Autocompleter.prototype.autocomplete = function(beforeCursor, afterCursor, callback) {
 Autocompleter.prototype.autocomplete = function(beforeCursor, afterCursor, callback) {
   var self = this;
   var self = this;
 
 
-  if (typeof self.currentDb == "undefined"
-    || self.currentDb == null
-    || self.currentDb == ""
+  if (typeof self.assistHelper.activeDatabase() == "undefined"
+    || self.assistHelper.activeDatabase() == null
+    || self.assistHelper.activeDatabase() == ""
     || (self.currentMode !== "hive" && self.currentMode !== "impala")) {
     || (self.currentMode !== "hive" && self.currentMode !== "impala")) {
     callback([]);
     callback([]);
     return;
     return;
@@ -131,7 +126,7 @@ Autocompleter.prototype.autocomplete = function(beforeCursor, afterCursor, callb
 
 
 
 
   if (tableNameAutoComplete || (selectBefore && !fromAfter)) {
   if (tableNameAutoComplete || (selectBefore && !fromAfter)) {
-    self.assistHelper.fetchTables(self.currentDb, function(data) {
+    self.assistHelper.fetchTables(function(data) {
       var fromKeyword = "";
       var fromKeyword = "";
       if (selectBefore) {
       if (selectBefore) {
         if (beforeCursor.indexOf("SELECT") > -1) {
         if (beforeCursor.indexOf("SELECT") > -1) {
@@ -197,7 +192,7 @@ Autocompleter.prototype.autocomplete = function(beforeCursor, afterCursor, callb
       }
       }
     });
     });
 
 
-    self.assistHelper.fetchFields(self.currentDb, tableName, fields, function(data) {
+    self.assistHelper.fetchFields(tableName, fields, function(data) {
       callback(self.extractFields(data, "", !fieldTermBefore));
       callback(self.extractFields(data, "", !fieldTermBefore));
     }, function() {
     }, function() {
       callback([]);
       callback([]);

+ 2 - 9
desktop/core/src/desktop/static/desktop/js/ko.hue-bindings.js

@@ -1662,6 +1662,7 @@ ko.bindingHandlers.aceEditor = {
     var onAfterExec = options.onAfterExec || function () {};
     var onAfterExec = options.onAfterExec || function () {};
     var onExecute = options.onExecute || function () {};
     var onExecute = options.onExecute || function () {};
     var autocompleter = options.autocompleter;
     var autocompleter = options.autocompleter;
+    var assistHelper = options.assistHelper;
 
 
     $el.text(options.value());
     $el.text(options.value());
 
 
@@ -1887,16 +1888,8 @@ ko.bindingHandlers.aceEditor = {
       }).call(HueLink.prototype);
       }).call(HueLink.prototype);
 
 
       exports.HueLink = HueLink;
       exports.HueLink = HueLink;
-
     });
     });
 
 
-
-    var currentAssistDb = "";
-    huePubSub.subscribe('hue.assist.databaseChanged', function (db) {
-      currentAssistDb = db;
-    });
-
-
     HueLink = ace.require("huelink").HueLink;
     HueLink = ace.require("huelink").HueLink;
     editor.hueLink = new HueLink(editor);
     editor.hueLink = new HueLink(editor);
     editor.hueLink.on("open", function (token) {
     editor.hueLink.on("open", function (token) {
@@ -1907,7 +1900,7 @@ ko.bindingHandlers.aceEditor = {
         window.open("/filebrowser/#" + token.value.replace(/\"/gi, ""));
         window.open("/filebrowser/#" + token.value.replace(/\"/gi, ""));
       }
       }
       else {
       else {
-        window.open("/metastore/table/" + currentAssistDb + "/" + token.value);
+        window.open("/metastore/table/" + self.assistHelper.activeDatabase() + "/" + token.value);
       }
       }
     });
     });
 
 

+ 6 - 14
desktop/core/src/desktop/static/desktop/spec/autocompleteSpec.js

@@ -23,13 +23,8 @@ describe("autocomplete.js", function() {
   };
   };
 
 
   beforeAll(function() {
   beforeAll(function() {
-    var totalStorage = {};
     $.totalStorage = function(key, value) {
     $.totalStorage = function(key, value) {
-      if (typeof value === "undefined") {
-        return totalStorage[key];
-      }
-      totalStorage[key] = value;
-      return value;
+      return null;
     };
     };
 
 
     jasmine.addMatchers({
     jasmine.addMatchers({
@@ -66,9 +61,9 @@ describe("autocomplete.js", function() {
     var options = {
     var options = {
       assistHelper: new AssistHelper({
       assistHelper: new AssistHelper({
         app: "testApp",
         app: "testApp",
-        user: "testUser"
-      }),
-      db: "testDb"
+        user: "testUser",
+        db: "testDb"
+      })
     };
     };
     subject = new Autocompleter(options);
     subject = new Autocompleter(options);
     ajaxHelper.responseForUrls = {};
     ajaxHelper.responseForUrls = {};
@@ -159,9 +154,9 @@ describe("autocomplete.js", function() {
       var options = {
       var options = {
         assistHelper: new AssistHelper({
         assistHelper: new AssistHelper({
           app: "testApp",
           app: "testApp",
-          user: "testUser"
+          user: "testUser",
+          db: "testDb"
         }),
         }),
-        db: "testDb",
         mode: "hive"
         mode: "hive"
       };
       };
       subject = new Autocompleter(options);
       subject = new Autocompleter(options);
@@ -247,7 +242,6 @@ describe("autocomplete.js", function() {
       });
       });
     });
     });
 
 
-    // TODO: Fix me
     it("should suggest columns for table after WHERE", function() {
     it("should suggest columns for table after WHERE", function() {
       assertAutoComplete({
       assertAutoComplete({
         serverResponses: {
         serverResponses: {
@@ -261,7 +255,6 @@ describe("autocomplete.js", function() {
       });
       });
     });
     });
 
 
-    // TODO: Fix me
     it("should suggest columns for table after ORDER BY ", function() {
     it("should suggest columns for table after ORDER BY ", function() {
       assertAutoComplete({
       assertAutoComplete({
         serverResponses: {
         serverResponses: {
@@ -275,7 +268,6 @@ describe("autocomplete.js", function() {
       });
       });
     });
     });
 
 
-    // TODO: Fix me
     it("should suggest columns for table after ON ", function() {
     it("should suggest columns for table after ON ", function() {
       assertAutoComplete({
       assertAutoComplete({
         serverResponses: {
         serverResponses: {

+ 38 - 46
desktop/core/src/desktop/templates/ko_components.mako

@@ -179,7 +179,7 @@ from desktop.views import _ko
           </div>
           </div>
         </li>
         </li>
         <li data-bind="visible: ! hasErrors()" >
         <li data-bind="visible: ! hasErrors()" >
-          <select data-bind="options: availableDatabaseNames, select2: { width: '100%', placeholder: '${ _ko("Choose a database...") }', update: selectedDatabaseName }" class="input-medium" data-placeholder="${_('Choose a database...')}"></select>
+          <select data-bind="options: availableDatabaseNames, select2: { width: '100%', placeholder: '${ _ko("Choose a database...") }', update: assistHelper.activeDatabase }" class="input-medium" data-placeholder="${_('Choose a database...')}"></select>
         </li>
         </li>
         <li data-bind="visible: hasErrors">
         <li data-bind="visible: hasErrors">
           <span>${ _('The database list cannot be loaded.') }</span>
           <span>${ _('The database list cannot be loaded.') }</span>
@@ -430,11 +430,11 @@ from desktop.views import _ko
         var tableName = hierarchy[1];
         var tableName = hierarchy[1];
 
 
         $assistQuickLook.find(".tableName").text(self.definition.name);
         $assistQuickLook.find(".tableName").text(self.definition.name);
-        $assistQuickLook.find(".tableLink").attr("href", "/metastore/table/" + databaseName + "/" + tableName);
+        $assistQuickLook.find(".tableLink").attr("href", "/metastore/table/" + self.assistPanel.assistHelper.activeDatabase() + "/" + tableName);
         $assistQuickLook.find(".sample").empty("");
         $assistQuickLook.find(".sample").empty("");
         $assistQuickLook.attr("style", "width: " + ($(window).width() - 120) + "px;margin-left:-" + (($(window).width() - 80) / 2) + "px!important;");
         $assistQuickLook.attr("style", "width: " + ($(window).width() - 120) + "px;margin-left:-" + (($(window).width() - 80) / 2) + "px!important;");
 
 
-        self.assistPanel.assistHelper.fetchTableHtmlPreview(databaseName, tableName, function(data) {
+        self.assistPanel.assistHelper.fetchTableHtmlPreview(tableName, function(data) {
           $assistQuickLook.find(".loader").hide();
           $assistQuickLook.find(".loader").hide();
           $assistQuickLook.find(".sample").html(data);
           $assistQuickLook.find(".sample").html(data);
         }, function(e) {
         }, function(e) {
@@ -507,7 +507,7 @@ from desktop.views import _ko
       TableStats.prototype.fetchData = function () {
       TableStats.prototype.fetchData = function () {
         var self = this;
         var self = this;
         self.loading(true);
         self.loading(true);
-        self.assistHelper.fetchStats(self.database, self.table, self.column != null ? self.column : null, function (data) {
+        self.assistHelper.fetchStats(self.table, self.column != null ? self.column : null, function (data) {
           if (data && data.status == 0) {
           if (data && data.status == 0) {
             self.statRows(data.stats);
             self.statRows(data.stats);
             var inaccurate = true;
             var inaccurate = true;
@@ -540,7 +540,7 @@ from desktop.views import _ko
         var shouldFetchTerms = self.termsTabActive() || self.terms().length > 0;
         var shouldFetchTerms = self.termsTabActive() || self.terms().length > 0;
         self.refreshing(true);
         self.refreshing(true);
 
 
-        self.assistHelper.refreshTableStats(self.database, self.table, function() {
+        self.assistHelper.refreshTableStats(self.table, function() {
           self.refreshing(false);
           self.refreshing(false);
           self.fetchData();
           self.fetchData();
           if (shouldFetchTerms) {
           if (shouldFetchTerms) {
@@ -559,7 +559,7 @@ from desktop.views import _ko
         }
         }
 
 
         self.loadingTerms(true);
         self.loadingTerms(true);
-        self.assistHelper.fetchTerms(self.database, self.table, self.column, self.prefixFilter(), function (data) {
+        self.assistHelper.fetchTerms(self.table, self.column, self.prefixFilter(), function (data) {
           if (data && data.status == 0) {
           if (data && data.status == 0) {
             self.terms($.map(data.terms, function (term) {
             self.terms($.map(data.terms, function (term) {
               return {
               return {
@@ -614,6 +614,10 @@ from desktop.views import _ko
         self.databases = ko.observableArray();
         self.databases = ko.observableArray();
         self.selectedDatabase = ko.observable();
         self.selectedDatabase = ko.observable();
 
 
+        self.loadingTables = ko.computed(function() {
+          return  ! (self.selectedDatabase() && !self.selectedDatabase().loading());
+        });
+
         self.selectedDatabase.subscribe(function(newValue) {
         self.selectedDatabase.subscribe(function(newValue) {
           if (newValue != null) {
           if (newValue != null) {
             newValue.loadEntries();
             newValue.loadEntries();
@@ -622,46 +626,22 @@ from desktop.views import _ko
 
 
         // We need the names because select2 does not support objects
         // We need the names because select2 does not support objects
         self.availableDatabaseNames = ko.observableArray();
         self.availableDatabaseNames = ko.observableArray();
-        self.selectedDatabaseName = ko.observable();
 
 
-        self.selectedDatabaseName.subscribe(function(name) {
-          if (name == null) {
+        self.fetchDatabases(function() {
+          self.assistHelper.activeDatabase.subscribe(setDatabase);
+
+          if ($.inArray(self.assistHelper.activeDatabase(), self.availableDatabaseNames()) > -1) {
+            setDatabase(self.assistHelper.activeDatabase());
             return;
             return;
           }
           }
-          self.options.lastSelectedDb(name);
-
-          // TODO: find a better criteria for showing the spinner
-          // This is deferred so that the spinner gets a chance to be shown
-          self.selectedDatabase(null);
-          window.setTimeout(function () {
-            self.selectedDatabase(ko.utils.arrayFirst(self.databases(), function(database) {
-              return name === database.definition.name;
-            }));
-          }, 10);
-          huePubSub.publish('hue.assist.databaseChanged', name);
-        });
-
-        huePubSub.subscribe('hue.assist.changeDatabase', function(name) {
-          self.selectedDatabaseName(name);
-        });
-
-        self.loadingTables = ko.computed(function() {
-          return  ! (self.selectedDatabase() && !self.selectedDatabase().loading());
-        });
+          if ($.inArray(self.options.lastSelectedDb(), self.availableDatabaseNames()) > -1) {
+            self.assistHelper.activeDatabase(self.options.lastSelectedDb());
+          } else if ($.inArray("default", self.availableDatabaseNames()) > -1) {
+            self.assistHelper.activeDatabase("default");
+          } else if (self.availableDatabaseNames().length > 0) {
+            self.assistHelper.activeDatabase(self.availableDatabaseNames()[0]);
+          }
 
 
-        self.fetchDatabases(function() {
-          window.setTimeout(function() {
-            if ($.inArray(self.selectedDatabaseName(), self.availableDatabaseNames()) > -1) {
-              return;
-            }
-            if ($.inArray(self.options.lastSelectedDb(), self.availableDatabaseNames()) > -1) {
-              self.selectedDatabaseName(self.options.lastSelectedDb());
-            } else if ($.inArray("default", self.availableDatabaseNames()) > -1) {
-              self.selectedDatabaseName("default");
-            } else if (self.availableDatabaseNames().length > 0) {
-              self.selectedDatabaseName(self.availableDatabaseNames()[0]);
-            }
-          }, 150);
         });
         });
 
 
         self.modalItem = ko.observable();
         self.modalItem = ko.observable();
@@ -701,6 +681,18 @@ from desktop.views import _ko
         };
         };
       }
       }
 
 
+      AssistPanel.prototype.setDatabase = function(name) {
+        var self = this;
+        if (name == null) {
+          return;
+        }
+        self.options.lastSelectedDb(name);
+
+        self.selectedDatabase(ko.utils.arrayFirst(self.databases(), function(database) {
+          return name === database.definition.name;
+        }));
+      };
+
       AssistPanel.prototype.toggleSearch = function () {
       AssistPanel.prototype.toggleSearch = function () {
         var self = this;
         var self = this;
         self.options.isSearchVisible(!self.options.isSearchVisible());
         self.options.isSearchVisible(!self.options.isSearchVisible());
@@ -709,11 +701,11 @@ from desktop.views import _ko
       AssistPanel.prototype.reloadAssist = function() {
       AssistPanel.prototype.reloadAssist = function() {
         var self = this;
         var self = this;
         self.reloading(true);
         self.reloading(true);
-        var selectedDb = self.selectedDatabaseName();
-        self.selectedDatabaseName(null);
+        self.selectedDatabase(null);
         self.assistHelper.clearCache();
         self.assistHelper.clearCache();
-        self.fetchDatabases();
-        self.selectedDatabaseName(selectedDb);
+        self.fetchDatabases(function() {
+          self.setDatabase(self.options.lastSelectedDb());
+        });
       };
       };
 
 
       AssistPanel.prototype.fetchDatabases = function(callback) {
       AssistPanel.prototype.fetchDatabases = function(callback) {