Skip to content

Commit 028a693

Browse files
committed
Add abandoned_usernames table
1 parent 3aec4b0 commit 028a693

6 files changed

Lines changed: 107 additions & 18 deletions

File tree

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use crate::schema::abandoned_usernames;
2+
use chrono::{DateTime, Utc};
3+
use diesel::prelude::*;
4+
5+
#[derive(Debug, Clone, Identifiable, HasQuery)]
6+
#[diesel(
7+
table_name = abandoned_usernames,
8+
check_for_backend(diesel::pg::Pg),
9+
)]
10+
pub struct AbandonedUsername {
11+
pub id: i64,
12+
pub username: String,
13+
pub previous_user_id: Option<i32>,
14+
pub abandoned_at: DateTime<Utc>,
15+
pub available_at: DateTime<Utc>,
16+
}
17+
18+
#[derive(Insertable, Debug)]
19+
#[diesel(table_name = abandoned_usernames, check_for_backend(diesel::pg::Pg))]
20+
pub struct NewAbandonedUsername<'a> {
21+
pub username: &'a str,
22+
pub previous_user_id: Option<i32>,
23+
pub abandoned_at: &'a DateTime<Utc>,
24+
pub available_at: &'a DateTime<Utc>,
25+
}

crates/crates_io_database/src/models/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
pub use self::abandoned_username::{AbandonedUsername, NewAbandonedUsername};
12
pub use self::action::{NewVersionOwnerAction, VersionAction, VersionOwnerAction};
23
pub use self::category::{Category, CrateCategory, NewCategory};
34
pub use self::cloudfront_invalidation_queue::{
@@ -23,6 +24,7 @@ pub use self::version::{NewVersion, TopVersions, Version};
2324

2425
pub mod helpers;
2526

27+
mod abandoned_username;
2628
mod action;
2729
pub mod category;
2830
mod cloudfront_invalidation_queue;

crates/crates_io_database/src/schema.rs

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,25 @@ pub mod sql_types {
1212
pub struct Ltree;
1313
}
1414

15+
diesel::table! {
16+
use diesel::sql_types::*;
17+
use diesel_full_text_search::Tsvector;
18+
19+
/// Usernames previously associated with users
20+
abandoned_usernames (id) {
21+
/// Date and time the user stopped using this username (due to name change, account deactivation, or similar)
22+
abandoned_at -> Timestamptz,
23+
/// Date and time this username will be available to other users
24+
available_at -> Timestamptz,
25+
/// Unique identifier of the `abandoned_usernames` row
26+
id -> Int8,
27+
/// The ID of the user who was using this username for this time period, or NULL if the user was deleted
28+
previous_user_id -> Nullable<Int4>,
29+
/// The abandoned username in question (use `canon_username()` for normalization, if needed)
30+
username -> Varchar,
31+
}
32+
}
33+
1534
diesel::table! {
1635
use diesel::sql_types::*;
1736
use diesel_full_text_search::Tsvector;
@@ -768,6 +787,24 @@ diesel::table! {
768787
}
769788
}
770789

790+
diesel::table! {
791+
/// Representation of the `recent_crate_downloads` view.
792+
///
793+
/// This data represents the downloads in the last 90 days.
794+
/// This view does not contain realtime data.
795+
/// It is refreshed by the `update-downloads` script.
796+
recent_crate_downloads (crate_id) {
797+
/// The `crate_id` column of the `recent_crate_downloads` view.
798+
///
799+
/// Its SQL type is `Integer`.
800+
crate_id -> Integer,
801+
/// The `downloads` column of the `recent_crate_downloads` table.
802+
///
803+
/// Its SQL type is `BigInt`.
804+
downloads -> BigInt,
805+
}
806+
}
807+
771808
diesel::table! {
772809
use diesel::sql_types::*;
773810
use diesel_full_text_search::Tsvector;
@@ -791,24 +828,6 @@ diesel::table! {
791828
}
792829
}
793830

794-
diesel::table! {
795-
/// Representation of the `recent_crate_downloads` view.
796-
///
797-
/// This data represents the downloads in the last 90 days.
798-
/// This view does not contain realtime data.
799-
/// It is refreshed by the `update-downloads` script.
800-
recent_crate_downloads (crate_id) {
801-
/// The `crate_id` column of the `recent_crate_downloads` view.
802-
///
803-
/// Its SQL type is `Integer`.
804-
crate_id -> Integer,
805-
/// The `downloads` column of the `recent_crate_downloads` table.
806-
///
807-
/// Its SQL type is `BigInt`.
808-
downloads -> BigInt,
809-
}
810-
}
811-
812831
diesel::table! {
813832
use diesel::sql_types::*;
814833
use diesel_full_text_search::Tsvector;
@@ -1274,6 +1293,7 @@ diesel::table! {
12741293
}
12751294
}
12761295

1296+
diesel::joinable!(abandoned_usernames -> users (previous_user_id));
12771297
diesel::joinable!(api_tokens -> users (user_id));
12781298
diesel::joinable!(crate_downloads -> crates (crate_id));
12791299
diesel::joinable!(crate_owner_invitations -> crates (crate_id));
@@ -1309,6 +1329,7 @@ diesel::joinable!(versions -> users (published_by));
13091329
diesel::joinable!(versions_published_by -> versions (version_id));
13101330

13111331
diesel::allow_tables_to_appear_in_same_query!(
1332+
abandoned_usernames,
13121333
api_tokens,
13131334
background_jobs,
13141335
categories,

crates/crates_io_database_dump/src/dump-db.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,15 @@ account_lock_until = "private"
274274
is_admin = "private"
275275
publish_notifications = "private"
276276

277+
[abandoned_usernames]
278+
dependencies = ["users"]
279+
[abandoned_usernames.columns]
280+
id = "private"
281+
username = "private"
282+
previous_user_id = "private"
283+
abandoned_at = "private"
284+
available_at = "private"
285+
277286
[version_downloads]
278287
dependencies = ["versions"]
279288
[version_downloads.columns]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
DROP TABLE abandoned_usernames;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
CREATE TABLE IF NOT EXISTS abandoned_usernames
2+
(
3+
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
4+
username VARCHAR NOT NULL,
5+
previous_user_id INTEGER
6+
CONSTRAINT fk_abandoned_usernames_previous_user_id
7+
REFERENCES users
8+
ON DELETE SET NULL,
9+
abandoned_at TIMESTAMPTZ NOT NULL,
10+
available_at TIMESTAMPTZ NOT NULL
11+
);
12+
13+
COMMENT ON TABLE abandoned_usernames IS
14+
'Usernames previously associated with users';
15+
COMMENT ON COLUMN abandoned_usernames.id IS
16+
'Unique identifier of the `abandoned_usernames` row';
17+
COMMENT ON COLUMN abandoned_usernames.username IS
18+
'The abandoned username in question (use `canon_username()` for normalization, if needed)';
19+
COMMENT ON COLUMN abandoned_usernames.previous_user_id IS
20+
'The ID of the user who was using this username for this time period, or NULL if the user was deleted';
21+
COMMENT ON COLUMN abandoned_usernames.abandoned_at IS
22+
'Date and time the user stopped using this username (due to name change, account deactivation, or similar)';
23+
COMMENT ON COLUMN abandoned_usernames.available_at IS
24+
'Date and time this username will be available to other users';
25+
26+
-- safety-assured:start
27+
-- This table doesn't exist yet, so creating this index concurrently isn't necessary.
28+
CREATE INDEX IF NOT EXISTS
29+
abandoned_usernames_canon_username_index
30+
ON abandoned_usernames (canon_username(username));
31+
-- safety-assured:end

0 commit comments

Comments
 (0)