summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.sqlx/query-397bdfdb77651e3e65e9ec53cf075037c794cae08f79a689c7a037aa68d7c00c.json20
-rw-r--r--.sqlx/query-54fe04ade0a01cfd0f3ddbedfa884d8a00f692eba656d3daa8119011b703cfcd.json20
-rw-r--r--migrations/20240928012031_channel_stored_sequence.sql60
-rw-r--r--src/events/repo/message.rs20
4 files changed, 90 insertions, 30 deletions
diff --git a/.sqlx/query-397bdfdb77651e3e65e9ec53cf075037c794cae08f79a689c7a037aa68d7c00c.json b/.sqlx/query-397bdfdb77651e3e65e9ec53cf075037c794cae08f79a689c7a037aa68d7c00c.json
new file mode 100644
index 0000000..5cb7282
--- /dev/null
+++ b/.sqlx/query-397bdfdb77651e3e65e9ec53cf075037c794cae08f79a689c7a037aa68d7c00c.json
@@ -0,0 +1,20 @@
+{
+ "db_name": "SQLite",
+ "query": "\n update channel\n set last_sequence = last_sequence + 1\n where id = $1\n returning last_sequence as \"next_sequence: Sequence\"\n ",
+ "describe": {
+ "columns": [
+ {
+ "name": "next_sequence: Sequence",
+ "ordinal": 0,
+ "type_info": "Integer"
+ }
+ ],
+ "parameters": {
+ "Right": 1
+ },
+ "nullable": [
+ false
+ ]
+ },
+ "hash": "397bdfdb77651e3e65e9ec53cf075037c794cae08f79a689c7a037aa68d7c00c"
+}
diff --git a/.sqlx/query-54fe04ade0a01cfd0f3ddbedfa884d8a00f692eba656d3daa8119011b703cfcd.json b/.sqlx/query-54fe04ade0a01cfd0f3ddbedfa884d8a00f692eba656d3daa8119011b703cfcd.json
deleted file mode 100644
index a739207..0000000
--- a/.sqlx/query-54fe04ade0a01cfd0f3ddbedfa884d8a00f692eba656d3daa8119011b703cfcd.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "db_name": "SQLite",
- "query": "\n -- `max` never returns null, but sqlx can't detect that\n select max(sequence) as \"sequence!: Sequence\"\n from message\n where channel = $1\n ",
- "describe": {
- "columns": [
- {
- "name": "sequence!: Sequence",
- "ordinal": 0,
- "type_info": "Null"
- }
- ],
- "parameters": {
- "Right": 1
- },
- "nullable": [
- true
- ]
- },
- "hash": "54fe04ade0a01cfd0f3ddbedfa884d8a00f692eba656d3daa8119011b703cfcd"
-}
diff --git a/migrations/20240928012031_channel_stored_sequence.sql b/migrations/20240928012031_channel_stored_sequence.sql
new file mode 100644
index 0000000..badd88d
--- /dev/null
+++ b/migrations/20240928012031_channel_stored_sequence.sql
@@ -0,0 +1,60 @@
+alter table channel
+rename to old_channel;
+
+-- Add new columns
+create table channel (
+ id text
+ not null
+ primary key,
+ name text
+ not null
+ unique,
+ created_at text
+ not null,
+ last_sequence bigint
+ not null
+);
+
+-- Transfer data from original table
+insert into channel
+select
+ channel.id,
+ channel.name,
+ channel.created_at,
+ coalesce(
+ max(message.sequence),
+ 0
+ ) as last_sequence
+from old_channel as channel
+ left join message on channel.id = message.channel
+group by channel.id, channel.name;
+
+-- Fix up `message` foreign keys
+alter table message
+rename to old_message;
+
+create table message (
+ id text
+ not null
+ primary key,
+ sequence bigint
+ not null,
+ channel text
+ not null
+ references channel (id),
+ sender text
+ not null
+ references login (id),
+ body text
+ not null,
+ sent_at text
+ not null,
+ unique (channel, sequence)
+);
+
+insert into message
+select * from old_message;
+
+-- Bury the bodies respectfully
+drop table old_message;
+drop table old_channel;
diff --git a/src/events/repo/message.rs b/src/events/repo/message.rs
index ec17d55..f6fce0e 100644
--- a/src/events/repo/message.rs
+++ b/src/events/repo/message.rs
@@ -4,7 +4,7 @@ use crate::{
clock::DateTime,
events::types::{self, Sequence},
repo::{
- channel::Channel,
+ channel::{self, Channel},
login::{self, Login},
message,
},
@@ -30,7 +30,7 @@ impl<'c> Events<'c> {
body: &str,
sent_at: &DateTime,
) -> Result<types::ChannelEvent, sqlx::Error> {
- let sequence = self.next_sequence_for(channel).await?;
+ let sequence = self.assign_sequence(&channel.id).await?;
let id = message::Id::generate();
@@ -72,20 +72,20 @@ impl<'c> Events<'c> {
Ok(message)
}
- async fn next_sequence_for(&mut self, channel: &Channel) -> Result<Sequence, sqlx::Error> {
- let current = sqlx::query_scalar!(
+ async fn assign_sequence(&mut self, channel: &channel::Id) -> Result<Sequence, sqlx::Error> {
+ let next = sqlx::query_scalar!(
r#"
- -- `max` never returns null, but sqlx can't detect that
- select max(sequence) as "sequence!: Sequence"
- from message
- where channel = $1
+ update channel
+ set last_sequence = last_sequence + 1
+ where id = $1
+ returning last_sequence as "next_sequence: Sequence"
"#,
- channel.id,
+ channel,
)
.fetch_one(&mut *self.0)
.await?;
- Ok(current.next())
+ Ok(next)
}
pub async fn expire(&mut self, expire_at: &DateTime) -> Result<(), sqlx::Error> {