format.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. package parser
  2. import (
  3. "fmt"
  4. "strings"
  5. "github.com/danfragoso/pizzasql-next/pkg/lexer"
  6. )
  7. // FormatExpr renders an expression as canonical SQL text. It is used to persist
  8. // expression indexes and generated-column definitions in the durable schema, so
  9. // the output only needs to be stable and re-parseable, not byte-identical to the
  10. // original input. A nil expression formats as an empty string.
  11. func FormatExpr(expr Expr) string {
  12. if expr == nil {
  13. return ""
  14. }
  15. switch e := expr.(type) {
  16. case *LiteralExpr:
  17. switch e.Type {
  18. case lexer.TokenString:
  19. return "'" + strings.ReplaceAll(e.Value, "'", "''") + "'"
  20. case lexer.TokenBlob:
  21. return "X'" + fmt.Sprintf("%X", []byte(e.Value)) + "'"
  22. case lexer.TokenNULL:
  23. return "NULL"
  24. case lexer.TokenTRUE:
  25. return "TRUE"
  26. case lexer.TokenFALSE:
  27. return "FALSE"
  28. default:
  29. return e.Value
  30. }
  31. case *ColumnRef:
  32. if e.Table != "" {
  33. return quoteFormatIdent(e.Table) + "." + quoteFormatIdent(e.Column)
  34. }
  35. return quoteFormatIdent(e.Column)
  36. case *BinaryExpr:
  37. return fmt.Sprintf("(%s %s %s)", FormatExpr(e.Left), operatorString(e.Op), FormatExpr(e.Right))
  38. case *UnaryExpr:
  39. if e.Op == lexer.TokenNOT {
  40. return fmt.Sprintf("(NOT %s)", FormatExpr(e.Operand))
  41. }
  42. return fmt.Sprintf("(%s%s)", operatorString(e.Op), FormatExpr(e.Operand))
  43. case *ParenExpr:
  44. return fmt.Sprintf("(%s)", FormatExpr(e.Expr))
  45. case *FunctionCall:
  46. if e.Star {
  47. return strings.ToLower(e.Name) + "(*)"
  48. }
  49. args := make([]string, len(e.Args))
  50. for i, a := range e.Args {
  51. args[i] = FormatExpr(a)
  52. }
  53. prefix := ""
  54. if e.Distinct {
  55. prefix = "DISTINCT "
  56. }
  57. return strings.ToLower(e.Name) + "(" + prefix + strings.Join(args, ", ") + ")"
  58. case *CastExpr:
  59. return fmt.Sprintf("CAST(%s AS %s)", FormatExpr(e.Expr), e.Type.Name)
  60. case *CaseExpr:
  61. var b strings.Builder
  62. b.WriteString("CASE")
  63. if e.Operand != nil {
  64. b.WriteString(" ")
  65. b.WriteString(FormatExpr(e.Operand))
  66. }
  67. for _, w := range e.Whens {
  68. b.WriteString(" WHEN ")
  69. b.WriteString(FormatExpr(w.Condition))
  70. b.WriteString(" THEN ")
  71. b.WriteString(FormatExpr(w.Result))
  72. }
  73. if e.Else != nil {
  74. b.WriteString(" ELSE ")
  75. b.WriteString(FormatExpr(e.Else))
  76. }
  77. b.WriteString(" END")
  78. return b.String()
  79. case *InExpr:
  80. not := ""
  81. if e.Not {
  82. not = "NOT "
  83. }
  84. if e.Subquery != nil {
  85. return fmt.Sprintf("(%s %sIN (SELECT ...))", FormatExpr(e.Left), not)
  86. }
  87. vals := make([]string, len(e.Values))
  88. for i, v := range e.Values {
  89. vals[i] = FormatExpr(v)
  90. }
  91. return fmt.Sprintf("(%s %sIN (%s))", FormatExpr(e.Left), not, strings.Join(vals, ", "))
  92. case *BetweenExpr:
  93. not := ""
  94. if e.Not {
  95. not = "NOT "
  96. }
  97. return fmt.Sprintf("(%s %sBETWEEN %s AND %s)", FormatExpr(e.Left), not, FormatExpr(e.Low), FormatExpr(e.High))
  98. case *LikeExpr:
  99. not := ""
  100. if e.Not {
  101. not = "NOT "
  102. }
  103. out := fmt.Sprintf("(%s %sLIKE %s)", FormatExpr(e.Left), not, FormatExpr(e.Pattern))
  104. if e.Escape != nil {
  105. out = fmt.Sprintf("(%s %sLIKE %s ESCAPE %s)", FormatExpr(e.Left), not, FormatExpr(e.Pattern), FormatExpr(e.Escape))
  106. }
  107. return out
  108. case *IsNullExpr:
  109. if e.Not {
  110. return fmt.Sprintf("(%s IS NOT NULL)", FormatExpr(e.Left))
  111. }
  112. return fmt.Sprintf("(%s IS NULL)", FormatExpr(e.Left))
  113. case *IsDistinctExpr:
  114. op := "IS DISTINCT FROM"
  115. if e.Not {
  116. op = "IS NOT DISTINCT FROM"
  117. }
  118. return fmt.Sprintf("(%s %s %s)", FormatExpr(e.Left), op, FormatExpr(e.Right))
  119. case *SubqueryExpr:
  120. return "(SELECT ...)"
  121. default:
  122. return ""
  123. }
  124. }
  125. // operatorString renders an operator token back to SQL.
  126. func operatorString(op lexer.TokenType) string {
  127. switch op {
  128. case lexer.TokenPlus:
  129. return "+"
  130. case lexer.TokenMinus:
  131. return "-"
  132. case lexer.TokenStar:
  133. return "*"
  134. case lexer.TokenSlash:
  135. return "/"
  136. case lexer.TokenPercent:
  137. return "%"
  138. case lexer.TokenConcat:
  139. return "||"
  140. case lexer.TokenEq:
  141. return "="
  142. case lexer.TokenNeq:
  143. return "<>"
  144. case lexer.TokenLt:
  145. return "<"
  146. case lexer.TokenLte:
  147. return "<="
  148. case lexer.TokenGt:
  149. return ">"
  150. case lexer.TokenGte:
  151. return ">="
  152. case lexer.TokenAND:
  153. return "AND"
  154. case lexer.TokenOR:
  155. return "OR"
  156. case lexer.TokenBitAnd:
  157. return "&"
  158. case lexer.TokenBitOr:
  159. return "|"
  160. case lexer.TokenBitNot:
  161. return "~"
  162. case lexer.TokenShiftLeft:
  163. return "<<"
  164. case lexer.TokenShiftRight:
  165. return ">>"
  166. default:
  167. return op.String()
  168. }
  169. }
  170. // quoteFormatIdent quotes an identifier when it is not a bare word.
  171. func quoteFormatIdent(name string) string {
  172. if name == "" {
  173. return name
  174. }
  175. bare := true
  176. for i := 0; i < len(name); i++ {
  177. c := name[i]
  178. if !(c == '_' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (i > 0 && c >= '0' && c <= '9')) {
  179. bare = false
  180. break
  181. }
  182. }
  183. if bare {
  184. return name
  185. }
  186. return `"` + strings.ReplaceAll(name, `"`, `""`) + `"`
  187. }