diff --git a/src/bin/monitor.rs b/src/bin/monitor.rs index c543d8891b4..ce0e89f0681 100644 --- a/src/bin/monitor.rs +++ b/src/bin/monitor.rs @@ -108,7 +108,7 @@ fn check_stalled_update_downloads(conn: &PgConnection) -> Result<()> { /// Check for known spam patterns fn check_spam_attack(conn: &PgConnection) -> Result<()> { - use cargo_registry::models::krate::canon_crate_name; + use cargo_registry::sql::canon_crate_name; use diesel::dsl::*; const EVENT_KEY: &str = "spam_attack"; diff --git a/src/controllers/krate/downloads.rs b/src/controllers/krate/downloads.rs index 0ea2324da39..72a47f9764a 100644 --- a/src/controllers/krate/downloads.rs +++ b/src/controllers/krate/downloads.rs @@ -9,10 +9,9 @@ use crate::controllers::frontend_prelude::*; use crate::models::{Crate, CrateVersions, Version, VersionDownload}; use crate::schema::version_downloads; +use crate::sql::to_char; use crate::views::EncodableVersionDownload; -use crate::models::krate::to_char; - /// Handles the `GET /crates/:crate_id/downloads` route. pub fn downloads(req: &mut dyn RequestExt) -> EndpointResult { use diesel::dsl::*; diff --git a/src/controllers/krate/search.rs b/src/controllers/krate/search.rs index d1af65110d2..d34520399bb 100644 --- a/src/controllers/krate/search.rs +++ b/src/controllers/krate/search.rs @@ -1,6 +1,7 @@ //! Endpoint for searching and discovery functionality use diesel::dsl::*; +use diesel::sql_types::Array; use diesel_full_text_search::*; use indexmap::IndexMap; @@ -14,7 +15,8 @@ use crate::util::errors::bad_request; use crate::views::EncodableCrate; use crate::controllers::helpers::pagination::{Page, Paginated, PaginationOptions}; -use crate::models::krate::{canon_crate_name, ALL_COLUMNS}; +use crate::models::krate::ALL_COLUMNS; +use crate::sql::{array_agg, canon_crate_name, lower}; /// Handles the `GET /crates` route. /// Returns a list of crates. Called in a variety of scenarios in the @@ -109,9 +111,6 @@ pub fn search(req: &mut dyn RequestExt) -> EndpointResult { } if let Some(kws) = params.get("all_keywords") { - use diesel::sql_types::Array; - sql_function!(#[aggregate] fn array_agg(x: T) -> Array); - // Calculating the total number of results with filters is not supported yet. supports_seek = false; @@ -141,7 +140,7 @@ pub fn search(req: &mut dyn RequestExt) -> EndpointResult { crates_keywords::table .select(crates_keywords::crate_id) .inner_join(keywords::table) - .filter(crate::lower(keywords::keyword).eq(crate::lower(kw))), + .filter(lower(keywords::keyword).eq(lower(kw))), ), ); } else if let Some(letter) = params.get("letter") { diff --git a/src/controllers/user/other.rs b/src/controllers/user/other.rs index 72d51a449d3..4444d6cf0e8 100644 --- a/src/controllers/user/other.rs +++ b/src/controllers/user/other.rs @@ -2,16 +2,17 @@ use crate::controllers::frontend_prelude::*; use crate::models::{CrateOwner, OwnerKind, User}; use crate::schema::{crate_owners, crates, users}; +use crate::sql::lower; use crate::views::EncodablePublicUser; /// Handles the `GET /users/:user_id` route. pub fn show(req: &mut dyn RequestExt) -> EndpointResult { use self::users::dsl::{gh_login, id, users}; - let name = crate::lower(&req.params()["user_id"]); + let name = lower(&req.params()["user_id"]); let conn = req.db_conn()?; let user: User = users - .filter(crate::lower(gh_login).eq(name)) + .filter(lower(gh_login).eq(name)) .order(id.desc()) .first(&*conn)?; diff --git a/src/lib.rs b/src/lib.rs index 5b433601094..aad445d9e33 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,6 +47,7 @@ pub mod middleware; mod publish_rate_limit; pub mod render; pub mod schema; +pub mod sql; pub mod tasks; mod test_util; pub mod uploaders; @@ -126,5 +127,3 @@ pub fn env_optional(s: &str) -> Option { .unwrap_or_else(|_| panic!("`{}` was defined but could not be parsed", s)) }) } - -sql_function!(fn lower(x: ::diesel::sql_types::Text) -> ::diesel::sql_types::Text); diff --git a/src/models/category.rs b/src/models/category.rs index c4f09007833..0d0a2780654 100644 --- a/src/models/category.rs +++ b/src/models/category.rs @@ -15,7 +15,7 @@ pub struct Category { pub created_at: NaiveDateTime, } -type WithSlug<'a> = diesel::dsl::Eq>; +type WithSlug<'a> = diesel::dsl::Eq>; type BySlug<'a> = diesel::dsl::Filter>; type WithSlugsCaseSensitive<'a> = diesel::dsl::Eq< categories::slug, @@ -40,7 +40,7 @@ pub struct CrateCategory { impl Category { pub fn with_slug(slug: &str) -> WithSlug<'_> { - categories::slug.eq(crate::lower(slug)) + categories::slug.eq(crate::sql::lower(slug)) } pub fn by_slug(slug: &str) -> BySlug<'_> { diff --git a/src/models/keyword.rs b/src/models/keyword.rs index f11bedc3ac3..6bf0eb1e824 100644 --- a/src/models/keyword.rs +++ b/src/models/keyword.rs @@ -3,6 +3,7 @@ use diesel::prelude::*; use crate::models::Crate; use crate::schema::*; +use crate::sql::lower; #[derive(Clone, Identifiable, Queryable, Debug)] pub struct Keyword { @@ -25,7 +26,7 @@ pub struct CrateKeyword { impl Keyword { pub fn find_by_keyword(conn: &PgConnection, name: &str) -> QueryResult { keywords::table - .filter(keywords::keyword.eq(crate::lower(name))) + .filter(keywords::keyword.eq(lower(name))) .first(&*conn) } diff --git a/src/models/krate.rs b/src/models/krate.rs index 624c4ed875d..3d6a95ff275 100644 --- a/src/models/krate.rs +++ b/src/models/krate.rs @@ -2,7 +2,7 @@ use chrono::NaiveDateTime; use diesel::associations::Identifiable; use diesel::pg::Pg; use diesel::prelude::*; -use diesel::sql_types::Bool; +use diesel::sql_types::{Bool, Text}; use url::Url; use crate::app::App; @@ -17,6 +17,7 @@ use crate::util::errors::{cargo_err, AppResult}; use crate::models::helpers::with_count::*; use crate::publish_rate_limit::PublishRateLimit; use crate::schema::*; +use crate::sql::canon_crate_name; #[derive(Debug, Queryable, Identifiable, Associations, Clone, Copy)] #[belongs_to(Crate)] @@ -72,7 +73,7 @@ pub const ALL_COLUMNS: AllColumns = ( pub const MAX_NAME_LENGTH: usize = 64; -type CanonCrateName = self::canon_crate_name::HelperType; +type CanonCrateName = canon_crate_name::HelperType; type All = diesel::dsl::Select; type WithName<'a> = diesel::dsl::Eq, CanonCrateName<&'a str>>; type ByName<'a> = diesel::dsl::Filter>; @@ -440,10 +441,6 @@ impl Crate { } } -use diesel::sql_types::{Date, Text}; -sql_function!(fn canon_crate_name(x: Text) -> Text); -sql_function!(fn to_char(a: Date, b: Text) -> Text); - #[cfg(test)] mod tests { use crate::models::{Crate, NewCrate}; diff --git a/src/models/owner.rs b/src/models/owner.rs index f7f50aeeec0..3dc4ec2574d 100644 --- a/src/models/owner.rs +++ b/src/models/owner.rs @@ -6,6 +6,7 @@ use crate::util::errors::{cargo_err, AppResult}; use crate::models::{Crate, Team, User}; use crate::schema::{crate_owners, users}; +use crate::sql::lower; #[derive(Insertable, Associations, Identifiable, Debug, Clone, Copy)] #[belongs_to(Crate)] @@ -69,7 +70,7 @@ impl Owner { )?)) } else { users::table - .filter(crate::lower(users::gh_login).eq(name.to_lowercase())) + .filter(lower(users::gh_login).eq(name.to_lowercase())) .filter(users::gh_id.ne(-1)) .order(users::gh_id.desc()) .first(conn) diff --git a/src/publish_rate_limit.rs b/src/publish_rate_limit.rs index 643be617ede..f6d03408663 100644 --- a/src/publish_rate_limit.rs +++ b/src/publish_rate_limit.rs @@ -1,9 +1,11 @@ use chrono::{NaiveDateTime, Utc}; use diesel::data_types::PgInterval; use diesel::prelude::*; +use diesel::sql_types::Interval; use std::time::Duration; use crate::schema::{publish_limit_buckets, publish_rate_overrides}; +use crate::sql::{date_part, floor, greatest, interval_part, least}; use crate::util::errors::{AppResult, TooManyRequests}; #[derive(Debug, Clone, Copy)] @@ -67,16 +69,6 @@ impl PublishRateLimit { conn: &PgConnection, ) -> QueryResult { use self::publish_limit_buckets::dsl::*; - use diesel::sql_types::{Double, Interval, Text, Timestamp}; - - sql_function!(fn date_part(x: Text, y: Timestamp) -> Double); - sql_function! { - #[sql_name = "date_part"] - fn interval_part(x: Text, y: Interval) -> Double; - } - sql_function!(fn floor(x: Double) -> Integer); - sql_function!(fn greatest(x: T, y: T) -> T); - sql_function!(fn least(x: T, y: T) -> T); let burst: i32 = publish_rate_overrides::table .find(uploader) diff --git a/src/sql.rs b/src/sql.rs new file mode 100644 index 00000000000..c1ec9a61f80 --- /dev/null +++ b/src/sql.rs @@ -0,0 +1,14 @@ +use diesel::sql_types::{Array, Date, Double, Interval, Text, Timestamp}; + +sql_function!(#[aggregate] fn array_agg(x: T) -> Array); +sql_function!(fn canon_crate_name(x: Text) -> Text); +sql_function!(fn to_char(a: Date, b: Text) -> Text); +sql_function!(fn lower(x: Text) -> Text); +sql_function!(fn date_part(x: Text, y: Timestamp) -> Double); +sql_function! { + #[sql_name = "date_part"] + fn interval_part(x: Text, y: Interval) -> Double; +} +sql_function!(fn floor(x: Double) -> Integer); +sql_function!(fn greatest(x: T, y: T) -> T); +sql_function!(fn least(x: T, y: T) -> T);