Skip to content

Commit

Permalink
fix issue #983
Browse files Browse the repository at this point in the history
A readonly SPI session can now see the database modifications of a previous non-readonly SPI session.  This necessitates copying the active snapshot and incrementing its command id when a non-readonly SPI session is done.
  • Loading branch information
eeeebbbbrrrr committed Dec 27, 2022
1 parent 8678f75 commit 6abbdff
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 0 deletions.
42 changes: 42 additions & 0 deletions pgx-tests/src/tests/spi_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,4 +417,46 @@ mod tests {
Ok(())
})
}

#[pg_test]
fn test_spi_select_sees_update() -> spi::Result<()> {
let with_select = Spi::connect(|mut client| {
client.update("CREATE TABLE asd(id int)", None, None)?;
client.update("INSERT INTO asd(id) VALUES (1)", None, None)?;
client.select("SELECT COUNT(*) FROM asd", None, None)?.first().get_one::<i64>()
})?;
let with_get_one = Spi::get_one::<i64>("SELECT COUNT(*) FROM asd")?;

assert_eq!(with_select, with_get_one);
Ok(())
}

#[pg_test]
fn test_spi_select_sees_run() -> spi::Result<()> {
Spi::run("CREATE TABLE asd(id int)")?;
Spi::run("INSERT INTO asd(id) VALUES (1)")?;
let with_select = Spi::connect(|client| {
client.select("SELECT COUNT(*) FROM asd", None, None)?.first().get_one::<i64>()
})?;
let with_get_one = Spi::get_one::<i64>("SELECT COUNT(*) FROM asd")?;

assert_eq!(with_select, with_get_one);
Ok(())
}

#[pg_test]
fn test_spi_select_sees_update_in_other_session() -> spi::Result<()> {
Spi::connect::<spi::Result<()>, _>(|mut client| {
client.update("CREATE TABLE asd(id int)", None, None)?;
client.update("INSERT INTO asd(id) VALUES (1)", None, None)?;
Ok(())
})?;
let with_select = Spi::connect(|client| {
client.select("SELECT COUNT(*) FROM asd", None, None)?.first().get_one::<i64>()
})?;
let with_get_one = Spi::get_one::<i64>("SELECT COUNT(*) FROM asd")?;

assert_eq!(with_select, with_get_one);
Ok(())
}
}
14 changes: 14 additions & 0 deletions pgx/src/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,20 @@ pub struct SpiClient<'conn> {
__marker: PhantomData<&'conn SpiConnection>,
}

impl<'conn> Drop for SpiClient<'conn> {
fn drop(&mut self) {
if self.readonly == false {
// Assume the user actually modified the database during this SpiClient's lifetime
// and push a new snapshot with an updated CommandId. This ensures that subsequent
// `readonly == true` SpiClients will see the changes made by this one
unsafe {
pg_sys::PushCopiedSnapshot(pg_sys::GetActiveSnapshot());
pg_sys::UpdateActiveSnapshotCommandId();
}
}
}
}

/// a struct to manage our SPI connection lifetime
struct SpiConnection(PhantomData<*mut ()>);

Expand Down

0 comments on commit 6abbdff

Please sign in to comment.