Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Associated id is save automatically? #199

Open
manicar2093 opened this issue Aug 30, 2021 · 3 comments
Open

Associated id is save automatically? #199

manicar2093 opened this issue Aug 30, 2021 · 3 comments

Comments

@manicar2093
Copy link

Hi!.

I'm having a little problem to save an associated id. I don't know if I'm doing it well. Let me explain what it is happen to me.

I have this db struct:

-- authors definition

CREATE TABLE authors (
	id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
	name TEXT
);

-- books definition

CREATE TABLE books (
	id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
	title TEXT,
	category TEXT,
	price INTEGER,
	discount NUMERIC,
	stock INTEGER,
	author_id INTEGER NOT NULL,
	FOREIGN KEY(author_id) REFERENCES authors(id)
);

These are my go models:

type Author struct {
	ID   int32
	Name string
}

type Book struct {
	ID       int32
	Title    string
	Category string
	Price    int
	Discount bool
	Stock    int
	Author   Author `ref:"author_id" fk:"id" autosave:"true"`
	AuthorID int32
}

I want to save an Author instance and pass it to a Book instance. I was expecting that the relation would save AuthorID automatically but no. It shows this error:

panic: ForeignKeyConstraintError: rel: inconsistent belongs to ref and fk

This is the code I'm running:

const dbPath = "./go-rel-example.db"

func main() {
	adapter, err := sqlite3.Open(dbPath)
	if err != nil {
		panic(err)
	}

	defer adapter.Close()

	repo := rel.New(adapter)

	err = Example(context.Background(), repo)
	if err != nil {
		panic(err)
	}

}

func Example(ctx context.Context, repo rel.Repository) error {

	return repo.Transaction(ctx, func(ctx context.Context) error {
		author := Author{
			Name: "Anne Paterson",
		}

		err := repo.Insert(ctx, &author)
		if err != nil {
			return err
		}
		log.Println(author)

		book := Book{
			Title:    "A new story",
			Category: "horror",
			Price:    10,
			Discount: false,
			Stock:    2,
			Author:   author,
		}
		err = repo.Insert(ctx, &book)
		if err != nil {
			return err
		}

		log.Println(book)

		log.Println("-----DONE-----")

		return nil
	})

}

Now my questing here is if this can be done. I don have any problem to pass the id to the association, but I thing would be great to pass the saved instance and rel takes the associated id to save it.

Thanks!!! 🏆 REL is awesome! 😃

@Fs02
Copy link
Member

Fs02 commented Aug 31, 2021

Hi, thanks for using REL and reporting this,

Currently REL checks if foreign and association key have the same key to prevent modifying association of other records.

rel/filter_query.go

Lines 636 to 651 in 9969cea

func filterBelongsTo(assoc Association) (FilterQuery, error) {
var (
rValue = assoc.ReferenceValue()
fValue = assoc.ForeignValue()
filter = Eq(assoc.ForeignField(), fValue)
)
if rValue != fValue {
return filter, ConstraintError{
Key: assoc.ReferenceField(),
Type: ForeignKeyConstraint,
Err: errors.New("rel: inconsistent belongs to ref and fk"),
}
}
return filter, nil

but I think it's make sense to support your case for belongs to, we can set the reference value if it's a zero value around here:

rel/repository.go

Lines 558 to 567 in 9969cea

if loaded {
filter, err := filterBelongsTo(assoc)
if err != nil {
return err
}
if err := r.update(cw, assocDoc, assocMut, filter); err != nil {
return err
}
} else {

let me know if you are interested to submit fix for this, Thank you

@manicar2093
Copy link
Author

Hi! Thank for your answer.

Let me give it a check and I send my PR. :D

@Fs02
Copy link
Member

Fs02 commented Aug 31, 2021

Thank you, let me know if you have any question!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants