Bläddra i källkod

[flink] Describe Function autocomplete for flink (#1684)

* [flink] Describe Function autocomplete for flink
Asnaik HWX 4 år sedan
förälder
incheckning
870f7b19ec

+ 51 - 0
desktop/core/src/desktop/js/parse/jison/sql/calcite/describe/describe_table.jison

@@ -0,0 +1,51 @@
+// 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' SchemaQualifiedTableIdentifier
+   {
+     parser.addTablePrimary($2);
+   }
+ | 'DESCRIBE' RegularOrBacktickedIdentifier '.' SchemaQualifiedTableIdentifier
+   {
+     parser.addTablePrimary($4);
+   }
+ ;
+
+DescribeStatement_EDIT
+ : 'DESCRIBE' 'CURSOR'
+   {
+     parser.suggestTables();
+     parser.suggestDatabases({ appendDot: true });
+   }
+ | 'DESCRIBE' SchemaQualifiedTableIdentifier_EDIT
+ | 'DESCRIBE' 'CURSOR' SchemaQualifiedTableIdentifier
+   {
+     parser.addTablePrimary($3);
+   }
+ | 'DESCRIBE' RegularOrBacktickedIdentifier '.' SchemaQualifiedTableIdentifier 
+   {
+     parser.addTablePrimary($4);
+   }
+ ;

+ 1 - 0
desktop/core/src/desktop/js/parse/jison/sql/calcite/sql.jisonlex

@@ -48,6 +48,7 @@
 'DATABASE'                                 { return 'DATABASE'; }
 'DECIMAL'                                  { return 'DECIMAL'; }
 'DESC'                                     { return 'DESC'; }
+'DESCRIBE'                                 { parser.determineCase(yytext); parser.addStatementTypeLocation('DESCRIBE', yylloc); return 'DESCRIBE'; }
 'DISTINCT'                                 { return 'DISTINCT'; }
 'DIV'                                      { return 'ARITHMETIC_OPERATOR'; }
 'DOUBLE'                                   { return 'DOUBLE'; }

+ 2 - 0
desktop/core/src/desktop/js/parse/jison/sql/calcite/structure.json

@@ -55,6 +55,7 @@
     "select/select_stream.jison",
     "../generic/sql_error.jison",
     "../generic/sql_valueExpression.jison",
+    "describe/describe_table.jison",
     "../generic/autocomplete_footer.jison"
   ],
   "syntax": [
@@ -111,6 +112,7 @@
     "../generic/sql_main.jison",
     "select/select_stream.jison",
     "../generic/sql_valueExpression.jison",
+    "describe/describe_table.jison",
     "../generic/syntax_footer.jison"
   ]
 }

+ 0 - 0
desktop/core/src/desktop/js/parse/jison/sql/flink/sql_show.jison → desktop/core/src/desktop/js/parse/jison/sql/flink/show/sql_show.jison


+ 227 - 0
desktop/core/src/desktop/js/parse/jison/sql/flink/sql.jisonlex

