// 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 }
// 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 }
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 }