Repository: AfterShip/clickhouse-sql-parser
Pull request #9 (2023-09-26 06:25:44)

Add the support REPLACE inside ALTER TABLE


Patch:
diff --git a/parser/ast.go b/parser/ast.go
index ea8dbf7..34f7233 100644
--- a/parser/ast.go
+++ b/parser/ast.go
@@ -539,6 +539,33 @@ func (a *AlterTableModifyColumn) String(level int) string {
 	return builder.String()
 }
 
+type AlterTableReplacePartition struct {
+	ReplacePos Pos
+	Partition  *PartitionExpr
+	Table      *TableIdentifier
+}
+
+func (a *AlterTableReplacePartition) Pos() Pos {
+	return a.ReplacePos
+}
+
+func (a *AlterTableReplacePartition) End() Pos {
+	return a.Table.End()
+}
+
+func (a *AlterTableReplacePartition) AlterType() string {
+	return "REPLACE_PARTITION"
+}
+
+func (a *AlterTableReplacePartition) String(level int) string {
+	var builder strings.Builder
+	builder.WriteString("REPLACE ")
+	builder.WriteString(a.Partition.String(level))
+	builder.WriteString(" FROM ")
+	builder.WriteString(a.Table.String(level))
+	return builder.String()
+}
+
 type RemovePropertyType struct {
 	RemovePos Pos
 
diff --git a/parser/parser_alter.go b/parser/parser_alter.go
index 0868d5e..c0704dd 100644
--- a/parser/parser_alter.go
+++ b/parser/parser_alter.go
@@ -50,6 +50,8 @@ func (p *Parser) parseAlterTable(pos Pos) (*AlterTable, error) {
 			alterExpr, err = p.parseAlterTableClear(p.Pos())
 		case p.matchKeyword(KeywordModify):
 			alterExpr, err = p.parseAlterTableModify(p.Pos())
+		case p.matchKeyword(KeywordReplace):
+			alterExpr, err = p.parseAlterTableReplacePartition(p.Pos())
 
 		default:
 			return nil, errors.New("expected token: ADD|DROP|ATTACH|DETACH|FREEZE|REMOVE|CLEAR")
@@ -591,3 +593,29 @@ func (p *Parser) tryParseRemovePropertyTypeExpr(pos Pos) (*RemovePropertyType, e
 		PropertyType: columnPropertyType,
 	}, nil
 }
+
+func (p *Parser) parseAlterTableReplacePartition(pos Pos) (AlterTableExpr, error) {
+	if err := p.consumeKeyword(KeywordReplace); err != nil {
+		return nil, err
+	}
+
+	partitionExpr, err := p.parsePartitionExpr(p.Pos())
+	if err != nil {
+		return nil, err
+	}
+
+	if err = p.consumeKeyword(KeywordFrom); err != nil {
+		return nil, err
+	}
+
+	table, err := p.parseTableIdentifier(p.Pos())
+	if err != nil {
+		return nil, err
+	}
+
+	return &AlterTableReplacePartition{
+		ReplacePos: pos,
+		Partition:  partitionExpr,
+		Table:      table,
+	}, nil
+}


Test patch:
diff --git a/parser/testdata/ddl/alter_table_replace_partition.sql b/parser/testdata/ddl/alter_table_replace_partition.sql
new file mode 100644
index 0000000..e5df6d6
--- /dev/null
+++ b/parser/testdata/ddl/alter_table_replace_partition.sql
@@ -0,0 +1,1 @@
+ALTER TABLE t2 REPLACE PARTITION 'partition' FROM t1;
\ No newline at end of file
diff --git a/parser/testdata/ddl/format/alter_table_replace_partition.sql b/parser/testdata/ddl/format/alter_table_replace_partition.sql
new file mode 100644
index 0000000..cb5249d
--- /dev/null
+++ b/parser/testdata/ddl/format/alter_table_replace_partition.sql
@@ -0,0 +1,6 @@
+-- Origin SQL:
+ALTER TABLE t2 REPLACE PARTITION 'partition' FROM t1;
+
+-- Format SQL:
+ALTER TABLE t2
+REPLACE PARTITION 'partition' FROM t1;
diff --git a/parser/testdata/ddl/output/alter_table_replace_partition.sql.golden.json b/parser/testdata/ddl/output/alter_table_replace_partition.sql.golden.json
new file mode 100644
index 0000000..8ac9f8a
--- /dev/null
+++ b/parser/testdata/ddl/output/alter_table_replace_partition.sql.golden.json
@@ -0,0 +1,40 @@
+[
+  {
+    "AlterPos": 0,
+    "StatementEnd": 52,
+    "TableIdentifier": {
+      "Database": null,
+      "Table": {
+        "Name": "t2",
+        "Unquoted": false,
+        "NamePos": 12,
+        "NameEnd": 14
+      }
+    },
+    "OnCluster": null,
+    "AlterExprs": [
+      {
+        "ReplacePos": 15,
+        "Partition": {
+          "PartitionPos": 23,
+          "Expr": {
+            "LiteralPos": 34,
+            "LiteralEnd": 43,
+            "Literal": "partition"
+          },
+          "ID": null,
+          "All": false
+        },
+        "Table": {
+          "Database": null,
+          "Table": {
+            "Name": "t1",
+            "Unquoted": false,
+            "NamePos": 50,
+            "NameEnd": 52
+          }
+        }
+      }
+    ]
+  }
+]
\ No newline at end of file