Skip to content

Commit

Permalink
Moved alias creation entirely into runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
gammelalf committed Jul 2, 2024
1 parent 513be73 commit e83cf01
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 66 deletions.
40 changes: 0 additions & 40 deletions src/internal/const_concat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,46 +91,6 @@ impl ConstString<1024> {
}
}

impl ConstString<2048> {
pub(crate) const OOM_ERROR: Self = {
match ConstString::new().push_str("The error message is longer than 1024 bytes. Try using shorter names or contact the library authors.") {
Some(ok) => ok,
None => unreachable!(), // The error message is less than 2048 bytes
}
};

pub(crate) const fn join_alias(mut strings: &[&str]) -> Self {
let mut string = Self::new();

let [head, tail @ ..] = strings else {
return string;
};
strings = tail;
match string.push_str(head) {
Some(some) => {
string = some;
}
None => {
return Self::OOM_ERROR;
}
}

sugar! {
for slice in strings {
match string.push_str("__") {
Some(some) => match some.push_str(slice) {
Some(some) => {string = some;},
None => return Self::OOM_ERROR,
}
None => return Self::OOM_ERROR,
}

}
}
string
}
}

/// A contiguous growable array type for const expressions.
///
/// ## Required invariant
Expand Down
26 changes: 16 additions & 10 deletions src/internal/query_context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@ impl<'v> QueryContext<'v> {

/// Add a field to select returning its index and alias
pub fn select_field<F: Field, P: Path>(&mut self) -> (usize, String) {
P::add_to_context(self);
let alias = format!("{path}__{field}", path = P::ALIAS, field = F::NAME);
let alias = format!(
"{path}__{field}",
path = P::add_to_context(self),
field = F::NAME
);
self.selects.push(Select {
table_name: PathId::of::<P>(),
column_name: F::NAME,
Expand All @@ -51,10 +54,9 @@ impl<'v> QueryContext<'v> {

/// Add a field to aggregate returning its index and alias
pub fn select_aggregation<A: AggregationFunc, F: Field, P: Path>(&mut self) -> (usize, String) {
P::add_to_context(self);
let alias = format!(
"{path}__{field}___{func}",
path = P::ALIAS,
path = P::add_to_context(self),
field = F::NAME,
func = A::NAME,
);
Expand Down Expand Up @@ -217,28 +219,31 @@ impl<'v> QueryContext<'v> {
/// **Use [`Path::add_to_context`], this method is its impl detail!**
///
/// Add the origin model to the builder
pub(crate) fn add_origin_path<M: Model>(&mut self) {
pub(crate) fn add_origin_path<M: Model>(&mut self) -> &'static str {
self.join_aliases
.entry(PathId::of::<M>())
.or_insert_with(|| M::TABLE.to_string());
M::TABLE
}

/// **Use [`Path::add_to_context`], this method is its impl detail!**
///
/// Recursively add a relation path to the builder
///
/// The generic parameters are the parameters defining the outer most [PathStep].
pub(crate) fn add_relation_path<F, P>(&mut self)
pub(crate) fn add_relation_path<F, P>(&mut self) -> &str
where
F: Field + PathField<<F as Field>::Type>,
P: Path<Current = <F::ParentField as Field>::Model>,
{
let path_id = PathId::of::<P::Step<F>>();
if !self.join_aliases.contains_key(&path_id) {
P::add_to_context(self);

let join_alias = <P::Step<F> as Path>::ALIAS;
self.join_aliases.insert(path_id, join_alias.to_string());
let alias = format!(
"{field}__{path}",
field = F::NAME,
path = P::add_to_context(self)
);
self.join_aliases.insert(path_id, alias);
self.joins.push({
Join {
table_name: <<F as PathField<_>>::ChildField as Field>::Model::TABLE,
Expand All @@ -252,6 +257,7 @@ impl<'v> QueryContext<'v> {
FlatCondition::Column(PathId::of::<P>(), <F as PathField<_>>::ParentField::NAME),
]);
}
self.join_aliases.get(&path_id).unwrap()
}
}

Expand Down
11 changes: 3 additions & 8 deletions src/internal/relation_path/impls.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::internal::const_concat::ConstString;
use crate::internal::field::foreign_model::{ForeignModelField, ForeignModelTrait};
use crate::internal::field::{Field, SingleColumnField};
use crate::internal::query_context::QueryContext;
Expand All @@ -20,11 +19,9 @@ impl<M: Model> Path for M {
F: Field + PathField<<F as Field>::Type>,
F::ParentField: Field<Model = Self::Current>;

fn add_to_context(context: &mut QueryContext) {
fn add_to_context<'ctx>(context: &'ctx mut QueryContext) -> &'ctx str {
context.add_origin_path::<Self>()
}

const ALIAS: &'static str = M::TABLE;
}

impl<F, P> Path for (F, P)
Expand All @@ -43,11 +40,9 @@ where
F2: Field + PathField<<F2 as Field>::Type>,
F2::ParentField: Field<Model = Self::Current>;

fn add_to_context(context: &mut QueryContext) {
context.add_relation_path::<F, P>();
fn add_to_context<'ctx>(context: &'ctx mut QueryContext) -> &'ctx str {
context.add_relation_path::<F, P>()
}

const ALIAS: &'static str = ConstString::join_alias(&[P::ALIAS, F::NAME]).as_str();
}

impl<FF, F> PathField<ForeignModelByField<FF>> for F
Expand Down
11 changes: 3 additions & 8 deletions src/internal/relation_path/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@

mod impls;

use crate::internal::field::Field;
use crate::internal::field::SingleColumnField;
use crate::internal::field::{Field, SingleColumnField};
use crate::internal::query_context::QueryContext;
use crate::sealed;
use crate::Model;
use crate::{sealed, Model};

/// Trait to store a relation path in generics
///
Expand Down Expand Up @@ -82,10 +80,7 @@ pub trait Path: 'static {
// SubPath: Path<Origin = Self::Current>;

/// Add all joins required to use this path to the query context
fn add_to_context(context: &mut QueryContext);

/// Unique join alias
const ALIAS: &'static str;
fn add_to_context<'ctx>(context: &'ctx mut QueryContext) -> &'ctx str;
}

/// A field representing a db relation which can be used to construct paths.
Expand Down

0 comments on commit e83cf01

Please sign in to comment.