Example #1
0
// 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
}
Example #2
0
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
}