Browse Source

HUE-9429 [editor] Split Impala SELECT grammar and reduce duplication with the generic parser

Johan Ahlen 5 years ago
parent
commit
a5a994c7df

+ 49 - 0
desktop/core/src/desktop/js/parse/jison/sql/impala/describe/describe.jison

@@ -0,0 +1,49 @@
+// Licensed to Cloudera, Inc. under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  Cloudera, Inc. licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+DataDefinition
+ : DescribeStatement
+ ;
+
+DataDefinition_EDIT
+ : DescribeStatement_EDIT
+ ;
+
+DescribeStatement
+ : 'DESCRIBE' OptionalExtendedOrFormatted SchemaQualifiedTableIdentifier
+   {
+     parser.addTablePrimary($3);
+   }
+ ;
+
+DescribeStatement_EDIT
+ : 'DESCRIBE' OptionalExtendedOrFormatted 'CURSOR'
+   {
+     if (!$2) {
+       parser.suggestKeywords(parser.DESCRIBE_KEYWORDS);
+     }
+     parser.suggestTables();
+     parser.suggestDatabases({ appendDot: true });
+   }
+ | 'DESCRIBE' OptionalExtendedOrFormatted SchemaQualifiedTableIdentifier_EDIT
+ | 'DESCRIBE' OptionalExtendedOrFormatted 'CURSOR' SchemaQualifiedTableIdentifier
+   {
+     parser.addTablePrimary($4);
+     if (!$2) {
+       parser.suggestKeywords(parser.DESCRIBE_KEYWORDS);
+     }
+   }
+ ;

+ 47 - 0
desktop/core/src/desktop/js/parse/jison/sql/impala/describe/describe_database.jison

@@ -0,0 +1,47 @@
+// Licensed to Cloudera, Inc. under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  Cloudera, Inc. licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+DataDefinition
+ : DescribeDatabaseStatement
+ ;
+
+DataDefinition_EDIT
+ : DescribeDatabaseStatement_EDIT
+ ;
+
+DescribeDatabaseStatement
+ : 'DESCRIBE' 'DATABASE' OptionalExtendedOrFormatted DatabaseIdentifier
+   {
+     parser.addDatabaseLocation(@4, [{ name: $4 }]);
+   }
+ ;
+
+DescribeDatabaseStatement_EDIT
+ : 'DESCRIBE' 'DATABASE' OptionalExtendedOrFormatted 'CURSOR'
+   {
+     if (!$3) {
+       parser.suggestKeywords(['EXTENDED', 'FORMATTED']);
+     }
+     parser.suggestDatabases();
+   }
+ | 'DESCRIBE' 'DATABASE' OptionalExtendedOrFormatted 'CURSOR' DatabaseIdentifier
+    {
+      if (!$3) {
+        parser.suggestKeywords(['EXTENDED', 'FORMATTED']);
+      }
+      parser.addDatabaseLocation(@5, [{ name: $5 }]);
+    }
+ ;

+ 185 - 0
desktop/core/src/desktop/js/parse/jison/sql/impala/select/joins.jison

