64 lines
4.0 KiB
Markdown
64 lines
4.0 KiB
Markdown
## Query Ops
|
|
|
|
This crate provides a small set of query operators that can be used to implement a simple query-plan executor.
|
|
The operators are: atom scan, semijoin, and natural join.
|
|
|
|
### Public API
|
|
|
|
| Item | Type | Description |
|
|
|--------------------------------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
| `scan_atom(&Table, &AtomPattern) -> Relation` | function | Scans the table under the pattern and returns a binding relation with one column per distinct variable in first-occurrence order. Literal positions and repeated variables filter rows during the scan. |
|
|
| `semijoin(&Relation, &Relation) -> Relation` | function | Returns the rows of `left` whose values on the columns shared with `right` also appear in `right`. The output column list is the same as `left.columns`. |
|
|
| `natural_join(&Relation, &Relation) -> Relation` | function | Returns every pair of `left` and `right` rows that agree on shared columns. Each output row holds the columns of `left` followed by the non-shared columns of `right`. |
|
|
| `Table` | struct | Holds positional input rows of fixed arity and carries no column names. Construct it with `Table::new(arity)` or `Table::from_rows(arity, rows)`. |
|
|
| `AtomPattern` | struct | Specifies, for each table column, either a variable to bind or a literal value to match. The pattern is a `Vec<Term>` whose length must equal the table's arity. |
|
|
| `Term` | enum | Represents one position of an `AtomPattern`. A term is either `Var(String)` to bind the cell to a named variable, or `Lit(Value)` to require the cell to equal a given value. |
|
|
| `Relation` | struct | Holds rows over named columns and is the type produced by every operator. Construct it with `Relation::new(columns)` or `Relation::from_rows(columns, rows)`. Column names within a single relation must be unique. |
|
|
| `Value` | enum | Represents a single cell value stored in a `Table` or `Relation`. A value is either `Int(i64)` or `Str(String)`. |
|
|
|
|
### Example
|
|
|
|
`Q(X) :- edge(X, X), labeled(X).` (labeled self-loops):
|
|
|
|
```rust
|
|
use query_ops::atom::{AtomPattern, Term, scan_atom};
|
|
use query_ops::join::semijoin;
|
|
use query_ops::table::Table;
|
|
use query_ops::value::Value;
|
|
|
|
fn main() {
|
|
let edge = Table::from_rows(
|
|
2,
|
|
vec![
|
|
vec![Value::Int(1), Value::Int(2)],
|
|
vec![Value::Int(3), Value::Int(3)], // self-loop on 3
|
|
vec![Value::Int(2), Value::Int(2)], // self-loop on 2
|
|
],
|
|
);
|
|
let labeled = Table::from_rows(1, vec![vec![Value::Int(2)]]);
|
|
|
|
let self_loops = scan_atom(
|
|
&edge,
|
|
&AtomPattern {
|
|
columns: vec![Term::Var("X".to_string()), Term::Var("X".to_string())],
|
|
},
|
|
);
|
|
let labeled_x = scan_atom(
|
|
&labeled,
|
|
&AtomPattern {
|
|
columns: vec![Term::Var("X".to_string())],
|
|
},
|
|
);
|
|
let result = semijoin(&self_loops, &labeled_x);
|
|
|
|
assert_eq!(result.columns, vec!["X".to_string()]);
|
|
assert_eq!(result.rows, vec![vec![Value::Int(2)]]);
|
|
}
|
|
```
|
|
|
|
### Test
|
|
|
|
```sh
|
|
cargo test -p query-ops
|
|
```
|