-
Notifications
You must be signed in to change notification settings - Fork 332
Closed
Labels
Description
Elixir version
1.19.4
Database and Version
PostgreSQL 17.7
Ecto Versions
ecto 3.13.5, ecto_sql 3.13.2
Database Adapter and Versions (postgrex, myxql, etc)
postgrex 0.21.1
Current behavior
This small script attempts to stream a single line of text into a database table while using a dynamic repo:
Mix.install([
{:ecto_sql, "~> 3.10"},
{:postgrex, ">= 0.0.0"}
])
Application.put_env(:myapp, Repo, database: "example_db")
defmodule Repo do
use Ecto.Repo, adapter: Ecto.Adapters.Postgres, otp_app: :myapp
end
# Bring up the Repo
Repo.__adapter__().storage_up(Repo.config())
{:ok, _pid} = Repo.start_link(Repo.config())
# Now, the actual test case.
default_dyn_repo = Repo.get_dynamic_repo()
{:ok, dyn_repo} = Repo.config() |> Keyword.put(:name, nil) |> Repo.start_link()
Repo.put_dynamic_repo(dyn_repo)
Repo.transaction(fn ->
["data"]
|> Stream.into(Ecto.Adapters.SQL.stream(Repo, "COPY tmp_table FROM STDIN"))
|> Stream.run()
end)
Repo.put_dynamic_repo(default_dyn_repo)It currently fails with
** (RuntimeError) cannot collect into stream outside of transaction
(ecto_sql 3.13.3) lib/ecto/adapters/sql.ex:1152: Ecto.Adapters.SQL.into/4
(ecto_sql 3.13.3) lib/ecto/adapters/sql/stream.ex:29: Collectable.Ecto.Adapters.SQL.Stream.into/1
(elixir 1.19.4) lib/stream.ex:589: Stream.do_into/5
(elixir 1.19.4) lib/stream.ex:707: Stream.run/1
repo.exs:9: anonymous fn/1 in Repo.transaction/2
(ecto 3.13.5) lib/ecto/repo/transaction.ex:11: anonymous fn/3 in Ecto.Repo.Transaction.transact/4
(ecto_sql 3.13.3) lib/ecto/adapters/sql.ex:1468: anonymous fn/3 in Ecto.Adapters.SQL.checkout_or_transaction/4
(db_connection 2.8.1) lib/db_connection.ex:1753: DBConnection.run_transaction/4
To fix this, I currently have to pass dyn_repo (the PID of the dynamic repo) resp. Repo.get_dynamic_repo() to Ecto.Adapters.SQL.stream/2 explicitly, instead of the module Repo. It is unclear if the desired (if so: undocumented) requirement, or if it's a missing feature in Ecto.Adapters.SQL.stream/2 to call get_dynamic_repo/0 itself.
Expected behavior
The Ecto.Adapters.SQL.stream/2 call should respect the dynamic repo. I.e. the example program should notice that there is an active transaction and start streaming, which should then run into the error
** (Postgrex.Error) ERROR 42P01 (undefined_table) relation "tmp_table" does not exist
(db_connection 2.8.1) lib/db_connection.ex:848: DBConnection.execute!/4
(postgrex 0.21.1) lib/postgrex/stream.ex:85: anonymous fn/7 in Collectable.Postgrex.Stream.make_into/4
(ecto_sql 3.13.3) lib/ecto/adapters/sql/stream.ex:36: anonymous fn/4 in Collectable.Ecto.Adapters.SQL.Stream.make_into/2
(elixir 1.19.4) lib/stream.ex:612: Stream.do_into/4
(elixir 1.19.4) lib/stream.ex:707: Stream.run/1
repo.exs:9: anonymous fn/1 in Repo.transaction/2
(ecto 3.13.5) lib/ecto/repo/transaction.ex:11: anonymous fn/3 in Ecto.Repo.Transaction.transact/4
(ecto_sql 3.13.3) lib/ecto/adapters/sql.ex:1468: anonymous fn/3 in Ecto.Adapters.SQL.checkout_or_transaction/4