Repository: tobymao/sqlglot

Issue:
Valid oracle sql can't be identified
**Description**
I have a valid oracle sql statement which I would like to transpile into snowflake sql. sql 

**Fully reproducible code snippet**
*Environement*
sqlglot = "12.2.0"
python = "3.8.13"

*Code snippet*
`import sqlglot

sql: str = """
create table DIM_AP_PRO_STOCK
(
    PK_AP_PRO_STOCK NUMBER(19) generated by default on null as identity (order nocache)
        constraint DIM_AP_PRO_STOCK_PK
            primary key,
    FK_STOCKWERK    NUMBER(19) not null
        constraint FK_DIM_AP_STOCKWERK
            references DIM_STOCKWERK,
    ANZAHL_AP       NUMBER(5),
    GUELTIG_VON     DATE,
    GUELTIG_BIS     DATE
);"""

result = sqlglot.transpile(sql, read="oracle", write="snowflake", identify=True, pretty=True)[0]

print(result)`

*Stack trace*
sqlglot.errors.ParseError: Required keyword: 'kind' missing for <class 'sqlglot.expressions.ColumnConstraint'>. Line 4, Col: 59.
  
create table DIM_AP_PRO_STOCK
(
    PK_AP_PRO_STOCK NUMBER(19) generated by default on null as identity (order nocache)
        constraint DIM_AP_PRO_STOCK_PK
            primary key,
    FK_

Process finished with exit code 1

**Official Documentation**
The sql has been verified on a oracle console and can be seen in https://www.oracletutorial.com/oracle-basics/oracle-identity-column/




Discussion:
Hey, I'll take a look soon. Thanks for the report.
Can you provide documentation on the `(order nocache)`? I can't find it in the link you sent or in Oracle's docs.

Resolving patch:
diff --git a/sqlglot/expressions.py b/sqlglot/expressions.py
--- a/sqlglot/expressions.py
+++ b/sqlglot/expressions.py
@@ -1172,6 +1172,7 @@ class GeneratedAsIdentityColumnConstraint(ColumnConstraintKind):
     # this: True -> ALWAYS, this: False -> BY DEFAULT
     arg_types = {
         "this": False,
+        "on_null": False,
         "start": False,
         "increment": False,
         "minvalue": False,
diff --git a/sqlglot/generator.py b/sqlglot/generator.py
--- a/sqlglot/generator.py
+++ b/sqlglot/generator.py
@@ -568,7 +568,9 @@ def generatedasidentitycolumnconstraint_sql(
     ) -> str:
         this = ""
         if expression.this is not None:
-            this = " ALWAYS " if expression.this else " BY DEFAULT "
+            on_null = "ON NULL " if expression.args.get("on_null") else ""
+            this = " ALWAYS " if expression.this else f" BY DEFAULT {on_null}"
+
         start = expression.args.get("start")
         start = f"START WITH {start}" if start else ""
         increment = expression.args.get("increment")
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -3227,7 +3227,10 @@ def _parse_compress(self) -> exp.Expression:
 
     def _parse_generated_as_identity(self) -> exp.Expression:
         if self._match(TokenType.BY_DEFAULT):
-            this = self.expression(exp.GeneratedAsIdentityColumnConstraint, this=False)
+            on_null = self._match_pair(TokenType.ON, TokenType.NULL)
+            this = self.expression(
+                exp.GeneratedAsIdentityColumnConstraint, this=False, on_null=on_null
+            )
         else:
             self._match_text_seq("ALWAYS")
             this = self.expression(exp.GeneratedAsIdentityColumnConstraint, this=True)


Test patch:
diff --git a/tests/fixtures/identity.sql b/tests/fixtures/identity.sql
--- a/tests/fixtures/identity.sql
+++ b/tests/fixtures/identity.sql
@@ -563,6 +563,7 @@ CREATE TABLE foo (bar INT REFERENCES baz(baz_id) ON UPDATE SET DEFAULT)
 CREATE TABLE asd AS SELECT asd FROM asd WITH NO DATA
 CREATE TABLE asd AS SELECT asd FROM asd WITH DATA
 CREATE TABLE products (x INT GENERATED BY DEFAULT AS IDENTITY)
+CREATE TABLE products (x INT GENERATED BY DEFAULT ON NULL AS IDENTITY)
 CREATE TABLE products (x INT GENERATED ALWAYS AS IDENTITY)
 CREATE TABLE konyvszerzo (szerzo_azon INT CONSTRAINT konyvszerzo_szerzo_fk REFERENCES szerzo)
 CREATE TABLE IF NOT EXISTS customer (pk BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY (INCREMENT BY 1))