a lot of things happened and my id is now null
cargo devel CI / cargo CI (push) Successful in 3m33s
Details
cargo devel CI / cargo CI (push) Successful in 3m33s
Details
This commit is contained in:
parent
53b0b36e66
commit
0603c3f460
|
@ -5,7 +5,7 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
diesel = { version = "2.2.1", features = ["serde_json", "sqlite", "uuid"] }
|
diesel = { version = "2.2.1", features = ["serde_json", "sqlite", "uuid", "returning_clauses_for_sqlite_3_35"] }
|
||||||
dotenvy = "0.15.7"
|
dotenvy = "0.15.7"
|
||||||
libpt.workspace = true
|
libpt.workspace = true
|
||||||
serde = { workspace = true, features = ["serde_derive"] }
|
serde = { workspace = true, features = ["serde_derive"] }
|
||||||
|
|
Binary file not shown.
|
@ -1,13 +1,19 @@
|
||||||
|
pub mod models;
|
||||||
pub mod schema;
|
pub mod schema;
|
||||||
|
|
||||||
use std::env;
|
use std::io::Write;
|
||||||
|
use std::{env, io};
|
||||||
|
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
use diesel::sqlite::SqliteConnection;
|
use diesel::sqlite::SqliteConnection;
|
||||||
|
|
||||||
use dotenvy::dotenv;
|
use dotenvy::dotenv;
|
||||||
|
|
||||||
use libpt::log::error; // load envars from a `.env` file
|
use libpt::log::{error, info, warn};
|
||||||
|
|
||||||
|
use self::models::*;
|
||||||
|
use self::schema::posts::dsl::*;
|
||||||
|
use diesel::prelude::*;
|
||||||
|
|
||||||
pub fn establish_connection() -> anyhow::Result<SqliteConnection> {
|
pub fn establish_connection() -> anyhow::Result<SqliteConnection> {
|
||||||
dotenv()?;
|
dotenv()?;
|
||||||
|
@ -16,3 +22,38 @@ pub fn establish_connection() -> anyhow::Result<SqliteConnection> {
|
||||||
Ok(SqliteConnection::establish(&database_url)
|
Ok(SqliteConnection::establish(&database_url)
|
||||||
.inspect_err(|e| error!("Error connecting to {}:\n{e:#?}", database_url))?)
|
.inspect_err(|e| error!("Error connecting to {}:\n{e:#?}", database_url))?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn load_posts(conn: &mut SqliteConnection) -> anyhow::Result<Vec<models::Post>> {
|
||||||
|
Ok(posts
|
||||||
|
.filter(published.eq(true))
|
||||||
|
.limit(5)
|
||||||
|
.select(Post::as_select())
|
||||||
|
.load(conn)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_posts(posts_to_print: &Vec<Post>) {
|
||||||
|
if !posts_to_print.is_empty() {
|
||||||
|
info!("Displaying {} posts", posts_to_print.len());
|
||||||
|
for post in posts_to_print {
|
||||||
|
println!("{}", post.title);
|
||||||
|
println!("-----------\n");
|
||||||
|
println!("{}", post.body);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warn!("Tried to display posts, but there are no posts stored in the database");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: this can't handle unicode stuff like 春 and I don't really care
|
||||||
|
pub fn read_buf_interactive(buf: &mut String) -> anyhow::Result<()> {
|
||||||
|
buf.clear();
|
||||||
|
let stdin = io::stdin();
|
||||||
|
let mut stdout = io::stdout();
|
||||||
|
|
||||||
|
print!("> ");
|
||||||
|
stdout.flush()?;
|
||||||
|
stdin.read_line(buf)?;
|
||||||
|
*buf = buf.trim().to_string();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
@ -1,16 +1,53 @@
|
||||||
use libpt::log::{self, debug};
|
use diesel::SqliteConnection;
|
||||||
|
use diesel_demo::models::PostDraft;
|
||||||
|
use libpt::log::{self, debug, info, trace, warn};
|
||||||
|
|
||||||
use diesel_demo as lib;
|
use diesel_demo as lib;
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
let _logger = log::Logger::builder()
|
let _logger = log::Logger::builder()
|
||||||
.max_level(log::Level::TRACE)
|
.max_level(log::Level::TRACE)
|
||||||
.uptime(true)
|
.show_time(false)
|
||||||
.build();
|
.build();
|
||||||
debug!("logger initialized");
|
debug!("logger initialized");
|
||||||
|
|
||||||
let conn = lib::establish_connection()?;
|
let mut conn = lib::establish_connection()?;
|
||||||
debug!("db connection established");
|
debug!("db connection established");
|
||||||
|
|
||||||
|
let posts = lib::load_posts(&mut conn)?;
|
||||||
|
|
||||||
|
lib::print_posts(&posts);
|
||||||
|
|
||||||
|
trace!("entering the repl");
|
||||||
|
repl(&mut conn)?;
|
||||||
|
trace!("leaving the repl");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn repl(conn: &mut SqliteConnection) -> anyhow::Result<()> {
|
||||||
|
let mut buf = String::new();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
lib::read_buf_interactive(&mut buf)?;
|
||||||
|
buf = buf.to_uppercase();
|
||||||
|
if buf.starts_with("HELP") {
|
||||||
|
println!("\
|
||||||
|
help - show this menu\n\
|
||||||
|
exit - exit the application\n\
|
||||||
|
new - create a new post")
|
||||||
|
}
|
||||||
|
else if buf.starts_with("EXIT") {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if buf.starts_with("NEW") {
|
||||||
|
let post = PostDraft::interactive_create()?;
|
||||||
|
post.post(conn)?;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
println!("Bad input: try 'help'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
use std::io::{self, Read, Write};
|
||||||
|
|
||||||
|
use diesel::prelude::*;
|
||||||
|
|
||||||
|
use crate::schema::posts;
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
const EOF: &str = "CTRL+D";
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
const EOF: &str = "CTRL+Z";
|
||||||
|
|
||||||
|
#[derive(Queryable, Selectable)]
|
||||||
|
#[diesel(table_name = crate::schema::posts)]
|
||||||
|
#[diesel(check_for_backend(diesel::sqlite::Sqlite))] // optional but improves generated compiler
|
||||||
|
// errors
|
||||||
|
pub struct Post {
|
||||||
|
pub id: i32,
|
||||||
|
pub title: String,
|
||||||
|
pub body: String,
|
||||||
|
pub published: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Insertable)]
|
||||||
|
#[diesel(table_name = crate::schema::posts)]
|
||||||
|
pub struct PostDraft {
|
||||||
|
pub title: String,
|
||||||
|
pub body: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PostDraft {
|
||||||
|
pub fn new<T: ToString>(title: T, body: T) -> Self {
|
||||||
|
Self {
|
||||||
|
title: title.to_string(),
|
||||||
|
body: body.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn post(self, conn: &mut SqliteConnection) -> anyhow::Result<Post> {
|
||||||
|
Ok(diesel::insert_into(posts::table)
|
||||||
|
.values(&self)
|
||||||
|
.returning(Post::as_returning())
|
||||||
|
.get_result(conn)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn interactive_create() -> anyhow::Result<Self> {
|
||||||
|
let mut title = String::new();
|
||||||
|
let mut body = String::new();
|
||||||
|
let mut stdin = io::stdin();
|
||||||
|
|
||||||
|
print!("Title: ");
|
||||||
|
io::stdout().flush()?;
|
||||||
|
stdin.read_line(&mut title)?;
|
||||||
|
title = title.trim().to_string();
|
||||||
|
|
||||||
|
println!("(End with {} when finished) Body:\n", EOF);
|
||||||
|
stdin.read_to_string(&mut body)?;
|
||||||
|
body = body.trim().to_string();
|
||||||
|
|
||||||
|
Ok(Self::new(&title, &body))
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,11 +2,9 @@
|
||||||
|
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
posts (id) {
|
posts (id) {
|
||||||
id -> Int4, // what the hell is an Int4???? I guess it must
|
id -> Integer,
|
||||||
// be a 4 byte integer (u32?), no way it would be a nibble.
|
title -> Text,
|
||||||
title -> Varchar,
|
body -> Text,
|
||||||
body -> Text, // What is the difference between Text and Varchar? I know Varchar
|
|
||||||
// from various DB stuff but idk Text
|
|
||||||
published -> Bool,
|
published -> Bool,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue