// WriteAt writes data in p into the LOB, starting at off. func (lrw *lobReadWriter) WriteAt(p []byte, off int64) (n int, err error) { //Log.Infof("LobWrite2 off=%d len=%d", off, n) byte_amtp := C.oraub8(len(p)) // Write to Oracle if C.OCILobWrite2( lrw.ses.ocisvcctx, //OCISvcCtx *svchp, lrw.ses.srv.env.ocierr, //OCIError *errhp, lrw.ociLobLocator, //OCILobLocator *locp, &byte_amtp, //oraub8 *byte_amtp, nil, //oraub8 *char_amtp, C.oraub8(off)+1, //oraub8 offset, starting position is 1 unsafe.Pointer(&p[0]), //void *bufp, C.oraub8(len(p)), C.OCI_ONE_PIECE, //ub1 piece, nil, //void *ctxp, nil, //OCICallbackLobWrite2 (cbfp) C.ub2(0), //ub2 csid, C.SQLCS_IMPLICIT, //ub1 csfrm ); //fmt.Printf("r %v, current %v, buffer %v\n", r, current, buffer) //fmt.Printf("C.OCI_NEED_DATA %v, C.OCI_SUCCESS %v\n", C.OCI_NEED_DATA, C.OCI_SUCCESS) ) == C.OCI_ERROR { return 0, lrw.ses.srv.env.ociError() } if C.oraub8(off)+byte_amtp > lrw.size { lrw.size = C.oraub8(off) + byte_amtp } return int(byte_amtp), nil }
func writeLob(ociLobLocator *C.OCILobLocator, stmt *Stmt, r io.Reader, lobBufferSize int) error { var actBuf, nextBuf []byte if lobChunkSize >= lobBufferSize { arr := lobChunkPool.Get().([lobChunkSize]byte) defer lobChunkPool.Put(arr) actBuf = arr[:lobBufferSize] arr = lobChunkPool.Get().([lobChunkSize]byte) defer lobChunkPool.Put(arr) nextBuf = arr[:lobBufferSize] } else { actBuf = make([]byte, lobBufferSize) nextBuf = make([]byte, lobBufferSize) } // write bytes to lob locator - at once, as we already have all bytes in memory var n int var byte_amtp, off C.oraub8 var actPiece, nextPiece C.ub1 = C.OCI_FIRST_PIECE, C.OCI_NEXT_PIECE // OCILobWrite2 doesn't support writing zero bytes // nor is writing 1 byte and erasing the one byte supported // therefore, throw an error var err error if n, err = io.ReadFull(r, actBuf); err != nil { switch err { case io.EOF: // no bytes read return errNew("writing a zero-length BLOB is unsupported") case io.ErrUnexpectedEOF: actPiece = C.OCI_ONE_PIECE default: return err } actBuf = actBuf[:n] } for { n = len(actBuf) if n == lobBufferSize { var n2 int if n2, err = io.ReadFull(r, nextBuf[:]); err != nil { switch err { case io.EOF: // no bytes read, lobSize == len(buffer[0]) if actPiece == C.OCI_FIRST_PIECE { actPiece = C.OCI_ONE_PIECE } else { actPiece = C.OCI_LAST_PIECE } case io.ErrUnexpectedEOF: nextPiece = C.OCI_LAST_PIECE default: return err } nextBuf = nextBuf[:n2] } } //Log.Infof("LobWrite2 off=%d len=%d piece=%d", off, n, actPiece) byte_amtp = 0 if actPiece == C.OCI_ONE_PIECE { byte_amtp = C.oraub8(n) } // Write to Oracle if C.OCILobWrite2( stmt.ses.srv.ocisvcctx, //OCISvcCtx *svchp, stmt.ses.srv.env.ocierr, //OCIError *errhp, ociLobLocator, //OCILobLocator *locp, &byte_amtp, //oraub8 *byte_amtp, nil, //oraub8 *char_amtp, off+1, //oraub8 offset, starting position is 1 unsafe.Pointer(&actBuf[0]), //void *bufp, C.oraub8(n), actPiece, //ub1 piece, nil, //void *ctxp, nil, //OCICallbackLobWrite2 (cbfp) C.ub2(0), //ub2 csid, C.SQLCS_IMPLICIT, //ub1 csfrm ); //fmt.Printf("r %v, current %v, buffer %v\n", r, current, buffer) //fmt.Printf("C.OCI_NEED_DATA %v, C.OCI_SUCCESS %v\n", C.OCI_NEED_DATA, C.OCI_SUCCESS) ) == C.OCI_ERROR { return stmt.ses.srv.env.ociError() } off += byte_amtp if actPiece == C.OCI_LAST_PIECE || actPiece == C.OCI_ONE_PIECE { break } actPiece, actBuf = nextPiece, nextBuf } return nil }