Browse Source

HUE-7986 [autocomplete] Update the autocompleter and UDF library for Impala

- Added new boolean operators impala (IS TRUE, IS NOT TRUE, IS FALSE, IS NOT FALSE, IS UNKNOWN, and IS NOT UNKNOWN)
- Add support for SET ALL
- Add support for altering Kudu columns using ALTER TABLE
- Support SET COLUMN STATS through ALTER TABLE
- Update the UDF function library
Johan Ahlen 7 years ago
parent
commit
953d14f4d3

File diff suppressed because it is too large
+ 0 - 0
desktop/core/src/desktop/static/desktop/js/ace/mode-impala.js


+ 1 - 0
desktop/core/src/desktop/static/desktop/js/autocomplete/jison/sql.jisonlex

@@ -316,6 +316,7 @@
 <impala>'ROLE'                             { return '<impala>ROLE'; }
 <impala>'ROLE'                             { return '<impala>ROLE'; }
 <impala>'ROLES'                            { return '<impala>ROLES'; }
 <impala>'ROLES'                            { return '<impala>ROLES'; }
 <impala>'STRUCT'                           { return 'STRUCT'; }
 <impala>'STRUCT'                           { return 'STRUCT'; }
+<impala>'UNKNOWN'                          { return '<impala>UNKNOWN'; }
 <impala>\[BROADCAST\]                      { return '<impala>BROADCAST'; }
 <impala>\[BROADCAST\]                      { return '<impala>BROADCAST'; }
 <impala>\[NOSHUFFLE\]                      { return '<impala>NOSHUFFLE'; }
 <impala>\[NOSHUFFLE\]                      { return '<impala>NOSHUFFLE'; }
 <impala>\[SHUFFLE\]                        { return '<impala>SHUFFLE'; }
 <impala>\[SHUFFLE\]                        { return '<impala>SHUFFLE'; }

+ 121 - 4
desktop/core/src/desktop/static/desktop/js/autocomplete/jison/sql_alter.jison

@@ -140,6 +140,7 @@ AlterTable
  | AlterTableLeftSide AnyAdd '<hive>CONSTRAINT' RegularOrBacktickedIdentifier HiveForeignKeySpecification
  | AlterTableLeftSide AnyAdd '<hive>CONSTRAINT' RegularOrBacktickedIdentifier HiveForeignKeySpecification
  | AlterTableLeftSide AnyRename 'TO' RegularOrBackTickedSchemaQualifiedName
  | AlterTableLeftSide AnyRename 'TO' RegularOrBackTickedSchemaQualifiedName
  | AlterTableLeftSide HiveSpecificOperations
  | AlterTableLeftSide HiveSpecificOperations
+ | AlterTableLeftSide ImpalaSpecificOperations
  | AlterTableLeftSide DropOperations
  | AlterTableLeftSide DropOperations
  | AlterTableLeftSide OptionalPartitionOperations
  | AlterTableLeftSide OptionalPartitionOperations
  | AlterTableLeftSide PartitionSpec OptionalPartitionOperations
  | AlterTableLeftSide PartitionSpec OptionalPartitionOperations
@@ -151,6 +152,7 @@ AlterTable_EDIT
  | AlterTableLeftSide_EDIT AnyAdd OptionalIfNotExists PartitionSpec OptionalHdfsLocation OptionalPartitionSpecs OptionalCachedInOrUncached
  | AlterTableLeftSide_EDIT AnyAdd OptionalIfNotExists PartitionSpec OptionalHdfsLocation OptionalPartitionSpecs OptionalCachedInOrUncached
  | AlterTableLeftSide_EDIT AnyRename 'TO' RegularOrBackTickedSchemaQualifiedName
  | AlterTableLeftSide_EDIT AnyRename 'TO' RegularOrBackTickedSchemaQualifiedName
  | AlterTableLeftSide_EDIT HiveSpecificOperations
  | AlterTableLeftSide_EDIT HiveSpecificOperations
+ | AlterTableLeftSide_EDIT ImpalaSpecificOperations
  | AlterTableLeftSide_EDIT DropOperations
  | AlterTableLeftSide_EDIT DropOperations
  | AlterTableLeftSide_EDIT OptionalPartitionOperations
  | AlterTableLeftSide_EDIT OptionalPartitionOperations
  | AlterTableLeftSide_EDIT PartitionSpec OptionalPartitionOperations
  | AlterTableLeftSide_EDIT PartitionSpec OptionalPartitionOperations
@@ -218,6 +220,7 @@ AlterTable_EDIT
  | AlterTableLeftSide AnyAdd '<hive>CONSTRAINT' RegularOrBacktickedIdentifier HivePrimaryKeySpecification_EDIT
  | AlterTableLeftSide AnyAdd '<hive>CONSTRAINT' RegularOrBacktickedIdentifier HivePrimaryKeySpecification_EDIT
  | AlterTableLeftSide AnyAdd '<hive>CONSTRAINT' RegularOrBacktickedIdentifier HiveForeignKeySpecification_EDIT
  | AlterTableLeftSide AnyAdd '<hive>CONSTRAINT' RegularOrBacktickedIdentifier HiveForeignKeySpecification_EDIT
  | AlterTableLeftSide HiveSpecificOperations_EDIT
  | AlterTableLeftSide HiveSpecificOperations_EDIT
+ | AlterTableLeftSide ImpalaSpecificOperations_EDIT
  | AlterTableLeftSide OptionalPartitionOperations_EDIT
  | AlterTableLeftSide OptionalPartitionOperations_EDIT
  | AlterTableLeftSide DropOperations_EDIT
  | AlterTableLeftSide DropOperations_EDIT
  | AlterTableLeftSide 'CURSOR'
  | AlterTableLeftSide 'CURSOR'
