CLOBs, BLOBs, BFILEs
Let's assume a table was created:
CREATE TABLE lob_example (
id NUMBER GENERATED ALWAYS AS IDENTITY,
bin BLOB
);
We can then create and write data into that LOB as:
// ... create OCI environment, connect to the database, etc.
let file = BFile::new(&session)?;
file.set_file_name("MEDIA_DIR", "mousepad_comp_ad.pdf")?;
let file_len = file.len()?;
file.open_file()?;
let mut data = Vec::new();
let num_read = file.read(0, file_len, &mut data)?;
file.close_file()?;
// ... or do not close now as it will be closed
// automatically when `file` goes out of scope
// Insert new BLOB and lock its row
let stmt = session.prepare("
DECLARE
row_id ROWID;
BEGIN
INSERT INTO lob_example (bin) VALUES (Empty_Blob()) RETURNING rowid INTO row_id;
SELECT bin INTO :NEW_BLOB FROM lob_example WHERE rowid = row_id FOR UPDATE;
END;
")?;
let mut lob = BLOB::new(&session)?;
stmt.execute(&mut lob)?;
lob.open()?;
let num_bytes_written = lob.write(0, &data)?;
lob.close()?;
session.commit()?;
And then later it could be read as:
let id: usize = 1234; // assume it was retrieved from somewhere...
let stmt = session.prepare("SELECT bin FROM lob_example WHERE id = :ID")?;
let row = stmt.query_single(&id)?;
if let Some(row) = row {
if let Some(lob) = row.get(0)? {
let data = read_blob(lob)?;
// ...
}
}
// Where `read_blob` could be this:
fn read_blob(lob: BLOB<'_>) -> Result<Vec<u8>> {
let mut data = Vec::new();
let lob_len = lob.len()?;
let offset = 0;
lob.read(offset, lob_len, &mut data)?;
Ok(data)
}