Skip to main content

Relation

Struct Relation 

Source
pub struct Relation { /* private fields */ }
Expand description

Represents a relation with a heading and a set of tuples.

§Example

use darwen::prelude::{AttributeName, HeadingBuilder, Relation, ScalarType};

let relation = Relation::new(
    HeadingBuilder::new()
        .with_attribute(AttributeName::from("id"), ScalarType::Integer)
        .build()?,
);

assert_eq!(
    relation,
    Relation::new_from_iter(
        HeadingBuilder::new()
            .with_attribute(AttributeName::from("id"), ScalarType::Integer)
            .build()?,
        Vec::new(),
    )?,
);

Implementations§

Source§

impl Relation

Source

pub fn difference(&self, other: &Relation) -> Result<Relation, Error>

Returns tuples that exist in self but not in other ().

a

value
1
2
3

b

value
2

Output

value
1
3
§Errors

Returns Error::HeadingMismatch if the relations do not have the same heading.

§Example
use darwen::prelude::{AttributeName, Heading, Relation, Scalar, ScalarType, Tuple};

let a = Relation::new_from_iter(
    Heading::try_from(vec![(AttributeName::from("value"), ScalarType::Integer)])?,
    vec![
        Tuple::try_from(vec![(AttributeName::from("value"), Scalar::Integer(1))])?,
        Tuple::try_from(vec![(AttributeName::from("value"), Scalar::Integer(2))])?,
        Tuple::try_from(vec![(AttributeName::from("value"), Scalar::Integer(3))])?,
    ],
)?;
let b = Relation::new_from_iter(
    Heading::try_from(vec![(AttributeName::from("value"), ScalarType::Integer)])?,
    vec![Tuple::try_from(vec![(AttributeName::from("value"), Scalar::Integer(2))])?],
)?;

let difference = a.difference(&b)?;

assert_eq!(
    difference,
    Relation::new_from_iter(
        Heading::try_from(vec![(AttributeName::from("value"), ScalarType::Integer)])?,
        vec![
            Tuple::try_from(vec![(AttributeName::from("value"), Scalar::Integer(1))])?,
            Tuple::try_from(vec![(AttributeName::from("value"), Scalar::Integer(3))])?,
        ],
    )?
);
Examples found in repository?
examples/difference.rs (line 37)
33fn main() {
34    let all_numbers = all_numbers();
35    let already_typed = already_typed();
36
37    println!("{}", all_numbers.difference(&already_typed).unwrap());
38}
Source§

impl Relation

Source

pub fn divide(&self, other: &Relation) -> Result<Relation, Error>

Divides one relation by another (÷).

students

namecourse
AliceRust
AliceMath
BobRust
BobMath
AnnMath

courses

course
Rust
Math

Output

name
Alice
Bob
§Errors

Returns Error::HeadingMismatch if the divisor heading is not a subset of the dividend heading.

§Example
use darwen::{
    heading,
    tuple,
    prelude::{RelationBuilder, ScalarType},
};

let students = RelationBuilder::new()
    .with_heading(heading!(name = ScalarType::String, course = ScalarType::String)?)
    .with_body(vec![
        tuple!(name = "Alice", course = "Rust")?,
        tuple!(name = "Alice", course = "Math")?,
        tuple!(name = "Bob", course = "Rust")?,
        tuple!(name = "Bob", course = "Math")?,
        tuple!(name = "Ann", course = "Math")?,
    ])
    .build()?;

let courses = RelationBuilder::new()
    .with_heading(heading!(course = ScalarType::String)?)
    .with_body(vec![
        tuple!(course = "Rust")?,
        tuple!(course = "Math")?,
    ])
    .build()?;

let result = students.divide(&courses)?;

let expected = RelationBuilder::new()
    .with_heading(heading!(name = ScalarType::String)?)
    .with_body(vec![
        tuple!(name = "Alice")?,
        tuple!(name = "Bob")?,
    ])
    .build()?;

assert_eq!(result, expected);
Examples found in repository?
examples/divide.rs (line 39)
35fn main() {
36    let enrollments = enrollments();
37    let required_courses = required_courses();
38
39    println!("{}", enrollments.divide(&required_courses).unwrap());
40}
Source§

impl Relation

Source

pub fn intersect(&self, other: &Relation) -> Result<Relation, Error>

Returns tuples common to both relations ().

a

value
1
2

b

value
2
3

Output

value
2
§Errors

Returns Error::HeadingMismatch if the relations do not have the same heading.

§Example
use darwen::prelude::{AttributeName, Heading, Relation, Scalar, ScalarType, Tuple};

