Hannu

Hannu

Correct Ecto_sql v3 migration lock function when using adapter for sqlite3

Hi,

What should the lock_for_migrations function be for sqlite3 when writing an adapter to use with ecto_sql?

Reference issue in ecto.

That’s pretty old comment and things have changed with ecto_sql v3 since then.

My current implementation:

def lock_for_migrations(meta, query, _opts, fun) do
    %{opts: adapter_opts, repo: repo} = meta

    if Keyword.fetch(adapter_opts, :pool_size) == {:ok, 1} do
      raise_pool_size_error()
    end

    query
    |> Map.put(:lock, nil)
    |> repo.all()
    |> fun.()
  end

When running tests this fails with

** (Protocol.UndefinedError) protocol Ecto.Queryable not implemented for [] of type List. This protocol is implemented for the following type(s): Tuple, BitString, Ecto.SubQuery, Atom, Ecto.Query
    (ecto 3.5.5) lib/ecto/queryable.ex:1: Ecto.Queryable.impl_for!/1
    (ecto 3.5.5) lib/ecto/queryable.ex:9: Ecto.Queryable.to_query/1
    (ecto 3.5.5) lib/ecto/repo/queryable.ex:14: Ecto.Repo.Queryable.all/3
    (ecto_sql 3.5.3) lib/ecto/migrator.ex:516: anonymous fn/6 in Ecto.Migrator.lock_for_migrations/4
    (ecto_sql 3.5.3) lib/ecto/migrator.ex:512: Ecto.Migrator.lock_for_migrations/4
    integration/sqlite/test_helper.exs:116: (file)

Looking at the code in question it seems that the locked_query variable is an empty list

_ = migration_repo.all(locked_query, all_opts)

If I don’t call repo.all() in the lock_for_migrations function then the code fails with

{"busy",0}
{"busy",1}
{"busy",2}
{"busy",3}
{"busy",4}
{"busy",5}

18:19:44.272 [error] GenServer #PID<0.402.0> terminating
** (stop) bad return value: :too_many_tries
Last message (from #PID<0.95.0>): {:query_rows, "INSERT INTO \"schema_migrations\" (\"version\",\"inserted_at\") VALUES (?1,?2)", [timeout: :infinity, decode: :manual, types: true, bind: [0, ~N[2020-12-12 16:19:30]]]}

18:19:44.281 [error] Could not update schema migrations. This error usually happens due to the following:

  * The database does not exist
  * The "schema_migrations" table, which Ecto uses for managing
    migrations, was defined by another library
  * There is a deadlock while migrating (such as using concurrent
    indexes with a migration_lock)

To fix the first issue, run "mix ecto.create".

To address the second, you can run "mix ecto.drop" followed by
"mix ecto.create". Alternatively you may configure Ecto to use
another table and/or repository for managing migrations:

    config :ecto_sql, Ecto.Integration.TestRepo,
      migration_source: "some_other_table_for_schema_migrations",
      migration_repo: AnotherRepoForSchemaMigrations

The full error report is shown below.


18:19:44.282 [error] Sqlite.DbConnection.Protocol (#PID<0.384.0>) disconnected: ** (DBConnection.ConnectionError) client #PID<0.426.0> exited
** (Sqlite.DbConnection.Error) {{:bad_return_value, :too_many_tries}, {GenServer, :call, [#PID<0.402.0>, {:query_rows, "INSERT INTO \"schema_migrations\" (\"version\",\"inserted_at\") VALUES (?1,?2)", [timeout: :infinity, decode: :manual, types: true, bind: [0, ~N[2020-12-12 16:19:30]]]}, :infinity]}}
    (ecto_sql 3.5.3) lib/ecto/adapters/sql.ex:751: Ecto.Adapters.SQL.raise_sql_call_error/1
    (ecto 3.5.5) lib/ecto/repo/schema.ex:649: Ecto.Repo.Schema.apply/4
    (ecto 3.5.5) lib/ecto/repo/schema.ex:262: anonymous fn/15 in Ecto.Repo.Schema.do_insert/4
    (ecto_sql 3.5.3) lib/ecto/migrator.ex:672: Ecto.Migrator.verbose_schema_migration/3
    (ecto_sql 3.5.3) lib/ecto/migrator.ex:300: Ecto.Migrator.async_migrate_maybe_in_transaction/7
    (ecto_sql 3.5.3) lib/ecto/migrator.ex:218: anonymous fn/6 in Ecto.Migrator.up/4
    (ecto_sql 3.5.3) lib/ecto/migrator.ex:512: Ecto.Migrator.lock_for_migrations/4
    integration/sqlite/test_helper.exs:116: (file)

So the question is: Should the repo.all() be called or not?

Where Next?

Popular in Questions Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
sabri
Can someone explain the settings of pool_size of Ecto in config file? and what is the recommend size? Thanks
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New

Other popular topics Top

pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
beno
I will often find my self writing things similar to: case some_value do nil -&gt; something() "" -&gt; something() _ -&gt; someth...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New

We're in Beta

About us Mission Statement