Repository: tobymao/sqlglot

Issue:
Field name unknown is parsed as NULL in BigQuery dialect
We have a field Unknown which we can use in the SELECT without quotes, but sqlglot parses it as a `NULL`.

**Fully reproducible code snippet**
```python
>>> import sqlglot; sqlglot.parse_one("SELECT test.Unknown FROM test", 'bigquery').sql()
'SELECT test.NULL FROM test'
```
expected: `SELECT test.Unknown FROM test'`

if you don't use the dialect option, you do get the correct result:
```python
>>> import sqlglot; sqlglot.parse_one("SELECT test.Unknown FROM test", None).sql()
'SELECT test.Unknown FROM test'
```

**Official Documentation**
Unknown is not a [reserved keyword](https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#reserved_keywords), it only needs special handling in the `IS UNKNOWN` and `IS NOT UNKNOWN` [IS operators](https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#is_operators).


Discussion:

Patch:
diff --git a/sqlglot/dialects/bigquery.py b/sqlglot/dialects/bigquery.py
index fe692003..10889104 100644
--- a/sqlglot/dialects/bigquery.py
+++ b/sqlglot/dialects/bigquery.py
@@ -258,7 +258,6 @@ class BigQuery(Dialect):
             "RECORD": TokenType.STRUCT,
             "TIMESTAMP": TokenType.TIMESTAMPTZ,
             "NOT DETERMINISTIC": TokenType.VOLATILE,
-            "UNKNOWN": TokenType.NULL,
             "FOR SYSTEM_TIME": TokenType.TIMESTAMP_SNAPSHOT,
         }
         KEYWORDS.pop("DIV")
@@ -344,6 +343,8 @@ class BigQuery(Dialect):
             "OPTIONS": lambda self: exp.Properties(expressions=self._parse_with_property()),
         }
 
+        NULL_TOKENS = {TokenType.NULL, TokenType.UNKNOWN}
+
         def _parse_table_part(self, schema: bool = False) -> t.Optional[exp.Expression]:
             this = super()._parse_table_part(schema=schema) or self._parse_number()
 
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
index c7028dde..669935dc 100644
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -858,6 +858,8 @@ class Parser(metaclass=_Parser):
 
     DISTINCT_TOKENS = {TokenType.DISTINCT}
 
+    NULL_TOKENS = {TokenType.NULL}
+
     STRICT_CAST = True
 
     # A NULL arg in CONCAT yields NULL by default
@@ -4577,7 +4579,7 @@ class Parser(metaclass=_Parser):
         return self._parse_var() or self._parse_string()
 
     def _parse_null(self) -> t.Optional[exp.Expression]:
-        if self._match(TokenType.NULL):
+        if self._match_set(self.NULL_TOKENS):
             return self.PRIMARY_PARSERS[TokenType.NULL](self, self._prev)
         return self._parse_placeholder()
 


Test patch:
diff --git a/tests/dialects/test_bigquery.py b/tests/dialects/test_bigquery.py
index b666290f..f7bcb6d0 100644
--- a/tests/dialects/test_bigquery.py
+++ b/tests/dialects/test_bigquery.py
@@ -33,6 +33,7 @@ class TestBigQuery(Validator):
         with self.assertRaises(ParseError):
             transpile("DATE_ADD(x, day)", read="bigquery")
 
+        self.validate_identity("SELECT test.Unknown FROM test")
         self.validate_identity(r"SELECT '\n\r\a\v\f\t'")
         self.validate_identity("SELECT * FROM tbl FOR SYSTEM_TIME AS OF z")
         self.validate_identity("STRING_AGG(DISTINCT a ORDER BY b DESC, c DESC LIMIT 10)")
@@ -452,6 +453,16 @@ class TestBigQuery(Validator):
                 "spark": "x IS NULL",
             },
         )
+        self.validate_all(
+            "x IS NOT unknown",
+            write={
+                "bigquery": "NOT x IS NULL",
+                "duckdb": "NOT x IS NULL",
+                "presto": "NOT x IS NULL",
+                "hive": "NOT x IS NULL",
+                "spark": "NOT x IS NULL",
+            },
+        )
         self.validate_all(
             "CURRENT_TIMESTAMP()",
             read={