let a = Relation::new_from_iter(
    Heading::try_from(vec![(AttributeName::from("value"), ScalarType::Integer)])?,
    vec![
        Tuple::try_from(vec![(AttributeName::from("value"), Scalar::Integer(1))])?,
        Tuple::try_from(vec![(AttributeName::from("value"), Scalar::Integer(2))])?,
    ],
)?;
let b = Relation::new_from_iter(
    Heading::try_from(vec![(AttributeName::from("value"), ScalarType::Integer)])?,
    vec![
        Tuple::try_from(vec![(AttributeName::from("value"), Scalar::Integer(2))])?,
        Tuple::try_from(vec![(AttributeName::from("value"), Scalar::Integer(3))])?,
    ],
)?;

let intersection = a.intersect(&b)?;

assert_eq!(
    intersection,
    Relation::new_from_iter(
        Heading::try_from(vec![(AttributeName::from("value"), ScalarType::Integer)])?,
        vec![Tuple::try_from(vec![(AttributeName::from("value"), Scalar::Integer(2))])?],
    )?
);
Examples found in repository?
examples/intersect.rs (line 36)
32fn main() {
33    let side_a = side_a();
34    let side_b = side_b();
35
36    println!("{}", side_a.intersect(&side_b).unwrap());
37}
Source§

impl Relation

Source

pub fn join(&self, other: &Relation) -> Result<Relation, Error>

Performs a natural join on attributes shared by both relations ().

users

idscore
110
220

cities

idlevel
1100
3300

Output

idscorelevel
110100
§Errors

Returns Error::ScalarTypeMismatch if shared attribute names exist in both relations with different scalar types.

§Example
use darwen::prelude::{AttributeName, Heading, Relation, Scalar, ScalarType, Tuple};

let users = Relation::new_from_iter(
    Heading::try_from(vec![
        (AttributeName::from("id"), ScalarType::Integer),
        (AttributeName::from("score"), ScalarType::Integer),
    ])?,
    vec![
        Tuple::try_from(vec![
            (AttributeName::from("id"), Scalar::Integer(1)),
            (AttributeName::from("score"), Scalar::Integer(10)),
        ])?,
        Tuple::try_from(vec![
            (AttributeName::from("id"), Scalar::Integer(2)),
            (AttributeName::from("score"), Scalar::Integer(20)),
        ])?,
    ],
)?;
let cities = Relation::new_from_iter(
    Heading::try_from(vec![
        (AttributeName::from("id"), ScalarType::Integer),
        (AttributeName::from("level"), ScalarType::Integer),
    ])?,
    vec![
        Tuple::try_from(vec![
            (AttributeName::from("id"), Scalar::Integer(1)),
            (AttributeName::from("level"), Scalar::Integer(100)),
        ])?,
        Tuple::try_from(vec![
            (AttributeName::from("id"), Scalar::Integer(3)),
            (AttributeName::from("level"), Scalar::Integer(300)),
        ])?,
    ],
)?;

let users_with_levels = users.join(&cities)?;

assert_eq!(
    users_with_levels,
    Relation::new_from_iter(
        Heading::try_from(vec![
            (AttributeName::from("id"), ScalarType::Integer),
            (AttributeName::from("score"), ScalarType::Integer),
            (AttributeName::from("level"), ScalarType::Integer),
        ])?,
        vec![Tuple::try_from(vec![
            (AttributeName::from("id"), Scalar::Integer(1)),
            (AttributeName::from("score"), Scalar::Integer(10)),
            (AttributeName::from("level"), Scalar::Integer(100)),
        ])?],
    )?
);
Examples found in repository?
examples/join.rs (line 38)
34fn main() {
35    let castaways = castaways();
36    let hatch = hatch();
37
38    println!("{}", castaways.join(&hatch).unwrap());
39}
Source§

impl Relation

Source

pub fn product(&self, other: &Relation) -> Result<Relation, Error>

Returns the Cartesian product of two relations (×).

colors

left
1
2

sizes

right
10
20

Output

leftright
110
120
210
220
§Errors

Returns Error::AttributeAlreadyExists if both relations contain the same attribute name, making the Cartesian product ambiguous.

§Example
use darwen::prelude::{AttributeName, Heading, Relation, Scalar, ScalarType, Tuple};

