// Cancel executes an OCIBreak() to cause an immediate (asynchronous) abort of any // currently executing OCI function. func (conn *Connection) Cancel() error { // make sure we are actually connected if !conn.IsConnected() { return nil } // perform the break return conn.environment.CheckStatus(C.OCIBreak(unsafe.Pointer(conn.handle), conn.environment.errorHandle), "Cancel") }
// Break stops the currently running OCI function. func (ses *Ses) Break() (err error) { ses.mu.Lock() defer ses.mu.Unlock() ses.log(_drv.cfg.Log.Ses.Break) err = ses.checkClosed() if err != nil { return errE(err) } r := C.OCIBreak(unsafe.Pointer(ses.ocisvcctx), ses.srv.env.ocierr) if r == C.OCI_ERROR { return errE(ses.srv.env.ociError()) } return nil }
func (s *OCI8Stmt) exec(ctx context.Context, args []namedValue) (r driver.Result, err error) { var ( fbp []oci8bind ) if fbp, err = s.bind(args); err != nil { return nil, err } defer freeBoundParameters(fbp) mode := C.ub4(C.OCI_DEFAULT) if s.c.inTransaction == false { mode = mode | C.OCI_COMMIT_ON_SUCCESS } done := make(chan struct{}) defer close(done) go func() { select { case <-ctx.Done(): C.OCIBreak( unsafe.Pointer(s.c.svc), (*C.OCIError)(s.c.err)) case <-done: } }() rv := C.OCIStmtExecute( (*C.OCISvcCtx)(s.c.svc), (*C.OCIStmt)(s.s), (*C.OCIError)(s.c.err), 1, 0, nil, nil, mode) if rv != C.OCI_SUCCESS { return nil, ociGetError(rv, s.c.err) } n, en := s.rowsAffected() var id int64 var ei error if n > 0 { id, ei = s.lastInsertId() } return &OCI8Result{s: s, n: n, errn: en, id: id, errid: ei}, nil }
func (s *OCI8Stmt) query(ctx context.Context, args []namedValue) (driver.Rows, error) { var ( fbp []oci8bind err error ) if fbp, err = s.bind(args); err != nil { return nil, err } defer freeBoundParameters(fbp) iter := C.ub4(1) if retUb2 := C.WrapOCIAttrGetUb2(s.s, C.OCI_HTYPE_STMT, C.OCI_ATTR_STMT_TYPE, (*C.OCIError)(s.c.err)); retUb2.rv != C.OCI_SUCCESS { return nil, ociGetError(retUb2.rv, s.c.err) } else if retUb2.num == C.OCI_STMT_SELECT { iter = 0 } // set the row prefetch. Only one extra row per fetch will be returned unless this is set. if s.c.prefetch_rows > 0 { if rv := C.WrapOCIAttrSetUb4(s.s, C.OCI_HTYPE_STMT, C.ub4(s.c.prefetch_rows), C.OCI_ATTR_PREFETCH_ROWS, (*C.OCIError)(s.c.err)); rv != C.OCI_SUCCESS { return nil, ociGetError(rv, 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 if s.c.prefetch_memory > 0 { if rv := C.WrapOCIAttrSetUb4(s.s, C.OCI_HTYPE_STMT, C.ub4(s.c.prefetch_memory), C.OCI_ATTR_PREFETCH_MEMORY, (*C.OCIError)(s.c.err)); rv != C.OCI_SUCCESS { return nil, ociGetError(rv, s.c.err) } } mode := C.ub4(C.OCI_DEFAULT) if !s.c.inTransaction { mode = mode | C.OCI_COMMIT_ON_SUCCESS } if rv := C.OCIStmtExecute( (*C.OCISvcCtx)(s.c.svc), (*C.OCIStmt)(s.s), (*C.OCIError)(s.c.err), iter, 0, nil, nil, mode); rv != C.OCI_SUCCESS { return nil, ociGetError(rv, s.c.err) } var rc int if retUb2 := C.WrapOCIAttrGetUb2(s.s, C.OCI_HTYPE_STMT, C.OCI_ATTR_PARAM_COUNT, (*C.OCIError)(s.c.err)); retUb2.rv != C.OCI_SUCCESS { return nil, ociGetError(retUb2.rv, s.c.err) } else { rc = int(retUb2.num) } oci8cols := make([]oci8col, rc) indrlenptr := C.calloc(C.size_t(rc), C.sizeof_indrlen) indrlen := (*[1 << 16]C.indrlen)(indrlenptr)[0:rc] for i := 0; i < rc; i++ { var p unsafe.Pointer var tp C.ub2 var lp C.ub2 if rp := C.WrapOCIParamGet(s.s, C.OCI_HTYPE_STMT, (*C.OCIError)(s.c.err), C.ub4(i+1)); rp.rv != C.OCI_SUCCESS { return nil, ociGetError(rp.rv, s.c.err) } else { p = rp.ptr } if tpr := C.WrapOCIAttrGetUb2(p, C.OCI_DTYPE_PARAM, C.OCI_ATTR_DATA_TYPE, (*C.OCIError)(s.c.err)); tpr.rv != C.OCI_SUCCESS { return nil, ociGetError(tpr.rv, s.c.err) } else { tp = tpr.num } if nsr := C.WrapOCIAttrGetString(p, C.OCI_DTYPE_PARAM, C.OCI_ATTR_NAME, (*C.OCIError)(s.c.err)); nsr.rv != C.OCI_SUCCESS { return nil, ociGetError(nsr.rv, s.c.err) } else { oci8cols[i].name = string((*[1 << 30]byte)(unsafe.Pointer(nsr.ptr))[0:int(nsr.size)]) } if lpr := C.WrapOCIAttrGetUb2(p, C.OCI_DTYPE_PARAM, C.OCI_ATTR_DATA_SIZE, (*C.OCIError)(s.c.err)); lpr.rv != C.OCI_SUCCESS { return nil, ociGetError(lpr.rv, s.c.err) } else { lp = lpr.num } /* var ( defp *C.OCIDefine ) */ *s.defp = nil switch tp { case C.SQLT_CHR, C.SQLT_AFC, C.SQLT_VCS, C.SQLT_AVC: // TODO: transfer as clob, read all bytes in loop // lp *= 4 // utf8 enc oci8cols[i].kind = C.SQLT_CHR // tp oci8cols[i].size = int(lp) * 4 // utf8 enc oci8cols[i].pbuf = C.malloc(C.size_t(oci8cols[i].size) + 1) case C.SQLT_BIN: oci8cols[i].kind = C.SQLT_BIN oci8cols[i].size = int(lp) oci8cols[i].pbuf = C.malloc(C.size_t(oci8cols[i].size)) case C.SQLT_NUM: oci8cols[i].kind = C.SQLT_CHR oci8cols[i].size = int(lp * 4) oci8cols[i].pbuf = C.malloc(C.size_t(oci8cols[i].size) + 1) case C.SQLT_IBDOUBLE, C.SQLT_IBFLOAT: oci8cols[i].kind = C.SQLT_IBDOUBLE oci8cols[i].size = int(8) oci8cols[i].pbuf = C.malloc(8) case C.SQLT_LNG: // allocate +io buffers + ub4 size := int(unsafe.Sizeof(unsafe.Pointer(nil)) + unsafe.Sizeof(C.ub4(0))) if oci8cols[i].size < blobBufSize { size += blobBufSize } else { size += oci8cols[i].size } if ret := C.WrapOCIDescriptorAlloc(s.c.env, C.OCI_DTYPE_LOB, C.size_t(size)); ret.rv != C.OCI_SUCCESS { return nil, ociGetError(ret.rv, s.c.err) } else { oci8cols[i].kind = tp oci8cols[i].size = size oci8cols[i].pbuf = ret.extra *(*unsafe.Pointer)(ret.extra) = ret.ptr } case C.SQLT_CLOB, C.SQLT_BLOB: // allocate +io buffers + ub4 size := int(unsafe.Sizeof(unsafe.Pointer(nil)) + unsafe.Sizeof(C.ub4(0))) if oci8cols[i].size < blobBufSize { size += blobBufSize } else { size += oci8cols[i].size } if ret := C.WrapOCIDescriptorAlloc(s.c.env, C.OCI_DTYPE_LOB, C.size_t(size)); ret.rv != C.OCI_SUCCESS { return nil, ociGetError(ret.rv, s.c.err) } else { oci8cols[i].kind = tp oci8cols[i].size = int(unsafe.Sizeof(unsafe.Pointer(nil))) oci8cols[i].pbuf = ret.extra *(*unsafe.Pointer)(ret.extra) = ret.ptr } // testing // case C.SQLT_DAT: // // oci8cols[i].kind = C.SQLT_DAT // oci8cols[i].size = int(lp) // oci8cols[i].pbuf = C.malloc(C.size_t(lp)) // case C.SQLT_TIMESTAMP, C.SQLT_DAT: if ret := C.WrapOCIDescriptorAlloc(s.c.env, C.OCI_DTYPE_TIMESTAMP, C.size_t(unsafe.Sizeof(unsafe.Pointer(nil)))); ret.rv != C.OCI_SUCCESS { return nil, ociGetError(ret.rv, s.c.err) } else { oci8cols[i].kind = C.SQLT_TIMESTAMP oci8cols[i].size = int(unsafe.Sizeof(unsafe.Pointer(nil))) oci8cols[i].pbuf = ret.extra *(*unsafe.Pointer)(ret.extra) = ret.ptr } case C.SQLT_TIMESTAMP_TZ, C.SQLT_TIMESTAMP_LTZ: if ret := C.WrapOCIDescriptorAlloc(s.c.env, C.OCI_DTYPE_TIMESTAMP_TZ, C.size_t(unsafe.Sizeof(unsafe.Pointer(nil)))); ret.rv != C.OCI_SUCCESS { return nil, ociGetError(ret.rv, s.c.err) } else { oci8cols[i].kind = C.SQLT_TIMESTAMP_TZ oci8cols[i].size = int(unsafe.Sizeof(unsafe.Pointer(nil))) oci8cols[i].pbuf = ret.extra *(*unsafe.Pointer)(ret.extra) = ret.ptr } case C.SQLT_INTERVAL_DS: if ret := C.WrapOCIDescriptorAlloc(s.c.env, C.OCI_DTYPE_INTERVAL_DS, C.size_t(unsafe.Sizeof(unsafe.Pointer(nil)))); ret.rv != C.OCI_SUCCESS { return nil, ociGetError(ret.rv, s.c.err) } else { oci8cols[i].kind = C.SQLT_INTERVAL_DS oci8cols[i].size = int(unsafe.Sizeof(unsafe.Pointer(nil))) oci8cols[i].pbuf = ret.extra *(*unsafe.Pointer)(ret.extra) = ret.ptr } case C.SQLT_INTERVAL_YM: if ret := C.WrapOCIDescriptorAlloc(s.c.env, C.OCI_DTYPE_INTERVAL_YM, C.size_t(unsafe.Sizeof(unsafe.Pointer(nil)))); ret.rv != C.OCI_SUCCESS { return nil, ociGetError(ret.rv, s.c.err) } else { oci8cols[i].kind = C.SQLT_INTERVAL_YM oci8cols[i].size = int(unsafe.Sizeof(unsafe.Pointer(nil))) oci8cols[i].pbuf = ret.extra *(*unsafe.Pointer)(ret.extra) = ret.ptr } case C.SQLT_RDD: // rowid lp = 40 oci8cols[i].pbuf = C.malloc(C.size_t(lp) + 1) oci8cols[i].kind = C.SQLT_CHR // tp oci8cols[i].size = int(lp + 1) default: oci8cols[i].pbuf = C.malloc(C.size_t(lp) + 1) oci8cols[i].kind = C.SQLT_CHR // tp oci8cols[i].size = int(lp + 1) } oci8cols[i].ind = &indrlen[i].ind oci8cols[i].rlen = &indrlen[i].rlen if rv := C.OCIDefineByPos( (*C.OCIStmt)(s.s), s.defp, (*C.OCIError)(s.c.err), C.ub4(i+1), oci8cols[i].pbuf, C.sb4(oci8cols[i].size), oci8cols[i].kind, unsafe.Pointer(oci8cols[i].ind), oci8cols[i].rlen, nil, C.OCI_DEFAULT); rv != C.OCI_SUCCESS { C.free(indrlenptr) return nil, ociGetError(rv, s.c.err) } } rows := &OCI8Rows{ s: s, cols: oci8cols, e: false, indrlenptr: indrlenptr, closed: false, done: make(chan struct{}), cls: false, } go func() { select { case <-ctx.Done(): C.OCIBreak( unsafe.Pointer(s.c.svc), (*C.OCIError)(s.c.err)) rows.Close() case <-rows.done: } }() return rows, nil }