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 }
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") }
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 }
// 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 }
// 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 }
// 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(¶m)), 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 }
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 }
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 }
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 }