Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
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
40 changes: 23 additions & 17 deletions benches/association.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ use std::hint::black_box;
use tests::{models, LoggingDriver, Setup};
use toasty::stmt::Id;

type SetupFactory = Box<dyn Fn() -> Box<dyn Setup>>;

#[derive(Debug, toasty::Model)]
#[allow(dead_code)]
struct User {
Expand Down Expand Up @@ -50,14 +52,14 @@ async fn setup_test_data(
) {
for i in 0..num_users {
let user = User::create()
.name(&format!("User {}", i))
.name(format!("User {}", i))
.exec(db)
.await
.unwrap();

for j in 0..posts_per_user {
Post::create()
.title(&format!("Post {} for User {}", j, i))
.title(format!("Post {} for User {}", j, i))
.user(&user)
.exec(db)
.await
Expand All @@ -66,7 +68,7 @@ async fn setup_test_data(

for j in 0..comments_per_user {
Comment::create()
.text(&format!("Comment {} for User {}", j, i))
.text(format!("Comment {} for User {}", j, i))
.user(&user)
.exec(db)
.await
Expand Down Expand Up @@ -97,27 +99,31 @@ async fn setup_database_and_data(
fn association_benchmarks(c: &mut Criterion) {
let sizes = vec![(50, 10, 10), (100, 20, 20), (200, 25, 25)];

let database_setups = vec![
let database_setups: Vec<(&str, SetupFactory)> = vec![
#[cfg(feature = "sqlite")]
("sqlite", || {
Box::new(tests::db::sqlite::SetupSqlite::new()) as Box<dyn Setup>
}),
(
"sqlite",
Box::new(|| Box::new(tests::db::sqlite::SetupSqlite::new()) as Box<dyn Setup>),
),
#[cfg(feature = "postgresql")]
("postgresql", || {
Box::new(tests::db::postgresql::SetupPostgreSQL::new()) as Box<dyn Setup>
}),
(
"postgresql",
Box::new(|| Box::new(tests::db::postgresql::SetupPostgreSQL::new()) as Box<dyn Setup>),
),
#[cfg(feature = "mysql")]
("mysql", || {
Box::new(tests::db::mysql::SetupMySQL::new()) as Box<dyn Setup>
}),
(
"mysql",
Box::new(|| Box::new(tests::db::mysql::SetupMySQL::new()) as Box<dyn Setup>),
),
#[cfg(feature = "dynamodb")]
("dynamodb", || {
Box::new(tests::db::dynamodb::SetupDynamoDb::new()) as Box<dyn Setup>
}),
(
"dynamodb",
Box::new(|| Box::new(tests::db::dynamodb::SetupDynamoDb::new()) as Box<dyn Setup>),
),
];

for (db_name, setup_fn) in database_setups {
let mut group = c.benchmark_group(&format!("association_performance_{}", db_name));
let mut group = c.benchmark_group(format!("association_performance_{}", db_name));
group.sample_size(10);

for (users, posts, comments) in &sizes {
Expand Down
41 changes: 36 additions & 5 deletions crates/toasty-core/src/driver/response.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::stmt::ValueStream;
use crate::{stmt::ValueStream, Result};

#[derive(Debug)]
pub struct Response {
Expand All @@ -15,15 +15,15 @@ pub enum Rows {
}

impl Response {
pub fn from_count(count: u64) -> Self {
pub fn count(count: u64) -> Self {
Self {
rows: Rows::Count(count),
}
}

pub fn from_value_stream(values: ValueStream) -> Self {
pub fn value_stream(values: impl Into<ValueStream>) -> Self {
Self {
rows: Rows::Values(values),
rows: Rows::value_stream(values),
}
}

Expand All @@ -35,14 +35,45 @@ impl Response {
}

impl Rows {
pub fn value_stream(values: impl Into<ValueStream>) -> Self {
Self::Values(values.into())
}

pub fn is_count(&self) -> bool {
matches!(self, Self::Count(_))
}

pub fn is_values(&self) -> bool {
matches!(self, Self::Values(_))
}

pub async fn dup(&mut self) -> Result<Self> {
match self {
Rows::Count(count) => Ok(Rows::Count(*count)),
Rows::Values(values) => Ok(Rows::Values(values.dup().await?)),
}
}

pub fn try_clone(&self) -> Option<Self> {
match self {
Rows::Count(count) => Some(Rows::Count(*count)),
Rows::Values(values) => values.try_clone().map(Rows::Values),
}
}

#[track_caller]
pub fn into_count(self) -> u64 {
match self {
Rows::Count(count) => count,
_ => todo!("rows={self:#?}"),
}
}

#[track_caller]
pub fn into_values(self) -> ValueStream {
match self {
Self::Values(values) => values,
_ => todo!(),
_ => todo!("rows={self:#?}"),
}
}
}
8 changes: 6 additions & 2 deletions crates/toasty-core/src/schema/app/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ impl Model {
let filter = match &self.primary_key.fields[..] {
[pk_field] => stmt::Expr::eq(
stmt::Expr::ref_self_field(pk_field),
input.resolve_arg_as_expr(&0.into()),
input
.resolve_arg(&0.into(), &stmt::Projection::identity())
.unwrap(),
),
pk_fields => stmt::Expr::and_from_vec(
pk_fields
Expand All @@ -63,7 +65,9 @@ impl Model {
.map(|(i, pk_field)| {
stmt::Expr::eq(
stmt::Expr::ref_self_field(pk_field),
input.resolve_arg_as_expr(&i.into()),
input
.resolve_arg(&i.into(), &stmt::Projection::identity())
.unwrap(),
)
})
.collect(),
Expand Down
90 changes: 14 additions & 76 deletions crates/toasty-core/src/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ pub use assignments::{Assignment, AssignmentOp, Assignments};
mod association;
pub use association::Association;

mod condition;
pub use condition::Condition;

mod cte;
pub use cte::Cte;

mod cx;
pub use cx::{ExprContext, ExprTarget, IntoExprTarget, ResolvedRef};
pub use cx::{ExprContext, ExprTarget, IntoExprTarget, Resolve, ResolvedRef};

mod delete;
pub use delete::Delete;
Expand All @@ -25,12 +28,17 @@ pub use entry_mut::EntryMut;
mod entry_path;
pub use entry_path::EntryPath;

mod eval;

mod expr;
pub use expr::Expr;

mod expr_and;
pub use expr_and::ExprAnd;

mod expr_any;
pub use expr_any::ExprAny;

mod expr_arg;
pub use expr_arg::ExprArg;

Expand Down Expand Up @@ -124,6 +132,9 @@ pub use insert_table::InsertTable;
mod insert_target;
pub use insert_target::InsertTarget;

mod input;
pub use input::{ConstInput, Input, TypedInput};

mod join;
pub use join::{Join, JoinOp};

Expand Down Expand Up @@ -160,7 +171,7 @@ mod path_field_set;
pub use path_field_set::PathFieldSet;

mod projection;
pub use projection::Projection;
pub use projection::{Project, Projection};

mod query;
pub use query::{Lock, Query};
Expand All @@ -184,7 +195,6 @@ mod sparse_record;
pub use sparse_record::SparseRecord;

mod substitute;
pub use substitute::Input;
use substitute::Substitute;

mod table_derived;
Expand Down Expand Up @@ -253,82 +263,10 @@ pub enum Statement {
}

impl Statement {
pub fn substitute(&mut self, input: impl substitute::Input) {
pub fn substitute(&mut self, input: impl Input) {
Substitute::new(input).visit_stmt_mut(self);
}

/// Attempts to return a reference to an inner [`Delete`].
///
/// * If `self` is a [`Statement::Delete`], a reference to the inner [`Delete`] is
/// returned wrapped in [`Some`].
/// * Else, [`None`] is returned.
pub fn as_delete(&self) -> Option<&Delete> {
match self {
Self::Delete(delete) => Some(delete),
_ => None,
}
}

/// Consumes `self` and attempts to return the inner [`Delete`].
///
/// * If `self` is a [`Statement::Delete`], inner [`Delete`] is returned wrapped in
/// [`Some`].
/// * Else, [`None`] is returned.
pub fn into_delete(self) -> Option<Delete> {
match self {
Self::Delete(delete) => Some(delete),
_ => None,
}
}

/// Consumes `self` and returns the inner [`Delete`].
///
/// # Panics
///
/// If `self` is not a [`Statement::Delete`].
pub fn unwrap_delete(self) -> Delete {
match self {
Self::Delete(delete) => delete,
v => panic!("expected `Delete`, found {v:#?}"),
}
}

/// Attempts to return a reference to an inner [`Insert`].
///
/// * If `self` is a [`Statement::Insert`], a reference to the inner [`Insert`] is
/// returned wrapped in [`Some`].
/// * Else, [`None`] is returned.
pub fn as_insert(&self) -> Option<&Insert> {
match self {
Self::Insert(insert) => Some(insert),
_ => None,
}
}

/// Consumes `self` and attempts to return the inner [`Insert`].
///
/// * If `self` is a [`Statement::Insert`], inner [`Insert`] is returned wrapped in
/// [`Some`].
/// * Else, [`None`] is returned.
pub fn into_insert(self) -> Option<Insert> {
match self {
Self::Insert(insert) => Some(insert),
_ => None,
}
}

/// Consumes `self` and returns the inner [`Insert`].
///
/// # Panics
///
/// If `self` is not a [`Statement::Insert`].
pub fn unwrap_insert(self) -> Insert {
match self {
Self::Insert(insert) => insert,
v => panic!("expected `Insert`, found {v:#?}"),
}
}

/// Attempts to return a reference to an inner [`Update`].
///
/// * If `self` is a [`Statement::Update`], a reference to the inner [`Update`] is
Expand Down
18 changes: 16 additions & 2 deletions crates/toasty-core/src/stmt/assignments.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::stmt::Statement;

use super::{Expr, Projection};

use indexmap::{Equivalent, IndexMap};
Expand Down Expand Up @@ -32,6 +34,15 @@ pub enum AssignmentOp {
Remove,
}

impl Statement {
pub fn assignments(&self) -> Option<&Assignments> {
match self {
Statement::Update(update) => Some(&update.assignments),
_ => None,
}
}
}

impl Assignments {
pub fn with_capacity(capacity: usize) -> Self {
Self {
Expand Down Expand Up @@ -118,8 +129,11 @@ impl Assignments {
}
}

pub fn take(&mut self, key: usize) -> Assignment {
self.assignments.swap_remove(&key).unwrap()
pub fn take<Q>(&mut self, key: &Q) -> Option<Assignment>
where
Q: ?Sized + Hash + Equivalent<usize>,
{
self.assignments.swap_remove(key)
}

pub fn keys(&self) -> impl Iterator<Item = usize> + '_ {
Expand Down
Loading
Loading