Skip to content

Commit 9be959f

Browse files
committed
don’t emit ANSI colors on mix format
1 parent 2d22fe0 commit 9be959f

File tree

4 files changed

+100
-64
lines changed

4 files changed

+100
-64
lines changed

lib/format.ex

Lines changed: 95 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ defmodule SQL.Format do
1515

1616
@doc false
1717
@doc since: "0.4.0"
18-
def to_iodata(tokens, context, indent \\ 0), do: pad(to_iodata(tokens, context.binding, context.case, context.errors, indent, []))
18+
def to_iodata(tokens, context, indent, color), do: pad(to_iodata(tokens, color, context.binding, context.case, context.errors, indent, []))
1919

2020
defp indention(acc, [{_, {_,_,_,_,_,0}}|_], _), do: acc
2121
defp indention(acc, [{_, {_,_,_,_,_,0,_,_}}|_], _), do: acc
@@ -34,123 +34,159 @@ defmodule SQL.Format do
3434
newline = ~w[select from join where having window limit offset fetch]a
3535
{reserved, non_reserved, operators} = SQL.BNF.get_rules()
3636
for atom <- Enum.uniq(Enum.map(reserved++non_reserved++operators,&elem(&1, 0))), atom not in newline do
37-
defp to_iodata(unquote(atom), _binding ,:lower, _errors, _indent, acc) do
37+
defp to_iodata(unquote(atom), true, _binding ,:lower, _errors, _indent, acc) do
3838
[@keyword, unquote("#{atom}"), @reset|acc]
3939
end
40-
defp to_iodata(unquote(atom), _binding, :upper, _errors, _indent, acc) do
40+
defp to_iodata(unquote(atom), true, _binding, :upper, _errors, _indent, acc) do
4141
[@keyword, unquote(String.upcase("#{atom}")), @reset|acc]
4242
end
43+
defp to_iodata(unquote(atom), false, _binding ,:lower, _errors, _indent, acc) do
44+
[unquote("#{atom}")|acc]
45+
end
46+
defp to_iodata(unquote(atom), false, _binding, :upper, _errors, _indent, acc) do
47+
[unquote(String.upcase("#{atom}"))|acc]
48+
end
4349
end
4450
for atom <- newline do
45-
defp to_iodata({unquote(atom), _m, values}, binding, :lower=case, errors, indent, acc) do
46-
newline([@keyword, unquote("#{atom}"), @reset|pad(to_iodata(values, binding, case, errors, indent+1, acc))], indent)
51+
defp to_iodata({unquote(atom), _m, values}, true=color, binding, :lower=case, errors, indent, acc) do
52+
newline([@keyword, unquote("#{atom}"), @reset|pad(to_iodata(values, color, binding, case, errors, indent+1, acc))], indent)
53+
end
54+
defp to_iodata({unquote(atom), _m, values}, true=color, binding, :upper=case, errors, indent, acc) do
55+
newline([@keyword, unquote(String.upcase("#{atom}")), @reset|pad(to_iodata(values, color, binding, case, errors, indent+1, acc))], indent)
56+
end
57+
defp to_iodata({unquote(atom), _m, values}, false=color, binding, :lower=case, errors, indent, acc) do
58+
newline([unquote("#{atom}")|pad(to_iodata(values, color, binding, case, errors, indent+1, acc))], indent)
4759
end
48-
defp to_iodata({unquote(atom), _m, values}, binding, :upper=case, errors, indent, acc) do
49-
newline([@keyword, unquote(String.upcase("#{atom}")), @reset|pad(to_iodata(values, binding, case, errors, indent+1, acc))], indent)
60+
defp to_iodata({unquote(atom), _m, values}, false=color, binding, :upper=case, errors, indent, acc) do
61+
newline([unquote(String.upcase("#{atom}"))|pad(to_iodata(values, color, binding, case, errors, indent+1, acc))], indent)
5062
end
5163
end
5264
for atom <- ~w[group order]a do
53-
defp to_iodata({unquote(atom), _m, values}, binding, :lower=case, errors, indent, acc) do
54-
newline([@keyword, unquote("#{atom}"), @reset|to_iodata(values, binding, case, errors, indent, acc)], indent)
65+
defp to_iodata({unquote(atom), _m, values}, true=color, binding, :lower=case, errors, indent, acc) do
66+
newline([@keyword, unquote("#{atom}"), @reset|to_iodata(values, color, binding, case, errors, indent, acc)], indent)
5567
end
56-
defp to_iodata({unquote(atom), _m, values}, binding, :upper=case, errors, indent, acc) do
57-
newline([@keyword, unquote(String.upcase("#{atom}")), @reset|to_iodata(values, binding, case, errors, indent, acc)], indent)
68+
defp to_iodata({unquote(atom), _m, values}, true=color, binding, :upper=case, errors, indent, acc) do
69+
newline([@keyword, unquote(String.upcase("#{atom}")), @reset|to_iodata(values, color, binding, case, errors, indent, acc)], indent)
70+
end
71+
defp to_iodata({unquote(atom), _m, values}, false=color, binding, :lower=case, errors, indent, acc) do
72+
newline([unquote("#{atom}")|to_iodata(values, color, binding, case, errors, indent, acc)], indent)
73+
end
74+
defp to_iodata({unquote(atom), _m, values}, false=color, binding, :upper=case, errors, indent, acc) do
75+
newline([unquote(String.upcase("#{atom}"))|to_iodata(values, color, binding, case, errors, indent, acc)], indent)
5876
end
5977
end
60-
defp to_iodata({tag, m, values}, binding, case, errors, indent, acc) when tag in ~w[by on]a do
61-
indention(to_iodata(tag, binding, case, errors, 0, newline(to_iodata(values, binding, case, errors, indent, acc), indent)), m, 0)
78+
defp to_iodata({tag, m, values}, color, binding, case, errors, indent, acc) when tag in ~w[by on]a do
79+
indention(to_iodata(tag, color, binding, case, errors, 0, newline(to_iodata(values, color, binding, case, errors, indent, acc), indent)), m, 0)
6280
end
63-
defp to_iodata(:comma, _binding, _case, _errors, 0, acc) do
81+
defp to_iodata(:comma, _color, _binding, _case, _errors, 0, acc) do
6482
[?,|acc]
6583
end
66-
defp to_iodata(:comma, _binding, _case, _errors, _indent, acc) do
84+
defp to_iodata(:comma, _color, _binding, _case, _errors, _indent, acc) do
6785
[?,|pad(acc)]
6886
end
69-
defp to_iodata(:dot, _binding, _case, _errors, _indent, acc) do
87+
defp to_iodata(:dot, _color, _binding, _case, _errors, _indent, acc) do
7088
[?.|acc]
7189
end
72-
defp to_iodata(:paren, _binding, _case, _errors, _indent, acc) do
90+
defp to_iodata(:paren, _color, _binding, _case, _errors, _indent, acc) do
7391
[?(,?)|acc]
7492
end
75-
defp to_iodata({:colon, _m, values}, binding, case, errors, indent, acc) do
76-
to_iodata(values, binding, case, errors, indent, [?;|acc])
93+
defp to_iodata({:colon, _m, values}, color, binding, case, errors, indent, acc) do
94+
to_iodata(values, color, binding, case, errors, indent, [?;|acc])
7795
end
78-
defp to_iodata({:binding, m, [idx]}, binding, _case, _errors, indent, acc) do
96+
defp to_iodata({:binding, m, [idx]}, _color, binding, _case, _errors, indent, acc) do
7997
indention([?{,?{,Macro.to_string(Enum.at(binding, idx-1)),?},?}|acc], m, indent)
8098
end
81-
defp to_iodata({:comment, _m, value}, _binding, _case, _errors, _indent, acc) do
99+
defp to_iodata({:comment, _m, value}, _color, _binding, _case, _errors, _indent, acc) do
82100
[?-,?-,value|acc]
83101
end
84-
defp to_iodata({:comments, _m, value}, _binding, _case, _errors, _indent, acc) do
102+
defp to_iodata({:comments, _m, value}, _color, _binding, _case, _errors, _indent, acc) do
85103
[?\\,?*,value,?*,?\\|acc]
86104
end
87-
defp to_iodata({:quote, m, value}, _binding, _case, _errors, indent, acc) do
105+
defp to_iodata({:quote, m, value}, true, _binding, _case, _errors, indent, acc) do
88106
indention([?',@enclosed, value, @reset,?'|acc], m, indent)
89107
end
90-
defp to_iodata({:backtick, m, value}, _binding, _case, _errors, indent, acc) do
108+
defp to_iodata({:quote, m, value}, false, _binding, _case, _errors, indent, acc) do
109+
indention([?', value,?'|acc], m, indent)
110+
end
111+
defp to_iodata({:backtick, m, value}, true, _binding, _case, _errors, indent, acc) do
91112
indention([?`,@enclosed, value, @reset,?`|acc], m, indent)
92113
end
93-
defp to_iodata({tag, m, []}, binding, case, errors, indent, acc) do
94-
indention(to_iodata(tag, binding, case, errors, indent, acc), m, indent)
114+
defp to_iodata({:backtick, m, value}, false, _binding, _case, _errors, indent, acc) do
115+
indention([?`, value,?`|acc], m, indent)
95116
end
96-
defp to_iodata({:paren, m, [{t, _, _}|_]=values}, binding, case, errors, indent, acc) when t in unquote(newline++~w[group order union except intersect]a) do
97-
indention([?(|to_iodata(values, binding, case, errors, indent+1, [?\n,?)|acc])], m, indent)
117+
defp to_iodata({tag, m, []}, color, binding, case, errors, indent, acc) do
118+
indention(to_iodata(tag, color, binding, case, errors, indent, acc), m, indent)
98119
end
99-
defp to_iodata({:paren, m, values}, binding, case, errors, indent, acc) do
100-
indention([?(|to_iodata(values, binding, case, errors, 0, [?)|acc])], m, indent)
120+
defp to_iodata({:paren, m, [{t, _, _}|_]=values}, color, binding, case, errors, indent, acc) when t in unquote(newline++~w[group order union except intersect]a) do
121+
indention([?(|to_iodata(values, color, binding, case, errors, indent+1, [?\n,?)|acc])], m, indent)
101122
end
102-
defp to_iodata({:bracket, m, values}, binding, case, errors, indent, acc) do
103-
indention([?[|to_iodata(values, binding, case, errors, 0, [?]|acc])], m, indent)
123+
defp to_iodata({:paren, m, values}, color, binding, case, errors, indent, acc) do
124+
indention([?(|to_iodata(values, color, binding, case, errors, 0, [?)|acc])], m, indent)
104125
end
105-
defp to_iodata({:brace, m, values}, binding, case, errors, indent, acc) do
106-
indention([?{|to_iodata(values, binding, case, errors, 0, [?}|acc])], m, indent)
126+
defp to_iodata({:bracket, m, values}, color, binding, case, errors, indent, acc) do
127+
indention([?[|to_iodata(values, color, binding, case, errors, 0, [?]|acc])], m, indent)
107128
end
108-
defp to_iodata({_, [], values}, binding, case, errors, indent, acc) do
109-
to_iodata(values, binding, case, errors, indent, acc)
129+
defp to_iodata({:brace, m, values}, color, binding, case, errors, indent, acc) do
130+
indention([?{|to_iodata(values, color, binding, case, errors, 0, [?}|acc])], m, indent)
110131
end
111-
defp to_iodata({:ident, [_,_,{:tag, tag}|_]=m, [{:paren, _, _}]=values}, binding, case, errors, indent, acc) do
112-
indention(to_iodata(tag, binding, case, errors, indent, to_iodata(values, binding, case, errors, indent, acc)), m, indent)
132+
defp to_iodata({_, [], values}, color, binding, case, errors, indent, acc) do
133+
to_iodata(values, color, binding, case, errors, indent, acc)
113134
end
114-
defp to_iodata({tag, [{_, {l,c,_,_,_,_}}|_]=m, [{_, [{_, {l,lc,_,_,_,_}}|_], _}=left, {_, [{_, {l,rc,_,_,_,_}}|_], _}=right]}, binding, case, errors, indent, acc) when (c > lc and c < rc) do
115-
to_iodata(left, binding, case, errors, indent, indention(to_iodata(tag, binding, case, errors, 0, to_iodata(right, binding, case, errors, 0, acc)), m, 0))
135+
defp to_iodata({:ident, [_,_,{:tag, tag}|_]=m, [{:paren, _, _}]=values},color, binding, case, errors, indent, acc) do
136+
indention(to_iodata(tag, color, binding, case, errors, indent, to_iodata(values, color, binding, case, errors, indent, acc)), m, indent)
116137
end
117-
defp to_iodata({tag, [{_, {l,c,_,_,_,_}}|_]=m, [{_, [{_, {l,lc,_,_,_,_,_,_}}|_], _}=left, {_, [{_, {l,rc,_,_,_,_,_,_}}|_], _}=right]}, binding, case, errors, indent, acc) when (c > lc and c < rc) do
118-
to_iodata(left, binding, case, errors, indent, indention(to_iodata(tag, binding, case, errors, 0, to_iodata(right, binding, case, errors, 0, acc)), m, 0))
138+
defp to_iodata({tag, [{_, {l,c,_,_,_,_}}|_]=m, [{_, [{_, {l,lc,_,_,_,_}}|_], _}=left, {_, [{_, {l,rc,_,_,_,_}}|_], _}=right]}, color, binding, case, errors, indent, acc) when (c > lc and c < rc) do
139+
to_iodata(left, color, binding, case, errors, indent, indention(to_iodata(tag, color, binding, case, errors, 0, to_iodata(right, color, binding, case, errors, 0, acc)), m, 0))
119140
end
120-
defp to_iodata({tag, [{_, {l,c,_,_,_,_}}|_]=m, [{_, [{_, {l,lc,_,_,_,_}}|_], _}=left, {_, [{_, {l,rc,_,_,_,_,_,_}}|_], _}=right]}, binding, case, errors, indent, acc) when (c > lc and c < rc) do
121-
to_iodata(left, binding, case, errors, indent, indention(to_iodata(tag, binding, case, errors, 0, to_iodata(right, binding, case, errors, 0, acc)), m, 0))
141+
defp to_iodata({tag, [{_, {l,c,_,_,_,_}}|_]=m, [{_, [{_, {l,lc,_,_,_,_,_,_}}|_], _}=left, {_, [{_, {l,rc,_,_,_,_,_,_}}|_], _}=right]}, color, binding, case, errors, indent, acc) when (c > lc and c < rc) do
142+
to_iodata(left, color, binding, case, errors, indent, indention(to_iodata(tag, color, binding, case, errors, 0, to_iodata(right, color, binding, case, errors, 0, acc)), m, 0))
122143
end
123-
defp to_iodata({tag, [{_, {l,c,_,_,_,_}}|_]=m, [{_, [{_, {l,lc,_,_,_,_,_,_}}|_], _}=left, {_, [{_, {l,rc,_,_,_,_}}|_], _}=right]}, binding, case, errors, indent, acc) when (c > lc and c < rc) do
124-
to_iodata(left, binding, case, errors, indent, indention(to_iodata(tag, binding, case, errors, 0, to_iodata(right, binding, case, errors, 0, acc)), m, 0))
144+
defp to_iodata({tag, [{_, {l,c,_,_,_,_}}|_]=m, [{_, [{_, {l,lc,_,_,_,_}}|_], _}=left, {_, [{_, {l,rc,_,_,_,_,_,_}}|_], _}=right]}, color, binding, case, errors, indent, acc) when (c > lc and c < rc) do
145+
to_iodata(left, color, binding, case, errors, indent, indention(to_iodata(tag, color, binding, case, errors, 0, to_iodata(right, color, binding, case, errors, 0, acc)), m, 0))
125146
end
126-
defp to_iodata({tag, [{_, {l,c,_,_,_,_}}|_]=m, [{_, [{_, {ll,cc,_,_,_,_}}|_], _}]=values}, binding, case, errors, indent, acc) when (l == ll and c < cc and tag in ~w[desc asc not]a) do
127-
to_iodata(values, binding, case, errors, indent, indention(to_iodata(tag, binding, case, errors, indent, acc), m, 0))
147+
defp to_iodata({tag, [{_, {l,c,_,_,_,_}}|_]=m, [{_, [{_, {l,lc,_,_,_,_,_,_}}|_], _}=left, {_, [{_, {l,rc,_,_,_,_}}|_], _}=right]}, color, binding, case, errors, indent, acc) when (c > lc and c < rc) do
148+
to_iodata(left, color, binding, case, errors, indent, indention(to_iodata(tag, color, binding, case, errors, 0, to_iodata(right, color, binding, case, errors, 0, acc)), m, 0))
128149
end
129-
defp to_iodata({tag, [{_, {l,c,_,_,_,_}}|_]=m, [{_, [{_, {ll,cc,_,_,_,_,_,_}}|_], _}]=values}, binding, case, errors, indent, acc) when (l == ll and c < cc and tag in ~w[desc asc not]a) do
130-
to_iodata(values, binding, case, errors, indent, indention(to_iodata(tag, binding, case, errors, indent, acc), m, 0))
150+
defp to_iodata({tag, [{_, {l,c,_,_,_,_}}|_]=m, [{_, [{_, {ll,cc,_,_,_,_}}|_], _}]=values}, color, binding, case, errors, indent, acc) when (l == ll and c < cc and tag in ~w[desc asc not]a) do
151+
to_iodata(values, color, binding, case, errors, indent, indention(to_iodata(tag, color, binding, case, errors, indent, acc), m, 0))
131152
end
132-
defp to_iodata({tag, _m, [left, right]}, binding, case, errors, indent, acc) when tag in ~w[union except intersect]a do
133-
to_iodata(left, binding, case, errors, indent, newline(to_iodata(tag, binding, case, errors, indent, to_iodata(right, binding, case, errors, indent, acc)), indent))
153+
defp to_iodata({tag, [{_, {l,c,_,_,_,_}}|_]=m, [{_, [{_, {ll,cc,_,_,_,_,_,_}}|_], _}]=values}, color, binding, case, errors, indent, acc) when (l == ll and c < cc and tag in ~w[desc asc not]a) do
154+
to_iodata(values, color, binding, case, errors, indent, indention(to_iodata(tag, color, binding, case, errors, indent, acc), m, 0))
134155
end
135-
defp to_iodata({tag, m, [{_,_,_}|_]=values}, binding, case, errors, indent, acc) do
136-
indention(to_iodata(tag, binding, case, errors, indent, to_iodata(values, binding, case, errors, indent, acc)), m, 0)
156+
defp to_iodata({tag, _m, [left, right]}, color, binding, case, errors, indent, acc) when tag in ~w[union except intersect]a do
157+
to_iodata(left, color, binding, case, errors, indent, newline(to_iodata(tag, color, binding, case, errors, indent, to_iodata(right, color, binding, case, errors, indent, acc)), indent))
137158
end
138-
defp to_iodata({tag, m, value}=node, _binding, _case, errors, indent, acc) when tag in ~w[ident numeric special]a do
159+
defp to_iodata({tag, m, [{_,_,_}|_]=values}, color, binding, case, errors, indent, acc) do
160+
indention(to_iodata(tag, color, binding, case, errors, indent, to_iodata(values, color, binding, case, errors, indent, acc)), m, 0)
161+
end
162+
defp to_iodata({tag, m, value}=node, true, _binding, _case, errors, indent, acc) when tag in ~w[ident numeric special]a do
139163
case node in errors do
140164
true -> indention([@error, value, @reset|acc], m, indent)
141165
false -> indention([@literal, value, @reset|acc], m, indent)
142166
end
143167
end
144-
defp to_iodata({:double_quote, m, value}=node, _binding, _case, errors, indent, acc) do
168+
defp to_iodata({tag, m, value}=node, false, _binding, _case, errors, indent, acc) when tag in ~w[ident numeric special]a do
169+
case node in errors do
170+
true -> indention([value|acc], m, indent)
171+
false -> indention([value|acc], m, indent)
172+
end
173+
end
174+
defp to_iodata({:double_quote, m, value}=node, true, _binding, _case, errors, indent, acc) do
145175
case node in errors do
146176
true -> indention([?",@error,value, @reset, ?"|acc], m, indent)
147177
false -> indention([?", @enclosed , value, @reset, ?"|acc], m, indent)
148178
end
149179
end
150-
defp to_iodata([token|tokens], binding, case, errors, indent, acc) do
151-
to_iodata(token, binding, case, errors, indent, to_iodata(tokens, binding, case, errors, indent, acc))
180+
defp to_iodata({:double_quote, m, value}=node, false, _binding, _case, errors, indent, acc) do
181+
case node in errors do
182+
true -> indention([?",value, ?"|acc], m, indent)
183+
false -> indention([?", value, ?"|acc], m, indent)
184+
end
185+
end
186+
defp to_iodata([token|tokens], color, binding, case, errors, indent, acc) do
187+
to_iodata(token, color, binding, case, errors, indent, to_iodata(tokens, color, binding, case, errors, indent, acc))
152188
end
153-
defp to_iodata([], _binding, _case, _errors, _indent, acc) do
189+
defp to_iodata([], _color, _binding, _case, _errors, _indent, acc) do
154190
acc
155191
end
156192
end

