瀏覽代碼

[editor] Add SparkSQL autocomplete for CREATE statements

Johan Åhlén 3 年之前
父節點
當前提交
49e647f144

+ 25 - 0
desktop/core/src/desktop/js/parse/sql/sparksql/jison/common.jison

@@ -0,0 +1,25 @@
+// 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.
+
+NonReservedKeyword
+ : 'CSV'
+ | 'JDBC'
+ | 'JSON'
+ | 'ORC'
+ | 'PARQUET'
+ | 'TEXTFILE'
+ | 'TXT'
+ ;

+ 128 - 43
desktop/core/src/desktop/js/parse/sql/sparksql/jison/create/create_common.jison

@@ -14,6 +14,57 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+DataDefinition_EDIT
+ : 'CREATE' OptionalOrReplace OptionalTemporary 'CURSOR'
+   {
+     if (!$2 && !$3) {
+       parser.suggestKeywords([
+         'DATABASE', 'EXTERNAL TABLE', 'FUNCTION', 'GLOBAL TEMPORARY VIEW', 'OR REPLACE', 'SCHEMA', 'TABLE', 'TEMPORARY FUNCTION', 'TEMPORARY VIEW', 'VIEW']);
+     } else if ($2 && !$3) {
+       parser.suggestKeywords(['FUNCTION', 'GLOBAL TEMPORARY VIEW', 'TEMPORARY FUNCTION', 'TEMPORARY VIEW', 'VIEW']);
+     } else if ($3) {
+       parser.suggestKeywords(['FUNCTION', 'VIEW']);
+     }
+   }
+ | 'CREATE' OrReplace_EDIT
+ | 'CREATE' OptionalOrReplace Temporary_EDIT
+ ;
+
+
+OptionalTemporary
+ :
+ | 'TEMPORARY'
+ | 'GLOBAL' 'TEMPORARY'
+ ;
+
+Temporary_EDIT
+ : 'GLOBAL' 'CURSOR'
+   {
+     parser.suggestKeywords(['TEMPORARY']);
+   }
+ ;
+
+OptionalOrReplace
+ :
+ | OrReplace
+ ;
+
+OrReplace
+ : 'OR' 'REPLACE'
+ ;
+
+OrReplace_EDIT
+ : 'OR' 'CURSOR'
+   {
+     parser.suggestKeywords(['REPLACE']);
+   }
+ ;
+
+OptionalParenthesizedColumnSpecificationList
+ :
+ | ParenthesizedColumnSpecificationList
+ ;
+
 ParenthesizedColumnSpecificationList
  : '(' ColumnSpecificationList ')'                              -> $2
  ;
@@ -51,64 +102,29 @@ ColumnSpecificationList_EDIT
  ;
 
 ColumnSpecification
