summaryrefslogtreecommitdiff
path: root/src/channel
diff options
context:
space:
mode:
authorOwen Jacobson <owen@grimoire.ca>2024-10-18 23:25:21 -0400
committerOwen Jacobson <owen@grimoire.ca>2024-10-18 23:27:21 -0400
commitd3fbecc57b5d6fa3223b945a45fe21eb78ffd49b (patch)
treec62a5cb6636d5ef942c65e369e07b77fda42784c /src/channel
parent777e4281431a036eb663b5eec70f347b7425737d (diff)
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.
Diffstat (limited to 'src/channel')
-rw-r--r--src/channel/app.rs6
-rw-r--r--src/channel/repo.rs49
2 files changed, 15 insertions, 40 deletions
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<Channel, CreateError> {
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<History, sqlx::Error> {
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),
@@ -176,17 +160,6 @@ impl<'c> Channels<'c> {
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)
values ($1, $2, $3)
returning 1 as "deleted: bool"
@@ -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),