diff --git a/integration_test/constraints_test.exs b/integration_test/constraints_test.exs index eaa2697..229d871 100644 --- a/integration_test/constraints_test.exs +++ b/integration_test/constraints_test.exs @@ -39,6 +39,7 @@ defmodule Ecto.Integration.ConstraintsTest do :ok end + @tag :create_constraint test "check constraint" do changeset = Ecto.Changeset.change(%Constraint{}, fromm: 0, too: 10) {:ok, _} = PoolRepo.insert(changeset) diff --git a/integration_test/test_helper.exs b/integration_test/test_helper.exs index 5ce6d69..ebe16d3 100644 --- a/integration_test/test_helper.exs +++ b/integration_test/test_helper.exs @@ -57,6 +57,85 @@ _ = Ecto.Adapters.SQLite3.storage_down(PoolRepo.config()) {:ok, _} = TestRepo.start_link() {:ok, _pid} = PoolRepo.start_link() +excludes = [ + :delete_with_join, + :right_join, + + # SQLite does not have an array type + :array_type, + :transaction_isolation, + :insert_cell_wise_defaults, + :insert_select, + + # sqlite does not support microsecond precision, only millisecond + :microsecond_precision, + + # sqlite supports FKs, but does not return sufficient data + # for ecto to support matching on a given constraint violation name + # which is what most of the tests validate + :foreign_key_constraint, + + # SQLite with DSQLITE_LIKE_DOESNT_MATCH_BLOBS=1 + # does not support using LIKE on BLOB types + :like_match_blob, + + # SQLite will return a string for schemaless map types as + # Ecto does not have enough information to call the associated loader + # that converts the string JSON representaiton into a map + :map_type_schemaless, + + # right now in lock_for_migrations() we do effectively nothing, this is because + # SQLite is single-writer so there isn't really a need for us to do anything. + # ecto assumes all implementing adapters need >=2 connections for migrations + # which is not true for SQLite + :lock_for_migrations, + + # Migration we don't support + :prefix, + :add_column_if_not_exists, + :remove_column_if_exists, + :alter_primary_key, + :alter_foreign_key, + :assigns_id_type, + :modify_column, + :restrict, + + # SQLite3 does not support the concat function + :concat, + + # SQLite3 does not support placeholders + :placeholders, + + # SQLite3 stores booleans as integers, causing Ecto's json_extract_path tests to fail + :json_extract_path, + + # SQLite3 doesn't support specifying columns for ON DELETE SET NULL + :on_delete_nilify_column_list, + + # not sure how to support this yet + :bitstring_type, + + # sqlite does not have a duration type... yet + :duration_type, + + # We don't support selected_as + :selected_as_with_group_by, + :selected_as_with_order_by, + :selected_as_with_order_by_expression, + :selected_as_with_having, + + # Distinct with options not supported + :distinct_count, + + # SQLite does not support anything except a single column in DISTINCT + :multicolumn_distinct, + + # Values list + :values_list +] + +ExUnit.configure(exclude: excludes) + # migrate the pool repo case Ecto.Migrator.migrated_versions(PoolRepo) do [] -> @@ -71,64 +150,4 @@ end Ecto.Adapters.SQL.Sandbox.mode(TestRepo, :manual) Process.flag(:trap_exit, true) -ExUnit.start( - exclude: [ - :delete_with_join, - :right_join, - # SQLite does not have an array type - :array_type, - :transaction_isolation, - :insert_cell_wise_defaults, - :insert_select, - # sqlite does not support microsecond precision, only millisecond - :microsecond_precision, - # sqlite supports FKs, but does not return sufficient data - # for ecto to support matching on a given constraint violation name - # which is what most of the tests validate - :foreign_key_constraint, - # SQLite with DSQLITE_LIKE_DOESNT_MATCH_BLOBS=1 - # does not support using LIKE on BLOB types - :like_match_blob, - # SQLite will return a string for schemaless map types as - # Ecto does not have enough information to call the associated loader - # that converts the string JSON representaiton into a map - :map_type_schemaless, - - # right now in lock_for_migrations() we do effectively nothing, this is because - # SQLite is single-writer so there isn't really a need for us to do anything. - # ecto assumes all implementing adapters need >=2 connections for migrations - # which is not true for SQLite - :lock_for_migrations, - - # Migration we don't support - :prefix, - :add_column_if_not_exists, - :remove_column_if_exists, - :alter_primary_key, - :alter_foreign_key, - :assigns_id_type, - :modify_column, - :restrict, - - # SQLite3 does not support the concat function - :concat, - # SQLite3 does not support placeholders - :placeholders, - # SQLite3 stores booleans as integers, causing Ecto's json_extract_path tests to fail - :json_extract_path, - # SQLite3 doesn't support specifying columns for ON DELETE SET NULL - :on_delete_nilify_column_list, - - # We don't support selected_as - :selected_as_with_group_by, - :selected_as_with_order_by, - :selected_as_with_order_by_expression, - :selected_as_with_having, - - # Distinct with options not supported - :distinct_count, - - # Values list - :values_list - ] -) +ExUnit.start() diff --git a/lib/ecto/adapters/sqlite3/connection.ex b/lib/ecto/adapters/sqlite3/connection.ex index a991f5e..790d1c7 100644 --- a/lib/ecto/adapters/sqlite3/connection.ex +++ b/lib/ecto/adapters/sqlite3/connection.ex @@ -9,6 +9,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do alias Ecto.Migration.Reference alias Ecto.Migration.Table alias Ecto.Query.BooleanExpr + alias Ecto.Query.ByExpr alias Ecto.Query.JoinExpr alias Ecto.Query.QueryExpr alias Ecto.Query.WithExpr @@ -284,10 +285,10 @@ defmodule Ecto.Adapters.SQLite3.Connection do @impl true def update(prefix, table, fields, filters, returning) do - fields = intersperse_map(fields, ", ", &[quote_name(&1), " = ?"]) + fields = Enum.map_intersperse(fields, ", ", &[quote_name(&1), " = ?"]) filters = - intersperse_map(filters, " AND ", fn + Enum.map_intersperse(filters, " AND ", fn {field, nil} -> [quote_name(field), " IS NULL"] @@ -309,7 +310,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do @impl true def delete(prefix, table, filters, returning) do filters = - intersperse_map(filters, " AND ", fn + Enum.map_intersperse(filters, " AND ", fn {field, nil} -> [quote_name(field), " IS NULL"] @@ -481,7 +482,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do @impl true def execute_ddl({:create, %Index{} = index}) do - fields = intersperse_map(index.columns, ", ", &index_expr/1) + fields = Enum.map_intersperse(index.columns, ", ", &index_expr/1) [ [ @@ -501,7 +502,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do @impl true def execute_ddl({:create_if_not_exists, %Index{} = index}) do - fields = intersperse_map(index.columns, ", ", &index_expr/1) + fields = Enum.map_intersperse(index.columns, ", ", &index_expr/1) [ [ @@ -590,7 +591,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do @impl true def execute_ddl({:create, %Index{} = index}) do - fields = intersperse_map(index.columns, ", ", &index_expr/1) + fields = Enum.map_intersperse(index.columns, ", ", &index_expr/1) [ [ @@ -610,7 +611,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do end def execute_ddl({:create_if_not_exists, %Index{} = index}) do - fields = intersperse_map(index.columns, ", ", &index_expr/1) + fields = Enum.map_intersperse(index.columns, ", ", &index_expr/1) [ [ @@ -752,13 +753,13 @@ defmodule Ecto.Adapters.SQLite3.Connection do do: [fragment, ?\s] defp conflict_target(targets) do - [?(, intersperse_map(targets, ?,, "e_name/1), ?), ?\s] + [?(, Enum.map_intersperse(targets, ?,, "e_name/1), ?), ?\s] end defp replace(fields) do [ "UPDATE SET " - | intersperse_map(fields, ?,, fn field -> + | Enum.map_intersperse(fields, ?,, fn field -> quoted = quote_name(field) [quoted, " = ", "EXCLUDED." | quoted] end) @@ -767,12 +768,6 @@ defmodule Ecto.Adapters.SQLite3.Connection do def insert_all(rows, on_conflict), do: insert_all(rows, on_conflict, 1) - def insert_all(%Ecto.Query{wheres: []} = _query, on_conflict, _counter) - when not is_nil(on_conflict) do - raise ArgumentError, - "SQLite3 requires a where clause to avoid ambiguity. Even simply specify where: true will work" - end - def insert_all(%Ecto.Query{} = query, _on_conflict, _counter) do [all(query)] end @@ -844,16 +839,16 @@ defmodule Ecto.Adapters.SQLite3.Connection do def handle_call(fun, _arity), do: {:fun, Atom.to_string(fun)} defp distinct(nil, _sources, _query), do: [] - defp distinct(%QueryExpr{expr: true}, _sources, _query), do: "DISTINCT " - defp distinct(%QueryExpr{expr: false}, _sources, _query), do: [] + defp distinct(%ByExpr{expr: true}, _sources, _query), do: "DISTINCT " + defp distinct(%ByExpr{expr: false}, _sources, _query), do: [] - defp distinct(%QueryExpr{expr: exprs}, _sources, query) when is_list(exprs) do + defp distinct(%ByExpr{expr: exprs}, _sources, query) when is_list(exprs) do raise Ecto.QueryError, query: query, message: "DISTINCT with multiple columns is not supported by SQLite3" end - def select(%{select: %{fields: fields}, distinct: distinct} = query, sources) do + defp select(%{select: %{fields: fields}, distinct: distinct} = query, sources) do [ "SELECT ", distinct(distinct, sources, query) | select_fields(fields, sources, query) @@ -863,7 +858,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do defp select_fields([], _sources, _query), do: "1" defp select_fields(fields, sources, query) do - intersperse_map(fields, ", ", fn + Enum.map_intersperse(fields, ", ", fn {:&, _, [idx]} -> case elem(sources, idx) do {source, _, nil} -> @@ -905,7 +900,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do sources ) do recursive_opt = if recursive, do: "RECURSIVE ", else: "" - ctes = intersperse_map(queries, ", ", &cte_expr(&1, sources, query)) + ctes = Enum.map_intersperse(queries, ", ", &cte_expr(&1, sources, query)) [ "WITH ", @@ -992,7 +987,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do defp using_join(%{joins: joins} = query, _kind, prefix, sources) do froms = - intersperse_map(joins, ", ", fn + Enum.map_intersperse(joins, ", ", fn %JoinExpr{qual: _qual, ix: ix, source: source} -> {join, name} = get_source(query, sources, ix, source) [join, " AS " | name] @@ -1065,8 +1060,8 @@ defmodule Ecto.Adapters.SQLite3.Connection do def group_by(%{group_bys: group_bys} = query, sources) do [ " GROUP BY " - | intersperse_map(group_bys, ", ", fn %QueryExpr{expr: expression} -> - intersperse_map(expression, ", ", &expr(&1, sources, query)) + | Enum.map_intersperse(group_bys, ", ", fn %ByExpr{expr: expression} -> + Enum.map_intersperse(expression, ", ", &top_level_expr(&1, sources, query)) end) ] end @@ -1076,22 +1071,25 @@ defmodule Ecto.Adapters.SQLite3.Connection do def window(%{windows: windows} = query, sources) do [ " WINDOW " - | intersperse_map(windows, ", ", fn {name, %{expr: kw}} -> + | Enum.map_intersperse(windows, ", ", fn {name, %{expr: kw}} -> [quote_name(name), " AS " | window_exprs(kw, sources, query)] end) ] end defp window_exprs(kw, sources, query) do - [?(, intersperse_map(kw, ?\s, &window_expr(&1, sources, query)), ?)] + [?(, Enum.map_intersperse(kw, ?\s, &window_expr(&1, sources, query)), ?)] end defp window_expr({:partition_by, fields}, sources, query) do - ["PARTITION BY " | intersperse_map(fields, ", ", &expr(&1, sources, query))] + ["PARTITION BY " | Enum.map_intersperse(fields, ", ", &expr(&1, sources, query))] end defp window_expr({:order_by, fields}, sources, query) do - ["ORDER BY " | intersperse_map(fields, ", ", &order_by_expr(&1, sources, query))] + [ + "ORDER BY " + | Enum.map_intersperse(fields, ", ", &order_by_expr(&1, sources, query)) + ] end defp window_expr({:frame, {:fragment, _, _} = fragment}, sources, query) do @@ -1105,12 +1103,12 @@ defmodule Ecto.Adapters.SQLite3.Connection do [ " ORDER BY " - | intersperse_map(order_bys, ", ", &order_by_expr(&1, sources, query)) + | Enum.map_intersperse(order_bys, ", ", &order_by_expr(&1, sources, query)) ] end defp order_by_expr({dir, expression}, sources, query) do - str = expr(expression, sources, query) + str = top_level_expr(expression, sources, query) case dir do :asc -> @@ -1219,78 +1217,93 @@ defmodule Ecto.Adapters.SQLite3.Connection do [?(, expr(expression, sources, query), ?)] end + defp top_level_expr(%Ecto.SubQuery{query: query}, sources, parent_query) do + combinations = + Enum.map(query.combinations, fn {type, combination_query} -> + {type, put_in(combination_query.aliases[@parent_as], {parent_query, sources})} + end) + + query = put_in(query.combinations, combinations) + query = put_in(query.aliases[@parent_as], {parent_query, sources}) + [all(query, subquery_as_prefix(sources))] + end + + defp top_level_expr(other, sources, parent_query) do + expr(other, sources, parent_query) + end + ## ## Expression generation ## - def expr({:^, [], [_ix]}, _sources, _query) do + defp expr({:^, [], [_ix]}, _sources, _query) do ~c"?" end # workaround for the fact that SQLite3 as of 3.35.4 does not support specifying table # in the returning clause. when a later release adds the ability, this code can be deleted - def expr( - {{:., _, [{:parent_as, _, [{:&, _, [_idx]}]}, field]}, _, []}, - _sources, - %{returning: true} - ) - when is_atom(field) do + defp expr( + {{:., _, [{:parent_as, _, [{:&, _, [_idx]}]}, field]}, _, []}, + _sources, + %{returning: true} + ) + when is_atom(field) do quote_name(field) end # workaround for the fact that SQLite3 as of 3.35.4 does not support specifying table # in the returning clause. when a later release adds the ability, this code can be deleted - def expr({{:., _, [{:&, _, [_idx]}, field]}, _, []}, _sources, %{returning: true}) - when is_atom(field) do + defp expr({{:., _, [{:&, _, [_idx]}, field]}, _, []}, _sources, %{returning: true}) + when is_atom(field) do quote_name(field) end - def expr({{:., _, [{:parent_as, _, [as]}, field]}, _, []}, _sources, query) - when is_atom(field) do + defp expr({{:., _, [{:parent_as, _, [as]}, field]}, _, []}, _sources, query) + when is_atom(field) do {ix, sources} = get_parent_sources_ix(query, as) {_, name, _} = elem(sources, ix) [name, ?. | quote_name(field)] end - def expr({{:., _, [{:&, _, [idx]}, field]}, _, []}, sources, _query) - when is_atom(field) do + defp expr({{:., _, [{:&, _, [idx]}, field]}, _, []}, sources, _query) + when is_atom(field) do {_, name, _} = elem(sources, idx) [name, ?. | quote_name(field)] end - def expr({:&, _, [idx]}, sources, _query) do + defp expr({:&, _, [idx]}, sources, _query) do {_, source, _} = elem(sources, idx) source end - def expr({:in, _, [_left, "[]"]}, _sources, _query) do + defp expr({:in, _, [_left, "[]"]}, _sources, _query) do "0" end - def expr({:in, _, [_left, []]}, _sources, _query) do + defp expr({:in, _, [_left, []]}, _sources, _query) do "0" end - def expr({:in, _, [left, right]}, sources, query) when is_list(right) do - args = intersperse_map(right, ?,, &expr(&1, sources, query)) + defp expr({:in, _, [left, right]}, sources, query) when is_list(right) do + args = Enum.map_intersperse(right, ?,, &expr(&1, sources, query)) [expr(left, sources, query), " IN (", args, ?)] end - def expr({:in, _, [_, {:^, _, [_, 0]}]}, _sources, _query) do + defp expr({:in, _, [_, {:^, _, [_, 0]}]}, _sources, _query) do "0" end - def expr({:in, _, [left, {:^, _, [_, len]}]}, sources, query) do + defp expr({:in, _, [left, {:^, _, [_, len]}]}, sources, query) do args = Enum.intersperse(List.duplicate(??, len), ?,) [expr(left, sources, query), " IN (", args, ?)] end - def expr({:in, _, [left, %Ecto.SubQuery{} = subquery]}, sources, query) do + defp expr({:in, _, [left, %Ecto.SubQuery{} = subquery]}, sources, query) do [expr(left, sources, query), " IN ", expr(subquery, sources, query)] end # Super Hack to handle arrays in json - def expr({:in, _, [left, right]}, sources, query) do + defp expr({:in, _, [left, right]}, sources, query) do [ expr(left, sources, query), " IN (SELECT value FROM JSON_EACH(", @@ -1300,20 +1313,20 @@ defmodule Ecto.Adapters.SQLite3.Connection do ] end - def expr({:is_nil, _, [arg]}, sources, query) do + defp expr({:is_nil, _, [arg]}, sources, query) do [expr(arg, sources, query) | " IS NULL"] end - def expr({:not, _, [expression]}, sources, query) do + defp expr({:not, _, [expression]}, sources, query) do ["NOT (", expr(expression, sources, query), ?)] end - def expr({:filter, _, [agg, filter]}, sources, query) do + defp expr({:filter, _, [agg, filter]}, sources, query) do aggregate = expr(agg, sources, query) [aggregate, " FILTER (WHERE ", expr(filter, sources, query), ?)] end - def expr(%Ecto.SubQuery{query: query}, sources, parent_query) do + defp expr(%Ecto.SubQuery{query: query}, sources, parent_query) do combinations = Enum.map(query.combinations, fn {type, combination_query} -> {type, put_in(combination_query.aliases[@parent_as], {parent_query, sources})} @@ -1324,14 +1337,14 @@ defmodule Ecto.Adapters.SQLite3.Connection do [?(, all(query, subquery_as_prefix(sources)), ?)] end - def expr({:fragment, _, [kw]}, _sources, query) - when is_list(kw) or tuple_size(kw) == 3 do + defp expr({:fragment, _, [kw]}, _sources, query) + when is_list(kw) or tuple_size(kw) == 3 do raise Ecto.QueryError, query: query, message: "SQLite3 adapter does not support keyword or interpolated fragments" end - def expr({:fragment, _, parts}, sources, query) do + defp expr({:fragment, _, parts}, sources, query) do parts |> Enum.map(fn {:raw, part} -> part @@ -1340,23 +1353,23 @@ defmodule Ecto.Adapters.SQLite3.Connection do |> parens_for_select end - def expr({:values, _, _}, _, _query) do + defp expr({:values, _, _}, _, _query) do raise ArgumentError, "SQLite3 adapter does not support values lists" end - def expr({:literal, _, [literal]}, _sources, _query) do + defp expr({:literal, _, [literal]}, _sources, _query) do quote_name(literal) end - def expr({:splice, _, [{:^, _, [_, length]}]}, _sources, _query) do + defp expr({:splice, _, [{:^, _, [_, length]}]}, _sources, _query) do Enum.intersperse(List.duplicate(??, length), ?,) end - def expr({:selected_as, _, [name]}, _sources, _query) do + defp expr({:selected_as, _, [name]}, _sources, _query) do [quote_name(name)] end - def expr({:datetime_add, _, [datetime, count, interval]}, sources, query) do + defp expr({:datetime_add, _, [datetime, count, interval]}, sources, query) do [ "CAST (", "strftime('%Y-%m-%d %H:%M:%f000Z'", @@ -1368,7 +1381,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do ] end - def expr({:date_add, _, [date, count, interval]}, sources, query) do + defp expr({:date_add, _, [date, count, interval]}, sources, query) do [ "CAST (", "strftime('%Y-%m-%d'", @@ -1380,33 +1393,33 @@ defmodule Ecto.Adapters.SQLite3.Connection do ] end - def expr({:ilike, _, [_, _]}, _sources, query) do + defp expr({:ilike, _, [_, _]}, _sources, query) do raise Ecto.QueryError, query: query, message: "ilike is not supported by SQLite3" end - def expr({:over, _, [agg, name]}, sources, query) when is_atom(name) do + defp expr({:over, _, [agg, name]}, sources, query) when is_atom(name) do [expr(agg, sources, query), " OVER " | quote_name(name)] end - def expr({:over, _, [agg, kw]}, sources, query) do + defp expr({:over, _, [agg, kw]}, sources, query) do [expr(agg, sources, query), " OVER " | window_exprs(kw, sources, query)] end - def expr({:{}, _, elems}, sources, query) do - [?(, intersperse_map(elems, ?,, &expr(&1, sources, query)), ?)] + defp expr({:{}, _, elems}, sources, query) do + [?(, Enum.map_intersperse(elems, ?,, &expr(&1, sources, query)), ?)] end - def expr({:count, _, []}, _sources, _query), do: "count(*)" + defp expr({:count, _, []}, _sources, _query), do: "count(*)" - def expr({:count, _, [{:&, _, [_]}]}, _sources, query) do + defp expr({:count, _, [{:&, _, [_]}]}, _sources, query) do raise Ecto.QueryError, query: query, message: "The argument to `count/1` must be a column in SQLite3" end - def expr({:json_extract_path, _, [expr, path]}, sources, query) do + defp expr({:json_extract_path, _, [expr, path]}, sources, query) do path = Enum.map(path, fn binary when is_binary(binary) -> @@ -1419,11 +1432,11 @@ defmodule Ecto.Adapters.SQLite3.Connection do ["json_extract(", expr(expr, sources, query), ", '$", path, "')"] end - def expr({:exists, _, [subquery]}, sources, query) do + defp expr({:exists, _, [subquery]}, sources, query) do ["exists", expr(subquery, sources, query)] end - def expr({fun, _, args}, sources, query) when is_atom(fun) and is_list(args) do + defp expr({fun, _, args}, sources, query) when is_atom(fun) and is_list(args) do {modifier, args} = case args do [_rest, :distinct] -> @@ -1441,28 +1454,34 @@ defmodule Ecto.Adapters.SQLite3.Connection do [op_to_binary(left, sources, query), op | op_to_binary(right, sources, query)] {:fun, fun} -> - [fun, ?(, modifier, intersperse_map(args, ", ", &expr(&1, sources, query)), ?)] + [ + fun, + ?(, + modifier, + Enum.map_intersperse(args, ", ", &expr(&1, sources, query)), + ?) + ] end end # TODO It technically is, its just a json array, so we *could* support it - def expr(list, _sources, query) when is_list(list) do + defp expr(list, _sources, query) when is_list(list) do raise Ecto.QueryError, query: query, message: "Array literals are not supported by SQLite3" end - def expr(%Decimal{} = decimal, _sources, _query) do + defp expr(%Decimal{} = decimal, _sources, _query) do Decimal.to_string(decimal, :normal) end - def expr(%Ecto.Query.Tagged{value: binary, type: :binary}, _sources, _query) - when is_binary(binary) do + defp expr(%Ecto.Query.Tagged{value: binary, type: :binary}, _sources, _query) + when is_binary(binary) do hex = Base.encode16(binary, case: :lower) [?x, ?', hex, ?'] end - def expr(%Ecto.Query.Tagged{value: expr, type: :binary_id}, sources, query) do + defp expr(%Ecto.Query.Tagged{value: expr, type: :binary_id}, sources, query) do case Application.get_env(:ecto_sqlite3, :binary_id_type, :string) do :string -> ["CAST(", expr(expr, sources, query), " AS ", column_type(:string, query), ?)] @@ -1472,7 +1491,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do end end - def expr(%Ecto.Query.Tagged{value: expr, type: :uuid}, sources, query) do + defp expr(%Ecto.Query.Tagged{value: expr, type: :uuid}, sources, query) do case Application.get_env(:ecto_sqlite3, :uuid_type, :string) do :string -> ["CAST(", expr(expr, sources, query), " AS ", column_type(:string, query), ?)] @@ -1482,32 +1501,32 @@ defmodule Ecto.Adapters.SQLite3.Connection do end end - def expr(%Ecto.Query.Tagged{value: other, type: type}, sources, query) - when type in [:decimal, :float] do + defp expr(%Ecto.Query.Tagged{value: other, type: type}, sources, query) + when type in [:decimal, :float] do ["CAST(", expr(other, sources, query), " AS REAL)"] end - def expr(%Ecto.Query.Tagged{value: other, type: type}, sources, query) do + defp expr(%Ecto.Query.Tagged{value: other, type: type}, sources, query) do ["CAST(", expr(other, sources, query), " AS ", column_type(type, query), ?)] end - def expr(nil, _sources, _query), do: "NULL" - def expr(true, _sources, _query), do: "1" - def expr(false, _sources, _query), do: "0" + defp expr(nil, _sources, _query), do: "NULL" + defp expr(true, _sources, _query), do: "1" + defp expr(false, _sources, _query), do: "0" - def expr(literal, _sources, _query) when is_binary(literal) do + defp expr(literal, _sources, _query) when is_binary(literal) do [?', escape_string(literal), ?'] end - def expr(literal, _sources, _query) when is_integer(literal) do + defp expr(literal, _sources, _query) when is_integer(literal) do Integer.to_string(literal) end - def expr(literal, _sources, _query) when is_float(literal) do + defp expr(literal, _sources, _query) when is_float(literal) do ["CAST(", Float.to_string(literal), " AS REAL)"] end - def expr(expr, _sources, query) do + defp expr(expr, _sources, query) do raise Ecto.QueryError, query: query, message: "unsupported expression #{inspect(expr)}" @@ -1591,7 +1610,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do end defp column_definitions(table, columns) do - intersperse_map(columns, ", ", &column_definition(table, &1)) + Enum.map_intersperse(columns, ", ", &column_definition(table, &1)) end defp column_definition(table, {:add, name, %Reference{} = ref, opts}) do @@ -1681,7 +1700,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do check = Keyword.get(opts, :check) [ - default_expr(default, type), + default_expr(default), null_expr(null), collate_expr(collate), check_expr(check), @@ -1705,48 +1724,30 @@ defmodule Ecto.Adapters.SQLite3.Connection do defp null_expr(true), do: " NULL" defp null_expr(_), do: [] - defp default_expr({:ok, nil}, _type) do + defp default_expr({:ok, nil}) do " DEFAULT NULL" end - defp default_expr({:ok, literal}, _type) when is_binary(literal) do - [ - " DEFAULT '", - escape_string(literal), - ?' - ] + defp default_expr({:ok, literal}) when is_binary(literal) do + [" DEFAULT '", escape_string(literal), ?'] end - defp default_expr({:ok, literal}, _type) - when is_number(literal) or is_boolean(literal) do - [ - " DEFAULT ", - to_string(literal) - ] + defp default_expr({:ok, literal}) when is_number(literal) or is_boolean(literal) do + [" DEFAULT ", to_string(literal)] end - defp default_expr({:ok, {:fragment, expression}}, _type) do - [ - " DEFAULT ", - expression - ] + defp default_expr({:ok, {:fragment, expression}}) do + [" DEFAULT ", expression] end - defp default_expr({:ok, value}, _type) when is_map(value) or is_list(value) do + defp default_expr({:ok, value}) when is_map(value) or is_list(value) do library = Application.get_env(:ecto_sqlite3, :json_library, Jason) expression = IO.iodata_to_binary(library.encode_to_iodata!(value)) - [ - " DEFAULT ", - ?(, - ?', - escape_string(expression), - ?', - ?) - ] + [" DEFAULT ('", escape_string(expression), "')"] end - defp default_expr(:error, _type), do: [] + defp default_expr(:error), do: [] defp index_expr(literal) when is_binary(literal), do: literal defp index_expr(literal), do: quote_name(literal) @@ -1884,7 +1885,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do end end - defp quote_names(names), do: intersperse_map(names, ?,, "e_name/1) + defp quote_names(names), do: Enum.map_intersperse(names, ?,, "e_name/1) def quote_name(name), do: quote_entity(name) @@ -1902,20 +1903,6 @@ defmodule Ecto.Adapters.SQLite3.Connection do defp quote_entity(val), do: [[?", val, ?"]] - defp intersperse_map(list, separator, mapper, acc \\ []) - - defp intersperse_map([], _separator, _mapper, acc) do - acc - end - - defp intersperse_map([elem], _separator, mapper, acc) do - [acc | mapper.(elem)] - end - - defp intersperse_map([elem | rest], separator, mapper, acc) do - intersperse_map(rest, separator, mapper, [acc, mapper.(elem), separator]) - end - defp intersperse_reduce(list, separator, user_acc, reducer, acc \\ []) defp intersperse_reduce([], _separator, user_acc, _reducer, acc), diff --git a/lib/ecto/adapters/sqlite3/data_type.ex b/lib/ecto/adapters/sqlite3/data_type.ex index f15958b..0781d87 100644 --- a/lib/ecto/adapters/sqlite3/data_type.ex +++ b/lib/ecto/adapters/sqlite3/data_type.ex @@ -12,6 +12,7 @@ defmodule Ecto.Adapters.SQLite3.DataType do def column_type(:serial, _opts), do: "INTEGER" def column_type(:bigserial, _opts), do: "INTEGER" def column_type(:boolean, _opts), do: "INTEGER" + def column_type(:integer, _opts), do: "INTEGER" def column_type(:bigint, _opts), do: "INTEGER" def column_type(:string, _opts), do: "TEXT" def column_type(:float, _opts), do: "NUMERIC" diff --git a/mix.lock b/mix.lock index a060422..fc64bf9 100644 --- a/mix.lock +++ b/mix.lock @@ -1,27 +1,27 @@ %{ - "benchee": {:hex, :benchee, "1.3.0", "f64e3b64ad3563fa9838146ddefb2d2f94cf5b473bdfd63f5ca4d0657bf96694", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}, {:statistex, "~> 1.0", [hex: :statistex, repo: "hexpm", optional: false]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "34f4294068c11b2bd2ebf2c59aac9c7da26ffa0068afdf3419f1b176e16c5f81"}, + "benchee": {:hex, :benchee, "1.3.1", "c786e6a76321121a44229dde3988fc772bca73ea75170a73fd5f4ddf1af95ccf", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}, {:statistex, "~> 1.0", [hex: :statistex, repo: "hexpm", optional: false]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "76224c58ea1d0391c8309a8ecbfe27d71062878f59bd41a390266bf4ac1cc56d"}, "benchee_markdown": {:hex, :benchee_markdown, "0.3.3", "d48a1d9782693fae6c294fdb12f653bb90088172d467996bedb9887ff41cf4ef", [:mix], [{:benchee, ">= 1.1.0 and < 2.0.0", [hex: :benchee, repo: "hexpm", optional: false]}], "hexpm", "106dab9ae0b448747da89b9af7285b71841f5d8131f37c6612b7370a157860a4"}, "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, "cc_precompiler": {:hex, :cc_precompiler, "0.1.10", "47c9c08d8869cf09b41da36538f62bc1abd3e19e41701c2cea2675b53c704258", [:mix], [{:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "f6e046254e53cd6b41c6bacd70ae728011aa82b2742a80d6e2214855c6e06b22"}, - "credo": {:hex, :credo, "1.7.6", "b8f14011a5443f2839b04def0b252300842ce7388f3af177157c86da18dfbeea", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "146f347fb9f8cbc5f7e39e3f22f70acbef51d441baa6d10169dd604bfbc55296"}, - "db_connection": {:hex, :db_connection, "2.6.0", "77d835c472b5b67fc4f29556dee74bf511bbafecdcaf98c27d27fa5918152086", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c2f992d15725e721ec7fbc1189d4ecdb8afef76648c746a8e1cad35e3b8a35f3"}, + "credo": {:hex, :credo, "1.7.7", "771445037228f763f9b2afd612b6aa2fd8e28432a95dbbc60d8e03ce71ba4446", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8bc87496c9aaacdc3f90f01b7b0582467b69b4bd2441fe8aae3109d843cc2f2e"}, + "db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"}, "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, "deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"}, - "earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"}, - "ecto": {:hex, :ecto, "3.11.2", "e1d26be989db350a633667c5cda9c3d115ae779b66da567c68c80cfb26a8c9ee", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3c38bca2c6f8d8023f2145326cc8a80100c3ffe4dcbd9842ff867f7fc6156c65"}, - "ecto_sql": {:hex, :ecto_sql, "3.11.2", "c7cc7f812af571e50b80294dc2e535821b3b795ce8008d07aa5f336591a185a8", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.11.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "73c07f995ac17dbf89d3cfaaf688fcefabcd18b7b004ac63b0dc4ef39499ed6b"}, - "elixir_make": {:hex, :elixir_make, "0.8.3", "d38d7ee1578d722d89b4d452a3e36bcfdc644c618f0d063b874661876e708683", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "5c99a18571a756d4af7a4d89ca75c28ac899e6103af6f223982f09ce44942cc9"}, - "ex_doc": {:hex, :ex_doc, "0.33.0", "690562b153153c7e4d455dc21dab86e445f66ceba718defe64b0ef6f0bd83ba0", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "3f69adc28274cb51be37d09b03e4565232862a4b10288a3894587b0131412124"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.41", "ab34711c9dc6212dda44fcd20ecb87ac3f3fce6f0ca2f28d4a00e4154f8cd599", [:mix], [], "hexpm", "a81a04c7e34b6617c2792e291b5a2e57ab316365c2644ddc553bb9ed863ebefa"}, + "ecto": {:hex, :ecto, "3.12.1", "626765f7066589de6fa09e0876a253ff60c3d00870dd3a1cd696e2ba67bfceea", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "df0045ab9d87be947228e05a8d153f3e06e0d05ab10c3b3cc557d2f7243d1940"}, + "ecto_sql": {:hex, :ecto_sql, "3.12.0", "73cea17edfa54bde76ee8561b30d29ea08f630959685006d9c6e7d1e59113b7d", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dc9e4d206f274f3947e96142a8fdc5f69a2a6a9abb4649ef5c882323b6d512f0"}, + "elixir_make": {:hex, :elixir_make, "0.8.4", "4960a03ce79081dee8fe119d80ad372c4e7badb84c493cc75983f9d3bc8bde0f", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "6e7f1d619b5f61dfabd0a20aa268e575572b542ac31723293a4c1a567d5ef040"}, + "ex_doc": {:hex, :ex_doc, "0.34.2", "13eedf3844ccdce25cfd837b99bea9ad92c4e511233199440488d217c92571e8", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "5ce5f16b41208a50106afed3de6a2ed34f4acfd65715b82a0b84b49d995f95c1"}, "exqlite": {:hex, :exqlite, "0.23.0", "6e851c937a033299d0784994c66da24845415072adbc455a337e20087bce9033", [:make, :mix], [{:cc_precompiler, "~> 0.1", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.8", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "404341cceec5e6466aaed160cf0b58be2019b60af82588c215e1224ebd3ec831"}, "file_system": {:hex, :file_system, "1.0.0", "b689cc7dcee665f774de94b5a832e578bd7963c8e637ef940cd44327db7de2cd", [:mix], [], "hexpm", "6752092d66aec5a10e662aefeed8ddb9531d79db0bc145bb8c40325ca1d8536d"}, - "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, + "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, "makeup": {:hex, :makeup, "1.1.2", "9ba8837913bdf757787e71c1581c21f9d2455f4dd04cfca785c70bbfff1a76a3", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cce1566b81fbcbd21eca8ffe808f33b221f9eee2cbc7a1706fc3da9ff18e6cac"}, "makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"}, - "makeup_erlang": {:hex, :makeup_erlang, "1.0.0", "6f0eff9c9c489f26b69b61440bf1b238d95badae49adac77973cbacae87e3c2e", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "ea7a9307de9d1548d2a72d299058d1fd2339e3d398560a0e46c27dab4891e4d2"}, - "myxql": {:hex, :myxql, "0.6.4", "1502ea37ee23c31b79725b95d4cc3553693c2bda7421b1febc50722fd988c918", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:geo, "~> 3.4", [hex: :geo, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "a3307f4671f3009d3708283649adf205bfe280f7e036fc8ef7f16dbf821ab8e9"}, + "makeup_erlang": {:hex, :makeup_erlang, "1.0.1", "c7f58c120b2b5aa5fd80d540a89fdf866ed42f1f3994e4fe189abebeab610839", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "8a89a1eeccc2d798d6ea15496a6e4870b75e014d1af514b1b71fa33134f57814"}, + "myxql": {:hex, :myxql, "0.7.1", "7c7b75aa82227cd2bc9b7fbd4de774fb19a1cdb309c219f411f82ca8860f8e01", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:geo, "~> 3.4", [hex: :geo, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "a491cdff53353a09b5850ac2d472816ebe19f76c30b0d36a43317a67c9004936"}, "nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"}, - "postgrex": {:hex, :postgrex, "0.18.0", "f34664101eaca11ff24481ed4c378492fed2ff416cd9b06c399e90f321867d7e", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "a042989ba1bc1cca7383ebb9e461398e3f89f868c92ce6671feb7ef132a252d1"}, + "postgrex": {:hex, :postgrex, "0.19.1", "73b498508b69aded53907fe48a1fee811be34cc720e69ef4ccd568c8715495ea", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "8bac7885a18f381e091ec6caf41bda7bb8c77912bb0e9285212829afe5d8a8f8"}, "statistex": {:hex, :statistex, "1.0.0", "f3dc93f3c0c6c92e5f291704cf62b99b553253d7969e9a5fa713e5481cd858a5", [:mix], [], "hexpm", "ff9d8bee7035028ab4742ff52fc80a2aa35cece833cf5319009b52f1b5a86c27"}, "telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"}, - "temp": {:hex, :temp, "0.4.7", "2c78482cc2294020a4bc0c95950b907ff386523367d4e63308a252feffbea9f2", [:mix], [], "hexpm", "6af19e7d6a85a427478be1021574d1ae2a1e1b90882586f06bde76c63cd03e0d"}, + "temp": {:hex, :temp, "0.4.8", "89769b507614e50969aee1ee51bc799cf658bdde7aa73ec3909cbf68d93b7525", [:mix], [], "hexpm", "1e86d2361df398d3803e0d495042a9a4548d2b7316b83c0d60ad54250b03c5db"}, } diff --git a/test/ecto/adapters/sqlite3/connection/insert_test.exs b/test/ecto/adapters/sqlite3/connection/insert_test.exs index 166213f..d9508be 100644 --- a/test/ecto/adapters/sqlite3/connection/insert_test.exs +++ b/test/ecto/adapters/sqlite3/connection/insert_test.exs @@ -131,9 +131,10 @@ defmodule Ecto.Adapters.SQLite3.Connection.InsertTest do test "insert with query as rows" do query = from(s in "schema", select: %{foo: fragment("3"), bar: s.bar}) |> plan(:all) - assert_raise ArgumentError, fn -> - insert(nil, "schema", [:foo, :bar], query, {:raise, [], []}, [:foo]) - end + query = insert(nil, "schema", [:foo, :bar], query, {:raise, [], []}, [:foo]) + + assert query == + ~s{INSERT INTO "schema" ("foo","bar") SELECT 3, s0."bar" FROM "schema" AS s0 RETURNING "foo"} query = from(s in "schema", select: %{foo: fragment("3"), bar: s.bar}, where: true)