(pos Pos)
| 653 | } |
| 654 | |
| 655 | func (p *Parser) parseWindowFrameClause(pos Pos) (*WindowFrameClause, error) { |
| 656 | var windowFrameType string |
| 657 | if p.matchKeyword(KeywordRows) || p.matchKeyword(KeywordRange) { |
| 658 | windowFrameType = p.last().String |
| 659 | _ = p.lexer.consumeToken() |
| 660 | } else { |
| 661 | return nil, fmt.Errorf("expected ROWS or RANGE for window frame") |
| 662 | } |
| 663 | |
| 664 | var expr Expr |
| 665 | if p.tryConsumeKeywords(KeywordBetween) { |
| 666 | left, err := p.parseFrameExtent() |
| 667 | if err != nil { |
| 668 | return nil, err |
| 669 | } |
| 670 | andPos := p.Pos() |
| 671 | if err := p.expectKeyword(KeywordAnd); err != nil { |
| 672 | return nil, err |
| 673 | } |
| 674 | right, err := p.parseFrameExtent() |
| 675 | if err != nil { |
| 676 | return nil, err |
| 677 | } |
| 678 | expr = &BetweenClause{ |
| 679 | Between: left, |
| 680 | AndPos: andPos, |
| 681 | And: right, |
| 682 | } |
| 683 | } else { |
| 684 | // single extent |
| 685 | extent, err := p.parseFrameExtent() |
| 686 | if err != nil { |
| 687 | return nil, err |
| 688 | } |
| 689 | expr = extent |
| 690 | } |
| 691 | |
| 692 | return &WindowFrameClause{ |
| 693 | FramePos: pos, |
| 694 | Type: windowFrameType, |
| 695 | Extend: expr, |
| 696 | }, nil |
| 697 | } |
| 698 | |
| 699 | // parseFrameExtent parses a single frame extent |
| 700 | func (p *Parser) parseFrameExtent() (Expr, error) { |
no test coverage detected