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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
use sqlx::{self, ConnectOptions, Connection, Executor, Row};
use thiserror;
use crate::github;
#[derive(Debug)]
pub struct Repo {
id: i64,
name: Option<String>,
updated_at: Option<String>,
}
impl From<github::Repo> for Repo {
fn from(repo: github::Repo) -> Self {
Self {
id: repo.id,
name: Some(repo.name),
updated_at: Some(repo.updated_at),
}
}
}
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("database error")]
Db(#[from] sqlx::Error),
}
#[derive(Debug)]
pub struct Db {
connection: sqlx::SqliteConnection,
}
impl Db {
pub async fn connect(path: &str) -> Result<Self, Error> {
Ok(
Db {
connection: sqlx::sqlite::SqliteConnectOptions::new()
.filename(path)
.create_if_missing(true)
.connect()
.await?,
}
)
}
pub async fn create(&mut self) -> Result<(), 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, Error> {
let mut tx = self.connection.begin().await?;
// NOTE: Returns `RowNotFound` if not found.
let row = sqlx::query(r#"
SELECT id, name, updated_at
FROM repositories
WHERE id = ?
"#)
.bind(id)
.fetch_one(&mut tx)
.await?;
tx.commit().await?;
Ok(
Repo {
id: row.get(0),
name: Some(row.get(1)),
updated_at: Some(row.get(2)),
}
)
}
pub async fn repo_insert(&mut self, repo: Repo) -> Result<(), Error> {
let mut tx = self.connection.begin().await?;
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 async fn repo_is_updated(
&mut self,
repo: &Repo,
) -> Result<bool, Error> {
let mut tx = self.connection.begin().await?;
let is_updated = match sqlx::query(r#"
SELECT 1
FROM repositories
WHERE id = ?
AND datetime(updated_at) < datetime(?)
"#)
.bind(repo.id)
.bind(&repo.updated_at)
.fetch_optional(&mut tx)
.await
{
Ok(Some(_)) => Ok(true),
Ok(None) => Ok(false),
Err(e) => Err(e.into()),
};
tx.commit().await?;
is_updated
}
pub fn repo_update(repo: &Repo) -> Result<(), Error> {
Ok(())
}
}
|