Repository navigation
Expand file tree
/
Copy pathlib.rs
More file actions
203 lines (184 loc) · 7.31 KB
/
Copy pathlib.rs
File metadata and controls
203 lines (184 loc) · 7.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
#![forbid(unsafe_code)]
#![warn(missing_docs)]
#![cfg_attr(
test,
allow(
clippy::unwrap_used,
clippy::expect_used,
clippy::panic,
clippy::indexing_slicing,
clippy::cast_possible_truncation,
clippy::cast_possible_wrap,
clippy::cast_sign_loss,
)
)]
#![cfg_attr(docsrs, feature(doc_cfg))]
//! Zero-config, single-file, embedded graph database with bi-temporal Datalog queries.
//!
//! Minigraf is the SQLite of graph databases: embedded, no server, no configuration,
//! a single portable `.graph` file. It stores data as Entity-Attribute-Value facts,
//! queries them with [Datalog](https://en.wikipedia.org/wiki/Datalog), and tracks every
//! change with full bi-temporal history (transaction time + valid time).
//!
//! # Installation
//!
//! ```toml
//! [dependencies]
//! minigraf = "0.21"
//! ```
//!
//! # Quick Start
//!
//! ```
//! use minigraf::{Minigraf, BindValue};
//!
//! // Open (or create) a database
//! let db = Minigraf::in_memory().unwrap();
//!
//! // Assert facts
//! db.execute(r#"(transact [[:alice :person/name "Alice"]
//! [:alice :person/age 30]
//! [:alice :friend :bob]
//! [:bob :person/name "Bob"]])"#).unwrap();
//!
//! // Query with Datalog
//! let results = db.execute(r#"
//! (query [:find ?friend-name
//! :where [:alice :friend ?friend]
//! [?friend :person/name ?friend-name]])
//! "#).unwrap();
//!
//! // Explicit transaction — all-or-nothing
//! let mut tx = db.begin_write().unwrap();
//! tx.execute(r#"(transact [[:alice :person/age 31]])"#).unwrap();
//! tx.commit().unwrap();
//!
//! // Time travel — query the state as of transaction 1
//! db.execute("(query [:find ?age :as-of 1 :where [:alice :person/age ?age]])").unwrap();
//! ```
//!
//! # Feature Flags
//!
//! | Feature | Target | Description |
//! |---------|--------|-------------|
//! | *(default)* | native / WASI | File-backed and in-memory databases; full Datalog engine |
//! | `browser` | `wasm32-unknown-unknown` | Enables the `browser` module (`BrowserDb`), backed by IndexedDB for use inside a web browser via `wasm-pack` |
//!
//! The `browser` feature is only meaningful on the `wasm32-unknown-unknown` target.
//! When browsing docs on [docs.rs](https://docs.rs/minigraf), switch the target to
//! `wasm32-unknown-unknown` (top-right target selector) to see the full browser API.
//!
//! ## WebAssembly targets
//!
//! - **Browser** (`wasm32-unknown-unknown` + `browser` feature) — `wasm-pack build --target web --features browser`
//! - **WASI / server-side** (`wasm32-wasip1`) — `cargo build --target wasm32-wasip1 --release --bin minigraf`
// The engine's unit tests share `tests/answers/`, which names the crate.
#[cfg(all(test, not(target_arch = "wasm32")))]
extern crate self as minigraf;
/// Incremental delivery of query results: [`Cursor`] and [`Batch`].
pub mod cursor;
pub mod db;
pub mod error;
/// Every fact version, streamed: [`FactLog`], [`FactFilter`], [`FactRecord`].
pub mod fact_log;
#[cfg(all(test, not(target_arch = "wasm32")))]
mod fault_matrix;
pub(crate) mod graph;
/// Build a new database from explicit fact records: [`LogWriter`].
#[cfg(not(target_arch = "wasm32"))]
pub mod log_writer;
mod overrides;
pub(crate) mod query;
/// Interactive REPL for exploring a [`Minigraf`] database from the command line.
pub mod repl;
pub(crate) mod storage;
pub(crate) mod temporal;
/// The sidecar WAL of file-backed databases; wasm32 targets have no file backend.
#[cfg(not(target_arch = "wasm32"))]
pub(crate) mod wal;
#[cfg(all(target_arch = "wasm32", feature = "browser"))]
#[cfg_attr(docsrs, doc(cfg(all(target_arch = "wasm32", feature = "browser"))))]
pub mod browser;
#[cfg(not(target_arch = "wasm32"))]
pub use db::OpenOptionsWithPath;
pub use db::{IntegrityReport, Minigraf, OpenOptions, SyncMode, WriteTransaction};
pub use error::{ErrorCategory, MinigrafError};
pub use overrides::Overridable;
pub use query::datalog::functions::UdfError;
pub use repl::Repl;
// EAV value types — users construct and match on these
pub use graph::types::{EntityId, Value, ValueSet};
// Query result types
pub use cursor::{Batch, Cursor};
pub use fact_log::{FactFilter, FactLog, FactOrder, FactRecord};
#[cfg(not(target_arch = "wasm32"))]
pub use log_writer::LogWriter;
pub use query::datalog::executor::QueryResult;
// Bi-temporal query types
pub use query::datalog::types::{AsOf, ValidAt};
// Prepared statements
pub use query::datalog::prepared::{BindValue, PreparedQuery};
// Plan-independence tests (#596): run queries without reordering.
#[cfg(feature = "test-hooks")]
#[doc(hidden)]
pub use query::datalog::optimizer::ReorderGuard;
/// Turns clause reordering on or off for queries on this thread until the
/// returned guard drops. Only for tests that check no answer depends on the
/// plan (#596); built with the `test-hooks` feature only.
#[cfg(feature = "test-hooks")]
#[doc(hidden)]
pub fn __reorder(on: bool) -> ReorderGuard {
query::datalog::optimizer::set_reorder(on)
}
#[cfg(feature = "test-hooks")]
#[doc(hidden)]
pub use query::engine::InputOrderGuard;
/// Enables input-order optimizations on this thread for differential tests.
/// The previous setting is restored on drop; test-hooks builds only.
#[cfg(feature = "test-hooks")]
#[doc(hidden)]
pub fn __input_order(on: bool) -> InputOrderGuard {
query::engine::set_input_order(on)
}
/// This thread's path events since the last call, which clears them: how
/// often queries took the paths the nightly acceptance tests guard (#863),
/// such as `ancestor_alternative_selected` and `bound_value_avet_range`.
/// Only for tests; built with the `test-hooks` feature only.
#[cfg(feature = "test-hooks")]
#[doc(hidden)]
pub fn __path_events() -> std::collections::BTreeMap<&'static str, u64> {
query::engine::take_path_events()
}
// Large-transaction tests (#550): statements read and written in small chunks.
#[cfg(feature = "test-hooks")]
#[doc(hidden)]
pub use query::datalog::parser::statement::TxChunkGuard;
/// Sets how many facts a `transact` or `retract` materialises at once on this
/// thread until the returned guard drops (`None`: the built-in size), so a
/// statement with more facts takes the large-transaction path (#550). Only
/// for tests; built with the `test-hooks` feature only.
#[cfg(feature = "test-hooks")]
#[doc(hidden)]
pub fn __tx_chunk_facts(n: Option<usize>) -> TxChunkGuard {
query::datalog::parser::statement::set_tx_chunk_facts(n)
}
/// The most materialised statement facts this thread held at once since the
/// last call (#550 acceptance). Built with the `test-hooks` feature only.
#[cfg(feature = "test-hooks")]
#[doc(hidden)]
pub fn __statement_facts_high_water() -> usize {
query::datalog::parser::statement::take_held_high_water()
}
// Plan-independence tests (#546): force how negation bodies and `or` branches run.
#[cfg(feature = "test-hooks")]
#[doc(hidden)]
pub use query::datalog::optimizer::{Subplans, SubplansGuard};
/// Forces how the streaming engine runs `not` / `not-join` bodies (hashed or
/// correlated) on this thread until the returned guard drops. Only for tests
/// that check both forms give the same rows (#546); built with the
/// `test-hooks` feature only.
#[cfg(feature = "test-hooks")]
#[doc(hidden)]
pub fn __subplans(mode: Subplans) -> SubplansGuard {
query::datalog::optimizer::set_subplans(mode)
}