@@ -139,32 +139,46 @@ func explainSelectQueryWithInheritedWith(sb *strings.Builder, stmt ast.Statement
139139 Node (sb , i , depth + 2 )
140140 }
141141 }
142- // OFFSET
143- if sq .Offset != nil {
144- Node (sb , sq .Offset , depth + 1 )
145- }
146- // LIMIT BY handling
142+ // LIMIT BY handling - order: LimitByOffset, LimitByLimit, LimitBy expressions, Offset, Limit
147143 if sq .LimitByLimit != nil {
144+ // Output LIMIT BY offset first (if present)
145+ if sq .LimitByOffset != nil {
146+ Node (sb , sq .LimitByOffset , depth + 1 )
147+ }
148+ // Output LIMIT BY count
148149 Node (sb , sq .LimitByLimit , depth + 1 )
150+ // Output LIMIT BY expressions
149151 if len (sq .LimitBy ) > 0 {
150152 fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , len (sq .LimitBy ))
151153 for _ , expr := range sq .LimitBy {
152154 Node (sb , expr , depth + 2 )
153155 }
154156 }
157+ // Output regular OFFSET
158+ if sq .Offset != nil {
159+ Node (sb , sq .Offset , depth + 1 )
160+ }
161+ // Output regular LIMIT
155162 if sq .Limit != nil {
156163 Node (sb , sq .Limit , depth + 1 )
157164 }
158165 } else if len (sq .LimitBy ) > 0 {
166+ // LIMIT BY without explicit LimitByLimit
159167 if sq .Limit != nil {
160168 Node (sb , sq .Limit , depth + 1 )
161169 }
162170 fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , len (sq .LimitBy ))
163171 for _ , expr := range sq .LimitBy {
164172 Node (sb , expr , depth + 2 )
165173 }
166- } else if sq .Limit != nil {
167- Node (sb , sq .Limit , depth + 1 )
174+ } else {
175+ // No LIMIT BY - just regular OFFSET and LIMIT
176+ if sq .Offset != nil {
177+ Node (sb , sq .Offset , depth + 1 )
178+ }
179+ if sq .Limit != nil {
180+ Node (sb , sq .Limit , depth + 1 )
181+ }
168182 }
169183 // SETTINGS (when no INTERPOLATE - the case with INTERPOLATE is handled above)
170184 if len (sq .Settings ) > 0 && len (sq .Interpolate ) == 0 && ! sq .SettingsAfterFormat {
@@ -417,35 +431,46 @@ func explainSelectQuery(sb *strings.Builder, n *ast.SelectQuery, indent string,
417431 Node (sb , i , depth + 2 )
418432 }
419433 }
420- // OFFSET (ClickHouse outputs offset before limit in EXPLAIN AST)
421- if n .Offset != nil {
422- Node (sb , n .Offset , depth + 1 )
423- }
424- // LIMIT BY handling
434+ // LIMIT BY handling - order: LimitByOffset, LimitByLimit, LimitBy expressions, Offset, Limit
425435 if n .LimitByLimit != nil {
426- // Case: LIMIT n BY x LIMIT m -> output LimitByLimit, LimitBy, Limit
436+ // Output LIMIT BY offset first (if present)
437+ if n .LimitByOffset != nil {
438+ Node (sb , n .LimitByOffset , depth + 1 )
439+ }
440+ // Output LIMIT BY count
427441 Node (sb , n .LimitByLimit , depth + 1 )
442+ // Output LIMIT BY expressions
428443 if len (n .LimitBy ) > 0 {
429444 fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , len (n .LimitBy ))
430445 for _ , expr := range n .LimitBy {
431446 Node (sb , expr , depth + 2 )
432447 }
433448 }
449+ // Output regular OFFSET
450+ if n .Offset != nil {
451+ Node (sb , n .Offset , depth + 1 )
452+ }
453+ // Output regular LIMIT
434454 if n .Limit != nil {
435455 Node (sb , n .Limit , depth + 1 )
436456 }
437457 } else if len (n .LimitBy ) > 0 {
438- // Case: LIMIT n BY x (no second LIMIT) -> output Limit, then LimitBy
458+ // LIMIT BY without explicit LimitByLimit
439459 if n .Limit != nil {
440460 Node (sb , n .Limit , depth + 1 )
441461 }
442462 fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , len (n .LimitBy ))
443463 for _ , expr := range n .LimitBy {
444464 Node (sb , expr , depth + 2 )
445465 }
446- } else if n .Limit != nil {
447- // Case: plain LIMIT n (no BY)
448- Node (sb , n .Limit , depth + 1 )
466+ } else {
467+ // No LIMIT BY - just regular OFFSET and LIMIT
468+ if n .Offset != nil {
469+ Node (sb , n .Offset , depth + 1 )
470+ }
471+ if n .Limit != nil {
472+ Node (sb , n .Limit , depth + 1 )
473+ }
449474 }
450475 // SETTINGS is output at SelectQuery level only when NOT after FORMAT
451476 // When SettingsAfterFormat is true, it's output at SelectWithUnionQuery level instead
@@ -617,8 +642,11 @@ func countSelectQueryChildren(n *ast.SelectQuery) int {
617642 if len (n .Interpolate ) > 0 {
618643 count ++
619644 }
645+ if n .LimitByOffset != nil {
646+ count ++ // LIMIT offset in "LIMIT offset, count BY x"
647+ }
620648 if n .LimitByLimit != nil {
621- count ++ // LIMIT n in "LIMIT n BY x LIMIT m"
649+ count ++ // LIMIT count in "LIMIT n BY x LIMIT m"
622650 }
623651 if n .Limit != nil {
624652 count ++
0 commit comments