diff --git a/parser/ast.go b/parser/ast.go index 7416eee..15ad871 100644 --- a/parser/ast.go +++ b/parser/ast.go @@ -6658,12 +6658,38 @@ func (w *WindowExpr) Accept(visitor ASTVisitor) error { return visitor.VisitWindowConditionExpr(w) } -type WindowClause struct { - *WindowExpr +type WindowDefinition struct { + Name *Ident + AsPos Pos + Expr *WindowExpr +} + +func (w *WindowDefinition) Pos() Pos { + if w == nil || w.Name == nil { + return 0 + } + return w.Name.Pos() +} + +func (w *WindowDefinition) End() Pos { + if w == nil || w.Expr == nil { + return 0 + } + return w.Expr.End() +} + +func (w *WindowDefinition) String() string { + var builder strings.Builder + builder.WriteString(w.Name.String()) + builder.WriteString(" AS ") + builder.WriteString(w.Expr.String()) + return builder.String() +} +type WindowClause struct { WindowPos Pos - Name *Ident - AsPos Pos + EndPos Pos + Windows []*WindowDefinition } func (w *WindowClause) Pos() Pos { @@ -6671,29 +6697,43 @@ func (w *WindowClause) Pos() Pos { } func (w *WindowClause) End() Pos { - return w.WindowExpr.End() + if w.EndPos != 0 { + return w.EndPos + } + if len(w.Windows) == 0 { + return w.WindowPos + } + return w.Windows[len(w.Windows)-1].End() } func (w *WindowClause) String() string { var builder strings.Builder builder.WriteString("WINDOW ") - builder.WriteString(w.Name.String()) - builder.WriteString(" AS ") - builder.WriteString(w.WindowExpr.String()) + for i, window := range w.Windows { + builder.WriteString(window.String()) + if i != len(w.Windows)-1 { + builder.WriteString(", ") + } + } return builder.String() } func (w *WindowClause) Accept(visitor ASTVisitor) error { visitor.Enter(w) defer visitor.Leave(w) - if w.WindowExpr != nil { - if err := w.WindowExpr.Accept(visitor); err != nil { - return err + for _, window := range w.Windows { + if window == nil { + continue } - } - if w.Name != nil { - if err := w.Name.Accept(visitor); err != nil { - return err + if window.Name != nil { + if err := window.Name.Accept(visitor); err != nil { + return err + } + } + if window.Expr != nil { + if err := window.Expr.Accept(visitor); err != nil { + return err + } } } return visitor.VisitWindowExpr(w) @@ -6731,7 +6771,9 @@ func (f *WindowFrameClause) Accept(visitor ASTVisitor) error { } type WindowFrameExtendExpr struct { - Expr Expr + Expr Expr + Direction string + EndPos Pos } func (f *WindowFrameExtendExpr) Pos() Pos { @@ -6739,11 +6781,20 @@ func (f *WindowFrameExtendExpr) Pos() Pos { } func (f *WindowFrameExtendExpr) End() Pos { + if f.EndPos != 0 { + return f.EndPos + } return f.Expr.End() } func (f *WindowFrameExtendExpr) String() string { - return f.Expr.String() + var builder strings.Builder + builder.WriteString(f.Expr.String()) + if f.Direction != "" { + builder.WriteByte(' ') + builder.WriteString(f.Direction) + } + return builder.String() } func (f *WindowFrameExtendExpr) Accept(visitor ASTVisitor) error { @@ -6850,9 +6901,9 @@ func (f *WindowFrameUnbounded) Accept(visitor ASTVisitor) error { } type WindowFrameNumber struct { - Number *NumberLiteral - UnboundedEnd Pos - Direction string + Number *NumberLiteral + EndPos Pos + Direction string } func (f *WindowFrameNumber) Pos() Pos { @@ -6860,7 +6911,7 @@ func (f *WindowFrameNumber) Pos() Pos { } func (f *WindowFrameNumber) End() Pos { - return f.UnboundedEnd + return f.EndPos } func (f *WindowFrameNumber) String() string { @@ -6880,6 +6931,37 @@ func (f *WindowFrameNumber) Accept(visitor ASTVisitor) error { return visitor.VisitWindowFrameNumber(f) } +type WindowFrameParam struct { + Param *QueryParam + EndPos Pos + Direction string +} + +func (f *WindowFrameParam) Pos() Pos { + return f.Param.Pos() +} + +func (f *WindowFrameParam) End() Pos { + return f.EndPos +} + +func (f *WindowFrameParam) String() string { + var builder strings.Builder + builder.WriteString(f.Param.String()) + builder.WriteByte(' ') + builder.WriteString(f.Direction) + return builder.String() +} + +func (f *WindowFrameParam) Accept(visitor ASTVisitor) error { + visitor.Enter(f) + defer visitor.Leave(f) + if err := f.Param.Accept(visitor); err != nil { + return err + } + return visitor.VisitWindowFrameParam(f) +} + type ArrayJoinClause struct { ArrayPos Pos Type string diff --git a/parser/ast_visitor.go b/parser/ast_visitor.go index 269e264..234b335 100644 --- a/parser/ast_visitor.go +++ b/parser/ast_visitor.go @@ -148,6 +148,7 @@ type ASTVisitor interface { VisitWindowFrameCurrentRow(expr *WindowFrameCurrentRow) error VisitWindowFrameUnbounded(expr *WindowFrameUnbounded) error VisitWindowFrameNumber(expr *WindowFrameNumber) error + VisitWindowFrameParam(expr *WindowFrameParam) error VisitArrayJoinExpr(expr *ArrayJoinClause) error VisitSelectQuery(expr *SelectQuery) error VisitSubQueryExpr(expr *SubQuery) error @@ -1228,6 +1229,13 @@ func (v *DefaultASTVisitor) VisitWindowFrameNumber(expr *WindowFrameNumber) erro return nil } +func (v *DefaultASTVisitor) VisitWindowFrameParam(expr *WindowFrameParam) error { + if v.Visit != nil { + return v.Visit(expr) + } + return nil +} + func (v *DefaultASTVisitor) VisitArrayJoinExpr(expr *ArrayJoinClause) error { if v.Visit != nil { return v.Visit(expr) diff --git a/parser/parser_query.go b/parser/parser_query.go index c673b48..260758b 100644 --- a/parser/parser_query.go +++ b/parser/parser_query.go @@ -603,81 +603,38 @@ func (p *Parser) parseWindowFrameClause(pos Pos) (*WindowFrameClause, error) { if p.matchKeyword(KeywordRows) || p.matchKeyword(KeywordRange) { windowFrameType = p.last().String _ = p.lexer.consumeToken() + } else { + return nil, fmt.Errorf("expected ROWS or RANGE for window frame") } var expr Expr - switch { - case p.tryConsumeKeywords(KeywordBetween): - betweenWindowFrame, err := p.parseWindowFrameClause(p.Pos()) + if p.tryConsumeKeywords(KeywordBetween) { + left, err := p.parseFrameExtent() if err != nil { return nil, err } - andPos := p.Pos() if err := p.expectKeyword(KeywordAnd); err != nil { return nil, err } - - andWindowFrame, err := p.parseWindowFrameClause(p.Pos()) + right, err := p.parseFrameExtent() if err != nil { return nil, err } expr = &BetweenClause{ - Between: betweenWindowFrame, + Between: left, AndPos: andPos, - And: andWindowFrame, - } - case p.matchKeyword(KeywordCurrent): - currentPos := p.Pos() - _ = p.lexer.consumeToken() - rowEnd := p.End() - if err := p.expectKeyword(KeywordRow); err != nil { - return nil, err - } - expr = &WindowFrameCurrentRow{ - CurrentPos: currentPos, - RowEnd: rowEnd, - } - case p.matchKeyword(KeywordUnbounded): - unboundedPos := p.Pos() - _ = p.lexer.consumeToken() - - direction := "" - switch { - case p.matchKeyword(KeywordPreceding), p.matchKeyword(KeywordFollowing): - direction = p.last().String - _ = p.lexer.consumeToken() - default: - return nil, fmt.Errorf("expected PRECEDING or FOLLOWING, got %s", p.lastTokenKind()) + And: right, } - expr = &WindowFrameUnbounded{ - UnboundedPos: unboundedPos, - Direction: direction, - } - case p.matchTokenKind(TokenKindInt): - number, err := p.parseNumber(p.Pos()) + } else { + // single extent + extent, err := p.parseFrameExtent() if err != nil { return nil, err } - - var unboundedEnd Pos - direction := "" - switch { - case p.matchKeyword(KeywordPreceding), p.matchKeyword(KeywordFollowing): - direction = p.last().String - unboundedEnd = p.End() - _ = p.lexer.consumeToken() - default: - return nil, fmt.Errorf("expected PRECEDING or FOLLOWING, got %s", p.lastTokenKind()) - } - expr = &WindowFrameNumber{ - UnboundedEnd: unboundedEnd, - Number: number, - Direction: direction, - } - default: - return nil, fmt.Errorf("expected BETWEEN, CURRENT, UNBOUNDED or integer, got %s", p.lastTokenKind()) + expr = extent } + return &WindowFrameClause{ FramePos: pos, Type: windowFrameType, @@ -685,6 +642,123 @@ func (p *Parser) parseWindowFrameClause(pos Pos) (*WindowFrameClause, error) { }, nil } +// parseFrameExtent parses a single frame extent +func (p *Parser) parseFrameExtent() (Expr, error) { + switch { + case p.matchKeyword(KeywordCurrent): + return p.parseFrameCurrentRow() + case p.matchKeyword(KeywordUnbounded): + return p.parseFrameUnbounded() + case p.matchTokenKind(TokenKindInt): + return p.parseFrameNumber() + case p.matchTokenKind(TokenKindLBrace): + return p.parseFrameParam() + case p.matchKeyword(KeywordInterval): + return p.parseFrameInterval() + default: + return nil, fmt.Errorf("expected UNBOUNDED, CURRENT ROW, integer, parameter, or interval") + } +} + +func (p *Parser) parseFrameCurrentRow() (Expr, error) { + currentPos := p.Pos() + _ = p.lexer.consumeToken() + if err := p.expectKeyword(KeywordRow); err != nil { + return nil, err + } + rowEnd := p.End() + return &WindowFrameCurrentRow{ + CurrentPos: currentPos, + RowEnd: rowEnd, + }, nil +} + +func (p *Parser) parseFrameUnbounded() (Expr, error) { + unboundedPos := p.Pos() + _ = p.lexer.consumeToken() + + direction, err := p.parseFrameDirection() + if err != nil { + return nil, err + } + return &WindowFrameUnbounded{ + UnboundedPos: unboundedPos, + Direction: direction, + }, nil +} + +func (p *Parser) parseFrameNumber() (Expr, error) { + number, err := p.parseNumber(p.Pos()) + if err != nil { + return nil, err + } + + direction, endPos, err := p.parseFrameDirectionWithEnd() + if err != nil { + return nil, err + } + return &WindowFrameNumber{ + EndPos: endPos, + Number: number, + Direction: direction, + }, nil +} + +func (p *Parser) parseFrameParam() (Expr, error) { + queryParam, err := p.parseQueryParam(p.Pos()) + if err != nil { + return nil, err + } + + direction, endPos, err := p.parseFrameDirectionWithEnd() + if err != nil { + return nil, err + } + return &WindowFrameParam{ + Param: queryParam, + EndPos: endPos, + Direction: direction, + }, nil +} + +func (p *Parser) parseFrameInterval() (Expr, error) { + intervalExpr, err := p.parseInterval(true) + if err != nil { + return nil, err + } + + direction, endPos, err := p.parseFrameDirectionWithEnd() + if err != nil { + return nil, err + } + return &WindowFrameExtendExpr{ + Expr: intervalExpr, + Direction: direction, + EndPos: endPos, + }, nil +} + +func (p *Parser) parseFrameDirection() (string, error) { + switch { + case p.matchKeyword(KeywordPreceding), p.matchKeyword(KeywordFollowing): + direction := p.last().String + _ = p.lexer.consumeToken() + return direction, nil + default: + return "", fmt.Errorf("expected PRECEDING or FOLLOWING, got %s", p.lastTokenKind()) + } +} + +func (p *Parser) parseFrameDirectionWithEnd() (string, Pos, error) { + if !p.matchKeyword(KeywordPreceding) && !p.matchKeyword(KeywordFollowing) { + return "", 0, fmt.Errorf("expected PRECEDING or FOLLOWING, got %s", p.lastTokenKind()) + } + endPos := p.End() + direction := p.last().String + _ = p.lexer.consumeToken() + return direction, endPos, nil +} + func (p *Parser) tryParseWindowClause(pos Pos) (*WindowClause, error) { if !p.matchKeyword(KeywordWindow) { return nil, nil @@ -726,24 +800,43 @@ func (p *Parser) parseWindowClause(pos Pos) (*WindowClause, error) { return nil, err } - windowName, err := p.parseIdent() - if err != nil { - return nil, err - } + windows := make([]*WindowDefinition, 0, 1) + for { + windowName, err := p.parseIdent() + if err != nil { + return nil, err + } - if err := p.expectKeyword(KeywordAs); err != nil { - return nil, err + asPos := p.Pos() + if err := p.expectKeyword(KeywordAs); err != nil { + return nil, err + } + + condition, err := p.parseWindowCondition(p.Pos()) + if err != nil { + return nil, err + } + + windows = append(windows, &WindowDefinition{ + Name: windowName, + AsPos: asPos, + Expr: condition, + }) + + if p.tryConsumeTokenKind(TokenKindComma) == nil { + break + } } - condition, err := p.parseWindowCondition(p.Pos()) - if err != nil { - return nil, err + var endPos Pos + if len(windows) > 0 { + endPos = windows[len(windows)-1].End() } return &WindowClause{ - WindowPos: pos, - Name: windowName, - WindowExpr: condition, + WindowPos: pos, + EndPos: endPos, + Windows: windows, }, nil } diff --git a/parser/parser_table.go b/parser/parser_table.go index 46d6996..ee58edb 100644 --- a/parser/parser_table.go +++ b/parser/parser_table.go @@ -276,7 +276,7 @@ func (p *Parser) parseIdentOrFunction(_ Pos) (Expr, error) { return nil, err } default: - return nil, fmt.Errorf("expected IDENT or (, but got %q", p.lastTokenKind()) + return nil, fmt.Errorf("expected window name or (, but got %q", p.lastTokenKind()) } if err != nil { diff --git a/parser/testdata/query/create_window_view.sql b/parser/testdata/query/create_window_view.sql new file mode 100644 index 0000000..a552990 --- /dev/null +++ b/parser/testdata/query/create_window_view.sql @@ -0,0 +1,10 @@ +CREATE OR REPLACE VIEW asdf AS +SELECT id, + price * 1.5 AS computed_value, + row_number() OVER ( + PARTITION BY category + ORDER BY created_at + RANGE BETWEEN 3600 PRECEDING AND CURRENT ROW + ) AS rn +FROM source_table +WHERE date >= '2023-01-01'; diff --git a/parser/testdata/query/format/create_window_view.sql b/parser/testdata/query/format/create_window_view.sql new file mode 100644 index 0000000..62a456c --- /dev/null +++ b/parser/testdata/query/format/create_window_view.sql @@ -0,0 +1,15 @@ +-- Origin SQL: +CREATE OR REPLACE VIEW asdf AS +SELECT id, + price * 1.5 AS computed_value, + row_number() OVER ( + PARTITION BY category + ORDER BY created_at + RANGE BETWEEN 3600 PRECEDING AND CURRENT ROW + ) AS rn +FROM source_table +WHERE date >= '2023-01-01'; + + +-- Format SQL: +CREATE OR REPLACE VIEW asdf AS SELECT id, price * 1.5 AS computed_value, row_number() OVER (PARTITION BY category ORDER BY created_at RANGE BETWEEN 3600 PRECEDING AND CURRENT ROW) AS rn FROM source_table WHERE date >= '2023-01-01'; diff --git a/parser/testdata/query/format/select_window_comprehensive.sql b/parser/testdata/query/format/select_window_comprehensive.sql new file mode 100644 index 0000000..1c51a26 --- /dev/null +++ b/parser/testdata/query/format/select_window_comprehensive.sql @@ -0,0 +1,57 @@ +-- Origin SQL: +-- Comprehensive window spec coverage: ad-hoc specs, named windows, ROWS/RANGE frames +-- multiple functions, multi-column PARTITION/ORDER, and expression-based specs. +SELECT + -- Ad-hoc windows + sum(x) OVER (ORDER BY y ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS running_total, + avg(x) + OVER (PARTITION BY z ORDER BY y RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS avg_range1, + + -- Named window reuse (OVER w1) + row_number() OVER w1 AS rn_w1, + rank() OVER w1 AS rank_w1, + sum(x) OVER w1 AS sum_w1, + + -- Frame variants (incl. shorthand & RANGE) + sum(x) OVER (ROWS 10 PRECEDING) AS rows_10_preceding, + sum(x) OVER (ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS rows_cur_to_unbounded_following, + sum(x) OVER (ROWS BETWEEN 5 PRECEDING AND 3 FOLLOWING) AS rows_5p_3f, + sum(x) OVER (RANGE BETWEEN 10 PRECEDING AND CURRENT ROW) AS range_10p_cur, + sum(x) OVER (RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS range_unbounded_to_cur, + + -- Ranking & navigation + row_number() OVER (PARTITION BY y ORDER BY x) AS row_num, + rank() OVER (PARTITION BY y ORDER BY x) AS rank_val, + dense_rank() OVER (PARTITION BY y ORDER BY x) AS dense_rank_val, + first_value(x) + OVER (PARTITION BY y ORDER BY x ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS first_val, + last_value(x) + OVER (PARTITION BY y ORDER BY x ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_val, + lag(x, 1) OVER (PARTITION BY y ORDER BY x) AS prev_x, + lead(x, 1) OVER (PARTITION BY y ORDER BY x) AS next_x, + percent_rank() OVER (PARTITION BY y ORDER BY x) AS pct_rank, + + -- Named window reference via OVER w (no parentheses) + sum(x) OVER w AS sum_over_w, + avg(x) OVER w AS avg_over_w, + row_number() OVER w AS rn_over_w, + + -- Multiple columns in PARTITION BY / ORDER BY + count(*) OVER (PARTITION BY col1, col2, col3 ORDER BY col4, col5 DESC) AS cnt_multi, + sum(val) + OVER (PARTITION BY col1, col2 ORDER BY col4, col5 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS total_multi, + + -- Expressions in PARTITION/ORDER + sum(amount) + OVER (PARTITION BY date_trunc('day', timestamp) ORDER BY timestamp ROWS BETWEEN 10 PRECEDING AND CURRENT ROW) AS daily_total, + avg(amount) + OVER (ORDER BY extract(HOUR FROM timestamp) RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS hourly_avg +FROM t +WINDOW w AS (ORDER BY y), + w1 AS (PARTITION BY y ORDER BY x ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + w4 AS (PARTITION BY y ORDER BY x ROWS BETWEEN 3 PRECEDING AND CURRENT ROW), + w5 AS (PARTITION BY z ORDER BY x RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW); + + +-- Format SQL: +SELECT sum(x) OVER (ORDER BY y ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS running_total, avg(x) OVER (PARTITION BY z ORDER BY y RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS avg_range1, row_number() OVER w1 AS rn_w1, rank() OVER w1 AS rank_w1, sum(x) OVER w1 AS sum_w1, sum(x) OVER (ROWS 10 PRECEDING) AS rows_10_preceding, sum(x) OVER (ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS rows_cur_to_unbounded_following, sum(x) OVER (ROWS BETWEEN 5 PRECEDING AND 3 FOLLOWING) AS rows_5p_3f, sum(x) OVER (RANGE BETWEEN 10 PRECEDING AND CURRENT ROW) AS range_10p_cur, sum(x) OVER (RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS range_unbounded_to_cur, row_number() OVER (PARTITION BY y ORDER BY x) AS row_num, rank() OVER (PARTITION BY y ORDER BY x) AS rank_val, dense_rank() OVER (PARTITION BY y ORDER BY x) AS dense_rank_val, first_value(x) OVER (PARTITION BY y ORDER BY x ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS first_val, last_value(x) OVER (PARTITION BY y ORDER BY x ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_val, lag(x, 1) OVER (PARTITION BY y ORDER BY x) AS prev_x, lead(x, 1) OVER (PARTITION BY y ORDER BY x) AS next_x, percent_rank() OVER (PARTITION BY y ORDER BY x) AS pct_rank, sum(x) OVER w AS sum_over_w, avg(x) OVER w AS avg_over_w, row_number() OVER w AS rn_over_w, count(*) OVER (PARTITION BY col1, col2, col3 ORDER BY col4, col5 DESC) AS cnt_multi, sum(val) OVER (PARTITION BY col1, col2 ORDER BY col4, col5 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS total_multi, sum(amount) OVER (PARTITION BY date_trunc('day', timestamp) ORDER BY timestamp ROWS BETWEEN 10 PRECEDING AND CURRENT ROW) AS daily_total, avg(amount) OVER (ORDER BY EXTRACT(HOUR FROM timestamp) RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS hourly_avg FROM t WINDOW w AS (ORDER BY y), w1 AS (PARTITION BY y ORDER BY x ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), w4 AS (PARTITION BY y ORDER BY x ROWS BETWEEN 3 PRECEDING AND CURRENT ROW), w5 AS (PARTITION BY z ORDER BY x RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW); diff --git a/parser/testdata/query/format/select_window_cte.sql b/parser/testdata/query/format/select_window_cte.sql new file mode 100644 index 0000000..7c89fb4 --- /dev/null +++ b/parser/testdata/query/format/select_window_cte.sql @@ -0,0 +1,32 @@ +-- Origin SQL: +WITH + monthly AS ( + SELECT toStartOfMonth(date) AS month, + department, + avg(salary) AS avg_salary + FROM salary_table + WHERE year = 2023 + GROUP BY month, department + ), + ranked AS ( + SELECT month, + department, + avg_salary, + row_number() OVER (PARTITION BY department ORDER BY avg_salary DESC) AS dept_rank + FROM monthly + ) +SELECT month, + department, + avg_salary, + lag(avg_salary, 1, 0) OVER ( + PARTITION BY department + ORDER BY month + ROWS BETWEEN 1 PRECEDING AND CURRENT ROW + ) AS prev_month_avg +FROM ranked +WHERE dept_rank <= 5 +ORDER BY month, department; + + +-- Format SQL: +WITH monthly AS (SELECT toStartOfMonth(date) AS month, department, avg(salary) AS avg_salary FROM salary_table WHERE year = 2023 GROUP BY month, department), ranked AS (SELECT month, department, avg_salary, row_number() OVER (PARTITION BY department ORDER BY avg_salary DESC) AS dept_rank FROM monthly) SELECT month, department, avg_salary, lag(avg_salary, 1, 0) OVER (PARTITION BY department ORDER BY month ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prev_month_avg FROM ranked WHERE dept_rank <= 5 ORDER BY month, department; diff --git a/parser/testdata/query/format/select_window_params.sql b/parser/testdata/query/format/select_window_params.sql new file mode 100644 index 0000000..d5d2a1b --- /dev/null +++ b/parser/testdata/query/format/select_window_params.sql @@ -0,0 +1,13 @@ +-- Origin SQL: +-- Parameters in WHERE and in window frames (UInt32 & String; both spacing styles; shorthand frame) +SELECT sum(x) OVER (ORDER BY y ROWS BETWEEN {start:UInt32} PRECEDING AND CURRENT ROW) AS total1, + avg(x) OVER (ORDER BY y ROWS BETWEEN CURRENT ROW AND {end:UInt32} FOLLOWING) AS avg1, + count(*) OVER (ORDER BY y RANGE BETWEEN {range_start:UInt32} PRECEDING AND {range_end:UInt32} FOLLOWING) AS cnt1, + sum(x) OVER (ROWS {window_size :UInt32} PRECEDING) AS rows_shorthand +FROM t +WHERE category = {category :String} + AND type = {type:String}; + + +-- Format SQL: +SELECT sum(x) OVER (ORDER BY y ROWS BETWEEN {start: UInt32} PRECEDING AND CURRENT ROW) AS total1, avg(x) OVER (ORDER BY y ROWS BETWEEN CURRENT ROW AND {end: UInt32} FOLLOWING) AS avg1, count(*) OVER (ORDER BY y RANGE BETWEEN {range_start: UInt32} PRECEDING AND {range_end: UInt32} FOLLOWING) AS cnt1, sum(x) OVER (ROWS {window_size: UInt32} PRECEDING) AS rows_shorthand FROM t WHERE category = {category: String} AND type = {type: String}; diff --git a/parser/testdata/query/format/select_with_window_function.sql b/parser/testdata/query/format/select_with_window_function.sql index 984a60b..bf5fc77 100644 --- a/parser/testdata/query/format/select_with_window_function.sql +++ b/parser/testdata/query/format/select_with_window_function.sql @@ -14,4 +14,4 @@ WINDOW w AS (PARTITION BY aggregation_target ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING); -- Format SQL: -SELECT aggregation_target AS aggregation_target, timestamp AS timestamp, step_0 AS step_0, latest_0 AS latest_0, step_1 AS step_1, latest_1 AS latest_1, step_2 AS step_2, min(latest_2) OVER (PARTITION BY aggregation_target ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_2, min(latest_1) OVER w AS latest_1 FROM t0 WINDOW w AS (PARTITION BY aggregation_target ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING); +SELECT aggregation_target AS aggregation_target, timestamp AS timestamp, step_0 AS step_0, latest_0 AS latest_0, step_1 AS step_1, latest_1 AS latest_1, step_2 AS step_2, min(latest_2) OVER (PARTITION BY aggregation_target ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) AS latest_2, min(latest_1) OVER w AS latest_1 FROM t0 WINDOW w AS (PARTITION BY aggregation_target ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING); diff --git a/parser/testdata/query/output/create_window_view.sql.golden.json b/parser/testdata/query/output/create_window_view.sql.golden.json new file mode 100644 index 0000000..06dae23 --- /dev/null +++ b/parser/testdata/query/output/create_window_view.sql.golden.json @@ -0,0 +1,218 @@ +[ + { + "CreatePos": 0, + "StatementEnd": 295, + "OrReplace": true, + "Name": { + "Database": null, + "Table": { + "Name": "asdf", + "QuoteType": 1, + "NamePos": 23, + "NameEnd": 27 + } + }, + "IfNotExists": false, + "UUID": null, + "OnCluster": null, + "TableSchema": null, + "SubQuery": { + "HasParen": false, + "Select": { + "SelectPos": 31, + "StatementEnd": 295, + "With": null, + "Top": null, + "HasDistinct": false, + "DistinctOn": null, + "SelectItems": [ + { + "Expr": { + "Name": "id", + "QuoteType": 1, + "NamePos": 38, + "NameEnd": 40 + }, + "Modifiers": [], + "Alias": null + }, + { + "Expr": { + "LeftExpr": { + "Name": "price", + "QuoteType": 1, + "NamePos": 49, + "NameEnd": 54 + }, + "Operation": "*", + "RightExpr": { + "NumPos": 57, + "NumEnd": 60, + "Literal": "1.5", + "Base": 10 + }, + "HasGlobal": false, + "HasNot": false + }, + "Modifiers": [], + "Alias": { + "Name": "computed_value", + "QuoteType": 1, + "NamePos": 64, + "NameEnd": 78 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "row_number", + "QuoteType": 1, + "NamePos": 87, + "NameEnd": 97 + }, + "Params": { + "LeftParenPos": 97, + "RightParenPos": 98, + "Items": { + "ListPos": 98, + "ListEnd": 98, + "HasDistinct": false, + "Items": [] + }, + "ColumnArgList": null + } + }, + "OverPos": 100, + "OverExpr": { + "LeftParenPos": 105, + "RightParenPos": 238, + "PartitionBy": { + "PartitionPos": 105, + "Expr": { + "ListPos": 131, + "ListEnd": 139, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "category", + "QuoteType": 1, + "NamePos": 131, + "NameEnd": 139 + }, + "Alias": null + } + ] + } + }, + "OrderBy": { + "OrderPos": 151, + "ListEnd": 170, + "Items": [ + { + "OrderPos": 151, + "Expr": { + "Name": "created_at", + "QuoteType": 1, + "NamePos": 160, + "NameEnd": 170 + }, + "Alias": null, + "Direction": "" + } + ] + }, + "Frame": { + "FramePos": 182, + "Type": "RANGE", + "Extend": { + "Expr": null, + "Between": { + "Number": { + "NumPos": 196, + "NumEnd": 200, + "Literal": "3600", + "Base": 10 + }, + "EndPos": 210, + "Direction": "PRECEDING" + }, + "AndPos": 211, + "And": { + "CurrentPos": 215, + "RowEnd": 239 + } + } + } + } + }, + "Modifiers": [], + "Alias": { + "Name": "rn", + "QuoteType": 1, + "NamePos": 249, + "NameEnd": 251 + } + } + ], + "From": { + "FromPos": 252, + "Expr": { + "Table": { + "TablePos": 257, + "TableEnd": 269, + "Alias": null, + "Expr": { + "Database": null, + "Table": { + "Name": "source_table", + "QuoteType": 1, + "NamePos": 257, + "NameEnd": 269 + } + }, + "HasFinal": false + }, + "StatementEnd": 269, + "SampleRatio": null, + "HasFinal": false + } + }, + "ArrayJoin": null, + "Window": null, + "Prewhere": null, + "Where": { + "WherePos": 270, + "Expr": { + "LeftExpr": { + "Name": "date", + "QuoteType": 1, + "NamePos": 276, + "NameEnd": 280 + }, + "Operation": "\u003e=", + "RightExpr": { + "LiteralPos": 285, + "LiteralEnd": 295, + "Literal": "2023-01-01" + }, + "HasGlobal": false, + "HasNot": false + } + }, + "GroupBy": null, + "WithTotal": false, + "Having": null, + "OrderBy": null, + "LimitBy": null, + "Limit": null, + "Settings": null, + "Format": null, + "UnionAll": null, + "UnionDistinct": null, + "Except": null + } + } + } +] \ No newline at end of file diff --git a/parser/testdata/query/output/select_window_comprehensive.sql.golden.json b/parser/testdata/query/output/select_window_comprehensive.sql.golden.json new file mode 100644 index 0000000..6710e78 --- /dev/null +++ b/parser/testdata/query/output/select_window_comprehensive.sql.golden.json @@ -0,0 +1,2196 @@ +[ + { + "SelectPos": 167, + "StatementEnd": 4194, + "With": null, + "Top": null, + "HasDistinct": false, + "DistinctOn": null, + "SelectItems": [ + { + "Expr": { + "Function": { + "Name": { + "Name": "sum", + "QuoteType": 1, + "NamePos": 200, + "NameEnd": 203 + }, + "Params": { + "LeftParenPos": 203, + "RightParenPos": 205, + "Items": { + "ListPos": 204, + "ListEnd": 205, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 204, + "NameEnd": 205 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "OverPos": 207, + "OverExpr": { + "LeftParenPos": 212, + "RightParenPos": 272, + "PartitionBy": null, + "OrderBy": { + "OrderPos": 213, + "ListEnd": 223, + "Items": [ + { + "OrderPos": 213, + "Expr": { + "Name": "y", + "QuoteType": 1, + "NamePos": 222, + "NameEnd": 223 + }, + "Alias": null, + "Direction": "" + } + ] + }, + "Frame": { + "FramePos": 224, + "Type": "ROWS", + "Extend": { + "Expr": null, + "Between": { + "UnboundedPos": 237, + "UnboundedEnd": 0, + "Direction": "PRECEDING" + }, + "AndPos": 257, + "And": { + "CurrentPos": 261, + "RowEnd": 273 + } + } + } + } + }, + "Modifiers": [], + "Alias": { + "Name": "running_total", + "QuoteType": 1, + "NamePos": 317, + "NameEnd": 330 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "avg", + "QuoteType": 1, + "NamePos": 336, + "NameEnd": 339 + }, + "Params": { + "LeftParenPos": 339, + "RightParenPos": 341, + "Items": { + "ListPos": 340, + "ListEnd": 341, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 340, + "NameEnd": 341 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "OverPos": 351, + "OverExpr": { + "LeftParenPos": 356, + "RightParenPos": 424, + "PartitionBy": { + "PartitionPos": 356, + "Expr": { + "ListPos": 370, + "ListEnd": 371, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "z", + "QuoteType": 1, + "NamePos": 370, + "NameEnd": 371 + }, + "Alias": null + } + ] + } + }, + "OrderBy": { + "OrderPos": 372, + "ListEnd": 382, + "Items": [ + { + "OrderPos": 372, + "Expr": { + "Name": "y", + "QuoteType": 1, + "NamePos": 381, + "NameEnd": 382 + }, + "Alias": null, + "Direction": "" + } + ] + }, + "Frame": { + "FramePos": 383, + "Type": "RANGE", + "Extend": { + "Expr": null, + "Between": { + "Number": { + "NumPos": 397, + "NumEnd": 398, + "Literal": "1", + "Base": 10 + }, + "EndPos": 408, + "Direction": "PRECEDING" + }, + "AndPos": 409, + "And": { + "Number": { + "NumPos": 413, + "NumEnd": 414, + "Literal": "1", + "Base": 10 + }, + "EndPos": 424, + "Direction": "FOLLOWING" + } + } + } + } + }, + "Modifiers": [], + "Alias": { + "Name": "avg_range1", + "QuoteType": 1, + "NamePos": 464, + "NameEnd": 474 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "row_number", + "QuoteType": 1, + "NamePos": 517, + "NameEnd": 527 + }, + "Params": { + "LeftParenPos": 527, + "RightParenPos": 528, + "Items": { + "ListPos": 528, + "ListEnd": 528, + "HasDistinct": false, + "Items": [] + }, + "ColumnArgList": null + } + }, + "OverPos": 530, + "OverExpr": { + "Name": "w1", + "QuoteType": 1, + "NamePos": 535, + "NameEnd": 537 + } + }, + "Modifiers": [], + "Alias": { + "Name": "rn_w1", + "QuoteType": 1, + "NamePos": 634, + "NameEnd": 639 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "rank", + "QuoteType": 1, + "NamePos": 645, + "NameEnd": 649 + }, + "Params": { + "LeftParenPos": 649, + "RightParenPos": 650, + "Items": { + "ListPos": 650, + "ListEnd": 650, + "HasDistinct": false, + "Items": [] + }, + "ColumnArgList": null + } + }, + "OverPos": 652, + "OverExpr": { + "Name": "w1", + "QuoteType": 1, + "NamePos": 657, + "NameEnd": 659 + } + }, + "Modifiers": [], + "Alias": { + "Name": "rank_w1", + "QuoteType": 1, + "NamePos": 762, + "NameEnd": 769 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "sum", + "QuoteType": 1, + "NamePos": 775, + "NameEnd": 778 + }, + "Params": { + "LeftParenPos": 778, + "RightParenPos": 780, + "Items": { + "ListPos": 779, + "ListEnd": 780, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 779, + "NameEnd": 780 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "OverPos": 782, + "OverExpr": { + "Name": "w1", + "QuoteType": 1, + "NamePos": 787, + "NameEnd": 789 + } + }, + "Modifiers": [], + "Alias": { + "Name": "sum_w1", + "QuoteType": 1, + "NamePos": 892, + "NameEnd": 898 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "sum", + "QuoteType": 1, + "NamePos": 953, + "NameEnd": 956 + }, + "Params": { + "LeftParenPos": 956, + "RightParenPos": 958, + "Items": { + "ListPos": 957, + "ListEnd": 958, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 957, + "NameEnd": 958 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "OverPos": 960, + "OverExpr": { + "LeftParenPos": 965, + "RightParenPos": 983, + "PartitionBy": null, + "OrderBy": null, + "Frame": { + "FramePos": 966, + "Type": "ROWS", + "Extend": { + "Number": { + "NumPos": 971, + "NumEnd": 973, + "Literal": "10", + "Base": 10 + }, + "EndPos": 983, + "Direction": "PRECEDING" + } + } + } + }, + "Modifiers": [], + "Alias": { + "Name": "rows_10_preceding", + "QuoteType": 1, + "NamePos": 1070, + "NameEnd": 1087 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "sum", + "QuoteType": 1, + "NamePos": 1093, + "NameEnd": 1096 + }, + "Params": { + "LeftParenPos": 1096, + "RightParenPos": 1098, + "Items": { + "ListPos": 1097, + "ListEnd": 1098, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 1097, + "NameEnd": 1098 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "OverPos": 1100, + "OverExpr": { + "LeftParenPos": 1105, + "RightParenPos": 1154, + "PartitionBy": null, + "OrderBy": null, + "Frame": { + "FramePos": 1106, + "Type": "ROWS", + "Extend": { + "Expr": null, + "Between": { + "CurrentPos": 1119, + "RowEnd": 1134 + }, + "AndPos": 1131, + "And": { + "UnboundedPos": 1135, + "UnboundedEnd": 0, + "Direction": "FOLLOWING" + } + } + } + } + }, + "Modifiers": [], + "Alias": { + "Name": "rows_cur_to_unbounded_following", + "QuoteType": 1, + "NamePos": 1210, + "NameEnd": 1241 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "sum", + "QuoteType": 1, + "NamePos": 1247, + "NameEnd": 1250 + }, + "Params": { + "LeftParenPos": 1250, + "RightParenPos": 1252, + "Items": { + "ListPos": 1251, + "ListEnd": 1252, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 1251, + "NameEnd": 1252 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "OverPos": 1254, + "OverExpr": { + "LeftParenPos": 1259, + "RightParenPos": 1300, + "PartitionBy": null, + "OrderBy": null, + "Frame": { + "FramePos": 1260, + "Type": "ROWS", + "Extend": { + "Expr": null, + "Between": { + "Number": { + "NumPos": 1273, + "NumEnd": 1274, + "Literal": "5", + "Base": 10 + }, + "EndPos": 1284, + "Direction": "PRECEDING" + }, + "AndPos": 1285, + "And": { + "Number": { + "NumPos": 1289, + "NumEnd": 1290, + "Literal": "3", + "Base": 10 + }, + "EndPos": 1300, + "Direction": "FOLLOWING" + } + } + } + } + }, + "Modifiers": [], + "Alias": { + "Name": "rows_5p_3f", + "QuoteType": 1, + "NamePos": 1364, + "NameEnd": 1374 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "sum", + "QuoteType": 1, + "NamePos": 1380, + "NameEnd": 1383 + }, + "Params": { + "LeftParenPos": 1383, + "RightParenPos": 1385, + "Items": { + "ListPos": 1384, + "ListEnd": 1385, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 1384, + "NameEnd": 1385 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "OverPos": 1387, + "OverExpr": { + "LeftParenPos": 1392, + "RightParenPos": 1435, + "PartitionBy": null, + "OrderBy": null, + "Frame": { + "FramePos": 1393, + "Type": "RANGE", + "Extend": { + "Expr": null, + "Between": { + "Number": { + "NumPos": 1407, + "NumEnd": 1409, + "Literal": "10", + "Base": 10 + }, + "EndPos": 1419, + "Direction": "PRECEDING" + }, + "AndPos": 1420, + "And": { + "CurrentPos": 1424, + "RowEnd": 1436 + } + } + } + } + }, + "Modifiers": [], + "Alias": { + "Name": "range_10p_cur", + "QuoteType": 1, + "NamePos": 1497, + "NameEnd": 1510 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "sum", + "QuoteType": 1, + "NamePos": 1516, + "NameEnd": 1519 + }, + "Params": { + "LeftParenPos": 1519, + "RightParenPos": 1521, + "Items": { + "ListPos": 1520, + "ListEnd": 1521, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 1520, + "NameEnd": 1521 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "OverPos": 1523, + "OverExpr": { + "LeftParenPos": 1528, + "RightParenPos": 1578, + "PartitionBy": null, + "OrderBy": null, + "Frame": { + "FramePos": 1529, + "Type": "RANGE", + "Extend": { + "Expr": null, + "Between": { + "UnboundedPos": 1543, + "UnboundedEnd": 0, + "Direction": "PRECEDING" + }, + "AndPos": 1563, + "And": { + "CurrentPos": 1567, + "RowEnd": 1579 + } + } + } + } + }, + "Modifiers": [], + "Alias": { + "Name": "range_unbounded_to_cur", + "QuoteType": 1, + "NamePos": 1633, + "NameEnd": 1655 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "row_number", + "QuoteType": 1, + "NamePos": 1690, + "NameEnd": 1700 + }, + "Params": { + "LeftParenPos": 1700, + "RightParenPos": 1701, + "Items": { + "ListPos": 1701, + "ListEnd": 1701, + "HasDistinct": false, + "Items": [] + }, + "ColumnArgList": null + } + }, + "OverPos": 1703, + "OverExpr": { + "LeftParenPos": 1708, + "RightParenPos": 1734, + "PartitionBy": { + "PartitionPos": 1708, + "Expr": { + "ListPos": 1722, + "ListEnd": 1723, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "y", + "QuoteType": 1, + "NamePos": 1722, + "NameEnd": 1723 + }, + "Alias": null + } + ] + } + }, + "OrderBy": { + "OrderPos": 1724, + "ListEnd": 1734, + "Items": [ + { + "OrderPos": 1724, + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 1733, + "NameEnd": 1734 + }, + "Alias": null, + "Direction": "" + } + ] + }, + "Frame": null + } + }, + "Modifiers": [], + "Alias": { + "Name": "row_num", + "QuoteType": 1, + "NamePos": 1807, + "NameEnd": 1814 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "rank", + "QuoteType": 1, + "NamePos": 1820, + "NameEnd": 1824 + }, + "Params": { + "LeftParenPos": 1824, + "RightParenPos": 1825, + "Items": { + "ListPos": 1825, + "ListEnd": 1825, + "HasDistinct": false, + "Items": [] + }, + "ColumnArgList": null + } + }, + "OverPos": 1827, + "OverExpr": { + "LeftParenPos": 1832, + "RightParenPos": 1858, + "PartitionBy": { + "PartitionPos": 1832, + "Expr": { + "ListPos": 1846, + "ListEnd": 1847, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "y", + "QuoteType": 1, + "NamePos": 1846, + "NameEnd": 1847 + }, + "Alias": null + } + ] + } + }, + "OrderBy": { + "OrderPos": 1848, + "ListEnd": 1858, + "Items": [ + { + "OrderPos": 1848, + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 1857, + "NameEnd": 1858 + }, + "Alias": null, + "Direction": "" + } + ] + }, + "Frame": null + } + }, + "Modifiers": [], + "Alias": { + "Name": "rank_val", + "QuoteType": 1, + "NamePos": 1937, + "NameEnd": 1945 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "dense_rank", + "QuoteType": 1, + "NamePos": 1951, + "NameEnd": 1961 + }, + "Params": { + "LeftParenPos": 1961, + "RightParenPos": 1962, + "Items": { + "ListPos": 1962, + "ListEnd": 1962, + "HasDistinct": false, + "Items": [] + }, + "ColumnArgList": null + } + }, + "OverPos": 1964, + "OverExpr": { + "LeftParenPos": 1969, + "RightParenPos": 1995, + "PartitionBy": { + "PartitionPos": 1969, + "Expr": { + "ListPos": 1983, + "ListEnd": 1984, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "y", + "QuoteType": 1, + "NamePos": 1983, + "NameEnd": 1984 + }, + "Alias": null + } + ] + } + }, + "OrderBy": { + "OrderPos": 1985, + "ListEnd": 1995, + "Items": [ + { + "OrderPos": 1985, + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 1994, + "NameEnd": 1995 + }, + "Alias": null, + "Direction": "" + } + ] + }, + "Frame": null + } + }, + "Modifiers": [], + "Alias": { + "Name": "dense_rank_val", + "QuoteType": 1, + "NamePos": 2068, + "NameEnd": 2082 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "first_value", + "QuoteType": 1, + "NamePos": 2088, + "NameEnd": 2099 + }, + "Params": { + "LeftParenPos": 2099, + "RightParenPos": 2101, + "Items": { + "ListPos": 2100, + "ListEnd": 2101, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 2100, + "NameEnd": 2101 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "OverPos": 2119, + "OverExpr": { + "LeftParenPos": 2124, + "RightParenPos": 2207, + "PartitionBy": { + "PartitionPos": 2124, + "Expr": { + "ListPos": 2138, + "ListEnd": 2139, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "y", + "QuoteType": 1, + "NamePos": 2138, + "NameEnd": 2139 + }, + "Alias": null + } + ] + } + }, + "OrderBy": { + "OrderPos": 2140, + "ListEnd": 2150, + "Items": [ + { + "OrderPos": 2140, + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 2149, + "NameEnd": 2150 + }, + "Alias": null, + "Direction": "" + } + ] + }, + "Frame": { + "FramePos": 2151, + "Type": "ROWS", + "Extend": { + "Expr": null, + "Between": { + "UnboundedPos": 2164, + "UnboundedEnd": 0, + "Direction": "PRECEDING" + }, + "AndPos": 2184, + "And": { + "UnboundedPos": 2188, + "UnboundedEnd": 0, + "Direction": "FOLLOWING" + } + } + } + } + }, + "Modifiers": [], + "Alias": { + "Name": "first_val", + "QuoteType": 1, + "NamePos": 2224, + "NameEnd": 2233 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "last_value", + "QuoteType": 1, + "NamePos": 2239, + "NameEnd": 2249 + }, + "Params": { + "LeftParenPos": 2249, + "RightParenPos": 2251, + "Items": { + "ListPos": 2250, + "ListEnd": 2251, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 2250, + "NameEnd": 2251 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "OverPos": 2268, + "OverExpr": { + "LeftParenPos": 2273, + "RightParenPos": 2356, + "PartitionBy": { + "PartitionPos": 2273, + "Expr": { + "ListPos": 2287, + "ListEnd": 2288, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "y", + "QuoteType": 1, + "NamePos": 2287, + "NameEnd": 2288 + }, + "Alias": null + } + ] + } + }, + "OrderBy": { + "OrderPos": 2289, + "ListEnd": 2299, + "Items": [ + { + "OrderPos": 2289, + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 2298, + "NameEnd": 2299 + }, + "Alias": null, + "Direction": "" + } + ] + }, + "Frame": { + "FramePos": 2300, + "Type": "ROWS", + "Extend": { + "Expr": null, + "Between": { + "UnboundedPos": 2313, + "UnboundedEnd": 0, + "Direction": "PRECEDING" + }, + "AndPos": 2333, + "And": { + "UnboundedPos": 2337, + "UnboundedEnd": 0, + "Direction": "FOLLOWING" + } + } + } + } + }, + "Modifiers": [], + "Alias": { + "Name": "last_val", + "QuoteType": 1, + "NamePos": 2374, + "NameEnd": 2382 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "lag", + "QuoteType": 1, + "NamePos": 2388, + "NameEnd": 2391 + }, + "Params": { + "LeftParenPos": 2391, + "RightParenPos": 2396, + "Items": { + "ListPos": 2392, + "ListEnd": 2396, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 2392, + "NameEnd": 2393 + }, + "Alias": null + }, + { + "Expr": { + "NumPos": 2395, + "NumEnd": 2396, + "Literal": "1", + "Base": 10 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "OverPos": 2398, + "OverExpr": { + "LeftParenPos": 2403, + "RightParenPos": 2429, + "PartitionBy": { + "PartitionPos": 2403, + "Expr": { + "ListPos": 2417, + "ListEnd": 2418, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "y", + "QuoteType": 1, + "NamePos": 2417, + "NameEnd": 2418 + }, + "Alias": null + } + ] + } + }, + "OrderBy": { + "OrderPos": 2419, + "ListEnd": 2429, + "Items": [ + { + "OrderPos": 2419, + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 2428, + "NameEnd": 2429 + }, + "Alias": null, + "Direction": "" + } + ] + }, + "Frame": null + } + }, + "Modifiers": [], + "Alias": { + "Name": "prev_x", + "QuoteType": 1, + "NamePos": 2505, + "NameEnd": 2511 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "lead", + "QuoteType": 1, + "NamePos": 2517, + "NameEnd": 2521 + }, + "Params": { + "LeftParenPos": 2521, + "RightParenPos": 2526, + "Items": { + "ListPos": 2522, + "ListEnd": 2526, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 2522, + "NameEnd": 2523 + }, + "Alias": null + }, + { + "Expr": { + "NumPos": 2525, + "NumEnd": 2526, + "Literal": "1", + "Base": 10 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "OverPos": 2528, + "OverExpr": { + "LeftParenPos": 2533, + "RightParenPos": 2559, + "PartitionBy": { + "PartitionPos": 2533, + "Expr": { + "ListPos": 2547, + "ListEnd": 2548, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "y", + "QuoteType": 1, + "NamePos": 2547, + "NameEnd": 2548 + }, + "Alias": null + } + ] + } + }, + "OrderBy": { + "OrderPos": 2549, + "ListEnd": 2559, + "Items": [ + { + "OrderPos": 2549, + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 2558, + "NameEnd": 2559 + }, + "Alias": null, + "Direction": "" + } + ] + }, + "Frame": null + } + }, + "Modifiers": [], + "Alias": { + "Name": "next_x", + "QuoteType": 1, + "NamePos": 2634, + "NameEnd": 2640 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "percent_rank", + "QuoteType": 1, + "NamePos": 2646, + "NameEnd": 2658 + }, + "Params": { + "LeftParenPos": 2658, + "RightParenPos": 2659, + "Items": { + "ListPos": 2659, + "ListEnd": 2659, + "HasDistinct": false, + "Items": [] + }, + "ColumnArgList": null + } + }, + "OverPos": 2661, + "OverExpr": { + "LeftParenPos": 2666, + "RightParenPos": 2692, + "PartitionBy": { + "PartitionPos": 2666, + "Expr": { + "ListPos": 2680, + "ListEnd": 2681, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "y", + "QuoteType": 1, + "NamePos": 2680, + "NameEnd": 2681 + }, + "Alias": null + } + ] + } + }, + "OrderBy": { + "OrderPos": 2682, + "ListEnd": 2692, + "Items": [ + { + "OrderPos": 2682, + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 2691, + "NameEnd": 2692 + }, + "Alias": null, + "Direction": "" + } + ] + }, + "Frame": null + } + }, + "Modifiers": [], + "Alias": { + "Name": "pct_rank", + "QuoteType": 1, + "NamePos": 2763, + "NameEnd": 2771 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "sum", + "QuoteType": 1, + "NamePos": 2836, + "NameEnd": 2839 + }, + "Params": { + "LeftParenPos": 2839, + "RightParenPos": 2841, + "Items": { + "ListPos": 2840, + "ListEnd": 2841, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 2840, + "NameEnd": 2841 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "OverPos": 2843, + "OverExpr": { + "Name": "w", + "QuoteType": 1, + "NamePos": 2848, + "NameEnd": 2849 + } + }, + "Modifiers": [], + "Alias": { + "Name": "sum_over_w", + "QuoteType": 1, + "NamePos": 2953, + "NameEnd": 2963 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "avg", + "QuoteType": 1, + "NamePos": 2969, + "NameEnd": 2972 + }, + "Params": { + "LeftParenPos": 2972, + "RightParenPos": 2974, + "Items": { + "ListPos": 2973, + "ListEnd": 2974, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 2973, + "NameEnd": 2974 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "OverPos": 2976, + "OverExpr": { + "Name": "w", + "QuoteType": 1, + "NamePos": 2981, + "NameEnd": 2982 + } + }, + "Modifiers": [], + "Alias": { + "Name": "avg_over_w", + "QuoteType": 1, + "NamePos": 3086, + "NameEnd": 3096 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "row_number", + "QuoteType": 1, + "NamePos": 3102, + "NameEnd": 3112 + }, + "Params": { + "LeftParenPos": 3112, + "RightParenPos": 3113, + "Items": { + "ListPos": 3113, + "ListEnd": 3113, + "HasDistinct": false, + "Items": [] + }, + "ColumnArgList": null + } + }, + "OverPos": 3115, + "OverExpr": { + "Name": "w", + "QuoteType": 1, + "NamePos": 3120, + "NameEnd": 3121 + } + }, + "Modifiers": [], + "Alias": { + "Name": "rn_over_w", + "QuoteType": 1, + "NamePos": 3219, + "NameEnd": 3228 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "count", + "QuoteType": 1, + "NamePos": 3286, + "NameEnd": 3291 + }, + "Params": { + "LeftParenPos": 3291, + "RightParenPos": 3293, + "Items": { + "ListPos": 3292, + "ListEnd": 3292, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "*", + "QuoteType": 0, + "NamePos": 3292, + "NameEnd": 3292 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "OverPos": 3295, + "OverExpr": { + "LeftParenPos": 3300, + "RightParenPos": 3355, + "PartitionBy": { + "PartitionPos": 3300, + "Expr": { + "ListPos": 3314, + "ListEnd": 3330, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "col1", + "QuoteType": 1, + "NamePos": 3314, + "NameEnd": 3318 + }, + "Alias": null + }, + { + "Expr": { + "Name": "col2", + "QuoteType": 1, + "NamePos": 3320, + "NameEnd": 3324 + }, + "Alias": null + }, + { + "Expr": { + "Name": "col3", + "QuoteType": 1, + "NamePos": 3326, + "NameEnd": 3330 + }, + "Alias": null + } + ] + } + }, + "OrderBy": { + "OrderPos": 3331, + "ListEnd": 3350, + "Items": [ + { + "OrderPos": 3331, + "Expr": { + "Name": "col4", + "QuoteType": 1, + "NamePos": 3340, + "NameEnd": 3344 + }, + "Alias": null, + "Direction": "" + }, + { + "OrderPos": 3331, + "Expr": { + "Name": "col5", + "QuoteType": 1, + "NamePos": 3346, + "NameEnd": 3350 + }, + "Alias": null, + "Direction": "DESC" + } + ] + }, + "Frame": null + } + }, + "Modifiers": [], + "Alias": { + "Name": "cnt_multi", + "QuoteType": 1, + "NamePos": 3403, + "NameEnd": 3412 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "sum", + "QuoteType": 1, + "NamePos": 3418, + "NameEnd": 3421 + }, + "Params": { + "LeftParenPos": 3421, + "RightParenPos": 3425, + "Items": { + "ListPos": 3422, + "ListEnd": 3425, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "val", + "QuoteType": 1, + "NamePos": 3422, + "NameEnd": 3425 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "OverPos": 3435, + "OverExpr": { + "LeftParenPos": 3440, + "RightParenPos": 3533, + "PartitionBy": { + "PartitionPos": 3440, + "Expr": { + "ListPos": 3454, + "ListEnd": 3464, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "col1", + "QuoteType": 1, + "NamePos": 3454, + "NameEnd": 3458 + }, + "Alias": null + }, + { + "Expr": { + "Name": "col2", + "QuoteType": 1, + "NamePos": 3460, + "NameEnd": 3464 + }, + "Alias": null + } + ] + } + }, + "OrderBy": { + "OrderPos": 3465, + "ListEnd": 3484, + "Items": [ + { + "OrderPos": 3465, + "Expr": { + "Name": "col4", + "QuoteType": 1, + "NamePos": 3474, + "NameEnd": 3478 + }, + "Alias": null, + "Direction": "" + }, + { + "OrderPos": 3465, + "Expr": { + "Name": "col5", + "QuoteType": 1, + "NamePos": 3480, + "NameEnd": 3484 + }, + "Alias": null, + "Direction": "" + } + ] + }, + "Frame": { + "FramePos": 3485, + "Type": "ROWS", + "Extend": { + "Expr": null, + "Between": { + "UnboundedPos": 3498, + "UnboundedEnd": 0, + "Direction": "PRECEDING" + }, + "AndPos": 3518, + "And": { + "CurrentPos": 3522, + "RowEnd": 3534 + } + } + } + } + }, + "Modifiers": [], + "Alias": { + "Name": "total_multi", + "QuoteType": 1, + "NamePos": 3548, + "NameEnd": 3559 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "sum", + "QuoteType": 1, + "NamePos": 3604, + "NameEnd": 3607 + }, + "Params": { + "LeftParenPos": 3607, + "RightParenPos": 3614, + "Items": { + "ListPos": 3608, + "ListEnd": 3614, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "amount", + "QuoteType": 1, + "NamePos": 3608, + "NameEnd": 3614 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "OverPos": 3624, + "OverExpr": { + "LeftParenPos": 3629, + "RightParenPos": 3732, + "PartitionBy": { + "PartitionPos": 3629, + "Expr": { + "ListPos": 3643, + "ListEnd": 3670, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": { + "Name": "date_trunc", + "QuoteType": 1, + "NamePos": 3643, + "NameEnd": 3653 + }, + "Params": { + "LeftParenPos": 3653, + "RightParenPos": 3670, + "Items": { + "ListPos": 3655, + "ListEnd": 3670, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "LiteralPos": 3655, + "LiteralEnd": 3658, + "Literal": "day" + }, + "Alias": null + }, + { + "Expr": { + "Name": "timestamp", + "QuoteType": 1, + "NamePos": 3661, + "NameEnd": 3670 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "Alias": null + } + ] + } + }, + "OrderBy": { + "OrderPos": 3672, + "ListEnd": 3690, + "Items": [ + { + "OrderPos": 3672, + "Expr": { + "Name": "timestamp", + "QuoteType": 1, + "NamePos": 3681, + "NameEnd": 3690 + }, + "Alias": null, + "Direction": "" + } + ] + }, + "Frame": { + "FramePos": 3691, + "Type": "ROWS", + "Extend": { + "Expr": null, + "Between": { + "Number": { + "NumPos": 3704, + "NumEnd": 3706, + "Literal": "10", + "Base": 10 + }, + "EndPos": 3716, + "Direction": "PRECEDING" + }, + "AndPos": 3717, + "And": { + "CurrentPos": 3721, + "RowEnd": 3733 + } + } + } + } + }, + "Modifiers": [], + "Alias": { + "Name": "daily_total", + "QuoteType": 1, + "NamePos": 3737, + "NameEnd": 3748 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "avg", + "QuoteType": 1, + "NamePos": 3754, + "NameEnd": 3757 + }, + "Params": { + "LeftParenPos": 3757, + "RightParenPos": 3764, + "Items": { + "ListPos": 3758, + "ListEnd": 3764, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "amount", + "QuoteType": 1, + "NamePos": 3758, + "NameEnd": 3764 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "OverPos": 3774, + "OverExpr": { + "LeftParenPos": 3779, + "RightParenPos": 3859, + "PartitionBy": null, + "OrderBy": { + "OrderPos": 3780, + "ListEnd": 3816, + "Items": [ + { + "OrderPos": 3780, + "Expr": { + "ExtractPos": 3780, + "Interval": { + "Name": "HOUR", + "QuoteType": 1, + "NamePos": 3797, + "NameEnd": 3801 + }, + "FromPos": 3802, + "FromExpr": { + "Name": "timestamp", + "QuoteType": 1, + "NamePos": 3807, + "NameEnd": 3816 + } + }, + "Alias": null, + "Direction": "" + } + ] + }, + "Frame": { + "FramePos": 3818, + "Type": "RANGE", + "Extend": { + "Expr": null, + "Between": { + "Number": { + "NumPos": 3832, + "NumEnd": 3833, + "Literal": "1", + "Base": 10 + }, + "EndPos": 3843, + "Direction": "PRECEDING" + }, + "AndPos": 3844, + "And": { + "Number": { + "NumPos": 3848, + "NumEnd": 3849, + "Literal": "1", + "Base": 10 + }, + "EndPos": 3859, + "Direction": "FOLLOWING" + } + } + } + } + }, + "Modifiers": [], + "Alias": { + "Name": "hourly_avg", + "QuoteType": 1, + "NamePos": 3887, + "NameEnd": 3897 + } + } + ], + "From": { + "FromPos": 3898, + "Expr": { + "Table": { + "TablePos": 3903, + "TableEnd": 3904, + "Alias": null, + "Expr": { + "Database": null, + "Table": { + "Name": "t", + "QuoteType": 1, + "NamePos": 3903, + "NameEnd": 3904 + } + }, + "HasFinal": false + }, + "StatementEnd": 3904, + "SampleRatio": null, + "HasFinal": false + } + }, + "ArrayJoin": null, + "Window": { + "WindowPos": 3905, + "EndPos": 4194, + "Windows": [ + { + "Name": { + "Name": "w", + "QuoteType": 1, + "NamePos": 3912, + "NameEnd": 3913 + }, + "AsPos": 3914, + "Expr": { + "LeftParenPos": 3917, + "RightParenPos": 3928, + "PartitionBy": null, + "OrderBy": { + "OrderPos": 3918, + "ListEnd": 3928, + "Items": [ + { + "OrderPos": 3918, + "Expr": { + "Name": "y", + "QuoteType": 1, + "NamePos": 3927, + "NameEnd": 3928 + }, + "Alias": null, + "Direction": "" + } + ] + }, + "Frame": null + } + }, + { + "Name": { + "Name": "w1", + "QuoteType": 1, + "NamePos": 3938, + "NameEnd": 3940 + }, + "AsPos": 3941, + "Expr": { + "LeftParenPos": 3944, + "RightParenPos": 4019, + "PartitionBy": { + "PartitionPos": 3944, + "Expr": { + "ListPos": 3958, + "ListEnd": 3959, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "y", + "QuoteType": 1, + "NamePos": 3958, + "NameEnd": 3959 + }, + "Alias": null + } + ] + } + }, + "OrderBy": { + "OrderPos": 3960, + "ListEnd": 3970, + "Items": [ + { + "OrderPos": 3960, + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 3969, + "NameEnd": 3970 + }, + "Alias": null, + "Direction": "" + } + ] + }, + "Frame": { + "FramePos": 3971, + "Type": "ROWS", + "Extend": { + "Expr": null, + "Between": { + "UnboundedPos": 3984, + "UnboundedEnd": 0, + "Direction": "PRECEDING" + }, + "AndPos": 4004, + "And": { + "CurrentPos": 4008, + "RowEnd": 4020 + } + } + } + } + }, + { + "Name": { + "Name": "w4", + "QuoteType": 1, + "NamePos": 4029, + "NameEnd": 4031 + }, + "AsPos": 4032, + "Expr": { + "LeftParenPos": 4035, + "RightParenPos": 4102, + "PartitionBy": { + "PartitionPos": 4035, + "Expr": { + "ListPos": 4049, + "ListEnd": 4050, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "y", + "QuoteType": 1, + "NamePos": 4049, + "NameEnd": 4050 + }, + "Alias": null + } + ] + } + }, + "OrderBy": { + "OrderPos": 4051, + "ListEnd": 4061, + "Items": [ + { + "OrderPos": 4051, + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 4060, + "NameEnd": 4061 + }, + "Alias": null, + "Direction": "" + } + ] + }, + "Frame": { + "FramePos": 4062, + "Type": "ROWS", + "Extend": { + "Expr": null, + "Between": { + "Number": { + "NumPos": 4075, + "NumEnd": 4076, + "Literal": "3", + "Base": 10 + }, + "EndPos": 4086, + "Direction": "PRECEDING" + }, + "AndPos": 4087, + "And": { + "CurrentPos": 4091, + "RowEnd": 4103 + } + } + } + } + }, + { + "Name": { + "Name": "w5", + "QuoteType": 1, + "NamePos": 4112, + "NameEnd": 4114 + }, + "AsPos": 4115, + "Expr": { + "LeftParenPos": 4118, + "RightParenPos": 4194, + "PartitionBy": { + "PartitionPos": 4118, + "Expr": { + "ListPos": 4132, + "ListEnd": 4133, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "z", + "QuoteType": 1, + "NamePos": 4132, + "NameEnd": 4133 + }, + "Alias": null + } + ] + } + }, + "OrderBy": { + "OrderPos": 4134, + "ListEnd": 4144, + "Items": [ + { + "OrderPos": 4134, + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 4143, + "NameEnd": 4144 + }, + "Alias": null, + "Direction": "" + } + ] + }, + "Frame": { + "FramePos": 4145, + "Type": "RANGE", + "Extend": { + "Expr": null, + "Between": { + "UnboundedPos": 4159, + "UnboundedEnd": 0, + "Direction": "PRECEDING" + }, + "AndPos": 4179, + "And": { + "CurrentPos": 4183, + "RowEnd": 4195 + } + } + } + } + } + ] + }, + "Prewhere": null, + "Where": null, + "GroupBy": null, + "WithTotal": false, + "Having": null, + "OrderBy": null, + "LimitBy": null, + "Limit": null, + "Settings": null, + "Format": null, + "UnionAll": null, + "UnionDistinct": null, + "Except": null + } +] \ No newline at end of file diff --git a/parser/testdata/query/output/select_window_cte.sql.golden.json b/parser/testdata/query/output/select_window_cte.sql.golden.json new file mode 100644 index 0000000..08d06b5 --- /dev/null +++ b/parser/testdata/query/output/select_window_cte.sql.golden.json @@ -0,0 +1,605 @@ +[ + { + "SelectPos": 0, + "StatementEnd": 746, + "With": { + "WithPos": 0, + "EndPos": 249, + "CTEs": [ + { + "CTEPos": 9, + "Expr": { + "Name": "monthly", + "QuoteType": 1, + "NamePos": 9, + "NameEnd": 16 + }, + "Alias": { + "SelectPos": 30, + "StatementEnd": 236, + "With": null, + "Top": null, + "HasDistinct": false, + "DistinctOn": null, + "SelectItems": [ + { + "Expr": { + "Name": { + "Name": "toStartOfMonth", + "QuoteType": 1, + "NamePos": 37, + "NameEnd": 51 + }, + "Params": { + "LeftParenPos": 51, + "RightParenPos": 56, + "Items": { + "ListPos": 52, + "ListEnd": 56, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "date", + "QuoteType": 1, + "NamePos": 52, + "NameEnd": 56 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "Modifiers": [], + "Alias": { + "Name": "month", + "QuoteType": 1, + "NamePos": 61, + "NameEnd": 66 + } + }, + { + "Expr": { + "Name": "department", + "QuoteType": 1, + "NamePos": 83, + "NameEnd": 93 + }, + "Modifiers": [], + "Alias": null + }, + { + "Expr": { + "Name": { + "Name": "avg", + "QuoteType": 1, + "NamePos": 110, + "NameEnd": 113 + }, + "Params": { + "LeftParenPos": 113, + "RightParenPos": 120, + "Items": { + "ListPos": 114, + "ListEnd": 120, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "salary", + "QuoteType": 1, + "NamePos": 114, + "NameEnd": 120 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "Modifiers": [], + "Alias": { + "Name": "avg_salary", + "QuoteType": 1, + "NamePos": 134, + "NameEnd": 144 + } + } + ], + "From": { + "FromPos": 153, + "Expr": { + "Table": { + "TablePos": 158, + "TableEnd": 170, + "Alias": null, + "Expr": { + "Database": null, + "Table": { + "Name": "salary_table", + "QuoteType": 1, + "NamePos": 158, + "NameEnd": 170 + } + }, + "HasFinal": false + }, + "StatementEnd": 170, + "SampleRatio": null, + "HasFinal": false + } + }, + "ArrayJoin": null, + "Window": null, + "Prewhere": null, + "Where": { + "WherePos": 179, + "Expr": { + "LeftExpr": { + "Name": "year", + "QuoteType": 1, + "NamePos": 185, + "NameEnd": 189 + }, + "Operation": "=", + "RightExpr": { + "NumPos": 192, + "NumEnd": 196, + "Literal": "2023", + "Base": 10 + }, + "HasGlobal": false, + "HasNot": false + } + }, + "GroupBy": { + "GroupByPos": 205, + "GroupByEnd": 236, + "AggregateType": "", + "Expr": { + "ListPos": 214, + "ListEnd": 231, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "month", + "QuoteType": 1, + "NamePos": 214, + "NameEnd": 219 + }, + "Alias": null + }, + { + "Expr": { + "Name": "department", + "QuoteType": 1, + "NamePos": 221, + "NameEnd": 231 + }, + "Alias": null + } + ] + }, + "WithCube": false, + "WithRollup": false, + "WithTotals": false + }, + "WithTotal": false, + "Having": null, + "OrderBy": null, + "LimitBy": null, + "Limit": null, + "Settings": null, + "Format": null, + "UnionAll": null, + "UnionDistinct": null, + "Except": null + } + }, + { + "CTEPos": 243, + "Expr": { + "Name": "ranked", + "QuoteType": 1, + "NamePos": 243, + "NameEnd": 249 + }, + "Alias": { + "SelectPos": 263, + "StatementEnd": 448, + "With": null, + "Top": null, + "HasDistinct": false, + "DistinctOn": null, + "SelectItems": [ + { + "Expr": { + "Name": "month", + "QuoteType": 1, + "NamePos": 270, + "NameEnd": 275 + }, + "Modifiers": [], + "Alias": null + }, + { + "Expr": { + "Name": "department", + "QuoteType": 1, + "NamePos": 292, + "NameEnd": 302 + }, + "Modifiers": [], + "Alias": null + }, + { + "Expr": { + "Name": "avg_salary", + "QuoteType": 1, + "NamePos": 319, + "NameEnd": 329 + }, + "Modifiers": [], + "Alias": null + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "row_number", + "QuoteType": 1, + "NamePos": 346, + "NameEnd": 356 + }, + "Params": { + "LeftParenPos": 356, + "RightParenPos": 357, + "Items": { + "ListPos": 357, + "ListEnd": 357, + "HasDistinct": false, + "Items": [] + }, + "ColumnArgList": null + } + }, + "OverPos": 359, + "OverExpr": { + "LeftParenPos": 364, + "RightParenPos": 413, + "PartitionBy": { + "PartitionPos": 364, + "Expr": { + "ListPos": 378, + "ListEnd": 388, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "department", + "QuoteType": 1, + "NamePos": 378, + "NameEnd": 388 + }, + "Alias": null + } + ] + } + }, + "OrderBy": { + "OrderPos": 389, + "ListEnd": 408, + "Items": [ + { + "OrderPos": 389, + "Expr": { + "Name": "avg_salary", + "QuoteType": 1, + "NamePos": 398, + "NameEnd": 408 + }, + "Alias": null, + "Direction": "DESC" + } + ] + }, + "Frame": null + } + }, + "Modifiers": [], + "Alias": { + "Name": "dept_rank", + "QuoteType": 1, + "NamePos": 418, + "NameEnd": 427 + } + } + ], + "From": { + "FromPos": 436, + "Expr": { + "Table": { + "TablePos": 441, + "TableEnd": 448, + "Alias": null, + "Expr": { + "Database": null, + "Table": { + "Name": "monthly", + "QuoteType": 1, + "NamePos": 441, + "NameEnd": 448 + } + }, + "HasFinal": false + }, + "StatementEnd": 448, + "SampleRatio": null, + "HasFinal": false + } + }, + "ArrayJoin": null, + "Window": null, + "Prewhere": null, + "Where": null, + "GroupBy": null, + "WithTotal": false, + "Having": null, + "OrderBy": null, + "LimitBy": null, + "Limit": null, + "Settings": null, + "Format": null, + "UnionAll": null, + "UnionDistinct": null, + "Except": null + } + } + ] + }, + "Top": null, + "HasDistinct": false, + "DistinctOn": null, + "SelectItems": [ + { + "Expr": { + "Name": "month", + "QuoteType": 1, + "NamePos": 462, + "NameEnd": 467 + }, + "Modifiers": [], + "Alias": null + }, + { + "Expr": { + "Name": "department", + "QuoteType": 1, + "NamePos": 476, + "NameEnd": 486 + }, + "Modifiers": [], + "Alias": null + }, + { + "Expr": { + "Name": "avg_salary", + "QuoteType": 1, + "NamePos": 495, + "NameEnd": 505 + }, + "Modifiers": [], + "Alias": null + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "lag", + "QuoteType": 1, + "NamePos": 514, + "NameEnd": 517 + }, + "Params": { + "LeftParenPos": 517, + "RightParenPos": 534, + "Items": { + "ListPos": 518, + "ListEnd": 534, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "avg_salary", + "QuoteType": 1, + "NamePos": 518, + "NameEnd": 528 + }, + "Alias": null + }, + { + "Expr": { + "NumPos": 530, + "NumEnd": 531, + "Literal": "1", + "Base": 10 + }, + "Alias": null + }, + { + "Expr": { + "NumPos": 533, + "NumEnd": 534, + "Literal": "0", + "Base": 10 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "OverPos": 536, + "OverExpr": { + "LeftParenPos": 541, + "RightParenPos": 667, + "PartitionBy": { + "PartitionPos": 541, + "Expr": { + "ListPos": 567, + "ListEnd": 577, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "department", + "QuoteType": 1, + "NamePos": 567, + "NameEnd": 577 + }, + "Alias": null + } + ] + } + }, + "OrderBy": { + "OrderPos": 589, + "ListEnd": 603, + "Items": [ + { + "OrderPos": 589, + "Expr": { + "Name": "month", + "QuoteType": 1, + "NamePos": 598, + "NameEnd": 603 + }, + "Alias": null, + "Direction": "" + } + ] + }, + "Frame": { + "FramePos": 615, + "Type": "ROWS", + "Extend": { + "Expr": null, + "Between": { + "Number": { + "NumPos": 628, + "NumEnd": 629, + "Literal": "1", + "Base": 10 + }, + "EndPos": 639, + "Direction": "PRECEDING" + }, + "AndPos": 640, + "And": { + "CurrentPos": 644, + "RowEnd": 668 + } + } + } + } + }, + "Modifiers": [], + "Alias": { + "Name": "prev_month_avg", + "QuoteType": 1, + "NamePos": 672, + "NameEnd": 686 + } + } + ], + "From": { + "FromPos": 687, + "Expr": { + "Table": { + "TablePos": 692, + "TableEnd": 698, + "Alias": null, + "Expr": { + "Database": null, + "Table": { + "Name": "ranked", + "QuoteType": 1, + "NamePos": 692, + "NameEnd": 698 + } + }, + "HasFinal": false + }, + "StatementEnd": 698, + "SampleRatio": null, + "HasFinal": false + } + }, + "ArrayJoin": null, + "Window": null, + "Prewhere": null, + "Where": { + "WherePos": 699, + "Expr": { + "LeftExpr": { + "Name": "dept_rank", + "QuoteType": 1, + "NamePos": 705, + "NameEnd": 714 + }, + "Operation": "\u003c=", + "RightExpr": { + "NumPos": 718, + "NumEnd": 719, + "Literal": "5", + "Base": 10 + }, + "HasGlobal": false, + "HasNot": false + } + }, + "GroupBy": null, + "WithTotal": false, + "Having": null, + "OrderBy": { + "OrderPos": 720, + "ListEnd": 746, + "Items": [ + { + "OrderPos": 720, + "Expr": { + "Name": "month", + "QuoteType": 1, + "NamePos": 729, + "NameEnd": 734 + }, + "Alias": null, + "Direction": "" + }, + { + "OrderPos": 720, + "Expr": { + "Name": "department", + "QuoteType": 1, + "NamePos": 736, + "NameEnd": 746 + }, + "Alias": null, + "Direction": "" + } + ] + }, + "LimitBy": null, + "Limit": null, + "Settings": null, + "Format": null, + "UnionAll": null, + "UnionDistinct": null, + "Except": null + } +] \ No newline at end of file diff --git a/parser/testdata/query/output/select_window_params.sql.golden.json b/parser/testdata/query/output/select_window_params.sql.golden.json new file mode 100644 index 0000000..160c91b --- /dev/null +++ b/parser/testdata/query/output/select_window_params.sql.golden.json @@ -0,0 +1,497 @@ +[ + { + "SelectPos": 100, + "StatementEnd": 663, + "With": null, + "Top": null, + "HasDistinct": false, + "DistinctOn": null, + "SelectItems": [ + { + "Expr": { + "Function": { + "Name": { + "Name": "sum", + "QuoteType": 1, + "NamePos": 107, + "NameEnd": 110 + }, + "Params": { + "LeftParenPos": 110, + "RightParenPos": 112, + "Items": { + "ListPos": 111, + "ListEnd": 112, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 111, + "NameEnd": 112 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "OverPos": 114, + "OverExpr": { + "LeftParenPos": 119, + "RightParenPos": 184, + "PartitionBy": null, + "OrderBy": { + "OrderPos": 120, + "ListEnd": 130, + "Items": [ + { + "OrderPos": 120, + "Expr": { + "Name": "y", + "QuoteType": 1, + "NamePos": 129, + "NameEnd": 130 + }, + "Alias": null, + "Direction": "" + } + ] + }, + "Frame": { + "FramePos": 131, + "Type": "ROWS", + "Extend": { + "Expr": null, + "Between": { + "Param": { + "LBracePos": 144, + "RBracePos": 157, + "Name": { + "Name": "start", + "QuoteType": 1, + "NamePos": 145, + "NameEnd": 150 + }, + "Type": { + "Name": { + "Name": "UInt32", + "QuoteType": 1, + "NamePos": 151, + "NameEnd": 157 + } + } + }, + "EndPos": 168, + "Direction": "PRECEDING" + }, + "AndPos": 169, + "And": { + "CurrentPos": 173, + "RowEnd": 185 + } + } + } + } + }, + "Modifiers": [], + "Alias": { + "Name": "total1", + "QuoteType": 1, + "NamePos": 215, + "NameEnd": 221 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "avg", + "QuoteType": 1, + "NamePos": 230, + "NameEnd": 233 + }, + "Params": { + "LeftParenPos": 233, + "RightParenPos": 235, + "Items": { + "ListPos": 234, + "ListEnd": 235, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 234, + "NameEnd": 235 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "OverPos": 237, + "OverExpr": { + "LeftParenPos": 242, + "RightParenPos": 305, + "PartitionBy": null, + "OrderBy": { + "OrderPos": 243, + "ListEnd": 253, + "Items": [ + { + "OrderPos": 243, + "Expr": { + "Name": "y", + "QuoteType": 1, + "NamePos": 252, + "NameEnd": 253 + }, + "Alias": null, + "Direction": "" + } + ] + }, + "Frame": { + "FramePos": 254, + "Type": "ROWS", + "Extend": { + "Expr": null, + "Between": { + "CurrentPos": 267, + "RowEnd": 282 + }, + "AndPos": 279, + "And": { + "Param": { + "LBracePos": 283, + "RBracePos": 294, + "Name": { + "Name": "end", + "QuoteType": 1, + "NamePos": 284, + "NameEnd": 287 + }, + "Type": { + "Name": { + "Name": "UInt32", + "QuoteType": 1, + "NamePos": 288, + "NameEnd": 294 + } + } + }, + "EndPos": 305, + "Direction": "FOLLOWING" + } + } + } + } + }, + "Modifiers": [], + "Alias": { + "Name": "avg1", + "QuoteType": 1, + "NamePos": 338, + "NameEnd": 342 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "count", + "QuoteType": 1, + "NamePos": 351, + "NameEnd": 356 + }, + "Params": { + "LeftParenPos": 356, + "RightParenPos": 358, + "Items": { + "ListPos": 357, + "ListEnd": 357, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "*", + "QuoteType": 0, + "NamePos": 357, + "NameEnd": 357 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "OverPos": 360, + "OverExpr": { + "LeftParenPos": 365, + "RightParenPos": 454, + "PartitionBy": null, + "OrderBy": { + "OrderPos": 366, + "ListEnd": 376, + "Items": [ + { + "OrderPos": 366, + "Expr": { + "Name": "y", + "QuoteType": 1, + "NamePos": 375, + "NameEnd": 376 + }, + "Alias": null, + "Direction": "" + } + ] + }, + "Frame": { + "FramePos": 377, + "Type": "RANGE", + "Extend": { + "Expr": null, + "Between": { + "Param": { + "LBracePos": 391, + "RBracePos": 410, + "Name": { + "Name": "range_start", + "QuoteType": 1, + "NamePos": 392, + "NameEnd": 403 + }, + "Type": { + "Name": { + "Name": "UInt32", + "QuoteType": 1, + "NamePos": 404, + "NameEnd": 410 + } + } + }, + "EndPos": 421, + "Direction": "PRECEDING" + }, + "AndPos": 422, + "And": { + "Param": { + "LBracePos": 426, + "RBracePos": 443, + "Name": { + "Name": "range_end", + "QuoteType": 1, + "NamePos": 427, + "NameEnd": 436 + }, + "Type": { + "Name": { + "Name": "UInt32", + "QuoteType": 1, + "NamePos": 437, + "NameEnd": 443 + } + } + }, + "EndPos": 454, + "Direction": "FOLLOWING" + } + } + } + } + }, + "Modifiers": [], + "Alias": { + "Name": "cnt1", + "QuoteType": 1, + "NamePos": 459, + "NameEnd": 463 + } + }, + { + "Expr": { + "Function": { + "Name": { + "Name": "sum", + "QuoteType": 1, + "NamePos": 472, + "NameEnd": 475 + }, + "Params": { + "LeftParenPos": 475, + "RightParenPos": 477, + "Items": { + "ListPos": 476, + "ListEnd": 477, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "x", + "QuoteType": 1, + "NamePos": 476, + "NameEnd": 477 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "OverPos": 479, + "OverExpr": { + "LeftParenPos": 484, + "RightParenPos": 521, + "PartitionBy": null, + "OrderBy": null, + "Frame": { + "FramePos": 485, + "Type": "ROWS", + "Extend": { + "Param": { + "LBracePos": 490, + "RBracePos": 510, + "Name": { + "Name": "window_size", + "QuoteType": 1, + "NamePos": 491, + "NameEnd": 502 + }, + "Type": { + "Name": { + "Name": "UInt32", + "QuoteType": 1, + "NamePos": 504, + "NameEnd": 510 + } + } + }, + "EndPos": 521, + "Direction": "PRECEDING" + } + } + } + }, + "Modifiers": [], + "Alias": { + "Name": "rows_shorthand", + "QuoteType": 1, + "NamePos": 580, + "NameEnd": 594 + } + } + ], + "From": { + "FromPos": 595, + "Expr": { + "Table": { + "TablePos": 600, + "TableEnd": 601, + "Alias": null, + "Expr": { + "Database": null, + "Table": { + "Name": "t", + "QuoteType": 1, + "NamePos": 600, + "NameEnd": 601 + } + }, + "HasFinal": false + }, + "StatementEnd": 601, + "SampleRatio": null, + "HasFinal": false + } + }, + "ArrayJoin": null, + "Window": null, + "Prewhere": null, + "Where": { + "WherePos": 602, + "Expr": { + "LeftExpr": { + "LeftExpr": { + "Name": "category", + "QuoteType": 1, + "NamePos": 608, + "NameEnd": 616 + }, + "Operation": "=", + "RightExpr": { + "LBracePos": 619, + "RBracePos": 636, + "Name": { + "Name": "category", + "QuoteType": 1, + "NamePos": 620, + "NameEnd": 628 + }, + "Type": { + "Name": { + "Name": "String", + "QuoteType": 1, + "NamePos": 630, + "NameEnd": 636 + } + } + }, + "HasGlobal": false, + "HasNot": false + }, + "Operation": "AND", + "RightExpr": { + "LeftExpr": { + "Name": "type", + "QuoteType": 1, + "NamePos": 644, + "NameEnd": 648 + }, + "Operation": "=", + "RightExpr": { + "LBracePos": 651, + "RBracePos": 663, + "Name": { + "Name": "type", + "QuoteType": 1, + "NamePos": 652, + "NameEnd": 656 + }, + "Type": { + "Name": { + "Name": "String", + "QuoteType": 1, + "NamePos": 657, + "NameEnd": 663 + } + } + }, + "HasGlobal": false, + "HasNot": false + }, + "HasGlobal": false, + "HasNot": false + } + }, + "GroupBy": null, + "WithTotal": false, + "Having": null, + "OrderBy": null, + "LimitBy": null, + "Limit": null, + "Settings": null, + "Format": null, + "UnionAll": null, + "UnionDistinct": null, + "Except": null + } +] \ No newline at end of file diff --git a/parser/testdata/query/output/select_with_window_function.sql.golden.json b/parser/testdata/query/output/select_with_window_function.sql.golden.json index 2f0f9a4..57d395a 100644 --- a/parser/testdata/query/output/select_with_window_function.sql.golden.json +++ b/parser/testdata/query/output/select_with_window_function.sql.golden.json @@ -189,28 +189,20 @@ "Extend": { "Expr": null, "Between": { - "FramePos": 292, - "Type": "", - "Extend": { - "UnboundedPos": 292, - "UnboundedEnd": 0, - "Direction": "PRECEDING" - } + "UnboundedPos": 292, + "UnboundedEnd": 0, + "Direction": "PRECEDING" }, "AndPos": 312, "And": { - "FramePos": 316, - "Type": "", - "Extend": { - "Number": { - "NumPos": 316, - "NumEnd": 317, - "Literal": "0", - "Base": 10 - }, - "UnboundedEnd": 327, - "Direction": "PRECEDING" - } + "Number": { + "NumPos": 316, + "NumEnd": 317, + "Literal": "0", + "Base": 10 + }, + "EndPos": 327, + "Direction": "PRECEDING" } } } @@ -297,83 +289,82 @@ }, "ArrayJoin": null, "Window": { - "LeftParenPos": 399, - "RightParenPos": 508, - "PartitionBy": { - "PartitionPos": 399, - "Expr": { - "ListPos": 413, - "ListEnd": 431, - "HasDistinct": false, - "Items": [ - { + "WindowPos": 387, + "EndPos": 508, + "Windows": [ + { + "Name": { + "Name": "w", + "QuoteType": 1, + "NamePos": 394, + "NameEnd": 395 + }, + "AsPos": 396, + "Expr": { + "LeftParenPos": 399, + "RightParenPos": 508, + "PartitionBy": { + "PartitionPos": 399, "Expr": { - "Name": "aggregation_target", - "QuoteType": 1, - "NamePos": 413, - "NameEnd": 431 - }, - "Alias": null - } - ] - } - }, - "OrderBy": { - "OrderPos": 436, - "ListEnd": 454, - "Items": [ - { - "OrderPos": 436, - "Expr": { - "Name": "timestamp", - "QuoteType": 1, - "NamePos": 445, - "NameEnd": 454 + "ListPos": 413, + "ListEnd": 431, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "aggregation_target", + "QuoteType": 1, + "NamePos": 413, + "NameEnd": 431 + }, + "Alias": null + } + ] + } }, - "Alias": null, - "Direction": "DESC" - } - ] - }, - "Frame": { - "FramePos": 460, - "Type": "ROWS", - "Extend": { - "Expr": null, - "Between": { - "FramePos": 473, - "Type": "", - "Extend": { - "UnboundedPos": 473, - "UnboundedEnd": 0, - "Direction": "PRECEDING" - } - }, - "AndPos": 493, - "And": { - "FramePos": 497, - "Type": "", - "Extend": { - "Number": { - "NumPos": 497, - "NumEnd": 498, - "Literal": "0", - "Base": 10 - }, - "UnboundedEnd": 508, - "Direction": "PRECEDING" + "OrderBy": { + "OrderPos": 436, + "ListEnd": 454, + "Items": [ + { + "OrderPos": 436, + "Expr": { + "Name": "timestamp", + "QuoteType": 1, + "NamePos": 445, + "NameEnd": 454 + }, + "Alias": null, + "Direction": "DESC" + } + ] + }, + "Frame": { + "FramePos": 460, + "Type": "ROWS", + "Extend": { + "Expr": null, + "Between": { + "UnboundedPos": 473, + "UnboundedEnd": 0, + "Direction": "PRECEDING" + }, + "AndPos": 493, + "And": { + "Number": { + "NumPos": 497, + "NumEnd": 498, + "Literal": "0", + "Base": 10 + }, + "EndPos": 508, + "Direction": "PRECEDING" + } + } } } } - }, - "WindowPos": 387, - "Name": { - "Name": "w", - "QuoteType": 1, - "NamePos": 394, - "NameEnd": 395 - }, - "AsPos": 0 + ] }, "Prewhere": null, "Where": null, diff --git a/parser/testdata/query/select_window_comprehensive.sql b/parser/testdata/query/select_window_comprehensive.sql new file mode 100644 index 0000000..3b43a1b --- /dev/null +++ b/parser/testdata/query/select_window_comprehensive.sql @@ -0,0 +1,52 @@ +-- Comprehensive window spec coverage: ad-hoc specs, named windows, ROWS/RANGE frames +-- multiple functions, multi-column PARTITION/ORDER, and expression-based specs. +SELECT + -- Ad-hoc windows + sum(x) OVER (ORDER BY y ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS running_total, + avg(x) + OVER (PARTITION BY z ORDER BY y RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS avg_range1, + + -- Named window reuse (OVER w1) + row_number() OVER w1 AS rn_w1, + rank() OVER w1 AS rank_w1, + sum(x) OVER w1 AS sum_w1, + + -- Frame variants (incl. shorthand & RANGE) + sum(x) OVER (ROWS 10 PRECEDING) AS rows_10_preceding, + sum(x) OVER (ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS rows_cur_to_unbounded_following, + sum(x) OVER (ROWS BETWEEN 5 PRECEDING AND 3 FOLLOWING) AS rows_5p_3f, + sum(x) OVER (RANGE BETWEEN 10 PRECEDING AND CURRENT ROW) AS range_10p_cur, + sum(x) OVER (RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS range_unbounded_to_cur, + + -- Ranking & navigation + row_number() OVER (PARTITION BY y ORDER BY x) AS row_num, + rank() OVER (PARTITION BY y ORDER BY x) AS rank_val, + dense_rank() OVER (PARTITION BY y ORDER BY x) AS dense_rank_val, + first_value(x) + OVER (PARTITION BY y ORDER BY x ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS first_val, + last_value(x) + OVER (PARTITION BY y ORDER BY x ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_val, + lag(x, 1) OVER (PARTITION BY y ORDER BY x) AS prev_x, + lead(x, 1) OVER (PARTITION BY y ORDER BY x) AS next_x, + percent_rank() OVER (PARTITION BY y ORDER BY x) AS pct_rank, + + -- Named window reference via OVER w (no parentheses) + sum(x) OVER w AS sum_over_w, + avg(x) OVER w AS avg_over_w, + row_number() OVER w AS rn_over_w, + + -- Multiple columns in PARTITION BY / ORDER BY + count(*) OVER (PARTITION BY col1, col2, col3 ORDER BY col4, col5 DESC) AS cnt_multi, + sum(val) + OVER (PARTITION BY col1, col2 ORDER BY col4, col5 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS total_multi, + + -- Expressions in PARTITION/ORDER + sum(amount) + OVER (PARTITION BY date_trunc('day', timestamp) ORDER BY timestamp ROWS BETWEEN 10 PRECEDING AND CURRENT ROW) AS daily_total, + avg(amount) + OVER (ORDER BY extract(HOUR FROM timestamp) RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS hourly_avg +FROM t +WINDOW w AS (ORDER BY y), + w1 AS (PARTITION BY y ORDER BY x ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), + w4 AS (PARTITION BY y ORDER BY x ROWS BETWEEN 3 PRECEDING AND CURRENT ROW), + w5 AS (PARTITION BY z ORDER BY x RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW); diff --git a/parser/testdata/query/select_window_cte.sql b/parser/testdata/query/select_window_cte.sql new file mode 100644 index 0000000..e93cd6a --- /dev/null +++ b/parser/testdata/query/select_window_cte.sql @@ -0,0 +1,27 @@ +WITH + monthly AS ( + SELECT toStartOfMonth(date) AS month, + department, + avg(salary) AS avg_salary + FROM salary_table + WHERE year = 2023 + GROUP BY month, department + ), + ranked AS ( + SELECT month, + department, + avg_salary, + row_number() OVER (PARTITION BY department ORDER BY avg_salary DESC) AS dept_rank + FROM monthly + ) +SELECT month, + department, + avg_salary, + lag(avg_salary, 1, 0) OVER ( + PARTITION BY department + ORDER BY month + ROWS BETWEEN 1 PRECEDING AND CURRENT ROW + ) AS prev_month_avg +FROM ranked +WHERE dept_rank <= 5 +ORDER BY month, department; diff --git a/parser/testdata/query/select_window_params.sql b/parser/testdata/query/select_window_params.sql new file mode 100644 index 0000000..bf1a467 --- /dev/null +++ b/parser/testdata/query/select_window_params.sql @@ -0,0 +1,8 @@ +-- Parameters in WHERE and in window frames (UInt32 & String; both spacing styles; shorthand frame) +SELECT sum(x) OVER (ORDER BY y ROWS BETWEEN {start:UInt32} PRECEDING AND CURRENT ROW) AS total1, + avg(x) OVER (ORDER BY y ROWS BETWEEN CURRENT ROW AND {end:UInt32} FOLLOWING) AS avg1, + count(*) OVER (ORDER BY y RANGE BETWEEN {range_start:UInt32} PRECEDING AND {range_end:UInt32} FOLLOWING) AS cnt1, + sum(x) OVER (ROWS {window_size :UInt32} PRECEDING) AS rows_shorthand +FROM t +WHERE category = {category :String} + AND type = {type:String}; diff --git a/parser/walk.go b/parser/walk.go index ec165ff..9f18ef1 100644 --- a/parser/walk.go +++ b/parser/walk.go @@ -348,11 +348,16 @@ func Walk(node Expr, fn WalkFunc) bool { } } case *WindowClause: - if !Walk(n.Name, fn) { - return false - } - if !Walk(n.WindowExpr, fn) { - return false + for _, window := range n.Windows { + if window == nil { + continue + } + if !Walk(window.Name, fn) { + return false + } + if !Walk(window.Expr, fn) { + return false + } } case *WindowExpr: if !Walk(n.PartitionBy, fn) {