lib/formatter.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ defmodule SQL.MixFormatter do
1313
opts = Map.new(Keyword.merge([validate: nil], opts))
1414
{:ok, context, tokens} = SQL.Lexer.lex(source)
1515
{:ok, context, tokens} = SQL.Parser.parse(tokens, Map.merge(context, opts))
16-
if context.errors != [], do: IO.warn([?\n,SQL.format_error(context.errors)," \n ",SQL.Format.to_iodata(tokens, context, 1),?\n])
17-
IO.iodata_to_binary(SQL.Format.to_iodata(tokens, context))
16+
if context.errors != [], do: IO.warn([?\n,SQL.format_error(context.errors)," \n ",SQL.Format.to_iodata(tokens, context, 1, true),?\n])
17+
IO.iodata_to_binary(SQL.Format.to_iodata(tokens, context, 0, false))
1818
end
1919
end

lib/sql.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,12 +224,12 @@ defmodule SQL do
224224

225225
@doc false
226226
def __inspect__(tokens, context, stack) do
227-
inspect = IO.iodata_to_binary([@reset, "~SQL\"\"\""|[SQL.Format.to_iodata(tokens, context)|~c"\n\"\"\""]])
227+
inspect = IO.iodata_to_binary([@reset, "~SQL\"\"\""|[SQL.Format.to_iodata(tokens, context, 0, true)|~c"\n\"\"\""]])
228228
case context.errors do
229229
[] -> inspect
230230
errors ->
231231
{:current_stacktrace, [_|t]} = Process.info(self(), :current_stacktrace)
232-
IO.warn([?\n,format_error(errors), IO.iodata_to_binary([@reset, " ~SQL\"\"\""|[SQL.Format.to_iodata(tokens, context, 1)|~c"\n \"\"\""]])], [stack|t])
232+
IO.warn([?\n,format_error(errors), IO.iodata_to_binary([@reset, " ~SQL\"\"\""|[SQL.Format.to_iodata(tokens, context, 1, true)|~c"\n \"\"\""]])], [stack|t])
233233
inspect
234234
end
235235
end

