(ctx context.Context, base *DB, op clause.Association)
| 793 | } |
| 794 | |
| 795 | func (s setCreateOrUpdateG[T]) handleAssociation(ctx context.Context, base *DB, op clause.Association) error { |
| 796 | assoc := base.Association(op.Association) |
| 797 | if assoc.Error != nil { |
| 798 | return assoc.Error |
| 799 | } |
| 800 | |
| 801 | var ( |
| 802 | rel = assoc.Relationship |
| 803 | assocModel = reflect.New(rel.FieldSchema.ModelType).Interface() |
| 804 | fkNil = map[string]any{} |
| 805 | setMap = make(map[string]any, len(op.Set)) |
| 806 | ownerPKNames []string |
| 807 | ownerFKNames []string |
| 808 | primaryColumns []any |
| 809 | foreignColumns []any |
| 810 | ) |
| 811 | |
| 812 | for _, a := range op.Set { |
| 813 | setMap[a.Column.Name] = a.Value |
| 814 | } |
| 815 | |
| 816 | for _, ref := range rel.References { |
| 817 | fkNil[ref.ForeignKey.DBName] = nil |
| 818 | |
| 819 | if ref.OwnPrimaryKey && ref.PrimaryKey != nil { |
| 820 | ownerPKNames = append(ownerPKNames, ref.PrimaryKey.DBName) |
| 821 | primaryColumns = append(primaryColumns, clause.Column{Name: ref.PrimaryKey.DBName}) |
| 822 | foreignColumns = append(foreignColumns, clause.Column{Name: ref.ForeignKey.DBName}) |
| 823 | } else if !ref.OwnPrimaryKey && ref.PrimaryKey != nil { |
| 824 | ownerFKNames = append(ownerFKNames, ref.ForeignKey.DBName) |
| 825 | primaryColumns = append(primaryColumns, clause.Column{Name: ref.PrimaryKey.DBName}) |
| 826 | } |
| 827 | } |
| 828 | |
| 829 | assocDB := s.c.g.db.Session(&Session{NewDB: true, Context: ctx}).Model(assocModel).Where(op.Conditions) |
| 830 | |
| 831 | switch rel.Type { |
| 832 | case schema.HasOne, schema.HasMany: |
| 833 | assocDB = assocDB.Where("? IN (?)", foreignColumns, base.Select(ownerPKNames)) |
| 834 | switch op.Type { |
| 835 | case clause.OpUnlink: |
| 836 | return assocDB.Updates(fkNil).Error |
| 837 | case clause.OpDelete: |
| 838 | return assocDB.Delete(assocModel).Error |
| 839 | case clause.OpUpdate: |
| 840 | return assocDB.Updates(setMap).Error |
| 841 | } |
| 842 | case schema.BelongsTo: |
| 843 | switch op.Type { |
| 844 | case clause.OpDelete: |
| 845 | return base.Transaction(func(tx *DB) error { |
| 846 | assocDB.Statement.ConnPool = tx.Statement.ConnPool |
| 847 | base.Statement.ConnPool = tx.Statement.ConnPool |
| 848 | |
| 849 | if err := assocDB.Where("? IN (?)", primaryColumns, base.Select(ownerFKNames)).Delete(assocModel).Error; err != nil { |
| 850 | return err |
| 851 | } |
| 852 | return base.Updates(fkNil).Error |
no test coverage detected