gorm icon indicating copy to clipboard operation
gorm copied to clipboard

[QUESTION] - Looking for some help for many to many in gorm v2

Open sujit-baniya opened this issue 2 years ago • 4 comments

Your Question

Hi all, I'm finding it difficult to define many to many relationship using Gorm in following cases

features(feature_id, name, slug)
operations(operation_id, name, slug)
feature_operations(feature_id, operation_id)

type Feature struct {
	FeatureID  int64       `gorm:"primaryKey;column:feature_id" json:"feature_id"`
	Name       string      `validate:"required" json:"name"`
	Slug       string      `json:"slug"`
	Status     string      `json:"status"`
	Operations []Operation `gorm:"many2many:feature_operations;foreignKey:feature_id"`
	appModels.BaseModel
}

When using feature_id, I get error

column feature_operations.feature_feature_id does not exist

When using id, I get error

invalid foreign key: id

Please suggest any opinion

The document you expected this should be explained

Expected answer

I wanted to link Operations with feature based on primary key other than "ID"

sujit-baniya avatar Feb 06 '23 14:02 sujit-baniya

I think that gorm will consider id as a special field while concat 'feature' and 'feature_id' to 'feature_feature_id' as a non-special field.

I found some code at line 228 of schema/relationship.go joinFieldName := strings.Title(schema.Name) + ownField.Name that may be related to this bug.

I don't know if this is a violation of "convention", but I don't think GORM should have this problem (instead of letting users follow GORM and use id).

Looking forward to someone's help!

package main

import (
	"github.com/stretchr/testify/assert"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
	"testing"
)

type Feature struct {
	FeatureID  int64 `gorm:"primaryKey;column:feature_id"`
	Name       string
	Slug       string
	Operations []Operation `gorm:"many2many:feature_operations;foreignKey:feature_id"`
}

type Operation struct {
	OperationID int64 `gorm:"primaryKey;column:operation_id"`
	Name        string
	Slug        string
	Features    []Feature `gorm:"many2many:feature_operations;foreignKey:operation_id"`
}

func TestGORM(t *testing.T) {
	a := assert.New(t)

	db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
	a.NoError(err)

	db = db.Exec(`
CREATE TABLE features (
	feature_id INTEGER PRIMARY KEY,
	name VARCHAR(20),
	slug VARCHAR(100)
);

CREATE TABLE operations (
	operation_id INTEGER PRIMARY KEY,
	name VARCHAR(20),
	slug VARCHAR(100)
);

CREATE TABLE feature_operations(
    feature_id INTEGER,
    operation_id INTEGER,
    FOREIGN KEY (feature_id) REFERENCES features(feature_id),
    FOREIGN KEY (operation_id) REFERENCES operations(operation_id)
);

INSERT INTO features(feature_id, name, slug) 
VALUES (0, "feature_name0", "feature_slug0"),
       (1, "feature_name1", "feature_slug1");

INSERT INTO operations(operation_id, name, slug) 
VALUES (0, "operation_name0", "operation_slug0"),
       (1, "operation_name1", "operation_slug1"),
       (2, "operation_name2", "operation_slug2");

INSERT INTO feature_operations(feature_id, operation_id) 
VALUES (0, 0),
       (0, 1),
       (1, 1),
       (1, 2);
`)

	var features []Feature
	a.NoError(db.Debug().Model(&Feature{}).Preload("Operations").Find(&features).Error)
	t.Log(features)
}

tzq0301 avatar Feb 06 '23 20:02 tzq0301

@tzq0301 Exactly the place of issue. Temporarily, I'm using the following changes to work.

https://github.com/sujit-baniya/gorm/commit/d9c8b15855a757f05a9e812fef2bca35b10a99c7

sujit-baniya avatar Feb 07 '23 02:02 sujit-baniya

Also, users should not be forced to use id or ID as primary key

sujit-baniya avatar Feb 07 '23 02:02 sujit-baniya

This issue has been automatically marked as stale because it has been open 360 days with no activity. Remove stale label or comment or this will be closed in 180 days

github-actions[bot] avatar Feb 02 '24 02:02 github-actions[bot]