// Allocate a variable and bind it to the given statement. func (v *Variable) internalBind() (err error) { var status C.sword // perform the bind aL, rC := v.aLrC() allElts := C.ub4(0) //actElts := C.ub4(v.actualElements) pActElts := &v.actualElements if v.isArray { allElts = C.ub4(v.allocatedElements) } else { pActElts = nil } //log.Printf("%v isArray? %b allElts=%d", v.typ.Name, v.isArray, allElts) if v.boundName != "" { bname := []byte(v.boundName) if CTrace { ctrace("internalBind.OCIBindByName", v.boundCursorHandle, &v.bindHandle, v.environment.errorHandle, "name="+string(bname), len(bname), v.getDataArr(), v.bufferSize, v.typ.oracleType, v.indicator, aL, rC, allElts, pActElts, "DEFAULT") } status = C.OCIBindByName(v.boundCursorHandle, &v.bindHandle, v.environment.errorHandle, (*C.OraText)(&bname[0]), C.sb4(len(bname)), v.getDataArr(), C.sb4(v.bufferSize), v.typ.oracleType, unsafe.Pointer(&v.indicator[0]), aL, rC, allElts, pActElts, C.OCI_DEFAULT) } else { if CTrace { ctrace("internalBind.OCIBindByPos", v.boundCursorHandle, &v.bindHandle, v.environment.errorHandle, fmt.Sprintf("pos=%d", v.boundPos), "dataArr:", fmt.Sprintf("%x", v.dataBytes[:v.bufferSize]), "bufsize:", v.bufferSize, "typ:", v.typ.oracleType, v.indicator, aL, rC, allElts, pActElts, "DEFAULT") } status = C.OCIBindByPos(v.boundCursorHandle, &v.bindHandle, v.environment.errorHandle, C.ub4(v.boundPos), v.getDataArr(), C.sb4(v.bufferSize), v.typ.oracleType, unsafe.Pointer(&v.indicator[0]), aL, rC, allElts, pActElts, C.OCI_DEFAULT) } if err = v.environment.CheckStatus(status, "BindBy"); err != nil { return } // set the max data size for strings if (v.typ == StringVarType || v.typ == FixedCharVarType) && v.size > v.typ.size { err = v.environment.AttrSet( unsafe.Pointer(v.bindHandle), C.OCI_HTYPE_BIND, C.OCI_ATTR_MAXDATA_SIZE, unsafe.Pointer(&v.typ.size), C.sizeof_ub4) } return }
// Allocate a variable and bind it to the given statement. func (v *Variable) internalBind() (err error) { if CTrace { ctrace("%s.internalBind", v) } var status C.sword // perform the bind indic, aL, rC := v.aLrC() allElts := C.ub4(0) pActElts := &v.actualElements if v.isArray { allElts = C.ub4(v.allocatedElements) } else { pActElts = nil } //log.Printf("%v isArray? %b allElts=%d", v.typ.Name, v.isArray, allElts) var bindName string var bufSlice interface{} var m int if CTrace { m = int(v.bufferSize) if m > 40 { m = 40 } switch { case v.dataInts != nil: if m > len(v.dataInts) { m = len(v.dataInts) } bufSlice = v.dataInts[:m] case v.dataFloats != nil: if m > len(v.dataFloats) { m = len(v.dataFloats) } bufSlice = v.dataFloats[:m] default: if m > len(v.dataBytes) { m = len(v.dataBytes) } bufSlice = v.dataBytes[:m] } } if v.boundName != "" { bname := []byte(v.boundName) if CTrace { ctrace("internalBind.OCIBindByName(cur=%p, bind=%p, env=%p, name=%q, bufferSize=%d, oracleType=%d, data[:%d]=%v, indicator=%v, aL=%v, rC=%v, allElts=%v, pActElts=%v, DEFAULT)", v.boundCursorHandle, &v.bindHandle, v.environment.errorHandle, bname, v.bufferSize, v.typ.oracleType, m, bufSlice, v.indicator, aL, rC, allElts, pActElts) } bindName = fmt.Sprintf("%q", bname) status = C.OCIBindByName(v.boundCursorHandle, &v.bindHandle, v.environment.errorHandle, (*C.OraText)(&bname[0]), C.sb4(len(bname)), v.getDataArr(), C.sb4(v.bufferSize), v.typ.oracleType, indic, aL, rC, allElts, pActElts, C.OCI_DEFAULT) } else { if CTrace { m := int(v.bufferSize) if m > 40 { m = 40 } switch { case v.dataInts != nil: if m > len(v.dataInts) { m = len(v.dataInts) } bufSlice = v.dataInts[:m] case v.dataFloats != nil: if m > len(v.dataFloats) { m = len(v.dataFloats) } bufSlice = v.dataFloats[:m] default: if m > len(v.dataBytes) { m = len(v.dataBytes) } bufSlice = v.dataBytes[:m] } ctrace("internalBind.OCIBindByPos(cur=%p, boundPos=%d, data[:%d]=%v, bufSize=%d, oracleType=%d, indicator=%v, actLen=%v, rc=%p, allElts=%p pActElts=%p)", v.boundCursorHandle, v.boundPos, m, bufSlice, v.bufferSize, v.typ.oracleType, v.indicator, aL, rC, allElts, pActElts) } bindName = fmt.Sprintf("%d", v.boundPos) status = C.OCIBindByPos(v.boundCursorHandle, &v.bindHandle, v.environment.errorHandle, C.ub4(v.boundPos), v.getDataArr(), C.sb4(v.bufferSize), v.typ.oracleType, indic, aL, rC, allElts, pActElts, C.OCI_DEFAULT) } if err = v.environment.CheckStatus(status, fmt.Sprintf("BindBy(%s)", bindName)); err != nil { err = errgo.Mask(err) return } if v.typ.charsetForm != C.SQLCS_IMPLICIT { if err = v.environment.AttrSet( unsafe.Pointer(v.bindHandle), C.OCI_HTYPE_BIND, C.OCI_ATTR_CHARSET_FORM, unsafe.Pointer(&v.typ.size), C.sizeof_ub4); err != nil { err = errgo.Mask(err) return } // why do we set this here? if err = v.environment.AttrSet( unsafe.Pointer(v.bindHandle), C.OCI_HTYPE_BIND, C.OCI_ATTR_MAXDATA_SIZE, unsafe.Pointer(&v.bufferSize), C.sizeof_ub4); err != nil { err = errgo.Mask(err) return } } // set the max data size for strings if (v.typ == StringVarType || v.typ == FixedCharVarType) && v.size > v.typ.size { err = v.environment.AttrSet( unsafe.Pointer(v.bindHandle), C.OCI_HTYPE_BIND, C.OCI_ATTR_MAXDATA_SIZE, unsafe.Pointer(&v.typ.size), C.sizeof_ub4) } if err != nil { err = errgo.Mask(err) } return }
func (s *OCI8Stmt) bind(args []namedValue) (boundParameters []oci8bind, err error) { if len(args) == 0 { return nil, nil } var ( dty C.ub2 cdata *C.char clen C.sb4 ) *s.bp = nil for i, uv := range args { switch v := uv.Value.(type) { case nil: dty = C.SQLT_STR cdata = nil clen = 0 case []byte: dty = C.SQLT_BIN cdata = CByte(v) clen = C.sb4(len(v)) boundParameters = append(boundParameters, oci8bind{dty, unsafe.Pointer(cdata)}) case float64: fb := math.Float64bits(v) if fb&0x8000000000000000 != 0 { fb ^= 0xffffffffffffffff } else { fb |= 0x8000000000000000 } dty = C.SQLT_IBDOUBLE cdata = CByte([]byte{byte(fb >> 56), byte(fb >> 48), byte(fb >> 40), byte(fb >> 32), byte(fb >> 24), byte(fb >> 16), byte(fb >> 8), byte(fb)}) clen = 8 boundParameters = append(boundParameters, oci8bind{dty, unsafe.Pointer(cdata)}) case time.Time: var pt unsafe.Pointer var zp unsafe.Pointer zone, offset := v.Zone() size := len(zone) if size < 8 { size = 8 } size += int(unsafe.Sizeof(unsafe.Pointer(nil))) if ret := C.WrapOCIDescriptorAlloc( s.c.env, C.OCI_DTYPE_TIMESTAMP_TZ, C.size_t(size)); ret.rv != C.OCI_SUCCESS { defer freeBoundParameters(boundParameters) return nil, ociGetError(ret.rv, s.c.err) } else { dty = C.SQLT_TIMESTAMP_TZ clen = C.sb4(unsafe.Sizeof(pt)) pt = ret.extra *(*unsafe.Pointer)(ret.extra) = ret.ptr zp = unsafe.Pointer(uintptr(ret.extra) + unsafe.Sizeof(unsafe.Pointer(nil))) boundParameters = append(boundParameters, oci8bind{dty, pt}) } tryagain := false copy((*[1 << 30]byte)(zp)[0:len(zone)], zone) rv := C.OCIDateTimeConstruct( s.c.env, (*C.OCIError)(s.c.err), (*C.OCIDateTime)(*(*unsafe.Pointer)(pt)), C.sb2(v.Year()), C.ub1(v.Month()), C.ub1(v.Day()), C.ub1(v.Hour()), C.ub1(v.Minute()), C.ub1(v.Second()), C.ub4(v.Nanosecond()), (*C.OraText)(zp), C.size_t(len(zone)), ) if rv != C.OCI_SUCCESS { tryagain = true } else { //check if oracle timezone offset is same ? rvz := C.WrapOCIDateTimeGetTimeZoneNameOffset( (*C.OCIEnv)(s.c.env), (*C.OCIError)(s.c.err), (*C.OCIDateTime)(*(*unsafe.Pointer)(pt))) if rvz.rv != C.OCI_SUCCESS { defer freeBoundParameters(boundParameters) return nil, ociGetError(rvz.rv, s.c.err) } if offset != int(rvz.h)*60*60+int(rvz.m)*60 { //fmt.Println("oracle timezone offset dont match", zone, offset, int(rvz.h)*60*60+int(rvz.m)*60) tryagain = true } } if tryagain { sign := '+' if offset < 0 { offset = -offset sign = '-' } offset /= 60 // oracle accept zones "[+-]hh:mm", try second time zone = fmt.Sprintf("%c%02d:%02d", sign, offset/60, offset%60) copy((*[1 << 30]byte)(zp)[0:len(zone)], zone) rv := C.OCIDateTimeConstruct( s.c.env, (*C.OCIError)(s.c.err), (*C.OCIDateTime)(*(*unsafe.Pointer)(pt)), C.sb2(v.Year()), C.ub1(v.Month()), C.ub1(v.Day()), C.ub1(v.Hour()), C.ub1(v.Minute()), C.ub1(v.Second()), C.ub4(v.Nanosecond()), (*C.OraText)(zp), C.size_t(len(zone)), ) if rv != C.OCI_SUCCESS { defer freeBoundParameters(boundParameters) return nil, ociGetError(rv, s.c.err) } } cdata = (*C.char)(pt) case string: dty = C.SQLT_AFC // don't trim strings !!! cdata = C.CString(v) clen = C.sb4(len(v)) boundParameters = append(boundParameters, oci8bind{dty, unsafe.Pointer(cdata)}) case int64: dty = C.SQLT_INT clen = C.sb4(8) // not tested on i386. may only work on amd64 cdata = (*C.char)(C.malloc(8)) buf := (*[1 << 30]byte)(unsafe.Pointer(cdata))[0:8] buf[0] = byte(v & 0x0ff) buf[1] = byte(v >> 8 & 0x0ff) buf[2] = byte(v >> 16 & 0x0ff) buf[3] = byte(v >> 24 & 0x0ff) buf[4] = byte(v >> 32 & 0x0ff) buf[5] = byte(v >> 40 & 0x0ff) buf[6] = byte(v >> 48 & 0x0ff) buf[7] = byte(v >> 56 & 0x0ff) boundParameters = append(boundParameters, oci8bind{dty, unsafe.Pointer(cdata)}) case bool: // oracle dont have bool, handle as 0/1 dty = C.SQLT_INT clen = C.sb4(1) cdata = (*C.char)(C.malloc(10)) if v { *cdata = 1 } else { *cdata = 0 } boundParameters = append(boundParameters, oci8bind{dty, unsafe.Pointer(cdata)}) default: dty = C.SQLT_CHR d := fmt.Sprintf("%v", v) clen = C.sb4(len(d)) cdata = C.CString(d) boundParameters = append(boundParameters, oci8bind{dty, unsafe.Pointer(cdata)}) } if uv.Name != "" { name := ":" + uv.Name cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) if rv := C.OCIBindByName( (*C.OCIStmt)(s.s), s.bp, (*C.OCIError)(s.c.err), (*C.OraText)(unsafe.Pointer(cname)), C.sb4(len(name)), unsafe.Pointer(cdata), clen, dty, nil, nil, nil, 0, nil, C.OCI_DEFAULT); rv != C.OCI_SUCCESS { } } else { if rv := C.OCIBindByPos( (*C.OCIStmt)(s.s), s.bp, (*C.OCIError)(s.c.err), C.ub4(i+1), unsafe.Pointer(cdata), clen, dty, nil, nil, nil, 0, nil, C.OCI_DEFAULT); rv != C.OCI_SUCCESS { defer freeBoundParameters(boundParameters) return nil, ociGetError(rv, s.c.err) } } } return boundParameters, nil }