Skip to content

Commit

Permalink
update join query builder to better support filters, ordering and pag…
Browse files Browse the repository at this point in the history
…ination
  • Loading branch information
Weakky committed Nov 27, 2023
1 parent 306e5cc commit 4c0582d
Show file tree
Hide file tree
Showing 7 changed files with 319 additions and 238 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub enum AliasMode {
#[derive(Clone, Copy, Debug, Default)]
/// Aliasing tool to count the nesting level to help with heavily nested
/// self-related queries.
pub(crate) struct Alias {
pub struct Alias {
counter: usize,
mode: AliasMode,
}
Expand Down Expand Up @@ -49,6 +49,10 @@ impl Alias {
AliasMode::Join => format!("j{}", self.counter),
}
}

pub fn to_table_string(&self) -> String {
self.to_string(Some(AliasMode::Table))
}
}

pub(crate) trait AliasedColumn {
Expand Down
4 changes: 2 additions & 2 deletions query-engine/connectors/sql-query-connector/src/filter/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
mod alias;
pub mod alias;
mod visitor;

use quaint::prelude::*;
use query_structure::Filter;
use visitor::*;
pub use visitor::*;

use crate::{context::Context, join_utils::AliasedJoin};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub(crate) trait FilterVisitorExt {
}

#[derive(Debug, Clone, Default)]
pub(crate) struct FilterVisitor {
pub struct FilterVisitor {
/// The last alias that's been rendered.
last_alias: Option<Alias>,
/// The parent alias, used when rendering nested filters so that a child filter can refer to its join.
Expand Down Expand Up @@ -68,6 +68,11 @@ impl FilterVisitor {
self.parent_alias
}

pub fn set_parent_alias_opt(mut self, alias: Option<Alias>) -> Self {
self.parent_alias = alias;
self
}

/// A top-level join can be rendered if we're explicitly allowing it or if we're in a nested visitor.
fn can_render_join(&self) -> bool {
self.with_top_level_joins || self.is_nested
Expand Down
14 changes: 12 additions & 2 deletions query-engine/connectors/sql-query-connector/src/ordering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,14 @@ impl OrderByBuilder {
// Unwraps are safe because the SQL connector doesn't yet support any other type of orderBy hop but the relation hop.
let mut joins: Vec<AliasedJoin> = vec![];

let parent_alias = self.parent_alias.clone();

for (i, hop) in rest_hops.iter().enumerate() {
let previous_join = if i > 0 { joins.get(i - 1) } else { None };
let previous_alias = previous_join.map(|j| j.alias.as_str());

let previous_alias = previous_join
.map(|j| j.alias.as_str())
.or_else(|| parent_alias.as_deref());
let join = compute_one2m_join(hop.as_relation_hop().unwrap(), &self.join_prefix(), previous_alias, ctx);

joins.push(join);
Expand Down Expand Up @@ -192,9 +197,14 @@ impl OrderByBuilder {
) -> (Vec<AliasedJoin>, Column<'static>) {
let mut joins: Vec<AliasedJoin> = vec![];

let parent_alias = self.parent_alias.clone();

for (i, hop) in order_by.path.iter().enumerate() {
let previous_join = if i > 0 { joins.get(i - 1) } else { None };
let previous_alias = previous_join.map(|j| j.alias.as_str());
let previous_alias = previous_join
.map(|j| &j.alias)
.or(parent_alias.as_ref())
.map(|alias| alias.as_str());
let join = compute_one2m_join(hop.as_relation_hop().unwrap(), &self.join_prefix(), previous_alias, ctx);

joins.push(join);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,16 @@ use crate::{
cursor_condition, filter::FilterBuilder, model_extensions::*, nested_aggregations, ordering::OrderByBuilder,
sql_trace::SqlTraceComment, Context,
};
use connector_interface::{AggregationSelection, RelAggregationSelection, RelatedQuery};
use connector_interface::{AggregationSelection, RelAggregationSelection};
use itertools::Itertools;
use quaint::ast::*;
use query_structure::*;
use tracing::Span;

use super::select;

pub(crate) trait SelectDefinition {
fn into_select(
self,
_: &Model,
nested: Vec<RelatedQuery>,
aggr_selections: &[RelAggregationSelection],
ctx: &Context<'_>,
) -> (Select<'static>, Vec<Expression<'static>>);
Expand All @@ -24,32 +21,29 @@ impl SelectDefinition for Filter {
fn into_select(
self,
model: &Model,
nested: Vec<RelatedQuery>,
aggr_selections: &[RelAggregationSelection],
ctx: &Context<'_>,
) -> (Select<'static>, Vec<Expression<'static>>) {
let args = QueryArguments::from((model.clone(), self));
args.into_select(model, nested, aggr_selections, ctx)
args.into_select(model, aggr_selections, ctx)
}
}

impl SelectDefinition for &Filter {
fn into_select(
self,
model: &Model,
nested: Vec<RelatedQuery>,
aggr_selections: &[RelAggregationSelection],
ctx: &Context<'_>,
) -> (Select<'static>, Vec<Expression<'static>>) {
self.clone().into_select(model, nested, aggr_selections, ctx)
self.clone().into_select(model, aggr_selections, ctx)
}
}

impl SelectDefinition for Select<'static> {
fn into_select(
self,
_: &Model,
_: Vec<RelatedQuery>,
_: &[RelAggregationSelection],
_ctx: &Context<'_>,
) -> (Select<'static>, Vec<Expression<'static>>) {
Expand All @@ -61,7 +55,6 @@ impl SelectDefinition for QueryArguments {
fn into_select(
self,
model: &Model,
nested: Vec<RelatedQuery>,
aggr_selections: &[RelAggregationSelection],
ctx: &Context<'_>,
) -> (Select<'static>, Vec<Expression<'static>>) {
Expand Down Expand Up @@ -125,13 +118,12 @@ pub(crate) fn get_records<T>(
columns: impl Iterator<Item = Column<'static>>,
aggr_selections: &[RelAggregationSelection],
query: T,
nested: Vec<RelatedQuery>,
ctx: &Context<'_>,
) -> Select<'static>
where
T: SelectDefinition,
{
let (select, additional_selection_set) = query.into_select(model, nested, aggr_selections, ctx);
let (select, additional_selection_set) = query.into_select(model, aggr_selections, ctx);
let select = columns.fold(select, |acc, col| acc.column(col));

let select = select.append_trace(&Span::current()).add_trace_id(ctx.trace_id);
Expand Down Expand Up @@ -174,7 +166,7 @@ pub(crate) fn aggregate(
ctx: &Context<'_>,
) -> Select<'static> {
let columns = extract_columns(model, selections, ctx);
let sub_query = get_records(model, columns.into_iter(), &[], args, Vec::new(), ctx);
let sub_query = get_records(model, columns.into_iter(), &[], args, ctx);
let sub_table = Table::from(sub_query).alias("sub");

selections.iter().fold(
Expand Down Expand Up @@ -231,7 +223,7 @@ pub(crate) fn group_by_aggregate(
having: Option<Filter>,
ctx: &Context<'_>,
) -> Select<'static> {
let (base_query, _) = args.into_select(model, Vec::new(), &[], ctx);
let (base_query, _) = args.into_select(model, &[], ctx);

let select_query = selections.iter().fold(base_query, |select, next_op| match next_op {
AggregationSelection::Field(field) => select.column(field.as_column(ctx).set_is_selected(true)),
Expand Down
Loading

0 comments on commit 4c0582d

Please sign in to comment.