From b2f8bb9990d7ac0b22dc4c0d7d68649a9066cdc3 Mon Sep 17 00:00:00 2001 From: Geometrically <18202329+Geometrically@users.noreply.github.com> Date: Mon, 19 Jul 2021 14:47:14 -0700 Subject: [PATCH] Fix panic on requesting projects (#223) --- sqlx-data.json | 326 +++++++++++++++------------- src/database/models/categories.rs | 21 +- src/database/models/project_item.rs | 36 ++- src/database/models/version_item.rs | 262 +++++++++++----------- src/routes/tags.rs | 2 + 5 files changed, 348 insertions(+), 299 deletions(-) diff --git a/sqlx-data.json b/sqlx-data.json index e4a0f66a4..29847b285 100644 --- a/sqlx-data.json +++ b/sqlx-data.json @@ -1143,6 +1143,48 @@ "nullable": [] } }, + "3d384766d179f804c17e03d1917da65cc6043f88971ddc3fd23ba3be00717dfc": { + "query": "\n SELECT gv.id id, gv.version version_, gv.type type_, gv.created created, gv.major FROM game_versions gv\n ORDER BY created DESC\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "version_", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "type_", + "type_info": "Varchar" + }, + { + "ordinal": 3, + "name": "created", + "type_info": "Timestamptz" + }, + { + "ordinal": 4, + "name": "major", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + false, + false, + false, + false, + false + ] + } + }, "3d700aaeb0d5129ac8c297ee0542757435a50a35ec94582d9d6ce67aa5302291": { "query": "\n UPDATE mods\n SET title = $1\n WHERE (id = $2)\n ", "describe": { @@ -1206,6 +1248,51 @@ "nullable": [] } }, + "447350097928db863d47d756354cd52668f52f7156dd7f3673a826f7b9aca2fd": { + "query": "\n SELECT gv.id id, gv.version version_, gv.type type_, gv.created created, gv.major major FROM game_versions gv\n WHERE major = $1 AND type = $2\n ORDER BY created DESC\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "version_", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "type_", + "type_info": "Varchar" + }, + { + "ordinal": 3, + "name": "created", + "type_info": "Timestamptz" + }, + { + "ordinal": 4, + "name": "major", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Bool", + "Text" + ] + }, + "nullable": [ + false, + false, + false, + false, + false + ] + } + }, "449920c44d498adf8b771973d6034dc97e1c7f3ff4d9d23599af432f294ed564": { "query": "\n INSERT INTO files (id, version_id, url, filename)\n VALUES ($1, $2, $3, $4)\n ", "describe": { @@ -2674,6 +2761,50 @@ ] } }, + "78a60cf0febcc6e35b8ffe38f2c021c13ab660c81c4775bbb26004d30242a1a8": { + "query": "\n SELECT gv.id id, gv.version version_, gv.type type_, gv.created created, gv.major major FROM game_versions gv\n WHERE major = $1\n ORDER BY created DESC\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "version_", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "type_", + "type_info": "Varchar" + }, + { + "ordinal": 3, + "name": "created", + "type_info": "Timestamptz" + }, + { + "ordinal": 4, + "name": "major", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Bool" + ] + }, + "nullable": [ + false, + false, + false, + false, + false + ] + } + }, "78bf8232ddae2db486b9ff791ea525af1330e6904740b2a943c4ae3466bf02d0": { "query": "\n SELECT game_version_id id FROM game_versions_versions\n WHERE joining_version_id = $1\n ", "describe": { @@ -3316,80 +3447,6 @@ ] } }, - "9782399687ae7a79ea2931e8d3eb38c5c786240d214ff7fd7d0ae39f2d683108": { - "query": "\n SELECT gv.id id, gv.version version_, gv.type type_, gv.created created FROM game_versions gv\n ORDER BY created DESC\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int4" - }, - { - "ordinal": 1, - "name": "version_", - "type_info": "Varchar" - }, - { - "ordinal": 2, - "name": "type_", - "type_info": "Varchar" - }, - { - "ordinal": 3, - "name": "created", - "type_info": "Timestamptz" - } - ], - "parameters": { - "Left": [] - }, - "nullable": [ - false, - false, - false, - false - ] - } - }, - "98841ab141b5133690c2d1d1a37de982b960a5d75d2aa98565fadb4a1ac206a1": { - "query": "\n SELECT gv.id id, gv.version version_, gv.type type_, gv.created created FROM game_versions gv\n WHERE type = $1\n ORDER BY created DESC\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int4" - }, - { - "ordinal": 1, - "name": "version_", - "type_info": "Varchar" - }, - { - "ordinal": 2, - "name": "type_", - "type_info": "Varchar" - }, - { - "ordinal": 3, - "name": "created", - "type_info": "Timestamptz" - } - ], - "parameters": { - "Left": [ - "Text" - ] - }, - "nullable": [ - false, - false, - false, - false - ] - } - }, "99a1eac69d7f5a5139703df431e6a5c3012a90143a8c635f93632f04d0bc41d4": { "query": "\n UPDATE mods\n SET wiki_url = $1\n WHERE (id = $2)\n ", "describe": { @@ -3932,45 +3989,6 @@ "nullable": [] } }, - "b90ec97f24315f2eeb918d4be26b3bfb1191548bb26626eee844314d25a894be": { - "query": "\n SELECT gv.id id, gv.version version_, gv.type type_, gv.created created FROM game_versions gv\n WHERE major = $1 AND type = $2\n ORDER BY created DESC\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int4" - }, - { - "ordinal": 1, - "name": "version_", - "type_info": "Varchar" - }, - { - "ordinal": 2, - "name": "type_", - "type_info": "Varchar" - }, - { - "ordinal": 3, - "name": "created", - "type_info": "Timestamptz" - } - ], - "parameters": { - "Left": [ - "Bool", - "Text" - ] - }, - "nullable": [ - false, - false, - false, - false - ] - } - }, "b9399840dbbf807a03d69b7fcb3bd479ef20920ab1e3c91706a1c2c7089f48e7": { "query": "\n INSERT INTO teams (id)\n VALUES ($1)\n ", "describe": { @@ -4760,44 +4778,6 @@ ] } }, - "d4f7661c0156b04720d83ec5d76d901dd1dff23b1c93c7e2fde650f43c8ed86a": { - "query": "\n SELECT gv.id id, gv.version version_, gv.type type_, gv.created created FROM game_versions gv\n WHERE major = $1\n ORDER BY created DESC\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int4" - }, - { - "ordinal": 1, - "name": "version_", - "type_info": "Varchar" - }, - { - "ordinal": 2, - "name": "type_", - "type_info": "Varchar" - }, - { - "ordinal": 3, - "name": "created", - "type_info": "Timestamptz" - } - ], - "parameters": { - "Left": [ - "Bool" - ] - }, - "nullable": [ - false, - false, - false, - false - ] - } - }, "d5b00d6237b04018822db529995f0b001cd1cabf5ca93b4aff37f12c4feb83f6": { "query": "\n INSERT INTO donation_platforms (short, name)\n VALUES ($1, $2)\n ON CONFLICT (short) DO NOTHING\n RETURNING id\n ", "describe": { @@ -5546,6 +5526,50 @@ ] } }, + "e8ad94314ec2972c3102041b1bf06872c8e4c8a55156a17334a0e317fe41b784": { + "query": "\n SELECT gv.id id, gv.version version_, gv.type type_, gv.created created, gv.major major FROM game_versions gv\n WHERE type = $1\n ORDER BY created DESC\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "version_", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "type_", + "type_info": "Varchar" + }, + { + "ordinal": 3, + "name": "created", + "type_info": "Timestamptz" + }, + { + "ordinal": 4, + "name": "major", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false, + false, + false, + false, + false + ] + } + }, "e8d4589132b094df1e7a3ca0440344fc8013c0d20b3c71a1142ccbee91fb3c70": { "query": "SELECT EXISTS(SELECT 1 FROM teams WHERE id=$1)", "describe": { diff --git a/src/database/models/categories.rs b/src/database/models/categories.rs index 96bbb9b3c..73ffcad4f 100644 --- a/src/database/models/categories.rs +++ b/src/database/models/categories.rs @@ -19,6 +19,7 @@ pub struct GameVersion { pub version: String, pub version_type: String, pub date: chrono::DateTime, + pub major: bool, } pub struct Category { @@ -496,7 +497,7 @@ impl GameVersion { { let result = sqlx::query!( " - SELECT gv.id id, gv.version version_, gv.type type_, gv.created created FROM game_versions gv + SELECT gv.id id, gv.version version_, gv.type type_, gv.created created, gv.major FROM game_versions gv ORDER BY created DESC " ) @@ -505,7 +506,8 @@ impl GameVersion { id: GameVersionId(c.id), version: c.version_, version_type: c.type_, - date: c.created + date: c.created, + major: c.major })) }) .try_collect::>() .await?; @@ -527,7 +529,7 @@ impl GameVersion { if let Some(major) = major_option { result = sqlx::query!( " - SELECT gv.id id, gv.version version_, gv.type type_, gv.created created FROM game_versions gv + SELECT gv.id id, gv.version version_, gv.type type_, gv.created created, gv.major major FROM game_versions gv WHERE major = $1 AND type = $2 ORDER BY created DESC ", @@ -539,14 +541,15 @@ impl GameVersion { id: GameVersionId(c.id), version: c.version_, version_type: c.type_, - date: c.created + date: c.created, + major: c.major, })) }) .try_collect::>() .await?; } else { result = sqlx::query!( " - SELECT gv.id id, gv.version version_, gv.type type_, gv.created created FROM game_versions gv + SELECT gv.id id, gv.version version_, gv.type type_, gv.created created, gv.major major FROM game_versions gv WHERE type = $1 ORDER BY created DESC ", @@ -557,7 +560,8 @@ impl GameVersion { id: GameVersionId(c.id), version: c.version_, version_type: c.type_, - date: c.created + date: c.created, + major: c.major, })) }) .try_collect::>() .await?; @@ -565,7 +569,7 @@ impl GameVersion { } else if let Some(major) = major_option { result = sqlx::query!( " - SELECT gv.id id, gv.version version_, gv.type type_, gv.created created FROM game_versions gv + SELECT gv.id id, gv.version version_, gv.type type_, gv.created created, gv.major major FROM game_versions gv WHERE major = $1 ORDER BY created DESC ", @@ -576,7 +580,8 @@ impl GameVersion { id: GameVersionId(c.id), version: c.version_, version_type: c.type_, - date: c.created + date: c.created, + major: c.major, })) }) .try_collect::>() .await?; diff --git a/src/database/models/project_item.rs b/src/database/models/project_item.rs index 40a1fd3ac..099cc0bf9 100644 --- a/src/database/models/project_item.rs +++ b/src/database/models/project_item.rs @@ -650,14 +650,20 @@ impl Project { .split(" ,") .map(|d| { let strings: Vec<&str> = d.split(", ").collect(); - DonationUrl { - project_id: id, - platform_id: DonationPlatformId(strings[0].parse().unwrap_or(0)), - platform_short: strings[2].to_string(), - platform_name: strings[3].to_string(), - url: strings[1].to_string(), + + if strings.len() >= 3 { + Some(DonationUrl { + project_id: id, + platform_id: DonationPlatformId(strings[0].parse().unwrap_or(0)), + platform_short: strings[2].to_string(), + platform_name: strings[3].to_string(), + url: strings[1].to_string(), + }) + } else { + None } }) + .flatten() .collect(), gallery_items: m .gallery @@ -755,14 +761,20 @@ impl Project { .split(" ,") .map(|d| { let strings: Vec<&str> = d.split(", ").collect(); - DonationUrl { - project_id: ProjectId(id), - platform_id: DonationPlatformId(strings[0].parse().unwrap_or(0)), - platform_short: strings[2].to_string(), - platform_name: strings[3].to_string(), - url: strings[1].to_string(), + + if strings.len() >= 3 { + Some(DonationUrl { + project_id: ProjectId(id), + platform_id: DonationPlatformId(strings[0].parse().unwrap_or(0)), + platform_short: strings[2].to_string(), + platform_name: strings[3].to_string(), + url: strings[1].to_string(), + }) + } else { + None } }) + .flatten() .collect(), gallery_items: m.gallery.iter().map(|x| GalleryItem { project_id: ProjectId(id), diff --git a/src/database/models/version_item.rs b/src/database/models/version_item.rs index bbf536459..9be30175f 100644 --- a/src/database/models/version_item.rs +++ b/src/database/models/version_item.rs @@ -626,73 +626,25 @@ impl Version { .await?; if let Some(v) = result { - let mut hashes: Vec<(FileId, String, Vec)> = Vec::new(); - - v.hashes.unwrap_or_default().split(" ,").for_each(|f| { - let hash: Vec<&str> = f.split(", ").collect(); - - if hash.len() >= 3 { - hashes.push(( - FileId(hash[2].parse().unwrap_or(0)), - hash[0].to_string(), - hash[1].to_string().into_bytes(), - )); - } - }); - - let mut files = Vec::new(); - - v.files.unwrap_or_default().split(" ,").for_each(|f| { - let file: Vec<&str> = f.split(", ").collect(); - - if file.len() >= 4 { - let file_id = FileId(file[0].parse().unwrap_or(0)); - let mut file_hashes = HashMap::new(); - - for hash in &hashes { - if (hash.0).0 == file_id.0 { - file_hashes.insert(hash.1.clone(), hash.2.clone()); - } - } - - files.push(QueryFile { - id: file_id, - url: file[3].to_string(), - filename: file[1].to_string(), - hashes: file_hashes, - primary: file[2].parse().unwrap_or(false), - }) - } - }); - - let mut dependencies = Vec::new(); - - v.dependencies + let hashes: Vec<(FileId, String, Vec)> = v + .hashes .unwrap_or_default() .split(" ,") - .for_each(|f| { - let dependency: Vec<&str> = f.split(", ").collect(); + .map(|f| { + let hash: Vec<&str> = f.split(", ").collect(); - if dependency.len() >= 3 { - dependencies.push(QueryDependency { - project_id: match &*dependency[2] { - "0" => None, - _ => match dependency[2].parse() { - Ok(x) => Some(ProjectId(x)), - Err(_) => None, - }, - }, - version_id: match &*dependency[0] { - "0" => None, - _ => match dependency[0].parse() { - Ok(x) => Some(VersionId(x)), - Err(_) => None, - }, - }, - dependency_type: dependency[1].to_string(), - }); + if hash.len() >= 3 { + Some(( + FileId(hash[2].parse().unwrap_or(0)), + hash[0].to_string(), + hash[1].to_string().into_bytes(), + )) + } else { + None } - }); + }) + .flatten() + .collect(); Ok(Some(QueryVersion { id: VersionId(v.id), @@ -705,7 +657,36 @@ impl Version { date_published: v.date_published, downloads: v.downloads, release_channel: v.release_channel, - files, + files: v + .files + .unwrap_or_default() + .split(" ,") + .map(|f| { + let file: Vec<&str> = f.split(", ").collect(); + + if file.len() >= 4 { + let file_id = FileId(file[0].parse().unwrap_or(0)); + let mut file_hashes = HashMap::new(); + + for hash in &hashes { + if (hash.0).0 == file_id.0 { + file_hashes.insert(hash.1.clone(), hash.2.clone()); + } + } + + Some(QueryFile { + id: file_id, + url: file[3].to_string(), + filename: file[1].to_string(), + hashes: file_hashes, + primary: file[2].parse().unwrap_or(false), + }) + } else { + None + } + }) + .flatten() + .collect(), game_versions: v .game_versions .unwrap_or_default() @@ -719,7 +700,37 @@ impl Version { .map(|x| x.to_string()) .collect(), featured: v.featured, - dependencies, + dependencies: v + .dependencies + .unwrap_or_default() + .split(" ,") + .map(|f| { + let dependency: Vec<&str> = f.split(", ").collect(); + + if dependency.len() >= 3 { + Some(QueryDependency { + project_id: match &*dependency[2] { + "0" => None, + _ => match dependency[2].parse() { + Ok(x) => Some(ProjectId(x)), + Err(_) => None, + }, + }, + version_id: match &*dependency[0] { + "0" => None, + _ => match dependency[0].parse() { + Ok(x) => Some(VersionId(x)), + Err(_) => None, + }, + }, + dependency_type: dependency[1].to_string(), + }) + } else { + None + } + }) + .flatten() + .collect(), })) } else { Ok(None) @@ -763,74 +774,19 @@ impl Version { .fetch_many(exec) .try_filter_map(|e| async { Ok(e.right().map(|v| { - let mut hashes : Vec<(FileId, String, Vec)> = Vec::new(); - - v.hashes.unwrap_or_default().split(" ,").for_each(|f| { + let hashes: Vec<(FileId, String, Vec)> = v.hashes.unwrap_or_default().split(" ,").map(|f| { let hash: Vec<&str> = f.split(", ").collect(); if hash.len() >= 3 { - hashes.push(( + Some(( FileId(hash[2].parse().unwrap_or(0)), hash[0].to_string(), hash[1].to_string().into_bytes(), - )); + )) + } else { + None } - }); - - let mut files = Vec::new(); - - v.files.unwrap_or_default().split(" ,").for_each(|f| { - let file : Vec<&str> = f.split(", ").collect(); - - if file.len() >= 4 { - let file_id = FileId(file[0].parse().unwrap_or(0)); - let mut file_hashes = HashMap::new(); - - for hash in &hashes { - if (hash.0).0 == file_id.0 { - file_hashes.insert(hash.1.clone(), hash.2.clone()); - } - } - - files.push(QueryFile { - id: file_id, - url: file[3].to_string(), - filename: file[1].to_string(), - hashes: file_hashes, - primary: file[2].parse().unwrap_or(false) - }) - } - }); - - let mut dependencies = Vec::new(); - - v.dependencies.unwrap_or_default().split(" ,").for_each(|f| { - let dependency: Vec<&str> = f.split(", ").collect(); - - if dependency.len() >= 3 { - dependencies.push(QueryDependency { - project_id: match &*dependency[2] { - "0" => None, - _ => { - match dependency[2].parse() { - Ok(x) => Some(ProjectId(x)), - Err(_) => None, - } - }, - }, - version_id: match &*dependency[0] { - "0" => None, - _ => { - match dependency[0].parse() { - Ok(x) => Some(VersionId(x)), - Err(_) => None, - } - }, - }, - dependency_type: dependency[1].to_string() - }); - } - }); + }).flatten().collect(); QueryVersion { id: VersionId(v.id), @@ -843,11 +799,61 @@ impl Version { date_published: v.date_published, downloads: v.downloads, release_channel: v.release_channel, - files, + files: v.files.unwrap_or_default().split(" ,").map(|f| { + let file: Vec<&str> = f.split(", ").collect(); + + if file.len() >= 4 { + let file_id = FileId(file[0].parse().unwrap_or(0)); + let mut file_hashes = HashMap::new(); + + for hash in &hashes { + if (hash.0).0 == file_id.0 { + file_hashes.insert(hash.1.clone(), hash.2.clone()); + } + } + + Some(QueryFile { + id: file_id, + url: file[3].to_string(), + filename: file[1].to_string(), + hashes: file_hashes, + primary: file[2].parse().unwrap_or(false), + }) + } else { + None + } + }).flatten().collect(), game_versions: v.game_versions.unwrap_or_default().split(',').map(|x| x.to_string()).collect(), loaders: v.loaders.unwrap_or_default().split(',').map(|x| x.to_string()).collect(), featured: v.featured, - dependencies, + dependencies: v.dependencies + .unwrap_or_default() + .split(" ,") + .map(|f| { + let dependency: Vec<&str> = f.split(", ").collect(); + + if dependency.len() >= 3 { + Some(QueryDependency { + project_id: match &*dependency[2] { + "0" => None, + _ => match dependency[2].parse() { + Ok(x) => Some(ProjectId(x)), + Err(_) => None, + }, + }, + version_id: match &*dependency[0] { + "0" => None, + _ => match dependency[0].parse() { + Ok(x) => Some(VersionId(x)), + Err(_) => None, + }, + }, + dependency_type: dependency[1].to_string(), + }) + } else { + None + } + }).flatten().collect(), } })) }) diff --git a/src/routes/tags.rs b/src/routes/tags.rs index cbdffa1e2..e7b80f7f5 100644 --- a/src/routes/tags.rs +++ b/src/routes/tags.rs @@ -185,6 +185,7 @@ pub struct GameVersionQueryData { pub version: String, pub version_type: String, pub date: chrono::DateTime, + pub major: bool, } #[derive(serde::Deserialize)] @@ -209,6 +210,7 @@ pub async fn game_version_list( version: x.version, version_type: x.version_type, date: x.date, + major: x.major, }) .collect();