Skip to content

Commit ae4d3fd

Browse files
authored
Implement explain query plan (#77)
1 parent edef95f commit ae4d3fd

File tree

1 file changed

+35
-6
lines changed

1 file changed

+35
-6
lines changed

lib/ecto/adapters/sqlite3/connection.ex

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -319,15 +319,48 @@ defmodule Ecto.Adapters.SQLite3.Connection do
319319

320320
@impl true
321321
def explain_query(conn, query, params, opts) do
322-
case query(conn, build_explain_query(query), params, opts) do
322+
type = Keyword.get(opts, :type, :query_plan)
323+
324+
case query(conn, build_explain_query(query, type), params, opts) do
323325
{:ok, %Exqlite.Result{} = result} ->
324-
{:ok, SQL.format_table(result)}
326+
case type do
327+
:query_plan -> {:ok, format_query_plan_explain(result)}
328+
:instructions -> {:ok, SQL.format_table(result)}
329+
end
325330

326331
error ->
327332
error
328333
end
329334
end
330335

336+
defp build_explain_query(query, :query_plan) do
337+
IO.iodata_to_binary(["EXPLAIN QUERY PLAN", query])
338+
end
339+
340+
defp build_explain_query(query, :instructions) do
341+
IO.iodata_to_binary(["EXPLAIN ", query])
342+
end
343+
344+
# Mimics the ASCII format of the sqlite CLI
345+
defp format_query_plan_explain(%{rows: rows}) do
346+
{lines, _} =
347+
rows
348+
|> Enum.chunk_every(2, 1, [nil])
349+
|> Enum.map_reduce(0, fn [[id, parent, _, text], next], depth ->
350+
{branch, next_depth} =
351+
case {id, parent, next} do
352+
{id, _, [_, id, _, _]} -> {"|--", depth + 1}
353+
{_, p, [_, p, _, _]} -> {"|--", depth}
354+
_ -> {"`--", depth - 1}
355+
end
356+
357+
formatted_line = String.duplicate("| ", depth) <> branch <> text
358+
{formatted_line, next_depth}
359+
end)
360+
361+
Enum.join(["QUERY PLAN" | lines], "\n")
362+
end
363+
331364
##
332365
## DDL
333366
##
@@ -654,10 +687,6 @@ defmodule Ecto.Adapters.SQLite3.Connection do
654687
{"SELECT name FROM sqlite_master WHERE type='table' AND name=? LIMIT 1", [table]}
655688
end
656689

657-
def build_explain_query(query) do
658-
IO.iodata_to_binary(["EXPLAIN ", query])
659-
end
660-
661690
##
662691
## Query generation
663692
##

0 commit comments

Comments
 (0)