aboutsummaryrefslogtreecommitdiffstats
path: root/src/database.rs
blob: e4ca5e9cb29b63ab736417cdaf33021c86bca5d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use sqlx::{self, ConnectOptions, Connection, Executor, Row};

use crate::github::Repo as GithubRepo;


#[derive(Debug)]
pub struct Repo {
    id: Option<i64>,
    name: Option<String>,
    updated_at: Option<String>,
}


#[derive(Debug)]
pub struct Db {
    connection: sqlx::SqliteConnection,
}

impl Db {
    pub async fn connect(
        path: &str,
    ) -> Result<Self, Box<dyn std::error::Error>> {
        Ok(
            Db {
                connection: sqlx::sqlite::SqliteConnectOptions::new()
                    .filename(path)
                    .create_if_missing(true)
                    .connect()
                    .await?,
            }
        )
    }

    pub async fn create(&mut self) -> Result<(), Box<dyn std::error::Error>> {
        let mut tx = self.connection.begin().await?;

        tx.execute(r#"
            CREATE TABLE repositories (
                id INTEGER PRIMARY KEY,
                name TEXT NOT NULL,
                updated_at TEXT NOT NULL
            );
        "#).await?;

        tx.execute(r#"
            CREATE UNIQUE INDEX idx_repositories_id
                ON repositories (id);
        "#).await?;

        tx.commit().await?;

        Ok(())
    }

    pub async fn repo_get(
        &mut self,
        id: i64,
    ) -> Result<Repo, Box<dyn std::error::Error>> {
        let mut tx = self.connection.begin().await?;

        // NOTE: Returns `RowNotFound` if not found.
        let row = sqlx::query("SELECT id, name FROM repositories where id = ?")
            .bind(id)
            .fetch_one(&mut tx)
            .await?;

        tx.commit().await?;

        Ok(
            Repo {
                id: Some(row.get(0)),
                name: Some(row.get(1)),
                updated_at: None,
            }
        )
    }

    pub async fn repo_insert(
        &mut self,
        repos: &[GithubRepo],
    ) -> Result<(), Box<dyn std::error::Error>> {
        let mut tx = self.connection.begin().await?;

        for repo in repos {
            sqlx::query(r#"
                INSERT INTO repositories
                    (id, name, updated_at)
                    VALUES
                    (?, ?, ?)
            "#)
                .bind(repo.id)
                .bind(&repo.name)
                .bind(&repo.updated_at)
                .execute(&mut tx)
                .await?;
        }

        tx.commit().await?;

        Ok(())
    }

    pub fn repo_is_updated() -> Result<bool, Box<dyn std::error::Error>> {
        // select id from repositories where updated_at > datetime("2020-07-13T17:57:56Z");
        Ok(false)
    }

    pub fn repo_update(repo: &GithubRepo) -> Result<(), Box<dyn std::error::Error>> {
        Ok(())
    }
}