|
1 | 1 | use std::{
|
| 2 | + collections::HashMap, |
2 | 3 | fs,
|
3 | 4 | io::{BufRead, BufReader},
|
4 | 5 | path::Path,
|
@@ -316,28 +317,54 @@ fn add_keywords_into_database(
|
316 | 317 | pkg: &MetadataPackage,
|
317 | 318 | release_id: i32,
|
318 | 319 | ) -> Result<()> {
|
319 |
| - for keyword in &pkg.keywords { |
320 |
| - let slug = slugify(&keyword); |
321 |
| - let keyword_id: i32 = { |
322 |
| - let rows = conn.query("SELECT id FROM keywords WHERE slug = $1", &[&slug])?; |
323 |
| - if !rows.is_empty() { |
324 |
| - rows[0].get(0) |
325 |
| - } else { |
326 |
| - conn.query( |
327 |
| - "INSERT INTO keywords (name, slug) VALUES ($1, $2) RETURNING id", |
328 |
| - &[&keyword, &slug], |
329 |
| - )?[0] |
330 |
| - .get(0) |
331 |
| - } |
332 |
| - }; |
| 320 | + let wanted_keywords: HashMap<String, String> = pkg |
| 321 | + .keywords |
| 322 | + .iter() |
| 323 | + .map(|kw| (slugify(&kw), kw.clone())) |
| 324 | + .collect(); |
| 325 | + |
| 326 | + let mut existing_keyword_slugs: HashMap<String, i32> = conn |
| 327 | + .query( |
| 328 | + "SELECT slug, id FROM keywords WHERE slug IN $1", |
| 329 | + &[&wanted_keywords.keys().collect::<Vec<_>>()], |
| 330 | + )? |
| 331 | + .iter() |
| 332 | + .map(|row| (row.get("slug"), row.get("id"))) |
| 333 | + .collect(); |
333 | 334 |
|
334 |
| - // add releationship |
335 |
| - let _ = conn.query( |
336 |
| - "INSERT INTO keyword_rels (rid, kid) VALUES ($1, $2)", |
337 |
| - &[&release_id, &keyword_id], |
338 |
| - ); |
| 335 | + let new_keywords: Vec<(&String, &String)> = wanted_keywords |
| 336 | + .iter() |
| 337 | + .filter(|(k, _)| !(existing_keyword_slugs.contains_key(*k))) |
| 338 | + .collect(); |
| 339 | + |
| 340 | + if !new_keywords.is_empty() { |
| 341 | + // we create new keywords one-by-one, since most of the time we already have them, |
| 342 | + // and because support for multi-record inserts is a mess without adding a new |
| 343 | + // library |
| 344 | + let insert_keyword_query = |
| 345 | + conn.prepare("INSERT INTO keywords (name, slug) VALUES ($1, $2) RETURNING id")?; |
| 346 | + |
| 347 | + for (slug, name) in new_keywords { |
| 348 | + existing_keyword_slugs.insert( |
| 349 | + slug.clone(), |
| 350 | + conn.query_one(&insert_keyword_query, &[&name, &slug])? |
| 351 | + .get(0), |
| 352 | + ); |
| 353 | + } |
339 | 354 | }
|
340 | 355 |
|
| 356 | + conn.query( |
| 357 | + "INSERT INTO keyword_rels (rid, kid) |
| 358 | + SELECT |
| 359 | + $1 as rid, |
| 360 | + id as kid |
| 361 | + FROM |
| 362 | + keywords |
| 363 | + WHERE |
| 364 | + slug in $2", |
| 365 | + &[&release_id, &wanted_keywords.keys().collect::<Vec<_>>()], |
| 366 | + )?; |
| 367 | + |
341 | 368 | Ok(())
|
342 | 369 | }
|
343 | 370 |
|
|
0 commit comments