mirror of
https://github.com/trailbaseio/trailbase.git
synced 2026-05-21 17:18:51 -05:00
Hoist ExecuteReturnedResults and make sure it behaves consistently across SQLite and PG.
This commit is contained in:
@@ -16,6 +16,9 @@ pub enum Error {
|
||||
decl_type: Option<crate::rows::ValueType>,
|
||||
},
|
||||
|
||||
#[error("ExecuteReturnedResults")]
|
||||
ExecuteReturnedResults,
|
||||
|
||||
#[error("FromSql: {0}")]
|
||||
FromSql(#[from] crate::from_sql::FromSqlError),
|
||||
|
||||
|
||||
@@ -783,6 +783,15 @@ mod tests {
|
||||
.await
|
||||
.unwrap()
|
||||
);
|
||||
|
||||
// Make sure queries returning rows fail.
|
||||
assert!(matches!(
|
||||
conn.execute("SELECT 5;", ()).await,
|
||||
Err(Error::ExecuteReturnedResults)
|
||||
));
|
||||
|
||||
// Batch succeeds (consistent with rusqlite's execute_batch).
|
||||
conn.execute_batch("SELECT 5;").await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -851,17 +860,20 @@ mod tests {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
conn
|
||||
.execute(
|
||||
r#"INSERT INTO foo ("bool", "uuid", "text") VALUES (:b, :u, :t)"#,
|
||||
named_params! {
|
||||
":b": true,
|
||||
":u": [0u8; 16],
|
||||
":t": "test",
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
1,
|
||||
conn
|
||||
.execute(
|
||||
r#"INSERT INTO foo ("bool", "uuid", "text") VALUES (:b, :u, :t)"#,
|
||||
named_params! {
|
||||
":b": true,
|
||||
":u": [0u8; 16],
|
||||
":t": "test",
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
@@ -31,7 +31,10 @@ impl SyncConnectionTrait for postgres::Client {
|
||||
fn execute(&mut self, sql: impl AsRef<str>, params: impl Params) -> Result<usize, Error> {
|
||||
let (sql, params) = PgStatement::new(sql.as_ref())?.bind(params)?;
|
||||
let mut row_iter = self.query_raw(&sql, params)?;
|
||||
row_iter.next()?;
|
||||
// Actually execute query.
|
||||
if row_iter.next()?.is_some() {
|
||||
return Err(Error::ExecuteReturnedResults);
|
||||
}
|
||||
return Ok(row_iter.rows_affected().unwrap_or_default() as usize);
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,11 @@ pub(super) fn execute(
|
||||
) -> Result<usize, Error> {
|
||||
let mut stmt = conn.prepare_cached(sql.as_ref())?;
|
||||
params.bind(&mut stmt)?;
|
||||
return Ok(stmt.raw_execute()?);
|
||||
|
||||
return match stmt.raw_execute() {
|
||||
Err(rusqlite::Error::ExecuteReturnedResults) => Err(Error::ExecuteReturnedResults),
|
||||
r => Ok(r?),
|
||||
};
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -96,7 +100,13 @@ pub(super) fn execute_batch(
|
||||
// NOTE: We must use `raw_query` instead of `raw_execute`, otherwise queries
|
||||
// returning rows (e.g. SELECT) will return an error. Rusqlite's batch_execute
|
||||
// behaves consistently.
|
||||
let _row = stmt.raw_query().next()?;
|
||||
match stmt.raw_query().next() {
|
||||
Err(rusqlite::Error::ExecuteReturnedResults) => return Err(Error::ExecuteReturnedResults),
|
||||
Err(err) => {
|
||||
return Err(err.into());
|
||||
}
|
||||
Ok(_) => {}
|
||||
};
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -644,3 +644,18 @@ fn test_busy() {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_execute_returning_rows() {
|
||||
let conn = Connection::open_in_memory().unwrap();
|
||||
|
||||
assert!(matches!(
|
||||
conn.execute("SELECT 4;", ()).await,
|
||||
Err(Error::ExecuteReturnedResults)
|
||||
));
|
||||
|
||||
// Make sure rusqlite and trailabse_sqlite consistently succeed for `execute_batch()`.
|
||||
conn.execute_batch("SELECT 4;").await.unwrap();
|
||||
let c = rusqlite::Connection::open_in_memory().unwrap();
|
||||
c.execute_batch("SELECT 4;").unwrap();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user