let colors = Relation::new_from_iter(
    Heading::try_from(vec![(AttributeName::from("left"), ScalarType::Integer)])?,
    vec![
        Tuple::try_from(vec![(AttributeName::from("left"), Scalar::Integer(1))])?,
        Tuple::try_from(vec![(AttributeName::from("left"), Scalar::Integer(2))])?,
    ],
)?;
let sizes = Relation::new_from_iter(
    Heading::try_from(vec![(AttributeName::from("right"), ScalarType::Integer)])?,
    vec![
        Tuple::try_from(vec![(AttributeName::from("right"), Scalar::Integer(10))])?,
        Tuple::try_from(vec![(AttributeName::from("right"), Scalar::Integer(20))])?,
    ],
)?;

let combinations = colors.product(&sizes)?;

assert_eq!(
    combinations,
    Relation::new_from_iter(
        Heading::try_from(vec![
            (AttributeName::from("left"), ScalarType::Integer),
            (AttributeName::from("right"), ScalarType::Integer),
        ])?,
        vec![
            Tuple::try_from(vec![
                (AttributeName::from("left"), Scalar::Integer(1)),
                (AttributeName::from("right"), Scalar::Integer(10)),
            ])?,
            Tuple::try_from(vec![
                (AttributeName::from("left"), Scalar::Integer(1)),
                (AttributeName::from("right"), Scalar::Integer(20)),
            ])?,
            Tuple::try_from(vec![
                (AttributeName::from("left"), Scalar::Integer(2)),
                (AttributeName::from("right"), Scalar::Integer(10)),
            ])?,
            Tuple::try_from(vec![
                (AttributeName::from("left"), Scalar::Integer(2)),
                (AttributeName::from("right"), Scalar::Integer(20)),
            ])?,
        ],
    )?
);
Examples found in repository?
examples/product.rs (line 34)
30fn main() {
31    let singers = singers();
32    let elements = elements();
33
34    println!("{}", singers.product(&elements).unwrap());
35}
Source§

impl Relation

Source

pub fn project(&self, attributes: &[AttributeName]) -> Result<Relation, Error>

Projects a relation onto a subset of attributes (π).

people

idage
119
224

Output

id
1
2
§Errors

Returns Error::AttributeNotFound if one of the requested attributes does not exist in the relation heading. Returns Error::AttributeAlreadyExists if the projection list repeats the same attribute name more than once.

§Example
use darwen::prelude::{
    AttributeName, Heading, Relation, Scalar, ScalarType, Tuple,
};

let people = Relation::new_from_iter(
    Heading::try_from(vec![
        (AttributeName::from("id"), ScalarType::Integer),
        (AttributeName::from("age"), ScalarType::Integer),
    ])?,
    vec![
        Tuple::try_from(vec![
            (AttributeName::from("id"), Scalar::Integer(1)),
            (AttributeName::from("age"), Scalar::Integer(19)),
        ])?,
        Tuple::try_from(vec![
            (AttributeName::from("id"), Scalar::Integer(2)),
            (AttributeName::from("age"), Scalar::Integer(24)),
        ])?,
    ],
)?;

let ids = people.project(&[AttributeName::from("id")])?;

assert_eq!(
    ids,
    Relation::new_from_iter(
        Heading::try_from(vec![(AttributeName::from("id"), ScalarType::Integer)])?,
        vec![
            Tuple::try_from(vec![(AttributeName::from("id"), Scalar::Integer(1))])?,
            Tuple::try_from(vec![(AttributeName::from("id"), Scalar::Integer(2))])?,
        ],
    )?
);
Examples found in repository?
examples/project.rs (line 31)
25fn main() {
26    let hotline = hotline();
27
28    println!(
29        "{}",
30        hotline
31            .project(&[AttributeName::from("name"), AttributeName::from("number")])
32            .unwrap()
33    );
34}
Source§

impl Relation

Source

pub fn rename( &self, mapping: &[(AttributeName, AttributeName)], ) -> Result<Relation, Error>

Renames relation attributes according to a mapping (ρ).

people

idage
119
224

Output

user_idage
119
224
§Errors

Returns Error::AttributeNotFound if the rename mapping references an unknown attribute. Returns Error::InvalidRenameMapping if the rename mapping repeats the same source attribute. Returns Error::AttributeAlreadyExists if the rename result would produce duplicate target names.

§Example
use darwen::prelude::{
    AttributeName, Heading, Relation, Scalar, ScalarType, Tuple,
};

let people = Relation::new_from_iter(
    Heading::try_from(vec![
        (AttributeName::from("id"), ScalarType::Integer),
        (AttributeName::from("age"), ScalarType::Integer),
    ])?,
    vec![
        Tuple::try_from(vec![
            (AttributeName::from("id"), Scalar::Integer(1)),
            (AttributeName::from("age"), Scalar::Integer(19)),
        ])?,
        Tuple::try_from(vec![
            (AttributeName::from("id"), Scalar::Integer(2)),
            (AttributeName::from("age"), Scalar::Integer(24)),
        ])?,
    ],
)?;