@@ -0,0 +1,185 @@
+// Licensed to Cloudera, Inc. under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  Cloudera, Inc. licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+OptionalJoins
+ :
+ | Joins
+ | Joins_INVALID
+ ;
+
+Joins
+ : JoinType OptionalBroadcastOrShuffle TablePrimary OptionalJoinCondition
+   {
+     if ($4 && $4.valueExpression) {
+       $$ = $4.valueExpression;
+     } else {
+       $$ = {};
+     }
+     $$.joinType = $1;
+     if ($4.noJoinCondition) {
+       $$.suggestJoinConditions = { prependOn: true, tablePrimaries: parser.yy.latestTablePrimaries.concat() }
+     }
+     if ($4.suggestKeywords) {
+       $$.suggestKeywords = $4.suggestKeywords;
+     }
+     if (parser.yy.latestTablePrimaries.length > 0) {
+        parser.yy.latestTablePrimaries[parser.yy.latestTablePrimaries.length - 1].join = true;
+     }
+   }
+ | Joins JoinType OptionalBroadcastOrShuffle TablePrimary OptionalJoinCondition
+   {
+     if ($5 && $5.valueExpression) {
+       $$ = $5.valueExpression;
+     } else {
+       $$ = {};
+     }
+     $$.joinType = $1;
+     if ($5.noJoinCondition) {
+       $$.suggestJoinConditions = { prependOn: true, tablePrimaries: parser.yy.latestTablePrimaries.concat() }
+     }
+     if ($5.suggestKeywords) {
+       $$.suggestKeywords = $5.suggestKeywords;
+     }
+     if (parser.yy.latestTablePrimaries.length > 0) {
+       parser.yy.latestTablePrimaries[parser.yy.latestTablePrimaries.length - 1].join = true;
+     }
+   }
+ ;
+
+Joins_INVALID
+ : JoinType OptionalBroadcastOrShuffle                                           -> { joinType: $1 }
+ | JoinType OptionalBroadcastOrShuffle Joins                                     -> { joinType: $1 }
+ ;
+
+Join_EDIT
+ : JoinType_EDIT OptionalBroadcastOrShuffle TablePrimary OptionalJoinCondition
+   {
+     if ($1.suggestKeywords) {
+       parser.suggestKeywords($1.suggestKeywords);
+     }
+   }
+ | JoinType_EDIT OptionalBroadcastOrShuffle
+   {
+     if ($1.suggestKeywords) {
+       parser.suggestKeywords($1.suggestKeywords);
+     }
+   }
+ | JoinType OptionalBroadcastOrShuffle TablePrimary_EDIT OptionalJoinCondition
+ | JoinType OptionalBroadcastOrShuffle TablePrimary JoinCondition_EDIT
+ | JoinType OptionalBroadcastOrShuffle 'CURSOR' OptionalJoinCondition
+   {
+     if (!$2) {
+       parser.suggestKeywords(['[BROADCAST]', '[SHUFFLE]']);
+     }
+     if (!$2 && parser.yy.latestTablePrimaries.length > 0) {
+       var idx = parser.yy.latestTablePrimaries.length - 1;
+       var tables = [];
+       do {
+         var tablePrimary = parser.yy.latestTablePrimaries[idx];
+         if (!tablePrimary.subQueryAlias) {
+           tables.unshift(tablePrimary.alias ? { identifierChain: tablePrimary.identifierChain, alias: tablePrimary.alias } : { identifierChain: tablePrimary.identifierChain })
+         }
+         idx--;
+       } while (idx >= 0 && tablePrimary.join && !tablePrimary.subQueryAlias)
+
+       if (tables.length > 0) {
+         parser.suggestJoins({
+           prependJoin: false,
+           joinType: $1,
+           tables: tables
+         })
+       }
+     }
+     parser.suggestTables();
+     parser.suggestDatabases({
+       appendDot: true
+     });
+   }
+ ;
+
+Joins_EDIT
+ : Join_EDIT
+ | Join_EDIT Joins
+ | Joins Join_EDIT
+ | Joins Join_EDIT Joins
+ ;
+
+JoinType
+ : 'JOIN'                         -> 'JOIN'
+ | 'ANTI' 'JOIN'          -> 'ANTI JOIN'
+ | 'CROSS' 'JOIN'                 -> 'CROSS JOIN'
+ | 'INNER' 'JOIN'                 -> 'INNER JOIN'
+ | 'OUTER' 'JOIN'                 -> 'OUTER JOIN'
+ | 'SEMI' 'JOIN'                  -> 'SEMI JOIN'
+ | 'FULL' 'JOIN'                  -> 'FULL JOIN'
+ | 'FULL' 'OUTER' 'JOIN'          -> 'FULL OUTER JOIN'
+ | 'LEFT' 'JOIN'                  -> 'LEFT JOIN'
+ | 'LEFT' 'ANTI' 'JOIN'   -> 'LEFT ANTI JOIN'
+ | 'LEFT' 'INNER' 'JOIN'          -> 'LEFT INNER JOIN'
+ | 'LEFT' 'OUTER' 'JOIN'          -> 'LEFT OUTER JOIN'
+ | 'LEFT' 'SEMI' 'JOIN'           -> 'LEFT SEMI JOIN'
+ | 'RIGHT' 'JOIN'                 -> 'RIGHT JOIN'
+ | 'RIGHT' 'ANTI' 'JOIN'  -> 'RIGHT ANTI JOIN'
+ | 'RIGHT' 'INNER' 'JOIN'         -> 'RIGHT OUTER JOIN'
+ | 'RIGHT' 'OUTER' 'JOIN'         -> 'RIGHT OUTER JOIN'
+ | 'RIGHT' 'SEMI' 'JOIN'          -> 'RIGHT SEMI JOIN'
+ ;
+
+JoinType_EDIT
+ : 'ANTI' 'CURSOR'          -> { suggestKeywords: ['JOIN'] }
+ | 'CROSS' 'CURSOR'                 -> { suggestKeywords: ['JOIN'] }
+ | 'INNER' 'CURSOR'                 -> { suggestKeywords: ['JOIN'] }
+ | 'OUTER' 'CURSOR'                 -> { suggestKeywords: ['JOIN'] }
+ | 'SEMI' 'CURSOR'                  -> { suggestKeywords: ['JOIN'] }
+ | 'FULL' 'OUTER' 'CURSOR'          -> { suggestKeywords: ['JOIN'] }
+ | 'FULL' 'CURSOR' 'JOIN'           -> { suggestKeywords: ['OUTER'] }
+ | 'LEFT' 'ANTI' 'CURSOR'   -> { suggestKeywords: ['JOIN'] }
+ | 'LEFT' 'INNER' 'CURSOR'          -> { suggestKeywords: ['JOIN'] }
+ | 'LEFT' 'OUTER' 'CURSOR'          -> { suggestKeywords: ['JOIN'] }
+ | 'LEFT' 'SEMI' 'CURSOR'           -> { suggestKeywords: ['JOIN'] }
+ | 'LEFT' 'CURSOR' 'JOIN'           -> { suggestKeywords: ['ANTI', 'INNER', 'OUTER', 'SEMI'] }
+ | 'RIGHT' 'ANTI' 'CURSOR'          -> { suggestKeywords: ['JOIN'] }
+ | 'RIGHT' 'INNER' 'CURSOR'         -> { suggestKeywords: ['JOIN'] }
+ | 'RIGHT' 'OUTER' 'CURSOR'         -> { suggestKeywords: ['JOIN'] }
+ | 'RIGHT' 'SEMI' 'CURSOR'          -> { suggestKeywords: ['JOIN'] }
+ | 'RIGHT' 'CURSOR' 'JOIN'          -> { suggestKeywords: ['ANTI', 'INNER', 'OUTER', 'SEMI'] }
+ ;
+
+OptionalBroadcastOrShuffle
+ :
+ | 'BROADCAST'
+ | 'SHUFFLE'
+ ;
+
+OptionalJoinCondition
+ :                                       -> { noJoinCondition: true, suggestKeywords: ['ON', 'USING'] }
+ | 'ON' ValueExpression                  -> { valueExpression: $2 }
+ | 'USING' '(' UsingColList ')'          -> {}
+ ;
+
+UsingColList
+ : RegularOrBacktickedIdentifier
+ | UsingColList ',' RegularOrBacktickedIdentifier
+ ;
+
+JoinCondition_EDIT
+ : 'ON' ValueExpression_EDIT
+ | 'ON' 'CURSOR'
+   {
+     parser.valueExpressionSuggest();
+     parser.suggestJoinConditions({ prependOn: false });
+   }
+ ;

+ 36 - 0
desktop/core/src/desktop/js/parse/jison/sql/impala/select/limit_clause.jison

@@ -0,0 +1,36 @@
+// Licensed to Cloudera, Inc. under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  Cloudera, Inc. licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+OptionalLimitClause
+ :
+ | LimitClause
+ ;
+
+LimitClause
+ : 'LIMIT' ValueExpression
+ ;
+
+LimitClause_EDIT
+ : 'LIMIT' 'CURSOR'
+   {
+     parser.suggestKeywords([{ value: '10', weight: 10000 }, { value: '100', weight: 10000 }, { value: '1000', weight: 10000 }, { value: '5000', weight: 10000 }, { value: '10000', weight: 10000 }])
+     parser.suggestFunctions({ types: ['BIGINT'] });
+   }
+ | 'LIMIT' ValueExpression_EDIT
+   {
+     delete parser.yy.result.suggestColumns;
+   }
+ ;

