mirror of
https://github.com/isar/rusqlite.git
synced 2024-11-23 09:09:19 +08:00
Expand comments.
This commit is contained in:
parent
900c241c4e
commit
d24968db15
71
src/blob.rs
71
src/blob.rs
@ -1,4 +1,52 @@
|
|||||||
//! incremental BLOB I/O
|
//! Incremental BLOB I/O.
|
||||||
|
//!
|
||||||
|
//! Note that SQLite does not provide API-level access to change the size of a BLOB; that must
|
||||||
|
//! be performed through SQL statements.
|
||||||
|
//!
|
||||||
|
//! `Blob` conforms to `std::io::Read`, `std::io::Write`, and `std::io::Seek`, so it plays
|
||||||
|
//! nicely with other types that build on these (such as `std::io::BufReader` and
|
||||||
|
//! `std::io::BufWriter`). However, you must be careful with the size of the blob. For example,
|
||||||
|
//! when using a `BufWriter`, the `BufWriter` will accept more data than the `Blob` will allow,
|
||||||
|
//! so make sure to call `flush` and check for errors. (See the unit tests in this module for
|
||||||
|
//! an example.)
|
||||||
|
//!
|
||||||
|
//! ## Example
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! extern crate libsqlite3_sys;
|
||||||
|
//! extern crate rusqlite;
|
||||||
|
//!
|
||||||
|
//! use rusqlite::{Connection, DatabaseName};
|
||||||
|
//! use std::io::{Read, Write, Seek, SeekFrom};
|
||||||
|
//!
|
||||||
|
//! fn main() {
|
||||||
|
//! let db = Connection::open_in_memory().unwrap();
|
||||||
|
//! db.execute_batch("CREATE TABLE test (content BLOB);").unwrap();
|
||||||
|
//! db.execute("INSERT INTO test (content) VALUES (ZEROBLOB(10))", &[]).unwrap();
|
||||||
|
//!
|
||||||
|
//! let rowid = db.last_insert_rowid();
|
||||||
|
//! let mut blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, false).unwrap();
|
||||||
|
//!
|
||||||
|
//! // Make sure to test that the number of bytes written matches what you expect;
|
||||||
|
//! // if you try to write too much, the data will be truncated to the size of the BLOB.
|
||||||
|
//! let bytes_written = blob.write(b"01234567").unwrap();
|
||||||
|
//! assert_eq!(bytes_written, 8);
|
||||||
|
//!
|
||||||
|
//! // Same guidance - make sure you check the number of bytes read!
|
||||||
|
//! blob.seek(SeekFrom::Start(0)).unwrap();
|
||||||
|
//! let mut buf = [0u8; 20];
|
||||||
|
//! let bytes_read = blob.read(&mut buf[..]).unwrap();
|
||||||
|
//! assert_eq!(bytes_read, 10); // note we read 10 bytes because the blob has size 10
|
||||||
|
//!
|
||||||
|
//! db.execute("INSERT INTO test (content) VALUES (ZEROBLOB(64))", &[]).unwrap();
|
||||||
|
//!
|
||||||
|
//! // given a new row ID, we can reopen the blob on that row
|
||||||
|
//! let rowid = db.last_insert_rowid();
|
||||||
|
//! blob.reopen(rowid).unwrap();
|
||||||
|
//!
|
||||||
|
//! assert_eq!(blob.size(), 64);
|
||||||
|
//! }
|
||||||
|
//! ```
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
@ -7,7 +55,7 @@ use std::ptr;
|
|||||||
use super::ffi;
|
use super::ffi;
|
||||||
use {Result, Connection, DatabaseName};
|
use {Result, Connection, DatabaseName};
|
||||||
|
|
||||||
/// Handle to an open BLOB
|
/// Handle to an open BLOB.
|
||||||
pub struct Blob<'conn> {
|
pub struct Blob<'conn> {
|
||||||
conn: &'conn Connection,
|
conn: &'conn Connection,
|
||||||
blob: *mut ffi::sqlite3_blob,
|
blob: *mut ffi::sqlite3_blob,
|
||||||
@ -19,8 +67,8 @@ impl Connection {
|
|||||||
///
|
///
|
||||||
/// # Failure
|
/// # Failure
|
||||||
///
|
///
|
||||||
/// Will return `Err` if `db`/`table`/`column` cannot be converted to a C-compatible string or if the
|
/// Will return `Err` if `db`/`table`/`column` cannot be converted to a C-compatible string
|
||||||
/// underlying SQLite BLOB open call fails.
|
/// or if the underlying SQLite BLOB open call fails.
|
||||||
pub fn blob_open<'a>(&'a self,
|
pub fn blob_open<'a>(&'a self,
|
||||||
db: DatabaseName,
|
db: DatabaseName,
|
||||||
table: &str,
|
table: &str,
|
||||||
@ -57,7 +105,7 @@ impl Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'conn> Blob<'conn> {
|
impl<'conn> Blob<'conn> {
|
||||||
/// Move a BLOB handle to a new row
|
/// Move a BLOB handle to a new row.
|
||||||
///
|
///
|
||||||
/// # Failure
|
/// # Failure
|
||||||
///
|
///
|
||||||
@ -71,12 +119,15 @@ impl<'conn> Blob<'conn> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the size in bytes of the BLOB
|
/// Return the size in bytes of the BLOB.
|
||||||
pub fn size(&self) -> i32 {
|
pub fn size(&self) -> i32 {
|
||||||
unsafe { ffi::sqlite3_blob_bytes(self.blob) }
|
unsafe { ffi::sqlite3_blob_bytes(self.blob) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Close a BLOB handle
|
/// Close a BLOB handle.
|
||||||
|
///
|
||||||
|
/// Calling `close` explicitly is not required (the BLOB will be closed when the
|
||||||
|
/// `Blob` is dropped), but it is available so you can get any errors that occur.
|
||||||
///
|
///
|
||||||
/// # Failure
|
/// # Failure
|
||||||
///
|
///
|
||||||
@ -93,7 +144,8 @@ impl<'conn> Blob<'conn> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'conn> io::Read for Blob<'conn> {
|
impl<'conn> io::Read for Blob<'conn> {
|
||||||
/// Read data from a BLOB incrementally
|
/// Read data from a BLOB incrementally. Will return Ok(0) if the end of the blob
|
||||||
|
/// has been reached.
|
||||||
///
|
///
|
||||||
/// # Failure
|
/// # Failure
|
||||||
///
|
///
|
||||||
@ -118,7 +170,8 @@ impl<'conn> io::Read for Blob<'conn> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'conn> io::Write for Blob<'conn> {
|
impl<'conn> io::Write for Blob<'conn> {
|
||||||
/// Write data into a BLOB incrementally
|
/// Write data into a BLOB incrementally. Will return `Ok(0)` if the end of the blob
|
||||||
|
/// has been reached.
|
||||||
///
|
///
|
||||||
/// This function may only modify the contents of the BLOB; it is not possible to increase
|
/// This function may only modify the contents of the BLOB; it is not possible to increase
|
||||||
/// the size of a BLOB using this API.
|
/// the size of a BLOB using this API.
|
||||||
|
Loading…
Reference in New Issue
Block a user