-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add basic support for additional expressions in from clause
This is useful for things like full text search, where you need to do an expensive calculation to a parameter going into the where clause, but doing it inline would repeat the calculation for each loop. I had to expose a lot of internals here, because this is yet another case where we can't properly express what we want without either specialization or rust-lang/rust#29864. I could not find a way to properly enforce the selectability of `Aliased` when `with` was called more than once (this is ultimately the same problem as joining multiple times). In the interim, we'll allow the alias to be used anywhere.
- Loading branch information
Showing
7 changed files
with
132 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
use expression::{Expression, NonAggregate, SelectableExpression}; | ||
use query_builder::*; | ||
use query_source::*; | ||
|
||
#[derive(Debug, Clone, Copy)] | ||
pub struct Aliased<'a, Expr> { | ||
expr: Expr, | ||
alias: &'a str, | ||
} | ||
|
||
impl<'a, Expr> Aliased<'a, Expr> { | ||
pub fn new(expr: Expr, alias: &'a str) -> Self { | ||
Aliased { | ||
expr: expr, | ||
alias: alias, | ||
} | ||
} | ||
} | ||
|
||
pub struct FromEverywhere; | ||
|
||
impl<'a, T> Expression for Aliased<'a, T> where T: Expression { | ||
type SqlType = T::SqlType; | ||
|
||
fn to_sql(&self, out: &mut QueryBuilder) -> BuildQueryResult { | ||
out.push_identifier(&self.alias) | ||
} | ||
} | ||
|
||
// FIXME This is incorrect, should only be selectable from WithQuerySource | ||
impl<'a, T, QS> SelectableExpression<QS> for Aliased<'a, T> where | ||
Aliased<'a, T>: Expression, | ||
{ | ||
} | ||
|
||
impl<'a, T: Expression> QuerySource for Aliased<'a, T> { | ||
fn from_clause(&self, out: &mut QueryBuilder) -> BuildQueryResult { | ||
try!(self.expr.to_sql(out)); | ||
out.push_sql(" "); | ||
out.push_identifier(&self.alias) | ||
} | ||
} | ||
|
||
impl<'a, T> NonAggregate for Aliased<'a, T> where Aliased<'a, T>: Expression { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
#[macro_use] | ||
pub mod ops; | ||
|
||
pub mod aliased; | ||
pub mod array_comparison; | ||
pub mod bound; | ||
pub mod count; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
use expression::Expression; | ||
use expression::aliased::Aliased; | ||
use query_builder::*; | ||
use query_source::QuerySource; | ||
|
||
pub trait WithDsl<'a, Expr> { | ||
type Output: AsQuery; | ||
|
||
fn with(self, expr: Aliased<'a, Expr>) -> Self::Output; | ||
} | ||
|
||
impl<'a, T, Expr> WithDsl<'a, Expr> for T where | ||
T: QuerySource + AsQuery, | ||
T::Query: WithDsl<'a, Expr> | ||
{ | ||
type Output = <T::Query as WithDsl<'a, Expr>>::Output; | ||
|
||
fn with(self, expr: Aliased<'a, Expr>) -> Self::Output { | ||
self.as_query().with(expr) | ||
} | ||
} | ||
|
||
pub struct WithQuerySource<'a, Left, Right> { | ||
left: Left, | ||
right: Aliased<'a, Right>, | ||
} | ||
|
||
impl<'a, Left, Right> WithQuerySource<'a, Left, Right> { | ||
pub fn new(left: Left, right: Aliased<'a, Right>) -> Self { | ||
WithQuerySource { | ||
left: left, | ||
right: right, | ||
} | ||
} | ||
} | ||
|
||
impl<'a, Left, Right> QuerySource for WithQuerySource<'a, Left, Right> where | ||
Left: QuerySource, | ||
Aliased<'a, Right>: QuerySource + Expression, | ||
{ | ||
fn from_clause(&self, out: &mut QueryBuilder) -> BuildQueryResult { | ||
try!(self.left.from_clause(out)); | ||
out.push_sql(", "); | ||
self.right.from_clause(out) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters