diff --git a/connection.go b/connection.go index 43801b31..33b16e72 100644 --- a/connection.go +++ b/connection.go @@ -416,7 +416,22 @@ func (c *Connection) Execute(sql string, arguments ...interface{}) (commandTag s } func (c *Connection) Transaction(f func() bool) (committed bool, err error) { - if _, err = c.Execute("begin"); err != nil { + return c.transaction("", f) +} + +func (c *Connection) TransactionIso(isoLevel string, f func() bool) (committed bool, err error) { + return c.transaction(isoLevel, f) +} + +func (c *Connection) transaction(isoLevel string, f func() bool) (committed bool, err error) { + var beginSql string + if isoLevel == "" { + beginSql = "begin" + } else { + beginSql = fmt.Sprintf("begin isolation level %s", isoLevel) + } + + if _, err = c.Execute(beginSql); err != nil { return } defer func() { diff --git a/connection_test.go b/connection_test.go index 9e3baf42..55c86b66 100644 --- a/connection_test.go +++ b/connection_test.go @@ -536,3 +536,24 @@ func TestTransaction(t *testing.T) { } }() } + +func TestTransactionIso(t *testing.T) { + conn, err := Connect(*defaultConnectionParameters) + if err != nil { + t.Fatalf("Unable to establish connection: %v", err) + } + defer conn.Close() + + isoLevels := []string{"serializable", "repeatable read", "read committed", "read uncommitted"} + for _, iso := range isoLevels { + _, err := conn.TransactionIso(iso, func() bool { + if level := mustSelectValue(t, conn, "select current_setting('transaction_isolation')"); level != iso { + t.Errorf("Expected to be in isolation level %v but was %v", iso, level) + } + return true + }) + if err != nil { + t.Fatalf("Unexpected transaction failure: %v", err) + } + } +}