let renamed_people = people.rename(&[(
    AttributeName::from("id"),
    AttributeName::from("user_id"),
)])?;

assert_eq!(
    renamed_people,
    Relation::new_from_iter(
        Heading::try_from(vec![
            (AttributeName::from("user_id"), ScalarType::Integer),
            (AttributeName::from("age"), ScalarType::Integer),
        ])?,
        vec![
            Tuple::try_from(vec![
                (AttributeName::from("user_id"), Scalar::Integer(1)),
                (AttributeName::from("age"), Scalar::Integer(19)),
            ])?,
            Tuple::try_from(vec![
                (AttributeName::from("user_id"), Scalar::Integer(2)),
                (AttributeName::from("age"), Scalar::Integer(24)),
            ])?,
        ],
    )?
);
Examples found in repository?
examples/rename.rs (lines 24-27)
18fn main() {
19    let contacts = contacts();
20
21    println!(
22        "{}",
23        contacts
24            .rename(&[(
25                AttributeName::from("phone"),
26                AttributeName::from("red_phone")
27            )])
28            .unwrap()
29    );
30}
Source§

impl Relation

Source

pub fn restrict(&self, predicate: &Predicate) -> Result<Relation, Error>

Restricts a relation to tuples that satisfy a predicate (σ).

people

idage
119
224

Output

idage
224
§Errors

Returns Error::AttributeNotFound if the predicate references an attribute that does not exist in the relation tuples. Returns Error::ScalarTypeMismatch if the predicate uses Eq to compare values of different scalar types. Returns Error::NonComparableTypes if the predicate uses < or > with non-integer operands.

§Example
use darwen::prelude::{
    AttributeName, Heading, Predicate, Relation, Scalar, ScalarType, Tuple,
};

let people = Relation::new_from_iter(
    Heading::try_from(vec![
        (AttributeName::from("id"), ScalarType::Integer),
        (AttributeName::from("age"), ScalarType::Integer),
    ])?,
    vec![
        Tuple::try_from(vec![
            (AttributeName::from("id"), Scalar::Integer(1)),
            (AttributeName::from("age"), Scalar::Integer(19)),
        ])?,
        Tuple::try_from(vec![
            (AttributeName::from("id"), Scalar::Integer(2)),
            (AttributeName::from("age"), Scalar::Integer(24)),
        ])?,
    ],
)?;

let adults = people.restrict(&Predicate::eq(
    AttributeName::from("age"),
    Scalar::Integer(24),
))?;

assert_eq!(
    adults,
    Relation::new_from_iter(
        Heading::try_from(vec![
            (AttributeName::from("id"), ScalarType::Integer),
            (AttributeName::from("age"), ScalarType::Integer),
        ])?,
        vec![Tuple::try_from(vec![
            (AttributeName::from("id"), Scalar::Integer(2)),
            (AttributeName::from("age"), Scalar::Integer(24)),
        ])?],
    )?
);
Examples found in repository?
examples/predicate.rs (line 67)
65fn show(title: &str, relation: &Relation, predicate: Predicate) {
66    println!("{title}");
67    println!("{}", relation.restrict(&predicate).unwrap());
68}
More examples
Hide additional examples
examples/restrict.rs (lines 28-31)
22fn main() {
23    let users = users();
24
25    println!(
26        "{}",
27        users
28            .restrict(&Predicate::gt(
29                Expression::Attribute(AttributeName::from("age")),
30                Expression::Const(Scalar::Integer(20))
31            ))
32            .unwrap()
33    )
34}
Source§

impl Relation

Source

pub fn union(&self, other: &Relation) -> Result<Relation, Error>

Returns the union of two compatible relations ().

a

value
1
2

b

value
2
3

Output

value
1
2
3
§Errors

Returns Error::HeadingMismatch if the relations do not have the same heading.

§Example
use darwen::prelude::{AttributeName, Heading, Relation, Scalar, ScalarType, Tuple};

let a = Relation::new_from_iter(
    Heading::try_from(vec![(AttributeName::from("value"), ScalarType::Integer)])?,
    vec![
        Tuple::try_from(vec![(AttributeName::from("value"), Scalar::Integer(1))])?,
        Tuple::try_from(vec![(AttributeName::from("value"), Scalar::Integer(2))])?,
    ],
)?;
let b = Relation::new_from_iter(
    Heading::try_from(vec![(AttributeName::from("value"), ScalarType::Integer)])?,
    vec![
        Tuple::try_from(vec![(AttributeName::from("value"), Scalar::Integer(2))])?,
        Tuple::try_from(vec![(AttributeName::from("value"), Scalar::Integer(3))])?,
    ],
)?;

