Home > database >  How to avoid stack overflow with gorm?
How to avoid stack overflow with gorm?

Time:01-25

First, database is created with sqlite3 test.db < schema.sql.

Contents of schema.sql:

CREATE TABLE x (
    id   INTEGER PRIMARY KEY,
    name TEXT
);

CREATE TABLE y (
    id   INTEGER PRIMARY KEY,
    name TEXT,
    x_id INTEGER REFERENCES x
);

Then the program is run with go run main.go.

Contents of main.go:

package main

import (
    "gorm.io/gorm"
    "gorm.io/driver/sqlite"
)

type X struct {
    ID   uint
    Name string
    Ys   []*Y
}

type Y struct {
    ID   uint
    Name string
    X    *X     `gorm:"column:x_id"`
}

func (X) TableName() string {
    return "x"
}

func (Y) TableName() string {
    return "y"
}

func main() {
    db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})

    x := &X{Name: "X"}
    y := &Y{Name: "Y", X: x}
    x.Ys = []*Y{y}

    db.Create(&x)
}

After which fatal error: stack overflow is thrown.

I guess it has something to do with the recursive nature of the structs and objects involved. When I comment out the Ys []*Y line along with y := &Y{Name: "Y", X: x} and x.Ys = []*Y{y} it successfully inserts "X" into table x, but when I comment out the Ys []*Y and x.Ys = []*Y{y} only and change db.Create(&x) to db.Create(&y) nothing gets inserted in either table.

EDIT

It saves x and y when y := &Y{Name: "Y", X: x} is changed to y := &Y{Name: "Y"}, but with x_id as NULL.

CodePudding user response:

The issue is indeed with the recursive nature of the relations: X contains []Y, and Y contains X.

As explained in documentation, the has-many relation is modeled simply using uint for the foreign key column:

type X struct {
    ID   uint
    Name string
    Ys   []*Y     `gorm:"foreignKey:XID"`
}

type Y struct {
    ID   uint
    Name string
    XID  uint     `gorm:"column:x_id"`
}

And you don't need to set y.XID, it will be filled automatically.

CodePudding user response:

Implementing Valuer interface did the trick.

func (x X) Value() (driver.Value, error) {
    return int64(x.ID), nil
}

https://gorm.io/docs/data_types.html

  •  Tags:  
  • Related