@@ -8,6 +8,7 @@ use uuid::Uuid;
8
8
9
9
use crate :: {
10
10
error:: Result ,
11
+ parsers:: json:: JsonVal ,
11
12
report:: { models, Report , ReportBuilder } ,
12
13
} ;
13
14
@@ -30,6 +31,14 @@ fn open_database(filename: &PathBuf) -> Result<Connection> {
30
31
Ok ( conn)
31
32
}
32
33
34
+ /// Can't implement foreign traits (`ToSql`/`FromSql`) on foreign types
35
+ /// (`serde_json::Value`) so this helper function fills in.
36
+ fn json_value_from_sql ( s : String , col : usize ) -> rusqlite:: Result < Option < JsonVal > > {
37
+ serde_json:: from_str ( s. as_str ( ) ) . map_err ( |e| {
38
+ rusqlite:: Error :: FromSqlConversionFailure ( col, rusqlite:: types:: Type :: Text , Box :: new ( e) )
39
+ } )
40
+ }
41
+
33
42
impl SqliteReport {
34
43
pub fn new ( filename : PathBuf ) -> Result < SqliteReport > {
35
44
let conn = open_database ( & filename) ?;
@@ -156,6 +165,32 @@ impl Report for SqliteReport {
156
165
Ok ( result)
157
166
}
158
167
168
+ fn get_details_for_upload ( & self , upload : & models:: Context ) -> Result < models:: UploadDetails > {
169
+ assert_eq ! ( upload. context_type, models:: ContextType :: Upload ) ;
170
+ let mut stmt = self . conn . prepare ( "SELECT context_id, timestamp, raw_upload_url, flags, provider, build, name, job_name, ci_run_url, state, env, session_type, session_extras FROM upload_details WHERE context_id = ?1" ) ?;
171
+ Ok ( stmt. query_row ( [ upload. id ] , |row| {
172
+ Ok ( models:: UploadDetails {
173
+ context_id : row. get ( 0 ) ?,
174
+ timestamp : row. get ( 1 ) ?,
175
+ raw_upload_url : row. get ( 2 ) ?,
176
+ flags : row
177
+ . get :: < usize , String > ( 3 )
178
+ . and_then ( |s| json_value_from_sql ( s, 3 ) ) ?,
179
+ provider : row. get ( 4 ) ?,
180
+ build : row. get ( 5 ) ?,
181
+ name : row. get ( 6 ) ?,
182
+ job_name : row. get ( 7 ) ?,
183
+ ci_run_url : row. get ( 8 ) ?,
184
+ state : row. get ( 9 ) ?,
185
+ env : row. get ( 10 ) ?,
186
+ session_type : row. get ( 11 ) ?,
187
+ session_extras : row
188
+ . get :: < usize , String > ( 12 )
189
+ . and_then ( |s| json_value_from_sql ( s, 12 ) ) ?,
190
+ } )
191
+ } ) ?)
192
+ }
193
+
159
194
/// Merge `other` into `self` without modifying `other`.
160
195
///
161
196
/// TODO: Probably put this in a commit
@@ -413,6 +448,35 @@ impl ReportBuilder<SqliteReport> for SqliteReportBuilder {
413
448
) ?)
414
449
}
415
450
451
+ fn insert_upload_details (
452
+ & mut self ,
453
+ context_id : i64 ,
454
+ mut upload_details : models:: UploadDetails ,
455
+ ) -> Result < models:: UploadDetails > {
456
+ upload_details. context_id = context_id;
457
+ let mut stmt = self . conn . prepare ( "INSERT INTO upload_details (context_id, timestamp, raw_upload_url, flags, provider, build, name, job_name, ci_run_url, state, env, session_type, session_extras) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13)" ) ?;
458
+ let _ = stmt. execute ( (
459
+ & upload_details. context_id ,
460
+ & upload_details. timestamp ,
461
+ & upload_details. raw_upload_url ,
462
+ & upload_details. flags . as_ref ( ) . map ( |v| v. to_string ( ) ) ,
463
+ & upload_details. provider ,
464
+ & upload_details. build ,
465
+ & upload_details. name ,
466
+ & upload_details. job_name ,
467
+ & upload_details. ci_run_url ,
468
+ & upload_details. state ,
469
+ & upload_details. env ,
470
+ & upload_details. session_type ,
471
+ & upload_details
472
+ . session_extras
473
+ . as_ref ( )
474
+ . map ( |v| v. to_string ( ) ) ,
475
+ ) ) ?;
476
+
477
+ Ok ( upload_details)
478
+ }
479
+
416
480
fn build ( self ) -> SqliteReport {
417
481
SqliteReport {
418
482
filename : self . filename ,
@@ -652,6 +716,8 @@ mod tests {
652
716
}
653
717
654
718
mod sqlite_report_builder {
719
+ use serde_json:: { json, json_internal} ;
720
+
655
721
use super :: * ;
656
722
657
723
fn hash_id ( key : & str ) -> i64 {
@@ -949,5 +1015,51 @@ mod tests {
949
1015
. unwrap ( ) ;
950
1016
assert_eq ! ( actual_assoc, expected_assoc) ;
951
1017
}
1018
+
1019
+ #[ test]
1020
+ fn test_insert_upload_details ( ) {
1021
+ let ctx = setup ( ) ;
1022
+ let db_file = ctx. temp_dir . path ( ) . join ( "db.sqlite" ) ;
1023
+ let mut report_builder = SqliteReportBuilder :: new ( db_file) . unwrap ( ) ;
1024
+
1025
+ let upload = report_builder
1026
+ . insert_context ( models:: ContextType :: Upload , "codecov-rs CI" )
1027
+ . unwrap ( ) ;
1028
+ let inserted_details = models:: UploadDetails {
1029
+ context_id : upload. id ,
1030
+ timestamp : Some ( 123 ) ,
1031
+ raw_upload_url : Some ( "https://example.com" . to_string ( ) ) ,
1032
+ flags : Some ( json ! ( [ "abc" . to_string( ) , "def" . to_string( ) ] ) ) ,
1033
+ provider : Some ( "provider" . to_string ( ) ) ,
1034
+ build : Some ( "build" . to_string ( ) ) ,
1035
+ name : Some ( "name" . to_string ( ) ) ,
1036
+ job_name : Some ( "job name" . to_string ( ) ) ,
1037
+ ci_run_url : Some ( "https://example.com" . to_string ( ) ) ,
1038
+ state : Some ( "state" . to_string ( ) ) ,
1039
+ env : Some ( "env" . to_string ( ) ) ,
1040
+ session_type : Some ( "uploaded" . to_string ( ) ) ,
1041
+ session_extras : Some ( json ! ( { } ) ) ,
1042
+ } ;
1043
+ let inserted_details = report_builder
1044
+ . insert_upload_details ( upload. id , inserted_details)
1045
+ . unwrap ( ) ;
1046
+
1047
+ let other_upload = report_builder
1048
+ . insert_context ( models:: ContextType :: Upload , "codecov-rs CI 2" )
1049
+ . unwrap ( ) ;
1050
+
1051
+ let report = report_builder. build ( ) ;
1052
+ let fetched_details = report. get_details_for_upload ( & upload) . unwrap ( ) ;
1053
+ assert_eq ! ( fetched_details, inserted_details) ;
1054
+
1055
+ let other_details_result = report. get_details_for_upload ( & other_upload) ;
1056
+ assert ! ( other_details_result. is_err( ) ) ;
1057
+ match other_details_result {
1058
+ Err ( crate :: error:: CodecovError :: SqliteError (
1059
+ rusqlite:: Error :: QueryReturnedNoRows ,
1060
+ ) ) => { }
1061
+ _ => assert ! ( false ) ,
1062
+ }
1063
+ }
952
1064
}
953
1065
}
0 commit comments