Repository: AfterShip/clickhouse-sql-parser
Pull request #34 (2024-01-29 20:02:06)

Added FINAL processing to SELECT and fixed conversion of selectExpr to string
Hi! 

While using -format I encountered an unexpected behavior

You can see it:
SELECT * FROM clickhouse FINAL;
SELECT * FROM clickhouse LIMIT 100;

Thank you in advance!

git-hulk: Hi @Dolso, thanks for your contribution. 

Would you mind running `make update_test` on your side to update the test data?
Dolso: > Would you mind running `make update_test` on your side to update the test data?
I did it

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


* **-9** of **17**   **(47.06%)**  changed or added relevant lines in **2** files are covered.
* No unchanged relevant lines lost coverage.
* Overall coverage decreased (**-0.03%**) to **58.896%**

---

|  Changes Missing Coverage | Covered Lines | Changed/Added Lines | % |
| :-----|--------------|--------|---: |
| [parser/parser_query.go](https://coveralls.io/builds/65375652/source?filename=parser%2Fparser_query.go#L271) | 6 | 10 | 60.0%
| [parser/ast.go](https://coveralls.io/builds/65375652/source?filename=parser%2Fast.go#L2502) | 2 | 7 | 28.57%
<!-- | **Total:** | **8** | **17** | **47.06%** | -->


|  Totals | [![Coverage Status](https://coveralls.io/builds/65375652/badge)](https://coveralls.io/builds/65375652) |
| :-- | --: |
| Change from base [Build 7498464439](https://coveralls.io/builds/65033179): |  -0.03% |
| Covered Lines: | 4330 |
| Relevant Lines: | 7352 |

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


Patch:
diff --git a/parser/ast.go b/parser/ast.go
index ab52212..5c3679a 100644
--- a/parser/ast.go
+++ b/parser/ast.go
@@ -2480,6 +2480,7 @@ type TableExpr struct {
 	TableEnd Pos
 	Alias    *AliasExpr
 	Expr     Expr
+	HasFinal bool
 }
 
 func (t *TableExpr) Pos() Pos {
@@ -2497,6 +2498,9 @@ func (t *TableExpr) String(level int) string {
 		builder.WriteByte(' ')
 		builder.WriteString(t.Alias.String(level + 1))
 	}
+	if t.HasFinal {
+		builder.WriteString(" FINAL")
+	}
 	return builder.String()
 }
 
@@ -3139,6 +3143,10 @@ func (s *SelectQuery) String(level int) string { // nolint: funlen
 		builder.WriteString(NewLine(level))
 		builder.WriteString(s.LimitBy.String(level))
 	}
+	if s.Limit != nil {
+		builder.WriteString(NewLine(level))
+		builder.WriteString(s.Limit.String(level))
+	}
 	if s.Settings != nil {
 		builder.WriteString(NewLine(level))
 		builder.WriteString(s.Settings.String(level))
diff --git a/parser/parser_query.go b/parser/parser_query.go
index 79344d6..7d2b355 100644
--- a/parser/parser_query.go
+++ b/parser/parser_query.go
@@ -264,10 +264,24 @@ func (p *Parser) parseTableExpr(pos Pos) (*TableExpr, error) {
 		}
 		tableEnd = expr.End()
 	}
+
+	isFinalExist := false
+	if asToken := p.tryConsumeKeyword(KeywordFinal); asToken != nil {
+		switch expr.(type) {
+		case *TableFunctionExpr:
+			return nil, errors.New("tablefunction doesn't support FINAL")
+		case *SelectQuery:
+			return nil, errors.New("subquery doesn't support FINAL")
+		}
+		isFinalExist = true
+		tableEnd = expr.End()
+	}
+
 	return &TableExpr{
 		TablePos: pos,
 		TableEnd: tableEnd,
 		Expr:     expr,
+		HasFinal: isFinalExist,
 	}, 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 4e4dcaa..92aeed6 100644
--- a/parser/testdata/ddl/output/bug_001.sql.golden.json
+++ b/parser/testdata/ddl/output/bug_001.sql.golden.json
@@ -450,7 +450,8 @@
                 "NamePos": 600,
                 "NameEnd": 605
               }
-            }
+            },
+            "HasFinal": false
           }
         },
         "ArrayJoin": 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 872a3f4..f57a6de 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
@@ -103,7 +103,8 @@
                 "NamePos": 93,
                 "NameEnd": 101
               }
-            }
+            },
+            "HasFinal": false
           }
         },
         "ArrayJoin": 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 9d83cdc..263ff5a 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
@@ -347,7 +347,8 @@
                         "NamePos": 370,
                         "NameEnd": 371
                       }
