1
0
Fork 0
mirror of https://github.com/Nutomic/ibis.git synced 2025-02-10 15:54:42 +00:00

join lateral

This commit is contained in:
Felix Ableitner 2025-01-24 15:12:40 +01:00
parent 18514e082c
commit 0ffbcb7471
6 changed files with 47 additions and 63 deletions

View file

@ -7,11 +7,16 @@ use crate::{
},
common::{
instance::{
DbInstance, FollowInstanceParams, GetInstanceParams, InstanceView, InstanceView2,
DbInstance,
FollowInstanceParams,
GetInstanceParams,
InstanceView,
InstanceView2,
UpdateInstanceParams,
},
user::LocalUserView,
ResolveObjectParams, SuccessResponse,
ResolveObjectParams,
SuccessResponse,
},
};
use activitypub_federation::{config::Data, fetch::object_id::ObjectId};

View file

@ -5,14 +5,14 @@ use crate::{
IbisContext,
},
federation::objects::{
articles_collection::DbArticleCollection, instance_collection::DbInstanceCollection,
articles_collection::DbArticleCollection,
instance_collection::DbInstanceCollection,
},
utils::error::MyResult,
},
common::{
article::DbArticle,
instance::{DbInstance, InstanceView, InstanceView2},
newtypes::{ArticleId, CommentId, InstanceId},
newtypes::{CommentId, InstanceId},
user::DbPerson,
},
};
@ -21,20 +21,9 @@ use activitypub_federation::{
fetch::{collection_id::CollectionId, object_id::ObjectId},
};
use chrono::{DateTime, Utc};
use diesel::{
associations::HasTable,
define_sql_function,
deserialize::{self, FromSql},
insert_into,
pg::{Pg, PgValue},
sql_types::Record,
update, AsChangeset, ExpressionMethods, Insertable, JoinOnDsl, NullableExpressionMethods,
QueryDsl, RunQueryDsl,
};
use diesel::*;
use std::{fmt::Debug, ops::DerefMut};
use super::array_agg;
#[derive(Debug, Clone, Insertable, AsChangeset)]
#[diesel(table_name = instance, check_for_backend(diesel::pg::Pg))]
pub struct DbInstanceForm {
@ -151,26 +140,28 @@ impl DbInstance {
pub fn list(context: &Data<IbisContext>) -> MyResult<Vec<InstanceView>> {
let mut conn = context.db_pool.get()?;
// select instance, array_agg(article) from instance left join article on instance.id=article.instance_id group by instance.id;
let res: Vec<_> = instance::table
.left_join(article::table.on(instance::id.eq(article::instance_id)))
.select((
instance::all_columns,
//array_agg(article::all_columns)
diesel::dsl::sql::<diesel::sql_types::Array<article::SqlType>>(
"array_agg(article.*)",
),
))
.group_by(instance::id)
// TODO: throws invalid trait bound
.get_results::<(DbInstance, Vec<DbArticle>)>(conn.deref_mut())?;
Ok(res
.into_iter()
.map(|x| InstanceView {
instance: x.0,
articles: x.1,
})
.collect())
let res: Vec<_> = sql_query(
"SELECT
instance,
array_agg(a) as articles
FROM
instance
CROSS JOIN LATERAL (
SELECT
title
FROM
article
WHERE
instance.id = article.instance_id
GROUP BY
article.id
LIMIT 5) a
GROUP BY
id;",
)
.select(InstanceView::as_select())
.get_results::<InstanceView>(conn.deref_mut())?;
Ok(res)
}
/// Read the instance where an article is hosted, based on a comment id.
@ -188,16 +179,3 @@ impl DbInstance {
.get_result(conn.deref_mut())?)
}
}
define_sql_function!(fn array_agg<T: diesel::sql_types::SingleValue>(expr: T) -> Array<T>);
// https://github.com/diesel-rs/diesel/discussions/3826
impl FromSql<diesel::sql_types::Record<article::SqlType>, Pg> for DbArticle {
fn from_sql(value: PgValue<'_>) -> deserialize::Result<Self> {
//let mut bytes = value.as_bytes();
//let res: (i32,) = FromSql::<Record<article::SqlType>, Pg>::from_sql(value)?;
//Ok(Label1 { id: res.0 })
todo!()
}
}

View file

@ -4,7 +4,9 @@ use crate::backend::{
};
use diesel::{
r2d2::{ConnectionManager, Pool},
PgConnection, QueryDsl, RunQueryDsl,
PgConnection,
QueryDsl,
RunQueryDsl,
};
use std::ops::DerefMut;

View file

@ -5,6 +5,7 @@ use super::{
user::DbPerson,
};
use chrono::{DateTime, Utc};
use diesel::QueryableByName;
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use uuid::Uuid;
@ -39,7 +40,7 @@ pub struct DbArticleView {
pub latest_version: EditVersion,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, QueryableByName)]
#[cfg_attr(feature = "ssr", derive(Queryable, Selectable, Identifiable))]
#[cfg_attr(feature = "ssr", diesel(table_name = article, check_for_backend(diesel::pg::Pg), belongs_to(DbInstance, foreign_key = instance_id)))]
pub struct DbArticle {

View file

@ -4,13 +4,15 @@ use super::{
user::{DbPerson, LocalUserView},
};
use chrono::{DateTime, Utc};
use diesel::QueryableByName;
use serde::{Deserialize, Serialize};
use smart_default::SmartDefault;
use url::Url;
#[cfg(feature = "ssr")]
use {
crate::backend::{
database::schema::instance, federation::objects::articles_collection::DbArticleCollection,
database::schema::instance,
federation::objects::articles_collection::DbArticleCollection,
federation::objects::instance_collection::DbInstanceCollection,
},
activitypub_federation::fetch::{collection_id::CollectionId, object_id::ObjectId},
@ -18,7 +20,7 @@ use {
doku::Document,
};
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, QueryableByName)]
#[cfg_attr(feature = "ssr", derive(Queryable, Selectable, Identifiable))]
#[cfg_attr(feature = "ssr", diesel(table_name = instance, check_for_backend(diesel::pg::Pg)))]
pub struct DbInstance {
@ -52,10 +54,12 @@ impl DbInstance {
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[cfg_attr(feature = "ssr", derive(Queryable))]
#[cfg_attr(feature = "ssr", diesel(table_name = article, check_for_backend(diesel::pg::Pg)))]
#[cfg_attr(feature = "ssr", derive(Queryable, QueryableByName))]
#[cfg_attr(feature = "ssr", diesel(check_for_backend(diesel::pg::Pg)))]
pub struct InstanceView {
#[diesel(embed)]
pub instance: DbInstance,
#[diesel(embed)]
pub articles: Vec<DbArticle>,
}

View file

@ -1,13 +1,7 @@
use super::{result_to_option, ApiClient};
use crate::common::{
article::{DbArticle, SearchArticleParams},
instance::{
DbInstance,
FollowInstanceParams,
InstanceView2,
SiteView,
UpdateInstanceParams,
},
instance::{DbInstance, FollowInstanceParams, InstanceView2, SiteView, UpdateInstanceParams},
Notification,
ResolveObjectParams,
SuccessResponse,