Add select APIs
This commit is contained in:
parent
5667eb06e9
commit
dde85d83bd
@ -104,22 +104,12 @@ async fn count_fruits_by_cake(db: &Database) -> Result<(), QueryErr> {
|
|||||||
|
|
||||||
print!("count fruits by cake: ");
|
print!("count fruits by cake: ");
|
||||||
|
|
||||||
let mut select = cake::Entity::find().left_join(cake::Relation::Fruit);
|
let select = cake::Entity::find()
|
||||||
{
|
.left_join(cake::Relation::Fruit)
|
||||||
use sea_orm::sea_query::*;
|
.clear_selects()
|
||||||
type Cake = cake::Column;
|
.column(cake::Column::Name)
|
||||||
type Fruit = fruit::Column;
|
.expr_as(fruit::Column::Id.count(), "num_of_fruits")
|
||||||
|
.group_by(cake::Column::Name);
|
||||||
select
|
|
||||||
.query()
|
|
||||||
.clear_selects()
|
|
||||||
.column((cake::Entity, Cake::Name))
|
|
||||||
.expr_as(
|
|
||||||
Expr::tbl(fruit::Entity, Fruit::Id).count(),
|
|
||||||
Alias::new("num_of_fruits"),
|
|
||||||
)
|
|
||||||
.group_by_col((cake::Entity, Cake::Name));
|
|
||||||
}
|
|
||||||
|
|
||||||
let results = select.into_model::<SelectResult>().all(db).await?;
|
let results = select.into_model::<SelectResult>().all(db).await?;
|
||||||
|
|
||||||
|
@ -15,6 +15,27 @@ macro_rules! bind_oper {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! bind_agg_func {
|
||||||
|
( $func: ident ) => {
|
||||||
|
fn $func(&self) -> SimpleExpr {
|
||||||
|
Expr::tbl(self.entity_name(), *self).$func()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! bind_vec_func {
|
||||||
|
( $func: ident ) => {
|
||||||
|
#[allow(clippy::wrong_self_convention)]
|
||||||
|
fn $func<V, I>(&self, v: I) -> SimpleExpr
|
||||||
|
where
|
||||||
|
V: Into<Value>,
|
||||||
|
I: IntoIterator<Item = V>,
|
||||||
|
{
|
||||||
|
Expr::tbl(self.entity_name(), *self).$func(v)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub trait ColumnTrait: IdenStatic {
|
pub trait ColumnTrait: IdenStatic {
|
||||||
type EntityName: EntityName;
|
type EntityName: EntityName;
|
||||||
|
|
||||||
@ -24,6 +45,10 @@ pub trait ColumnTrait: IdenStatic {
|
|||||||
Rc::new(Self::EntityName::default()) as Rc<dyn Iden>
|
Rc::new(Self::EntityName::default()) as Rc<dyn Iden>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_column_ref(&self) -> (Rc<dyn Iden>, Rc<dyn Iden>) {
|
||||||
|
(self.entity_name(), Rc::new(*self) as Rc<dyn Iden>)
|
||||||
|
}
|
||||||
|
|
||||||
bind_oper!(eq);
|
bind_oper!(eq);
|
||||||
bind_oper!(ne);
|
bind_oper!(ne);
|
||||||
bind_oper!(gt);
|
bind_oper!(gt);
|
||||||
@ -144,4 +169,19 @@ pub trait ColumnTrait: IdenStatic {
|
|||||||
let pattern = format!("%{}%", s);
|
let pattern = format!("%{}%", s);
|
||||||
Expr::tbl(self.entity_name(), *self).like(&pattern)
|
Expr::tbl(self.entity_name(), *self).like(&pattern)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
bind_agg_func!(max);
|
||||||
|
bind_agg_func!(min);
|
||||||
|
bind_agg_func!(sum);
|
||||||
|
bind_agg_func!(count);
|
||||||
|
|
||||||
|
fn if_null<V>(&self, v: V) -> SimpleExpr
|
||||||
|
where
|
||||||
|
V: Into<Value>,
|
||||||
|
{
|
||||||
|
Expr::tbl(self.entity_name(), *self).if_null(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
bind_vec_func!(is_in);
|
||||||
|
bind_vec_func!(is_not_in);
|
||||||
|
}
|
@ -1,11 +1,13 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
EntityTrait, Identity, Iterable, PrimaryKeyOfModel, Related, RelationDef, RelationTrait,
|
ColumnTrait, EntityTrait, Identity, Iterable, ModelTrait, PrimaryKeyOfModel, Related,
|
||||||
Statement,
|
RelationDef, RelationTrait, Statement,
|
||||||
};
|
};
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
pub use sea_query::JoinType;
|
pub use sea_query::JoinType;
|
||||||
use sea_query::{Expr, Iden, IntoIden, Order, QueryBuilder, SelectStatement, SimpleExpr};
|
use sea_query::{
|
||||||
|
Alias, Expr, Iden, IntoIden, Order, QueryBuilder, SelectExpr, SelectStatement, SimpleExpr,
|
||||||
|
};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -74,6 +76,72 @@ where
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clear_selects(mut self) -> Self {
|
||||||
|
self.query.clear_selects();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ```
|
||||||
|
/// use sea_orm::{ColumnTrait, EntityTrait, tests_cfg::cake, sea_query::PostgresQueryBuilder};
|
||||||
|
///
|
||||||
|
/// assert_eq!(
|
||||||
|
/// cake::Entity::find()
|
||||||
|
/// .clear_selects()
|
||||||
|
/// .column(cake::Column::Name)
|
||||||
|
/// .build(PostgresQueryBuilder)
|
||||||
|
/// .to_string(),
|
||||||
|
/// r#"SELECT "cake"."name" FROM "cake""#
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
|
pub fn column<C>(mut self, col: C) -> Self
|
||||||
|
where
|
||||||
|
C: ColumnTrait,
|
||||||
|
{
|
||||||
|
self.query.column(col.as_column_ref());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ```
|
||||||
|
/// use sea_orm::{ColumnTrait, EntityTrait, tests_cfg::cake, sea_query::PostgresQueryBuilder};
|
||||||
|
///
|
||||||
|
/// assert_eq!(
|
||||||
|
/// cake::Entity::find()
|
||||||
|
/// .clear_selects()
|
||||||
|
/// .column(cake::Column::Name)
|
||||||
|
/// .group_by(cake::Column::Name)
|
||||||
|
/// .build(PostgresQueryBuilder)
|
||||||
|
/// .to_string(),
|
||||||
|
/// r#"SELECT "cake"."name" FROM "cake" GROUP BY "cake"."name""#
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
|
pub fn group_by<C>(mut self, col: C) -> Self
|
||||||
|
where
|
||||||
|
C: ColumnTrait,
|
||||||
|
{
|
||||||
|
self.query.group_by_col(col.as_column_ref());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ```
|
||||||
|
/// use sea_orm::{ColumnTrait, EntityTrait, tests_cfg::cake, sea_query::PostgresQueryBuilder};
|
||||||
|
///
|
||||||
|
/// assert_eq!(
|
||||||
|
/// cake::Entity::find()
|
||||||
|
/// .clear_selects()
|
||||||
|
/// .expr_as(cake::Column::Id.count(), "count")
|
||||||
|
/// .build(PostgresQueryBuilder)
|
||||||
|
/// .to_string(),
|
||||||
|
/// r#"SELECT COUNT("cake"."id") AS "count" FROM "cake""#
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
|
pub fn expr_as(mut self, expr: SimpleExpr, alias: &str) -> Self {
|
||||||
|
self.query.expr(SelectExpr {
|
||||||
|
expr,
|
||||||
|
alias: Some(Rc::new(Alias::new(alias))),
|
||||||
|
});
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{ColumnTrait, EntityTrait, tests_cfg::cake, sea_query::MysqlQueryBuilder};
|
/// use sea_orm::{ColumnTrait, EntityTrait, tests_cfg::cake, sea_query::MysqlQueryBuilder};
|
||||||
///
|
///
|
||||||
@ -95,8 +163,6 @@ where
|
|||||||
R: EntityTrait + Related<E>,
|
R: EntityTrait + Related<E>,
|
||||||
R::PrimaryKey: PrimaryKeyOfModel<R::Model>,
|
R::PrimaryKey: PrimaryKeyOfModel<R::Model>,
|
||||||
{
|
{
|
||||||
use crate::{ColumnTrait, ModelTrait};
|
|
||||||
|
|
||||||
if let Some(key) = R::PrimaryKey::iter().next() {
|
if let Some(key) = R::PrimaryKey::iter().next() {
|
||||||
// TODO: supporting composite primary key
|
// TODO: supporting composite primary key
|
||||||
let col = key.into_column();
|
let col = key.into_column();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user