let union = a.union(&b)?;

assert_eq!(
    union,
    Relation::new_from_iter(
        Heading::try_from(vec![(AttributeName::from("value"), ScalarType::Integer)])?,
        vec![
            Tuple::try_from(vec![(AttributeName::from("value"), Scalar::Integer(1))])?,
            Tuple::try_from(vec![(AttributeName::from("value"), Scalar::Integer(2))])?,
            Tuple::try_from(vec![(AttributeName::from("value"), Scalar::Integer(3))])?,
        ],
    )?
);
Examples found in repository?
examples/union.rs (line 35)
31fn main() {
32    let station_a = station_a();
33    let station_b = station_b();
34
35    println!("{}", station_a.union(&station_b).unwrap());
36}
Source§

impl Relation

Source

pub fn new(heading: Heading) -> Self

Creates an empty relation with the given heading.

§Example
use darwen::prelude::{AttributeName, HeadingBuilder, Relation, ScalarType};

let relation = Relation::new(
    HeadingBuilder::new()
        .with_attribute(AttributeName::from("id"), ScalarType::Integer)
        .build()?,
);

assert_eq!(
    relation,
    Relation::new_from_iter(
        HeadingBuilder::new()
            .with_attribute(AttributeName::from("id"), ScalarType::Integer)
            .build()?,
        Vec::new(),
    )?,
);
Source

pub fn new_from_iter<T>(heading: Heading, body: T) -> Result<Self, Error>
where T: IntoIterator<Item = Tuple>,

Builds a relation from a heading and an iterator of tuples.

§Example
use darwen::prelude::{
    AttributeName, HeadingBuilder, Relation, Scalar, ScalarType, TupleBuilder,
};

let relation = Relation::new_from_iter(
    HeadingBuilder::new()
        .with_attribute(AttributeName::from("id"), ScalarType::Integer)
        .build()?,
    vec![
        TupleBuilder::new()
            .with_value(AttributeName::from("id"), Scalar::Integer(1))
            .build()?,
    ],
)?;

let _ = relation;
§Errors

Returns Error::InvalidWidth if any tuple has a different arity than the provided heading degree. Returns Error::AttributeNotFound if any tuple is missing an attribute required by the provided heading. Returns Error::ScalarTypeMismatch if any tuple contains a value with a different scalar type than the provided heading requires.

Source

pub fn insert(&mut self, tuple: Tuple) -> Result<(), Error>

Inserts a tuple into the relation.

§Example
use darwen::prelude::{
    AttributeName, HeadingBuilder, Relation, Scalar, ScalarType, TupleBuilder,
};

let mut relation = Relation::new(
    HeadingBuilder::new()
        .with_attribute(AttributeName::from("id"), ScalarType::Integer)
        .build()?,
);
relation.insert(
    TupleBuilder::new()
        .with_value(AttributeName::from("id"), Scalar::Integer(1))
        .build()?,
)?;

assert_eq!(
    relation,
    Relation::new_from_iter(
        HeadingBuilder::new()
            .with_attribute(AttributeName::from("id"), ScalarType::Integer)
            .build()?,
        vec![
            TupleBuilder::new()
                .with_value(AttributeName::from("id"), Scalar::Integer(1))
                .build()?,
        ],
    )?,
);
§Errors

Returns Error::InvalidWidth if the tuple arity does not match the relation heading degree. Returns Error::AttributeNotFound if the tuple is missing an attribute required by the relation heading. Returns Error::ScalarTypeMismatch if the tuple contains a value with a different scalar type than the relation heading requires.

Source

pub fn iter(&self) -> impl Iterator<Item = &Tuple>

Iterates over relation tuples in key order.

§Example
use darwen::{
    heading,
    tuple,
    prelude::{RelationBuilder, ScalarType},
};

let relation = RelationBuilder::new()
    .with_heading(heading!(id = ScalarType::Integer)?)
    .with_body(vec![
        tuple!(id = 2)?,
        tuple!(id = 1)?,
    ])
    .build()?;

let tuples = relation.iter().cloned().collect::<Vec<_>>();

assert_eq!(tuples.len(), 2);
assert_eq!(tuples[0], tuple!(id = 1)?);
assert_eq!(tuples[1], tuple!(id = 2)?);

Trait Implementations§

Source§

impl Debug for Relation

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for Relation

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl PartialEq for Relation

Source§

fn eq(&self, other: &Relation) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Eq for Relation

Source§

impl StructuralPartialEq for Relation

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.