-                    }
+                    },
+                    "HasFinal": false
                   }
                 },
                 "ArrayJoin": null,
@@ -433,7 +434,8 @@
                 "NamePos": 444,
                 "NameEnd": 447
               }
-            }
+            },
+            "HasFinal": false
           }
         },
         "ArrayJoin": 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 02e2b3f..4735372 100644
--- a/parser/testdata/ddl/output/create_view_basic.sql.golden.json
+++ b/parser/testdata/ddl/output/create_view_basic.sql.golden.json
@@ -112,7 +112,8 @@
                 "NamePos": 96,
                 "NameEnd": 104
               }
-            }
+            },
+            "HasFinal": false
           }
         },
         "ArrayJoin": 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 7c27e62..45985c9 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
@@ -73,7 +73,8 @@
                 "NamePos": 185,
                 "NameEnd": 199
               }
-            }
+            },
+            "HasFinal": false
           }
         },
         "ArrayJoin": 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 84e9686..e5bd0aa 100644
--- a/parser/testdata/dml/output/insert_with_select.sql.golden.json
+++ b/parser/testdata/dml/output/insert_with_select.sql.golden.json
@@ -73,7 +73,8 @@
               "NamePos": 97,
               "NameEnd": 103
             }
-          }
+          },
+          "HasFinal": false
         }
       },
       "ArrayJoin": null,
diff --git a/parser/testdata/query/output/select_simple.sql.golden.json b/parser/testdata/query/output/select_simple.sql.golden.json
index bf18d8b..215cefb 100644
--- a/parser/testdata/query/output/select_simple.sql.golden.json
+++ b/parser/testdata/query/output/select_simple.sql.golden.json
@@ -145,7 +145,8 @@
             "NamePos": 107,
             "NameEnd": 119
           }
-        }
+        },
+        "HasFinal": false
       }
     },
     "ArrayJoin": 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 9505ba5..df608e8 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
@@ -90,7 +90,8 @@
                     "NamePos": 53,
                     "NameEnd": 58
                   }
-                }
+                },
+                "HasFinal": false
               }
             },
             "ArrayJoin": null,
@@ -178,7 +179,8 @@
             "NamePos": 129,
             "NameEnd": 133
           }
-        }
+        },
+        "HasFinal": false
       }
     },
     "ArrayJoin": 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 b4fa91a..2beaeac 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
@@ -57,7 +57,8 @@
             "NamePos": 24,
             "NameEnd": 36
           }
-        }
+        },
+        "HasFinal": false
       }
     },
     "ArrayJoin": 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 8bb7a4e..454ffcd 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
@@ -63,7 +63,8 @@
             "NamePos": 35,
             "NameEnd": 47
           }
-        }
+        },
+        "HasFinal": false
       }
     },
     "ArrayJoin": 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 a466312..f85b1c8 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
@@ -63,7 +63,8 @@
             "NamePos": 35,
             "NameEnd": 47
           }
-        }
+        },
+        "HasFinal": false
       }
     },
     "ArrayJoin": 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 0e8944d..2b517f7 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
@@ -41,7 +41,8 @@
             "NamePos": 29,
             "NameEnd": 38
           }
-        }
+        },
+        "HasFinal": false
       }
     },
     "ArrayJoin": 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 70e06e5..9323aec 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
@@ -46,7 +46,8 @@
                     "NamePos": 33,
                     "NameEnd": 35
                   }
-                }
+                },
+                "HasFinal": false
               }
             },
             "ArrayJoin": null,
@@ -105,7 +106,8 @@
                     "NamePos": 66,
                     "NameEnd": 68
                   }
-                }
+                },
+                "HasFinal": false
               }
             },
             "ArrayJoin": null,
@@ -195,7 +197,8 @@
               "NamePos": 122,
               "NameEnd": 124
             }
-          }
+          },
+          "HasFinal": false
         },
         "Right": {
           "JoinPos": 125,
@@ -211,7 +214,8 @@
                 "NamePos": 125,
                 "NameEnd": 129
               }
-            }
+            },
+            "HasFinal": false
           },
           "Right": {
             "TablePos": 130,
@@ -225,7 +229,8 @@
                 "NamePos": 130,
                 "NameEnd": 134
               }
-            }
+            },
+            "HasFinal": false
           },
           "JoinType": "",
           "SampleRatio": 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 c894763..8e7ac71 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
@@ -36,7 +36,8 @@
             "NamePos": 32,
             "NameEnd": 43
           }
-        }
+        },
+        "HasFinal": false
       }
     },
     "ArrayJoin": null,
@@ -88,7 +89,8 @@
               "NamePos": 91,
               "NameEnd": 109
             }
-          }
+          },
+          "HasFinal": false
         }
       },
       "ArrayJoin": null,