Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flatten ColumnOp, avoiding allocation in the common case #1234

Merged
merged 1 commit into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 17 additions & 54 deletions crates/core/src/sql/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,6 @@ mod tests {
use crate::sql::execute::tests::run_for_testing;
use crate::vm::tests::create_table_with_rows;
use spacetimedb_lib::error::{ResultTest, TestError};
use spacetimedb_lib::operator::OpQuery;
use spacetimedb_lib::{Address, Identity};
use spacetimedb_primitives::{col_list, ColList, TableId};
use spacetimedb_sats::{product, AlgebraicType, AlgebraicValue, ProductType};
Expand Down Expand Up @@ -634,25 +633,16 @@ mod tests {
assert_eq!(source_lhs.table_id().unwrap(), lhs_id);
assert_eq!(query.len(), 2);

// The first operation in the pipeline should be a selection
let Query::Select(ColumnOp::Cmp {
op: OpQuery::Cmp(OpCmp::Eq),
ref lhs,
ref rhs,
// The first operation in the pipeline should be a selection with `col#0 = 3`
let Query::Select(ColumnOp::ColCmpVal {
cmp: OpCmp::Eq,
lhs: ColId(0),
rhs: AlgebraicValue::U64(3),
}) = query[0]
else {
panic!("unexpected operator {:#?}", query[0]);
};

let ColumnOp::Col(ColExpr::Col(col)) = **lhs else {
panic!("unexpected left hand side {:#?}", **lhs);
};
assert_eq!(col, 0.into());

let ColumnOp::Col(ColExpr::Value(AlgebraicValue::U64(3))) = **rhs else {
panic!("unexpected right hand side {:#?}", **rhs);
};

// The join should follow the selection
let Query::JoinInner(JoinExpr {
ref rhs,
Expand Down Expand Up @@ -718,23 +708,14 @@ mod tests {
assert_eq!(&**inner_header, &source_lhs.head().extend(rhs.source.head()));

// The selection should be pushed onto the rhs of the join
let Query::Select(ColumnOp::Cmp {
op: OpQuery::Cmp(OpCmp::Eq),
ref lhs,
ref rhs,
let Query::Select(ColumnOp::ColCmpVal {
cmp: OpCmp::Eq,
lhs: ColId(1),
rhs: AlgebraicValue::U64(3),
}) = rhs.query[0]
else {
panic!("unexpected operator {:#?}", rhs.query[0]);
};

let ColumnOp::Col(ColExpr::Col(col)) = **lhs else {
panic!("unexpected left hand side {:#?}", **lhs);
};
assert_eq!(col, 1.into());

let ColumnOp::Col(ColExpr::Value(AlgebraicValue::U64(3))) = **rhs else {
panic!("unexpected right hand side {:#?}", **rhs);
};
Ok(())
}

Expand Down Expand Up @@ -876,23 +857,14 @@ mod tests {
assert_eq!(table_id, rhs_id);

// Followed by a selection
let Query::Select(ColumnOp::Cmp {
op: OpQuery::Cmp(OpCmp::Eq),
lhs: ref field,
rhs: ref value,
let Query::Select(ColumnOp::ColCmpVal {
cmp: OpCmp::Eq,
lhs: ColId(2),
rhs: AlgebraicValue::U64(3),
}) = rhs[1]
else {
panic!("unexpected operator {:#?}", rhs[0]);
};

let ColumnOp::Col(ColExpr::Col(col)) = **field else {
panic!("unexpected left hand side {:#?}", field);
};
assert_eq!(col, 2.into());

let ColumnOp::Col(ColExpr::Value(AlgebraicValue::U64(3))) = **value else {
panic!("unexpected right hand side {:#?}", value);
};
Ok(())
}

Expand Down Expand Up @@ -962,23 +934,14 @@ mod tests {
assert_eq!(table_id, rhs_id);

// Followed by a selection
let Query::Select(ColumnOp::Cmp {
op: OpQuery::Cmp(OpCmp::Eq),
lhs: ref field,
rhs: ref value,
let Query::Select(ColumnOp::ColCmpVal {
cmp: OpCmp::Eq,
lhs: ColId(2),
rhs: AlgebraicValue::U64(3),
}) = rhs[1]
else {
panic!("unexpected operator {:#?}", rhs[0]);
};

let ColumnOp::Col(ColExpr::Col(col)) = **field else {
panic!("unexpected left hand side {:#?}", field);
};
assert_eq!(col, 2.into());

let ColumnOp::Col(ColExpr::Value(AlgebraicValue::U64(3))) = **value else {
panic!("unexpected right hand side {:#?}", value);
};
Ok(())
}

Expand Down
6 changes: 3 additions & 3 deletions crates/core/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ static_assert_size!(IndexSemiJoinLeft<Box<IterRows<'static>>>, 312);

impl<'a, Rhs: RelOps<'a>> IndexSemiJoinLeft<'a, '_, Rhs> {
fn filter(&self, index_row: &RelValue<'_>) -> bool {
self.index_select.as_ref().map_or(true, |op| op.compare(index_row))
self.index_select.as_ref().map_or(true, |op| op.eval_bool(index_row))
}
}

Expand Down Expand Up @@ -335,7 +335,7 @@ impl<'a, Rhs: RelOps<'a>> RelOps<'a> for IndexSemiJoinLeft<'a, '_, Rhs> {
}
}

/// An index join operator that returns matching rows from the index side.
/// An index join operator that returns matching rows from the probe side.
pub struct IndexSemiJoinRight<'a, 'c, Rhs: RelOps<'a>> {
/// An iterator for the probe side.
/// The values returned will be used to probe the index.
Expand All @@ -360,7 +360,7 @@ static_assert_size!(IndexSemiJoinRight<Box<IterRows<'static>>>, 64);

impl<'a, Rhs: RelOps<'a>> IndexSemiJoinRight<'a, '_, Rhs> {
fn filter(&self, index_row: &RelValue<'_>) -> bool {
self.index_select.as_ref().map_or(true, |op| op.compare(index_row))
self.index_select.as_ref().map_or(true, |op| op.eval_bool(index_row))
}
}

Expand Down
3 changes: 1 addition & 2 deletions crates/vm/src/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use spacetimedb_sats::ProductValue;
pub type IterRows<'a> = dyn RelOps<'a> + 'a;

pub fn build_select<'a>(base: impl RelOps<'a> + 'a, cmp: &'a ColumnOp) -> Box<IterRows<'a>> {
Box::new(base.select(move |row| cmp.compare(row)))
Box::new(base.select(move |row| cmp.eval_bool(row)))
}

pub fn build_project<'a>(base: impl RelOps<'a> + 'a, proj: &'a ProjectExpr) -> Box<IterRows<'a>> {
Expand Down Expand Up @@ -306,7 +306,6 @@ pub mod tests {
let second_source_expr = sources.add_mem_table(table);

let q = QueryExpr::new(source_expr).with_join_inner(second_source_expr, col, col, false);
dbg!(&q);
let result = run_query(q.into(), sources);

// The expected result.
Expand Down
Loading
Loading