test/formatter_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ defmodule SQL.FormatterTest do
99
end
1010

1111
test "format/2 preserve interpolation" do
12-
assert "\n\e[35mwith\e[0m \e[35mrecursive\e[0m \e[33mtemp\e[0m(\e[33mn\e[0m, \e[33mfact\e[0m) \e[35mas\e[0m (\n \e[35mselect\e[0m\n \e[33m0\e[0m,\n \e[33m1\e[0m\n \e[35munion\e[0m \e[35mall\e[0m\n \e[35mselect\e[0m\n \e[33mn\e[0m \e[35m+\e[0m {{one}},\n (\e[33mn\e[0m \e[35m+\e[0m {{one}}) \e[35m*\e[0m \e[33mfact\e[0m\n \e[35mfrom\e[0m\n \e[33mtemp\e[0m\n \e[35mwhere\e[0m\n \e[33mn\e[0m \e[35m<\e[0m \e[33m9\e[0m\n)" == SQL.MixFormatter.format("with recursive temp(n, fact) as (select 0, 1 union all select n + {{one}}, (n + {{one}}) * fact from temp where n < 9)", [])
12+
assert "\nwith recursive temp(n, fact) as (\n select\n 0,\n 1\n union all\n select\n n + {{one}},\n (n + {{one}}) * fact\n from\n temp\n where\n n < 9\n)" == SQL.MixFormatter.format("with recursive temp(n, fact) as (select 0, 1 union all select n + {{one}}, (n + {{one}}) * fact from temp where n < 9)", [])
1313
end
1414
end

0 commit comments

Comments
 (0)