func ExampleBegin() { type Person struct { // ... } // Lets begin transaction: tx, err := rebecca.Begin() if err != nil { // Handle error when unable to begin transaction here. panic(err) } // Lets make sure, that transaction gets rolled back if we return prematurely: defer tx.Rollback() // Now you can use `tx` the same way as `rebecca` package, i.e.: people := []Person{} if err := tx.Where(&people, "name = $1 AND age > $2", "James", 25); err != nil { panic(err) } // At this point people contains all Person records with name="James" and // with age > 25. fmt.Print(people) // This way you can use all main exported functions of rebecca package as // methods on `tx`: // - tx.All(records) // - tx.First(record, where, args...) // - tx.Get(ID, record) // - tx.Remove(record) // - tx.Save(record) // - tx.Where(records, where, args...) }
func ExampleTransaction_Rollback() { tx, err := rebecca.Begin() if err != nil { panic(err) } defer tx.Rollback() // Sometimes `defer tx.Rollback()` is not acceptable and you might need // better control, in that case, you can just call `tx.Rollback()` when // necessary: if someBadCondition() { tx.Rollback() } }
func ExampleTransaction_Commit() { tx, err := rebecca.Begin() if err != nil { panic(err) } defer tx.Rollback() // .. doing some hard work with tx .. // And finally, lets commit the transaction: if err := tx.Commit(); err != nil { // Handle error, when transaction can not be committed, here. panic(err) } // At this point transaction `tx` is committed and should not be used // further. }
func ExampleTransaction_Context() { type Person struct { // ... } tx, err := rebecca.Begin() if err != nil { panic(err) } defer tx.Rollback() // When you need to use rebecca.Context features (like Order or Limit/Skip, // or even Group) together with transaction, you can instantiate // rebecca.Context using transaction method Context: ctx := tx.Context(&rebecca.Context{Order: "age ASC", Limit: 30, Skip: 90}) // And then use `ctx` as usual: people := []Person{} if err := ctx.All(&people); err != nil { panic(err) } fmt.Print(people) }
func TestDoubleCommit(t *testing.T) { rebecca.SetupDriver(fake.NewDriver()) tx, err := rebecca.Begin() if err != nil { t.Fatal(err) } if err := tx.Commit(); err != nil { t.Fatal(err) } err = tx.Commit() if err == nil { t.Fatal("Expected transaction to no being able to be committed twice") } expected := `Unable to commit transaction - Current transaction is already finished` actual := err.Error() if actual != expected { t.Errorf("Expected %s to equal %s", actual, expected) } }
func TestTransactions(t *testing.T) { d := fake.NewDriver() rebecca.SetupDriver(d) d.RegisterWhere("title = $1", func(record []field.Field, args ...interface{}) (bool, error) { for _, f := range record { if f.DriverName == "title" { return f.Value.(string) == args[0].(string), nil } } return false, fmt.Errorf("record %+v does not have title field", record) }) txa, err := rebecca.Begin() if err != nil { t.Fatal(err) } defer txa.Rollback() txb, err := rebecca.Begin() if err != nil { t.Fatal(err) } defer txb.Rollback() pa := &Post{Title: "Hello world", Content: "Content of Hello World, many hellos", CreatedAt: time.Now()} if err := txa.Save(pa); err != nil { t.Fatal(err) } pa2 := &Post{Title: "Hello Blog", Content: "More hellos here!", CreatedAt: time.Now()} if err := txa.Save(pa2); err != nil { t.Fatal(err) } actual := &Post{} if err := txa.Get(pa.ID, actual); err != nil { t.Fatal(err) } actual = &Post{} if err := txb.Get(pa.ID, actual); err == nil { t.Errorf( "Expected transaction B not to find record saved in transaction A, but got: %+v", actual, ) } pb := &Post{Title: "Super Post", Content: "Super Content", CreatedAt: time.Now()} if err := txb.Save(pb); err != nil { t.Fatal(err) } actual = &Post{} if err := txa.Get(pb.ID, actual); err == nil { t.Errorf( "Expected transaction A not to find record saved in transaction B, but got: %+v", actual, ) } expecteds := []Post{*pa, *pa2} actuals := []Post{} if err := txa.All(&actuals); err != nil { t.Fatal(err) } if !equalPosts(actuals, expecteds) { t.Errorf("Expected %+v to equal %+v", actuals, expecteds) } expecteds = []Post{*pa} actuals = []Post{} if err := txa.Where(&actuals, "title = $1", "Hello world"); err != nil { t.Fatal(err) } if !equalPosts(actuals, expecteds) { t.Errorf("Expected %+v to equal %+v", actuals, expecteds) } expecteds = []Post{*pa2} actuals = []Post{} if err := txa.Where(&actuals, "title = $1", "Hello Blog"); err != nil { t.Fatal(err) } if !equalPosts(actuals, expecteds) { t.Errorf("Expected %+v to equal %+v", actuals, expecteds) } expecteds = []Post{} actuals = []Post{} if err := txa.Where(&actuals, "title = $1", "Super Post"); err != nil { t.Fatal(err) } if !equalPosts(actuals, expecteds) { t.Errorf("Expected %+v to equal %+v", actuals, expecteds) } expecteds = []Post{*pb} actuals = []Post{} if err := txb.All(&actuals); err != nil { t.Fatal(err) } if !equalPosts(actuals, expecteds) { t.Errorf("Expected %+v to equal %+v", actuals, expecteds) } if err := txa.Commit(); err != nil { t.Fatal(err) } txb.Rollback() txc, err := rebecca.Begin() if err != nil { t.Fatal(err) } actual = &Post{} if err := txc.Get(pa.ID, actual); err != nil { t.Fatal(err) } if !actual.Equal(pa) { t.Errorf("Expected %+v to equal %+v", actual, pa) } expecteds = []Post{} actuals = []Post{} if err := txc.Where(&actuals, "title = $1", "Super Post"); err != nil { t.Fatal(err) } if !equalPosts(actuals, expecteds) { t.Errorf("Expected %+v to equal %+v", actuals, expecteds) } expected := pa2 actual = &Post{} if err := txc.First(actual, "title = $1", "Hello Blog"); err != nil { t.Fatal(err) } if !actual.Equal(expected) { t.Errorf("Expected %+v to equal %+v", actual, expected) } txd, err := rebecca.Begin() if err != nil { t.Fatal(err) } if err := txd.Remove(pa); err != nil { t.Fatal(err) } expecteds = []Post{*pa2} actuals = []Post{} if err := txd.All(&actuals); err != nil { t.Fatal(err) } if !equalPosts(actuals, expecteds) { t.Errorf("Expected %+v to equal %+v", actuals, expecteds) } expecteds = []Post{*pa, *pa2} actuals = []Post{} if err := txc.All(&actuals); err != nil { t.Fatal(err) } if !equalPosts(actuals, expecteds) { t.Errorf("Expected %+v to equal %+v", actuals, expecteds) } expecteds = []Post{*pa, *pa2} actuals = []Post{} if err := rebecca.All(&actuals); err != nil { t.Fatal(err) } if !equalPosts(actuals, expecteds) { t.Errorf("Expected %+v to equal %+v", actuals, expecteds) } if err := txd.Commit(); err != nil { t.Fatal(err) } expecteds = []Post{*pa2} actuals = []Post{} if err := rebecca.All(&actuals); err != nil { t.Fatal(err) } if !equalPosts(actuals, expecteds) { t.Errorf("Expected %+v to equal %+v", actuals, expecteds) } }
func TestTransactions(t *testing.T) { setup(t) txa, err := rebecca.Begin() if err != nil { t.Fatal(err) } defer txa.Rollback() txb, err := rebecca.Begin() if err != nil { t.Fatal(err) } defer txb.Rollback() pa := &Post{Title: "Hello world", Content: "Content of Hello World, many hellos", CreatedAt: time.Now()} if err := txa.Save(pa); err != nil { t.Fatal(err) } actual := &Post{} if err := txa.Get(pa.ID, actual); err != nil { t.Fatal(err) } actual = &Post{} if err := txb.Get(pa.ID, actual); err == nil { t.Errorf( "Expected transaction B not to find record saved in transaction A, but got: %+v", actual, ) } pb := &Post{Title: "Super Post", Content: "Super Content", CreatedAt: time.Now()} if err := txb.Save(pb); err != nil { t.Fatal(err) } actual = &Post{} if err := txa.Get(pb.ID, actual); err == nil { t.Errorf( "Expected transaction A not to find record saved in transaction B, but got: %+v", actual, ) } expecteds := []Post{*pa} actuals := []Post{} if err := txa.All(&actuals); err != nil { t.Fatal(err) } if !equalPosts(actuals, expecteds) { t.Errorf("Expected %+v to equal %+v", actuals, expecteds) } expecteds = []Post{*pb} actuals = []Post{} if err := txb.All(&actuals); err != nil { t.Fatal(err) } if !equalPosts(actuals, expecteds) { t.Errorf("Expected %+v to equal %+v", actuals, expecteds) } if err := txa.Commit(); err != nil { t.Fatal(err) } txb.Rollback() txc, err := rebecca.Begin() if err != nil { t.Fatal(err) } actual = &Post{} if err := txc.Get(pa.ID, actual); err != nil { t.Fatal(err) } if !actual.Equal(pa) { t.Errorf("Expected %+v to equal %+v", actual, pa) } }