+ 35 - 0
desktop/core/src/desktop/js/parse/jison/sql/impala/select/offset_clause.jison

@@ -0,0 +1,35 @@
+// Licensed to Cloudera, Inc. under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  Cloudera, Inc. licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+OptionalOffsetClause
+ :
+ | OffsetClause
+ ;
+
+OffsetClause
+ : 'OFFSET' ValueExpression
+ ;
+
+OffsetClause_EDIT
+ : 'OFFSET' 'CURSOR'
+   {
+     parser.suggestFunctions({ types: ['BIGINT'] });
+   }
+ | 'OFFSET' ValueExpression_EDIT
+   {
+     delete parser.yy.result.suggestColumns;
+   }
+ ;

+ 101 - 0
desktop/core/src/desktop/js/parse/jison/sql/impala/select/order_by_clause.jison

@@ -0,0 +1,101 @@
+// Licensed to Cloudera, Inc. under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  Cloudera, Inc. licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+OptionalOrderByClause
+ :
+ | OrderByClause
+ ;
+
+OrderByClause
+ : 'ORDER' 'BY' OrderByColumnList  -> $3
+ ;
+
+OrderByClause_EDIT
+ : 'ORDER' 'BY' OrderByColumnList_EDIT
+   {
+     if ($3.emptyOrderBy) {
+       parser.suggestOrderBys({ tablePrimaries: parser.yy.latestTablePrimaries.concat() });
+     }
+   }
+ | 'ORDER' 'CURSOR'
+   {
+     parser.suggestKeywords(['BY']);
+     parser.suggestOrderBys({ prefix: 'BY', tablePrimaries: parser.yy.latestTablePrimaries.concat() });
+   }
+ ;
+
+OrderByColumnList
+ : OrderByIdentifier
+ | OrderByColumnList ',' OrderByIdentifier  -> $3
+ ;
+
+OrderByColumnList_EDIT
+ : OrderByIdentifier_EDIT
+ | 'CURSOR' OrderByIdentifier
+   {
+     $$ = { emptyOrderBy: false }
+     parser.valueExpressionSuggest();
+     parser.suggestAnalyticFunctions();
+     parser.suggestSelectListAliases();
+   }
+ | OrderByColumnList ',' OrderByIdentifier_EDIT                        -> { emptyOrderBy: false }
+ | OrderByColumnList ',' OrderByIdentifier_EDIT ','                    -> { emptyOrderBy: false }
+ | OrderByColumnList ',' OrderByIdentifier_EDIT ',' OrderByColumnList  -> { emptyOrderBy: false }
+ ;
+
+OrderByIdentifier
+ : ValueExpression OptionalAscOrDesc OptionalNullsFirstOrLast  -> parser.mergeSuggestKeywords($2, $3)
+ ;
+
+OrderByIdentifier_EDIT
+ : ValueExpression_EDIT OptionalAscOrDesc OptionalNullsFirstOrLast
+   {
+     parser.suggestSelectListAliases();
+   }
+ | ValueExpression OptionalAscOrDesc NullsFirstOrLast_EDIT
+ | AnyCursor OptionalAscOrDesc OptionalNullsFirstOrLast
+   {
+     $$ = { emptyOrderBy: true }
+     parser.valueExpressionSuggest();
+     parser.suggestAnalyticFunctions();
+     parser.suggestSelectListAliases();
+   }
+ ;
+
+OptionalAscOrDesc
+ :
+  {
+    $$ = { suggestKeywords: ['ASC', 'DESC'] };
+  }
+ | 'ASC'
+ | 'DESC'
+ ;
+
+OptionalNullsFirstOrLast
+ :
+  {
+    $$ = { suggestKeywords: ['NULLS FIRST', 'NULLS LAST'] };
+  }
+ | 'NULLS' 'FIRST'
+ | 'NULLS' 'LAST'
+ ;
+
+NullsFirstOrLast_EDIT
+ : 'NULLS' 'CURSOR'
+   {
+     parser.suggestKeywords(['FIRST', 'LAST']);
+   }
+ ;

+ 383 - 0
desktop/core/src/desktop/js/parse/jison/sql/impala/select/select.jison

