chuchi_postgres/
migrations.rs1use std::borrow::Cow;
9
10use crate::{connection::ConnectionOwned, filter, table::Table, Error};
11
12use chuchi_postgres_derive::{row, FromRow};
13use tracing::debug;
14use types::time::DateTime;
15
16#[derive(Debug, FromRow)]
17pub struct ExecutedMigration {
18 datetime: DateTime,
19}
20
21#[derive(Debug, Clone)]
25pub struct Migrations {
26 table: Table,
27}
28
29impl Migrations {
30 pub(super) fn new(table_name: Option<String>) -> Self {
32 Self {
33 table: Table::new(
34 table_name.map(Cow::Owned).unwrap_or("migrations".into()),
35 ),
36 }
37 }
38
39 pub(super) async fn init(
40 &self,
41 db: &mut ConnectionOwned,
42 ) -> Result<(), Error> {
43 let db = db.transaction().await?;
44 let conn = db.connection();
45
46 let table_exists =
48 TABLE_EXISTS.replace("migrations", self.table.name());
49
50 let [result] =
52 conn.query_one::<[bool; 1], _>(&table_exists, &[]).await?;
53
54 if !result {
55 let create_table =
56 CREATE_TABLE.replace("migrations", self.table.name());
57 conn.batch_execute(&create_table).await?;
58 }
59
60 db.commit().await?;
61
62 Ok(())
63 }
64
65 pub async fn add(
66 &self,
67 conn: &mut ConnectionOwned,
68 name: &str,
69 sql: &str,
70 ) -> Result<(), Error> {
71 let trans = conn.transaction().await?;
72 let conn = trans.connection();
73 let table = self.table.with_conn(conn);
74
75 let existing: Option<ExecutedMigration> =
77 table.select_opt(filter!(&name)).await?;
78 if let Some(mig) = existing {
79 debug!("migration {} was executed at {}", name, mig.datetime);
80 return Ok(());
81 }
82
83 conn.batch_execute(&sql).await?;
85
86 table
87 .insert(row! {
88 name,
89 "datetime": DateTime::now(),
90 })
91 .await?;
92
93 trans.commit().await?;
94
95 Ok(())
96 }
97}
98
99const TABLE_EXISTS: &str = "\
100SELECT EXISTS (
101 SELECT FROM information_schema.tables
102 WHERE table_schema = 'public'
103 AND table_name = 'migrations'
104);";
105
106const CREATE_TABLE: &str = "\
107CREATE TABLE migrations (
108 name text PRIMARY KEY,
109 datetime timestamp
110);
111
112CREATE INDEX ON migrations (datetime);";