Beispiel #1
0
func (s *OCI8Stmt) bind(args []driver.Value) error {
	if args == nil {
		return nil
	}

	var bp *C.OCIBind
	for i, v := range args {
		b := []byte(fmt.Sprintf("%v", v))
		b = append(b, 0)
		rv := C.OCIBindByPos(
			(*C.OCIStmt)(s.s),
			&bp,
			(*C.OCIError)(s.c.err),
			C.ub4(i+1),
			unsafe.Pointer(&b[0]),
			C.sb4(len(b)),
			C.SQLT_STR,
			nil,
			nil,
			nil,
			0,
			nil,
			OCI_MODE)

		if rv == C.OCI_ERROR {
			return ociGetError(s.c.err)
		}
	}
	return nil
}
Beispiel #2
0
// 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
}
Beispiel #3
0
func (stmt *statement) bind(args []driver.Value) error {
	var binding *C.OCIBind
	for pos, value := range args {
		buffer := []byte(fmt.Sprint("%v", value))
		buffer = append(buffer, 0)
		result := C.OCIBindByPos((*C.OCIStmt)(stmt.handle), &binding, (*C.OCIError)(stmt.conn.err), C.ub4(pos+1),
			unsafe.Pointer(&buffer[0]), C.sb4(len(buffer)), C.SQLT_STR, nil, nil, nil, 0, nil, C.OCI_DEFAULT)
		if result != C.OCI_SUCCESS {
			return ociGetError(stmt.conn.err)
		}
	}
	return nil
}
Beispiel #4
0
func (s *OCI8Stmt) bind(args []driver.Value) (boundParameters []oci8bind, err error) {
	if args == nil {
		return nil, nil
	}

	var (
		dty   C.ub2
		cdata *C.char
		clen  C.sb4
	)
	*s.bp = nil
	for i, v := range args {

		switch v.(type) {
		case nil:
			dty = C.SQLT_STR
			cdata = nil
			clen = 0
		case []byte:
			v := v.([]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.(float64))
			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

			now := v.(time.Time)
			_, offset := now.Zone()

			sign := '+'
			if offset < 0 {
				offset = -offset
				sign = '-'
			}
			offset /= 60

			// oracle accepts zones "[+-]hh:mm"
			zone := fmt.Sprintf("%c%02d:%02d", sign, offset/60, offset%60)
			zoneTxt := now.Location().String()

			size := len(zoneTxt)
			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(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})

			}
			for first := true; ; first = 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(now.Year()),
					C.ub1(now.Month()),
					C.ub1(now.Day()),
					C.ub1(now.Hour()),
					C.ub1(now.Minute()),
					C.ub1(now.Second()),
					C.ub4(now.Nanosecond()),
					(*C.OraText)(zp),
					C.size_t(len(zone)),
				)
				if rv != C.OCI_SUCCESS {
					if !first {
						defer freeBoundParameters(boundParameters)
						return nil, ociGetError(s.c.err)
					}
					zone = zoneTxt
				} else {
					break
				}
			}

			cdata = (*C.char)(pt)

		case string:
			v := v.(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:
			val := v.(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(val & 0x0ff)
			buf[1] = byte(val >> 8 & 0x0ff)
			buf[2] = byte(val >> 16 & 0x0ff)
			buf[3] = byte(val >> 24 & 0x0ff)
			buf[4] = byte(val >> 32 & 0x0ff)
			buf[5] = byte(val >> 40 & 0x0ff)
			buf[6] = byte(val >> 48 & 0x0ff)
			buf[7] = byte(val >> 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.(bool) {
				*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 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(s.c.err)
		}
	}
	return boundParameters, nil
}
Beispiel #5
0
// 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
}
Beispiel #6
0
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
}
Beispiel #7
0
func (s *OCI8Stmt) bind(args []driver.Value) (freeBoundParameters func(), err error) {
	if args == nil {
		return func() {}, nil
	}

	var (
		bp              *C.OCIBind
		dty             C.ub2
		data            []byte
		cdata           *C.char
		boundParameters []oci8bind
	)

	freeBoundParameters = func() {
		for _, col := range boundParameters {
			if col.pbuf != nil {
				if col.kind == C.SQLT_CLOB || col.kind == C.SQLT_BLOB {
					C.OCIDescriptorFree(
						col.pbuf,
						C.OCI_DTYPE_LOB)
				} else {
					C.free(col.pbuf)
				}
			}
		}
	}

	for i, v := range args {
		data = []byte{}

		switch v.(type) {
		case nil:
			dty = C.SQLT_STR
			boundParameters = append(boundParameters, oci8bind{dty, nil})
			rv := C.OCIBindByPos(
				(*C.OCIStmt)(s.s),
				&bp,
				(*C.OCIError)(s.c.err),
				C.ub4(i+1),
				nil,
				0,
				dty,
				nil,
				nil,
				nil,
				0,
				nil,
				C.OCI_DEFAULT)
			if rv == C.OCI_ERROR {
				defer freeBoundParameters()
				return nil, ociGetError(s.c.err)
			}
		case []byte:
			// FIXME: Currently, CLOB not supported
			dty = C.SQLT_BLOB
			data = v.([]byte)
			var bamt C.ub4
			var pbuf unsafe.Pointer
			rv := C.OCIDescriptorAlloc(
				s.c.env,
				&pbuf,
				C.OCI_DTYPE_LOB,
				0,
				nil)
			if rv == C.OCI_ERROR {
				defer freeBoundParameters()
				return nil, ociGetError(s.c.err)
			}

			rv = C.OCILobCreateTemporary(
				(*C.OCISvcCtx)(s.c.svc),
				(*C.OCIError)(s.c.err),
				(*C.OCILobLocator)(pbuf),
				0,
				C.SQLCS_IMPLICIT,
				C.OCI_TEMP_BLOB,
				C.OCI_ATTR_NOCACHE,
				C.OCI_DURATION_SESSION)
			if rv == C.OCI_ERROR {
				defer freeBoundParameters()
				return nil, ociGetError(s.c.err)
			}

			bamt = C.ub4(len(data))
			rv = C.OCILobWrite(
				(*C.OCISvcCtx)(s.c.svc),
				(*C.OCIError)(s.c.err),
				(*C.OCILobLocator)(pbuf),
				&bamt,
				1,
				unsafe.Pointer(&data[0]),
				C.ub4(len(data)),
				C.OCI_ONE_PIECE,
				nil,
				nil,
				0,
				C.SQLCS_IMPLICIT)
			if rv == C.OCI_ERROR {
				defer freeBoundParameters()
				return nil, ociGetError(s.c.err)
			}
			boundParameters = append(boundParameters, oci8bind{dty, pbuf})
			rv = C.OCIBindByPos(
				(*C.OCIStmt)(s.s),
				&bp,
				(*C.OCIError)(s.c.err),
				C.ub4(i+1),
				unsafe.Pointer(&pbuf),
				0,
				dty,
				nil,
				nil,
				nil,
				0,
				nil,
				C.OCI_DEFAULT)
			if rv == C.OCI_ERROR {
				defer freeBoundParameters()
				return nil, ociGetError(s.c.err)
			}
		case time.Time:
			dty = C.SQLT_DAT
			now := v.(time.Time).In(s.c.location)
			//TODO Handle BCE dates (http://docs.oracle.com/cd/B12037_01/appdev.101/b10779/oci03typ.htm#438305)
			//TODO Handle timezones (http://docs.oracle.com/cd/B12037_01/appdev.101/b10779/oci03typ.htm#443601)
			data = []byte{
				byte(now.Year()/100 + 100),
				byte(now.Year()%100 + 100),
				byte(now.Month()),
				byte(now.Day()),
				byte(now.Hour() + 1),
				byte(now.Minute() + 1),
				byte(now.Second() + 1),
			}

			cdata = C.CString(string(data))
			boundParameters = append(boundParameters, oci8bind{dty, unsafe.Pointer(cdata)})
			rv := C.OCIBindByPos(
				(*C.OCIStmt)(s.s),
				&bp,
				(*C.OCIError)(s.c.err),
				C.ub4(i+1),
				unsafe.Pointer(cdata),
				C.sb4(len(data)),
				dty,
				nil,
				nil,
				nil,
				0,
				nil,
				C.OCI_DEFAULT)
			if rv == C.OCI_ERROR {
				defer freeBoundParameters()
				return nil, ociGetError(s.c.err)
			}
		default:
			dty = C.SQLT_STR
			data = []byte(fmt.Sprintf("%v", v))
			data = append(data, 0)

			cdata = C.CString(string(data))
			boundParameters = append(boundParameters, oci8bind{dty, unsafe.Pointer(cdata)})
			rv := C.OCIBindByPos(
				(*C.OCIStmt)(s.s),
				&bp,
				(*C.OCIError)(s.c.err),
				C.ub4(i+1),
				unsafe.Pointer(cdata),
				C.sb4(len(data)),
				dty,
				nil,
				nil,
				nil,
				0,
				nil,
				C.OCI_DEFAULT)
			if rv == C.OCI_ERROR {
				defer freeBoundParameters()
				return nil, ociGetError(s.c.err)
			}
		}
	}
	return freeBoundParameters, nil
}
Beispiel #8
0
func (s *OCI8Stmt) bind(args []driver.Value) (freeBoundParameters func(), err error) {
	if args == nil {
		return func() {}, nil
	}

	var (
		bp              *C.OCIBind
		dty             int
		data            []byte
		cdata           *C.char
		boundParameters []*C.char
	)

	freeBoundParameters = func() {
		for _, p := range boundParameters {
			C.free(unsafe.Pointer(p))
		}
	}

	for i, v := range args {
		data = []byte{}

		switch v.(type) {
		case nil:
			dty = C.SQLT_STR
			data = []byte{0}
		case time.Time:
			dty = C.SQLT_DAT
			now := v.(time.Time).In(s.c.location)
			//TODO Handle BCE dates (http://docs.oracle.com/cd/B12037_01/appdev.101/b10779/oci03typ.htm#438305)
			//TODO Handle timezones (http://docs.oracle.com/cd/B12037_01/appdev.101/b10779/oci03typ.htm#443601)
			data = []byte{
				byte(now.Year()/100 + 100),
				byte(now.Year()%100 + 100),
				byte(now.Month()),
				byte(now.Day()),
				byte(now.Hour() + 1),
				byte(now.Minute() + 1),
				byte(now.Second() + 1),
			}
		default:
			dty = C.SQLT_STR
			data = []byte(fmt.Sprintf("%v", v))
			data = append(data, 0)
		}

		cdata = C.CString(string(data))
		boundParameters = append(boundParameters, cdata)
		rv := C.OCIBindByPos(
			(*C.OCIStmt)(s.s),
			&bp,
			(*C.OCIError)(s.c.err),
			C.ub4(i+1),
			unsafe.Pointer(cdata),
			C.sb4(len(data)),
			C.ub2(dty),
			nil,
			nil,
			nil,
			0,
			nil,
			C.OCI_DEFAULT)

		if rv == C.OCI_ERROR {
			defer freeBoundParameters()
			return nil, ociGetError(s.c.err)
		}
	}
	return freeBoundParameters, nil
}