// Commit or rollback transaction in consistent manner func (tx *transaction) completeTransaction(completeType odbc.SQLSMALLINT) error { //Complete transaction by either committing or rolling back ret := odbc.SQLEndTran(odbc.SQL_HANDLE_DBC, tx.conn.handle, completeType) if isError(ret) { return errorConnection(tx.conn.handle) } //Make transaction as finished and turn auto commit back on tx.conn.isTransactionActive = false ret = odbc.SQLSetConnectAttr(tx.conn.handle, odbc.SQL_ATTR_AUTOCOMMIT, odbc.SQLPOINTER(odbc.SQL_AUTOCOMMIT_ON), 0, nil) if isError(ret) { return errorConnection(tx.conn.handle) } return nil }
// Close invalidates and potentially stops any current // prepared statements and transactions, marking this // connection as no longer in use. func (c *connection) Close() error { // Verify that connHandle is valid if c.handle == 0 { return nil } // Verify that connection has not already been closed if c.isClosed { return nil } var err error // Close all of the statements owned by the connection for key, _ := range c.statements { // Skip the statement if it is already nil if isNil(key) { continue } key.Close() } c.statements = nil // If the transaction is active, roll it back if c.isTransactionActive { ret := odbc.SQLEndTran(odbc.SQL_HANDLE_DBC, c.handle, odbc.SQL_ROLLBACK) if isError(ret) { err = errorConnection(c.handle) } //Turn AutoCommit back on ret = odbc.SQLSetConnectAttr(c.handle, odbc.SQL_ATTR_AUTOCOMMIT, odbc.SQLPOINTER(odbc.SQL_AUTOCOMMIT_ON), 0, nil) if isError(ret) { err = errorConnection(c.handle) } } // Disconnect connection ret := odbc.SQLDisconnect(c.handle) if isError(ret) { err = errorConnection(c.handle) } // Deallocate connection ret = odbc.SQLFreeHandle(odbc.SQL_HANDLE_DBC, c.handle) if isError(ret) { err = errorConnection(c.handle) } // Clear the handle c.handle = 0 // Set connection to closed c.isClosed = true //Clear the finalizer runtime.SetFinalizer(c, nil) // Return any error if err != nil { return err } return nil }