Example #1
0
func (c *OCI8Conn) Begin() (driver.Tx, error) {
	if c.transactionMode != C.OCI_TRANS_READWRITE {
		var th unsafe.Pointer
		if rv := C.WrapOCIHandleAlloc(
			c.env,
			C.OCI_HTYPE_TRANS,
			0); rv.rv != C.OCI_SUCCESS {
			return nil, errors.New("can't allocate handle")
		} else {
			th = rv.ptr
		}
		if rv := C.OCIAttrSet(
			c.svc,
			C.OCI_HTYPE_SVCCTX,
			th,
			0,
			C.OCI_ATTR_TRANS,
			(*C.OCIError)(c.err)); rv != C.OCI_SUCCESS {
			return nil, ociGetError(c.err)
		}

		if rv := C.OCITransStart(
			(*C.OCISvcCtx)(c.svc),
			(*C.OCIError)(c.err),
			0,
			c.transactionMode); // C.OCI_TRANS_SERIALIZABLE C.OCI_TRANS_READWRITE C.OCI_TRANS_READONLY
		rv != C.OCI_SUCCESS {
			return nil, ociGetError(c.err)
		}
	}
	c.inTransaction = true
	return &OCI8Tx{c}, nil
}
Example #2
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 #3
0
func (conn *OCI8Conn) Begin() (driver.Tx, error) {
	if conn.inTx {
		return nil, errors.New("transaction already in progress")
	}

	var txHandle unsafe.Pointer
	// determine if a transaction handle was previously allocated
	rv := C.OCIAttrGet(
		conn.svc,
		C.OCI_HTYPE_SVCCTX,
		unsafe.Pointer(&txHandle),
		nil,
		C.OCI_ATTR_TRANS,
		(*C.OCIError)(conn.err),
	)
	if err := conn.check(rv, "OCI8Conn.Begin() find existing transaction handle"); err != nil {
		return nil, err
	}
	if txHandle == nil {
		rv := C.OCIHandleAlloc(
			conn.env,
			&txHandle,
			C.OCI_HTYPE_TRANS,
			0,
			nil,
		)
		if err := conn.check(rv, "OCI8Conn.Begin() allocate transaction handle"); err != nil {
			return nil, err
		}
	}
	rv = C.OCIAttrSet(
		conn.svc,
		C.OCI_HTYPE_SVCCTX,
		txHandle,
		0,
		C.OCI_ATTR_TRANS,
		(*C.OCIError)(conn.err),
	)
	if err := conn.check(rv, "OCI8Conn.Begin(): associate transaction"); err != nil {
		return nil, err
	}

	rv = C.OCITransStart(
		(*C.OCISvcCtx)(conn.svc),
		(*C.OCIError)(conn.err),
		60,
		C.OCI_TRANS_NEW,
	)
	if err := conn.check(rv, "OCI8Conn.Begin(): start transaction"); err != nil {
		return nil, err
	}

	conn.inTx = true

	return conn, nil
}
Example #4
0
// setAttr sets an attribute on the statement handle. No locking occurs.
func (stmt *Stmt) setAttr(attrup unsafe.Pointer, attrSize C.ub4, attrType C.ub4) error {
	r := C.OCIAttrSet(
		unsafe.Pointer(stmt.ocistmt), //void        *trgthndlp,
		C.OCI_HTYPE_STMT,             //ub4         trghndltyp,
		attrup,                       //void        *attributep,
		attrSize,                     //ub4         size,
		attrType,                     //ub4         attrtype,
		stmt.ses.srv.env.ocierr)      //OCIError    *errhp );
	if r == C.OCI_ERROR {
		return errE(stmt.ses.srv.env.ociError())
	}

	return nil
}
Example #5
0
File: env.go Project: optimuse/ora
// setOciAttribute sets an attribute value on a handle or descriptor. No locking occurs.
func (env *Env) setAttr(
	target unsafe.Pointer,
	targetType C.ub4,
	attribute unsafe.Pointer,
	attributeSize C.ub4,
	attributeType C.ub4) (err error) {

	r := C.OCIAttrSet(
		target,        //void        *trgthndlp,
		targetType,    //ub4         trghndltyp,
		attribute,     //void        *attributep,
		attributeSize, //ub4         size,
		attributeType, //ub4         attrtype,
		env.ocierr)    //OCIError    *errhp );
	if r == C.OCI_ERROR {
		return errE(env.ociError())
	}
	return nil
}
Example #6
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
}
Example #7
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
}
Example #8
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
}
Example #9
0
func (d *DriverOracle) NewConnection(tns string, username string, password string) (c *ConnectionOracle, err int) {
	fmt.Printf("username=%v, password=%v, tns=%v\n", username, password, tns)
	fmt.Println("Connecting to Oracle...")

	c = new(ConnectionOracle)
	pServer := unsafe.Pointer(&c.hServer)
	res := C.OCIHandleAlloc(unsafe.Pointer(d.hEnv), (*unsafe.Pointer)(pServer), C.OCI_HTYPE_SERVER, 0, nil)
	if C.OCI_SUCCESS != res && C.OCI_STILL_EXECUTING != res {
		fmt.Printf("Resultado3=%v\n", res)
		return nil, 4
	}
	pTns := C.CString(tns)
	defer C.free(unsafe.Pointer(pTns))
	//    C.Printw (pTns);
	res = C.AuxOCIServerAttach(c.hServer, d.hError, pTns)
	if C.OCI_SUCCESS != res && C.OCI_STILL_EXECUTING != res {
		fmt.Printf("Resultado OCIServerAttach=%v\n", res)
		C.AuxOCIErrorGet(d.hError)
		return nil, 5
	}

	res = C.OCIAttrSet(unsafe.Pointer(d.hService), C.OCI_HTYPE_SVCCTX, unsafe.Pointer(c.hServer), 0, C.OCI_ATTR_SERVER, d.hError)
	if C.OCI_SUCCESS != res && C.OCI_STILL_EXECUTING != res {
		fmt.Printf("Resultado OCIAttrSet SERVICE-SERVER=%v\n", res)
		C.AuxOCIErrorGet(d.hError)
		return nil, 6
	}

	var test [1000]C.OraText
	res = C.OCIServerVersion(unsafe.Pointer(c.hServer), d.hError, &test[0], C.ub4(len(test)), C.OCI_HTYPE_SERVER)
	if C.OCI_SUCCESS != res && C.OCI_STILL_EXECUTING != res {
		fmt.Printf("Resultado OCIServerVersion=%v\n", res)
		C.AuxOCIErrorGet(d.hError)
		return nil, 7
	}
	fmt.Printf("Version=%s\n", test)

	pSession := unsafe.Pointer(&c.hSession)
	res = C.OCIHandleAlloc(unsafe.Pointer(d.hEnv), (*unsafe.Pointer)(pSession), C.OCI_HTYPE_SESSION, 0, nil)
	if C.OCI_SUCCESS != res && C.OCI_STILL_EXECUTING != res {
		fmt.Printf("Resultado hSession=%v\n", res)
		return nil, 8
	}
	pUsername := unsafe.Pointer(C.CString(username))
	defer C.free(pUsername)
	res = C.OCIAttrSet(unsafe.Pointer(c.hSession), C.OCI_HTYPE_SESSION, pUsername, C.ub4(len(username)), C.OCI_ATTR_USERNAME, d.hError)
	if C.OCI_SUCCESS != res && C.OCI_STILL_EXECUTING != res {
		fmt.Printf("Resultado OCIAttrSet USERNAME=%v\n", res)
		return nil, 9
	}
	cPassword := C.CString(password)
	//    pPassword := unsafe.Pointer(C.CString(password))
	pPassword := unsafe.Pointer(cPassword)
	defer C.free(pPassword)
	res = C.OCIAttrSet(unsafe.Pointer(c.hSession), C.OCI_HTYPE_SESSION, pPassword, C.ub4(len(password)), C.OCI_ATTR_PASSWORD, d.hError)
	if C.OCI_SUCCESS != res && C.OCI_STILL_EXECUTING != res {
		fmt.Printf("Resultado OCIAttrSet PASSWORD=%v\n", res)
		return nil, 10
	}
	res = C.OCISessionBegin(d.hService, d.hError, c.hSession, C.OCI_CRED_RDBMS, C.OCI_DEFAULT)
	if C.OCI_SUCCESS != res && C.OCI_STILL_EXECUTING != res {
		fmt.Printf("Resultado OCIAttrSet SessionBegin=%v\n", res)
		C.AuxOCIErrorGet(d.hError)
		return nil, 11
	}
	res = C.OCIAttrSet(unsafe.Pointer(d.hService), C.OCI_HTYPE_SVCCTX, unsafe.Pointer(c.hSession), 0, C.OCI_ATTR_SESSION, d.hError)
	if C.OCI_SUCCESS != res && C.OCI_STILL_EXECUTING != res {
		fmt.Printf("Resultado OCIAttrSet Service<-Session=%v\n", res)
		C.AuxOCIErrorGet(d.hError)
		return nil, 12
	}
	fmt.Printf("End NewConnection\n")

	c.driver = d
	return c, 0
}