|
1 | | -use crate::schema::{crate_downloads, crate_owners, teams, users}; |
| 1 | +use crate::schema::crate_downloads; |
2 | 2 | use crate::worker::jobs; |
3 | 3 | use crate::{admin::dialoguer, db, schema::crates}; |
4 | 4 | use anyhow::Context; |
5 | 5 | use colored::Colorize; |
6 | 6 | use crates_io_worker::BackgroundJob; |
7 | 7 | use diesel::dsl::sql; |
8 | | -use diesel::sql_types::Text; |
9 | | -use diesel::{ExpressionMethods, JoinOnDsl, QueryDsl}; |
| 8 | +use diesel::sql_types::{Array, Text}; |
| 9 | +use diesel::{ExpressionMethods, QueryDsl}; |
10 | 10 | use diesel_async::RunQueryDsl; |
| 11 | +use futures_util::TryStreamExt; |
11 | 12 | use std::collections::HashMap; |
12 | 13 | use std::fmt::Display; |
13 | 14 |
|
@@ -35,32 +36,38 @@ pub async fn run(opts: Opts) -> anyhow::Result<()> { |
35 | 36 | let mut crate_names = opts.crate_names; |
36 | 37 | crate_names.sort(); |
37 | 38 |
|
38 | | - let query_result = crates::table |
| 39 | + let existing_crates = crates::table |
39 | 40 | .inner_join(crate_downloads::table) |
40 | | - .left_join(crate_owners::table.on(crate_owners::crate_id.eq(crates::id))) |
41 | | - .left_join(teams::table.on(teams::id.eq(crate_owners::owner_id))) |
42 | | - .left_join(users::table.on(users::id.eq(crate_owners::owner_id))) |
43 | 41 | .filter(crates::name.eq_any(&crate_names)) |
44 | 42 | .select(( |
45 | 43 | crates::name, |
46 | 44 | crates::id, |
47 | 45 | crate_downloads::downloads, |
48 | | - sql::<Text>( |
49 | | - "CASE WHEN crate_owners.owner_kind = 1 THEN teams.login ELSE users.gh_login END", |
| 46 | + sql::<Array<Text>>( |
| 47 | + r#" |
| 48 | + ARRAY( |
| 49 | + SELECT |
| 50 | + CASE WHEN crate_owners.owner_kind = 1 THEN |
| 51 | + teams.login |
| 52 | + ELSE |
| 53 | + users.gh_login |
| 54 | + END |
| 55 | + FROM crate_owners |
| 56 | + LEFT JOIN teams ON teams.id = crate_owners.owner_id |
| 57 | + LEFT JOIN users ON users.id = crate_owners.owner_id |
| 58 | + WHERE crate_owners.crate_id = crates.id |
| 59 | + ) |
| 60 | + "#, |
50 | 61 | ), |
51 | 62 | )) |
52 | | - .load::<(String, i32, i64, String)>(&mut conn) |
| 63 | + .load_stream::<(String, i32, i64, Vec<String>)>(&mut conn) |
53 | 64 | .await |
54 | | - .context("Failed to look up crate name from the database")?; |
55 | | - |
56 | | - let mut existing_crates: HashMap<String, CrateInfo> = HashMap::new(); |
57 | | - for (name, id, downloads, login) in query_result { |
58 | | - let entry = existing_crates |
59 | | - .entry(name) |
60 | | - .or_insert_with(|| CrateInfo::new(id, downloads)); |
61 | | - |
62 | | - entry.owners.push(login); |
63 | | - } |
| 65 | + .context("Failed to look up crate name from the database")? |
| 66 | + .try_fold(HashMap::new(), |mut map, (name, id, downloads, owners)| { |
| 67 | + map.insert(name, CrateInfo::new(id, downloads, owners)); |
| 68 | + futures_util::future::ready(Ok(map)) |
| 69 | + }) |
| 70 | + .await?; |
64 | 71 |
|
65 | 72 | println!("Deleting the following crates:"); |
66 | 73 | println!(); |
@@ -122,11 +129,11 @@ struct CrateInfo { |
122 | 129 | } |
123 | 130 |
|
124 | 131 | impl CrateInfo { |
125 | | - pub fn new(id: i32, downloads: i64) -> Self { |
| 132 | + pub fn new(id: i32, downloads: i64, owners: Vec<String>) -> Self { |
126 | 133 | Self { |
127 | 134 | id, |
128 | 135 | downloads, |
129 | | - owners: Vec::with_capacity(1), |
| 136 | + owners, |
130 | 137 | } |
131 | 138 | } |
132 | 139 | } |
|
0 commit comments