Pārlūkot izejas kodu

HUE-4753 [editor] The autocompleter doesn't merge columns correctly

- Fixed issue with column name merging with multiple tables
- Fixed issue with complex type suggestions for Hive
- Always include DB when calling API
- It will now suggest columns just before 'AS alias'
- It won't suggest virtual columns after '.'
- On failure it now makes sure the autocomplete spinner is hidden
Johan Ahlen 9 gadi atpakaļ
vecāks
revīzija
8d55bae

+ 6 - 2
desktop/core/src/desktop/static/desktop/js/autocomplete/jison/sql_main.jison

@@ -2158,6 +2158,12 @@ SelectSubList
 
 SelectSubList_EDIT
  : ValueExpression_EDIT OptionalCorrelationName
+ | AnyCursor AnyAs RegularOrBacktickedIdentifier
+   {
+     suggestFunctions();
+     suggestColumns();
+     $$ = { suggestAggregateFunctions: true };
+   }
  | ValueExpression OptionalCorrelationName_EDIT  -> $2
  ;
 
@@ -2180,14 +2186,12 @@ SelectList_EDIT
    {
      suggestFunctions();
      suggestColumns();
-     suggestFunctions();
      $$ = { cursorAtStart : true, suggestAggregateFunctions: true };
    }
  | 'CURSOR' SelectList
    {
      suggestFunctions();
      suggestColumns();
-     suggestFunctions();
      $$ = { cursorAtStart : true, suggestAggregateFunctions: true };
    }
  | SelectList 'CURSOR' SelectList

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
desktop/core/src/desktop/static/desktop/js/autocomplete/sql.js


+ 8 - 3
desktop/core/src/desktop/static/desktop/js/autocompleter.js

@@ -88,9 +88,14 @@
     var before = editor.getTextBeforeCursor();
     var after = editor.getTextAfterCursor(";");
 
