-
Notifications
You must be signed in to change notification settings - Fork 1
/
friends.rs
110 lines (91 loc) · 3.46 KB
/
friends.rs
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
use qjack::{q, Model};
type Result<T> = std::result::Result<T, qjack::Error>;
#[derive(Model, Debug)]
struct Friend {
id: i32,
name: String,
password: String,
}
impl Friend {
async fn create_table_if_not_exists() -> Result<()> {
q("CREATE TABLE IF NOT EXISTS friends (
id SERIAL PRIMARY KEY,
name VARCHAR(32) NOT NULL,
password VARCHAR(64) NOT NULL
)").await?; Ok(())
}
async fn find_by_id(id: i32) -> Result<Self> {
q(Self::one("
SELECT id, name, password FROM friends
WHERE id = $1
"), id).await
}
async fn search_by_password(password: &str) -> Result<Option<Self>> {
q(Self::optional("
SELECT id, name, password FROM friends
WHERE password = $1
"), password).await
}
async fn find_all_with_limit_by_name_like(like: &str, limit: i32) -> Result<Vec<Friend>> {
q(Self::all("
SELECT id, name, password FROM friends
WHERE name LIKE $1
LIMIT $2
"), like, limit).await
}
async fn create_many(name_passwords: impl IntoIterator<Item = (String, String)>) -> Result<()> {
let mut name_passwords = name_passwords.into_iter();
let mut insert = String::from("INSERT INTO friends (name, password) VALUES");
if let Some((first_name, first_password)) = name_passwords.next() {
insert.push_str(&format!(" ('{first_name}', '{first_password}')"))
} else {return Ok(())}
for (name, password) in name_passwords {
insert.push_str(&format!(", ('{name}', '{password}')"))
}
q(&*insert).await?; Ok(())
}
}
#[tokio::main]
async fn main() -> Result<()> {
q.jack("postgres://qjack:password@postgres:5432/db")
.max_connections(42)
.await?;
println!("Hi, jacked!");
Friend::create_table_if_not_exists().await?;
let friends: Vec<(String, String)> = {
println!();
println!("Happy jacking! Could you enter data of some of your firends?");
println!("(press q when you stop entering)");
println!();
let mut inputs = Vec::new(); loop {use std::io::{stdin, stdout, Write};
print!("name: "); stdout().flush().ok();
let mut name = String::new();
stdin().read_line(&mut name).ok();
name.pop(/* final '\n' */);
if name == "q" {break}
print!("password: "); stdout().flush().ok();
let mut password = String::new();
stdin().read_line(&mut password).ok();
password.pop(/* final '\n' */);
if password == "q" {break}
inputs.push((name, password));
println!()
}
println!("Ok, thanks!\n");
inputs
};
if friends.is_empty() {
println!("Oh No! You have no friends...");
return Ok(())
}
Friend::create_many(friends).await?;
let first_user = Friend::find_by_id(1).await?;
println!("First user is `{}` (password: \"{}\").", first_user.name, first_user.password);
match Friend::search_by_password("password").await? {
None => println!("No user has password \"password\"."),
Some(one) => println!("{}th user `{}` has password \"password\"!.", one.id, one.name),
}
let friends_ending_with_a = Friend::find_all_with_limit_by_name_like("%a", 100).await?;
println!("Fiends whose name end with 'a': {friends_ending_with_a:#?}");
Ok(())
}