@@ -0,0 +1,383 @@
+// Licensed to Cloudera, Inc. under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  Cloudera, Inc. licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+QuerySpecification
+ : SelectStatement OptionalUnions                                   -> $1
+ ;
+
+QuerySpecification_EDIT
+ : SelectStatement_EDIT OptionalUnions
+ | SelectStatement OptionalUnions_EDIT
+ ;
+
+SelectStatement
+ : 'SELECT' OptionalAllOrDistinct OptionalStraightJoin SelectList
+   {
+     parser.addClauseLocation('selectList', parser.firstDefined($3, @3, $2, @2, $1, @1), @4);
+     $$ = { selectList: $4 };
+   }
+ | 'SELECT' OptionalAllOrDistinct OptionalStraightJoin SelectList TableExpression
+   {
+     parser.addClauseLocation('selectList', parser.firstDefined($3, @3, $2, @2, $1, @1), @4);
+     $$ = { selectList: $4, tableExpression: $5 }
+   }
+ ;
+
+SelectStatement_EDIT
+ : 'SELECT' OptionalAllOrDistinct OptionalStraightJoin SelectList_EDIT
+   {
+     parser.addClauseLocation('selectList', parser.firstDefined($3, @3, $2, @2, $1, @1), @4);
+     if ($4.cursorAtStart) {
+       var keywords = parser.getSelectListKeywords();
+       if (!$3 && !$2) {
+         keywords.push({ value: 'ALL', weight: 2 });
+         keywords.push({ value: 'DISTINCT', weight: 2 });
+       }
+       if (!$3) {
+         keywords.push({ value: 'STRAIGHT_JOIN', weight: 1 });
+       }
+       parser.suggestKeywords(keywords);
+     } else {
+       parser.checkForSelectListKeywords($4);
+     }
+     if ($4.suggestFunctions) {
+       parser.suggestFunctions();
+     }
+     if ($4.suggestColumns) {
+       parser.suggestColumns({ identifierChain: [], source: 'select' });
+     }
+     if ($4.suggestTables) {
+       parser.suggestTables({ prependQuestionMark: true, prependFrom: true });
+     }
+     if ($4.suggestDatabases) {
+       parser.suggestDatabases({ prependQuestionMark: true, prependFrom: true, appendDot: true });
+     }
+     if ($4.suggestAggregateFunctions && (!$2 || $2 === 'ALL')) {
+       parser.suggestAggregateFunctions();
+       parser.suggestAnalyticFunctions();
+     }
+   }
+ | 'SELECT' OptionalAllOrDistinct OptionalStraightJoin 'CURSOR'
+   {
+     parser.addClauseLocation('selectList', parser.firstDefined($3, @3, $2, @2, $1, @1), @4, true);
+     var keywords = parser.getSelectListKeywords();
+     if (!$2 || $2 === 'ALL') {
+       parser.suggestAggregateFunctions();
+       parser.suggestAnalyticFunctions();
+     }
+     if (!$3 && !$2) {
+       keywords.push({ value: 'ALL', weight: 2 });
+       keywords.push({ value: 'DISTINCT', weight: 2 });
+     }
+     if (!$3) {
+       keywords.push({ value: 'STRAIGHT_JOIN', weight: 1 });
+     }
+     parser.suggestKeywords(keywords);
+     parser.suggestFunctions();
+     parser.suggestColumns({ identifierChain: [], source: 'select' });
+     parser.suggestTables({ prependQuestionMark: true, prependFrom: true });
+     parser.suggestDatabases({ prependQuestionMark: true, prependFrom: true, appendDot: true });
+   }
+ | 'SELECT' OptionalAllOrDistinct OptionalStraightJoin SelectList TableExpression_EDIT
+   {
+     parser.addClauseLocation('selectList', parser.firstDefined($3, @3, $2, @2, $1, @1), @4);
+   }
+ | 'SELECT' OptionalAllOrDistinct OptionalStraightJoin SelectList_EDIT TableExpression
+   {
+     parser.addClauseLocation('selectList', parser.firstDefined($3, @3, $2, @2, $1, @1), @4);
+     parser.selectListNoTableSuggest($4, $2);
+     if (parser.yy.result.suggestColumns) {
+       parser.yy.result.suggestColumns.source = 'select';
+     }
+   }
+ | 'SELECT' OptionalAllOrDistinct OptionalStraightJoin 'CURSOR' TableExpression
+   {
+     parser.addClauseLocation('selectList', parser.firstDefined($3, @3, $2, @2, $1, @1), @4, true);
+     var keywords = parser.getSelectListKeywords();
+     if (!$2 || $2 === 'ALL') {
+       parser.suggestAggregateFunctions();
+       parser.suggestAnalyticFunctions();
+     }
+     if (!$3 && !$2) {
+       keywords.push({ value: 'ALL', weight: 2 });
+       keywords.push({ value: 'DISTINCT', weight: 2 });
+     }
+     if (!$3) {
+       keywords.push({ value: 'STRAIGHT_JOIN', weight: 1 });
+     }
+     parser.suggestKeywords(keywords);
+     parser.suggestFunctions();
+     parser.suggestColumns({ identifierChain: [], source: 'select' });
+     parser.suggestTables({ prependQuestionMark: true, prependFrom: true });
+     parser.suggestDatabases({ prependQuestionMark: true, prependFrom: true, appendDot: true });
+   }
+ | 'SELECT' OptionalAllOrDistinct OptionalStraightJoin SelectList 'CURSOR' TableExpression
+   {
+     parser.addClauseLocation('selectList', parser.firstDefined($3, @3, $2, @2, $1, @1), @4);
+     parser.checkForSelectListKeywords($4);
+   }
+ | 'SELECT' OptionalAllOrDistinct OptionalStraightJoin SelectList 'CURSOR' ',' TableExpression
+   {
+     parser.addClauseLocation('selectList', parser.firstDefined($3, @3, $2, @2, $1, @1), @4);
+     parser.checkForSelectListKeywords($4);
+   }
+ | 'SELECT' OptionalAllOrDistinct OptionalStraightJoin SelectList 'CURSOR'
+   {
+     parser.addClauseLocation('selectList', parser.firstDefined($3, @3, $2, @2, $1, @1), @4);
+     parser.checkForSelectListKeywords($4);
+     var keywords = ['FROM'];
+     if (parser.yy.result.suggestKeywords) {
+       keywords = parser.yy.result.suggestKeywords.concat(keywords);
+     }
+     parser.suggestKeywords(keywords);
+     parser.suggestTables({ prependFrom: true });
+     parser.suggestDatabases({ prependFrom: true, appendDot: true });
+   }
+ ;
+
+OptionalAllOrDistinct
+ :
+ | 'ALL'
+ | 'DISTINCT'
+ ;
+
+TableExpression
+ : FromClause OptionalSelectConditions
+   {
+     parser.addClauseLocation('whereClause', @1, $2.whereClauseLocation);
+     parser.addClauseLocation('limitClause', $2.limitClausePreceding || @1, $2.limitClauseLocation);
+   }
+ ;
+
+TableExpression_EDIT
+ : FromClause_EDIT OptionalSelectConditions
+   {
+     parser.addClauseLocation('whereClause', @1, $2.whereClauseLocation);
+     parser.addClauseLocation('limitClause', $2.limitClausePreceding || @1, $2.limitClauseLocation);
+   }
+ | FromClause 'CURSOR' OptionalSelectConditions OptionalJoins
+   {
+     var keywords = [];
+
+     parser.addClauseLocation('whereClause', @1, $3.whereClauseLocation);
+     parser.addClauseLocation('limitClause', $2.limitClausePreceding || @1, $2.limitClauseLocation);
+
+     if ($1) {
+       if (typeof $1.tableReferenceList.hasJoinCondition !== 'undefined' && !$1.tableReferenceList.hasJoinCondition) {
+         keywords.push({ value: 'ON', weight: 3 });
+         keywords.push({ value: 'USING', weight: 3 });
+       }
+       if ($1.suggestKeywords) {
+         keywords = parser.createWeightedKeywords($1.suggestKeywords, 3);
+       }
+       if ($1.tableReferenceList.suggestJoinConditions) {
+         parser.suggestJoinConditions($1.tableReferenceList.suggestJoinConditions);
+       }
+       if ($1.tableReferenceList.suggestJoins) {
+         parser.suggestJoins($1.tableReferenceList.suggestJoins);
+       }
+       if ($1.tableReferenceList.suggestKeywords) {
+         keywords = keywords.concat(parser.createWeightedKeywords($1.tableReferenceList.suggestKeywords, 3));
+       }
+
+       // Lower the weights for 'TABLESAMPLE' and 'LATERAL VIEW'
+       keywords.forEach(function (keyword) {
+         if (keyword.value === 'TABLESAMPLE' || keyword.value === 'LATERAL VIEW') {
+           keyword.weight = 1.1;
+         }
+       });
+
+       if ($1.tableReferenceList.types) {
+         var veKeywords = parser.getValueExpressionKeywords($1.tableReferenceList);
+         keywords = keywords.concat(veKeywords.suggestKeywords);
+         if (veKeywords.suggestColRefKeywords) {
+           parser.suggestColRefKeywords(veKeywords.suggestColRefKeywords);
+           parser.addColRefIfExists($1.tableReferenceList);
+         }
+       }
+     }
+
+     if ($3.empty && $4 && $4.joinType.toUpperCase() === 'JOIN') {
+       keywords = keywords.concat(['FULL', 'FULL OUTER', 'LEFT', 'LEFT OUTER', 'RIGHT', 'RIGHT OUTER']);
+       keywords = keywords.concat(['ANTI', 'CROSS', 'INNER', 'LEFT ANTI', 'LEFT INNER', 'LEFT SEMI', 'OUTER', 'RIGHT ANTI', 'RIGHT INNER', 'RIGHT SEMI', 'SEMI']);
+       parser.suggestKeywords(keywords);
+       return;
+     }
+
+     if ($3.suggestKeywords) {
+       keywords = keywords.concat(parser.createWeightedKeywords($3.suggestKeywords, 2));
+     }
+
+     if ($3.suggestFilters) {
+       parser.suggestFilters($3.suggestFilters);
+     }
+     if ($3.suggestGroupBys) {
+       parser.suggestGroupBys($3.suggestGroupBys);
+     }
+     if ($3.suggestOrderBys) {
+       parser.suggestOrderBys($3.suggestOrderBys);
+     }
+
+     if ($3.empty) {
+       keywords.push({ value: 'UNION', weight: 2.11 });
+     }
+
+     keywords = keywords.concat([
+       { value: 'ANTI JOIN', weight: 1 },
+       { value: 'FULL JOIN', weight: 1 },
+       { value: 'FULL OUTER JOIN', weight: 1 },
+       { value: 'INNER JOIN', weight: 1 },
+       { value: 'JOIN', weight: 1 },
+       { value: 'LEFT ANTI JOIN', weight: 1 },
+       { value: 'LEFT INNER JOIN', weight: 1 },
+       { value: 'LEFT JOIN', weight: 1 },
+       { value: 'LEFT OUTER JOIN', weight: 1 },
+       { value: 'LEFT SEMI JOIN', weight: 1 },
+       { value: 'OUTER JOIN', weight: 1 },
+       { value: 'RIGHT ANTI JOIN', weight: 1 },
+       { value: 'RIGHT INNER JOIN', weight: 1 },
+       { value: 'RIGHT JOIN', weight: 1 },
+       { value: 'RIGHT OUTER JOIN', weight: 1 },
+       { value: 'RIGHT SEMI JOIN', weight: 1 },
+       { value: 'SEMI JOIN', weight: 1 }
+     ]);
+     parser.suggestKeywords(keywords);
+  }
+ | FromClause OptionalSelectConditions_EDIT OptionalJoins
+   {
+     // A couple of things are going on here:
+     // - If there are no SelectConditions (WHERE, GROUP BY, etc.) we should suggest complete join options
+     // - If there's an OptionalJoin at the end, i.e. 'SELECT * FROM foo | JOIN ...' we should suggest
+     //   different join types
+     // - The FromClause could end with a valueExpression, in which case we should suggest keywords like '='
+     //   or 'AND' based on type
+
+     if (!$2) {
+       parser.addClauseLocation('whereClause', @1);
+       parser.addClauseLocation('limitClause', @1);
+       return;
+     }
+     parser.addClauseLocation('whereClause', @1, $2.whereClauseLocation);
+     parser.addClauseLocation('limitClause', $2.limitClausePreceding || @1, $2.limitClauseLocation);
+     var keywords = [];
+
+     if ($2.suggestColRefKeywords) {
+       parser.suggestColRefKeywords($2.suggestColRefKeywords);
+       parser.addColRefIfExists($2);
+     }
+
+     if ($2.suggestKeywords && $2.suggestKeywords.length) {
+       keywords = keywords.concat(parser.createWeightedKeywords($2.suggestKeywords, 2));
+     }
+
+     if ($2.cursorAtEnd) {
+       keywords.push({ value: 'UNION', weight: 2.11 });
+     }
+     parser.suggestKeywords(keywords);
+   }
+ ;
+
+SelectList
+ : SelectSpecification                 -> [ $1 ]
+ | SelectList ',' SelectSpecification
+   {
+     $1.push($3);
+   }
+ ;
+
+SelectList_EDIT
+ : SelectSpecification_EDIT
+ | 'CURSOR' SelectList
+   {
+     $$ = { cursorAtStart : true, suggestFunctions: true, suggestColumns: true, suggestAggregateFunctions: true };
+   }
+ | 'CURSOR' ',' SelectList
+   {
+     $$ = { cursorAtStart : true, suggestFunctions: true, suggestColumns: true, suggestAggregateFunctions: true };
+   }
+ | SelectSpecification_EDIT ',' SelectList
+ | SelectList 'CURSOR' SelectList
+   {
+     parser.checkForSelectListKeywords($1);
+   }
+ | SelectList 'CURSOR' ',' SelectList
+   {
+     parser.checkForSelectListKeywords($1);
+   }
+ | SelectList ',' AnyCursor
+   {
+     $$ = { suggestKeywords: parser.getSelectListKeywords(), suggestTables: true, suggestDatabases: true, suggestFunctions: true, suggestColumns: true, suggestAggregateFunctions: true };
+   }
+ | SelectList ',' SelectSpecification_EDIT                 -> $3
+ | SelectList ',' AnyCursor SelectList
+   {
+     $$ = { suggestKeywords: parser.getSelectListKeywords(), suggestFunctions: true, suggestColumns: true, suggestAggregateFunctions: true,  };
+   }
+ | SelectList ',' AnyCursor ','
+   {
+     $$ = { suggestKeywords: parser.getSelectListKeywords(), suggestFunctions: true, suggestColumns: true, suggestAggregateFunctions: true,  };
+   }
+ | SelectList ',' SelectSpecification_EDIT ','             -> $3
+ | SelectList ',' AnyCursor ',' SelectList
+   {
+     $$ = { suggestKeywords: parser.getSelectListKeywords(), suggestFunctions: true, suggestColumns: true, suggestAggregateFunctions: true,  };
+   }
+ | SelectList ',' SelectSpecification_EDIT ',' SelectList  -> $3
+ ;
+
+SelectSpecification
+ : ValueExpression OptionalCorrelationName
+   {
+     if ($2) {
+       parser.addColumnAliasLocation($2.location, $2.alias, @1);
+       $$ = { valueExpression: $1, alias: $2.alias };
+       if (!parser.yy.selectListAliases) {
+         parser.yy.selectListAliases = [];
+       }
+       parser.yy.selectListAliases.push($1.function && $1.types && $1.types.length && $1.types[0] === 'UDFREF' ? { name: $2.alias, udfRef: $1.function, types: $1.types } : { name: $2.alias, types: $1.types || ['T'] });
+     } else {
+       $$ = { valueExpression: $1 }
+     }
+   }
+ | '*'
+   {
+     parser.addAsteriskLocation(@1, [{ asterisk: true }]);
+     $$ = { asterisk: true }
+   }
+ ;
+
+SelectSpecification_EDIT
+ : ValueExpression_EDIT OptionalCorrelationName
+   {
+     if ($2) {
+       parser.addColumnAliasLocation($2.location, $2.alias, @1);
+     }
+   }
+
+ | AnyCursor 'AS' RegularOrBacktickedIdentifier
+   {
+     parser.suggestFunctions();
+     parser.suggestColumns();
+     parser.addColumnAliasLocation(@3, $3, @1);
+     $$ = { suggestAggregateFunctions: true };
+   }
+ | ValueExpression OptionalCorrelationName_EDIT  -> $2
+ ;
+
+OptionalStraightJoin
+ :
+ | 'STRAIGHT_JOIN'
+ ;

