Repository: AfterShip/clickhouse-sql-parser
Pull request #7 (2023-09-25 09:37:59)

Add the support of CHECK expression


Patch:
diff --git a/parser/ast.go b/parser/ast.go
index ea57de9..2899d9f 100644
--- a/parser/ast.go
+++ b/parser/ast.go
@@ -3454,3 +3454,28 @@ func (i *InsertExpr) String(level int) string {
 	}
 	return builder.String()
 }
+
+type CheckExpr struct {
+	CheckPos  Pos
+	Table     *TableIdentifier
+	Partition *PartitionExpr
+}
+
+func (c *CheckExpr) Pos() Pos {
+	return c.CheckPos
+}
+
+func (c *CheckExpr) End() Pos {
+	return c.Partition.End()
+}
+
+func (c *CheckExpr) String(level int) string {
+	var builder strings.Builder
+	builder.WriteString("CHECK TABLE ")
+	builder.WriteString(c.Table.String(level))
+	builder.WriteString(NewLine(level))
+	if c.Partition != nil {
+		builder.WriteString(c.Partition.String(level))
+	}
+	return builder.String()
+}
diff --git a/parser/parse_system.go b/parser/parse_system.go
index f16a161..f81d533 100644
--- a/parser/parse_system.go
+++ b/parser/parse_system.go
@@ -318,3 +318,25 @@ func (p *Parser) parseSystemExpr(pos Pos) (*SystemExpr, error) {
 		Expr:      expr,
 	}, nil
 }
