Refactored aliases
ci/woodpecker/push/ociImagePush Pipeline is running
Details
ci/woodpecker/push/ociImagePush Pipeline is running
Details
This commit is contained in:
parent
3b1eab8069
commit
a658452138
|
@ -15,11 +15,10 @@ use chrono::Utc;
|
|||
use ext_calckey_model_migration::{Migrator, MigratorTrait};
|
||||
use futures_util::StreamExt;
|
||||
use redis::IntoConnectionInfo;
|
||||
use sea_orm::sea_query::IntoIden;
|
||||
use sea_orm::ActiveValue::Set;
|
||||
use sea_orm::{
|
||||
ColumnTrait, ConnectOptions, DatabaseConnection, DbErr, EntityTrait, QueryFilter, RelationDef,
|
||||
RelationTrait, TransactionTrait,
|
||||
ColumnTrait, ConnectOptions, DatabaseConnection, DbErr, EntityTrait, QueryFilter,
|
||||
TransactionTrait,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::future::Future;
|
||||
|
@ -44,18 +43,6 @@ pub enum CalckeyDbError {
|
|||
DbError(#[from] DbErr),
|
||||
}
|
||||
|
||||
trait AliasSourceExt {
|
||||
fn with_alias<I: IntoIden>(&self, alias: I) -> RelationDef;
|
||||
}
|
||||
|
||||
impl<T: RelationTrait> AliasSourceExt for T {
|
||||
fn with_alias<I: IntoIden>(&self, alias: I) -> RelationDef {
|
||||
let mut def = self.def();
|
||||
def.from_tbl = def.from_tbl.alias(alias);
|
||||
def
|
||||
}
|
||||
}
|
||||
|
||||
impl CalckeyModel {
|
||||
pub async fn new(config: ConnectorConfig) -> Result<Self, CalckeyDbError> {
|
||||
let opt = ConnectOptions::new(config.url)
|
||||
|
|
|
@ -1,21 +1,70 @@
|
|||
use ext_calckey_model_migration::{Alias, Expr, IntoIden, SelectExpr, SelectStatement, TableRef};
|
||||
use sea_orm::{ColumnTrait, Condition, EntityTrait, Iden, Iterable, JoinType, RelationDef};
|
||||
use ext_calckey_model_migration::{
|
||||
Alias, Expr, IntoIden, Quote, SelectExpr, SelectStatement, TableRef,
|
||||
};
|
||||
use sea_orm::{
|
||||
ColumnTrait, Condition, DynIden, EntityTrait, Iden, Iterable, JoinType, RelationDef,
|
||||
RelationTrait,
|
||||
};
|
||||
use std::fmt::Write;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum MagIden {
|
||||
DynIden(DynIden),
|
||||
Alias(Alias),
|
||||
}
|
||||
|
||||
impl MagIden {
|
||||
pub fn alias(alias: &str) -> MagIden {
|
||||
Self::Alias(Alias::new(alias))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DynIden> for MagIden {
|
||||
fn from(value: DynIden) -> Self {
|
||||
Self::DynIden(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Iden for MagIden {
|
||||
fn prepare(&self, s: &mut dyn Write, q: Quote) {
|
||||
match self {
|
||||
MagIden::DynIden(di) => di.prepare(s, q),
|
||||
MagIden::Alias(a) => a.prepare(s, q),
|
||||
}
|
||||
}
|
||||
|
||||
fn quoted(&self, q: Quote) -> String {
|
||||
match self {
|
||||
MagIden::DynIden(di) => di.quoted(q),
|
||||
MagIden::Alias(a) => a.quoted(q),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_string(&self) -> String {
|
||||
match self {
|
||||
MagIden::DynIden(di) => di.to_string(),
|
||||
MagIden::Alias(a) => a.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn unquoted(&self, s: &mut dyn Write) {
|
||||
match self {
|
||||
MagIden::DynIden(di) => di.unquoted(s),
|
||||
MagIden::Alias(a) => a.unquoted(s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait SelectColumnsExt {
|
||||
fn add_aliased_columns<T: EntityTrait>(&mut self, alias: &str) -> &mut Self;
|
||||
fn add_aliased_columns<T: EntityTrait>(&mut self, alias: &MagIden) -> &mut Self;
|
||||
|
||||
fn join_columns<I: IntoIden>(
|
||||
fn join_columns(&mut self, join: JoinType, rel: RelationDef, alias: &MagIden) -> &mut Self;
|
||||
|
||||
fn join_columns_on(
|
||||
&mut self,
|
||||
join: JoinType,
|
||||
rel: RelationDef,
|
||||
alias: I,
|
||||
) -> &mut Self;
|
||||
|
||||
fn join_columns_on<I: IntoIden>(
|
||||
&mut self,
|
||||
join: JoinType,
|
||||
rel: RelationDef,
|
||||
alias: I,
|
||||
alias: &MagIden,
|
||||
condition: Condition,
|
||||
) -> &mut Self;
|
||||
}
|
||||
|
@ -41,17 +90,15 @@ pub(crate) fn join_columns_default(rel: RelationDef) -> Condition {
|
|||
}
|
||||
|
||||
impl SelectColumnsExt for SelectStatement {
|
||||
fn add_aliased_columns<T: EntityTrait>(&mut self, iden: &str) -> &mut Self {
|
||||
fn add_aliased_columns<T: EntityTrait>(&mut self, iden: &MagIden) -> &mut Self {
|
||||
for col in T::Column::iter() {
|
||||
let column: &T::Column = &col;
|
||||
|
||||
let alias = format!("{}{}", iden, col.to_string());
|
||||
|
||||
let column_ref = Expr::col((Alias::new(iden), column.as_column_ref().1));
|
||||
let alias = iden.join(&col);
|
||||
let column_ref = iden.col(column.as_column_ref().1);
|
||||
|
||||
self.expr(SelectExpr {
|
||||
expr: col.select_as(column_ref),
|
||||
alias: Some(Alias::new(&alias).into_iden()),
|
||||
alias: Some(alias.into_iden()),
|
||||
window: None,
|
||||
});
|
||||
}
|
||||
|
@ -59,48 +106,66 @@ impl SelectColumnsExt for SelectStatement {
|
|||
self
|
||||
}
|
||||
|
||||
fn join_columns<I: IntoIden>(
|
||||
&mut self,
|
||||
join: JoinType,
|
||||
mut rel: RelationDef,
|
||||
alias: I,
|
||||
) -> &mut Self {
|
||||
let alias = alias.into_iden();
|
||||
rel.to_tbl = rel.to_tbl.alias(alias);
|
||||
fn join_columns(&mut self, join: JoinType, mut rel: RelationDef, alias: &MagIden) -> &mut Self {
|
||||
rel.to_tbl = rel.to_tbl.alias(alias.clone().into_iden());
|
||||
self.join(join, rel.to_tbl.clone(), join_columns_default(rel));
|
||||
self
|
||||
}
|
||||
|
||||
fn join_columns_on<I: IntoIden>(
|
||||
fn join_columns_on(
|
||||
&mut self,
|
||||
join: JoinType,
|
||||
mut rel: RelationDef,
|
||||
alias: I,
|
||||
alias: &MagIden,
|
||||
condition: Condition,
|
||||
) -> &mut Self {
|
||||
let alias = alias.into_iden();
|
||||
rel.to_tbl = rel.to_tbl.alias(alias);
|
||||
rel.to_tbl = rel.to_tbl.alias(alias.clone().into_iden());
|
||||
self.join(join, rel.to_tbl.clone(), condition);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn joined_prefix_str(prefix: &str, suffix: &str) -> String {
|
||||
format!("{prefix}{suffix}")
|
||||
pub trait AliasColumnExt {
|
||||
fn col(&self, col: impl IntoIden) -> Expr;
|
||||
}
|
||||
|
||||
pub(crate) fn joined_prefix_alias(prefix: &str, suffix: &str) -> Alias {
|
||||
Alias::new(joined_prefix_str(prefix, suffix))
|
||||
impl<T: Iden + ?Sized> AliasColumnExt for T {
|
||||
fn col(&self, col: impl IntoIden) -> Expr {
|
||||
Expr::col((Alias::new(self.to_string()).into_iden(), col.into_iden()))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn joined_prefix(prefix: &str, suffix: &str) -> impl IntoIden {
|
||||
joined_prefix_alias(prefix, suffix).into_iden()
|
||||
pub trait AliasSuffixExt {
|
||||
fn join(&self, suffix: &dyn Iden) -> MagIden;
|
||||
|
||||
fn join_str(&self, suffix: &str) -> MagIden;
|
||||
|
||||
fn join_as_str(&self, suffix: &dyn Iden) -> String;
|
||||
|
||||
fn join_str_as_str(&self, suffix: &str) -> String;
|
||||
}
|
||||
|
||||
impl<T: Iden + ?Sized> AliasSuffixExt for T {
|
||||
fn join(&self, suffix: &dyn Iden) -> MagIden {
|
||||
MagIden::alias(&self.join_as_str(suffix))
|
||||
}
|
||||
|
||||
fn join_str(&self, suffix: &str) -> MagIden {
|
||||
MagIden::alias(&self.join_str_as_str(suffix))
|
||||
}
|
||||
|
||||
fn join_as_str(&self, suffix: &dyn Iden) -> String {
|
||||
format!("{}{}", self.to_string(), suffix.to_string())
|
||||
}
|
||||
|
||||
fn join_str_as_str(&self, suffix: &str) -> String {
|
||||
format!("{}{}", self.to_string(), suffix)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait EntityPrefixExt {
|
||||
fn base_prefix_str(&self) -> String;
|
||||
fn base_prefix_alias(&self) -> Alias;
|
||||
fn base_prefix(&self) -> impl IntoIden;
|
||||
fn base_prefix(&self) -> MagIden;
|
||||
}
|
||||
|
||||
impl<T: EntityTrait> EntityPrefixExt for T {
|
||||
|
@ -108,11 +173,28 @@ impl<T: EntityTrait> EntityPrefixExt for T {
|
|||
format!("{}.", self.table_name())
|
||||
}
|
||||
|
||||
fn base_prefix_alias(&self) -> Alias {
|
||||
Alias::new(self.base_prefix_str())
|
||||
}
|
||||
|
||||
fn base_prefix(&self) -> impl IntoIden {
|
||||
self.base_prefix_alias().into_iden()
|
||||
fn base_prefix(&self) -> MagIden {
|
||||
MagIden::alias(&self.base_prefix_str())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AliasSourceExt {
|
||||
fn with_from_alias(&self, alias: &MagIden) -> RelationDef;
|
||||
|
||||
fn with_alias(&self, from: &MagIden, to: &MagIden) -> RelationDef;
|
||||
}
|
||||
|
||||
impl<T: RelationTrait> AliasSourceExt for T {
|
||||
fn with_from_alias(&self, alias: &MagIden) -> RelationDef {
|
||||
let mut def = self.def();
|
||||
def.from_tbl = def.from_tbl.alias(Alias::new(alias.clone().to_string()));
|
||||
def
|
||||
}
|
||||
|
||||
fn with_alias(&self, from: &MagIden, to: &MagIden) -> RelationDef {
|
||||
let mut def = self.def();
|
||||
def.from_tbl = def.from_tbl.alias(from.clone().into_iden());
|
||||
def.to_tbl = def.to_tbl.alias(to.clone().into_iden());
|
||||
def
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
use crate::model_ext::{AliasSuffixExt, EntityPrefixExt, MagIden};
|
||||
use crate::note_model::{INTERACTION_REACTION, INTERACTION_RENOTE, RENOTE, REPLY, USER};
|
||||
use crate::user_model::UserData;
|
||||
use ck::note;
|
||||
use ext_calckey_model_migration::IntoIden;
|
||||
use sea_orm::sea_query::Alias;
|
||||
use sea_orm::Iden;
|
||||
use sea_orm::{DbErr, FromQueryResult, QueryResult};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub mod sub_interaction_renote {
|
||||
use sea_orm::{DeriveColumn, EnumIter, FromQueryResult};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, FromQueryResult, Serialize, Deserialize)]
|
||||
pub struct Model {
|
||||
pub renotes: Option<i64>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
||||
pub enum Column {
|
||||
Renotes,
|
||||
}
|
||||
}
|
||||
|
||||
pub mod sub_interaction_reaction {
|
||||
use sea_orm::{DeriveColumn, EnumIter, FromQueryResult};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, FromQueryResult, Serialize, Deserialize)]
|
||||
pub struct Model {
|
||||
pub reaction_name: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
||||
pub enum Column {
|
||||
ReactionName,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct NoteData {
|
||||
pub note: note::Model,
|
||||
pub interaction_user_renote: Option<sub_interaction_renote::Model>,
|
||||
pub interaction_user_reaction: Option<sub_interaction_reaction::Model>,
|
||||
pub user: UserData,
|
||||
pub reply: Option<Box<NoteData>>,
|
||||
pub renote: Option<Box<NoteData>>,
|
||||
}
|
||||
|
||||
impl FromQueryResult for NoteData {
|
||||
fn from_query_result(res: &QueryResult, prefix: &str) -> Result<Self, DbErr> {
|
||||
let prefix = if prefix.is_empty() {
|
||||
note::Entity.base_prefix()
|
||||
} else {
|
||||
MagIden::alias(&prefix)
|
||||
};
|
||||
|
||||
Ok(NoteData {
|
||||
note: note::Model::from_query_result(res, &prefix.to_string())?,
|
||||
interaction_user_renote: sub_interaction_renote::Model::from_query_result_optional(
|
||||
res,
|
||||
&prefix.join_str_as_str(INTERACTION_RENOTE),
|
||||
)?,
|
||||
interaction_user_reaction: sub_interaction_reaction::Model::from_query_result_optional(
|
||||
res,
|
||||
&prefix.join_str_as_str(INTERACTION_REACTION),
|
||||
)?,
|
||||
user: UserData::from_query_result(res, &prefix.join_str_as_str(USER))?,
|
||||
reply: NoteData::from_query_result_optional(res, &prefix.join_str_as_str(REPLY))?
|
||||
.map(Box::new),
|
||||
renote: NoteData::from_query_result_optional(res, &prefix.join_str_as_str(RENOTE))?
|
||||
.map(Box::new),
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,61 +1,23 @@
|
|||
pub mod data;
|
||||
|
||||
use ext_calckey_model_migration::SelectStatement;
|
||||
use sea_orm::sea_query::{Alias, Asterisk, Expr, IntoIden, Query, SelectExpr, SimpleExpr};
|
||||
use sea_orm::sea_query::{Asterisk, Expr, IntoIden, Query, SelectExpr, SimpleExpr};
|
||||
use sea_orm::{
|
||||
Condition, DbErr, EntityName, EntityTrait, FromQueryResult, Iden, JoinType, QueryFilter,
|
||||
QueryOrder, QueryResult, QuerySelect, QueryTrait, Select,
|
||||
Condition, CursorTrait, EntityName, EntityTrait, Iden, JoinType, QueryFilter, QueryOrder,
|
||||
QuerySelect, QueryTrait, Select,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use ck::{note, note_reaction, user, user_note_pining};
|
||||
use data::{sub_interaction_reaction, sub_interaction_renote, NoteData};
|
||||
use magnetar_sdk::types::SpanFilter;
|
||||
|
||||
use crate::model_ext::{
|
||||
join_columns_default, joined_prefix, joined_prefix_alias, joined_prefix_str, EntityPrefixExt,
|
||||
join_columns_default, AliasColumnExt, AliasSourceExt, AliasSuffixExt, EntityPrefixExt, MagIden,
|
||||
SelectColumnsExt,
|
||||
};
|
||||
use crate::paginated::PaginatedModel;
|
||||
use crate::user_model::{UserData, UserResolver};
|
||||
use crate::{AliasSourceExt, CalckeyDbError, CalckeyModel};
|
||||
|
||||
pub mod sub_interaction_renote {
|
||||
use sea_orm::{DeriveColumn, EnumIter, FromQueryResult};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, FromQueryResult, Serialize, Deserialize)]
|
||||
pub struct Model {
|
||||
pub renotes: Option<i64>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
||||
pub enum Column {
|
||||
Renotes,
|
||||
}
|
||||
}
|
||||
|
||||
pub mod sub_interaction_reaction {
|
||||
use sea_orm::{DeriveColumn, EnumIter, FromQueryResult};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, FromQueryResult, Serialize, Deserialize)]
|
||||
pub struct Model {
|
||||
pub reaction_name: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
||||
pub enum Column {
|
||||
ReactionName,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct NoteData {
|
||||
pub note: note::Model,
|
||||
pub interaction_user_renote: Option<sub_interaction_renote::Model>,
|
||||
pub interaction_user_reaction: Option<sub_interaction_reaction::Model>,
|
||||
pub user: UserData,
|
||||
pub reply: Option<Box<NoteData>>,
|
||||
pub renote: Option<Box<NoteData>>,
|
||||
}
|
||||
use crate::user_model::{UserResolveOptions, UserResolver};
|
||||
use crate::{CalckeyDbError, CalckeyModel};
|
||||
|
||||
const PIN: &str = "pin.";
|
||||
const INTERACTION_REACTION: &str = "interaction.reaction.";
|
||||
|
@ -64,37 +26,13 @@ const USER: &str = "user.";
|
|||
const REPLY: &str = "reply.";
|
||||
const RENOTE: &str = "renote.";
|
||||
|
||||
impl FromQueryResult for NoteData {
|
||||
fn from_query_result(res: &QueryResult, prefix: &str) -> Result<Self, DbErr> {
|
||||
let fallback = format!("{}.", note::Entity.table_name());
|
||||
let prefix = if prefix.is_empty() { &fallback } else { prefix };
|
||||
|
||||
Ok(NoteData {
|
||||
note: note::Model::from_query_result(res, prefix)?,
|
||||
interaction_user_renote: sub_interaction_renote::Model::from_query_result_optional(
|
||||
res,
|
||||
&joined_prefix_str(prefix, INTERACTION_RENOTE),
|
||||
)?,
|
||||
interaction_user_reaction: sub_interaction_reaction::Model::from_query_result_optional(
|
||||
res,
|
||||
&joined_prefix_str(prefix, INTERACTION_REACTION),
|
||||
)?,
|
||||
user: UserData::from_query_result(res, &joined_prefix_str(prefix, USER))?,
|
||||
reply: NoteData::from_query_result_optional(res, &joined_prefix_str(prefix, REPLY))?
|
||||
.map(Box::new),
|
||||
renote: NoteData::from_query_result_optional(res, &joined_prefix_str(prefix, RENOTE))?
|
||||
.map(Box::new),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NoteResolver {
|
||||
db: CalckeyModel,
|
||||
user_resolver: UserResolver,
|
||||
}
|
||||
|
||||
pub trait NoteVisibilityFilterFactory: Send + Sync {
|
||||
fn with_note_and_user_tables(&self, note: Option<Alias>) -> SimpleExpr;
|
||||
fn with_note_and_user_tables(&self, note: &dyn Iden) -> SimpleExpr;
|
||||
}
|
||||
|
||||
pub struct NoteResolveOptions {
|
||||
|
@ -102,45 +40,39 @@ pub struct NoteResolveOptions {
|
|||
pub visibility_filter: Box<dyn NoteVisibilityFilterFactory>,
|
||||
pub time_range: Option<SpanFilter>,
|
||||
pub limit: Option<u64>,
|
||||
pub with_user: bool,
|
||||
pub with_reply_target: bool,
|
||||
pub with_renote_target: bool,
|
||||
pub with_interactions_from: Option<String>, // User ID
|
||||
pub only_pins_from: Option<String>, // User ID
|
||||
pub user_options: UserResolveOptions,
|
||||
}
|
||||
|
||||
trait SelectNoteInteractionsExt {
|
||||
fn add_sub_select_interaction_reaction(
|
||||
&mut self,
|
||||
source_note_alias: &str,
|
||||
alias: &str,
|
||||
note_tbl: &MagIden,
|
||||
user_id: &str,
|
||||
) -> &mut Self;
|
||||
|
||||
fn add_sub_select_interaction_renote(
|
||||
&mut self,
|
||||
source_note_alias: &str,
|
||||
alias: &str,
|
||||
user_id: &str,
|
||||
) -> &mut Self;
|
||||
fn add_sub_select_interaction_renote(&mut self, note_tbl: &MagIden, user_id: &str)
|
||||
-> &mut Self;
|
||||
}
|
||||
|
||||
impl SelectNoteInteractionsExt for SelectStatement {
|
||||
fn add_sub_select_interaction_reaction(
|
||||
&mut self,
|
||||
iden: &str,
|
||||
prefix_alias: &str,
|
||||
note_tbl: &MagIden,
|
||||
user_id: &str,
|
||||
) -> &mut Self {
|
||||
let note_id_col = Expr::col((Alias::new(iden), note::Column::Id));
|
||||
|
||||
let column = sub_interaction_reaction::Column::ReactionName;
|
||||
let alias = format!("{}{}", prefix_alias, column.to_string());
|
||||
let note_id_col = note_tbl.col(note::Column::Id);
|
||||
let alias = note_tbl
|
||||
.join_str(INTERACTION_REACTION)
|
||||
.join(&sub_interaction_reaction::Column::ReactionName);
|
||||
|
||||
let sub_query = Query::select()
|
||||
.expr(SelectExpr {
|
||||
expr: Expr::col(note_reaction::Column::Reaction).into(),
|
||||
alias: Some(Alias::new(alias).into_iden()),
|
||||
alias: Some(alias.into_iden()),
|
||||
window: None,
|
||||
})
|
||||
.from(note_reaction::Entity)
|
||||
|
@ -155,28 +87,26 @@ impl SelectNoteInteractionsExt for SelectStatement {
|
|||
|
||||
fn add_sub_select_interaction_renote(
|
||||
&mut self,
|
||||
iden: &str,
|
||||
prefix_alias: &str,
|
||||
note_tbl: &MagIden,
|
||||
user_id: &str,
|
||||
) -> &mut Self {
|
||||
let note_id_col = Expr::col((Alias::new(iden), note::Column::Id));
|
||||
|
||||
let renote_note_tbl = joined_prefix_alias(prefix_alias, "note");
|
||||
|
||||
let column = sub_interaction_renote::Column::Renotes;
|
||||
let alias = format!("{}{}", prefix_alias, column.to_string());
|
||||
let interaction_tbl_prefix = note_tbl.join_str(INTERACTION_RENOTE);
|
||||
let renote_note_tbl = interaction_tbl_prefix.join_str("note");
|
||||
let alias = interaction_tbl_prefix.join(&sub_interaction_renote::Column::Renotes);
|
||||
|
||||
let sub_query = Query::select()
|
||||
.expr(SelectExpr {
|
||||
expr: Expr::count(Expr::col(Asterisk)),
|
||||
alias: Some(Alias::new(alias).into_iden()),
|
||||
alias: Some(alias.into_iden()),
|
||||
window: None,
|
||||
})
|
||||
.from_as(note::Entity, renote_note_tbl.clone())
|
||||
.from_as(note::Entity, renote_note_tbl.clone().into_iden())
|
||||
.cond_where(
|
||||
Expr::col((renote_note_tbl.clone(), note::Column::RenoteId)).eq(note_id_col),
|
||||
renote_note_tbl
|
||||
.col(note::Column::RenoteId)
|
||||
.eq(note_tbl.col(note::Column::Id)),
|
||||
)
|
||||
.and_where(Expr::col((renote_note_tbl.clone(), note::Column::UserId)).eq(user_id))
|
||||
.and_where(renote_note_tbl.col(note::Column::UserId).eq(user_id))
|
||||
.take()
|
||||
.into_sub_query_statement();
|
||||
|
||||
|
@ -186,7 +116,7 @@ impl SelectNoteInteractionsExt for SelectStatement {
|
|||
}
|
||||
|
||||
fn ids_into_expr(ids: &Vec<String>) -> SimpleExpr {
|
||||
let id_col = Expr::col((note::Entity.base_prefix(), note::Column::Id));
|
||||
let id_col = note::Entity.base_prefix().col(note::Column::Id);
|
||||
|
||||
if ids.len() == 1 {
|
||||
id_col.eq(&ids[0])
|
||||
|
@ -207,11 +137,11 @@ impl NoteResolver {
|
|||
let select = self.resolve(options);
|
||||
let visibility_filter = options
|
||||
.visibility_filter
|
||||
.with_note_and_user_tables(Some(note::Entity.base_prefix_alias()));
|
||||
.with_note_and_user_tables(¬e::Entity.base_prefix());
|
||||
let time_filter = options
|
||||
.time_range
|
||||
.as_ref()
|
||||
.and_then(note::Model::range_into_expr);
|
||||
.and_then(note::Entity::range_into_expr);
|
||||
let id_filter = options.ids.as_ref().map(ids_into_expr);
|
||||
|
||||
let notes = select
|
||||
|
@ -232,11 +162,11 @@ impl NoteResolver {
|
|||
let select = self.resolve(options);
|
||||
let visibility_filter = options
|
||||
.visibility_filter
|
||||
.with_note_and_user_tables(Some(note::Entity.base_prefix_alias()));
|
||||
.with_note_and_user_tables(¬e::Entity.base_prefix());
|
||||
let time_filter = options
|
||||
.time_range
|
||||
.as_ref()
|
||||
.and_then(note::Model::range_into_expr);
|
||||
.and_then(note::Entity::range_into_expr);
|
||||
let id_filter = options.ids.as_ref().map(ids_into_expr);
|
||||
|
||||
let notes = select
|
||||
|
@ -245,7 +175,7 @@ impl NoteResolver {
|
|||
.apply_if(time_filter, Select::<note::Entity>::filter)
|
||||
.apply_if(options.only_pins_from.as_deref(), |s, _| {
|
||||
s.order_by_desc(Expr::col((
|
||||
joined_prefix(¬e::Entity.base_prefix_str(), PIN),
|
||||
note::Entity.base_prefix().into_iden().join_str(PIN),
|
||||
user_note_pining::Column::CreatedAt,
|
||||
)))
|
||||
})
|
||||
|
@ -257,59 +187,70 @@ impl NoteResolver {
|
|||
Ok(notes)
|
||||
}
|
||||
|
||||
/*
|
||||
pub async fn get_children(&self, options: &NoteResolveOptions) -> Select<note::Entity> {
|
||||
let max_breadth: usize = 10;
|
||||
|
||||
let nth_child = Alias::new("nth_child");
|
||||
|
||||
let mut select = Query::select();
|
||||
select.distinct();
|
||||
select.columns([Alias::new("id")]);
|
||||
select.from(cte);
|
||||
select.and_where(Expr::col(nth_child).lt(max_breadth))
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
fn attach_note(
|
||||
&self,
|
||||
q: &mut SelectStatement,
|
||||
prefix: &str,
|
||||
note_tbl: &MagIden,
|
||||
reply_depth: usize,
|
||||
renote_depth: usize,
|
||||
options: &NoteResolveOptions,
|
||||
user_resolver: &UserResolver,
|
||||
) {
|
||||
q.add_aliased_columns::<note::Entity>(prefix);
|
||||
q.add_aliased_columns::<note::Entity>(note_tbl);
|
||||
|
||||
// Add the note's author
|
||||
q.add_aliased_columns::<user::Entity>(&joined_prefix_str(prefix, USER));
|
||||
let user_tbl = note_tbl.join_str(USER);
|
||||
q.add_aliased_columns::<user::Entity>(&user_tbl);
|
||||
q.join_columns(
|
||||
JoinType::LeftJoin,
|
||||
note::Relation::User.with_alias(Alias::new(prefix).into_iden()),
|
||||
joined_prefix(prefix, USER),
|
||||
note::Relation::User.with_from_alias(note_tbl),
|
||||
&user_tbl,
|
||||
);
|
||||
|
||||
// user_resolver.resolve(q, &user_tbl, &options.user_options);
|
||||
|
||||
// Interactions like renotes or reactions from the specified user
|
||||
if let Some(user_id) = &options.with_interactions_from {
|
||||
q.add_sub_select_interaction_reaction(
|
||||
prefix,
|
||||
&joined_prefix_str(prefix, INTERACTION_REACTION),
|
||||
user_id,
|
||||
);
|
||||
q.add_sub_select_interaction_renote(
|
||||
prefix,
|
||||
&joined_prefix_str(prefix, INTERACTION_RENOTE),
|
||||
user_id,
|
||||
);
|
||||
q.add_sub_select_interaction_reaction(note_tbl, user_id);
|
||||
q.add_sub_select_interaction_renote(note_tbl, user_id);
|
||||
}
|
||||
|
||||
// Recursively attach reply parents
|
||||
if reply_depth > 0 {
|
||||
let reply_tbl = note_tbl.join_str(REPLY);
|
||||
let visibility_filter = options
|
||||
.visibility_filter
|
||||
.with_note_and_user_tables(Some(joined_prefix_alias(prefix, REPLY)));
|
||||
let mut rel = note::Relation::SelfRef2.with_alias(Alias::new(prefix).into_iden());
|
||||
rel.to_tbl = rel.to_tbl.alias(joined_prefix_alias(prefix, REPLY));
|
||||
.with_note_and_user_tables(&reply_tbl);
|
||||
let condition = Condition::all()
|
||||
.add(join_columns_default(rel))
|
||||
.add(join_columns_default(
|
||||
note::Relation::SelfRef2.with_alias(note_tbl, &reply_tbl),
|
||||
))
|
||||
.add(visibility_filter);
|
||||
q.join_columns_on(
|
||||
JoinType::LeftJoin,
|
||||
note::Relation::SelfRef2.with_alias(Alias::new(prefix).into_iden()),
|
||||
joined_prefix(prefix, REPLY),
|
||||
note::Relation::SelfRef2.with_from_alias(note_tbl),
|
||||
&reply_tbl,
|
||||
condition,
|
||||
);
|
||||
|
||||
self.attach_note(
|
||||
q,
|
||||
&joined_prefix_str(prefix, REPLY),
|
||||
&reply_tbl,
|
||||
reply_depth - 1,
|
||||
renote_depth,
|
||||
options,
|
||||
|
@ -319,24 +260,25 @@ impl NoteResolver {
|
|||
|
||||
// Recursively attach renote/quote targets
|
||||
if renote_depth > 0 {
|
||||
let renote_tbl = note_tbl.join_str(RENOTE);
|
||||
let visibility_filter = options
|
||||
.visibility_filter
|
||||
.with_note_and_user_tables(Some(joined_prefix_alias(prefix, RENOTE)));
|
||||
let mut rel = note::Relation::SelfRef1.with_alias(Alias::new(prefix).into_iden());
|
||||
rel.to_tbl = rel.to_tbl.alias(joined_prefix_alias(prefix, RENOTE));
|
||||
.with_note_and_user_tables(&renote_tbl);
|
||||
let condition = Condition::all()
|
||||
.add(join_columns_default(rel))
|
||||
.add(join_columns_default(
|
||||
note::Relation::SelfRef1.with_alias(note_tbl, &renote_tbl),
|
||||
))
|
||||
.add(visibility_filter);
|
||||
q.join_columns_on(
|
||||
JoinType::LeftJoin,
|
||||
note::Relation::SelfRef1.with_alias(Alias::new(prefix).into_iden()),
|
||||
joined_prefix(prefix, RENOTE),
|
||||
note::Relation::SelfRef1.with_from_alias(note_tbl),
|
||||
&renote_tbl,
|
||||
condition,
|
||||
);
|
||||
|
||||
self.attach_note(
|
||||
q,
|
||||
&joined_prefix_str(prefix, RENOTE),
|
||||
&renote_tbl,
|
||||
reply_depth,
|
||||
renote_depth - 1,
|
||||
options,
|
||||
|
@ -346,30 +288,24 @@ impl NoteResolver {
|
|||
}
|
||||
|
||||
pub fn resolve(&self, options: &NoteResolveOptions) -> Select<note::Entity> {
|
||||
let prefix = note::Entity.base_prefix_str();
|
||||
let note_tbl = note::Entity.base_prefix();
|
||||
|
||||
let mut select = Query::select();
|
||||
select.from_as(note::Entity, Alias::new(&prefix));
|
||||
select.from_as(note::Entity, note_tbl.clone().into_iden());
|
||||
|
||||
if let Some(pins_user) = &options.only_pins_from {
|
||||
select
|
||||
.join_columns(
|
||||
JoinType::InnerJoin,
|
||||
note::Relation::UserNotePining.with_alias(Alias::new(&prefix)),
|
||||
joined_prefix(&prefix, PIN),
|
||||
note::Relation::UserNotePining.with_from_alias(¬e_tbl),
|
||||
¬e_tbl.join_str(PIN),
|
||||
)
|
||||
.and_where(
|
||||
Expr::col((
|
||||
joined_prefix(&prefix, PIN),
|
||||
user_note_pining::Column::UserId,
|
||||
))
|
||||
.eq(pins_user),
|
||||
);
|
||||
.and_where(note_tbl.col(user_note_pining::Column::UserId).eq(pins_user));
|
||||
}
|
||||
|
||||
self.attach_note(
|
||||
&mut select,
|
||||
&prefix,
|
||||
¬e_tbl,
|
||||
options.with_reply_target.then_some(1).unwrap_or_default(),
|
||||
options.with_renote_target.then_some(1).unwrap_or_default(),
|
||||
options,
|
|
@ -54,7 +54,7 @@ pub trait PaginatedModel: 'static {
|
|||
}
|
||||
}
|
||||
|
||||
impl PaginatedModel for ck::note::Model {
|
||||
impl PaginatedModel for ck::note::Entity {
|
||||
fn time_column() -> impl Iden {
|
||||
ck::note::Column::CreatedAt
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ impl PaginatedModel for ck::note::Model {
|
|||
}
|
||||
}
|
||||
|
||||
impl PaginatedModel for ck::user::Model {
|
||||
impl PaginatedModel for ck::user::Entity {
|
||||
fn time_column() -> impl Iden {
|
||||
ck::user::Column::CreatedAt
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ impl PaginatedModel for ck::user::Model {
|
|||
}
|
||||
}
|
||||
|
||||
impl PaginatedModel for ck::following::Model {
|
||||
impl PaginatedModel for ck::following::Entity {
|
||||
fn time_column() -> impl Iden {
|
||||
ck::following::Column::CreatedAt
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ impl PaginatedModel for ck::following::Model {
|
|||
}
|
||||
}
|
||||
|
||||
impl PaginatedModel for ck::follow_request::Model {
|
||||
impl PaginatedModel for ck::follow_request::Entity {
|
||||
fn time_column() -> impl Iden {
|
||||
ck::follow_request::Column::CreatedAt
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
use crate::model_ext::EntityPrefixExt;
|
||||
use crate::{
|
||||
model_ext::{joined_prefix, joined_prefix_str, SelectColumnsExt},
|
||||
AliasSourceExt, CalckeyModel,
|
||||
};
|
||||
use ck::{drive_file, follow_request, following, user};
|
||||
use ext_calckey_model_migration::{Alias, SelectStatement};
|
||||
use sea_orm::{DbErr, FromQueryResult, JoinType, QueryResult};
|
||||
use crate::model_ext::{AliasSourceExt, AliasSuffixExt, EntityPrefixExt, MagIden};
|
||||
use crate::{model_ext::SelectColumnsExt, CalckeyModel};
|
||||
use ck::{drive_file, user};
|
||||
use ext_calckey_model_migration::{IntoIden, SelectStatement};
|
||||
use sea_orm::sea_query::Alias;
|
||||
use sea_orm::{DbErr, FromQueryResult, Iden, JoinType, QueryResult};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
|
@ -24,18 +22,21 @@ const BANNER: &str = "banner.";
|
|||
|
||||
impl FromQueryResult for UserData {
|
||||
fn from_query_result(res: &QueryResult, prefix: &str) -> Result<Self, DbErr> {
|
||||
let fallback = user::Entity.base_prefix_str();
|
||||
let prefix = if prefix.is_empty() { &fallback } else { prefix };
|
||||
let prefix = if prefix.is_empty() {
|
||||
user::Entity.base_prefix()
|
||||
} else {
|
||||
MagIden::alias(prefix)
|
||||
};
|
||||
|
||||
Ok(UserData {
|
||||
user: user::Model::from_query_result(res, prefix)?,
|
||||
user: user::Model::from_query_result(res, &prefix.to_string())?,
|
||||
avatar: drive_file::Model::from_query_result_optional(
|
||||
res,
|
||||
&joined_prefix_str(prefix, AVATAR),
|
||||
&prefix.join_str_as_str(AVATAR),
|
||||
)?,
|
||||
banner: drive_file::Model::from_query_result_optional(
|
||||
res,
|
||||
&joined_prefix_str(prefix, BANNER),
|
||||
&prefix.join_str_as_str(BANNER),
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
@ -53,26 +54,29 @@ impl UserResolver {
|
|||
pub fn resolve(
|
||||
&self,
|
||||
q: &mut SelectStatement,
|
||||
prefix: &str,
|
||||
user_tbl: &MagIden,
|
||||
UserResolveOptions {
|
||||
with_avatar_and_banner,
|
||||
}: &UserResolveOptions,
|
||||
) {
|
||||
q.add_aliased_columns::<user::Entity>(prefix);
|
||||
q.add_aliased_columns::<user::Entity>(user_tbl);
|
||||
|
||||
if *with_avatar_and_banner {
|
||||
q.add_aliased_columns::<drive_file::Entity>(&joined_prefix_str(prefix, AVATAR))
|
||||
.add_aliased_columns::<drive_file::Entity>(&joined_prefix_str(prefix, BANNER));
|
||||
let avatar_tbl = user_tbl.join_str(AVATAR);
|
||||
let banner_tbl = user_tbl.join_str(BANNER);
|
||||
|
||||
q.add_aliased_columns::<drive_file::Entity>(&avatar_tbl)
|
||||
.add_aliased_columns::<drive_file::Entity>(&banner_tbl);
|
||||
|
||||
q.join_columns(
|
||||
JoinType::LeftJoin,
|
||||
user::Relation::DriveFile2.with_alias(Alias::new(prefix)),
|
||||
joined_prefix(prefix, AVATAR),
|
||||
user::Relation::DriveFile2.with_from_alias(user_tbl),
|
||||
&avatar_tbl,
|
||||
)
|
||||
.join_columns(
|
||||
JoinType::LeftJoin,
|
||||
user::Relation::DriveFile1.with_alias(Alias::new(prefix)),
|
||||
joined_prefix(prefix, BANNER),
|
||||
user::Relation::DriveFile1.with_from_alias(user_tbl),
|
||||
&banner_tbl,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use magnetar_calckey_model::ck;
|
||||
use magnetar_calckey_model::note_model::sub_interaction_renote;
|
||||
use magnetar_calckey_model::note_model::data::sub_interaction_renote;
|
||||
use magnetar_sdk::types::note::{
|
||||
NoteDetailExt, NoteSelfContextExt, PackNoteMaybeAttachments, PackNoteMaybeFull, PackPollBase,
|
||||
ReactionPair,
|
||||
NoteDetailExt, NoteSelfContextExt, PackNoteMaybeFull, PackPollBase, ReactionPair,
|
||||
};
|
||||
use magnetar_sdk::types::user::PackUserBase;
|
||||
use magnetar_sdk::types::{
|
||||
|
|
|
@ -12,14 +12,15 @@ use futures_util::future::{try_join_all, BoxFuture};
|
|||
use futures_util::{FutureExt, StreamExt, TryFutureExt, TryStreamExt};
|
||||
use magnetar_calckey_model::ck::sea_orm_active_enums::NoteVisibilityEnum;
|
||||
use magnetar_calckey_model::emoji::EmojiTag;
|
||||
use magnetar_calckey_model::note_model::{
|
||||
sub_interaction_reaction, sub_interaction_renote, NoteData, NoteResolveOptions,
|
||||
NoteVisibilityFilterFactory,
|
||||
use magnetar_calckey_model::model_ext::AliasColumnExt;
|
||||
use magnetar_calckey_model::note_model::data::{
|
||||
sub_interaction_reaction, sub_interaction_renote, NoteData,
|
||||
};
|
||||
use magnetar_calckey_model::note_model::{NoteResolveOptions, NoteVisibilityFilterFactory};
|
||||
use magnetar_calckey_model::poll::PollResolver;
|
||||
use magnetar_calckey_model::sea_orm::prelude::Expr;
|
||||
use magnetar_calckey_model::sea_orm::sea_query::{Alias, IntoIden, PgFunc, Query, SimpleExpr};
|
||||
use magnetar_calckey_model::sea_orm::{ActiveEnum, ColumnTrait, IntoSimpleExpr};
|
||||
use magnetar_calckey_model::sea_orm::sea_query::{IntoIden, PgFunc, Query, SimpleExpr};
|
||||
use magnetar_calckey_model::sea_orm::{ActiveEnum, ColumnTrait, Iden, IntoSimpleExpr};
|
||||
use magnetar_calckey_model::user_model::UserResolveOptions;
|
||||
use magnetar_calckey_model::{ck, CalckeyDbError};
|
||||
use magnetar_common::util::{parse_reaction, RawReaction};
|
||||
use magnetar_sdk::mmm::Token;
|
||||
|
@ -43,22 +44,12 @@ use super::user::UserShapedData;
|
|||
pub struct NoteVisibilityFilterSimple(Option<String>);
|
||||
|
||||
impl NoteVisibilityFilterFactory for NoteVisibilityFilterSimple {
|
||||
fn with_note_and_user_tables(&self, note_tbl: Option<Alias>) -> SimpleExpr {
|
||||
let note_tbl_name =
|
||||
note_tbl.map_or_else(|| ck::note::Entity.into_iden(), |a| a.into_iden());
|
||||
|
||||
let note_visibility = Expr::col((note_tbl_name.clone(), ck::note::Column::Visibility));
|
||||
let note_mentions = Expr::col((note_tbl_name.clone(), ck::note::Column::Mentions));
|
||||
let note_reply_user_id = Expr::col((note_tbl_name.clone(), ck::note::Column::ReplyUserId));
|
||||
let note_visible_user_ids =
|
||||
Expr::col((note_tbl_name.clone(), ck::note::Column::VisibleUserIds));
|
||||
let note_user_id = Expr::col((note_tbl_name, ck::note::Column::UserId));
|
||||
|
||||
let is_public = note_visibility
|
||||
.clone()
|
||||
fn with_note_and_user_tables(&self, note_tbl: &dyn Iden) -> SimpleExpr {
|
||||
let is_public = note_tbl
|
||||
.col(ck::note::Column::Visibility)
|
||||
.eq(NoteVisibilityEnum::Public.as_enum())
|
||||
.or(note_visibility
|
||||
.clone()
|
||||
.or(note_tbl
|
||||
.col(ck::note::Column::Visibility)
|
||||
.eq(NoteVisibilityEnum::Home.as_enum()));
|
||||
|
||||
let Some(user_id_str) = &self.0 else {
|
||||
|
@ -67,30 +58,34 @@ impl NoteVisibilityFilterFactory for NoteVisibilityFilterSimple {
|
|||
|
||||
let self_user_id = SimpleExpr::Constant(user_id_str.into());
|
||||
|
||||
let is_self = note_user_id.clone().eq(self_user_id.clone());
|
||||
let is_self = note_tbl
|
||||
.col(ck::note::Column::UserId)
|
||||
.eq(self_user_id.clone());
|
||||
|
||||
let is_visible_specified = {
|
||||
let either_specified_or_followers = note_visibility
|
||||
.clone()
|
||||
let either_specified_or_followers = note_tbl
|
||||
.col(ck::note::Column::Visibility)
|
||||
.eq(NoteVisibilityEnum::Specified.as_enum())
|
||||
.or(note_visibility
|
||||
.clone()
|
||||
.eq(NoteVisibilityEnum::Followers.as_enum()))
|
||||
.into_simple_expr();
|
||||
.or(note_tbl
|
||||
.col(ck::note::Column::Visibility)
|
||||
.eq(NoteVisibilityEnum::Followers.as_enum()));
|
||||
|
||||
let mentioned_or_specified = self_user_id
|
||||
.clone()
|
||||
.eq(PgFunc::any(note_mentions.into_simple_expr()))
|
||||
.or(self_user_id.eq(PgFunc::any(note_visible_user_ids)));
|
||||
.eq(PgFunc::any(
|
||||
note_tbl.col(ck::note::Column::Mentions).into_simple_expr(),
|
||||
))
|
||||
.or(self_user_id.eq(PgFunc::any(note_tbl.col(ck::note::Column::VisibleUserIds))));
|
||||
|
||||
either_specified_or_followers.and(mentioned_or_specified)
|
||||
};
|
||||
|
||||
let is_visible_followers = {
|
||||
note_visibility
|
||||
note_tbl
|
||||
.col(ck::note::Column::Visibility)
|
||||
.eq(NoteVisibilityEnum::Followers.as_enum())
|
||||
.and(
|
||||
note_user_id.in_subquery(
|
||||
note_tbl.col(ck::note::Column::UserId).in_subquery(
|
||||
Query::select()
|
||||
.column(ck::following::Column::FolloweeId)
|
||||
.from(ck::following::Entity)
|
||||
|
@ -98,7 +93,7 @@ impl NoteVisibilityFilterFactory for NoteVisibilityFilterSimple {
|
|||
.to_owned(),
|
||||
),
|
||||
)
|
||||
.or(note_reply_user_id.eq(user_id_str))
|
||||
.or(note_tbl.col(ck::note::Column::ReplyUserId).eq(user_id_str))
|
||||
};
|
||||
|
||||
is_self
|
||||
|
@ -584,7 +579,9 @@ impl NoteModel {
|
|||
)),
|
||||
time_range: None,
|
||||
limit: None,
|
||||
with_user: self.with_context,
|
||||
user_options: UserResolveOptions {
|
||||
with_avatar_and_banner: self.with_context,
|
||||
},
|
||||
with_reply_target: self.with_context,
|
||||
with_renote_target: self.with_context,
|
||||
with_interactions_from: self
|
||||
|
@ -620,7 +617,9 @@ impl NoteModel {
|
|||
)),
|
||||
time_range: None,
|
||||
limit: None,
|
||||
with_user: self.with_context,
|
||||
user_options: UserResolveOptions {
|
||||
with_avatar_and_banner: self.with_context,
|
||||
},
|
||||
with_reply_target: self.with_context,
|
||||
with_renote_target: self.with_context,
|
||||
with_interactions_from: self
|
||||
|
|
Loading…
Reference in New Issue