mirror of
https://github.com/isar/rusqlite.git
synced 2024-11-27 03:51:38 +08:00
Merge pull request #837 from gwenn/test_result
Make tests return Result
This commit is contained in:
commit
a376ae4895
@ -310,96 +310,84 @@ impl Drop for Backup<'_, '_> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::Backup;
|
use super::Backup;
|
||||||
use crate::{Connection, DatabaseName};
|
use crate::{Connection, DatabaseName, Result};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_backup() {
|
fn test_backup() -> Result<()> {
|
||||||
let src = Connection::open_in_memory().unwrap();
|
let src = Connection::open_in_memory()?;
|
||||||
let sql = "BEGIN;
|
let sql = "BEGIN;
|
||||||
CREATE TABLE foo(x INTEGER);
|
CREATE TABLE foo(x INTEGER);
|
||||||
INSERT INTO foo VALUES(42);
|
INSERT INTO foo VALUES(42);
|
||||||
END;";
|
END;";
|
||||||
src.execute_batch(sql).unwrap();
|
src.execute_batch(sql)?;
|
||||||
|
|
||||||
let mut dst = Connection::open_in_memory().unwrap();
|
let mut dst = Connection::open_in_memory()?;
|
||||||
|
|
||||||
{
|
{
|
||||||
let backup = Backup::new(&src, &mut dst).unwrap();
|
let backup = Backup::new(&src, &mut dst)?;
|
||||||
backup.step(-1).unwrap();
|
backup.step(-1)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let the_answer: i64 = dst
|
let the_answer: i64 = dst.query_row("SELECT x FROM foo", [], |r| r.get(0))?;
|
||||||
.query_row("SELECT x FROM foo", [], |r| r.get(0))
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(42, the_answer);
|
assert_eq!(42, the_answer);
|
||||||
|
|
||||||
src.execute_batch("INSERT INTO foo VALUES(43)").unwrap();
|
src.execute_batch("INSERT INTO foo VALUES(43)")?;
|
||||||
|
|
||||||
{
|
{
|
||||||
let backup = Backup::new(&src, &mut dst).unwrap();
|
let backup = Backup::new(&src, &mut dst)?;
|
||||||
backup
|
backup.run_to_completion(5, Duration::from_millis(250), None)?;
|
||||||
.run_to_completion(5, Duration::from_millis(250), None)
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let the_answer: i64 = dst
|
let the_answer: i64 = dst.query_row("SELECT SUM(x) FROM foo", [], |r| r.get(0))?;
|
||||||
.query_row("SELECT SUM(x) FROM foo", [], |r| r.get(0))
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(42 + 43, the_answer);
|
assert_eq!(42 + 43, the_answer);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_backup_temp() {
|
fn test_backup_temp() -> Result<()> {
|
||||||
let src = Connection::open_in_memory().unwrap();
|
let src = Connection::open_in_memory()?;
|
||||||
let sql = "BEGIN;
|
let sql = "BEGIN;
|
||||||
CREATE TEMPORARY TABLE foo(x INTEGER);
|
CREATE TEMPORARY TABLE foo(x INTEGER);
|
||||||
INSERT INTO foo VALUES(42);
|
INSERT INTO foo VALUES(42);
|
||||||
END;";
|
END;";
|
||||||
src.execute_batch(sql).unwrap();
|
src.execute_batch(sql)?;
|
||||||
|
|
||||||
let mut dst = Connection::open_in_memory().unwrap();
|
let mut dst = Connection::open_in_memory()?;
|
||||||
|
|
||||||
{
|
{
|
||||||
let backup =
|
let backup =
|
||||||
Backup::new_with_names(&src, DatabaseName::Temp, &mut dst, DatabaseName::Main)
|
Backup::new_with_names(&src, DatabaseName::Temp, &mut dst, DatabaseName::Main)?;
|
||||||
.unwrap();
|
backup.step(-1)?;
|
||||||
backup.step(-1).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let the_answer: i64 = dst
|
let the_answer: i64 = dst.query_row("SELECT x FROM foo", [], |r| r.get(0))?;
|
||||||
.query_row("SELECT x FROM foo", [], |r| r.get(0))
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(42, the_answer);
|
assert_eq!(42, the_answer);
|
||||||
|
|
||||||
src.execute_batch("INSERT INTO foo VALUES(43)").unwrap();
|
src.execute_batch("INSERT INTO foo VALUES(43)")?;
|
||||||
|
|
||||||
{
|
{
|
||||||
let backup =
|
let backup =
|
||||||
Backup::new_with_names(&src, DatabaseName::Temp, &mut dst, DatabaseName::Main)
|
Backup::new_with_names(&src, DatabaseName::Temp, &mut dst, DatabaseName::Main)?;
|
||||||
.unwrap();
|
backup.run_to_completion(5, Duration::from_millis(250), None)?;
|
||||||
backup
|
|
||||||
.run_to_completion(5, Duration::from_millis(250), None)
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let the_answer: i64 = dst
|
let the_answer: i64 = dst.query_row("SELECT SUM(x) FROM foo", [], |r| r.get(0))?;
|
||||||
.query_row("SELECT SUM(x) FROM foo", [], |r| r.get(0))
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(42 + 43, the_answer);
|
assert_eq!(42 + 43, the_answer);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_backup_attached() {
|
fn test_backup_attached() -> Result<()> {
|
||||||
let src = Connection::open_in_memory().unwrap();
|
let src = Connection::open_in_memory()?;
|
||||||
let sql = "ATTACH DATABASE ':memory:' AS my_attached;
|
let sql = "ATTACH DATABASE ':memory:' AS my_attached;
|
||||||
BEGIN;
|
BEGIN;
|
||||||
CREATE TABLE my_attached.foo(x INTEGER);
|
CREATE TABLE my_attached.foo(x INTEGER);
|
||||||
INSERT INTO my_attached.foo VALUES(42);
|
INSERT INTO my_attached.foo VALUES(42);
|
||||||
END;";
|
END;";
|
||||||
src.execute_batch(sql).unwrap();
|
src.execute_batch(sql)?;
|
||||||
|
|
||||||
let mut dst = Connection::open_in_memory().unwrap();
|
let mut dst = Connection::open_in_memory()?;
|
||||||
|
|
||||||
{
|
{
|
||||||
let backup = Backup::new_with_names(
|
let backup = Backup::new_with_names(
|
||||||
@ -407,17 +395,14 @@ mod test {
|
|||||||
DatabaseName::Attached("my_attached"),
|
DatabaseName::Attached("my_attached"),
|
||||||
&mut dst,
|
&mut dst,
|
||||||
DatabaseName::Main,
|
DatabaseName::Main,
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
backup.step(-1)?;
|
||||||
backup.step(-1).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let the_answer: i64 = dst
|
let the_answer: i64 = dst.query_row("SELECT x FROM foo", [], |r| r.get(0))?;
|
||||||
.query_row("SELECT x FROM foo", [], |r| r.get(0))
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(42, the_answer);
|
assert_eq!(42, the_answer);
|
||||||
|
|
||||||
src.execute_batch("INSERT INTO foo VALUES(43)").unwrap();
|
src.execute_batch("INSERT INTO foo VALUES(43)")?;
|
||||||
|
|
||||||
{
|
{
|
||||||
let backup = Backup::new_with_names(
|
let backup = Backup::new_with_names(
|
||||||
@ -425,16 +410,12 @@ mod test {
|
|||||||
DatabaseName::Attached("my_attached"),
|
DatabaseName::Attached("my_attached"),
|
||||||
&mut dst,
|
&mut dst,
|
||||||
DatabaseName::Main,
|
DatabaseName::Main,
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
backup.run_to_completion(5, Duration::from_millis(250), None)?;
|
||||||
backup
|
|
||||||
.run_to_completion(5, Duration::from_millis(250), None)
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let the_answer: i64 = dst
|
let the_answer: i64 = dst.query_row("SELECT SUM(x) FROM foo", [], |r| r.get(0))?;
|
||||||
.query_row("SELECT SUM(x) FROM foo", [], |r| r.get(0))
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(42 + 43, the_answer);
|
assert_eq!(42 + 43, the_answer);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -434,22 +434,18 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_blob() {
|
fn test_blob() -> Result<()> {
|
||||||
let (db, rowid) = db_with_test_blob().unwrap();
|
let (db, rowid) = db_with_test_blob()?;
|
||||||
|
|
||||||
let mut blob = db
|
let mut blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, false)?;
|
||||||
.blob_open(DatabaseName::Main, "test", "content", rowid, false)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(4, blob.write(b"Clob").unwrap());
|
assert_eq!(4, blob.write(b"Clob").unwrap());
|
||||||
assert_eq!(6, blob.write(b"567890xxxxxx").unwrap()); // cannot write past 10
|
assert_eq!(6, blob.write(b"567890xxxxxx").unwrap()); // cannot write past 10
|
||||||
assert_eq!(0, blob.write(b"5678").unwrap()); // still cannot write past 10
|
assert_eq!(0, blob.write(b"5678").unwrap()); // still cannot write past 10
|
||||||
|
|
||||||
blob.reopen(rowid).unwrap();
|
blob.reopen(rowid)?;
|
||||||
blob.close().unwrap();
|
blob.close()?;
|
||||||
|
|
||||||
blob = db
|
blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, true)?;
|
||||||
.blob_open(DatabaseName::Main, "test", "content", rowid, true)
|
|
||||||
.unwrap();
|
|
||||||
let mut bytes = [0u8; 5];
|
let mut bytes = [0u8; 5];
|
||||||
assert_eq!(5, blob.read(&mut bytes[..]).unwrap());
|
assert_eq!(5, blob.read(&mut bytes[..]).unwrap());
|
||||||
assert_eq!(&bytes, b"Clob5");
|
assert_eq!(&bytes, b"Clob5");
|
||||||
@ -470,7 +466,7 @@ mod test {
|
|||||||
assert_eq!(5, blob.read(&mut bytes[..]).unwrap());
|
assert_eq!(5, blob.read(&mut bytes[..]).unwrap());
|
||||||
assert_eq!(&bytes, b"56789");
|
assert_eq!(&bytes, b"56789");
|
||||||
|
|
||||||
blob.reopen(rowid).unwrap();
|
blob.reopen(rowid)?;
|
||||||
assert_eq!(5, blob.read(&mut bytes[..]).unwrap());
|
assert_eq!(5, blob.read(&mut bytes[..]).unwrap());
|
||||||
assert_eq!(&bytes, b"Clob5");
|
assert_eq!(&bytes, b"Clob5");
|
||||||
|
|
||||||
@ -481,20 +477,19 @@ mod test {
|
|||||||
|
|
||||||
// write_all should detect when we return Ok(0) because there is no space left,
|
// write_all should detect when we return Ok(0) because there is no space left,
|
||||||
// and return a write error
|
// and return a write error
|
||||||
blob.reopen(rowid).unwrap();
|
blob.reopen(rowid)?;
|
||||||
assert!(blob.write_all(b"0123456789x").is_err());
|
assert!(blob.write_all(b"0123456789x").is_err());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_blob_in_bufreader() {
|
fn test_blob_in_bufreader() -> Result<()> {
|
||||||
let (db, rowid) = db_with_test_blob().unwrap();
|
let (db, rowid) = db_with_test_blob()?;
|
||||||
|
|
||||||
let mut blob = db
|
let mut blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, false)?;
|
||||||
.blob_open(DatabaseName::Main, "test", "content", rowid, false)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(8, blob.write(b"one\ntwo\n").unwrap());
|
assert_eq!(8, blob.write(b"one\ntwo\n").unwrap());
|
||||||
|
|
||||||
blob.reopen(rowid).unwrap();
|
blob.reopen(rowid)?;
|
||||||
let mut reader = BufReader::new(blob);
|
let mut reader = BufReader::new(blob);
|
||||||
|
|
||||||
let mut line = String::new();
|
let mut line = String::new();
|
||||||
@ -508,16 +503,15 @@ mod test {
|
|||||||
line.truncate(0);
|
line.truncate(0);
|
||||||
assert_eq!(2, reader.read_line(&mut line).unwrap());
|
assert_eq!(2, reader.read_line(&mut line).unwrap());
|
||||||
assert_eq!("\0\0", line);
|
assert_eq!("\0\0", line);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_blob_in_bufwriter() {
|
fn test_blob_in_bufwriter() -> Result<()> {
|
||||||
let (db, rowid) = db_with_test_blob().unwrap();
|
let (db, rowid) = db_with_test_blob()?;
|
||||||
|
|
||||||
{
|
{
|
||||||
let blob = db
|
let blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, false)?;
|
||||||
.blob_open(DatabaseName::Main, "test", "content", rowid, false)
|
|
||||||
.unwrap();
|
|
||||||
let mut writer = BufWriter::new(blob);
|
let mut writer = BufWriter::new(blob);
|
||||||
|
|
||||||
// trying to write too much and then flush should fail
|
// trying to write too much and then flush should fail
|
||||||
@ -528,18 +522,14 @@ mod test {
|
|||||||
|
|
||||||
{
|
{
|
||||||
// ... but it should've written the first 10 bytes
|
// ... but it should've written the first 10 bytes
|
||||||
let mut blob = db
|
let mut blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, false)?;
|
||||||
.blob_open(DatabaseName::Main, "test", "content", rowid, false)
|
|
||||||
.unwrap();
|
|
||||||
let mut bytes = [0u8; 10];
|
let mut bytes = [0u8; 10];
|
||||||
assert_eq!(10, blob.read(&mut bytes[..]).unwrap());
|
assert_eq!(10, blob.read(&mut bytes[..]).unwrap());
|
||||||
assert_eq!(b"0123456701", &bytes);
|
assert_eq!(b"0123456701", &bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let blob = db
|
let blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, false)?;
|
||||||
.blob_open(DatabaseName::Main, "test", "content", rowid, false)
|
|
||||||
.unwrap();
|
|
||||||
let mut writer = BufWriter::new(blob);
|
let mut writer = BufWriter::new(blob);
|
||||||
|
|
||||||
// trying to write_all too much should fail
|
// trying to write_all too much should fail
|
||||||
@ -549,12 +539,11 @@ mod test {
|
|||||||
|
|
||||||
{
|
{
|
||||||
// ... but it should've written the first 10 bytes
|
// ... but it should've written the first 10 bytes
|
||||||
let mut blob = db
|
let mut blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, false)?;
|
||||||
.blob_open(DatabaseName::Main, "test", "content", rowid, false)
|
|
||||||
.unwrap();
|
|
||||||
let mut bytes = [0u8; 10];
|
let mut bytes = [0u8; 10];
|
||||||
assert_eq!(10, blob.read(&mut bytes[..]).unwrap());
|
assert_eq!(10, blob.read(&mut bytes[..]).unwrap());
|
||||||
assert_eq!(b"aaaaaaaaaa", &bytes);
|
assert_eq!(b"aaaaaaaaaa", &bytes);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -194,22 +194,18 @@ impl<'conn> Blob<'conn> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::{Connection, DatabaseName};
|
use crate::{Connection, DatabaseName, Result};
|
||||||
// to ensure we don't modify seek pos
|
// to ensure we don't modify seek pos
|
||||||
use std::io::Seek as _;
|
use std::io::Seek as _;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_pos_io() {
|
fn test_pos_io() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.execute_batch("CREATE TABLE test_table(content BLOB);")
|
db.execute_batch("CREATE TABLE test_table(content BLOB);")?;
|
||||||
.unwrap();
|
db.execute("INSERT INTO test_table(content) VALUES (ZEROBLOB(10))", [])?;
|
||||||
db.execute("INSERT INTO test_table(content) VALUES (ZEROBLOB(10))", [])
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let rowid = db.last_insert_rowid();
|
let rowid = db.last_insert_rowid();
|
||||||
let mut blob = db
|
let mut blob = db.blob_open(DatabaseName::Main, "test_table", "content", rowid, false)?;
|
||||||
.blob_open(DatabaseName::Main, "test_table", "content", rowid, false)
|
|
||||||
.unwrap();
|
|
||||||
// modify the seek pos to ensure we aren't using it or modifying it.
|
// modify the seek pos to ensure we aren't using it or modifying it.
|
||||||
blob.seek(std::io::SeekFrom::Start(1)).unwrap();
|
blob.seek(std::io::SeekFrom::Start(1)).unwrap();
|
||||||
|
|
||||||
@ -274,5 +270,6 @@ mod test {
|
|||||||
|
|
||||||
let end_pos = blob.seek(std::io::SeekFrom::Current(0)).unwrap();
|
let end_pos = blob.seek(std::io::SeekFrom::Current(0)).unwrap();
|
||||||
assert_eq!(end_pos, 1);
|
assert_eq!(end_pos, 1);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
12
src/busy.rs
12
src/busy.rs
@ -86,15 +86,13 @@ mod test {
|
|||||||
use crate::{Connection, Error, ErrorCode, Result, TransactionBehavior};
|
use crate::{Connection, Error, ErrorCode, Result, TransactionBehavior};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_default_busy() {
|
fn test_default_busy() -> Result<()> {
|
||||||
let temp_dir = tempfile::tempdir().unwrap();
|
let temp_dir = tempfile::tempdir().unwrap();
|
||||||
let path = temp_dir.path().join("test.db3");
|
let path = temp_dir.path().join("test.db3");
|
||||||
|
|
||||||
let mut db1 = Connection::open(&path).unwrap();
|
let mut db1 = Connection::open(&path)?;
|
||||||
let tx1 = db1
|
let tx1 = db1.transaction_with_behavior(TransactionBehavior::Exclusive)?;
|
||||||
.transaction_with_behavior(TransactionBehavior::Exclusive)
|
let db2 = Connection::open(&path)?;
|
||||||
.unwrap();
|
|
||||||
let db2 = Connection::open(&path).unwrap();
|
|
||||||
let r: Result<()> = db2.query_row("PRAGMA schema_version", [], |_| unreachable!());
|
let r: Result<()> = db2.query_row("PRAGMA schema_version", [], |_| unreachable!());
|
||||||
match r.unwrap_err() {
|
match r.unwrap_err() {
|
||||||
Error::SqliteFailure(err, _) => {
|
Error::SqliteFailure(err, _) => {
|
||||||
@ -102,7 +100,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
err => panic!("Unexpected error {}", err),
|
err => panic!("Unexpected error {}", err),
|
||||||
}
|
}
|
||||||
tx1.rollback().unwrap();
|
tx1.rollback()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
93
src/cache.rs
93
src/cache.rs
@ -175,7 +175,7 @@ impl StatementCache {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::StatementCache;
|
use super::StatementCache;
|
||||||
use crate::Connection;
|
use crate::{Connection, Result};
|
||||||
use fallible_iterator::FallibleIterator;
|
use fallible_iterator::FallibleIterator;
|
||||||
|
|
||||||
impl StatementCache {
|
impl StatementCache {
|
||||||
@ -193,8 +193,8 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cache() {
|
fn test_cache() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let cache = &db.cache;
|
let cache = &db.cache;
|
||||||
let initial_capacity = cache.capacity();
|
let initial_capacity = cache.capacity();
|
||||||
assert_eq!(0, cache.len());
|
assert_eq!(0, cache.len());
|
||||||
@ -202,34 +202,35 @@ mod test {
|
|||||||
|
|
||||||
let sql = "PRAGMA schema_version";
|
let sql = "PRAGMA schema_version";
|
||||||
{
|
{
|
||||||
let mut stmt = db.prepare_cached(sql).unwrap();
|
let mut stmt = db.prepare_cached(sql)?;
|
||||||
assert_eq!(0, cache.len());
|
assert_eq!(0, cache.len());
|
||||||
assert_eq!(0, stmt.query_row([], |r| r.get::<_, i64>(0)).unwrap());
|
assert_eq!(0, stmt.query_row([], |r| r.get::<_, i64>(0))?);
|
||||||
}
|
}
|
||||||
assert_eq!(1, cache.len());
|
assert_eq!(1, cache.len());
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut stmt = db.prepare_cached(sql).unwrap();
|
let mut stmt = db.prepare_cached(sql)?;
|
||||||
assert_eq!(0, cache.len());
|
assert_eq!(0, cache.len());
|
||||||
assert_eq!(0, stmt.query_row([], |r| r.get::<_, i64>(0)).unwrap());
|
assert_eq!(0, stmt.query_row([], |r| r.get::<_, i64>(0))?);
|
||||||
}
|
}
|
||||||
assert_eq!(1, cache.len());
|
assert_eq!(1, cache.len());
|
||||||
|
|
||||||
cache.clear();
|
cache.clear();
|
||||||
assert_eq!(0, cache.len());
|
assert_eq!(0, cache.len());
|
||||||
assert_eq!(initial_capacity, cache.capacity());
|
assert_eq!(initial_capacity, cache.capacity());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_set_capacity() {
|
fn test_set_capacity() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let cache = &db.cache;
|
let cache = &db.cache;
|
||||||
|
|
||||||
let sql = "PRAGMA schema_version";
|
let sql = "PRAGMA schema_version";
|
||||||
{
|
{
|
||||||
let mut stmt = db.prepare_cached(sql).unwrap();
|
let mut stmt = db.prepare_cached(sql)?;
|
||||||
assert_eq!(0, cache.len());
|
assert_eq!(0, cache.len());
|
||||||
assert_eq!(0, stmt.query_row([], |r| r.get::<_, i64>(0)).unwrap());
|
assert_eq!(0, stmt.query_row([], |r| r.get::<_, i64>(0))?);
|
||||||
}
|
}
|
||||||
assert_eq!(1, cache.len());
|
assert_eq!(1, cache.len());
|
||||||
|
|
||||||
@ -237,55 +238,53 @@ mod test {
|
|||||||
assert_eq!(0, cache.len());
|
assert_eq!(0, cache.len());
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut stmt = db.prepare_cached(sql).unwrap();
|
let mut stmt = db.prepare_cached(sql)?;
|
||||||
assert_eq!(0, cache.len());
|
assert_eq!(0, cache.len());
|
||||||
assert_eq!(0, stmt.query_row([], |r| r.get::<_, i64>(0)).unwrap());
|
assert_eq!(0, stmt.query_row([], |r| r.get::<_, i64>(0))?);
|
||||||
}
|
}
|
||||||
assert_eq!(0, cache.len());
|
assert_eq!(0, cache.len());
|
||||||
|
|
||||||
db.set_prepared_statement_cache_capacity(8);
|
db.set_prepared_statement_cache_capacity(8);
|
||||||
{
|
{
|
||||||
let mut stmt = db.prepare_cached(sql).unwrap();
|
let mut stmt = db.prepare_cached(sql)?;
|
||||||
assert_eq!(0, cache.len());
|
assert_eq!(0, cache.len());
|
||||||
assert_eq!(0, stmt.query_row([], |r| r.get::<_, i64>(0)).unwrap());
|
assert_eq!(0, stmt.query_row([], |r| r.get::<_, i64>(0))?);
|
||||||
}
|
}
|
||||||
assert_eq!(1, cache.len());
|
assert_eq!(1, cache.len());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_discard() {
|
fn test_discard() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let cache = &db.cache;
|
let cache = &db.cache;
|
||||||
|
|
||||||
let sql = "PRAGMA schema_version";
|
let sql = "PRAGMA schema_version";
|
||||||
{
|
{
|
||||||
let mut stmt = db.prepare_cached(sql).unwrap();
|
let mut stmt = db.prepare_cached(sql)?;
|
||||||
assert_eq!(0, cache.len());
|
assert_eq!(0, cache.len());
|
||||||
assert_eq!(0, stmt.query_row([], |r| r.get::<_, i64>(0)).unwrap());
|
assert_eq!(0, stmt.query_row([], |r| r.get::<_, i64>(0))?);
|
||||||
stmt.discard();
|
stmt.discard();
|
||||||
}
|
}
|
||||||
assert_eq!(0, cache.len());
|
assert_eq!(0, cache.len());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ddl() {
|
fn test_ddl() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.execute_batch(
|
db.execute_batch(
|
||||||
r#"
|
r#"
|
||||||
CREATE TABLE foo (x INT);
|
CREATE TABLE foo (x INT);
|
||||||
INSERT INTO foo VALUES (1);
|
INSERT INTO foo VALUES (1);
|
||||||
"#,
|
"#,
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let sql = "SELECT * FROM foo";
|
let sql = "SELECT * FROM foo";
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut stmt = db.prepare_cached(sql).unwrap();
|
let mut stmt = db.prepare_cached(sql)?;
|
||||||
assert_eq!(
|
assert_eq!(Ok(Some(1i32)), stmt.query([])?.map(|r| r.get(0)).next());
|
||||||
Ok(Some(1i32)),
|
|
||||||
stmt.query([]).unwrap().map(|r| r.get(0)).next()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
db.execute_batch(
|
db.execute_batch(
|
||||||
@ -293,55 +292,55 @@ mod test {
|
|||||||
ALTER TABLE foo ADD COLUMN y INT;
|
ALTER TABLE foo ADD COLUMN y INT;
|
||||||
UPDATE foo SET y = 2;
|
UPDATE foo SET y = 2;
|
||||||
"#,
|
"#,
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut stmt = db.prepare_cached(sql).unwrap();
|
let mut stmt = db.prepare_cached(sql)?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok(Some((1i32, 2i32))),
|
Ok(Some((1i32, 2i32))),
|
||||||
stmt.query([])
|
stmt.query([])?.map(|r| Ok((r.get(0)?, r.get(1)?))).next()
|
||||||
.unwrap()
|
|
||||||
.map(|r| Ok((r.get(0)?, r.get(1)?)))
|
|
||||||
.next()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_connection_close() {
|
fn test_connection_close() -> Result<()> {
|
||||||
let conn = Connection::open_in_memory().unwrap();
|
let conn = Connection::open_in_memory()?;
|
||||||
conn.prepare_cached("SELECT * FROM sqlite_master;").unwrap();
|
conn.prepare_cached("SELECT * FROM sqlite_master;")?;
|
||||||
|
|
||||||
conn.close().expect("connection not closed");
|
conn.close().expect("connection not closed");
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cache_key() {
|
fn test_cache_key() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let cache = &db.cache;
|
let cache = &db.cache;
|
||||||
assert_eq!(0, cache.len());
|
assert_eq!(0, cache.len());
|
||||||
|
|
||||||
//let sql = " PRAGMA schema_version; -- comment";
|
//let sql = " PRAGMA schema_version; -- comment";
|
||||||
let sql = "PRAGMA schema_version; ";
|
let sql = "PRAGMA schema_version; ";
|
||||||
{
|
{
|
||||||
let mut stmt = db.prepare_cached(sql).unwrap();
|
let mut stmt = db.prepare_cached(sql)?;
|
||||||
assert_eq!(0, cache.len());
|
assert_eq!(0, cache.len());
|
||||||
assert_eq!(0, stmt.query_row([], |r| r.get::<_, i64>(0)).unwrap());
|
assert_eq!(0, stmt.query_row([], |r| r.get::<_, i64>(0))?);
|
||||||
}
|
}
|
||||||
assert_eq!(1, cache.len());
|
assert_eq!(1, cache.len());
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut stmt = db.prepare_cached(sql).unwrap();
|
let mut stmt = db.prepare_cached(sql)?;
|
||||||
assert_eq!(0, cache.len());
|
assert_eq!(0, cache.len());
|
||||||
assert_eq!(0, stmt.query_row([], |r| r.get::<_, i64>(0)).unwrap());
|
assert_eq!(0, stmt.query_row([], |r| r.get::<_, i64>(0))?);
|
||||||
}
|
}
|
||||||
assert_eq!(1, cache.len());
|
assert_eq!(1, cache.len());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_empty_stmt() {
|
fn test_empty_stmt() -> Result<()> {
|
||||||
let conn = Connection::open_in_memory().unwrap();
|
let conn = Connection::open_in_memory()?;
|
||||||
conn.prepare_cached("").unwrap();
|
conn.prepare_cached("")?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,26 +171,24 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_unicase() {
|
fn test_unicase() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
|
|
||||||
db.create_collation("unicase", unicase_compare).unwrap();
|
db.create_collation("unicase", unicase_compare)?;
|
||||||
|
|
||||||
collate(db);
|
collate(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collate(db: Connection) {
|
fn collate(db: Connection) -> Result<()> {
|
||||||
db.execute_batch(
|
db.execute_batch(
|
||||||
"CREATE TABLE foo (bar);
|
"CREATE TABLE foo (bar);
|
||||||
INSERT INTO foo (bar) VALUES ('Maße');
|
INSERT INTO foo (bar) VALUES ('Maße');
|
||||||
INSERT INTO foo (bar) VALUES ('MASSE');",
|
INSERT INTO foo (bar) VALUES ('MASSE');",
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
let mut stmt = db.prepare("SELECT DISTINCT bar COLLATE unicase FROM foo ORDER BY 1")?;
|
||||||
let mut stmt = db
|
let rows = stmt.query([])?;
|
||||||
.prepare("SELECT DISTINCT bar COLLATE unicase FROM foo ORDER BY 1")
|
assert_eq!(rows.count()?, 1);
|
||||||
.unwrap();
|
Ok(())
|
||||||
let rows = stmt.query([]).unwrap();
|
|
||||||
assert_eq!(rows.count().unwrap(), 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collation_needed(db: &Connection, collation_name: &str) -> Result<()> {
|
fn collation_needed(db: &Connection, collation_name: &str) -> Result<()> {
|
||||||
@ -202,9 +200,9 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_collation_needed() {
|
fn test_collation_needed() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.collation_needed(collation_needed).unwrap();
|
db.collation_needed(collation_needed)?;
|
||||||
collate(db);
|
collate(db)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,15 +176,15 @@ impl<'stmt> Row<'stmt> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::Connection;
|
use crate::{Connection, Result};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "column_decltype")]
|
#[cfg(feature = "column_decltype")]
|
||||||
fn test_columns() {
|
fn test_columns() -> Result<()> {
|
||||||
use super::Column;
|
use super::Column;
|
||||||
|
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let query = db.prepare("SELECT * FROM sqlite_master").unwrap();
|
let query = db.prepare("SELECT * FROM sqlite_master")?;
|
||||||
let columns = query.columns();
|
let columns = query.columns();
|
||||||
let column_names: Vec<&str> = columns.iter().map(Column::name).collect();
|
let column_names: Vec<&str> = columns.iter().map(Column::name).collect();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -196,22 +196,22 @@ mod test {
|
|||||||
&column_types[..3],
|
&column_types[..3],
|
||||||
&[Some("text"), Some("text"), Some("text"),]
|
&[Some("text"), Some("text"), Some("text"),]
|
||||||
);
|
);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_column_name_in_error() {
|
fn test_column_name_in_error() -> Result<()> {
|
||||||
use crate::{types::Type, Error};
|
use crate::{types::Type, Error};
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.execute_batch(
|
db.execute_batch(
|
||||||
"BEGIN;
|
"BEGIN;
|
||||||
CREATE TABLE foo(x INTEGER, y TEXT);
|
CREATE TABLE foo(x INTEGER, y TEXT);
|
||||||
INSERT INTO foo VALUES(4, NULL);
|
INSERT INTO foo VALUES(4, NULL);
|
||||||
END;",
|
END;",
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
let mut stmt = db.prepare("SELECT x as renamed, y FROM foo")?;
|
||||||
let mut stmt = db.prepare("SELECT x as renamed, y FROM foo").unwrap();
|
let mut rows = stmt.query([])?;
|
||||||
let mut rows = stmt.query([]).unwrap();
|
let row = rows.next()?.unwrap();
|
||||||
let row = rows.next().unwrap().unwrap();
|
|
||||||
match row.get::<_, String>(0).unwrap_err() {
|
match row.get::<_, String>(0).unwrap_err() {
|
||||||
Error::InvalidColumnType(idx, name, ty) => {
|
Error::InvalidColumnType(idx, name, ty) => {
|
||||||
assert_eq!(idx, 0);
|
assert_eq!(idx, 0);
|
||||||
@ -232,5 +232,6 @@ mod test {
|
|||||||
panic!("Unexpected error type: {:?}", e);
|
panic!("Unexpected error type: {:?}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,13 +122,13 @@ impl Connection {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::DbConfig;
|
use super::DbConfig;
|
||||||
use crate::Connection;
|
use crate::{Connection, Result};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_db_config() {
|
fn test_db_config() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
|
|
||||||
let opposite = !db.db_config(DbConfig::SQLITE_DBCONFIG_ENABLE_FKEY).unwrap();
|
let opposite = !db.db_config(DbConfig::SQLITE_DBCONFIG_ENABLE_FKEY)?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
db.set_db_config(DbConfig::SQLITE_DBCONFIG_ENABLE_FKEY, opposite),
|
db.set_db_config(DbConfig::SQLITE_DBCONFIG_ENABLE_FKEY, opposite),
|
||||||
Ok(opposite)
|
Ok(opposite)
|
||||||
@ -138,9 +138,7 @@ mod test {
|
|||||||
Ok(opposite)
|
Ok(opposite)
|
||||||
);
|
);
|
||||||
|
|
||||||
let opposite = !db
|
let opposite = !db.db_config(DbConfig::SQLITE_DBCONFIG_ENABLE_TRIGGER)?;
|
||||||
.db_config(DbConfig::SQLITE_DBCONFIG_ENABLE_TRIGGER)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
db.set_db_config(DbConfig::SQLITE_DBCONFIG_ENABLE_TRIGGER, opposite),
|
db.set_db_config(DbConfig::SQLITE_DBCONFIG_ENABLE_TRIGGER, opposite),
|
||||||
Ok(opposite)
|
Ok(opposite)
|
||||||
@ -149,5 +147,6 @@ mod test {
|
|||||||
db.db_config(DbConfig::SQLITE_DBCONFIG_ENABLE_TRIGGER),
|
db.db_config(DbConfig::SQLITE_DBCONFIG_ENABLE_TRIGGER),
|
||||||
Ok(opposite)
|
Ok(opposite)
|
||||||
);
|
);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
114
src/functions.rs
114
src/functions.rs
@ -761,36 +761,36 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_function_half() {
|
fn test_function_half() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.create_scalar_function(
|
db.create_scalar_function(
|
||||||
"half",
|
"half",
|
||||||
1,
|
1,
|
||||||
FunctionFlags::SQLITE_UTF8 | FunctionFlags::SQLITE_DETERMINISTIC,
|
FunctionFlags::SQLITE_UTF8 | FunctionFlags::SQLITE_DETERMINISTIC,
|
||||||
half,
|
half,
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
let result: Result<f64> = db.query_row("SELECT half(6)", [], |r| r.get(0));
|
let result: Result<f64> = db.query_row("SELECT half(6)", [], |r| r.get(0));
|
||||||
|
|
||||||
assert!((3f64 - result.unwrap()).abs() < EPSILON);
|
assert!((3f64 - result?).abs() < EPSILON);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_remove_function() {
|
fn test_remove_function() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.create_scalar_function(
|
db.create_scalar_function(
|
||||||
"half",
|
"half",
|
||||||
1,
|
1,
|
||||||
FunctionFlags::SQLITE_UTF8 | FunctionFlags::SQLITE_DETERMINISTIC,
|
FunctionFlags::SQLITE_UTF8 | FunctionFlags::SQLITE_DETERMINISTIC,
|
||||||
half,
|
half,
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
let result: Result<f64> = db.query_row("SELECT half(6)", [], |r| r.get(0));
|
let result: Result<f64> = db.query_row("SELECT half(6)", [], |r| r.get(0));
|
||||||
assert!((3f64 - result.unwrap()).abs() < EPSILON);
|
assert!((3f64 - result?).abs() < EPSILON);
|
||||||
|
|
||||||
db.remove_function("half", 1).unwrap();
|
db.remove_function("half", 1)?;
|
||||||
let result: Result<f64> = db.query_row("SELECT half(6)", [], |r| r.get(0));
|
let result: Result<f64> = db.query_row("SELECT half(6)", [], |r| r.get(0));
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// This implementation of a regexp scalar function uses SQLite's auxilliary data
|
// This implementation of a regexp scalar function uses SQLite's auxilliary data
|
||||||
@ -817,8 +817,8 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_function_regexp_with_auxilliary() {
|
fn test_function_regexp_with_auxilliary() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.execute_batch(
|
db.execute_batch(
|
||||||
"BEGIN;
|
"BEGIN;
|
||||||
CREATE TABLE foo (x string);
|
CREATE TABLE foo (x string);
|
||||||
@ -826,20 +826,18 @@ mod test {
|
|||||||
INSERT INTO foo VALUES ('lXsi');
|
INSERT INTO foo VALUES ('lXsi');
|
||||||
INSERT INTO foo VALUES ('lisX');
|
INSERT INTO foo VALUES ('lisX');
|
||||||
END;",
|
END;",
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
db.create_scalar_function(
|
db.create_scalar_function(
|
||||||
"regexp",
|
"regexp",
|
||||||
2,
|
2,
|
||||||
FunctionFlags::SQLITE_UTF8 | FunctionFlags::SQLITE_DETERMINISTIC,
|
FunctionFlags::SQLITE_UTF8 | FunctionFlags::SQLITE_DETERMINISTIC,
|
||||||
regexp_with_auxilliary,
|
regexp_with_auxilliary,
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let result: Result<bool> =
|
let result: Result<bool> =
|
||||||
db.query_row("SELECT regexp('l.s[aeiouy]', 'lisa')", [], |r| r.get(0));
|
db.query_row("SELECT regexp('l.s[aeiouy]', 'lisa')", [], |r| r.get(0));
|
||||||
|
|
||||||
assert_eq!(true, result.unwrap());
|
assert_eq!(true, result?);
|
||||||
|
|
||||||
let result: Result<i64> = db.query_row(
|
let result: Result<i64> = db.query_row(
|
||||||
"SELECT COUNT(*) FROM foo WHERE regexp('l.s[aeiouy]', x) == 1",
|
"SELECT COUNT(*) FROM foo WHERE regexp('l.s[aeiouy]', x) == 1",
|
||||||
@ -847,12 +845,13 @@ mod test {
|
|||||||
|r| r.get(0),
|
|r| r.get(0),
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(2, result.unwrap());
|
assert_eq!(2, result?);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_varargs_function() {
|
fn test_varargs_function() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.create_scalar_function(
|
db.create_scalar_function(
|
||||||
"my_concat",
|
"my_concat",
|
||||||
-1,
|
-1,
|
||||||
@ -867,42 +866,40 @@ mod test {
|
|||||||
|
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
},
|
},
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
for &(expected, query) in &[
|
for &(expected, query) in &[
|
||||||
("", "SELECT my_concat()"),
|
("", "SELECT my_concat()"),
|
||||||
("onetwo", "SELECT my_concat('one', 'two')"),
|
("onetwo", "SELECT my_concat('one', 'two')"),
|
||||||
("abc", "SELECT my_concat('a', 'b', 'c')"),
|
("abc", "SELECT my_concat('a', 'b', 'c')"),
|
||||||
] {
|
] {
|
||||||
let result: String = db.query_row(query, [], |r| r.get(0)).unwrap();
|
let result: String = db.query_row(query, [], |r| r.get(0))?;
|
||||||
assert_eq!(expected, result);
|
assert_eq!(expected, result);
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_aux_type_checking() {
|
fn test_get_aux_type_checking() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.create_scalar_function("example", 2, FunctionFlags::default(), |ctx| {
|
db.create_scalar_function("example", 2, FunctionFlags::default(), |ctx| {
|
||||||
if !ctx.get::<bool>(1)? {
|
if !ctx.get::<bool>(1)? {
|
||||||
ctx.set_aux::<i64>(0, 100)?;
|
ctx.set_aux::<i64>(0, 100)?;
|
||||||
} else {
|
} else {
|
||||||
assert_eq!(ctx.get_aux::<String>(0), Err(Error::GetAuxWrongType));
|
assert_eq!(ctx.get_aux::<String>(0), Err(Error::GetAuxWrongType));
|
||||||
assert_eq!(*ctx.get_aux::<i64>(0).unwrap().unwrap(), 100);
|
assert_eq!(*ctx.get_aux::<i64>(0)?.unwrap(), 100);
|
||||||
}
|
}
|
||||||
Ok(true)
|
Ok(true)
|
||||||
})
|
})?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let res: bool = db
|
let res: bool = db.query_row(
|
||||||
.query_row(
|
|
||||||
"SELECT example(0, i) FROM (SELECT 0 as i UNION SELECT 1)",
|
"SELECT example(0, i) FROM (SELECT 0 as i UNION SELECT 1)",
|
||||||
[],
|
[],
|
||||||
|r| r.get(0),
|
|r| r.get(0),
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
// Doesn't actually matter, we'll assert in the function if there's a problem.
|
// Doesn't actually matter, we'll assert in the function if there's a problem.
|
||||||
assert!(res);
|
assert!(res);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Sum;
|
struct Sum;
|
||||||
@ -939,52 +936,50 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sum() {
|
fn test_sum() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.create_aggregate_function(
|
db.create_aggregate_function(
|
||||||
"my_sum",
|
"my_sum",
|
||||||
1,
|
1,
|
||||||
FunctionFlags::SQLITE_UTF8 | FunctionFlags::SQLITE_DETERMINISTIC,
|
FunctionFlags::SQLITE_UTF8 | FunctionFlags::SQLITE_DETERMINISTIC,
|
||||||
Sum,
|
Sum,
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// sum should return NULL when given no columns (contrast with count below)
|
// sum should return NULL when given no columns (contrast with count below)
|
||||||
let no_result = "SELECT my_sum(i) FROM (SELECT 2 AS i WHERE 1 <> 1)";
|
let no_result = "SELECT my_sum(i) FROM (SELECT 2 AS i WHERE 1 <> 1)";
|
||||||
let result: Option<i64> = db.query_row(no_result, [], |r| r.get(0)).unwrap();
|
let result: Option<i64> = db.query_row(no_result, [], |r| r.get(0))?;
|
||||||
assert!(result.is_none());
|
assert!(result.is_none());
|
||||||
|
|
||||||
let single_sum = "SELECT my_sum(i) FROM (SELECT 2 AS i UNION ALL SELECT 2)";
|
let single_sum = "SELECT my_sum(i) FROM (SELECT 2 AS i UNION ALL SELECT 2)";
|
||||||
let result: i64 = db.query_row(single_sum, [], |r| r.get(0)).unwrap();
|
let result: i64 = db.query_row(single_sum, [], |r| r.get(0))?;
|
||||||
assert_eq!(4, result);
|
assert_eq!(4, result);
|
||||||
|
|
||||||
let dual_sum = "SELECT my_sum(i), my_sum(j) FROM (SELECT 2 AS i, 1 AS j UNION ALL SELECT \
|
let dual_sum = "SELECT my_sum(i), my_sum(j) FROM (SELECT 2 AS i, 1 AS j UNION ALL SELECT \
|
||||||
2, 1)";
|
2, 1)";
|
||||||
let result: (i64, i64) = db
|
let result: (i64, i64) = db.query_row(dual_sum, [], |r| Ok((r.get(0)?, r.get(1)?)))?;
|
||||||
.query_row(dual_sum, [], |r| Ok((r.get(0)?, r.get(1)?)))
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!((4, 2), result);
|
assert_eq!((4, 2), result);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_count() {
|
fn test_count() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.create_aggregate_function(
|
db.create_aggregate_function(
|
||||||
"my_count",
|
"my_count",
|
||||||
-1,
|
-1,
|
||||||
FunctionFlags::SQLITE_UTF8 | FunctionFlags::SQLITE_DETERMINISTIC,
|
FunctionFlags::SQLITE_UTF8 | FunctionFlags::SQLITE_DETERMINISTIC,
|
||||||
Count,
|
Count,
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// count should return 0 when given no columns (contrast with sum above)
|
// count should return 0 when given no columns (contrast with sum above)
|
||||||
let no_result = "SELECT my_count(i) FROM (SELECT 2 AS i WHERE 1 <> 1)";
|
let no_result = "SELECT my_count(i) FROM (SELECT 2 AS i WHERE 1 <> 1)";
|
||||||
let result: i64 = db.query_row(no_result, [], |r| r.get(0)).unwrap();
|
let result: i64 = db.query_row(no_result, [], |r| r.get(0))?;
|
||||||
assert_eq!(result, 0);
|
assert_eq!(result, 0);
|
||||||
|
|
||||||
let single_sum = "SELECT my_count(i) FROM (SELECT 2 AS i UNION ALL SELECT 2)";
|
let single_sum = "SELECT my_count(i) FROM (SELECT 2 AS i UNION ALL SELECT 2)";
|
||||||
let result: i64 = db.query_row(single_sum, [], |r| r.get(0)).unwrap();
|
let result: i64 = db.query_row(single_sum, [], |r| r.get(0))?;
|
||||||
assert_eq!(2, result);
|
assert_eq!(2, result);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "window")]
|
#[cfg(feature = "window")]
|
||||||
@ -1001,17 +996,16 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "window")]
|
#[cfg(feature = "window")]
|
||||||
fn test_window() {
|
fn test_window() -> Result<()> {
|
||||||
use fallible_iterator::FallibleIterator;
|
use fallible_iterator::FallibleIterator;
|
||||||
|
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.create_window_function(
|
db.create_window_function(
|
||||||
"sumint",
|
"sumint",
|
||||||
1,
|
1,
|
||||||
FunctionFlags::SQLITE_UTF8 | FunctionFlags::SQLITE_DETERMINISTIC,
|
FunctionFlags::SQLITE_UTF8 | FunctionFlags::SQLITE_DETERMINISTIC,
|
||||||
Sum,
|
Sum,
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
db.execute_batch(
|
db.execute_batch(
|
||||||
"CREATE TABLE t3(x, y);
|
"CREATE TABLE t3(x, y);
|
||||||
INSERT INTO t3 VALUES('a', 4),
|
INSERT INTO t3 VALUES('a', 4),
|
||||||
@ -1019,24 +1013,19 @@ mod test {
|
|||||||
('c', 3),
|
('c', 3),
|
||||||
('d', 8),
|
('d', 8),
|
||||||
('e', 1);",
|
('e', 1);",
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut stmt = db
|
let mut stmt = db.prepare(
|
||||||
.prepare(
|
|
||||||
"SELECT x, sumint(y) OVER (
|
"SELECT x, sumint(y) OVER (
|
||||||
ORDER BY x ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
|
ORDER BY x ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
|
||||||
) AS sum_y
|
) AS sum_y
|
||||||
FROM t3 ORDER BY x;",
|
FROM t3 ORDER BY x;",
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let results: Vec<(String, i64)> = stmt
|
let results: Vec<(String, i64)> = stmt
|
||||||
.query([])
|
.query([])?
|
||||||
.unwrap()
|
|
||||||
.map(|row| Ok((row.get("x")?, row.get("sum_y")?)))
|
.map(|row| Ok((row.get("x")?, row.get("sum_y")?)))
|
||||||
.collect()
|
.collect()?;
|
||||||
.unwrap();
|
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
("a".to_owned(), 9),
|
("a".to_owned(), 9),
|
||||||
("b".to_owned(), 12),
|
("b".to_owned(), 12),
|
||||||
@ -1045,5 +1034,6 @@ mod test {
|
|||||||
("e".to_owned(), 9),
|
("e".to_owned(), 9),
|
||||||
];
|
];
|
||||||
assert_eq!(expected, results);
|
assert_eq!(expected, results);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
45
src/hooks.rs
45
src/hooks.rs
@ -305,26 +305,26 @@ unsafe fn free_boxed_hook<F>(p: *mut c_void) {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::Action;
|
use super::Action;
|
||||||
use crate::Connection;
|
use crate::{Connection, Result};
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_commit_hook() {
|
fn test_commit_hook() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
|
|
||||||
let mut called = false;
|
let mut called = false;
|
||||||
db.commit_hook(Some(|| {
|
db.commit_hook(Some(|| {
|
||||||
called = true;
|
called = true;
|
||||||
false
|
false
|
||||||
}));
|
}));
|
||||||
db.execute_batch("BEGIN; CREATE TABLE foo (t TEXT); COMMIT;")
|
db.execute_batch("BEGIN; CREATE TABLE foo (t TEXT); COMMIT;")?;
|
||||||
.unwrap();
|
|
||||||
assert!(called);
|
assert!(called);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fn_commit_hook() {
|
fn test_fn_commit_hook() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
|
|
||||||
fn hook() -> bool {
|
fn hook() -> bool {
|
||||||
true
|
true
|
||||||
@ -333,24 +333,25 @@ mod test {
|
|||||||
db.commit_hook(Some(hook));
|
db.commit_hook(Some(hook));
|
||||||
db.execute_batch("BEGIN; CREATE TABLE foo (t TEXT); COMMIT;")
|
db.execute_batch("BEGIN; CREATE TABLE foo (t TEXT); COMMIT;")
|
||||||
.unwrap_err();
|
.unwrap_err();
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rollback_hook() {
|
fn test_rollback_hook() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
|
|
||||||
let mut called = false;
|
let mut called = false;
|
||||||
db.rollback_hook(Some(|| {
|
db.rollback_hook(Some(|| {
|
||||||
called = true;
|
called = true;
|
||||||
}));
|
}));
|
||||||
db.execute_batch("BEGIN; CREATE TABLE foo (t TEXT); ROLLBACK;")
|
db.execute_batch("BEGIN; CREATE TABLE foo (t TEXT); ROLLBACK;")?;
|
||||||
.unwrap();
|
|
||||||
assert!(called);
|
assert!(called);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_update_hook() {
|
fn test_update_hook() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
|
|
||||||
let mut called = false;
|
let mut called = false;
|
||||||
db.update_hook(Some(|action, db: &str, tbl: &str, row_id| {
|
db.update_hook(Some(|action, db: &str, tbl: &str, row_id| {
|
||||||
@ -360,14 +361,15 @@ mod test {
|
|||||||
assert_eq!(1, row_id);
|
assert_eq!(1, row_id);
|
||||||
called = true;
|
called = true;
|
||||||
}));
|
}));
|
||||||
db.execute_batch("CREATE TABLE foo (t TEXT)").unwrap();
|
db.execute_batch("CREATE TABLE foo (t TEXT)")?;
|
||||||
db.execute_batch("INSERT INTO foo VALUES ('lisa')").unwrap();
|
db.execute_batch("INSERT INTO foo VALUES ('lisa')")?;
|
||||||
assert!(called);
|
assert!(called);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_progress_handler() {
|
fn test_progress_handler() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
|
|
||||||
static CALLED: AtomicBool = AtomicBool::new(false);
|
static CALLED: AtomicBool = AtomicBool::new(false);
|
||||||
db.progress_handler(
|
db.progress_handler(
|
||||||
@ -377,14 +379,14 @@ mod test {
|
|||||||
false
|
false
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
db.execute_batch("BEGIN; CREATE TABLE foo (t TEXT); COMMIT;")
|
db.execute_batch("BEGIN; CREATE TABLE foo (t TEXT); COMMIT;")?;
|
||||||
.unwrap();
|
|
||||||
assert!(CALLED.load(Ordering::Relaxed));
|
assert!(CALLED.load(Ordering::Relaxed));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_progress_handler_interrupt() {
|
fn test_progress_handler_interrupt() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
|
|
||||||
fn handler() -> bool {
|
fn handler() -> bool {
|
||||||
true
|
true
|
||||||
@ -393,5 +395,6 @@ mod test {
|
|||||||
db.progress_handler(1, Some(handler));
|
db.progress_handler(1, Some(handler));
|
||||||
db.execute_batch("BEGIN; CREATE TABLE foo (t TEXT); COMMIT;")
|
db.execute_batch("BEGIN; CREATE TABLE foo (t TEXT); COMMIT;")
|
||||||
.unwrap_err();
|
.unwrap_err();
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
365
src/lib.rs
365
src/lib.rs
@ -1060,38 +1060,32 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_concurrent_transactions_busy_commit() {
|
fn test_concurrent_transactions_busy_commit() -> Result<()> {
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
let tmp = tempfile::tempdir().unwrap();
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
let path = tmp.path().join("transactions.db3");
|
let path = tmp.path().join("transactions.db3");
|
||||||
|
|
||||||
Connection::open(&path)
|
Connection::open(&path)?.execute_batch(
|
||||||
.expect("create temp db")
|
|
||||||
.execute_batch(
|
|
||||||
"
|
"
|
||||||
BEGIN; CREATE TABLE foo(x INTEGER);
|
BEGIN; CREATE TABLE foo(x INTEGER);
|
||||||
INSERT INTO foo VALUES(42); END;",
|
INSERT INTO foo VALUES(42); END;",
|
||||||
)
|
)?;
|
||||||
.expect("create temp db");
|
|
||||||
|
|
||||||
let mut db1 =
|
let mut db1 = Connection::open_with_flags(&path, OpenFlags::SQLITE_OPEN_READ_WRITE)?;
|
||||||
Connection::open_with_flags(&path, OpenFlags::SQLITE_OPEN_READ_WRITE).unwrap();
|
let mut db2 = Connection::open_with_flags(&path, OpenFlags::SQLITE_OPEN_READ_ONLY)?;
|
||||||
let mut db2 = Connection::open_with_flags(&path, OpenFlags::SQLITE_OPEN_READ_ONLY).unwrap();
|
|
||||||
|
|
||||||
db1.busy_timeout(Duration::from_millis(0)).unwrap();
|
db1.busy_timeout(Duration::from_millis(0))?;
|
||||||
db2.busy_timeout(Duration::from_millis(0)).unwrap();
|
db2.busy_timeout(Duration::from_millis(0))?;
|
||||||
|
|
||||||
{
|
{
|
||||||
let tx1 = db1.transaction().unwrap();
|
let tx1 = db1.transaction()?;
|
||||||
let tx2 = db2.transaction().unwrap();
|
let tx2 = db2.transaction()?;
|
||||||
|
|
||||||
// SELECT first makes sqlite lock with a shared lock
|
// SELECT first makes sqlite lock with a shared lock
|
||||||
tx1.query_row("SELECT x FROM foo LIMIT 1", [], |_| Ok(()))
|
tx1.query_row("SELECT x FROM foo LIMIT 1", [], |_| Ok(()))?;
|
||||||
.unwrap();
|
tx2.query_row("SELECT x FROM foo LIMIT 1", [], |_| Ok(()))?;
|
||||||
tx2.query_row("SELECT x FROM foo LIMIT 1", [], |_| Ok(()))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
tx1.execute("INSERT INTO foo VALUES(?1)", &[&1]).unwrap();
|
tx1.execute("INSERT INTO foo VALUES(?1)", &[&1])?;
|
||||||
let _ = tx2.execute("INSERT INTO foo VALUES(?1)", [2]);
|
let _ = tx2.execute("INSERT INTO foo VALUES(?1)", [2]);
|
||||||
|
|
||||||
let _ = tx1.commit();
|
let _ = tx1.commit();
|
||||||
@ -1104,27 +1098,29 @@ mod test {
|
|||||||
let _ = db2
|
let _ = db2
|
||||||
.transaction()
|
.transaction()
|
||||||
.expect("commit should have closed transaction");
|
.expect("commit should have closed transaction");
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_persistence() {
|
fn test_persistence() -> Result<()> {
|
||||||
let temp_dir = tempfile::tempdir().unwrap();
|
let temp_dir = tempfile::tempdir().unwrap();
|
||||||
let path = temp_dir.path().join("test.db3");
|
let path = temp_dir.path().join("test.db3");
|
||||||
|
|
||||||
{
|
{
|
||||||
let db = Connection::open(&path).unwrap();
|
let db = Connection::open(&path)?;
|
||||||
let sql = "BEGIN;
|
let sql = "BEGIN;
|
||||||
CREATE TABLE foo(x INTEGER);
|
CREATE TABLE foo(x INTEGER);
|
||||||
INSERT INTO foo VALUES(42);
|
INSERT INTO foo VALUES(42);
|
||||||
END;";
|
END;";
|
||||||
db.execute_batch(sql).unwrap();
|
db.execute_batch(sql)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let path_string = path.to_str().unwrap();
|
let path_string = path.to_str().unwrap();
|
||||||
let db = Connection::open(&path_string).unwrap();
|
let db = Connection::open(&path_string)?;
|
||||||
let the_answer: Result<i64> = db.query_row("SELECT x FROM foo", [], |r| r.get(0));
|
let the_answer: Result<i64> = db.query_row("SELECT x FROM foo", [], |r| r.get(0));
|
||||||
|
|
||||||
assert_eq!(42i64, the_answer.unwrap());
|
assert_eq!(42i64, the_answer?);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1157,7 +1153,7 @@ mod test {
|
|||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_invalid_unicode_file_names() {
|
fn test_invalid_unicode_file_names() -> Result<()> {
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::os::unix::ffi::OsStrExt;
|
use std::os::unix::ffi::OsStrExt;
|
||||||
@ -1166,26 +1162,27 @@ mod test {
|
|||||||
let path = temp_dir.path();
|
let path = temp_dir.path();
|
||||||
if File::create(path.join(OsStr::from_bytes(&[0xFE]))).is_err() {
|
if File::create(path.join(OsStr::from_bytes(&[0xFE]))).is_err() {
|
||||||
// Skip test, filesystem doesn't support invalid Unicode
|
// Skip test, filesystem doesn't support invalid Unicode
|
||||||
return;
|
return Ok(());
|
||||||
}
|
}
|
||||||
let db_path = path.join(OsStr::from_bytes(&[0xFF]));
|
let db_path = path.join(OsStr::from_bytes(&[0xFF]));
|
||||||
{
|
{
|
||||||
let db = Connection::open(&db_path).unwrap();
|
let db = Connection::open(&db_path)?;
|
||||||
let sql = "BEGIN;
|
let sql = "BEGIN;
|
||||||
CREATE TABLE foo(x INTEGER);
|
CREATE TABLE foo(x INTEGER);
|
||||||
INSERT INTO foo VALUES(42);
|
INSERT INTO foo VALUES(42);
|
||||||
END;";
|
END;";
|
||||||
db.execute_batch(sql).unwrap();
|
db.execute_batch(sql)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let db = Connection::open(&db_path).unwrap();
|
let db = Connection::open(&db_path)?;
|
||||||
let the_answer: Result<i64> = db.query_row("SELECT x FROM foo", [], |r| r.get(0));
|
let the_answer: Result<i64> = db.query_row("SELECT x FROM foo", [], |r| r.get(0));
|
||||||
|
|
||||||
assert_eq!(42i64, the_answer.unwrap());
|
assert_eq!(42i64, the_answer?);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_close_retry() {
|
fn test_close_retry() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
|
|
||||||
// force the DB to be busy by preparing a statement; this must be done at the
|
// force the DB to be busy by preparing a statement; this must be done at the
|
||||||
@ -1199,7 +1196,7 @@ mod test {
|
|||||||
let raw_db = db.db.borrow_mut().db;
|
let raw_db = db.db.borrow_mut().db;
|
||||||
let sql = "SELECT 1";
|
let sql = "SELECT 1";
|
||||||
let mut raw_stmt: *mut ffi::sqlite3_stmt = ptr::null_mut();
|
let mut raw_stmt: *mut ffi::sqlite3_stmt = ptr::null_mut();
|
||||||
let cstring = str_to_cstring(sql).unwrap();
|
let cstring = str_to_cstring(sql)?;
|
||||||
let rc = unsafe {
|
let rc = unsafe {
|
||||||
ffi::sqlite3_prepare_v2(
|
ffi::sqlite3_prepare_v2(
|
||||||
raw_db,
|
raw_db,
|
||||||
@ -1223,6 +1220,7 @@ mod test {
|
|||||||
assert_eq!(ffi::SQLITE_OK, unsafe { ffi::sqlite3_finalize(raw_stmt) });
|
assert_eq!(ffi::SQLITE_OK, unsafe { ffi::sqlite3_finalize(raw_stmt) });
|
||||||
|
|
||||||
db.close().unwrap();
|
db.close().unwrap();
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1237,7 +1235,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_execute_batch() {
|
fn test_execute_batch() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
let sql = "BEGIN;
|
let sql = "BEGIN;
|
||||||
CREATE TABLE foo(x INTEGER);
|
CREATE TABLE foo(x INTEGER);
|
||||||
@ -1246,33 +1244,27 @@ mod test {
|
|||||||
INSERT INTO foo VALUES(3);
|
INSERT INTO foo VALUES(3);
|
||||||
INSERT INTO foo VALUES(4);
|
INSERT INTO foo VALUES(4);
|
||||||
END;";
|
END;";
|
||||||
db.execute_batch(sql).unwrap();
|
db.execute_batch(sql)?;
|
||||||
|
|
||||||
db.execute_batch("UPDATE foo SET x = 3 WHERE x < 3")
|
db.execute_batch("UPDATE foo SET x = 3 WHERE x < 3")?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert!(db.execute_batch("INVALID SQL").is_err());
|
assert!(db.execute_batch("INVALID SQL").is_err());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_execute() {
|
fn test_execute() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
db.execute_batch("CREATE TABLE foo(x INTEGER)").unwrap();
|
db.execute_batch("CREATE TABLE foo(x INTEGER)")?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(1, db.execute("INSERT INTO foo(x) VALUES (?)", [1i32])?);
|
||||||
1,
|
assert_eq!(1, db.execute("INSERT INTO foo(x) VALUES (?)", [2i32])?);
|
||||||
db.execute("INSERT INTO foo(x) VALUES (?)", [1i32]).unwrap()
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
1,
|
|
||||||
db.execute("INSERT INTO foo(x) VALUES (?)", [2i32]).unwrap()
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
3i32,
|
3i32,
|
||||||
db.query_row::<i32, _, _>("SELECT SUM(x) FROM foo", [], |r| r.get(0))
|
db.query_row::<i32, _, _>("SELECT SUM(x) FROM foo", [], |r| r.get(0))?
|
||||||
.unwrap()
|
|
||||||
);
|
);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1302,77 +1294,78 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_prepare_column_names() {
|
fn test_prepare_column_names() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
db.execute_batch("CREATE TABLE foo(x INTEGER);").unwrap();
|
db.execute_batch("CREATE TABLE foo(x INTEGER);")?;
|
||||||
|
|
||||||
let stmt = db.prepare("SELECT * FROM foo").unwrap();
|
let stmt = db.prepare("SELECT * FROM foo")?;
|
||||||
assert_eq!(stmt.column_count(), 1);
|
assert_eq!(stmt.column_count(), 1);
|
||||||
assert_eq!(stmt.column_names(), vec!["x"]);
|
assert_eq!(stmt.column_names(), vec!["x"]);
|
||||||
|
|
||||||
let stmt = db.prepare("SELECT x AS a, x AS b FROM foo").unwrap();
|
let stmt = db.prepare("SELECT x AS a, x AS b FROM foo")?;
|
||||||
assert_eq!(stmt.column_count(), 2);
|
assert_eq!(stmt.column_count(), 2);
|
||||||
assert_eq!(stmt.column_names(), vec!["a", "b"]);
|
assert_eq!(stmt.column_names(), vec!["a", "b"]);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_prepare_execute() {
|
fn test_prepare_execute() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
db.execute_batch("CREATE TABLE foo(x INTEGER);").unwrap();
|
db.execute_batch("CREATE TABLE foo(x INTEGER);")?;
|
||||||
|
|
||||||
let mut insert_stmt = db.prepare("INSERT INTO foo(x) VALUES(?)").unwrap();
|
let mut insert_stmt = db.prepare("INSERT INTO foo(x) VALUES(?)")?;
|
||||||
assert_eq!(insert_stmt.execute([1i32]).unwrap(), 1);
|
assert_eq!(insert_stmt.execute([1i32])?, 1);
|
||||||
assert_eq!(insert_stmt.execute([2i32]).unwrap(), 1);
|
assert_eq!(insert_stmt.execute([2i32])?, 1);
|
||||||
assert_eq!(insert_stmt.execute([3i32]).unwrap(), 1);
|
assert_eq!(insert_stmt.execute([3i32])?, 1);
|
||||||
|
|
||||||
assert_eq!(insert_stmt.execute(["hello".to_string()]).unwrap(), 1);
|
assert_eq!(insert_stmt.execute(["hello".to_string()])?, 1);
|
||||||
assert_eq!(insert_stmt.execute(["goodbye".to_string()]).unwrap(), 1);
|
assert_eq!(insert_stmt.execute(["goodbye".to_string()])?, 1);
|
||||||
assert_eq!(insert_stmt.execute([types::Null]).unwrap(), 1);
|
assert_eq!(insert_stmt.execute([types::Null])?, 1);
|
||||||
|
|
||||||
let mut update_stmt = db.prepare("UPDATE foo SET x=? WHERE x<?").unwrap();
|
let mut update_stmt = db.prepare("UPDATE foo SET x=? WHERE x<?")?;
|
||||||
assert_eq!(update_stmt.execute([3i32, 3i32]).unwrap(), 2);
|
assert_eq!(update_stmt.execute([3i32, 3i32])?, 2);
|
||||||
assert_eq!(update_stmt.execute([3i32, 3i32]).unwrap(), 0);
|
assert_eq!(update_stmt.execute([3i32, 3i32])?, 0);
|
||||||
assert_eq!(update_stmt.execute([8i32, 8i32]).unwrap(), 3);
|
assert_eq!(update_stmt.execute([8i32, 8i32])?, 3);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_prepare_query() {
|
fn test_prepare_query() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
db.execute_batch("CREATE TABLE foo(x INTEGER);").unwrap();
|
db.execute_batch("CREATE TABLE foo(x INTEGER);")?;
|
||||||
|
|
||||||
let mut insert_stmt = db.prepare("INSERT INTO foo(x) VALUES(?)").unwrap();
|
let mut insert_stmt = db.prepare("INSERT INTO foo(x) VALUES(?)")?;
|
||||||
assert_eq!(insert_stmt.execute([1i32]).unwrap(), 1);
|
assert_eq!(insert_stmt.execute([1i32])?, 1);
|
||||||
assert_eq!(insert_stmt.execute([2i32]).unwrap(), 1);
|
assert_eq!(insert_stmt.execute([2i32])?, 1);
|
||||||
assert_eq!(insert_stmt.execute([3i32]).unwrap(), 1);
|
assert_eq!(insert_stmt.execute([3i32])?, 1);
|
||||||
|
|
||||||
let mut query = db
|
let mut query = db.prepare("SELECT x FROM foo WHERE x < ? ORDER BY x DESC")?;
|
||||||
.prepare("SELECT x FROM foo WHERE x < ? ORDER BY x DESC")
|
|
||||||
.unwrap();
|
|
||||||
{
|
{
|
||||||
let mut rows = query.query([4i32]).unwrap();
|
let mut rows = query.query([4i32])?;
|
||||||
let mut v = Vec::<i32>::new();
|
let mut v = Vec::<i32>::new();
|
||||||
|
|
||||||
while let Some(row) = rows.next().unwrap() {
|
while let Some(row) = rows.next()? {
|
||||||
v.push(row.get(0).unwrap());
|
v.push(row.get(0)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(v, [3i32, 2, 1]);
|
assert_eq!(v, [3i32, 2, 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut rows = query.query([3i32]).unwrap();
|
let mut rows = query.query([3i32])?;
|
||||||
let mut v = Vec::<i32>::new();
|
let mut v = Vec::<i32>::new();
|
||||||
|
|
||||||
while let Some(row) = rows.next().unwrap() {
|
while let Some(row) = rows.next()? {
|
||||||
v.push(row.get(0).unwrap());
|
v.push(row.get(0)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(v, [2i32, 1]);
|
assert_eq!(v, [2i32, 1]);
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_map() {
|
fn test_query_map() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
let sql = "BEGIN;
|
let sql = "BEGIN;
|
||||||
CREATE TABLE foo(x INTEGER, y TEXT);
|
CREATE TABLE foo(x INTEGER, y TEXT);
|
||||||
@ -1381,16 +1374,17 @@ mod test {
|
|||||||
INSERT INTO foo VALUES(2, \"world\");
|
INSERT INTO foo VALUES(2, \"world\");
|
||||||
INSERT INTO foo VALUES(1, \"!\");
|
INSERT INTO foo VALUES(1, \"!\");
|
||||||
END;";
|
END;";
|
||||||
db.execute_batch(sql).unwrap();
|
db.execute_batch(sql)?;
|
||||||
|
|
||||||
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC").unwrap();
|
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC")?;
|
||||||
let results: Result<Vec<String>> = query.query([]).unwrap().map(|row| row.get(1)).collect();
|
let results: Result<Vec<String>> = query.query([])?.map(|row| row.get(1)).collect();
|
||||||
|
|
||||||
assert_eq!(results.unwrap().concat(), "hello, world!");
|
assert_eq!(results?.concat(), "hello, world!");
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_row() {
|
fn test_query_row() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
let sql = "BEGIN;
|
let sql = "BEGIN;
|
||||||
CREATE TABLE foo(x INTEGER);
|
CREATE TABLE foo(x INTEGER);
|
||||||
@ -1399,12 +1393,11 @@ mod test {
|
|||||||
INSERT INTO foo VALUES(3);
|
INSERT INTO foo VALUES(3);
|
||||||
INSERT INTO foo VALUES(4);
|
INSERT INTO foo VALUES(4);
|
||||||
END;";
|
END;";
|
||||||
db.execute_batch(sql).unwrap();
|
db.execute_batch(sql)?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
10i64,
|
10i64,
|
||||||
db.query_row::<i64, _, _>("SELECT SUM(x) FROM foo", [], |r| r.get(0))
|
db.query_row::<i64, _, _>("SELECT SUM(x) FROM foo", [], |r| r.get(0))?
|
||||||
.unwrap()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let result: Result<i64> = db.query_row("SELECT x FROM foo WHERE x > 5", [], |r| r.get(0));
|
let result: Result<i64> = db.query_row("SELECT x FROM foo WHERE x > 5", [], |r| r.get(0));
|
||||||
@ -1416,22 +1409,23 @@ mod test {
|
|||||||
let bad_query_result = db.query_row("NOT A PROPER QUERY; test123", [], |_| Ok(()));
|
let bad_query_result = db.query_row("NOT A PROPER QUERY; test123", [], |_| Ok(()));
|
||||||
|
|
||||||
assert!(bad_query_result.is_err());
|
assert!(bad_query_result.is_err());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_optional() {
|
fn test_optional() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
|
|
||||||
let result: Result<i64> = db.query_row("SELECT 1 WHERE 0 <> 0", [], |r| r.get(0));
|
let result: Result<i64> = db.query_row("SELECT 1 WHERE 0 <> 0", [], |r| r.get(0));
|
||||||
let result = result.optional();
|
let result = result.optional();
|
||||||
match result.unwrap() {
|
match result? {
|
||||||
None => (),
|
None => (),
|
||||||
_ => panic!("Unexpected result"),
|
_ => panic!("Unexpected result"),
|
||||||
}
|
}
|
||||||
|
|
||||||
let result: Result<i64> = db.query_row("SELECT 1 WHERE 0 == 0", [], |r| r.get(0));
|
let result: Result<i64> = db.query_row("SELECT 1 WHERE 0 == 0", [], |r| r.get(0));
|
||||||
let result = result.optional();
|
let result = result.optional();
|
||||||
match result.unwrap() {
|
match result? {
|
||||||
Some(1) => (),
|
Some(1) => (),
|
||||||
_ => panic!("Unexpected result"),
|
_ => panic!("Unexpected result"),
|
||||||
}
|
}
|
||||||
@ -1439,47 +1433,48 @@ mod test {
|
|||||||
let bad_query_result: Result<i64> = db.query_row("NOT A PROPER QUERY", [], |r| r.get(0));
|
let bad_query_result: Result<i64> = db.query_row("NOT A PROPER QUERY", [], |r| r.get(0));
|
||||||
let bad_query_result = bad_query_result.optional();
|
let bad_query_result = bad_query_result.optional();
|
||||||
assert!(bad_query_result.is_err());
|
assert!(bad_query_result.is_err());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_pragma_query_row() {
|
fn test_pragma_query_row() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"memory",
|
"memory",
|
||||||
db.query_row::<String, _, _>("PRAGMA journal_mode", [], |r| r.get(0))
|
db.query_row::<String, _, _>("PRAGMA journal_mode", [], |r| r.get(0))?
|
||||||
.unwrap()
|
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"off",
|
"off",
|
||||||
db.query_row::<String, _, _>("PRAGMA journal_mode=off", [], |r| r.get(0))
|
db.query_row::<String, _, _>("PRAGMA journal_mode=off", [], |r| r.get(0))?
|
||||||
.unwrap()
|
|
||||||
);
|
);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_prepare_failures() {
|
fn test_prepare_failures() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
db.execute_batch("CREATE TABLE foo(x INTEGER);").unwrap();
|
db.execute_batch("CREATE TABLE foo(x INTEGER);")?;
|
||||||
|
|
||||||
let err = db.prepare("SELECT * FROM does_not_exist").unwrap_err();
|
let err = db.prepare("SELECT * FROM does_not_exist").unwrap_err();
|
||||||
assert!(format!("{}", err).contains("does_not_exist"));
|
assert!(format!("{}", err).contains("does_not_exist"));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_last_insert_rowid() {
|
fn test_last_insert_rowid() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
db.execute_batch("CREATE TABLE foo(x INTEGER PRIMARY KEY)")
|
db.execute_batch("CREATE TABLE foo(x INTEGER PRIMARY KEY)")?;
|
||||||
.unwrap();
|
db.execute_batch("INSERT INTO foo DEFAULT VALUES")?;
|
||||||
db.execute_batch("INSERT INTO foo DEFAULT VALUES").unwrap();
|
|
||||||
|
|
||||||
assert_eq!(db.last_insert_rowid(), 1);
|
assert_eq!(db.last_insert_rowid(), 1);
|
||||||
|
|
||||||
let mut stmt = db.prepare("INSERT INTO foo DEFAULT VALUES").unwrap();
|
let mut stmt = db.prepare("INSERT INTO foo DEFAULT VALUES")?;
|
||||||
for _ in 0i32..9 {
|
for _ in 0i32..9 {
|
||||||
stmt.execute([]).unwrap();
|
stmt.execute([])?;
|
||||||
}
|
}
|
||||||
assert_eq!(db.last_insert_rowid(), 10);
|
assert_eq!(db.last_insert_rowid(), 10);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1493,32 +1488,34 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "modern_sqlite")]
|
#[cfg(feature = "modern_sqlite")]
|
||||||
fn test_is_busy() {
|
fn test_is_busy() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
assert!(!db.is_busy());
|
assert!(!db.is_busy());
|
||||||
let mut stmt = db.prepare("PRAGMA schema_version").unwrap();
|
let mut stmt = db.prepare("PRAGMA schema_version")?;
|
||||||
assert!(!db.is_busy());
|
assert!(!db.is_busy());
|
||||||
{
|
{
|
||||||
let mut rows = stmt.query([]).unwrap();
|
let mut rows = stmt.query([])?;
|
||||||
assert!(!db.is_busy());
|
assert!(!db.is_busy());
|
||||||
let row = rows.next().unwrap();
|
let row = rows.next()?;
|
||||||
assert!(db.is_busy());
|
assert!(db.is_busy());
|
||||||
assert!(row.is_some());
|
assert!(row.is_some());
|
||||||
}
|
}
|
||||||
assert!(!db.is_busy());
|
assert!(!db.is_busy());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_statement_debugging() {
|
fn test_statement_debugging() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
let query = "SELECT 12345";
|
let query = "SELECT 12345";
|
||||||
let stmt = db.prepare(query).unwrap();
|
let stmt = db.prepare(query)?;
|
||||||
|
|
||||||
assert!(format!("{:?}", stmt).contains(query));
|
assert!(format!("{:?}", stmt).contains(query));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_notnull_constraint_error() {
|
fn test_notnull_constraint_error() -> Result<()> {
|
||||||
// extended error codes for constraints were added in SQLite 3.7.16; if we're
|
// extended error codes for constraints were added in SQLite 3.7.16; if we're
|
||||||
// running on our bundled version, we know the extended error code exists.
|
// running on our bundled version, we know the extended error code exists.
|
||||||
#[cfg(feature = "modern_sqlite")]
|
#[cfg(feature = "modern_sqlite")]
|
||||||
@ -1529,7 +1526,7 @@ mod test {
|
|||||||
fn check_extended_code(_extended_code: c_int) {}
|
fn check_extended_code(_extended_code: c_int) {}
|
||||||
|
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
db.execute_batch("CREATE TABLE foo(x NOT NULL)").unwrap();
|
db.execute_batch("CREATE TABLE foo(x NOT NULL)")?;
|
||||||
|
|
||||||
let result = db.execute("INSERT INTO foo (x) VALUES (NULL)", []);
|
let result = db.execute("INSERT INTO foo (x) VALUES (NULL)", []);
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
@ -1541,6 +1538,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
err => panic!("Unexpected error {}", err),
|
err => panic!("Unexpected error {}", err),
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1555,7 +1553,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "functions")]
|
#[cfg(feature = "functions")]
|
||||||
fn test_interrupt() {
|
fn test_interrupt() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
|
|
||||||
let interrupt_handle = db.get_interrupt_handle();
|
let interrupt_handle = db.get_interrupt_handle();
|
||||||
@ -1568,14 +1566,12 @@ mod test {
|
|||||||
interrupt_handle.interrupt();
|
interrupt_handle.interrupt();
|
||||||
Ok(0)
|
Ok(0)
|
||||||
},
|
},
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut stmt = db
|
let mut stmt =
|
||||||
.prepare("SELECT interrupt() FROM (SELECT 1 UNION SELECT 2 UNION SELECT 3)")
|
db.prepare("SELECT interrupt() FROM (SELECT 1 UNION SELECT 2 UNION SELECT 3)")?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let result: Result<Vec<i32>> = stmt.query([]).unwrap().map(|r| r.get(0)).collect();
|
let result: Result<Vec<i32>> = stmt.query([])?.map(|r| r.get(0)).collect();
|
||||||
|
|
||||||
match result.unwrap_err() {
|
match result.unwrap_err() {
|
||||||
Error::SqliteFailure(err, _) => {
|
Error::SqliteFailure(err, _) => {
|
||||||
@ -1585,6 +1581,7 @@ mod test {
|
|||||||
panic!("Unexpected error {}", err);
|
panic!("Unexpected error {}", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1604,36 +1601,38 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_raw() {
|
fn test_get_raw() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
db.execute_batch("CREATE TABLE foo(i, x);").unwrap();
|
db.execute_batch("CREATE TABLE foo(i, x);")?;
|
||||||
let vals = ["foobar", "1234", "qwerty"];
|
let vals = ["foobar", "1234", "qwerty"];
|
||||||
let mut insert_stmt = db.prepare("INSERT INTO foo(i, x) VALUES(?, ?)").unwrap();
|
let mut insert_stmt = db.prepare("INSERT INTO foo(i, x) VALUES(?, ?)")?;
|
||||||
for (i, v) in vals.iter().enumerate() {
|
for (i, v) in vals.iter().enumerate() {
|
||||||
let i_to_insert = i as i64;
|
let i_to_insert = i as i64;
|
||||||
assert_eq!(insert_stmt.execute(params![i_to_insert, v]).unwrap(), 1);
|
assert_eq!(insert_stmt.execute(params![i_to_insert, v])?, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut query = db.prepare("SELECT i, x FROM foo").unwrap();
|
let mut query = db.prepare("SELECT i, x FROM foo")?;
|
||||||
let mut rows = query.query([]).unwrap();
|
let mut rows = query.query([])?;
|
||||||
|
|
||||||
while let Some(row) = rows.next().unwrap() {
|
while let Some(row) = rows.next()? {
|
||||||
let i = row.get_raw(0).as_i64().unwrap();
|
let i = row.get_raw(0).as_i64()?;
|
||||||
let expect = vals[i as usize];
|
let expect = vals[i as usize];
|
||||||
let x = row.get_raw("x").as_str().unwrap();
|
let x = row.get_raw("x").as_str()?;
|
||||||
assert_eq!(x, expect);
|
assert_eq!(x, expect);
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_from_handle() {
|
fn test_from_handle() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
let handle = unsafe { db.handle() };
|
let handle = unsafe { db.handle() };
|
||||||
{
|
{
|
||||||
let db = unsafe { Connection::from_handle(handle) }.unwrap();
|
let db = unsafe { Connection::from_handle(handle) }?;
|
||||||
db.execute_batch("PRAGMA VACUUM").unwrap();
|
db.execute_batch("PRAGMA VACUUM")?;
|
||||||
}
|
}
|
||||||
db.close().unwrap();
|
db.close().unwrap();
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
mod query_and_then_tests {
|
mod query_and_then_tests {
|
||||||
@ -1677,7 +1676,7 @@ mod test {
|
|||||||
type CustomResult<T> = Result<T, CustomError>;
|
type CustomResult<T> = Result<T, CustomError>;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_and_then() {
|
fn test_query_and_then() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
let sql = "BEGIN;
|
let sql = "BEGIN;
|
||||||
CREATE TABLE foo(x INTEGER, y TEXT);
|
CREATE TABLE foo(x INTEGER, y TEXT);
|
||||||
@ -1686,19 +1685,18 @@ mod test {
|
|||||||
INSERT INTO foo VALUES(2, \"world\");
|
INSERT INTO foo VALUES(2, \"world\");
|
||||||
INSERT INTO foo VALUES(1, \"!\");
|
INSERT INTO foo VALUES(1, \"!\");
|
||||||
END;";
|
END;";
|
||||||
db.execute_batch(sql).unwrap();
|
db.execute_batch(sql)?;
|
||||||
|
|
||||||
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC").unwrap();
|
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC")?;
|
||||||
let results: Result<Vec<String>> = query
|
let results: Result<Vec<String>> =
|
||||||
.query_and_then([], |row| row.get(1))
|
query.query_and_then([], |row| row.get(1))?.collect();
|
||||||
.unwrap()
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
assert_eq!(results.unwrap().concat(), "hello, world!");
|
assert_eq!(results?.concat(), "hello, world!");
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_and_then_fails() {
|
fn test_query_and_then_fails() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
let sql = "BEGIN;
|
let sql = "BEGIN;
|
||||||
CREATE TABLE foo(x INTEGER, y TEXT);
|
CREATE TABLE foo(x INTEGER, y TEXT);
|
||||||
@ -1707,32 +1705,28 @@ mod test {
|
|||||||
INSERT INTO foo VALUES(2, \"world\");
|
INSERT INTO foo VALUES(2, \"world\");
|
||||||
INSERT INTO foo VALUES(1, \"!\");
|
INSERT INTO foo VALUES(1, \"!\");
|
||||||
END;";
|
END;";
|
||||||
db.execute_batch(sql).unwrap();
|
db.execute_batch(sql)?;
|
||||||
|
|
||||||
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC").unwrap();
|
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC")?;
|
||||||
let bad_type: Result<Vec<f64>> = query
|
let bad_type: Result<Vec<f64>> = query.query_and_then([], |row| row.get(1))?.collect();
|
||||||
.query_and_then([], |row| row.get(1))
|
|
||||||
.unwrap()
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
match bad_type.unwrap_err() {
|
match bad_type.unwrap_err() {
|
||||||
Error::InvalidColumnType(..) => (),
|
Error::InvalidColumnType(..) => (),
|
||||||
err => panic!("Unexpected error {}", err),
|
err => panic!("Unexpected error {}", err),
|
||||||
}
|
}
|
||||||
|
|
||||||
let bad_idx: Result<Vec<String>> = query
|
let bad_idx: Result<Vec<String>> =
|
||||||
.query_and_then([], |row| row.get(3))
|
query.query_and_then([], |row| row.get(3))?.collect();
|
||||||
.unwrap()
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
match bad_idx.unwrap_err() {
|
match bad_idx.unwrap_err() {
|
||||||
Error::InvalidColumnIndex(_) => (),
|
Error::InvalidColumnIndex(_) => (),
|
||||||
err => panic!("Unexpected error {}", err),
|
err => panic!("Unexpected error {}", err),
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_and_then_custom_error() {
|
fn test_query_and_then_custom_error() -> CustomResult<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
let sql = "BEGIN;
|
let sql = "BEGIN;
|
||||||
CREATE TABLE foo(x INTEGER, y TEXT);
|
CREATE TABLE foo(x INTEGER, y TEXT);
|
||||||
@ -1741,19 +1735,19 @@ mod test {
|
|||||||
INSERT INTO foo VALUES(2, \"world\");
|
INSERT INTO foo VALUES(2, \"world\");
|
||||||
INSERT INTO foo VALUES(1, \"!\");
|
INSERT INTO foo VALUES(1, \"!\");
|
||||||
END;";
|
END;";
|
||||||
db.execute_batch(sql).unwrap();
|
db.execute_batch(sql)?;
|
||||||
|
|
||||||
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC").unwrap();
|
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC")?;
|
||||||
let results: CustomResult<Vec<String>> = query
|
let results: CustomResult<Vec<String>> = query
|
||||||
.query_and_then([], |row| row.get(1).map_err(CustomError::Sqlite))
|
.query_and_then([], |row| row.get(1).map_err(CustomError::Sqlite))?
|
||||||
.unwrap()
|
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
assert_eq!(results.unwrap().concat(), "hello, world!");
|
assert_eq!(results?.concat(), "hello, world!");
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_and_then_custom_error_fails() {
|
fn test_query_and_then_custom_error_fails() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
let sql = "BEGIN;
|
let sql = "BEGIN;
|
||||||
CREATE TABLE foo(x INTEGER, y TEXT);
|
CREATE TABLE foo(x INTEGER, y TEXT);
|
||||||
@ -1762,12 +1756,11 @@ mod test {
|
|||||||
INSERT INTO foo VALUES(2, \"world\");
|
INSERT INTO foo VALUES(2, \"world\");
|
||||||
INSERT INTO foo VALUES(1, \"!\");
|
INSERT INTO foo VALUES(1, \"!\");
|
||||||
END;";
|
END;";
|
||||||
db.execute_batch(sql).unwrap();
|
db.execute_batch(sql)?;
|
||||||
|
|
||||||
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC").unwrap();
|
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC")?;
|
||||||
let bad_type: CustomResult<Vec<f64>> = query
|
let bad_type: CustomResult<Vec<f64>> = query
|
||||||
.query_and_then([], |row| row.get(1).map_err(CustomError::Sqlite))
|
.query_and_then([], |row| row.get(1).map_err(CustomError::Sqlite))?
|
||||||
.unwrap()
|
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
match bad_type.unwrap_err() {
|
match bad_type.unwrap_err() {
|
||||||
@ -1776,8 +1769,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let bad_idx: CustomResult<Vec<String>> = query
|
let bad_idx: CustomResult<Vec<String>> = query
|
||||||
.query_and_then([], |row| row.get(3).map_err(CustomError::Sqlite))
|
.query_and_then([], |row| row.get(3).map_err(CustomError::Sqlite))?
|
||||||
.unwrap()
|
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
match bad_idx.unwrap_err() {
|
match bad_idx.unwrap_err() {
|
||||||
@ -1786,40 +1778,41 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let non_sqlite_err: CustomResult<Vec<String>> = query
|
let non_sqlite_err: CustomResult<Vec<String>> = query
|
||||||
.query_and_then([], |_| Err(CustomError::SomeError))
|
.query_and_then([], |_| Err(CustomError::SomeError))?
|
||||||
.unwrap()
|
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
match non_sqlite_err.unwrap_err() {
|
match non_sqlite_err.unwrap_err() {
|
||||||
CustomError::SomeError => (),
|
CustomError::SomeError => (),
|
||||||
err => panic!("Unexpected error {}", err),
|
err => panic!("Unexpected error {}", err),
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_row_and_then_custom_error() {
|
fn test_query_row_and_then_custom_error() -> CustomResult<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
let sql = "BEGIN;
|
let sql = "BEGIN;
|
||||||
CREATE TABLE foo(x INTEGER, y TEXT);
|
CREATE TABLE foo(x INTEGER, y TEXT);
|
||||||
INSERT INTO foo VALUES(4, \"hello\");
|
INSERT INTO foo VALUES(4, \"hello\");
|
||||||
END;";
|
END;";
|
||||||
db.execute_batch(sql).unwrap();
|
db.execute_batch(sql)?;
|
||||||
|
|
||||||
let query = "SELECT x, y FROM foo ORDER BY x DESC";
|
let query = "SELECT x, y FROM foo ORDER BY x DESC";
|
||||||
let results: CustomResult<String> =
|
let results: CustomResult<String> =
|
||||||
db.query_row_and_then(query, [], |row| row.get(1).map_err(CustomError::Sqlite));
|
db.query_row_and_then(query, [], |row| row.get(1).map_err(CustomError::Sqlite));
|
||||||
|
|
||||||
assert_eq!(results.unwrap(), "hello");
|
assert_eq!(results?, "hello");
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_row_and_then_custom_error_fails() {
|
fn test_query_row_and_then_custom_error_fails() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
let sql = "BEGIN;
|
let sql = "BEGIN;
|
||||||
CREATE TABLE foo(x INTEGER, y TEXT);
|
CREATE TABLE foo(x INTEGER, y TEXT);
|
||||||
INSERT INTO foo VALUES(4, \"hello\");
|
INSERT INTO foo VALUES(4, \"hello\");
|
||||||
END;";
|
END;";
|
||||||
db.execute_batch(sql).unwrap();
|
db.execute_batch(sql)?;
|
||||||
|
|
||||||
let query = "SELECT x, y FROM foo ORDER BY x DESC";
|
let query = "SELECT x, y FROM foo ORDER BY x DESC";
|
||||||
let bad_type: CustomResult<f64> =
|
let bad_type: CustomResult<f64> =
|
||||||
@ -1845,39 +1838,38 @@ mod test {
|
|||||||
CustomError::SomeError => (),
|
CustomError::SomeError => (),
|
||||||
err => panic!("Unexpected error {}", err),
|
err => panic!("Unexpected error {}", err),
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_dynamic() {
|
fn test_dynamic() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
let sql = "BEGIN;
|
let sql = "BEGIN;
|
||||||
CREATE TABLE foo(x INTEGER, y TEXT);
|
CREATE TABLE foo(x INTEGER, y TEXT);
|
||||||
INSERT INTO foo VALUES(4, \"hello\");
|
INSERT INTO foo VALUES(4, \"hello\");
|
||||||
END;";
|
END;";
|
||||||
db.execute_batch(sql).unwrap();
|
db.execute_batch(sql)?;
|
||||||
|
|
||||||
db.query_row("SELECT * FROM foo", [], |r| {
|
db.query_row("SELECT * FROM foo", [], |r| {
|
||||||
assert_eq!(2, r.column_count());
|
assert_eq!(2, r.column_count());
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_dyn_box() {
|
fn test_dyn_box() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
db.execute_batch("CREATE TABLE foo(x INTEGER);").unwrap();
|
db.execute_batch("CREATE TABLE foo(x INTEGER);")?;
|
||||||
let b: Box<dyn ToSql> = Box::new(5);
|
let b: Box<dyn ToSql> = Box::new(5);
|
||||||
db.execute("INSERT INTO foo VALUES(?)", [b]).unwrap();
|
db.execute("INSERT INTO foo VALUES(?)", [b])?;
|
||||||
db.query_row("SELECT x FROM foo", [], |r| {
|
db.query_row("SELECT x FROM foo", [], |r| {
|
||||||
assert_eq!(5, r.get_unwrap::<_, i32>(0));
|
assert_eq!(5, r.get_unwrap::<_, i32>(0));
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_params() {
|
fn test_params() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
db.query_row(
|
db.query_row(
|
||||||
"SELECT
|
"SELECT
|
||||||
@ -1894,20 +1886,20 @@ mod test {
|
|||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(not(feature = "extra_check"))]
|
#[cfg(not(feature = "extra_check"))]
|
||||||
fn test_alter_table() {
|
fn test_alter_table() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
db.execute_batch("CREATE TABLE x(t);").unwrap();
|
db.execute_batch("CREATE TABLE x(t);")?;
|
||||||
// `execute_batch` should be used but `execute` should also work
|
// `execute_batch` should be used but `execute` should also work
|
||||||
db.execute("ALTER TABLE x RENAME TO y;", []).unwrap();
|
db.execute("ALTER TABLE x RENAME TO y;", [])?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_batch() {
|
fn test_batch() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
let sql = r"
|
let sql = r"
|
||||||
CREATE TABLE tbl1 (col);
|
CREATE TABLE tbl1 (col);
|
||||||
@ -1915,8 +1907,9 @@ mod test {
|
|||||||
";
|
";
|
||||||
let batch = Batch::new(&db, sql);
|
let batch = Batch::new(&db, sql);
|
||||||
for stmt in batch {
|
for stmt in batch {
|
||||||
let mut stmt = stmt.unwrap();
|
let mut stmt = stmt?;
|
||||||
stmt.execute([]).unwrap();
|
stmt.execute([])?;
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,11 +27,11 @@ impl Connection {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::ffi::Limit;
|
use crate::ffi::Limit;
|
||||||
use crate::Connection;
|
use crate::{Connection, Result};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_limit() {
|
fn test_limit() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.set_limit(Limit::SQLITE_LIMIT_LENGTH, 1024);
|
db.set_limit(Limit::SQLITE_LIMIT_LENGTH, 1024);
|
||||||
assert_eq!(1024, db.limit(Limit::SQLITE_LIMIT_LENGTH));
|
assert_eq!(1024, db.limit(Limit::SQLITE_LIMIT_LENGTH));
|
||||||
|
|
||||||
@ -70,5 +70,6 @@ mod test {
|
|||||||
db.set_limit(Limit::SQLITE_LIMIT_WORKER_THREADS, 2);
|
db.set_limit(Limit::SQLITE_LIMIT_WORKER_THREADS, 2);
|
||||||
assert_eq!(2, db.limit(Limit::SQLITE_LIMIT_WORKER_THREADS));
|
assert_eq!(2, db.limit(Limit::SQLITE_LIMIT_WORKER_THREADS));
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -314,95 +314,95 @@ fn is_identifier_continue(c: char) -> bool {
|
|||||||
mod test {
|
mod test {
|
||||||
use super::Sql;
|
use super::Sql;
|
||||||
use crate::pragma;
|
use crate::pragma;
|
||||||
use crate::{Connection, DatabaseName};
|
use crate::{Connection, DatabaseName, Result};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pragma_query_value() {
|
fn pragma_query_value() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let user_version: i32 = db
|
let user_version: i32 = db.pragma_query_value(None, "user_version", |row| row.get(0))?;
|
||||||
.pragma_query_value(None, "user_version", |row| row.get(0))
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(0, user_version);
|
assert_eq!(0, user_version);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "modern_sqlite")]
|
#[cfg(feature = "modern_sqlite")]
|
||||||
fn pragma_func_query_value() {
|
fn pragma_func_query_value() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let user_version: i32 = db
|
let user_version: i32 =
|
||||||
.query_row("SELECT user_version FROM pragma_user_version", [], |row| {
|
db.query_row("SELECT user_version FROM pragma_user_version", [], |row| {
|
||||||
row.get(0)
|
row.get(0)
|
||||||
})
|
})?;
|
||||||
.unwrap();
|
|
||||||
assert_eq!(0, user_version);
|
assert_eq!(0, user_version);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pragma_query_no_schema() {
|
fn pragma_query_no_schema() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let mut user_version = -1;
|
let mut user_version = -1;
|
||||||
db.pragma_query(None, "user_version", |row| {
|
db.pragma_query(None, "user_version", |row| {
|
||||||
user_version = row.get(0)?;
|
user_version = row.get(0)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})?;
|
||||||
.unwrap();
|
|
||||||
assert_eq!(0, user_version);
|
assert_eq!(0, user_version);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pragma_query_with_schema() {
|
fn pragma_query_with_schema() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let mut user_version = -1;
|
let mut user_version = -1;
|
||||||
db.pragma_query(Some(DatabaseName::Main), "user_version", |row| {
|
db.pragma_query(Some(DatabaseName::Main), "user_version", |row| {
|
||||||
user_version = row.get(0)?;
|
user_version = row.get(0)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})?;
|
||||||
.unwrap();
|
|
||||||
assert_eq!(0, user_version);
|
assert_eq!(0, user_version);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pragma() {
|
fn pragma() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let mut columns = Vec::new();
|
let mut columns = Vec::new();
|
||||||
db.pragma(None, "table_info", &"sqlite_master", |row| {
|
db.pragma(None, "table_info", &"sqlite_master", |row| {
|
||||||
let column: String = row.get(1)?;
|
let column: String = row.get(1)?;
|
||||||
columns.push(column);
|
columns.push(column);
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})?;
|
||||||
.unwrap();
|
|
||||||
assert_eq!(5, columns.len());
|
assert_eq!(5, columns.len());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "modern_sqlite")]
|
#[cfg(feature = "modern_sqlite")]
|
||||||
fn pragma_func() {
|
fn pragma_func() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let mut table_info = db.prepare("SELECT * FROM pragma_table_info(?)").unwrap();
|
let mut table_info = db.prepare("SELECT * FROM pragma_table_info(?)")?;
|
||||||
let mut columns = Vec::new();
|
let mut columns = Vec::new();
|
||||||
let mut rows = table_info.query(&["sqlite_master"]).unwrap();
|
let mut rows = table_info.query(&["sqlite_master"])?;
|
||||||
|
|
||||||
while let Some(row) = rows.next().unwrap() {
|
while let Some(row) = rows.next()? {
|
||||||
let row = row;
|
let row = row;
|
||||||
let column: String = row.get(1).unwrap();
|
let column: String = row.get(1)?;
|
||||||
columns.push(column);
|
columns.push(column);
|
||||||
}
|
}
|
||||||
assert_eq!(5, columns.len());
|
assert_eq!(5, columns.len());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pragma_update() {
|
fn pragma_update() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.pragma_update(None, "user_version", &1).unwrap();
|
db.pragma_update(None, "user_version", &1)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pragma_update_and_check() {
|
fn pragma_update_and_check() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let journal_mode: String = db
|
let journal_mode: String =
|
||||||
.pragma_update_and_check(None, "journal_mode", &"OFF", |row| row.get(0))
|
db.pragma_update_and_check(None, "journal_mode", &"OFF", |row| row.get(0))?;
|
||||||
.unwrap();
|
|
||||||
assert_eq!("off", &journal_mode);
|
assert_eq!("off", &journal_mode);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -428,13 +428,14 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn locking_mode() {
|
fn locking_mode() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let r = db.pragma_update(None, "locking_mode", &"exclusive");
|
let r = db.pragma_update(None, "locking_mode", &"exclusive");
|
||||||
if cfg!(feature = "extra_check") {
|
if cfg!(feature = "extra_check") {
|
||||||
r.unwrap_err();
|
r.unwrap_err();
|
||||||
} else {
|
} else {
|
||||||
r.unwrap();
|
r?;
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
52
src/row.rs
52
src/row.rs
@ -413,53 +413,46 @@ tuples_try_from_row!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::redundant_closure)] // false positives due to lifetime issues; clippy issue #5594
|
#![allow(clippy::redundant_closure)] // false positives due to lifetime issues; clippy issue #5594
|
||||||
|
use crate::{Connection, Result};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_try_from_row_for_tuple_1() {
|
fn test_try_from_row_for_tuple_1() -> Result<()> {
|
||||||
use crate::{Connection, ToSql};
|
use crate::ToSql;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
let conn = Connection::open_in_memory().expect("failed to create in-memoory database");
|
let conn = Connection::open_in_memory()?;
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"CREATE TABLE test (a INTEGER)",
|
"CREATE TABLE test (a INTEGER)",
|
||||||
crate::params_from_iter(std::iter::empty::<&dyn ToSql>()),
|
crate::params_from_iter(std::iter::empty::<&dyn ToSql>()),
|
||||||
)
|
)?;
|
||||||
.expect("failed to create table");
|
conn.execute("INSERT INTO test VALUES (42)", [])?;
|
||||||
conn.execute("INSERT INTO test VALUES (42)", [])
|
let val = conn.query_row("SELECT a FROM test", [], |row| <(u32,)>::try_from(row))?;
|
||||||
.expect("failed to insert value");
|
|
||||||
let val = conn
|
|
||||||
.query_row("SELECT a FROM test", [], |row| <(u32,)>::try_from(row))
|
|
||||||
.expect("failed to query row");
|
|
||||||
assert_eq!(val, (42,));
|
assert_eq!(val, (42,));
|
||||||
let fail = conn.query_row("SELECT a FROM test", [], |row| <(u32, u32)>::try_from(row));
|
let fail = conn.query_row("SELECT a FROM test", [], |row| <(u32, u32)>::try_from(row));
|
||||||
assert!(fail.is_err());
|
assert!(fail.is_err());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_try_from_row_for_tuple_2() {
|
fn test_try_from_row_for_tuple_2() -> Result<()> {
|
||||||
use crate::Connection;
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
let conn = Connection::open_in_memory().expect("failed to create in-memoory database");
|
let conn = Connection::open_in_memory()?;
|
||||||
conn.execute("CREATE TABLE test (a INTEGER, b INTEGER)", [])
|
conn.execute("CREATE TABLE test (a INTEGER, b INTEGER)", [])?;
|
||||||
.expect("failed to create table");
|
conn.execute("INSERT INTO test VALUES (42, 47)", [])?;
|
||||||
conn.execute("INSERT INTO test VALUES (42, 47)", [])
|
let val = conn.query_row("SELECT a, b FROM test", [], |row| {
|
||||||
.expect("failed to insert value");
|
|
||||||
let val = conn
|
|
||||||
.query_row("SELECT a, b FROM test", [], |row| {
|
|
||||||
<(u32, u32)>::try_from(row)
|
<(u32, u32)>::try_from(row)
|
||||||
})
|
})?;
|
||||||
.expect("failed to query row");
|
|
||||||
assert_eq!(val, (42, 47));
|
assert_eq!(val, (42, 47));
|
||||||
let fail = conn.query_row("SELECT a, b FROM test", [], |row| {
|
let fail = conn.query_row("SELECT a, b FROM test", [], |row| {
|
||||||
<(u32, u32, u32)>::try_from(row)
|
<(u32, u32, u32)>::try_from(row)
|
||||||
});
|
});
|
||||||
assert!(fail.is_err());
|
assert!(fail.is_err());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_try_from_row_for_tuple_16() {
|
fn test_try_from_row_for_tuple_16() -> Result<()> {
|
||||||
use crate::Connection;
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
let create_table = "CREATE TABLE test (
|
let create_table = "CREATE TABLE test (
|
||||||
@ -519,14 +512,10 @@ mod tests {
|
|||||||
u32,
|
u32,
|
||||||
);
|
);
|
||||||
|
|
||||||
let conn = Connection::open_in_memory().expect("failed to create in-memoory database");
|
let conn = Connection::open_in_memory()?;
|
||||||
conn.execute(create_table, [])
|
conn.execute(create_table, [])?;
|
||||||
.expect("failed to create table");
|
conn.execute(insert_values, [])?;
|
||||||
conn.execute(insert_values, [])
|
let val = conn.query_row("SELECT * FROM test", [], |row| BigTuple::try_from(row))?;
|
||||||
.expect("failed to insert value");
|
|
||||||
let val = conn
|
|
||||||
.query_row("SELECT * FROM test", [], |row| BigTuple::try_from(row))
|
|
||||||
.expect("failed to query row");
|
|
||||||
// Debug is not implemented for tuples of 16
|
// Debug is not implemented for tuples of 16
|
||||||
assert_eq!(val.0, 0);
|
assert_eq!(val.0, 0);
|
||||||
assert_eq!(val.1, 1);
|
assert_eq!(val.1, 1);
|
||||||
@ -546,5 +535,6 @@ mod tests {
|
|||||||
assert_eq!(val.15, 15);
|
assert_eq!(val.15, 15);
|
||||||
|
|
||||||
// We don't test one bigger because it's unimplemented
|
// We don't test one bigger because it's unimplemented
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
130
src/session.rs
130
src/session.rs
@ -781,80 +781,77 @@ mod test {
|
|||||||
|
|
||||||
use super::{Changeset, ChangesetIter, ConflictAction, ConflictType, Session};
|
use super::{Changeset, ChangesetIter, ConflictAction, ConflictType, Session};
|
||||||
use crate::hooks::Action;
|
use crate::hooks::Action;
|
||||||
use crate::Connection;
|
use crate::{Connection, Result};
|
||||||
|
|
||||||
fn one_changeset() -> Changeset {
|
fn one_changeset() -> Result<Changeset> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.execute_batch("CREATE TABLE foo(t TEXT PRIMARY KEY NOT NULL);")
|
db.execute_batch("CREATE TABLE foo(t TEXT PRIMARY KEY NOT NULL);")?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut session = Session::new(&db).unwrap();
|
let mut session = Session::new(&db)?;
|
||||||
assert!(session.is_empty());
|
assert!(session.is_empty());
|
||||||
|
|
||||||
session.attach(None).unwrap();
|
session.attach(None)?;
|
||||||
db.execute("INSERT INTO foo (t) VALUES (?);", &["bar"])
|
db.execute("INSERT INTO foo (t) VALUES (?);", &["bar"])?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
session.changeset().unwrap()
|
session.changeset()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn one_changeset_strm() -> Vec<u8> {
|
fn one_changeset_strm() -> Result<Vec<u8>> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.execute_batch("CREATE TABLE foo(t TEXT PRIMARY KEY NOT NULL);")
|
db.execute_batch("CREATE TABLE foo(t TEXT PRIMARY KEY NOT NULL);")?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut session = Session::new(&db).unwrap();
|
let mut session = Session::new(&db)?;
|
||||||
assert!(session.is_empty());
|
assert!(session.is_empty());
|
||||||
|
|
||||||
session.attach(None).unwrap();
|
session.attach(None)?;
|
||||||
db.execute("INSERT INTO foo (t) VALUES (?);", &["bar"])
|
db.execute("INSERT INTO foo (t) VALUES (?);", &["bar"])?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut output = Vec::new();
|
let mut output = Vec::new();
|
||||||
session.changeset_strm(&mut output).unwrap();
|
session.changeset_strm(&mut output)?;
|
||||||
output
|
Ok(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_changeset() {
|
fn test_changeset() -> Result<()> {
|
||||||
let changeset = one_changeset();
|
let changeset = one_changeset()?;
|
||||||
let mut iter = changeset.iter().unwrap();
|
let mut iter = changeset.iter()?;
|
||||||
let item = iter.next().unwrap();
|
let item = iter.next()?;
|
||||||
assert!(item.is_some());
|
assert!(item.is_some());
|
||||||
|
|
||||||
let item = item.unwrap();
|
let item = item.unwrap();
|
||||||
let op = item.op().unwrap();
|
let op = item.op()?;
|
||||||
assert_eq!("foo", op.table_name());
|
assert_eq!("foo", op.table_name());
|
||||||
assert_eq!(1, op.number_of_columns());
|
assert_eq!(1, op.number_of_columns());
|
||||||
assert_eq!(Action::SQLITE_INSERT, op.code());
|
assert_eq!(Action::SQLITE_INSERT, op.code());
|
||||||
assert_eq!(false, op.indirect());
|
assert_eq!(false, op.indirect());
|
||||||
|
|
||||||
let pk = item.pk().unwrap();
|
let pk = item.pk()?;
|
||||||
assert_eq!(&[1], pk);
|
assert_eq!(&[1], pk);
|
||||||
|
|
||||||
let new_value = item.new_value(0).unwrap();
|
let new_value = item.new_value(0)?;
|
||||||
assert_eq!(Ok("bar"), new_value.as_str());
|
assert_eq!(Ok("bar"), new_value.as_str());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_changeset_strm() {
|
fn test_changeset_strm() -> Result<()> {
|
||||||
let output = one_changeset_strm();
|
let output = one_changeset_strm()?;
|
||||||
assert!(!output.is_empty());
|
assert!(!output.is_empty());
|
||||||
assert_eq!(14, output.len());
|
assert_eq!(14, output.len());
|
||||||
|
|
||||||
let input: &mut dyn Read = &mut output.as_slice();
|
let input: &mut dyn Read = &mut output.as_slice();
|
||||||
let mut iter = ChangesetIter::start_strm(&input).unwrap();
|
let mut iter = ChangesetIter::start_strm(&input)?;
|
||||||
let item = iter.next().unwrap();
|
let item = iter.next()?;
|
||||||
assert!(item.is_some());
|
assert!(item.is_some());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_changeset_apply() {
|
fn test_changeset_apply() -> Result<()> {
|
||||||
let changeset = one_changeset();
|
let changeset = one_changeset()?;
|
||||||
|
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.execute_batch("CREATE TABLE foo(t TEXT PRIMARY KEY NOT NULL);")
|
db.execute_batch("CREATE TABLE foo(t TEXT PRIMARY KEY NOT NULL);")?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
static CALLED: AtomicBool = AtomicBool::new(false);
|
static CALLED: AtomicBool = AtomicBool::new(false);
|
||||||
db.apply(
|
db.apply(
|
||||||
@ -864,15 +861,12 @@ mod test {
|
|||||||
CALLED.store(true, Ordering::Relaxed);
|
CALLED.store(true, Ordering::Relaxed);
|
||||||
ConflictAction::SQLITE_CHANGESET_OMIT
|
ConflictAction::SQLITE_CHANGESET_OMIT
|
||||||
},
|
},
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert!(!CALLED.load(Ordering::Relaxed));
|
assert!(!CALLED.load(Ordering::Relaxed));
|
||||||
let check = db
|
let check = db.query_row("SELECT 1 FROM foo WHERE t = ?", &["bar"], |row| {
|
||||||
.query_row("SELECT 1 FROM foo WHERE t = ?", &["bar"], |row| {
|
|
||||||
row.get::<_, i32>(0)
|
row.get::<_, i32>(0)
|
||||||
})
|
})?;
|
||||||
.unwrap();
|
|
||||||
assert_eq!(1, check);
|
assert_eq!(1, check);
|
||||||
|
|
||||||
// conflict expected when same changeset applied again on the same db
|
// conflict expected when same changeset applied again on the same db
|
||||||
@ -886,68 +880,66 @@ mod test {
|
|||||||
assert_eq!(Ok("bar"), conflict.as_str());
|
assert_eq!(Ok("bar"), conflict.as_str());
|
||||||
ConflictAction::SQLITE_CHANGESET_OMIT
|
ConflictAction::SQLITE_CHANGESET_OMIT
|
||||||
},
|
},
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
assert!(CALLED.load(Ordering::Relaxed));
|
assert!(CALLED.load(Ordering::Relaxed));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_changeset_apply_strm() {
|
fn test_changeset_apply_strm() -> Result<()> {
|
||||||
let output = one_changeset_strm();
|
let output = one_changeset_strm()?;
|
||||||
|
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.execute_batch("CREATE TABLE foo(t TEXT PRIMARY KEY NOT NULL);")
|
db.execute_batch("CREATE TABLE foo(t TEXT PRIMARY KEY NOT NULL);")?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut input = output.as_slice();
|
let mut input = output.as_slice();
|
||||||
db.apply_strm(
|
db.apply_strm(
|
||||||
&mut input,
|
&mut input,
|
||||||
None::<fn(&str) -> bool>,
|
None::<fn(&str) -> bool>,
|
||||||
|_conflict_type, _item| ConflictAction::SQLITE_CHANGESET_OMIT,
|
|_conflict_type, _item| ConflictAction::SQLITE_CHANGESET_OMIT,
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let check = db
|
let check = db.query_row("SELECT 1 FROM foo WHERE t = ?", &["bar"], |row| {
|
||||||
.query_row("SELECT 1 FROM foo WHERE t = ?", &["bar"], |row| {
|
|
||||||
row.get::<_, i32>(0)
|
row.get::<_, i32>(0)
|
||||||
})
|
})?;
|
||||||
.unwrap();
|
|
||||||
assert_eq!(1, check);
|
assert_eq!(1, check);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_session_empty() {
|
fn test_session_empty() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.execute_batch("CREATE TABLE foo(t TEXT PRIMARY KEY NOT NULL);")
|
db.execute_batch("CREATE TABLE foo(t TEXT PRIMARY KEY NOT NULL);")?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut session = Session::new(&db).unwrap();
|
let mut session = Session::new(&db)?;
|
||||||
assert!(session.is_empty());
|
assert!(session.is_empty());
|
||||||
|
|
||||||
session.attach(None).unwrap();
|
session.attach(None)?;
|
||||||
db.execute("INSERT INTO foo (t) VALUES (?);", &["bar"])
|
db.execute("INSERT INTO foo (t) VALUES (?);", &["bar"])?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert!(!session.is_empty());
|
assert!(!session.is_empty());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_session_set_enabled() {
|
fn test_session_set_enabled() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
|
|
||||||
let mut session = Session::new(&db).unwrap();
|
let mut session = Session::new(&db)?;
|
||||||
assert!(session.is_enabled());
|
assert!(session.is_enabled());
|
||||||
session.set_enabled(false);
|
session.set_enabled(false);
|
||||||
assert!(!session.is_enabled());
|
assert!(!session.is_enabled());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_session_set_indirect() {
|
fn test_session_set_indirect() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
|
|
||||||
let mut session = Session::new(&db).unwrap();
|
let mut session = Session::new(&db)?;
|
||||||
assert!(!session.is_indirect());
|
assert!(!session.is_indirect());
|
||||||
session.set_indirect(true);
|
session.set_indirect(true);
|
||||||
assert!(session.is_indirect());
|
assert!(session.is_indirect());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
353
src/statement.rs
353
src/statement.rs
@ -940,26 +940,23 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
fn test_execute_named() {
|
fn test_execute_named() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.execute_batch("CREATE TABLE foo(x INTEGER)").unwrap();
|
db.execute_batch("CREATE TABLE foo(x INTEGER)")?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
db.execute_named("INSERT INTO foo(x) VALUES (:x)", &[(":x", &1i32)])
|
db.execute_named("INSERT INTO foo(x) VALUES (:x)", &[(":x", &1i32)])?,
|
||||||
.unwrap(),
|
|
||||||
1
|
1
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
db.execute("INSERT INTO foo(x) VALUES (:x)", &[(":x", &2i32)])
|
db.execute("INSERT INTO foo(x) VALUES (:x)", &[(":x", &2i32)])?,
|
||||||
.unwrap(),
|
|
||||||
1
|
1
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
db.execute(
|
db.execute(
|
||||||
"INSERT INTO foo(x) VALUES (:x)",
|
"INSERT INTO foo(x) VALUES (:x)",
|
||||||
crate::named_params! {":x": 3i32}
|
crate::named_params! {":x": 3i32}
|
||||||
)
|
)?,
|
||||||
.unwrap(),
|
|
||||||
1
|
1
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -969,8 +966,7 @@ mod test {
|
|||||||
"SELECT SUM(x) FROM foo WHERE x > :x",
|
"SELECT SUM(x) FROM foo WHERE x > :x",
|
||||||
&[(":x", &0i32)],
|
&[(":x", &0i32)],
|
||||||
|r| r.get(0)
|
|r| r.get(0)
|
||||||
)
|
)?
|
||||||
.unwrap()
|
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
5i32,
|
5i32,
|
||||||
@ -978,133 +974,118 @@ mod test {
|
|||||||
"SELECT SUM(x) FROM foo WHERE x > :x",
|
"SELECT SUM(x) FROM foo WHERE x > :x",
|
||||||
&[(":x", &1i32)],
|
&[(":x", &1i32)],
|
||||||
|r| r.get(0)
|
|r| r.get(0)
|
||||||
)
|
)?
|
||||||
.unwrap()
|
|
||||||
);
|
);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
fn test_stmt_execute_named() {
|
fn test_stmt_execute_named() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let sql = "CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag \
|
let sql = "CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag \
|
||||||
INTEGER)";
|
INTEGER)";
|
||||||
db.execute_batch(sql).unwrap();
|
db.execute_batch(sql)?;
|
||||||
|
|
||||||
let mut stmt = db
|
let mut stmt = db.prepare("INSERT INTO test (name) VALUES (:name)")?;
|
||||||
.prepare("INSERT INTO test (name) VALUES (:name)")
|
stmt.execute_named(&[(":name", &"one")])?;
|
||||||
.unwrap();
|
|
||||||
stmt.execute_named(&[(":name", &"one")]).unwrap();
|
|
||||||
|
|
||||||
let mut stmt = db
|
let mut stmt = db.prepare("SELECT COUNT(*) FROM test WHERE name = :name")?;
|
||||||
.prepare("SELECT COUNT(*) FROM test WHERE name = :name")
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
1i32,
|
1i32,
|
||||||
stmt.query_row_named::<i32, _>(&[(":name", &"one")], |r| r.get(0))
|
stmt.query_row_named::<i32, _>(&[(":name", &"one")], |r| r.get(0))?
|
||||||
.unwrap()
|
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
1i32,
|
1i32,
|
||||||
stmt.query_row::<i32, _, _>(&[(":name", &"one")], |r| r.get(0))
|
stmt.query_row::<i32, _, _>(&[(":name", &"one")], |r| r.get(0))?
|
||||||
.unwrap()
|
|
||||||
);
|
);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
fn test_query_named() {
|
fn test_query_named() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let sql = r#"
|
let sql = r#"
|
||||||
CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag INTEGER);
|
CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag INTEGER);
|
||||||
INSERT INTO test(id, name) VALUES (1, "one");
|
INSERT INTO test(id, name) VALUES (1, "one");
|
||||||
"#;
|
"#;
|
||||||
db.execute_batch(sql).unwrap();
|
db.execute_batch(sql)?;
|
||||||
|
|
||||||
let mut stmt = db
|
let mut stmt = db.prepare("SELECT id FROM test where name = :name")?;
|
||||||
.prepare("SELECT id FROM test where name = :name")
|
|
||||||
.unwrap();
|
|
||||||
// legacy `_named` api
|
// legacy `_named` api
|
||||||
{
|
{
|
||||||
let mut rows = stmt.query_named(&[(":name", &"one")]).unwrap();
|
let mut rows = stmt.query_named(&[(":name", &"one")])?;
|
||||||
let id: Result<i32> = rows.next().unwrap().unwrap().get(0);
|
let id: Result<i32> = rows.next()?.unwrap().get(0);
|
||||||
assert_eq!(Ok(1), id);
|
assert_eq!(Ok(1), id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// plain api
|
// plain api
|
||||||
{
|
{
|
||||||
let mut rows = stmt.query(&[(":name", &"one")]).unwrap();
|
let mut rows = stmt.query(&[(":name", &"one")])?;
|
||||||
let id: Result<i32> = rows.next().unwrap().unwrap().get(0);
|
let id: Result<i32> = rows.next()?.unwrap().get(0);
|
||||||
assert_eq!(Ok(1), id);
|
assert_eq!(Ok(1), id);
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
fn test_query_map_named() {
|
fn test_query_map_named() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let sql = r#"
|
let sql = r#"
|
||||||
CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag INTEGER);
|
CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag INTEGER);
|
||||||
INSERT INTO test(id, name) VALUES (1, "one");
|
INSERT INTO test(id, name) VALUES (1, "one");
|
||||||
"#;
|
"#;
|
||||||
db.execute_batch(sql).unwrap();
|
db.execute_batch(sql)?;
|
||||||
|
|
||||||
let mut stmt = db
|
let mut stmt = db.prepare("SELECT id FROM test where name = :name")?;
|
||||||
.prepare("SELECT id FROM test where name = :name")
|
|
||||||
.unwrap();
|
|
||||||
// legacy `_named` api
|
// legacy `_named` api
|
||||||
{
|
{
|
||||||
let mut rows = stmt
|
let mut rows = stmt.query_map_named(&[(":name", &"one")], |row| {
|
||||||
.query_map_named(&[(":name", &"one")], |row| {
|
|
||||||
let id: Result<i32> = row.get(0);
|
let id: Result<i32> = row.get(0);
|
||||||
id.map(|i| 2 * i)
|
id.map(|i| 2 * i)
|
||||||
})
|
})?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let doubled_id: i32 = rows.next().unwrap().unwrap();
|
let doubled_id: i32 = rows.next().unwrap()?;
|
||||||
assert_eq!(2, doubled_id);
|
assert_eq!(2, doubled_id);
|
||||||
}
|
}
|
||||||
// plain api
|
// plain api
|
||||||
{
|
{
|
||||||
let mut rows = stmt
|
let mut rows = stmt.query_map(&[(":name", &"one")], |row| {
|
||||||
.query_map(&[(":name", &"one")], |row| {
|
|
||||||
let id: Result<i32> = row.get(0);
|
let id: Result<i32> = row.get(0);
|
||||||
id.map(|i| 2 * i)
|
id.map(|i| 2 * i)
|
||||||
})
|
})?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let doubled_id: i32 = rows.next().unwrap().unwrap();
|
let doubled_id: i32 = rows.next().unwrap()?;
|
||||||
assert_eq!(2, doubled_id);
|
assert_eq!(2, doubled_id);
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
fn test_query_and_then_named() {
|
fn test_query_and_then_named() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let sql = r#"
|
let sql = r#"
|
||||||
CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag INTEGER);
|
CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag INTEGER);
|
||||||
INSERT INTO test(id, name) VALUES (1, "one");
|
INSERT INTO test(id, name) VALUES (1, "one");
|
||||||
INSERT INTO test(id, name) VALUES (2, "one");
|
INSERT INTO test(id, name) VALUES (2, "one");
|
||||||
"#;
|
"#;
|
||||||
db.execute_batch(sql).unwrap();
|
db.execute_batch(sql)?;
|
||||||
|
|
||||||
let mut stmt = db
|
let mut stmt = db.prepare("SELECT id FROM test where name = :name ORDER BY id ASC")?;
|
||||||
.prepare("SELECT id FROM test where name = :name ORDER BY id ASC")
|
let mut rows = stmt.query_and_then_named(&[(":name", &"one")], |row| {
|
||||||
.unwrap();
|
|
||||||
let mut rows = stmt
|
|
||||||
.query_and_then_named(&[(":name", &"one")], |row| {
|
|
||||||
let id: i32 = row.get(0)?;
|
let id: i32 = row.get(0)?;
|
||||||
if id == 1 {
|
if id == 1 {
|
||||||
Ok(id)
|
Ok(id)
|
||||||
} else {
|
} else {
|
||||||
Err(Error::SqliteSingleThreadedMode)
|
Err(Error::SqliteSingleThreadedMode)
|
||||||
}
|
}
|
||||||
})
|
})?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// first row should be Ok
|
// first row should be Ok
|
||||||
let doubled_id: i32 = rows.next().unwrap().unwrap();
|
let doubled_id: i32 = rows.next().unwrap()?;
|
||||||
assert_eq!(1, doubled_id);
|
assert_eq!(1, doubled_id);
|
||||||
|
|
||||||
// second row should be Err
|
// second row should be Err
|
||||||
@ -1114,34 +1095,31 @@ mod test {
|
|||||||
Err(Error::SqliteSingleThreadedMode) => (),
|
Err(Error::SqliteSingleThreadedMode) => (),
|
||||||
Err(_) => panic!("invalid Err"),
|
Err(_) => panic!("invalid Err"),
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_and_then_by_name() {
|
fn test_query_and_then_by_name() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let sql = r#"
|
let sql = r#"
|
||||||
CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag INTEGER);
|
CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag INTEGER);
|
||||||
INSERT INTO test(id, name) VALUES (1, "one");
|
INSERT INTO test(id, name) VALUES (1, "one");
|
||||||
INSERT INTO test(id, name) VALUES (2, "one");
|
INSERT INTO test(id, name) VALUES (2, "one");
|
||||||
"#;
|
"#;
|
||||||
db.execute_batch(sql).unwrap();
|
db.execute_batch(sql)?;
|
||||||
|
|
||||||
let mut stmt = db
|
let mut stmt = db.prepare("SELECT id FROM test where name = :name ORDER BY id ASC")?;
|
||||||
.prepare("SELECT id FROM test where name = :name ORDER BY id ASC")
|
let mut rows = stmt.query_and_then(&[(":name", &"one")], |row| {
|
||||||
.unwrap();
|
|
||||||
let mut rows = stmt
|
|
||||||
.query_and_then(&[(":name", &"one")], |row| {
|
|
||||||
let id: i32 = row.get(0)?;
|
let id: i32 = row.get(0)?;
|
||||||
if id == 1 {
|
if id == 1 {
|
||||||
Ok(id)
|
Ok(id)
|
||||||
} else {
|
} else {
|
||||||
Err(Error::SqliteSingleThreadedMode)
|
Err(Error::SqliteSingleThreadedMode)
|
||||||
}
|
}
|
||||||
})
|
})?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// first row should be Ok
|
// first row should be Ok
|
||||||
let doubled_id: i32 = rows.next().unwrap().unwrap();
|
let doubled_id: i32 = rows.next().unwrap()?;
|
||||||
assert_eq!(1, doubled_id);
|
assert_eq!(1, doubled_id);
|
||||||
|
|
||||||
// second row should be Err
|
// second row should be Err
|
||||||
@ -1151,29 +1129,28 @@ mod test {
|
|||||||
Err(Error::SqliteSingleThreadedMode) => (),
|
Err(Error::SqliteSingleThreadedMode) => (),
|
||||||
Err(_) => panic!("invalid Err"),
|
Err(_) => panic!("invalid Err"),
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
fn test_unbound_parameters_are_null() {
|
fn test_unbound_parameters_are_null() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let sql = "CREATE TABLE test (x TEXT, y TEXT)";
|
let sql = "CREATE TABLE test (x TEXT, y TEXT)";
|
||||||
db.execute_batch(sql).unwrap();
|
db.execute_batch(sql)?;
|
||||||
|
|
||||||
let mut stmt = db
|
let mut stmt = db.prepare("INSERT INTO test (x, y) VALUES (:x, :y)")?;
|
||||||
.prepare("INSERT INTO test (x, y) VALUES (:x, :y)")
|
stmt.execute_named(&[(":x", &"one")])?;
|
||||||
.unwrap();
|
|
||||||
stmt.execute_named(&[(":x", &"one")]).unwrap();
|
|
||||||
|
|
||||||
let result: Option<String> = db
|
let result: Option<String> =
|
||||||
.query_row("SELECT y FROM test WHERE x = 'one'", [], |row| row.get(0))
|
db.query_row("SELECT y FROM test WHERE x = 'one'", [], |row| row.get(0))?;
|
||||||
.unwrap();
|
|
||||||
assert!(result.is_none());
|
assert!(result.is_none());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_raw_binding() -> Result<()> {
|
fn test_raw_binding() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.execute_batch("CREATE TABLE test (name TEXT, value INTEGER)")?;
|
db.execute_batch("CREATE TABLE test (name TEXT, value INTEGER)")?;
|
||||||
{
|
{
|
||||||
let mut stmt = db.prepare("INSERT INTO test (name, value) VALUES (:name, ?3)")?;
|
let mut stmt = db.prepare("INSERT INTO test (name, value) VALUES (:name, ?3)")?;
|
||||||
@ -1203,164 +1180,147 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_unbound_parameters_are_reused() {
|
fn test_unbound_parameters_are_reused() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let sql = "CREATE TABLE test (x TEXT, y TEXT)";
|
let sql = "CREATE TABLE test (x TEXT, y TEXT)";
|
||||||
db.execute_batch(sql).unwrap();
|
db.execute_batch(sql)?;
|
||||||
|
|
||||||
let mut stmt = db
|
let mut stmt = db.prepare("INSERT INTO test (x, y) VALUES (:x, :y)")?;
|
||||||
.prepare("INSERT INTO test (x, y) VALUES (:x, :y)")
|
stmt.execute(&[(":x", &"one")])?;
|
||||||
.unwrap();
|
stmt.execute(&[(":y", &"two")])?;
|
||||||
stmt.execute(&[(":x", &"one")]).unwrap();
|
|
||||||
stmt.execute(&[(":y", &"two")]).unwrap();
|
|
||||||
|
|
||||||
let result: String = db
|
let result: String =
|
||||||
.query_row("SELECT x FROM test WHERE y = 'two'", [], |row| row.get(0))
|
db.query_row("SELECT x FROM test WHERE y = 'two'", [], |row| row.get(0))?;
|
||||||
.unwrap();
|
|
||||||
assert_eq!(result, "one");
|
assert_eq!(result, "one");
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_insert() {
|
fn test_insert() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.execute_batch("CREATE TABLE foo(x INTEGER UNIQUE)")
|
db.execute_batch("CREATE TABLE foo(x INTEGER UNIQUE)")?;
|
||||||
.unwrap();
|
let mut stmt = db.prepare("INSERT OR IGNORE INTO foo (x) VALUES (?)")?;
|
||||||
let mut stmt = db
|
assert_eq!(stmt.insert(&[&1i32])?, 1);
|
||||||
.prepare("INSERT OR IGNORE INTO foo (x) VALUES (?)")
|
assert_eq!(stmt.insert(&[&2i32])?, 2);
|
||||||
.unwrap();
|
|
||||||
assert_eq!(stmt.insert(&[&1i32]).unwrap(), 1);
|
|
||||||
assert_eq!(stmt.insert(&[&2i32]).unwrap(), 2);
|
|
||||||
match stmt.insert(&[&1i32]).unwrap_err() {
|
match stmt.insert(&[&1i32]).unwrap_err() {
|
||||||
Error::StatementChangedRows(0) => (),
|
Error::StatementChangedRows(0) => (),
|
||||||
err => panic!("Unexpected error {}", err),
|
err => panic!("Unexpected error {}", err),
|
||||||
}
|
}
|
||||||
let mut multi = db
|
let mut multi = db.prepare("INSERT INTO foo (x) SELECT 3 UNION ALL SELECT 4")?;
|
||||||
.prepare("INSERT INTO foo (x) SELECT 3 UNION ALL SELECT 4")
|
|
||||||
.unwrap();
|
|
||||||
match multi.insert([]).unwrap_err() {
|
match multi.insert([]).unwrap_err() {
|
||||||
Error::StatementChangedRows(2) => (),
|
Error::StatementChangedRows(2) => (),
|
||||||
err => panic!("Unexpected error {}", err),
|
err => panic!("Unexpected error {}", err),
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_insert_different_tables() {
|
fn test_insert_different_tables() -> Result<()> {
|
||||||
// Test for https://github.com/rusqlite/rusqlite/issues/171
|
// Test for https://github.com/rusqlite/rusqlite/issues/171
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.execute_batch(
|
db.execute_batch(
|
||||||
r"
|
r"
|
||||||
CREATE TABLE foo(x INTEGER);
|
CREATE TABLE foo(x INTEGER);
|
||||||
CREATE TABLE bar(x INTEGER);
|
CREATE TABLE bar(x INTEGER);
|
||||||
",
|
",
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(db.prepare("INSERT INTO foo VALUES (10)")?.insert([])?, 1);
|
||||||
db.prepare("INSERT INTO foo VALUES (10)")
|
assert_eq!(db.prepare("INSERT INTO bar VALUES (10)")?.insert([])?, 1);
|
||||||
.unwrap()
|
Ok(())
|
||||||
.insert([])
|
|
||||||
.unwrap(),
|
|
||||||
1
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
db.prepare("INSERT INTO bar VALUES (10)")
|
|
||||||
.unwrap()
|
|
||||||
.insert([])
|
|
||||||
.unwrap(),
|
|
||||||
1
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_exists() {
|
fn test_exists() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let sql = "BEGIN;
|
let sql = "BEGIN;
|
||||||
CREATE TABLE foo(x INTEGER);
|
CREATE TABLE foo(x INTEGER);
|
||||||
INSERT INTO foo VALUES(1);
|
INSERT INTO foo VALUES(1);
|
||||||
INSERT INTO foo VALUES(2);
|
INSERT INTO foo VALUES(2);
|
||||||
END;";
|
END;";
|
||||||
db.execute_batch(sql).unwrap();
|
db.execute_batch(sql)?;
|
||||||
let mut stmt = db.prepare("SELECT 1 FROM foo WHERE x = ?").unwrap();
|
let mut stmt = db.prepare("SELECT 1 FROM foo WHERE x = ?")?;
|
||||||
assert!(stmt.exists([1i32]).unwrap());
|
assert!(stmt.exists([1i32])?);
|
||||||
assert!(stmt.exists(&[&2i32]).unwrap());
|
assert!(stmt.exists(&[&2i32])?);
|
||||||
assert!(!stmt.exists([&0i32]).unwrap());
|
assert!(!stmt.exists([&0i32])?);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_row() {
|
fn test_query_row() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let sql = "BEGIN;
|
let sql = "BEGIN;
|
||||||
CREATE TABLE foo(x INTEGER, y INTEGER);
|
CREATE TABLE foo(x INTEGER, y INTEGER);
|
||||||
INSERT INTO foo VALUES(1, 3);
|
INSERT INTO foo VALUES(1, 3);
|
||||||
INSERT INTO foo VALUES(2, 4);
|
INSERT INTO foo VALUES(2, 4);
|
||||||
END;";
|
END;";
|
||||||
db.execute_batch(sql).unwrap();
|
db.execute_batch(sql)?;
|
||||||
let mut stmt = db.prepare("SELECT y FROM foo WHERE x = ?").unwrap();
|
let mut stmt = db.prepare("SELECT y FROM foo WHERE x = ?")?;
|
||||||
let y: Result<i64> = stmt.query_row([1i32], |r| r.get(0));
|
let y: Result<i64> = stmt.query_row([1i32], |r| r.get(0));
|
||||||
assert_eq!(3i64, y.unwrap());
|
assert_eq!(3i64, y?);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_by_column_name() {
|
fn test_query_by_column_name() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let sql = "BEGIN;
|
let sql = "BEGIN;
|
||||||
CREATE TABLE foo(x INTEGER, y INTEGER);
|
CREATE TABLE foo(x INTEGER, y INTEGER);
|
||||||
INSERT INTO foo VALUES(1, 3);
|
INSERT INTO foo VALUES(1, 3);
|
||||||
END;";
|
END;";
|
||||||
db.execute_batch(sql).unwrap();
|
db.execute_batch(sql)?;
|
||||||
let mut stmt = db.prepare("SELECT y FROM foo").unwrap();
|
let mut stmt = db.prepare("SELECT y FROM foo")?;
|
||||||
let y: Result<i64> = stmt.query_row([], |r| r.get("y"));
|
let y: Result<i64> = stmt.query_row([], |r| r.get("y"));
|
||||||
assert_eq!(3i64, y.unwrap());
|
assert_eq!(3i64, y?);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_query_by_column_name_ignore_case() {
|
fn test_query_by_column_name_ignore_case() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let sql = "BEGIN;
|
let sql = "BEGIN;
|
||||||
CREATE TABLE foo(x INTEGER, y INTEGER);
|
CREATE TABLE foo(x INTEGER, y INTEGER);
|
||||||
INSERT INTO foo VALUES(1, 3);
|
INSERT INTO foo VALUES(1, 3);
|
||||||
END;";
|
END;";
|
||||||
db.execute_batch(sql).unwrap();
|
db.execute_batch(sql)?;
|
||||||
let mut stmt = db.prepare("SELECT y as Y FROM foo").unwrap();
|
let mut stmt = db.prepare("SELECT y as Y FROM foo")?;
|
||||||
let y: Result<i64> = stmt.query_row([], |r| r.get("y"));
|
let y: Result<i64> = stmt.query_row([], |r| r.get("y"));
|
||||||
assert_eq!(3i64, y.unwrap());
|
assert_eq!(3i64, y?);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "modern_sqlite")]
|
#[cfg(feature = "modern_sqlite")]
|
||||||
fn test_expanded_sql() {
|
fn test_expanded_sql() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let stmt = db.prepare("SELECT ?").unwrap();
|
let stmt = db.prepare("SELECT ?")?;
|
||||||
stmt.bind_parameter(&1, 1).unwrap();
|
stmt.bind_parameter(&1, 1)?;
|
||||||
assert_eq!(Some("SELECT 1".to_owned()), stmt.expanded_sql());
|
assert_eq!(Some("SELECT 1".to_owned()), stmt.expanded_sql());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bind_parameters() {
|
fn test_bind_parameters() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
// dynamic slice:
|
// dynamic slice:
|
||||||
db.query_row(
|
db.query_row(
|
||||||
"SELECT ?1, ?2, ?3",
|
"SELECT ?1, ?2, ?3",
|
||||||
&[&1u8 as &dyn ToSql, &"one", &Some("one")],
|
&[&1u8 as &dyn ToSql, &"one", &Some("one")],
|
||||||
|row| row.get::<_, u8>(0),
|
|row| row.get::<_, u8>(0),
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
// existing collection:
|
// existing collection:
|
||||||
let data = vec![1, 2, 3];
|
let data = vec![1, 2, 3];
|
||||||
db.query_row("SELECT ?1, ?2, ?3", params_from_iter(&data), |row| {
|
db.query_row("SELECT ?1, ?2, ?3", params_from_iter(&data), |row| {
|
||||||
row.get::<_, u8>(0)
|
row.get::<_, u8>(0)
|
||||||
})
|
})?;
|
||||||
.unwrap();
|
|
||||||
db.query_row(
|
db.query_row(
|
||||||
"SELECT ?1, ?2, ?3",
|
"SELECT ?1, ?2, ?3",
|
||||||
params_from_iter(data.as_slice()),
|
params_from_iter(data.as_slice()),
|
||||||
|row| row.get::<_, u8>(0),
|
|row| row.get::<_, u8>(0),
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
db.query_row("SELECT ?1, ?2, ?3", params_from_iter(data), |row| {
|
db.query_row("SELECT ?1, ?2, ?3", params_from_iter(data), |row| {
|
||||||
row.get::<_, u8>(0)
|
row.get::<_, u8>(0)
|
||||||
})
|
})?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
let data: BTreeSet<String> = ["one", "two", "three"]
|
let data: BTreeSet<String> = ["one", "two", "three"]
|
||||||
@ -1369,76 +1329,73 @@ mod test {
|
|||||||
.collect();
|
.collect();
|
||||||
db.query_row("SELECT ?1, ?2, ?3", params_from_iter(&data), |row| {
|
db.query_row("SELECT ?1, ?2, ?3", params_from_iter(&data), |row| {
|
||||||
row.get::<_, String>(0)
|
row.get::<_, String>(0)
|
||||||
})
|
})?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let data = [0; 3];
|
let data = [0; 3];
|
||||||
db.query_row("SELECT ?1, ?2, ?3", params_from_iter(&data), |row| {
|
db.query_row("SELECT ?1, ?2, ?3", params_from_iter(&data), |row| {
|
||||||
row.get::<_, u8>(0)
|
row.get::<_, u8>(0)
|
||||||
})
|
})?;
|
||||||
.unwrap();
|
|
||||||
db.query_row("SELECT ?1, ?2, ?3", params_from_iter(data.iter()), |row| {
|
db.query_row("SELECT ?1, ?2, ?3", params_from_iter(data.iter()), |row| {
|
||||||
row.get::<_, u8>(0)
|
row.get::<_, u8>(0)
|
||||||
})
|
})?;
|
||||||
.unwrap();
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_empty_stmt() {
|
fn test_empty_stmt() -> Result<()> {
|
||||||
let conn = Connection::open_in_memory().unwrap();
|
let conn = Connection::open_in_memory()?;
|
||||||
let mut stmt = conn.prepare("").unwrap();
|
let mut stmt = conn.prepare("")?;
|
||||||
assert_eq!(0, stmt.column_count());
|
assert_eq!(0, stmt.column_count());
|
||||||
assert!(stmt.parameter_index("test").is_ok());
|
assert!(stmt.parameter_index("test").is_ok());
|
||||||
assert!(stmt.step().is_err());
|
assert!(stmt.step().is_err());
|
||||||
stmt.reset();
|
stmt.reset();
|
||||||
assert!(stmt.execute([]).is_err());
|
assert!(stmt.execute([]).is_err());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_comment_stmt() {
|
fn test_comment_stmt() -> Result<()> {
|
||||||
let conn = Connection::open_in_memory().unwrap();
|
let conn = Connection::open_in_memory()?;
|
||||||
conn.prepare("/*SELECT 1;*/").unwrap();
|
conn.prepare("/*SELECT 1;*/")?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_comment_and_sql_stmt() {
|
fn test_comment_and_sql_stmt() -> Result<()> {
|
||||||
let conn = Connection::open_in_memory().unwrap();
|
let conn = Connection::open_in_memory()?;
|
||||||
let stmt = conn.prepare("/*...*/ SELECT 1;").unwrap();
|
let stmt = conn.prepare("/*...*/ SELECT 1;")?;
|
||||||
assert_eq!(1, stmt.column_count());
|
assert_eq!(1, stmt.column_count());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_semi_colon_stmt() {
|
fn test_semi_colon_stmt() -> Result<()> {
|
||||||
let conn = Connection::open_in_memory().unwrap();
|
let conn = Connection::open_in_memory()?;
|
||||||
let stmt = conn.prepare(";").unwrap();
|
let stmt = conn.prepare(";")?;
|
||||||
assert_eq!(0, stmt.column_count());
|
assert_eq!(0, stmt.column_count());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_utf16_conversion() {
|
fn test_utf16_conversion() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.pragma_update(None, "encoding", &"UTF-16le").unwrap();
|
db.pragma_update(None, "encoding", &"UTF-16le")?;
|
||||||
let encoding: String = db
|
let encoding: String = db.pragma_query_value(None, "encoding", |row| row.get(0))?;
|
||||||
.pragma_query_value(None, "encoding", |row| row.get(0))
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!("UTF-16le", encoding);
|
assert_eq!("UTF-16le", encoding);
|
||||||
db.execute_batch("CREATE TABLE foo(x TEXT)").unwrap();
|
db.execute_batch("CREATE TABLE foo(x TEXT)")?;
|
||||||
let expected = "テスト";
|
let expected = "テスト";
|
||||||
db.execute("INSERT INTO foo(x) VALUES (?)", &[&expected])
|
db.execute("INSERT INTO foo(x) VALUES (?)", &[&expected])?;
|
||||||
.unwrap();
|
let actual: String = db.query_row("SELECT x FROM foo", [], |row| row.get(0))?;
|
||||||
let actual: String = db
|
|
||||||
.query_row("SELECT x FROM foo", [], |row| row.get(0))
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(expected, actual);
|
assert_eq!(expected, actual);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_nul_byte() {
|
fn test_nul_byte() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
let expected = "a\x00b";
|
let expected = "a\x00b";
|
||||||
let actual: String = db
|
let actual: String = db.query_row("SELECT ?", [expected], |row| row.get(0))?;
|
||||||
.query_row("SELECT ?", [expected], |row| row.get(0))
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(expected, actual);
|
assert_eq!(expected, actual);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
16
src/trace.rs
16
src/trace.rs
@ -128,10 +128,10 @@ mod test {
|
|||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::Connection;
|
use crate::{Connection, Result};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_trace() {
|
fn test_trace() -> Result<()> {
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref TRACED_STMTS: Mutex<Vec<String>> = Mutex::new(Vec::new());
|
static ref TRACED_STMTS: Mutex<Vec<String>> = Mutex::new(Vec::new());
|
||||||
}
|
}
|
||||||
@ -140,7 +140,7 @@ mod test {
|
|||||||
traced_stmts.push(s.to_owned());
|
traced_stmts.push(s.to_owned());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut db = Connection::open_in_memory().unwrap();
|
let mut db = Connection::open_in_memory()?;
|
||||||
db.trace(Some(tracer));
|
db.trace(Some(tracer));
|
||||||
{
|
{
|
||||||
let _ = db.query_row("SELECT ?", &[&1i32], |_| Ok(()));
|
let _ = db.query_row("SELECT ?", &[&1i32], |_| Ok(()));
|
||||||
@ -156,10 +156,11 @@ mod test {
|
|||||||
assert_eq!(traced_stmts.len(), 2);
|
assert_eq!(traced_stmts.len(), 2);
|
||||||
assert_eq!(traced_stmts[0], "SELECT 1");
|
assert_eq!(traced_stmts[0], "SELECT 1");
|
||||||
assert_eq!(traced_stmts[1], "SELECT 'hello'");
|
assert_eq!(traced_stmts[1], "SELECT 'hello'");
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_profile() {
|
fn test_profile() -> Result<()> {
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref PROFILED: Mutex<Vec<(String, Duration)>> = Mutex::new(Vec::new());
|
static ref PROFILED: Mutex<Vec<(String, Duration)>> = Mutex::new(Vec::new());
|
||||||
}
|
}
|
||||||
@ -168,14 +169,15 @@ mod test {
|
|||||||
profiled.push((s.to_owned(), d));
|
profiled.push((s.to_owned(), d));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut db = Connection::open_in_memory().unwrap();
|
let mut db = Connection::open_in_memory()?;
|
||||||
db.profile(Some(profiler));
|
db.profile(Some(profiler));
|
||||||
db.execute_batch("PRAGMA application_id = 1").unwrap();
|
db.execute_batch("PRAGMA application_id = 1")?;
|
||||||
db.profile(None);
|
db.profile(None);
|
||||||
db.execute_batch("PRAGMA application_id = 2").unwrap();
|
db.execute_batch("PRAGMA application_id = 2")?;
|
||||||
|
|
||||||
let profiled = PROFILED.lock().unwrap();
|
let profiled = PROFILED.lock().unwrap();
|
||||||
assert_eq!(profiled.len(), 1);
|
assert_eq!(profiled.len(), 1);
|
||||||
assert_eq!(profiled[0].0, "PRAGMA application_id = 1");
|
assert_eq!(profiled[0].0, "PRAGMA application_id = 1");
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -500,35 +500,35 @@ impl Connection {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::DropBehavior;
|
use super::DropBehavior;
|
||||||
use crate::{Connection, Error};
|
use crate::{Connection, Error, Result};
|
||||||
|
|
||||||
fn checked_memory_handle() -> Connection {
|
fn checked_memory_handle() -> Result<Connection> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.execute_batch("CREATE TABLE foo (x INTEGER)").unwrap();
|
db.execute_batch("CREATE TABLE foo (x INTEGER)")?;
|
||||||
db
|
Ok(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_drop() {
|
fn test_drop() -> Result<()> {
|
||||||
let mut db = checked_memory_handle();
|
let mut db = checked_memory_handle()?;
|
||||||
{
|
{
|
||||||
let tx = db.transaction().unwrap();
|
let tx = db.transaction()?;
|
||||||
tx.execute_batch("INSERT INTO foo VALUES(1)").unwrap();
|
tx.execute_batch("INSERT INTO foo VALUES(1)")?;
|
||||||
// default: rollback
|
// default: rollback
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let mut tx = db.transaction().unwrap();
|
let mut tx = db.transaction()?;
|
||||||
tx.execute_batch("INSERT INTO foo VALUES(2)").unwrap();
|
tx.execute_batch("INSERT INTO foo VALUES(2)")?;
|
||||||
tx.set_drop_behavior(DropBehavior::Commit)
|
tx.set_drop_behavior(DropBehavior::Commit)
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let tx = db.transaction().unwrap();
|
let tx = db.transaction()?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
2i32,
|
2i32,
|
||||||
tx.query_row::<i32, _, _>("SELECT SUM(x) FROM foo", [], |r| r.get(0))
|
tx.query_row::<i32, _, _>("SELECT SUM(x) FROM foo", [], |r| r.get(0))?
|
||||||
.unwrap()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
fn assert_nested_tx_error(e: crate::Error) {
|
fn assert_nested_tx_error(e: crate::Error) {
|
||||||
if let Error::SqliteFailure(e, Some(m)) = &e {
|
if let Error::SqliteFailure(e, Some(m)) = &e {
|
||||||
@ -542,165 +542,168 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_unchecked_nesting() {
|
fn test_unchecked_nesting() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle()?;
|
||||||
|
|
||||||
{
|
{
|
||||||
let tx = db.unchecked_transaction().unwrap();
|
let tx = db.unchecked_transaction()?;
|
||||||
let e = tx.unchecked_transaction().unwrap_err();
|
let e = tx.unchecked_transaction().unwrap_err();
|
||||||
assert_nested_tx_error(e);
|
assert_nested_tx_error(e);
|
||||||
// default: rollback
|
// default: rollback
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let tx = db.unchecked_transaction().unwrap();
|
let tx = db.unchecked_transaction()?;
|
||||||
tx.execute_batch("INSERT INTO foo VALUES(1)").unwrap();
|
tx.execute_batch("INSERT INTO foo VALUES(1)")?;
|
||||||
// Ensure this doesn't interfere with ongoing transaction
|
// Ensure this doesn't interfere with ongoing transaction
|
||||||
let e = tx.unchecked_transaction().unwrap_err();
|
let e = tx.unchecked_transaction().unwrap_err();
|
||||||
assert_nested_tx_error(e);
|
assert_nested_tx_error(e);
|
||||||
|
|
||||||
tx.execute_batch("INSERT INTO foo VALUES(1)").unwrap();
|
tx.execute_batch("INSERT INTO foo VALUES(1)")?;
|
||||||
tx.commit().unwrap();
|
tx.commit()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
2i32,
|
2i32,
|
||||||
db.query_row::<i32, _, _>("SELECT SUM(x) FROM foo", [], |r| r.get(0))
|
db.query_row::<i32, _, _>("SELECT SUM(x) FROM foo", [], |r| r.get(0))?
|
||||||
.unwrap()
|
|
||||||
);
|
);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_explicit_rollback_commit() {
|
fn test_explicit_rollback_commit() -> Result<()> {
|
||||||
let mut db = checked_memory_handle();
|
let mut db = checked_memory_handle()?;
|
||||||
{
|
{
|
||||||
let mut tx = db.transaction().unwrap();
|
let mut tx = db.transaction()?;
|
||||||
{
|
{
|
||||||
let mut sp = tx.savepoint().unwrap();
|
let mut sp = tx.savepoint()?;
|
||||||
sp.execute_batch("INSERT INTO foo VALUES(1)").unwrap();
|
sp.execute_batch("INSERT INTO foo VALUES(1)")?;
|
||||||
sp.rollback().unwrap();
|
sp.rollback()?;
|
||||||
sp.execute_batch("INSERT INTO foo VALUES(2)").unwrap();
|
sp.execute_batch("INSERT INTO foo VALUES(2)")?;
|
||||||
sp.commit().unwrap();
|
sp.commit()?;
|
||||||
}
|
}
|
||||||
tx.commit().unwrap();
|
tx.commit()?;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let tx = db.transaction().unwrap();
|
let tx = db.transaction()?;
|
||||||
tx.execute_batch("INSERT INTO foo VALUES(4)").unwrap();
|
tx.execute_batch("INSERT INTO foo VALUES(4)")?;
|
||||||
tx.commit().unwrap();
|
tx.commit()?;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let tx = db.transaction().unwrap();
|
let tx = db.transaction()?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
6i32,
|
6i32,
|
||||||
tx.query_row::<i32, _, _>("SELECT SUM(x) FROM foo", [], |r| r.get(0))
|
tx.query_row::<i32, _, _>("SELECT SUM(x) FROM foo", [], |r| r.get(0))?
|
||||||
.unwrap()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_savepoint() {
|
fn test_savepoint() -> Result<()> {
|
||||||
let mut db = checked_memory_handle();
|
let mut db = checked_memory_handle()?;
|
||||||
{
|
{
|
||||||
let mut tx = db.transaction().unwrap();
|
let mut tx = db.transaction()?;
|
||||||
tx.execute_batch("INSERT INTO foo VALUES(1)").unwrap();
|
tx.execute_batch("INSERT INTO foo VALUES(1)")?;
|
||||||
assert_current_sum(1, &tx);
|
assert_current_sum(1, &tx)?;
|
||||||
tx.set_drop_behavior(DropBehavior::Commit);
|
tx.set_drop_behavior(DropBehavior::Commit);
|
||||||
{
|
{
|
||||||
let mut sp1 = tx.savepoint().unwrap();
|
let mut sp1 = tx.savepoint()?;
|
||||||
sp1.execute_batch("INSERT INTO foo VALUES(2)").unwrap();
|
sp1.execute_batch("INSERT INTO foo VALUES(2)")?;
|
||||||
assert_current_sum(3, &sp1);
|
assert_current_sum(3, &sp1)?;
|
||||||
// will rollback sp1
|
// will rollback sp1
|
||||||
{
|
{
|
||||||
let mut sp2 = sp1.savepoint().unwrap();
|
let mut sp2 = sp1.savepoint()?;
|
||||||
sp2.execute_batch("INSERT INTO foo VALUES(4)").unwrap();
|
sp2.execute_batch("INSERT INTO foo VALUES(4)")?;
|
||||||
assert_current_sum(7, &sp2);
|
assert_current_sum(7, &sp2)?;
|
||||||
// will rollback sp2
|
// will rollback sp2
|
||||||
{
|
{
|
||||||
let sp3 = sp2.savepoint().unwrap();
|
let sp3 = sp2.savepoint()?;
|
||||||
sp3.execute_batch("INSERT INTO foo VALUES(8)").unwrap();
|
sp3.execute_batch("INSERT INTO foo VALUES(8)")?;
|
||||||
assert_current_sum(15, &sp3);
|
assert_current_sum(15, &sp3)?;
|
||||||
sp3.commit().unwrap();
|
sp3.commit()?;
|
||||||
// committed sp3, but will be erased by sp2 rollback
|
// committed sp3, but will be erased by sp2 rollback
|
||||||
}
|
}
|
||||||
assert_current_sum(15, &sp2);
|
assert_current_sum(15, &sp2)?;
|
||||||
}
|
}
|
||||||
assert_current_sum(3, &sp1);
|
assert_current_sum(3, &sp1)?;
|
||||||
}
|
}
|
||||||
assert_current_sum(1, &tx);
|
assert_current_sum(1, &tx)?;
|
||||||
}
|
}
|
||||||
assert_current_sum(1, &db);
|
assert_current_sum(1, &db)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ignore_drop_behavior() {
|
fn test_ignore_drop_behavior() -> Result<()> {
|
||||||
let mut db = checked_memory_handle();
|
let mut db = checked_memory_handle()?;
|
||||||
|
|
||||||
let mut tx = db.transaction().unwrap();
|
let mut tx = db.transaction()?;
|
||||||
{
|
{
|
||||||
let mut sp1 = tx.savepoint().unwrap();
|
let mut sp1 = tx.savepoint()?;
|
||||||
insert(1, &sp1);
|
insert(1, &sp1)?;
|
||||||
sp1.rollback().unwrap();
|
sp1.rollback()?;
|
||||||
insert(2, &sp1);
|
insert(2, &sp1)?;
|
||||||
{
|
{
|
||||||
let mut sp2 = sp1.savepoint().unwrap();
|
let mut sp2 = sp1.savepoint()?;
|
||||||
sp2.set_drop_behavior(DropBehavior::Ignore);
|
sp2.set_drop_behavior(DropBehavior::Ignore);
|
||||||
insert(4, &sp2);
|
insert(4, &sp2)?;
|
||||||
}
|
}
|
||||||
assert_current_sum(6, &sp1);
|
assert_current_sum(6, &sp1)?;
|
||||||
sp1.commit().unwrap();
|
sp1.commit()?;
|
||||||
}
|
}
|
||||||
assert_current_sum(6, &tx);
|
assert_current_sum(6, &tx)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_savepoint_names() {
|
fn test_savepoint_names() -> Result<()> {
|
||||||
let mut db = checked_memory_handle();
|
let mut db = checked_memory_handle()?;
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut sp1 = db.savepoint_with_name("my_sp").unwrap();
|
let mut sp1 = db.savepoint_with_name("my_sp")?;
|
||||||
insert(1, &sp1);
|
insert(1, &sp1)?;
|
||||||
assert_current_sum(1, &sp1);
|
assert_current_sum(1, &sp1)?;
|
||||||
{
|
{
|
||||||
let mut sp2 = sp1.savepoint_with_name("my_sp").unwrap();
|
let mut sp2 = sp1.savepoint_with_name("my_sp")?;
|
||||||
sp2.set_drop_behavior(DropBehavior::Commit);
|
sp2.set_drop_behavior(DropBehavior::Commit);
|
||||||
insert(2, &sp2);
|
insert(2, &sp2)?;
|
||||||
assert_current_sum(3, &sp2);
|
assert_current_sum(3, &sp2)?;
|
||||||
sp2.rollback().unwrap();
|
sp2.rollback()?;
|
||||||
assert_current_sum(1, &sp2);
|
assert_current_sum(1, &sp2)?;
|
||||||
insert(4, &sp2);
|
insert(4, &sp2)?;
|
||||||
}
|
}
|
||||||
assert_current_sum(5, &sp1);
|
assert_current_sum(5, &sp1)?;
|
||||||
sp1.rollback().unwrap();
|
sp1.rollback()?;
|
||||||
{
|
{
|
||||||
let mut sp2 = sp1.savepoint_with_name("my_sp").unwrap();
|
let mut sp2 = sp1.savepoint_with_name("my_sp")?;
|
||||||
sp2.set_drop_behavior(DropBehavior::Ignore);
|
sp2.set_drop_behavior(DropBehavior::Ignore);
|
||||||
insert(8, &sp2);
|
insert(8, &sp2)?;
|
||||||
}
|
}
|
||||||
assert_current_sum(8, &sp1);
|
assert_current_sum(8, &sp1)?;
|
||||||
sp1.commit().unwrap();
|
sp1.commit()?;
|
||||||
}
|
}
|
||||||
assert_current_sum(8, &db);
|
assert_current_sum(8, &db)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rc() {
|
fn test_rc() -> Result<()> {
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
let mut conn = Connection::open_in_memory().unwrap();
|
let mut conn = Connection::open_in_memory()?;
|
||||||
let rc_txn = Rc::new(conn.transaction().unwrap());
|
let rc_txn = Rc::new(conn.transaction()?);
|
||||||
|
|
||||||
// This will compile only if Transaction is Debug
|
// This will compile only if Transaction is Debug
|
||||||
Rc::try_unwrap(rc_txn).unwrap();
|
Rc::try_unwrap(rc_txn).unwrap();
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert(x: i32, conn: &Connection) {
|
fn insert(x: i32, conn: &Connection) -> Result<usize> {
|
||||||
conn.execute("INSERT INTO foo VALUES(?)", [x]).unwrap();
|
conn.execute("INSERT INTO foo VALUES(?)", [x])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assert_current_sum(x: i32, conn: &Connection) {
|
fn assert_current_sum(x: i32, conn: &Connection) -> Result<()> {
|
||||||
let i = conn
|
let i = conn.query_row::<i32, _, _>("SELECT SUM(x) FROM foo", [], |r| r.get(0))?;
|
||||||
.query_row::<i32, _, _>("SELECT SUM(x) FROM foo", [], |r| r.get(0))
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(x, i);
|
assert_eq!(x, i);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,114 +137,109 @@ mod test {
|
|||||||
use crate::{Connection, Result};
|
use crate::{Connection, Result};
|
||||||
use chrono::{DateTime, Duration, Local, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc};
|
use chrono::{DateTime, Duration, Local, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc};
|
||||||
|
|
||||||
fn checked_memory_handle() -> Connection {
|
fn checked_memory_handle() -> Result<Connection> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.execute_batch("CREATE TABLE foo (t TEXT, i INTEGER, f FLOAT, b BLOB)")
|
db.execute_batch("CREATE TABLE foo (t TEXT, i INTEGER, f FLOAT, b BLOB)")?;
|
||||||
.unwrap();
|
Ok(db)
|
||||||
db
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_naive_date() {
|
fn test_naive_date() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle()?;
|
||||||
let date = NaiveDate::from_ymd(2016, 2, 23);
|
let date = NaiveDate::from_ymd(2016, 2, 23);
|
||||||
db.execute("INSERT INTO foo (t) VALUES (?)", &[&date])
|
db.execute("INSERT INTO foo (t) VALUES (?)", &[&date])?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let s: String = db.query_row("SELECT t FROM foo", [], |r| r.get(0)).unwrap();
|
let s: String = db.query_row("SELECT t FROM foo", [], |r| r.get(0))?;
|
||||||
assert_eq!("2016-02-23", s);
|
assert_eq!("2016-02-23", s);
|
||||||
let t: NaiveDate = db.query_row("SELECT t FROM foo", [], |r| r.get(0)).unwrap();
|
let t: NaiveDate = db.query_row("SELECT t FROM foo", [], |r| r.get(0))?;
|
||||||
assert_eq!(date, t);
|
assert_eq!(date, t);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_naive_time() {
|
fn test_naive_time() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle()?;
|
||||||
let time = NaiveTime::from_hms(23, 56, 4);
|
let time = NaiveTime::from_hms(23, 56, 4);
|
||||||
db.execute("INSERT INTO foo (t) VALUES (?)", &[&time])
|
db.execute("INSERT INTO foo (t) VALUES (?)", &[&time])?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let s: String = db.query_row("SELECT t FROM foo", [], |r| r.get(0)).unwrap();
|
let s: String = db.query_row("SELECT t FROM foo", [], |r| r.get(0))?;
|
||||||
assert_eq!("23:56:04", s);
|
assert_eq!("23:56:04", s);
|
||||||
let v: NaiveTime = db.query_row("SELECT t FROM foo", [], |r| r.get(0)).unwrap();
|
let v: NaiveTime = db.query_row("SELECT t FROM foo", [], |r| r.get(0))?;
|
||||||
assert_eq!(time, v);
|
assert_eq!(time, v);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_naive_date_time() {
|
fn test_naive_date_time() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle()?;
|
||||||
let date = NaiveDate::from_ymd(2016, 2, 23);
|
let date = NaiveDate::from_ymd(2016, 2, 23);
|
||||||
let time = NaiveTime::from_hms(23, 56, 4);
|
let time = NaiveTime::from_hms(23, 56, 4);
|
||||||
let dt = NaiveDateTime::new(date, time);
|
let dt = NaiveDateTime::new(date, time);
|
||||||
|
|
||||||
db.execute("INSERT INTO foo (t) VALUES (?)", &[&dt])
|
db.execute("INSERT INTO foo (t) VALUES (?)", &[&dt])?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let s: String = db.query_row("SELECT t FROM foo", [], |r| r.get(0)).unwrap();
|
let s: String = db.query_row("SELECT t FROM foo", [], |r| r.get(0))?;
|
||||||
assert_eq!("2016-02-23T23:56:04", s);
|
assert_eq!("2016-02-23T23:56:04", s);
|
||||||
let v: NaiveDateTime = db.query_row("SELECT t FROM foo", [], |r| r.get(0)).unwrap();
|
let v: NaiveDateTime = db.query_row("SELECT t FROM foo", [], |r| r.get(0))?;
|
||||||
assert_eq!(dt, v);
|
assert_eq!(dt, v);
|
||||||
|
|
||||||
db.execute("UPDATE foo set b = datetime(t)", []).unwrap(); // "YYYY-MM-DD HH:MM:SS"
|
db.execute("UPDATE foo set b = datetime(t)", [])?; // "YYYY-MM-DD HH:MM:SS"
|
||||||
let hms: NaiveDateTime = db.query_row("SELECT b FROM foo", [], |r| r.get(0)).unwrap();
|
let hms: NaiveDateTime = db.query_row("SELECT b FROM foo", [], |r| r.get(0))?;
|
||||||
assert_eq!(dt, hms);
|
assert_eq!(dt, hms);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_date_time_utc() {
|
fn test_date_time_utc() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle()?;
|
||||||
let date = NaiveDate::from_ymd(2016, 2, 23);
|
let date = NaiveDate::from_ymd(2016, 2, 23);
|
||||||
let time = NaiveTime::from_hms_milli(23, 56, 4, 789);
|
let time = NaiveTime::from_hms_milli(23, 56, 4, 789);
|
||||||
let dt = NaiveDateTime::new(date, time);
|
let dt = NaiveDateTime::new(date, time);
|
||||||
let utc = Utc.from_utc_datetime(&dt);
|
let utc = Utc.from_utc_datetime(&dt);
|
||||||
|
|
||||||
db.execute("INSERT INTO foo (t) VALUES (?)", &[&utc])
|
db.execute("INSERT INTO foo (t) VALUES (?)", &[&utc])?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let s: String = db.query_row("SELECT t FROM foo", [], |r| r.get(0)).unwrap();
|
let s: String = db.query_row("SELECT t FROM foo", [], |r| r.get(0))?;
|
||||||
assert_eq!("2016-02-23T23:56:04.789+00:00", s);
|
assert_eq!("2016-02-23T23:56:04.789+00:00", s);
|
||||||
|
|
||||||
let v1: DateTime<Utc> = db.query_row("SELECT t FROM foo", [], |r| r.get(0)).unwrap();
|
let v1: DateTime<Utc> = db.query_row("SELECT t FROM foo", [], |r| r.get(0))?;
|
||||||
assert_eq!(utc, v1);
|
assert_eq!(utc, v1);
|
||||||
|
|
||||||
let v2: DateTime<Utc> = db
|
let v2: DateTime<Utc> =
|
||||||
.query_row("SELECT '2016-02-23 23:56:04.789'", [], |r| r.get(0))
|
db.query_row("SELECT '2016-02-23 23:56:04.789'", [], |r| r.get(0))?;
|
||||||
.unwrap();
|
|
||||||
assert_eq!(utc, v2);
|
assert_eq!(utc, v2);
|
||||||
|
|
||||||
let v3: DateTime<Utc> = db
|
let v3: DateTime<Utc> = db.query_row("SELECT '2016-02-23 23:56:04'", [], |r| r.get(0))?;
|
||||||
.query_row("SELECT '2016-02-23 23:56:04'", [], |r| r.get(0))
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(utc - Duration::milliseconds(789), v3);
|
assert_eq!(utc - Duration::milliseconds(789), v3);
|
||||||
|
|
||||||
let v4: DateTime<Utc> = db
|
let v4: DateTime<Utc> =
|
||||||
.query_row("SELECT '2016-02-23 23:56:04.789+00:00'", [], |r| r.get(0))
|
db.query_row("SELECT '2016-02-23 23:56:04.789+00:00'", [], |r| r.get(0))?;
|
||||||
.unwrap();
|
|
||||||
assert_eq!(utc, v4);
|
assert_eq!(utc, v4);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_date_time_local() {
|
fn test_date_time_local() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle()?;
|
||||||
let date = NaiveDate::from_ymd(2016, 2, 23);
|
let date = NaiveDate::from_ymd(2016, 2, 23);
|
||||||
let time = NaiveTime::from_hms_milli(23, 56, 4, 789);
|
let time = NaiveTime::from_hms_milli(23, 56, 4, 789);
|
||||||
let dt = NaiveDateTime::new(date, time);
|
let dt = NaiveDateTime::new(date, time);
|
||||||
let local = Local.from_local_datetime(&dt).single().unwrap();
|
let local = Local.from_local_datetime(&dt).single().unwrap();
|
||||||
|
|
||||||
db.execute("INSERT INTO foo (t) VALUES (?)", &[&local])
|
db.execute("INSERT INTO foo (t) VALUES (?)", &[&local])?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// Stored string should be in UTC
|
// Stored string should be in UTC
|
||||||
let s: String = db.query_row("SELECT t FROM foo", [], |r| r.get(0)).unwrap();
|
let s: String = db.query_row("SELECT t FROM foo", [], |r| r.get(0))?;
|
||||||
assert!(s.ends_with("+00:00"));
|
assert!(s.ends_with("+00:00"));
|
||||||
|
|
||||||
let v: DateTime<Local> = db.query_row("SELECT t FROM foo", [], |r| r.get(0)).unwrap();
|
let v: DateTime<Local> = db.query_row("SELECT t FROM foo", [], |r| r.get(0))?;
|
||||||
assert_eq!(local, v);
|
assert_eq!(local, v);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sqlite_functions() {
|
fn test_sqlite_functions() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle()?;
|
||||||
let result: Result<NaiveTime> = db.query_row("SELECT CURRENT_TIME", [], |r| r.get(0));
|
let result: Result<NaiveTime> = db.query_row("SELECT CURRENT_TIME", [], |r| r.get(0));
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let result: Result<NaiveDate> = db.query_row("SELECT CURRENT_DATE", [], |r| r.get(0));
|
let result: Result<NaiveDate> = db.query_row("SELECT CURRENT_DATE", [], |r| r.get(0));
|
||||||
@ -255,5 +250,6 @@ mod test {
|
|||||||
let result: Result<DateTime<Utc>> =
|
let result: Result<DateTime<Utc>> =
|
||||||
db.query_row("SELECT CURRENT_TIMESTAMP", [], |r| r.get(0));
|
db.query_row("SELECT CURRENT_TIMESTAMP", [], |r| r.get(0));
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -235,15 +235,11 @@ impl FromSql for Value {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::FromSql;
|
use super::FromSql;
|
||||||
use crate::{Connection, Error};
|
use crate::{Connection, Error, Result};
|
||||||
|
|
||||||
fn checked_memory_handle() -> Connection {
|
|
||||||
Connection::open_in_memory().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_integral_ranges() {
|
fn test_integral_ranges() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = Connection::open_in_memory()?;
|
||||||
|
|
||||||
fn check_ranges<T>(db: &Connection, out_of_range: &[i64], in_range: &[i64])
|
fn check_ranges<T>(db: &Connection, out_of_range: &[i64], in_range: &[i64])
|
||||||
where
|
where
|
||||||
@ -278,5 +274,6 @@ mod test {
|
|||||||
check_ranges::<u8>(&db, &[-2, -1, 256], &[0, 1, 255]);
|
check_ranges::<u8>(&db, &[-2, -1, 256], &[0, 1, 255]);
|
||||||
check_ranges::<u16>(&db, &[-2, -1, 65536], &[0, 1, 65535]);
|
check_ranges::<u16>(&db, &[-2, -1, 65536], &[0, 1, 65535]);
|
||||||
check_ranges::<u32>(&db, &[-2, -1, 4_294_967_296], &[0, 1, 4_294_967_295]);
|
check_ranges::<u32>(&db, &[-2, -1, 4_294_967_296], &[0, 1, 4_294_967_295]);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
164
src/types/mod.rs
164
src/types/mod.rs
@ -131,95 +131,92 @@ impl fmt::Display for Type {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::Value;
|
use super::Value;
|
||||||
use crate::{params, Connection, Error, Statement};
|
use crate::{params, Connection, Error, Result, Statement};
|
||||||
use std::f64::EPSILON;
|
use std::f64::EPSILON;
|
||||||
use std::os::raw::{c_double, c_int};
|
use std::os::raw::{c_double, c_int};
|
||||||
|
|
||||||
fn checked_memory_handle() -> Connection {
|
fn checked_memory_handle() -> Result<Connection> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.execute_batch("CREATE TABLE foo (b BLOB, t TEXT, i INTEGER, f FLOAT, n)")
|
db.execute_batch("CREATE TABLE foo (b BLOB, t TEXT, i INTEGER, f FLOAT, n)")?;
|
||||||
.unwrap();
|
Ok(db)
|
||||||
db
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_blob() {
|
fn test_blob() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle()?;
|
||||||
|
|
||||||
let v1234 = vec![1u8, 2, 3, 4];
|
let v1234 = vec![1u8, 2, 3, 4];
|
||||||
db.execute("INSERT INTO foo(b) VALUES (?)", &[&v1234])
|
db.execute("INSERT INTO foo(b) VALUES (?)", &[&v1234])?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let v: Vec<u8> = db.query_row("SELECT b FROM foo", [], |r| r.get(0)).unwrap();
|
let v: Vec<u8> = db.query_row("SELECT b FROM foo", [], |r| r.get(0))?;
|
||||||
assert_eq!(v, v1234);
|
assert_eq!(v, v1234);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_empty_blob() {
|
fn test_empty_blob() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle()?;
|
||||||
|
|
||||||
let empty = vec![];
|
let empty = vec![];
|
||||||
db.execute("INSERT INTO foo(b) VALUES (?)", &[&empty])
|
db.execute("INSERT INTO foo(b) VALUES (?)", &[&empty])?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let v: Vec<u8> = db.query_row("SELECT b FROM foo", [], |r| r.get(0)).unwrap();
|
let v: Vec<u8> = db.query_row("SELECT b FROM foo", [], |r| r.get(0))?;
|
||||||
assert_eq!(v, empty);
|
assert_eq!(v, empty);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_str() {
|
fn test_str() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle()?;
|
||||||
|
|
||||||
let s = "hello, world!";
|
let s = "hello, world!";
|
||||||
db.execute("INSERT INTO foo(t) VALUES (?)", &[&s]).unwrap();
|
db.execute("INSERT INTO foo(t) VALUES (?)", &[&s])?;
|
||||||
|
|
||||||
let from: String = db.query_row("SELECT t FROM foo", [], |r| r.get(0)).unwrap();
|
let from: String = db.query_row("SELECT t FROM foo", [], |r| r.get(0))?;
|
||||||
assert_eq!(from, s);
|
assert_eq!(from, s);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_string() {
|
fn test_string() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle()?;
|
||||||
|
|
||||||
let s = "hello, world!";
|
let s = "hello, world!";
|
||||||
db.execute("INSERT INTO foo(t) VALUES (?)", [s.to_owned()])
|
db.execute("INSERT INTO foo(t) VALUES (?)", [s.to_owned()])?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let from: String = db.query_row("SELECT t FROM foo", [], |r| r.get(0)).unwrap();
|
let from: String = db.query_row("SELECT t FROM foo", [], |r| r.get(0))?;
|
||||||
assert_eq!(from, s);
|
assert_eq!(from, s);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_value() {
|
fn test_value() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle()?;
|
||||||
|
|
||||||
db.execute("INSERT INTO foo(i) VALUES (?)", [Value::Integer(10)])
|
db.execute("INSERT INTO foo(i) VALUES (?)", [Value::Integer(10)])?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
10i64,
|
10i64,
|
||||||
db.query_row::<i64, _, _>("SELECT i FROM foo", [], |r| r.get(0))
|
db.query_row::<i64, _, _>("SELECT i FROM foo", [], |r| r.get(0))?
|
||||||
.unwrap()
|
|
||||||
);
|
);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_option() {
|
fn test_option() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle()?;
|
||||||
|
|
||||||
let s = Some("hello, world!");
|
let s = Some("hello, world!");
|
||||||
let b = Some(vec![1u8, 2, 3, 4]);
|
let b = Some(vec![1u8, 2, 3, 4]);
|
||||||
|
|
||||||
db.execute("INSERT INTO foo(t) VALUES (?)", &[&s]).unwrap();
|
db.execute("INSERT INTO foo(t) VALUES (?)", &[&s])?;
|
||||||
db.execute("INSERT INTO foo(b) VALUES (?)", &[&b]).unwrap();
|
db.execute("INSERT INTO foo(b) VALUES (?)", &[&b])?;
|
||||||
|
|
||||||
let mut stmt = db
|
let mut stmt = db.prepare("SELECT t, b FROM foo ORDER BY ROWID ASC")?;
|
||||||
.prepare("SELECT t, b FROM foo ORDER BY ROWID ASC")
|
let mut rows = stmt.query([])?;
|
||||||
.unwrap();
|
|
||||||
let mut rows = stmt.query([]).unwrap();
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let row1 = rows.next().unwrap().unwrap();
|
let row1 = rows.next()?.unwrap();
|
||||||
let s1: Option<String> = row1.get_unwrap(0);
|
let s1: Option<String> = row1.get_unwrap(0);
|
||||||
let b1: Option<Vec<u8>> = row1.get_unwrap(1);
|
let b1: Option<Vec<u8>> = row1.get_unwrap(1);
|
||||||
assert_eq!(s.unwrap(), s1.unwrap());
|
assert_eq!(s.unwrap(), s1.unwrap());
|
||||||
@ -227,42 +224,42 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let row2 = rows.next().unwrap().unwrap();
|
let row2 = rows.next()?.unwrap();
|
||||||
let s2: Option<String> = row2.get_unwrap(0);
|
let s2: Option<String> = row2.get_unwrap(0);
|
||||||
let b2: Option<Vec<u8>> = row2.get_unwrap(1);
|
let b2: Option<Vec<u8>> = row2.get_unwrap(1);
|
||||||
assert!(s2.is_none());
|
assert!(s2.is_none());
|
||||||
assert_eq!(b, b2);
|
assert_eq!(b, b2);
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[allow(clippy::cognitive_complexity)]
|
#[allow(clippy::cognitive_complexity)]
|
||||||
fn test_mismatched_types() {
|
fn test_mismatched_types() -> Result<()> {
|
||||||
fn is_invalid_column_type(err: Error) -> bool {
|
fn is_invalid_column_type(err: Error) -> bool {
|
||||||
matches!(err, Error::InvalidColumnType(..))
|
matches!(err, Error::InvalidColumnType(..))
|
||||||
}
|
}
|
||||||
|
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle()?;
|
||||||
|
|
||||||
db.execute(
|
db.execute(
|
||||||
"INSERT INTO foo(b, t, i, f) VALUES (X'0102', 'text', 1, 1.5)",
|
"INSERT INTO foo(b, t, i, f) VALUES (X'0102', 'text', 1, 1.5)",
|
||||||
[],
|
[],
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut stmt = db.prepare("SELECT b, t, i, f, n FROM foo").unwrap();
|
let mut stmt = db.prepare("SELECT b, t, i, f, n FROM foo")?;
|
||||||
let mut rows = stmt.query([]).unwrap();
|
let mut rows = stmt.query([])?;
|
||||||
|
|
||||||
let row = rows.next().unwrap().unwrap();
|
let row = rows.next()?.unwrap();
|
||||||
|
|
||||||
// check the correct types come back as expected
|
// check the correct types come back as expected
|
||||||
assert_eq!(vec![1, 2], row.get::<_, Vec<u8>>(0).unwrap());
|
assert_eq!(vec![1, 2], row.get::<_, Vec<u8>>(0)?);
|
||||||
assert_eq!("text", row.get::<_, String>(1).unwrap());
|
assert_eq!("text", row.get::<_, String>(1)?);
|
||||||
assert_eq!(1, row.get::<_, c_int>(2).unwrap());
|
assert_eq!(1, row.get::<_, c_int>(2)?);
|
||||||
assert!((1.5 - row.get::<_, c_double>(3).unwrap()).abs() < EPSILON);
|
assert!((1.5 - row.get::<_, c_double>(3)?).abs() < EPSILON);
|
||||||
assert_eq!(row.get::<_, Option<c_int>>(4).unwrap(), None);
|
assert_eq!(row.get::<_, Option<c_int>>(4)?, None);
|
||||||
assert_eq!(row.get::<_, Option<c_double>>(4).unwrap(), None);
|
assert_eq!(row.get::<_, Option<c_double>>(4)?, None);
|
||||||
assert_eq!(row.get::<_, Option<String>>(4).unwrap(), None);
|
assert_eq!(row.get::<_, Option<String>>(4)?, None);
|
||||||
|
|
||||||
// check some invalid types
|
// check some invalid types
|
||||||
|
|
||||||
@ -347,58 +344,50 @@ mod test {
|
|||||||
assert!(is_invalid_column_type(
|
assert!(is_invalid_column_type(
|
||||||
row.get::<_, time::OffsetDateTime>(4).err().unwrap()
|
row.get::<_, time::OffsetDateTime>(4).err().unwrap()
|
||||||
));
|
));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_dynamic_type() {
|
fn test_dynamic_type() -> Result<()> {
|
||||||
use super::Value;
|
use super::Value;
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle()?;
|
||||||
|
|
||||||
db.execute(
|
db.execute(
|
||||||
"INSERT INTO foo(b, t, i, f) VALUES (X'0102', 'text', 1, 1.5)",
|
"INSERT INTO foo(b, t, i, f) VALUES (X'0102', 'text', 1, 1.5)",
|
||||||
[],
|
[],
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut stmt = db.prepare("SELECT b, t, i, f, n FROM foo").unwrap();
|
let mut stmt = db.prepare("SELECT b, t, i, f, n FROM foo")?;
|
||||||
let mut rows = stmt.query([]).unwrap();
|
let mut rows = stmt.query([])?;
|
||||||
|
|
||||||
let row = rows.next().unwrap().unwrap();
|
let row = rows.next()?.unwrap();
|
||||||
assert_eq!(Value::Blob(vec![1, 2]), row.get::<_, Value>(0).unwrap());
|
assert_eq!(Value::Blob(vec![1, 2]), row.get::<_, Value>(0)?);
|
||||||
assert_eq!(
|
assert_eq!(Value::Text(String::from("text")), row.get::<_, Value>(1)?);
|
||||||
Value::Text(String::from("text")),
|
assert_eq!(Value::Integer(1), row.get::<_, Value>(2)?);
|
||||||
row.get::<_, Value>(1).unwrap()
|
match row.get::<_, Value>(3)? {
|
||||||
);
|
|
||||||
assert_eq!(Value::Integer(1), row.get::<_, Value>(2).unwrap());
|
|
||||||
match row.get::<_, Value>(3).unwrap() {
|
|
||||||
Value::Real(val) => assert!((1.5 - val).abs() < EPSILON),
|
Value::Real(val) => assert!((1.5 - val).abs() < EPSILON),
|
||||||
x => panic!("Invalid Value {:?}", x),
|
x => panic!("Invalid Value {:?}", x),
|
||||||
}
|
}
|
||||||
assert_eq!(Value::Null, row.get::<_, Value>(4).unwrap());
|
assert_eq!(Value::Null, row.get::<_, Value>(4)?);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! test_conversion {
|
macro_rules! test_conversion {
|
||||||
($db_etc:ident, $insert_value:expr, $get_type:ty,expect $expected_value:expr) => {
|
($db_etc:ident, $insert_value:expr, $get_type:ty,expect $expected_value:expr) => {
|
||||||
$db_etc
|
$db_etc.insert_statement.execute(params![$insert_value])?;
|
||||||
.insert_statement
|
|
||||||
.execute(params![$insert_value])
|
|
||||||
.unwrap();
|
|
||||||
let res = $db_etc
|
let res = $db_etc
|
||||||
.query_statement
|
.query_statement
|
||||||
.query_row([], |row| row.get::<_, $get_type>(0));
|
.query_row([], |row| row.get::<_, $get_type>(0));
|
||||||
assert_eq!(res.unwrap(), $expected_value);
|
assert_eq!(res?, $expected_value);
|
||||||
$db_etc.delete_statement.execute([]).unwrap();
|
$db_etc.delete_statement.execute([])?;
|
||||||
};
|
};
|
||||||
($db_etc:ident, $insert_value:expr, $get_type:ty,expect_from_sql_error) => {
|
($db_etc:ident, $insert_value:expr, $get_type:ty,expect_from_sql_error) => {
|
||||||
$db_etc
|
$db_etc.insert_statement.execute(params![$insert_value])?;
|
||||||
.insert_statement
|
|
||||||
.execute(params![$insert_value])
|
|
||||||
.unwrap();
|
|
||||||
let res = $db_etc
|
let res = $db_etc
|
||||||
.query_statement
|
.query_statement
|
||||||
.query_row([], |row| row.get::<_, $get_type>(0));
|
.query_row([], |row| row.get::<_, $get_type>(0));
|
||||||
res.unwrap_err();
|
res.unwrap_err();
|
||||||
$db_etc.delete_statement.execute([]).unwrap();
|
$db_etc.delete_statement.execute([])?;
|
||||||
};
|
};
|
||||||
($db_etc:ident, $insert_value:expr, $get_type:ty,expect_to_sql_error) => {
|
($db_etc:ident, $insert_value:expr, $get_type:ty,expect_to_sql_error) => {
|
||||||
$db_etc
|
$db_etc
|
||||||
@ -409,12 +398,12 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_numeric_conversions() {
|
fn test_numeric_conversions() -> Result<()> {
|
||||||
#![allow(clippy::float_cmp)]
|
#![allow(clippy::float_cmp)]
|
||||||
|
|
||||||
// Test what happens when we store an f32 and retrieve an i32 etc.
|
// Test what happens when we store an f32 and retrieve an i32 etc.
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.execute_batch("CREATE TABLE foo (x)").unwrap();
|
db.execute_batch("CREATE TABLE foo (x)")?;
|
||||||
|
|
||||||
// SQLite actually ignores the column types, so we just need to test
|
// SQLite actually ignores the column types, so we just need to test
|
||||||
// different numeric values.
|
// different numeric values.
|
||||||
@ -426,9 +415,9 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut db_etc = DbEtc {
|
let mut db_etc = DbEtc {
|
||||||
insert_statement: db.prepare("INSERT INTO foo VALUES (?1)").unwrap(),
|
insert_statement: db.prepare("INSERT INTO foo VALUES (?1)")?,
|
||||||
query_statement: db.prepare("SELECT x FROM foo").unwrap(),
|
query_statement: db.prepare("SELECT x FROM foo")?,
|
||||||
delete_statement: db.prepare("DELETE FROM foo").unwrap(),
|
delete_statement: db.prepare("DELETE FROM foo")?,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Basic non-converting test.
|
// Basic non-converting test.
|
||||||
@ -466,5 +455,6 @@ mod test {
|
|||||||
// FromSql float to int conversion, never works even if the actual value
|
// FromSql float to int conversion, never works even if the actual value
|
||||||
// is an integer.
|
// is an integer.
|
||||||
test_conversion!(db_etc, 0f64, i64, expect_from_sql_error);
|
test_conversion!(db_etc, 0f64, i64, expect_from_sql_error);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,30 +29,29 @@ impl FromSql for Value {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::types::ToSql;
|
use crate::types::ToSql;
|
||||||
use crate::Connection;
|
use crate::{Connection, Result};
|
||||||
|
|
||||||
fn checked_memory_handle() -> Connection {
|
fn checked_memory_handle() -> Result<Connection> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.execute_batch("CREATE TABLE foo (t TEXT, b BLOB)")
|
db.execute_batch("CREATE TABLE foo (t TEXT, b BLOB)")?;
|
||||||
.unwrap();
|
Ok(db)
|
||||||
db
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_json_value() {
|
fn test_json_value() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle()?;
|
||||||
|
|
||||||
let json = r#"{"foo": 13, "bar": "baz"}"#;
|
let json = r#"{"foo": 13, "bar": "baz"}"#;
|
||||||
let data: serde_json::Value = serde_json::from_str(json).unwrap();
|
let data: serde_json::Value = serde_json::from_str(json).unwrap();
|
||||||
db.execute(
|
db.execute(
|
||||||
"INSERT INTO foo (t, b) VALUES (?, ?)",
|
"INSERT INTO foo (t, b) VALUES (?, ?)",
|
||||||
&[&data as &dyn ToSql, &json.as_bytes()],
|
&[&data as &dyn ToSql, &json.as_bytes()],
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let t: serde_json::Value = db.query_row("SELECT t FROM foo", [], |r| r.get(0)).unwrap();
|
let t: serde_json::Value = db.query_row("SELECT t FROM foo", [], |r| r.get(0))?;
|
||||||
assert_eq!(data, t);
|
assert_eq!(data, t);
|
||||||
let b: serde_json::Value = db.query_row("SELECT b FROM foo", [], |r| r.get(0)).unwrap();
|
let b: serde_json::Value = db.query_row("SELECT b FROM foo", [], |r| r.get(0))?;
|
||||||
assert_eq!(data, b);
|
assert_eq!(data, b);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,16 +37,15 @@ mod test {
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
|
|
||||||
fn checked_memory_handle() -> Connection {
|
fn checked_memory_handle() -> Result<Connection> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.execute_batch("CREATE TABLE foo (t TEXT, i INTEGER, f FLOAT)")
|
db.execute_batch("CREATE TABLE foo (t TEXT, i INTEGER, f FLOAT)")?;
|
||||||
.unwrap();
|
Ok(db)
|
||||||
db
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_offset_date_time() {
|
fn test_offset_date_time() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle()?;
|
||||||
|
|
||||||
let mut ts_vec = vec![];
|
let mut ts_vec = vec![];
|
||||||
|
|
||||||
@ -61,21 +60,23 @@ mod test {
|
|||||||
ts_vec.push(make_datetime(10_000_000_000, 0)); //November 20, 2286
|
ts_vec.push(make_datetime(10_000_000_000, 0)); //November 20, 2286
|
||||||
|
|
||||||
for ts in ts_vec {
|
for ts in ts_vec {
|
||||||
db.execute("INSERT INTO foo(t) VALUES (?)", &[&ts]).unwrap();
|
db.execute("INSERT INTO foo(t) VALUES (?)", &[&ts])?;
|
||||||
|
|
||||||
let from: OffsetDateTime = db.query_row("SELECT t FROM foo", [], |r| r.get(0)).unwrap();
|
let from: OffsetDateTime = db.query_row("SELECT t FROM foo", [], |r| r.get(0))?;
|
||||||
|
|
||||||
db.execute("DELETE FROM foo", []).unwrap();
|
db.execute("DELETE FROM foo", [])?;
|
||||||
|
|
||||||
assert_eq!(from, ts);
|
assert_eq!(from, ts);
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sqlite_functions() {
|
fn test_sqlite_functions() -> Result<()> {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle()?;
|
||||||
let result: Result<OffsetDateTime> =
|
let result: Result<OffsetDateTime> =
|
||||||
db.query_row("SELECT CURRENT_TIMESTAMP", [], |r| r.get(0));
|
db.query_row("SELECT CURRENT_TIMESTAMP", [], |r| r.get(0));
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -339,12 +339,11 @@ mod test {
|
|||||||
|
|
||||||
#[cfg(feature = "i128_blob")]
|
#[cfg(feature = "i128_blob")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_i128() {
|
fn test_i128() -> crate::Result<()> {
|
||||||
use crate::Connection;
|
use crate::Connection;
|
||||||
use std::i128;
|
use std::i128;
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.execute_batch("CREATE TABLE foo (i128 BLOB, desc TEXT)")
|
db.execute_batch("CREATE TABLE foo (i128 BLOB, desc TEXT)")?;
|
||||||
.unwrap();
|
|
||||||
db.execute(
|
db.execute(
|
||||||
"
|
"
|
||||||
INSERT INTO foo(i128, desc) VALUES
|
INSERT INTO foo(i128, desc) VALUES
|
||||||
@ -353,20 +352,15 @@ mod test {
|
|||||||
(?, 'pos one'), (?, 'pos two'),
|
(?, 'pos one'), (?, 'pos two'),
|
||||||
(?, 'min'), (?, 'max')",
|
(?, 'min'), (?, 'max')",
|
||||||
[0i128, -1i128, -2i128, 1i128, 2i128, i128::MIN, i128::MAX],
|
[0i128, -1i128, -2i128, 1i128, 2i128, i128::MIN, i128::MAX],
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut stmt = db
|
let mut stmt = db.prepare("SELECT i128, desc FROM foo ORDER BY i128 ASC")?;
|
||||||
.prepare("SELECT i128, desc FROM foo ORDER BY i128 ASC")
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let res = stmt
|
let res = stmt
|
||||||
.query_map([], |row| {
|
.query_map([], |row| {
|
||||||
Ok((row.get::<_, i128>(0)?, row.get::<_, String>(1)?))
|
Ok((row.get::<_, i128>(0)?, row.get::<_, String>(1)?))
|
||||||
})
|
})?
|
||||||
.unwrap()
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
.collect::<Result<Vec<_>, _>>()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
res,
|
res,
|
||||||
@ -380,37 +374,35 @@ mod test {
|
|||||||
(i128::MAX, "max".to_owned()),
|
(i128::MAX, "max".to_owned()),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "uuid")]
|
#[cfg(feature = "uuid")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_uuid() {
|
fn test_uuid() -> crate::Result<()> {
|
||||||
use crate::{params, Connection};
|
use crate::{params, Connection};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.execute_batch("CREATE TABLE foo (id BLOB CHECK(length(id) = 16), label TEXT);")
|
db.execute_batch("CREATE TABLE foo (id BLOB CHECK(length(id) = 16), label TEXT);")?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let id = Uuid::new_v4();
|
let id = Uuid::new_v4();
|
||||||
|
|
||||||
db.execute(
|
db.execute(
|
||||||
"INSERT INTO foo (id, label) VALUES (?, ?)",
|
"INSERT INTO foo (id, label) VALUES (?, ?)",
|
||||||
params![id, "target"],
|
params![id, "target"],
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut stmt = db
|
let mut stmt = db.prepare("SELECT id, label FROM foo WHERE id = ?")?;
|
||||||
.prepare("SELECT id, label FROM foo WHERE id = ?")
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut rows = stmt.query(params![id]).unwrap();
|
let mut rows = stmt.query(params![id])?;
|
||||||
let row = rows.next().unwrap().unwrap();
|
let row = rows.next()?.unwrap();
|
||||||
|
|
||||||
let found_id: Uuid = row.get_unwrap(0);
|
let found_id: Uuid = row.get_unwrap(0);
|
||||||
let found_label: String = row.get_unwrap(1);
|
let found_label: String = row.get_unwrap(1);
|
||||||
|
|
||||||
assert_eq!(found_id, id);
|
assert_eq!(found_id, id);
|
||||||
assert_eq!(found_label, "target");
|
assert_eq!(found_label, "target");
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,11 +30,10 @@ mod test {
|
|||||||
use crate::{params, Connection, Error, Result};
|
use crate::{params, Connection, Error, Result};
|
||||||
use url::{ParseError, Url};
|
use url::{ParseError, Url};
|
||||||
|
|
||||||
fn checked_memory_handle() -> Connection {
|
fn checked_memory_handle() -> Result<Connection> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
db.execute_batch("CREATE TABLE urls (i INTEGER, v TEXT)")
|
db.execute_batch("CREATE TABLE urls (i INTEGER, v TEXT)")?;
|
||||||
.unwrap();
|
Ok(db)
|
||||||
db
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_url(db: &Connection, id: i64) -> Result<Url> {
|
fn get_url(db: &Connection, id: i64) -> Result<Url> {
|
||||||
@ -42,8 +41,8 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sql_url() {
|
fn test_sql_url() -> Result<()> {
|
||||||
let db = &checked_memory_handle();
|
let db = &checked_memory_handle()?;
|
||||||
|
|
||||||
let url0 = Url::parse("http://www.example1.com").unwrap();
|
let url0 = Url::parse("http://www.example1.com").unwrap();
|
||||||
let url1 = Url::parse("http://www.example1.com/👌").unwrap();
|
let url1 = Url::parse("http://www.example1.com/👌").unwrap();
|
||||||
@ -54,16 +53,15 @@ mod test {
|
|||||||
// also insert a non-hex encoded url (which might be present if it was
|
// also insert a non-hex encoded url (which might be present if it was
|
||||||
// inserted separately)
|
// inserted separately)
|
||||||
params![url0, url1, url2, "illegal"],
|
params![url0, url1, url2, "illegal"],
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(get_url(db, 0).unwrap(), url0);
|
assert_eq!(get_url(db, 0)?, url0);
|
||||||
|
|
||||||
assert_eq!(get_url(db, 1).unwrap(), url1);
|
assert_eq!(get_url(db, 1)?, url1);
|
||||||
|
|
||||||
// Should successfully read it, even though it wasn't inserted as an
|
// Should successfully read it, even though it wasn't inserted as an
|
||||||
// escaped url.
|
// escaped url.
|
||||||
let out_url2: Url = get_url(db, 2).unwrap();
|
let out_url2: Url = get_url(db, 2)?;
|
||||||
assert_eq!(out_url2, Url::parse(url2).unwrap());
|
assert_eq!(out_url2, Url::parse(url2).unwrap());
|
||||||
|
|
||||||
// Make sure the conversion error comes through correctly.
|
// Make sure the conversion error comes through correctly.
|
||||||
@ -79,5 +77,6 @@ mod test {
|
|||||||
panic!("Expected conversion failure, got {}", e);
|
panic!("Expected conversion failure, got {}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,11 +106,11 @@ mod test {
|
|||||||
use std::time;
|
use std::time;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_unlock_notify() {
|
fn test_unlock_notify() -> Result<()> {
|
||||||
let url = "file::memory:?cache=shared";
|
let url = "file::memory:?cache=shared";
|
||||||
let flags = OpenFlags::SQLITE_OPEN_READ_WRITE | OpenFlags::SQLITE_OPEN_URI;
|
let flags = OpenFlags::SQLITE_OPEN_READ_WRITE | OpenFlags::SQLITE_OPEN_URI;
|
||||||
let db1 = Connection::open_with_flags(url, flags).unwrap();
|
let db1 = Connection::open_with_flags(url, flags)?;
|
||||||
db1.execute_batch("CREATE TABLE foo (x)").unwrap();
|
db1.execute_batch("CREATE TABLE foo (x)")?;
|
||||||
let (rx, tx) = sync_channel(0);
|
let (rx, tx) = sync_channel(0);
|
||||||
let child = thread::spawn(move || {
|
let child = thread::spawn(move || {
|
||||||
let mut db2 = Connection::open_with_flags(url, flags).unwrap();
|
let mut db2 = Connection::open_with_flags(url, flags).unwrap();
|
||||||
@ -123,7 +123,8 @@ mod test {
|
|||||||
});
|
});
|
||||||
assert_eq!(tx.recv().unwrap(), 1);
|
assert_eq!(tx.recv().unwrap(), 1);
|
||||||
let the_answer: Result<i64> = db1.query_row("SELECT x FROM foo", [], |r| r.get(0));
|
let the_answer: Result<i64> = db1.query_row("SELECT x FROM foo", [], |r| r.get(0));
|
||||||
assert_eq!(42i64, the_answer.unwrap());
|
assert_eq!(42i64, the_answer?);
|
||||||
child.join().unwrap();
|
child.join().unwrap();
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,29 +197,30 @@ unsafe impl VTabCursor for ArrayTabCursor<'_> {
|
|||||||
mod test {
|
mod test {
|
||||||
use crate::types::Value;
|
use crate::types::Value;
|
||||||
use crate::vtab::array;
|
use crate::vtab::array;
|
||||||
use crate::Connection;
|
use crate::{Connection, Result};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_array_module() {
|
fn test_array_module() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
array::load_module(&db).unwrap();
|
array::load_module(&db)?;
|
||||||
|
|
||||||
let v = vec![1i64, 2, 3, 4];
|
let v = vec![1i64, 2, 3, 4];
|
||||||
let values: Vec<Value> = v.into_iter().map(Value::from).collect();
|
let values: Vec<Value> = v.into_iter().map(Value::from).collect();
|
||||||
let ptr = Rc::new(values);
|
let ptr = Rc::new(values);
|
||||||
{
|
{
|
||||||
let mut stmt = db.prepare("SELECT value from rarray(?);").unwrap();
|
let mut stmt = db.prepare("SELECT value from rarray(?);")?;
|
||||||
|
|
||||||
let rows = stmt.query_map(&[&ptr], |row| row.get::<_, i64>(0)).unwrap();
|
let rows = stmt.query_map(&[&ptr], |row| row.get::<_, i64>(0))?;
|
||||||
assert_eq!(2, Rc::strong_count(&ptr));
|
assert_eq!(2, Rc::strong_count(&ptr));
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
for (i, value) in rows.enumerate() {
|
for (i, value) in rows.enumerate() {
|
||||||
assert_eq!(i as i64, value.unwrap() - 1);
|
assert_eq!(i as i64, value? - 1);
|
||||||
count += 1;
|
count += 1;
|
||||||
}
|
}
|
||||||
assert_eq!(4, count);
|
assert_eq!(4, count);
|
||||||
}
|
}
|
||||||
assert_eq!(1, Rc::strong_count(&ptr));
|
assert_eq!(1, Rc::strong_count(&ptr));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -367,49 +367,41 @@ mod test {
|
|||||||
use fallible_iterator::FallibleIterator;
|
use fallible_iterator::FallibleIterator;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_csv_module() {
|
fn test_csv_module() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
csvtab::load_module(&db).unwrap();
|
csvtab::load_module(&db)?;
|
||||||
db.execute_batch("CREATE VIRTUAL TABLE vtab USING csv(filename='test.csv', header=yes)")
|
db.execute_batch("CREATE VIRTUAL TABLE vtab USING csv(filename='test.csv', header=yes)")?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut s = db.prepare("SELECT rowid, * FROM vtab").unwrap();
|
let mut s = db.prepare("SELECT rowid, * FROM vtab")?;
|
||||||
{
|
{
|
||||||
let headers = s.column_names();
|
let headers = s.column_names();
|
||||||
assert_eq!(vec!["rowid", "colA", "colB", "colC"], headers);
|
assert_eq!(vec!["rowid", "colA", "colB", "colC"], headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
let ids: Result<Vec<i32>> = s
|
let ids: Result<Vec<i32>> = s.query([])?.map(|row| row.get::<_, i32>(0)).collect();
|
||||||
.query([])
|
let sum = ids?.iter().sum::<i32>();
|
||||||
.unwrap()
|
|
||||||
.map(|row| row.get::<_, i32>(0))
|
|
||||||
.collect();
|
|
||||||
let sum = ids.unwrap().iter().sum::<i32>();
|
|
||||||
assert_eq!(sum, 15);
|
assert_eq!(sum, 15);
|
||||||
}
|
}
|
||||||
db.execute_batch("DROP TABLE vtab").unwrap();
|
db.execute_batch("DROP TABLE vtab")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_csv_cursor() {
|
fn test_csv_cursor() -> Result<()> {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
csvtab::load_module(&db).unwrap();
|
csvtab::load_module(&db)?;
|
||||||
db.execute_batch("CREATE VIRTUAL TABLE vtab USING csv(filename='test.csv', header=yes)")
|
db.execute_batch("CREATE VIRTUAL TABLE vtab USING csv(filename='test.csv', header=yes)")?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut s = db
|
let mut s = db.prepare(
|
||||||
.prepare(
|
|
||||||
"SELECT v1.rowid, v1.* FROM vtab v1 NATURAL JOIN vtab v2 WHERE \
|
"SELECT v1.rowid, v1.* FROM vtab v1 NATURAL JOIN vtab v2 WHERE \
|
||||||
v1.rowid < v2.rowid",
|
v1.rowid < v2.rowid",
|
||||||
)
|
)?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut rows = s.query([]).unwrap();
|
let mut rows = s.query([])?;
|
||||||
let row = rows.next().unwrap().unwrap();
|
let row = rows.next()?.unwrap();
|
||||||
assert_eq!(row.get_unwrap::<_, i32>(0), 2);
|
assert_eq!(row.get_unwrap::<_, i32>(0), 2);
|
||||||
}
|
}
|
||||||
db.execute_batch("DROP TABLE vtab").unwrap();
|
db.execute_batch("DROP TABLE vtab")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -273,26 +273,27 @@ unsafe impl VTabCursor for SeriesTabCursor<'_> {
|
|||||||
mod test {
|
mod test {
|
||||||
use crate::ffi;
|
use crate::ffi;
|
||||||
use crate::vtab::series;
|
use crate::vtab::series;
|
||||||
use crate::Connection;
|
use crate::{Connection, Result};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_series_module() {
|
fn test_series_module() -> Result<()> {
|
||||||
let version = unsafe { ffi::sqlite3_libversion_number() };
|
let version = unsafe { ffi::sqlite3_libversion_number() };
|
||||||
if version < 3_008_012 {
|
if version < 3_008_012 {
|
||||||
return;
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
series::load_module(&db).unwrap();
|
series::load_module(&db)?;
|
||||||
|
|
||||||
let mut s = db.prepare("SELECT * FROM generate_series(0,20,5)").unwrap();
|
let mut s = db.prepare("SELECT * FROM generate_series(0,20,5)")?;
|
||||||
|
|
||||||
let series = s.query_map([], |row| row.get::<_, i32>(0)).unwrap();
|
let series = s.query_map([], |row| row.get::<_, i32>(0))?;
|
||||||
|
|
||||||
let mut expected = 0;
|
let mut expected = 0;
|
||||||
for value in series {
|
for value in series {
|
||||||
assert_eq!(expected, value.unwrap());
|
assert_eq!(expected, value?);
|
||||||
expected += 5;
|
expected += 5;
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#[cfg(feature = "vtab")]
|
#[cfg(feature = "vtab")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_dummy_module() {
|
fn test_dummy_module() -> rusqlite::Result<()> {
|
||||||
use rusqlite::types::ToSql;
|
use rusqlite::types::ToSql;
|
||||||
use rusqlite::vtab::{
|
use rusqlite::vtab::{
|
||||||
eponymous_only_module, sqlite3_vtab, sqlite3_vtab_cursor, Context, IndexInfo, VTab,
|
eponymous_only_module, sqlite3_vtab, sqlite3_vtab_cursor, Context, IndexInfo, VTab,
|
||||||
@ -84,20 +84,18 @@ fn test_dummy_module() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory()?;
|
||||||
|
|
||||||
db.create_module::<DummyTab>("dummy", &module, None)
|
db.create_module::<DummyTab>("dummy", &module, None)?;
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let version = version_number();
|
let version = version_number();
|
||||||
if version < 3_008_012 {
|
if version < 3_008_012 {
|
||||||
return;
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut s = db.prepare("SELECT * FROM dummy()").unwrap();
|
let mut s = db.prepare("SELECT * FROM dummy()")?;
|
||||||
|
|
||||||
let dummy = s
|
let dummy = s.query_row(&[] as &[&dyn ToSql], |row| row.get::<_, i32>(0))?;
|
||||||
.query_row(&[] as &[&dyn ToSql], |row| row.get::<_, i32>(0))
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(1, dummy);
|
assert_eq!(1, dummy);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user