- : ColumnIdentifier ColumnDataType OptionalColumnOptions
+ : ColumnIdentifier ColumnDataType OptionalComment
    {
      $$ = $1;
      $$.type = $2;
      var keywords = [];
-     if (!$3['comment']) {
+     if (!$3) {
        keywords.push('COMMENT');
      }
-     if (keywords.length > 0) {
+     if (!$3 && $2 && $2.suggestKeywords) {
+       keywords = keywords.concat($2.suggestKeywords);
+     }
+     if (keywords.length) {
        $$.suggestKeywords = keywords;
      }
    }
  ;
 
 ColumnSpecification_EDIT
- : ColumnIdentifier 'CURSOR' OptionalColumnOptions
+ : ColumnIdentifier 'CURSOR' OptionalComment
    {
      parser.suggestKeywords(parser.getColumnDataTypeKeywords());
    }
- | ColumnIdentifier ColumnDataType_EDIT OptionalColumnOptions
- | ColumnIdentifier ColumnDataType ColumnOptions_EDIT
- ;
-
-OptionalColumnOptions
- :                      -> {}
- | ColumnOptions
- ;
-
-ColumnOptions
- : ColumnOption
-   {
-     $$ = {};
-     $$[$1] = true;
-   }
- | ColumnOptions ColumnOption
-   {
-     $1[$2] = true;
-   }
- ;
-
-ColumnOptions_EDIT
- : ColumnOption_EDIT
- | ColumnOption_EDIT ColumnOptions
- | ColumnOptions ColumnOption_EDIT
- | ColumnOptions ColumnOption_EDIT ColumnOptions
- ;
-
-ColumnOption
- : 'NOT' 'NULL'                                              -> 'null'
- | 'NULL'                                                    -> 'null'
- | Comment                                                   -> 'comment'
- ;
-
-ColumnOption_EDIT
- : 'NOT' 'CURSOR'
-   {
-     parser.suggestKeywords(['NULL']);
-   }
+ | ColumnIdentifier ColumnDataType_EDIT OptionalComment
  ;
 
 ColumnDataType
@@ -119,12 +135,14 @@ ColumnDataType
  | ArrayType_INVALID
  | MapType_INVALID
  | StructType_INVALID
+ | IntervalType
  ;
 
 ColumnDataType_EDIT
  : ArrayType_EDIT
  | MapType_EDIT
  | StructType_EDIT
+ | IntervalType_EDIT
  ;
 
 ArrayType
@@ -257,3 +275,70 @@ PartitionList
  : PartitionSpec
  | PartitionList, PartitionSpec
  ;
+
+
+OptionalComment
+ :
+ | Comment
+ ;
+
+Comment
+ : 'COMMENT' QuotedValue
+ ;
+
+// Extension of PrimitiveType in sql_main.jison
+PrimitiveType
+ : 'BYTE'
+ | 'SHORT'
+ | 'INTEGER'
+ | 'LONG'
+ | 'REAL'
+ | 'DATE'
+ | 'BINARY'
+ | 'NUMERIC'
+ | 'DEC'
+ ;
+
+IntervalType
+ : 'INTERVAL' IntervalUnit
+   {
+     if ($2.toUpperCase() == 'MINUTE') {
+       $$ = { suggestKeywords: ['TO SECOND'] };
+     } else if ($2.toUpperCase() == 'HOUR') {
+       $$ = { suggestKeywords: ['TO SECOND', 'TO MINUTE'] };
+     } else if ($2.toUpperCase() == 'DAY') {
+       $$ = { suggestKeywords: ['TO HOUR', 'TO SECOND', 'TO MINUTE'] };
+     } else if ($2.toUpperCase() == 'YEAR') {
+       $$ = { suggestKeywords: ['TO MONTH'] };
+     }
+   }
+ | 'INTERVAL' IntervalUnit 'TO' IntervalUnit
+ ;
+
+IntervalType_EDIT
+ : 'INTERVAL' 'CURSOR'
+   {
+     parser.suggestKeywords(['SECOND', 'MINUTE', 'HOUR', 'DAY', 'MONTH', 'YEAR']);
+   }
+ | 'INTERVAL' IntervalUnit 'TO' 'CURSOR'
+   {
+     if ($2.toUpperCase() == 'MINUTE') {
+       $$ = { suggestKeywords: ['SECOND'] };
+     } else if ($2.toUpperCase() == 'HOUR') {
+       $$ = { suggestKeywords: ['SECOND', 'MINUTE'] };
+     } else if ($2.toUpperCase() == 'DAY') {
+       $$ = { suggestKeywords: ['HOUR', 'SECOND', 'MINUTE'] };
+     } else if ($2.toUpperCase() == 'YEAR') {
+       $$ = { suggestKeywords: ['MONTH'] };
+     }
+   }
+ ;
+
+IntervalUnit
+ : 'DAY'
+ | 'YEAR'
+ | 'HOUR'
+ | 'MINUTE'
+ | 'MONTH'
+ | 'SECOND'
+ ;

+ 13 - 0
desktop/core/src/desktop/js/parse/sql/sparksql/jison/create/create_common.test.json

@@ -0,0 +1,13 @@
+[
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "",
+    "afterCursor": "",
+    "containsKeywords": [
+      "CREATE"
+    ],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  }
+]

+ 96 - 0
desktop/core/src/desktop/js/parse/sql/sparksql/jison/create/create_database.jison

@@ -0,0 +1,96 @@
+// 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
+ : CreateDatabase
+ ;
+
+DataDefinition_EDIT
+ : CreateDatabase_EDIT
+ ;
+
+CreateDatabase
+ : 'CREATE' DatabaseOrSchema OptionalIfNotExists RegularOrBacktickedIdentifier OptionalComment OptionalLocation OptionalWithDbProperties
+ ;
+
+CreateDatabase_EDIT
+ : 'CREATE' DatabaseOrSchema OptionalIfNotExists 'CURSOR'
+   {
+     if (!$3) {
+       parser.suggestKeywords(['IF NOT EXISTS']);
+     }
+   }
+ | 'CREATE' DatabaseOrSchema IfNotExists_EDIT
+ | 'CREATE' DatabaseOrSchema OptionalIfNotExists 'CURSOR' RegularOrBacktickedIdentifier OptionalComment OptionalLocation OptionalWithDbProperties
+   {
+     if (!$3) {
+       parser.suggestKeywords(['IF NOT EXISTS']);
+     }
+   }
+ | 'CREATE' DatabaseOrSchema IfNotExists_EDIT RegularOrBacktickedIdentifier OptionalComment OptionalLocation OptionalWithDbProperties
+ | 'CREATE' DatabaseOrSchema OptionalIfNotExists RegularOrBacktickedIdentifier 'CURSOR' OptionalComment OptionalLocation OptionalWithDbProperties
+   {
+     var keywords = parser.getKeywordsForOptionalsLR(
+       [$6, $7, $8],
+       [{ value: 'COMMENT', weight: 3 }, { value: 'LOCATION', weight: 2 }, { value: 'WITH DBPROPERTIES', weight: 1 }],
+       [true, true, true]);
+     if (keywords.length) {
+       parser.suggestKeywords(keywords);
+     }
+   }
+ | 'CREATE' DatabaseOrSchema OptionalIfNotExists RegularOrBacktickedIdentifier Comment 'CURSOR' OptionalLocation OptionalWithDbProperties
+   {
+     var keywords = parser.getKeywordsForOptionalsLR(
+       [$7, $8],
+       [{ value: 'LOCATION', weight: 2 }, { value: 'WITH DBPROPERTIES', weight: 1 }],
+       [true, true]);
+     if (keywords.length) {
+       parser.suggestKeywords(keywords);
+     }
+   }
+ | 'CREATE' DatabaseOrSchema OptionalIfNotExists RegularOrBacktickedIdentifier OptionalComment Location 'CURSOR' OptionalWithDbProperties
+   {
+     if (!$8) {
+       parser.suggestKeywords(["WITH DBPROPERTIES"]);
+     }
+   }
+ | 'CREATE' DatabaseOrSchema OptionalIfNotExists RegularOrBacktickedIdentifier OptionalComment OptionalLocation WithDbProperties_EDIT
+ ;
+
+OptionalLocation
+ :
+ | Location
+ ;
+
+Location
+ : 'LOCATION' QuotedValue
+ ;
+
+OptionalWithDbProperties
+ :
+ | WithDbProperties
+ ;
+
+WithDbProperties
+ : 'WITH' 'DBPROPERTIES' ParenthesizedPropertyAssignmentList
+ ;
+
+WithDbProperties_EDIT
+ : 'WITH' 'CURSOR'
+   {
+     parser.suggestKeywords(['DBPROPERTIES']);
+   }
+ ;

+ 122 - 0
desktop/core/src/desktop/js/parse/sql/sparksql/jison/create/create_database.test.json

@@ -0,0 +1,122 @@
+[
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE ",
+    "afterCursor": "",
+    "containsKeywords": [
+      "DATABASE",
+      "SCHEMA"
+    ],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE DATABASE ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["IF NOT EXISTS"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE DATABASE IF ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["NOT EXISTS"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE DATABASE IF NOT ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["EXISTS"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE DATABASE foo ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["COMMENT", "LOCATION", "WITH DBPROPERTIES"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE DATABASE foo COMMENT 'some comment' ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["LOCATION", "WITH DBPROPERTIES"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE SCHEMA foo COMMENT 'some comment' ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["LOCATION", "WITH DBPROPERTIES"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE DATABASE foo COMMENT 'some comment' LOCATION 'bar' ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["WITH DBPROPERTIES"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE DATABASE foo COMMENT 'some comment' LOCATION 'bar' WITH ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["DBPROPERTIES"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE DATABASE foo COMMENT 'some comment' ",
+    "afterCursor": " WITH DBPROPERTIES ('a'='b')",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["LOCATION"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE SCHEMA foo ",
+    "afterCursor": " LOCATION 'some location' WITH DBPROPERTIES ('a'='b')",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["COMMENT"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE DATABASE ",
+    "afterCursor": " foo WITH DBPROPERTIES ('a'='b')",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["IF NOT EXISTS"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE SCHEMA IF NOT ",
+    "afterCursor": " foo WITH DBPROPERTIES ('a'='b')",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["EXISTS"]
+    }
+  }
+]

+ 95 - 0
desktop/core/src/desktop/js/parse/sql/sparksql/jison/create/create_function.jison

@@ -0,0 +1,95 @@
+// 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
+ : CreateFunction
+ ;
+
+DataDefinition_EDIT
+ : CreateFunction_EDIT
+ ;
+
+CreateFunction
+ : 'CREATE' OptionalOrReplace OptionalTemporary 'FUNCTION' OptionalIfNotExists ColumnOrArbitraryFunctionRef 'AS' QuotedValue OptionalResourceLocation
+ ;
+
+CreateFunction_EDIT
+ : 'CREATE' OptionalOrReplace OptionalTemporary 'CURSOR' 'FUNCTION'
+   {
+     if (!$3 && !$2) {
+       parser.suggestKeywords([{ value: 'OR REPLACE', weight: 2 }, { value: 'TEMPORARY', weight: 1 }])
+     } else if (!$3 && $2) {
+       parser.suggestKeywords(['TEMPORARY']);
+     }
+   }
+ | 'CREATE' OptionalOrReplace OptionalTemporary 'FUNCTION' OptionalIfNotExists 'CURSOR'
+   {
+     if (!$5) {
+       parser.suggestKeywords(['IF NOT EXISTS']);
+     }
+     parser.suggestDatabases({ appendDot: true });
+   }
+ | 'CREATE' OptionalOrReplace OptionalTemporary 'FUNCTION' IfNotExists_EDIT
+ | 'CREATE' OptionalOrReplace OptionalTemporary 'FUNCTION' OptionalIfNotExists ColumnOrArbitraryFunctionRef 'CURSOR'
+   {
+     parser.suggestKeywords(['AS']);
+   }
+ | 'CREATE' OptionalOrReplace OptionalTemporary 'FUNCTION' OptionalIfNotExists ColumnOrArbitraryFunctionRef 'AS' QuotedValue OptionalResourceLocation 'CURSOR'
+   {
+     if (!$9) {
+       parser.suggestKeywords(['USING']);
+     }
+   }
+ | 'CREATE' OptionalOrReplace OptionalTemporary 'FUNCTION' OptionalIfNotExists ColumnOrArbitraryFunctionRef 'AS' QuotedValue ResourceLocation_EDIT
+ | 'CREATE' OptionalOrReplace OptionalTemporary 'CURSOR' 'FUNCTION' OptionalIfNotExists ColumnOrArbitraryFunctionRef 'AS' QuotedValue OptionalResourceLocation
+   {
+     if (!$3 && !$2) {
+       parser.suggestKeywords([{ value: 'OR REPLACE', weight: 2 }, { value: 'TEMPORARY', weight: 1 }])
+     } else if (!$3 && $2) {
+       parser.suggestKeywords(['TEMPORARY']);
+     }
+   }
+ | 'CREATE' OptionalOrReplace OptionalTemporary 'FUNCTION' OptionalIfNotExists 'CURSOR' ColumnOrArbitraryFunctionRef 'AS' QuotedValue OptionalResourceLocation
+   {
+     if (!$5) {
+       parser.suggestKeywords(['IF NOT EXISTS']);
+     }
+   }
+ | 'CREATE' OrReplace_EDIT OptionalTemporary 'FUNCTION' OptionalIfNotExists ColumnOrArbitraryFunctionRef 'AS' QuotedValue OptionalResourceLocation
+ | 'CREATE' OptionalOrReplace OptionalTemporary 'FUNCTION' IfNotExists_EDIT ColumnOrArbitraryFunctionRef 'AS' QuotedValue OptionalResourceLocation
+ ;
+
+OptionalResourceLocation
+ :
+ | ResourceLocation
+ ;
+
+ResourceLocation
+ : 'USING' JarFileOrArchive QuotedValue
+ ;
+
+ResourceLocation_EDIT
+ : 'USING' 'CURSOR'
+   {
+     parser.suggestKeywords(['ARCHIVE', 'FILE', 'JAR']);
+   }
+ ;
+
+JarFileOrArchive
+ : 'ARCHIVE'
+ | 'FILE'
+ | 'JAR'
+ ;

+ 138 - 0
desktop/core/src/desktop/js/parse/sql/sparksql/jison/create/create_function.test.json

@@ -0,0 +1,138 @@
+[
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE ",
+    "afterCursor": "",
+    "containsKeywords": [
+      "FUNCTION",
+      "TEMPORARY FUNCTION",
+      "OR REPLACE"
+    ],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE OR ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["REPLACE"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE OR REPLACE ",
+    "afterCursor": "",
+    "containsKeywords": ["FUNCTION", "TEMPORARY FUNCTION"],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE OR REPLACE TEMPORARY ",
+    "afterCursor": "",
+    "containsKeywords": ["FUNCTION"],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TEMPORARY ",
+    "afterCursor": "",
+    "containsKeywords": ["FUNCTION"],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE FUNCTION ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["IF NOT EXISTS"],
+      "suggestDatabases": {
+        "appendDot": true
+      }
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE OR REPLACE FUNCTION IF ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["NOT EXISTS"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TEMPORARY FUNCTION IF NOT ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["EXISTS"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TEMPORARY FUNCTION IF NOT EXISTS foo.bar ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["AS"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TEMPORARY FUNCTION IF NOT EXISTS foo AS 'SimpleUdf' ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["USING"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE FUNCTION foo AS 'SimpleUdf' USING ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["ARCHIVE", "FILE", "JAR"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE FUNCTION ",
+    "afterCursor": " foo AS 'SimpleUdf' USING JAR 'some.jar';",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["IF NOT EXISTS"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TEMPORARY FUNCTION IF NOT ",
+    "afterCursor": " foo AS 'SimpleUdf' USING JAR 'some.jar';",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["EXISTS"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE ",
+    "afterCursor": " FUNCTION foo AS 'SimpleUdf';",
+    "containsKeywords": [
+      "TEMPORARY",
+      "OR REPLACE"
+    ],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  }
+]

+ 248 - 0
desktop/core/src/desktop/js/parse/sql/sparksql/jison/create/create_table.jison

@@ -0,0 +1,248 @@
+// 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
+ : CreateTable
+ ;
+
+DataDefinition_EDIT
+ : CreateTable_EDIT
+ ;
+
+CreateTable
+ : 'CREATE' 'TABLE' OptionalIfNotExists CreateTableOptions
+ | 'CREATE' 'EXTERNAL' 'TABLE' OptionalIfNotExists CreateTableOptions
+ ;
+
+CreateTable_EDIT
+ : 'CREATE' 'EXTERNAL' 'CURSOR'
+   {
+     parser.suggestKeywords(['TABLE']);
+   }
+ | 'CREATE' 'TABLE' OptionalIfNotExists 'CURSOR'
+   {
+     if (!$3) {
+       parser.suggestKeywords(['IF NOT EXISTS']);
+     }
+     parser.suggestDatabases({ appendDot: true });
+   }
+ | 'CREATE' 'TABLE' IfNotExists_EDIT
+ | 'CREATE' 'EXTERNAL' 'TABLE' OptionalIfNotExists 'CURSOR'
+   {
+     if (!$4) {
+       parser.suggestKeywords(['IF NOT EXISTS']);
+     }
+     parser.suggestDatabases({ appendDot: true });
+   }
+ | 'CREATE' 'EXTERNAL' 'TABLE' IfNotExists_EDIT
+ | 'CREATE' 'TABLE' OptionalIfNotExists 'CURSOR' CreateTableOptions
+     {
+       if (!$3) {
+         parser.suggestKeywords(['IF NOT EXISTS']);
+       }
+     }
+   | 'CREATE' 'TABLE' IfNotExists_EDIT CreateTableOptions
+   | 'CREATE' 'EXTERNAL' 'TABLE' OptionalIfNotExists 'CURSOR' CreateTableOptions
+     {
+       if (!$4) {
+         parser.suggestKeywords(['IF NOT EXISTS']);
+       }
+     }
+   | 'CREATE' 'EXTERNAL' 'TABLE' IfNotExists_EDIT CreateTableOptions
+   | 'CREATE' 'TABLE' OptionalIfNotExists CreateTableOptions_EDIT
+   | 'CREATE' 'EXTERNAL' 'TABLE' OptionalIfNotExists CreateTableOptions_EDIT
+ ;
+
+CreateTableOptions
+ : SchemaQualifiedTableIdentifier 'LIKE' SchemaQualifiedTableIdentifier 'USING' DataSource OptionalRowFormat
+   OptionalStoredAs OptionalTblProperties OptionalLocation
+ | SchemaQualifiedTableIdentifier OptionalParenthesizedColumnSpecificationList 'USING' DataSource OptionalOptions
+   OptionalPartitionedBy OptionalClusteredBy OptionalLocation OptionalComment OptionalTblProperties
+   OptionalAsQuerySpecification
+ | SchemaQualifiedTableIdentifier OptionalParenthesizedColumnSpecificationList OptionalComment OptionalPartitionedBy
+   OptionalClusteredBy OptionalRowFormat OptionalStoredAs OptionalLocation OptionalTblProperties
+   OptionalAsQuerySpecification
+ ;
+
+CreateTableOptions_EDIT
+ : SchemaQualifiedTableIdentifier_EDIT
+   {
+     if (parser.yy.result.suggestTables) {
+       delete parser.yy.result.suggestTables
+     }
+   }
+ | SchemaQualifiedTableIdentifier OptionalParenthesizedColumnSpecificationList OptionalComment OptionalPartitionedBy
+   OptionalClusteredBy OptionalRowFormat OptionalStoredAs OptionalLocation OptionalTblProperties
+   'CURSOR' OptionalAsQuerySpecification
+   {
+     var keywords = parser.getKeywordsForOptionalsLR(
+       [$9, $8, $7, $6, $5, $4, $3, undefined, undefined],
+       [{ value: 'TBLPROPERTIES', weight: 2 },
+        { value: 'LOCATION', weight: 3 },
+        { value: 'STORED AS', weight: 4 },
+        { value: 'ROW FORMAT', weight: 5 },
+        { value: 'CLUSTERED BY', weight: 6 },
+        { value: 'PARTITIONED BY', weight: 7 },
+        { value: 'COMMENT', weight: 8 },
+        { value: 'USING', weight: 9 },
+        { value: 'LIKE', weight: 9 }]);
+
+     if ($6 && $6.suggestKeywords && !$7 && !$8 && !$9) {
+       keywords = keywords.concat($6.suggestKeywords);
+     }
+     if (!$11) {
+       keywords.push({ value: 'AS', weight: 1 });
+     }
+     if (keywords.length) {
+       parser.suggestKeywords(keywords);
+     }
+   }
+ | SchemaQualifiedTableIdentifier 'LIKE' 'CURSOR'
+   {
+     parser.suggestDatabases({ appendDot: true });
+     parser.suggestTables();
+   }
+ | SchemaQualifiedTableIdentifier 'LIKE' SchemaQualifiedTableIdentifier_EDIT
+ | SchemaQualifiedTableIdentifier 'LIKE' SchemaQualifiedTableIdentifier 'CURSOR'
+   {
+     parser.suggestKeywords(['USING']);
+   }
+ | SchemaQualifiedTableIdentifier 'LIKE' SchemaQualifiedTableIdentifier 'USING' 'CURSOR'
+   {
+     parser.suggestKeywords(parser.getDataSourceKeywords());
+   }
+ | SchemaQualifiedTableIdentifier 'LIKE' SchemaQualifiedTableIdentifier 'USING' DataSource OptionalRowFormat OptionalStoredAs OptionalTblProperties OptionalLocation 'CURSOR'
+   {
+     var keywords = parser.getKeywordsForOptionalsLR(
+       [$9, $8, $7, $6],
+       [{ value: 'LOCATION', weight: 1 },
+        { value: 'TBLPROPERTIES', weight: 2 },
+        { value: 'STORED AS', weight: 3 },
+        { value: 'ROW FORMAT', weight: 4 }]);
+     if ($6 && $6.suggestKeywords && !$7 && !$8 && !$9) {
+       keywords = keywords.concat($6.suggestKeywords);
+     }
+     if (keywords.length) {
+       parser.suggestKeywords(keywords);
+     }
+   }
+ | SchemaQualifiedTableIdentifier 'LIKE' SchemaQualifiedTableIdentifier 'USING' DataSource RowFormat_EDIT OptionalStoredAs OptionalTblProperties OptionalLocation
+ | SchemaQualifiedTableIdentifier 'LIKE' SchemaQualifiedTableIdentifier 'USING' DataSource OptionalRowFormat StoredAs_EDIT OptionalTblProperties OptionalLocation
+ | SchemaQualifiedTableIdentifier ParenthesizedColumnSpecificationList_EDIT OptionalComment OptionalPartitionedBy OptionalClusteredBy OptionalRowFormat OptionalStoredAs OptionalLocation OptionalTblProperties OptionalAsQuerySpecification
+ | SchemaQualifiedTableIdentifier OptionalParenthesizedColumnSpecificationList 'USING' 'CURSOR'
+   {
+     parser.suggestKeywords(parser.getDataSourceKeywords());
+   }
+ | SchemaQualifiedTableIdentifier OptionalParenthesizedColumnSpecificationList 'USING' DataSource OptionalOptions OptionalPartitionedBy OptionalClusteredBy OptionalLocation OptionalComment OptionalTblProperties 'CURSOR' OptionalAsQuerySpecification
+   {
+     var keywords = parser.getKeywordsForOptionalsLR(
+       [$10, $9, $8, $7, $6, $5],
+       [{ value: 'TBLPROPERTIES', weight: 2 },
+        { value: 'COMMENT', weight: 3 },
+        { value: 'LOCATION', weight: 4 },
+        { value: 'CLUSTERED BY', weight: 5 },
+        { value: 'PARTITIONED BY', weight: 6 },
+        { value: 'OPTIONS', weight: 7 }]);
+     if (!$12) {
+       keywords.push({ value: 'AS', weight: 1 });
+     }
+     if (keywords.length) {
+       parser.suggestKeywords(keywords);
+     }
+   }
+ | SchemaQualifiedTableIdentifier OptionalParenthesizedColumnSpecificationList 'USING' DataSource OptionalOptions PartitionedBy_EDIT OptionalClusteredBy OptionalLocation OptionalComment OptionalTblProperties OptionalAsQuerySpecification
+ | SchemaQualifiedTableIdentifier OptionalParenthesizedColumnSpecificationList 'USING' DataSource OptionalOptions OptionalPartitionedBy ClusteredBy_EDIT OptionalLocation OptionalComment OptionalTblProperties OptionalAsQuerySpecification
+ | SchemaQualifiedTableIdentifier OptionalParenthesizedColumnSpecificationList 'USING' DataSource OptionalOptions OptionalPartitionedBy OptionalClusteredBy OptionalLocation OptionalComment OptionalTblProperties AsQuerySpecification_EDIT
+
+ | SchemaQualifiedTableIdentifier OptionalParenthesizedColumnSpecificationList OptionalComment PartitionedBy_EDIT OptionalClusteredBy OptionalRowFormat OptionalStoredAs OptionalLocation OptionalTblProperties OptionalAsQuerySpecification
+ | SchemaQualifiedTableIdentifier OptionalParenthesizedColumnSpecificationList OptionalComment OptionalPartitionedBy ClusteredBy_EDIT OptionalRowFormat OptionalStoredAs OptionalLocation OptionalTblProperties OptionalAsQuerySpecification
+ | SchemaQualifiedTableIdentifier OptionalParenthesizedColumnSpecificationList OptionalComment OptionalPartitionedBy OptionalClusteredBy RowFormat_EDIT OptionalStoredAs OptionalLocation OptionalTblProperties OptionalAsQuerySpecification
+ | SchemaQualifiedTableIdentifier OptionalParenthesizedColumnSpecificationList OptionalComment OptionalPartitionedBy OptionalClusteredBy OptionalRowFormat StoredAs_EDIT OptionalLocation OptionalTblProperties OptionalAsQuerySpecification
+ | SchemaQualifiedTableIdentifier OptionalParenthesizedColumnSpecificationList OptionalComment OptionalPartitionedBy OptionalClusteredBy OptionalRowFormat OptionalStoredAs OptionalLocation OptionalTblProperties AsQuerySpecification_EDIT
+ ;
+
+OptionalExternal
+ :
+ | 'EXTERNAL'
+ ;
+
+DataSource
+ : 'CSV'
+ | 'JDBC'
+ | 'ORC'
+ | 'PARQUET'
+ | 'TXT'
+ ;
+
+OptionalStoredAs
+ :
+ | StoredAs
+ ;
+
+StoredAs
+ : 'STORED' 'AS' FileFormat
+ ;
+
+StoredAs_EDIT
+ : 'STORED' 'CURSOR'
+   {
+     parser.suggestKeywords(['AS']);
+   }
+ | 'STORED' 'AS' 'CURSOR'
+   {
+     parser.suggestFileFormats();
+   }
+ ;
+
+OptionalTblProperties
+ :
+ | TblProperties
+ ;
+
+TblProperties
+ : 'TBLPROPERTIES' ParenthesizedPropertyAssignmentList
+ ;
+
+OptionalOptions
+ :
+ | Options
+ ;
+
+Options
+ : 'OPTIONS' ParenthesizedPropertyAssignmentList
+ ;
+
+OptionalPartitionedBy
+ :
+ | PartitionedBy
+ ;
+
+PartitionedBy
+ : 'PARTITIONED' 'BY' ParenthesizedColumnSpecificationList
+ | 'PARTITIONED' 'BY' '(' ColumnIdentifierList ')'
+ ;
+
+PartitionedBy_EDIT
+ : 'PARTITIONED' 'CURSOR'
+   {
+     parser.suggestKeywords(['BY']);
+   }
+ ;
+
+// Extension of RowFormatSpec in hive/create/row_format.jison
+RowFormatSpec
+ : 'SERDE' QuotedValue WithSerdeProperties
+ ;

+ 714 - 0
desktop/core/src/desktop/js/parse/sql/sparksql/jison/create/create_table.test.json

@@ -0,0 +1,714 @@
+[
+  {
+    "namePrefix": "should not report errors",
+    "beforeCursor": "CREATE TABLE IF NOT EXISTS foo LIKE db.tbl USING CSV ROW FORMAT DELIMITED STORED AS PARQUET TBLPROPERTIES ('a'='b') LOCATION 'boo'; ",
+    "afterCursor": "",
+    "noErrors": true,
+    "containsKeywords": [
+      "SELECT"
+    ],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE ",
+    "afterCursor": "",
+    "containsKeywords": [
+      "TABLE",
+      "EXTERNAL TABLE"
+    ],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE EXTERNAL ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "TABLE"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "IF NOT EXISTS"
+      ],
+      "suggestDatabases": {
+        "appendDot": true
+      }
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE IF ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "NOT EXISTS"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE EXTERNAL TABLE IF NOT ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "EXISTS"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE foo ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "LIKE",
+        "USING",
+        "COMMENT",
+        "PARTITIONED BY",
+        "CLUSTERED BY",
+        "ROW FORMAT",
+        "STORED AS",
+        "LOCATION",
+        "TBLPROPERTIES",
+        "AS"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest tables",
+    "beforeCursor": "CREATE TABLE foo LIKE ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestDatabases": {
+        "appendDot": true
+      },
+      "suggestTables": {}
+    }
+  },
+  {
+    "namePrefix": "should suggest tables",
+    "beforeCursor": "CREATE TABLE foo LIKE foo.",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestTables": {
+        "identifierChain": [
+          {
+            "name": "foo"
+          }
+        ]
+      }
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE IF NOT EXISTS foo LIKE bar ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "USING"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE IF NOT EXISTS foo LIKE bar USING ",
+    "afterCursor": "",
+    "containsKeywords": [
+      "PARQUET"
+    ],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE IF NOT EXISTS foo LIKE bar USING CSV ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "ROW FORMAT",
+        "STORED AS",
+        "TBLPROPERTIES",
+        "LOCATION"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE IF NOT EXISTS foo LIKE bar USING CSV ROW ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "FORMAT"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE IF NOT EXISTS foo LIKE bar USING CSV ROW FORMAT ",
+    "afterCursor": "",
+    "containsKeywords": [
+      "DELIMITED",
+      "SERDE"
+    ],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE IF NOT EXISTS foo LIKE bar USING CSV ROW FORMAT DELIMITED ",
+    "afterCursor": "",
+    "containsKeywords": [
+      "STORED AS",
+      "LOCATION"
+    ],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE foo LIKE bar USING CSV STORED ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "AS"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE foo LIKE bar USING CSV STORED AS ",
+    "afterCursor": "",
+    "containsKeywords": [
+      "ORC"
+    ],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE foo LIKE bar USING CSV STORED AS ORC ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "TBLPROPERTIES",
+        "LOCATION"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE foo LIKE bar USING CSV STORED AS ORC TBLPROPERTIES ('a' = 'b') ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "LOCATION"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE ",
+    "afterCursor": " foo LIKE bar USING CSV STORED AS ORC TBLPROPERTIES ('a' = 'b')",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "IF NOT EXISTS"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE IF ",
+    "afterCursor": " foo LIKE bar USING CSV STORED AS ORC TBLPROPERTIES ('a' = 'b')",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "NOT EXISTS"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE boo (id ",
+    "afterCursor": "",
+    "containsKeywords": [
+      "INT",
+      "INTERVAL MINUTE"
+    ],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE boo (id INTERVAL MINUTE ",
+    "afterCursor": "",
+    "containsKeywords": [
+      "COMMENT",
+      "TO SECOND"
+    ],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE boo (id INTERVAL MINUTE, foo ",
+    "afterCursor": "",
+    "containsKeywords": [
+      "STRING"
+    ],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE boo (id INTERVAL MINUTE, foo STRING) ",
+    "afterCursor": "",
+    "containsKeywords": [
+      "COMMENT",
+      "USING",
+      "ROW FORMAT",
+      "AS"
+    ],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE boo (id INTERVAL MINUTE, foo STRING) USING ",
+    "afterCursor": "",
+    "containsKeywords": [
+      "CSV"
+    ],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE boo (id INTERVAL MINUTE, foo STRING) USING CSV ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "OPTIONS",
+        "PARTITIONED BY",
+        "CLUSTERED BY",
+        "LOCATION",
+        "COMMENT",
+        "TBLPROPERTIES",
+        "AS"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE IF NOT EXISTS boo (id INTERVAL MINUTE, foo STRING) USING CSV OPTIONS ('a'='b') ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "PARTITIONED BY",
+        "CLUSTERED BY",
+        "LOCATION",
+        "COMMENT",
+        "TBLPROPERTIES",
+        "AS"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE IF NOT EXISTS boo (id INTERVAL MINUTE, foo STRING) USING CSV OPTIONS ('a'='b') PARTITIONED ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "BY"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE IF NOT EXISTS boo (id INTERVAL MINUTE, foo STRING) USING CSV OPTIONS ('a'='b') PARTITIONED BY (a, b, c) ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "CLUSTERED BY",
+        "LOCATION",
+        "COMMENT",
+        "TBLPROPERTIES",
+        "AS"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE IF NOT EXISTS boo (id INTERVAL MINUTE, foo STRING) USING CSV OPTIONS ('a'='b') PARTITIONED BY (a, b, c) CLUSTERED ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "BY"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE IF NOT EXISTS boo (id INTERVAL MINUTE, foo STRING) USING CSV OPTIONS ('a'='b') PARTITIONED BY (a, b, c) CLUSTERED BY (e, f) ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "SORTED BY",
+        "INTO"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE IF NOT EXISTS boo (id INTERVAL MINUTE, foo STRING) USING CSV OPTIONS ('a'='b') PARTITIONED BY (a, b, c) CLUSTERED BY (e, f) SORTED ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "BY"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE IF NOT EXISTS boo (id INTERVAL MINUTE, foo STRING) USING CSV OPTIONS ('a'='b') PARTITIONED BY (a, b, c) CLUSTERED BY (e, f) SORTED BY (d) ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "INTO"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE boo (id int) USING CSV CLUSTERED BY (e, f) INTO 1 ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "BUCKETS"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE boo (id int) USING CSV CLUSTERED BY (e, f) SORTED BY (d) INTO 1 ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "BUCKETS"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE boo (id int) USING CSV CLUSTERED BY (e, f) INTO 1 BUCKETS ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "LOCATION",
+        "COMMENT",
+        "TBLPROPERTIES",
+        "AS"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE boo (id int) USING CSV CLUSTERED BY (e, f) INTO 1 BUCKETS LOCATION 'foo' ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "COMMENT",
+        "TBLPROPERTIES",
+        "AS"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE boo (id int) USING CSV CLUSTERED BY (e, f) INTO 1 BUCKETS LOCATION 'foo' COMMENT 'boo' ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "TBLPROPERTIES",
+        "AS"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE boo (id int) USING CSV LOCATION 'foo' COMMENT 'boo' TBLPROPERTIES ('a'='b') ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "AS"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE boo (id int) USING CSV LOCATION 'foo' COMMENT 'boo' TBLPROPERTIES ('a'='b') AS ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "SELECT"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE boo (id int) USING CSV AS SELECT ",
+    "afterCursor": "",
+    "containsKeywords": [
+      "*"
+    ],
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestAggregateFunctions": {
+        "tables": []
+      },
+      "suggestAnalyticFunctions": true,
+      "suggestFunctions": {},
+      "suggestTables": {
+        "prependQuestionMark": true,
+        "prependFrom": true
+      },
+      "suggestDatabases": {
+        "prependQuestionMark": true,
+        "prependFrom": true,
+        "appendDot": true
+      }
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE ",
+    "afterCursor": " boo (id int) USING CSV AS SELECT * FROM foo;",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "IF NOT EXISTS"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE IF NOT ",
+    "afterCursor": " boo (id int) USING CSV AS SELECT * FROM foo;",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "EXISTS"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE EXTERNAL TABLE foo (id ",
+    "afterCursor": "",
+    "containsKeywords": ["NUMERIC"],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE EXTERNAL TABLE foo (id int) ",
+    "afterCursor": "",
+    "containsKeywords": ["COMMENT","PARTITIONED BY","CLUSTERED BY","ROW FORMAT","STORED AS","LOCATION","TBLPROPERTIES","AS"],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE EXTERNAL TABLE foo (id int) COMMENT 'bla' ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["PARTITIONED BY","CLUSTERED BY","ROW FORMAT","STORED AS","LOCATION","TBLPROPERTIES","AS"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE EXTERNAL TABLE foo (id int) COMMENT 'bla' PARTITIONED ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["BY"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE EXTERNAL TABLE foo (id int) COMMENT 'bla' PARTITIONED BY (a) ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["CLUSTERED BY","ROW FORMAT","STORED AS","LOCATION","TBLPROPERTIES","AS"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE EXTERNAL TABLE foo (id int) COMMENT 'bla' PARTITIONED BY (a) CLUSTERED ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["BY"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE EXTERNAL TABLE foo (id int) COMMENT 'bla' PARTITIONED BY (a) CLUSTERED BY (a) ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["SORTED BY", "INTO"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE EXTERNAL TABLE foo (id int) COMMENT 'bla' PARTITIONED BY (a) CLUSTERED BY (a) INTO 10 BUCKETS ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["ROW FORMAT","STORED AS","LOCATION","TBLPROPERTIES","AS"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE foo (id int) COMMENT 'bla' PARTITIONED BY (a) CLUSTERED BY (a) INTO 10 BUCKETS ROW ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["FORMAT"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE EXTERNAL TABLE foo (id int) ROW FORMAT DELIMITED ",
+    "afterCursor": "",
+    "containsKeywords": ["STORED AS","LOCATION","TBLPROPERTIES","AS"],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE EXTERNAL TABLE foo (id int) ROW FORMAT DELIMITED STORED ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["AS"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE IF NOT EXISTS foo (id int) ROW FORMAT DELIMITED STORED AS PARQUET ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["LOCATION","TBLPROPERTIES","AS"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE EXTERNAL TABLE foo (id int) LOCATION 'foo' ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["TBLPROPERTIES","AS"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE EXTERNAL TABLE foo (id int) TBLPROPERTIES ('foo'='1') ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["AS"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE boo (id int) AS ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "SELECT"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE TABLE boo (id int) AS SELECT ",
+    "afterCursor": "",
+    "containsKeywords": [
+      "*"
+    ],
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestAggregateFunctions": {
+        "tables": []
+      },
+      "suggestAnalyticFunctions": true,
+      "suggestFunctions": {},
+      "suggestTables": {
+        "prependQuestionMark": true,
+        "prependFrom": true
+      },
+      "suggestDatabases": {
+        "prependQuestionMark": true,
+        "prependFrom": true,
+        "appendDot": true
+      }
+    }
+  }
+]

+ 82 - 0
desktop/core/src/desktop/js/parse/sql/sparksql/jison/create/create_view.jison

@@ -0,0 +1,82 @@
+// 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
+ : CreateView
+ ;
+
+DataDefinition_EDIT
+ : CreateView_EDIT
+ ;
+
+CreateView
+ : CreateViewLeftPart SchemaQualifiedTableIdentifier OptionalParenthesizedColumnSpecificationList OptionalComment OptionalTblProperties AsQuerySpecification
+ ;
+
+CreateView_EDIT
+ : CreateViewLeftPart_EDIT
+ | CreateViewLeftPart_EDIT SchemaQualifiedTableIdentifier OptionalParenthesizedColumnSpecificationList OptionalComment OptionalTblProperties
+ | CreateViewLeftPart_EDIT SchemaQualifiedTableIdentifier OptionalParenthesizedColumnSpecificationList OptionalComment OptionalTblProperties AsQuerySpecification
+ | CreateViewLeftPart 'CURSOR'
+   {
+     parser.checkForKeywords($1);
+     parser.suggestDatabases({ appendDot: true });
+   }
+ | CreateViewLeftPart SchemaQualifiedTableIdentifier_EDIT
+   {
+     if (parser.yy.result.suggestTables) {
+       delete parser.yy.result.suggestTables;
+     }
+   }
+ | CreateViewLeftPart SchemaQualifiedTableIdentifier OptionalParenthesizedColumnSpecificationList OptionalComment OptionalTblProperties 'CURSOR'
+   {
+     parser.suggestKeywords(parser.getKeywordsForOptionalsLR(
+       [undefined, $5, $4],
+       [{ value: 'AS', weight: 1 },
+        { value: 'TBLPROPERTIES', weight: 2 },
+        { value: 'COMMENT', weight: 3 }]));
+   }
+ | CreateViewLeftPart SchemaQualifiedTableIdentifier ParenthesizedColumnSpecificationList_EDIT OptionalComment OptionalTblProperties
+ | CreateViewLeftPart SchemaQualifiedTableIdentifier ParenthesizedColumnSpecificationList_EDIT OptionalComment OptionalTblProperties AsQuerySpecification
+ | CreateViewLeftPart SchemaQualifiedTableIdentifier OptionalParenthesizedColumnSpecificationList OptionalComment OptionalTblProperties AsQuerySpecification_EDIT
+ | CreateViewLeftPart 'CURSOR' SchemaQualifiedTableIdentifier OptionalParenthesizedColumnSpecificationList OptionalComment OptionalTblProperties AsQuerySpecification
+   {
+     parser.checkForKeywords($1);
+   }
+ ;
+
+CreateViewLeftPart
+ : 'CREATE' OptionalOrReplace OptionalTemporary 'VIEW' OptionalIfNotExists
+   {
+     if (!$5) {
+       $$ = { suggestKeywords: ['IF NOT EXISTS'] };
+     }
+   }
+ ;
+
+CreateViewLeftPart_EDIT
+ : 'CREATE' OptionalOrReplace OptionalTemporary 'CURSOR' 'VIEW' OptionalIfNotExists
+   {
+     if (!$3 && !$2) {
+       parser.yy.suggestKeywords(['OR REPLACE', 'GLOBAL TEMPORARY', 'TEMPORARY']);
+     } else if (!$2) {
+       parser.yy.suggestKeywords(['GLOBAL TEMPORARY', 'TEMPORARY']);
+     }
+   }
+ | 'CREATE' OrReplace_EDIT OptionalTemporary 'VIEW' OptionalIfNotExists
+ | 'CREATE' OptionalOrReplace Temporary_EDIT 'VIEW' OptionalIfNotExists
+ | 'CREATE' OptionalOrReplace OptionalTemporary 'VIEW' IfNotExists_EDIT
+ ;

+ 170 - 0
desktop/core/src/desktop/js/parse/sql/sparksql/jison/create/create_view.test.json

@@ -0,0 +1,170 @@
+[
+  {
+    "namePrefix": "should not report errors",
+    "beforeCursor": "CREATE OR REPLACE GLOBAL TEMPORARY VIEW IF NOT EXISTS foo.bar (id int) COMMENT 'bla' TBLPROPERTIES ('a' = 'b') AS SELECT * FROM bla; ",
+    "afterCursor": "",
+    "noErrors": true,
+    "containsKeywords": [
+      "SELECT"
+    ],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE ",
+    "afterCursor": "",
+    "containsKeywords": [
+      "OR REPLACE",
+      "GLOBAL TEMPORARY VIEW",
+      "TEMPORARY VIEW",
+      "VIEW"
+    ],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE OR REPLACE ",
+    "afterCursor": "",
+    "containsKeywords": [
+      "GLOBAL TEMPORARY VIEW",
+      "TEMPORARY VIEW",
+      "VIEW"
+    ],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE OR REPLACE GLOBAL ",
+    "afterCursor": "",
+    "containsKeywords": [
+      "TEMPORARY"
+    ],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE OR REPLACE GLOBAL TEMPORARY ",
+    "afterCursor": "",
+    "containsKeywords": [
+      "VIEW"
+    ],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE OR REPLACE GLOBAL TEMPORARY VIEW ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "IF NOT EXISTS"
+      ],
+      "suggestDatabases": { "appendDot": true }
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE OR REPLACE GLOBAL TEMPORARY VIEW IF ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "NOT EXISTS"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE OR REPLACE GLOBAL TEMPORARY VIEW IF NOT ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "EXISTS"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE OR REPLACE GLOBAL TEMPORARY VIEW IF NOT EXISTS ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestDatabases": { "appendDot": true }
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE OR REPLACE GLOBAL TEMPORARY VIEW IF NOT EXISTS foo ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": ["COMMENT", "TBLPROPERTIES", "AS"]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE VIEW foo ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "COMMENT", "TBLPROPERTIES", "AS"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE VIEW foo COMMENT 'bla' ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "TBLPROPERTIES", "AS"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE VIEW foo COMMENT 'bla' TBLPROPERTIES ('a'='b') ",
+    "afterCursor": "",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "AS"
+      ]
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE VIEW foo COMMENT 'bla' TBLPROPERTIES ('a'='b') AS ",
+    "afterCursor": "",
+    "containsKeywords": [
+      "SELECT"
+    ],
+    "expectedResult": {
+      "lowerCase": false
+    }
+  },
+  {
+    "namePrefix": "should suggest keywords",
+    "beforeCursor": "CREATE OR REPLACE GLOBAL TEMPORARY VIEW ",
+    "afterCursor": " foo COMMENT 'bla' TBLPROPERTIES ('a'='b') AS SELECT * FROM foo; ",
+    "expectedResult": {
+      "lowerCase": false,
+      "suggestKeywords": [
+        "IF NOT EXISTS"
+      ]
+    }
+  }
+]

+ 66 - 16
desktop/core/src/desktop/js/parse/sql/sparksql/jison/sql.jisonlex

@@ -29,7 +29,6 @@
 <between>'AND'                             { this.popState(); return 'BETWEEN_AND'; }
 
 // Reserved Keywords
-'ADD'                                      { return 'ADD'; }
 'ALL'                                      { return 'ALL'; }
 'ALTER'                                    { parser.determineCase(yytext); parser.addStatementTypeLocation('ALTER', yylloc, yy.lexer.upcomingInput()); return 'ALTER'; }
 'AND'                                      { return 'AND'; }
@@ -41,16 +40,13 @@
 'BY'                                       { return 'BY'; }
 'CASCADE'                                  { return 'CASCADE'; }
 'CASE'                                     { return 'CASE'; }
-'CHANGE'                                   { return 'CHANGE'; }
 'CHAR'                                     { return 'CHAR'; }
-'COLUMN'                                   { return 'COLUMN'; }
 'COLUMNS'                                  { return 'COLUMNS'; }
 'COMMENT'                                  { return 'COMMENT'; }
 'CREATE'                                   { parser.determineCase(yytext); return 'CREATE'; }
 'CROSS'                                    { return 'CROSS'; }
 'CURRENT'                                  { return 'CURRENT'; }
 'DATABASE'                                 { return 'DATABASE'; }
-'DBPROPERTIES'                             { return 'DBPROPERTIES'; }
 'DECIMAL'                                  { return 'DECIMAL'; }
 'DESC'                                     { return 'DESC'; }
 'DISTINCT'                                 { return 'DISTINCT'; }
@@ -61,7 +57,6 @@
 'END'                                      { return 'END'; }
 'EXISTS'                                   { parser.yy.correlatedSubQuery = true; return 'EXISTS'; }
 'FALSE'                                    { return 'FALSE'; }
-'FILEFORMAT'                               { return 'FILEFORMAT'; }
 'FLOAT'                                    { return 'FLOAT'; }
 'FOLLOWING'                                { return 'FOLLOWING'; }
 'FROM'                                     { parser.determineCase(yytext); return 'FROM'; }
@@ -79,8 +74,6 @@
 'LEFT'                                     { return 'LEFT'; }
 'LIKE'                                     { return 'LIKE'; }
 'LIMIT'                                    { return 'LIMIT'; }
-'LOCATION'                                 { return 'LOCATION'; }
-'NAMESPACE'                                { return 'NAMESPACE'; }
 'NOT'                                      { return 'NOT'; }
 'NULL'                                     { return 'NULL'; }
 'ON'                                       { return 'ON'; }
@@ -89,15 +82,10 @@
 'ORDER'                                    { return 'ORDER'; }
 'OUTER'                                    { return 'OUTER'; }
 'PARTITION'                                { return 'PARTITION'; }
-'PARTITIONS'                               { return 'PARTITIONS'; }
 'PRECEDING'                                { return 'PRECEDING'; }
-'PROPERTIES'                               { return 'PROPERTIES'; }
 'PURGE'                                    { return 'PURGE'; }
 'RANGE'                                    { return 'RANGE'; }
-'RECOVER'                                  { return 'RECOVER'; }
 'REGEXP'                                   { return 'REGEXP'; }
-'RENAME'                                   { return 'RENAME'; }
-'REPLACE'                                  { return 'REPLACE'; }
 'RIGHT'                                    { return 'RIGHT'; }
 'RLIKE'                                    { return 'RLIKE'; }
 'ROW'                                      { return 'ROW'; }
@@ -107,15 +95,12 @@
 'SCHEMAS'                                  { return 'SCHEMAS'; }
 'SELECT'                                   { parser.determineCase(yytext); parser.addStatementTypeLocation('SELECT', yylloc); return 'SELECT'; }
 'SEMI'                                     { return 'SEMI'; }
-'SERDE'                                    { return 'SERDE'; }
-'SERDEPROPERTIES'                          { return 'SERDEPROPERTIES'; }
 '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'; }
 'TABLES'                                   { return 'TABLES'; }
-'TBLPROPERTIES'                            { return 'TBLPROPERTIES'; }
 'THEN'                                     { return 'THEN'; }
 'TIMESTAMP'                                { return 'TIMESTAMP'; }
 'TINYINT'                                  { return 'TINYINT'; }
@@ -124,7 +109,6 @@
 'TRUNCATE'                                 { parser.determineCase(yytext); parser.addStatementTypeLocation('TRUNCATE', yylloc, yy.lexer.upcomingInput()); return 'TRUNCATE'; }
 'UNBOUNDED'                                { return 'UNBOUNDED'; }
 'UNION'                                    { return 'UNION'; }
-'UNSET'                                    { return 'UNSET'; }
 'UPDATE'                                   { parser.determineCase(yytext); return 'UPDATE'; }
 'USE'                                      { parser.determineCase(yytext); parser.addStatementTypeLocation('USE', yylloc); return 'USE'; }
 'VALUES'                                   { return 'VALUES'; }
@@ -134,9 +118,75 @@
 'WHERE'                                    { return 'WHERE'; }
 'WITH'                                     { parser.determineCase(yytext); parser.addStatementTypeLocation('WITH', yylloc); return 'WITH'; }
 
+// Unknown if reserved or not
+'ADD'                                      { return 'ADD'; }
+'ARCHIVE'                                  { return 'ARCHIVE'; }
+'BINARY'                                   { return 'BINARY'; }
+'BUCKETS'                                  { return 'BUCKETS'; }
+'BYTE'                                     { return 'BYTE'; }
+'CHANGE'                                   { return 'CHANGE'; }
+'CLUSTERED'                                { return 'CLUSTERED'; }
+'COLLECTION'                               { return 'COLLECTION'; }
+'COLUMN'                                   { return 'COLUMN'; }
+'DATE'                                     { return 'DATE'; }
+'DAY'                                      { return 'DAY'; }
+'DBPROPERTIES'                             { return 'DBPROPERTIES'; }
+'DEC'                                      { return 'DEC'; }
+'DEFINED'                                  { return 'DEFINED'; }
+'DELIMITED'                                { return 'DELIMITED'; }
+'ESCAPED'                                  { return 'ESCAPED'; }
+'EXTERNAL'                                 { return 'EXTERNAL'; }
+'FIELDS'                                   { return 'FIELDS'; }
+'FILE'                                     { return 'FILE'; }
+'FILEFORMAT'                               { return 'FILEFORMAT'; }
+'FORMAT'                                   { return 'FORMAT'; }
+'FUNCTION'                                 { return 'FUNCTION'; }
+'GLOBAL'                                   { return 'GLOBAL'; }
+'HOUR'                                     { return 'HOUR'; }
+'INTEGER'                                  { return 'INTEGER'; }
+'INTERVAL'                                 { return 'INTERVAL'; }
+'ITEMS'                                    { return 'ITEMS'; }
+'JAR'                                      { return 'JAR'; }
+'KEYS'                                     { return 'KEYS'; }
+'LINES'                                    { return 'LINES'; }
+'LOCATION'                                 { return 'LOCATION'; }
+'LONG'                                     { return 'LONG'; }
+'MAP'                                      { return 'MAP'; }
+'MINUTE'                                   { return 'MINUTE'; }
+'MONTH'                                    { return 'MONTH'; }
+'NAMESPACE'                                { return 'NAMESPACE'; }
+'NUMERIC'                                  { return 'NUMERIC'; }
+'OPTIONS'                                  { return 'OPTIONS'; }
+'PARTITIONED'                              { return 'PARTITIONED'; }
+'PARTITIONS'                               { return 'PARTITIONS'; }
+'PROPERTIES'                               { return 'PROPERTIES'; }
+'REAL'                                     { return 'REAL'; }
+'RECOVER'                                  { return 'RECOVER'; }
+'RENAME'                                   { return 'RENAME'; }
+'REPLACE'                                  { return 'REPLACE'; }
+'SECOND'                                   { return 'SECOND'; }
+'SERDE'                                    { return 'SERDE'; }
+'SERDEPROPERTIES'                          { return 'SERDEPROPERTIES'; }
+'SHORT'                                    { return 'SHORT'; }
+'SORTED'                                   { return 'SORTED'; }
+'STORED'                                   { return 'STORED'; }
+'TBLPROPERTIES'                            { return 'TBLPROPERTIES'; }
+'TEMPORARY'                                { return 'TEMPORARY'; }
+'TERMINATED'                               { return 'TERMINATED'; }
+'UNSET'                                    { return 'UNSET'; }
+'USING'                                    { return 'USING'; }
+'YEAR'                                     { return 'YEAR'; }
+
 // Non-reserved Keywords
+'CSV'                                      { return 'CSV'; }
+'JDBC'                                     { return 'JDBC'; }
+'JSON'                                     { return 'JSON'; }
+'ORC'                                      { return 'ORC'; }
 'OVER'                                     { return 'OVER'; }
+'PARQUET'                                  { return 'PARQUET'; }
 'ROLE'                                     { return 'ROLE'; }
+'TEXTFILE'                                 { return 'TEXTFILE'; }
+'TXT'                                      { return 'TXT'; }
 
 // --- UDFs ---
 AVG\s*\(                                   { yy.lexer.unput('('); yytext = 'avg'; parser.addFunctionLocation(yylloc, yytext); return 'AVG'; }

+ 14 - 0
desktop/core/src/desktop/js/parse/sql/sparksql/jison/structure.json

@@ -6,7 +6,14 @@
     "alter/alter_database.jison",
     "alter/alter_table.jison",
     "alter/alter_view.jison",
+    "common.jison",
+    "../../hive/jison/create/clustered_by.jison",
     "create/create_common.jison",
+    "create/create_database.jison",
+    "create/create_function.jison",
+    "create/create_table.jison",
+    "create/create_view.jison",
+    "../../hive/jison/create/row_format.jison",
     "../../generic/jison/select/cte_select_statement.jison",
     "../../generic/jison/select/from_clause.jison",
     "../../generic/jison/select/group_by_clause.jison",
@@ -47,7 +54,14 @@
     "alter/alter_database.jison",
     "alter/alter_table.jison",
     "alter/alter_view.jison",
+    "common.jison",
+    "../../hive/jison/create/clustered_by.jison",
     "create/create_common.jison",
+    "create/create_database.jison",
+    "create/create_function.jison",
+    "create/create_table.jison",
+    "create/create_view.jison",
+    "../../hive/jison/create/row_format.jison",
     "../../generic/jison/select/cte_select_statement.jison",
     "../../generic/jison/select/from_clause.jison",
     "../../generic/jison/select/group_by_clause.jison",

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


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


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