Recently I decided to try out Ecto 2.0 beta in one of my private projects. In doing so I ran into a small bug and decided to put together a simple case to reproduce the problem and then file an issue against Ecto. This post describes how I went about this process.
In my project I found that Phoenix’s mix ecto.reset command wasn’t working in that seeding the database would fail with an error like this:
** (ArgumentError) no extension found for oid `1822277`
(postgrex) lib/postgrex/types.ex:298: Postgrex.Types.fetch!/2
(postgrex) lib/postgrex/types.ex:215: Postgrex.Types.encoder/2
(elixir) lib/enum.ex:1088: Enum."-map/2-lists^map/1-0-"/2
(elixir) lib/enum.ex:1088: Enum."-map/2-lists^map/1-0-"/2
(postgrex) lib/postgrex/query.ex:82: DBConnection.Query.Postgrex.Query.encoders/2
(postgrex) lib/postgrex/query.ex:43: DBConnection.Query.Postgrex.Query.describe/2
(db_connection) lib/db_connection.ex:884: DBConnection.describe_execute/5
(db_connection) lib/db_connection.ex:966: anonymous fn/4 in DBConnection.run_meter/5
(db_connection) lib/db_connection.ex:1009: DBConnection.run_begin/3
(db_connection) lib/db_connection.ex:421: DBConnection.query/4
(ecto) lib/ecto/adapters/sql.ex:380: Ecto.Adapters.SQL.struct/6
(ecto) lib/ecto/repo/schema.ex:369: Ecto.Repo.Schema.apply/5
(ecto) lib/ecto/repo/schema.ex:175: anonymous fn/11 in Ecto.Repo.Schema.do_insert/4
(ecto) lib/ecto/repo/schema.ex:108: Ecto.Repo.Schema.insert!/4
(elixir) lib/code.ex:363: Code.require_file/2
(mix) lib/mix/tasks/run.ex:68: Mix.Tasks.Run.run/1
(mix) lib/mix/task.ex:309: Mix.Task.run_alias/3
After experimenting a bit I concluded that the problem was related to the PostGIS extension. I set about creating a new project with the minimal set of dependencies and code that can reproduce this problem.
For reference, I’m using Elixir 1.2.2 and starting out with a mix.lock file like this:
%{"connection": {:hex, :connection, "1.0.2"},
"cowboy": {:hex, :cowboy, "1.0.4"},
"cowlib": {:hex, :cowlib, "1.0.2"},
"db_connection": {:hex, :db_connection, "0.2.4"},
"decimal": {:hex, :decimal, "1.1.1"},
"ecto": {:hex, :ecto, "1.1.4"},
"fs": {:hex, :fs, "0.9.2"},
"geo": {:hex, :geo, "1.0.1"},
"gettext": {:hex, :gettext, "0.10.0"},
"phoenix": {:hex, :phoenix, "1.1.4"},
"phoenix_ecto": {:hex, :phoenix_ecto, "2.0.1"},
"phoenix_html": {:hex, :phoenix_html, "2.5.0"},
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.0.3"},
"plug": {:hex, :plug, "1.1.2"},
"poison": {:hex, :poison, "1.5.2"},
"poolboy": {:hex, :poolboy, "1.5.1"},
"postgrex": {:hex, :postgrex, "0.11.1"},
"ranch": {:hex, :ranch, "1.2.1"}}Then I’ll be upgrading ecto and other packages to:
index aca7970..d8d5231 100644
--- a/mix.lock
+++ b/mix.lock
@@ -3,15 +3,16 @@
"cowlib": {:hex, :cowlib, "1.0.2"},
"db_connection": {:hex, :db_connection, "0.2.4"},
"decimal": {:hex, :decimal, "1.1.1"},
+ "ecto": {:hex, :ecto, "2.0.0-beta.1"},
"fs": {:hex, :fs, "0.9.2"},
"geo": {:hex, :geo, "1.0.1"},
"gettext": {:hex, :gettext, "0.10.0"},
"phoenix": {:hex, :phoenix, "1.1.4"},
- "phoenix_ecto": {:hex, :phoenix_ecto, "2.0.1"},
+ "phoenix_ecto": {:hex, :phoenix_ecto, "3.0.0-beta.2"},
"phoenix_html": {:hex, :phoenix_html, "2.5.0"},
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.0.3"},
"plug": {:hex, :plug, "1.1.2"},
- "poison": {:hex, :poison, "1.5.2"},
+ "poison": {:hex, :poison, "2.1.0"},
"poolboy": {:hex, :poolboy, "1.5.1"},
"postgrex": {:hex, :postgrex, "0.11.1"},
"ranch": {:hex, :ranch, "1.2.1"}}Setup the app
First, let’s create a brand new Elixir / Phoenix application:
$ mix phoenix.new oid_migration_issue
* creating oid_migration_issue/config/config.exs
* creating oid_migration_issue/config/dev.exs
* creating oid_migration_issue/config/prod.exs
* creating oid_migration_issue/config/prod.secret.exs
* creating oid_migration_issue/config/test.exs
* creating oid_migration_issue/lib/oid_migration_issue.ex
* creating oid_migration_issue/lib/oid_migration_issue/endpoint.ex
* creating oid_migration_issue/test/views/error_view_test.exs
* creating oid_migration_issue/test/support/conn_case.ex
* creating oid_migration_issue/test/support/channel_case.ex
* creating oid_migration_issue/test/test_helper.exs
* creating oid_migration_issue/web/channels/user_socket.ex
* creating oid_migration_issue/web/router.ex
* creating oid_migration_issue/web/views/error_view.ex
* creating oid_migration_issue/web/web.ex
* creating oid_migration_issue/mix.exs
* creating oid_migration_issue/README.md
* creating oid_migration_issue/web/gettext.ex
* creating oid_migration_issue/priv/gettext/errors.pot
* creating oid_migration_issue/priv/gettext/en/LC_MESSAGES/errors.po
* creating oid_migration_issue/web/views/error_helpers.ex
* creating oid_migration_issue/lib/oid_migration_issue/repo.ex
* creating oid_migration_issue/test/support/model_case.ex
* creating oid_migration_issue/priv/repo/seeds.exs
* creating oid_migration_issue/.gitignore
* creating oid_migration_issue/brunch-config.js
* creating oid_migration_issue/package.json
* creating oid_migration_issue/web/static/css/app.css
* creating oid_migration_issue/web/static/js/app.js
* creating oid_migration_issue/web/static/js/socket.js
* creating oid_migration_issue/web/static/assets/robots.txt
* creating oid_migration_issue/web/static/assets/images/phoenix.png
* creating oid_migration_issue/web/static/assets/favicon.ico
* creating oid_migration_issue/test/controllers/page_controller_test.exs
* creating oid_migration_issue/test/views/layout_view_test.exs
* creating oid_migration_issue/test/views/page_view_test.exs
* creating oid_migration_issue/web/controllers/page_controller.ex
* creating oid_migration_issue/web/templates/layout/app.html.eex
* creating oid_migration_issue/web/templates/page/index.html.eex
* creating oid_migration_issue/web/views/layout_view.ex
* creating oid_migration_issue/web/views/page_view.ex
Fetch and install dependencies? [Yn]
* running mix deps.get
* running npm install && node node_modules/brunch/bin/brunch build
We are all set! Run your Phoenix application:
$ cd oid_migration_issue
$ mix phoenix.server
You can also run your app inside IEx (Interactive Elixir) as:
$ iex -S mix phoenix.server
Before moving on, configure your database in config/dev.exs and run:
$ mix ecto.create
I won’t follow the instructions and run mix ecto.create just yet. Instead, I’ll add Geo as a dependency.
--- a/mix.exs
+++ b/mix.exs
@@ -36,7 +36,9 @@ defmodule OidMigrationIssue.Mixfile do
{:phoenix_html, "~> 2.4"},
{:phoenix_live_reload, "~> 1.0", only: :dev},
{:gettext, "~> 0.9"},
- {:cowboy, "~> 1.0"}]
+ {:cowboy, "~> 1.0"},
+ {:geo, "~> 1.0"}
+ ]
end$ mix deps.get
Running dependency resolution
Dependency resolution completed
geo: 1.0.1
* Getting geo (Hex package)
Checking package (https://s3.amazonaws.com/s3.hex.pm/tarballs/geo-1.0.1.tar)
Using locally cached package
And enable the extension for Ecto:
--- a/config/dev.exs
+++ b/config/dev.exs
@@ -39,4 +39,5 @@ config :oid_migration_issue, OidMigrationIssue.Repo,
password: "postgres",
database: "oid_migration_issue_dev",
hostname: "localhost",
- pool_size: 10
+ pool_size: 10,
+ extensions: [{Geo.PostGIS.Extension, library: Geo}]We also need to enable the PostGIS extension in the database via a migration. We’ll start by generating a new migration:
$ mix ecto.gen.migration enable_postgis
* creating priv/repo/migrations
* creating priv/repo/migrations/20160303080907_enable_postgis.exs
Of course, the timestamp will differ if you run this command yourself.
Next, we fill the following (taken from the Geo README) into the migration:
defmodule OidMigrationIssue.Repo.Migrations.EnablePostgis do
use Ecto.Migration
def up do
execute "CREATE EXTENSION IF NOT EXISTS postgis"
end
def down do
execute "DROP EXTENSION IF EXISTS postgis"
end
endLet’s try it out with the ecto.setup alias. This command is a convinient alias that Phoenix creates that just runs
ecto.createto create the databaseecto.migrateto migrate the database-
run priv/repo/seeds.exsto seed the database.$ mix ecto.setup The database for OidMigrationIssue.Repo has been created.
00:10:47.066 [info] == Running OidMigrationIssue.Repo.Migrations.EnablePostgis.up/0 forward
00:10:47.067 [info] execute “CREATE EXTENSION IF NOT EXISTS postgis”
00:10:48.611 [info] == Migrated in 15.4s
So far, so good.
Creating a PostGIS model
Now that we have Geo and PostGIS configured we need to put them to use and create a model:
$ mix phoenix.gen.model GeoModel geo_models geom:Geo.Point
** (Mix) Unknown type `Geo.Point` given to generator
Hmm, ok so we can’t use the Geo.Point type here. Instead we’ll lie and fix up the generated code later:
$ mix phoenix.gen.model GeoModel geo_models geom:string
* creating priv/repo/migrations/20160303081329_create_geo_model.exs
* creating web/models/geo_model.ex
* creating test/models/geo_model_test.exs
Remember to update your repository by running migrations:
$ mix ecto.migrate
Then we’ll switch over to using Geo.Point and :geometry:
diff --git a/priv/repo/migrations/20160303081329_create_geo_model.exs b/priv/repo/migrations/20160303081329_create_geo_model.exs
index 62db09b..abc0c55 100644
--- a/priv/repo/migrations/20160303081329_create_geo_model.exs
+++ b/priv/repo/migrations/20160303081329_create_geo_model.exs
@@ -3,7 +3,7 @@ defmodule OidMigrationIssue.Repo.Migrations.CreateGeoModel do
def change do
create table(:geo_models) do
- add :geom, :string
+ add :geom, :geometry
timestamps
end
diff --git a/test/models/geo_model_test.exs b/test/models/geo_model_test.exs
index d6f380b..29cb661 100644
--- a/test/models/geo_model_test.exs
+++ b/test/models/geo_model_test.exs
@@ -3,7 +3,7 @@ defmodule OidMigrationIssue.GeoModelTest do
alias OidMigrationIssue.GeoModel
- @valid_attrs %{geom: "some content"}
+ @valid_attrs %{geom: %Geo.Point{coordinates: {30, -90}, srid: 4326}}
@invalid_attrs %{}
test "changeset with valid attributes" do
diff --git a/web/models/geo_model.ex b/web/models/geo_model.ex
index f0eeeff..46dfe49 100644
--- a/web/models/geo_model.ex
+++ b/web/models/geo_model.ex
@@ -2,7 +2,7 @@ defmodule OidMigrationIssue.GeoModel do
use OidMigrationIssue.Web, :model
schema "geo_models" do
- field :geom, :string
+ field :geom, Geo.Point
timestamps
endAdding Seeds
Let’s just write a simple seeds script to seed a point into our database. Here’s my seeds.exs script:
alias OidMigrationIssue.{Repo, GeoModel}
%GeoModel{}
|> GeoModel.changeset(%{geom: %Geo.Point{coordinates: {30, -90}, srid: 4326}})
|> Repo.insert!Then, we can use ecto.reset to reset our database using the new seeds:
$ mix ecto.reset
The database for OidMigrationIssue.Repo has been dropped.
The database for OidMigrationIssue.Repo has been created.
00:21:44.809 [info] == Running OidMigrationIssue.Repo.Migrations.EnablePostgis.up/0 forward
00:21:44.811 [info] execute "CREATE EXTENSION IF NOT EXISTS postgis"
00:21:45.941 [info] == Migrated in 11.2s
00:21:45.996 [info] == Running OidMigrationIssue.Repo.Migrations.CreateGeoModel.change/0 forward
00:21:45.996 [info] create table geo_models
00:21:46.006 [info] == Migrated in 0.1s
[debug] INSERT INTO "geo_models" ("inserted_at", "updated_at", "geom") VALUES ($1, $2, $3) RETURNING "id" [{ {2016, 3, 3}, {8, 21, 46, 0} }, { {2016, 3, 3}, {8, 21, 46, 0} }, %Geo.Point{coordinates: {30, -90}, srid: 4326}] OK query=43.3ms
Good, everything seems to be working fine.
Updating to Ecto 2.0 beta
The next step is to upgrade to Ecto 2.0 beta. We’ll follow the instructions from http://blog.plataformatec.com.br/2016/02/ecto-2-0-0-beta-0-is-out/. Fortunately, we don’t have that much to do since we’ve written so little code.
diff --git a/mix.exs b/mix.exs
index 58cda12..f2a3e9e 100644
--- a/mix.exs
+++ b/mix.exs
@@ -32,7 +32,7 @@ defmodule OidMigrationIssue.Mixfile do
defp deps do
[{:phoenix, "~> 1.1.4"},
{:postgrex, ">= 0.0.0"},
- {:phoenix_ecto, "~> 2.0"},
+ {:phoenix_ecto, "~> 3.0.0-beta"},
{:phoenix_html, "~> 2.4"},
{:phoenix_live_reload, "~> 1.0", only: :dev},
{:gettext, "~> 0.9"},
diff --git a/test/support/channel_case.ex b/test/support/channel_case.ex
index ca65c92..bd242ec 100644
--- a/test/support/channel_case.ex
+++ b/test/support/channel_case.ex
@@ -32,10 +32,7 @@ defmodule OidMigrationIssue.ChannelCase do
end
setup tags do
- unless tags[:async] do
- Ecto.Adapters.SQL.restart_test_transaction(OidMigrationIssue.Repo, [])
- end
-
+ :ok = Ecto.Adapters.SQL.Sandbox.checkout(Demo.Repo)
:ok
end
end
diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex
index 8affedf..67dd527 100644
--- a/test/support/conn_case.ex
+++ b/test/support/conn_case.ex
@@ -33,10 +33,7 @@ defmodule OidMigrationIssue.ConnCase do
end
setup tags do
- unless tags[:async] do
- Ecto.Adapters.SQL.restart_test_transaction(OidMigrationIssue.Repo, [])
- end
-
+ :ok = Ecto.Adapters.SQL.Sandbox.checkout(Demo.Repo)
{:ok, conn: Phoenix.ConnTest.conn()}
end
end
diff --git a/test/support/model_case.ex b/test/support/model_case.ex
index c3b0e07..6db2da6 100644
--- a/test/support/model_case.ex
+++ b/test/support/model_case.ex
@@ -26,10 +26,7 @@ defmodule OidMigrationIssue.ModelCase do
end
setup tags do
- unless tags[:async] do
- Ecto.Adapters.SQL.restart_test_transaction(OidMigrationIssue.Repo, [])
- end
-
+ :ok = Ecto.Adapters.SQL.Sandbox.checkout(Demo.Repo)
:ok
end
diff --git a/test/test_helper.exs b/test/test_helper.exs
index 973f1a8..6892146 100644
--- a/test/test_helper.exs
+++ b/test/test_helper.exs
@@ -2,5 +2,4 @@ ExUnit.start
Mix.Task.run "ecto.create", ~w(-r OidMigrationIssue.Repo --quiet)
Mix.Task.run "ecto.migrate", ~w(-r OidMigrationIssue.Repo --quiet)
-Ecto.Adapters.SQL.begin_test_transaction(OidMigrationIssue.Repo)
-
+Ecto.Adapters.SQL.Sandbox.mode(OidMigrationIssue.Repo, :manual)Now, to install the deps:
$ mix deps.get
Running dependency resolution
Conflict on ecto
mix.lock: 1.1.4
phoenix_ecto from 3.0.0-beta.0 to 3.0.0-beta.2: ~> 2.0-beta
** (Mix) Hex dependency resolution failed, relax the version requirements
or unlock dependencies
We need to follow the instructions here and unlock ecto:
$ mix deps.unlock ecto
$ mix deps.get
Running dependency resolution
Conflict on ecto 2.0.0-beta.0, 2.0.0-beta.1
geo 1.0.1: ~> 1.1
phoenix_ecto from 3.0.0-beta.0 to 3.0.0-beta.2: ~> 2.0-beta
** (Mix) Hex dependency resolution failed, relax the version requirements
or unlock dependencies
Ah, so Geo says it depends on Ecto 1.1. I’ve tested this before and I think Geo can work fine with Ecto 2.0 so let’s override it:
diff --git a/mix.exs b/mix.exs
index f2a3e9e..1772008 100644
--- a/mix.exs
+++ b/mix.exs
@@ -35,6 +35,7 @@ defmodule OidMigrationIssue.Mixfile do
{:phoenix_ecto, "~> 3.0.0-beta"},
{:phoenix_html, "~> 2.4"},
{:phoenix_live_reload, "~> 1.0", only: :dev},
+ {:ecto, "~> 2.0-beta", override: true},
{:gettext, "~> 0.9"},
{:cowboy, "~> 1.0"},
{:geo, "~> 1.0"}And now we can install the deps we want:
$ mix deps.unlock --all
$ mix deps.get
Running dependency resolution
Dependency resolution completed
connection: 1.0.2
cowboy: 1.0.4
cowlib: 1.0.2
db_connection: 0.2.4
decimal: 1.1.1
ecto: 2.0.0-beta.1
fs: 0.9.2
geo: 1.0.1
gettext: 0.10.0
phoenix: 1.1.4
phoenix_ecto: 3.0.0-beta.2
phoenix_html: 2.5.0
phoenix_live_reload: 1.0.3
plug: 1.1.2
poison: 2.1.0
poolboy: 1.5.1
postgrex: 0.11.1
ranch: 1.2.1
* Updating poison (Hex package)
Checking package (https://s3.amazonaws.com/s3.hex.pm/tarballs/poison-2.1.0.tar)
Using locally cached package
Ecto reset
Now, let’s retry our ecto.reset command again:
$ mix ecto.reset
The database for OidMigrationIssue.Repo has been dropped.
The database for OidMigrationIssue.Repo has been created.
00:34:57.457 [info] == Running OidMigrationIssue.Repo.Migrations.EnablePostgis.up/0 forward
00:34:57.459 [info] execute "CREATE EXTENSION IF NOT EXISTS postgis"
00:34:58.653 [info] == Migrated in 11.9s
00:34:58.710 [info] == Running OidMigrationIssue.Repo.Migrations.CreateGeoModel.change/0 forward
00:34:58.710 [info] create table geo_models
00:34:58.715 [info] == Migrated in 0.0s
** (ArgumentError) no extension found for oid `1822277`
(postgrex) lib/postgrex/types.ex:298: Postgrex.Types.fetch!/2
(postgrex) lib/postgrex/types.ex:215: Postgrex.Types.encoder/2
(elixir) lib/enum.ex:1088: Enum."-map/2-lists^map/1-0-"/2
(elixir) lib/enum.ex:1088: Enum."-map/2-lists^map/1-0-"/2
(postgrex) lib/postgrex/query.ex:82: DBConnection.Query.Postgrex.Query.encoders/2
(postgrex) lib/postgrex/query.ex:43: DBConnection.Query.Postgrex.Query.describe/2
(db_connection) lib/db_connection.ex:884: DBConnection.describe_execute/5
(db_connection) lib/db_connection.ex:966: anonymous fn/4 in DBConnection.run_meter/5
(db_connection) lib/db_connection.ex:1009: DBConnection.run_begin/3
(db_connection) lib/db_connection.ex:421: DBConnection.query/4
(ecto) lib/ecto/adapters/sql.ex:380: Ecto.Adapters.SQL.struct/6
(ecto) lib/ecto/repo/schema.ex:369: Ecto.Repo.Schema.apply/5
(ecto) lib/ecto/repo/schema.ex:175: anonymous fn/11 in Ecto.Repo.Schema.do_insert/4
(ecto) lib/ecto/repo/schema.ex:108: Ecto.Repo.Schema.insert!/4
(elixir) lib/code.ex:363: Code.require_file/2
(mix) lib/mix/tasks/run.ex:68: Mix.Tasks.Run.run/1
(mix) lib/mix/task.ex:309: Mix.Task.run_alias/3
Ok, good. This is the failure we expected. Our reproduction case is doing its job. Let’s confirm it’s behaving the way I claim it is.
Note that if I remove the seed command from the aliases like this:
diff --git a/mix.exs b/mix.exs
index 1772008..ccd92b7 100644
--- a/mix.exs
+++ b/mix.exs
@@ -49,7 +49,7 @@ defmodule OidMigrationIssue.Mixfile do
#
# See the documentation for `Mix` for more info on aliases.
defp aliases do
- ["ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
+ ["ecto.setup": ["ecto.create", "ecto.migrate"],
"ecto.reset": ["ecto.drop", "ecto.setup"]]
end
endand then run reset and seed as two commands then everything works as it should:
$ mix ecto.reset && mix run priv/repo/seeds.exs
The database for OidMigrationIssue.Repo has been dropped.
The database for OidMigrationIssue.Repo has been created.
09:10:52.465 [info] == Running OidMigrationIssue.Repo.Migrations.EnablePostgis.up/0 forward
09:10:52.467 [info] execute "CREATE EXTENSION IF NOT EXISTS postgis"
09:10:53.649 [info] == Migrated in 11.8s
09:10:53.702 [info] == Running OidMigrationIssue.Repo.Migrations.CreateGeoModel.change/0 forward
09:10:53.702 [info] create table geo_models
09:10:53.707 [info] == Migrated in 0.0s
[debug] INSERT INTO "geo_models" ("inserted_at","updated_at","geom") VALUES ($1,$2,$3) RETURNING "id" [{ {2016, 3, 3}, {17, 10, 54, 0} }, { {2016, 3, 3}, {17, 10, 54, 0} }, %Geo.Point{coordinates: {30, -90}, srid: 4326}] OK query=6.7ms queue=48.7ms
So this appears to be a problem running the commands within a single mix invocation.
Look over the existing issues
Before I go ahead and file an issue against Ecto I should check to see if there is one already filed. Searching, I see Reload TYPE ENUM (Postgre) before migration which has been fixed. But, reading through the issue, it sounds like it describes a very similar issue that would come up when migrating a database due to the Postgres types cache. I wonder if our issue is due to the same root cause? That is, the problem has been fixed for migrations but the problem affects seeds as well.
I can try adding some code to my seeds based on the fix for the above issue. Based on my reading of the fixes I need to add:
diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs
index 13152f0..dd2b82b 100644
--- a/priv/repo/seeds.exs
+++ b/priv/repo/seeds.exs
@@ -12,6 +12,9 @@
alias OidMigrationIssue.{Repo, GeoModel}
+{:ok, _} = Application.ensure_all_started(:ecto)
+{:ok, _} = Application.ensure_all_started(:postgrex)
+
%GeoModel{}
|> GeoModel.changeset(%{geom: %Geo.Point{coordinates: {30, -90}, srid: 4326}})
|> Repo.insert!But running this version I still get the same error.
Try out Ecto master
We should try out the master branch of Ecto to see if the issue has been fixed there but not yet published in a release. To do this we make this change to mix.exs:
diff --git a/mix.exs b/mix.exs
index 1772008..5c0827b 100644
--- a/mix.exs
+++ b/mix.exs
@@ -35,7 +35,7 @@ defmodule OidMigrationIssue.Mixfile do
{:phoenix_ecto, "~> 3.0.0-beta"},
{:phoenix_html, "~> 2.4"},
{:phoenix_live_reload, "~> 1.0", only: :dev},
- {:ecto, "~> 2.0-beta", override: true},
+ {:ecto, github: "elixir-lang/ecto", branch: "master", override: true},
{:gettext, "~> 0.9"},
{:cowboy, "~> 1.0"},
{:geo, "~> 1.0"}Then update the deps
$ mix deps.get
* Getting ecto (https://github.com/elixir-lang/ecto.git)
Cloning into '/Users/jkain/Documents/Projects/elixir/oid_migration_issue/deps/ecto'...
remote: Counting objects: 25829, done.
remote: Compressing objects: 100% (232/232), done.
remote: Total 25829 (delta 110), reused 2 (delta 2), pack-reused 25594
Receiving objects: 100% (25829/25829), 6.58 MiB | 2.59 MiB/s, done.
Resolving deltas: 100% (14906/14906), done.
Checking connectivity... done.
Running dependency resolution
I see the same problem:
$ mix ecto.reset
The database for OidMigrationIssue.Repo has been dropped.
The database for OidMigrationIssue.Repo has been created.
09:20:59.536 [info] == Running OidMigrationIssue.Repo.Migrations.EnablePostgis.up/0 forward
09:20:59.537 [info] execute "CREATE EXTENSION IF NOT EXISTS postgis"
09:21:00.774 [info] == Migrated in 12.3s
09:21:00.817 [info] == Running OidMigrationIssue.Repo.Migrations.CreateGeoModel.change/0 forward
09:21:00.817 [info] create table geo_models
09:21:00.822 [info] == Migrated in 0.0s
** (ArgumentError) no extension found for oid `1841936`
(postgrex) lib/postgrex/types.ex:298: Postgrex.Types.fetch!/2
(postgrex) lib/postgrex/types.ex:215: Postgrex.Types.encoder/2
(elixir) lib/enum.ex:1088: Enum."-map/2-lists^map/1-0-"/2
(elixir) lib/enum.ex:1088: Enum."-map/2-lists^map/1-0-"/2
(postgrex) lib/postgrex/query.ex:82: DBConnection.Query.Postgrex.Query.encoders/2
(postgrex) lib/postgrex/query.ex:43: DBConnection.Query.Postgrex.Query.describe/2
(db_connection) lib/db_connection.ex:884: DBConnection.describe_execute/5
(db_connection) lib/db_connection.ex:966: anonymous fn/4 in DBConnection.run_meter/5
(db_connection) lib/db_connection.ex:1009: DBConnection.run_begin/3
(db_connection) lib/db_connection.ex:421: DBConnection.query/4
(ecto) lib/ecto/adapters/sql.ex:387: Ecto.Adapters.SQL.struct/6
(ecto) lib/ecto/repo/schema.ex:369: Ecto.Repo.Schema.apply/5
(ecto) lib/ecto/repo/schema.ex:175: anonymous fn/11 in Ecto.Repo.Schema.do_insert/4
(ecto) lib/ecto/repo/schema.ex:108: Ecto.Repo.Schema.insert!/4
(elixir) lib/code.ex:363: Code.require_file/2
(mix) lib/mix/tasks/run.ex:68: Mix.Tasks.Run.run/1
(mix) lib/mix/task.ex:309: Mix.Task.run_alias/3
File an Issue and See it Fixed
I filed a new issue and filled in the template and a link to the repo for this simple reproducer.
The issue was fixed in under an hour and half. Here’s the commit.
The fix is in master, let’s try it out. We already have the change to fetch Ecto from master. I just need to unlock Ecto and update to the newest master. Then
$ mix ecto.reset
The database for OidMigrationIssue.Repo has been dropped.
The database for OidMigrationIssue.Repo has been created.
07:37:25.415 [info] == Running OidMigrationIssue.Repo.Migrations.EnablePostgis.up/0 forward
07:37:25.417 [info] execute "CREATE EXTENSION IF NOT EXISTS postgis"
07:37:26.941 [info] == Migrated in 15.2s
07:37:26.994 [info] == Running OidMigrationIssue.Repo.Migrations.CreateGeoModel.change/0 forward
07:37:26.994 [info] create table geo_models
07:37:26.999 [info] == Migrated in 0.0s
[debug] INSERT INTO "geo_models" ("inserted_at","updated_at","geom") VALUES ($1,$2,$3) RETURNING "id" [{ {2016, 3, 5}, {15, 37, 27, 0} }, { {2016, 3, 5}, {15, 37, 27, 0} }, %Geo.Point{coordinates: {30, -90}, srid: 4326}] OK query=7.0ms queue=27.3ms
It works! Thanks José and Ecto team!
Conclusion
I hope you enjoyed this post on my experiences with Ecto 2.0-beta and building a simple reproduction case. I know it was a good oppourtunity for me to help out with the testing of Ecto 2.0.