Can I use a migration file to change the name of a field?

Based on the post below, I know that I can use a migration file to add a field to a table.

I want to know if I can use a migration to change the name and/or datatype of an existing field of a table and if so, what is the syntax.

Thank you.

EDIT

I found the syntax to update a field name and ran it in a migration. My goal is to change a field named status_action_value to testbed_url.

I ran this code in the migration:

defmodule App.Repo.Migrations.ChangeStatusActionValueToTestbedUrl do
  use Ecto.Migration

  def change do
    rename table("testbeds"), :status_action_value, to: :testbed_url
  end
end

It was successful. In the postgres shell when I inspect the table it is updated.

When I start my Phoenix server a postgres SQL error renders to the page.

I went into my Phoenix app and did a search and replace for all status_action_value strings and changed them to testbed_url

I still get the error.

I do not know how to fix it.

`ERROR 42703 (undefined_column) column t0.status_action_value does not exist

    query: SELECT t0."id", t0."developer", t0."name", t0."note", t0."status", t0."status_action_value", t0."version", t0."url", t0."inserted_at", t0."updated_at" FROM "testbeds" AS t0`

I don’t understand where the error is coming from “status_action_value” is not anywhere in my code due to the search and replace I invoked.

Full error

Request: GET /testbeds
** (exit) an exception was raised:
    ** (Postgrex.Error) ERROR 42703 (undefined_column) column t0.status_action_value does not exist

    query: SELECT t0."id", t0."developer", t0."name", t0."note", t0."status", t0."status_action_value", t0."version", t0."url", t0."inserted_at", t0."updated_at" FROM "testbeds" AS t0
        (ecto_sql 3.10.1) lib/ecto/adapters/sql.ex:913: Ecto.Adapters.SQL.raise_sql_call_error/1
        (ecto_sql 3.10.1) lib/ecto/adapters/sql.ex:828: Ecto.Adapters.SQL.execute/6
        (ecto 3.10.1) lib/ecto/repo/queryable.ex:229: Ecto.Repo.Queryable.execute/4
        (ecto 3.10.1) lib/ecto/repo/queryable.ex:19: Ecto.Repo.Queryable.all/3
        (app 0.1.0) lib/app_web/controllers/test_bed_controller.ex:8: AppWeb.TestBedController.index/2
        (app 0.1.0) lib/app_web/controllers/test_bed_controller.ex:1: AppWeb.TestBedController.action/2
        (app 0.1.0) lib/app_web/controllers/test_bed_controller.ex:1: AppWeb.TestBedController.phoenix_controller_pipeline/2
        (phoenix 1.7.2) lib/phoenix/router.ex:430: Phoenix.Router.__call__/5
        (app 0.1.0) lib/app_web/endpoint.ex:1: AppWeb.Endpoint.plug_builder_call/2
        (app 0.1.0) lib/plug/debugger.ex:136: AppWeb.Endpoint."call (overridable 3)"/2
        (app 0.1.0) lib/app_web/endpoint.ex:1: AppWeb.Endpoint.call/2
        (phoenix 1.7.2) lib/phoenix/endpoint/sync_code_reload_plug.ex:22: Phoenix.Endpoint.SyncCodeReloadPlug.do_call/4
        (plug_cowboy 2.6.1) lib/plug/cowboy/handler.ex:11: Plug.Cowboy.Handler.init/2
        (cowboy 2.10.0) c:/Users/Bill/Desktop/testbed one field test/app/deps/cowboy/src/cowboy_handler.erl:37: :cowboy_handler.execute/2
        (cowboy 2.10.0) c:/Users/Bill/Desktop/testbed one field test/app/deps/cowboy/src/cowboy_stream_h.erl:306: :cowboy_stream_h.execute/3
        (cowboy 2.10.0) c:/Users/Bill/Desktop/testbed one field test/app/deps/cowboy/src/cowboy_stream_h.erl:295: :cowboy_stream_h.request_process/3
        (stdlib 4.0.1) proc_lib.erl:240: :proc_lib.init_p_do_apply/3

I’m pretty sure you still need to modify your related schema file, renaming the field in it from status_action_value to testbed_url.

When you run something like Repo.all(Testbed) or from(Testbed) |> Repo.all(), where you’re not specifying which columns to retrieve (using Ecto.Query.select/3), Ecto will fetch all fields defined in the schema module. This may seem redundant, that you need to define all the tables columns in migrations, and you need to specify them again as fields in the schema, but Ecto favors explicitness over “magic.” Also, there are valid use cases to have multiple schema modules for the same database table (for instance an “admin” schema module that can see and edit all fields and a “public” module that only exposes a subset), and in those cases that explicitness comes in handy.

3 Likes

I did the renaming as stated in my original post.

I don’t understand where the error is coming from “status_action_value” is not anywhere in my code due to the search and replace I invoked.

I am away from my work machine at the moment and won’t get back for a few days, but the reason I posted the question is because I had the same conclusion you did.

My guess is that Ecto has cached the query: Caching In Ecto v3.0 - DockYard

When you say all strings, do you actually mean you searched for "status_action_value", quotes included? Because in your schema module, that column name will be an atom, :status_action_value.

1 Like

Can you show the code generating the query then?