@@ -7,10 +7,15 @@ import (
77 "github.com/sqlc-dev/doubleclick/ast"
88)
99
10+ // escapeAlias escapes backslashes in alias names for EXPLAIN output
11+ func escapeAlias (alias string ) string {
12+ return strings .ReplaceAll (alias , "\\ " , "\\ \\ " )
13+ }
14+
1015func explainIdentifier (sb * strings.Builder , n * ast.Identifier , indent string ) {
1116 name := formatIdentifierName (n )
1217 if n .Alias != "" {
13- fmt .Fprintf (sb , "%sIdentifier %s (alias %s)\n " , indent , name , n .Alias )
18+ fmt .Fprintf (sb , "%sIdentifier %s (alias %s)\n " , indent , name , escapeAlias ( n .Alias ) )
1419 } else {
1520 fmt .Fprintf (sb , "%sIdentifier %s\n " , indent , name )
1621 }
@@ -319,7 +324,7 @@ func explainUnaryExpr(sb *strings.Builder, n *ast.UnaryExpr, indent string, dept
319324func explainSubquery (sb * strings.Builder , n * ast.Subquery , indent string , depth int ) {
320325 children := 1
321326 if n .Alias != "" {
322- fmt .Fprintf (sb , "%sSubquery (alias %s) (children %d)\n " , indent , n .Alias , children )
327+ fmt .Fprintf (sb , "%sSubquery (alias %s) (children %d)\n " , indent , escapeAlias ( n .Alias ) , children )
323328 } else {
324329 fmt .Fprintf (sb , "%sSubquery (children %d)\n " , indent , children )
325330 }
@@ -349,7 +354,7 @@ func explainAliasedExpr(sb *strings.Builder, n *ast.AliasedExpr, depth int) {
349354 }
350355 if hasComplexExpr {
351356 // Render as Function tuple with alias
352- fmt .Fprintf (sb , "%sFunction tuple (alias %s) (children %d)\n " , indent , n .Alias , 1 )
357+ fmt .Fprintf (sb , "%sFunction tuple (alias %s) (children %d)\n " , indent , escapeAlias ( n .Alias ) , 1 )
353358 fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , len (exprs ))
354359 for _ , expr := range exprs {
355360 Node (sb , expr , depth + 2 )
@@ -380,7 +385,7 @@ func explainAliasedExpr(sb *strings.Builder, n *ast.AliasedExpr, depth int) {
380385 }
381386 if needsFunctionFormat {
382387 // Render as Function array with alias
383- fmt .Fprintf (sb , "%sFunction array (alias %s) (children %d)\n " , indent , n .Alias , 1 )
388+ fmt .Fprintf (sb , "%sFunction array (alias %s) (children %d)\n " , indent , escapeAlias ( n .Alias ) , 1 )
384389 if len (exprs ) > 0 {
385390 fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , len (exprs ))
386391 } else {
@@ -393,20 +398,20 @@ func explainAliasedExpr(sb *strings.Builder, n *ast.AliasedExpr, depth int) {
393398 }
394399 }
395400 }
396- fmt .Fprintf (sb , "%sLiteral %s (alias %s)\n " , indent , FormatLiteral (e ), n .Alias )
401+ fmt .Fprintf (sb , "%sLiteral %s (alias %s)\n " , indent , FormatLiteral (e ), escapeAlias ( n .Alias ) )
397402 case * ast.BinaryExpr :
398403 // Binary expressions become functions with alias
399404 fnName := OperatorToFunction (e .Op )
400405 // For || (concat) operator, flatten chained concatenations
401406 if e .Op == "||" {
402407 operands := collectConcatOperands (e )
403- fmt .Fprintf (sb , "%sFunction %s (alias %s) (children %d)\n " , indent , fnName , n .Alias , 1 )
408+ fmt .Fprintf (sb , "%sFunction %s (alias %s) (children %d)\n " , indent , fnName , escapeAlias ( n .Alias ) , 1 )
404409 fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , len (operands ))
405410 for _ , op := range operands {
406411 Node (sb , op , depth + 2 )
407412 }
408413 } else {
409- fmt .Fprintf (sb , "%sFunction %s (alias %s) (children %d)\n " , indent , fnName , n .Alias , 1 )
414+ fmt .Fprintf (sb , "%sFunction %s (alias %s) (children %d)\n " , indent , fnName , escapeAlias ( n .Alias ) , 1 )
410415 fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , 2 )
411416 Node (sb , e .Left , depth + 2 )
412417 Node (sb , e .Right , depth + 2 )
@@ -423,39 +428,39 @@ func explainAliasedExpr(sb *strings.Builder, n *ast.AliasedExpr, depth int) {
423428 if inSubqueryContext {
424429 switch val := lit .Value .(type ) {
425430 case int64 :
426- fmt .Fprintf (sb , "%sLiteral Int64_%d (alias %s)\n " , indent , - val , n .Alias )
431+ fmt .Fprintf (sb , "%sLiteral Int64_%d (alias %s)\n " , indent , - val , escapeAlias ( n .Alias ) )
427432 return
428433 case uint64 :
429- fmt .Fprintf (sb , "%sLiteral Int64_-%d (alias %s)\n " , indent , val , n .Alias )
434+ fmt .Fprintf (sb , "%sLiteral Int64_-%d (alias %s)\n " , indent , val , escapeAlias ( n .Alias ) )
430435 return
431436 }
432437 }
433438 case ast .LiteralFloat :
434439 // Always convert negated floats to literals (especially for -inf, -nan)
435440 val := lit .Value .(float64 )
436441 s := FormatFloat (- val )
437- fmt .Fprintf (sb , "%sLiteral Float64_%s (alias %s)\n " , indent , s , n .Alias )
442+ fmt .Fprintf (sb , "%sLiteral Float64_%s (alias %s)\n " , indent , s , escapeAlias ( n .Alias ) )
438443 return
439444 }
440445 }
441446 }
442447 // Unary expressions become functions with alias
443448 fnName := UnaryOperatorToFunction (e .Op )
444- fmt .Fprintf (sb , "%sFunction %s (alias %s) (children %d)\n " , indent , fnName , n .Alias , 1 )
449+ fmt .Fprintf (sb , "%sFunction %s (alias %s) (children %d)\n " , indent , fnName , escapeAlias ( n .Alias ) , 1 )
445450 fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , 1 )
446451 Node (sb , e .Operand , depth + 2 )
447452 case * ast.FunctionCall :
448453 // Function calls already handle aliases
449454 explainFunctionCallWithAlias (sb , e , n .Alias , indent , depth )
450455 case * ast.Identifier :
451456 // Identifiers with alias
452- fmt .Fprintf (sb , "%sIdentifier %s (alias %s)\n " , indent , e .Name (), n .Alias )
457+ fmt .Fprintf (sb , "%sIdentifier %s (alias %s)\n " , indent , e .Name (), escapeAlias ( n .Alias ) )
453458 case * ast.IntervalExpr :
454459 // Interval expressions with alias
455460 explainIntervalExpr (sb , e , n .Alias , indent , depth )
456461 case * ast.TernaryExpr :
457462 // Ternary expressions become if functions with alias
458- fmt .Fprintf (sb , "%sFunction if (alias %s) (children %d)\n " , indent , n .Alias , 1 )
463+ fmt .Fprintf (sb , "%sFunction if (alias %s) (children %d)\n " , indent , escapeAlias ( n .Alias ) , 1 )
459464 fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , 3 )
460465 Node (sb , e .Condition , depth + 2 )
461466 Node (sb , e .Then , depth + 2 )
0 commit comments