Repository: AfterShip/clickhouse-sql-parser
Pull request #79 (2024-07-16 08:56:15)

Add support of the format clause for the select stmt

coveralls: ## Pull Request Test Coverage Report for [Build 9953792793](https://coveralls.io/builds/68666228)


### Details

* **12** of **16**   **(75.0%)**  changed or added relevant lines in **2** files are covered.
* No unchanged relevant lines lost coverage.
* Overall coverage increased (+**0.2%**) to **58.23%**

---

|  Changes Missing Coverage | Covered Lines | Changed/Added Lines | % |
| :-----|--------------|--------|---: |
| [parser/ast.go](https://coveralls.io/builds/68666228/source?filename=parser%2Fast.go#L5125) | 6 | 8 | 75.0%
| [parser/parser_query.go](https://coveralls.io/builds/68666228/source?filename=parser%2Fparser_query.go#L912) | 6 | 8 | 75.0%
<!-- | **Total:** | **12** | **16** | **75.0%** | -->


|  Totals | [![Coverage Status](https://coveralls.io/builds/68666228/badge)](https://coveralls.io/builds/68666228) |
| :-- | --: |
| Change from base [Build 9949491275](https://coveralls.io/builds/68660546): |  0.2% |
| Covered Lines: | 5922 |
| Relevant Lines: | 10170 |

---
##### 💛  - [Coveralls](https://coveralls.io)


Patch:
diff --git a/parser/ast.go b/parser/ast.go
index f654d8c..f1c05f3 100644
--- a/parser/ast.go
+++ b/parser/ast.go
@@ -4942,6 +4942,7 @@ type SelectQuery struct {
 	LimitBy       *LimitByClause
 	Limit         *LimitClause
 	Settings      *SettingsClause
+	Format        *FormatClause
 	UnionAll      *SelectQuery
 	UnionDistinct *SelectQuery
 	Except        *SelectQuery
@@ -5026,6 +5027,10 @@ func (s *SelectQuery) String(level int) string { // nolint: funlen
 		builder.WriteString(NewLine(level))
 		builder.WriteString(s.Settings.String(level))
 	}
+	if s.Format != nil {
+		builder.WriteString(NewLine(level))
+		builder.WriteString(s.Format.String(level))
+	}
 	if s.UnionAll != nil {
 		builder.WriteString(NewLine(level))
 		builder.WriteString(" UNION ALL ")
@@ -5115,6 +5120,11 @@ func (s *SelectQuery) Accept(visitor ASTVisitor) error {
 			return err
 		}
 	}
+	if s.Format != nil {
+		if err := s.Format.Accept(visitor); err != nil {
+			return err
+		}
+	}
 	if s.UnionAll != nil {
 		if err := s.UnionAll.Accept(visitor); err != nil {
 			return err
diff --git a/parser/parser_query.go b/parser/parser_query.go
index 6ff3a5d..6efe8a6 100644
--- a/parser/parser_query.go
+++ b/parser/parser_query.go
@@ -907,6 +907,14 @@ func (p *Parser) parseSelectStmt(pos Pos) (*SelectQuery, error) { // nolint: fun
 		statementEnd = settings.End()
 	}
 
+	format, err := p.tryParseFormat(p.Pos())
+	if err != nil {
+		return nil, err
+	}
+	if format != nil {
+		statementEnd = format.End()
+	}
+
 	return &SelectQuery{
 		With:          withClause,
 		SelectPos:     pos,
@@ -924,6 +932,7 @@ func (p *Parser) parseSelectStmt(pos Pos) (*SelectQuery, error) { // nolint: fun
 		LimitBy:       limitBy,
 		Limit:         limit,
 		Settings:      settings,
+		Format:        format,
 		WithTotal:     withTotal,
 	}, nil
 }


Test patch:
diff --git a/parser/testdata/ddl/output/bug_001.sql.golden.json b/parser/testdata/ddl/output/bug_001.sql.golden.json
index 3a07232..1bf1334 100644
--- a/parser/testdata/ddl/output/bug_001.sql.golden.json
+++ b/parser/testdata/ddl/output/bug_001.sql.golden.json
@@ -501,6 +501,7 @@
         "LimitBy": null,
         "Limit": null,
         "Settings": null,
+        "Format": null,
         "UnionAll": null,
         "UnionDistinct": null,
         "Except": null
diff --git a/parser/testdata/ddl/output/create_live_view_basic.sql.golden.json b/parser/testdata/ddl/output/create_live_view_basic.sql.golden.json
index 43f159f..7146443 100644
--- a/parser/testdata/ddl/output/create_live_view_basic.sql.golden.json
+++ b/parser/testdata/ddl/output/create_live_view_basic.sql.golden.json
@@ -127,6 +127,7 @@
         "LimitBy": null,
         "Limit": null,
         "Settings": null,
+        "Format": null,
         "UnionAll": null,
         "UnionDistinct": null,
         "Except": null
diff --git a/parser/testdata/ddl/output/create_materialized_view_basic.sql.golden.json b/parser/testdata/ddl/output/create_materialized_view_basic.sql.golden.json
index 3e50d25..f4aba51 100644
--- a/parser/testdata/ddl/output/create_materialized_view_basic.sql.golden.json
+++ b/parser/testdata/ddl/output/create_materialized_view_basic.sql.golden.json
@@ -486,6 +486,7 @@
         "LimitBy": null,
         "Limit": null,
         "Settings": null,
+        "Format": null,
         "UnionAll": null,
         "UnionDistinct": null,
         "Except": null
diff --git a/parser/testdata/ddl/output/create_materialized_view_with_empty_table_schema.sql.golden.json b/parser/testdata/ddl/output/create_materialized_view_with_empty_table_schema.sql.golden.json
index a379f2a..ead806a 100644
--- a/parser/testdata/ddl/output/create_materialized_view_with_empty_table_schema.sql.golden.json
+++ b/parser/testdata/ddl/output/create_materialized_view_with_empty_table_schema.sql.golden.json
@@ -427,6 +427,7 @@
                   "LimitBy": null,
                   "Limit": null,
                   "Settings": null,
+                  "Format": null,
                   "UnionAll": null,
                   "UnionDistinct": null,
                   "Except": null
@@ -476,6 +477,7 @@
         "LimitBy": null,
         "Limit": null,
         "Settings": null,
+        "Format": null,
         "UnionAll": null,
         "UnionDistinct": null,
         "Except": null
diff --git a/parser/testdata/ddl/output/create_view_basic.sql.golden.json b/parser/testdata/ddl/output/create_view_basic.sql.golden.json
index 69a6817..403222e 100644
--- a/parser/testdata/ddl/output/create_view_basic.sql.golden.json
+++ b/parser/testdata/ddl/output/create_view_basic.sql.golden.json
@@ -138,6 +138,7 @@
         "LimitBy": null,
         "Limit": null,
         "Settings": null,
+        "Format": null,
         "UnionAll": null,
         "UnionDistinct": null,
         "Except": null
diff --git a/parser/testdata/ddl/output/create_view_on_cluster_with_uuid.sql.golden.json b/parser/testdata/ddl/output/create_view_on_cluster_with_uuid.sql.golden.json
index 9be946b..f5cf10a 100644
--- a/parser/testdata/ddl/output/create_view_on_cluster_with_uuid.sql.golden.json
+++ b/parser/testdata/ddl/output/create_view_on_cluster_with_uuid.sql.golden.json
@@ -93,6 +93,7 @@
         "LimitBy": null,
         "Limit": null,
         "Settings": null,
+        "Format": null,
         "UnionAll": null,
         "UnionDistinct": null,
         "Except": null
diff --git a/parser/testdata/dml/output/insert_with_select.sql.golden.json b/parser/testdata/dml/output/insert_with_select.sql.golden.json
index a2d3afa..28502bb 100644
--- a/parser/testdata/dml/output/insert_with_select.sql.golden.json
+++ b/parser/testdata/dml/output/insert_with_select.sql.golden.json
@@ -93,6 +93,7 @@
       "LimitBy": null,
       "Limit": null,
       "Settings": null,
+      "Format": null,
       "UnionAll": null,
       "UnionDistinct": null,
       "Except": null
diff --git a/parser/testdata/query/format/select_with_union_distinct.sql b/parser/testdata/query/format/select_with_union_distinct.sql
index 77c9a59..a9becdd 100644
--- a/parser/testdata/query/format/select_with_union_distinct.sql
+++ b/parser/testdata/query/format/select_with_union_distinct.sql
@@ -11,4 +11,5 @@ FROM
 SELECT 
   replica_name
 FROM
-  system.ha_unique_replicas;
+  system.ha_unique_replicas
+FORMAT JSON;
diff --git a/parser/testdata/query/output/select_cast.sql.golden.json b/parser/testdata/query/output/select_cast.sql.golden.json
index 33bc315..bab844b 100644
--- a/parser/testdata/query/output/select_cast.sql.golden.json
+++ b/parser/testdata/query/output/select_cast.sql.golden.json
@@ -51,6 +51,7 @@
     "LimitBy": null,
     "Limit": null,
     "Settings": null,
+    "Format": null,
     "UnionAll": null,
     "UnionDistinct": null,
     "Except": null
@@ -104,6 +105,7 @@
     "LimitBy": null,
     "Limit": null,
     "Settings": null,
+    "Format": null,
     "UnionAll": null,
     "UnionDistinct": null,
     "Except": null
@@ -168,6 +170,7 @@
     "LimitBy": null,
     "Limit": null,
     "Settings": null,
+    "Format": null,
     "UnionAll": null,
     "UnionDistinct": null,
     "Except": null
@@ -222,6 +225,7 @@
     "LimitBy": null,
     "Limit": null,
     "Settings": null,
+    "Format": null,
     "UnionAll": null,
     "UnionDistinct": null,
     "Except": null
diff --git a/parser/testdata/query/output/select_column_alias_string.sql.golden.json b/parser/testdata/query/output/select_column_alias_string.sql.golden.json
index 6bb5559..25e1997 100644
--- a/parser/testdata/query/output/select_column_alias_string.sql.golden.json
+++ b/parser/testdata/query/output/select_column_alias_string.sql.golden.json
@@ -37,6 +37,7 @@
     "LimitBy": null,
     "Limit": null,
     "Settings": null,
+    "Format": null,
     "UnionAll": null,
     "UnionDistinct": null,
     "Except": null
diff --git a/parser/testdata/query/output/select_simple.sql.golden.json b/parser/testdata/query/output/select_simple.sql.golden.json
index 25f492a..f6c6d37 100644
--- a/parser/testdata/query/output/select_simple.sql.golden.json
+++ b/parser/testdata/query/output/select_simple.sql.golden.json
@@ -380,6 +380,7 @@
     },
     "Limit": null,
     "Settings": null,
+    "Format": null,
     "UnionAll": null,
     "UnionDistinct": null,
     "Except": null
diff --git a/parser/testdata/query/output/select_simple_with_bracket.sql.golden.json b/parser/testdata/query/output/select_simple_with_bracket.sql.golden.json
index 6eb1271..8c12b68 100644
--- a/parser/testdata/query/output/select_simple_with_bracket.sql.golden.json
+++ b/parser/testdata/query/output/select_simple_with_bracket.sql.golden.json
@@ -155,6 +155,7 @@
     "LimitBy": null,
     "Limit": null,
     "Settings": null,
+    "Format": null,
     "UnionAll": null,
     "UnionDistinct": null,
     "Except": null
diff --git a/parser/testdata/query/output/select_simple_with_cte_with_column_aliases.sql.golden.json b/parser/testdata/query/output/select_simple_with_cte_with_column_aliases.sql.golden.json
index c818d37..d46ee71 100644
--- a/parser/testdata/query/output/select_simple_with_cte_with_column_aliases.sql.golden.json
+++ b/parser/testdata/query/output/select_simple_with_cte_with_column_aliases.sql.golden.json
@@ -110,6 +110,7 @@
             "LimitBy": null,
             "Limit": null,
             "Settings": null,
+            "Format": null,
             "UnionAll": null,
             "UnionDistinct": null,
             "Except": null
@@ -204,6 +205,7 @@
     "LimitBy": null,
     "Limit": null,
     "Settings": null,
+    "Format": null,
     "UnionAll": null,
     "UnionDistinct": null,
     "Except": null
diff --git a/parser/testdata/query/output/select_simple_with_group_by_with_cube_totals.sql.golden.json b/parser/testdata/query/output/select_simple_with_group_by_with_cube_totals.sql.golden.json
index 863deac..5028eed 100644
--- a/parser/testdata/query/output/select_simple_with_group_by_with_cube_totals.sql.golden.json
+++ b/parser/testdata/query/output/select_simple_with_group_by_with_cube_totals.sql.golden.json
@@ -116,6 +116,7 @@
     "LimitBy": null,
     "Limit": null,
     "Settings": null,
+    "Format": null,
     "UnionAll": null,
     "UnionDistinct": null,
     "Except": null
diff --git a/parser/testdata/query/output/select_simple_with_is_not_null.sql.golden.json b/parser/testdata/query/output/select_simple_with_is_not_null.sql.golden.json
index 58968b2..4867063 100644
--- a/parser/testdata/query/output/select_simple_with_is_not_null.sql.golden.json
+++ b/parser/testdata/query/output/select_simple_with_is_not_null.sql.golden.json
@@ -196,6 +196,7 @@
     "LimitBy": null,
     "Limit": null,
     "Settings": null,
+    "Format": null,
     "UnionAll": null,
     "UnionDistinct": null,
     "Except": null
diff --git a/parser/testdata/query/output/select_simple_with_is_null.sql.golden.json b/parser/testdata/query/output/select_simple_with_is_null.sql.golden.json
index b41a093..f6c0114 100644
--- a/parser/testdata/query/output/select_simple_with_is_null.sql.golden.json
+++ b/parser/testdata/query/output/select_simple_with_is_null.sql.golden.json
@@ -182,6 +182,7 @@
     "LimitBy": null,
     "Limit": null,
     "Settings": null,
+    "Format": null,
     "UnionAll": null,
     "UnionDistinct": null,
     "Except": null
diff --git a/parser/testdata/query/output/select_simple_with_top_clause.sql.golden.json b/parser/testdata/query/output/select_simple_with_top_clause.sql.golden.json
index 6e75392..c584082 100644
--- a/parser/testdata/query/output/select_simple_with_top_clause.sql.golden.json
+++ b/parser/testdata/query/output/select_simple_with_top_clause.sql.golden.json
@@ -61,6 +61,7 @@
     "LimitBy": null,
     "Limit": null,
     "Settings": null,
+    "Format": null,
     "UnionAll": null,
     "UnionDistinct": null,
     "Except": null
diff --git a/parser/testdata/query/output/select_simple_with_with_clause.sql.golden.json b/parser/testdata/query/output/select_simple_with_with_clause.sql.golden.json
index 5d55b8b..a0dddd9 100644
--- a/parser/testdata/query/output/select_simple_with_with_clause.sql.golden.json
+++ b/parser/testdata/query/output/select_simple_with_with_clause.sql.golden.json
@@ -66,6 +66,7 @@
             "LimitBy": null,
             "Limit": null,
             "Settings": null,
+            "Format": null,
             "UnionAll": null,
             "UnionDistinct": null,
             "Except": null
@@ -131,6 +132,7 @@
             "LimitBy": null,
             "Limit": null,
             "Settings": null,
+            "Format": null,
             "UnionAll": null,
             "UnionDistinct": null,
             "Except": null
@@ -275,6 +277,7 @@
     "LimitBy": null,
     "Limit": null,
     "Settings": null,
+    "Format": null,
     "UnionAll": null,
     "UnionDistinct": null,
     "Except": null
diff --git a/parser/testdata/query/output/select_table_alias_without_keyword.sql.golden.json b/parser/testdata/query/output/select_table_alias_without_keyword.sql.golden.json
index 6207280..1487980 100644
--- a/parser/testdata/query/output/select_table_alias_without_keyword.sql.golden.json
+++ b/parser/testdata/query/output/select_table_alias_without_keyword.sql.golden.json
@@ -156,6 +156,7 @@
     "LimitBy": null,
     "Limit": null,
     "Settings": null,
+    "Format": null,
     "UnionAll": null,
     "UnionDistinct": null,
     "Except": null
diff --git a/parser/testdata/query/output/select_with_join_only.sql.golden.json b/parser/testdata/query/output/select_with_join_only.sql.golden.json
index 6bcefd1..2e61223 100644
--- a/parser/testdata/query/output/select_with_join_only.sql.golden.json
+++ b/parser/testdata/query/output/select_with_join_only.sql.golden.json
@@ -99,6 +99,7 @@
     "LimitBy": null,
     "Limit": null,
     "Settings": null,
+    "Format": null,
     "UnionAll": null,
     "UnionDistinct": null,
     "Except": null
diff --git a/parser/testdata/query/output/select_with_left_join.sql.golden.json b/parser/testdata/query/output/select_with_left_join.sql.golden.json
index e4eb41a..2ea4c66 100644
--- a/parser/testdata/query/output/select_with_left_join.sql.golden.json
+++ b/parser/testdata/query/output/select_with_left_join.sql.golden.json
@@ -53,6 +53,7 @@
             "LimitBy": null,
             "Limit": null,
             "Settings": null,
+            "Format": null,
             "UnionAll": null,
             "UnionDistinct": null,
             "Except": null
@@ -105,6 +106,7 @@
             "LimitBy": null,
             "Limit": null,
             "Settings": null,
+            "Format": null,
             "UnionAll": null,
             "UnionDistinct": null,
             "Except": null
@@ -209,6 +211,7 @@
     "LimitBy": null,
     "Limit": null,
     "Settings": null,
+    "Format": null,
     "UnionAll": null,
     "UnionDistinct": null,
     "Except": null
diff --git a/parser/testdata/query/output/select_with_literal_table_name.sql.golden.json b/parser/testdata/query/output/select_with_literal_table_name.sql.golden.json
index 6a0ad35..4f8a106 100644
--- a/parser/testdata/query/output/select_with_literal_table_name.sql.golden.json
+++ b/parser/testdata/query/output/select_with_literal_table_name.sql.golden.json
@@ -65,6 +65,7 @@
       "Offset": null
     },
     "Settings": null,
+    "Format": null,
     "UnionAll": null,
     "UnionDistinct": null,
     "Except": null
diff --git a/parser/testdata/query/output/select_with_multi_join.sql.golden.json b/parser/testdata/query/output/select_with_multi_join.sql.golden.json
index b4eed35..5113869 100644
--- a/parser/testdata/query/output/select_with_multi_join.sql.golden.json
+++ b/parser/testdata/query/output/select_with_multi_join.sql.golden.json
@@ -52,6 +52,7 @@
             "LimitBy": null,
             "Limit": null,
             "Settings": null,
+            "Format": null,
             "UnionAll": null,
             "UnionDistinct": null,
             "Except": null
@@ -103,6 +104,7 @@
             "LimitBy": null,
             "Limit": null,
             "Settings": null,
+            "Format": null,
             "UnionAll": null,
             "UnionDistinct": null,
             "Except": null
@@ -154,6 +156,7 @@
             "LimitBy": null,
             "Limit": null,
             "Settings": null,
+            "Format": null,
             "UnionAll": null,
             "UnionDistinct": null,
             "Except": null
@@ -419,6 +422,7 @@
     "LimitBy": null,
     "Limit": null,
     "Settings": null,
+    "Format": null,
     "UnionAll": null,
     "UnionDistinct": null,
     "Except": null
diff --git a/parser/testdata/query/output/select_with_multi_line_comment.sql.golden.json b/parser/testdata/query/output/select_with_multi_line_comment.sql.golden.json
index 393d38e..2a6b80e 100644
--- a/parser/testdata/query/output/select_with_multi_line_comment.sql.golden.json
+++ b/parser/testdata/query/output/select_with_multi_line_comment.sql.golden.json
@@ -51,6 +51,7 @@
     "LimitBy": null,
     "Limit": null,
     "Settings": null,
+    "Format": null,
     "UnionAll": null,
     "UnionDistinct": null,
     "Except": null
diff --git a/parser/testdata/query/output/select_with_string_expr.sql.golden.json b/parser/testdata/query/output/select_with_string_expr.sql.golden.json
index 90e27d4..1872786 100644
--- a/parser/testdata/query/output/select_with_string_expr.sql.golden.json
+++ b/parser/testdata/query/output/select_with_string_expr.sql.golden.json
@@ -53,6 +53,7 @@
             "LimitBy": null,
             "Limit": null,
             "Settings": null,
+            "Format": null,
             "UnionAll": null,
             "UnionDistinct": null,
             "Except": null
@@ -108,6 +109,7 @@
     "LimitBy": null,
     "Limit": null,
     "Settings": null,
+    "Format": null,
     "UnionAll": null,
     "UnionDistinct": null,
     "Except": null
diff --git a/parser/testdata/query/output/select_with_union_distinct.sql.golden.json b/parser/testdata/query/output/select_with_union_distinct.sql.golden.json
index e26ec64..a98c0b0 100644
--- a/parser/testdata/query/output/select_with_union_distinct.sql.golden.json
+++ b/parser/testdata/query/output/select_with_union_distinct.sql.golden.json
@@ -56,10 +56,11 @@
     "LimitBy": null,
     "Limit": null,
     "Settings": null,
+    "Format": null,
     "UnionAll": null,
     "UnionDistinct": {
       "SelectPos": 59,
-      "StatementEnd": 109,
+      "StatementEnd": 121,
       "With": null,
       "Top": null,
       "SelectColumns": {
@@ -114,6 +115,15 @@
       "LimitBy": null,
       "Limit": null,
       "Settings": null,
+      "Format": {
+        "FormatPos": 110,
+        "Format": {
+          "Name": "JSON",
+          "QuoteType": 1,
+          "NamePos": 117,
+          "NameEnd": 121
+        }
+      },
       "UnionAll": null,
       "UnionDistinct": null,
       "Except": null
diff --git a/parser/testdata/query/output/select_with_variable.sql.golden.json b/parser/testdata/query/output/select_with_variable.sql.golden.json
index ad5b84c..e27d903 100644
--- a/parser/testdata/query/output/select_with_variable.sql.golden.json
+++ b/parser/testdata/query/output/select_with_variable.sql.golden.json
@@ -53,6 +53,7 @@
             "LimitBy": null,
             "Limit": null,
             "Settings": null,
+            "Format": null,
             "UnionAll": null,
             "UnionDistinct": null,
             "Except": null
@@ -108,6 +109,7 @@
     "LimitBy": null,
     "Limit": null,
     "Settings": null,
+    "Format": null,
     "UnionAll": null,
     "UnionDistinct": null,
     "Except": null