浏览代码

HUE-4759 [editor] Don't suggest tables in the select list when there is a FROM clause

This also takes care of a bunch of other small issues including:

- Dropped keywords for lateral views
- No aliases suggested for some lateral views
Johan Ahlen 9 年之前
父节点
当前提交
f5e72fd

+ 9 - 15
desktop/core/src/desktop/static/desktop/js/autocomplete/jison/sql_error.jison

@@ -39,6 +39,9 @@ SelectStatement
 
 SelectStatement_EDIT
  : 'SELECT' OptionalAllOrDistinct SelectList_ERROR_EDIT TableExpression
+   {
+     selectListNoTableSuggest($3, $2);
+   }
  | 'SELECT' OptionalAllOrDistinct SelectList_ERROR TableExpression_EDIT
  ;
 
@@ -51,29 +54,20 @@ SelectList_ERROR
  ;
 
 SelectList_ERROR_EDIT
- : ErrorList ',' SelectList_EDIT
- | SelectList ',' ErrorList ',' SelectList_EDIT
- | ErrorList ',' SelectList ',' ErrorList ',' SelectList_EDIT
+ : ErrorList ',' SelectList_EDIT                               -> $3
+ | SelectList ',' ErrorList ',' SelectList_EDIT                -> $5
+ | ErrorList ',' SelectList ',' ErrorList ',' SelectList_EDIT  -> $7
  | ErrorList ',' AnyCursor
    {
-     suggestFunctions();
-     suggestColumns();
-     suggestFunctions();
-     $$ = { cursorAtStart : false, suggestAggregateFunctions: true };
+     $$ = { cursorAtStart : false, suggestFunctions: true, suggestColumns: true, suggestAggregateFunctions: true };
    }
  | SelectList ',' ErrorList ',' AnyCursor
    {
-     suggestFunctions();
-     suggestColumns();
-     suggestFunctions();
-     $$ = { cursorAtStart : false, suggestAggregateFunctions: true };
+     $$ = { cursorAtStart : false, suggestFunctions: true, suggestColumns: true, suggestAggregateFunctions: true };
    }
  | ErrorList ',' SelectList ',' Errors ',' AnyCursor
    {
-     suggestFunctions();
-     suggestColumns();
-     suggestFunctions();
-     $$ = { cursorAtStart : false, suggestAggregateFunctions: true };
+     $$ = { cursorAtStart : true, suggestFunctions: true, suggestColumns: true, suggestAggregateFunctions: true };
    }
  ;
 

+ 1 - 20
desktop/core/src/desktop/static/desktop/js/autocomplete/jison/sql_insert.jison

@@ -332,24 +332,7 @@ SelectWithoutTableExpression_EDIT
    }
  | 'SELECT' OptionalAllOrDistinct SelectList_EDIT
    {
-     if ($3.cursorAtStart) {
-       var keywords = [];
-       if ($2) {
-         keywords = [{ value: '*', weight: 1000 }];
-       } else {
-         keywords = [{ value: '*', weight: 1000 }, 'ALL', 'DISTINCT'];
-       }
-       if (isImpala()) {
-         keywords.push('STRAIGHT_JOIN');
-       }
-       suggestKeywords(keywords);
-     } else {
-       checkForSelectListKeywords($3);
-     }
-     if ($3.suggestAggregateFunctions && (!$2 || $2 === 'ALL')) {
-       suggestAggregateFunctions();
-       suggestAnalyticFunctions();
-     }
+     selectListNoTableSuggest($3, $2);
    }
  | 'SELECT' OptionalAllOrDistinct 'CURSOR'
    {
@@ -371,8 +354,6 @@ SelectWithoutTableExpression_EDIT
      suggestKeywords(keywords);
      suggestFunctions();
      suggestColumns();
-     suggestTables({ prependQuestionMark: true, prependFrom: true });
-     suggestDatabases({ prependQuestionMark: true, prependFrom: true, appendDot: true });
    }
  ;
 

+ 40 - 55
desktop/core/src/desktop/static/desktop/js/autocomplete/jison/sql_main.jison

@@ -1238,6 +1238,18 @@ SelectStatement_EDIT
      } else {
        checkForSelectListKeywords($3);
      }