@@ -229,9 +232,10 @@ AlterTable_EDIT
          'RECOVER PARTITIONS', 'RENAME TO', 'REPLACE COLUMNS', 'SET FILEFORMAT', 'SET LOCATION', 'SET SERDE',
          'RECOVER PARTITIONS', 'RENAME TO', 'REPLACE COLUMNS', 'SET FILEFORMAT', 'SET LOCATION', 'SET SERDE',
          'SET SERDEPROPERTIES', 'SET SKEWED LOCATION', 'SET TBLPROPERTIES', 'SKEWED BY', 'TOUCH', 'UNARCHIVE PARTITION']);
          'SET SERDEPROPERTIES', 'SET SKEWED LOCATION', 'SET TBLPROPERTIES', 'SKEWED BY', 'TOUCH', 'UNARCHIVE PARTITION']);
      } else if (parser.isImpala()) {
      } else if (parser.isImpala()) {
-       parser.suggestKeywords(['ADD COLUMNS', 'ADD PARTITION', 'ADD RANGE PARTITION', 'CHANGE', 'DROP COLUMN',
-         'DROP PARTITION', 'DROP RANGE PARTITION', 'PARTITION', 'RECOVER PARTITIONS', 'RENAME TO', 'REPLACE COLUMNS',
-         'SET CACHED IN', 'SET FILEFORMAT', 'SET LOCATION','SET SERDEPROPERTIES', 'SET TBLPROPERTIES', 'SET UNCACHED']);
+       parser.suggestKeywords(['ADD COLUMNS', 'ADD PARTITION', 'ADD RANGE PARTITION', 'ALTER', 'ALTER COLUMN', 'CHANGE',
+         'DROP COLUMN', 'DROP PARTITION', 'DROP RANGE PARTITION', 'PARTITION', 'RECOVER PARTITIONS', 'RENAME TO',
+         'REPLACE COLUMNS', 'SET CACHED IN', 'SET COLUMN STATS', 'SET FILEFORMAT', 'SET LOCATION','SET SERDEPROPERTIES',
+         'SET TBLPROPERTIES', 'SET UNCACHED']);
      }
      }
    }
    }
  | AlterTableLeftSide PartitionSpec 'CURSOR'
  | AlterTableLeftSide PartitionSpec 'CURSOR'
@@ -262,7 +266,7 @@ AlterTable_EDIT
      if (parser.isHive()) {
      if (parser.isHive()) {
        parser.suggestKeywords(['FILEFORMAT', 'LOCATION', 'SERDE', 'SERDEPROPERTIES', 'SKEWED LOCATION', 'TBLPROPERTIES']);
        parser.suggestKeywords(['FILEFORMAT', 'LOCATION', 'SERDE', 'SERDEPROPERTIES', 'SKEWED LOCATION', 'TBLPROPERTIES']);
      } else if (parser.isImpala()) {
      } else if (parser.isImpala()) {
-       parser.suggestKeywords(['CACHED IN', 'FILEFORMAT', 'LOCATION', 'SERDEPROPERTIES', 'TBLPROPERTIES', 'UNCACHED']);
+       parser.suggestKeywords(['CACHED IN', 'COLUMN STATS', 'FILEFORMAT', 'LOCATION', 'SERDEPROPERTIES', 'TBLPROPERTIES', 'UNCACHED']);
      }
      }
    }
    }
  | AlterTableLeftSide PartitionSpec OptionalPartitionOperations_EDIT
  | AlterTableLeftSide PartitionSpec OptionalPartitionOperations_EDIT
@@ -357,6 +361,119 @@ HiveSpecificOperations_EDIT
  | '<hive>TOUCH' OptionalPartitionSpec_EDIT
  | '<hive>TOUCH' OptionalPartitionSpec_EDIT
  ;
  ;
 
 
+ImpalaSpecificOperations
+ : 'ALTER' OptionalImpalaColumn ColumnIdentifier 'SET' KuduStorageAttribute SetValue
+   {
+     parser.addColumnLocation($3.location, [ $3.identifier ]);
+   }
+ | 'ALTER' OptionalImpalaColumn ColumnIdentifier 'DROP' '<impala>DEFAULT'
+   {
+     parser.addColumnLocation($3.location, [ $3.identifier ]);
+   }
+ | 'SET' '<impala>COLUMN' '<impala>STATS' ColumnIdentifier ParenthesizedStatsList
+   {
+     parser.addColumnLocation($4.location, [ $4.identifier ]);
+   }
+ ;
+
+ImpalaSpecificOperations_EDIT
+ : 'ALTER' OptionalImpalaColumn 'CURSOR'
+   {
+     if (parser.isImpala()) {
+       if (!$2) {
+         parser.suggestKeywords(['COLUMN']);
+       }
+       parser.suggestColumns();
+     }
+   }
+ | 'ALTER' OptionalImpalaColumn ColumnIdentifier 'CURSOR'
+   {
+     if (parser.isImpala()) {
+       parser.suggestKeywords(['DROP DEFAULT', 'SET BLOCK_SIZE', 'SET COMMENT', 'SET COMPRESSION', 'SET DEFAULT',
+         'SET ENCODING']);
+        parser.addColumnLocation($3.location, [ $3.identifier ]);
+     }
+   }
+ | 'ALTER' OptionalImpalaColumn ColumnIdentifier 'DROP' 'CURSOR'
+   {
+     if (parser.isImpala()) {
+       parser.suggestKeywords(['DEFAULT']);
+       parser.addColumnLocation($3.location, [ $3.identifier ]);
+     }
+   }
+ | 'ALTER' OptionalImpalaColumn ColumnIdentifier 'SET' 'CURSOR'
+   {
+     if (parser.isImpala()) {
+       parser.suggestKeywords(['BLOCK_SIZE', 'COMMENT', 'COMPRESSION', 'DEFAULT', 'ENCODING']);
+       parser.addColumnLocation($3.location, [ $3.identifier ]);
+     }
+   }
+ | 'ALTER' OptionalImpalaColumn ColumnIdentifier 'SET' KuduStorageAttribute 'CURSOR'
+   {
+     parser.addColumnLocation($3.location, [ $3.identifier ]);
+   }
+ | 'SET' '<impala>COLUMN' 'CURSOR'
+   {
+     parser.suggestKeywords(['STATS']);
+   }
+ | 'SET' '<impala>COLUMN' '<impala>STATS' 'CURSOR'
+   {
+     parser.suggestColumns();
+   }
+ | 'SET' '<impala>COLUMN' '<impala>STATS' ColumnIdentifier 'CURSOR'
+   {
+     parser.addColumnLocation($4.location, [ $4.identifier ]);
+   }
+ | 'SET' '<impala>COLUMN' '<impala>STATS' ColumnIdentifier ParenthesizedStatsList_EDIT
+   {
+     parser.addColumnLocation($4.location, [ $4.identifier ]);
+   }
+ ;
+
+KuduStorageAttribute
+ : '<impala>BLOCK_SIZE'
+ | '<impala>COMMENT'
+ | '<impala>COMPRESSION'
+ | '<impala>DEFAULT'
+ | '<impala>ENCODING'
+ ;
+
+OptionalImpalaColumn
+ :
+ | '<impala>COLUMN'
+ ;
+
+ParenthesizedStatsList
+ : '(' StatsList ')'
+ ;
+
+ParenthesizedStatsList_EDIT
+ : '(' StatsList_EDIT RightParenthesisOrError
+ ;
+
+StatsList
+ : StatsAssignment
+ | StatsList ',' StatsAssignment
+ ;
+
+StatsList_EDIT
+ : StatsAssignment_EDIT
+ | StatsList ',' StatsAssignment_EDIT
+ | StatsList ',' StatsAssignment_EDIT ',' StatsList
+ | StatsAssignment_EDIT ',' StatsList
+ ;
+
+StatsAssignment
+ : QuotedValue '=' QuotedValue
+ ;
+
+StatsAssignment_EDIT
+ : 'CURSOR'
+   {
+     parser.suggestIdentifiers(['\'avgSize\'', '\'maxSize\'', '\'numDVs\'', '\'numNulls\'']);
+   }
+ ;
+
 OptionalPartitionOperations
 OptionalPartitionOperations
  : 'SET' AnyFileFormat FileFormat
  : 'SET' AnyFileFormat FileFormat
  | 'SET' HdfsLocation
  | 'SET' HdfsLocation

