Как вставить слайс

У меня есть база данных postgres, для которой я хотел бы сгенерировать таблицы и записать их с помощью Gorp, однако я получаю сообщение об ошибке, когда пытаюсь вставить из-за срезов, содержащихся в моих структурах "sql: преобразование аргумента $4 тип: неподдерживаемый тип [] core.EmbeddedStruct, часть структуры.

Мои структуры выглядят следующим образом:

type Struct1 struct {
	ID              string
	Name            string
	Location        string
	EmbeddedStruct  []EmbeddedStruct
}

type EmbeddedStruct struct {
	ID         string
	Name       string
	struct1Id  string
	EmbeddedStruct2  []EmbeddedStruct2
}

type EmbeddedStruct2 struct {
	ID               string
	Name             string
	embeddedStructId string
}

func (repo *PgStruct1Repo) Write(t *core.Struct1) error {
	trans, err := createTransaction(repo.dbMap)
	defer closeTransaction(trans)

	if err != nil {
		return err
	}

	// Check to see if struct1 item already exists
	exists, err := repo.exists(t.ID, trans)
	if err != nil {
		return err
	}

	if !exists {
		log.Debugf("saving new struct1 with ID %s", t.ID)
		err = trans.Insert(t)
		if err != nil {
			return err
		}
		return nil
	}

	return nil
}

Кто-нибудь имеет опыт или знает, поддерживает ли Gorp вставку фрагментов? Из того, что я читал, кажется, что поддерживаются срезы только для операторов SELECT.


person luepin    schedule 20.11.2019    source источник


Ответы (1)


Gorp поддерживает вставку вариативного количества фрагментов, поэтому, если у вас есть фрагмент records , ты можешь сделать:

 err = db.Insert(records...)

Однако из вашего вопроса кажется, что вы хотите сохранить одну запись с полем структуры среза.

https://github.com/go-gorp/gorp

gorp ничего не знает об отношениях между вашими структурами (по крайней мере пока).

Итак, вы должны сами разобраться в отношениях. Лично я решил бы эту проблему так: Gorp игнорирует фрагмент на родитель:

type Struct1 struct {
    ID              string
    Name            string
    Location        string
    EmbeddedStruct  []EmbeddedStruct `db:"-"`
}

А затем используйте PostInsert хук, чтобы сохранить EmbeddedStruct (примечание, это плохой имя, так как на самом деле это не встроенная структура)

func (s *Struct1) PostInsert(sql gorp.SqlExecutor) error {
    for i := range s.EmbeddedStruct {
        s.EmbeddedStruct[i].struct1Id = s.ID
    }
    return sql.Insert(s.EmbeddedStruct...)
}

Затем повторите процесс на EmbeddedStruct2.

Позаботьтесь о правильной настройке отношений на стороне БД, чтобы обеспечить ссылочную целостность (например, ON DELETE CASCADE/RESTRICT), и, вероятно, было бы неплохо обернуть все это в транзакцию.

person dave    schedule 20.11.2019
comment
Спасибо! Это сработало для меня! Только одно исправление: для вставки требуется, чтобы аргумент был типа []interface{}, поэтому вам нужно сначала преобразовать s.EmbeddedStruct в это, прежде чем вставлять вариативное количество фрагментов. - person luepin; 23.11.2019