Browse Source

HUE-5287 [editor] Suggest popular join conditions in the editor

Johan Ahlen 9 years ago
parent
commit
ab14ffe

+ 66 - 0
desktop/core/src/desktop/static/desktop/js/apiHelper.js

@@ -1391,6 +1391,72 @@ var ApiHelper = (function () {
     }));
   };
 
+  /**
+   * Fetches a navigator entity for the given identifierChain
+   *
+   * @param {Object} options
+   * @param {string} options.sourceType
+   * @param {Function} options.successCallback
+   * @param {Function} [options.errorCallback]
+   * @param {boolean} [options.silenceErrors]
+   *
+   * @param {Object[]} options.tables
+   * @param {Object[]} options.tables.identifierChain
+   * @param {string} options.tables.identifierChain.name
+   * @param {string} [options.defaultDatabase]
+   */
+  ApiHelper.prototype.fetchNavOptJoinConditions = function (options) {
+    var self = this;
+
+    var dbTables = [];
+    options.tables.forEach(function (table) {
+      var clonedIdentifierChain = table.identifierChain.concat();
+      var database = options.defaultDatabase && !self.containsDatabase(options.sourceType, clonedIdentifierChain[0].name) ? options.defaultDatabase : clonedIdentifierChain.shift().name;
+      dbTables.push(database + '.' + $.map(clonedIdentifierChain, function (identifier) { return identifier.name }).join('.'));
+    });
+
+    var url = '/metadata/api/optimizer/top_joins';
+    var hash = ko.mapping.toJSON(dbTables).hashCode();
+
+    var fetchFunction = function (storeInCache) {
+      if (options.timeout === 0) {
+        self.assistErrorCallback(options)({ status: -1 });
+        return;
+      }
+
+      $.ajax({
+        type: 'post',
+        url: url,
+        data: {
+          dbTables: ko.mapping.toJSON(dbTables)
+        },
+        timeout: options.timeout
+      })
+      .done(function (data) {
+        if (data.status === 0 && !self.successResponseIsError(data)) {
+          if (typeof data.values !== 'undefined' && data.values.length > 0) {
+            storeInCache(data);
+          }
+          options.successCallback(data);
+        } else {
+          self.assistErrorCallback(options)(data);
+        }
+      })
+      .fail(self.assistErrorCallback(options))
+      .always(function () {
+        if (typeof options.editor !== 'undefined' && options.editor !== null) {
+          options.editor.hideSpinner();
+        }
+      });
+    };
+
+    fetchCached.bind(self)($.extend({}, options, {
+      url: url,
+      hash: hash,
+      fetchFunction: fetchFunction
+    }));
+  };
+
   ApiHelper.prototype.globalSearchAutocomplete = function (options) {
     var self = this;
 

+ 11 - 0
desktop/core/src/desktop/static/desktop/js/hue.utils.js

@@ -356,6 +356,17 @@ Number.prototype.toHHMMSS = function () {
   return (days > 0 ? days + "d, " : "") + (hours > 0 ? hours + "h, " : "") + (minutes > 0 ? minutes + "m, " : "") + seconds + (millis > 0 && minutes == 0 && hours == 0 && days == 0 ? "." + millis : "") + "s";
 }
 
+String.prototype.hashCode = function() {
+  var hash = 0, i, chr, len;
+  if (this.length === 0) return hash;
+  for (i = 0, len = this.length; i < len; i++) {
+    chr   = this.charCodeAt(i);
+    hash  = ((hash << 5) - hash) + chr;
+    hash |= 0; // Convert to 32bit integer
+  }
+  return hash;
+};
+
 if (!('getParameter' in window.location)) {
   window.location.getParameter = function (name) {
     name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");

+ 33 - 0
desktop/core/src/desktop/static/desktop/js/sqlAutocompleter2.js

@@ -32,6 +32,7 @@ var SqlAutocompleter2 = (function () {
 
   // Keyword weights come from the parser
   var DEFAULT_WEIGHTS = {
+    JOIN_CONDITION: 1100,
     COLUMN: 1000,
     SAMPLE: 900,
     IDENTIFIER: 800,
@@ -114,6 +115,38 @@ var SqlAutocompleter2 = (function () {
       colRefDeferral.resolve();
     }
 
+    if (parseResult.suggestJoinConditions) {
+      var joinDeferral = $.Deferred();
+      deferrals.push(joinDeferral);
+      self.snippet.getApiHelper().fetchNavOptJoinConditions({
+        sourceType: self.snippet.type(),
+        timeout: self.timeout,
+        defaultDatabase: database,
+        silenceErrors: true,
+        tables: parseResult.suggestJoinConditions.tables,
+        successCallback: function (data) {
+          data.values.forEach(function (value) {
+            var suggestionString = parseResult.suggestJoinConditions.prependOn ? (parseResult.lowerCase ? 'on ' : 'ON ') : '';
+            var first = true;
+            value.joinCols.forEach(function (joinColPair) {
+              if (!first) {
+                suggestionString += parseResult.lowerCase ? ' and ' : ' AND ';
+              }
+              suggestionString += joinColPair.columns[0] + ' = ' + joinColPair.columns[1];
+              first = false;
+            });
+            completions.push({
+              value: suggestionString,
+              meta: 'condition',
+              weight: DEFAULT_WEIGHTS.JOIN_CONDITION
+            });
+          });
+          joinDeferral.resolve();
+        },
+        errorCallback: joinDeferral.resolve
+      });
+    }
+
     if (parseResult.suggestFunctions) {
       var suggestFunctionsDeferral = $.Deferred();
       if (parseResult.suggestFunctions.types && parseResult.suggestFunctions.types[0] === 'COLREF') {