Repository: AfterShip/clickhouse-sql-parser
Pull request #32 (2024-01-09 07:39:08)

Add the support of MODIFY TTL syntax


Patch:
diff --git a/parser/ast.go b/parser/ast.go
index 28725b4..e4d43e1 100644
--- a/parser/ast.go
+++ b/parser/ast.go
@@ -505,6 +505,32 @@ func (a *AlterTableRenameColumn) String(level int) string {
 	return builder.String()
 }
 
+type AlterTableModifyTTL struct {
+	ModifyPos    Pos
+	StatementEnd Pos
+	TTL          *TTLExpr
+}
+
+func (a *AlterTableModifyTTL) Pos() Pos {
+	return a.ModifyPos
+}
+
+func (a *AlterTableModifyTTL) End() Pos {
+	return a.StatementEnd
+}
+
+func (a *AlterTableModifyTTL) AlterType() string {
+	return "MODIFY_TTL"
+}
+
+func (a *AlterTableModifyTTL) String(level int) string {
+	var builder strings.Builder
+	builder.WriteString("MODIFY ")
+	builder.WriteString("TTL ")
+	builder.WriteString(a.TTL.String(level))
+	return builder.String()
+}
+
 type AlterTableModifyColumn struct {
 	ModifyPos    Pos
 	StatementEnd Pos
diff --git a/parser/parser_alter.go b/parser/parser_alter.go
index 29602b2..36a215f 100644
--- a/parser/parser_alter.go
+++ b/parser/parser_alter.go
@@ -530,6 +530,17 @@ func (p *Parser) parseAlterTableModify(pos Pos) (AlterTableExpr, error) {
 	switch {
 	case p.matchKeyword(KeywordColumn):
 		return p.parseAlterTableModifyColumn(pos)
+	case p.matchKeyword(KeywordTtl):
+		_ = p.lexer.consumeToken()
+		ttlExpr, err := p.parseTTLExpr(p.Pos())
+		if err != nil {
+			return nil, err
+		}
+		return &AlterTableModifyTTL{
+			ModifyPos:    pos,
+			StatementEnd: ttlExpr.End(),
+			TTL:          ttlExpr,
+		}, nil
 	default:
 		return nil, fmt.Errorf("expected keyword: COLUMN, but got %q",
 			p.last().String)


Test patch:
diff --git a/parser/testdata/dml/alter_table_with_modify_remove_ttl.sql b/parser/testdata/dml/alter_table_with_modify_remove_ttl.sql
new file mode 100644
index 0000000..f69525e
--- /dev/null
+++ b/parser/testdata/dml/alter_table_with_modify_remove_ttl.sql
@@ -0,0 +1,1 @@
+ALTER TABLE infra.flow_processed_emails_local ON CLUSTER default_cluster REMOVE TTL;
\ No newline at end of file
diff --git a/parser/testdata/dml/alter_table_with_modify_ttl.sql b/parser/testdata/dml/alter_table_with_modify_ttl.sql
new file mode 100644
index 0000000..ed3b9de
--- /dev/null
+++ b/parser/testdata/dml/alter_table_with_modify_ttl.sql
@@ -0,0 +1,1 @@
+ALTER TABLE infra.flow_processed_emails_local ON CLUSTER default_cluster MODIFY TTL created_at + INTERVAL 3 YEAR;
\ No newline at end of file
diff --git a/parser/testdata/dml/format/alter_table_with_modify_remove_ttl.sql b/parser/testdata/dml/format/alter_table_with_modify_remove_ttl.sql
new file mode 100644
index 0000000..aa7f352
--- /dev/null
+++ b/parser/testdata/dml/format/alter_table_with_modify_remove_ttl.sql
@@ -0,0 +1,7 @@
+-- Origin SQL:
+ALTER TABLE infra.flow_processed_emails_local ON CLUSTER default_cluster REMOVE TTL;
+
+-- Format SQL:
+ALTER TABLE infra.flow_processed_emails_local
+ON CLUSTER default_cluster
+REMOVE TTL;
diff --git a/parser/testdata/dml/format/alter_table_with_modify_ttl.sql b/parser/testdata/dml/format/alter_table_with_modify_ttl.sql
new file mode 100644
index 0000000..16c6b9b
--- /dev/null
+++ b/parser/testdata/dml/format/alter_table_with_modify_ttl.sql
@@ -0,0 +1,7 @@
+-- Origin SQL:
+ALTER TABLE infra.flow_processed_emails_local ON CLUSTER default_cluster MODIFY TTL created_at + INTERVAL 3 YEAR;
+
+-- Format SQL:
+ALTER TABLE infra.flow_processed_emails_local
+ON CLUSTER default_cluster
+MODIFY TTL created_at + INTERVAL 3 YEAR;
diff --git a/parser/testdata/dml/output/alter_table_with_modify_remove_ttl.sql.golden.json b/parser/testdata/dml/output/alter_table_with_modify_remove_ttl.sql.golden.json
new file mode 100644
index 0000000..eeaccb8
--- /dev/null
+++ b/parser/testdata/dml/output/alter_table_with_modify_remove_ttl.sql.golden.json
@@ -0,0 +1,35 @@
+[
+  {
+    "AlterPos": 0,
+    "StatementEnd": 83,
+    "TableIdentifier": {
+      "Database": {
+        "Name": "infra",
+        "Unquoted": false,
+        "NamePos": 12,
+        "NameEnd": 17
+      },
+      "Table": {
+        "Name": "flow_processed_emails_local",
+        "Unquoted": false,
+        "NamePos": 18,
+        "NameEnd": 45
+      }
+    },
+    "OnCluster": {
+      "OnPos": 46,
+      "Expr": {
+        "Name": "default_cluster",
+        "Unquoted": false,
+        "NamePos": 57,
+        "NameEnd": 72
+      }
+    },
+    "AlterExprs": [
+      {
+        "RemovePos": 73,
+        "StatementEnd": 83
+      }
+    ]
+  }
+]
\ No newline at end of file
diff --git a/parser/testdata/dml/output/alter_table_with_modify_ttl.sql.golden.json b/parser/testdata/dml/output/alter_table_with_modify_ttl.sql.golden.json
new file mode 100644
index 0000000..726b8f3
--- /dev/null
+++ b/parser/testdata/dml/output/alter_table_with_modify_ttl.sql.golden.json
@@ -0,0 +1,64 @@
+[
+  {
+    "AlterPos": 0,
+    "StatementEnd": 112,
+    "TableIdentifier": {
+      "Database": {
+        "Name": "infra",
+        "Unquoted": false,
+        "NamePos": 12,
+        "NameEnd": 17
+      },
+      "Table": {
+        "Name": "flow_processed_emails_local",
+        "Unquoted": false,
+        "NamePos": 18,
+        "NameEnd": 45
+      }
+    },
+    "OnCluster": {
+      "OnPos": 46,
+      "Expr": {
+        "Name": "default_cluster",
+        "Unquoted": false,
+        "NamePos": 57,
+        "NameEnd": 72
+      }
+    },
+    "AlterExprs": [
+      {
+        "ModifyPos": 73,
+        "StatementEnd": 112,
+        "TTL": {
+          "TTLPos": 84,
+          "Expr": {
+            "LeftExpr": {
+              "Name": "created_at",
+              "Unquoted": false,
+              "NamePos": 84,
+              "NameEnd": 94
+            },
+            "Operation": "+",
+            "RightExpr": {
+              "IntervalPos": 97,
+              "Expr": {
+                "NumPos": 106,
+                "NumEnd": 107,
+                "Literal": "3",
+                "Base": 10
+              },
+              "Unit": {
+                "Name": "YEAR",
+                "Unquoted": false,
+                "NamePos": 108,
+                "NameEnd": 112
+              }
+            },
+            "HasGlobal": false,
+            "HasNot": false
+          }
+        }
+      }
+    ]
+  }
+]
\ No newline at end of file