-    self.autocomplete(before, after, function(result) {
-      callback(null, result);
-    }, editor);
+    try {
+      self.autocomplete(before, after, function(result) {
+        callback(null, result);
+      }, editor);
+    } catch (err) {
+      editor.hideSpinner();
+      throw err;
+    }
   };
 
   Autocompleter.prototype.getDocTooltip = function (item) {

+ 47 - 16
desktop/core/src/desktop/static/desktop/js/sqlAutocompleter2.js

@@ -175,6 +175,10 @@
 
     if (parseResult.suggestColumns) {
       var suggestColumnsDeferral =  $.Deferred();
+      if (self.snippet.type() === 'hive' && /[^\.]$/.test(beforeCursor)) {
+        completions.push({value: 'BLOCK__OFFSET__INSIDE__FILE', meta: 'virtual', weight: DEFAULT_WEIGHTS.VIRTUAL_COLUMN});
+        completions.push({value: 'INPUT__FILE__NAME', meta: 'virtual', weight: DEFAULT_WEIGHTS.VIRTUAL_COLUMN});
+      }
       if (parseResult.suggestColumns.types && parseResult.suggestColumns.types[0] === 'COLREF') {
         colRefDeferral.done(function () {
           parseResult.suggestColumns.tables.forEach(function (table) {
@@ -192,10 +196,6 @@
         });
         suggestColumnsDeferral.resolve();
       }
-      if (typeof parseResult.suggestColumns.identifierChain === 'undefined' && self.snippet.type() === 'hive') {
-        completions.push({value: 'BLOCK__OFFSET__INSIDE__FILE', meta: 'virtual', weight: DEFAULT_WEIGHTS.VIRTUAL_COLUMN});
-        completions.push({value: 'INPUT__FILE__NAME', meta: 'virtual', weight: DEFAULT_WEIGHTS.VIRTUAL_COLUMN});
-      }
       deferrals.push(suggestColumnsDeferral);
     }
 
@@ -254,17 +254,28 @@
       var suggestion = columnSuggestions[i];
       var hasDuplicates = false;
       for (i; i + 1 < columnSuggestions.length && columnSuggestions[i + 1].value === suggestion.value; i++) {
-        if (typeof columnSuggestions[i + 1].table.alias !== 'undefined') {
-          columnSuggestions[i + 1].value = columnSuggestions[i + 1].table.alias + '.' + columnSuggestions[i + 1].value
-        } else {
-          columnSuggestions[i + 1].value = columnSuggestions[i + 1].table.table + '.' + columnSuggestions[i + 1].value
+        var nextTable = columnSuggestions[i + 1].table;
+        if (typeof nextTable.alias !== 'undefined') {
+          columnSuggestions[i + 1].value = nextTable.alias + '.' + columnSuggestions[i + 1].value
+        } else if (typeof nextTable.identifierChain !== 'undefined' && nextTable.identifierChain.length > 0) {
+          var lastIdentifier = nextTable.identifierChain[nextTable.identifierChain.length - 1];
+          if (typeof lastIdentifier.name !== 'undefined') {
+            columnSuggestions[i + 1].value = lastIdentifier.name + '.' + columnSuggestions[i + 1].value;
+          } else if (typeof lastIdentifier.subQuery !== 'undefined') {
+            columnSuggestions[i + 1].value = lastIdentifier.subQuery + '.' + columnSuggestions[i + 1].value;
+          }
         }
         hasDuplicates = true;
       }
       if (typeof suggestion.table.alias !== 'undefined') {
         suggestion.value = suggestion.table.alias + '.' + suggestion.value;
-      } else if (hasDuplicates) {
-        suggestion.value = suggestion.table.table + '.' + suggestion.value;
+      } else if (hasDuplicates && typeof suggestion.table.identifierChain !== 'undefined' && suggestion.table.identifierChain.length > 0) {
+        var lastIdentifier = suggestion.table.identifierChain[suggestion.table.identifierChain.length - 1];
+        if (typeof lastIdentifier.name !== 'undefined') {
+          suggestion.value = lastIdentifier.name + '.' + suggestion.value;
+        } else if (typeof lastIdentifier.subQuery !== 'undefined') {
+          suggestion.value = lastIdentifier.subQuery + '.' + suggestion.value;
+        }
       }
       delete suggestion.table;
     }
@@ -321,12 +332,24 @@
         fields: fetchedFields,
         timeout: self.timeout,
         successCallback: function (data) {
+          if (self.snippet.type() === 'hive'
+              && typeof data.extended_columns !== 'undefined'
+              && data.extended_columns.length === 1
+              && data.extended_columns.length
+              && /^map|array|struct/i.test(data.extended_columns[0].type)) {
+            identifierChain.unshift({ name: data.extended_columns[0].name })
+          }
           if (identifierChain.length > 0) {
-            if (data.type === 'array') {
-              fetchedFields.push('item')
-            }
-            if (data.type === 'map') {
-              fetchedFields.push('value')
+            if (typeof identifierChain[0].name !== 'undefined' && /value|item|key/i.test(identifierChain[0].name)) {
+              fetchedFields.push(identifierChain[0].name);
+              identifierChain.shift();
+            } else {
+              if (data.type === 'array') {
+                fetchedFields.push('item')
+              }
+              if (data.type === 'map') {
+                fetchedFields.push('value')
+              }
             }
             fetchFieldsInternal(table, database, identifierChain, callback, errorCallback, fetchedFields)
           } else {
@@ -340,7 +363,10 @@
 
     // For Impala the first parts of the identifier chain could be either database or table, either:
     // SELECT | FROM database.table -or- SELECT | FROM table.column
-    if (self.snippet.type() === 'impala') {
+
+    // For Hive it could be either:
+    // SELECT col.struct FROM db.tbl -or- SELECT col.struct FROM tbl
+    if (self.snippet.type() === 'impala' || self.snippet.type() === 'hive') {
       if (identifierChain.length > 1) {
         self.snippet.getApiHelper().loadDatabases({
           sourceType: self.snippet.type(),
@@ -406,6 +432,9 @@
   };
 
   SqlAutocompleter2.prototype.locateSubQuery = function (subQueries, subQueryName) {
+    if (typeof subQueries === 'undefined') {
+      return null;
+    }
     var foundSubQueries = subQueries.filter(function (knownSubQuery) {
       return knownSubQuery.alias === subQueryName
     });
@@ -444,6 +473,8 @@
       };
       if (foundSubQuery !== null) {
         addSubQueryColumns(foundSubQuery.columns);
+      } else {
+        addColumnsDeferred.resolve();
       }
     } else {
       var callback = function (data) {

+ 46 - 0
desktop/core/src/desktop/static/desktop/spec/autocomplete/sqlSpecSelect.js

@@ -814,6 +814,52 @@ define([
         });
       });
 
+      it('should suggest tables for "SELECT | AS boo FROM tableA;"', function() {
+        assertAutoComplete({
+          beforeCursor: 'SELECT ',
+          afterCursor: ' AS boo FROM tableA;',
+          hasLocations: true,
+          expectedResult: {
+            lowerCase: false,
+            suggestAggregateFunctions: true,
+            suggestAnalyticFunctions: true,
+            suggestFunctions: {},
+            suggestColumns: { tables: [{ identifierChain: [{ name: 'tableA' }] }] }
+          }
+        });
+      });
+
+      it('should suggest tables for "SELECT | boo FROM tableA;"', function() {
+        assertAutoComplete({
+          beforeCursor: 'SELECT ',
+          afterCursor: ' boo FROM tableA;',
+          hasLocations: true,
+          containsKeywords: ['*', 'ALL', 'DISTINCT'],
+          expectedResult: {
+            lowerCase: false,
+            suggestAggregateFunctions: true,
+            suggestAnalyticFunctions: true,
+            suggestFunctions: {},
+            suggestColumns: { tables: [{ identifierChain: [{ name: 'tableA' }] }] }
+          }
+        });
+      });
+
+      it('should suggest tables for "SELECT bla| AS boo FROM tableA;"', function() {
+        assertAutoComplete({
+          beforeCursor: 'SELECT bla',
+          afterCursor: ' AS boo FROM tableA;',
+          hasLocations: true,
+          expectedResult: {
+            lowerCase: false,
+            suggestAggregateFunctions: true,
+            suggestAnalyticFunctions: true,
+            suggestFunctions: {},
+            suggestColumns: { tables: [{ identifierChain: [{ name: 'tableA' }] }] }
+          }
+        });
+      });
+
       it('should suggest columns for "SELECT | FROM testWHERE"', function () {
         assertAutoComplete({
           beforeCursor: 'SELECT ',

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels