func BenchmarkModelHasMany2ManyGopg(b *testing.B) { seedDB() db := pg.Connect(pgOptions()) defer db.Close() b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { var books []Book err := db.Model(&books). Columns("book.*", "Genres"). Limit(100). Select() if err != nil { b.Fatal(err) } if len(books) != 100 { b.Fatalf("got %d, wanted 100", len(books)) } for _, book := range books { if len(book.Genres) != 10 { b.Fatalf("got %d, wanted 10", len(book.Genres)) } } } }) }
func BenchmarkExecWithError(b *testing.B) { db := pg.Connect(pgOptions()) defer db.Close() _, err := db.Exec( `CREATE TABLE exec_with_error_test(id bigint PRIMARY KEY, name varchar(500))`) if err != nil { b.Fatal(err) } _, err = db.Exec(` INSERT INTO exec_with_error_test(id, name) VALUES(?, ?) `, 1, "hello world") if err != nil { b.Fatal(err) } defer db.Exec(`DROP TABLE exec_with_error_test`) b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _, err := db.Exec(`INSERT INTO exec_with_error_test(id) VALUES(?)`, 1) if err == nil { b.Fatalf("got nil error, expected IntegrityError") } else if _, ok := err.(*pg.IntegrityError); !ok { b.Fatalf("got " + err.Error() + ", expected IntegrityError") } } }) }
func TestStatementTimeout(t *testing.T) { opt := pgOptions() opt.Params = map[string]interface{}{ "statement_timeout": 1000, } db := pg.Connect(opt) defer db.Close() _, err := db.Exec("SELECT pg_sleep(60)") if err == nil { t.Fatalf("err is nil") } if err.Error() != "ERROR #57014 canceling statement due to statement timeout: " { t.Fatalf("got %q", err.Error()) } if db.Pool().Len() != 1 || db.Pool().FreeLen() != 1 { t.Fatalf("pool is empty") } err = eventually(func() error { return verifyNoActivity(db) }, 10*time.Second) if err != nil { t.Fatal(err) } }
func TestCancelRequestOnTimeout(t *testing.T) { opt := pgOptions() opt.ReadTimeout = time.Second db := pg.Connect(opt) defer db.Close() _, err := db.Exec("SELECT pg_sleep(60)") if err == nil { t.Fatalf("err is nil") } neterr, ok := err.(net.Error) if !ok { t.Fatalf("got %v, expected net.Error", err) } if !neterr.Timeout() { t.Fatalf("got %v, expected timeout", err) } if db.Pool().FreeLen() != 1 { t.Fatalf("len is %d", db.Pool().FreeLen()) } if db.Pool().Len() != 1 { t.Fatalf("size is %d", db.Pool().Len()) } err = eventually(func() error { return verifyNoActivity(db) }, 10*time.Second) if err != nil { t.Fatal(err) } }
func Example_json() { db := pg.Connect(&pg.Options{ User: "******", }) defer db.Close() _, err := db.Exec(`CREATE TEMP TABLE items (id serial, data json)`) if err != nil { panic(err) } item1 := Item{ Id: 1, Data: map[string]interface{}{"hello": "world"}, } if err := db.Create(&item1); err != nil { panic(err) } var item Item err = db.Model(&item).Where("id = ?", 1).Select() if err != nil { panic(err) } fmt.Println(item) // Output: {1 map[hello:world]} }
func ExampleConnect() { db := pg.Connect(&pg.Options{ User: "******", }) err := db.Close() fmt.Println(err) // Output: <nil> }
func (t *ListenerTest) SetUpTest(c *C) { opt := pgOptions() opt.PoolSize = 2 opt.PoolTimeout = time.Second t.db = pg.Connect(opt) ln, err := t.db.Listen("test_channel") c.Assert(err, IsNil) t.ln = ln }
func TestUnixSocket(t *testing.T) { opt := pgOptions() opt.Network = "unix" opt.Addr = "/var/run/postgresql/.s.PGSQL.5432" db := pg.Connect(opt) defer db.Close() _, err := db.Exec("SELECT 'test_unix_socket'") if err != nil { t.Fatal(err) } }
func BenchmarkQueryRow(b *testing.B) { db := pg.Connect(pgOptions()) defer db.Close() b.ResetTimer() for i := 0; i < b.N; i++ { var dst numLoader _, err := db.QueryOne(&dst, `SELECT ?::bigint AS num`, 1) if err != nil { b.Fatal(err) } if dst.Num != 1 { b.Fatalf("got %d, wanted 1", dst.Num) } } }
func BenchmarkQueryRowsGopgDiscard(b *testing.B) { seedDB() db := pg.Connect(pgOptions()) defer db.Close() b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _, err := db.Query(pg.Discard, `SELECT * FROM records LIMIT 100`) if err != nil { b.Fatal(err) } } }) }
func BenchmarkQueryRowScan(b *testing.B) { db := pg.Connect(pgOptions()) defer db.Close() b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { var n int64 _, err := db.QueryOne(pg.Scan(&n), `SELECT ? AS num`, 1) if err != nil { b.Fatal(err) } if n != 1 { b.Fatalf("got %d, wanted 1", n) } } }) }
func connectDB() *pg.DB { db := pg.Connect(&pg.Options{ User: "******", }) err := createTestSchema(db) if err != nil { panic(err) } err = db.Create(&Book{ Title: "book 1", AuthorID: 10, EditorID: 11, CreatedAt: time.Now(), }) if err != nil { panic(err) } err = db.Create(&Book{ Title: "book 2", AuthorID: 10, EditorID: 12, CreatedAt: time.Now(), }) if err != nil { panic(err) } err = db.Create(&Book{ Title: "book 3", AuthorID: 11, EditorID: 11, CreatedAt: time.Now(), }) if err != nil { panic(err) } return db }
func BenchmarkQueryRowsGopgORM(b *testing.B) { seedDB() db := pg.Connect(pgOptions()) defer db.Close() b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { var rs []Record err := db.Model(&rs).Limit(100).Select() if err != nil { b.Fatal(err) } if len(rs) != 100 { b.Fatalf("got %d, wanted 100", len(rs)) } } }) }
func BenchmarkQueryRowsGopgReflect(b *testing.B) { seedDB() db := pg.Connect(pgOptions()) defer db.Close() b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { var rs []Record _, err := db.Query(&rs, `SELECT * FROM records LIMIT 100`) if err != nil { b.Fatal(err) } if len(rs) != 100 { b.Fatalf("got %d, wanted 100", len(rs)) } } }) }
func BenchmarkExec(b *testing.B) { db := pg.Connect(pgOptions()) defer db.Close() _, err := db.Exec( `CREATE TABLE exec_test(id bigint, name varchar(500))`) if err != nil { b.Fatal(err) } defer db.Exec(`DROP TABLE exec_test`) b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _, err := db.Exec(`INSERT INTO exec_test(id, name) VALUES(?, ?)`, 1, "hello world") if err != nil { b.Fatal(err) } } }) }
func BenchmarkQueryRowStmtScan(b *testing.B) { db := pg.Connect(pgOptions()) defer db.Close() stmt, err := db.Prepare(`SELECT $1::bigint AS num`) if err != nil { b.Fatal(err) } defer stmt.Close() b.ResetTimer() for i := 0; i < b.N; i++ { var n int64 _, err := stmt.QueryOne(pg.Scan(&n), 1) if err != nil { b.Fatal(err) } if n != 1 { b.Fatalf("got %d, wanted 1", n) } } }
func BenchmarkExecStmt(b *testing.B) { db := pg.Connect(pgOptions()) defer db.Close() _, err := db.Exec(`CREATE TEMP TABLE statement_exec(id bigint, name varchar(500))`) if err != nil { b.Fatal(err) } stmt, err := db.Prepare(`INSERT INTO statement_exec(id, name) VALUES($1, $2)`) if err != nil { b.Fatal(err) } defer stmt.Close() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := stmt.Exec(1, "hello world") if err != nil { b.Fatal(err) } } }
func init() { db = pg.Connect(&pg.Options{ User: "******", }) }
func (t *DBTest) SetUpTest(c *C) { t.db = pg.Connect(pgOptions()) }
PoolTimeout: 30 * time.Second, IdleTimeout: time.Second, // be aggressive in tests } } type valuerError string func (e valuerError) Value() (driver.Value, error) { return nil, errors.New(string(e)) } var _ = Describe("driver.Valuer", func() { var db *pg.DB BeforeEach(func() { db = pg.Connect(pgOptions()) }) AfterEach(func() { Expect(db.Close()).NotTo(HaveOccurred()) }) It("handles driver.Valuer error", func() { _, err := db.Exec("SELECT ?", valuerError("driver.Valuer error")) Expect(err).To(MatchError("driver.Valuer error")) }) }) var _ = Describe("Collection", func() { var db *pg.DB
func Init(options *pg.Options) { db = pg.Connect(options) }
func (t *PoolTest) SetUpTest(c *C) { opt := pgOptions() opt.IdleTimeout = time.Second t.db = pg.Connect(opt) }
func TestConversion(t *testing.T) { conversionTests := []conversionTest{ {src: true, dst: nil, wanterr: "pg: Decode(nil)"}, {src: true, dst: new(uintptr), wanterr: "pg: Decode(unsupported uintptr)"}, {src: true, dst: true, wanterr: "pg: Decode(nonsettable bool)"}, {src: true, dst: (*bool)(nil), wanterr: "pg: Decode(nonsettable *bool)"}, {src: nil, dst: new(*bool), pgtype: "bool", wantnil: true}, {src: nil, dst: new(bool), pgtype: "bool", wantzero: true}, {src: true, dst: new(bool), pgtype: "bool"}, {src: true, dst: new(*bool), pgtype: "bool"}, {src: nil, dst: new(string), pgtype: "text", wantzero: true}, {src: nil, dst: new(*string), pgtype: "text", wantnil: true}, {src: "hello world", dst: new(string), pgtype: "text"}, {src: "hello world", dst: new(*string), pgtype: "text"}, {src: "'\"\000", dst: new(string), wanted: `'"`, pgtype: "text"}, {src: []byte("hello world\000"), dst: new([]byte), pgtype: "bytea"}, {src: []byte{}, dst: new([]byte), pgtype: "bytea", wantzero: true}, {src: nil, dst: new([]byte), pgtype: "bytea", wantnil: true}, {src: int(math.MaxInt32), dst: new(int), pgtype: "int"}, {src: int(math.MinInt32), dst: new(int), pgtype: "int"}, {src: nil, dst: new(int), pgtype: "int", wantzero: true}, {src: int(math.MaxInt32), dst: new(*int), pgtype: "int"}, {src: nil, dst: new(*int), pgtype: "int", wantnil: true}, {src: int8(math.MaxInt8), dst: new(int8), pgtype: "smallint"}, {src: int8(math.MinInt8), dst: new(int8), pgtype: "smallint"}, {src: int16(math.MaxInt16), dst: new(int16), pgtype: "smallint"}, {src: int16(math.MinInt16), dst: new(int16), pgtype: "smallint"}, {src: int32(math.MaxInt32), dst: new(int32), pgtype: "int"}, {src: int32(math.MinInt32), dst: new(int32), pgtype: "int"}, {src: int64(math.MaxInt64), dst: new(int64), pgtype: "bigint"}, {src: int64(math.MinInt64), dst: new(int64), pgtype: "bigint"}, {src: uint(math.MaxUint32), dst: new(uint), pgtype: "bigint"}, {src: uint8(math.MaxUint8), dst: new(uint8), pgtype: "smallint"}, {src: uint16(math.MaxUint16), dst: new(uint16), pgtype: "int"}, {src: uint32(math.MaxUint32), dst: new(uint32), pgtype: "bigint"}, {src: uint64(math.MaxUint64), dst: new(uint64)}, {src: float32(math.MaxFloat32), dst: new(float32), pgtype: "decimal"}, {src: float32(math.SmallestNonzeroFloat32), dst: new(float32), pgtype: "decimal"}, {src: float64(math.MaxFloat64), dst: new(float64), pgtype: "decimal"}, {src: float64(math.SmallestNonzeroFloat64), dst: new(float64), pgtype: "decimal"}, {src: nil, dst: new([]int), pgtype: "jsonb", wantnil: true}, {src: []int(nil), dst: new([]int), pgtype: "jsonb", wantnil: true}, {src: []int{}, dst: new([]int), pgtype: "jsonb", wantzero: true}, {src: []int{1, 2, 3}, dst: new([]int), pgtype: "jsonb"}, {src: IntSlice{1, 2, 3}, dst: new(IntSlice), pgtype: "jsonb"}, { src: nil, dst: &types.Array{[]int(nil)}, pgtype: "int[]", wantzero: true, }, { src: types.Array{[]int(nil)}, dst: &types.Array{[]int(nil)}, pgtype: "int[]", wantzero: true, }, { src: types.Array{[]int{}}, dst: &types.Array{[]int(nil)}, pgtype: "int[]", }, { src: types.Array{[]int{1, 2, 3}}, dst: &types.Array{[]int(nil)}, pgtype: "int[]", }, {src: nil, dst: new([]int64), pgtype: "jsonb", wantnil: true}, {src: []int64(nil), dst: new([]int64), pgtype: "jsonb", wantnil: true}, {src: []int64{}, dst: new([]int64), pgtype: "jsonb", wantzero: true}, {src: []int64{1, 2, 3}, dst: new([]int64), pgtype: "jsonb"}, {src: Int64Slice{1, 2, 3}, dst: new(Int64Slice), pgtype: "jsonb"}, { src: nil, dst: &types.Array{[]int64(nil)}, pgtype: "bigint[]", wantzero: true, }, { src: types.Array{[]int64(nil)}, dst: &types.Array{[]int64(nil)}, pgtype: "bigint[]", wantzero: true, }, { src: types.Array{[]int64{}}, dst: &types.Array{[]int64(nil)}, pgtype: "bigint[]", }, { src: types.Array{[]int64{1, 2, 3}}, dst: &types.Array{[]int64(nil)}, pgtype: "bigint[]", }, {src: nil, dst: new([]float64), pgtype: "jsonb", wantnil: true}, {src: []float64(nil), dst: new([]float64), pgtype: "jsonb", wantnil: true}, {src: []float64{1.1, 2.22, 3.333}, dst: new([]float64), pgtype: "jsonb"}, {src: Float64Slice{1.1, 2.22, 3.333}, dst: new(Float64Slice), pgtype: "jsonb"}, { src: nil, dst: &types.Array{[]float64(nil)}, pgtype: "decimal[]", wantzero: true, }, { src: types.Array{[]float64(nil)}, dst: &types.Array{[]float64(nil)}, pgtype: "decimal[]", wantzero: true, }, { src: types.Array{[]float64{}}, dst: &types.Array{[]float64(nil)}, pgtype: "decimal[]", }, { src: types.Array{[]float64{1.1, 2.22, 3.333}}, dst: &types.Array{[]float64(nil)}, pgtype: "decimal[]", }, {src: nil, dst: new([]string), pgtype: "jsonb", wantnil: true}, {src: []string(nil), dst: new([]string), pgtype: "jsonb", wantnil: true}, {src: []string{}, dst: new([]string), pgtype: "jsonb", wantzero: true}, {src: []string{"foo\n", "bar {}", "'\\\""}, dst: new([]string), pgtype: "jsonb"}, {src: StringSlice{"foo", "bar"}, dst: new(StringSlice), pgtype: "jsonb"}, { src: nil, dst: &types.Array{[]string(nil)}, pgtype: "text[]", wantzero: true, }, { src: types.Array{[]string(nil)}, dst: &types.Array{[]string(nil)}, pgtype: "text[]", wantzero: true, }, { src: types.Array{[]string{}}, dst: &types.Array{[]string(nil)}, pgtype: "text[]", }, { src: types.Array{[]string{"one", "two", "three"}}, dst: &types.Array{[]string(nil)}, pgtype: "text[]", }, { src: nil, dst: new(map[string]string), pgtype: "jsonb", wantnil: true, }, { src: map[string]string(nil), dst: new(map[string]string), pgtype: "jsonb", wantnil: true, }, { src: map[string]string{"foo\n =>": "bar\n =>", "'\\\"": "'\\\""}, dst: new(map[string]string), pgtype: "jsonb", }, {src: &sql.NullBool{}, dst: &sql.NullBool{}, pgtype: "bool"}, {src: &sql.NullBool{Valid: true}, dst: &sql.NullBool{}, pgtype: "bool"}, {src: &sql.NullBool{Valid: true, Bool: true}, dst: &sql.NullBool{}, pgtype: "bool"}, {src: &sql.NullString{}, dst: &sql.NullString{}, pgtype: "text"}, {src: &sql.NullString{Valid: true}, dst: &sql.NullString{}, pgtype: "text"}, {src: &sql.NullString{Valid: true, String: "foo"}, dst: &sql.NullString{}, pgtype: "text"}, {src: &sql.NullInt64{}, dst: &sql.NullInt64{}, pgtype: "bigint"}, {src: &sql.NullInt64{Valid: true}, dst: &sql.NullInt64{}, pgtype: "bigint"}, {src: &sql.NullInt64{Valid: true, Int64: math.MaxInt64}, dst: &sql.NullInt64{}, pgtype: "bigint"}, {src: &sql.NullFloat64{}, dst: &sql.NullFloat64{}, pgtype: "decimal"}, {src: &sql.NullFloat64{Valid: true}, dst: &sql.NullFloat64{}, pgtype: "decimal"}, {src: &sql.NullFloat64{Valid: true, Float64: math.MaxFloat64}, dst: &sql.NullFloat64{}, pgtype: "decimal"}, {src: nil, dst: &customStrSlice{}, wantnil: true}, {src: customStrSlice{}, dst: &customStrSlice{}, wantzero: true}, {src: customStrSlice{"one", "two"}, dst: &customStrSlice{}}, {src: time.Time{}, dst: &time.Time{}, pgtype: "timestamp"}, {src: time.Now(), dst: &time.Time{}, pgtype: "timestamp"}, {src: time.Now().UTC(), dst: &time.Time{}, pgtype: "timestamp"}, {src: nil, dst: &time.Time{}, pgtype: "timestamp", wantzero: true}, {src: time.Now(), dst: new(*time.Time), pgtype: "timestamp"}, {src: nil, dst: new(*time.Time), pgtype: "timestamp", wantnil: true}, {src: time.Time{}, dst: &time.Time{}, pgtype: "timestamptz"}, {src: time.Now(), dst: &time.Time{}, pgtype: "timestamptz"}, {src: time.Now().UTC(), dst: &time.Time{}, pgtype: "timestamptz"}, {src: nil, dst: &time.Time{}, pgtype: "timestamptz", wantzero: true}, {src: time.Now(), dst: new(*time.Time), pgtype: "timestamptz"}, {src: nil, dst: new(*time.Time), pgtype: "timestamptz", wantnil: true}, {src: 1, dst: new(pg.Ints), wanted: pg.Ints{1}}, {src: "hello", dst: new(pg.Strings), wanted: pg.Strings{"hello"}}, {src: 1, dst: new(pg.IntSet), wanted: pg.IntSet{1: struct{}{}}}, {src: nil, dst: new(*JSONMap), wantnil: true, pgtype: "json"}, {src: nil, dst: new(JSONMap), wantnil: true, pgtype: "json"}, {src: JSONMap{}, dst: &JSONMap{}, pgtype: "json"}, {src: JSONMap{"foo": "bar"}, dst: &JSONMap{}, pgtype: "json"}, {src: JSONMap{"foo": "bar"}, dst: new(*JSONMap), pgtype: "json"}, {src: `{"foo": "bar"}`, dst: &JSONField{}, wanted: JSONField{Foo: "bar"}}, {src: nil, dst: new(*Struct), wantnil: true, pgtype: "json"}, {src: nil, dst: new(Struct), wantzero: true, pgtype: "json"}, {src: Struct{}, dst: &Struct{}, pgtype: "json"}, {src: Struct{Foo: "bar"}, dst: &Struct{}, pgtype: "json"}, {src: Struct{Foo: "bar"}, dst: new(*Struct), pgtype: "json"}, {src: `{"foo": "bar"}`, dst: new(Struct), wanted: Struct{Foo: "bar"}}, } db := pg.Connect(pgOptions()) db.Exec("CREATE EXTENSION hstore") defer db.Exec("DROP EXTENSION hstore") for i, test := range conversionTests { test.i = i var err error if _, ok := test.dst.(orm.ColumnScanner); ok { _, err = db.QueryOne(test.dst, "SELECT (?) AS dst", test.src) } else { dst := struct{ Dst interface{} }{Dst: test.dst} _, err = db.QueryOne(&dst, "SELECT (?) AS dst", test.src) } test.Assert(t, err) } for i, test := range conversionTests { test.i = i if test.pgtype == "" { continue } stmt, err := db.Prepare(fmt.Sprintf("SELECT ($1::%s) AS dst", test.pgtype)) if err != nil { t.Fatal(err) } if _, ok := test.dst.(orm.ColumnScanner); ok { _, err = stmt.QueryOne(test.dst, test.src) } else { dst := struct{ Dst interface{} }{Dst: test.dst} _, err = stmt.QueryOne(&dst, test.src) } test.Assert(t, err) if err := stmt.Close(); err != nil { t.Fatal(err) } } for i, test := range conversionTests { test.i = i if _, ok := test.dst.(orm.ColumnScanner); ok { continue } _, err := db.QueryOne(pg.Scan(test.dst), "SELECT (?) AS dst", test.src) test.Assert(t, err) } for i, test := range conversionTests { test.i = i if _, ok := test.dst.(orm.ColumnScanner); ok { continue } if test.pgtype == "" { continue } stmt, err := db.Prepare(fmt.Sprintf("SELECT ($1::%s) AS dst", test.pgtype)) if err != nil { t.Fatal(err) } _, err = stmt.QueryOne(pg.Scan(test.dst), test.src) test.Assert(t, err) if err := stmt.Close(); err != nil { t.Fatal(err) } } }
func ExampleDB_Query() { db := pg.Connect(&pg.Options{ User: "******", }) err := createSchema(db) if err != nil { panic(err) } user1 := &User{ Name: "admin", Emails: []string{"admin1@admin", "admin2@admin"}, } err = db.Create(user1) if err != nil { panic(err) } err = db.Create(&User{ Name: "root", Emails: []string{"root1@root", "root2@root"}, }) if err != nil { panic(err) } story1 := &Story{ Title: "Cool story", UserId: user1.Id, } err = db.Create(story1) var user User err = db.Model(&user).Where("id = ?", user1.Id).Select() if err != nil { panic(err) } var users []User err = db.Model(&users).Select() if err != nil { panic(err) } var story Story err = db.Model(&story). Columns("story.*", "User"). Where("story.id = ?", story1.Id). Select() if err != nil { panic(err) } fmt.Println(user) fmt.Println(users[0], users[1]) fmt.Println(story) // Output: User<1 admin [admin1@admin admin2@admin]> // User<1 admin [admin1@admin admin2@admin]> User<2 root [root1@root root2@root]> // Story<1 Cool story User<1 admin [admin1@admin admin2@admin]>> }
func _seedDB() error { db := pg.Connect(pgOptions()) defer db.Close() _, err := db.Exec(`DROP TABLE IF EXISTS records`) if err != nil { return err } _, err = db.Exec(` CREATE TABLE records( num1 serial, num2 serial, num3 serial, str1 text, str2 text, str3 text ) `) if err != nil { return err } for i := 0; i < 1000; i++ { _, err := db.Exec(` INSERT INTO records (str1, str2, str3) VALUES (?, ?, ?) `, randSeq(100), randSeq(200), randSeq(300)) if err != nil { return err } } err = createTestSchema(db) if err != nil { return err } for i := 1; i < 100; i++ { genre := Genre{ Id: i, Name: fmt.Sprintf("genre %d", i), } err = db.Create(&genre) if err != nil { return err } author := Author{ ID: i, Name: fmt.Sprintf("author %d", i), } err = db.Create(&author) if err != nil { return err } } for i := 1; i <= 1000; i++ { err = db.Create(&Book{ Id: i, Title: fmt.Sprintf("book %d", i), AuthorID: rand.Intn(99) + 1, CreatedAt: time.Now(), }) if err != nil { return err } for j := 1; j <= 10; j++ { err = db.Create(&BookGenre{ BookId: i, GenreId: rand.Intn(99) + 1, }) if err != nil { return err } err = db.Create(&Translation{ BookId: i, Lang: fmt.Sprintf("%d", j), }) if err != nil { return err } } } return nil }