@@ -0,0 +1,227 @@
+// 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.
+
+%options case-insensitive flex
+%s between
+%x hdfs doubleQuotedValue singleQuotedValue backtickedValue
+%%
+
+\s                                         { /* skip whitespace */ }
+'--'.*                                     { /* skip comments */ }
+[/][*][^*]*[*]+([^/*][^*]*[*]+)*[/]        { /* skip comments */ }
+
+'\u2020'                                   { parser.yy.partialCursor = false; parser.yy.cursorFound = yylloc; return 'CURSOR'; }
+'\u2021'                                   { parser.yy.partialCursor = true; parser.yy.cursorFound = yylloc; return 'PARTIAL_CURSOR'; }
+
+<between>'AND'                             { this.popState(); return 'BETWEEN_AND'; }
+
+// Reserved Keywords
+'ALL'                                      { return 'ALL'; }
+'ALTER'                                    { parser.determineCase(yytext); parser.addStatementTypeLocation('ALTER', yylloc, yy.lexer.upcomingInput()); return 'ALTER'; }
+'AND'                                      { return 'AND'; }
+'AS'                                       { return 'AS'; }
+'ASC'                                      { return 'ASC'; }
+'BETWEEN'                                  { this.begin('between'); return 'BETWEEN'; }
+'BIGINT'                                   { return 'BIGINT'; }
+'BOOLEAN'                                  { return 'BOOLEAN'; }
+'BY'                                       { return 'BY'; }
+'CASCADE'                                  { return 'CASCADE'; }
+'CASE'                                     { return 'CASE'; }
+'CHAR'                                     { return 'CHAR'; }
+'COMMENT'                                  { return 'COMMENT'; }
+'CREATE'                                   { parser.determineCase(yytext); return 'CREATE'; }
+'CROSS'                                    { return 'CROSS'; }
+'CURRENT'                                  { return 'CURRENT'; }
+'DATABASE'                                 { return 'DATABASE'; }
+'DECIMAL'                                  { return 'DECIMAL'; }
+'DESC'                                     { return 'DESC'; }
+'DESCRIBE'                                 { parser.determineCase(yytext); parser.addStatementTypeLocation('DESCRIBE', yylloc); return 'DESCRIBE'; }
+'DISTINCT'                                 { return 'DISTINCT'; }
+'DIV'                                      { return 'ARITHMETIC_OPERATOR'; }
+'DOUBLE'                                   { return 'DOUBLE'; }
+'DROP'                                     { parser.determineCase(yytext); parser.addStatementTypeLocation('DROP', yylloc, yy.lexer.upcomingInput()); return 'DROP'; }
+'ELSE'                                     { return 'ELSE'; }
+'END'                                      { return 'END'; }
+'EXISTS'                                   { parser.yy.correlatedSubQuery = true; return 'EXISTS'; }
+'FALSE'                                    { return 'FALSE'; }
+'FLOAT'                                    { return 'FLOAT'; }
+'FOLLOWING'                                { return 'FOLLOWING'; }
+'FROM'                                     { parser.determineCase(yytext); return 'FROM'; }
+'FULL'                                     { return 'FULL'; }
+'GROUP'                                    { return 'GROUP'; }
+'HAVING'                                   { return 'HAVING'; }
+'IF'                                       { return 'IF'; }
+'IN'                                       { return 'IN'; }
+'INNER'                                    { return 'INNER'; }
+'INSERT'                                   { return 'INSERT'; }
+'INT'                                      { return 'INT'; }
+'INTO'                                     { return 'INTO'; }
+'IS'                                       { return 'IS'; }
+'JOIN'                                     { return 'JOIN'; }
+'LEFT'                                     { return 'LEFT'; }
+'LIKE'                                     { return 'LIKE'; }
+'LIMIT'                                    { return 'LIMIT'; }
+'NOT'                                      { return 'NOT'; }
+'NULL'                                     { return 'NULL'; }
+'ON'                                       { return 'ON'; }
+'OPTION'                                   { return 'OPTION'; }
+'OR'                                       { return 'OR'; }
+'ORDER'                                    { return 'ORDER'; }
+'OUTER'                                    { return 'OUTER'; }
+'PARTITION'                                { return 'PARTITION'; }
+'PRECEDING'                                { return 'PRECEDING'; }
+'PURGE'                                    { return 'PURGE'; }
+'RANGE'                                    { return 'RANGE'; }
+'REGEXP'                                   { return 'REGEXP'; }
+'RIGHT'                                    { return 'RIGHT'; }
+'RLIKE'                                    { return 'RLIKE'; }
+'ROW'                                      { return 'ROW'; }
+'ROLE'                                     { return 'ROLE'; }
+'ROWS'                                     { return 'ROWS'; }
+'SCHEMA'                                   { return 'SCHEMA'; }
+'SELECT'                                   { parser.determineCase(yytext); parser.addStatementTypeLocation('SELECT', yylloc); return 'SELECT'; }
+'SEMI'                                     { return 'SEMI'; }
+'SET'                                      { parser.determineCase(yytext); parser.addStatementTypeLocation('SET', yylloc); return 'SET'; }
+'SHOW'                                     { parser.determineCase(yytext); parser.addStatementTypeLocation('SHOW', yylloc); return 'SHOW'; }
+'SMALLINT'                                 { return 'SMALLINT'; }
+'STRING'                                   { return 'STRING'; }
+'TABLE'                                    { return 'TABLE'; }
+'THEN'                                     { return 'THEN'; }
+'TIMESTAMP'                                { return 'TIMESTAMP'; }
+'TINYINT'                                  { return 'TINYINT'; }
+'TO'                                       { return 'TO'; }
+'TRUE'                                     { return 'TRUE'; }
+'TRUNCATE'                                 { parser.determineCase(yytext); parser.addStatementTypeLocation('TRUNCATE', yylloc, yy.lexer.upcomingInput()); return 'TRUNCATE'; }
+'UNBOUNDED'                                { return 'UNBOUNDED'; }
+'UNION'                                    { return 'UNION'; }
+'UPDATE'                                   { parser.determineCase(yytext); return 'UPDATE'; }
+'USE'                                      { parser.determineCase(yytext); parser.addStatementTypeLocation('USE', yylloc); return 'USE'; }
+'VALUES'                                   { return 'VALUES'; }
+'VARCHAR'                                  { return 'VARCHAR'; }
+'VIEW'                                     { return 'VIEW'; }
+'WHEN'                                     { return 'WHEN'; }
+'WHERE'                                    { return 'WHERE'; }
+'WITH'                                     { parser.determineCase(yytext); parser.addStatementTypeLocation('WITH', yylloc); return 'WITH'; }
+
+// Non-reserved Keywords
+'OVER'                                     { return 'OVER'; }
+'ROLE'                                     { return 'ROLE'; }
+
+// --- UDFs ---
+AVG\s*\(                                   { yy.lexer.unput('('); yytext = 'avg'; parser.addFunctionLocation(yylloc, yytext); return 'AVG'; }
+CAST\s*\(                                  { yy.lexer.unput('('); yytext = 'cast'; parser.addFunctionLocation(yylloc, yytext); return 'CAST'; }
+COUNT\s*\(                                 { yy.lexer.unput('('); yytext = 'count'; parser.addFunctionLocation(yylloc, yytext); return 'COUNT'; }
+MAX\s*\(                                   { yy.lexer.unput('('); yytext = 'max'; parser.addFunctionLocation(yylloc, yytext); return 'MAX'; }
+MIN\s*\(                                   { yy.lexer.unput('('); yytext = 'min'; parser.addFunctionLocation(yylloc, yytext); return 'MIN'; }
+STDDEV_POP\s*\(                            { yy.lexer.unput('('); yytext = 'stddev_pop'; parser.addFunctionLocation(yylloc, yytext); return 'STDDEV_POP'; }
+STDDEV_SAMP\s*\(                           { yy.lexer.unput('('); yytext = 'stddev_samp'; parser.addFunctionLocation(yylloc, yytext); return 'STDDEV_SAMP'; }
+SUM\s*\(                                   { yy.lexer.unput('('); yytext = 'sum'; parser.addFunctionLocation(yylloc, yytext); return 'SUM'; }
+VAR_POP\s*\(                               { yy.lexer.unput('('); yytext = 'var_pop'; parser.addFunctionLocation(yylloc, yytext); return 'VAR_POP'; }
+VAR_SAMP\s*\(                              { yy.lexer.unput('('); yytext = 'var_samp'; parser.addFunctionLocation(yylloc, yytext); return 'VAR_SAMP'; }
+VARIANCE\s*\(                              { yy.lexer.unput('('); yytext = 'variance'; parser.addFunctionLocation(yylloc, yytext); return 'VARIANCE'; }
+
+// Analytical functions
+CUME_DIST\s*\(                             { yy.lexer.unput('('); yytext = 'cume_dist'; parser.addFunctionLocation(yylloc, yytext); return 'ANALYTIC'; }
+DENSE_RANK\s*\(                            { yy.lexer.unput('('); yytext = 'dense_rank'; parser.addFunctionLocation(yylloc, yytext); return 'ANALYTIC'; }
+FIRST_VALUE\s*\(                           { yy.lexer.unput('('); yytext = 'first_value'; parser.addFunctionLocation(yylloc, yytext); return 'ANALYTIC'; }
+LAG\s*\(                                   { yy.lexer.unput('('); yytext = 'lag'; parser.addFunctionLocation(yylloc, yytext); return 'ANALYTIC'; }
+LAST_VALUE\s*\(                            { yy.lexer.unput('('); yytext = 'last_value'; parser.addFunctionLocation(yylloc, yytext); return 'ANALYTIC'; }
+LEAD\s*\(                                  { yy.lexer.unput('('); yytext = 'lead'; parser.addFunctionLocation(yylloc, yytext); return 'ANALYTIC'; }
+RANK\s*\(                                  { yy.lexer.unput('('); yytext = 'rank'; parser.addFunctionLocation(yylloc, yytext); return 'ANALYTIC'; }
+ROW_NUMBER\s*\(                            { yy.lexer.unput('('); yytext = 'row_number'; parser.addFunctionLocation(yylloc, yytext); return 'ANALYTIC'; }
+
+[0-9]+                                     { return 'UNSIGNED_INTEGER'; }
+[0-9]+(?:[YSL]|BD)?                        { return 'UNSIGNED_INTEGER'; }
+[0-9]+E                                    { return 'UNSIGNED_INTEGER_E'; }
+[A-Za-z0-9_]+                              { return 'REGULAR_IDENTIFIER'; }
+
+<hdfs>'\u2020'                             { parser.yy.cursorFound = true; return 'CURSOR'; }
+<hdfs>'\u2021'                             { parser.yy.cursorFound = true; return 'PARTIAL_CURSOR'; }
+<hdfs>\s+['"]                              { return 'HDFS_START_QUOTE'; }
+<hdfs>[^'"\u2020\u2021]+                   { parser.addFileLocation(yylloc, yytext); return 'HDFS_PATH'; }
+<hdfs>['"]                                 { this.popState(); return 'HDFS_END_QUOTE'; }
+<hdfs><<EOF>>                              { return 'EOF'; }
+
+'&&'                                       { return 'AND'; }
+'||'                                       { return 'OR'; }
+
+'='                                        { return '='; }
+'<'                                        { return '<'; }
+'>'                                        { return '>'; }
+'!='                                       { return 'COMPARISON_OPERATOR'; }
+'<='                                       { return 'COMPARISON_OPERATOR'; }
+'>='                                       { return 'COMPARISON_OPERATOR'; }
+'<>'                                       { return 'COMPARISON_OPERATOR'; }
+'<=>'                                      { return 'COMPARISON_OPERATOR'; }
+
+'-'                                        { return '-'; }
+'*'                                        { return '*'; }
+'+'                                        { return 'ARITHMETIC_OPERATOR'; }
+'/'                                        { return 'ARITHMETIC_OPERATOR'; }
+'%'                                        { return 'ARITHMETIC_OPERATOR'; }
+'|'                                        { return 'ARITHMETIC_OPERATOR'; }
+'^'                                        { return 'ARITHMETIC_OPERATOR'; }
+'&'                                        { return 'ARITHMETIC_OPERATOR'; }
+
+','                                        { return ','; }
+'.'                                        { return '.'; }
+':'                                        { return ':'; }
+';'                                        { return ';'; }
+'~'                                        { return '~'; }
+'!'                                        { return '!'; }
+
+'('                                        { return '('; }
+')'                                        { return ')'; }
+'['                                        { return '['; }
+']'                                        { return ']'; }
+
+\$\{[^}]*\}                                { return 'VARIABLE_REFERENCE'; }
+
+\`                                         { this.begin('backtickedValue'); return 'BACKTICK'; }
+<backtickedValue>[^`]+                     {
+                                             if (parser.handleQuotedValueWithCursor(this, yytext, yylloc, '`')) {
+                                               return 'PARTIAL_VALUE';
+                                             }
+                                             return 'VALUE';
+                                           }
+<backtickedValue>\`                        { this.popState(); return 'BACKTICK'; }
+
+\'                                         { this.begin('singleQuotedValue'); return 'SINGLE_QUOTE'; }
+<singleQuotedValue>(?:\\\\|\\[']|[^'])+         {
+                                             if (parser.handleQuotedValueWithCursor(this, yytext, yylloc, '\'')) {
+                                               return 'PARTIAL_VALUE';
+                                             }
+                                             return 'VALUE';
+                                           }
+<singleQuotedValue>\'                      { this.popState(); return 'SINGLE_QUOTE'; }
+
+\"                                         { this.begin('doubleQuotedValue'); return 'DOUBLE_QUOTE'; }
+<doubleQuotedValue>(?:\\\\|\\["]|[^"])+         {
+                                             if (parser.handleQuotedValueWithCursor(this, yytext, yylloc, '"')) {
+                                               return 'PARTIAL_VALUE';
+                                             }
+                                             return 'VALUE';
+                                           }
+<doubleQuotedValue>\"                      { this.popState(); return 'DOUBLE_QUOTE'; }
+
+<<EOF>>                                    { return 'EOF'; }
+
+.                                          { /* To prevent console logging of unknown chars */ }
+<between>.                                 { }
+<hdfs>.                                    { }
+<backtickedValue>.                         { }
+<singleQuotedValue>.                       { }
+<doubleQuotedValue>.                       { }

+ 5 - 3
desktop/core/src/desktop/js/parse/jison/sql/flink/structure.json

@@ -1,5 +1,5 @@
 {
-  "lexer": "../generic/sql.jisonlex",
+  "lexer": "sql.jisonlex",
   "autocomplete": [
     "../generic/autocomplete_header.jison",
     "../generic/alter/alter_common.jison",
@@ -53,7 +53,8 @@
     "../generic/use/use.jison",
     "../generic/sql_error.jison",
     "../generic/sql_main.jison",
-    "sql_show.jison",
+    "show/sql_show.jison",
+    "../calcite/describe/describe_table.jison",
     "../generic/sql_valueExpression.jison",
     "../generic/autocomplete_footer.jison"
   ],
@@ -109,7 +110,8 @@
     "../generic/update/update_table.jison",
     "../generic/use/use.jison",
     "../generic/sql_main.jison",
-    "sql_show.jison",
+    "show/sql_show.jison",
+    "../calcite/describe/describe_table.jison",
     "../generic/sql_valueExpression.jison",
     "../generic/syntax_footer.jison"
   ]

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
desktop/core/src/desktop/js/parse/sql/calcite/calciteAutocompleteParser.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
desktop/core/src/desktop/js/parse/sql/calcite/calciteSyntaxParser.js


+ 8 - 14
desktop/core/src/desktop/js/parse/sql/calcite/test/calciteAutocompleteParser.Select.stream.test.js

@@ -64,22 +64,16 @@ describe('calciteAutocompleteParser.js SELECT STREAM statements', () => {
       beforeCursor: 'SELECT STREAM ',
       afterCursor: '',
       noErrors: true,
-      containsKeywords: ['ALL', 'DISTINCT'],
       doesNotContainKeywords: ['STREAM'],
       expectedResult: {
-        lowerCase: false
-      }
-    });
-  });
-
-  it('should not suggest DISTINCT keyword after for "SELECT STREAM DISTINCT |"', () => {
-    assertAutoComplete({
-      beforeCursor: 'SELECT STREAM DISTINCT ',
-      afterCursor: '',
-      noErrors: true,
-      containsKeywords: undefined,
-      expectedResult: {
-        lowerCase: false
+        lowerCase: false,
+        suggestTables: {
+          prependFrom: true
+        },
+        suggestDatabases: {
+          prependFrom: true,
+          appendDot: true
+        }
       }
     });
   });

+ 4 - 2
desktop/core/src/desktop/js/parse/sql/calcite/test/calciteSyntaxParser.test.js

@@ -139,7 +139,8 @@ describe('calciteSyntaxParser.js', () => {
       'DROP',
       'TRUNCATE',
       'UPDATE',
-      'WITH'
+      'WITH',
+      'DESCRIBE'
     ]);
   });
 
@@ -157,7 +158,8 @@ describe('calciteSyntaxParser.js', () => {
       'drop',
       'truncate',
       'update',
-      'with'
+      'with',
+      'describe'
     ]);
   });
 

+ 70 - 0
desktop/core/src/desktop/js/parse/sql/calcite/test/calciteutocompleteParser.Describe.test.js

@@ -0,0 +1,70 @@
+// 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.
+
+import calciteAutocompleteParser from '../calciteAutocompleteParser';
+
+describe('calciteAutocompleteParser.js DESCRIBE statements', () => {
+  beforeAll(() => {
+    calciteAutocompleteParser.yy.parseError = function (msg) {
+      throw Error(msg);
+    };
+  });
+
+  const assertAutoComplete = testDefinition => {
+    const debug = false;
+
+    expect(
+      calciteAutocompleteParser.parseSql(
+        testDefinition.beforeCursor,
+        testDefinition.afterCursor,
+        debug
+      )
+    ).toEqualDefinition(testDefinition);
+  };
+
+  it('should suggest keywords for "|"', () => {
+    assertAutoComplete({
+      beforeCursor: '',
+      afterCursor: '',
+      containsKeywords: ['DESCRIBE'],
+      expectedResult: {
+        lowerCase: false
+      }
+    });
+  });
+
+  it('should suggest keywords for "DESCRIBE |"', () => {
+    assertAutoComplete({
+      beforeCursor: 'DESCRIBE ',
+      afterCursor: '',
+      expectedResult: {
+        lowerCase: false
+      }
+    });
+  });
+
+  it('should handle "DESCRIBE db.tbl;|"', () => {
+    assertAutoComplete({
+      beforeCursor: 'DESCRIBE db.tbl;',
+      afterCursor: '',
+      containsKeywords: ['SELECT'],
+      expectedResult: {
+        lowerCase: false,
+        locations: []
+      }
+    });
+  });
+});

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
desktop/core/src/desktop/js/parse/sql/flink/flinkAutocompleteParser.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
desktop/core/src/desktop/js/parse/sql/flink/flinkSyntaxParser.js


+ 103 - 0
desktop/core/src/desktop/js/parse/sql/flink/test/flinkAutoCompleteParser.Show.test.js

@@ -0,0 +1,103 @@
+// 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.
+
+import flinkAutocompleteParser from '../flinkAutocompleteParser';
+
+describe('flinkAutocompleteParser.js SHOW statements', () => {
+  beforeAll(() => {
+    flinkAutocompleteParser.yy.parseError = function (msg) {
+      throw Error(msg);
+    };
+  });
+
+  const assertAutoComplete = testDefinition => {
+    const debug = false;
+
+    expect(
+      flinkAutocompleteParser.parseSql(
+        testDefinition.beforeCursor,
+        testDefinition.afterCursor,
+        debug
+      )
+    ).toEqualDefinition(testDefinition);
+  };
+
+  it('should suggest keywords for "|"', () => {
+    assertAutoComplete({
+      beforeCursor: '',
+      afterCursor: '',
+      containsKeywords: ['SHOW'],
+      expectedResult: {
+        lowerCase: false
+      }
+    });
+  });
+
+  it('should suggest keywords for "SHOW |"', () => {
+    assertAutoComplete({
+      beforeCursor: 'SHOW ',
+      afterCursor: '',
+      expectedResult: {
+        lowerCase: false,
+        suggestKeywords: [
+          'CATALOGS',
+          'CURRENT CATALOG',
+          'CURRENT DATABASE',
+          'DATABASES',
+          'FUNCTIONS',
+          'TABLES',
+          'VIEWS'
+        ]
+      }
+    });
+  });
+
+  it('should handle "SHOW CA"', () => {
+    assertAutoComplete({
+      beforeCursor: 'SHOW CA',
+      afterCursor: '',
+      noErrors: true,
+      containsKeywords: ['CATALOGS', 'CURRENT CATALOG'],
+      expectedResult: {
+        lowerCase: false
+      }
+    });
+  });
+
+  it('should handle "SHOW TAB"', () => {
+    assertAutoComplete({
+      beforeCursor: 'SHOW TAB',
+      afterCursor: '',
+      noErrors: true,
+      containsKeywords: ['TABLES', 'CURRENT DATABASE', 'DATABASES'],
+      expectedResult: {
+        lowerCase: false
+      }
+    });
+  });
+
+  it('should handle "SHOW DAT"', () => {
+    assertAutoComplete({
+      beforeCursor: 'SHOW DAT',
+      afterCursor: '',
+      noErrors: true,
+      containsKeywords: ['DATABASES', 'CURRENT DATABASE'],
+      expectedResult: {
+        lowerCase: false
+      }
+    });
+  });
+});

+ 104 - 0
desktop/core/src/desktop/js/parse/sql/flink/test/flinkAutocompleteParser.Describe.test.js

@@ -0,0 +1,104 @@
+// 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.
+
+import flinkAutocompleteParser from '../flinkAutocompleteParser';
+
+describe('flinkAutocompleteParser.js DESCRIBE statements', () => {
+  beforeAll(() => {
+    flinkAutocompleteParser.yy.parseError = function (msg) {
+      throw Error(msg);
+    };
+  });
+
+  const assertAutoComplete = testDefinition => {
+    const debug = false;
+
+    expect(
+      flinkAutocompleteParser.parseSql(
+        testDefinition.beforeCursor,
+        testDefinition.afterCursor,
+        debug
+      )
+    ).toEqualDefinition(testDefinition);
+  };
+
+  it('should suggest keywords for "|"', () => {
+    assertAutoComplete({
+      beforeCursor: '',
+      afterCursor: '',
+      containsKeywords: ['DESCRIBE'],
+      expectedResult: {
+        lowerCase: false
+      }
+    });
+  });
+
+  it('should suggest keywords for "DESCRIBE |"', () => {
+    assertAutoComplete({
+      beforeCursor: 'DESCRIBE ',
+      afterCursor: '',
+      expectedResult: {
+        lowerCase: false,
+        suggestTables: {},
+        suggestDatabases: { appendDot: true }
+      }
+    });
+  });
+
+  it('should handle "DESCRIBE db.tbl;|"', () => {
+    assertAutoComplete({
+      beforeCursor: 'DESCRIBE db.tbl;',
+      afterCursor: '',
+      containsKeywords: ['SELECT'],
+      expectedResult: {
+        lowerCase: false,
+        locations: [
+          {
+            type: 'statement',
+            location: { first_line: 1, last_line: 1, first_column: 1, last_column: 16 }
+          },
+          {
+            type: 'statementType',
+            location: { first_line: 1, last_line: 1, first_column: 1, last_column: 9 },
+            identifier: 'DESCRIBE'
+          },
+          {
+            type: 'database',
+            location: { first_line: 1, last_line: 1, first_column: 10, last_column: 12 },
+            identifierChain: [{ name: 'db' }]
+          },
+          {
+            type: 'table',
+            location: { first_line: 1, last_line: 1, first_column: 13, last_column: 16 },
+            identifierChain: [{ name: 'db' }, { name: 'tbl' }]
+          }
+        ]
+      }
+    });
+  });
+
+  it('should suggest tables for "DESCRIBE |"', () => {
+    assertAutoComplete({
+      beforeCursor: 'DESCRIBE ',
+      afterCursor: '',
+      expectedResult: {
+        lowerCase: false,
+        suggestTables: {},
+        suggestDatabases: { appendDot: true }
+      }
+    });
+  });
+});

+ 41 - 2
desktop/core/src/desktop/js/parse/sql/flink/test/flinkSyntaxParser.test.js

@@ -135,11 +135,13 @@ describe('flinkSyntaxParser.js', () => {
       'ALTER',
       'INSERT',
       'CREATE',
+      'SHOW',
       'USE',
       'DROP',
       'TRUNCATE',
       'UPDATE',
-      'WITH'
+      'WITH',
+      'DESCRIBE'
     ]);
   });
 
@@ -153,11 +155,13 @@ describe('flinkSyntaxParser.js', () => {
       'alter',
       'insert',
       'create',
+      'show',
       'use',
       'drop',
       'truncate',
       'update',
-      'with'
+      'with',
+      'describe'
     ]);
   });
 
@@ -205,4 +209,39 @@ describe('flinkSyntaxParser.js', () => {
 
     expectNonEqualIds('slelect ', '', 'select * form ', '');
   });
+
+  it('should not find errors for "DESCRIBE tbl"', () => {
+    const result = flinkSyntaxParser.parseSyntax('DESCRIBE tbl;', '');
+    expect(result).toBeFalsy();
+  });
+
+  it('should not find errors for "DESCRIBE db.tbl"', () => {
+    const result = flinkSyntaxParser.parseSyntax('DESCRIBE db.tbl;', '');
+    expect(result).toBeFalsy();
+  });
+
+  it('should not find errors for "DESCRIBE ctlg.db.tbl"', () => {
+    const result = flinkSyntaxParser.parseSyntax('DESCRIBE ctlg.db.tbl;', '');
+    expect(result).toBeFalsy();
+  });
+
+  it('should find errors for "DESCRIBE fake.ctlg.db.tbl"', () => {
+    const result = flinkSyntaxParser.parseSyntax('DESCRIBE fake.ctlg.db.tbl;', '');
+    expect(result.incompleteStatement).toBeTruthy();
+  });
+
+  it('should report incomplete statement for "DESCRIBE"', () => {
+    const result = flinkSyntaxParser.parseSyntax('DESCRIBE', '');
+    expect(result.incompleteStatement).toBeTruthy();
+  });
+
+  it('should report incomplete statement for "DESCRIBE db.;"', () => {
+    const result = flinkSyntaxParser.parseSyntax('DESCRIBE db.;', '');
+    expect(result.incompleteStatement).toBeTruthy();
+  });
+
+  it('should report incomplete statement for "DESCRIBE ctlg.db.;"', () => {
+    const result = flinkSyntaxParser.parseSyntax('DESCRIBE ctlg.db.;', '');
+    expect(result.incompleteStatement).toBeTruthy();
+  });
 });

+ 3 - 3
package-lock.json

@@ -22140,9 +22140,9 @@
       "integrity": "sha512-IZYYsqyF1wC7hFm2g6gkf7lXp9hFau+po6dL0JTaMvSglsAgnowcbkpaOUl8exC7Bs6Ir9smJSXmKGFapml6TA=="
     },
     "vue-eslint-parser": {
-      "version": "7.3.0",
-      "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.3.0.tgz",
-      "integrity": "sha512-n5PJKZbyspD0+8LnaZgpEvNCrjQx1DyDHw8JdWwoxhhC+yRip4TAvSDpXGf9SWX6b0umeB5aR61gwUo6NVvFxw==",
+      "version": "7.4.1",
+      "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.4.1.tgz",
+      "integrity": "sha512-AFvhdxpFvliYq1xt/biNBslTHE/zbEvSnr1qfHA/KxRIpErmEDrQZlQnvEexednRHmLfDNOMuDYwZL5xkLzIXQ==",
       "dev": true,
       "requires": {
         "debug": "^4.1.1",

Vissa filer visades inte eftersom för många filer har ändrats