Skip to content

Commit b5bb5bd

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

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, num_rows, query), ?)]
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, num_rows, query) do
1558+
col_names = Enum.map(types, &elem(&1, 0)) |> Enum.join(", ")
1559+
rows = :lists.seq(1, num_rows, 1)
1560+
1561+
[
1562+
"WITH xxx(",
1563+
col_names,
1564+
") AS (VALUES ",
1565+
Enum.map_intersperse(rows, ?,, fn _ ->
1566+
[?(, values_expr(types, query), ?)]
1567+
end),
1568+
") SELECT * FROM xxx"
1569+
]
1570+
end
1571+
1572+
defp values_expr(types, _query) do
1573+
Enum.map_intersperse(types, ?,, fn {_field, type} ->
1574+
# TODO: cast?
1575+
# ["CAST(", ??, " AS ", ecto_cast_to_db(type, query), ?)]
1576+
??
1577+
end)
1578+
end
1579+
1580+
# defp ecto_cast_to_db(:id, _query), do: "INTEGER"
1581+
# defp ecto_cast_to_db(:integer, _query), do: "INTEGER"
1582+
# defp ecto_cast_to_db(:string, _query), do: "char"
1583+
# defp ecto_cast_to_db(:utc_datetime_usec, _query), do: "datetime(6)"
1584+
# defp ecto_cast_to_db(:naive_datetime_usec, _query), do: "datetime(6)"
1585+
# defp ecto_cast_to_db(_type, _query), do: "TEXT"
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)