Repository: tobymao/sqlglot

Issue:
Problem with parsing Teradata COLLECT STATISTICS command
I have found a problem parsing the COLLECT STATISTICS command in Teradata.  
All variations of the COLLECT STATISTICS command fail

COLLECT STATISTICS ON TABLE1
INDEX(COL1);

COLLECT STATS
ON TABLE1
COLUMNS(COL1);

COLLECT STATS ON TABLE1
COLUMNS(COL1);

COLLECT STATS
COLUMNS(COL1)
ON TABLE1;

sqlglot Version: 17.4.1
Teradata version 17.10

Error message is 

File ~\AppData\Roaming\Python\Python311\site-packages\sqlglot\parser.py:946, in Parser._parse(self, parse_method, raw_tokens, sql)
    943     expressions.append(parse_method(self))
    945     if self._index < len(self._tokens):
--> 946         self.raise_error("Invalid expression / Unexpected token")
    948     self.check_errors()
    950 return expressions

File ~\AppData\Roaming\Python\Python311\site-packages\sqlglot\parser.py:987, in Parser.raise_error(self, message, token)
    975 error = ParseError.new(
    976     f"{message}. Line {token.line}, Col: {token.col}.\n"
    977     f"  {start_context}\033[4m{highlight}\033[0m{end_context}",
   (...)
    983     end_context=end_context,
    984 )
    986 if self.error_level == ErrorLevel.IMMEDIATE:
--> 987     raise error
    989 self.errors.append(error)

or 

File ~\AppData\Roaming\Python\Python311\site-packages\sqlglot\parser.py:946, in Parser._parse(self, parse_method, raw_tokens, sql)
    943     expressions.append(parse_method(self))
    945     if self._index < len(self._tokens):
--> 946         self.raise_error("Invalid expression / Unexpected token")
    948     self.check_errors()
    950 return expressions

File ~\AppData\Roaming\Python\Python311\site-packages\sqlglot\parser.py:987, in Parser.raise_error(self, message, token)
    975 error = ParseError.new(
    976     f"{message}. Line {token.line}, Col: {token.col}.\n"
    977     f"  {start_context}\033[4m{highlight}\033[0m{end_context}",
   (...)
    983     end_context=end_context,
    984 )
    986 if self.error_level == ErrorLevel.IMMEDIATE:
--> 987     raise error
    989 self.errors.append(error)

ParseError: Invalid expression / Unexpected token. Line 2, Col: 16.
  
COLLECT STATS ON TABLE1
COLUMNS(COL1);



Discussion:
Hey, thanks for the report. Could you please provide any related documentation for this command? Having an official specification about the syntax is helpful for the implementation.
I think this has the full syntax definition https://docs.teradata.com/r/SQL-Data-Definition-Language-Syntax-and-Examples/March-2019/Statistics-Statements/COLLECT-STATISTICS-Optimizer-Form
Thanks Trey! I think I might just parse it as a `Command` after all for now since it's very Teradata-specific (and based on the spec could be a bit complicated to add in one go).

Resolving patch:
diff --git a/sqlglot/dialects/teradata.py b/sqlglot/dialects/teradata.py
--- a/sqlglot/dialects/teradata.py
+++ b/sqlglot/dialects/teradata.py
@@ -33,8 +33,11 @@ class Tokenizer(tokens.Tokenizer):
             **tokens.Tokenizer.KEYWORDS,
             "^=": TokenType.NEQ,
             "BYTEINT": TokenType.SMALLINT,
+            "COLLECT STATS": TokenType.COMMAND,
+            "COLLECT STATISTICS": TokenType.COMMAND,
             "GE": TokenType.GTE,
             "GT": TokenType.GT,
+            "HELP": TokenType.COMMAND,
             "INS": TokenType.INSERT,
             "LE": TokenType.LTE,
             "LT": TokenType.LT,


Test patch:
diff --git a/tests/dialects/test_teradata.py b/tests/dialects/test_teradata.py
--- a/tests/dialects/test_teradata.py
+++ b/tests/dialects/test_teradata.py
@@ -22,6 +22,13 @@ def test_update(self):
             },
         )
 
+    def test_statistics(self):
+        self.validate_identity("COLLECT STATISTICS ON tbl INDEX(col)")
+        self.validate_identity("COLLECT STATS ON tbl COLUMNS(col)")
+        self.validate_identity("COLLECT STATS COLUMNS(col) ON tbl")
+        self.validate_identity("HELP STATISTICS personel.employee")
+        self.validate_identity("HELP STATISTICS personnel.employee FROM my_qcd")
+
     def test_create(self):
         self.validate_identity("CREATE TABLE x (y INT) PRIMARY INDEX (y) PARTITION BY y INDEX (y)")
         self.validate_identity("CREATE TABLE x (y INT) PARTITION BY y INDEX (y)")