Browse Source

HUE-8330 [metadata] Include compute when accessing the data catalog throughout

Johan Ahlen 7 years ago
parent
commit
fc9f8939b9
24 changed files with 225 additions and 95 deletions
  1. 4 1
      apps/metastore/src/metastore/static/metastore/js/metastore.model.js
  2. 4 4
      apps/metastore/src/metastore/templates/metastore.mako
  3. 2 2
      apps/pig/src/pig/templates/app.mako
  4. 5 5
      desktop/core/src/desktop/static/desktop/js/apiHelper.js
  5. 20 2
      desktop/core/src/desktop/static/desktop/js/assist/assistDbSource.js
  6. 7 0
      desktop/core/src/desktop/static/desktop/js/contextCatalog.js
  7. 36 23
      desktop/core/src/desktop/static/desktop/js/dataCatalog.js
  8. 6 3
      desktop/core/src/desktop/static/desktop/js/jquery.hiveautocomplete.js
  9. 10 3
      desktop/core/src/desktop/static/desktop/js/ko.hue-bindings.js
  10. 13 10
      desktop/core/src/desktop/static/desktop/js/sqlAutocompleter2.js
  11. 11 10
      desktop/core/src/desktop/static/desktop/js/sqlAutocompleter3.js
  12. 3 0
      desktop/core/src/desktop/static/desktop/js/sqlUtils.js
  13. 1 0
      desktop/core/src/desktop/templates/ace_sql_location_worker.mako
  14. 11 2
      desktop/core/src/desktop/templates/assist.mako
  15. 1 1
      desktop/core/src/desktop/templates/common_dashboard.mako
  16. 10 7
      desktop/core/src/desktop/templates/ko_components/ko_context_popover.mako
  17. 1 1
      desktop/core/src/desktop/templates/ko_components/ko_history_panel.mako
  18. 4 0
      desktop/libs/dashboard/src/dashboard/static/dashboard/js/search.ko.js
  19. 2 2
      desktop/libs/dashboard/src/dashboard/templates/common_search.mako
  20. 5 3
      desktop/libs/indexer/src/indexer/templates/importer.mako
  21. 4 2
      desktop/libs/indexer/src/indexer/templates/indexes.mako
  22. 3 0
      desktop/libs/indexer/src/indexer/templates/topics.mako
  23. 53 11
      desktop/libs/notebook/src/notebook/static/notebook/js/notebook.ko.js
  24. 9 3
      desktop/libs/notebook/src/notebook/templates/editor_components.mako

+ 4 - 1
apps/metastore/src/metastore/static/metastore/js/metastore.model.js

