Skip to content

Commit bbd1dbb

Browse files
author
spicychickensauce
committed
Implement values via CTE
1 parent ff6b2e1 commit bbd1dbb

File tree

1 file changed

+35
-8
lines changed

1 file changed

+35
-8
lines changed

lib/ecto/adapters/sqlite3/connection.ex

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,12 +1037,6 @@ defmodule Ecto.Adapters.SQLite3.Connection do
10371037
message: "join hints are not supported by SQLite3"
10381038
end
10391039

1040-
defp assert_valid_join(%JoinExpr{source: {:values, _, _}}, query) do
1041-
raise Ecto.QueryError,
1042-
query: query,
1043-
message: "SQLite3 adapter does not support values lists"
1044-
end
1045-
10461040
defp assert_valid_join(_join_expr, _query), do: :ok
10471041

10481042
defp join_on(:cross, true, _sources, _query), do: []
@@ -1368,8 +1362,8 @@ defmodule Ecto.Adapters.SQLite3.Connection do
13681362
|> parens_for_select
13691363
end
13701364

1371-
defp expr({:values, _, _}, _, _query) do
1372-
raise ArgumentError, "SQLite3 adapter does not support values lists"
1365+
defp expr({:values, _, [types, idx, num_rows]}, _, _query) do
1366+
[?(, values_list(types, idx + 1, num_rows), ?)]
13731367
end
13741368

13751369
defp expr({:identifier, _, [literal]}, _sources, _query) do
@@ -1560,6 +1554,36 @@ defmodule Ecto.Adapters.SQLite3.Connection do
15601554
message: "unsupported expression #{inspect(expr)}"
15611555
end
15621556

1557+
defp values_list(types, idx, num_rows) do
1558+
rows = :lists.seq(1, num_rows, 1)
1559+
col_names = Enum.map_join(types, ", ", &elem(&1, 0))
1560+
1561+
[
1562+
"WITH xxx(",
1563+
col_names,
1564+
") AS (VALUES ",
1565+
intersperse_reduce(rows, ?,, idx, fn _, idx ->
1566+
{value, idx} = values_expr(types, idx)
1567+
{[?(, value, ?)], idx}
1568+
end)
1569+
|> elem(0),
1570+
") SELECT * FROM xxx"
1571+
]
1572+
end
1573+
1574+
defp values_expr(types, idx) do
1575+
intersperse_reduce(types, ?,, idx, fn {_field, _type}, idx ->
1576+
# TODO: cast?
1577+
# {[?$, Integer.to_string(idx), ?:, ?: | tagged_to_db(type)], idx + 1}
1578+
{[?$, Integer.to_string(idx)], idx + 1}
1579+
end)
1580+
end
1581+
1582+
# defp tagged_to_db(:id), do: "bigint"
1583+
# defp tagged_to_db(:integer), do: "bigint"
1584+
# defp tagged_to_db({:array, type}), do: [tagged_to_db(type), ?[, ?]]
1585+
# defp tagged_to_db(type), do: ecto_to_db(type)
1586+
15631587
def interval(_, "microsecond", _sources) do
15641588
raise ArgumentError,
15651589
"SQLite does not support microsecond precision in datetime intervals"
@@ -1618,6 +1642,9 @@ defmodule Ecto.Adapters.SQLite3.Connection do
16181642
{:fragment, _, _} ->
16191643
{nil, as_prefix ++ [?f | Integer.to_string(pos)], nil}
16201644

1645+
{:values, _, _} ->
1646+
{nil, as_prefix ++ [?v | Integer.to_string(pos)], nil}
1647+
16211648
{table, schema, prefix} ->
16221649
name = as_prefix ++ [create_alias(table) | Integer.to_string(pos)]
16231650
{quote_table(prefix, table), name, schema}

0 commit comments

Comments
 (0)