예제 #1
0
파일: bndTimePtr.go 프로젝트: optimuse/ora
func (bnd *bndTimePtr) bind(value *time.Time, position int, stmt *Stmt) error {
	bnd.stmt = stmt
	bnd.value = value
	r := C.OCIDescriptorAlloc(
		unsafe.Pointer(bnd.stmt.ses.srv.env.ocienv),         //CONST dvoid   *parenth,
		(*unsafe.Pointer)(unsafe.Pointer(&bnd.ociDateTime)), //dvoid         **descpp,
		C.OCI_DTYPE_TIMESTAMP_TZ,                            //ub4           type,
		0,   //size_t        xtramem_sz,
		nil) //dvoid         **usrmempp);
	if r == C.OCI_ERROR {
		return bnd.stmt.ses.srv.env.ociError()
	} else if r == C.OCI_INVALID_HANDLE {
		return errNew("unable to allocate oci timestamp handle during bind")
	}
	r = C.OCIBINDBYPOS(
		bnd.stmt.ocistmt,                              //OCIStmt      *stmtp,
		(**C.OCIBind)(&bnd.ocibnd),                    //OCIBind      **bindpp,
		bnd.stmt.ses.srv.env.ocierr,                   //OCIError     *errhp,
		C.ub4(position),                               //ub4          position,
		unsafe.Pointer(&bnd.ociDateTime),              //void         *valuep,
		C.LENGTH_TYPE(unsafe.Sizeof(bnd.ociDateTime)), //sb8          value_sz,
		C.SQLT_TIMESTAMP_TZ,                           //ub2          dty,
		unsafe.Pointer(&bnd.isNull),                   //void         *indp,
		nil,           //ub2          *alenp,
		nil,           //ub2          *rcodep,
		0,             //ub4          maxarr_len,
		nil,           //ub4          *curelep,
		C.OCI_DEFAULT) //ub4          mode );
	if r == C.OCI_ERROR {
		return bnd.stmt.ses.srv.env.ociError()
	}
	return nil
}
예제 #2
0
func (env *Environment) ociDescrAlloc(dst *unsafe.Pointer, typ C.ub4, at string) error {
	if err := checkStatus(
		C.OCIDescriptorAlloc(unsafe.Pointer(env.handle), dst, typ, C.size_t(0), nil),
		false); err != nil {
		return errgo.New(at + ": " + err.Error())
	}
	return nil
}
예제 #3
0
파일: bndBfile.go 프로젝트: optimuse/ora
func (bnd *bndBfile) bind(value Bfile, position int, stmt *Stmt) error {
	// DirectoryAlias must be specified to avoid error "ORA-24801: illegal parameter value in OCI lob function"
	// Raising a driver error clarifies the user error
	if value.DirectoryAlias == "" {
		return errNew("DirectoryAlias must be specified when binding a non-null Bfile")
	}
	// Filename must be specified to avoid error "ORA-24801: illegal parameter value in OCI lob function"
	// Raising a driver error clarifies the user error
	if value.Filename == "" {
		return errNew("Filename must be specified when binding a non-null Bfile")
	}

	bnd.stmt = stmt
	// Allocate lob locator handle
	r := C.OCIDescriptorAlloc(
		unsafe.Pointer(bnd.stmt.ses.srv.env.ocienv),           //CONST dvoid   *parenth,
		(*unsafe.Pointer)(unsafe.Pointer(&bnd.ociLobLocator)), //dvoid         **descpp,
		C.OCI_DTYPE_FILE,                                      //ub4           type,
		0,                                                     //size_t        xtramem_sz,
		nil)                                                   //dvoid         **usrmempp);
	if r == C.OCI_ERROR {
		return bnd.stmt.ses.srv.env.ociError()
	} else if r == C.OCI_INVALID_HANDLE {
		return errNew("unable to allocate oci lob handle during bind")
	}

	bnd.cDirectoryAlias = C.CString(value.DirectoryAlias)
	bnd.cFilename = C.CString(value.Filename)
	r = C.OCILobFileSetName(
		bnd.stmt.ses.srv.env.ocienv,                       //OCIEnv             *envhp,
		bnd.stmt.ses.srv.env.ocierr,                       //OCIError           *errhp,
		&bnd.ociLobLocator,                                //OCILobLocator      **filepp,
		(*C.OraText)(unsafe.Pointer(bnd.cDirectoryAlias)), //const OraText      *dir_alias,
		C.ub2(len(value.DirectoryAlias)),                  //ub2                d_length,
		(*C.OraText)(unsafe.Pointer(bnd.cFilename)),       //const OraText      *filename,
		C.ub2(len(value.Filename)))                        //ub2                f_length );
	if r == C.OCI_ERROR {
		return bnd.stmt.ses.srv.env.ociError()
	}
	r = C.OCIBINDBYPOS(
		bnd.stmt.ocistmt,                                //OCIStmt      *stmtp,
		(**C.OCIBind)(&bnd.ocibnd),                      //OCIBind      **bindpp,
		bnd.stmt.ses.srv.env.ocierr,                     //OCIError     *errhp,
		C.ub4(position),                                 //ub4          position,
		unsafe.Pointer(&bnd.ociLobLocator),              //void         *valuep,
		C.LENGTH_TYPE(unsafe.Sizeof(bnd.ociLobLocator)), //sb8          value_sz,
		C.SQLT_FILE,   //ub2          dty,
		nil,           //void         *indp,
		nil,           //ub2          *alenp,
		nil,           //ub2          *rcodep,
		0,             //ub4          maxarr_len,
		nil,           //ub4          *curelep,
		C.OCI_DEFAULT) //ub4          mode );
	if r == C.OCI_ERROR {
		return bnd.stmt.ses.srv.env.ociError()
	}
	return nil
}
예제 #4
0
파일: bndTimePtr.go 프로젝트: ricsmania/ora
func (bnd *bndTimePtr) bind(value *time.Time, position int, stmt *Stmt) error {
	bnd.stmt = stmt
	bnd.value = value
	r := C.OCIDescriptorAlloc(
		unsafe.Pointer(bnd.stmt.ses.srv.env.ocienv),         //CONST dvoid   *parenth,
		(*unsafe.Pointer)(unsafe.Pointer(&bnd.ociDateTime)), //dvoid         **descpp,
		C.OCI_DTYPE_TIMESTAMP_TZ,                            //ub4           type,
		0,   //size_t        xtramem_sz,
		nil) //dvoid         **usrmempp);
	if r == C.OCI_ERROR {
		return bnd.stmt.ses.srv.env.ociError()
	} else if r == C.OCI_INVALID_HANDLE {
		return errNew("unable to allocate oci timestamp handle during bind")
	}
	if value == nil {
		bnd.isNull = C.sb2(-1)
	} else {
		zone := zoneOffset(*value, &bnd.zoneBuf)
		bnd.cZone = C.CString(zone)
		r = C.OCIDateTimeConstruct(
			unsafe.Pointer(bnd.stmt.ses.srv.env.ocienv), //dvoid         *hndl,
			bnd.stmt.ses.srv.env.ocierr,                 //OCIError      *err,
			bnd.ociDateTime,                             //OCIDateTime   *datetime,
			C.sb2(value.Year()),                         //sb2           year,
			C.ub1(int32(value.Month())),                 //ub1           month,
			C.ub1(value.Day()),                          //ub1           day,
			C.ub1(value.Hour()),                         //ub1           hour,
			C.ub1(value.Minute()),                       //ub1           min,
			C.ub1(value.Second()),                       //ub1           sec,
			C.ub4(value.Nanosecond()),                   //ub4           fsec,
			(*C.OraText)(unsafe.Pointer(bnd.cZone)),     //OraText       *timezone,
			C.size_t(len(zone)))                         //size_t        timezone_length );
		if r == C.OCI_ERROR {
			return bnd.stmt.ses.srv.env.ociError()
		}
	}
	r = C.OCIBINDBYPOS(
		bnd.stmt.ocistmt,                              //OCIStmt      *stmtp,
		(**C.OCIBind)(&bnd.ocibnd),                    //OCIBind      **bindpp,
		bnd.stmt.ses.srv.env.ocierr,                   //OCIError     *errhp,
		C.ub4(position),                               //ub4          position,
		unsafe.Pointer(&bnd.ociDateTime),              //void         *valuep,
		C.LENGTH_TYPE(unsafe.Sizeof(bnd.ociDateTime)), //sb8          value_sz,
		C.SQLT_TIMESTAMP_TZ,                           //ub2          dty,
		unsafe.Pointer(&bnd.isNull),                   //void         *indp,
		nil,           //ub2          *alenp,
		nil,           //ub2          *rcodep,
		0,             //ub4          maxarr_len,
		nil,           //ub4          *curelep,
		C.OCI_DEFAULT) //ub4          mode );
	if r == C.OCI_ERROR {
		return bnd.stmt.ses.srv.env.ociError()
	}
	return nil
}
예제 #5
0
func (def *defIntervalDS) alloc() error {
	r := C.OCIDescriptorAlloc(
		unsafe.Pointer(def.rset.stmt.ses.srv.env.ocienv),    //CONST dvoid   *parenth,
		(*unsafe.Pointer)(unsafe.Pointer(&def.ociInterval)), //dvoid         **descpp,
		C.OCI_DTYPE_INTERVAL_DS,                             //ub4           type,
		0,   //size_t        xtramem_sz,
		nil) //dvoid         **usrmempp);
	if r == C.OCI_ERROR {
		return def.rset.stmt.ses.srv.env.ociError()
	} else if r == C.OCI_INVALID_HANDLE {
		return errNew("unable to allocate oci interval handle during define")
	}
	return nil
}
예제 #6
0
파일: defBfile.go 프로젝트: optimuse/ora
func (def *defBfile) alloc() error {
	// Allocate lob locator handle
	r := C.OCIDescriptorAlloc(
		unsafe.Pointer(def.rset.stmt.ses.srv.env.ocienv),      //CONST dvoid   *parenth,
		(*unsafe.Pointer)(unsafe.Pointer(&def.ociLobLocator)), //dvoid         **descpp,
		C.OCI_DTYPE_FILE,                                      //ub4           type,
		0,                                                     //size_t        xtramem_sz,
		nil)                                                   //dvoid         **usrmempp);
	if r == C.OCI_ERROR {
		return def.rset.stmt.ses.srv.env.ociError()
	} else if r == C.OCI_INVALID_HANDLE {
		return errNew("unable to allocate oci lob handle during define")
	}
	return nil
}
예제 #7
0
파일: bndLob.go 프로젝트: optimuse/ora
func allocTempLob(stmt *Stmt) (
	ociLobLocator *C.OCILobLocator,
	finish func(),
	err error,
) {
	// Allocate lob locator handle
	r := C.OCIDescriptorAlloc(
		unsafe.Pointer(stmt.ses.srv.env.ocienv),           //CONST dvoid   *parenth,
		(*unsafe.Pointer)(unsafe.Pointer(&ociLobLocator)), //dvoid         **descpp,
		C.OCI_DTYPE_LOB,                                   //ub4           type,
		0,                                                 //size_t        xtramem_sz,
		nil)                                               //dvoid         **usrmempp);
	if r == C.OCI_ERROR {
		return nil, nil, stmt.ses.srv.env.ociError()
	} else if r == C.OCI_INVALID_HANDLE {
		return nil, nil, errNew("unable to allocate oci lob handle during bind")
	}

	// Create temporary lob
	r = C.OCILobCreateTemporary(
		stmt.ses.srv.ocisvcctx,  //OCISvcCtx          *svchp,
		stmt.ses.srv.env.ocierr, //OCIError           *errhp,
		ociLobLocator,           //OCILobLocator      *locp,
		C.OCI_DEFAULT,           //ub2                csid,
		C.SQLCS_IMPLICIT,        //ub1                csfrm,
		C.OCI_TEMP_BLOB,         //ub1                lobtype,
		C.TRUE,                  //boolean            cache,
		C.OCI_DURATION_SESSION)  //OCIDuration        duration);
	if r == C.OCI_ERROR {
		// free lob locator handle
		C.OCIDescriptorFree(
			unsafe.Pointer(ociLobLocator), //void     *descp,
			C.OCI_DTYPE_LOB)               //ub4      type );
		return nil, nil, stmt.ses.srv.env.ociError()
	}

	return ociLobLocator, func() {
		C.OCILobFreeTemporary(
			stmt.ses.srv.ocisvcctx,  //OCISvcCtx          *svchp,
			stmt.ses.srv.env.ocierr, //OCIError           *errhp,
			ociLobLocator)           //OCILobLocator      *locp,
		// free lob locator handle
		C.OCIDescriptorFree(
			unsafe.Pointer(ociLobLocator), //void     *descp,
			C.OCI_DTYPE_LOB)               //ub4      type );
	}, nil
}
예제 #8
0
func (bnd *bndIntervalDS) bind(value IntervalDS, position int, stmt *Stmt) error {
	bnd.stmt = stmt
	r := C.OCIDescriptorAlloc(
		unsafe.Pointer(bnd.stmt.ses.srv.env.ocienv),         //CONST dvoid   *parenth,
		(*unsafe.Pointer)(unsafe.Pointer(&bnd.ociInterval)), //dvoid         **descpp,
		C.OCI_DTYPE_INTERVAL_DS,                             //ub4           type,
		0,   //size_t        xtramem_sz,
		nil) //dvoid         **usrmempp);
	if r == C.OCI_ERROR {
		return bnd.stmt.ses.srv.env.ociError()
	} else if r == C.OCI_INVALID_HANDLE {
		return errNew("unable to allocate oci interval handle during bind")
	}
	r = C.OCIIntervalSetDaySecond(
		unsafe.Pointer(bnd.stmt.ses.srv.env.ocienv), //void               *hndl,
		bnd.stmt.ses.srv.env.ocierr,                 //OCIError           *err,
		C.sb4(value.Day),                            //sb4                dy,
		C.sb4(value.Hour),                           //sb4                hr,
		C.sb4(value.Minute),                         //sb4                mm,
		C.sb4(value.Second),                         //sb4                ss,
		C.sb4(value.Nanosecond),                     //sb4                fsec,
		bnd.ociInterval)                             //OCIInterval        *result );
	if r == C.OCI_ERROR {
		return bnd.stmt.ses.srv.env.ociError()
	}
	r = C.OCIBINDBYPOS(
		bnd.stmt.ocistmt,                              //OCIStmt      *stmtp,
		(**C.OCIBind)(&bnd.ocibnd),                    //OCIBind      **bindpp,
		bnd.stmt.ses.srv.env.ocierr,                   //OCIError     *errhp,
		C.ub4(position),                               //ub4          position,
		unsafe.Pointer(&bnd.ociInterval),              //void         *valuep,
		C.LENGTH_TYPE(unsafe.Sizeof(bnd.ociInterval)), //sb8          value_sz,
		C.SQLT_INTERVAL_DS,                            //ub2          dty,
		nil,                                           //void         *indp,
		nil,                                           //ub2          *alenp,
		nil,                                           //ub2          *rcodep,
		0,                                             //ub4          maxarr_len,
		nil,                                           //ub4          *curelep,
		C.OCI_DEFAULT)                                 //ub4          mode );
	if r == C.OCI_ERROR {
		return bnd.stmt.ses.srv.env.ociError()
	}
	return nil
}
예제 #9
0
// Initialize the variable.
func lobVar_Initialize(v *Variable, cur *Cursor) error {
	// initialize members
	v.connection = cur.connection
	// v.isFile = v.typ == BFileVarType

	// initialize the LOB locators
	var err error
	for i := uint(0); i < v.allocatedElements; i++ {
		if err = v.environment.CheckStatus(
			C.OCIDescriptorAlloc(unsafe.Pointer(v.environment.handle),
				(*unsafe.Pointer)(unsafe.Pointer(&v.dataBytes[i])),
				C.OCI_DTYPE_LOB, 0, nil),
			"DescrAlloc"); err != nil {
			return err
		}
	}

	return nil
}
예제 #10
0
func (bnd *bndIntervalDSSlice) bind(values []IntervalDS, position int, stmt *Stmt) error {
	bnd.stmt = stmt
	bnd.ociIntervals = make([]*C.OCIInterval, len(values))
	nullInds := make([]C.sb2, len(values))
	alenp := make([]C.ACTUAL_LENGTH_TYPE, len(values))
	rcodep := make([]C.ub2, len(values))
	for n, value := range values {
		r := C.OCIDescriptorAlloc(
			unsafe.Pointer(bnd.stmt.ses.srv.env.ocienv),             //CONST dvoid   *parenth,
			(*unsafe.Pointer)(unsafe.Pointer(&bnd.ociIntervals[n])), //dvoid         **descpp,
			C.OCI_DTYPE_INTERVAL_DS,                                 //ub4           type,
			0,   //size_t        xtramem_sz,
			nil) //dvoid         **usrmempp);
		if r == C.OCI_ERROR {
			return bnd.stmt.ses.srv.env.ociError()
		} else if r == C.OCI_INVALID_HANDLE {
			return errNew("unable to allocate oci interval handle during bind")
		}
		r = C.OCIIntervalSetDaySecond(
			unsafe.Pointer(bnd.stmt.ses.srv.env.ocienv), //void               *hndl,
			bnd.stmt.ses.srv.env.ocierr,                 //OCIError           *err,
			C.sb4(value.Day),                            //sb4                dy,
			C.sb4(value.Hour),                           //sb4                hr,
			C.sb4(value.Minute),                         //sb4                mm,
			C.sb4(value.Second),                         //sb4                ss,
			C.sb4(value.Nanosecond),                     //sb4                fsec,
			bnd.ociIntervals[n])                         //OCIInterval        *result );
		if r == C.OCI_ERROR {
			return bnd.stmt.ses.srv.env.ociError()
		}
		if values[n].IsNull {
			nullInds[n] = C.sb2(-1)
		} else {
			nullInds[n] = C.sb2(0)
		}
		alenp[n] = C.ACTUAL_LENGTH_TYPE(unsafe.Sizeof(bnd.ociIntervals[n]))
	}
	r := C.OCIBINDBYPOS(
		bnd.stmt.ocistmt,                                  //OCIStmt      *stmtp,
		(**C.OCIBind)(&bnd.ocibnd),                        //OCIBind      **bindpp,
		bnd.stmt.ses.srv.env.ocierr,                       //OCIError     *errhp,
		C.ub4(position),                                   //ub4          position,
		unsafe.Pointer(&bnd.ociIntervals[0]),              //void         *valuep,
		C.LENGTH_TYPE(unsafe.Sizeof(bnd.ociIntervals[0])), //sb8          value_sz,
		C.SQLT_INTERVAL_DS,                                //ub2          dty,
		unsafe.Pointer(&nullInds[0]),                      //void         *indp,
		&alenp[0],                                         //ub2          *alenp,
		&rcodep[0],                                        //ub2          *rcodep,
		0,                                                 //ub4          maxarr_len,
		nil,                                               //ub4          *curelep,
		C.OCI_DEFAULT)                                     //ub4          mode );
	if r == C.OCI_ERROR {
		return bnd.stmt.ses.srv.env.ociError()
	}
	r = C.OCIBindArrayOfStruct(
		bnd.ocibnd,
		bnd.stmt.ses.srv.env.ocierr,
		C.ub4(unsafe.Sizeof(bnd.ociIntervals[0])), //ub4         pvskip,
		C.ub4(C.sizeof_sb2),                       //ub4         indskip,
		C.ub4(C.sizeof_ub4),                       //ub4         alskip,
		C.ub4(C.sizeof_ub2))                       //ub4         rcskip
	if r == C.OCI_ERROR {
		return bnd.stmt.ses.srv.env.ociError()
	}
	return nil
}
예제 #11
0
파일: oci8.go 프로젝트: jprobinson/go-oci8
func (s *OCI8Stmt) Query(args []driver.Value) (rows driver.Rows, err error) {
	var (
		freeBoundParameters func()
	)

	if freeBoundParameters, err = s.bind(args); err != nil {
		return nil, err
	}

	defer freeBoundParameters()

	var t C.int
	C.OCIAttrGet(
		s.s,
		C.OCI_HTYPE_STMT,
		unsafe.Pointer(&t),
		nil,
		C.OCI_ATTR_STMT_TYPE,
		(*C.OCIError)(s.c.err))
	iter := C.ub4(1)
	if t == C.OCI_STMT_SELECT {
		iter = 0
	}

	// set the row prefetch.  Only one extra row per fetch will be returned unless this is set.
	prefetch_size := C.ub4(s.c.attrs.Get("prefetch_rows").(int))
	C.OCIAttrSet(s.s, C.OCI_HTYPE_STMT, unsafe.Pointer(&prefetch_size), 0, C.OCI_ATTR_PREFETCH_ROWS, (*C.OCIError)(s.c.err))

	// if non-zero, oci will fetch rows until the memory limit or row prefetch limit is hit.
	// useful for memory constrained systems
	prefetch_memory := C.ub4(s.c.attrs.Get("prefetch_memory").(int64))
	C.OCIAttrSet(s.s, C.OCI_HTYPE_STMT, unsafe.Pointer(&prefetch_memory), 0, C.OCI_ATTR_PREFETCH_MEMORY, (*C.OCIError)(s.c.err))

	rv := C.OCIStmtExecute(
		(*C.OCISvcCtx)(s.c.svc),
		(*C.OCIStmt)(s.s),
		(*C.OCIError)(s.c.err),
		iter,
		0,
		nil,
		nil,
		C.OCI_DEFAULT)
	if rv == C.OCI_ERROR {
		return nil, ociGetError(s.c.err)
	}

	var rc C.ub2
	C.OCIAttrGet(
		s.s,
		C.OCI_HTYPE_STMT,
		unsafe.Pointer(&rc),
		nil,
		C.OCI_ATTR_PARAM_COUNT,
		(*C.OCIError)(s.c.err))

	oci8cols := make([]oci8col, int(rc))
	for i := 0; i < int(rc); i++ {
		var p unsafe.Pointer
		var np *C.char
		var ns C.ub4
		var tp C.ub2
		var lp C.ub2
		C.OCIParamGet(
			s.s,
			C.OCI_HTYPE_STMT,
			(*C.OCIError)(s.c.err),
			(*unsafe.Pointer)(unsafe.Pointer(&p)),
			C.ub4(i+1))
		C.OCIAttrGet(
			p,
			C.OCI_DTYPE_PARAM,
			unsafe.Pointer(&tp),
			nil,
			C.OCI_ATTR_DATA_TYPE,
			(*C.OCIError)(s.c.err))
		C.OCIAttrGet(
			p,
			C.OCI_DTYPE_PARAM,
			unsafe.Pointer(&np),
			&ns,
			C.OCI_ATTR_NAME,
			(*C.OCIError)(s.c.err))
		C.OCIAttrGet(
			p,
			C.OCI_DTYPE_PARAM,
			unsafe.Pointer(&lp),
			nil,
			C.OCI_ATTR_DATA_SIZE,
			(*C.OCIError)(s.c.err))

		switch tp {
		case C.SQLT_NUM:
			oci8cols[i].kind = C.SQLT_CHR
		default:
			oci8cols[i].kind = tp
		}
		oci8cols[i].name = string((*[1 << 30]byte)(unsafe.Pointer(np))[0:int(ns)])
		oci8cols[i].size = int(lp)

		var defp *C.OCIDefine
		if tp == C.SQLT_CLOB || tp == C.SQLT_BLOB {
			rv = C.OCIDescriptorAlloc(
				s.c.env,
				&oci8cols[i].pbuf,
				C.OCI_DTYPE_LOB,
				0,
				nil)
			if rv == C.OCI_ERROR {
				return nil, ociGetError(s.c.err)
			}
			rv = C.OCIDefineByPos(
				(*C.OCIStmt)(s.s),
				&defp,
				(*C.OCIError)(s.c.err),
				C.ub4(i+1),
				unsafe.Pointer(&oci8cols[i].pbuf),
				-1,
				oci8cols[i].kind,
				unsafe.Pointer(&oci8cols[i].ind),
				&oci8cols[i].rlen,
				nil,
				C.OCI_DEFAULT)
		} else {
			oci8cols[i].pbuf = C.malloc(C.size_t(lp) + 1)
			rv = C.OCIDefineByPos(
				(*C.OCIStmt)(s.s),
				&defp,
				(*C.OCIError)(s.c.err),
				C.ub4(i+1),
				oci8cols[i].pbuf,
				C.sb4(lp+1),
				oci8cols[i].kind,
				unsafe.Pointer(&oci8cols[i].ind),
				&oci8cols[i].rlen,
				nil,
				C.OCI_DEFAULT)
		}

		if rv == C.OCI_ERROR {
			return nil, ociGetError(s.c.err)
		}
	}
	return &OCI8Rows{s, oci8cols, false}, nil
}
예제 #12
0
파일: oci8.go 프로젝트: jprobinson/go-oci8
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
}
예제 #13
0
func (bnd *bndTimeSlice) bind(values []time.Time, nullInds []C.sb2, position int, stmt *Stmt) error {
	bnd.stmt = stmt
	bnd.ociDateTimes = make([]*C.OCIDateTime, len(values))
	if nullInds == nil {
		nullInds = make([]C.sb2, len(values))
	}
	alenp := make([]C.ACTUAL_LENGTH_TYPE, len(values))
	rcodep := make([]C.ub2, len(values))
	for n, timeValue := range values {
		timezoneStr := zoneOffset(timeValue, &bnd.zoneBuf)
		cTimezoneStr := C.CString(timezoneStr)
		defer func() {
			C.free(unsafe.Pointer(cTimezoneStr))
		}()
		r := C.OCIDescriptorAlloc(
			unsafe.Pointer(bnd.stmt.ses.srv.env.ocienv),             //CONST dvoid   *parenth,
			(*unsafe.Pointer)(unsafe.Pointer(&bnd.ociDateTimes[n])), //dvoid         **descpp,
			C.OCI_DTYPE_TIMESTAMP_TZ,                                //ub4           type,
			0,   //size_t        xtramem_sz,
			nil) //dvoid         **usrmempp);
		if r == C.OCI_ERROR {
			return bnd.stmt.ses.srv.env.ociError()
		} else if r == C.OCI_INVALID_HANDLE {
			return errNew("unable to allocate oci timestamp handle during bind")
		}
		r = C.OCIDateTimeConstruct(
			unsafe.Pointer(bnd.stmt.ses.srv.env.ocienv), //dvoid         *hndl,
			bnd.stmt.ses.srv.env.ocierr,                 //OCIError      *err,
			bnd.ociDateTimes[n],                         //OCIDateTime   *datetime,
			C.sb2(timeValue.Year()),                     //sb2           year,
			C.ub1(int32(timeValue.Month())),             //ub1           month,
			C.ub1(timeValue.Day()),                      //ub1           day,
			C.ub1(timeValue.Hour()),                     //ub1           hour,
			C.ub1(timeValue.Minute()),                   //ub1           min,
			C.ub1(timeValue.Second()),                   //ub1           sec,
			C.ub4(timeValue.Nanosecond()),               //ub4           fsec,
			(*C.OraText)(unsafe.Pointer(cTimezoneStr)),  //OraText       *timezone,
			C.size_t(len(timezoneStr)))                  //size_t        timezone_length );
		if r == C.OCI_ERROR {
			return bnd.stmt.ses.srv.env.ociError()
		}
		alenp[n] = C.ACTUAL_LENGTH_TYPE(unsafe.Sizeof(bnd.ociDateTimes[n]))
	}

	r := C.OCIBINDBYPOS(
		bnd.stmt.ocistmt,                                  //OCIStmt      *stmtp,
		(**C.OCIBind)(&bnd.ocibnd),                        //OCIBind      **bindpp,
		bnd.stmt.ses.srv.env.ocierr,                       //OCIError     *errhp,
		C.ub4(position),                                   //ub4          position,
		unsafe.Pointer(&bnd.ociDateTimes[0]),              //void         *valuep,
		C.LENGTH_TYPE(unsafe.Sizeof(bnd.ociDateTimes[0])), //sb8          value_sz,
		C.SQLT_TIMESTAMP_TZ,                               //ub2          dty,
		unsafe.Pointer(&nullInds[0]),                      //void         *indp,
		&alenp[0],                                         //ub2          *alenp,
		&rcodep[0],                                        //ub2          *rcodep,
		0,                                                 //ub4          maxarr_len,
		nil,                                               //ub4          *curelep,
		C.OCI_DEFAULT)                                     //ub4          mode );
	if r == C.OCI_ERROR {
		return bnd.stmt.ses.srv.env.ociError()
	}
	r = C.OCIBindArrayOfStruct(
		bnd.ocibnd,
		bnd.stmt.ses.srv.env.ocierr,
		C.ub4(unsafe.Sizeof(bnd.ociDateTimes[0])), //ub4         pvskip,
		C.ub4(C.sizeof_sb2),                       //ub4         indskip,
		C.ub4(C.sizeof_ub4),                       //ub4         alskip,
		C.ub4(C.sizeof_ub2))                       //ub4         rcskip
	if r == C.OCI_ERROR {
		return bnd.stmt.ses.srv.env.ociError()
	}
	return nil
}