+
+func (p *Parser) parseCheckExpr(pos Pos) (*CheckExpr, error) {
+	if err := p.consumeKeyword(KeywordCheck); err != nil {
+		return nil, err
+	}
+	if err := p.consumeKeyword(KeywordTable); err != nil {
+		return nil, err
+	}
+	table, err := p.parseTableIdentifier(p.Pos())
+	if err != nil {
+		return nil, err
+	}
+	partition, err := p.tryParsePartitionExpr(p.Pos())
+	if err != nil {
+		return nil, err
+	}
+	return &CheckExpr{
+		CheckPos:  pos,
+		Table:     table,
+		Partition: partition,
+	}, nil
+}
diff --git a/parser/parser_alter.go b/parser/parser_alter.go
index e2b5ab3..0868d5e 100644
--- a/parser/parser_alter.go
+++ b/parser/parser_alter.go
@@ -233,7 +233,7 @@ func (p *Parser) parseAlterTableDetachPartition(pos Pos) (AlterTableExpr, error)
 }
 
 func (p *Parser) tryParsePartitionExpr(pos Pos) (*PartitionExpr, error) {
-	if p.tryConsumeKeyword(KeywordIn) == nil {
+	if !p.matchKeyword(KeywordPartition) {
 		return nil, nil // nolint
 	}
 	return p.parsePartitionExpr(pos)
@@ -429,12 +429,15 @@ func (p *Parser) parseAlterTableClearColumn(pos Pos) (AlterTableExpr, error) {
 	}
 	statementEnd := columnName.End()
 
-	partitionExpr, err := p.tryParsePartitionExpr(p.Pos())
-	if err != nil {
-		return nil, err
-	}
-	if partitionExpr != nil {
-		statementEnd = partitionExpr.End()
+	var partitionExpr *PartitionExpr
+	if p.tryConsumeKeyword(KeywordIn) != nil {
+		partitionExpr, err = p.tryParsePartitionExpr(p.Pos())
+		if err != nil {
+			return nil, err
+		}
+		if partitionExpr != nil {
+			statementEnd = partitionExpr.End()
+		}
 	}
 
 	return &AlterTableClearColumn{
@@ -463,12 +466,15 @@ func (p *Parser) parseAlterTableClearIndex(pos Pos) (AlterTableExpr, error) {
 	}
 	statementEnd := indexName.End()
 
-	partitionExpr, err := p.tryParsePartitionExpr(p.Pos())
-	if err != nil {
-		return nil, err
-	}
-	if partitionExpr != nil {
-		statementEnd = partitionExpr.End()
+	var partitionExpr *PartitionExpr
+	if p.tryConsumeKeyword(KeywordIn) != nil {
+		partitionExpr, err = p.tryParsePartitionExpr(p.Pos())
+		if err != nil {
+			return nil, err
+		}
+		if partitionExpr != nil {
+			statementEnd = partitionExpr.End()
+		}
 	}
 
 	return &AlterTableClearIndex{
diff --git a/parser/parser_table.go b/parser/parser_table.go
index f13196a..51ccb75 100644
--- a/parser/parser_table.go
+++ b/parser/parser_table.go
@@ -906,6 +906,8 @@ func (p *Parser) parseStatement(pos Pos) (Expr, error) {
 		expr, err = p.parseSystemExpr(pos)
 	case p.matchKeyword(KeywordOptimize):
 		expr, err = p.parseOptimizeExpr(pos)
+	case p.matchKeyword(KeywordCheck):
+		expr, err = p.parseCheckExpr(pos)
 	default:
 		return nil, fmt.Errorf("unexpected token: %q", p.last().String)
 	}


Test patch:
diff --git a/parser/testdata/ddl/check.sql b/parser/testdata/ddl/check.sql
new file mode 100644
index 0000000..0e7fcd8
--- /dev/null
+++ b/parser/testdata/ddl/check.sql
@@ -0,0 +1,2 @@
+CHECK TABLE test_table;
+CHECK TABLE test_table PARTITION 'col';
diff --git a/parser/testdata/ddl/format/check.sql b/parser/testdata/ddl/format/check.sql
new file mode 100644
index 0000000..5d7df67
--- /dev/null
+++ b/parser/testdata/ddl/format/check.sql
@@ -0,0 +1,10 @@
+-- Origin SQL:
+CHECK TABLE test_table;
+CHECK TABLE test_table PARTITION 'col';
+
+
+-- Format SQL:
+CHECK TABLE test_table
+;
+CHECK TABLE test_table
+PARTITION 'col';
diff --git a/parser/testdata/ddl/output/alter_table_clear_column.sql.golden.json b/parser/testdata/ddl/output/alter_table_clear_column.sql.golden.json
index ca7621f..1f66cd3 100644
--- a/parser/testdata/ddl/output/alter_table_clear_column.sql.golden.json
+++ b/parser/testdata/ddl/output/alter_table_clear_column.sql.golden.json
@@ -27,7 +27,7 @@
           "DotIdent": null
         },
         "PartitionExpr": {
-          "PartitionPos": 49,
+          "PartitionPos": 52,
           "Expr": {
             "Name": "partition_name",
             "Unquoted": false,
diff --git a/parser/testdata/ddl/output/alter_table_clear_index.sql.golden.json b/parser/testdata/ddl/output/alter_table_clear_index.sql.golden.json
index 59a8479..d9bc8b6 100644
--- a/parser/testdata/ddl/output/alter_table_clear_index.sql.golden.json
+++ b/parser/testdata/ddl/output/alter_table_clear_index.sql.golden.json
@@ -27,7 +27,7 @@
           "DotIdent": null
         },
         "PartitionExpr": {
-          "PartitionPos": 47,
+          "PartitionPos": 50,
           "Expr": {
             "Name": "partition_name",
             "Unquoted": false,
diff --git a/parser/testdata/ddl/output/check.sql.golden.json b/parser/testdata/ddl/output/check.sql.golden.json
new file mode 100644
index 0000000..bb4168f
--- /dev/null
+++ b/parser/testdata/ddl/output/check.sql.golden.json
@@ -0,0 +1,37 @@
+[
+  {
+    "CheckPos": 0,
+    "Table": {
+      "Database": null,
+      "Table": {
+        "Name": "test_table",
+        "Unquoted": false,
+        "NamePos": 12,
+        "NameEnd": 22
+      }
+    },
+    "Partition": null
+  },
+  {
+    "CheckPos": 24,
+    "Table": {
+      "Database": null,
+      "Table": {
+        "Name": "test_table",
+        "Unquoted": false,
+        "NamePos": 36,
+        "NameEnd": 46
+      }
+    },
+    "Partition": {
+      "PartitionPos": 47,
+      "Expr": {
+        "LiteralPos": 58,
+        "LiteralEnd": 61,
+        "Literal": "col"
+      },
+      "ID": null,
+      "All": false
+    }
+  }
+]
\ No newline at end of file