@@ -198,6 +198,9 @@ var MetastoreNamespace = (function () {
     var self = this;
     self.apiHelper = ApiHelper.getInstance();
     self.namespace = options.namespace;
+
+    // TODO: Compute selection in the metastore?
+    self.compute = options.namespace.computes[0];
     self.id = options.namespace.id;
     self.name = options.namespace.name;
     self.metastoreViewModel = options.metastoreViewModel;
@@ -230,7 +233,7 @@ var MetastoreNamespace = (function () {
       self.loadingDatabases(false);
     });
 
-    DataCatalog.getEntry({ namespace: self.namespace, sourceType: self.sourceType, path: [], definition: { type: 'source' } }).done(function (entry) {
+    DataCatalog.getEntry({ namespace: self.namespace, compute: self.compute, sourceType: self.sourceType, path: [], definition: { type: 'source' } }).done(function (entry) {
       self.catalogEntry(entry);
       entry.getChildren().done(function (databaseEntries) {
         self.databases($.map(databaseEntries, function (databaseEntry) {

+ 4 - 4
apps/metastore/src/metastore/templates/metastore.mako

@@ -872,14 +872,14 @@ ${ components.menubar(is_embeddable) }
     <!-- /ko -->
     <!-- ko foreach: topJoins -->
     <tr>
-      <td><a href="javscript:void(0);" data-bind="text: tableName, sqlContextPopover: { sourceType: $parents[1].catalogEntry.getSourceType(), namespace: parents[1].catalogEntry.namespace, path: tablePath, offset: { top: -3, left: 3 }}"></a></td>
+      <td><a href="javscript:void(0);" data-bind="text: tableName, sqlContextPopover: { sourceType: $parents[1].catalogEntry.getSourceType(), namespace: parents[1].catalogEntry.namespace, compute: parents[1].catalogEntry.compute, path: tablePath, offset: { top: -3, left: 3 }}"></a></td>
       <td>
         <table class="metastore-join-column-table">
           <tbody data-bind="foreach: joinCols">
           <tr>
-            <td><a href="javscript:void(0);" data-bind="text: target, sqlContextPopover: { sourceType: $parents[2].catalogEntry.getSourceType(), namespace: $parents[2].catalogEntry.namespace, path: targetPath, offset: { top: -3, left: 3 }}"></a></td>
+            <td><a href="javscript:void(0);" data-bind="text: target, sqlContextPopover: { sourceType: $parents[2].catalogEntry.getSourceType(), namespace: $parents[2].catalogEntry.namespace, compute: parents[2].catalogEntry.compute, path: targetPath, offset: { top: -3, left: 3 }}"></a></td>
             <td class="metastore-join-arrow"><i class="fa fa-arrows-h"></i></td>
-            <td><a href="javscript:void(0);" data-bind="text: source, sqlContextPopover: { sourceType: $parents[2].catalogEntry.getSourceType(), namespace: $parents[2].catalogEntry.namespace, path: sourcePath, offset: { top: -3, left: 3 }}"></a></td>
+            <td><a href="javscript:void(0);" data-bind="text: source, sqlContextPopover: { sourceType: $parents[2].catalogEntry.getSourceType(), namespace: $parents[2].catalogEntry.namespace, compute: parents[2].catalogEntry.compute, path: sourcePath, offset: { top: -3, left: 3 }}"></a></td>
           </tr>
           </tbody>
         </table>
@@ -1253,7 +1253,7 @@ ${ components.menubar(is_embeddable) }
       ko.applyBindings(viewModel, $('#metastoreComponents')[0]);
 
       if (location.getParameter('refresh') === 'true') {
-        DataCatalog.getEntry({ namespace: viewModel.source().namespace().namespace, sourceType: viewModel.source().type, path: [], definition: { type: 'source' }}).done(function (entry) {
+        DataCatalog.getEntry({ namespace: viewModel.source().namespace().namespace, compute: viewModel.source().namespace().compute, sourceType: viewModel.source().type, path: [], definition: { type: 'source' }}).done(function (entry) {
           entry.clearCache({ invalidate: viewMode.source().type === 'impala' ? 'invalidate' : 'cache', silenceErrors: true });
           hueUtils.replaceURL('?');
         });

+ 2 - 2
apps/pig/src/pig/templates/app.mako

@@ -1021,8 +1021,8 @@ ${ commonshare() | n,unicode }
         user: '${ user }'
       });
       ContextCatalog.getNamespaces({ sourceType: 'hive' }).done(function (context) {
-        // TODO: Namespace selection
-        DataCatalog.getChildren({ namespace: context.namespaces[0], sourceType: 'hive', path: ['default'], silenceErrors: true }).done(function (childEntries) {
+        // TODO: Namespace and compute selection
+        DataCatalog.getChildren({ namespace: context.namespaces[0], compute: context.namespaces[0].computes[0], sourceType: 'hive', path: ['default'], silenceErrors: true }).done(function (childEntries) {
           availableTables = $.map(childEntries, function (entry) { return entry.name }).join(' ');
         });
       });

+ 5 - 5
desktop/core/src/desktop/static/desktop/js/apiHelper.js

@@ -1273,7 +1273,7 @@ var ApiHelper = (function () {
   /**
    * @param {Object} options
    * @param {string} options.sourceType
-   * @param {ContextNamespace} options.namespace
+   * @param {ContextCompute} options.compute
    * @param {boolean} [options.silenceErrors]
    * @param {number} [options.timeout]
    *
@@ -1297,7 +1297,7 @@ var ApiHelper = (function () {
           type: sourceType,
           source: isQuery ? 'query' : 'data',
         }),
-        cluster: '"' + options.namespace.id + '"'
+        cluster: '"' + options.compute.id + '"'
       },
       timeout: options.timeout
     }).success(function (data) {
@@ -1369,7 +1369,7 @@ var ApiHelper = (function () {
    *
    * @param {Object} options
    * @param {boolean} [options.silenceErrors]
-   * @param {ContextNamespace} [options.namespace]
+   * @param {ContextCompute} [options.compute]
    *
    * @param {string[]} options.path
    *
@@ -1399,8 +1399,8 @@ var ApiHelper = (function () {
       'format' : 'json'
     }
 
-    if (options.namespace && options.namespace.id) {
-      params['cluster'] = options.namespace.id;
+    if (options.compute && options.compute.id) {
+      params['cluster'] = options.compute.id;
     }
 
     var request = self.simpleGet(url, params, {

+ 20 - 2
desktop/core/src/desktop/static/desktop/js/assist/assistDbSource.js

@@ -20,6 +20,7 @@ var AssistDbSource = (function () {
    * @param {Object} options.i18n
    * @param {string} options.type
    * @param {ContextNamespace} [options.initialNamespace] - Optional initial namespace to use
+   * @param {ContextCompute} [options.initialCompute] - Optional initial compute to use
    * @param {string} options.name
    * @param {Object} options.navigationSettings
    * @constructor
@@ -31,7 +32,8 @@ var AssistDbSource = (function () {
     self.name = options.name;
     self.i18n = options.i18n;
     self.navigationSettings = options.navigationSettings;
-    self.initialNamespace = options.activeNamespace;
+    self.initialNamespace = options.initialNamespace;
+    self.initialCompute = options.initialCompute
 
     self.selectedNamespace = ko.observable();
     self.namespaces = ko.observableArray();
@@ -121,6 +123,7 @@ var AssistDbSource = (function () {
     ContextCatalog.getNamespaces({ sourceType: self.sourceType }).done(function (context) {
       var assistNamespaces = [];
       var activeNamespace;
+      var activeCompute;
       self.namespaceRefreshEnabled(context.dynamic);
       context.namespaces.forEach(function (namespace) {
         var assistNamespace = new AssistDbNamespace({
@@ -132,6 +135,13 @@ var AssistDbSource = (function () {
 
         if (self.initialNamespace && namespace.id === self.initialNamespace.id) {
           activeNamespace = assistNamespace;
+          if (self.initialCompute) {
+            activeNamespace.computes.some(function (compute) {
+              if (compute.id === self.initialCompute.id) {
+                activeCompute = compute;
+              }
+            })
+          }
         }
         assistNamespaces.push(assistNamespace);
       });
@@ -141,6 +151,9 @@ var AssistDbSource = (function () {
       } else if (assistNamespaces.length) {
         self.selectedNamespace(assistNamespaces[0]);
       }
+      if (activeCompute) {
+        self.selectedNamespace().compute(activeCompute);
+      }
     }).fail(function () {
       self.hasErrors(true);
     }).always(function () {
@@ -182,6 +195,11 @@ var AssistDbNamespace = (function () {
     self.sourceType = options.sourceType;
 
     self.namespace = options.namespace;
+    // TODO: Compute selection in assist?
+    self.compute = ko.observable();
+    if (self.namespace.computes.length) {
+      self.compute(self.namespace.computes[0]);
+    }
     self.name = options.namespace.name;
 
     self.catalogEntry;
@@ -313,7 +331,7 @@ var AssistDbNamespace = (function () {
       self.selectedDatabase(null);
       self.databases([]);
 
-      DataCatalog.getEntry({ sourceType: self.sourceType, namespace: self.namespace, path : [], definition: { type: 'source' } }).done(function (catalogEntry) {
+      DataCatalog.getEntry({ sourceType: self.sourceType, namespace: self.namespace, compute: self.compute(), path : [], definition: { type: 'source' } }).done(function (catalogEntry) {
         self.catalogEntry = catalogEntry;
         self.catalogEntry.getChildren({ silenceErrors: self.navigationSettings.rightAssist }).done(function (databaseEntries) {
           self.dbIndex = {};

+ 7 - 0
desktop/core/src/desktop/static/desktop/js/contextCatalog.js

@@ -14,10 +14,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+/**
+ * @typedef {Object} ContextCompute
+ * @property {string} id
+ * @property {string} name
+ */
+
 /**
  * @typedef {Object} ContextNamespace
  * @property {string} id
  * @property {string} name
+ * @property {ContextCompute} computes
  */
 
 var ContextCatalog = (function () {

+ 36 - 23
desktop/core/src/desktop/static/desktop/js/dataCatalog.js

@@ -18,7 +18,7 @@ var DataCatalog = (function () {
 
   var STORAGE_POSTFIX = LOGGED_USERNAME;
 
-  var DATA_CATALOG_VERSION = 4;
+  var DATA_CATALOG_VERSION = 5;
 
   var cacheEnabled = true;
 
@@ -66,7 +66,7 @@ var DataCatalog = (function () {
   var fetchAndSave = function (apiHelperFunction, attributeName, entry, apiOptions) {
     return ApiHelper.getInstance()[apiHelperFunction]({
       sourceType: entry.dataCatalog.sourceType,
-      namespace: entry.namespace,
+      compute: entry.compute,
       path: entry.path, // Set for DataCatalogEntry
       paths: entry.paths, // Set for MultiTableEntry
       silenceErrors: apiOptions && apiOptions.silenceErrors,
@@ -124,12 +124,13 @@ var DataCatalog = (function () {
      * Clears the data catalog and cache for the given path and any children thereof.
      *
      * @param {ContextNamespace} [namespace] - The context namespace
+     * @param {ContextCompute} [compute] - The context compute
      * @param {string[]} rootPath - The path to clear
      */
-    DataCatalog.prototype.clearStorageCascade = function (namespace, rootPath) {
+    DataCatalog.prototype.clearStorageCascade = function (namespace, compute, rootPath) {
       var self = this;
       var deferred = $.Deferred();
-      if (!namespace) {
+      if (!namespace || !compute) {
         if (rootPath.length === 0) {
           self.entries = {};
           self.store.clear().then(deferred.resolve).catch(deferred.reject);
@@ -138,7 +139,7 @@ var DataCatalog = (function () {
         return deferred.reject().promise();
       }
 
-      var keyPrefix = namespace.id;
+      var keyPrefix = namespace.id + '_' + compute.id;
       if (rootPath.length) {
         keyPrefix += '_' +  rootPath.join('.');
       }
@@ -178,7 +179,7 @@ var DataCatalog = (function () {
       }
       var deferred = $.Deferred();
 
-      var identifier = dataCatalogEntry.namespace.id;
+      var identifier = dataCatalogEntry.namespace.id + '_' + dataCatalogEntry.compute.id;
       if (dataCatalogEntry.path.length) {
         identifier += '_' + dataCatalogEntry.path.join('.');
       }
@@ -203,6 +204,7 @@ var DataCatalog = (function () {
      *
      * @param {Object} options
      * @param {ContextNamespace} options.namespace - The context namespace
+     * @param {ContextCompute} options.compute - The context compute
      * @param {string[][]} options.paths
      * @param {boolean} [options.silenceErrors] - Default true
      * @param {boolean} [options.cancellable] - Default false
@@ -221,7 +223,7 @@ var DataCatalog = (function () {
       var existingPromises = [];
       options.paths.forEach(function (path) {
         var existingDeferred = $.Deferred();
-        self.getEntry({ namespace: options.namespace, path: path }).done(function (tableEntry) {
+        self.getEntry({ namespace: options.namespace, compute: options.compute, path: path }).done(function (tableEntry) {
           if (tableEntry.navOptPopularityForChildrenPromise) {
             tableEntry.navOptPopularityForChildrenPromise.done(function (existingPopularEntries) {
               popularEntries = popularEntries.concat(existingPopularEntries);
@@ -281,7 +283,7 @@ var DataCatalog = (function () {
 
             Object.keys(perTable).forEach(function (path) {
               var tableDeferred = $.Deferred();
-              self.getEntry({ namespace: options.namespace, path: path }).done(function (entry) {
+              self.getEntry({ namespace: options.namespace, compute: options.compute, path: path }).done(function (entry) {
                 cancellablePromises.push(entry.trackedPromise('navOptPopularityForChildrenPromise', entry.applyNavOptResponseToChildren(perTable[path], options).done(function (entries) {
                   popularEntries = popularEntries.concat(entries);
                   tableDeferred.resolve();
@@ -336,13 +338,14 @@ var DataCatalog = (function () {
     /**
      * @param {Object} options
      * @param {ContextNamespace} options.namespace - The context namespace
+     * @param {ContextCompute} options.compute - The context compute
      * @param {string|string[]} options.path
      * @return {DataCatalogEntry}
      */
     DataCatalog.prototype.getKnownEntry = function (options) {
       var self = this;
       var identifier = typeof options.path === 'string' ? options.path : options.path.join('.');
-      identifier = options.namespace.id + (identifier ? '_' + identifier : '');
+      identifier = options.namespace.id + '_' + options.compute.id + (identifier ? '_' + identifier : '');
       return self.entries[identifier];
     };
 
@@ -350,6 +353,7 @@ var DataCatalog = (function () {
      * @param {Object} options
      * @param {string|string[]} options.path
      * @param {ContextNamespace} options.namespace - The context namespace
+     * @param {ContextCompute} options.compute - The context compute
      * @param {Object} [options.definition] - The initial definition if not already set on the entry
      * @param {boolean} [options.cachedOnly] - Default: false
      * @return {Promise}
@@ -357,7 +361,7 @@ var DataCatalog = (function () {
     DataCatalog.prototype.getEntry = function (options) {
       var self = this;
       var identifier = typeof options.path === 'string' ? options.path : options.path.join('.');
-      identifier = options.namespace.id + (identifier ? '_' + identifier : '');
+      identifier = options.namespace.id + '_' + options.compute.id + (identifier ? '_' + identifier : '');
       if (self.entries[identifier]) {
         return self.entries[identifier];
       }
@@ -366,11 +370,11 @@ var DataCatalog = (function () {
       self.entries[identifier] = deferred.promise();
 
       if (!cacheEnabled) {
-        deferred.resolve(new DataCatalogEntry({ dataCatalog: self, namespace: options.namespace, path: options.path, definition: options.definition })).promise();
+        deferred.resolve(new DataCatalogEntry({ dataCatalog: self, namespace: options.namespace, compute: options.compute, path: options.path, definition: options.definition })).promise();
       } else {
         self.store.getItem(identifier).then(function (storeEntry) {
           var definition = storeEntry ? storeEntry.definition : options.definition;
-          var entry = new DataCatalogEntry({ dataCatalog: self, namespace: options.namespace, path: options.path, definition: definition });
+          var entry = new DataCatalogEntry({ dataCatalog: self, namespace: options.namespace, compute: options.compute, path: options.path, definition: definition });
           if (storeEntry) {
             mergeEntry(entry, storeEntry);
           } else if (!options.cachedOnly && options.definition) {
@@ -379,7 +383,7 @@ var DataCatalog = (function () {
           deferred.resolve(entry);
         }).catch(function (error) {
           console.warn(error);
-          var entry = new DataCatalogEntry({ dataCatalog: self, namespace: options.namespace, path: options.path, definition: options.definition });
+          var entry = new DataCatalogEntry({ dataCatalog: self, namespace: options.namespace, compute: options.compute, path: options.path, definition: options.definition });
           if (!options.cachedOnly && options.definition) {
             entry.saveLater();
           }
@@ -415,31 +419,34 @@ var DataCatalog = (function () {
     /**
      * Creates an identifier for the given paths with duplicates removed
      *
+     * @oaram {Object} options
      * @param {ContextNamespace} options.namespace - The context namespace
-     * @param {string[][]} paths
+     * @param {ContextCompute} options.compute - The context compute
+     * @param {string[][]} options.paths
      * @return {string}
      */
-    var createMultiTableIdentifier = function (namespace, paths) {
+    var createMultiTableIdentifier = function (options) {
       var pathSet = {};
-      paths.forEach(function (path) {
+      options.paths.forEach(function (path) {
         pathSet[path.join('.')] = true;
       });
       var uniquePaths = Object.keys(pathSet);
       uniquePaths.sort();
-      return namespace.id + '_' + uniquePaths.join(',');
+      return options.namespace.id + '_' + options.compute.id + '_' + uniquePaths.join(',');
     };
 
     /**
      *
      * @param {Object} options
      * @param {ContextNamespace} options.namespace - The context namespace
+     * @param {ContextCompute} options.compute - The context compute
      * @param {string[][]} options.paths
      *
      * @return {Promise}
      */
     DataCatalog.prototype.getMultiTableEntry = function (options) {
       var self = this;
-      var identifier = createMultiTableIdentifier(options.namespace, options.paths);
+      var identifier = createMultiTableIdentifier(options);
       if (self.multiTableEntries[identifier]) {
         return self.multiTableEntries[identifier];
       }
@@ -597,6 +604,7 @@ var DataCatalog = (function () {
      * @param {DataCatalog} options.dataCatalog
      * @param {string|string[]} options.path
      * @param {ContextNamespace} options.namespace - The context namespace
+     * @param {ContextCompute} options.compute - The context compute
      * @param {Object} options.definition - Initial known metadata on creation (normally comes from the parent entry)
      *
      * @constructor
@@ -605,6 +613,7 @@ var DataCatalog = (function () {
       var self = this;
 
       self.namespace = options.namespace;
+      self.compute = options.compute;
       self.dataCatalog = options.dataCatalog;
       self.path = typeof options.path === 'string' && options.path ? options.path.split('.') : options.path || [];
       self.name = self.path.length ? self.path[self.path.length - 1] : options.dataCatalog.sourceType;
@@ -655,7 +664,7 @@ var DataCatalog = (function () {
       self.childrenPromise = undefined;
       
       if (self.path.length) {
-        var parent = self.dataCatalog.getKnownEntry({ namespace: self.namespace, path: self.path.slice(0, self.path.length - 1) });
+        var parent = self.dataCatalog.getKnownEntry({ namespace: self.namespace, compute: self.compute, path: self.path.slice(0, self.path.length - 1) });
         if (parent) {
           parent.navigatorMetaForChildrenPromise = undefined;
           parent.navOptPopularityForChildrenPromise = undefined;
@@ -722,7 +731,7 @@ var DataCatalog = (function () {
       }
 
       self.reset();
-      var saveDeferred = options.cascade ? self.dataCatalog.clearStorageCascade(self.namespace, self.path) : self.save();
+      var saveDeferred = options.cascade ? self.dataCatalog.clearStorageCascade(self.namespace, self.compute, self.path) : self.save();
 
       var clearPromise = $.when(invalidatePromise, saveDeferred);
 
@@ -801,6 +810,7 @@ var DataCatalog = (function () {
             if (!sourceMeta.databases || ((entity.name || entity) !== '_impala_builtins')) {
               promises.push(self.dataCatalog.getEntry({
                 namespace: self.namespace,
+                compute: self.compute,
                 path: self.path.concat(entity.name || entity)
               }).done(function (catalogEntry) {
                 if (!catalogEntry.definition || typeof catalogEntry.definition.index === 'undefined') {
@@ -828,7 +838,7 @@ var DataCatalog = (function () {
         if ((self.getSourceType() === 'impala' || self.getSourceType() === 'hive') && self.isComplex()) {
           (sourceMeta.type === 'map' ? ['key', 'value'] : ['item']).forEach(function (path) {
             if (sourceMeta[path]) {
-              promises.push(self.dataCatalog.getEntry({ namespace: self.namespace, path: self.path.concat(path) }).done(function (catalogEntry) {
+              promises.push(self.dataCatalog.getEntry({ namespace: self.namespace, compute: self.compute, path: self.path.concat(path) }).done(function (catalogEntry) {
                 if (!catalogEntry.definition || typeof catalogEntry.definition.index === 'undefined') {
                   var definition = sourceMeta[path];
                   definition.index = index++;
@@ -1741,7 +1751,7 @@ var DataCatalog = (function () {
           }
         };
 
-        self.dataCatalog.getEntry({ namespace: self.namespace, path: self.path.slice(0, 2), definition: { type: 'table' } }).done(function (tableEntry) {
+        self.dataCatalog.getEntry({ namespace: self.namespace, compute: self.compute, path: self.path.slice(0, 2), definition: { type: 'table' } }).done(function (tableEntry) {
           if (tableEntry && tableEntry.samplePromise) {
             cancellablePromises.push(applyCancellable(tableEntry.samplePromise, options));
 
@@ -1806,7 +1816,7 @@ var DataCatalog = (function () {
         return deferred.reject();
       }
       var cancellablePromises = [];
-      catalogEntry.dataCatalog.getMultiTableEntry({ namespace: catalogEntry.namespace, paths: [ catalogEntry.path ] }).done(function (multiTableEntry) {
+      catalogEntry.dataCatalog.getMultiTableEntry({ namespace: catalogEntry.namespace, compute: catalogEntry.compute, paths: [ catalogEntry.path ] }).done(function (multiTableEntry) {
         cancellablePromises.push(multiTableEntry[functionName](options).done(deferred.resolve).fail(deferred.reject));
       }).fail(deferred.reject);
       return new CancellablePromise(deferred, undefined, cancellablePromises);
@@ -2153,6 +2163,7 @@ var DataCatalog = (function () {
        * @param {Object} options
        * @param {string} options.sourceType
        * @param {ContextNamespace} options.namespace - The context namespace
+       * @param {ContextCompute} options.compute - The context compute
        * @param {string|string[]} options.path
        * @param {Object} [options.definition] - Optional initial definition
        *
@@ -2166,6 +2177,7 @@ var DataCatalog = (function () {
        * @param {Object} options
        * @param {string} options.sourceType
        * @param {ContextNamespace} options.namespace - The context namespace
+       * @param {ContextCompute} options.compute - The context compute
        * @param {string[][]} options.paths
        *
        * @return {Promise}
@@ -2181,6 +2193,7 @@ var DataCatalog = (function () {
        * @param {Object} options
        * @param {string} options.sourceType
        * @param {ContextNamespace} options.namespace - The context namespace
+       * @param {ContextCompute} options.compute - The context compute
        * @param {string|string[]} options.path
        * @param {Object} [options.definition] - Optional initial definition of the parent entry
        * @param {boolean} [options.silenceErrors]

+ 6 - 3
desktop/core/src/desktop/static/desktop/js/jquery.hiveautocomplete.js

@@ -242,7 +242,8 @@
     self.getDatabases = function (callback) {
       var self = this;
       self.activeContextNamespaceDeferred.done(function (namespace) {
-        DataCatalog.getChildren({ sourceType: self.options.apiHelperType, namespace: namespace, path: [] }).done(function (dbEntries) {
+        // TODO: compute selection?
+        DataCatalog.getChildren({ sourceType: self.options.apiHelperType, namespace: namespace, compute: namespace.computes[0], path: [] }).done(function (dbEntries) {
           callback($.map(dbEntries, function (entry) { return entry.name }));
         });
       })
@@ -251,7 +252,8 @@
     self.getTables = function (database, callback) {
       var self = this;
       self.activeContextNamespaceDeferred.done(function (namespace) {
-        DataCatalog.getEntry({ sourceType: self.options.apiHelperType, namespace: namespace, path: [ database ] }).done(function (entry) {
+        // TODO: compute selection?
+        DataCatalog.getEntry({ sourceType: self.options.apiHelperType, namespace: namespace, compute: namespace.computes[0], path: [ database ] }).done(function (entry) {
           entry.getSourceMeta().done(callback)
         });
       });
@@ -260,7 +262,8 @@
     self.getColumns = function (database, table, callback) {
       var self = this;
       self.activeContextNamespaceDeferred.done(function (namespace) {
-        DataCatalog.getEntry({sourceType: self.options.apiHelperType, namespace: namespace, path: [ database, table ]}).done(function (entry) {
+        // TODO: compute selection?
+        DataCatalog.getEntry({sourceType: self.options.apiHelperType, namespace: namespace, compute: namespace.computes[0], path: [ database, table ]}).done(function (entry) {
           entry.getSourceMeta().done(callback)
         });
       });

+ 10 - 3
desktop/core/src/desktop/static/desktop/js/ko.hue-bindings.js

@@ -2487,6 +2487,7 @@
    *
    * {string} sourceType - 'impala', 'hive' etc.
    * {ContextNamespace} namespace
+   * {ContextCompute} compute
    * {string} path - the path, i.e. 'default.customers' or ['default', 'customers'
    * {string} [orientation] - 'top', 'right', 'bottom', 'left'. Default 'right'
    * {Object} [offset] - Optional offset from the element
@@ -2495,8 +2496,8 @@
    *
    * Examples:
    *
-   * data-bind="sqlContextPopover: { sourceType: 'impala', namespace: { id: 'myNamespace' }, path: 'default.customers' }"
-   * data-bind="sqlContextPopover: { sourceType: 'hive', namespace: { id: 'myNamespace' }, path: 'default', orientation: 'bottom', offset: { top: 5 } }"
+   * data-bind="sqlContextPopover: { sourceType: 'impala', namespace: { id: 'myNamespace' }, compute: { id: 'myCompute' }, path: 'default.customers' }"
+   * data-bind="sqlContextPopover: { sourceType: 'hive', namespace: { id: 'myNamespace' }, compute: { id: 'myCompute' }, path: 'default', orientation: 'bottom', offset: { top: 5 } }"
    *
    * @type {{init: ko.bindingHandlers.sqlContextPopover.init}}
    */
@@ -2505,7 +2506,7 @@
       ko.bindingHandlers.click.init(element, function () {
         return function () {
           var options = valueAccessor();
-          DataCatalog.getEntry({ sourceType: options.sourceType, namespace: options.namespace, path: options.path }).done(function (entry) {
+          DataCatalog.getEntry(options).done(function (entry) {
             var $source = $(element);
             var offset = $source.offset();
             if (options.offset) {
@@ -4371,6 +4372,7 @@
       DataCatalog.getChildren({
         sourceType: self.snippet.type(),
         namespace: self.snippet.namespace(),
+        compute: self.snippet.compute(),
         path: $.map(identifierChain, function (identifier) { return identifier.name }),
         silenceErrors: true,
         cachedOnly: true
@@ -4452,6 +4454,7 @@
               DataCatalog.getChildren({
                 sourceType: self.snippet.type(),
                 namespace: self.snippet.namespace(),
+                compute: self.snippet.compute(),
                 path: $.map(nextTable.identifierChain, function (identifier) { return identifier.name }),
                 cachedOnly: true,
                 silenceErrors: true
@@ -4636,6 +4639,7 @@
           id: self.editorId,
           type: self.snippet.type(),
           namespace: self.snippet.namespace(),
+          compute: self.snippet.compute(),
           defaultDatabase: self.snippet.database(),
           locations: e.data.locations,
           editorChangeTime: e.data.editorChangeTime,
@@ -4740,6 +4744,7 @@
             statementDetails: statementDetails,
             type: self.snippet.type(),
             namespace: self.snippet.namespace(),
+            compute: self.snippet.compute(),
             defaultDatabase: self.snippet.database()
           });
         }
@@ -5153,6 +5158,7 @@
                         DataCatalog.getEntry({
                           sourceType: snippet.type(),
                           namespace: snippet.namespace(),
+                          compute: snippet.compute(),
                           path: $.map(tableChain, function (identifier) { return identifier.name })
                         }).done(function (entry) {
                           entry.getSourceMeta({ cachedOnly: true, silenceErrors: true }).done(function (sourceMeta) {
@@ -5308,6 +5314,7 @@
                     data: token.parseLocation,
                     sourceType: snippet.type(),
                     namespace: snippet.namespace(),
+                    compute: snippet.compute(),
                     defaultDatabase: snippet.database(),
                     pinEnabled: true,
                     source: source

+ 13 - 10
desktop/core/src/desktop/static/desktop/js/sqlAutocompleter2.js

@@ -148,7 +148,7 @@ var SqlAutocompleter2 = (function () {
 
       var paths = self.tableIdentifierChainsToPaths(parseResult.suggestJoins.tables, database);
       if (paths.length) {
-        DataCatalog.getMultiTableEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), paths: paths }).done(function (multiTableEntry) {
+        DataCatalog.getMultiTableEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), compute: self.snippet.compute(), paths: paths }).done(function (multiTableEntry) {
           multiTableEntry.getTopJoins({ silenceErrors: true }).done(function (topJoins) {
             if (topJoins.values) {
               topJoins.values.forEach(function (value) {
@@ -210,7 +210,7 @@ var SqlAutocompleter2 = (function () {
 
       var paths = self.tableIdentifierChainsToPaths(parseResult.suggestJoinConditions.tables, database);
       if (paths.length) {
-        DataCatalog.getMultiTableEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), paths: paths }).done(function (multiTableEntry) {
+        DataCatalog.getMultiTableEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), compute: self.snippet.compute(), paths: paths }).done(function (multiTableEntry) {
           multiTableEntry.getTopJoins({ silenceErrors: true }).done(function (topJoins) {
             if (topJoins.values) {
               topJoins.values.forEach(function (value) {
@@ -263,7 +263,7 @@ var SqlAutocompleter2 = (function () {
 
         var paths = self.tableIdentifierChainsToPaths(parseResult.suggestAggregateFunctions.tables, database);
         if (paths.length) {
-          DataCatalog.getMultiTableEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), paths: paths }).done(function (multiTableEntry) {
+          DataCatalog.getMultiTableEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), compute: self.snippet.compute(), paths: paths }).done(function (multiTableEntry) {
             multiTableEntry.getTopAggs({ silenceErrors: true }).done(function (topAggs) {
               if (topAggs.values.length > 0) {
 
@@ -397,7 +397,7 @@ var SqlAutocompleter2 = (function () {
 
       var paths = self.tableIdentifierChainsToPaths(parseResult.suggestFilters.tables, database);
       if (paths.length) {
-        DataCatalog.getMultiTableEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), paths: paths }).done(function (multiTableEntry) {
+        DataCatalog.getMultiTableEntry({ sourceType: self.snippet.type(), compute: self.snippet.compute(), namespace: self.snippet.namespace(), paths: paths }).done(function (multiTableEntry) {
           multiTableEntry.getTopFilters({ silenceErrors: true }).done(function (topFilters) {
             if (topFilters.values) {
               topFilters.values.forEach(function (value) {
@@ -442,7 +442,7 @@ var SqlAutocompleter2 = (function () {
 
       var paths = self.tableIdentifierChainsToPaths(tables, database);
       if (paths.length) {
-        DataCatalog.getMultiTableEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), paths: paths }).done(function (multiTableEntry) {
+        DataCatalog.getMultiTableEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), compute: self.snippet.compute(), paths: paths }).done(function (multiTableEntry) {
           multiTableEntry.getTopColumns({ silenceErrors: true }).done(function (topColumns) {
             if (topColumns.values && parseResult.suggestGroupBys && typeof topColumns.values.groupbyColumns !== 'undefined') {
               var prefix = parseResult.suggestGroupBys.prefix ? (parseResult.lowerCase ? parseResult.suggestGroupBys.prefix.toLowerCase() : parseResult.suggestGroupBys.prefix) + ' ' : '';
@@ -485,7 +485,7 @@ var SqlAutocompleter2 = (function () {
 
       $.when(topColumnsDeferral, suggestColumnsDeferral).then(function (topColumns, suggestions) {
         if (topColumns.length > 0) {
-          DataCatalog.getChildren({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), path: [], silenceErrors: true }).done(function (dbEntries) {
+          DataCatalog.getChildren({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), compute: self.snippet.compute(), path: [], silenceErrors: true }).done(function (dbEntries) {
             var databases = $.map(dbEntries, function (dbEntry) { return dbEntry.name });
             suggestions.forEach(function (suggestion) {
               var path = '';
@@ -535,7 +535,7 @@ var SqlAutocompleter2 = (function () {
       if (HAS_OPTIMIZER && typeof parseResult.suggestColumns.source !== 'undefined') {
         var paths = self.tableIdentifierChainsToPaths(parseResult.suggestColumns.tables, database);
         if (paths.length) {
-          DataCatalog.getMultiTableEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), paths: paths }).done(function (multiTableEntry) {
+          DataCatalog.getMultiTableEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), compute: self.snippet.compute(), paths: paths }).done(function (multiTableEntry) {
             multiTableEntry.getTopColumns({ silenceErrors: true }).done(function (topColumns) {
               var values = [];
               if (topColumns.values) {
@@ -584,7 +584,7 @@ var SqlAutocompleter2 = (function () {
         var topTablesDeferral = $.Deferred();
         deferrals.push(topTablesDeferral);
 
-        DataCatalog.getCatalog(self.snippet.type()).loadNavOptPopularityForTables({ paths: [[database]], namespace: self.snippet.namespace(), silenceErrors: true }).done(function (popularTables) {
+        DataCatalog.getCatalog(self.snippet.type()).loadNavOptPopularityForTables({ paths: [[database]], namespace: self.snippet.namespace(), compute: self.snippet.compute(), silenceErrors: true }).done(function (popularTables) {
           var popularityIndex = {};
           popularTables.forEach(function (popularTable) {
             if (popularTable.navOptPopularity) {
@@ -614,6 +614,7 @@ var SqlAutocompleter2 = (function () {
         DataCatalog.getChildren({
           sourceType: self.snippet.type(),
           namespace: self.snippet.namespace(),
+          compute: self.snippet.compute(),
           path: [],
           silenceErrors: true
         }).done(function (dbEntries) {
@@ -803,7 +804,7 @@ var SqlAutocompleter2 = (function () {
         identifierChain = identifierChain.slice(1);
       }
 
-      DataCatalog.getEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), path: [database, table].concat(fetchedFields) }).done(function (entry) {
+      DataCatalog.getEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), compute: self.snippet.compute(), path: [database, table].concat(fetchedFields) }).done(function (entry) {
         entry.getSourceMeta({ silenceErrors: true }).done(function (sourceMeta) {
           if (self.snippet.type() === 'hive'
             && typeof sourceMeta.extended_columns !== 'undefined'
@@ -842,6 +843,7 @@ var SqlAutocompleter2 = (function () {
         DataCatalog.getChildren({
           sourceType: self.snippet.type(),
           namespace: self.snippet.namespace(),
+          compute: self.snippet.compute(),
           path: [],
           silenceErrors: true
         }).done(function (dbEntries) {
@@ -878,7 +880,7 @@ var SqlAutocompleter2 = (function () {
         prefix += parseResult.lowerCase ? 'from ' : 'FROM ';
       }
 
-      DataCatalog.getChildren({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), path: [databaseName], silenceErrors: true }).done(function (tableEntries) {
+      DataCatalog.getChildren({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), compute: self.snippet.compute(), path: [databaseName], silenceErrors: true }).done(function (tableEntries) {
         var tables = [];
         tableEntries.forEach(function (tableEntry) {
           if (parseResult.suggestTables.onlyTables && tableEntry.isTable() ||
@@ -1050,6 +1052,7 @@ var SqlAutocompleter2 = (function () {
     DataCatalog.getChildren({
       sourceType: self.snippet.type(),
       namespace: self.snippet.namespace(),
+      compute: self.snippet.compute(),
       path: [],
       silenceErrors: true
     }).done(function (dbEntries) {

+ 11 - 10
desktop/core/src/desktop/static/desktop/js/sqlAutocompleter3.js

@@ -326,7 +326,7 @@ var AutocompleteResults = (function () {
   AutocompleteResults.prototype.loadDatabases = function () {
     var self = this;
     var databasesDeferred = $.Deferred();
-    DataCatalog.getEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), path: [] }).done(function (entry) {
+    DataCatalog.getEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), compute: self.snippet.compute(), path: [] }).done(function (entry) {
       self.cancellablePromises.push(entry.getChildren({ silenceErrors: true, cancellable: true }).done(function (databases) {
         databasesDeferred.resolve(databases);
       }).fail(databasesDeferred.reject));
@@ -544,7 +544,7 @@ var AutocompleteResults = (function () {
 
         var database = suggestTables.identifierChain && suggestTables.identifierChain.length === 1 ? suggestTables.identifierChain[0].name : self.activeDatabase;
 
-        DataCatalog.getEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), path: [ database ]}).done(function (dbEntry) {
+        DataCatalog.getEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), compute: self.snippet.compute(), path: [ database ]}).done(function (dbEntry) {
           self.cancellablePromises.push(dbEntry.getChildren({ silenceErrors: true, cancellable: true }).done(function (tableEntries) {
             var tableSuggestions = [];
 
@@ -984,7 +984,7 @@ var AutocompleteResults = (function () {
 
       var paths = self.tableIdentifierChainsToPaths(suggestJoins.tables);
       if (paths.length) {
-        DataCatalog.getMultiTableEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), paths: paths }).done(function (multiTableEntry) {
+        DataCatalog.getMultiTableEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), compute: self.snippet.compute(), paths: paths }).done(function (multiTableEntry) {
         self.cancellablePromises.push(multiTableEntry.getTopJoins({ silenceErrors: true, cancellable: true  }).done(function (topJoins) {
           var joinSuggestions = [];
           var totalCount = 0;
@@ -1065,7 +1065,7 @@ var AutocompleteResults = (function () {
 
       var paths = self.tableIdentifierChainsToPaths(suggestJoinConditions.tables);
       if (paths.length) {
-        DataCatalog.getMultiTableEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), paths: paths }).done(function (multiTableEntry) {
+        DataCatalog.getMultiTableEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), compute: self.snippet.compute(), paths: paths }).done(function (multiTableEntry) {
           self.cancellablePromises.push(multiTableEntry.getTopJoins({ silenceErrors: true, cancellable: true }).done(function (topJoins) {
           var joinConditionSuggestions = [];
           var totalCount = 0;
@@ -1121,7 +1121,7 @@ var AutocompleteResults = (function () {
 
       var paths = self.tableIdentifierChainsToPaths(suggestAggregateFunctions.tables);
       if (paths.length) {
-        DataCatalog.getMultiTableEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), paths: paths }).done(function (multiTableEntry) {
+        DataCatalog.getMultiTableEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), compute: self.snippet.compute(), paths: paths }).done(function (multiTableEntry) {
           self.cancellablePromises.push(multiTableEntry.getTopAggs({ silenceErrors: true, cancellable: true }).done(function (topAggs) {
             var aggregateFunctionsSuggestions = [];
             if (topAggs.values && topAggs.values.length > 0) {
@@ -1227,7 +1227,7 @@ var AutocompleteResults = (function () {
     });
 
     self.cancellablePromises.push(DataCatalog.getCatalog(self.snippet.type())
-      .loadNavOptPopularityForTables({ namespace: self.snippet.namespace(), paths: paths, silenceErrors: true, cancellable: true }).done(function (entries) {
+      .loadNavOptPopularityForTables({ namespace: self.snippet.namespace(), compute: self.snippet.compute(), paths: paths, silenceErrors: true, cancellable: true }).done(function (entries) {
         var totalColumnCount = 0;
         var matchedEntries = [];
         var prefix = suggestSpec.prefix ? (self.parseResult.lowerCase ? suggestSpec.prefix.toLowerCase() : suggestSpec.prefix) + ' ' : '';
@@ -1303,7 +1303,7 @@ var AutocompleteResults = (function () {
 
       var paths = self.tableIdentifierChainsToPaths(suggestFilters.tables);
       if (paths.length) {
-        DataCatalog.getMultiTableEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), paths: paths }).done(function (multiTableEntry) {
+        DataCatalog.getMultiTableEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), compute: self.snippet.compute(), paths: paths }).done(function (multiTableEntry) {
           self.cancellablePromises.push(multiTableEntry.getTopFilters({ silenceErrors: true, cancellable: true }).done(function (topFilters) {
             var filterSuggestions = [];
             var totalCount = 0;
@@ -1364,7 +1364,7 @@ var AutocompleteResults = (function () {
         && self.parseResult.suggestTables.identifierChain.length === 1
         && self.parseResult.suggestTables.identifierChain[0].name ? self.parseResult.suggestTables.identifierChain[0].name : self.activeDatabase;
 
-      DataCatalog.getEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), path: [ db ]}).done(function (entry) {
+      DataCatalog.getEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), compute: self.snippet.compute(), path: [ db ]}).done(function (entry) {
         self.cancellablePromises.push(entry.loadNavOptPopularityForChildren({ silenceErrors: true, cancellable: true }).done(function (childEntries) {
           var totalPopularity = 0;
           var popularityIndex = {};
@@ -1425,6 +1425,7 @@ var AutocompleteResults = (function () {
 
       self.cancellablePromises.push(DataCatalog.getCatalog(self.snippet.type()).loadNavOptPopularityForTables({
         namespace: self.snippet.namespace(),
+        compute: self.snippet.compute(),
         paths: paths,
         silenceErrors: true,
         cancellable: true
@@ -1586,7 +1587,7 @@ var AutocompleteResults = (function () {
         }
       }
 
-      DataCatalog.getEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), path: fetchedPath }).done(function (catalogEntry) {
+      DataCatalog.getEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), compute: self.snippet.compute(), path: fetchedPath }).done(function (catalogEntry) {
         self.cancellablePromises.push(catalogEntry.getSourceMeta({ silenceErrors: true, cancellable: true }).done(function (sourceMeta) {
           if (self.snippet.type() === 'hive'
               && typeof sourceMeta.extended_columns !== 'undefined'
@@ -1616,7 +1617,7 @@ var AutocompleteResults = (function () {
     // For Hive it could be either:
     // SELECT col.struct FROM db.tbl -or- SELECT col.struct FROM tbl
     if (path.length > 1 && (self.snippet.type() === 'impala' || self.snippet.type() === 'hive')) {
-      DataCatalog.getEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), path: [] }).done(function (catalogEntry) {
+      DataCatalog.getEntry({ sourceType: self.snippet.type(), namespace: self.snippet.namespace(), compute: self.snippet.compute(), path: [] }).done(function (catalogEntry) {
         self.cancellablePromises.push(catalogEntry.getChildren({ silenceErrors: true, cancellable: true }).done(function (databaseEntries) {
           var firstIsDb = databaseEntries.some(function (dbEntry) {
             return hueUtils.equalIgnoreCase(dbEntry.name, path[0]);

+ 3 - 0
desktop/core/src/desktop/static/desktop/js/sqlUtils.js

@@ -121,6 +121,7 @@ var SqlUtils = (function () {
    * @param {Object} options
    * @param {String} options.sourceType
    * @param {ContextNamespace} options.namespace
+   * @param {ContextCompute} options.compute
    * @param {Object[]} [options.identifierChain]
    * @param {Object[]} [options.tables]
    * @param {Object} [options.cancellable]
@@ -191,6 +192,7 @@ var SqlUtils = (function () {
       cancellablePromises.push(DataCatalog.getChildren({
         sourceType: options.sourceType,
         namespace: options.namespace,
+        compute: options.compute,
         path: SqlUtils.identifierChainToPath(nextTable.identifierChain),
         cachedOnly: options && options.cachedOnly,
         cancellable: options && options.cancellable,
@@ -220,6 +222,7 @@ var SqlUtils = (function () {
       DataCatalog.getEntry({
         sourceType: options.sourceType,
         namespace: options.namespace,
+        compute: options.compute,
         path: [],
         cachedOnly: options && options.cachedOnly,
         cancellable: options && options.cancellable,

+ 1 - 0
desktop/core/src/desktop/templates/ace_sql_location_worker.mako

@@ -102,6 +102,7 @@ importScripts(scriptPrefix + '${ static('desktop/js/sqlFunctions.js') }');
           id: msg.data.id,
           sourceType: msg.data.type,
           namespace: msg.data.namespace,
+          compute: msg.data.compute,
           editorChangeTime: msg.data.statementDetails.editorChangeTime,
           locations: locations,
           activeStatementLocations: activeStatementLocations,

+ 11 - 2
desktop/core/src/desktop/templates/assist.mako

@@ -869,7 +869,12 @@ from desktop.views import _ko
       <!-- /ko -->
       <ul class="assist-tables" data-bind="foreach: filteredNamespaces">
         <li class="assist-table">
+          <!-- ko if: namespace.computes.length -->
           <a class="assist-table-link" href="javascript: void(0);" data-bind="click: function () { $parent.selectedNamespace($data); }"><i class="fa fa-fw fa-snowflake-o muted valign-middle"></i> <span data-bind="text: name"></span></a>
+          <!-- /ko -->
+          <!-- ko ifnot: namespace.computes.length -->
+          <span class="assist-table-link" title="${_('No related computes')}" data-bind="tooltip: { placement: 'bottom' }"><i class="fa fa-fw fa-warning muted valign-middle"></i> <span data-bind="text: name"></span></span>
+          <!-- /ko -->
         </li>
       </ul>
     </div>
@@ -1219,7 +1224,7 @@ from desktop.views import _ko
         });
 
         huePubSub.subscribe('assist.collections.refresh', function() {
-          DataCatalog.getEntry({ sourceType: 'solr', namespace: self.sourceIndex['solr'].activeNamespace(), path: [] }).done(function (entry) {
+          DataCatalog.getEntry({ sourceType: 'solr', namespace: self.sourceIndex['solr'].activeNamespace(), compute: self.sourceIndex['solr'].activeCompute(), path: [] }).done(function (entry) {
             entry.clearCache({ cascade: true });
           });
         });
@@ -2687,6 +2692,7 @@ from desktop.views import _ko
                     DataCatalog.getEntry({
                       sourceType: activeLocations.type,
                       namespace: activeLocations.namespace,
+                      compute: activeLocations.compute,
                       path: [ database ],
                       definition: { type: 'database' }
                     }).done(function (catalogEntry) {
@@ -2742,7 +2748,7 @@ from desktop.views import _ko
                                   self.reloading(false)
                                 })
                               });
-                              DataCatalog.getEntry({ sourceType: activeLocations.type, namespace: activeLocations.namespace, path: [] }).done(function (sourceEntry) {
+                              DataCatalog.getEntry({ sourceType: activeLocations.type, namespace: activeLocations.namespace, compute: activeLocations.compute, path: [] }).done(function (sourceEntry) {
                                 sourceEntry.getChildren().done(function (dbEntries) {
                                   var clearPromise;
                                    // Clear the database first if it exists without cascade
@@ -3101,6 +3107,7 @@ from desktop.views import _ko
           var assistDbSource = new AssistDbSource({
             i18n : i18n,
             initialNamespace: collection.activeNamespace,
+            initialCompute: collection.activeCompute,
             type: collection.engine(),
             name: collection.engine(),
             navigationSettings: navigationSettings
@@ -3113,6 +3120,7 @@ from desktop.views import _ko
           DataCatalog.getEntry({
             sourceType: sourceType,
             namespace: collection.activeNamespace,
+            compute: collection.activeCompute,
             path: [ fakeParentName ],
             definition: { type: 'database' }
           }).done(function (fakeDbCatalogEntry) {
@@ -3120,6 +3128,7 @@ from desktop.views import _ko
             DataCatalog.getEntry({
               sourceType: sourceType,
               namespace: collection.activeNamespace,
+              compute: collection.activeCompute,
               path: [fakeParentName, collectionName.indexOf('.') > -1 ? collectionName.split('.')[1] : collectionName],
               definition: { type: 'table' }
             }).done(function (collectionCatalogEntry) {

+ 1 - 1
desktop/core/src/desktop/templates/common_dashboard.mako

@@ -232,7 +232,7 @@
                 <select data-bind="selectize: fieldOperations, optionsText: 'label', optionsValue: 'value', value: fieldOperation" class="input-small"></select>
                 <select data-bind="selectize: $root.collection.template.filteredModalFields().sort(function (l, r) { return l.name() > r.name() ? 1 : -1 }), value: fieldName, optionsValue: 'name', optionsText: 'name', optionsCaption: '${ _ko('Field...') }'" class="hit-options input-small" style="margin-bottom: 0"></select>
                 <!-- ko if: fieldName -->
-                <a class="inactive-action context-popover-icon" href="javascript:void(0);" data-bind="sqlContextPopover: { sourceType: 'solr', namespace: $root.collection.activeNamespace(), path: 'default.' + $root.collection.name() + '.' + fieldName()  }">
+                <a class="inactive-action context-popover-icon" href="javascript:void(0);" data-bind="sqlContextPopover: { sourceType: 'solr', namespace: $root.collection.activeNamespace(), compute: $root.collection.activeCompute(), path: 'default.' + $root.collection.name() + '.' + fieldName()  }">
                   <i class="fa fa-fw fa-info" title="${_('Show Details')}"/>
                 </a>
                 <!-- /ko -->

+ 10 - 7
desktop/core/src/desktop/templates/ko_components/ko_context_popover.mako

@@ -534,7 +534,7 @@ from metadata.conf import has_navigator
                 path: catalogEntry.path.slice(0, i + 1),
                 catalogEntry: self.catalogEntry,
                 makeActive: function () {
-                  self.catalogEntry().dataCatalog.getEntry({ namespace: self.catalogEntry().namespace, path: this.path }).done(self.catalogEntry);
+                  self.catalogEntry().dataCatalog.getEntry({ namespace: self.catalogEntry().namespace, compute: self.catalogEntry().compute, path: this.path }).done(self.catalogEntry);
                 }
               })
             }
@@ -639,7 +639,7 @@ from metadata.conf import has_navigator
         huePubSub.publish('global.search.close');
       };
 
-      function AsteriskData(data, sourceType, namespace, defaultDatabase) {
+      function AsteriskData(data, sourceType, namespace, compute, defaultDatabase) {
         var self = this;
         self.loading = ko.observable(true);
         self.hasErrors = ko.observable(false);
@@ -702,6 +702,7 @@ from metadata.conf import has_navigator
             DataCatalog.getEntry({
               sourceType: sourceType,
               namespace: namespace,
+              compute: compute,
               path: path
             }).done(function (entry) {
               entry.getSourceMeta({ silenceErrors: true }).done(function (sourceMeta) {
@@ -740,9 +741,9 @@ from metadata.conf import has_navigator
         });
       }
 
-      function AsteriskContextTabs(data, sourceType, namespace, defaultDatabase) {
+      function AsteriskContextTabs(data, sourceType, namespace, compute, defaultDatabase) {
         var self = this;
-        self.data = new AsteriskData(data, sourceType, namespace, defaultDatabase);
+        self.data = new AsteriskData(data, sourceType, namespace, compute, defaultDatabase);
 
         self.tabs = [
           { id: 'details', label: '${ _("Details") }', template: 'context-popover-asterisk-details', templateData: self.data }
@@ -1205,6 +1206,7 @@ from metadata.conf import has_navigator
         self.data = params.data;
         self.sourceType = params.sourceType;
         self.namespace = params.namespace;
+        self.compute = params.compute;
         self.defaultDatabase = params.defaultDatabase;
         self.close = hidePopover;
         var orientation = params.orientation || 'bottom';
@@ -1291,6 +1293,7 @@ from metadata.conf import has_navigator
           self.isCollection = true;
           self.isCatalogEntry = false;
           self.namespace = params.data.catalogEntry.namespace;
+          self.compute = params.data.catalogEntry.compute;
         }
 
         self.showInAssistEnabled = (typeof params.showInAssistEnabled !== 'undefined' ? params.showInAssistEnabled : true)
@@ -1314,7 +1317,7 @@ from metadata.conf import has_navigator
           self.titleTemplate = 'context-storage-entry-title';
           self.contentsTemplate = 'context-storage-entry-contents';
         } else if (self.isAsterisk) {
-          self.contents = new AsteriskContextTabs(self.data, self.sourceType, self.namespace, self.defaultDatabase);
+          self.contents = new AsteriskContextTabs(self.data, self.sourceType, self.namespace, self.compute, self.defaultDatabase);
           self.title = '*';
           self.iconClass = 'fa-table';
         } else if (self.isDocument) {
@@ -1471,8 +1474,8 @@ from metadata.conf import has_navigator
 
         if (self.isCatalogEntry) {
           ContextCatalog.getNamespaces({ sourceType: sourceType }).done(function (context) {
-            // TODO: Namespace selection for global search results?
-            DataCatalog.getEntry({ sourceType: sourceType, namespace: context.namespaces[0], path: path, definition: { type: params.data.type.toLowerCase() }}).done(function (catalogEntry) {
+            // TODO: Namespace and compute selection for global search results?
+            DataCatalog.getEntry({ sourceType: sourceType, namespace: context.namespaces[0], compute: context.namespaces[0].computes[0], path: path, definition: { type: params.data.type.toLowerCase() }}).done(function (catalogEntry) {
               catalogEntry.navigatorMeta = params.data;
               catalogEntry.navigatorMetaPromise = $.Deferred().resolve(catalogEntry.navigatorMeta);
               catalogEntry.saveLater();

+ 1 - 1
desktop/core/src/desktop/templates/ko_components/ko_history_panel.mako

@@ -236,7 +236,7 @@ from desktop.views import _ko
                   }
 
                   if (notebook.onSuccessUrl() === 'assist.db.refresh') {
-                    DataCatalog.getEntry({ sourceType: snippet.type(), namespace: snippet.namespace(), path: [] }).done(function (entry) {
+                    DataCatalog.getEntry({ sourceType: snippet.type(), namespace: snippet.namespace(), compute: snippet.compute(), path: [] }).done(function (entry) {
                       entry.clearCache({ invalidate: 'cache', cascade: true, silenceErrors: true });
                     });
                   } else if (notebook.onSuccessUrl()) {

+ 4 - 0
desktop/libs/dashboard/src/dashboard/static/dashboard/js/search.ko.js

@@ -557,10 +557,12 @@ var Collection = function (vm, collection) {
   self.description = ko.observable(typeof collection.description != "undefined" && collection.description != null ? collection.description : "");
   self.suggest = ko.mapping.fromJS(collection.suggest);
   self.activeNamespace = ko.observable();
+  self.activeCompute = ko.observable();
 
   ContextCatalog.getNamespaces({ sourceType: collection.engine || 'solr' }).done(function (context) {
     // TODO: Namespace selection
     self.activeNamespace(context.namespaces[0]);
+    self.activeCompute(context.namespaces[0].computes[0]);
   });
 
   self.engine = ko.observable(typeof collection.engine != "undefined" && collection.engine != null ? collection.engine : "solr");
@@ -1861,6 +1863,8 @@ var Collection = function (vm, collection) {
       showInAssistEnabled: true,
       sourceType: self.engine(),
       orientation: 'right',
+      namespace: self.activeNamespace(),
+      compute: self.activeCompute(),
       defaultDatabase: 'default',
       pinEnabled: false,
       source: {

+ 2 - 2
desktop/libs/dashboard/src/dashboard/templates/common_search.mako

@@ -2248,7 +2248,7 @@ ${ dashboard.layout_skeleton(suffix='search') }
       <!-- ko if: $data.function() != 'formula' -->
       <select data-bind="selectize: facetFieldsNames, value: $parent.field, optionsValue: 'name', optionsText: 'name', optionsCaption: '${ _ko('Field...') }'" class="hit-options input-small" style="margin-bottom: 0"></select>
         <!-- ko if: $parent.field -->
-        <a class="inactive-action context-popover-icon" href="javascript:void(0);" data-bind="sqlContextPopover: { sourceType: 'solr', namespace: $root.collection.activeNamespace(), path: 'default.' + $root.collection.name() + '.' + $parent.field()  }">
+        <a class="inactive-action context-popover-icon" href="javascript:void(0);" data-bind="sqlContextPopover: { sourceType: 'solr', namespace: $root.collection.activeNamespace(), compute: $root.collection.activeCompute(), path: 'default.' + $root.collection.name() + '.' + $parent.field()  }">
           <i class="fa fa-fw fa-info" title="${_('Show Details')}"/>
         </a>
         <!-- /ko -->
@@ -2715,7 +2715,7 @@ ${ dashboard.layout_skeleton(suffix='search') }
           class="unstyled inline fields-chooser" style="height: 100px; overflow-y: auto">
         <li data-bind="visibleOnHover: { 'selector': '.entity-field-picker' }">
             <span class="badge badge-info" data-bind="text: name(), attr: {'title': type()}, click: addFacetDemiModalFieldPreview"></span>
-            <a class="entity-field-picker inactive-action margin-right-10" href="javascript:void(0);" data-bind="sqlContextPopover: { sourceType: 'solr', namespace: $root.collection.activeNamespace(), path: 'default.' + $root.collection.name() + '.' + name()  }" style="margin-left: 2px;">
+            <a class="entity-field-picker inactive-action margin-right-10" href="javascript:void(0);" data-bind="sqlContextPopover: { sourceType: 'solr', namespace: $root.collection.activeNamespace(), compute: $root.collection.activeCompute(), path: 'default.' + $root.collection.name() + '.' + name()  }" style="margin-left: 2px;">
               <i class="fa fa-info" title="${_('Show Details')}"/>
             </a>
         </li>

+ 5 - 3
desktop/libs/indexer/src/indexer/templates/importer.mako

@@ -568,7 +568,7 @@ ${ assist.assistPanel() }
 
               <label class="control-label "><div>${ _('Database') }</div></label>
               <input type="text" class="form-control input-xlarge" data-bind="value: name" placeholder="${ _('Database') }">
-              <a href="javscript:void(0);" data-bind="sqlContextPopover: { sourceType: $root.createWizard.source.apiHelperType(), namespace: namespace, path: 'default', offset: { top: -3, left: 3 }}">
+              <a href="javscript:void(0);" data-bind="sqlContextPopover: { sourceType: $root.createWizard.source.apiHelperType(), namespace: namespace, compute: compute, path: 'default', offset: { top: -3, left: 3 }}">
                 <i class="fa fa-info"></i>
               </a>
             <!-- /ko -->
@@ -2124,11 +2124,13 @@ ${ assist.assistPanel() }
       var guessFieldTypesXhr;
 
       self.activeNamespace = ko.observable();
+      self.activeCompute = ko.observable();
 
       // TODO: sourceType? --> self.apiHelperType
       ContextCatalog.getNamespaces({ sourceType: 'hive' }).done(function (context) {
         // TODO: Namespace selection for create wizard
         self.activeNamespace(context.namespaces[0]);
+        self.activeCompute(context.namespaces[0].computes[0]);
       });
 
       self.fileType = ko.observable();
@@ -2397,13 +2399,13 @@ ${ assist.assistPanel() }
                       var match = snippet.statement_raw().match(/CREATE TABLE `([^`]+)`/i);
                       if (match) {
                         var db = match[1];
-                        DataCatalog.getEntry({ sourceType: snippet.type(), namespace: self.activeNamespace(), path: [ db ]}).done(function (dbEntry) {
+                        DataCatalog.getEntry({ sourceType: snippet.type(), namespace: self.activeNamespace(), compute: self.activeCompute(), path: [ db ]}).done(function (dbEntry) {
                           dbEntry.clearCache({ invalidate: 'invalidate', silenceErrors: true }).done(function () {
                             window.location.href = self.editorVM.selectedNotebook().onSuccessUrl();
                           })
                         });
                       } else {
-                        DataCatalog.getEntry({ sourceType: snippet.type(), namespace: self.activeNamespace(), path: []}).done(function (sourceEntry) {
+                        DataCatalog.getEntry({ sourceType: snippet.type(), namespace: self.activeNamespace(), compute: self.activeCompute(), path: []}).done(function (sourceEntry) {
                           sourceEntry.clearCache({ silenceErrors: true }).done(function () {
                             window.location.href = self.editorVM.selectedNotebook().onSuccessUrl();
                           })

+ 4 - 2
desktop/libs/indexer/src/indexer/templates/indexes.mako

@@ -648,11 +648,12 @@ ${ assist.assistPanel() }
       self.baseURL = (IS_HUE_4 ? '/hue' : '') + '/indexer/indexes/';
 
       self.activeNamespace = ko.observable();
-
+      self.activeCompute = ko.observable();
 
       ContextCatalog.getNamespaces({ sourceType: 'solr' }).done(function (context) {
         // TODO: Namespace selection
         self.activeNamespace(context.namespaces[0]);
+        self.activeCompute(context.namespaces[0].computes[0]);
       });
 
       self.assistAvailable = ko.observable(true);
@@ -855,7 +856,6 @@ ${ assist.assistPanel() }
 
         huePubSub.publish('context.popover.show', {
           data: {
-            namespace: self.activeNamespace(),
             type: 'collection',
             identifierChain: [
               {}, // empty, needed by the context popover
@@ -863,6 +863,8 @@ ${ assist.assistPanel() }
               ko.mapping.toJS(field)
             ]
           },
+          namespace: self.activeNamespace(),
+          compute: self.activeCompute(),
           showInAssistEnabled: true,
           orientation: 'right',
           pinEnabled: false,

+ 3 - 0
desktop/libs/indexer/src/indexer/templates/topics.mako

@@ -623,10 +623,12 @@ ${ assist.assistPanel() }
       self.baseURL = (IS_HUE_4 ? '/hue' : '') + '/indexer/topics/';
 
       self.activeNamespace = ko.observable();
+      self.activeCompute = ko.observable();
 
       ContextCatalog.getNamespaces({ sourceType: 'solr' }).done(function (context) {
         // TODO: Namespace selection
         self.activeNamespace(context.namespaces[0]);
+        self.activeCompute(context.namespaces[0].computes[0]);
       });
 
       self.assistAvailable = ko.observable(true);
@@ -830,6 +832,7 @@ ${ assist.assistPanel() }
           data: {
             type: 'collection',
             namespace: self.activeNamespace(),
+            compute: self.activeCompute(),
             identifierChain: [
               {}, // empty, needed by the context popover
               ko.mapping.toJS(self.index),

+ 53 - 11
desktop/libs/notebook/src/notebook/static/notebook/js/notebook.ko.js

@@ -359,18 +359,23 @@ var EditorViewModel = (function() {
     self.namespaceRefreshEnabled = ko.observable(false);
     self.availableNamespaces = ko.observableArray();
     self.namespace = ko.observable();
-    self.availableComputes = ko.observableArray();
+    self.availableComputes = ko.pureComputed(function () {
+      if (self.namespace()) {
+        return self.namespace().computes;
+      }
+      return [];
+    });
+
     self.compute = ko.observable();
 
-    var computesPromise = ContextCatalog.getComputes({ sourceType: self.type() }).done(function (computes) {
-      self.availableComputes(computes);
-      if (!snippet.compute || !computes.some(function (compute) {
-        if (compute.id === snippet.compute.id) {
-          self.compute(compute);
+    self.availableComputes.subscribe(function (newComputes) {
+      if (!self.compute() || !newComputes.some(function (newCompute) {
+        if (newCompute.id === self.compute().id) {
+          self.compute(newCompute);
           return true;
         }
       })) {
-        self.compute(computes[0]);
+        self.compute(newComputes.length ? newComputes[0] : undefined);
       }
     });
 
@@ -385,6 +390,26 @@ var EditorViewModel = (function() {
             return true;
           }})) {
           self.namespace(context.namespaces[0]);
+
+          var previousComputeId;
+          var newCompute;
+          if (self.compute()) {
+            previousComputeId = self.compute().id;
+          } else if (snippet.compute) {
+            previousComputeId = snippet.compute.id;
+          }
+          if (previousComputeId) {
+            self.namespace().computes.some(function (compute) {
+              if (compute.id === previousComputeId) {
+                newCompute = compute;
+                return true;
+              }
+            })
+          }
+          if (!newCompute && self.namespace().computes.length) {
+            newCompute = self.namespace().computes[0];
+          }
+          self.compute(newCompute);
         }
       });
     };
@@ -406,11 +431,20 @@ var EditorViewModel = (function() {
     self.database(typeof snippet.database != "undefined" && snippet.database != null ? snippet.database : null);
     self.availableDatabases = ko.observableArray();
 
+    self.availableDatabases.subscribe(function (newDatabases) {
+      if (self.database() && newDatabases.indexOf(self.database()) === -1) {
+        if (newDatabases.length === 0 || newDatabases.indexOf('default') !== -1) {
+          self.database('default');
+        } else {
+          self.database(newDatabases[0])
+        }
+      }
+    });
+
     self.updateDatabases = function () {
       if (self.isSqlDialect()) {
-
-        $.when(computesPromise, namespacesPromise).done(function () {
-          DataCatalog.getEntry({ sourceType: self.type(), namespace: self.namespace(), path: [], definition: { type: 'source' }}).done(function (sourceEntry) {
+        namespacesPromise.done(function () {
+          DataCatalog.getEntry({ sourceType: self.type(), namespace: self.namespace(), compute: self.compute(), path: [], definition: { type: 'source' }}).done(function (sourceEntry) {
             sourceEntry.getChildren({ silenceErrors: true }).done(function (databaseEntries) {
               var databaseNames = [];
               databaseEntries.forEach(function (databaseEntry) {
@@ -427,6 +461,14 @@ var EditorViewModel = (function() {
       }
     };
 
+    namespacesPromise.done(function () {
+      self.compute.subscribe(function () {
+        window.setTimeout(function () {
+          self.updateDatabases();
+        }, 0)
+      })
+    });
+
     // History is currently in Notebook, same with saved queries by snippets, might be better in assist
     self.currentQueryTab = ko.observable(typeof snippet.currentQueryTab != "undefined" && snippet.currentQueryTab != null ? snippet.currentQueryTab : 'queryHistory');
     self.pinnedContextTabs = ko.observableArray(typeof snippet.pinnedContextTabs != "undefined" && snippet.pinnedContextTabs != null ? snippet.pinnedContextTabs : []);
@@ -951,7 +993,7 @@ var EditorViewModel = (function() {
           }
         }
         ignoreNextAssistDatabaseUpdate = true;
-        DataCatalog.getEntry({ sourceType: self.type(), namespace: self.namespace(), path: path }).done(function (entry) {
+        DataCatalog.getEntry({ sourceType: self.type(), namespace: self.namespace(), compute: self.compute(), path: path }).done(function (entry) {
           entry.clearCache({ invalidate: 'invalidate', cascade: true, silenceErrors: true });
         });
       });

+ 9 - 3
desktop/libs/notebook/src/notebook/templates/editor_components.mako

@@ -946,9 +946,14 @@ ${ sqlSyntaxDropdown.sqlSyntaxDropdown() }
     <div data-bind="component: { name: 'hue-drop-down', params: { value: namespace, entries: availableNamespaces, labelAttribute: 'name', searchable: true, linkTitle: '${ _ko('Active namespace') }' } }" style="display: inline-block"></div>
     <!-- /ko -->
     <!-- ko if: availableComputes().length > 1 || namespaceRefreshEnabled() -->
+    <!-- ko if: availableComputes().length > 0-->
     <span class="editor-header-title">${ _('Compute') }</span>
     <div data-bind="component: { name: 'hue-drop-down', params: { value: compute, entries: availableComputes, labelAttribute: 'name', searchable: true, linkTitle: '${ _ko('Active compute') }' } }" style="display: inline-block"></div>
     <!-- /ko -->
+    <!-- ko if: availableComputes().length === 0-->
+    <span class="editor-header-title"><i class="fa fa-warning"></i> ${ _('No computes found') }</span>
+    <!-- /ko -->
+    <!-- /ko -->
     <!-- ko if: availableDatabases().length > 0 && isSqlDialect() -->
     <span class="editor-header-title">${ _('Database') }</span>
     <div data-bind="component: { name: 'hue-drop-down', params: { value: database, entries: availableDatabases, foreachVisible: true, searchable: true, linkTitle: '${ _ko('Active database') }' } }" style="display: inline-block"></div>
@@ -3277,7 +3282,7 @@ function togglePresentation(value) {};
       ko.applyBindings(viewModel, $('#${ bindableElement }')[0]);
       viewModel.init();
 
-      var attachEntryResolver = function (location, sourceType, namespace) {
+      var attachEntryResolver = function (location, sourceType, namespace, compute) {
         location.resolveCatalogEntry = function(options) {
           if (!options) {
             options = {};
@@ -3297,6 +3302,7 @@ function togglePresentation(value) {};
           var promise = SqlUtils.resolveCatalogEntry({
             sourceType: sourceType,
             namespace: namespace,
+            compute: compute,
             cancellable: options.cancellable,
             cachedOnly: options.cachedOnly,
             identifierChain: location.identifierChain || location.colRef.identifierChain,
@@ -3348,7 +3354,7 @@ function togglePresentation(value) {};
             } else {
               if (e.data.locations) {
                 e.data.locations.forEach(function (location) {
-                  attachEntryResolver(location, e.data.sourceType, e.data.namespace);
+                  attachEntryResolver(location, e.data.sourceType, e.data.namespace, e.data.compute);
                 })
               }
               huePubSub.publish('ace.sql.location.worker.message', e);
@@ -3370,7 +3376,7 @@ function togglePresentation(value) {};
           if (event.data.locationWorkerResponse) {
             if (event.data.locationWorkerResponse.locations) {
               event.data.locationWorkerResponse.locations.forEach(function (location) {
-                attachEntryResolver(location, event.data.locationWorkerResponse.sourceType, event.data.locationWorkerResponse.namespace);
+                attachEntryResolver(location, event.data.locationWorkerResponse.sourceType, event.data.locationWorkerResponse.namespace, event.data.locationWorkerResponse.compute);
               })
             }
             huePubSub.publish('ace.sql.location.worker.message', { data: event.data.locationWorkerResponse });