Skip to content

Commit

Permalink
Add graph tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jpschorr committed Mar 7, 2025
1 parent ae2e149 commit b33bffd
Show file tree
Hide file tree
Showing 9 changed files with 331 additions and 60 deletions.
4 changes: 2 additions & 2 deletions extension/partiql-extension-ion/src/boxed_ion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ pub struct BoxedIon {

#[cfg(feature = "serde")]
impl Serialize for BoxedIon {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
fn serialize<S>(&self, _serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: Serializer,
{
Expand All @@ -179,7 +179,7 @@ impl Serialize for BoxedIon {

#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for BoxedIon {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
fn deserialize<D>(_deserializer: D) -> std::result::Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Expand Down
59 changes: 25 additions & 34 deletions extension/partiql-extension-ion/src/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,23 @@ fn has_annotation(
static TIME_PARTS_PATTERN_SET: Lazy<RegexSet> =
Lazy::new(|| RegexSet::new(RE_SET_TIME_PARTS).unwrap());

type GNode = (String, HashSet<String>, Option<Value>);
type GNodes = (Vec<String>, Vec<HashSet<String>>, Vec<Option<Value>>);
#[allow(clippy::type_complexity)]
type GEdge = (
String,
HashSet<String>,
(String, String, String),
Option<Value>,
);
#[allow(clippy::type_complexity)]
type GEdges = (
Vec<String>,
Vec<HashSet<String>>,
Vec<(String, String, String)>,
Vec<Option<Value>>,
);

impl PartiqlEncodedIonValueDecoder {
fn decode_date<R>(&self, reader: &mut R) -> IonDecodeResult
where
Expand Down Expand Up @@ -570,10 +587,7 @@ impl PartiqlEncodedIonValueDecoder {
)))))
}

fn decode_nodes<R>(
&self,
reader: &mut R,
) -> Result<(Vec<String>, Vec<HashSet<String>>, Vec<Option<Value>>), IonDecodeError>
fn decode_nodes<R>(&self, reader: &mut R) -> Result<GNodes, IonDecodeError>
where
R: IonReader<Item = StreamItem, Symbol = Symbol>,
{
Expand All @@ -599,10 +613,7 @@ impl PartiqlEncodedIonValueDecoder {
Ok((ids, labels, payloads))
}

fn decode_node<R>(
&self,
reader: &mut R,
) -> Result<(String, HashSet<String>, Option<Value>), IonDecodeError>
fn decode_node<R>(&self, reader: &mut R) -> Result<GNode, IonDecodeError>
where
R: IonReader<Item = StreamItem, Symbol = Symbol>,
{
Expand All @@ -625,10 +636,11 @@ impl PartiqlEncodedIonValueDecoder {
("labels", StreamItem::Value(IonType::List)) => {
let mut labelset = HashSet::new();
reader.step_in()?;
#[allow(irrefutable_let_patterns)]
while let item = reader.next()? {
match item {
StreamItem::Value(IonType::String) => {
labelset.insert(reader.read_string()?.to_string());
labelset.insert(reader.read_string()?.text().to_string());
}
StreamItem::Nothing => break,
_ => return Err(err()),
Expand All @@ -650,18 +662,7 @@ impl PartiqlEncodedIonValueDecoder {
Ok((id, labels, payload))
}

fn decode_edges<R>(
&self,
reader: &mut R,
) -> Result<
(
Vec<String>,
Vec<HashSet<String>>,
Vec<(String, String, String)>,
Vec<Option<Value>>,
),
IonDecodeError,
>
fn decode_edges<R>(&self, reader: &mut R) -> Result<GEdges, IonDecodeError>
where
R: IonReader<Item = StreamItem, Symbol = Symbol>,
{
Expand Down Expand Up @@ -689,18 +690,7 @@ impl PartiqlEncodedIonValueDecoder {
Ok((ids, labels, ends, payloads))
}

fn decode_edge<R>(
&self,
reader: &mut R,
) -> Result<
(
String,
HashSet<String>,
(String, String, String),
Option<Value>,
),
IonDecodeError,
>
fn decode_edge<R>(&self, reader: &mut R) -> Result<GEdge, IonDecodeError>
where
R: IonReader<Item = StreamItem, Symbol = Symbol>,
{
Expand All @@ -724,10 +714,11 @@ impl PartiqlEncodedIonValueDecoder {
("labels", StreamItem::Value(IonType::List)) => {
let mut labelset = HashSet::new();
reader.step_in()?;
#[allow(irrefutable_let_patterns)]
while let item = reader.next()? {
match item {
StreamItem::Value(IonType::String) => {
labelset.insert(reader.read_string()?.to_string());
labelset.insert(reader.read_string()?.text().to_string());
}
StreamItem::Nothing => break,
_ => return Err(err()),
Expand Down
3 changes: 0 additions & 3 deletions extension/partiql-extension-ion/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
#![deny(rust_2018_idioms)]
#![deny(clippy::all)]

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

pub mod boxed_ion;
mod common;
pub mod decode;
Expand Down
94 changes: 74 additions & 20 deletions partiql-value/src/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,38 @@ use crate::Value;
use lasso::{Key, Rodeo, RodeoReader, Spur};
use petgraph::{Directed, Undirected};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::cmp::Ordering;
use std::collections::{HashMap, HashSet};
use std::fmt::Debug;
use std::fmt::{Debug, Formatter};
use std::hash::{Hash, Hasher};
use std::rc::Rc;

#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Graph {
Simple(Rc<SimpleGraph>),
}

#[cfg(feature = "serde")]
impl Serialize for Graph {
fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
todo!("Serialize for Graph")
}
}

#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for Graph {
fn deserialize<D>(_: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
todo!("Deserialize for Graph")
}
}

impl Hash for Graph {
fn hash<H: Hasher>(&self, _state: &mut H) {
todo!("Hash for Graph")
Expand All @@ -40,10 +59,10 @@ impl Ord for Graph {
}
}

#[derive(Clone, Hash, PartialEq, Eq)]
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct GNodeId(pub usize);

#[derive(Clone, Hash, PartialEq, Eq)]
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct GEdgeId(pub usize);

#[derive(Clone, Hash, PartialEq, Eq)]
Expand All @@ -55,7 +74,6 @@ pub struct GLabels(pub HashSet<GLabelId>);
#[derive(Clone, PartialEq, Eq)]
pub struct GElem(pub Option<Value>, pub GLabels);

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct SimpleGraph {
directed: petgraph::stable_graph::StableGraph<GNodeId, GEdgeId, Directed>,
undirected: petgraph::stable_graph::StableGraph<GNodeId, GEdgeId, Undirected>,
Expand All @@ -66,7 +84,43 @@ pub struct SimpleGraph {

impl Debug for SimpleGraph {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
todo!("Debutg for SimpleGraph")
f.debug_struct("SimpleGraph")
.field("nodes", &DebugGElems("node", &self.nodes, &self.labels))
.field("edges", &DebugGElems("edge", &self.edges, &self.labels))
.field("directed", &self.directed)
.field("undirected", &self.undirected)
.finish()
}
}

pub struct DebugGElems<'a>(&'a str, &'a Vec<GElem>, &'a RodeoReader);
pub struct DebugGElem<'a>(usize, &'a str, &'a GElem, &'a RodeoReader);

impl Debug for DebugGElems<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut l = f.debug_list();

for (id, gelem) in self.1.iter().enumerate() {
l.entry(&DebugGElem(id, self.0, gelem, self.2));
}

l.finish()
}
}

impl Debug for DebugGElem<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let DebugGElem(id, name, GElem(value, labels), reader) = self;
let labels = labels
.0
.iter()
.map(|id| reader.resolve(&id.0))
.collect::<Vec<_>>();
f.debug_struct(name)
.field("id", id)
.field("value", value)
.field("labels", &labels)
.finish()
}
}

Expand All @@ -75,16 +129,16 @@ pub enum EdgeSpec {
Undirected(String, String), // node, node
}

type NodeSpec = (Vec<String>, Vec<HashSet<String>>, Vec<Option<Value>>);
#[allow(clippy::type_complexity)]
type EdgesSpec = (
Vec<String>,
Vec<HashSet<String>>,
Vec<EdgeSpec>,
Vec<Option<Value>>,
);
impl SimpleGraph {
pub fn from_spec(
node_specs: (Vec<String>, Vec<HashSet<String>>, Vec<Option<Value>>),
edge_specs: (
Vec<String>,
Vec<HashSet<String>>,
Vec<EdgeSpec>,
Vec<Option<Value>>,
),
) -> Self {
pub fn from_spec(node_specs: NodeSpec, edge_specs: EdgesSpec) -> Self {
let mut node_ids = Rodeo::default();
let mut label_ids = Rodeo::default();
let mut nodes: Vec<GElem> = vec![];
Expand Down Expand Up @@ -139,7 +193,7 @@ impl SimpleGraph {
assert_eq!(edges.len(), eidx);
edges.push(GElem(value, GLabels(labels)));

let e = match edge_spec {
match edge_spec {
EdgeSpec::Directed(l, r) => {
let mut get_or_insert = |idx: GNodeId| {
*directed_contains
Expand All @@ -150,7 +204,7 @@ impl SimpleGraph {
let ridx = GNodeId(node_ids.get(r).expect("expected node").into_usize());
let l = get_or_insert(lidx);
let r = get_or_insert(ridx);
directed.add_edge(l, r, GEdgeId(eidx))
directed.add_edge(l, r, GEdgeId(eidx));
}
EdgeSpec::Undirected(l, r) => {
let mut get_or_insert = |idx: GNodeId| {
Expand All @@ -162,9 +216,9 @@ impl SimpleGraph {
let ridx = GNodeId(node_ids.get(r).expect("expected node").into_usize());
let l = get_or_insert(lidx);
let r = get_or_insert(ridx);
undirected.add_edge(l, r, GEdgeId(eidx))
undirected.add_edge(l, r, GEdgeId(eidx));
}
};
}
}

let labels = label_ids.into_reader();
Expand Down
2 changes: 1 addition & 1 deletion partiql-value/src/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ impl PrettyDoc for Tuple {
}

impl PrettyDoc for Graph {
fn pretty_doc<'b, D, A>(&'b self, arena: &'b D) -> DocBuilder<'b, D, A>
fn pretty_doc<'b, D, A>(&'b self, _arena: &'b D) -> DocBuilder<'b, D, A>
where
D: DocAllocator<'b, A>,
D::Doc: Clone,
Expand Down
3 changes: 3 additions & 0 deletions partiql/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ partiql-extension-value-functions = { path = "../extension/partiql-extension-val
partiql-extension-ion = { path = "../extension/partiql-extension-ion" }


ion-rs_old = { version = "0.18", package = "ion-rs" }


insta = "1"


Expand Down
Loading

0 comments on commit b33bffd

Please sign in to comment.