diff --git a/postgres/src/lib.rs b/postgres/src/lib.rs index bfaa53e..f3776b4 100644 --- a/postgres/src/lib.rs +++ b/postgres/src/lib.rs @@ -272,8 +272,13 @@ impl StorageTxn for Txn { "UPDATE clients SET latest_version_id = $1, versions_since_snapshot = versions_since_snapshot + 1 - WHERE client_id = $2 and latest_version_id = $3", - &[&version_id, &self.client_id, &parent_version_id], + WHERE client_id = $2 and (latest_version_id = $3 or latest_version_id = $4)", + &[ + &version_id, + &self.client_id, + &parent_version_id, + &Uuid::nil(), + ], ) .await .context("error updating latest_version_id")?; @@ -689,4 +694,22 @@ mod test { }) .await } + + #[tokio::test] + /// When an add_version call specifies a `parent_version_id` that does not exist in the + /// DB, but no other versions exist, the call succeeds. + async fn test_add_version_no_history() -> anyhow::Result<()> { + with_db(async |connection_string, db_client| { + let storage = PostgresStorage::new(connection_string).await?; + let client_id = make_client(&db_client).await?; + + let mut txn = storage.txn(client_id).await?; + let version_id = Uuid::new_v4(); + let parent_version_id = Uuid::new_v4(); + txn.add_version(version_id, parent_version_id, b"v1".to_vec()) + .await?; + Ok(()) + }) + .await + } } diff --git a/sqlite/src/lib.rs b/sqlite/src/lib.rs index 668ed81..ad9dfc4 100644 --- a/sqlite/src/lib.rs +++ b/sqlite/src/lib.rs @@ -276,11 +276,12 @@ impl StorageTxn for Txn { SET latest_version_id = ?, versions_since_snapshot = versions_since_snapshot + 1 - WHERE client_id = ? and latest_version_id = ?", + WHERE client_id = ? and (latest_version_id = ? or latest_version_id = ?)", params![ StoredUuid(version_id), StoredUuid(self.client_id), - StoredUuid(parent_version_id) + StoredUuid(parent_version_id), + StoredUuid(Uuid::nil()) ], ) .context("Error updating client for new version")?; @@ -489,4 +490,21 @@ mod test { Ok(()) } + + #[tokio::test] + /// When an add_version call specifies a `parent_version_id` that does not exist in the + /// DB, but no other versions exist, the call succeeds. + async fn test_add_version_no_history() -> anyhow::Result<()> { + let tmp_dir = TempDir::new()?; + let storage = SqliteStorage::new(tmp_dir.path())?; + let client_id = Uuid::new_v4(); + let mut txn = storage.txn(client_id).await?; + txn.new_client(Uuid::nil()).await?; + + let version_id = Uuid::new_v4(); + let parent_version_id = Uuid::new_v4(); + txn.add_version(version_id, parent_version_id, b"v1".to_vec()) + .await?; + Ok(()) + } }