// 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 }
// OpenSes opens an Oracle session returning a *Ses and possible error. func (srv *Srv) OpenSes(cfg *SesCfg) (ses *Ses, err error) { srv.mu.Lock() defer srv.mu.Unlock() srv.log(_drv.cfg.Log.Srv.OpenSes) err = srv.checkClosed() if err != nil { return nil, errE(err) } if cfg == nil { return nil, er("Parameter 'cfg' may not be nil.") } // allocate session handle ocises, err := srv.env.allocOciHandle(C.OCI_HTYPE_SESSION) if err != nil { return nil, errE(err) } credentialType := C.ub4(C.OCI_CRED_EXT) if cfg.Username != "" || cfg.Password != "" { credentialType = C.OCI_CRED_RDBMS // set username on session handle cUsername := C.CString(cfg.Username) defer C.free(unsafe.Pointer(cUsername)) err = srv.env.setAttr(ocises, C.OCI_HTYPE_SESSION, unsafe.Pointer(cUsername), C.ub4(len(cfg.Username)), C.OCI_ATTR_USERNAME) if err != nil { return nil, errE(err) } // set password on session handle cPassword := C.CString(cfg.Password) defer C.free(unsafe.Pointer(cPassword)) err = srv.env.setAttr(ocises, C.OCI_HTYPE_SESSION, unsafe.Pointer(cPassword), C.ub4(len(cfg.Password)), C.OCI_ATTR_PASSWORD) if err != nil { return nil, errE(err) } } // allocate service context handle ocisvcctx, err := srv.env.allocOciHandle(C.OCI_HTYPE_SVCCTX) if err != nil { return nil, errE(err) } // set server handle onto service context handle err = srv.env.setAttr(ocisvcctx, C.OCI_HTYPE_SVCCTX, unsafe.Pointer(srv.ocisrv), C.ub4(0), C.OCI_ATTR_SERVER) if err != nil { return nil, errE(err) } //srv.logF(true, "CRED_EXT? %t username=%q", credentialType == C.OCI_CRED_EXT, username) // set driver name on the session handle // driver name is specified to aid diagnostics; max 9 single-byte characters // driver name will be visible in V$SESSION_CONNECT_INFO or GV$SESSION_CONNECT_INFO drvName := fmt.Sprintf("GO %v", Version) cDrvName := C.CString(drvName) defer C.free(unsafe.Pointer(cDrvName)) err = srv.env.setAttr(ocises, C.OCI_HTYPE_SESSION, unsafe.Pointer(cDrvName), C.ub4(len(drvName)), C.OCI_ATTR_DRIVER_NAME) if err != nil { return nil, errE(err) } // http://docs.oracle.com/cd/B28359_01/appdev.111/b28395/oci07lob.htm#CHDDHFAB // Set LOB prefetch size to chunk size lobPrefetchSize := C.ub4(lobChunkSize) err = srv.env.setAttr(ocises, C.OCI_HTYPE_SESSION, unsafe.Pointer(&lobPrefetchSize), C.ub4(0), C.OCI_ATTR_DEFAULT_LOBPREFETCH_SIZE) if err != nil { return nil, errE(err) } // begin session r := C.OCISessionBegin( (*C.OCISvcCtx)(ocisvcctx), //OCISvcCtx *svchp, srv.env.ocierr, //OCIError *errhp, (*C.OCISession)(ocises), //OCISession *usrhp, credentialType, //ub4 credt, C.OCI_DEFAULT) //ub4 mode ); if r == C.OCI_ERROR { return nil, errE(srv.env.ociError()) } // set session handle on service context handle err = srv.env.setAttr(unsafe.Pointer(ocisvcctx), C.OCI_HTYPE_SVCCTX, ocises, C.ub4(0), C.OCI_ATTR_SESSION) if err != nil { return nil, errE(err) } // set stmt cache size to zero // https://docs.oracle.com/database/121/LNOCI/oci09adv.htm#LNOCI16655 stmtCacheSize := C.ub4(0) err = srv.env.setAttr(unsafe.Pointer(ocisvcctx), C.OCI_HTYPE_SVCCTX, unsafe.Pointer(&stmtCacheSize), C.ub4(0), C.OCI_ATTR_STMTCACHESIZE) if err != nil { return nil, errE(err) } ses = _drv.sesPool.Get().(*Ses) // set *Ses ses.srv = srv ses.ocisvcctx = (*C.OCISvcCtx)(ocisvcctx) ses.ocises = (*C.OCISession)(ocises) if ses.id == 0 { ses.id = _drv.sesId.nextId() } ses.cfg = *cfg if ses.cfg.StmtCfg == nil && ses.srv.cfg.StmtCfg != nil { ses.cfg.StmtCfg = &(*ses.srv.cfg.StmtCfg) // copy by value so that user may change independently } srv.openSess.add(ses) return ses, nil }
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 }