+ 1 - 0
desktop/core/src/desktop/static/desktop/js/autocomplete/jison/sql_main.jison

@@ -247,6 +247,7 @@ NonReservedKeyword
  | '<impala>ROLES'
  | '<impala>ROLES'
  | '<impala>URI'
  | '<impala>URI'
  | '<impala>SERVER'
  | '<impala>SERVER'
+ | '<impala>UNKNOWN'
 // | '<impala>BROADCAST'
 // | '<impala>BROADCAST'
 // | '<impala>NOSHUFFLE'
 // | '<impala>NOSHUFFLE'
 // | '<impala>SHUFFLE'
 // | '<impala>SHUFFLE'

+ 4 - 0
desktop/core/src/desktop/static/desktop/js/autocomplete/jison/sql_set.jison

@@ -27,11 +27,15 @@ DataDefinition_EDIT
      if (parser.isHive()) {
      if (parser.isHive()) {
        parser.suggestKeywords(['ROLE']);
        parser.suggestKeywords(['ROLE']);
      }
      }
+     if (parser.isImpala()) {
+       parser.suggestKeywords(['ALL']);
+     }
    }
    }
  ;
  ;
 
 
 SetSpecification
 SetSpecification
  : 'SET' SetOption '=' SetValue
  : 'SET' SetOption '=' SetValue
+ | 'SET' 'ALL'
  ;
  ;
 
 
 SetOption
 SetOption

+ 20 - 7
desktop/core/src/desktop/static/desktop/js/autocomplete/jison/sql_valueExpression.jison

@@ -33,6 +33,9 @@ ValueExpression
      $2.types = ['NUMBER'];
      $2.types = ['NUMBER'];
    }
    }
  | ValueExpression 'IS' OptionalNot 'NULL'                             -> { types: [ 'BOOLEAN' ] }
  | ValueExpression 'IS' OptionalNot 'NULL'                             -> { types: [ 'BOOLEAN' ] }
+ | ValueExpression 'IS' OptionalNot 'TRUE'                             -> { types: [ 'BOOLEAN' ] }
+ | ValueExpression 'IS' OptionalNot 'FALSE'                            -> { types: [ 'BOOLEAN' ] }
+ | ValueExpression 'IS' OptionalNot '<impala>UNKNOWN'                  -> { types: [ 'BOOLEAN' ] }
  | ValueExpression 'IS' OptionalNot 'DISTINCT' 'FROM' ValueExpression  -> { types: [ 'BOOLEAN' ] }
  | ValueExpression 'IS' OptionalNot 'DISTINCT' 'FROM' ValueExpression  -> { types: [ 'BOOLEAN' ] }
  ;
  ;
 
 
@@ -74,21 +77,21 @@ ValueExpression_EDIT
    }
    }
  | ValueExpression 'IS' 'CURSOR'
  | ValueExpression 'IS' 'CURSOR'
    {
    {
+     var keywords = ['FALSE', 'NOT NULL', 'NOT TRUE', 'NOT FALSE', 'NULL', 'TRUE'];
      if (parser.isImpala()) {
      if (parser.isImpala()) {
-       parser.suggestKeywords(['DISTINCT FROM', 'NOT DISTINCT FROM', 'NOT NULL', 'NULL']);
-     } else {
-       parser.suggestKeywords(['NOT NULL', 'NULL']);
+       keywords = keywords.concat(['DISTINCT FROM', 'NOT DISTINCT FROM', 'NOT UNKNOWN', 'UNKNOWN']);
      }
      }
+     parser.suggestKeywords(keywords);
      $$ = { types: [ 'BOOLEAN' ] };
      $$ = { types: [ 'BOOLEAN' ] };
    }
    }
  | ValueExpression 'IS' 'NOT' 'CURSOR'
  | ValueExpression 'IS' 'NOT' 'CURSOR'
    {
    {
+     var keywords = ['FALSE', 'NULL', 'TRUE'];
      if (parser.isImpala()) {
      if (parser.isImpala()) {
-       parser.suggestKeywords(['DISTINCT FROM', 'NULL']);
-     } else {
-       parser.suggestKeywords(['NULL']);
+       keywords = keywords.concat(['DISTINCT FROM', 'UNKNOWN']);
      }
      }
-      $$ = { types: [ 'BOOLEAN' ] };
+     parser.suggestKeywords(keywords);
+     $$ = { types: [ 'BOOLEAN' ] };
    }
    }
  | ValueExpression 'IS' OptionalNot 'DISTINCT' 'CURSOR'
  | ValueExpression 'IS' OptionalNot 'DISTINCT' 'CURSOR'
    {
    {
@@ -102,6 +105,16 @@ ValueExpression_EDIT
      parser.suggestKeywords(['NOT']);
      parser.suggestKeywords(['NOT']);
      $$ = { types: [ 'BOOLEAN' ] };
      $$ = { types: [ 'BOOLEAN' ] };
    }
    }
