Example #1
0
func (c *OCI8Conn) Prepare(query string) (driver.Stmt, error) {
	pquery := C.CString(query)
	defer C.free(unsafe.Pointer(pquery))
	var s unsafe.Pointer

	rv := C.OCIHandleAlloc(
		c.env,
		&s,
		C.OCI_HTYPE_STMT,
		0,
		nil)
	if rv == C.OCI_ERROR {
		return nil, ociGetError(c.err)
	}

	rv = C.OCIStmtPrepare(
		(*C.OCIStmt)(s),
		(*C.OCIError)(c.err),
		(*C.OraText)(unsafe.Pointer(pquery)),
		C.ub4(C.strlen(pquery)),
		C.ub4(C.OCI_NTV_SYNTAX),
		C.ub4(OCI_MODE))
	if rv == C.OCI_ERROR {
		return nil, ociGetError(c.err)
	}

	return &OCI8Stmt{c: c, s: s}, nil
}
Example #2
0
func (c *OCI8Conn) Prepare(query string) (driver.Stmt, error) {
	pquery := C.CString(query)
	defer C.free(unsafe.Pointer(pquery))
	var s, bp, defp unsafe.Pointer

	if rv := C.WrapOCIHandleAlloc(
		c.env,
		C.OCI_HTYPE_STMT,
		(C.size_t)(unsafe.Sizeof(bp)*2)); rv.rv != C.OCI_SUCCESS {
		return nil, ociGetError(c.err)
	} else {
		s = rv.ptr
		bp = rv.extra
		defp = unsafe.Pointer(uintptr(rv.extra) + unsafe.Sizeof(unsafe.Pointer(nil)))
	}

	if rv := C.OCIStmtPrepare(
		(*C.OCIStmt)(s),
		(*C.OCIError)(c.err),
		(*C.OraText)(unsafe.Pointer(pquery)),
		C.ub4(C.strlen(pquery)),
		C.ub4(C.OCI_NTV_SYNTAX),
		C.ub4(C.OCI_DEFAULT)); rv != C.OCI_SUCCESS {
		return nil, ociGetError(c.err)
	}

	ss := &OCI8Stmt{c: c, s: s, bp: (**C.OCIBind)(bp), defp: (**C.OCIDefine)(defp)}
	runtime.SetFinalizer(ss, (*OCI8Stmt).Close)
	return ss, nil
}
Example #3
0
func (conn *connection) performLogon(dsn string) error {

	user, pwd, host := parseDsn(dsn)
	puser := C.CString(user)
	defer C.free(unsafe.Pointer(puser))
	ppwd := C.CString(pwd)
	defer C.free(unsafe.Pointer(ppwd))
	phost := C.CString(host)
	defer C.free(unsafe.Pointer(phost))

	result := C.OCILogon2((*C.OCIEnv)(unsafe.Pointer(conn.env)),
		(*C.OCIError)(conn.err),
		(**C.OCIServer)(unsafe.Pointer(&conn.svr)),
		(*C.OraText)(unsafe.Pointer(puser)),
		C.ub4(C.strlen(puser)),
		(*C.OraText)(unsafe.Pointer(ppwd)),
		C.ub4(C.strlen(ppwd)),
		(*C.OraText)(unsafe.Pointer(phost)),
		C.ub4(C.strlen(phost)),
		C.OCI_LOGON2_STMTCACHE)
	if result != C.OCI_SUCCESS {
		return ociGetError(conn.err)
	}
	return nil
}
Example #4
0
func (conn *OCI8Conn) Prepare(query string) (driver.Stmt, error) {
	pquery := C.CString(query)
	defer C.free(unsafe.Pointer(pquery))
	var s unsafe.Pointer

	rv := C.OCIHandleAlloc(
		conn.env,
		&s,
		C.OCI_HTYPE_STMT,
		0,
		nil)

	if err := conn.check(rv, "OCI8Conn.Prepare() allocate statement handle"); err != nil {
		return nil, err
	}

	rv = C.OCIStmtPrepare(
		(*C.OCIStmt)(s),
		(*C.OCIError)(conn.err),
		(*C.OraText)(unsafe.Pointer(pquery)),
		C.ub4(C.strlen(pquery)),
		C.ub4(C.OCI_NTV_SYNTAX),
		C.ub4(C.OCI_DEFAULT))

	if err := conn.check(rv, "OCI8Conn.Prepare() prepare statement"); err != nil {
		return nil, err
	}

	return &OCI8Stmt{c: conn, s: s}, nil
}
Example #5
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
}
Example #6
0
func (d *OCI8Driver) Open(dsn string) (driver.Conn, error) {
	var conn OCI8Conn
	token := strings.SplitN(dsn, "@", 2)
	userpass := strings.SplitN(token[0], "/", 2)

	rv := C.OCIInitialize(
		C.OCI_DEFAULT,
		nil,
		nil,
		nil,
		nil)
	if rv == C.OCI_ERROR {
		return nil, ociGetError(conn.err)
	}

	rv = C.OCIEnvInit(
		(**C.OCIEnv)(unsafe.Pointer(&conn.env)),
		C.OCI_DEFAULT,
		0,
		nil)

	rv = C.OCIHandleAlloc(
		conn.env,
		&conn.err,
		C.OCI_HTYPE_ERROR,
		0,
		nil)
	if rv == C.OCI_ERROR {
		return nil, ociGetError(conn.err)
	}

	var phost *C.char
	phostlen := C.size_t(0)
	if len(token) > 1 {
		phost = C.CString(token[1])
		defer C.free(unsafe.Pointer(phost))
		phostlen = C.strlen(phost)
	}
	puser := C.CString(userpass[0])
	defer C.free(unsafe.Pointer(puser))
	ppass := C.CString(userpass[1])
	defer C.free(unsafe.Pointer(ppass))

	rv = C.OCILogon(
		(*C.OCIEnv)(conn.env),
		(*C.OCIError)(conn.err),
		(**C.OCIServer)(unsafe.Pointer(&conn.svc)),
		(*C.OraText)(unsafe.Pointer(puser)),
		C.ub4(C.strlen(puser)),
		(*C.OraText)(unsafe.Pointer(ppass)),
		C.ub4(C.strlen(ppass)),
		(*C.OraText)(unsafe.Pointer(phost)),
		C.ub4(phostlen))
	if rv == C.OCI_ERROR {
		return nil, ociGetError(conn.err)
	}

	return &conn, nil
}
Example #7
0
File: ses.go Project: rjammala/ora
// Prep prepares a sql statement returning a *Stmt and possible error.
func (ses *Ses) Prep(sql string, gcts ...GoColumnType) (stmt *Stmt, err error) {
	ses.mu.Lock()
	defer ses.mu.Unlock()
	defer func() {
		if value := recover(); value != nil {
			err = errR(value)
		}
	}()
	ses.log(_drv.cfg.Log.Ses.Prep, sql)
	err = ses.checkClosed()
	if err != nil {
		return nil, errE(err)
	}
	// allocate statement handle
	upOciStmt, err := ses.srv.env.allocOciHandle(C.OCI_HTYPE_STMT)
	if err != nil {
		return nil, errE(err)
	}
	ocistmt := (*C.OCIStmt)(upOciStmt)
	cSql := C.CString(sql) // prepare sql text with statement handle
	defer C.free(unsafe.Pointer(cSql))
	r := C.OCIStmtPrepare2(
		ses.srv.ocisvcctx,                  // OCISvcCtx     *svchp,
		&ocistmt,                           // OCIStmt       *stmtp,
		ses.srv.env.ocierr,                 // OCIError      *errhp,
		(*C.OraText)(unsafe.Pointer(cSql)), // const OraText *stmt,
		C.ub4(len(sql)),                    // ub4           stmt_len,
		nil,                                // const OraText *key,
		C.ub4(0),                           // ub4           keylen,
		C.OCI_NTV_SYNTAX,                   // ub4           language,
		C.OCI_DEFAULT)                      // ub4           mode );
	if r == C.OCI_ERROR {
		return nil, errE(ses.srv.env.ociError())
	}
	// set stmt struct
	stmt = _drv.stmtPool.Get().(*Stmt)
	stmt.ses = ses
	stmt.ocistmt = (*C.OCIStmt)(ocistmt)
	stmtCfg := ses.cfg.StmtCfg
	if stmtCfg == nil {
		stmtCfg = NewStmtCfg()
	}
	if !ses.srv.dbIsUTF8 && stmtCfg.stringPtrBufferSize > 1000 {
		stmtCfg.stringPtrBufferSize = 1000
	}
	stmt.cfg = *stmtCfg
	stmt.sql = sql
	stmt.gcts = gcts
	if stmt.id == 0 {
		stmt.id = _drv.stmtId.nextId()
	}
	err = stmt.attr(unsafe.Pointer(&stmt.stmtType), 4, C.OCI_ATTR_STMT_TYPE) // determine statement type
	if err != nil {
		return nil, errE(err)
	}
	ses.openStmts.add(stmt)

	return stmt, nil
}
Example #8
0
func (bnd *bndStringSlice) bind(values []string, nullInds []C.sb2, position int, stmt *Stmt) (err error) {
	bnd.stmt = stmt
	if nullInds == nil {
		nullInds = make([]C.sb2, len(values))
	}
	alenp := make([]C.ACTUAL_LENGTH_TYPE, len(values))
	rcodep := make([]C.ub2, len(values))
	var maxLen int
	for _, str := range values {
		strLen := len(str)
		if strLen > maxLen {
			maxLen = strLen
		}
	}
	for m := 0; m < len(values); m++ {
		_, err = bnd.buf.WriteString(values[m])
		if err != nil {
			return err
		}
		// pad to make equal to max len if necessary
		padLen := maxLen - len(values[m])
		for n := 0; n < padLen; n++ {
			_, err = bnd.buf.WriteRune('0')
			if err != nil {
				return err
			}
		}
		alenp[m] = C.ACTUAL_LENGTH_TYPE(len(values[m]))
	}
	bnd.bytes = bnd.buf.Bytes()
	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.bytes[0]), //void         *valuep,
		C.LENGTH_TYPE(maxLen),         //sb8          value_sz,
		C.SQLT_CHR,                    //ub2          dty,
		unsafe.Pointer(&nullInds[0]),  //void         *indp,
		&alenp[0],                     //ub4          *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(maxLen),       //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
}
Example #9
0
// close closes the SQL statement.
// does not remove Stmt from Ses.openStmts
func (stmt *Stmt) close() (err error) {
	stmt.mu.Lock()
	defer stmt.mu.Unlock()
	stmt.log(_drv.cfg.Log.Stmt.Close)
	err = stmt.checkClosed()
	if err != nil {
		return errE(err)
	}
	errs := _drv.listPool.Get().(*list.List)
	defer func() {
		if value := recover(); value != nil {
			errs.PushBack(errR(value))
		}
		// free ocistmt to release cursor on server
		// OCIStmtRelease must be called with OCIStmtPrepare2
		// See https://docs.oracle.com/database/121/LNOCI/oci09adv.htm#LNOCI16655
		r := C.OCIStmtRelease(
			stmt.ocistmt,            // OCIStmt        *stmthp
			stmt.ses.srv.env.ocierr, // OCIError       *errhp,
			nil,           // const OraText  *key
			C.ub4(0),      // ub4 keylen
			C.OCI_DEFAULT, // ub4 mode
		)
		if r == C.OCI_ERROR {
			errs.PushBack(errE(stmt.ses.srv.env.ociError()))
		}

		stmt.ses = nil
		stmt.ocistmt = nil
		stmt.stmtType = C.ub4(0)
		stmt.sql = ""
		stmt.gcts = nil
		stmt.bnds = nil
		stmt.hasPtrBind = false
		stmt.openRsets.clear()
		_drv.stmtPool.Put(stmt)

		multiErr := newMultiErrL(errs)
		if multiErr != nil {
			err = errE(*multiErr)
		}
		errs.Init()
		_drv.listPool.Put(errs)
	}()
	if len(stmt.bnds) > 0 { // close binds
		for _, bind := range stmt.bnds {
			if bind != nil {
				err = bind.close()
				if err != nil {
					errs.PushBack(errE(err))
				}
			}
		}
	}
	stmt.openRsets.closeAll(errs)

	return nil
}
Example #10
0
// Write data to the LOB variable.
func (v *Variable) lobVarWrite(data []byte, pos uint, off int64) (amount int, err error) {
	if !(v.typ == BlobVarType || v.typ == ClobVarType ||
		v.typ == NClobVarType || v.typ == BFileVarType) {
		return 0, fmt.Errorf("only LOBs an be written into, not %T", v.typ)
	}

	amount = len(data)
	// verify the data type
	if v.typ == BFileVarType {
		return 0, errors.New("BFILEs are read only")
	}
	if v.typ == BlobVarType {
		// amount = len(data)
		/*
			#if PY_MAJOR_VERSION < 3
			    } else if (var->type == &vt_NCLOB) {
			        if (cxBuffer_FromObject(&buffer, dataObj,
			                var->environment->nencoding) < 0)
			            return -1;
			        *amount = buffer.size;
			#endif
		*/
	} else {
		if v.environment.FixedWidth && (v.environment.MaxBytesPerCharacter > 1) {
			amount /= int(v.environment.MaxBytesPerCharacter)
		} else {
			// amount = len(p)
		}
	}

	// nothing to do if no data to write
	if amount == 0 {
		return 0, nil
	}

	oamount := C.ub4(amount)
	// Py_BEGIN_ALLOW_THREADS
	if CTrace {
		ctrace("OCILobWrite(conn=%p, lob=%x, &oamount=%p, off=%d, cF=%d)",
			v.connection.handle, v.getHandleBytes(pos), &oamount, off,
			v.typ.charsetForm)
	}
	if err := v.environment.CheckStatus(
		C.OCILobWrite(v.connection.handle,
			v.environment.errorHandle,
			(*C.OCILobLocator)(v.getHandle(pos)),
			&oamount, C.ub4(off),
			unsafe.Pointer(&data[0]), C.ub4(len(data)),
			C.OCI_ONE_PIECE, nil, nil, 0,
			v.typ.charsetForm),
		"LobWrite"); err != nil {
		return 0, err
	}
	amount = int(oamount)
	// Py_END_ALLOW_THREADS
	return int(oamount), nil
}
Example #11
0
func (bnd *bndBinSlice) bind(values [][]byte, nullInds []C.sb2, position int, lobBufferSize int, stmt *Stmt) error {
	bnd.stmt = stmt
	if nullInds == nil {
		nullInds = make([]C.sb2, len(values))
	}
	alenp := make([]C.ACTUAL_LENGTH_TYPE, len(values))
	rcodep := make([]C.ub2, len(values))
	var maxLen int
	for _, b := range values {
		if len(b) > maxLen {
			maxLen = len(b)
		}
	}
	n := maxLen * len(values)
	if cap(bnd.buf) < n {
		bnd.buf = make([]byte, n)
	} else {
		bnd.buf = bnd.buf[:n]
		// reset buffer
		for i := range bnd.buf {
			bnd.buf[i] = 0
		}
	}
	for i, b := range values {
		copy(bnd.buf[i*maxLen:], b)
		alenp[i] = C.ACTUAL_LENGTH_TYPE(len(b))
	}
	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.buf[0]),  //void         *valuep,
		C.LENGTH_TYPE(maxLen),        //sb8          value_sz,
		C.SQLT_LBI,                   //ub2          dty,
		unsafe.Pointer(&nullInds[0]), //void         *indp,
		&alenp[0],                    //ub4          *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(maxLen),       //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
}
Example #12
0
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
}
Example #13
0
func (d *OCI8Driver) Open(dsnString string) (connection driver.Conn, err error) {
	var (
		conn OCI8Conn
		dsn  *DSN
	)

	if dsn, err = ParseDSN(dsnString); err != nil {
		return nil, err
	}

	if rv := C.WrapOCIEnvCreate(
		C.OCI_DEFAULT|C.OCI_THREADED,
		0); rv.rv != C.OCI_SUCCESS && rv.rv != C.OCI_SUCCESS_WITH_INFO {
		// TODO: error handle not yet allocated, we can't get string error from oracle
		return nil, errors.New("can't OCIEnvCreate")
	} else {
		conn.env = rv.ptr
	}

	if rv := C.WrapOCIHandleAlloc(
		conn.env,
		C.OCI_HTYPE_ERROR,
		0); rv.rv != C.OCI_SUCCESS {
		return nil, errors.New("cant allocate error handle")
	} else {
		conn.err = rv.ptr
	}

	phost := C.CString(dsn.Connect)
	defer C.free(unsafe.Pointer(phost))
	puser := C.CString(dsn.Username)
	defer C.free(unsafe.Pointer(puser))
	ppass := C.CString(dsn.Password)
	defer C.free(unsafe.Pointer(ppass))

	if rv := C.WrapOCILogon(
		(*C.OCIEnv)(conn.env),
		(*C.OCIError)(conn.err),
		(*C.OraText)(unsafe.Pointer(puser)),
		C.ub4(len(dsn.Username)),
		(*C.OraText)(unsafe.Pointer(ppass)),
		C.ub4(len(dsn.Password)),
		(*C.OraText)(unsafe.Pointer(phost)),
		C.ub4(len(dsn.Connect))); rv.rv != C.OCI_SUCCESS && rv.rv != C.OCI_SUCCESS_WITH_INFO {
		return nil, ociGetError(rv.rv, conn.err)
	} else {
		conn.svc = rv.ptr
	}
	conn.location = dsn.Location
	conn.transactionMode = dsn.transactionMode
	conn.prefetch_rows = dsn.prefetch_rows
	conn.prefetch_memory = dsn.prefetch_memory
	conn.enableQMPlaceholders = dsn.enableQMPlaceholders
	return &conn, nil
}
Example #14
0
func (bnd *bndBoolSlice) bind(values []bool, nullInds []C.sb2, position int, falseRune rune, trueRune rune, stmt *Stmt) (err error) {
	bnd.stmt = stmt
	if nullInds == nil {
		nullInds = make([]C.sb2, len(values))
	}
	alenp := make([]C.ACTUAL_LENGTH_TYPE, len(values))
	rcodep := make([]C.ub2, len(values))
	var maxLen int = 1
	for n, bValue := range values {
		if bValue {
			_, err = bnd.buf.WriteRune(trueRune)
			if err != nil {
				return err
			}
		} else {
			_, err = bnd.buf.WriteRune(falseRune)
			if err != nil {
				return err
			}
		}
		alenp[n] = 1
	}
	bnd.bytes = bnd.buf.Bytes()

	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.bytes[0]), //void         *valuep,
		C.LENGTH_TYPE(maxLen),         //sb8          value_sz,
		C.SQLT_CHR,                    //ub2          dty,
		unsafe.Pointer(&nullInds[0]),  //void         *indp,
		&alenp[0],                     //ub4          *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,                  //OCIBind     *bindp,
		bnd.stmt.ses.srv.env.ocierr, //OCIError    *errhp,
		C.ub4(maxLen),               //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
}
Example #15
0
// qry runs a SQL query on an Oracle server returning a *Rset and possible error.
func (stmt *Stmt) qry(params []interface{}) (rset *Rset, err error) {
	stmt.mu.Lock()
	defer stmt.mu.Unlock()
	defer func() {
		if value := recover(); value != nil {
			err = errR(value)
		}
	}()
	stmt.log(_drv.cfg.Log.Stmt.Qry)
	err = stmt.checkClosed()
	if err != nil {
		return nil, errE(err)
	}
	_, err = stmt.bind(params) // bind parameters
	if err != nil {
		return nil, errE(err)
	}
	err = stmt.setPrefetchSize() // set prefetch size
	if err != nil {
		return nil, errE(err)
	}
	// Query statement on Oracle server
	r := C.OCIStmtExecute(
		stmt.ses.ocisvcctx,      //OCISvcCtx           *svchp,
		stmt.ocistmt,            //OCIStmt             *stmtp,
		stmt.ses.srv.env.ocierr, //OCIError            *errhp,
		C.ub4(0),                //ub4                 iters,
		C.ub4(0),                //ub4                 rowoff,
		nil,                     //const OCISnapshot   *snap_in,
		nil,                     //OCISnapshot         *snap_out,
		C.OCI_DEFAULT)           //ub4                 mode );
	if r == C.OCI_ERROR {
		return nil, errE(stmt.ses.srv.env.ociError())
	}
	if stmt.hasPtrBind { // set any bind pointers
		err = stmt.setBindPtrs()
		if err != nil {
			return nil, errE(err)
		}
	}
	// create result set and open
	rset = _drv.rsetPool.Get().(*Rset)
	if rset.id == 0 {
		rset.id = _drv.rsetId.nextId()
	}
	err = rset.open(stmt, stmt.ocistmt)
	if err != nil {
		rset.close()
		return nil, errE(err)
	}
	stmt.openRsets.add(rset)

	return rset, nil
}
Example #16
0
// Set the value of the variable from a Python decimal.Decimal object.
func (env *Environment) numberFromText(value string, dst unsafe.Pointer) error {
	valuebuf := []byte(value)
	formatbuf := []byte(numberVarformatForString(value))
	return env.CheckStatus(
		C.OCINumberFromText(env.errorHandle,
			(*C.oratext)(&valuebuf[0]), C.ub4(len(valuebuf)),
			(*C.oratext)(&formatbuf[0]), C.ub4(len(formatbuf)),
			(*C.oratext)(&env.nlsNumericCharactersBuffer[0]),
			C.ub4(len(env.nlsNumericCharactersBuffer)),
			(*C.OCINumber)(dst)),
		"numberFromText")
}
Example #17
0
// internalRead returns the size of the LOB variable for internal comsumption.
func (lv *ExternalLobVar) internalRead(p []byte, off int64) (length int64, err error) {
	var charsetID C.ub2
	j := lv.pos * lv.lobVar.typ.size

	if lv.isFile {
		// Py_BEGIN_ALLOW_THREADS
		if err = lv.lobVar.environment.CheckStatus(
			C.OCILobFileOpen(lv.lobVar.connection.handle,
				lv.lobVar.environment.errorHandle,
				(*C.OCILobLocator)(unsafe.Pointer(&lv.lobVar.dataBytes[j])),
				C.OCI_FILE_READONLY),
			"LobFileOpen"); err != nil {
			return
		}
	}
	// Py_END_ALLOW_THREADS

	// Py_BEGIN_ALLOW_THREADS
	if lv.lobVar.typ == NClobVarType {
		// charsetID = C.OCI_UTF16ID
		charsetID = CsIDAl32UTF8
	} else {
		charsetID = 0
	}
	length = int64(len(p))
	olength := C.ub4(length + 1)
	if err = lv.lobVar.environment.CheckStatus(
		C.OCILobRead(lv.lobVar.connection.handle,
			lv.lobVar.environment.errorHandle,
			(*C.OCILobLocator)(unsafe.Pointer(&lv.lobVar.dataBytes[j])),
			&olength, C.ub4(off+1), unsafe.Pointer(&p[0]),
			C.ub4(len(p)), nil, nil, charsetID, lv.lobVar.typ.charsetForm),
		"LobRead"); err != nil {
		// Py_END_ALLOW_THREADS
		C.OCILobFileClose(lv.lobVar.connection.handle,
			lv.lobVar.environment.errorHandle,
			(*C.OCILobLocator)(unsafe.Pointer(&lv.lobVar.dataBytes[j])))
		return
	}

	if lv.isFile {
		// Py_BEGIN_ALLOW_THREADS
		if err = lv.lobVar.environment.CheckStatus(
			C.OCILobFileClose(lv.lobVar.connection.handle,
				lv.lobVar.environment.errorHandle,
				(*C.OCILobLocator)(unsafe.Pointer(&lv.lobVar.dataBytes[j]))),
			"LobFileClose"); err != nil {
			return
		}
	}

	return
}
Example #18
0
func (env *Environment) AttrGet(parent unsafe.Pointer, parentType, key int,
	dst unsafe.Pointer, errText string) (int, error) {
	var osize C.ub4
	if CTrace {
		ctrace("OCIAttrGet", parent, C.ub4(parentType), dst, &osize, C.ub4(key), env.errorHandle)
	}
	if err := env.CheckStatus(
		C.OCIAttrGet(parent, C.ub4(parentType), dst, &osize, C.ub4(key),
			env.errorHandle), errText); err != nil {
		// log.Printf("error gettint attr: %s", err)
		return -1, err
	}
	return int(osize), nil
}
Example #19
0
func (bnd *bndInt16Slice) bind(values []int16, nullInds []C.sb2, position int, stmt *Stmt) error {
	bnd.stmt = stmt
	if nullInds == nil {
		nullInds = make([]C.sb2, len(values))
	}
	alenp := make([]C.ACTUAL_LENGTH_TYPE, len(values))
	rcodep := make([]C.ub2, len(values))
	bnd.ociNumbers = make([]C.OCINumber, len(values))
	for n := range values {
		alenp[n] = C.ACTUAL_LENGTH_TYPE(C.sizeof_OCINumber)
		r := C.OCINumberFromInt(
			bnd.stmt.ses.srv.env.ocierr, //OCIError            *err,
			unsafe.Pointer(&values[n]),  //const void          *inum,
			2,                   //uword               inum_length,
			C.OCI_NUMBER_SIGNED, //uword               inum_s_flag,
			&bnd.ociNumbers[n])  //OCINumber           *number );
		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.ociNumbers[0]), //void         *valuep,
		C.LENGTH_TYPE(C.sizeof_OCINumber),  //sb8          value_sz,
		C.SQLT_VNU,                         //ub2          dty,
		unsafe.Pointer(&nullInds[0]),       //void         *indp,
		&alenp[0],                          //ub4          *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(C.sizeof_OCINumber), //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
}
Example #20
0
//AttrGet gets the parent's attribute identified by key, and stores it in dst
func (env *Environment) AttrGet(parent unsafe.Pointer, parentType, key int,
	dst unsafe.Pointer, errText string) (int, error) {
	var osize C.ub4
	if CTrace {
		ctrace("OCIAttrGet(parent=%p, parentType=%d, dst=%p, osize=%p, key=%d, env=%p)",
			parent, C.ub4(parentType), dst, &osize, C.ub4(key), env.errorHandle)
	}
	if err := env.CheckStatus(
		C.OCIAttrGet(parent, C.ub4(parentType), dst, &osize, C.ub4(key),
			env.errorHandle), errText); err != nil {
		Log.Error("AttrGet", "attr", key, "error", err)
		return -1, err
	}
	return int(osize), nil
}
Example #21
0
// Returns the value stored at the given array position.
func numberVarGetValue(v *Variable, pos uint) (interface{}, error) {
	if v.dataFloats != nil {
		// log.Printf("getting pos=%d from %+v", pos, v.dataFloats)
		return v.dataFloats[pos], nil
	}
	if v.dataInts != nil {
		// log.Printf("getting pos=%d from %+v", pos, v.dataInts)
		return v.dataInts[pos], nil
	}

	num := (*C.OCINumber)(v.getHandle(pos))
	buf := make([]byte, 64)
	size := C.ub4(len(buf))
	if err := v.environment.CheckStatus(
		C.OCINumberToText(v.environment.errorHandle,
			num,
			(*C.oratext)(unsafe.Pointer(&v.environment.numberToStringFormatBuffer[0])),
			C.ub4(len(v.environment.numberToStringFormatBuffer)), nil, 0,
			&size, (*C.oratext)(&buf[0])),
		"NumberToText",
	); err != nil {
		var floatVal float64
		_ = v.environment.CheckStatus(
			C.OCINumberToReal(v.environment.errorHandle,
				num,
				C.sizeof_double, unsafe.Pointer(&floatVal)),
			"numberToFloat")
		log.Printf("floatVal=%f format=%q len=%d num=%p (%d) size=%p buf=%p",
			floatVal,
			v.environment.numberToStringFormatBuffer,
			len(v.environment.numberToStringFormatBuffer),
			num, *((*byte)(unsafe.Pointer(num))),
			&size, &buf[0])
		return 0, errgo.Notef(err, "want string (%f)", floatVal)
	}
	numS := strings.Replace(
		v.environment.FromEncodedString(buf[:int(size)]),
		",", ".", -1)
	if v.typ == NumberAsStringVarType {
		return numS, nil
	}

	if len(numS) <= 9 && strings.IndexByte(numS, '.') < 0 {
		intVal, err := numAsInt(v, num)
		return intVal, errgo.Mask(err)
	}
	return numS, nil
}
Example #22
0
func (env *Environment) AttrSet(parent unsafe.Pointer, parentTyp C.ub4,
	key C.ub4, value unsafe.Pointer, valueLength int) error {
	return env.CheckStatus(C.OCIAttrSet(parent, parentTyp,
		value, C.ub4(valueLength),
		key, env.errorHandle),
		"AttrSet")
}
Example #23
0
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
}
Example #24
0
func (c *ConnectionOracle) NewStatement(sql string) (s *StatementOracle, err int) {

	s = new(StatementOracle)
	pStatement := unsafe.Pointer(&s.hStatement)
	res := C.OCIHandleAlloc(unsafe.Pointer(c.driver.hEnv), (*unsafe.Pointer)(pStatement), C.OCI_HTYPE_STMT, 0, nil)
	if C.OCI_SUCCESS != res /*&& C.OCI_STILL_EXECUTING != res*/ {
		fmt.Printf("Result hSession=%v\n", res)
		C.AuxOCIErrorGet(c.driver.hError)
		return nil, -1
	}

	cSql := C.CString(sql)
	defer C.free(unsafe.Pointer(cSql))
	var osql *C.OraText = C.Get_OraText(cSql)
	//fmt.Printf( "%v:%v\n", C.strlen(sql), C.GoString(sql))
	res = C.OCIStmtPrepare(s.hStatement, c.driver.hError, osql, C.ub4(C.strlen(cSql)), C.OCI_NTV_SYNTAX, C.OCI_DEFAULT)
	if C.OCI_SUCCESS != res /*&& C.OCI_STILL_EXECUTING != res*/ {
		fmt.Printf("Resultado OCIStmtPrepare=%v\n", res)
		C.AuxOCIErrorGet(c.driver.hError)
		return nil, -2
	}
	s.fetchDone = false
	s.con = c
	return s, 0
}
Example #25
0
func (conn *connection) Prepare(query string) (driver.Stmt, error) {
	pquery := C.CString(query)
	defer C.free(unsafe.Pointer(pquery))
	var stmt unsafe.Pointer

	if C.OCIHandleAlloc(conn.env, &stmt, C.OCI_HTYPE_STMT, 0, nil) != C.OCI_SUCCESS {
		return nil, ociGetError(conn.err)
	}
	result := C.OCIStmtPrepare((*C.OCIStmt)(stmt), (*C.OCIError)(conn.err),
		(*C.OraText)(unsafe.Pointer(pquery)), C.ub4(C.strlen(pquery)),
		C.ub4(C.OCI_NTV_SYNTAX), C.ub4(C.OCI_DEFAULT))
	if result != C.OCI_SUCCESS {
		return nil, ociGetError(conn.err)
	}
	return &statement{handle: stmt, conn: conn}, nil
}
Example #26
0
func (bnd *bndBool) bind(value bool, position int, c StmtCfg, stmt *Stmt) (err error) {
	//Log.Infof("%s.bind(%t, %d)", bnd, value, position)
	bnd.stmt = stmt
	var str string
	if value {
		str, err = strconv.Unquote(strconv.QuoteRune(c.TrueRune))
	} else {
		str, err = strconv.Unquote(strconv.QuoteRune(c.FalseRune))
	}
	if err != nil {
		return err
	}
	bnd.cString = C.CString(str)
	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.cString), //void         *valuep,
		C.LENGTH_TYPE(1),            //sb8          value_sz,
		C.SQLT_AFC,                  //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
}
Example #27
0
func (bnd *bndInt32) bind(value int32, position int, stmt *Stmt) error {
	bnd.stmt = stmt
	r := C.OCINumberFromInt(
		bnd.stmt.ses.srv.env.ocierr, //OCIError            *err,
		unsafe.Pointer(&value),      //const void          *inum,
		4,                   //uword               inum_length,
		C.OCI_NUMBER_SIGNED, //uword               inum_s_flag,
		&bnd.ociNumber)      //OCINumber           *number );
	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.ociNumber),    //void         *valuep,
		C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8          value_sz,
		C.SQLT_VNU,                        //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
}
Example #28
0
func (bnd *bndFloat64Ptr) bind(value *float64, position int, stmt *Stmt) error {
	bnd.stmt = stmt
	bnd.value = value
	if value == nil {
		bnd.isNull = C.sb2(-1)
	} else {
		r := C.OCINumberFromReal(
			bnd.stmt.ses.srv.env.ocierr, //OCIError            *err,
			unsafe.Pointer(value),       //const void          *rnum,
			8,              //uword               rnum_length,
			&bnd.ociNumber) //OCINumber           *number );
		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.ociNumber),    //void         *valuep,
		C.LENGTH_TYPE(C.sizeof_OCINumber), //sb8          value_sz,
		C.SQLT_VNU,                        //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
}
Example #29
0
// Allocate a variable and define it for the given statement.
func (cur *Cursor) varDefine(numElements, position uint) (*Variable, error) {
	var param *C.OCIParam
	// retrieve parameter descriptor
	if cur.handle == nil {
		log.Printf("WARN: nil cursor handle in varDefine!")
	}
	// log.Printf("retrieve parameter descriptor cur.handle=%s pos=%d", cur.handle, position)
	if CTrace {
		ctrace("OCIParamGet(cur=%p, HTYPE_STMT, env=%p, param=%p, position=%d)",
			cur.handle, "HTYPE_STMT", cur.environment.errorHandle,
			&param, position)
	}
	if err := cur.environment.CheckStatus(
		C.OCIParamGet(unsafe.Pointer(cur.handle), C.OCI_HTYPE_STMT,
			cur.environment.errorHandle,
			(*unsafe.Pointer)(unsafe.Pointer(&param)), C.ub4(position)),
		"parameter"); err != nil {
		log.Printf("NO PARAM! %s", err)
		return nil, err
	}
	// log.Printf("got param handle")

	// call the helper to do the actual work
	v, err := cur.variableDefineHelper(param, position, numElements)
	// log.Printf("variable defined err=%s nil?%s", err, err == nil)
	if CTrace {
		ctrace("OCIDescriptorFree(%p, DTYPE_PARAM)", param)
	}
	C.OCIDescriptorFree(unsafe.Pointer(param), C.OCI_DTYPE_PARAM)
	return v, err
}
Example #30
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
}