@@ -548,6 +548,17 @@ func (p *Parser) parseOrderByClause() ([]ast.OrderByExpression, error) {
548548 }
549549 entry .NullsFirst = nullsFirst
550550
551+ // ClickHouse WITH FILL per-entry tail:
552+ // ORDER BY expr [ASC|DESC] WITH FILL [FROM x] [TO y] [STEP z]
553+ // Consume permissively; the clause is not modeled on the AST yet.
554+ if p .dialect == string (keywords .DialectClickHouse ) &&
555+ p .isType (models .TokenTypeWith ) &&
556+ strings .EqualFold (p .peekToken ().Token .Value , "FILL" ) {
557+ p .advance () // WITH
558+ p .advance () // FILL
559+ p .skipClickHouseWithFillTail ()
560+ }
561+
551562 orderByExprs = append (orderByExprs , entry )
552563
553564 if ! p .isType (models .TokenTypeComma ) {
@@ -558,6 +569,26 @@ func (p *Parser) parseOrderByClause() ([]ast.OrderByExpression, error) {
558569 return orderByExprs , nil
559570}
560571
572+ // skipClickHouseWithFillTail consumes the optional FROM / TO / STEP arguments
573+ // of a ClickHouse "ORDER BY expr WITH FILL" modifier. Each argument is a
574+ // single expression (possibly an INTERVAL). The tail ends at the next comma
575+ // (more ORDER BY items), next clause keyword, ';', or EOF.
576+ func (p * Parser ) skipClickHouseWithFillTail () {
577+ for {
578+ val := strings .ToUpper (p .currentToken .Token .Value )
579+ if val != "FROM" && val != "TO" && val != "STEP" {
580+ return
581+ }
582+ p .advance () // FROM / TO / STEP
583+ // Consume one expression; ignore parse errors so unusual forms
584+ // (INTERVAL '1 day', expressions with function calls, etc.) don't
585+ // surface as parser errors for this permissive skip.
586+ if _ , err := p .parseExpression (); err != nil {
587+ return
588+ }
589+ }
590+ }
591+
561592// parseLimitOffsetClause parses optional LIMIT and/or OFFSET clauses.
562593// Supports standard "LIMIT n OFFSET m", MySQL "LIMIT offset, count", and
563594// SQL-99 "OFFSET n ROWS" (ROW/ROWS consumed but value stored).
0 commit comments