func (c *Conn) setAutoCommitAttr(a uintptr) error { ret := api.SQLSetConnectAttr(c.h, api.SQL_ATTR_AUTOCOMMIT, api.SQLPOINTER(a), api.SQL_IS_UINTEGER) if IsError(ret) { return NewError("SQLSetConnectAttr", c.h) } return 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.SQLSetEnvAttr(drv.h, api.SQL_ATTR_ODBC_VERSION, api.SQLPOINTER(api.SQL_OV_ODBC3), 0) if IsError(ret) { defer releaseHandle(drv.h) return NewError("SQLSetEnvAttr ODBC v3", drv.h) } return nil }
func (l *BufferLen) Bind(h api.SQLHSTMT, idx int, ctype api.SQLSMALLINT, buf []byte) api.SQLRETURN { return api.SQLBindCol(h, api.SQLUSMALLINT(idx+1), ctype, api.SQLPOINTER(unsafe.Pointer(&buf[0])), api.SQLLEN(len(buf)), (*api.SQLLEN)(l)) }
func (p *Parameter) BindValue(h api.SQLHSTMT, idx int, v driver.Value) error { // TODO(brainman): Reuse memory for previously bound values. If memory // is reused, we, probably, do not need to call SQLBindParameter either. var ctype, sqltype, decimal api.SQLSMALLINT var size api.SQLULEN var buflen api.SQLLEN var plen *api.SQLLEN var buf unsafe.Pointer switch d := v.(type) { case nil: ctype = api.SQL_C_WCHAR p.Data = nil buf = nil size = 1 buflen = 0 plen = p.StoreStrLen_or_IndPtr(api.SQL_NULL_DATA) sqltype = api.SQL_WCHAR case string: ctype = api.SQL_C_WCHAR b := api.StringToUTF16(d) p.Data = b buf = unsafe.Pointer(&b[0]) l := len(b) l -= 1 // remove terminating 0 size = api.SQLULEN(l) if size < 1 { // size cannot be less then 1 even for empty fields size = 1 } l *= 2 // every char takes 2 bytes buflen = api.SQLLEN(l) plen = p.StoreStrLen_or_IndPtr(buflen) if p.isDescribed { // only so we can handle very long (>4000 chars) parameters sqltype = p.SQLType } else { sqltype = api.SQL_WCHAR } case int64: ctype = api.SQL_C_SBIGINT p.Data = &d buf = unsafe.Pointer(&d) sqltype = api.SQL_BIGINT size = 8 case bool: var b byte if d { b = 1 } ctype = api.SQL_C_BIT p.Data = &b buf = unsafe.Pointer(&b) sqltype = api.SQL_BIT size = 1 case float64: ctype = api.SQL_C_DOUBLE p.Data = &d buf = unsafe.Pointer(&d) sqltype = api.SQL_DOUBLE size = 8 case time.Time: ctype = api.SQL_C_TYPE_TIMESTAMP y, m, day := d.Date() b := api.SQL_TIMESTAMP_STRUCT{ Year: api.SQLSMALLINT(y), Month: api.SQLUSMALLINT(m), Day: api.SQLUSMALLINT(day), Hour: api.SQLUSMALLINT(d.Hour()), Minute: api.SQLUSMALLINT(d.Minute()), Second: api.SQLUSMALLINT(d.Second()), Fraction: api.SQLUINTEGER(d.Nanosecond()), } p.Data = &b buf = unsafe.Pointer(&b) sqltype = api.SQL_TYPE_TIMESTAMP if p.isDescribed && p.SQLType == api.SQL_TYPE_TIMESTAMP { decimal = p.Decimal } if decimal <= 0 { // represented as yyyy-mm-dd hh:mm:ss.fff format in ms sql server decimal = 3 } size = 20 + api.SQLULEN(decimal) case []byte: ctype = api.SQL_C_BINARY b := make([]byte, len(d)) copy(b, d) p.Data = b buf = unsafe.Pointer(&b[0]) buflen = api.SQLLEN(len(b)) plen = p.StoreStrLen_or_IndPtr(buflen) size = api.SQLULEN(len(b)) sqltype = api.SQL_BINARY default: panic(fmt.Errorf("unsupported type %T", v)) } ret := api.SQLBindParameter(h, api.SQLUSMALLINT(idx+1), api.SQL_PARAM_INPUT, ctype, sqltype, size, decimal, api.SQLPOINTER(buf), buflen, plen) if IsError(ret) { return NewError("SQLBindParameter", h) } return nil }