Newer
Older
pokemon-go-trade / vendor / github.com / go-pg / pg / tx_test.go
package pg_test

import (
	"strings"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"github.com/go-pg/pg"
)

var _ = Describe("Tx", func() {
	var db *pg.DB

	BeforeEach(func() {
		db = pg.Connect(pgOptions())
	})

	AfterEach(func() {
		err := db.Close()
		Expect(err).NotTo(HaveOccurred())
	})

	It("reconnects on bad connection", func() {
		cn, err := db.Pool().Get()
		Expect(err).NotTo(HaveOccurred())

		cn.SetNetConn(&badConn{})
		db.Pool().Put(cn)

		tx, err := db.Begin()
		Expect(err).NotTo(HaveOccurred())

		err = tx.Rollback()
		Expect(err).NotTo(HaveOccurred())
	})

	It("supports multiple statements", func() {
		tx, err := db.Begin()
		Expect(err).NotTo(HaveOccurred())

		stmt1, err := tx.Prepare(`SELECT 'test_multi_prepare_tx1'`)
		Expect(err).NotTo(HaveOccurred())

		stmt2, err := tx.Prepare(`SELECT 'test_multi_prepare_tx2'`)
		Expect(err).NotTo(HaveOccurred())

		var s1 string
		_, err = stmt1.QueryOne(pg.Scan(&s1))
		Expect(err).NotTo(HaveOccurred())
		Expect(s1).To(Equal("test_multi_prepare_tx1"))

		var s2 string
		_, err = stmt2.QueryOne(pg.Scan(&s2))
		Expect(err).NotTo(HaveOccurred())
		Expect(s2).To(Equal("test_multi_prepare_tx2"))

		err = tx.Rollback()
		Expect(err).NotTo(HaveOccurred())
	})

	It("supports CopyFrom and CopyIn", func() {
		data := "hello\t5\nworld\t5\nfoo\t3\nbar\t3\n"

		_, err := db.Exec("DROP TABLE IF EXISTS test_copy_from")
		Expect(err).NotTo(HaveOccurred())

		_, err = db.Exec("CREATE TABLE test_copy_from(word text, len int)")
		Expect(err).NotTo(HaveOccurred())

		tx1, err := db.Begin()
		Expect(err).NotTo(HaveOccurred())
		tx2, err := db.Begin()
		Expect(err).NotTo(HaveOccurred())

		r := strings.NewReader(data)
		res, err := tx1.CopyFrom(r, "COPY test_copy_from FROM STDIN")
		Expect(err).NotTo(HaveOccurred())
		Expect(res.RowsAffected()).To(Equal(4))

		var count int
		_, err = tx1.QueryOne(pg.Scan(&count), "SELECT COUNT(*) FROM test_copy_from")
		Expect(err).NotTo(HaveOccurred())
		Expect(count).To(Equal(4))

		_, err = tx2.QueryOne(pg.Scan(&count), "SELECT COUNT(*) FROM test_copy_from")
		Expect(err).NotTo(HaveOccurred())
		Expect(count).To(Equal(0))

		err = tx1.Commit()
		Expect(err).NotTo(HaveOccurred())

		_, err = tx2.QueryOne(pg.Scan(&count), "SELECT COUNT(*) FROM test_copy_from")
		Expect(err).NotTo(HaveOccurred())
		Expect(count).To(Equal(4)) // assuming READ COMMITTED

		err = tx2.Rollback()
		Expect(err).NotTo(HaveOccurred())

		_, err = db.Exec("DROP TABLE IF EXISTS test_copy_from")
		Expect(err).NotTo(HaveOccurred())
	})

	It("supports CopyFrom and CopyIn with errors", func() {
		// too many fields on second line
		data := "hello\t5\nworld\t5\t6\t8\t9\nfoo\t3\nbar\t3\n"

		_, err := db.Exec("DROP TABLE IF EXISTS test_copy_from")
		Expect(err).NotTo(HaveOccurred())

		_, err = db.Exec("CREATE TABLE test_copy_from(word text, len int)")
		Expect(err).NotTo(HaveOccurred())
		_, err = db.Exec("INSERT INTO test_copy_from VALUES ('xxx', 3)")
		Expect(err).NotTo(HaveOccurred())

		tx1, err := db.Begin()
		Expect(err).NotTo(HaveOccurred())
		tx2, err := db.Begin()
		Expect(err).NotTo(HaveOccurred())

		_, err = tx1.Exec("INSERT INTO test_copy_from VALUES ('yyy', 3)")
		Expect(err).NotTo(HaveOccurred())

		r := strings.NewReader(data)
		_, err = tx1.CopyFrom(r, "COPY test_copy_from FROM STDIN")
		Expect(err).To(HaveOccurred())

		var count int
		_, err = tx1.QueryOne(pg.Scan(&count), "SELECT COUNT(*) FROM test_copy_from")
		Expect(err).To(HaveOccurred()) // transaction has errors, cannot proceed

		_, err = tx2.QueryOne(pg.Scan(&count), "SELECT COUNT(*) FROM test_copy_from")
		Expect(err).NotTo(HaveOccurred())
		Expect(count).To(Equal(1))

		err = tx1.Commit()
		Expect(err).NotTo(HaveOccurred()) // actually ROLLBACK happens here

		_, err = tx2.QueryOne(pg.Scan(&count), "SELECT COUNT(*) FROM test_copy_from")
		Expect(err).NotTo(HaveOccurred())
		Expect(count).To(Equal(1)) // other transaction was rolled back so it's not 2 and not 6

		err = tx2.Rollback()
		Expect(err).NotTo(HaveOccurred())

		_, err = db.Exec("DROP TABLE IF EXISTS test_copy_from")
		Expect(err).NotTo(HaveOccurred())
	})
})