expanded the public API

main
Ziyang Hu 2 years ago
parent b91e456237
commit bcf37ddc52

@ -153,33 +153,42 @@ pub fn eval_bytecode(
Ok(stack.pop().unwrap())
}
/// Expression can be evaluated to yield a DataValue
#[derive(Clone, PartialEq, Eq, serde_derive::Serialize, serde_derive::Deserialize)]
pub enum Expr {
/// Binding to variables
Binding {
/// The variable name to bind
var: Symbol,
/// When executing in the context of a tuple, the position of the binding within the tuple
tuple_pos: Option<usize>,
},
/// Constant expression containing a value
Const {
/// The value
val: DataValue,
/// Source span
#[serde(skip)]
span: SourceSpan,
},
/// Function application
Apply {
/// Op representing the function to apply
op: &'static Op,
/// Arguments to the application
args: Box<[Expr]>,
/// Source span
#[serde(skip)]
span: SourceSpan,
},
/// Conditional expressions
Cond {
/// Conditional clauses, the first expression in each tuple should evaluate to a boolean
clauses: Vec<(Expr, Expr)>,
/// Source span
#[serde(skip)]
span: SourceSpan,
},
// Try {
// clauses: Vec<Expr>,
// #[serde(skip)]
// span: SourceSpan,
// },
}
impl Debug for Expr {

@ -18,6 +18,7 @@ use thiserror::Error;
use crate::parse::SourceSpan;
/// Names with associated source span
#[derive(Clone, Deserialize, Serialize)]
pub struct Symbol {
pub(crate) name: SmartString<LazyCompact>,

@ -39,12 +39,14 @@ use crate::runtime::transact::SessionTx;
pub(crate) mod algos;
pub(crate) mod utilities;
/// Passed into implementation of fixed rule, can be used to obtain relation inputs and options
pub struct FixedRulePayload<'a, 'b> {
pub(crate) manifest: &'a MagicFixedRuleApply,
pub(crate) stores: &'a BTreeMap<MagicSymbol, EpochStore>,
pub(crate) tx: &'a SessionTx<'b>,
}
/// Represents an input relation during the execution of a fixed rule
#[derive(Copy, Clone)]
pub struct FixedRuleInputRelation<'a, 'b> {
arg_manifest: &'a MagicFixedRuleRuleArg,
@ -53,9 +55,11 @@ pub struct FixedRuleInputRelation<'a, 'b> {
}
impl<'a, 'b> FixedRuleInputRelation<'a, 'b> {
/// The arity of the input relation
pub fn arity(&self) -> Result<usize> {
self.arg_manifest.arity(self.tx, self.stores)
}
/// Ensure the input relation contains tuples of the given minimal length.
pub fn ensure_min_len(self, len: usize) -> Result<Self> {
#[derive(Error, Diagnostic, Debug)]
#[error("Input relation to algorithm has insufficient arity")]
@ -70,9 +74,11 @@ impl<'a, 'b> FixedRuleInputRelation<'a, 'b> {
);
Ok(self)
}
/// Get the binding map of the input relation
pub fn get_binding_map(&self, offset: usize) -> BTreeMap<Symbol, usize> {
self.arg_manifest.get_binding_map(offset)
}
/// Iterate the input relation
pub fn iter(&self) -> Result<TupleIter<'a>> {
Ok(match &self.arg_manifest {
MagicFixedRuleRuleArg::InMem { name, .. } => {
@ -91,6 +97,7 @@ impl<'a, 'b> FixedRuleInputRelation<'a, 'b> {
}
})
}
/// Iterate the relation with the given single-value prefix
pub fn prefix_iter(&self, prefix: &DataValue) -> Result<TupleIter<'_>> {
Ok(match self.arg_manifest {
MagicFixedRuleRuleArg::InMem { name, .. } => {
@ -111,9 +118,16 @@ impl<'a, 'b> FixedRuleInputRelation<'a, 'b> {
}
})
}
/// Get the source span of the input relation. Useful for generating informative error messages.
pub fn span(&self) -> SourceSpan {
self.arg_manifest.span()
}
/// Convert the input relation into a directed graph.
/// If `undirected` is true, then each edge in the input relation is treated as a pair
/// of edges, one for each direction.
///
/// Returns the graph, the vertices in a vector with the index the same as used in the graph,
/// and the inverse vertex mapping.
#[cfg(feature = "graph-algo")]
pub fn as_directed_graph(
&self,
@ -180,6 +194,12 @@ impl<'a, 'b> FixedRuleInputRelation<'a, 'b> {
}
Ok((graph, indices, inv_indices))
}
/// Convert the input relation into a directed weighted graph.
/// If `undirected` is true, then each edge in the input relation is treated as a pair
/// of edges, one for each direction.
///
/// Returns the graph, the vertices in a vector with the index the same as used in the graph,
/// and the inverse vertex mapping.
#[cfg(feature = "graph-algo")]
pub fn as_directed_weighted_graph(
&self,
@ -305,6 +325,7 @@ impl<'a, 'b> FixedRuleInputRelation<'a, 'b> {
}
impl<'a, 'b> FixedRulePayload<'a, 'b> {
/// Get the input relation at `idx`.
pub fn get_input(&self, idx: usize) -> Result<FixedRuleInputRelation<'a, 'b>> {
let arg_manifest = self.manifest.relation(idx)?;
Ok(FixedRuleInputRelation {
@ -313,12 +334,15 @@ impl<'a, 'b> FixedRulePayload<'a, 'b> {
tx: self.tx,
})
}
/// Get the name of the current fixed rule
pub fn name(&self) -> &str {
&self.manifest.fixed_handle.name
}
/// Get the source span of the payloads. Useful for generating informative errors.
pub fn span(&self) -> SourceSpan {
self.manifest.span
}
/// Extract an expression option
pub fn expr_option(&self, name: &str, default: Option<Expr>) -> Result<Expr> {
match self.manifest.options.get(name) {
Some(ex) => Ok(ex.clone()),
@ -334,6 +358,7 @@ impl<'a, 'b> FixedRulePayload<'a, 'b> {
}
}
/// Extract a string option
pub fn string_option(
&self,
name: &str,
@ -362,6 +387,7 @@ impl<'a, 'b> FixedRulePayload<'a, 'b> {
}
}
/// Get the source span of the named option. Useful for generating informative error messages.
pub fn option_span(&self, name: &str) -> Result<SourceSpan> {
match self.manifest.options.get(name) {
None => Err(FixedRuleOptionNotFoundError {
@ -373,7 +399,7 @@ impl<'a, 'b> FixedRulePayload<'a, 'b> {
Some(v) => Ok(v.span()),
}
}
/// Extract an integer option
pub fn integer_option(&self, name: &str, default: Option<i64>) -> Result<i64> {
match self.manifest.options.get(name) {
Some(v) => match v.clone().eval_to_const() {
@ -405,7 +431,7 @@ impl<'a, 'b> FixedRulePayload<'a, 'b> {
},
}
}
/// Extract a positive integer option
pub fn pos_integer_option(&self, name: &str, default: Option<usize>) -> Result<usize> {
let i = self.integer_option(name, default.map(|i| i as i64))?;
ensure!(
@ -419,6 +445,7 @@ impl<'a, 'b> FixedRulePayload<'a, 'b> {
);
Ok(i as usize)
}
/// Extract a non-negative integer option
pub fn non_neg_integer_option(&self, name: &str, default: Option<usize>) -> Result<usize> {
let i = self.integer_option(name, default.map(|i| i as i64))?;
ensure!(
@ -432,6 +459,7 @@ impl<'a, 'b> FixedRulePayload<'a, 'b> {
);
Ok(i as usize)
}
/// Extract a floating point option
pub fn float_option(&self, name: &str, default: Option<f64>) -> Result<f64> {
match self.manifest.options.get(name) {
Some(v) => match v.clone().eval_to_const() {
@ -458,6 +486,7 @@ impl<'a, 'b> FixedRulePayload<'a, 'b> {
},
}
}
/// Extract a floating point option between 0. and 1.
pub fn unit_interval_option(&self, name: &str, default: Option<f64>) -> Result<f64> {
let f = self.float_option(name, default)?;
ensure!(
@ -471,6 +500,7 @@ impl<'a, 'b> FixedRulePayload<'a, 'b> {
);
Ok(f)
}
/// Extract a boolean option
pub fn bool_option(&self, name: &str, default: Option<bool>) -> Result<bool> {
match self.manifest.options.get(name) {
Some(v) => match v.clone().eval_to_const() {

@ -47,7 +47,7 @@ use miette::{
use serde_json::json;
pub use data::value::{DataValue, Num, RegexWrapper, UuidWrapper, Validity, ValidityTs};
pub use fixed_rule::FixedRule;
pub use fixed_rule::{FixedRule, FixedRuleInputRelation, FixedRulePayload};
pub use runtime::db::Db;
pub use runtime::db::NamedRows;
pub use runtime::relation::decode_tuple_from_kv;
@ -63,11 +63,12 @@ pub use storage::sqlite::{new_cozo_sqlite, SqliteStorage};
pub use storage::tikv::{new_cozo_tikv, TiKvStorage};
pub use storage::{Storage, StoreTx};
pub use crate::data::expr::Expr;
use crate::data::json::JsonValue;
use crate::runtime::callback::CallbackOp;
pub use crate::data::symb::Symbol;
pub use crate::runtime::callback::CallbackOp;
#[cfg(not(target_arch = "wasm32"))]
pub(crate) mod data;
pub(crate) mod fixed_rule;
pub(crate) mod parse;
@ -336,7 +337,11 @@ impl DbInstance {
}
}
/// Dispatcher method. See [crate::Db::import_from_backup].
pub fn import_from_backup(&self, in_file: impl AsRef<Path>, relations: &[String]) -> Result<()> {
pub fn import_from_backup(
&self,
in_file: impl AsRef<Path>,
relations: &[String],
) -> Result<()> {
match self {
DbInstance::Mem(db) => db.import_from_backup(in_file, relations),
#[cfg(feature = "storage-sqlite")]
@ -373,8 +378,9 @@ impl DbInstance {
/// The returned ID can be used to unregister the callbacks.
#[cfg(not(target_arch = "wasm32"))]
pub fn register_callback<CB>(&self, callback: CB, dependent: &str) -> Result<u32>
where
CB: Fn(CallbackOp, NamedRows, NamedRows) + Send + Sync + 'static {
where
CB: Fn(CallbackOp, NamedRows, NamedRows) + Send + Sync + 'static,
{
match self {
DbInstance::Mem(db) => db.register_callback(callback, dependent),
#[cfg(feature = "storage-sqlite")]
@ -387,6 +393,43 @@ impl DbInstance {
DbInstance::TiKv(db) => db.register_callback(callback, dependent),
}
}
/// Unregister callbacks to run when changes to relations are committed.
#[cfg(not(target_arch = "wasm32"))]
pub fn unregister_callback(&self, id: u32) -> bool {
match self {
DbInstance::Mem(db) => db.unregister_callback(id),
#[cfg(feature = "storage-sqlite")]
DbInstance::Sqlite(db) => db.unregister_callback(id),
#[cfg(feature = "storage-rocksdb")]
DbInstance::RocksDb(db) => db.unregister_callback(id),
#[cfg(feature = "storage-sled")]
DbInstance::Sled(db) => db.unregister_callback(id),
#[cfg(feature = "storage-tikv")]
DbInstance::TiKv(db) => db.unregister_callback(id),
}
}
/// Register a custom fixed rule implementation.
///
/// You must register fixed rules BEFORE you clone the database,
/// otherwise already cloned instances will not get the new fixed rule.
pub fn register_fixed_rule(
&mut self,
name: String,
rule_impl: Box<dyn FixedRule>,
) -> Result<()> {
match self {
DbInstance::Mem(db) => db.register_fixed_rule(name, rule_impl),
#[cfg(feature = "storage-sqlite")]
DbInstance::Sqlite(db) => db.register_fixed_rule(name, rule_impl),
#[cfg(feature = "storage-rocksdb")]
DbInstance::RocksDb(db) => db.register_fixed_rule(name, rule_impl),
#[cfg(feature = "storage-sled")]
DbInstance::Sled(db) => db.register_fixed_rule(name, rule_impl),
#[cfg(feature = "storage-tikv")]
DbInstance::TiKv(db) => db.register_fixed_rule(name, rule_impl),
}
}
}
/// Convert error raised by the database into friendly JSON format

@ -12,9 +12,12 @@ use smartstring::{LazyCompact, SmartString};
use crate::{Db, NamedRows, Storage};
/// Represents the kind of operation that triggered the callback
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum CallbackOp {
/// Triggered by Put operations
Put,
/// Triggered by Rm operations
Rm,
}

Loading…
Cancel
Save