Going somewhere.
This commit is contained in:
1 parent
4a86c4250a
commit
511b2a88f6
6 files changed
+127
-18
No files matched your search
Generated
+7
@@ -146,6 +146,7 @@ dependencies = [
|
|||||||
"clap-verbosity-flag",
|
"clap-verbosity-flag",
|
||||||
"home",
|
"home",
|
||||||
"log",
|
"log",
|
||||||
|
"resource",
|
||||||
"rusqlite",
|
"rusqlite",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@@ -335,6 +336,12 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "resource"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "11a7f6703c396037a02da99195e49138c37f3cc5146cb95f2f7d26debc0c5622"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rusqlite"
|
name = "rusqlite"
|
||||||
version = "0.28.0"
|
version = "0.28.0"
|
||||||
|
|||||||
+2
-1
@@ -14,4 +14,5 @@ simple_logger = "4.0.0"
|
|||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
home = "0.5.4"
|
home = "0.5.4"
|
||||||
sha2 = "0.10.6"
|
sha2 = "0.10.6"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
resource = "0.5.0"
|
||||||
@@ -2,23 +2,25 @@ CREATE TABLE IF NOT EXISTS users
|
|||||||
(
|
(
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
public_key TEXT NOT NULL
|
public_key TEXT NOT NULL,
|
||||||
|
foo INTEGER
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS security_types
|
CREATE TABLE IF NOT EXISTS security_types
|
||||||
(
|
(
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
name TEXT PRIMARY KEY
|
||||||
name TEXT NOT NULL UNIQUE
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
INSERT INTO security_types(name)
|
||||||
|
VALUES ('currency'), ('bond');
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS securities
|
CREATE TABLE IF NOT EXISTS securities
|
||||||
(
|
(
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
security_type INTEGER NOT NULL,
|
security_type TEXT NOT NULL,
|
||||||
name TEXT NOT NULL UNIQUE,
|
name TEXT NOT NULL UNIQUE,
|
||||||
symbol TEXT NOT NULL UNIQUE,
|
symbol TEXT NOT NULL UNIQUE,
|
||||||
|
FOREIGN KEY (security_type) REFERENCES security_types (name)
|
||||||
FOREIGN KEY (security_type) REFERENCES security_types (id)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS account
|
CREATE TABLE IF NOT EXISTS account
|
||||||
@@ -33,4 +35,4 @@ CREATE TABLE IF NOT EXISTS account
|
|||||||
CREATE TABLE IF NOT EXISTS account_values
|
CREATE TABLE IF NOT EXISTS account_values
|
||||||
(
|
(
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT
|
id INTEGER PRIMARY KEY AUTOINCREMENT
|
||||||
);
|
);
|
||||||
+6
-5
@@ -7,7 +7,7 @@ use log::{debug, info};
|
|||||||
use rusqlite::Connection;
|
use rusqlite::Connection;
|
||||||
use simple_logger::SimpleLogger;
|
use simple_logger::SimpleLogger;
|
||||||
|
|
||||||
use crate::migration::migrate;
|
use crate::migration::apply_migrations;
|
||||||
|
|
||||||
mod migration;
|
mod migration;
|
||||||
mod users;
|
mod users;
|
||||||
@@ -68,8 +68,8 @@ fn new_user_command_line_parser() -> Command {
|
|||||||
return Command::new("new")
|
return Command::new("new")
|
||||||
.long_flag("new")
|
.long_flag("new")
|
||||||
.about("Create new user.")
|
.about("Create new user.")
|
||||||
.arg(Arg::new("name").long("name").help("name of new user.").action(ArgAction::Set))
|
.arg(Arg::new("name").long("name").required(true).help("name of new user.").action(ArgAction::Set))
|
||||||
.arg(Arg::new("public_key").long("public-key").help("public key of users.").action(ArgAction::Set));
|
.arg(Arg::new("public_key").required(true).long("public-key").help("public key of users.").action(ArgAction::Set));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ls_user_command_line_parser() -> Command {
|
fn ls_user_command_line_parser() -> Command {
|
||||||
@@ -308,14 +308,15 @@ fn set_logger(m: &ArgMatches) {
|
|||||||
SimpleLogger::new().with_level(get_verbosity(&m)).init().unwrap();
|
SimpleLogger::new().with_level(get_verbosity(&m)).init().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let command = command_line_parser();
|
let command = command_line_parser();
|
||||||
let m = command.get_matches();
|
let m = command.get_matches();
|
||||||
|
|
||||||
set_logger(&m);
|
set_logger(&m);
|
||||||
let mut conn = get_connection(&m);
|
let mut conn = get_connection(&m);
|
||||||
let migrations: Vec<String> = Vec::new();
|
|
||||||
migrate(&mut conn, & migrations).unwrap();
|
apply_migrations(&mut conn).unwrap();
|
||||||
let mut logic = ProCommandLineLogic::new();
|
let mut logic = ProCommandLineLogic::new();
|
||||||
process_command_line(&conn, &m, &mut logic);
|
process_command_line(&conn, &m, &mut logic);
|
||||||
}
|
}
|
||||||
+15
-3
@@ -1,6 +1,7 @@
|
|||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use rusqlite::{Connection, Transaction};
|
use rusqlite::{Connection, Transaction};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
|
use resource::{resource_str};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum IntegrityError {
|
pub enum IntegrityError {
|
||||||
@@ -52,13 +53,12 @@ pub fn migrate(conn: &mut Connection, migrations: &Vec<String>) -> Result<(), Er
|
|||||||
fn apply_migration(tx: &Transaction, id: usize, migration: &String) -> Result<(), Error> {
|
fn apply_migration(tx: &Transaction, id: usize, migration: &String) -> Result<(), Error> {
|
||||||
let hash = compute_migration_sha256(migration);
|
let hash = compute_migration_sha256(migration);
|
||||||
|
|
||||||
|
|
||||||
let q = "INSERT INTO shitty_migrations(id, sha256) VALUES (?1, ?2)";
|
let q = "INSERT INTO shitty_migrations(id, sha256) VALUES (?1, ?2)";
|
||||||
tx.execute(q, (&id, &hash)).map_err(|e| Error::Sql(e))?;
|
tx.execute(q, (&id, &hash)).map_err(|e| Error::Sql(e))?;
|
||||||
// let migration_id = tx.last_insert_rowid();
|
|
||||||
|
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
tx.execute(migration, ()).map_err(|e| Error::Sql(e))?;
|
tx.execute_batch(migration).map_err(|e| Error::Sql(e))?;
|
||||||
let elapsed_time = now.elapsed();
|
let elapsed_time = now.elapsed();
|
||||||
|
|
||||||
let q = "UPDATE shitty_migrations SET duration = ?1 WHERE id = ?2";
|
let q = "UPDATE shitty_migrations SET duration = ?1 WHERE id = ?2";
|
||||||
@@ -89,6 +89,18 @@ fn check_migration(tx: &Transaction, id: usize, migration: &String) -> Result<()
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_migrations() -> Vec<String> {
|
||||||
|
let mut ret = Vec::new();
|
||||||
|
ret.push(resource_str!("migrations/create_tables_001.sql").as_ref().to_string());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn apply_migrations(conn: &mut Connection) -> Result<(), Error> {
|
||||||
|
let migrations = get_migrations();
|
||||||
|
return migrate(conn, &migrations);
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
@@ -1,2 +1,88 @@
|
|||||||
|
use rusqlite::{Connection, ToSql};
|
||||||
|
use serde::{Serialize};
|
||||||
|
use crate::migration;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub enum SecurityType {
|
||||||
|
Currency,
|
||||||
|
Bond,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToSql for SecurityType {
|
||||||
|
#[inline]
|
||||||
|
fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput<'_>> {
|
||||||
|
Ok(rusqlite::types::ToSqlOutput::from(match self {
|
||||||
|
SecurityType::Currency => "currency",
|
||||||
|
SecurityType::Bond => "bond",
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub struct Security {
|
||||||
|
id: i32,
|
||||||
|
security_type: SecurityType,
|
||||||
|
public_key: String,
|
||||||
|
symbol: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NewSecurity {
|
||||||
|
security_type: SecurityType,
|
||||||
|
public_key: String,
|
||||||
|
symbol: String,
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_security(conn: &mut Connection, sec: &NewSecurity) -> Result<(), rusqlite::Error> {
|
||||||
|
let tx = conn.transaction()?;
|
||||||
|
let q = "INSERT INTO
|
||||||
|
securities(name, symbol, security_type)
|
||||||
|
VALUES(?1, ?2, ?3)";
|
||||||
|
let params = (&sec.name, &sec.symbol, &sec.security_type);
|
||||||
|
tx.execute(q, params)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use rusqlite::{Connection, params};
|
||||||
|
|
||||||
|
|
||||||
|
fn setup() -> Connection {
|
||||||
|
let mut conn = Connection::open_in_memory().unwrap();
|
||||||
|
migration::apply_migrations(&mut conn).unwrap();
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_security_types() -> Result<(), rusqlite::Error> {
|
||||||
|
let conn = setup();
|
||||||
|
let q = "CREATE TABLE test_security_types(
|
||||||
|
name TEXT,
|
||||||
|
FOREIGN KEY (name) REFERENCES security_types (name)
|
||||||
|
)";
|
||||||
|
conn.execute(q, ())?;
|
||||||
|
let security_types = vec![SecurityType::Currency, SecurityType::Bond];
|
||||||
|
for sec in security_types.iter() {
|
||||||
|
let q = "INSERT INTO test_security_types(name) VALUES (?1)";
|
||||||
|
conn.execute(q, params![sec])?;
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_security() -> Result<(), rusqlite::Error> {
|
||||||
|
let mut conn = setup();
|
||||||
|
let sec = NewSecurity {
|
||||||
|
security_type: SecurityType::Currency,
|
||||||
|
public_key: "123".to_string(),
|
||||||
|
symbol: "P".to_string(),
|
||||||
|
name: "pisatre".to_string(),
|
||||||
|
};
|
||||||
|
create_security(&mut conn, &sec)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user