func (c *Conn) PrepareODBCStmt(query string) (*ODBCStmt, error) { var out api.SQLHANDLE ret := api.SQLAllocHandle(api.SQL_HANDLE_STMT, api.SQLHANDLE(c.h), &out) if IsError(ret) { return nil, c.newError("SQLAllocHandle", c.h) } h := api.SQLHSTMT(out) drv.Stats.updateHandleCount(api.SQL_HANDLE_STMT, 1) b := api.StringToUTF16(query) ret = api.SQLPrepare(h, (*api.SQLWCHAR)(unsafe.Pointer(&b[0])), api.SQL_NTS) if IsError(ret) { defer releaseHandle(h) return nil, c.newError("SQLPrepare", h) } ps, err := ExtractParameters(h) if err != nil { releaseHandle(h) return nil, err } return &ODBCStmt{ h: h, Parameters: ps, usedByStmt: true, }, nil }
func ToHandleAndType(handle interface{}) (h api.SQLHANDLE, ht api.SQLSMALLINT) { switch v := handle.(type) { case api.SQLHENV: if v == api.SQLHENV(api.SQL_NULL_HANDLE) { ht = 0 } else { ht = api.SQL_HANDLE_ENV } h = api.SQLHANDLE(v) case api.SQLHDBC: ht = api.SQL_HANDLE_DBC h = api.SQLHANDLE(v) case api.SQLHSTMT: ht = api.SQL_HANDLE_STMT h = api.SQLHANDLE(v) default: panic(fmt.Errorf("unexpected handle type %T", v)) } return h, ht }
func (d *Driver) Open(dsn string) (driver.Conn, error) { var out api.SQLHANDLE ret := api.SQLAllocHandle(api.SQL_HANDLE_DBC, api.SQLHANDLE(d.h), &out) if IsError(ret) { return nil, NewError("SQLAllocHandle", d.h) } h := api.SQLHDBC(out) drv.Stats.updateHandleCount(api.SQL_HANDLE_DBC, 1) b := api.StringToUTF16(dsn) ret = api.SQLDriverConnect(h, 0, (*api.SQLWCHAR)(unsafe.Pointer(&b[0])), api.SQL_NTS, nil, 0, nil, api.SQL_DRIVER_NOPROMPT) if IsError(ret) { defer releaseHandle(h) return nil, NewError("SQLDriverConnect", h) } return &Conn{h: h}, nil }
func initDriver() error { //Allocate environment handle var out api.SQLHANDLE in := api.SQLHANDLE(api.SQL_NULL_HANDLE) ret := api.SQLAllocHandle(api.SQL_HANDLE_ENV, in, &out) if IsError(ret) { return NewError("SQLAllocHandle", api.SQLHENV(in)) } drv.h = api.SQLHENV(out) drv.Stats.updateHandleCount(api.SQL_HANDLE_ENV, 1) // will use ODBC v3 ret = api.SQLSetEnvUIntPtrAttr(drv.h, api.SQL_ATTR_ODBC_VERSION, api.SQL_OV_ODBC3, 0) if IsError(ret) { defer releaseHandle(drv.h) return NewError("SQLSetEnvUIntPtrAttr", drv.h) } //TODO: find a way to make this attribute changeable at runtime //Enable connection pooling ret = api.SQLSetEnvUIntPtrAttr(drv.h, api.SQL_ATTR_CONNECTION_POOLING, api.SQL_CP_ONE_PER_HENV, api.SQL_IS_UINTEGER) if IsError(ret) { defer releaseHandle(drv.h) return NewError("SQLSetEnvUIntPtrAttr", drv.h) } //Set relaxed connection pool matching ret = api.SQLSetEnvUIntPtrAttr(drv.h, api.SQL_ATTR_CP_MATCH, api.SQL_CP_RELAXED_MATCH, api.SQL_IS_UINTEGER) if IsError(ret) { defer releaseHandle(drv.h) return NewError("SQLSetEnvUIntPtrAttr", drv.h) } //TODO: it would be nice if we could call "drv.SetMaxIdleConns(0)" here but from the docs it looks like //the user must call this function after db.Open return nil }
func (c *Conn) endTx(commit bool) error { if c.tx == nil { return errors.New("not in a transaction") } var howToEnd api.SQLSMALLINT if commit { howToEnd = api.SQL_COMMIT } else { howToEnd = api.SQL_ROLLBACK } ret := api.SQLEndTran(api.SQL_HANDLE_DBC, api.SQLHANDLE(c.h), howToEnd) if IsError(ret) { c.bad = true return c.newError("SQLEndTran", c.h) } c.tx = nil err := c.setAutoCommitAttr(api.SQL_AUTOCOMMIT_ON) if err != nil { c.bad = true return err } return nil }