+ | ValueExpression 'IS' 'CURSOR' 'FALSE'
+   {
+     parser.suggestKeywords(['NOT']);
+     $$ = { types: [ 'BOOLEAN' ] };
+   }
+ | ValueExpression 'IS' 'CURSOR' 'TRUE'
+   {
+     parser.suggestKeywords(['NOT']);
+     $$ = { types: [ 'BOOLEAN' ] };
+   }
  | ValueExpression 'IS' OptionalNot 'DISTINCT' 'FROM' PartialBacktickedOrAnyCursor
  | ValueExpression 'IS' OptionalNot 'DISTINCT' 'FROM' PartialBacktickedOrAnyCursor
    {
    {
      parser.valueExpressionSuggest($1, $3 ? 'IS NOT DISTINCT FROM' : 'IS DISTINCT FROM');
      parser.valueExpressionSuggest($1, $3 ? 'IS NOT DISTINCT FROM' : 'IS DISTINCT FROM');

+ 140 - 4
desktop/core/src/desktop/static/desktop/js/autocomplete/spec/sqlSpecAlter.js

@@ -228,6 +228,32 @@
     });
     });
 
 
     describe('ALTER TABLE', function () {
     describe('ALTER TABLE', function () {
+      it('should handle "ALTER TABLE foo ALTER COLUMN bar SET COMMENT \'boo\'; |"', function() {
+        assertAutoComplete({
+          beforeCursor: 'ALTER TABLE foo ALTER COLUMN bar SET COMMENT \'boo\';  ',
+          afterCursor: '',
+          noErrors: true,
+          dialect: 'impala',
+          containsKeywords: ['SELECT'],
+          expectedResult: {
+            lowerCase: false
+          }
+        });
+      });
+
+      it('should handle "ALTER TABLE foo ALTER bar DROP DEFAULT; |"', function() {
+        assertAutoComplete({
+          beforeCursor: 'ALTER TABLE foo ALTER bar DROP DEFAULT;  ',
+          afterCursor: '',
+          noErrors: true,
+          dialect: 'impala',
+          containsKeywords: ['SELECT'],
+          expectedResult: {
+            lowerCase: false
+          }
+        });
+      });
+
       it('should suggest keywords for "ALTER |"', function() {
       it('should suggest keywords for "ALTER |"', function() {
         assertAutoComplete({
         assertAutoComplete({
           beforeCursor: 'ALTER ',
           beforeCursor: 'ALTER ',
@@ -1559,7 +1585,20 @@
 
 
       });
       });
 
 
-      describe('Impala specific', function () {
+     describe('Impala specific', function () {
+        it('should handle "ALTER TABLE db.tbl SET COLUMN STATS foo (\'numDVs\'=\'2\',\'numNulls\'=\'0\'); |"', function() {
+          assertAutoComplete({
+            beforeCursor: 'ALTER TABLE db.tbl SET COLUMN STATS foo (\'numDVs\'=\'2\',\'numNulls\'=\'0\'); ',
+            afterCursor: '',
+            dialect: 'impala',
+            noErrors: true,
+            containsKeywords: ['SELECT'],
+            expectedResult: {
+              lowerCase: false
+            }
+          });
+        });
+
         it('should suggest databases for "ALTER TABLE db.tbl RENAME TO |"', function() {
         it('should suggest databases for "ALTER TABLE db.tbl RENAME TO |"', function() {
           assertAutoComplete({
           assertAutoComplete({
             beforeCursor: 'ALTER TABLE db.tbl RENAME TO  ',
             beforeCursor: 'ALTER TABLE db.tbl RENAME TO  ',
@@ -1627,14 +1666,111 @@
             dialect: 'impala',
             dialect: 'impala',
             expectedResult: {
             expectedResult: {
               lowerCase: false,
               lowerCase: false,
-              suggestKeywords: ['ADD COLUMNS', 'ADD PARTITION', 'ADD RANGE PARTITION', 'CHANGE',
-                'DROP COLUMN', 'DROP PARTITION', 'DROP RANGE PARTITION', 'PARTITION', 'RECOVER PARTITIONS',
-                'RENAME TO', 'REPLACE COLUMNS', 'SET CACHED IN', 'SET FILEFORMAT', 'SET LOCATION',
+              suggestKeywords: ['ADD COLUMNS', 'ADD PARTITION', 'ADD RANGE PARTITION', 'ALTER', 'ALTER COLUMN',
+                'CHANGE', 'DROP COLUMN', 'DROP PARTITION', 'DROP RANGE PARTITION', 'PARTITION', 'RECOVER PARTITIONS',
+                'RENAME TO', 'REPLACE COLUMNS', 'SET CACHED IN', 'SET COLUMN STATS', 'SET FILEFORMAT', 'SET LOCATION',
                 'SET SERDEPROPERTIES', 'SET TBLPROPERTIES', 'SET UNCACHED' ]
                 'SET SERDEPROPERTIES', 'SET TBLPROPERTIES', 'SET UNCACHED' ]
             }
             }
           });
           });
         });
         });
 
 
+        it('should suggest keywords for "ALTER TABLE bar SET |"', function() {
+          assertAutoComplete({
+            beforeCursor: 'ALTER TABLE bar SET ',
+            afterCursor: '',
+            dialect: 'impala',
+            expectedResult: {
+              lowerCase: false,
+              suggestKeywords: ['CACHED IN', 'COLUMN STATS', 'FILEFORMAT', 'LOCATION', 'SERDEPROPERTIES', 'TBLPROPERTIES', 'UNCACHED']
+            }
+          });
+        });
+
+        it('should suggest keywords for "ALTER TABLE bar SET COLUMN |"', function() {
+          assertAutoComplete({
+            beforeCursor: 'ALTER TABLE bar SET COLUMN ',
+            afterCursor: '',
+            dialect: 'impala',
+            expectedResult: {
+              lowerCase: false,
+              suggestKeywords: ['STATS']
+            }
+          });
+        });
+
+        it('should suggest columns for "ALTER TABLE bar SET COLUMN STATS |"', function() {
+          assertAutoComplete({
+            beforeCursor: 'ALTER TABLE bar SET COLUMN STATS ',
+            afterCursor: '',
+            dialect: 'impala',
+            expectedResult: {
+              lowerCase: false,
+              suggestColumns: { tables: [{ identifierChain: [{ name: 'bar' }] }] }
+            }
+          });
+        });
+
+       it('should handle "ALTER TABLE db.tbl SET COLUMN STATS foo (|"', function() {
+         assertAutoComplete({
+           beforeCursor: 'ALTER TABLE db.tbl SET COLUMN STATS foo (',
+           afterCursor: '',
+           dialect: 'impala',
+           expectedResult: {
+             lowerCase: false,
+             suggestIdentifiers: ['\'avgSize\'', '\'maxSize\'', '\'numDVs\'', '\'numNulls\''],
+           }
+         });
+       });
+
+        it('should suggest keywords for "ALTER TABLE bar ALTER |"', function() {
+          assertAutoComplete({
+            beforeCursor: 'ALTER TABLE bar ALTER ',
+            afterCursor: '',
+            dialect: 'impala',
+            expectedResult: {
+              lowerCase: false,
+              suggestColumns: { tables: [{ identifierChain: [{ name: 'bar' }] }] },
+              suggestKeywords: ['COLUMN']
+            }
+          });
+        });
+
+        it('should suggest keywords for "ALTER TABLE bar ALTER foo |"', function() {
+          assertAutoComplete({
+            beforeCursor: 'ALTER TABLE bar ALTER foo ',
+            afterCursor: '',
+            dialect: 'impala',
+            expectedResult: {
+              lowerCase: false,
+              suggestKeywords: ['DROP DEFAULT', 'SET BLOCK_SIZE', 'SET COMMENT', 'SET COMPRESSION', 'SET DEFAULT', 'SET ENCODING']
+            }
+          });
+        });
+
+        it('should suggest keywords for "ALTER TABLE bar ALTER foo SET |"', function() {
+          assertAutoComplete({
+            beforeCursor: 'ALTER TABLE bar ALTER foo SET ',
+            afterCursor: '',
+            dialect: 'impala',
+            expectedResult: {
+              lowerCase: false,
+              suggestKeywords: ['BLOCK_SIZE', 'COMMENT', 'COMPRESSION', 'DEFAULT', 'ENCODING']
+            }
+          });
+        });
+
+        it('should suggest keywords for "ALTER TABLE bar ALTER foo DROP |"', function() {
+          assertAutoComplete({
+            beforeCursor: 'ALTER TABLE bar ALTER foo DROP ',
+            afterCursor: '',
+            dialect: 'impala',
+            expectedResult: {
+              lowerCase: false,
+              suggestKeywords: ['DEFAULT']
+            }
+          });
+        });
+
         it('should suggest keywords for "ALTER TABLE bar ADD |"', function() {
         it('should suggest keywords for "ALTER TABLE bar ADD |"', function() {
           assertAutoComplete({
           assertAutoComplete({
             beforeCursor: 'ALTER TABLE bar ADD ',
             beforeCursor: 'ALTER TABLE bar ADD ',

+ 29 - 7
desktop/core/src/desktop/static/desktop/js/autocomplete/spec/sqlSpecSelect.js

@@ -4565,7 +4565,7 @@
             lowerCase: false,
             lowerCase: false,
             suggestGroupBys: { prefix: 'GROUP BY', tables: [{ identifierChain: [{ name: 'foo' }] }] },
             suggestGroupBys: { prefix: 'GROUP BY', tables: [{ identifierChain: [{ name: 'foo' }] }] },
             suggestOrderBys: { prefix: 'ORDER BY', tables: [{ identifierChain: [{ name: 'foo' }] }] },
             suggestOrderBys: { prefix: 'ORDER BY', tables: [{ identifierChain: [{ name: 'foo' }] }] },
-            suggestKeywords: ['GROUP BY', 'HAVING', 'ORDER BY', 'LIMIT', 'UNION', '<', '<=', '<=>', '<>', '=', '>', '>=', 'AND', 'BETWEEN', 'IN', 'IS NOT NULL', 'IS NULL', 'NOT BETWEEN', 'NOT IN', 'OR']
+            suggestKeywords: ['GROUP BY', 'HAVING', 'ORDER BY', 'LIMIT', 'UNION', '<', '<=', '<=>', '<>', '=', '>', '>=', 'AND', 'BETWEEN', 'IN', 'IS FALSE', 'IS NOT FALSE', 'IS NOT NULL', 'IS NOT TRUE', 'IS NULL', 'IS TRUE', 'NOT BETWEEN', 'NOT IN', 'OR']
           }
           }
         });
         });
       });
       });
@@ -4579,7 +4579,7 @@
             lowerCase: false,
             lowerCase: false,
             suggestGroupBys: { prefix: 'GROUP BY', tables: [{ identifierChain: [{ name: 'foo' }] }] },
             suggestGroupBys: { prefix: 'GROUP BY', tables: [{ identifierChain: [{ name: 'foo' }] }] },
             suggestOrderBys: { prefix: 'ORDER BY', tables: [{ identifierChain: [{ name: 'foo' }] }] },
             suggestOrderBys: { prefix: 'ORDER BY', tables: [{ identifierChain: [{ name: 'foo' }] }] },
-            suggestKeywords: ['GROUP BY', 'HAVING', 'ORDER BY', 'LIMIT', 'UNION', '<', '<=', '<=>', '<>', '=', '>', '>=', 'AND', 'BETWEEN', 'IN', 'IS NOT NULL', 'IS NULL', 'NOT BETWEEN', 'NOT IN', 'OR']
+            suggestKeywords: ['GROUP BY', 'HAVING', 'ORDER BY', 'LIMIT', 'UNION', '<', '<=', '<=>', '<>', '=', '>', '>=', 'AND', 'BETWEEN', 'IN', 'IS FALSE', 'IS NOT FALSE', 'IS NOT NULL', 'IS NOT TRUE', 'IS NULL', 'IS TRUE', 'NOT BETWEEN', 'NOT IN', 'OR']
           }
           }
         });
         });
       });
       });
