From d3fbecc57b5d6fa3223b945a45fe21eb78ffd49b Mon Sep 17 00:00:00 2001 From: Owen Jacobson Date: Fri, 18 Oct 2024 23:25:21 -0400 Subject: Switch to blanking tombstoned data with null, not empty string. This accomplishes two things: * It removes the need for an additional `channel_name_reservation` table, since `channel.name` now only contains non-null values for active channels, and * It nicely dovetails with the idea that `null` means an unknown value in SQL-land. --- src/channel/app.rs | 6 +++--- src/channel/repo.rs | 49 ++++++++++++------------------------------------- 2 files changed, 15 insertions(+), 40 deletions(-) (limited to 'src/channel') diff --git a/src/channel/app.rs b/src/channel/app.rs index 0409076..75c662d 100644 --- a/src/channel/app.rs +++ b/src/channel/app.rs @@ -23,9 +23,9 @@ impl<'a> Channels<'a> { pub async fn create(&self, name: &str, created_at: &DateTime) -> Result { let mut tx = self.db.begin().await?; let created = tx.sequence().next(created_at).await?; - let channel = tx.channels().create(name, &created).await?; - tx.channels() - .reserve_name(&channel, name) + let channel = tx + .channels() + .create(name, &created) .await .duplicate(|| CreateError::DuplicateName(name.into()))?; tx.commit().await?; diff --git a/src/channel/repo.rs b/src/channel/repo.rs index 4b10c54..1cd1c80 100644 --- a/src/channel/repo.rs +++ b/src/channel/repo.rs @@ -28,7 +28,7 @@ impl<'c> Channels<'c> { values ($1, $2, $3, $4) returning id as "id: Id", - name, + name as "name!", -- known non-null as we just set it created_at as "created_at: DateTime", created_sequence as "created_sequence: Sequence" "#, @@ -52,22 +52,6 @@ impl<'c> Channels<'c> { Ok(channel) } - pub async fn reserve_name(&mut self, channel: &History, name: &str) -> Result<(), sqlx::Error> { - let channel = channel.id(); - sqlx::query!( - r#" - insert into channel_name_reservation (id, name) - values ($1, $2) - "#, - channel, - name, - ) - .execute(&mut *self.0) - .await?; - - Ok(()) - } - pub async fn by_id(&mut self, channel: &Id) -> Result { let channel = sqlx::query!( r#" @@ -76,8 +60,8 @@ impl<'c> Channels<'c> { channel.name, channel.created_at as "created_at: DateTime", channel.created_sequence as "created_sequence: Sequence", - deleted.deleted_at as "deleted_at: DateTime", - deleted.deleted_sequence as "deleted_sequence: Sequence" + deleted.deleted_at as "deleted_at?: DateTime", + deleted.deleted_sequence as "deleted_sequence?: Sequence" from channel left join channel_deleted as deleted using (id) @@ -88,7 +72,7 @@ impl<'c> Channels<'c> { .map(|row| History { channel: Channel { id: row.id, - name: row.name, + name: row.name.unwrap_or_default(), deleted_at: row.deleted_at, }, created: Instant::new(row.created_at, row.created_sequence), @@ -121,7 +105,7 @@ impl<'c> Channels<'c> { .map(|row| History { channel: Channel { id: row.id, - name: row.name, + name: row.name.unwrap_or_default(), deleted_at: row.deleted_at, }, created: Instant::new(row.created_at, row.created_sequence), @@ -156,7 +140,7 @@ impl<'c> Channels<'c> { .map(|row| History { channel: Channel { id: row.id, - name: row.name, + name: row.name.unwrap_or_default(), deleted_at: row.deleted_at, }, created: Instant::new(row.created_at, row.created_sequence), @@ -174,17 +158,6 @@ impl<'c> Channels<'c> { deleted: &Instant, ) -> Result { let id = channel.id(); - sqlx::query_scalar!( - r#" - delete from channel_name_reservation - where id = $1 - returning 1 as "deleted: bool" - "#, - id, - ) - .fetch_one(&mut *self.0) - .await?; - sqlx::query_scalar!( r#" insert into channel_deleted (id, deleted_at, deleted_sequence) @@ -202,10 +175,12 @@ impl<'c> Channels<'c> { // retconned to have been the empty string. Someone reading the event stream // afterwards, or looking at channels via the API, cannot retrieve the // "deleted" channel's information by ignoring the deletion event. + // + // This also avoids the need for a separate name reservation table to ensure that live channels have unique names, since the `channel` table's name field is unique over non-null values. sqlx::query_scalar!( r#" update channel - set name = "" + set name = null where id = $1 returning 1 as "updated: bool" "#, @@ -261,8 +236,8 @@ impl<'c> Channels<'c> { channel.name, channel.created_at as "created_at: DateTime", channel.created_sequence as "created_sequence: Sequence", - deleted.deleted_at as "deleted_at: DateTime", - deleted.deleted_sequence as "deleted_sequence: Sequence" + deleted.deleted_at as "deleted_at?: DateTime", + deleted.deleted_sequence as "deleted_sequence?: Sequence" from channel left join channel_deleted as deleted using (id) @@ -276,7 +251,7 @@ impl<'c> Channels<'c> { .map(|row| History { channel: Channel { id: row.id, - name: row.name, + name: row.name.unwrap_or_default(), deleted_at: row.deleted_at, }, created: Instant::new(row.created_at, row.created_sequence), -- cgit v1.2.3