mirror of
https://github.com/atuinsh/atuin.git
synced 2024-11-22 08:13:57 +01:00
Start testing
This commit is contained in:
parent
5e79c02f78
commit
4b602c6fdb
@ -6,5 +6,9 @@ create table if not exists records (
|
||||
|
||||
tag text not null,
|
||||
version text not null,
|
||||
data blob not null,
|
||||
data blob not null
|
||||
);
|
||||
|
||||
create index host_idx on records (host);
|
||||
create index tag_idx on records (tag);
|
||||
create index host_tag_idx on records (host, tag);
|
||||
|
@ -2,23 +2,15 @@
|
||||
// Multiple stores of multiple types are all stored in one chonky table (for now), and we just index
|
||||
// by tag/host
|
||||
|
||||
yo tomorrow morning me
|
||||
drink that coffee
|
||||
then wrap up this interface
|
||||
|
||||
you will need to
|
||||
- make sure the records use string IDs
|
||||
- add the version in
|
||||
- write some tests with a memory sqlite
|
||||
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use eyre::Result;
|
||||
use fs_err as fs;
|
||||
use sqlx::{
|
||||
sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePool, SqlitePoolOptions, SqliteRow},
|
||||
Result, Row,
|
||||
Row,
|
||||
};
|
||||
|
||||
use atuin_common::record::Record;
|
||||
@ -60,11 +52,94 @@ impl SqliteStore {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn save_raw(tx: &mut sqlx::Transaction<'_, sqlx::Sqlite>, r: &Record) -> Result<()> {
|
||||
// In sqlite, we are "limited" to i64. But that is still fine, until 2262.
|
||||
sqlx::query(
|
||||
"insert or ignore into records(id, host, timestamp, tag, version, data)
|
||||
values(?1, ?2, ?3, ?4, ?5, ?6)",
|
||||
)
|
||||
.bind(r.id.as_str())
|
||||
.bind(r.host.as_str())
|
||||
.bind(r.timestamp as i64)
|
||||
.bind(r.tag.as_str())
|
||||
.bind(r.version.as_str())
|
||||
.bind(r.data.as_slice())
|
||||
.execute(tx)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn query_row(row: SqliteRow) -> Record {
|
||||
let timestamp: i64 = row.get("timestamp");
|
||||
|
||||
Record {
|
||||
id: row.get("id"),
|
||||
host: row.get("host"),
|
||||
timestamp: timestamp as u64,
|
||||
tag: row.get("tag"),
|
||||
version: row.get("version"),
|
||||
data: row.get("data"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Store for SqliteStore {
|
||||
async fn push(record: Record) -> Result<Record> {
|
||||
async fn push(&self, record: Record) -> Result<Record> {
|
||||
// TODO: batch inserts
|
||||
let mut tx = self.pool.begin().await?;
|
||||
Self::save_raw(&mut tx, &record).await?;
|
||||
|
||||
Ok(record)
|
||||
}
|
||||
|
||||
async fn get(&self, id: String) -> Result<Record> {
|
||||
let res = sqlx::query("select * from records where id = ?1")
|
||||
.bind(id.as_str())
|
||||
.map(Self::query_row)
|
||||
.fetch_one(&self.pool)
|
||||
.await?;
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
async fn len(&self, host: String, tag: String) -> Result<u64> {
|
||||
let res: (i64,) =
|
||||
sqlx::query_as("select count(1) from records where host = ?1 and tag = ?2")
|
||||
.bind(host.as_str())
|
||||
.bind(tag.as_str())
|
||||
.fetch_one(&self.pool)
|
||||
.await?;
|
||||
|
||||
Ok(res.0 as u64)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::SqliteStore;
|
||||
|
||||
#[tokio::test]
|
||||
async fn create_db() {
|
||||
let db = SqliteStore::new(":memory:").await;
|
||||
|
||||
assert!(
|
||||
db.is_ok(),
|
||||
"db could not be created, {:?}",
|
||||
db.err().unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn push_record() {
|
||||
let db = SqliteStore::new(":memory:").await;
|
||||
|
||||
assert!(
|
||||
db.is_ok(),
|
||||
"db could not be created, {:?}",
|
||||
db.err().unwrap()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ use atuin_common::record::Record;
|
||||
/// be shell history, kvs, etc.
|
||||
#[async_trait]
|
||||
pub trait Store {
|
||||
async fn push(record: Record) -> Result<Record>;
|
||||
async fn get(id: String) -> Result<Record>;
|
||||
async fn len(host: String, tag: String) -> Result<usize>;
|
||||
async fn push(&self, record: Record) -> Result<Record>;
|
||||
async fn get(&self, id: String) -> Result<Record>;
|
||||
async fn len(&self, host: String, tag: String) -> Result<u64>;
|
||||
}
|
||||
|
@ -1,13 +1,15 @@
|
||||
/// A single record stored inside of our local database
|
||||
pub struct Record {
|
||||
pub id: i64,
|
||||
pub id: String,
|
||||
|
||||
pub host: String,
|
||||
|
||||
pub timestamp: u64,
|
||||
|
||||
/// The type of data we are storing here. It is probably useful to also
|
||||
/// include some sort of version. For example, history.v2
|
||||
// However we want to track versions for this tag, eg v2
|
||||
pub version: String,
|
||||
|
||||
/// The type of data we are storing here. Eg, "history"
|
||||
pub tag: String,
|
||||
|
||||
/// Some data. This can be anything you wish to store. Use the tag field to know how to handle it.
|
||||
|
Loading…
Reference in New Issue
Block a user