@@ -137,7 +137,7 @@ pub(crate) fn add_build_into_database(
137
137
res : & BuildResult ,
138
138
) -> Result < i32 > {
139
139
debug ! ( "Adding build into database" ) ;
140
- let rows = conn. query (
140
+ let row = conn. query_one (
141
141
"INSERT INTO builds (rid, rustc_version,
142
142
cratesfyi_version,
143
143
build_status, output)
@@ -151,19 +151,23 @@ pub(crate) fn add_build_into_database(
151
151
& res. build_log ,
152
152
] ,
153
153
) ?;
154
- Ok ( rows [ 0 ] . get ( 0 ) )
154
+ Ok ( row . get ( 0 ) )
155
155
}
156
156
157
157
fn initialize_package_in_database ( conn : & mut Client , pkg : & MetadataPackage ) -> Result < i32 > {
158
- let mut rows = conn. query ( "SELECT id FROM crates WHERE name = $1" , & [ & pkg. name ] ) ?;
159
158
// insert crate into database if it is not exists
160
- if rows. is_empty ( ) {
161
- rows = conn. query (
162
- "INSERT INTO crates (name) VALUES ($1) RETURNING id" ,
163
- & [ & pkg. name ] ,
164
- ) ?;
165
- }
166
- Ok ( rows[ 0 ] . get ( 0 ) )
159
+ let row = conn
160
+ . query_opt ( "SELECT id FROM crates WHERE name = $1" , & [ & pkg. name ] )
161
+ . transpose ( )
162
+ . unwrap_or_else ( || {
163
+ conn. query_one (
164
+ "INSERT INTO crates (name)
165
+ VALUES ($1)
166
+ RETURNING id" ,
167
+ & [ & pkg. name ] ,
168
+ )
169
+ } ) ?;
170
+ Ok ( row. get ( 0 ) )
167
171
}
168
172
169
173
/// Convert dependencies into Vec<(String, String, String)>
@@ -257,23 +261,26 @@ fn add_keywords_into_database(
257
261
for keyword in & pkg. keywords {
258
262
let slug = slugify ( & keyword) ;
259
263
let keyword_id: i32 = {
260
- let rows = conn. query ( "SELECT id FROM keywords WHERE slug = $1" , & [ & slug] ) ?;
261
- if !rows. is_empty ( ) {
262
- rows[ 0 ] . get ( 0 )
263
- } else {
264
- conn. query (
265
- "INSERT INTO keywords (name, slug) VALUES ($1, $2) RETURNING id" ,
266
- & [ & keyword, & slug] ,
267
- ) ?[ 0 ]
268
- . get ( 0 )
269
- }
264
+ conn. query_opt ( "SELECT id FROM keywords WHERE slug = $1" , & [ & slug] )
265
+ . transpose ( )
266
+ . unwrap_or_else ( || {
267
+ conn. query_one (
268
+ "INSERT INTO keywords (name, slug)
269
+ VALUES ($1, $2)
270
+ RETURNING id" ,
271
+ & [ & keyword, & slug] ,
272
+ )
273
+ } ) ?
274
+ . get ( 0 )
270
275
} ;
271
276
272
- // add releationship
273
- let _ = conn. query (
274
- "INSERT INTO keyword_rels (rid, kid) VALUES ($1, $2)" ,
277
+ // add relationship
278
+ conn. execute (
279
+ "INSERT INTO keyword_rels (rid, kid)
280
+ VALUES ($1, $2)
281
+ ON CONFLICT DO NOTHING" ,
275
282
& [ & release_id, & keyword_id] ,
276
- ) ;
283
+ ) ? ;
277
284
}
278
285
279
286
Ok ( ( ) )
@@ -301,24 +308,32 @@ fn add_authors_into_database(
301
308
let slug = slugify ( & author) ;
302
309
303
310
let author_id: i32 = {
304
- let rows = conn. query ( "SELECT id FROM authors WHERE slug = $1" , & [ & slug] ) ?;
305
- if !rows. is_empty ( ) {
306
- rows[ 0 ] . get ( 0 )
307
- } else {
308
- conn. query (
309
- "INSERT INTO authors (name, email, slug) VALUES ($1, $2, $3)
310
- RETURNING id" ,
311
- & [ & author, & email, & slug] ,
312
- ) ?[ 0 ]
313
- . get ( 0 )
314
- }
311
+ // TODO: If an author uses different email addresses per crate, or multiple authors
312
+ // have the same slugified name, this will flip-flop their name and email address
313
+ // on each crate publish.
314
+ //
315
+ // But, at least doing an upsert will result in their email/exact name rendering
316
+ // being updated if they change it in a new release.
317
+ conn. query_one (
318
+ "INSERT INTO authors (name, email, slug)
319
+ VALUES ($1, $2, $3)
320
+ ON CONFLICT (slug) DO UPDATE
321
+ SET
322
+ name = $1,
323
+ email = $2
324
+ RETURNING id" ,
325
+ & [ & author, & email, & slug] ,
326
+ ) ?
327
+ . get ( 0 )
315
328
} ;
316
329
317
330
// add relationship
318
- let _ = conn. query (
319
- "INSERT INTO author_rels (rid, aid) VALUES ($1, $2)" ,
331
+ conn. execute (
332
+ "INSERT INTO author_rels (rid, aid)
333
+ VALUES ($1, $2)
334
+ ON CONFLICT DO NOTHING" ,
320
335
& [ & release_id, & author_id] ,
321
- ) ;
336
+ ) ? ;
322
337
}
323
338
}
324
339
@@ -331,7 +346,14 @@ pub fn update_crate_data_in_database(
331
346
registry_data : & CrateData ,
332
347
) -> Result < ( ) > {
333
348
info ! ( "Updating crate data for {}" , name) ;
334
- let crate_id = conn. query ( "SELECT id FROM crates WHERE crates.name = $1" , & [ & name] ) ?[ 0 ] . get ( 0 ) ;
349
+ let crate_id = conn
350
+ . query_one (
351
+ "SELECT id
352
+ FROM crates
353
+ WHERE crates.name = $1" ,
354
+ & [ & name] ,
355
+ ) ?
356
+ . get ( 0 ) ;
335
357
336
358
update_owners_in_database ( conn, & registry_data. owners , crate_id) ?;
337
359
@@ -362,7 +384,7 @@ fn update_owners_in_database(
362
384
// Update any existing owner data since it is mutable and could have changed since last
363
385
// time we pulled it
364
386
let owner_id: i32 = {
365
- conn. query (
387
+ conn. query_one (
366
388
"
367
389
INSERT INTO owners (login, avatar, name, email)
368
390
VALUES ($1, $2, $3, $4)
@@ -374,12 +396,12 @@ fn update_owners_in_database(
374
396
RETURNING id
375
397
" ,
376
398
& [ & owner. login , & owner. avatar , & owner. name , & owner. email ] ,
377
- ) ?[ 0 ]
378
- . get ( 0 )
399
+ ) ?
400
+ . get ( 0 )
379
401
} ;
380
402
381
403
// add relationship
382
- conn. query (
404
+ conn. execute (
383
405
"INSERT INTO owner_rels (cid, oid) VALUES ($1, $2) ON CONFLICT DO NOTHING" ,
384
406
& [ & crate_id, & owner_id] ,
385
407
) ?;
@@ -391,7 +413,7 @@ fn update_owners_in_database(
391
413
for login in to_remove {
392
414
debug ! ( "Removing owner relationship {}" , login) ;
393
415
// remove relationship
394
- conn. query (
416
+ conn. execute (
395
417
"
396
418
DELETE FROM owner_rels
397
419
USING owners
@@ -417,7 +439,7 @@ where
417
439
ON CONFLICT DO NOTHING;" ;
418
440
let prepared = conn. prepare ( sql) ?;
419
441
for alg in algorithms {
420
- conn. query ( & prepared, & [ & release_id, & ( alg as i32 ) ] ) ?;
442
+ conn. execute ( & prepared, & [ & release_id, & ( alg as i32 ) ] ) ?;
421
443
}
422
444
Ok ( ( ) )
423
445
}
0 commit comments