+ 159 - 0
desktop/core/src/desktop/js/parse/jison/sql/impala/select/select_conditions.jison

@@ -0,0 +1,159 @@
+// Licensed to Cloudera, Inc. under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  Cloudera, Inc. licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+OptionalSelectConditions
+ : OptionalWhereClause OptionalGroupByClause OptionalHavingClause OptionalOrderByClause OptionalLimitClause OptionalOffsetClause
+   {
+     var keywords = parser.getKeywordsForOptionalsLR(
+       [$1, $2, $3, $4, $5, $6],
+       [{ value: 'WHERE', weight: 9 },
+        { value: 'GROUP BY', weight: 8 },
+        { value: 'HAVING', weight: 7 },
+        { value: 'ORDER BY', weight: 5 },
+        { value: 'LIMIT', weight: 3 },
+        { value: 'OFFSET', weight: 2 }],
+       [true, true, true, true, true, true]);
+
+     if (keywords.length > 0) {
+       $$ = { suggestKeywords: keywords, empty: !$1 && !$2 && !$3 && !$4 && !$5 && !$6 };
+     } else {
+       $$ = {};
+     }
+
+     $$.whereClauseLocation = $1 ? @1 : undefined;
+     $$.limitClausePreceding = parser.firstDefined($4, @4, $3, @3, $2, @2, $1, @1);
+     $$.limitClauseLocation = $5 ? @5 : undefined;
+
+     if (!$1 && !$2 && !$3 && !$4 && !$5 && !$6) {
+       $$.suggestFilters = { prefix: 'WHERE', tablePrimaries: parser.yy.latestTablePrimaries.concat() };
+     }
+     if (!$2 && !$3 && !$4 && !$5 && !$6) {
+       $$.suggestGroupBys = { prefix: 'GROUP BY', tablePrimaries: parser.yy.latestTablePrimaries.concat() };
+     }
+     if (!$4 && !$5 && !$6) {
+       $$.suggestOrderBys = { prefix: 'ORDER BY', tablePrimaries: parser.yy.latestTablePrimaries.concat() };
+     }
+   }
+ ;
+
+OptionalSelectConditions_EDIT
+ : WhereClause_EDIT OptionalGroupByClause OptionalHavingClause OptionalOrderByClause OptionalLimitClause OptionalOffsetClause
+   {
+     if (parser.yy.result.suggestColumns) {
+       parser.yy.result.suggestColumns.source = 'where';
+     }
+   }
+ | OptionalWhereClause GroupByClause_EDIT OptionalHavingClause OptionalOrderByClause OptionalLimitClause OptionalOffsetClause
+   {
+     if (parser.yy.result.suggestColumns) {
+       parser.yy.result.suggestColumns.source = 'group by';
+     }
+   }
+ | OptionalWhereClause OptionalGroupByClause HavingClause_EDIT OptionalOrderByClause OptionalLimitClause OptionalOffsetClause
+ | OptionalWhereClause OptionalGroupByClause OptionalHavingClause OrderByClause_EDIT OptionalLimitClause OptionalOffsetClause
+   {
+     if (parser.yy.result.suggestColumns) {
+       parser.yy.result.suggestColumns.source = 'order by';
+     }
+   }
+ | OptionalWhereClause OptionalGroupByClause OptionalHavingClause OptionalOrderByClause LimitClause_EDIT OptionalOffsetClause
+ | OptionalWhereClause OptionalGroupByClause OptionalHavingClause OptionalOrderByClause OptionalLimitClause OffsetClause_EDIT
+ ;
+
+OptionalSelectConditions_EDIT
+ : WhereClause 'CURSOR' OptionalGroupByClause OptionalHavingClause OptionalOrderByClause OptionalLimitClause OptionalOffsetClause
+   {
+     var keywords = parser.getKeywordsForOptionalsLR(
+       [$3, $4, $5, $6, $7],
+       [{ value: 'GROUP BY', weight: 6 }, { value: 'HAVING', weight: 5 }, { value: 'ORDER BY', weight: 4 },  { value: 'LIMIT', weight: 3 }, { value: 'OFFSET', weight: 2 }],
+       [true, true, true, true, true]);
+     if ($1.suggestKeywords) {
+       keywords = keywords.concat(parser.createWeightedKeywords($1.suggestKeywords, 1));
+     }
+     $$ = parser.getValueExpressionKeywords($1, keywords);
+     $$.cursorAtEnd = !$3 && !$4 && !$5 && !$6 && !$7;
+     if ($1.columnReference) {
+       $$.columnReference = $1.columnReference;
+     }
+     if (!$3) {
+       parser.suggestGroupBys({ prefix: 'GROUP BY', tablePrimaries: parser.yy.latestTablePrimaries.concat() });
+     }
+     if (!$3 && !$4 && !$5) {
+       parser.suggestOrderBys({ prefix: 'ORDER BY', tablePrimaries: parser.yy.latestTablePrimaries.concat() });
+     }
+     $$.whereClauseLocation = $1 ? @1 : undefined;
+     $$.limitClausePreceding = parser.firstDefined($5, @5, $4, @4, $3, @3, $1, @1);
+     $$.limitClauseLocation = $6 ? @6 : undefined;
+   }
+ | OptionalWhereClause GroupByClause 'CURSOR' OptionalHavingClause OptionalOrderByClause OptionalLimitClause OptionalOffsetClause
+   {
+     var keywords = parser.getKeywordsForOptionalsLR(
+       [$4, $5, $6, $7],
+       [{ value: 'HAVING', weight: 5 }, { value: 'ORDER BY', weight: 4 }, { value: 'LIMIT', weight: 3 }, { value: 'OFFSET', weight: 2 }],
+       [true, true, true, true]);
+     if ($2.suggestKeywords) {
+       keywords = keywords.concat(parser.createWeightedKeywords($2.suggestKeywords, 6));
+     }
+     if ($2.valueExpression) {
+       $$ = parser.getValueExpressionKeywords($2.valueExpression, keywords);
+       if ($2.valueExpression.columnReference) {
+         $$.columnReference = $2.valueExpression.columnReference;
+       }
+     } else {
+       $$ = { suggestKeywords: keywords };
+     }
+     $$.cursorAtEnd = !$4 && !$5 && !$6 && !$7;
+     if (!$4 && !$5) {
+       parser.suggestOrderBys({ prefix: 'ORDER BY', tablePrimaries: parser.yy.latestTablePrimaries.concat() });
+     }
+     $$.whereClauseLocation = $1 ? @1 : undefined;
+     $$.limitClausePreceding = parser.firstDefined($5, @5, $4, @4, $2, @2);
+     $$.limitClauseLocation = $6 ? @6 : undefined;
+   }
+ | OptionalWhereClause OptionalGroupByClause HavingClause 'CURSOR' OptionalOrderByClause OptionalLimitClause OptionalOffsetClause
+   {
+     var keywords = parser.getKeywordsForOptionalsLR(
+       [$5, $6, $7],
+       [{ value: 'ORDER BY', weight: 5 }, { value: 'LIMIT', weight: 3 }, { value: 'OFFSET', weight: 2 }],
+       [true, true, true]);
+     $$ = { suggestKeywords: keywords, cursorAtEnd: !$5 && !$6 && !$7 };
+     if (!$5) {
+       parser.suggestOrderBys({ prefix: 'ORDER BY', tablePrimaries: parser.yy.latestTablePrimaries.concat() });
+     }
+     $$.whereClauseLocation = $1 ? @1 : undefined;
+     $$.limitClausePreceding = parser.firstDefined($5, @5, $3, @3);
+     $$.limitClauseLocation = $6 ? @6 : undefined;
+   }
+ | OptionalWhereClause OptionalGroupByClause OptionalHavingClause OrderByClause 'CURSOR' OptionalLimitClause OptionalOffsetClause
+   {
+     var keywords = parser.getKeywordsForOptionalsLR([$6, $7], [{ value: 'LIMIT', weight: 3 }, { value: 'OFFSET', weight: 2 }], [true, true]);
+     if ($4.suggestKeywords) {
+       keywords = keywords.concat(parser.createWeightedKeywords($4.suggestKeywords, 4));
+     }
+     $$ = { suggestKeywords: keywords, cursorAtEnd: !$6 && !$7 };
+     $$.whereClauseLocation = $1 ? @1 : undefined;
+     $$.limitClausePreceding = parser.firstDefined($4, @4);
+     $$.limitClauseLocation = $6 ? @6 : undefined;
+   }
+ | OptionalWhereClause OptionalGroupByClause OptionalHavingClause OptionalOrderByClause LimitClause 'CURSOR' OptionalOffsetClause
+   {
+     var keywords = parser.getKeywordsForOptionalsLR([$7], [{ value: 'OFFSET', weight: 2 }], [true]);
+     $$ = { suggestKeywords: keywords, cursorAtEnd: !$7 };
+     $$.whereClauseLocation = $1 ? @1 : undefined;
+     $$.limitClausePreceding = parser.firstDefined($4, @4, $3, @3, $2, @2, $1, @1);
+     $$.limitClauseLocation = @5;
+   }
+ ;

