I'm quite new to both PostgreSQL and golang. Mainly, I am trying to understand the following:
- Why did I need the Commit statement to close the connection and the other two
Close
calls didn't do the trick? - Would also appreciate pointers regarding the right/wrong way in which I'm going about working with cursors.
In the following function, I'm using gorp
to make a CURSOR, query my Postgres DB row by row and write each row to a writer function:
func(txn *gorp.Transaction,
q string,
params []interface{},
myWriter func([]byte, error)) {
cursor := "DECLARE GRABDATA NO SCROLL CURSOR FOR " + q
_, err := txn.Exec(cursor, params...)
if err != nil {
myWriter(nil, err)
return
}
rows, err := txn.Query("FETCH ALL in GRABDATA")
if err != nil {
myWriter(nil, err)
return
}
defer func() {
if _, err := txn.Exec("CLOSE GRABDATA"); err != nil {
fmt.Println("Error while closing cursor:", err)
}
if err = rows.Close(); err != nil {
fmt.Println("Error while closing rows:", err)
} else {
fmt.Println("
Closed rows without error", "
")
}
if err = txn.Commit(); err != nil {
fmt.Println("Error on commit:", err)
}
}()
pointers := make([]interface{}, len(cols))
container := make([]sql.NullString, len(cols))
values := make([]string, len(cols))
for i := range pointers {
pointers[i] = &container[i]
}
for rows.Next() {
if err = rows.Scan(pointers...); err != nil {
myWriter(nil, err)
return
}
stringLine := strings.Join(values, ",") + "
"
myWriter([]byte(stringLine), nil)
}
}
In the defer
section, I would initially, only Close
the rows
, but then I saw that pg_stat_activity
stay open in idle in transaction
state, with the FETCH ALL in GRABDATA
query.
Calling txn.Exec("CLOSE <cursor_name>")
didn't help. After that, I had a CLOSE GRABDATA
query in idle in transaction
state...
Only when I started calling Commit()
did the connection actually close. I thought that maybe I need to call Commit to execute anything on the transation, but if that's the case - how come I got the result of my queries without calling it?