• Home
  • Raw
  • Download

Lines Matching full:blob

1 //! Incremental BLOB I/O.
4 //! BLOB; that must be performed through SQL statements.
6 //! There are two choices for how to perform IO on a [`Blob`].
11 //! 2. A positional IO API, e.g. [`Blob::read_at`], [`Blob::write_at`] and
18 //! `Blob` conforms to `std::io::Read`, `std::io::Write`, and `std::io::Seek`,
21 //! with the size of the blob. For example, when using a `BufWriter`, the
22 //! `BufWriter` will accept more data than the `Blob` will allow, so make sure
28 //! `Blob`s also offer a `pread` / `pwrite`-style positional IO api in the form
29 //! of [`Blob::read_at`], [`Blob::write_at`], [`Blob::raw_read_at`],
30 //! [`Blob::read_at_exact`], and [`Blob::raw_read_at_exact`].
39 //! - [`Blob::read_at`]
40 //! - [`Blob::raw_read_at`]
41 //! - [`Blob::read_at_exact`]
42 //! - [`Blob::raw_read_at_exact`]
58 //! the blob as is available, and return how much they were able to read.
61 //! blob already, and the exact functions are preferable if you do.
67 //! `Blob`:
72 //! 2. (Pro) `Blob`'s positional read functions don't mutate the blob in any
97 //! interface is not a perfect fit for [`Blob`], so another small set of
103 //! # use rusqlite::blob::ZeroBlob;
109 //! db.execute_batch("CREATE TABLE test_table (content BLOB);")?;
111 //! // Insert a BLOB into the `content` column of `test_table`. Note that the Blob
116 //! // Get the row id off the BLOB we just inserted.
118 //! // Open the BLOB we just inserted for IO.
119 //! let mut blob = db.blob_open(DatabaseName::Main, "test_table", "content", rowid, false)?;
121 //! // Write some data into the blob. Make sure to test that the number of bytes
123 //! // will be truncated to the size of the BLOB.
124 //! let bytes_written = blob.write(b"01234567")?;
129 //! blob.seek(SeekFrom::Start(0))?;
131 //! let bytes_read = blob.read(&mut buf[..])?;
132 //! assert_eq!(bytes_read, 10); // note we read 10 bytes because the blob has size 10
134 //! // Insert another BLOB, this time using a parameter passed in from
141 //! // given a new row ID, we can reopen the blob on that row
143 //! blob.reopen(rowid)?;
145 //! assert_eq!(blob.len(), 64);
153 //! # use rusqlite::blob::ZeroBlob;
158 //! db.execute_batch("CREATE TABLE test_table (content BLOB);")?;
159 //! // Insert a blob into the `content` column of `test_table`. Note that the Blob
163 //! // Get the row id off the blob we just inserted.
165 //! // Open the blob we just inserted for IO.
166 //! let mut blob = db.blob_open(DatabaseName::Main, "test_table", "content", rowid, false)?;
167 //! // Write some data into the blob.
168 //! blob.write_at(b"ABCDEF", 2)?;
170 //! // Read the whole blob into a local buffer.
172 //! blob.read_at_exact(&mut buf, 0)?;
175 //! // Insert another blob, this time using a parameter passed in from
182 //! // given a new row ID, we can reopen the blob on that row
184 //! blob.reopen(rowid)?;
185 //! assert_eq!(blob.len(), 64);
199 /// Handle to an open BLOB. See
200 /// [`rusqlite::blob`](crate::blob) documentation for in-depth discussion.
201 pub struct Blob<'conn> { struct
203 blob: *mut ffi::sqlite3_blob, field
209 /// Open a handle to the BLOB located in `row_id`,
215 /// C-compatible string or if the underlying SQLite BLOB open call
225 ) -> Result<Blob<'a>> { in blob_open() argument
227 let mut blob = ptr::null_mut(); in blob_open() localVariable
239 &mut blob, in blob_open()
242 c.decode_result(rc).map(|_| Blob { in blob_open()
244 blob, in blob_open()
250 impl Blob<'_> { implementation
251 /// Move a BLOB handle to a new row.
255 /// Will return `Err` if the underlying SQLite BLOB reopen call fails.
258 let rc = unsafe { ffi::sqlite3_blob_reopen(self.blob, row) }; in reopen()
266 /// Return the size in bytes of the BLOB.
270 unsafe { ffi::sqlite3_blob_bytes(self.blob) } in size()
273 /// Return the current size in bytes of the BLOB.
281 /// Return true if the BLOB is empty.
288 /// Close a BLOB handle.
290 /// Calling `close` explicitly is not required (the BLOB will be closed
291 /// when the `Blob` is dropped), but it is available so you can get any
304 let rc = unsafe { ffi::sqlite3_blob_close(self.blob) }; in close_()
305 self.blob = ptr::null_mut(); in close_()
310 impl io::Read for Blob<'_> { implementation
311 /// Read data from a BLOB incrementally. Will return Ok(0) if the end of
312 /// the blob has been reached.
324 let rc = unsafe { ffi::sqlite3_blob_read(self.blob, buf.as_mut_ptr().cast(), n, self.pos) }; in read()
335 impl io::Write for Blob<'_> { implementation
336 /// Write data into a BLOB incrementally. Will return `Ok(0)` if the end of
337 /// the blob has been reached; consider using `Write::write_all(buf)`
341 /// This function may only modify the contents of the BLOB; it is not
342 /// possible to increase the size of a BLOB using this API.
354 let rc = unsafe { ffi::sqlite3_blob_write(self.blob, buf.as_ptr() as *mut _, n, self.pos) }; in write()
370 impl io::Seek for Blob<'_> { implementation
371 /// Seek to an offset, in bytes, in BLOB.
388 "invalid seek to position past end of blob", in seek()
398 impl Drop for Blob<'_> { implementation
405 /// BLOB of length N that is filled with zeroes.
408 /// later written using incremental BLOB I/O routines.
410 /// A negative value for the zeroblob results in a zero-length BLOB.
430 CREATE TABLE test (content BLOB); in db_with_test_blob()
442 let mut blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, false)?; in test_blob() localVariable
443 assert_eq!(4, blob.write(b"Clob").unwrap()); in test_blob()
444 assert_eq!(6, blob.write(b"567890xxxxxx").unwrap()); // cannot write past 10 in test_blob()
445 assert_eq!(0, blob.write(b"5678").unwrap()); // still cannot write past 10 in test_blob()
447 blob.reopen(rowid)?; in test_blob()
448 blob.close()?; in test_blob()
450 blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, true)?; in test_blob()
452 assert_eq!(5, blob.read(&mut bytes[..]).unwrap()); in test_blob()
454 assert_eq!(5, blob.read(&mut bytes[..]).unwrap()); in test_blob()
456 assert_eq!(0, blob.read(&mut bytes[..]).unwrap()); in test_blob()
458 blob.seek(SeekFrom::Start(2)).unwrap(); in test_blob()
459 assert_eq!(5, blob.read(&mut bytes[..]).unwrap()); in test_blob()
463 blob.seek(SeekFrom::Current(-1)).unwrap(); in test_blob()
464 assert_eq!(4, blob.read(&mut bytes[..]).unwrap()); in test_blob()
467 blob.seek(SeekFrom::End(-6)).unwrap(); in test_blob()
468 assert_eq!(5, blob.read(&mut bytes[..]).unwrap()); in test_blob()
471 blob.reopen(rowid)?; in test_blob()
472 assert_eq!(5, blob.read(&mut bytes[..]).unwrap()); in test_blob()
476 assert!(blob.seek(SeekFrom::Current(-20)).is_err()); in test_blob()
477 assert!(blob.seek(SeekFrom::End(0)).is_ok()); in test_blob()
478 assert!(blob.seek(SeekFrom::Current(1)).is_err()); in test_blob()
482 blob.reopen(rowid)?; in test_blob()
483 assert!(blob.write_all(b"0123456789x").is_err()); in test_blob()
491 let mut blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, false)?; in test_blob_in_bufreader() localVariable
492 assert_eq!(8, blob.write(b"one\ntwo\n").unwrap()); in test_blob_in_bufreader()
494 blob.reopen(rowid)?; in test_blob_in_bufreader()
495 let mut reader = BufReader::new(blob); in test_blob_in_bufreader()
516 let blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, false)?; in test_blob_in_bufwriter() localVariable
517 let mut writer = BufWriter::new(blob); in test_blob_in_bufwriter()
527 let mut blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, false)?; in test_blob_in_bufwriter() localVariable
529 assert_eq!(10, blob.read(&mut bytes[..]).unwrap()); in test_blob_in_bufwriter()
534 let blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, false)?; in test_blob_in_bufwriter() localVariable
535 let mut writer = BufWriter::new(blob); in test_blob_in_bufwriter()
544 let mut blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, false)?; in test_blob_in_bufwriter() localVariable
546 assert_eq!(10, blob.read(&mut bytes[..]).unwrap()); in test_blob_in_bufwriter()