2024-11-18 18:55:21 +00:00
//! Tables related to web page metadata, XRD and JRD, `host-meta`, `WebFinger`, and so on.
//!
//! # Intended usage
//!
//! 1. An user agent requests an application for the descriptor for a given resource;
//! 2. **The application queries the database using these structures to:**
//! 1. [Determine if a descriptor should be returned, or if it should be handled by another application](MetaSubject);
//! 2. [Determine which aliases the resource has](MetaAlias);
//! 3. [Determine which properties the resource has](MetaProperty);
//! 4. [Determine which links the resource has](MetaLink);
//! 5. [Determine the titles of each link](MetaLinkTitle);
//! 6. [Determine the properties of each link](MetaLinkProperty);
//! 3. The application compiles the data in a single structure that the user agent supports
//! 4. The application returns the data to the user agent
//!
//! # Matching
//!
//! Matching is performed for each single record separately, allowing for example a system administrator to define many separate subjects while globally defining a property for all the resources served.
//!
//! # Reference
//!
//! See [`acrate_rd`] for more information on the specification these structures are based on.
//!
//! # Used by
//!
//! - [`acrate_rdserver`]
//!
use std ::str ::FromStr ;
use diesel ::deserialize ::FromSql ;
use diesel ::{ AsExpression , Associations , FromSqlRow , Identifiable , Insertable , IntoSql , PgTextExpressionMethods , QueryResult , Queryable , QueryableByName , Selectable , SelectableHelper , ExpressionMethods , BelongingToDsl } ;
use diesel ::pg ::{ Pg , PgConnection } ;
use diesel ::serialize ::{ Output , ToSql } ;
2024-11-15 02:16:06 +00:00
use diesel_async ::AsyncPgConnection ;
2024-11-15 01:16:16 +00:00
use uuid ::Uuid ;
2024-11-18 18:55:21 +00:00
2024-11-15 01:16:16 +00:00
use super ::schema ;
2024-11-18 18:55:21 +00:00
/// Wrapper to use [`mime::Mime`] with [`diesel`].
#[ derive(Debug, Clone, PartialEq, Eq, FromSqlRow, AsExpression) ]
#[ diesel(sql_type = diesel::sql_types::Text) ]
pub struct Mime ( pub mime ::Mime ) ;
/// A matchable record denoting the existence of a resource descriptor.
///
/// # See also
///
/// - [`MetaSubjectInsert`]
///
#[ derive(Debug, Queryable, QueryableByName, Identifiable, Selectable) ]
2024-11-16 05:16:34 +00:00
#[ diesel(table_name = schema::meta_subjects) ]
2024-11-16 05:45:58 +00:00
#[ diesel(check_for_backend(Pg)) ]
2024-11-16 05:16:34 +00:00
pub struct MetaSubject {
2024-11-18 18:55:21 +00:00
/// The identity column of the record.
2024-11-16 05:16:34 +00:00
pub id : Uuid ,
2024-11-18 18:55:21 +00:00
/// The document the record is valid for.
pub document : String ,
/// The [PostgreSQL ILIKE pattern] to match the search term against for the record to be valid.
///
/// [PostgreSQL ILIKE pattern]: https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-LIKE
pub pattern : String ,
/// The value the `subject` property should take when this record is matched.
///
/// If [`None`], its value is up for specification by the querying application.
pub subject : Option < String > ,
/// Where the querying application should redirect the user agent to when this record is matched.
///
/// If [`Some`], should always override everything else.
pub redirect : Option < String > ,
}
/// An [`Insertable`] version of [`MetaSubject`].
#[ derive(Debug, Insertable) ]
#[ diesel(table_name = schema::meta_subjects) ]
#[ diesel(check_for_backend(Pg)) ]
pub struct MetaSubjectInsert {
/// The document the record is valid for.
2024-11-16 05:16:34 +00:00
pub document : String ,
2024-11-18 18:55:21 +00:00
/// The [PostgreSQL ILIKE pattern] to match the search term against for the record to be valid.
///
/// [PostgreSQL ILIKE pattern]: https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-LIKE
2024-11-16 05:16:34 +00:00
pub pattern : String ,
2024-11-18 18:55:21 +00:00
/// The value the `subject` property should take when this record is matched.
///
/// If [`None`], its value is up for specification by the querying application.
2024-11-16 06:43:54 +00:00
pub subject : Option < String > ,
2024-11-18 18:55:21 +00:00
/// Where the querying application should redirect the user agent to when this record is matched.
///
/// If [`Some`], should always override everything else.
2024-11-16 05:16:34 +00:00
pub redirect : Option < String > ,
}
2024-11-18 18:55:21 +00:00
/// A matchable record denoting an alias belonging to a subject.
///
/// # See also
///
/// - [`MetaAliasInsert`]
///
#[ derive(Debug, Queryable, QueryableByName, Identifiable, Selectable) ]
2024-11-15 01:16:16 +00:00
#[ diesel(table_name = schema::meta_aliases) ]
2024-11-16 05:45:58 +00:00
#[ diesel(check_for_backend(Pg)) ]
2024-11-15 01:16:16 +00:00
pub struct MetaAlias {
2024-11-18 18:55:21 +00:00
/// The identity column of the record.
2024-11-15 01:16:16 +00:00
pub id : Uuid ,
2024-11-18 18:55:21 +00:00
/// The document the record is valid for.
pub document : String ,
/// The [PostgreSQL ILIKE pattern] to match the search term against for the record to be valid.
///
/// [PostgreSQL ILIKE pattern]: https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-LIKE
pub pattern : String ,
/// The alias to **add** to the list of aliases of the resource.
pub alias : String ,
}
/// An [`Insertable`] version of [`MetaAlias`].
#[ derive(Debug, Insertable) ]
#[ diesel(table_name = schema::meta_aliases) ]
#[ diesel(check_for_backend(Pg)) ]
pub struct MetaAliasInsert {
/// The document the record is valid for.
2024-11-15 04:21:05 +00:00
pub document : String ,
2024-11-18 18:55:21 +00:00
/// The [PostgreSQL ILIKE pattern] to match the search term against for the record to be valid.
///
/// [PostgreSQL ILIKE pattern]: https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-LIKE
2024-11-15 01:16:16 +00:00
pub pattern : String ,
2024-11-18 18:55:21 +00:00
/// The alias to **add** to the list of aliases of the resource.
2024-11-15 01:16:16 +00:00
pub alias : String ,
}
2024-11-18 18:55:21 +00:00
/// A matchable record denoting a link towards another resource someway related with the subject.
///
/// # See also
///
/// - [`MetaLinkInsert`]
///
#[ derive(Debug, Queryable, QueryableByName, Identifiable, Selectable) ]
2024-11-15 01:16:16 +00:00
#[ diesel(table_name = schema::meta_links) ]
2024-11-16 05:45:58 +00:00
#[ diesel(check_for_backend(Pg)) ]
2024-11-15 01:16:16 +00:00
pub struct MetaLink {
2024-11-18 18:55:21 +00:00
/// The identity column of the record.
2024-11-15 01:16:16 +00:00
pub id : Uuid ,
2024-11-18 18:55:21 +00:00
/// The document the record is valid for.
pub document : String ,
/// The [PostgreSQL ILIKE pattern] to match the search term against for the record to be valid.
///
/// [PostgreSQL ILIKE pattern]: https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-LIKE
pub pattern : String ,
/// The relationship the link establishes between itself and the value of the link.
pub rel : String ,
/// The media type of the value of the link.
///
/// Can be [`None`] if it shouldn't be specified.
pub type_ : Option < Mime > ,
/// The URI to the document this property is linking the subject to.
///
/// Can be [`None`] if it shouldn't be specified, for example if [`Self::template`] is [`Some`].
pub href : Option < String > ,
/// The template to the document this property is linking the subject to.
///
/// Can be [`None`] if it shouldn't be specified, for example if [`Self::href`] is [`Some`].
pub template : Option < String > ,
}
/// An [`Insertable`] version of [`MetaLink`].
#[ derive(Debug, Insertable) ]
#[ diesel(table_name = schema::meta_links) ]
#[ diesel(check_for_backend(Pg)) ]
pub struct MetaLinkInsert {
/// The document the record is valid for.
2024-11-15 04:21:05 +00:00
pub document : String ,
2024-11-18 18:55:21 +00:00
/// The [PostgreSQL ILIKE pattern] to match the search term against for the record to be valid.
///
/// [PostgreSQL ILIKE pattern]: https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-LIKE
2024-11-15 01:16:16 +00:00
pub pattern : String ,
2024-11-18 18:55:21 +00:00
/// The relationship the link establishes between itself and the value of the link.
2024-11-15 01:16:16 +00:00
pub rel : String ,
2024-11-18 18:55:21 +00:00
/// The media type of the value of the link.
///
/// Can be [`None`] if it shouldn't be specified.
pub type_ : Option < Mime > ,
/// The URI to the document this property is linking the subject to.
///
/// Can be [`None`] if it shouldn't be specified, for example if [`Self::template`] is [`Some`].
2024-11-15 01:16:16 +00:00
pub href : Option < String > ,
2024-11-18 18:55:21 +00:00
/// The template to the document this property is linking the subject to.
///
/// Can be [`None`] if it shouldn't be specified, for example if [`Self::href`] is [`Some`].
2024-11-15 19:53:59 +00:00
pub template : Option < String > ,
2024-11-15 01:16:16 +00:00
}
2024-11-18 18:55:21 +00:00
/// A property that a [`MetaLink`] has.
///
/// # See also
///
/// - [`MetaLinkPropertyInsert`]
///
#[ derive(Debug, Queryable, QueryableByName, Identifiable, Selectable, Associations) ]
2024-11-15 01:16:16 +00:00
#[ diesel(belongs_to(MetaLink)) ]
#[ diesel(table_name = schema::meta_link_properties) ]
2024-11-16 05:45:58 +00:00
#[ diesel(check_for_backend(Pg)) ]
2024-11-15 01:16:16 +00:00
pub struct MetaLinkProperty {
2024-11-18 18:55:21 +00:00
/// The identity column of the record.
2024-11-15 01:16:16 +00:00
pub id : Uuid ,
2024-11-18 18:55:21 +00:00
/// The [`MetaLink::id`] this record refers to.
2024-11-15 01:16:16 +00:00
pub meta_link_id : Uuid ,
2024-11-18 18:55:21 +00:00
/// The relationship the property establishes between the [`MetaLink`] and the [`MetaLinkProperty::value`].
2024-11-15 01:16:16 +00:00
pub rel : String ,
2024-11-18 18:55:21 +00:00
/// The value that the property has.
2024-11-15 01:16:16 +00:00
pub value : Option < String > ,
}
2024-11-18 18:55:21 +00:00
/// An [`Insertable`] version of [`MetaLinkProperty`].
#[ derive(Debug, Insertable) ]
#[ diesel(belongs_to(MetaLink)) ]
#[ diesel(table_name = schema::meta_link_properties) ]
#[ diesel(check_for_backend(Pg)) ]
pub struct MetaLinkPropertyInsert {
/// The [`MetaLink::id`] this record refers to.
pub meta_link_id : Uuid ,
/// The relationship the property establishes between the [`MetaLink`] and the [`MetaLinkProperty::value`].
pub rel : String ,
/// The value that the property has.
pub value : Option < String > ,
}
/// A title that a [`MetaLink`] has in a certain language.
#[ derive(Debug, Queryable, QueryableByName, Identifiable, Selectable, Associations) ]
2024-11-15 19:53:59 +00:00
#[ diesel(belongs_to(MetaLink)) ]
#[ diesel(table_name = schema::meta_link_titles) ]
2024-11-16 05:45:58 +00:00
#[ diesel(check_for_backend(Pg)) ]
2024-11-15 19:53:59 +00:00
pub struct MetaLinkTitle {
2024-11-18 18:55:21 +00:00
/// The identity column of the record.
2024-11-15 19:53:59 +00:00
pub id : Uuid ,
2024-11-18 18:55:21 +00:00
/// The [`MetaLink::id`] this record refers to.
pub meta_link_id : Uuid ,
/// The language of the title.
pub language : String ,
/// The actual contents of the title.
pub value : String ,
}
/// An [`Insertable`] version of [`MetaLinkTitle`].
#[ derive(Debug, Insertable) ]
#[ diesel(belongs_to(MetaLink)) ]
#[ diesel(table_name = schema::meta_link_titles) ]
#[ diesel(check_for_backend(Pg)) ]
pub struct MetaLinkTitleInsert {
/// The [`MetaLink::id`] this record refers to.
2024-11-15 19:53:59 +00:00
pub meta_link_id : Uuid ,
2024-11-18 18:55:21 +00:00
/// The language of the title.
2024-11-15 19:53:59 +00:00
pub language : String ,
2024-11-18 18:55:21 +00:00
/// The actual contents of the title.
2024-11-15 19:53:59 +00:00
pub value : String ,
}
2024-11-18 18:55:21 +00:00
/// A matchable record denoting a property that a subject has.
///
/// # See also
///
/// - [`MetaPropertyInsert`]
///
#[ derive(Debug, Queryable, QueryableByName, Identifiable, Selectable) ]
2024-11-15 01:16:16 +00:00
#[ diesel(table_name = schema::meta_properties) ]
2024-11-16 05:45:58 +00:00
#[ diesel(check_for_backend(Pg)) ]
2024-11-15 01:16:16 +00:00
pub struct MetaProperty {
2024-11-18 18:55:21 +00:00
/// The identity column of the record.
2024-11-15 01:16:16 +00:00
pub id : Uuid ,
2024-11-18 18:55:21 +00:00
/// The document the record is valid for.
pub document : String ,
/// The [PostgreSQL ILIKE pattern] to match the search term against for the record to be valid.
///
/// [PostgreSQL ILIKE pattern]: https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-LIKE
pub pattern : String ,
/// The relationship the property establishes between the [`MetaSubject`] and the [`MetaProperty::value`].
pub rel : String ,
/// The value that the property has.
pub value : Option < String > ,
}
/// An [`Insertable`] version of [`MetaLinkTitle`].
#[ derive(Debug, Insertable) ]
#[ diesel(table_name = schema::meta_properties) ]
#[ diesel(check_for_backend(Pg)) ]
pub struct MetaPropertyInsert {
/// The document the record is valid for.
2024-11-15 04:21:05 +00:00
pub document : String ,
2024-11-18 18:55:21 +00:00
/// The [PostgreSQL ILIKE pattern] to match the search term against for the record to be valid.
///
/// [PostgreSQL ILIKE pattern]: https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-LIKE
2024-11-15 01:16:16 +00:00
pub pattern : String ,
2024-11-18 18:55:21 +00:00
/// The relationship the property establishes between the [`MetaSubject`] and the [`MetaProperty::value`].
2024-11-15 05:30:42 +00:00
pub rel : String ,
2024-11-18 18:55:21 +00:00
/// The value that the property has.
2024-11-15 01:16:16 +00:00
pub value : Option < String > ,
}
2024-11-15 02:16:06 +00:00
2024-11-18 18:55:21 +00:00
/// Allow [`diesel::sql_types::Text`] values to be parsed as [`Mime`].
impl < DB > FromSql < diesel ::sql_types ::Text , DB > for Mime
where
DB : diesel ::backend ::Backend ,
String : FromSql < diesel ::sql_types ::Text , DB > ,
{
fn from_sql ( bytes : < DB as diesel ::backend ::Backend > ::RawValue < '_ > ) -> diesel ::deserialize ::Result < Self > {
let s = < String as FromSql < diesel ::sql_types ::Text , DB > > ::from_sql ( bytes ) ? ;
let mime = mime ::Mime ::from_str ( & s ) ? ;
Ok ( Self ( mime ) )
}
}
/// Allow [`diesel::sql_types::Text`] values to be written to with [`Mime`].
impl < DB > ToSql < diesel ::sql_types ::Text , DB > for Mime
where
DB : diesel ::backend ::Backend ,
str : ToSql < diesel ::sql_types ::Text , DB > ,
{
fn to_sql < ' b > ( & ' b self , out : & mut Output < ' b , '_ , DB > ) -> diesel ::serialize ::Result {
let mime = self . 0. essence_str ( ) ;
< str as ToSql < diesel ::sql_types ::Text , DB > > ::to_sql ( mime , out )
}
}
2024-11-16 05:16:34 +00:00
impl MetaSubject {
2024-11-18 18:55:21 +00:00
/// Synchronously query the records matching the given document and resource.
pub fn query_matching ( conn : & mut PgConnection , doc : & str , resource : & str ) -> QueryResult < Vec < Self > > {
use diesel ::QueryDsl ;
use diesel ::RunQueryDsl ;
use schema ::meta_subjects ::dsl ::* ;
let document_is_equal = document . eq ( doc ) ;
let resource_matches_pattern = resource . into_sql ::< diesel ::sql_types ::Text > ( ) . ilike ( pattern ) ;
meta_subjects
. filter ( document_is_equal )
. filter ( resource_matches_pattern )
. select ( Self ::as_select ( ) )
. load ( conn )
}
/// Asynchronously query the records matching the given document and resource.
pub async fn aquery_matching ( conn : & mut AsyncPgConnection , doc : & str , resource : & str ) -> QueryResult < Vec < Self > > {
use diesel ::QueryDsl ;
2024-11-16 05:16:34 +00:00
use diesel_async ::RunQueryDsl ;
use schema ::meta_subjects ::dsl ::* ;
let document_is_equal = document . eq ( doc ) ;
2024-11-18 18:55:21 +00:00
let resource_matches_pattern = resource . into_sql ::< diesel ::sql_types ::Text > ( ) . ilike ( pattern ) ;
2024-11-16 05:16:34 +00:00
meta_subjects
. filter ( document_is_equal )
2024-11-18 18:55:21 +00:00
. filter ( resource_matches_pattern )
2024-11-16 05:16:34 +00:00
. select ( Self ::as_select ( ) )
. load ( conn )
. await
}
}
2024-11-15 02:16:06 +00:00
impl MetaAlias {
2024-11-18 18:55:21 +00:00
/// Synchronously query the records matching the given document and resource.
pub fn query_matching ( conn : & mut PgConnection , doc : & str , subject : & str ) -> QueryResult < Vec < Self > > {
use diesel ::QueryDsl ;
use diesel ::RunQueryDsl ;
use schema ::meta_aliases ::dsl ::* ;
let document_is_equal = document . eq ( doc ) ;
let subject_matches_pattern = subject . into_sql ::< diesel ::sql_types ::Text > ( ) . ilike ( pattern ) ;
meta_aliases
. filter ( document_is_equal )
. filter ( subject_matches_pattern )
. select ( Self ::as_select ( ) )
. load ( conn )
}
/// Asynchronously query the records matching the given document and resource.
pub async fn aquery_matching ( conn : & mut AsyncPgConnection , doc : & str , subject : & str ) -> QueryResult < Vec < Self > > {
use diesel ::QueryDsl ;
2024-11-15 02:16:06 +00:00
use diesel_async ::RunQueryDsl ;
use schema ::meta_aliases ::dsl ::* ;
2024-11-15 04:23:06 +00:00
let document_is_equal = document . eq ( doc ) ;
2024-11-15 02:16:06 +00:00
let subject_matches_pattern = subject . into_sql ::< diesel ::sql_types ::Text > ( ) . ilike ( pattern ) ;
meta_aliases
2024-11-15 04:23:06 +00:00
. filter ( document_is_equal )
2024-11-15 02:16:06 +00:00
. filter ( subject_matches_pattern )
. select ( Self ::as_select ( ) )
. load ( conn )
. await
}
}
impl MetaLink {
2024-11-18 18:55:21 +00:00
/// Synchronously query the records matching the given document and resource.
pub async fn query_matching ( conn : & mut PgConnection , doc : & str , subject : & str ) -> QueryResult < Vec < Self > > {
use diesel ::QueryDsl ;
use diesel ::RunQueryDsl ;
use schema ::meta_links ::dsl ::* ;
let document_is_equal = document . eq ( doc ) ;
let subject_matches_pattern = subject . into_sql ::< diesel ::sql_types ::Text > ( ) . ilike ( pattern ) ;
meta_links
. filter ( document_is_equal )
. filter ( subject_matches_pattern )
. select ( Self ::as_select ( ) )
. load ( conn )
}
/// Asynchronously query the records matching the given document and resource.
pub async fn aquery_matching ( conn : & mut AsyncPgConnection , doc : & str , subject : & str ) -> QueryResult < Vec < Self > > {
use diesel ::QueryDsl ;
2024-11-15 02:16:06 +00:00
use diesel_async ::RunQueryDsl ;
use schema ::meta_links ::dsl ::* ;
2024-11-15 04:23:06 +00:00
let document_is_equal = document . eq ( doc ) ;
2024-11-15 02:16:06 +00:00
let subject_matches_pattern = subject . into_sql ::< diesel ::sql_types ::Text > ( ) . ilike ( pattern ) ;
meta_links
2024-11-15 04:23:06 +00:00
. filter ( document_is_equal )
2024-11-15 02:16:06 +00:00
. filter ( subject_matches_pattern )
. select ( Self ::as_select ( ) )
. load ( conn )
. await
}
2024-11-16 01:54:55 +00:00
}
impl MetaLinkProperty {
2024-11-18 18:55:21 +00:00
/// Synchronously query the records belonging to the given [`MetaLink`]s.
pub fn query_by_link ( conn : & mut PgConnection , links : & [ MetaLink ] ) -> QueryResult < Vec < Self > > {
use diesel ::RunQueryDsl ;
Self ::belonging_to ( links )
. load ( conn )
}
/// Asynchronously query the records belonging to the given [`MetaLink`]s.
pub async fn aquery_by_link ( conn : & mut AsyncPgConnection , links : & [ MetaLink ] ) -> QueryResult < Vec < Self > > {
2024-11-15 02:16:06 +00:00
use diesel_async ::RunQueryDsl ;
2024-11-16 01:54:55 +00:00
Self ::belonging_to ( links )
2024-11-15 02:16:06 +00:00
. load ( conn )
. await
}
2024-11-16 01:54:55 +00:00
}
impl MetaLinkTitle {
2024-11-18 18:55:21 +00:00
/// Synchronously query the records belonging to the given [`MetaLink`]s.
pub fn query_by_link ( conn : & mut PgConnection , links : & [ MetaLink ] ) -> QueryResult < Vec < Self > > {
use diesel ::RunQueryDsl ;
Self ::belonging_to ( links )
. load ( conn )
}
/// Asynchronously query the records belonging to the given [`MetaLink`]s.
pub async fn aquery_by_link ( conn : & mut AsyncPgConnection , links : & [ MetaLink ] ) -> QueryResult < Vec < Self > > {
2024-11-15 19:53:59 +00:00
use diesel_async ::RunQueryDsl ;
2024-11-16 01:54:55 +00:00
Self ::belonging_to ( links )
2024-11-15 19:53:59 +00:00
. load ( conn )
. await
}
2024-11-15 02:16:06 +00:00
}
impl MetaProperty {
2024-11-18 18:55:21 +00:00
/// Synchronously query the records matching the given document and resource.
pub fn query_matching ( conn : & mut PgConnection , doc : & str , subject : & str ) -> QueryResult < Vec < Self > > {
use diesel ::QueryDsl ;
use diesel ::RunQueryDsl ;
use schema ::meta_properties ::dsl ::* ;
let document_is_equal = document . eq ( doc ) ;
let subject_matches_pattern = subject . into_sql ::< diesel ::sql_types ::Text > ( ) . ilike ( pattern ) ;
meta_properties
. filter ( document_is_equal )
. filter ( subject_matches_pattern )
. select ( Self ::as_select ( ) )
. load ( conn )
}
/// Asynchronously query the records matching the given document and resource.
pub async fn aquery_matching ( conn : & mut AsyncPgConnection , doc : & str , subject : & str ) -> QueryResult < Vec < Self > > {
use diesel ::QueryDsl ;
2024-11-15 02:16:06 +00:00
use diesel_async ::RunQueryDsl ;
use schema ::meta_properties ::dsl ::* ;
2024-11-15 04:23:06 +00:00
let document_is_equal = document . eq ( doc ) ;
2024-11-15 02:16:06 +00:00
let subject_matches_pattern = subject . into_sql ::< diesel ::sql_types ::Text > ( ) . ilike ( pattern ) ;
meta_properties
2024-11-15 04:23:06 +00:00
. filter ( document_is_equal )
2024-11-15 02:16:06 +00:00
. filter ( subject_matches_pattern )
. select ( Self ::as_select ( ) )
. load ( conn )
. await
}
}