kubo / rust-oracle

Oracle driver for Rust
193 stars 43 forks source link

API to upload file as BLOB without preallocation #70

Closed mcpiroman closed 1 year ago

mcpiroman commented 1 year ago

Hi, is there any API to load file (or other stream data) without loading it entirely to memory?

Right now I do:

let mut file = File::open(&schema_file.path)?;
let mut blob = Blob::new(&conn)?;
io::copy(&mut file, &mut blob)?;
stmt.execute(&[&blob])?;

for comparison, jdbc has

void setBlob(int parameterIndex, InputStream inputStream)
kubo commented 1 year ago

is there any API to load file (or other stream data) without loading it entirely to memory?

Yes. Your example sends file contents to the server for each Blob::write inside of io::copy.

Blob::write internally calls dpiLob_writeBytes, which requires network round-trips as listed here. If Blob::write stores bytes to memory, no round-trips are required.

mcpiroman commented 1 year ago

OK, so that's why Blob::new requires &connection. I did not think that was the case as I not expect anything to be sent before execute.

Anyway, big thanks.

kubo commented 1 year ago

io::copy uses 8K buffer for non-specialized implementation. I think that it is too small for network I/O. It is better to use BufWriter::with_capacity() to increase the size.

let buffer_size = 1024 * 1024; // This is by guesswork. The proper size depends on the network environment.
let mut file = File::open(&schema_file.path)?;
let mut blob = BufWriter::with_capacity(buffer_size, Blob::new(&conn)?);
io::copy(&mut file, &mut blob)?;
blob.flush()?; // Don't forget this.
stmt.execute(&[blob.get_ref()])?;