Exemple #1
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 #2
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 #3
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
}