File diff suppressed because it is too large
+ 0 - 983
desktop/core/src/desktop/js/parse/jison/sql/impala/sql_main.jison


+ 28 - 0
desktop/core/src/desktop/js/parse/jison/sql/impala/structure.json

@@ -16,6 +16,8 @@
     "create/create_table.jison",
     "create/create_view.jison",
     "delete/delete.jison",
+    "describe/describe.jison",
+    "describe/describe_database.jison",
     "drop/drop_aggregate_function.jison",
     "drop/drop_common.jison",
     "drop/drop_database.jison",
@@ -37,6 +39,18 @@
     "revoke/revoke_common.jison",
     "revoke/revoke_on.jison",
     "revoke/revoke_role.jison",
+    "../generic/select/cte_select_statement.jison",
+    "../generic/select/from_clause.jison",
+    "../generic/select/group_by_clause.jison",
+    "../generic/select/having_clause.jison",
+    "select/joins.jison",
+    "select/limit_clause.jison",
+    "select/offset_clause.jison",
+    "select/order_by_clause.jison",
+    "select/select.jison",
+    "select/select_conditions.jison",
+    "../generic/select/union_clause.jison",
+    "../generic/select/where_clause.jison",
     "set/set.jison",
     "show/show_column_stats.jison",
     "show/show_common.jison",
