Exemple #1
0
// intervalVarSetValue sets the value of the variable.
func intervalVarSetValue(v *Variable, pos uint, value interface{}) error {
	var days, hours, minutes, seconds, microseconds C.sb4

	x, ok := value.(time.Duration)
	if !ok {
		return fmt.Errorf("requires time.Duration, got %T", value)
	}

	days = C.sb4(x.Hours()) / 24
	hours = C.sb4(x.Hours()) - days*24
	minutes = C.sb4(x.Minutes() - x.Hours()*60)
	seconds = C.sb4(x.Seconds()-x.Minutes()) * 60
	microseconds = C.sb4(float64(x.Nanoseconds()/1000) - x.Seconds()*1000*1000)
	if CTrace {
		ctrace("OCIIntervalSetDaySecond(env=%p, err=%p, days=%d, hours=%d, min=%d, sec=%d, micro=%d, handle=%p)",
			v.environment.handle,
			v.environment.errorHandle,
			days, hours, minutes, seconds, microseconds,
			v.getHandle(pos))
	}
	return v.environment.CheckStatus(
		C.OCIIntervalSetDaySecond(unsafe.Pointer(v.environment.handle),
			v.environment.errorHandle,
			days, hours, minutes, seconds, microseconds,
			getIntervalHandle(v, pos)),
		"IntervalSetDaySecond")
}
Exemple #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
}
Exemple #3
0
// beginRow allocates a handle for each column and fetches one row.
func (rset *Rset) beginRow() (err error) {
	rset.log(_drv.cfg.Log.Rset.BeginRow)
	rset.Index++
	// check is open
	if rset.ocistmt == nil {
		return errF("Rset is closed")
	}
	// allocate define descriptor handles
	for _, define := range rset.defs {
		//glog.Infof("Rset.define: ", define)
		rset.logF(_drv.cfg.Log.Rset.BeginRow, "%#v", define)
		err := define.alloc()
		if err != nil {
			return err
		}
	}
	// fetch one row
	r := C.OCIStmtFetch2(
		rset.ocistmt,                 //OCIStmt     *stmthp,
		rset.stmt.ses.srv.env.ocierr, //OCIError    *errhp,
		C.ub4(1),                     //ub4         nrows,
		C.OCI_FETCH_NEXT,             //ub2         orientation,
		C.sb4(0),                     //sb4         fetchOffset,
		C.OCI_DEFAULT)                //ub4         mode );
	if r == C.OCI_ERROR {
		return rset.stmt.ses.srv.env.ociError()
	} else if r == C.OCI_NO_DATA {
		// Adjust Index so that Len() returns correct value when all rows read
		rset.Index--
		// return io.EOF to conform with database/sql/driver
		return io.EOF
	}
	return nil
}
Exemple #4
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
}
Exemple #5
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
}
Exemple #6
0
//   Set the value of the variable.
func internalVar_SetValue(v *Variable, pos uint, value interface{}) error {
	var days, hours, minutes, seconds, microseconds C.sb4

	x, ok := value.(time.Duration)
	if !ok {
		return fmt.Errorf("requires time.Duration, got %T", value)
	}

	days = C.sb4(x.Hours()) / 24
	hours = C.sb4(x.Hours()) - days*24
	minutes = C.sb4(x.Minutes() - x.Hours()*60)
	seconds = C.sb4(x.Seconds()-x.Minutes()) * 60
	microseconds = C.sb4(float64(x.Nanoseconds()/1000) - x.Seconds()*1000*1000)
	return v.environment.CheckStatus(
		C.OCIIntervalSetDaySecond(unsafe.Pointer(v.environment.handle),
			v.environment.errorHandle,
			days, hours, minutes, seconds, microseconds,
			(*C.OCIInterval)(unsafe.Pointer(&v.dataBytes[pos*v.typ.size]))),
		"IntervalSetDaySecond")
}
Exemple #7
0
// OpenSrv connects to an Oracle server returning a *Srv and possible error.
func (env *Env) OpenSrv(cfg *SrvCfg) (srv *Srv, err error) {
	env.mu.Lock()
	defer env.mu.Unlock()
	env.log(_drv.cfg.Log.Env.OpenSrv)
	err = env.checkClosed()
	if err != nil {
		return nil, errE(err)
	}
	if cfg == nil {
		return nil, er("Parameter 'cfg' may not be nil.")
	}
	// allocate server handle
	ocisrv, err := env.allocOciHandle(C.OCI_HTYPE_SERVER)
	if err != nil {
		return nil, errE(err)
	}
	// attach to server
	cDblink := C.CString(cfg.Dblink)
	defer C.free(unsafe.Pointer(cDblink))
	r := C.OCIServerAttach(
		(*C.OCIServer)(ocisrv),                //OCIServer     *srvhp,
		env.ocierr,                            //OCIError      *errhp,
		(*C.OraText)(unsafe.Pointer(cDblink)), //const OraText *dblink,
		C.sb4(len(cfg.Dblink)),                //sb4           dblink_len,
		C.OCI_DEFAULT)                         //ub4           mode);
	if r == C.OCI_ERROR {
		return nil, errE(env.ociError())
	}
	// allocate service context handle
	ocisvcctx, err := env.allocOciHandle(C.OCI_HTYPE_SVCCTX)
	if err != nil {
		return nil, errE(err)
	}
	// set server handle onto service context handle
	err = env.setAttr(ocisvcctx, C.OCI_HTYPE_SVCCTX, ocisrv, C.ub4(0), C.OCI_ATTR_SERVER)
	if err != nil {
		return nil, errE(err)
	}

	srv = _drv.srvPool.Get().(*Srv) // set *Srv
	srv.env = env
	srv.ocisrv = (*C.OCIServer)(ocisrv)
	srv.ocisvcctx = (*C.OCISvcCtx)(ocisvcctx)
	if srv.id == 0 {
		srv.id = _drv.srvId.nextId()
	}
	srv.cfg = *cfg
	if srv.cfg.StmtCfg == nil && srv.env.cfg.StmtCfg != nil {
		srv.cfg.StmtCfg = &(*srv.env.cfg.StmtCfg) // copy by value so that user may change independently
	}
	env.openSrvs.add(srv)

	return srv, nil
}
Exemple #8
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
}
Exemple #9
0
func (s *OCI8Stmt) Query(args []driver.Value) (rows driver.Rows, err error) {
	var (
		fbp []oci8bind
	)

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

	defer freeBoundParameters(fbp)

	iter := C.ub4(1)
	if retUb2 := C.WrapOCIAttrGetUb2(s.s, C.OCI_HTYPE_STMT, C.OCI_ATTR_STMT_TYPE, (*C.OCIError)(s.c.err)); retUb2.rv != C.OCI_SUCCESS {
		return nil, ociGetError(s.c.err)
	} else if retUb2.num == C.OCI_STMT_SELECT {
		iter = 0
	}

	// set the row prefetch.  Only one extra row per fetch will be returned unless this is set.
	if prefetch_size := C.ub4(s.c.attrs.Get("prefetch_rows").(int)); prefetch_size > 0 {
		if rv := C.WrapOCIAttrSetUb4(s.s, C.OCI_HTYPE_STMT, prefetch_size, C.OCI_ATTR_PREFETCH_ROWS, (*C.OCIError)(s.c.err)); rv != C.OCI_SUCCESS {
			return nil, ociGetError(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
	if prefetch_memory := C.ub4(s.c.attrs.Get("prefetch_memory").(int64)); prefetch_memory > 0 {
		if rv := C.WrapOCIAttrSetUb4(s.s, C.OCI_HTYPE_STMT, prefetch_memory, C.OCI_ATTR_PREFETCH_MEMORY, (*C.OCIError)(s.c.err)); rv != C.OCI_SUCCESS {
			return nil, ociGetError(s.c.err)
		}
	}

	mode := C.ub4(C.OCI_DEFAULT)
	if !s.c.inTransaction {
		mode = mode | C.OCI_COMMIT_ON_SUCCESS
	}
	if rv := C.OCIStmtExecute(
		(*C.OCISvcCtx)(s.c.svc),
		(*C.OCIStmt)(s.s),
		(*C.OCIError)(s.c.err),
		iter,
		0,
		nil,
		nil,
		mode); rv != C.OCI_SUCCESS {
		return nil, ociGetError(s.c.err)
	}

	var rc int
	if retUb2 := C.WrapOCIAttrGetUb2(s.s, C.OCI_HTYPE_STMT, C.OCI_ATTR_PARAM_COUNT, (*C.OCIError)(s.c.err)); retUb2.rv != C.OCI_SUCCESS {
		return nil, ociGetError(s.c.err)
	} else {
		rc = int(retUb2.num)
	}

	oci8cols := make([]oci8col, rc)
	for i := 0; i < rc; i++ {
		var p unsafe.Pointer
		var tp C.ub2
		var lp C.ub2

		if rp := C.WrapOCIParamGet(s.s, C.OCI_HTYPE_STMT, (*C.OCIError)(s.c.err), C.ub4(i+1)); rp.rv != C.OCI_SUCCESS {
			return nil, ociGetError(s.c.err)
		} else {
			p = rp.ptr
		}

		if tpr := C.WrapOCIAttrGetUb2(p, C.OCI_DTYPE_PARAM, C.OCI_ATTR_DATA_TYPE, (*C.OCIError)(s.c.err)); tpr.rv != C.OCI_SUCCESS {
			return nil, ociGetError(s.c.err)
		} else {
			tp = tpr.num
		}

		if nsr := C.WrapOCIAttrGetString(p, C.OCI_DTYPE_PARAM, C.OCI_ATTR_NAME, (*C.OCIError)(s.c.err)); nsr.rv != C.OCI_SUCCESS {
			return nil, ociGetError(s.c.err)
		} else {
			oci8cols[i].name = string((*[1 << 30]byte)(unsafe.Pointer(nsr.ptr))[0:int(nsr.size)])
		}

		if lpr := C.WrapOCIAttrGetUb2(p, C.OCI_DTYPE_PARAM, C.OCI_ATTR_DATA_SIZE, (*C.OCIError)(s.c.err)); lpr.rv != C.OCI_SUCCESS {
			return nil, ociGetError(s.c.err)
		} else {
			lp = lpr.num
		}
		/*
			var (
				defp *C.OCIDefine
			)
		*/
		*s.defp = nil
		switch tp {

		case C.SQLT_CHR, C.SQLT_AFC, C.SQLT_VCS, C.SQLT_AVC:
			// TODO: transfer as clob, read all bytes in loop
			// lp *= 4 // utf8 enc
			oci8cols[i].kind = C.SQLT_CHR  // tp
			oci8cols[i].size = int(lp) * 4 // utf8 enc
			oci8cols[i].pbuf = C.malloc(C.size_t(oci8cols[i].size) + 1)

		case C.SQLT_BIN:
			oci8cols[i].kind = C.SQLT_BIN
			oci8cols[i].size = int(lp)
			oci8cols[i].pbuf = C.malloc(C.size_t(oci8cols[i].size))

		case C.SQLT_NUM:
			oci8cols[i].kind = C.SQLT_CHR
			oci8cols[i].size = int(lp * 4)
			oci8cols[i].pbuf = C.malloc(C.size_t(oci8cols[i].size) + 1)

		case C.SQLT_IBDOUBLE, C.SQLT_IBFLOAT:
			oci8cols[i].kind = C.SQLT_IBDOUBLE
			oci8cols[i].size = int(8)
			oci8cols[i].pbuf = C.malloc(8)

		case C.SQLT_CLOB, C.SQLT_BLOB:
			// allocate +io buffers + ub4
			size := int(unsafe.Sizeof(unsafe.Pointer(nil)) + unsafe.Sizeof(C.ub4(0)))
			if oci8cols[i].size < blobBufSize {
				size += blobBufSize
			} else {
				size += oci8cols[i].size
			}
			if ret := C.WrapOCIDescriptorAlloc(s.c.env, C.OCI_DTYPE_LOB, C.size_t(size)); ret.rv != C.OCI_SUCCESS {
				return nil, ociGetError(s.c.err)
			} else {

				oci8cols[i].kind = tp
				oci8cols[i].size = int(unsafe.Sizeof(unsafe.Pointer(nil)))
				oci8cols[i].pbuf = ret.extra
				*(*unsafe.Pointer)(ret.extra) = ret.ptr

			}

			//      testing
			//		case C.SQLT_DAT:
			//
			//			oci8cols[i].kind = C.SQLT_DAT
			//			oci8cols[i].size = int(lp)
			//			oci8cols[i].pbuf = C.malloc(C.size_t(lp))
			//

		case C.SQLT_TIMESTAMP, C.SQLT_DAT:
			if ret := C.WrapOCIDescriptorAlloc(s.c.env, C.OCI_DTYPE_TIMESTAMP, C.size_t(unsafe.Sizeof(unsafe.Pointer(nil)))); ret.rv != C.OCI_SUCCESS {
				return nil, ociGetError(s.c.err)
			} else {

				oci8cols[i].kind = C.SQLT_TIMESTAMP
				oci8cols[i].size = int(unsafe.Sizeof(unsafe.Pointer(nil)))
				oci8cols[i].pbuf = ret.extra
				*(*unsafe.Pointer)(ret.extra) = ret.ptr
			}

		case C.SQLT_TIMESTAMP_TZ, C.SQLT_TIMESTAMP_LTZ:
			if ret := C.WrapOCIDescriptorAlloc(s.c.env, C.OCI_DTYPE_TIMESTAMP_TZ, C.size_t(unsafe.Sizeof(unsafe.Pointer(nil)))); ret.rv != C.OCI_SUCCESS {
				return nil, ociGetError(s.c.err)
			} else {

				oci8cols[i].kind = C.SQLT_TIMESTAMP_TZ
				oci8cols[i].size = int(unsafe.Sizeof(unsafe.Pointer(nil)))
				oci8cols[i].pbuf = ret.extra
				*(*unsafe.Pointer)(ret.extra) = ret.ptr
			}

		case C.SQLT_INTERVAL_DS:
			if ret := C.WrapOCIDescriptorAlloc(s.c.env, C.OCI_DTYPE_INTERVAL_DS, C.size_t(unsafe.Sizeof(unsafe.Pointer(nil)))); ret.rv != C.OCI_SUCCESS {
				return nil, ociGetError(s.c.err)
			} else {

				oci8cols[i].kind = C.SQLT_INTERVAL_DS
				oci8cols[i].size = int(unsafe.Sizeof(unsafe.Pointer(nil)))
				oci8cols[i].pbuf = ret.extra
				*(*unsafe.Pointer)(ret.extra) = ret.ptr
			}

		case C.SQLT_INTERVAL_YM:
			if ret := C.WrapOCIDescriptorAlloc(s.c.env, C.OCI_DTYPE_INTERVAL_YM, C.size_t(unsafe.Sizeof(unsafe.Pointer(nil)))); ret.rv != C.OCI_SUCCESS {
				return nil, ociGetError(s.c.err)
			} else {

				oci8cols[i].kind = C.SQLT_INTERVAL_YM
				oci8cols[i].size = int(unsafe.Sizeof(unsafe.Pointer(nil)))
				oci8cols[i].pbuf = ret.extra
				*(*unsafe.Pointer)(ret.extra) = ret.ptr
			}

		case C.SQLT_RDD: // rowid
			lp = 40
			oci8cols[i].pbuf = C.malloc(C.size_t(lp) + 1)
			oci8cols[i].kind = C.SQLT_CHR // tp
			oci8cols[i].size = int(lp + 1)

		default:
			oci8cols[i].pbuf = C.malloc(C.size_t(lp) + 1)
			oci8cols[i].kind = C.SQLT_CHR // tp
			oci8cols[i].size = int(lp + 1)
		}

		if rv := C.OCIDefineByPos(
			(*C.OCIStmt)(s.s),
			s.defp,
			(*C.OCIError)(s.c.err),
			C.ub4(i+1),
			oci8cols[i].pbuf,
			C.sb4(oci8cols[i].size),
			oci8cols[i].kind,
			unsafe.Pointer(&oci8cols[i].ind),
			&oci8cols[i].rlen,
			nil,
			C.OCI_DEFAULT); rv != C.OCI_SUCCESS {
			return nil, ociGetError(s.c.err)
		}
	}
	return &OCI8Rows{s, oci8cols, false}, nil
}
Exemple #10
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
}
Exemple #11
0
// Connect to the database.
// good minimal example: http://www.adp-gmbh.ch/ora/misc/oci/index.html
func (conn *Connection) Connect(mode int64, twophase bool /*, newPassword string*/) error {
	credentialType := C.OCI_CRED_EXT
	var (
		status C.sword
		err    error
	)
	defer func() {
		if err != nil {
			conn.Free(false)
		}
	}()

	// free handles
	conn.Free(false)
	// allocate the server handle
	if ociHandleAlloc(unsafe.Pointer(conn.environment.handle),
		C.OCI_HTYPE_SERVER,
		(*unsafe.Pointer)(unsafe.Pointer(&conn.serverHandle)),
		"Connect[allocate server handle]"); err != nil {
		return err
	}

	// attach to the server
	/*
	   if (cxBuffer_FromObject(&buffer, self->dsn,
	           self->environment->encoding) < 0)
	       return -1;
	*/

	buffer := make([]byte, max(16, len(conn.dsn), len(conn.username), len(conn.password))+1)
	copy(buffer, []byte(conn.dsn))
	buffer[len(conn.dsn)] = 0
	// dsn := C.CString(conn.dsn)
	// defer C.free(unsafe.Pointer(dsn))
	// Py_BEGIN_ALLOW_THREADS
	conn.srvMtx.Lock()
	// log.Printf("buffer=%s", buffer)
	status = C.OCIServerAttach(conn.serverHandle,
		conn.environment.errorHandle, (*C.OraText)(&buffer[0]),
		C.sb4(len(buffer)), C.OCI_DEFAULT)
	// Py_END_ALLOW_THREADS
	conn.srvMtx.Unlock()
	// cxBuffer_Clear(&buffer);
	if err = conn.environment.CheckStatus(status, "Connect[server attach]"); err != nil {
		return err
	}
	// log.Printf("attached to server %s", conn.serverHandle)

	// allocate the service context handle
	if err = ociHandleAlloc(unsafe.Pointer(conn.environment.handle),
		C.OCI_HTYPE_SVCCTX, (*unsafe.Pointer)(unsafe.Pointer(&conn.handle)),
		"Connect[allocate service context handle]"); err != nil {
		return err
	}
	// log.Printf("allocated service context handle")

	// set attribute for server handle
	if err = conn.AttrSet(C.OCI_ATTR_SERVER, unsafe.Pointer(conn.serverHandle), 0); err != nil {
		setErrAt(err, "Connect[set server handle]")
		return err
	}

	// set the internal and external names; these are needed for global
	// transactions but are limited in terms of the lengths of the strings
	if twophase {
		name := []byte("goracle")
		copy(buffer, name)
		buffer[len(name)] = 0

		if err = conn.ServerAttrSet(C.OCI_ATTR_INTERNAL_NAME,
			unsafe.Pointer(&buffer[0]), len(name)); err != nil {
			setErrAt(err, "Connect[set internal name]")
			return err
		}
		if err = conn.ServerAttrSet(C.OCI_ATTR_EXTERNAL_NAME,
			unsafe.Pointer(&buffer[0]), len(name)); err != nil {
			setErrAt(err, "Connect[set external name]")
			return err
		}
	}

	// allocate the session handle
	if err = ociHandleAlloc(unsafe.Pointer(conn.environment.handle),
		C.OCI_HTYPE_SESSION,
		(*unsafe.Pointer)(unsafe.Pointer(&conn.sessionHandle)),
		"Connect[allocate session handle]"); err != nil {
		return err
	}
	// log.Printf("allocated session handle")

	// set user name in session handle
	if conn.username != "" {
		copy(buffer, []byte(conn.username))
		buffer[len(conn.username)] = 0
		credentialType = C.OCI_CRED_RDBMS

		if err = conn.SessionAttrSet(C.OCI_ATTR_USERNAME,
			unsafe.Pointer(&buffer[0]), len(conn.username)); err != nil {
			setErrAt(err, "Connect[set user name]")
			return err
		}
		//fmt.Printf("set user name %s\n", buffer)
	}

	// set password in session handle
	if conn.password != "" {
		copy(buffer, []byte(conn.password))
		buffer[len(conn.password)] = 0
		credentialType = C.OCI_CRED_RDBMS
		if err = conn.SessionAttrSet(C.OCI_ATTR_PASSWORD,
			unsafe.Pointer(&buffer[0]), len(conn.password)); err != nil {
			setErrAt(err, "Connect[set password]")
			return err
		}
		//fmt.Printf("set password %s\n", buffer)
	}

	/*
	   #ifdef OCI_ATTR_DRIVER_NAME
	       status = OCIAttrSet(self->sessionHandle, OCI_HTYPE_SESSION,
	               (text*) DRIVER_NAME, strlen(DRIVER_NAME), OCI_ATTR_DRIVER_NAME,
	               self->environment->errorHandle);
	       if (Environment_CheckForError(self->environment, status,
	               "Connection_Connect(): set driver name") < 0)
	           return -1;

	   #endif
	*/

	// set the session handle on the service context handle
	if err = conn.AttrSet(C.OCI_ATTR_SESSION,
		unsafe.Pointer(conn.sessionHandle), 0); err != nil {
		setErrAt(err, "Connect[set session handle]")
		return err
	}

	/*
	   // if a new password has been specified, change it which will also
	   // establish the session
	   if (newPasswordObj)
	       return Connection_ChangePassword(self, self->password, newPasswordObj);
	*/

	// begin the session
	// Py_BEGIN_ALLOW_THREADS
	conn.srvMtx.Lock()
	status = C.OCISessionBegin(conn.handle, conn.environment.errorHandle,
		conn.sessionHandle, C.ub4(credentialType), C.ub4(mode))
	// Py_END_ALLOW_THREADS
	conn.srvMtx.Unlock()
	if err = conn.environment.CheckStatus(status, "Connect[begin session]"); err != nil {
		conn.sessionHandle = nil
		return err
	}

	return nil
}
Exemple #12
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
}
Exemple #13
0
// Helper routine for Variable_Define() used so that constant calls to
// OCIDescriptorFree() is not necessary.
func (cur *Cursor) variableDefineHelper(param *C.OCIParam, position, numElements uint) (v *Variable, err error) {
	var size C.ub4
	var varType *VariableType

	// determine data type
	varType, err = varTypeByOracleDescriptor(param, cur.environment)
	if err != nil {
		log.Printf("error determining data type: %s", err)
		return nil, err
	}
	// if (cursor->numbersAsStrings && varType == &vt_Float)
	//     varType = &vt_NumberAsString;

	// retrieve size of the parameter
	size = C.ub4(varType.size)
	if varType.isVariableLength {
		var sizeFromOracle C.ub2
		// determine the maximum length from Oracle
		if _, err = cur.environment.AttrGet(
			unsafe.Pointer(param), C.OCI_HTYPE_DESCRIBE,
			C.OCI_ATTR_DATA_SIZE, unsafe.Pointer(&sizeFromOracle),
			"data size"); err != nil {
			log.Printf("error getting data size: %+v", err)
			return nil, err
		}
		if CTrace {
			log.Printf("size of %p[%s] @ %d: %d", param, varType, position, sizeFromOracle)
		}

		// use the length from Oracle directly if available
		if uint(sizeFromOracle) > 0 {
			size = C.ub4(sizeFromOracle)
		} else if cur.outputSize >= 0 {
			// otherwise, use the value set with the setoutputsize() parameter
			if cur.outputSizeColumn < 0 ||
				int(position) == cur.outputSizeColumn {
				size = C.ub4(cur.outputSize)
			}
		}
	}

	// create a variable of the correct type
	/*
	   if cur.outputTypeHandler && cursor->outputTypeHandler != Py_None)
	       var = Variable_NewByOutputTypeHandler(cursor, param,
	               cursor->outputTypeHandler, varType, size, numElements);
	   else if (cursor->connection->outputTypeHandler &&
	           cursor->connection->outputTypeHandler != Py_None)
	       var = Variable_NewByOutputTypeHandler(cursor, param,
	               cursor->connection->outputTypeHandler, varType, size,
	               numElements);
	   else
	*/
	//log.Printf("varType=%#v size=%d", varType, size)
	v, err = cur.NewVariable(numElements, varType, uint(size))
	if err != nil {
		return nil, errgo.Newf("error creating variable: %s", err)
	}

	// call the procedure to set values prior to define
	if v.typ.preDefine != nil {
		if err = v.typ.preDefine(v, param); err != nil {
			return nil, errgo.Newf("error with preDefine(%s): %s", v, err)
		}
	}

	// perform the define
	//log.Printf("v=%#v", v)
	indic, aL, rC := v.aLrC()
	if CTrace {
		ctrace("OCIDefineByPos(cur=%p, defineHandle=%p, env=%p, position=%d, dataArr=%v, bufferSize=%d, oracleType=%d indicator=%v, aL=%v rC=%v, DEFAULT)",
			cur.handle, &v.defineHandle, v.environment.errorHandle,
			position, v.getDataArr(), v.bufferSize, v.typ.oracleType, v.indicator,
			aL, rC)
	}
	if err = cur.environment.CheckStatus(
		C.OCIDefineByPos(cur.handle,
			&v.defineHandle,
			v.environment.errorHandle, C.ub4(position), v.getDataArr(),
			C.sb4(v.bufferSize), v.typ.oracleType,
			indic, aL, rC, C.OCI_DEFAULT),
		"define"); err != nil {
		return nil, errgo.Newf("error defining: %s", err)
	}

	// call the procedure to set values after define
	if v.typ.postDefine != nil {
		if err = v.typ.postDefine(v); err != nil {
			return nil, errgo.Newf("error with postDefine(%s): %s", v, err)
		}
	}

	return v, nil
}
Exemple #14
0
func (s *OCI8Stmt) Query(args []driver.Value) (driver.Rows, error) {
	if err := s.bind(args); err != nil {
		return nil, err
	}

	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
	}

	rv := C.OCIStmtExecute(
		(*C.OCIServer)(s.c.svc),
		(*C.OCIStmt)(s.s),
		(*C.OCIError)(s.c.err),
		iter,
		0,
		nil,
		nil,
		OCI_MODE)
	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))
		oci8cols[i].name = string((*[1 << 30]byte)(unsafe.Pointer(np))[0:int(ns)])
		oci8cols[i].kind = int(tp)
		oci8cols[i].size = int(lp)
		oci8cols[i].pbuf = make([]byte, int(lp)+1)

		var defp *C.OCIDefine
		rv = C.OCIDefineByPos(
			(*C.OCIStmt)(s.s),
			&defp,
			(*C.OCIError)(s.c.err),
			C.ub4(i+1),
			unsafe.Pointer(&oci8cols[i].pbuf[0]),
			C.sb4(lp+1),
			C.SQLT_CHR,
			nil,
			nil,
			nil,
			OCI_MODE)
		if rv == C.OCI_ERROR {
			return nil, ociGetError(s.c.err)
		}
	}
	return &OCI8Rows{s, oci8cols, false}, nil
}
Exemple #15
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
}
Exemple #16
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
}
Exemple #17
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
	}

	// set safe defaults
	conn.attrs = make(Values)
	conn.attrs.Set("prefetch_rows", 10)
	conn.attrs.Set("prefetch_memory", int64(0))

	for k, v := range parseEnviron(os.Environ()) {
		conn.attrs.Set(k, v)
	}

	/*
		OCI_ENV_NO_MUTEX - No mutual exclusion (mutex) locking occurs in this mode.
		All OCI calls done on the environment handle,
		or on handles derived from the environment handle, must be serialized.
		OCI_THREADED must also be specified when OCI_ENV_NO_MUTEX is specified.
	*/
	rv := C.OCIEnvCreate(
		(**C.OCIEnv)(unsafe.Pointer(&conn.env)),
		C.OCI_THREADED|C.OCI_ENV_NO_MUTEX,
		nil,
		nil,
		nil,
		nil,
		0,
		nil)
	if err := conn.check(rv, "Open.OCIEnvCreate"); err != nil {
		return nil, err
	}

	rv = C.OCIHandleAlloc(
		conn.env,
		&conn.err,
		C.OCI_HTYPE_ERROR,
		0,
		nil)
	if err := conn.check(rv, "Open.OCIHandleAlloc conn.err"); err != nil {
		return nil, err
	}
	rv = C.OCIHandleAlloc(
		conn.env,
		&conn.srv,
		C.OCI_HTYPE_SERVER,
		0,
		nil)
	if err := conn.check(rv, "Open.OCIHandleAlloc conn.srv"); err != nil {
		return nil, err
	}

	var phost *C.char
	if dsn.Host != "" {
		phost = C.CString(fmt.Sprintf("%s:%d/%s", dsn.Host, dsn.Port, dsn.SID))
	} else {
		phost = C.CString(dsn.SID)
	}
	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))

	rv = C.OCIServerAttach(
		(*C.OCIServer)(conn.srv),
		(*C.OCIError)(conn.err),
		(*C.OraText)(unsafe.Pointer(phost)),
		C.sb4(C.strlen(phost)),
		0,
	)

	if err := conn.check(rv, "Open.OCIServerAttach"); err != nil {
		return nil, err
	}

	rv = C.OCIHandleAlloc(
		conn.env,
		&conn.svc,
		C.OCI_HTYPE_SVCCTX,
		0,
		nil)

	if err := conn.check(rv, "Open.OCIHandleAlloc conn.svc"); err != nil {
		return nil, err
	}

	rv = C.OCIAttrSet(
		conn.svc,
		C.OCI_HTYPE_SVCCTX,
		conn.srv,
		0,
		C.OCI_ATTR_SERVER,
		(*C.OCIError)(conn.err),
	)

	if err := conn.check(rv, "Open.OCIAttrSet - srv"); err != nil {
		return nil, err
	}

	rv = C.OCIHandleAlloc(
		conn.env,
		&conn.usr,
		C.OCI_HTYPE_SESSION,
		0,
		nil,
	)
	if err := conn.check(rv, "Open.OCIHandleAlloc - usr"); err != nil {
		return nil, err
	}

	rv = C.OCIAttrSet(
		conn.usr,
		C.OCI_HTYPE_SESSION,
		unsafe.Pointer(puser),
		C.ub4(C.strlen(puser)),
		C.OCI_ATTR_USERNAME,
		(*C.OCIError)(conn.err),
	)

	if err := conn.check(rv, "Open.OCIAttrSet - user"); err != nil {
		return nil, err
	}

	rv = C.OCIAttrSet(
		conn.usr,
		C.OCI_HTYPE_SESSION,
		unsafe.Pointer(ppass),
		C.ub4(C.strlen(ppass)),
		C.OCI_ATTR_PASSWORD,
		(*C.OCIError)(conn.err),
	)
	if err := conn.check(rv, "Open.OCIAttrSet - ppass"); err != nil {
		return nil, err
	}

	rv = C.OCISessionBegin(
		(*C.OCISvcCtx)(conn.svc),
		(*C.OCIError)(conn.err),
		(*C.OCISession)(conn.usr),
		C.OCI_CRED_RDBMS,
		C.OCI_DEFAULT,
	)
	if err := conn.check(rv, "Open.OCISessionBegin"); err != nil {
		return nil, err
	}

	rv = C.OCIAttrSet(
		conn.svc,
		C.OCI_HTYPE_SVCCTX,
		conn.usr,
		0,
		C.OCI_ATTR_SESSION,
		(*C.OCIError)(conn.err),
	)

	if err := conn.check(rv, "Open.OCIAttrSet svc"); err != nil {
		return nil, err
	}

	conn.location = dsn.Location
	conn.logDebug = dsn.LogDebug
	conn.logBadConn = dsn.LogBadConn

	return &conn, nil
}
Exemple #18
0
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
}
Exemple #19
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
}
func (s *StatementOracle) Next() (err int) {

	if !s.fetchDone {
		s.hDefine = new(C.OCIDefine)
		res := C.OCIStmtExecute(s.con.driver.hService, s.hStatement, s.con.driver.hError, 0, 0, nil, nil, C.OCI_DEFAULT)
		if C.OCI_SUCCESS != res && C.OCI_STILL_EXECUTING != res {
			fmt.Printf("Resultado OCIStmtExecute=%v\n", res)
			C.AuxOCIErrorGet(s.con.driver.hError)
			return -1
		}
		s.fetchDone = true
		/*
		    var idValue int
		    res = C.OCIDefineByPos( s.hStatement, &s.hDefine, s.con.driver.hError, 1 /*pos* /, unsafe.Pointer(&idValue), C.sb4(unsafe.Sizeof(idValue)), C.SQLT_INT, nil, nil, nil, C.OCI_DEFAULT);
		    if (C.OCI_SUCCESS != res /*&& C.OCI_STILL_EXECUTING != res* /) {
		 		fmt.Printf( "Resultado OCIDefineByPos=%v\n", res)
		     	C.AuxOCIErrorGet( s.con.driver.hError);
		     	return -2
		    }
		    var surnameValue [40]C.char
		    res = C.OCIDefineByPos( s.hStatement, &s.hDefine, s.con.driver.hError, 2 /*pos* /, unsafe.Pointer(&surnameValue[0]), C.sb4(unsafe.Sizeof(surnameValue)), C.SQLT_STR, nil, nil, nil, C.OCI_DEFAULT);
		    if (C.OCI_SUCCESS != res /*&& C.OCI_STILL_EXECUTING != res* /) {
		 		fmt.Printf( "Resultado OCIDefineByPos=%v\n", res)
		     	C.AuxOCIErrorGet( s.con.driver.hError);
		     	return -3
		    }
		*/
		res = C.OCIAttrGet(unsafe.Pointer(s.hStatement), C.OCI_HTYPE_STMT, unsafe.Pointer(&s.numColumns), nil, C.OCI_ATTR_PARAM_COUNT, s.con.driver.hError)
		if C.OCI_SUCCESS != res /*&& C.OCI_STILL_EXECUTING != res*/ {
			fmt.Printf("Resultado OCIAttrGet=%v\n", res)
			C.AuxOCIErrorGet(s.con.driver.hError)
			return -3
		}
		fmt.Printf("numColumns=%v\n", s.numColumns)

		s.columns = make([]*ColumnOracle, 0, 50)
		var hColumn C.ub4
		pColumn := unsafe.Pointer(&hColumn)
		for i := 1; i <= s.numColumns; i++ {
			/* get parameter for column i */
			res = C.OCIParamGet(unsafe.Pointer(s.hStatement), C.OCI_HTYPE_STMT, s.con.driver.hError, &pColumn, C.ub4(i))
			if C.OCI_SUCCESS != res /*&& C.OCI_STILL_EXECUTING != res*/ {
				fmt.Printf("Resultado OCIParamGet=%v\n", res)
				C.AuxOCIErrorGet(s.con.driver.hError)
				return -4
			}

			/* get data-type of column i */
			var columnType C.ub2
			pType := unsafe.Pointer(&columnType)
			res = C.OCIAttrGet(pColumn, C.OCI_DTYPE_PARAM, pType, nil, C.OCI_ATTR_DATA_TYPE, s.con.driver.hError)
			if C.OCI_SUCCESS != res /*&& C.OCI_STILL_EXECUTING != res*/ {
				fmt.Printf("Resultado OCIParamGet=%v\n", res)
				C.AuxOCIErrorGet(s.con.driver.hError)
				return -4
			}

			size := C.ub4(100)
			var column_name_tmp *C.char
			res = C.OCIAttrGet(pColumn, C.OCI_DTYPE_PARAM, unsafe.Pointer(&column_name_tmp), nil, C.OCI_ATTR_NAME, s.con.driver.hError)
			fmt.Printf("coumnName (size=%v) = %v\n", size, column_name_tmp)
			//column_name_tmp[size] = 0
			columnName := C.GoString(column_name_tmp)
			var columnSize int
			res = C.OCIAttrGet(pColumn, C.OCI_DTYPE_PARAM, unsafe.Pointer(&columnSize), nil, C.OCI_ATTR_DATA_SIZE, s.con.driver.hError)

			fmt.Printf("Column:%v Name:%v Size:%v Type:%v\n", i, columnName, columnSize, columnType)

			switch columnType {
			case C.SQLT_CHR:
				var columnValue = make([]C.char, columnSize+1)

				res = C.OCIDefineByPos(s.hStatement, &s.hDefine, s.con.driver.hError, C.ub4(i), /*pos*/
					unsafe.Pointer(&columnValue[0]), C.sb4(columnSize), columnType, nil, nil, nil, C.OCI_DEFAULT)
				if C.OCI_SUCCESS != res /*&& C.OCI_STILL_EXECUTING != res*/ {
					fmt.Printf("Resultado OCIDefineByPos=%v\n", res)
					C.AuxOCIErrorGet(s.con.driver.hError)
					return -2
				}
				s.columns = append(s.columns, NewColumnChrOracle(s, columnName, int(columnSize), columnValue))

			case C.SQLT_NUM:
				var columnValue int

				res = C.OCIDefineByPos(s.hStatement, &s.hDefine, s.con.driver.hError, C.ub4(i), /*pos*/
					unsafe.Pointer(&columnValue), C.sb4(4 /*sizeof(columnValue)*/), columnType, nil, nil, nil, C.OCI_DEFAULT)
				if C.OCI_SUCCESS != res /*&& C.OCI_STILL_EXECUTING != res*/ {
					fmt.Printf("Resultado OCIDefineByPos=%v\n", res)
					C.AuxOCIErrorGet(s.con.driver.hError)
					return -2
				}
				s.columns = append(s.columns, NewColumnNumberOracle(s, columnName, int(columnSize), columnValue))

			//case C.SQLT_LNG:
			//case C.SQLT_RID:
			//case C.SQLT_DAT:
			//case C.SQLT_BIN:
			//case C.SQLT_LBI:
			//case C.SQLT_AFC:
			//case C.SQLT_REF:
			//case C.SQLT_CLOB:
			//case C.SQLT_BLOB:
			//case C.SQLT_BFILEE:
			//case C.SQLT_TIMESTAMP:
			//case C.SQLT_TIME_TZ:
			//case C.SQLT_INTERVAL_YM:
			//case C.SQLT_INTERVAL_DS:
			//case C.SQLT_TIMESTAMP_LTZ:
			//case C.SQLT_RDD:
			default:
				s.columns = append(s.columns, NewColumnUnknownOracle(s, columnName, int(columnSize), int(columnType)))
			}
			fmt.Printf("Next len(stmt.columns)=%v\n", len(s.columns))
		}
		//return 0
	}

	res := C.OCIStmtFetch2(s.hStatement, s.con.driver.hError, 1 /*nrows*/, C.OCI_FETCH_NEXT, 0, C.OCI_DEFAULT)
	if C.OCI_SUCCESS != res && C.OCI_NO_DATA != res {
		fmt.Printf("Resultado OCIStmtFetch2=%v\n", res)
		C.AuxOCIErrorGet(s.con.driver.hError)
		return -4
	} else if C.OCI_NO_DATA == res {
		//fmt.Printf( "The result is:%v-%v\n", idValue, C.GoString(&surnameValue[0]))
		return 0
	}
	return 1
}
Exemple #21
0
// Exec executes a query that may return rows, such as SELECT.
func (stmt *statement) Query(v []driver.Value) (driver.Rows, error) {
	if err := stmt.bind(v); err != nil {
		return nil, err
	}

	// determine the type of statement.  For select statements iter is set to zero, for other statements, only execute once.
	// * NOTE * Should an error be returned if the statement is a non-select type?
	var stmt_type C.int
	if C.OCIAttrGet(stmt.handle, C.OCI_HTYPE_STMT, unsafe.Pointer(&stmt_type), nil, C.OCI_ATTR_STMT_TYPE, (*C.OCIError)(stmt.conn.err)) != C.OCI_SUCCESS {
		log.Println(ociGetError(stmt.conn.err))
	}
	iter := C.ub4(1)
	if stmt_type == C.OCI_STMT_SELECT {
		iter = 0
	}
	// set the row prefetch.  Only one extra row per fetch will be returned unless this is set.
	prefetchSize := C.ub4(100)
	if C.OCIAttrSet(stmt.handle, C.OCI_HTYPE_STMT, unsafe.Pointer(&prefetchSize), 0, C.OCI_ATTR_PREFETCH_ROWS, (*C.OCIError)(stmt.conn.err)) != C.OCI_SUCCESS {
		log.Println(ociGetError(stmt.conn.err))
	}

	// execute the statement
	if C.OCIStmtExecute((*C.OCIServer)(stmt.conn.svr), (*C.OCIStmt)(stmt.handle), (*C.OCIError)(stmt.conn.err), iter, 0, nil, nil, C.OCI_DEFAULT) != C.OCI_SUCCESS {
		err := ociGetError(stmt.conn.err)
		log.Println(err)
		return nil, err
	}

	// find out how many output columns there are
	var cols C.ub2
	if C.OCIAttrGet(stmt.handle, C.OCI_HTYPE_STMT, unsafe.Pointer(&cols), nil, C.OCI_ATTR_PARAM_COUNT, (*C.OCIError)(stmt.conn.err)) != C.OCI_SUCCESS {
		err := ociGetError(stmt.conn.err)
		log.Println(err)
		return nil, err
	}

	// build column meta-data
	columns := make([]column, int(cols))
	for pos := 0; pos < int(cols); pos++ {
		col := &columns[pos]
		var param unsafe.Pointer
		var colType C.ub2
		var colSize C.ub4
		var colName *C.char
		var nameSize C.ub4

		if C.OCIParamGet(stmt.handle, C.OCI_HTYPE_STMT, (*C.OCIError)(stmt.conn.err), (*unsafe.Pointer)(unsafe.Pointer(&param)), C.ub4(pos+1)) != C.OCI_SUCCESS {
			err := ociGetError(stmt.conn.err)
			log.Println(err)
			return nil, err
		}

		C.OCIAttrGet(param, C.OCI_DTYPE_PARAM, unsafe.Pointer(&colType), nil, C.OCI_ATTR_DATA_TYPE, (*C.OCIError)(stmt.conn.err))
		C.OCIAttrGet(param, C.OCI_DTYPE_PARAM, unsafe.Pointer(&colName), &nameSize, C.OCI_ATTR_NAME, (*C.OCIError)(stmt.conn.err))
		C.OCIAttrGet(param, C.OCI_DTYPE_PARAM, unsafe.Pointer(&colSize), nil, C.OCI_ATTR_DATA_SIZE, (*C.OCIError)(stmt.conn.err))

		col.kind = int(colType)
		col.size = int(colSize)
		col.name = C.GoStringN(colName, (C.int)(nameSize))
		col.raw = make([]byte, int(colSize+1))

		var def *C.OCIDefine
		result := C.OCIDefineByPos((*C.OCIStmt)(stmt.handle), &def, (*C.OCIError)(stmt.conn.err),
			C.ub4(pos+1), unsafe.Pointer(&col.raw[0]), C.sb4(colSize+1), C.SQLT_CHR, nil, nil, nil, C.OCI_DEFAULT)
		if result != C.OCI_SUCCESS {
			return nil, ociGetError(stmt.conn.err)
		}
	}

	return &rows{stmt, columns}, nil
}
Exemple #22
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
}