Skip to content

Commit d5beca6

Browse files
committed
Optimize SQL generation
1 parent 530fc0b commit d5beca6

File tree

2 files changed

+21
-5
lines changed

2 files changed

+21
-5
lines changed

bench.exs

+14-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
11
import SQL
2+
import Ecto.Query
3+
defmodule SQL.Repo do
4+
use Ecto.Repo, otp_app: :sql, adapter: Ecto.Adapters.Postgres
5+
end
6+
Application.put_env(:sql, :ecto_repos, [SQL.Repo])
7+
Application.put_env(:sql, SQL.Repo, username: "postgres", password: "postgres", hostname: "localhost", database: "sql_test#{System.get_env("MIX_TEST_PARTITION")}", pool: Ecto.Adapters.SQL.Sandbox, pool_size: 10)
8+
SQL.Repo.start_link()
9+
210
range = 1..10_000
11+
sql = ~SQL[with recursive temp (n, fact) as (select 0, 1 union all select n+1, (n+1)*fact from temp where n < 9)]
12+
query = "temp" |> recursive_ctes(true) |> with_cte("temp", as: ^union_all(select("temp", [t], %{n: 0, fact: 1}), ^where(select("temp", [t], [t.n+1, t.n+1*t.fact]), [t], t.n < 9))) |> select([t], [t.n])
313
Benchee.run(
414
%{
5-
"to_stirng" => fn -> for _ <- range, do: to_string(~SQL[with recursive temp (n, fact) as (select 0, 1 union all select n+1, (n+1)*fact from temp where n < 9)]) end,
6-
"to_sql" => fn -> for _ <- range, do: SQL.to_sql(~SQL[with recursive temp (n, fact) as (select 0, 1 union all select n+1, (n+1)*fact from temp where n < 9)]) end,
7-
"inspect" => fn -> for _ <- range, do: inspect(~SQL[with recursive temp (n, fact) as (select 0, 1 union all select n+1, (n+1)*fact from temp where n < 9)]) end
15+
"to_stirng" => fn -> for _ <- range, do: to_string(sql) end,
16+
"to_sql" => fn -> for _ <- range, do: SQL.to_sql(sql) end,
17+
"inspect" => fn -> for _ <- range, do: inspect(sql) end,
18+
"Ecto.Repo.to_sql" => fn -> for _ <- range, do: SQL.Repo.to_sql(:all, query) end
819
},
920
time: 10,
1021
memory_time: 2

lib/sql.ex

+7-2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ defmodule SQL do
3838
{"select id, email from users where email = $0", ["[email protected]"]}
3939
"""
4040
@doc since: "0.1.0"
41-
def to_sql(sql), do: {"#{sql}", sql.params}
41+
def to_sql(sql), do: {sql.string, sql.params}
4242

4343
@doc false
4444
def build(right, {:<<>>, meta, _} = left, _modifiers, env) do
@@ -49,9 +49,11 @@ defmodule SQL do
4949
{v, 0}, {tokens, params} -> {tokens ++ v.tokens, params ++ v.params}
5050
end)
5151
{:ok, opts, _, _, _, _, tokens} = SQL.Lexer.lex(left, binding(), meta, p)
52-
t ++ SQL.Parser.parse(tokens)
52+
sql = t ++ SQL.Parser.parse(tokens)
5353
|> SQL.to_query()
5454
|> Map.merge(%{module: __MODULE__, params: opts[:params]})
55+
56+
Map.put(sql, :string, to_string(sql))
5557
end
5658
end
5759

@@ -108,6 +110,9 @@ defmodule SQL do
108110
end
109111

110112
defimpl String.Chars, for: SQL do
113+
def to_string(%{string: string}) do
114+
string
115+
end
111116
def to_string(sql) do
112117
cond do
113118
Kernel.function_exported?(sql.module, :config, 0) -> Enum.map(sql.query, &sql.module.config()[:adapter].token_to_string(&1))

0 commit comments

Comments
 (0)