@@ -105,6 +119,8 @@
     "create/create_table.jison",
     "create/create_view.jison",
     "delete/delete.jison",
+    "describe/describe.jison",
+    "describe/describe_database.jison",
     "drop/drop_aggregate_function.jison",
     "drop/drop_common.jison",
     "drop/drop_database.jison",
@@ -126,6 +142,18 @@
     "revoke/revoke_common.jison",
     "revoke/revoke_on.jison",
     "revoke/revoke_role.jison",
+    "../generic/select/cte_select_statement.jison",
+    "../generic/select/from_clause.jison",
+    "../generic/select/group_by_clause.jison",
+    "../generic/select/having_clause.jison",
+    "select/joins.jison",
+    "select/limit_clause.jison",
+    "select/offset_clause.jison",
+    "select/order_by_clause.jison",
+    "select/select.jison",
+    "select/select_conditions.jison",
+    "../generic/select/union_clause.jison",
+    "../generic/select/where_clause.jison",
     "set/set.jison",
     "show/show_column_stats.jison",
     "show/show_common.jison",

File diff suppressed because it is too large
+ 0 - 0
desktop/core/src/desktop/js/parse/sql/impala/impalaAutocompleteParser.js


File diff suppressed because it is too large
+ 0 - 0
desktop/core/src/desktop/js/parse/sql/impala/impalaSyntaxParser.js