@@ -4588,7 +4588,7 @@
         assertAutoComplete({
         assertAutoComplete({
           beforeCursor: 'SELECT * FROM foo WHERE id IS ',
           beforeCursor: 'SELECT * FROM foo WHERE id IS ',
           afterCursor: '',
           afterCursor: '',
-          containsKeywords: ['NOT NULL', 'NULL'],
+          containsKeywords: ['NOT NULL', 'NULL', 'NOT TRUE', 'TRUE', 'NOT FALSE', 'FALSE'],
           expectedResult: {
           expectedResult: {
             lowerCase: false
             lowerCase: false
           }
           }
@@ -4599,7 +4599,7 @@
         assertAutoComplete({
         assertAutoComplete({
           beforeCursor: 'SELECT * FROM foo WHERE id IS NOT ',
           beforeCursor: 'SELECT * FROM foo WHERE id IS NOT ',
           afterCursor: '',
           afterCursor: '',
-          containsKeywords: ['NULL'],
+          containsKeywords: ['NULL', 'FALSE', 'TRUE'],
           expectedResult: {
           expectedResult: {
             lowerCase: false
             lowerCase: false
           }
           }
@@ -4617,6 +4617,28 @@
         });
         });
       });
       });
 
 
+      it('should suggest keywords for "SELECT * FROM foo WHERE id IS | FALSE"', function () {
+        assertAutoComplete({
+          beforeCursor: 'SELECT * FROM foo WHERE id IS ',
+          afterCursor: ' FALSE',
+          expectedResult: {
+            lowerCase: false,
+            suggestKeywords: ['NOT']
+          }
+        });
+      });
+
+      it('should suggest keywords for "SELECT * FROM foo WHERE id IS | TRUE"', function () {
+        assertAutoComplete({
+          beforeCursor: 'SELECT * FROM foo WHERE id IS ',
+          afterCursor: ' TRUE',
+          expectedResult: {
+            lowerCase: false,
+            suggestKeywords: ['NOT']
+          }
+        });
+      });
+
       // Fails because "NOT" is missing
       // Fails because "NOT" is missing
       xit('should suggest keywords for "SELECT * FROM foo WHERE id | LIKE \'bla bla\'"', function () {
       xit('should suggest keywords for "SELECT * FROM foo WHERE id | LIKE \'bla bla\'"', function () {
         assertAutoComplete({
         assertAutoComplete({
@@ -4803,7 +4825,7 @@
             afterCursor: '',
             afterCursor: '',
             dialect: 'impala',
             dialect: 'impala',
             noErrors: true,
             noErrors: true,
-            containsKeywords: ['DISTINCT FROM', 'NOT DISTINCT FROM'],
+            containsKeywords: ['DISTINCT FROM', 'NOT DISTINCT FROM', 'NOT UNKNOWN', 'UNKNOWN'],
             expectedResult: {
             expectedResult: {
               lowerCase: false
               lowerCase: false
             }
             }
@@ -4816,7 +4838,7 @@
             afterCursor: '',
             afterCursor: '',
             dialect: 'impala',
             dialect: 'impala',
             noErrors: true,
             noErrors: true,
-            containsKeywords: ['DISTINCT FROM'],
+            containsKeywords: ['DISTINCT FROM', 'UNKNOWN'],
             expectedResult: {
             expectedResult: {
               lowerCase: false
               lowerCase: false
             }
             }
@@ -4889,7 +4911,7 @@
               lowerCase: false,
               lowerCase: false,
               suggestGroupBys: { prefix: 'GROUP BY', tables: [{ identifierChain: [{ name: 'foo' }] }] },
               suggestGroupBys: { prefix: 'GROUP BY', tables: [{ identifierChain: [{ name: 'foo' }] }] },
               suggestOrderBys: { prefix: 'ORDER BY', tables: [{ identifierChain: [{ name: 'foo' }] }] },
               suggestOrderBys: { prefix: 'ORDER BY', tables: [{ identifierChain: [{ name: 'foo' }] }] },
-              suggestKeywords: ['GROUP BY', 'HAVING', 'WINDOW', 'ORDER BY', 'CLUSTER BY', 'DISTRIBUTE BY', 'SORT BY', 'LIMIT', 'UNION', '<', '<=', '<=>', '<>', '=', '>', '>=', 'AND', 'BETWEEN',  'IN', 'IS NOT NULL', 'IS NULL',  'NOT BETWEEN', 'NOT IN', 'OR']
+              suggestKeywords: ['GROUP BY', 'HAVING', 'WINDOW', 'ORDER BY', 'CLUSTER BY', 'DISTRIBUTE BY', 'SORT BY', 'LIMIT', 'UNION', '<', '<=', '<=>', '<>', '=', '>', '>=', 'AND', 'BETWEEN', 'IN', 'IS FALSE', 'IS NOT FALSE', 'IS NOT NULL', 'IS NOT TRUE', 'IS NULL', 'IS TRUE', 'NOT BETWEEN', 'NOT IN', 'OR']
             }
             }
           });
           });
         });
         });

