Ryzey

Ryzey

I have a many_to_many table with a migration that looks like this:

    def change do
      create table(:drivers_drivers) do
        add(:child_id, references(:drivers, on_delete: :delete_all), null: false)
        add(:parent_id, references(:drivers, on_delete: :delete_all), null: false)
        add(:position, :integer, null: false)
      end

      create(unique_index(:drivers_drivers, [:parent_id, :child_id], name: "unique_parent_child"))
      create(unique_index(:drivers_drivers, [:parent_id, :position], name: "unique_parent_position"))
    end

This creates indexes in PostgreSQL that look like this:

Indexes:
    "drivers_drivers_pkey" PRIMARY KEY, btree (id)
    "unique_parent_child" UNIQUE, btree (parent_id, child_id)
    "unique_parent_position" UNIQUE, btree (parent_id, "position")

I found that I was unable to reference the unique indexes as a :conflict_target in a call to insert_all/3. I was expecting that I could provide the options on_conflict: :replace_all, conflict_target: {:constraint, :unique_parent_child}, but this results in the error ERROR 42704 (undefined_object): constraint "unique_parent_child" for table "drivers_drivers" does not exist.

I was able to fix this issue by adding the following to the migration:

    execute("""
    ALTER TABLE drivers_drivers 
    ADD CONSTRAINT "unique_parent_child" 
    UNIQUE USING INDEX "unique_parent_child";
    """)
    
    execute("""
    ALTER TABLE drivers_drivers 
    ADD CONSTRAINT "unique_parent_position" 
    UNIQUE USING INDEX "unique_parent_position";
    """)

It feels like I am doing something wrong. Is there a way of referencing indexes in the :conflict_target option without defining them in PostgreSQL as constraints? Or, is there a way of specifying in the migration that an index should also be a constraint, without having to execute SQL?

A supplementary question is how can I specify more than one constraint as the :conflict_target to insert_all? It seems to only accept a tuple, with a single constraint specified as the second element in the tuple.

Showing Posts 1 to 4

josevalim

josevalim

Creator of Elixir

Postgres makes a distinction between indexes and constraints. If you pass conflict_target: :unique_parent_child then it should work, without the constraint definitions.

You also cannot pass multiple constraints. You can however pass multiple field names and let postgres do the job of inferring it. Did you try passing conflict_target: [:parent_id, :child_id, :position]?

Ryzey

Ryzey OP

Thank you for your help

I have now removed the execute statements from the migration and I am no longer using the constraint tuple to provide the value of conflict_target. However I have not found a conflict_target value that gives me the desired result.

If I specify either:
conflict_target: [:parent_id, :child_id]
or
conflict_target: [:parent_id, :position]
then the unique index specified appears to be correctly inferred by PostgreSQL as unique_violation errors only occur for the other unspecified unique index.

I want both unique indexes to be inferred, but if I specify:
conflict_target: [:parent_id, :child_id, :position]
then I get the error:
ERROR 42P10 (invalid_column_reference): there is no unique or exclusion constraint matching the ON CONFLICT specification.

josevalim

josevalim

Creator of Elixir

Oh, so it can only infer a single index. Do you know if what you are trying to achieve is possible at all in Postgres? What would be the equivalent in SQL?

Ryzey

Ryzey OP

I have been trying to figure that out, but without success, so I am not sure it is possible (although my SQL knowledge is limited, so it could also be that :blush:).

What I learnt about Postgres 9.6 - SQL Insert today (open to correction):

  1. INSERT permits a single ON CONFLICT clause to be specified;
  2. A conflict_target is optional for ON CONFLICT DO NOTHING and, if omitted, conflicts with all usable constraints and unique indexes are handled. However, a conflict_target must be provided for ON CONFLICT UPDATE;
  3. The conflict_target either performs unique index inference or names a constraint explicitly;
  4. When performing inference, all unique indexes that (without regard to order) contain exactly the conflict_target-specified columns/expressions are inferred.

So, to me, that sounds like I can either specify a single constraint explicitly or use inference, which can infer multiple constraints but only on a single set of columns/expressions. Therefore I cannot specify or infer constraints on both (parent_id, child_id) and (parent_id, position). If this is the case, then Ecto is allowing me to do everything that is possible in Postgres.

— All posts loaded —

Where Next? Top

Trending in Questions Top

katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
achenet
Hello, I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind. However, when I launch mix phx.server, I get an error...
New
peck
Hi everyone. My team and I have been working on a fairly modest app based around video streaming and chat, but we’ve landed a customer t...
New
bradley
I really like the adapter patterns that ecto, nebulex, waffle, etc. use and would love find something similar for a key management servic...
New
unaware8150
Hello folks! So at work, we are seeing some situations where we have to define some “fixed” strings that are used across the codebase in...
New
Cxx-mlr
I’m working on a small exercise involving update_in/3, and I came up with this solution: data = %{ name: "Periodic Table", category:...
New
Alvinkariuki
How Can I Optimise Compile Time Dependencies I have been building an elixir application for about 2 years now. Many modules and files ha...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
juhalehtonen
There has been a thread to discuss the Stack Overflow Developer Survey on this forum every year since 2018, so here’s yet another one for...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews