first pass on transaction read client
This commit is contained in:
parent
66e6fef75e
commit
b0c6399a38
3 changed files with 125 additions and 0 deletions
|
@ -16,6 +16,9 @@ uuid = { version = "0.5", features = ["v4", "serde"] }
|
||||||
|
|
||||||
error-chain = { git = "https://github.com/rnewman/error-chain", branch = "rnewman/sync" }
|
error-chain = { git = "https://github.com/rnewman/error-chain", branch = "rnewman/sync" }
|
||||||
|
|
||||||
|
[dependencies.mentat_core]
|
||||||
|
path = "../core"
|
||||||
|
|
||||||
[dependencies.mentat_db]
|
[dependencies.mentat_db]
|
||||||
path = "../db"
|
path = "../db"
|
||||||
|
|
||||||
|
|
|
@ -20,12 +20,14 @@ extern crate futures;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
extern crate mentat_db;
|
extern crate mentat_db;
|
||||||
|
extern crate mentat_core;
|
||||||
extern crate rusqlite;
|
extern crate rusqlite;
|
||||||
extern crate edn;
|
extern crate edn;
|
||||||
extern crate uuid;
|
extern crate uuid;
|
||||||
|
|
||||||
pub mod schema;
|
pub mod schema;
|
||||||
pub mod metadata;
|
pub mod metadata;
|
||||||
|
pub mod tx_client;
|
||||||
|
|
||||||
error_chain! {
|
error_chain! {
|
||||||
types {
|
types {
|
||||||
|
|
120
tolstoy/src/tx_client.rs
Normal file
120
tolstoy/src/tx_client.rs
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
// Copyright 2016 Mozilla
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||||
|
// this file except in compliance with the License. You may obtain a copy of the
|
||||||
|
// License at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
// read all txs from the database
|
||||||
|
// return a list of structures that represent all we need to know about transactions
|
||||||
|
|
||||||
|
// so, what do we need here then?
|
||||||
|
// we need a "way in"!
|
||||||
|
|
||||||
|
// could just query the transactions database directly, read stuff in, and represent
|
||||||
|
// it as some data structure on the way out
|
||||||
|
|
||||||
|
// will need to weed out transactions as we work through the records
|
||||||
|
// -> and then associate with it the "chunks"
|
||||||
|
|
||||||
|
// "transaction" then is a meta-concept, it's a label for a collection of concrete changes
|
||||||
|
|
||||||
|
// perhaps mentat has useful primitives, but let's begin by just "doing the work"
|
||||||
|
|
||||||
|
use rusqlite;
|
||||||
|
|
||||||
|
use Result;
|
||||||
|
|
||||||
|
use mentat_db::types::{
|
||||||
|
Entid
|
||||||
|
};
|
||||||
|
|
||||||
|
use mentat_core::{
|
||||||
|
DateTime,
|
||||||
|
Utc,
|
||||||
|
ValueType
|
||||||
|
};
|
||||||
|
|
||||||
|
use mentat_core::SQLValueType;
|
||||||
|
use edn::FromMicros;
|
||||||
|
|
||||||
|
struct TxPart {
|
||||||
|
e: Entid,
|
||||||
|
a: i32,
|
||||||
|
v: Vec<u8>,
|
||||||
|
added: i32,
|
||||||
|
value_type_tag: i32
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Tx {
|
||||||
|
tx: Entid,
|
||||||
|
tx_instant: DateTime<Utc>,
|
||||||
|
parts: Vec<TxPart>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tx {
|
||||||
|
fn new(conn: &rusqlite::Connection, tx: i64, tx_instant: i64) -> Result<Tx> {
|
||||||
|
let mut stmt = conn.prepare("SELECT e,a,v,added,value_type_tag FROM transactions WHERE tx = :tx")?;
|
||||||
|
let mapped_rows = stmt.query_map_named(&[(":tx", &tx)], |row| TxPart {
|
||||||
|
e: row.get(0),
|
||||||
|
a: row.get(1),
|
||||||
|
v: row.get(2),
|
||||||
|
added: row.get(3),
|
||||||
|
value_type_tag: row.get(4)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let mut parts = Vec::new();
|
||||||
|
for part in mapped_rows {
|
||||||
|
parts.push(part?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Tx {
|
||||||
|
tx: tx,
|
||||||
|
tx_instant: DateTime::<Utc>::from_micros(tx_instant),
|
||||||
|
parts: parts
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait TxReader {
|
||||||
|
fn txs(&self) -> Result<Vec<Tx>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TxClient {
|
||||||
|
conn: rusqlite::Connection
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO This needs to take a mentat connection, as we're making assumptions about
|
||||||
|
// what that connection will provide (a transactions table).
|
||||||
|
impl TxClient {
|
||||||
|
fn new(conn: rusqlite::Connection) -> Self {
|
||||||
|
TxClient {
|
||||||
|
conn: conn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TxReader for TxClient {
|
||||||
|
fn txs(&self) -> Result<Vec<Tx>> {
|
||||||
|
let mut stmt = self.conn.prepare("SELECT tx, v FROM transactions GROUP BY tx")?;
|
||||||
|
let mapped_rows = stmt.query_map(&[], |row| Tx::new(&self.conn, row.get(0), row.get(1)))?;
|
||||||
|
|
||||||
|
let mut txes = Vec::new();
|
||||||
|
for tx in mapped_rows {
|
||||||
|
txes.push(match tx? {
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
Ok(v) => v
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(txes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
}
|
Loading…
Reference in a new issue