@@ -225,7 +225,9 @@ func explainCreateQuery(sb *strings.Builder, n *ast.CreateQuery, indent string,
225225 // When SETTINGS comes after COMMENT (not before), Settings goes outside Storage definition
226226 // SettingsBeforeComment=true means SETTINGS came first, so it stays in Storage
227227 settingsInStorage := len (n .Settings ) > 0 && (n .Comment == "" || n .SettingsBeforeComment )
228- hasStorageChild := n .Engine != nil || len (n .OrderBy ) > 0 || len (n .PrimaryKey ) > 0 || n .PartitionBy != nil || n .SampleBy != nil || n .TTL != nil || settingsInStorage || len (n .ColumnsPrimaryKey ) > 0 || hasColumnPrimaryKey
228+ // For WINDOW VIEW with INNER ENGINE, ORDER BY goes inside ViewTargets, not in regular Storage definition
229+ orderByInRegularStorage := len (n .OrderBy ) > 0 && ! (n .WindowView && n .InnerEngine != nil )
230+ hasStorageChild := n .Engine != nil || orderByInRegularStorage || len (n .PrimaryKey ) > 0 || n .PartitionBy != nil || n .SampleBy != nil || n .TTL != nil || settingsInStorage || len (n .ColumnsPrimaryKey ) > 0 || hasColumnPrimaryKey
229231 if hasStorageChild {
230232 children ++
231233 }
@@ -245,6 +247,10 @@ func explainCreateQuery(sb *strings.Builder, n *ast.CreateQuery, indent string,
245247 if n .Materialized && n .To != "" && ! hasStorageChild {
246248 children ++ // ViewTargets
247249 }
250+ // For window views with INNER ENGINE, count ViewTargets as a child
251+ if n .WindowView && n .InnerEngine != nil {
252+ children ++ // ViewTargets with Storage definition
253+ }
248254 if n .AsSelect != nil {
249255 children ++
250256 }
@@ -374,7 +380,9 @@ func explainCreateQuery(sb *strings.Builder, n *ast.CreateQuery, indent string,
374380 inCreateQueryContext = false
375381 }
376382 }
377- hasStorage := n .Engine != nil || len (n .OrderBy ) > 0 || len (n .PrimaryKey ) > 0 || n .PartitionBy != nil || n .SampleBy != nil || n .TTL != nil || settingsInStorage || len (n .ColumnsPrimaryKey ) > 0 || hasColumnPrimaryKey
383+ // For WINDOW VIEW with INNER ENGINE, ORDER BY goes inside ViewTargets
384+ hasOrderByInStorage := len (n .OrderBy ) > 0 && ! (n .WindowView && n .InnerEngine != nil )
385+ hasStorage := n .Engine != nil || hasOrderByInStorage || len (n .PrimaryKey ) > 0 || n .PartitionBy != nil || n .SampleBy != nil || n .TTL != nil || settingsInStorage || len (n .ColumnsPrimaryKey ) > 0 || hasColumnPrimaryKey
378386 if hasStorage {
379387 storageChildren := 0
380388 if n .Engine != nil {
@@ -549,8 +557,58 @@ func explainCreateQuery(sb *strings.Builder, n *ast.CreateQuery, indent string,
549557 // output just ViewTargets without children
550558 fmt .Fprintf (sb , "%s ViewTargets\n " , indent )
551559 }
560+ // For window views, output AsSelect before ViewTargets
561+ if n .WindowView && n .AsSelect != nil {
562+ if hasFormat {
563+ inCreateQueryContext = true
564+ }
565+ Node (sb , n .AsSelect , depth + 1 )
566+ if hasFormat {
567+ inCreateQueryContext = false
568+ }
569+ }
570+ // For window views with INNER ENGINE, output ViewTargets with Storage definition
571+ if n .WindowView && n .InnerEngine != nil {
572+ // Count children in storage definition: engine + order by (if any)
573+ storageChildren := 1 // Always have the engine
574+ if len (n .OrderBy ) > 0 {
575+ storageChildren ++
576+ }
577+ fmt .Fprintf (sb , "%s ViewTargets (children 1)\n " , indent )
578+ fmt .Fprintf (sb , "%s Storage definition (children %d)\n " , indent , storageChildren )
579+ // Output the engine
580+ if n .InnerEngine .HasParentheses {
581+ fmt .Fprintf (sb , "%s Function %s (children 1)\n " , indent , n .InnerEngine .Name )
582+ if len (n .InnerEngine .Parameters ) > 0 {
583+ fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , len (n .InnerEngine .Parameters ))
584+ for _ , param := range n .InnerEngine .Parameters {
585+ Node (sb , param , depth + 5 )
586+ }
587+ } else {
588+ fmt .Fprintf (sb , "%s ExpressionList\n " , indent )
589+ }
590+ } else {
591+ fmt .Fprintf (sb , "%s Function %s\n " , indent , n .InnerEngine .Name )
592+ }
593+ // Output ORDER BY if present
594+ if len (n .OrderBy ) > 0 {
595+ if len (n .OrderBy ) == 1 {
596+ if ident , ok := n .OrderBy [0 ].(* ast.Identifier ); ok {
597+ fmt .Fprintf (sb , "%s Identifier %s\n " , indent , ident .Name ())
598+ } else {
599+ Node (sb , n .OrderBy [0 ], depth + 3 )
600+ }
601+ } else {
602+ fmt .Fprintf (sb , "%s Function tuple (children 1)\n " , indent )
603+ fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , len (n .OrderBy ))
604+ for _ , o := range n .OrderBy {
605+ Node (sb , o , depth + 5 )
606+ }
607+ }
608+ }
609+ }
552610 // For non-materialized views, output AsSelect after storage
553- if n .AsSelect != nil && ! n .Materialized {
611+ if n .AsSelect != nil && ! n .Materialized && ! n . WindowView {
554612 // Set context flag to prevent Format from being output at SelectWithUnionQuery level
555613 // (it will be output at CreateQuery level instead)
556614 if hasFormat {
0 commit comments