Skip to content

Commit 08fdec6

Browse files
authored
Merge pull request #13 from stackql/claude/port-window-functions-ctes-017gSQYGjQBqkJ5BQmU9nXkH
Add window function (OVER clause) and CTE (WITH clause) support
2 parents cd3a8cc + 1595204 commit 08fdec6

File tree

6 files changed

+4744
-4111
lines changed

6 files changed

+4744
-4111
lines changed

go/vt/sqlparser/ast.go

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ type (
5757

5858
// Select represents a SELECT statement.
5959
Select struct {
60+
With *With
6061
Cache *bool // a reference here so it can be nil
6162
Distinct bool
6263
StraightJoinHint bool
@@ -72,6 +73,19 @@ type (
7273
Lock string
7374
}
7475

76+
// With represents the WITH clause (Common Table Expressions).
77+
With struct {
78+
Recursive bool
79+
CTEs []*CommonTableExpr
80+
}
81+
82+
// CommonTableExpr represents a single CTE definition.
83+
CommonTableExpr struct {
84+
Name TableIdent
85+
Columns Columns
86+
Select SelectStatement
87+
}
88+
7589
// Exec represents an EXEC statement
7690
Exec struct {
7791
Await bool
@@ -802,6 +816,27 @@ type (
802816
Name ColIdent
803817
Distinct bool
804818
Exprs SelectExprs
819+
Over *OverClause
820+
}
821+
822+
// OverClause represents the OVER clause for window functions.
823+
OverClause struct {
824+
PartitionBy Exprs
825+
OrderBy OrderBy
826+
Frame *FrameClause
827+
}
828+
829+
// FrameClause represents the frame specification in a window function.
830+
FrameClause struct {
831+
Type string // ROWS or RANGE
832+
Start *FramePoint
833+
End *FramePoint
834+
}
835+
836+
// FramePoint represents a single point in a frame specification.
837+
FramePoint struct {
838+
Type string // CURRENT ROW, UNBOUNDED PRECEDING, UNBOUNDED FOLLOWING, or value PRECEDING/FOLLOWING
839+
Expr Expr // for value PRECEDING/FOLLOWING
805840
}
806841

807842
// GroupConcatExpr represents a call to GROUP_CONCAT
@@ -989,6 +1024,9 @@ type TableIdent struct {
9891024

9901025
// Format formats the node.
9911026
func (node *Select) Format(buf *TrackedBuffer) {
1027+
if node.With != nil {
1028+
buf.astPrintf(node, "%v ", node.With)
1029+
}
9921030
var options string
9931031
addIf := func(b bool, s string) {
9941032
if b {
@@ -1013,6 +1051,30 @@ func (node *Select) Format(buf *TrackedBuffer) {
10131051
node.Limit, node.Lock)
10141052
}
10151053

1054+
// Format formats the node.
1055+
func (node *With) Format(buf *TrackedBuffer) {
1056+
buf.WriteString("with ")
1057+
if node.Recursive {
1058+
buf.WriteString("recursive ")
1059+
}
1060+
for i, cte := range node.CTEs {
1061+
if i > 0 {
1062+
buf.WriteString(", ")
1063+
}
1064+
buf.astPrintf(node, "%v", cte)
1065+
}
1066+
}
1067+
1068+
// Format formats the node.
1069+
func (node *CommonTableExpr) Format(buf *TrackedBuffer) {
1070+
buf.astPrintf(node, "%v", node.Name)
1071+
if len(node.Columns) > 0 {
1072+
buf.WriteString(" ")
1073+
buf.astPrintf(node, "%v", node.Columns)
1074+
}
1075+
buf.astPrintf(node, " as (%v)", node.Select)
1076+
}
1077+
10161078
func (node *Exec) Format(buf *TrackedBuffer) {
10171079
buf.astPrintf(node, "exec %v %v", node.Comments, node.MethodName)
10181080
}
@@ -1892,6 +1954,61 @@ func (node *FuncExpr) Format(buf *TrackedBuffer) {
18921954
buf.WriteString(funcName)
18931955
}
18941956
buf.astPrintf(node, "(%s%v)", distinct, node.Exprs)
1957+
if node.Over != nil {
1958+
buf.astPrintf(node, " %v", node.Over)
1959+
}
1960+
}
1961+
1962+
// Format formats the node.
1963+
func (node *OverClause) Format(buf *TrackedBuffer) {
1964+
buf.WriteString("over (")
1965+
needSpace := false
1966+
if len(node.PartitionBy) > 0 {
1967+
buf.astPrintf(node, "partition by %v", node.PartitionBy)
1968+
needSpace = true
1969+
}
1970+
if len(node.OrderBy) > 0 {
1971+
if needSpace {
1972+
buf.WriteString(" ")
1973+
}
1974+
buf.WriteString("order by ")
1975+
for i, order := range node.OrderBy {
1976+
if i > 0 {
1977+
buf.WriteString(", ")
1978+
}
1979+
buf.astPrintf(node, "%v", order)
1980+
}
1981+
needSpace = true
1982+
}
1983+
if node.Frame != nil {
1984+
if needSpace {
1985+
buf.WriteString(" ")
1986+
}
1987+
buf.astPrintf(node, "%v", node.Frame)
1988+
}
1989+
buf.WriteString(")")
1990+
}
1991+
1992+
// Format formats the node.
1993+
func (node *FrameClause) Format(buf *TrackedBuffer) {
1994+
buf.WriteString(node.Type)
1995+
if node.End != nil {
1996+
buf.WriteString(" between ")
1997+
buf.astPrintf(node, "%v", node.Start)
1998+
buf.WriteString(" and ")
1999+
buf.astPrintf(node, "%v", node.End)
2000+
} else {
2001+
buf.WriteString(" ")
2002+
buf.astPrintf(node, "%v", node.Start)
2003+
}
2004+
}
2005+
2006+
// Format formats the node.
2007+
func (node *FramePoint) Format(buf *TrackedBuffer) {
2008+
if node.Expr != nil {
2009+
buf.astPrintf(node, "%v ", node.Expr)
2010+
}
2011+
buf.WriteString(node.Type)
18952012
}
18962013

18972014
// Format formats the node

go/vt/sqlparser/constants.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,4 +190,15 @@ const (
190190
// Cardinality increase functions
191191
JsonEachStr = "json_each"
192192
JsonArrayElementsTextStr = "json_array_elements_text"
193+
194+
// Window function frame types
195+
RowsStr = "rows"
196+
RangeStr = "range"
197+
198+
// Window function frame boundaries
199+
CurrentRowStr = "current row"
200+
UnboundedPrecedingStr = "unbounded preceding"
201+
UnboundedFollowingStr = "unbounded following"
202+
PrecedingStr = "preceding"
203+
FollowingStr = "following"
193204
)

go/vt/sqlparser/external_visitor.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,4 +116,9 @@ func (node VindexParam) Accept(vis SQLAstVisitor) error { return v
116116
func (node *VindexSpec) Accept(vis SQLAstVisitor) error { return vis.Visit(node) }
117117
func (node *When) Accept(vis SQLAstVisitor) error { return vis.Visit(node) }
118118
func (node *Where) Accept(vis SQLAstVisitor) error { return vis.Visit(node) }
119+
func (node *With) Accept(vis SQLAstVisitor) error { return vis.Visit(node) }
120+
func (node *CommonTableExpr) Accept(vis SQLAstVisitor) error { return vis.Visit(node) }
121+
func (node *OverClause) Accept(vis SQLAstVisitor) error { return vis.Visit(node) }
122+
func (node *FrameClause) Accept(vis SQLAstVisitor) error { return vis.Visit(node) }
123+
func (node *FramePoint) Accept(vis SQLAstVisitor) error { return vis.Visit(node) }
119124
func (node *XorExpr) Accept(vis SQLAstVisitor) error { return vis.Visit(node) }

0 commit comments

Comments
 (0)