main
Ziyang Hu 2 years ago
parent f22346862b
commit fd117c8244

@ -5,6 +5,10 @@ edition = "2021"
description = "A general-purpose, transactional, relational database that uses Datalog and focuses on graph data" description = "A general-purpose, transactional, relational database that uses Datalog and focuses on graph data"
authors = ["Ziyang Hu"] authors = ["Ziyang Hu"]
license = "AGPL-3.0-or-later" license = "AGPL-3.0-or-later"
exclude = [
"docs/*",
"tests/*",
]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

@ -2,8 +2,6 @@
* Copyright 2022, The Cozo Project Authors. Licensed under MIT/Apache-2.0/BSD-3-Clause. * Copyright 2022, The Cozo Project Authors. Licensed under MIT/Apache-2.0/BSD-3-Clause.
*/ */
use std::borrow::Cow;
use cxx::*; use cxx::*;
use crate::bridge::ffi::*; use crate::bridge::ffi::*;
@ -11,7 +9,6 @@ use crate::bridge::tx::TxBuilder;
#[derive(Default, Clone)] #[derive(Default, Clone)]
pub struct DbBuilder<'a> { pub struct DbBuilder<'a> {
pub cmp_fn: Option<fn(&[u8], &[u8]) -> i8>,
pub opts: DbOpts<'a>, pub opts: DbOpts<'a>,
} }
@ -120,8 +117,8 @@ pub struct RocksDb {
} }
impl RocksDb { impl RocksDb {
pub fn db_path(&self) -> Cow<str> { pub fn db_path(&self) -> std::string::String {
self.inner.get_db_path().to_string_lossy() self.inner.get_db_path().to_string_lossy().to_string()
} }
pub fn transact(&self) -> TxBuilder { pub fn transact(&self) -> TxBuilder {
TxBuilder { TxBuilder {

@ -116,8 +116,8 @@ pub(crate) mod ffi {
type RocksDbBridge; type RocksDbBridge;
fn get_db_path(self: &RocksDbBridge) -> &CxxString; fn get_db_path(self: &RocksDbBridge) -> &CxxString;
fn open_db( fn open_db<'a>(
builder: &DbOpts, builder: &'a DbOpts<'a>,
status: &mut RocksDbStatus, status: &mut RocksDbStatus,
) -> SharedPtr<RocksDbBridge>; ) -> SharedPtr<RocksDbBridge>;
fn transact(self: &RocksDbBridge) -> UniquePtr<TxBridge>; fn transact(self: &RocksDbBridge) -> UniquePtr<TxBridge>;

@ -2,6 +2,9 @@
* Copyright 2022, The Cozo Project Authors. Licensed under MIT/Apache-2.0/BSD-3-Clause. * Copyright 2022, The Cozo Project Authors. Licensed under MIT/Apache-2.0/BSD-3-Clause.
*/ */
#![warn(rust_2018_idioms, future_incompatible)]
#![allow(clippy::type_complexity)]
pub use bridge::db::DbBuilder; pub use bridge::db::DbBuilder;
pub use bridge::db::RocksDb; pub use bridge::db::RocksDb;
pub use bridge::ffi::RocksDbStatus; pub use bridge::ffi::RocksDbStatus;

@ -309,5 +309,5 @@ The rest of the query options are explained in the following.
The query returns nothing if the output relation contains at least one row, The query returns nothing if the output relation contains at least one row,
otherwise, execution aborts with an error. otherwise, execution aborts with an error.
Execution of the query stops as soon as the first row is produced if possible. Implies ``:limit 1`` to ensure early termination if possible.
Useful for transactions and triggers. Useful for transactions and triggers.

@ -224,5 +224,4 @@ you can use the library directly.
For languages other than Rust, you will need to provide custom bindings, For languages other than Rust, you will need to provide custom bindings,
but again for `Python <https://pyo3.rs/>`_ and `NodeJS <https://neon-bindings.com/>`_ this is trivial. but again for `Python <https://pyo3.rs/>`_ and `NodeJS <https://neon-bindings.com/>`_ this is trivial.
Cozo will always use multiple threads, embedded or not.
Note that Cozo, with its underlying RocksDB storage, will always use multiple threads, embedded or not.

@ -172,7 +172,7 @@ impl AlgoImpl for JsonReader {
} }
pub(crate) fn get_file_content_from_url(url: &str) -> Result<Response> { pub(crate) fn get_file_content_from_url(url: &str) -> Result<Response> {
minreq::get(&url as &str) minreq::get(url as &str)
.send() .send()
.map_err(|e| { .map_err(|e| {
error!("{:?}", e); error!("{:?}", e);

@ -3,6 +3,9 @@
*/ */
#![warn(rust_2018_idioms, future_incompatible)] #![warn(rust_2018_idioms, future_incompatible)]
#![warn(missing_docs)]
#![allow(clippy::type_complexity)]
#![allow(clippy::too_many_arguments)]
pub use miette::Error; pub use miette::Error;
@ -16,9 +19,9 @@ pub use runtime::db::Db;
// #[global_allocator] // #[global_allocator]
// static GLOBAL: Jemalloc = Jemalloc; // static GLOBAL: Jemalloc = Jemalloc;
pub(crate) mod algo;
pub(crate) mod data; pub(crate) mod data;
pub(crate) mod parse; pub(crate) mod parse;
pub(crate) mod query; pub(crate) mod query;
pub(crate) mod runtime; pub(crate) mod runtime;
pub(crate) mod utils; pub(crate) mod utils;
pub(crate) mod algo;

@ -5,7 +5,7 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering}; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::time::{Duration, SystemTime, UNIX_EPOCH}; use std::time::{Duration, SystemTime, UNIX_EPOCH};
use std::{fs, thread}; use std::{fs, thread};
@ -62,19 +62,13 @@ const CURRENT_STORAGE_VERSION: u64 = 1;
pub struct Db { pub struct Db {
db: RocksDb, db: RocksDb,
relation_store_id: Arc<AtomicU64>, relation_store_id: Arc<AtomicU64>,
n_sessions: Arc<AtomicUsize>,
queries_count: Arc<AtomicU64>, queries_count: Arc<AtomicU64>,
running_queries: Arc<Mutex<BTreeMap<u64, RunningQueryHandle>>>, running_queries: Arc<Mutex<BTreeMap<u64, RunningQueryHandle>>>,
session_id: usize,
} }
impl Debug for Db { impl Debug for Db {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!( write!(f, "Db")
f,
"Db<session {}, sessions: {:?}>",
self.session_id, self.n_sessions
)
} }
} }
@ -131,46 +125,27 @@ impl Db {
let ret = Self { let ret = Self {
db, db,
relation_store_id: Arc::new(Default::default()), relation_store_id: Arc::new(Default::default()),
n_sessions: Arc::new(Default::default()),
queries_count: Arc::new(Default::default()), queries_count: Arc::new(Default::default()),
running_queries: Arc::new(Mutex::new(Default::default())), running_queries: Arc::new(Mutex::new(Default::default())),
session_id: Default::default(),
}; };
ret.load_last_ids()?; ret.load_last_ids()?;
Ok(ret) Ok(ret)
} }
pub fn get_session_id(&self) -> usize { fn compact_relation(&self) -> Result<()> {
self.session_id
}
pub fn compact_relation(&self) -> Result<()> {
let l = Tuple::default().encode_as_key(RelationId(0)); let l = Tuple::default().encode_as_key(RelationId(0));
let u = Tuple(vec![DataValue::Bot]).encode_as_key(RelationId(u64::MAX)); let u = Tuple(vec![DataValue::Bot]).encode_as_key(RelationId(u64::MAX));
self.db.range_compact(&l, &u)?; self.db.range_compact(&l, &u)?;
Ok(()) Ok(())
} }
pub fn new_session(&self) -> Result<Self> {
let old_count = self.n_sessions.fetch_add(1, Ordering::AcqRel);
Ok(Self {
db: self.db.clone(),
relation_store_id: self.relation_store_id.clone(),
n_sessions: self.n_sessions.clone(),
queries_count: self.queries_count.clone(),
running_queries: self.running_queries.clone(),
session_id: old_count + 1,
})
}
fn load_last_ids(&self) -> Result<()> { fn load_last_ids(&self) -> Result<()> {
let tx = self.transact()?; let tx = self.transact()?;
self.relation_store_id self.relation_store_id
.store(tx.load_last_relation_store_id()?.0, Ordering::Release); .store(tx.load_last_relation_store_id()?.0, Ordering::Release);
Ok(()) Ok(())
} }
pub fn transact(&self) -> Result<SessionTx> { fn transact(&self) -> Result<SessionTx> {
let ret = SessionTx { let ret = SessionTx {
tx: self.db.transact().set_snapshot(true).start(), tx: self.db.transact().set_snapshot(true).start(),
mem_store_id: Default::default(), mem_store_id: Default::default(),
@ -178,7 +153,7 @@ impl Db {
}; };
Ok(ret) Ok(ret)
} }
pub fn transact_write(&self) -> Result<SessionTx> { fn transact_write(&self) -> Result<SessionTx> {
let ret = SessionTx { let ret = SessionTx {
tx: self.db.transact().set_snapshot(true).start(), tx: self.db.transact().set_snapshot(true).start(),
mem_store_id: Default::default(), mem_store_id: Default::default(),
@ -611,7 +586,7 @@ impl Db {
} else { } else {
Right(sorted_iter) Right(sorted_iter)
}; };
let sorted_iter = sorted_iter.map(|t| Ok(t)); let sorted_iter = sorted_iter.map(Ok);
if let Some((meta, relation_op)) = &input_program.out_opts.store_relation { if let Some((meta, relation_op)) = &input_program.out_opts.store_relation {
let to_clear = tx let to_clear = tx
.execute_relation( .execute_relation(
@ -682,7 +657,7 @@ impl Db {
.collect_vec(); .collect_vec();
Ok(json!({"rows": res, "headers": ["id", "started_at"]})) Ok(json!({"rows": res, "headers": ["id", "started_at"]}))
} }
pub fn list_relation(&self, name: &str) -> Result<JsonValue> { fn list_relation(&self, name: &str) -> Result<JsonValue> {
let tx = self.transact()?; let tx = self.transact()?;
let handle = tx.get_relation(name, false)?; let handle = tx.get_relation(name, false)?;
let mut ret = vec![]; let mut ret = vec![];
@ -709,7 +684,7 @@ impl Db {
} }
Ok(json!({"rows": ret, "headers": ["column", "is_key", "index", "type", "has_default"]})) Ok(json!({"rows": ret, "headers": ["column", "is_key", "index", "type", "has_default"]}))
} }
pub fn list_relations(&self) -> Result<JsonValue> { fn list_relations(&self) -> Result<JsonValue> {
let lower = let lower =
Tuple(vec![DataValue::Str(SmartString::from(""))]).encode_as_key(RelationId::SYSTEM); Tuple(vec![DataValue::Str(SmartString::from(""))]).encode_as_key(RelationId::SYSTEM);
let upper = Tuple(vec![DataValue::Str(SmartString::from(String::from( let upper = Tuple(vec![DataValue::Str(SmartString::from(String::from(

Loading…
Cancel
Save