+ 28 - 0
desktop/core/src/desktop/static/desktop/js/autocomplete/spec/sqlSpecSet.js

@@ -37,6 +37,34 @@
       });
       });
     });
     });
 
 
+    describe('Impala specific', function () {
+      it('should handle "SET ALL; |"', function () {
+        assertAutoComplete({
+          beforeCursor: 'SET ALL; ',
+          afterCursor: '',
+          noErrors: true,
+          dialect: 'impala',
+          containsKeywords: ['SELECT'],
+          expectedResult: {
+            lowerCase: false
+          }
+        });
+      });
+
+      it('should suggest keywords for "SET |"', function () {
+        assertAutoComplete({
+          beforeCursor: 'SET ',
+          afterCursor: '',
+          dialect: 'impala',
+          expectedResult: {
+            lowerCase: false,
+            suggestSetOptions: true,
+            suggestKeywords: ['ALL']
+          }
+        });
+      });
+    });
+
     describe('SET ROLE', function () {
     describe('SET ROLE', function () {
 
 
       it('should handle "SET ROLE baaa;', function () {
       it('should handle "SET ROLE baaa;', function () {

File diff suppressed because it is too large
+ 0 - 0
desktop/core/src/desktop/static/desktop/js/autocomplete/sqlAutocompleteParser.js


+ 7 - 4
desktop/core/src/desktop/static/desktop/js/autocomplete/sqlParseSupport.js

@@ -215,10 +215,9 @@ var SqlParseSupport = (function () {
     parser.getValueExpressionKeywords = function (valueExpression, extras) {
     parser.getValueExpressionKeywords = function (valueExpression, extras) {
       var types = valueExpression.lastType ? valueExpression.lastType.types : valueExpression.types;
       var types = valueExpression.lastType ? valueExpression.lastType.types : valueExpression.types;
       // We could have valueExpression.columnReference to suggest based on column type
       // We could have valueExpression.columnReference to suggest based on column type
-      var keywords = ['<', '<=', '<=>', '<>', '=', '>', '>=', 'BETWEEN', 'IN', 'IS NOT NULL', 'IS NULL', 'NOT BETWEEN', 'NOT IN'];
+      var keywords = ['<', '<=', '<=>', '<>', '=', '>', '>=', 'BETWEEN', 'IN', 'IS NOT NULL', 'IS NULL', 'IS NOT TRUE', 'IS TRUE', 'IS NOT FALSE', 'IS FALSE', 'NOT BETWEEN', 'NOT IN'];
       if (parser.isImpala()) {
       if (parser.isImpala()) {
-        keywords.push('IS DISTINCT FROM');
-        keywords.push('IS NOT DISTINCT FROM');
+        keywords = keywords.concat(['IS DISTINCT FROM', 'IS NOT DISTINCT FROM', 'IS NOT UNKNOWN', 'IS UNKNOWN']);
       }
       }
       if (extras) {
       if (extras) {
         keywords = keywords.concat(extras);
         keywords = keywords.concat(extras);
@@ -1322,6 +1321,10 @@ var SqlParseSupport = (function () {
       parser.yy.result.suggestSetOptions = true;
       parser.yy.result.suggestSetOptions = true;
     };
     };
 
 
+    parser.suggestIdentifiers = function (identifiers) {
+      parser.yy.result.suggestIdentifiers = identifiers;
+    };
+
     parser.suggestColumns = function (details) {
     parser.suggestColumns = function (details) {
       if (typeof details === 'undefined') {
       if (typeof details === 'undefined') {
         details = {identifierChain: []};
         details = {identifierChain: []};
@@ -1843,7 +1846,7 @@ var SqlParseSupport = (function () {
     'suggestJoins', 'valueExpressionSuggest', 'applyTypeToSuggestions', 'applyArgumentTypesToSuggestions', 'commitLocations', 'identifyPartials',
     'suggestJoins', 'valueExpressionSuggest', 'applyTypeToSuggestions', 'applyArgumentTypesToSuggestions', 'commitLocations', 'identifyPartials',
     'getSubQuery', 'addTablePrimary', 'suggestFileFormats', 'suggestDdlAndDmlKeywords', 'checkForSelectListKeywords', 'checkForKeywords',
     'getSubQuery', 'addTablePrimary', 'suggestFileFormats', 'suggestDdlAndDmlKeywords', 'checkForSelectListKeywords', 'checkForKeywords',
     'suggestKeywords', 'suggestColRefKeywords', 'suggestTablesOrColumns', 'suggestFunctions', 'suggestAggregateFunctions', 'suggestAnalyticFunctions',
     'suggestKeywords', 'suggestColRefKeywords', 'suggestTablesOrColumns', 'suggestFunctions', 'suggestAggregateFunctions', 'suggestAnalyticFunctions',
-    'suggestColumns', 'suggestGroupBys', 'suggestOrderBys', 'suggestFilters', 'suggestKeyValues', 'suggestTables', 'addFunctionLocation',
+    'suggestColumns', 'suggestGroupBys', 'suggestIdentifiers', 'suggestOrderBys', 'suggestFilters', 'suggestKeyValues', 'suggestTables', 'addFunctionLocation',
     'addStatementLocation', 'firstDefined', 'addClauseLocation', 'addHdfsLocation', 'addDatabaseLocation', 'addColumnAliasLocation', 'addTableAliasLocation',
     'addStatementLocation', 'firstDefined', 'addClauseLocation', 'addHdfsLocation', 'addDatabaseLocation', 'addColumnAliasLocation', 'addTableAliasLocation',
     'addSubqueryAliasLocation', 'addTableLocation', 'addAsteriskLocation', 'addVariableLocation', 'addColumnLocation', 'addCteAliasLocation', 'addUnknownLocation',
     'addSubqueryAliasLocation', 'addTableLocation', 'addAsteriskLocation', 'addVariableLocation', 'addColumnLocation', 'addCteAliasLocation', 'addUnknownLocation',
     'addColRefToVariableIfExists', 'suggestDatabases', 'suggestHdfs', 'suggestValues'];
     'addColRefToVariableIfExists', 'suggestDatabases', 'suggestHdfs', 'suggestValues'];

File diff suppressed because it is too large
+ 0 - 0
desktop/core/src/desktop/static/desktop/js/autocomplete/sqlSyntaxParser.js


+ 10 - 3
desktop/core/src/desktop/static/desktop/js/sqlFunctions.js

@@ -1835,6 +1835,13 @@ var SqlFunctions = (function () {
         draggable: 'date_sub()',
         draggable: 'date_sub()',
         description: 'Subtracts a specified number of days from a TIMESTAMP value. The first argument can be a string, which is automatically cast to TIMESTAMP if it uses the recognized format. With an INTERVAL expression as the second argument, you can calculate a delta value using other units such as weeks, years, hours, seconds, and so on.'
         description: 'Subtracts a specified number of days from a TIMESTAMP value. The first argument can be a string, which is automatically cast to TIMESTAMP if it uses the recognized format. With an INTERVAL expression as the second argument, you can calculate a delta value using other units such as weeks, years, hours, seconds, and so on.'
       },
       },
+      date_trunc: {
+        returnTypes: ['TIMESTAMP'],
+        arguments: [[{type: 'STRING'}], [{type: 'TIMESTAMP'}]],
+        signature: 'date_trunc(STRING unit, TIMESTAMP timestamp)',
+        draggable: 'date_trunc()',
+        description: 'Truncates a TIMESTAMP value to the specified precision. The unit argument value for truncating TIMESTAMP values is not case-sensitive. This argument string can be one of: \'microseconds\', \'milliseconds\', \'second\', \'minute\', \'hour\', \'day\', \'week\', \'month\', \'year\', \'decade\', \'century\' or \'millennium\'.'
+      },
       datediff: {
       datediff: {
         returnTypes: ['INT'],
         returnTypes: ['INT'],
         arguments: [[{type: 'TIMESTAMP'}], [{type: 'TIMESTAMP'}]],
         arguments: [[{type: 'TIMESTAMP'}], [{type: 'TIMESTAMP'}]],
@@ -1968,11 +1975,11 @@ var SqlFunctions = (function () {
 				draggable: 'microseconds_sub()',
 				draggable: 'microseconds_sub()',
         description: 'Returns the specified date and time minus some number of microseconds.'
         description: 'Returns the specified date and time minus some number of microseconds.'
       },
       },
-      milliseconds: {
+      millisecond: {
         returnTypes: ['INT'],
         returnTypes: ['INT'],
         arguments: [[{type: 'TIMESTAMP'}]],
         arguments: [[{type: 'TIMESTAMP'}]],
-        signature: 'milliseconds(TIMESTAMP date)',
-        draggable: 'milliseconds()',
+        signature: 'millisecond(TIMESTAMP date)',
+        draggable: 'millisecond()',
         description: 'Returns the millisecond portion of a TIMESTAMP value.'
         description: 'Returns the millisecond portion of a TIMESTAMP value.'
       },
       },
       milliseconds_add: {
       milliseconds_add: {

+ 2 - 2
tools/ace-editor/lib/ace/mode/impala_highlight_rules.js

@@ -25,11 +25,11 @@ define(function (require, exports, module) {
     // regexps are ordered -> the first match is used
     // regexps are ordered -> the first match is used
 
 
     var keywords = (
     var keywords = (
-        "ADD|AGGREGATE|ALL|ALTER|ANALYTIC|AND|ANTI|API_VERSION|AS|ASC|AVRO|BETWEEN|BINARY|BLOCK_SIZE|BY|CACHED|CASCADE|CASE|CAST|CHANGE|CLASS|CLOSE_FN|COLUMN|COLUMNS|COMMENT|COMPRESSION|COMPUTE|CREATE|CROSS|CURRENT|DATA|DATABASE|DATABASES|DATE|DATETIME|DEFAULT|DELETE|DELIMITED|DESC|DESCRIBE|DISTINCT|DIV|DROP|ELSE|ENCODING|END|ESCAPED|EXISTS|EXPLAIN|EXTENDED|EXTERNAL|FIELDS|FILEFORMAT|FILES|FINALIZE_FN|FIRST|FOLLOWING|FOR|FORMAT|FORMATTED|FROM|FULL|FUNCTION|FUNCTIONS|GRANT|GROUP|HASH|HAVING|IF|ILIKE|IN|INCREMENTAL|INIT_FN|INNER|INPATH|IREGEXP|INSERT|INTEGER|INTERMEDIATE|INTERVAL|INTO|INVALIDATE|IS|JOIN|KEY|LAST|LEFT|LIKE|LIMIT|LINES|LOAD|LOCATION|MERGE_FN|METADATA|NOT|NULLS|OFFSET|ON|OR|ORDER|OUTER|OVER|OVERWRITE|PARQUET|PARTITION|PARTITIONED|PARTITIONS|PRECEDING|PREPARE_FN|PRIMARY|PRODUCED|PURGE|RANGE|RECOVER|REFRESH|REGEXP|RENAME|RESTRICT|REPEATABLE|REPLACE|REPLICATION|RETURNS|REVOKE|RIGHT|RLIKE|ROLE|ROLES|ROW|ROWS|SCHEMA|SCHEMAS|SELECT|SEMI|SERDEPROPERTIES|SERIALIZE_FN|SET|SHOW|SORT|STATS|STORED|STRAIGHT_JOIN|SYMBOL|TABLE|TABLES|TABLESAMPLE|TBLPROPERTIES|TERMINATED|THEN|TO|UNBOUNDED|UNCACHED|UNION|UPDATE|UPDATE_FN|UPSERT|USE|USING|VALUES|VIEW|WHEN|WHERE|WITH"
+        "ADD|AGGREGATE|ALL|ALTER|ANALYTIC|AND|ANTI|API_VERSION|AS|ASC|AVRO|BETWEEN|BINARY|BLOCK_SIZE|BY|CACHED|CASCADE|CASE|CAST|CHANGE|CLASS|CLOSE_FN|COLUMN|COLUMNS|COMMENT|COMPRESSION|COMPUTE|CREATE|CROSS|CURRENT|DATA|DATABASE|DATABASES|DATE|DATETIME|DEFAULT|DELETE|DELIMITED|DESC|DESCRIBE|DISTINCT|DIV|DROP|ELSE|ENCODING|END|ESCAPED|EXISTS|EXPLAIN|EXTENDED|EXTERNAL|FIELDS|FILEFORMAT|FILES|FINALIZE_FN|FIRST|FOLLOWING|FOR|FORMAT|FORMATTED|FROM|FULL|FUNCTION|FUNCTIONS|GRANT|GROUP|HASH|HAVING|IF|ILIKE|IN|INCREMENTAL|INIT_FN|INNER|INPATH|IREGEXP|INSERT|INTEGER|INTERMEDIATE|INTERVAL|INTO|INVALIDATE|IS|JOIN|KEY|LAST|LEFT|LIKE|LIMIT|LINES|LOAD|LOCATION|MERGE_FN|METADATA|NOT|NULLS|OFFSET|ON|OR|ORDER|OUTER|OVER|OVERWRITE|PARQUET|PARTITION|PARTITIONED|PARTITIONS|PRECEDING|PREPARE_FN|PRIMARY|PRODUCED|PURGE|RANGE|RECOVER|REFRESH|REGEXP|RENAME|RESTRICT|REPEATABLE|REPLACE|REPLICATION|RETURNS|REVOKE|RIGHT|RLIKE|ROLE|ROLES|ROW|ROWS|SCHEMA|SCHEMAS|SELECT|SEMI|SERDEPROPERTIES|SERIALIZE_FN|SET|SHOW|SORT|STATS|STORED|STRAIGHT_JOIN|SYMBOL|TABLE|TABLES|TABLESAMPLE|TBLPROPERTIES|TERMINATED|THEN|TO|TRUNCATE|UNBOUNDED|UNCACHED|UNION|UPDATE|UPDATE_FN|UPSERT|USE|USING|VALUES|VIEW|WHEN|WHERE|WITH"
     );
     );
 
 
     var builtinConstants = (
     var builtinConstants = (
-        "DAY|DAYS|FALSE|HOUR|HOURS|MINUTE|MINUTES|MICROSECOND|MICROSECONDS|MILLISECOND|MILLISECONDS|MONTH|MONTHS|NANOSECOND|NANOSECONDS|NULL|SECOND|SECONDS|TRUE|WEEK|WEEKS|YEAR|YEARS"
+        "DAY|DAYS|FALSE|HOUR|HOURS|MINUTE|MINUTES|MICROSECOND|MICROSECONDS|MILLISECOND|MILLISECONDS|MONTH|MONTHS|NANOSECOND|NANOSECONDS|NULL|SECOND|SECONDS|TRUE|UNKNOWN|WEEK|WEEKS|YEAR|YEARS"
     );
     );
 
 
     var builtinFunctions = (
     var builtinFunctions = (

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