+     if ($3.suggestFunctions) {
+       suggestFunctions();
+     }
+     if ($3.suggestColumns) {
+       suggestColumns();
+     }
+     if ($3.suggestTables) {
+       suggestTables({ prependQuestionMark: true, prependFrom: true });
+     }
+     if ($3.suggestDatabases) {
+       suggestDatabases({ prependQuestionMark: true, prependFrom: true, appendDot: true });
+     }
      if ($3.suggestAggregateFunctions && (!$2 || $2 === 'ALL')) {
        suggestAggregateFunctions();
        suggestAnalyticFunctions();
@@ -1269,25 +1281,7 @@ SelectStatement_EDIT
  | 'SELECT' OptionalAllOrDistinct SelectList TableExpression_EDIT
  | 'SELECT' OptionalAllOrDistinct SelectList_EDIT TableExpression
    {
-     if ($3.cursorAtStart) {
-       var keywords = [];
-       if ($2) {
-         keywords = [{ value: '*', weight: 1000 }];
-       } else {
-         keywords = [{ value: '*', weight: 1000 }, 'ALL', 'DISTINCT'];
-       }
-       if (isImpala()) {
-         keywords.push('STRAIGHT_JOIN');
-       }
-       suggestKeywords(keywords);
-     } else {
-       checkForKeywords($3);
-     }
-
-     if ($3.suggestAggregateFunctions && (!$2 || $2 === 'ALL')) {
-       suggestAggregateFunctions();
-       suggestAnalyticFunctions();
-     }
+     selectListNoTableSuggest($3, $2);
    }
  | 'SELECT' OptionalAllOrDistinct 'CURSOR' TableExpression
    {
@@ -2137,7 +2131,7 @@ OptionalNot
  | 'NOT'
  ;
 
-SelectSubList
+SelectSpecification
  : ValueExpression OptionalCorrelationName
    {
      if ($2) {
@@ -2156,7 +2150,7 @@ SelectSubList
    }
  ;
 
-SelectSubList_EDIT
+SelectSpecification_EDIT
  : ValueExpression_EDIT OptionalCorrelationName
  | AnyCursor AnyAs RegularOrBacktickedIdentifier
    {
@@ -2168,60 +2162,51 @@ SelectSubList_EDIT
  ;
 
 SelectList
- : SelectSubList                 -> [ $1 ]
- | SelectList ',' SelectSubList
+ : SelectSpecification                 -> [ $1 ]
+ | SelectList ',' SelectSpecification
    {
      $1.push($3);
    }
  ;
 
 SelectList_EDIT
- : SelectSubList_EDIT
- | SelectSubList_EDIT ',' SelectList
- | SelectList 'CURSOR' ',' SelectList
+ : SelectSpecification_EDIT
+ | 'CURSOR' SelectList
    {
-     checkForSelectListKeywords($1);
+     $$ = { cursorAtStart : true, suggestFunctions: true, suggestColumns: true, suggestAggregateFunctions: true };
    }
  | 'CURSOR' ',' SelectList
    {
-     suggestFunctions();
-     suggestColumns();
-     $$ = { cursorAtStart : true, suggestAggregateFunctions: true };
+     $$ = { cursorAtStart : true, suggestFunctions: true, suggestColumns: true, suggestAggregateFunctions: true };
    }
- | 'CURSOR' SelectList
+ | SelectSpecification_EDIT ',' SelectList
+ | SelectList 'CURSOR' SelectList
    {
-     suggestFunctions();
-     suggestColumns();
-     $$ = { cursorAtStart : true, suggestAggregateFunctions: true };
+     checkForSelectListKeywords($1);
    }
- | SelectList 'CURSOR' SelectList
+ | SelectList 'CURSOR' ',' SelectList
    {
-     if ($1.suggestKeywords) {
-       suggestKeywords($1.suggestKeywords);
-     }
+     checkForSelectListKeywords($1);
    }
+ | SelectList ',' AnyCursor
+   {
+     $$ = { suggestKeywords: [{ value: '*', weight: 1000 }], suggestTables: true, suggestDatabases: true, suggestFunctions: true, suggestColumns: true, suggestAggregateFunctions: true };
+   }
+ | SelectList ',' SelectSpecification_EDIT                 -> $3
  | SelectList ',' AnyCursor SelectList
    {
-     suggestFunctions();
-     suggestColumns();
-     $$ = { suggestAggregateFunctions: true, suggestKeywords: [{ value: '*', weight: 1000 }] };
+     $$ = { suggestKeywords: [{ value: '*', weight: 1000 }], suggestFunctions: true, suggestColumns: true, suggestAggregateFunctions: true,  };
    }
- | SelectList ',' SelectListPartTwo_EDIT                 -> $3
- | SelectList ',' SelectListPartTwo_EDIT ','             -> $3
- | SelectList ',' SelectListPartTwo_EDIT ',' SelectList  -> $3
- ;
-
-SelectListPartTwo_EDIT
- : SelectSubList_EDIT
- | AnyCursor
+ | SelectList ',' AnyCursor ','
    {
-     suggestFunctions();
-     suggestColumns();
-     // TODO: Only if there's no FROM
-     suggestTables({ prependQuestionMark: true, prependFrom: true });
-     suggestDatabases({ prependQuestionMark: true, prependFrom: true, appendDot: true });
-     $$ = { suggestKeywords: [{ value: '*', weight: 1000 }], suggestAggregateFunctions: true };
+     $$ = { suggestKeywords: [{ value: '*', weight: 1000 }], suggestFunctions: true, suggestColumns: true, suggestAggregateFunctions: true,  };
+   }
+ | SelectList ',' SelectSpecification_EDIT ','             -> $3
+ | SelectList ',' AnyCursor ',' SelectList
+   {
+     $$ = { suggestKeywords: [{ value: '*', weight: 1000 }], suggestFunctions: true, suggestColumns: true, suggestAggregateFunctions: true,  };
    }
+ | SelectList ',' SelectSpecification_EDIT ',' SelectList  -> $3
  ;
 
 DerivedColumn_TWO

文件差异内容过多而无法显示
+ 0 - 0
desktop/core/src/desktop/static/desktop/js/autocomplete/sql.js


+ 65 - 12
desktop/core/src/desktop/static/desktop/js/autocomplete/sql_support.js

@@ -180,6 +180,33 @@ var addColRefIfExists = function (valueExpression) {
   }
 };
 
+var selectListNoTableSuggest = function (selectListEdit, hasDistinctOrAll) {
+  if (selectListEdit.cursorAtStart) {
+    var keywords = [];
+    if (hasDistinctOrAll) {
+      keywords = [{ value: '*', weight: 1000 }];
+    } else {
+      keywords = [{ value: '*', weight: 1000 }, 'ALL', 'DISTINCT'];
+    }
+    if (isImpala()) {
+      keywords.push('STRAIGHT_JOIN');
+    }
+    suggestKeywords(keywords);
+  } else {
+    checkForKeywords(selectListEdit);
+  }
+  if (selectListEdit.suggestFunctions) {
+    suggestFunctions();
+  }
+  if (selectListEdit.suggestColumns) {
+    suggestColumns();
+  }
+  if (selectListEdit.suggestAggregateFunctions && (!hasDistinctOrAll || hasDistinctOrAll === 'ALL')) {
+    suggestAggregateFunctions();
+    suggestAnalyticFunctions();
+  }
+};
+
 var valueExpressionSuggest = function (oppositeValueExpression, operator) {
   if (oppositeValueExpression && oppositeValueExpression.columnReference) {
     suggestValues();
@@ -259,6 +286,9 @@ var commitLocations = function () {
     }
 
     if (location.type === 'column') {
+      if (isHive() && !location.linked) {
+        location.identifierChain = parser.expandLateralViews(parser.yy.lateralViews, location.identifierChain);
+      }
       expandIdentifierChain(location, true);
     }
 
@@ -415,7 +445,7 @@ parser.identifyPartials = function (beforeCursor, afterCursor) {
   return {left: beforeMatch ? beforeMatch[0].length : 0, right: afterMatch ? afterMatch[0].length : 0};
 };
 
-parser.expandLateralViews = function (lateralViews, originalIdentifierChain) {
+parser.expandLateralViews = function (lateralViews, originalIdentifierChain, columnSuggestion) {
   var identifierChain = originalIdentifierChain.concat(); // Clone in case it's re-used
   var firstIdentifier = identifierChain[0];
   if (typeof lateralViews !== 'undefined') {
@@ -426,16 +456,20 @@ parser.expandLateralViews = function (lateralViews, originalIdentifierChain) {
       if (firstIdentifier.name === lateralView.tableAlias && identifierChain.length > 1) {
         identifierChain.shift();
         firstIdentifier = identifierChain[0];
-        delete parser.yy.result.suggestKeywords;
+        if (columnSuggestion) {
+          delete parser.yy.result.suggestKeywords;
+        }
       } else if (firstIdentifier.name === lateralView.tableAlias && identifierChain.length === 1 && typeof parser.yy.result.suggestColumns !== 'undefined') {
-        if (typeof parser.yy.result.suggestIdentifiers === 'undefined') {
-          parser.yy.result.suggestIdentifiers = [];
+        if (columnSuggestion) {
+          if (typeof parser.yy.result.suggestIdentifiers === 'undefined') {
+            parser.yy.result.suggestIdentifiers = [];
+          }
+          lateralView.columnAliases.forEach(function (columnAlias) {
+            parser.yy.result.suggestIdentifiers.push({name: columnAlias, type: 'alias'});
+          });
+          delete parser.yy.result.suggestColumns;
+          delete parser.yy.result.suggestKeywords;
         }
-        lateralView.columnAliases.forEach(function (columnAlias) {
-          parser.yy.result.suggestIdentifiers.push({name: columnAlias, type: 'alias'});
-        });
-        delete parser.yy.result.suggestColumns;
-        delete parser.yy.result.suggestKeywords;
         return identifierChain;
       }
       if (lateralView.columnAliases.indexOf(firstIdentifier.name) !== -1) {
@@ -447,7 +481,6 @@ parser.expandLateralViews = function (lateralViews, originalIdentifierChain) {
           identifierChain[0] = {name: 'item'};
         }
         identifierChain = lateralView.udtf.expression.columnReference.concat(identifierChain);
-        delete parser.yy.result.suggestKeywords;
         firstIdentifier = identifierChain[0];
       }
     });
@@ -631,7 +664,11 @@ var convertTablePrimariesToSuggestions = function (tablePrimaries) {
     }
   });
   if (identifiers.length > 0) {
-    parser.yy.result.suggestIdentifiers = identifiers;
+    if (typeof parser.yy.result.suggestIdentifiers === 'undefined') {
+      parser.yy.result.suggestIdentifiers = identifiers;
+    } else {
+      parser.yy.result.suggestIdentifiers = identifiers.concat(parser.yy.result.suggestIdentifiers);
+    }
   }
   parser.yy.result.suggestColumns.tables = tables;
   if (parser.yy.result.suggestColumns.identifierChain && parser.yy.result.suggestColumns.identifierChain.length == 0) {
@@ -665,7 +702,23 @@ var linkTablePrimaries = function () {
         expandIdentifierChain(parser.yy.result.suggestColumns);
       }
     } else {
-      expandIdentifierChain(parser.yy.result.suggestColumns);
+      // Expand exploded views in the identifier chain
+      if (isHive() && !parser.yy.result.suggestColumns.linked) {
+        var originalLength = parser.yy.result.suggestColumns.identifierChain.length;
+        parser.yy.result.suggestColumns.identifierChain = parser.expandLateralViews(parser.yy.lateralViews, parser.yy.result.suggestColumns.identifierChain, true);
+        // Drop '*' keyword for lateral views
+        if (typeof parser.yy.result.suggestColumns !== 'undefined') {
+          if (parser.yy.result.suggestColumns.identifierChain.length > originalLength &&
+              typeof parser.yy.result.suggestKeywords !== 'undefined' &&
+              parser.yy.result.suggestKeywords.length === 1 &&
+              parser.yy.result.suggestKeywords[0].value === '*') {
+            delete parser.yy.result.suggestKeywords;
+          }
+          expandIdentifierChain(parser.yy.result.suggestColumns);
+        }
+      } else {
+        expandIdentifierChain(parser.yy.result.suggestColumns);
+      }
     }
   }
 

+ 6 - 0
desktop/core/src/desktop/static/desktop/spec/autocomplete/sqlSpecError.js

@@ -38,6 +38,8 @@ define([
         expectedResult: {
           lowerCase: false,
           suggestFunctions: {},
+          suggestAggregateFunctions: true,
+          suggestAnalyticFunctions: true,
           suggestColumns: { tables: [{ identifierChain: [{ name: 'testTable' }] }] }
         }
       });
@@ -51,6 +53,8 @@ define([
         expectedResult: {
           lowerCase: false,
           suggestFunctions: {},
+          suggestAggregateFunctions: true,
+          suggestAnalyticFunctions: true,
           suggestColumns: { tables: [{ identifierChain: [{ name: 'testTable' }] }] }
         }
       });
@@ -64,6 +68,8 @@ define([
         expectedResult: {
           lowerCase: false,
           suggestFunctions: {},
+          suggestAggregateFunctions: true,
+          suggestAnalyticFunctions: true,
           suggestColumns: { tables: [{ identifierChain: [{ name: 'testTable' }] }] }
         }
       });

+ 1 - 0
desktop/core/src/desktop/static/desktop/spec/autocomplete/sqlSpecInsert.js

@@ -381,6 +381,7 @@ define([
           dialect: 'hive',
           noErrors: true,
           hasLocations: true,
+          containsKeywords: ['*'],
           expectedResult: {
             lowerCase: false,
             suggestFunctions: {},

+ 41 - 3
desktop/core/src/desktop/static/desktop/spec/autocomplete/sqlSpecSelect.js

@@ -3008,6 +3008,44 @@ define([
           });
         });
 
+        it('should suggest aliases for "SELECT | FROM testTable LATERAL VIEW EXPLODE(testTable.arr) a AS arr_exp LATERAL VIEW EXPLODE(arr_exp.items) i AS arr_items;"', function () {
+          assertAutoComplete({
+            beforeCursor: 'SELECT ',
+            afterCursor: ' FROM testTable LATERAL VIEW EXPLODE(testTable.arr) a AS arr_exp LATERAL VIEW EXPLODE(arr_exp.items) i AS arr_items;',
+            dialect: 'hive',
+            hasLocations: true,
+            noErrors: true,
+            containsKeywords: ['*', 'ALL', 'DISTINCT'],
+            expectedResult: {
+              suggestAggregateFunctions: true,
+              suggestAnalyticFunctions: true,
+              suggestFunctions: {},
+              suggestColumns: { tables: [{ identifierChain: [{ name: 'testTable' }] }] },
+              suggestIdentifiers: [{ name: 'a.', type: 'alias' }, { name: 'arr_exp', type: 'alias' }, { name: 'i.', type: 'alias' }, { name: 'arr_items', type: 'alias' }],
+              lowerCase: false
+            }
+          });
+        });
+
+        it('should suggest aliases for "SELECT | FROM testTable t LATERAL VIEW EXPLODE(t.arr) a AS arr_exp LATERAL VIEW EXPLODE(arr_exp.items) i AS arr_items;"', function () {
+          assertAutoComplete({
+            beforeCursor: 'SELECT ',
+            afterCursor: ' FROM testTable t LATERAL VIEW EXPLODE(t.arr) a AS arr_exp LATERAL VIEW EXPLODE(arr_exp.items) i AS arr_items;',
+            dialect: 'hive',
+            noErrors: true,
+            hasLocations: true,
+            containsKeywords: ['*', 'ALL', 'DISTINCT'],
+            expectedResult: {
+              suggestAggregateFunctions: true,
+              suggestAnalyticFunctions: true,
+              suggestFunctions: {},
+              suggestColumns: { tables: [{ identifierChain: [{ name: 'testTable' }], alias: 't' }] },
+              suggestIdentifiers: [{ name: 't.', type: 'alias' }, { name: 'a.', type: 'alias' }, { name: 'arr_exp', type: 'alias' }, { name: 'i.', type: 'alias' }, { name: 'arr_items', type: 'alias' }],
+              lowerCase: false
+            }
+          });
+        });
+
         it('should suggest columns for "SELECT | FROM testTable LATERAL VIEW explode("', function () {
           assertAutoComplete({
             beforeCursor: 'SELECT ',
@@ -3122,8 +3160,6 @@ define([
             '\t LATERAL VIEW EXPLODE(tt2.testArrayB) explodedTableB AS testItemB',
             dialect: 'hive',
             expectedResult: {
-              lowerCase: false,
-              suggestColumns: { tables: [{ identifierChain: [{ name: 'testTable2' }, { name: 'testArrayB' }, { name: 'item' }] }] },
               locations: [
                 { type: 'column', location: { first_line: 2, last_line: 2, first_column: 2, last_column: 11 }, identifierChain: [{ name: 'testTable2' }, { name: 'testArrayA'}, {name: 'item'}] },
                 { type: 'table', location: { first_line: 5, last_line: 5, first_column: 3, last_column: 13 }, identifierChain: [{ name: 'testTable2' }]},
@@ -3131,7 +3167,9 @@ define([
                 { type: 'column', location: { first_line: 6, last_line: 6, first_column: 24, last_column: 38 }, identifierChain: [{ name: 'testTable2' }, { name: 'testArrayA'}] },
                 { type: 'function', location: { first_line: 7, last_line: 7, first_column: 16, last_column: 22 }, function: 'explode'},
                 { type: 'column', location: { first_line: 7, last_line: 7, first_column: 24, last_column: 38 }, identifierChain: [{ name: 'testTable2' }, { name: 'testArrayB'}] }
-              ]
+              ],
+              suggestColumns: { tables: [{ identifierChain: [{ name: 'testTable2' }, { name: 'testArrayB' }, { name: 'item' }] }] },
+              lowerCase: false
             }
           });
         });

部分文件因为文件数量过多而无法显示