@@ -192,7 +192,12 @@ func explainCreateQuery(sb *strings.Builder, n *ast.CreateQuery, indent string,
192192 }
193193 }
194194 }
195- if n .Engine != nil || len (n .OrderBy ) > 0 || len (n .PrimaryKey ) > 0 || n .PartitionBy != nil || n .SampleBy != nil || n .TTL != nil || len (n .Settings ) > 0 {
195+ // For materialized views, output AsSelect before storage definition
196+ if n .Materialized && n .AsSelect != nil {
197+ Node (sb , n .AsSelect , depth + 1 )
198+ }
199+ hasStorage := n .Engine != nil || len (n .OrderBy ) > 0 || len (n .PrimaryKey ) > 0 || n .PartitionBy != nil || n .SampleBy != nil || n .TTL != nil || len (n .Settings ) > 0
200+ if hasStorage {
196201 storageChildren := 0
197202 if n .Engine != nil {
198203 storageChildren ++
@@ -231,80 +236,91 @@ func explainCreateQuery(sb *strings.Builder, n *ast.CreateQuery, indent string,
231236 if len (n .Settings ) > 0 {
232237 storageChildren ++
233238 }
234- fmt .Fprintf (sb , "%s Storage definition (children %d)\n " , indent , storageChildren )
239+ // For materialized views, wrap storage definition in ViewTargets
240+ // and use extra indentation for storage children
241+ storageIndent := indent + " " // 1 space for regular storage (format strings add 1 more)
242+ storageChildDepth := depth + 2
243+ if n .Materialized {
244+ fmt .Fprintf (sb , "%s ViewTargets (children %d)\n " , indent , 1 )
245+ fmt .Fprintf (sb , "%s Storage definition (children %d)\n " , indent , storageChildren )
246+ storageIndent = indent + " " // 2 spaces for materialized (format strings add 1 more = 3 total)
247+ storageChildDepth = depth + 3
248+ } else {
249+ fmt .Fprintf (sb , "%s Storage definition (children %d)\n " , indent , storageChildren )
250+ }
235251 if n .Engine != nil {
236252 if n .Engine .HasParentheses {
237- fmt .Fprintf (sb , "%s Function %s (children %d)\n " , indent , n .Engine .Name , 1 )
253+ fmt .Fprintf (sb , "%s Function %s (children %d)\n " , storageIndent , n .Engine .Name , 1 )
238254 if len (n .Engine .Parameters ) > 0 {
239- fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , len (n .Engine .Parameters ))
255+ fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , storageIndent , len (n .Engine .Parameters ))
240256 for _ , param := range n .Engine .Parameters {
241- Node (sb , param , depth + 4 )
257+ Node (sb , param , storageChildDepth + 2 )
242258 }
243259 } else {
244- fmt .Fprintf (sb , "%s ExpressionList\n " , indent )
260+ fmt .Fprintf (sb , "%s ExpressionList\n " , storageIndent )
245261 }
246262 } else {
247- fmt .Fprintf (sb , "%s Function %s\n " , indent , n .Engine .Name )
263+ fmt .Fprintf (sb , "%s Function %s\n " , storageIndent , n .Engine .Name )
248264 }
249265 }
250266 if n .PartitionBy != nil {
251267 if ident , ok := n .PartitionBy .(* ast.Identifier ); ok {
252- fmt .Fprintf (sb , "%s Identifier %s\n " , indent , ident .Name ())
268+ fmt .Fprintf (sb , "%s Identifier %s\n " , storageIndent , ident .Name ())
253269 } else {
254- Node (sb , n .PartitionBy , depth + 2 )
270+ Node (sb , n .PartitionBy , storageChildDepth )
255271 }
256272 }
257273 if len (n .OrderBy ) > 0 {
258274 if len (n .OrderBy ) == 1 {
259275 if ident , ok := n .OrderBy [0 ].(* ast.Identifier ); ok {
260- fmt .Fprintf (sb , "%s Identifier %s\n " , indent , ident .Name ())
276+ fmt .Fprintf (sb , "%s Identifier %s\n " , storageIndent , ident .Name ())
261277 } else if lit , ok := n .OrderBy [0 ].(* ast.Literal ); ok && lit .Type == ast .LiteralTuple {
262278 // Handle tuple literal (including empty tuple from ORDER BY ())
263279 exprs , _ := lit .Value .([]ast.Expression )
264- fmt .Fprintf (sb , "%s Function tuple (children %d)\n " , indent , 1 )
280+ fmt .Fprintf (sb , "%s Function tuple (children %d)\n " , storageIndent , 1 )
265281 if len (exprs ) > 0 {
266- fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , len (exprs ))
282+ fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , storageIndent , len (exprs ))
267283 for _ , e := range exprs {
268- Node (sb , e , depth + 4 )
284+ Node (sb , e , storageChildDepth + 2 )
269285 }
270286 } else {
271- fmt .Fprintf (sb , "%s ExpressionList\n " , indent )
287+ fmt .Fprintf (sb , "%s ExpressionList\n " , storageIndent )
272288 }
273289 } else {
274- Node (sb , n .OrderBy [0 ], depth + 2 )
290+ Node (sb , n .OrderBy [0 ], storageChildDepth )
275291 }
276292 } else {
277- fmt .Fprintf (sb , "%s Function tuple (children %d)\n " , indent , 1 )
278- fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , len (n .OrderBy ))
293+ fmt .Fprintf (sb , "%s Function tuple (children %d)\n " , storageIndent , 1 )
294+ fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , storageIndent , len (n .OrderBy ))
279295 for _ , o := range n .OrderBy {
280- Node (sb , o , depth + 4 )
296+ Node (sb , o , storageChildDepth + 2 )
281297 }
282298 }
283299 }
284300 if len (n .PrimaryKey ) > 0 {
285301 if len (n .PrimaryKey ) == 1 {
286302 if ident , ok := n .PrimaryKey [0 ].(* ast.Identifier ); ok {
287- fmt .Fprintf (sb , "%s Identifier %s\n " , indent , ident .Name ())
303+ fmt .Fprintf (sb , "%s Identifier %s\n " , storageIndent , ident .Name ())
288304 } else if lit , ok := n .PrimaryKey [0 ].(* ast.Literal ); ok && lit .Type == ast .LiteralTuple {
289305 // Handle tuple literal (including empty tuple from PRIMARY KEY ())
290306 exprs , _ := lit .Value .([]ast.Expression )
291- fmt .Fprintf (sb , "%s Function tuple (children %d)\n " , indent , 1 )
307+ fmt .Fprintf (sb , "%s Function tuple (children %d)\n " , storageIndent , 1 )
292308 if len (exprs ) > 0 {
293- fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , len (exprs ))
309+ fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , storageIndent , len (exprs ))
294310 for _ , e := range exprs {
295- Node (sb , e , depth + 4 )
311+ Node (sb , e , storageChildDepth + 2 )
296312 }
297313 } else {
298- fmt .Fprintf (sb , "%s ExpressionList\n " , indent )
314+ fmt .Fprintf (sb , "%s ExpressionList\n " , storageIndent )
299315 }
300316 } else {
301- Node (sb , n .PrimaryKey [0 ], depth + 2 )
317+ Node (sb , n .PrimaryKey [0 ], storageChildDepth )
302318 }
303319 } else {
304- fmt .Fprintf (sb , "%s Function tuple (children %d)\n " , indent , 1 )
305- fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , len (n .PrimaryKey ))
320+ fmt .Fprintf (sb , "%s Function tuple (children %d)\n " , storageIndent , 1 )
321+ fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , storageIndent , len (n .PrimaryKey ))
306322 for _ , p := range n .PrimaryKey {
307- Node (sb , p , depth + 4 )
323+ Node (sb , p , storageChildDepth + 2 )
308324 }
309325 }
310326 }
@@ -323,20 +339,21 @@ func explainCreateQuery(sb *strings.Builder, n *ast.CreateQuery, indent string,
323339 }
324340 }
325341 if showSampleBy {
326- Node (sb , n .SampleBy , depth + 2 )
342+ Node (sb , n .SampleBy , storageChildDepth )
327343 }
328344 }
329345 }
330346 if n .TTL != nil {
331- fmt .Fprintf (sb , "%s ExpressionList (children 1)\n " , indent )
332- fmt .Fprintf (sb , "%s TTLElement (children 1)\n " , indent )
333- Node (sb , n .TTL .Expression , depth + 4 )
347+ fmt .Fprintf (sb , "%s ExpressionList (children 1)\n " , storageIndent )
348+ fmt .Fprintf (sb , "%s TTLElement (children 1)\n " , storageIndent )
349+ Node (sb , n .TTL .Expression , storageChildDepth + 2 )
334350 }
335351 if len (n .Settings ) > 0 {
336- fmt .Fprintf (sb , "%s Set\n " , indent )
352+ fmt .Fprintf (sb , "%s Set\n " , storageIndent )
337353 }
338354 }
339- if n .AsSelect != nil {
355+ // For non-materialized views, output AsSelect after storage
356+ if n .AsSelect != nil && ! n .Materialized {
340357 // AS SELECT is output directly without Subquery wrapper
341358 Node (sb , n .AsSelect , depth + 1 )
342359 }
@@ -908,7 +925,7 @@ func countAlterCommandChildren(cmd *ast.AlterCommand) int {
908925 return children
909926}
910927
911- func explainOptimizeQuery (sb * strings.Builder , n * ast.OptimizeQuery , indent string ) {
928+ func explainOptimizeQuery (sb * strings.Builder , n * ast.OptimizeQuery , indent string , depth int ) {
912929 if n == nil {
913930 fmt .Fprintf (sb , "%s*ast.OptimizeQuery\n " , indent )
914931 return
@@ -919,7 +936,16 @@ func explainOptimizeQuery(sb *strings.Builder, n *ast.OptimizeQuery, indent stri
919936 name += "_final"
920937 }
921938
922- fmt .Fprintf (sb , "%sOptimizeQuery %s (children %d)\n " , indent , name , 1 )
939+ children := 1 // identifier
940+ if n .Partition != nil {
941+ children ++
942+ }
943+
944+ fmt .Fprintf (sb , "%sOptimizeQuery %s (children %d)\n " , indent , name , children )
945+ if n .Partition != nil {
946+ fmt .Fprintf (sb , "%s Partition (children 1)\n " , indent )
947+ Node (sb , n .Partition , depth + 2 )
948+ }
923949 fmt .Fprintf (sb , "%s Identifier %s\n " , indent , n .Table )
924950}
925951
@@ -950,12 +976,18 @@ func explainCheckQuery(sb *strings.Builder, n *ast.CheckQuery, indent string) {
950976 }
951977
952978 children := 1 // identifier
979+ if n .Format != "" {
980+ children ++
981+ }
953982 if len (n .Settings ) > 0 {
954983 children ++
955984 }
956985
957986 fmt .Fprintf (sb , "%sCheckQuery %s (children %d)\n " , indent , name , children )
958987 fmt .Fprintf (sb , "%s Identifier %s\n " , indent , name )
988+ if n .Format != "" {
989+ fmt .Fprintf (sb , "%s Identifier %s\n " , indent , n .Format )
990+ }
959991 if len (n .Settings ) > 0 {
960992 fmt .Fprintf (sb , "%s Set\n " , indent )
961993 }
0 commit comments