Potential Issue with Duplicate UUIDs in Many-to-Many Relationships
- Dominant language
- Go
- Stars
- 17.2k
- Forks
- 1k
- PR merge metrics
- No merged PRs in 30d
Description
Hello, First of all, I would like to express my appreciation for the excellent work on the ent library 🙌 ✨
---
It has been very beneficial in my project. I've encountered a potential issue that I wanted to bring to your attention.
Here is the sql and go code I'm using:
.sql
```sql
CREATE TABLE "public"."channel" (
"channel_id" uuid NOT NULL DEFAULT uuid_generate_v4(),
"alphabet_index" varchar DEFAULT ''::character varying,
"created_at" timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
"fk_parent_channel_id" uuid,
PRIMARY KEY ("channel_id")
);
CREATE TABLE "public"."channel_topic" (
"channel_topic_id" uuid NOT NULL DEFAULT uuid_generate_v4(),
"created_at" timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
"channel_id" uuid NOT NULL,
"topic_id" uuid NOT NULL,
PRIMARY KEY ("channel_topic_id")
);
CREATE TABLE "public"."topic" (
"topic_id" uuid NOT NULL DEFAULT uuid_generate_v4(),
"created_at" timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
"fk_topic_type_id" varchar NOT NULL,
PRIMARY KEY ("topic_id")
);
ALTER TABLE "public"."channel" ADD FOREIGN KEY ("fk_parent_channel_id") REFERENCES "public"."channel"("channel_id") ON DELETE SET NULL;
ALTER TABLE "public"."channel_topic" ADD FOREIGN KEY ("channel_id") REFERENCES "public"."channel"("channel_id");
ALTER TABLE "public"."channel_topic" ADD FOREIGN KEY ("topic_id") REFERENCES "public"."topic"("topic_id");
ALTER TABLE "public"."topic" ADD FOREIGN KEY ("fk_topic_type_id") REFERENCES "public"."topic_type"("topic_type_id");
```
.go
```go
func (db *db) create(ctx context.Context, record *record) (*ent.Channel, error) {
tx, _ := db.client.Debug().Tx(ctx)
topics, err := tx.
Topic.
Query().
Where(topic.IDIn(record.topicIDs...)).
All(ctx)
if err != nil {
_ = tx.Rollback()
return nil, err
}
channel, err := tx.
Channel.
Create().
SetAlphabetIndex("").
SetID(db.channelID(ctx, record.topicIDs...)).
AddTopics(topics...). // this is.
SetParentID(record.parentID).
Save(ctx)
if err != nil {
_ = tx.Rollback()
return nil, err
}
_ = tx.Commit()
return channel, nil
}
```
The problem arises when attempting to create a new channel and associate it with multiple topics.
The channel_topic table entries should each have a unique channel_topic_id generated by default via uuid_generate_v4().
However, when adding multiple topics to a channel using the `AddTopics(topics...)` method,
the same channel_topic_id is being used for all the entries, causing a below error 🤔.
```
add m2m edge for table channel_topic: pq: duplicate key value violates unique constraint \"channel_topic_pkey\""
```
I had to work around this issue by adding each topic individually in a loop, like this: (It's work 🙌)
```go
for _, t := range topics {
err = channel.Update().AddTopics(t).Exec(ctx)
if err != nil {
_ = tx.Rollback()
return nil, err
}
}
```
This ensures that each channel_topic entry gets a unique ID,
but it seems like something that should be handled internally by the ent library.
Could you please look into this? Thank you for your attention to this matter. 🙌
Contributor guide
Research direction
Start by reproducing the failure with the shown PostgreSQL schema and the Go transaction using Channel.Create().AddTopics(topics...). Inspect the many-to-many insertion path for channel_topic and compare it with adding topics individually. Done means bulk AddTopics creates a distinct channel_topic_id for every association without a duplicate-key error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, postgresql
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100