+ 52 - 4
desktop/core/src/desktop/js/parse/sql/impala/sqlParseSupport.js

@@ -26,11 +26,59 @@ import {
 const initSqlParser = function (parser) {
   initSharedAutocomplete(parser);
 
+  parser.DESCRIBE_KEYWORDS = [
+    { value: 'DATABASE', weight: 2 },
+    { value: 'EXTENDED', weight: 1 },
+    { value: 'FORMATTED', weight: 1 }
+  ];
   parser.GRANT_KEYWORDS = ['ALL', 'ALTER', 'CREATE', 'DROP', 'INSERT', 'REFRESH', 'ROLE', 'SELECT'];
-  parser.REVOKE_KEYWORDS = ['ALL', 'ALTER', 'CREATE', 'DROP', 'INSERT', 'REFRESH', 'ROLE', 'SELECT'];
-  parser.SHOW_KEYWORDS = ['AGGREGATE FUNCTIONS', 'ANALYTIC FUNCTIONS', 'COLUMN STATS', 'CREATE TABLE', 'CURRENT ROLES', 'CREATE VIEW', 'DATABASES', 'FILES IN', 'FUNCTIONS', 'GRANT ROLE', 'GRANT USER', 'PARTITIONS', 'RANGE PARTITIONS', 'ROLE GRANT GROUP', 'ROLES', 'SCHEMAS', 'TABLE STATS', 'TABLES'];
-  parser.SHOW_IDENTIFIER_KEYWORDS = ['COLUMN STATS', 'CREATE TABLE', 'CREATE VIEW', 'FILES IN', 'PARTITIONS', 'RANGE PARTITIONS', 'TABLE STATS'];
-  parser.SHOW_LIKE_KEYWORDS = ['AGGREGATE FUNCTIONS', 'ANALYTIC FUNCTIONS', 'DATABASES', 'FUNCTIONS', 'SCHEMAS', 'TABLES'];
+  parser.REVOKE_KEYWORDS = [
+    'ALL',
+    'ALTER',
+    'CREATE',
+    'DROP',
+    'INSERT',
+    'REFRESH',
+    'ROLE',
+    'SELECT'
+  ];
+  parser.SHOW_KEYWORDS = [
+    'AGGREGATE FUNCTIONS',
+    'ANALYTIC FUNCTIONS',
+    'COLUMN STATS',
+    'CREATE TABLE',
+    'CURRENT ROLES',
+    'CREATE VIEW',
+    'DATABASES',
+    'FILES IN',
+    'FUNCTIONS',
+    'GRANT ROLE',
+    'GRANT USER',
+    'PARTITIONS',
+    'RANGE PARTITIONS',
+    'ROLE GRANT GROUP',
+    'ROLES',
+    'SCHEMAS',
+    'TABLE STATS',
+    'TABLES'
+  ];
+  parser.SHOW_IDENTIFIER_KEYWORDS = [
+    'COLUMN STATS',
+    'CREATE TABLE',
+    'CREATE VIEW',
+    'FILES IN',
+    'PARTITIONS',
+    'RANGE PARTITIONS',
+    'TABLE STATS'
+  ];
+  parser.SHOW_LIKE_KEYWORDS = [
+    'AGGREGATE FUNCTIONS',
+    'ANALYTIC FUNCTIONS',
+    'DATABASES',
+    'FUNCTIONS',
+    'SCHEMAS',
+    'TABLES'
+  ];
 
   parser.prepareNewStatement = function () {
     linkTablePrimaries();

Some files were not shown because too many files changed in this diff