From c87e72e08e475bac9c26741105a408988c33218e Mon Sep 17 00:00:00 2001 From: Geometrically <18202329+Geometrically@users.noreply.github.com> Date: Wed, 1 Sep 2021 06:04:38 -0700 Subject: [PATCH] Switch to alternate query strategy which simplifies code (#244) --- sqlx-data.json | 1778 ++++++++++------------ src/database/models/ids.rs | 2 +- src/database/models/notification_item.rs | 172 +-- src/database/models/project_item.rs | 290 +--- src/database/models/version_item.rs | 313 ++-- src/routes/version_creation.rs | 4 +- src/search/indexing/local_import.rs | 34 +- 7 files changed, 1029 insertions(+), 1564 deletions(-) diff --git a/sqlx-data.json b/sqlx-data.json index 619aa29f6..9269b5302 100644 --- a/sqlx-data.json +++ b/sqlx-data.json @@ -366,116 +366,6 @@ ] } }, - "1560f729dd0cea789956345329c09bdb115392fa6a1d571a00985f3c9d7afdee": { - "query": "\n SELECT v.id id, v.mod_id mod_id, v.author_id author_id, v.name version_name, v.version_number version_number,\n v.changelog changelog, v.changelog_url changelog_url, v.date_published date_published, v.downloads downloads,\n v.version_type version_type, v.featured featured,\n ARRAY_AGG(DISTINCT gv.version) game_versions, ARRAY_AGG(DISTINCT l.loader) loaders,\n ARRAY_AGG(DISTINCT f.id || ', ' || f.filename || ', ' || f.is_primary || ', ' || f.url) files,\n ARRAY_AGG(DISTINCT h.algorithm || ', ' || encode(h.hash, 'escape') || ', ' || h.file_id) hashes,\n ARRAY_AGG(DISTINCT COALESCE(d.dependency_id, 0) || ', ' || COALESCE(d.mod_dependency_id, 0) || ', ' || d.dependency_type) dependencies\n FROM versions v\n LEFT OUTER JOIN game_versions_versions gvv on v.id = gvv.joining_version_id\n LEFT OUTER JOIN game_versions gv on gvv.game_version_id = gv.id\n LEFT OUTER JOIN loaders_versions lv on v.id = lv.version_id\n LEFT OUTER JOIN loaders l on lv.loader_id = l.id\n LEFT OUTER JOIN files f on v.id = f.version_id\n LEFT OUTER JOIN hashes h on f.id = h.file_id\n LEFT OUTER JOIN dependencies d on v.id = d.dependent_id\n WHERE v.id = $1\n GROUP BY v.id;\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int8" - }, - { - "ordinal": 1, - "name": "mod_id", - "type_info": "Int8" - }, - { - "ordinal": 2, - "name": "author_id", - "type_info": "Int8" - }, - { - "ordinal": 3, - "name": "version_name", - "type_info": "Varchar" - }, - { - "ordinal": 4, - "name": "version_number", - "type_info": "Varchar" - }, - { - "ordinal": 5, - "name": "changelog", - "type_info": "Varchar" - }, - { - "ordinal": 6, - "name": "changelog_url", - "type_info": "Varchar" - }, - { - "ordinal": 7, - "name": "date_published", - "type_info": "Timestamptz" - }, - { - "ordinal": 8, - "name": "downloads", - "type_info": "Int4" - }, - { - "ordinal": 9, - "name": "version_type", - "type_info": "Varchar" - }, - { - "ordinal": 10, - "name": "featured", - "type_info": "Bool" - }, - { - "ordinal": 11, - "name": "game_versions", - "type_info": "VarcharArray" - }, - { - "ordinal": 12, - "name": "loaders", - "type_info": "VarcharArray" - }, - { - "ordinal": 13, - "name": "files", - "type_info": "TextArray" - }, - { - "ordinal": 14, - "name": "hashes", - "type_info": "TextArray" - }, - { - "ordinal": 15, - "name": "dependencies", - "type_info": "TextArray" - } - ], - "parameters": { - "Left": [ - "Int8" - ] - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - true, - false, - false, - false, - false, - null, - null, - null, - null, - null - ] - } - }, "15b8ea323c2f6d03c2e385d9c46d7f13460764f2f106fd638226c42ae0217f75": { "query": "\n DELETE FROM notifications\n WHERE user_id = $1\n ", "describe": { @@ -819,6 +709,26 @@ ] } }, + "26a4ea4c0bbe4aea0d4db17bb7f80e6b6336ee7d4df503915cd6494ab72c05f2": { + "query": "\n SELECT l.loader loader\n FROM loaders_versions lv\n INNER JOIN loaders l on lv.loader_id = l.id\n WHERE lv.version_id = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "loader", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false + ] + } + }, "27a35fca63dfc3801f95958604f0ac27afd81800e2dc981382d6f923c4415d32": { "query": "\n DELETE FROM notifications_actions\n WHERE notification_id = ANY($1)\n ", "describe": { @@ -869,6 +779,50 @@ "nullable": [] } }, + "2c7c46497580e96c2ede1a696c960a8f53af9b8d0fc995484618b9090add8890": { + "query": "\n SELECT id, title, notification_id, action_route, action_route_method\n FROM notifications_actions\n WHERE notification_id = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "title", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "notification_id", + "type_info": "Int8" + }, + { + "ordinal": 3, + "name": "action_route", + "type_info": "Varchar" + }, + { + "ordinal": 4, + "name": "action_route_method", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + false, + false, + false, + false + ] + } + }, "2d2e5b06be5125226ed9e4d7b7b5f99043db73537f2199f2146bdcd56091ae75": { "query": "\n INSERT INTO team_members (id, team_id, user_id, role, permissions, accepted)\n VALUES ($1, $2, $3, $4, $5, $6)\n ", "describe": { @@ -1218,6 +1172,38 @@ "nullable": [] } }, + "47161ce6a3ccb92e795786d05db9c12377f4bf03d3ffcd798866fea8c46322da": { + "query": "\n SELECT h.algorithm algorithm, encode(h.hash, 'escape') hash, h.file_id file_id\n FROM files f\n INNER JOIN hashes h ON h.file_id = f.id\n WHERE f.version_id = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "algorithm", + "type_info": "Varchar" + }, + { + "ordinal": 1, + "name": "hash", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "file_id", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + null, + false + ] + } + }, "48294a4e0c594e80fff8d14a705aa7282f55e47cf3772e77f1d4bf4849008b60": { "query": "\n SELECT follower_id FROM mod_follows\n WHERE mod_id = $1\n ", "describe": { @@ -1500,116 +1486,6 @@ "nullable": [] } }, - "508e8432059af8bea725c40208ec0dd6b080946a5d634d413c978940660c82ab": { - "query": "\n SELECT v.id id, v.mod_id mod_id, v.author_id author_id, v.name version_name, v.version_number version_number,\n v.changelog changelog, v.changelog_url changelog_url, v.date_published date_published, v.downloads downloads,\n v.version_type version_type, v.featured featured,\n ARRAY_AGG(DISTINCT gv.version) game_versions, ARRAY_AGG(DISTINCT l.loader) loaders,\n ARRAY_AGG(DISTINCT f.id || ', ' || f.filename || ', ' || f.is_primary || ', ' || f.url) files,\n ARRAY_AGG(DISTINCT h.algorithm || ', ' || encode(h.hash, 'escape') || ', ' || h.file_id) hashes,\n ARRAY_AGG(DISTINCT COALESCE(d.dependency_id, 0) || ', ' || COALESCE(d.mod_dependency_id, 0) || ', ' || d.dependency_type) dependencies\n FROM versions v\n LEFT OUTER JOIN game_versions_versions gvv on v.id = gvv.joining_version_id\n LEFT OUTER JOIN game_versions gv on gvv.game_version_id = gv.id\n LEFT OUTER JOIN loaders_versions lv on v.id = lv.version_id\n LEFT OUTER JOIN loaders l on lv.loader_id = l.id\n LEFT OUTER JOIN files f on v.id = f.version_id\n LEFT OUTER JOIN hashes h on f.id = h.file_id\n LEFT OUTER JOIN dependencies d on v.id = d.dependent_id\n WHERE v.id = ANY($1)\n GROUP BY v.id\n ORDER BY v.date_published ASC;\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int8" - }, - { - "ordinal": 1, - "name": "mod_id", - "type_info": "Int8" - }, - { - "ordinal": 2, - "name": "author_id", - "type_info": "Int8" - }, - { - "ordinal": 3, - "name": "version_name", - "type_info": "Varchar" - }, - { - "ordinal": 4, - "name": "version_number", - "type_info": "Varchar" - }, - { - "ordinal": 5, - "name": "changelog", - "type_info": "Varchar" - }, - { - "ordinal": 6, - "name": "changelog_url", - "type_info": "Varchar" - }, - { - "ordinal": 7, - "name": "date_published", - "type_info": "Timestamptz" - }, - { - "ordinal": 8, - "name": "downloads", - "type_info": "Int4" - }, - { - "ordinal": 9, - "name": "version_type", - "type_info": "Varchar" - }, - { - "ordinal": 10, - "name": "featured", - "type_info": "Bool" - }, - { - "ordinal": 11, - "name": "game_versions", - "type_info": "VarcharArray" - }, - { - "ordinal": 12, - "name": "loaders", - "type_info": "VarcharArray" - }, - { - "ordinal": 13, - "name": "files", - "type_info": "TextArray" - }, - { - "ordinal": 14, - "name": "hashes", - "type_info": "TextArray" - }, - { - "ordinal": 15, - "name": "dependencies", - "type_info": "TextArray" - } - ], - "parameters": { - "Left": [ - "Int8Array" - ] - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - true, - false, - false, - false, - false, - null, - null, - null, - null, - null - ] - } - }, "53a8966ac345cc334ad65ea907be81af74e90b1217696c7eedcf8a8e3fca736e": { "query": "\n UPDATE versions\n SET version_number = $1\n WHERE (id = $2)\n ", "describe": { @@ -1831,6 +1707,68 @@ "nullable": [] } }, + "59db001df11e9730d089eca19a73ca6f934c6fd199e6411955072c767f9a2551": { + "query": "\n SELECT n.user_id, n.title, n.text, n.link, n.created, n.read, n.type notification_type,\n ARRAY_AGG(DISTINCT na.id || ', ' || na.title || ', ' || na.action_route || ', ' || na.action_route_method) actions\n FROM notifications n\n LEFT OUTER JOIN notifications_actions na on n.id = na.notification_id\n WHERE n.id = $1\n GROUP BY n.id, n.user_id;\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "user_id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "title", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "text", + "type_info": "Varchar" + }, + { + "ordinal": 3, + "name": "link", + "type_info": "Varchar" + }, + { + "ordinal": 4, + "name": "created", + "type_info": "Timestamptz" + }, + { + "ordinal": 5, + "name": "read", + "type_info": "Bool" + }, + { + "ordinal": 6, + "name": "notification_type", + "type_info": "Varchar" + }, + { + "ordinal": 7, + "name": "actions", + "type_info": "TextArray" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + false, + false, + false, + false, + false, + true, + null + ] + } + }, "5a03c653f1ff3339a01422ee4267a66157e6da9a51cc7d9beb0f87d59c3a444c": { "query": "\n SELECT d.dependent_id, d.dependency_id, d.mod_dependency_id\n FROM versions v\n INNER JOIN dependencies d ON d.dependent_id = v.id\n WHERE v.mod_id = $1\n ", "describe": { @@ -1953,8 +1891,8 @@ ] } }, - "5bda46260568ea941e3adaa722d38d1beb8c67be881eeeec56556f6206a43736": { - "query": "\n SELECT m.id id, m.project_type project_type, m.title title, m.description description, m.downloads downloads, m.follows follows,\n m.icon_url icon_url, m.body body, m.body_url body_url, m.published published,\n m.updated updated, m.status status,\n m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url,\n m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body,\n s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, l.name license_name, pt.name project_type_name,\n ARRAY_AGG(DISTINCT c.category) categories, ARRAY_AGG(DISTINCT v.id::text) versions,\n ARRAY_AGG(DISTINCT mg.image_url || ', ' || mg.featured || ', ' || COALESCE(mg.title, '') || ', ' || COALESCE(mg.description, '') || ', ' || mg.created) gallery,\n ARRAY_AGG(DISTINCT md.joining_platform_id || ', ' || md.url || ', ' || dp.short || ', ' || dp.name) donations\n FROM mods m\n INNER JOIN project_types pt ON pt.id = m.project_type\n INNER JOIN statuses s ON s.id = m.status\n INNER JOIN side_types cs ON m.client_side = cs.id\n INNER JOIN side_types ss ON m.server_side = ss.id\n INNER JOIN licenses l ON m.license = l.id\n LEFT JOIN mods_donations md ON md.joining_mod_id = m.id\n LEFT JOIN donation_platforms dp ON md.joining_platform_id = dp.id\n LEFT JOIN mods_categories mc ON mc.joining_mod_id = m.id\n LEFT JOIN categories c ON mc.joining_category_id = c.id\n LEFT JOIN versions v ON v.mod_id = m.id\n LEFT JOIN mods_gallery mg ON mg.mod_id = m.id\n WHERE m.id = $1\n GROUP BY pt.id, s.id, cs.id, ss.id, l.id, m.id;\n ", + "5b8ba75c6a3d7a3cb68885e213aa9145cf014ddcd13f3a385fb4c0b9f8f7483a": { + "query": "\n SELECT m.id id, m.project_type project_type, m.title title, m.description description, m.downloads downloads, m.follows follows,\n m.icon_url icon_url, m.published published,\n m.updated updated,\n m.team_id team_id, m.license license, m.slug slug,\n s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, pt.name project_type_name, u.username username,\n STRING_AGG(DISTINCT c.category, ',') categories, STRING_AGG(DISTINCT lo.loader, ',') loaders, STRING_AGG(DISTINCT gv.version, ',') versions,\n STRING_AGG(DISTINCT mg.image_url, ',') gallery\n FROM mods m\n LEFT OUTER JOIN mods_categories mc ON joining_mod_id = m.id\n LEFT OUTER JOIN categories c ON mc.joining_category_id = c.id\n LEFT OUTER JOIN versions v ON v.mod_id = m.id\n LEFT OUTER JOIN game_versions_versions gvv ON gvv.joining_version_id = v.id\n LEFT OUTER JOIN game_versions gv ON gvv.game_version_id = gv.id\n LEFT OUTER JOIN loaders_versions lv ON lv.version_id = v.id\n LEFT OUTER JOIN loaders lo ON lo.id = lv.loader_id\n LEFT OUTER JOIN mods_gallery mg ON mg.mod_id = m.id\n INNER JOIN statuses s ON s.id = m.status\n INNER JOIN project_types pt ON pt.id = m.project_type\n INNER JOIN side_types cs ON m.client_side = cs.id\n INNER JOIN side_types ss ON m.server_side = ss.id\n INNER JOIN licenses l ON m.license = l.id\n INNER JOIN team_members tm ON tm.team_id = m.team_id AND tm.role = $2\n INNER JOIN users u ON tm.user_id = u.id\n WHERE s.status = $1\n GROUP BY m.id, s.id, cs.id, ss.id, l.id, pt.id, u.id;\n ", "describe": { "columns": [ { @@ -1994,143 +1932,84 @@ }, { "ordinal": 7, - "name": "body", - "type_info": "Varchar" - }, - { - "ordinal": 8, - "name": "body_url", - "type_info": "Varchar" - }, - { - "ordinal": 9, "name": "published", "type_info": "Timestamptz" }, { - "ordinal": 10, + "ordinal": 8, "name": "updated", "type_info": "Timestamptz" }, { - "ordinal": 11, - "name": "status", - "type_info": "Int4" - }, - { - "ordinal": 12, - "name": "issues_url", - "type_info": "Varchar" - }, - { - "ordinal": 13, - "name": "source_url", - "type_info": "Varchar" - }, - { - "ordinal": 14, - "name": "wiki_url", - "type_info": "Varchar" - }, - { - "ordinal": 15, - "name": "discord_url", - "type_info": "Varchar" - }, - { - "ordinal": 16, - "name": "license_url", - "type_info": "Varchar" - }, - { - "ordinal": 17, + "ordinal": 9, "name": "team_id", "type_info": "Int8" }, { - "ordinal": 18, - "name": "client_side", - "type_info": "Int4" - }, - { - "ordinal": 19, - "name": "server_side", - "type_info": "Int4" - }, - { - "ordinal": 20, + "ordinal": 10, "name": "license", "type_info": "Int4" }, { - "ordinal": 21, + "ordinal": 11, "name": "slug", "type_info": "Varchar" }, { - "ordinal": 22, - "name": "moderation_message", - "type_info": "Varchar" - }, - { - "ordinal": 23, - "name": "moderation_message_body", - "type_info": "Varchar" - }, - { - "ordinal": 24, + "ordinal": 12, "name": "status_name", "type_info": "Varchar" }, { - "ordinal": 25, + "ordinal": 13, "name": "client_side_type", "type_info": "Varchar" }, { - "ordinal": 26, + "ordinal": 14, "name": "server_side_type", "type_info": "Varchar" }, { - "ordinal": 27, + "ordinal": 15, "name": "short", "type_info": "Varchar" }, { - "ordinal": 28, - "name": "license_name", - "type_info": "Varchar" - }, - { - "ordinal": 29, + "ordinal": 16, "name": "project_type_name", "type_info": "Varchar" }, { - "ordinal": 30, + "ordinal": 17, + "name": "username", + "type_info": "Varchar" + }, + { + "ordinal": 18, "name": "categories", - "type_info": "VarcharArray" + "type_info": "Text" }, { - "ordinal": 31, + "ordinal": 19, + "name": "loaders", + "type_info": "Text" + }, + { + "ordinal": 20, "name": "versions", - "type_info": "TextArray" + "type_info": "Text" }, { - "ordinal": 32, + "ordinal": 21, "name": "gallery", - "type_info": "TextArray" - }, - { - "ordinal": 33, - "name": "donations", - "type_info": "TextArray" + "type_info": "Text" } ], "parameters": { "Left": [ - "Int8" + "Text", + "Text" ] }, "nullable": [ @@ -2142,22 +2021,10 @@ false, true, false, - true, false, false, false, true, - true, - true, - true, - true, - false, - false, - false, - false, - true, - true, - true, false, false, false, @@ -2336,6 +2203,44 @@ "nullable": [] } }, + "6326543f7cbd0ce03bbfe234ee82ca1b61d411589dc2d61753598679942cfdd8": { + "query": "\n SELECT md.url url, dp.id platform_id, dp.name dp_name, dp.short short\n FROM mods_donations md\n INNER JOIN donation_platforms dp ON md.joining_platform_id = dp.id\n WHERE md.joining_mod_id = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "url", + "type_info": "Varchar" + }, + { + "ordinal": 1, + "name": "platform_id", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "dp_name", + "type_info": "Varchar" + }, + { + "ordinal": 3, + "name": "short", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + } + }, "67d021f0776276081d3c50ca97afa6b78b98860bf929009e845e9c00a192e3b5": { "query": "\n SELECT id FROM report_types\n WHERE name = $1\n ", "describe": { @@ -2818,6 +2723,26 @@ "nullable": [] } }, + "7be4ba7c3dd53abd79715b9a9ead6b8815a2e4994f6887ac853f832c5ca17150": { + "query": "\n SELECT id\n FROM notifications\n WHERE user_id = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false + ] + } + }, "7c61fee015231f0a97c25d24f2c6be24821e39e330ab82344ad3b985d0d2aaea": { "query": "\n SELECT id FROM mods_gallery\n WHERE image_url = $1\n ", "describe": { @@ -2838,153 +2763,6 @@ ] } }, - "7e7144d89439f18e1c9074e66a1198431a49813f8472d3497baf90b1e29f493c": { - "query": "\n SELECT m.id id, m.project_type project_type, m.title title, m.description description, m.downloads downloads, m.follows follows,\n m.icon_url icon_url, m.published published,\n m.updated updated,\n m.team_id team_id, m.license license, m.slug slug,\n s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, pt.name project_type_name, u.username username,\n ARRAY_AGG(DISTINCT c.category) categories, ARRAY_AGG(DISTINCT lo.loader) loaders, ARRAY_AGG(DISTINCT gv.version) versions,\n ARRAY_AGG(DISTINCT mg.image_url) gallery\n FROM mods m\n LEFT OUTER JOIN mods_categories mc ON joining_mod_id = m.id\n LEFT OUTER JOIN categories c ON mc.joining_category_id = c.id\n LEFT OUTER JOIN versions v ON v.mod_id = m.id\n LEFT OUTER JOIN game_versions_versions gvv ON gvv.joining_version_id = v.id\n LEFT OUTER JOIN game_versions gv ON gvv.game_version_id = gv.id\n LEFT OUTER JOIN loaders_versions lv ON lv.version_id = v.id\n LEFT OUTER JOIN loaders lo ON lo.id = lv.loader_id\n LEFT OUTER JOIN mods_gallery mg ON mg.mod_id = m.id\n INNER JOIN statuses s ON s.id = m.status\n INNER JOIN project_types pt ON pt.id = m.project_type\n INNER JOIN side_types cs ON m.client_side = cs.id\n INNER JOIN side_types ss ON m.server_side = ss.id\n INNER JOIN licenses l ON m.license = l.id\n INNER JOIN team_members tm ON tm.team_id = m.team_id AND tm.role = $2\n INNER JOIN users u ON tm.user_id = u.id\n WHERE m.id = $1\n GROUP BY m.id, s.id, cs.id, ss.id, l.id, pt.id, u.id;\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int8" - }, - { - "ordinal": 1, - "name": "project_type", - "type_info": "Int4" - }, - { - "ordinal": 2, - "name": "title", - "type_info": "Varchar" - }, - { - "ordinal": 3, - "name": "description", - "type_info": "Varchar" - }, - { - "ordinal": 4, - "name": "downloads", - "type_info": "Int4" - }, - { - "ordinal": 5, - "name": "follows", - "type_info": "Int4" - }, - { - "ordinal": 6, - "name": "icon_url", - "type_info": "Varchar" - }, - { - "ordinal": 7, - "name": "published", - "type_info": "Timestamptz" - }, - { - "ordinal": 8, - "name": "updated", - "type_info": "Timestamptz" - }, - { - "ordinal": 9, - "name": "team_id", - "type_info": "Int8" - }, - { - "ordinal": 10, - "name": "license", - "type_info": "Int4" - }, - { - "ordinal": 11, - "name": "slug", - "type_info": "Varchar" - }, - { - "ordinal": 12, - "name": "status_name", - "type_info": "Varchar" - }, - { - "ordinal": 13, - "name": "client_side_type", - "type_info": "Varchar" - }, - { - "ordinal": 14, - "name": "server_side_type", - "type_info": "Varchar" - }, - { - "ordinal": 15, - "name": "short", - "type_info": "Varchar" - }, - { - "ordinal": 16, - "name": "project_type_name", - "type_info": "Varchar" - }, - { - "ordinal": 17, - "name": "username", - "type_info": "Varchar" - }, - { - "ordinal": 18, - "name": "categories", - "type_info": "VarcharArray" - }, - { - "ordinal": 19, - "name": "loaders", - "type_info": "VarcharArray" - }, - { - "ordinal": 20, - "name": "versions", - "type_info": "VarcharArray" - }, - { - "ordinal": 21, - "name": "gallery", - "type_info": "VarcharArray" - } - ], - "parameters": { - "Left": [ - "Int8", - "Text" - ] - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - true, - false, - false, - false, - false, - true, - false, - false, - false, - false, - false, - false, - null, - null, - null, - null - ] - } - }, "7e73d3a17807f57ba6def5ff718e6dcb3a65ef8da653d839560b24635334cf05": { "query": "\n SELECT m.title FROM mods m\n WHERE id = $1\n ", "describe": { @@ -3105,74 +2883,6 @@ ] } }, - "84a77bc028646d6698d87682317fcb23f8db4fee5e2bcd2a0de5b68b9d83ae9d": { - "query": "\n SELECT n.id, n.user_id, n.title, n.text, n.link, n.created, n.read, n.type notification_type,\n ARRAY_AGG(DISTINCT na.id || ', ' || na.title || ', ' || na.action_route || ', ' || na.action_route_method) actions\n FROM notifications n\n LEFT OUTER JOIN notifications_actions na on n.id = na.notification_id\n WHERE n.id = ANY($1)\n GROUP BY n.id, n.user_id\n ORDER BY n.created DESC;\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int8" - }, - { - "ordinal": 1, - "name": "user_id", - "type_info": "Int8" - }, - { - "ordinal": 2, - "name": "title", - "type_info": "Varchar" - }, - { - "ordinal": 3, - "name": "text", - "type_info": "Varchar" - }, - { - "ordinal": 4, - "name": "link", - "type_info": "Varchar" - }, - { - "ordinal": 5, - "name": "created", - "type_info": "Timestamptz" - }, - { - "ordinal": 6, - "name": "read", - "type_info": "Bool" - }, - { - "ordinal": 7, - "name": "notification_type", - "type_info": "Varchar" - }, - { - "ordinal": 8, - "name": "actions", - "type_info": "TextArray" - } - ], - "parameters": { - "Left": [ - "Int8Array" - ] - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - false, - true, - null - ] - } - }, "87fd169e19ba231c6cf131ad2841d5c3b95adde53e5ed4000f8e7d54c0e87320": { "query": "\n DELETE FROM project_types\n WHERE name = $1\n ", "describe": { @@ -3421,224 +3131,6 @@ ] } }, - "8d4cdf8218485e8ef11ad2d94faa950e09ccd435d38eb3e877b1c91f12c5e815": { - "query": "\n SELECT m.id id, m.project_type project_type, m.title title, m.description description, m.downloads downloads, m.follows follows,\n m.icon_url icon_url, m.body body, m.body_url body_url, m.published published,\n m.updated updated, m.status status,\n m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url,\n m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body,\n s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, l.name license_name, pt.name project_type_name,\n ARRAY_AGG(DISTINCT c.category) categories, ARRAY_AGG(DISTINCT v.id::text) versions,\n ARRAY_AGG(DISTINCT mg.image_url || ', ' || mg.featured || ', ' || COALESCE(mg.title, '') || ', ' || COALESCE(mg.description, '') || ', ' || mg.created) gallery,\n ARRAY_AGG(DISTINCT md.joining_platform_id || ', ' || md.url || ', ' || dp.short || ', ' || dp.name) donations\n FROM mods m\n INNER JOIN project_types pt ON pt.id = m.project_type\n INNER JOIN statuses s ON s.id = m.status\n INNER JOIN side_types cs ON m.client_side = cs.id\n INNER JOIN side_types ss ON m.server_side = ss.id\n INNER JOIN licenses l ON m.license = l.id\n LEFT JOIN mods_donations md ON md.joining_mod_id = m.id\n LEFT JOIN donation_platforms dp ON md.joining_platform_id = dp.id\n LEFT JOIN mods_categories mc ON mc.joining_mod_id = m.id\n LEFT JOIN categories c ON mc.joining_category_id = c.id\n LEFT JOIN versions v ON v.mod_id = m.id\n LEFT JOIN mods_gallery mg ON mg.mod_id = m.id\n WHERE m.id = ANY($1)\n GROUP BY pt.id, s.id, cs.id, ss.id, l.id, m.id;\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int8" - }, - { - "ordinal": 1, - "name": "project_type", - "type_info": "Int4" - }, - { - "ordinal": 2, - "name": "title", - "type_info": "Varchar" - }, - { - "ordinal": 3, - "name": "description", - "type_info": "Varchar" - }, - { - "ordinal": 4, - "name": "downloads", - "type_info": "Int4" - }, - { - "ordinal": 5, - "name": "follows", - "type_info": "Int4" - }, - { - "ordinal": 6, - "name": "icon_url", - "type_info": "Varchar" - }, - { - "ordinal": 7, - "name": "body", - "type_info": "Varchar" - }, - { - "ordinal": 8, - "name": "body_url", - "type_info": "Varchar" - }, - { - "ordinal": 9, - "name": "published", - "type_info": "Timestamptz" - }, - { - "ordinal": 10, - "name": "updated", - "type_info": "Timestamptz" - }, - { - "ordinal": 11, - "name": "status", - "type_info": "Int4" - }, - { - "ordinal": 12, - "name": "issues_url", - "type_info": "Varchar" - }, - { - "ordinal": 13, - "name": "source_url", - "type_info": "Varchar" - }, - { - "ordinal": 14, - "name": "wiki_url", - "type_info": "Varchar" - }, - { - "ordinal": 15, - "name": "discord_url", - "type_info": "Varchar" - }, - { - "ordinal": 16, - "name": "license_url", - "type_info": "Varchar" - }, - { - "ordinal": 17, - "name": "team_id", - "type_info": "Int8" - }, - { - "ordinal": 18, - "name": "client_side", - "type_info": "Int4" - }, - { - "ordinal": 19, - "name": "server_side", - "type_info": "Int4" - }, - { - "ordinal": 20, - "name": "license", - "type_info": "Int4" - }, - { - "ordinal": 21, - "name": "slug", - "type_info": "Varchar" - }, - { - "ordinal": 22, - "name": "moderation_message", - "type_info": "Varchar" - }, - { - "ordinal": 23, - "name": "moderation_message_body", - "type_info": "Varchar" - }, - { - "ordinal": 24, - "name": "status_name", - "type_info": "Varchar" - }, - { - "ordinal": 25, - "name": "client_side_type", - "type_info": "Varchar" - }, - { - "ordinal": 26, - "name": "server_side_type", - "type_info": "Varchar" - }, - { - "ordinal": 27, - "name": "short", - "type_info": "Varchar" - }, - { - "ordinal": 28, - "name": "license_name", - "type_info": "Varchar" - }, - { - "ordinal": 29, - "name": "project_type_name", - "type_info": "Varchar" - }, - { - "ordinal": 30, - "name": "categories", - "type_info": "VarcharArray" - }, - { - "ordinal": 31, - "name": "versions", - "type_info": "TextArray" - }, - { - "ordinal": 32, - "name": "gallery", - "type_info": "TextArray" - }, - { - "ordinal": 33, - "name": "donations", - "type_info": "TextArray" - } - ], - "parameters": { - "Left": [ - "Int8Array" - ] - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - true, - false, - true, - false, - false, - false, - true, - true, - true, - true, - true, - false, - false, - false, - false, - true, - true, - true, - false, - false, - false, - false, - false, - false, - null, - null, - null, - null - ] - } - }, "8f706d78ac4235ea04c59e2c220a4791e1d08fdf287b783b4aaef36fd2445467": { "query": "\n DELETE FROM loaders\n WHERE loader = $1\n ", "describe": { @@ -3720,6 +3212,38 @@ "nullable": [] } }, + "9dfee6ef2fd11e7664b73b72611670c2a2f8f0b8887a6cabbc3f115b1de4675d": { + "query": "\n SELECT dependency_id, mod_dependency_id, dependency_type\n FROM dependencies\n WHERE dependent_id = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "dependency_id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "mod_dependency_id", + "type_info": "Int8" + }, + { + "ordinal": 2, + "name": "dependency_type", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + true, + true, + false + ] + } + }, "a39ce28b656032f862b205cffa393a76b989f4803654a615477a94fda5f57354": { "query": "\n DELETE FROM states\n WHERE id = $1\n ", "describe": { @@ -3756,6 +3280,50 @@ "nullable": [] } }, + "a6b3425fa78c6acac0693752a605d577cb04f507f9091fcc472af9f9ec41ebef": { + "query": "\n SELECT image_url, featured, title, description, created\n FROM mods_gallery\n WHERE mod_id = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "image_url", + "type_info": "Varchar" + }, + { + "ordinal": 1, + "name": "featured", + "type_info": "Bool" + }, + { + "ordinal": 2, + "name": "title", + "type_info": "Varchar" + }, + { + "ordinal": 3, + "name": "description", + "type_info": "Varchar" + }, + { + "ordinal": 4, + "name": "created", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + true, + true, + true, + false + ] + } + }, "a7a5fd1dfa3da7f476525f0b404dd0d609483154e0e91c781319f5c596b87b9e": { "query": "\n SELECT id, project_type, title, description, downloads, follows,\n icon_url, body, body_url, published,\n updated, status,\n issues_url, source_url, wiki_url, discord_url, license_url,\n team_id, client_side, server_side, license, slug,\n moderation_message, moderation_message_body\n FROM mods\n WHERE id = ANY($1)\n ", "describe": { @@ -4184,68 +3752,6 @@ "nullable": [] } }, - "b322ed0f98d9dc38d0a7596b1d20f5f6ef6459924dd1a11b02752de3662fafa5": { - "query": "\n SELECT n.user_id, n.title, n.text, n.link, n.created, n.read, n.type notification_type,\n ARRAY_AGG(DISTINCT na.id || ', ' || na.title || ', ' || na.action_route || ', ' || na.action_route_method) actions\n FROM notifications n\n LEFT OUTER JOIN notifications_actions na on n.id = na.notification_id\n WHERE n.id = $1\n GROUP BY n.id, n.user_id;\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "user_id", - "type_info": "Int8" - }, - { - "ordinal": 1, - "name": "title", - "type_info": "Varchar" - }, - { - "ordinal": 2, - "name": "text", - "type_info": "Varchar" - }, - { - "ordinal": 3, - "name": "link", - "type_info": "Varchar" - }, - { - "ordinal": 4, - "name": "created", - "type_info": "Timestamptz" - }, - { - "ordinal": 5, - "name": "read", - "type_info": "Bool" - }, - { - "ordinal": 6, - "name": "notification_type", - "type_info": "Varchar" - }, - { - "ordinal": 7, - "name": "actions", - "type_info": "TextArray" - } - ], - "parameters": { - "Left": [ - "Int8" - ] - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - true, - null - ] - } - }, "b69a6f42965b3e7103fcbf46e39528466926789ff31e9ed2591bb175527ec169": { "query": "\n DELETE FROM users\n WHERE id = $1\n ", "describe": { @@ -4344,6 +3850,200 @@ "nullable": [] } }, + "bb93df1953b22d06f0ad8bb6da5a448684679250855ec0621b1ddd599438d669": { + "query": "\n SELECT m.id id, m.project_type project_type, m.title title, m.description description, m.downloads downloads, m.follows follows,\n m.icon_url icon_url, m.body body, m.body_url body_url, m.published published,\n m.updated updated, m.status status,\n m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url,\n m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body,\n s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, l.name license_name, pt.name project_type_name\n FROM mods m\n INNER JOIN project_types pt ON pt.id = m.project_type\n INNER JOIN statuses s ON s.id = m.status\n INNER JOIN side_types cs ON m.client_side = cs.id\n INNER JOIN side_types ss ON m.server_side = ss.id\n INNER JOIN licenses l ON m.license = l.id\n WHERE m.id = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "project_type", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "title", + "type_info": "Varchar" + }, + { + "ordinal": 3, + "name": "description", + "type_info": "Varchar" + }, + { + "ordinal": 4, + "name": "downloads", + "type_info": "Int4" + }, + { + "ordinal": 5, + "name": "follows", + "type_info": "Int4" + }, + { + "ordinal": 6, + "name": "icon_url", + "type_info": "Varchar" + }, + { + "ordinal": 7, + "name": "body", + "type_info": "Varchar" + }, + { + "ordinal": 8, + "name": "body_url", + "type_info": "Varchar" + }, + { + "ordinal": 9, + "name": "published", + "type_info": "Timestamptz" + }, + { + "ordinal": 10, + "name": "updated", + "type_info": "Timestamptz" + }, + { + "ordinal": 11, + "name": "status", + "type_info": "Int4" + }, + { + "ordinal": 12, + "name": "issues_url", + "type_info": "Varchar" + }, + { + "ordinal": 13, + "name": "source_url", + "type_info": "Varchar" + }, + { + "ordinal": 14, + "name": "wiki_url", + "type_info": "Varchar" + }, + { + "ordinal": 15, + "name": "discord_url", + "type_info": "Varchar" + }, + { + "ordinal": 16, + "name": "license_url", + "type_info": "Varchar" + }, + { + "ordinal": 17, + "name": "team_id", + "type_info": "Int8" + }, + { + "ordinal": 18, + "name": "client_side", + "type_info": "Int4" + }, + { + "ordinal": 19, + "name": "server_side", + "type_info": "Int4" + }, + { + "ordinal": 20, + "name": "license", + "type_info": "Int4" + }, + { + "ordinal": 21, + "name": "slug", + "type_info": "Varchar" + }, + { + "ordinal": 22, + "name": "moderation_message", + "type_info": "Varchar" + }, + { + "ordinal": 23, + "name": "moderation_message_body", + "type_info": "Varchar" + }, + { + "ordinal": 24, + "name": "status_name", + "type_info": "Varchar" + }, + { + "ordinal": 25, + "name": "client_side_type", + "type_info": "Varchar" + }, + { + "ordinal": 26, + "name": "server_side_type", + "type_info": "Varchar" + }, + { + "ordinal": 27, + "name": "short", + "type_info": "Varchar" + }, + { + "ordinal": 28, + "name": "license_name", + "type_info": "Varchar" + }, + { + "ordinal": 29, + "name": "project_type_name", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + false, + false, + false, + false, + false, + true, + false, + true, + false, + false, + false, + true, + true, + true, + true, + true, + false, + false, + false, + false, + true, + true, + true, + false, + false, + false, + false, + false, + false + ] + } + }, "bbfb47ae2c972734785df6b7c3e62077dc544ef4ccf8bb89e9c22c2f50a933c1": { "query": "\n DELETE FROM report_types\n WHERE name = $1\n ", "describe": { @@ -5031,6 +4731,44 @@ "nullable": [] } }, + "d5807cb9a5766acc832b8715aab2b692a99e249a73974f0945710b1b394b1d74": { + "query": "\n SELECT id, filename, is_primary, url\n FROM files\n WHERE version_id = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "filename", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "is_primary", + "type_info": "Bool" + }, + { + "ordinal": 3, + "name": "url", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + } + }, "d5a496a0e17c5784f98ca2067bff996b23bb0a798609c4d4928df8080e4e1758": { "query": "\n SELECT v.id, v.mod_id, v.author_id, v.name, v.version_number,\n v.changelog, v.changelog_url, v.date_published, v.downloads,\n v.version_type, v.featured\n FROM versions v\n WHERE v.id = ANY($1)\n ORDER BY v.date_published ASC\n ", "describe": { @@ -5337,6 +5075,193 @@ "nullable": [] } }, + "dc70fb063947058851923f72ae1618e876c51335c0c6fdb82f097cb0bd68ccd7": { + "query": "\n SELECT m.id id, m.project_type project_type, m.title title, m.description description, m.downloads downloads, m.follows follows,\n m.icon_url icon_url, m.published published,\n m.updated updated,\n m.team_id team_id, m.license license, m.slug slug,\n s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, pt.name project_type_name, u.username username,\n STRING_AGG(DISTINCT c.category, ',') categories, STRING_AGG(DISTINCT lo.loader, ',') loaders, STRING_AGG(DISTINCT gv.version, ',') versions,\n STRING_AGG(DISTINCT mg.image_url, ',') gallery\n FROM mods m\n LEFT OUTER JOIN mods_categories mc ON joining_mod_id = m.id\n LEFT OUTER JOIN categories c ON mc.joining_category_id = c.id\n LEFT OUTER JOIN versions v ON v.mod_id = m.id\n LEFT OUTER JOIN game_versions_versions gvv ON gvv.joining_version_id = v.id\n LEFT OUTER JOIN game_versions gv ON gvv.game_version_id = gv.id\n LEFT OUTER JOIN loaders_versions lv ON lv.version_id = v.id\n LEFT OUTER JOIN loaders lo ON lo.id = lv.loader_id\n LEFT OUTER JOIN mods_gallery mg ON mg.mod_id = m.id\n INNER JOIN statuses s ON s.id = m.status\n INNER JOIN project_types pt ON pt.id = m.project_type\n INNER JOIN side_types cs ON m.client_side = cs.id\n INNER JOIN side_types ss ON m.server_side = ss.id\n INNER JOIN licenses l ON m.license = l.id\n INNER JOIN team_members tm ON tm.team_id = m.team_id AND tm.role = $2\n INNER JOIN users u ON tm.user_id = u.id\n WHERE m.id = $1\n GROUP BY m.id, s.id, cs.id, ss.id, l.id, pt.id, u.id;\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "project_type", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "title", + "type_info": "Varchar" + }, + { + "ordinal": 3, + "name": "description", + "type_info": "Varchar" + }, + { + "ordinal": 4, + "name": "downloads", + "type_info": "Int4" + }, + { + "ordinal": 5, + "name": "follows", + "type_info": "Int4" + }, + { + "ordinal": 6, + "name": "icon_url", + "type_info": "Varchar" + }, + { + "ordinal": 7, + "name": "published", + "type_info": "Timestamptz" + }, + { + "ordinal": 8, + "name": "updated", + "type_info": "Timestamptz" + }, + { + "ordinal": 9, + "name": "team_id", + "type_info": "Int8" + }, + { + "ordinal": 10, + "name": "license", + "type_info": "Int4" + }, + { + "ordinal": 11, + "name": "slug", + "type_info": "Varchar" + }, + { + "ordinal": 12, + "name": "status_name", + "type_info": "Varchar" + }, + { + "ordinal": 13, + "name": "client_side_type", + "type_info": "Varchar" + }, + { + "ordinal": 14, + "name": "server_side_type", + "type_info": "Varchar" + }, + { + "ordinal": 15, + "name": "short", + "type_info": "Varchar" + }, + { + "ordinal": 16, + "name": "project_type_name", + "type_info": "Varchar" + }, + { + "ordinal": 17, + "name": "username", + "type_info": "Varchar" + }, + { + "ordinal": 18, + "name": "categories", + "type_info": "Text" + }, + { + "ordinal": 19, + "name": "loaders", + "type_info": "Text" + }, + { + "ordinal": 20, + "name": "versions", + "type_info": "Text" + }, + { + "ordinal": 21, + "name": "gallery", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Int8", + "Text" + ] + }, + "nullable": [ + false, + false, + false, + false, + false, + false, + true, + false, + false, + false, + false, + true, + false, + false, + false, + false, + false, + false, + null, + null, + null, + null + ] + } + }, + "dd616640be8807405d0d98a55f8fa23a50186a6a87a64bcb872750c9f9404763": { + "query": "\n SELECT c.category category\n FROM mods_categories mc\n INNER JOIN categories c ON mc.joining_category_id = c.id\n WHERE mc.joining_mod_id = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "category", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false + ] + } + }, + "dd785c80c372e6d199099e839a481a0cd63de8161a6acd41cf615a6818d1ae38": { + "query": "\n SELECT gv.version game_version\n FROM game_versions_versions gvv\n INNER JOIN game_versions gv on gvv.game_version_id = gv.id\n WHERE gvv.joining_version_id = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "game_version", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false + ] + } + }, "e29da865af4a0a110275b9756394546a3bb88bff40e18c66029651f515caed98": { "query": "\n SELECT f.id id FROM files f\n WHERE f.version_id = $1\n ", "describe": { @@ -5420,8 +5345,8 @@ "nullable": [] } }, - "e63cf14daaa5098c99264876be87ef0fcaede049bef77460b9cff28e01402e64": { - "query": "\n SELECT n.id, n.user_id, n.title, n.text, n.link, n.created, n.read, n.type notification_type,\n ARRAY_AGG(DISTINCT na.id || ', ' || na.title || ', ' || na.action_route || ', ' || na.action_route_method) actions\n FROM notifications n\n LEFT OUTER JOIN notifications_actions na on n.id = na.notification_id\n WHERE n.user_id = $1\n GROUP BY n.id, n.user_id;\n ", + "e64c33dce1f23d32497a69ecfdac8d4ced262335b82d32d8353456322a0a7484": { + "query": "\n SELECT v.id id, v.mod_id mod_id, v.author_id author_id, v.name version_name, v.version_number version_number,\n v.changelog changelog, v.changelog_url changelog_url, v.date_published date_published, v.downloads downloads,\n v.version_type version_type, v.featured featured\n FROM versions v\n WHERE v.id = $1\n GROUP BY v.id;\n ", "describe": { "columns": [ { @@ -5431,43 +5356,53 @@ }, { "ordinal": 1, - "name": "user_id", + "name": "mod_id", "type_info": "Int8" }, { "ordinal": 2, - "name": "title", - "type_info": "Varchar" + "name": "author_id", + "type_info": "Int8" }, { "ordinal": 3, - "name": "text", + "name": "version_name", "type_info": "Varchar" }, { "ordinal": 4, - "name": "link", + "name": "version_number", "type_info": "Varchar" }, { "ordinal": 5, - "name": "created", - "type_info": "Timestamptz" - }, - { - "ordinal": 6, - "name": "read", - "type_info": "Bool" - }, - { - "ordinal": 7, - "name": "notification_type", + "name": "changelog", "type_info": "Varchar" }, + { + "ordinal": 6, + "name": "changelog_url", + "type_info": "Varchar" + }, + { + "ordinal": 7, + "name": "date_published", + "type_info": "Timestamptz" + }, { "ordinal": 8, - "name": "actions", - "type_info": "TextArray" + "name": "downloads", + "type_info": "Int4" + }, + { + "ordinal": 9, + "name": "version_type", + "type_info": "Varchar" + }, + { + "ordinal": 10, + "name": "featured", + "type_info": "Bool" } ], "parameters": { @@ -5482,9 +5417,11 @@ false, false, false, - false, true, - null + false, + false, + false, + false ] } }, @@ -5762,153 +5699,6 @@ "nullable": [] } }, - "ee460bbb6bd560aec5929684e1a91c80d69ac45abfc32d30981b3f3fd642c429": { - "query": "\n SELECT m.id id, m.project_type project_type, m.title title, m.description description, m.downloads downloads, m.follows follows,\n m.icon_url icon_url, m.published published,\n m.updated updated,\n m.team_id team_id, m.license license, m.slug slug,\n s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, pt.name project_type_name, u.username username,\n ARRAY_AGG(DISTINCT c.category) categories, ARRAY_AGG(DISTINCT lo.loader) loaders, ARRAY_AGG(DISTINCT gv.version) versions,\n ARRAY_AGG(DISTINCT mg.image_url) gallery\n FROM mods m\n LEFT OUTER JOIN mods_categories mc ON joining_mod_id = m.id\n LEFT OUTER JOIN categories c ON mc.joining_category_id = c.id\n LEFT OUTER JOIN versions v ON v.mod_id = m.id\n LEFT OUTER JOIN game_versions_versions gvv ON gvv.joining_version_id = v.id\n LEFT OUTER JOIN game_versions gv ON gvv.game_version_id = gv.id\n LEFT OUTER JOIN loaders_versions lv ON lv.version_id = v.id\n LEFT OUTER JOIN loaders lo ON lo.id = lv.loader_id\n LEFT OUTER JOIN mods_gallery mg ON mg.mod_id = m.id\n INNER JOIN statuses s ON s.id = m.status\n INNER JOIN project_types pt ON pt.id = m.project_type\n INNER JOIN side_types cs ON m.client_side = cs.id\n INNER JOIN side_types ss ON m.server_side = ss.id\n INNER JOIN licenses l ON m.license = l.id\n INNER JOIN team_members tm ON tm.team_id = m.team_id AND tm.role = $2\n INNER JOIN users u ON tm.user_id = u.id\n WHERE s.status = $1\n GROUP BY m.id, s.id, cs.id, ss.id, l.id, pt.id, u.id;\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int8" - }, - { - "ordinal": 1, - "name": "project_type", - "type_info": "Int4" - }, - { - "ordinal": 2, - "name": "title", - "type_info": "Varchar" - }, - { - "ordinal": 3, - "name": "description", - "type_info": "Varchar" - }, - { - "ordinal": 4, - "name": "downloads", - "type_info": "Int4" - }, - { - "ordinal": 5, - "name": "follows", - "type_info": "Int4" - }, - { - "ordinal": 6, - "name": "icon_url", - "type_info": "Varchar" - }, - { - "ordinal": 7, - "name": "published", - "type_info": "Timestamptz" - }, - { - "ordinal": 8, - "name": "updated", - "type_info": "Timestamptz" - }, - { - "ordinal": 9, - "name": "team_id", - "type_info": "Int8" - }, - { - "ordinal": 10, - "name": "license", - "type_info": "Int4" - }, - { - "ordinal": 11, - "name": "slug", - "type_info": "Varchar" - }, - { - "ordinal": 12, - "name": "status_name", - "type_info": "Varchar" - }, - { - "ordinal": 13, - "name": "client_side_type", - "type_info": "Varchar" - }, - { - "ordinal": 14, - "name": "server_side_type", - "type_info": "Varchar" - }, - { - "ordinal": 15, - "name": "short", - "type_info": "Varchar" - }, - { - "ordinal": 16, - "name": "project_type_name", - "type_info": "Varchar" - }, - { - "ordinal": 17, - "name": "username", - "type_info": "Varchar" - }, - { - "ordinal": 18, - "name": "categories", - "type_info": "VarcharArray" - }, - { - "ordinal": 19, - "name": "loaders", - "type_info": "VarcharArray" - }, - { - "ordinal": 20, - "name": "versions", - "type_info": "VarcharArray" - }, - { - "ordinal": 21, - "name": "gallery", - "type_info": "VarcharArray" - } - ], - "parameters": { - "Left": [ - "Text", - "Text" - ] - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - true, - false, - false, - false, - false, - true, - false, - false, - false, - false, - false, - false, - null, - null, - null, - null - ] - } - }, "ef3d43d3424824eed67370f10cc0672581a95a169bf404022cbe3cac0415d99c": { "query": "\n SELECT f.id id, f.version_id version_id, f.filename filename, v.version_number version_number, v.mod_id project_id FROM hashes h\n INNER JOIN files f ON h.file_id = f.id\n INNER JOIN versions v ON v.id = f.version_id\n WHERE h.algorithm = $2 AND h.hash = $1\n ", "describe": { @@ -6177,6 +5967,26 @@ ] } }, + "fd00809bd75662a8f21d812fd00071b4208f88186d9f86badece97c9c95ad3b9": { + "query": "\n SELECT id\n FROM versions\n WHERE mod_id = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false + ] + } + }, "fe73b6928f13955840e8df248688908fb6d82dd1d35dc803676639a6e0864ed5": { "query": "\n DELETE FROM downloads\n WHERE date < (CURRENT_DATE - INTERVAL '30 minutes ago')\n ", "describe": { diff --git a/src/database/models/ids.rs b/src/database/models/ids.rs index 2f516080b..33cfbef4c 100644 --- a/src/database/models/ids.rs +++ b/src/database/models/ids.rs @@ -153,7 +153,7 @@ pub struct ReportId(pub i64); #[sqlx(transparent)] pub struct ReportTypeId(pub i32); -#[derive(Copy, Clone, Debug, Type)] +#[derive(Copy, Clone, Debug, Type, Hash, Eq, PartialEq)] #[sqlx(transparent)] pub struct FileId(pub i64); diff --git a/src/database/models/notification_item.rs b/src/database/models/notification_item.rs index 8720d185f..56c383769 100644 --- a/src/database/models/notification_item.rs +++ b/src/database/models/notification_item.rs @@ -118,39 +118,32 @@ impl Notification { executor: E, ) -> Result, sqlx::error::Error> where - E: sqlx::Executor<'a, Database = sqlx::Postgres>, + E: sqlx::Executor<'a, Database = sqlx::Postgres> + Copy, { - let result = sqlx::query!( - " - SELECT n.user_id, n.title, n.text, n.link, n.created, n.read, n.type notification_type, - ARRAY_AGG(DISTINCT na.id || ', ' || na.title || ', ' || na.action_route || ', ' || na.action_route_method) actions - FROM notifications n - LEFT OUTER JOIN notifications_actions na on n.id = na.notification_id - WHERE n.id = $1 - GROUP BY n.id, n.user_id; - ", - id as NotificationId, - ) - .fetch_optional(executor) - .await?; - - if let Some(row) = result { - let mut actions: Vec = Vec::new(); - - row.actions.unwrap_or_default().iter().for_each(|x| { - let action: Vec<&str> = x.split(", ").collect(); - - if action.len() >= 3 { - actions.push(NotificationAction { - id: NotificationActionId(action[0].parse().unwrap_or(0)), - notification_id: id, - title: action[1].to_string(), - action_route_method: action[3].to_string(), - action_route: action[2].to_string(), - }); - } - }); + let (notifications, actions) = futures::join!( + sqlx::query!( + " + SELECT n.user_id, n.title, n.text, n.link, n.created, n.read, n.type notification_type, + ARRAY_AGG(DISTINCT na.id || ', ' || na.title || ', ' || na.action_route || ', ' || na.action_route_method) actions + FROM notifications n + LEFT OUTER JOIN notifications_actions na on n.id = na.notification_id + WHERE n.id = $1 + GROUP BY n.id, n.user_id; + ", + id as NotificationId, + ) + .fetch_optional(executor), + sqlx::query!( + " + SELECT id, title, notification_id, action_route, action_route_method + FROM notifications_actions + WHERE notification_id = $1 + ", + id as NotificationId, + ).fetch_all(executor), + ); + if let Some(row) = notifications? { Ok(Some(Notification { id, user_id: UserId(row.user_id), @@ -160,7 +153,16 @@ impl Notification { link: row.link, read: row.read, created: row.created, - actions, + actions: actions? + .into_iter() + .map(|x| NotificationAction { + id: NotificationActionId(x.id), + notification_id: NotificationId(x.notification_id), + title: x.title, + action_route_method: x.action_route_method, + action_route: x.action_route, + }) + .collect(), })) } else { Ok(None) @@ -174,56 +176,9 @@ impl Notification { where E: sqlx::Executor<'a, Database = sqlx::Postgres> + Copy, { - use futures::stream::TryStreamExt; - - let notification_ids_parsed: Vec = notification_ids.into_iter().map(|x| x.0).collect(); - sqlx::query!( - " - SELECT n.id, n.user_id, n.title, n.text, n.link, n.created, n.read, n.type notification_type, - ARRAY_AGG(DISTINCT na.id || ', ' || na.title || ', ' || na.action_route || ', ' || na.action_route_method) actions - FROM notifications n - LEFT OUTER JOIN notifications_actions na on n.id = na.notification_id - WHERE n.id = ANY($1) - GROUP BY n.id, n.user_id - ORDER BY n.created DESC; - ", - ¬ification_ids_parsed - ) - .fetch_many(exec) - .try_filter_map(|e| async { - Ok(e.right().map(|row| { - let id = NotificationId(row.id); - let mut actions: Vec = Vec::new(); - - row.actions.unwrap_or_default().iter().for_each(|x| { - let action: Vec<&str> = x.split(", ").collect(); - - if action.len() >= 3 { - actions.push(NotificationAction { - id: NotificationActionId(action[0].parse().unwrap_or(0)), - notification_id: id, - title: action[1].to_string(), - action_route_method: action[3].to_string(), - action_route: action[2].to_string(), - }); - } - }); - - Notification { - id, - user_id: UserId(row.user_id), - notification_type: row.notification_type, - title: row.title, - text: row.text, - link: row.link, - read: row.read, - created: row.created, - actions, - } - })) - }) - .try_collect::>() - .await + futures::future::try_join_all(notification_ids.into_iter().map(|id| Self::get(id, exec))) + .await + .map(|x| x.into_iter().flatten().collect()) } pub async fn get_many_user<'a, E>( @@ -233,54 +188,21 @@ impl Notification { where E: sqlx::Executor<'a, Database = sqlx::Postgres> + Copy, { - use futures::stream::TryStreamExt; - - sqlx::query!( + let notification_ids = sqlx::query!( " - SELECT n.id, n.user_id, n.title, n.text, n.link, n.created, n.read, n.type notification_type, - ARRAY_AGG(DISTINCT na.id || ', ' || na.title || ', ' || na.action_route || ', ' || na.action_route_method) actions - FROM notifications n - LEFT OUTER JOIN notifications_actions na on n.id = na.notification_id - WHERE n.user_id = $1 - GROUP BY n.id, n.user_id; + SELECT id + FROM notifications + WHERE user_id = $1 ", user_id as UserId ) - .fetch_many(exec) - .try_filter_map(|e| async { - Ok(e.right().map(|row| { - let id = NotificationId(row.id); - let mut actions: Vec = Vec::new(); + .fetch_all(exec) + .await? + .into_iter() + .map(|x| NotificationId(x.id)) + .collect(); - row.actions.unwrap_or_default().iter().for_each(|x| { - let action: Vec<&str> = x.split(", ").collect(); - - if action.len() >= 3 { - actions.push(NotificationAction { - id: NotificationActionId(action[0].parse().unwrap_or(0)), - notification_id: id, - title: action[1].to_string(), - action_route_method: action[3].to_string(), - action_route: action[2].to_string(), - }); - } - }); - - Notification { - id, - user_id: UserId(row.user_id), - notification_type: row.notification_type, - title: row.title, - text: row.text, - link: row.link, - read: row.read, - created: row.created, - actions, - } - })) - }) - .try_collect::>() - .await + Self::get_many(notification_ids, exec).await } pub async fn remove( diff --git a/src/database/models/project_item.rs b/src/database/models/project_item.rs index ae6719c08..c2920dc84 100644 --- a/src/database/models/project_item.rs +++ b/src/database/models/project_item.rs @@ -589,43 +589,69 @@ impl Project { executor: E, ) -> Result, sqlx::error::Error> where - E: sqlx::Executor<'a, Database = sqlx::Postgres>, + E: sqlx::Executor<'a, Database = sqlx::Postgres> + Copy, { - let result = sqlx::query!( - " - SELECT m.id id, m.project_type project_type, m.title title, m.description description, m.downloads downloads, m.follows follows, - m.icon_url icon_url, m.body body, m.body_url body_url, m.published published, - m.updated updated, m.status status, - m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url, - m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body, - s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, l.name license_name, pt.name project_type_name, - ARRAY_AGG(DISTINCT c.category) categories, ARRAY_AGG(DISTINCT v.id::text) versions, - ARRAY_AGG(DISTINCT mg.image_url || ', ' || mg.featured || ', ' || COALESCE(mg.title, '') || ', ' || COALESCE(mg.description, '') || ', ' || mg.created) gallery, - ARRAY_AGG(DISTINCT md.joining_platform_id || ', ' || md.url || ', ' || dp.short || ', ' || dp.name) donations - FROM mods m - INNER JOIN project_types pt ON pt.id = m.project_type - INNER JOIN statuses s ON s.id = m.status - INNER JOIN side_types cs ON m.client_side = cs.id - INNER JOIN side_types ss ON m.server_side = ss.id - INNER JOIN licenses l ON m.license = l.id - LEFT JOIN mods_donations md ON md.joining_mod_id = m.id - LEFT JOIN donation_platforms dp ON md.joining_platform_id = dp.id - LEFT JOIN mods_categories mc ON mc.joining_mod_id = m.id - LEFT JOIN categories c ON mc.joining_category_id = c.id - LEFT JOIN versions v ON v.mod_id = m.id - LEFT JOIN mods_gallery mg ON mg.mod_id = m.id - WHERE m.id = $1 - GROUP BY pt.id, s.id, cs.id, ss.id, l.id, m.id; - ", - id as ProjectId, - ) - .fetch_optional(executor) - .await?; + let (project, versions, categories, gallery, donations) = futures::join!( + sqlx::query!( + " + SELECT m.id id, m.project_type project_type, m.title title, m.description description, m.downloads downloads, m.follows follows, + m.icon_url icon_url, m.body body, m.body_url body_url, m.published published, + m.updated updated, m.status status, + m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url, + m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body, + s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, l.name license_name, pt.name project_type_name + FROM mods m + INNER JOIN project_types pt ON pt.id = m.project_type + INNER JOIN statuses s ON s.id = m.status + INNER JOIN side_types cs ON m.client_side = cs.id + INNER JOIN side_types ss ON m.server_side = ss.id + INNER JOIN licenses l ON m.license = l.id + WHERE m.id = $1 + ", + id as ProjectId, + ).fetch_optional(executor), + sqlx::query!( + " + SELECT id + FROM versions + WHERE mod_id = $1 + ", + id as ProjectId, + ).fetch_all(executor), + sqlx::query!( + " + SELECT c.category category + FROM mods_categories mc + INNER JOIN categories c ON mc.joining_category_id = c.id + WHERE mc.joining_mod_id = $1 + ", + id as ProjectId, + ).fetch_all(executor), + sqlx::query!( + " + SELECT image_url, featured, title, description, created + FROM mods_gallery + WHERE mod_id = $1 + ", + id as ProjectId, + ).fetch_all(executor), + sqlx::query!( + " + SELECT md.url url, dp.id platform_id, dp.name dp_name, dp.short short + FROM mods_donations md + INNER JOIN donation_platforms dp ON md.joining_platform_id = dp.id + WHERE md.joining_mod_id = $1 + ", + id as ProjectId, + ).fetch_all(executor) + ); + + if let Some(m) = project? { + let project_id = ProjectId(m.id); - if let Some(m) = result { Ok(Some(QueryProject { inner: Project { - id: ProjectId(m.id), + id: project_id, project_type: ProjectTypeId(m.project_type), team_id: TeamId(m.team_id), title: m.title.clone(), @@ -651,70 +677,28 @@ impl Project { moderation_message_body: m.moderation_message_body, }, project_type: m.project_type_name, - categories: m - .categories - .map(|x| x.iter().map(|x| x.to_string()).collect()) - .unwrap_or_default(), - versions: m - .versions - .map(|x| { - x.iter() - .map(|x| VersionId(x.parse().unwrap_or_default())) - .collect() + categories: categories?.into_iter().map(|x| x.category).collect(), + versions: versions?.into_iter().map(|x| VersionId(x.id)).collect(), + donation_urls: donations? + .into_iter() + .map(|x| DonationUrl { + project_id, + platform_id: DonationPlatformId(x.platform_id), + platform_short: x.short, + platform_name: x.dp_name, + url: x.url, }) - .unwrap_or_default(), - donation_urls: m - .donations - .unwrap_or_default() - .iter() - .map(|d| { - let strings: Vec<&str> = d.split(", ").collect(); - - 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 - .unwrap_or_default() - .iter() - .map(|d| { - let strings: Vec<&str> = d.split(", ").collect(); - - if strings.len() >= 5 { - Some(GalleryItem { - project_id: id, - image_url: strings[0].to_string(), - featured: strings[1].parse().unwrap_or(false), - title: if strings[2] == "" { - None - } else { - Some(strings[2].to_string()) - }, - description: if strings[3] == "" { - None - } else { - Some(strings[3].to_string()) - }, - created: chrono::DateTime::parse_from_rfc3339(strings[4]) - .map(|x| x.with_timezone(&chrono::Utc)) - .unwrap_or_else(|_| chrono::Utc::now()), - }) - } else { - None - } + gallery_items: gallery? + .into_iter() + .map(|x| GalleryItem { + project_id, + image_url: x.image_url, + featured: x.featured.unwrap_or(false), + title: x.title, + description: x.description, + created: x.created, }) - .flatten() .collect(), status: crate::models::projects::ProjectStatus::from_str(&m.status_name), license_id: m.short, @@ -734,123 +718,9 @@ impl Project { where E: sqlx::Executor<'a, Database = sqlx::Postgres> + Copy, { - use futures::TryStreamExt; - - let project_ids_parsed: Vec = project_ids.into_iter().map(|x| x.0).collect(); - sqlx::query!( - " - SELECT m.id id, m.project_type project_type, m.title title, m.description description, m.downloads downloads, m.follows follows, - m.icon_url icon_url, m.body body, m.body_url body_url, m.published published, - m.updated updated, m.status status, - m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url, - m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body, - s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, l.name license_name, pt.name project_type_name, - ARRAY_AGG(DISTINCT c.category) categories, ARRAY_AGG(DISTINCT v.id::text) versions, - ARRAY_AGG(DISTINCT mg.image_url || ', ' || mg.featured || ', ' || COALESCE(mg.title, '') || ', ' || COALESCE(mg.description, '') || ', ' || mg.created) gallery, - ARRAY_AGG(DISTINCT md.joining_platform_id || ', ' || md.url || ', ' || dp.short || ', ' || dp.name) donations - FROM mods m - INNER JOIN project_types pt ON pt.id = m.project_type - INNER JOIN statuses s ON s.id = m.status - INNER JOIN side_types cs ON m.client_side = cs.id - INNER JOIN side_types ss ON m.server_side = ss.id - INNER JOIN licenses l ON m.license = l.id - LEFT JOIN mods_donations md ON md.joining_mod_id = m.id - LEFT JOIN donation_platforms dp ON md.joining_platform_id = dp.id - LEFT JOIN mods_categories mc ON mc.joining_mod_id = m.id - LEFT JOIN categories c ON mc.joining_category_id = c.id - LEFT JOIN versions v ON v.mod_id = m.id - LEFT JOIN mods_gallery mg ON mg.mod_id = m.id - WHERE m.id = ANY($1) - GROUP BY pt.id, s.id, cs.id, ss.id, l.id, m.id; - ", - &project_ids_parsed - ) - .fetch_many(exec) - .try_filter_map(|e| async { - Ok(e.right().map(|m| { - let id = m.id; - QueryProject { - inner: Project { - id: ProjectId(id), - project_type: ProjectTypeId(m.project_type), - team_id: TeamId(m.team_id), - title: m.title.clone(), - description: m.description.clone(), - downloads: m.downloads, - body_url: m.body_url.clone(), - icon_url: m.icon_url.clone(), - published: m.published, - updated: m.updated, - issues_url: m.issues_url.clone(), - source_url: m.source_url.clone(), - wiki_url: m.wiki_url.clone(), - license_url: m.license_url.clone(), - discord_url: m.discord_url.clone(), - client_side: SideTypeId(m.client_side), - status: StatusId(m.status), - server_side: SideTypeId(m.server_side), - license: LicenseId(m.license), - slug: m.slug.clone(), - body: m.body.clone(), - follows: m.follows, - moderation_message: m.moderation_message, - moderation_message_body: m.moderation_message_body, - }, - project_type: m.project_type_name, - categories: m.categories.map(|x| x.iter().map(|x| x.to_string()).collect()).unwrap_or_default(), - versions: m.versions.map(|x| x.iter().map(|x| VersionId(x.parse().unwrap_or_default())).collect()).unwrap_or_default(), - gallery_items: m - .gallery - .unwrap_or_default() - .iter() - .map(|d| { - let strings: Vec<&str> = d.split(", ").collect(); - - if strings.len() >= 5 { - Some(GalleryItem { - project_id: ProjectId(id), - image_url: strings[0].to_string(), - featured: strings[1].parse().unwrap_or(false), - title: if strings[2] == " " { None } else { Some(strings[2].to_string()) }, - description: if strings[3] == " " { None } else { Some(strings[3].to_string()) }, - created: chrono::DateTime::parse_from_rfc3339(strings[4]).map(|x| x.with_timezone(&chrono::Utc)).unwrap_or_else(|_| chrono::Utc::now()) - }) - } else { - None - } - }) - .flatten() - .collect(), - donation_urls: m - .donations - .unwrap_or_default() - .iter() - .map(|d| { - let strings: Vec<&str> = d.split(", ").collect(); - - 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(), - status: crate::models::projects::ProjectStatus::from_str(&m.status_name), - license_id: m.short, - license_name: m.license_name, - client_side: crate::models::projects::SideType::from_str(&m.client_side_type), - server_side: crate::models::projects::SideType::from_str(&m.server_side_type), - }})) - }) - .try_collect::>() + futures::future::try_join_all(project_ids.into_iter().map(|id| Self::get_full(id, exec))) .await + .map(|x| x.into_iter().flatten().collect()) } } #[derive(Clone, Debug)] diff --git a/src/database/models/version_item.rs b/src/database/models/version_item.rs index 88477b68c..8a757e8ac 100644 --- a/src/database/models/version_item.rs +++ b/src/database/models/version_item.rs @@ -596,53 +596,78 @@ impl Version { executor: E, ) -> Result, sqlx::error::Error> where - E: sqlx::Executor<'a, Database = sqlx::Postgres>, + E: sqlx::Executor<'a, Database = sqlx::Postgres> + Copy, { - let result = sqlx::query!( - " - SELECT v.id id, v.mod_id mod_id, v.author_id author_id, v.name version_name, v.version_number version_number, - v.changelog changelog, v.changelog_url changelog_url, v.date_published date_published, v.downloads downloads, - v.version_type version_type, v.featured featured, - ARRAY_AGG(DISTINCT gv.version) game_versions, ARRAY_AGG(DISTINCT l.loader) loaders, - ARRAY_AGG(DISTINCT f.id || ', ' || f.filename || ', ' || f.is_primary || ', ' || f.url) files, - ARRAY_AGG(DISTINCT h.algorithm || ', ' || encode(h.hash, 'escape') || ', ' || h.file_id) hashes, - ARRAY_AGG(DISTINCT COALESCE(d.dependency_id, 0) || ', ' || COALESCE(d.mod_dependency_id, 0) || ', ' || d.dependency_type) dependencies - FROM versions v - LEFT OUTER JOIN game_versions_versions gvv on v.id = gvv.joining_version_id - LEFT OUTER JOIN game_versions gv on gvv.game_version_id = gv.id - LEFT OUTER JOIN loaders_versions lv on v.id = lv.version_id - LEFT OUTER JOIN loaders l on lv.loader_id = l.id - LEFT OUTER JOIN files f on v.id = f.version_id - LEFT OUTER JOIN hashes h on f.id = h.file_id - LEFT OUTER JOIN dependencies d on v.id = d.dependent_id - WHERE v.id = $1 - GROUP BY v.id; - ", - id as VersionId, - ) - .fetch_optional(executor) - .await?; + let (version, game_versions, loaders, files, hashes, dependencies) = futures::join!( + sqlx::query!( + " + SELECT v.id id, v.mod_id mod_id, v.author_id author_id, v.name version_name, v.version_number version_number, + v.changelog changelog, v.changelog_url changelog_url, v.date_published date_published, v.downloads downloads, + v.version_type version_type, v.featured featured + FROM versions v + WHERE v.id = $1 + GROUP BY v.id; + ", + id as VersionId, + ) + .fetch_optional(executor), + sqlx::query!( + " + SELECT gv.version game_version + FROM game_versions_versions gvv + INNER JOIN game_versions gv on gvv.game_version_id = gv.id + WHERE gvv.joining_version_id = $1 + ", + id as VersionId, + ).fetch_all(executor), + sqlx::query!( + " + SELECT l.loader loader + FROM loaders_versions lv + INNER JOIN loaders l on lv.loader_id = l.id + WHERE lv.version_id = $1 + ", + id as VersionId, + ).fetch_all(executor), + sqlx::query!( + " + SELECT id, filename, is_primary, url + FROM files + WHERE version_id = $1 + ", + id as VersionId, + ).fetch_all(executor), + sqlx::query!( + " + SELECT h.algorithm algorithm, encode(h.hash, 'escape') hash, h.file_id file_id + FROM files f + INNER JOIN hashes h ON h.file_id = f.id + WHERE f.version_id = $1 + ", + id as VersionId, + ).fetch_all(executor), + sqlx::query!( + " + SELECT dependency_id, mod_dependency_id, dependency_type + FROM dependencies + WHERE dependent_id = $1 + ", + id as VersionId, + ).fetch_all(executor), + ); - if let Some(v) = result { - let hashes: Vec<(FileId, String, Vec)> = v - .hashes - .unwrap_or_default() - .iter() - .map(|f| { - let hash: Vec<&str> = f.split(", ").collect(); + if let Some(v) = version? { + let mut hashes_map: HashMap>> = HashMap::new(); - 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(); + for hash in hashes? { + let entry = hashes_map + .entry(FileId(hash.file_id)) + .or_insert(HashMap::new()); + + if let Some(raw_hash) = hash.hash { + entry.insert(hash.algorithm, raw_hash.into_bytes()); + } + } Ok(Some(QueryVersion { id: VersionId(v.id), @@ -654,79 +679,26 @@ impl Version { changelog_url: v.changelog_url, date_published: v.date_published, downloads: v.downloads, - files: v - .files - .unwrap_or_default() - .iter() - .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 - } + files: files? + .into_iter() + .map(|x| QueryFile { + id: FileId(x.id), + url: x.url, + filename: x.filename, + hashes: hashes_map.entry(FileId(x.id)).or_default().clone(), + primary: x.is_primary, }) - .flatten() - .collect(), - game_versions: v - .game_versions - .unwrap_or_default() - .iter() - .map(|x| x.to_string()) - .collect(), - loaders: v - .loaders - .unwrap_or_default() - .iter() - .map(|x| x.to_string()) .collect(), + game_versions: game_versions?.into_iter().map(|x| x.game_version).collect(), + loaders: loaders?.into_iter().map(|x| x.loader).collect(), featured: v.featured, - dependencies: v - .dependencies - .unwrap_or_default() - .iter() - .map(|f| { - let dependency: Vec<&str> = f.split(", ").collect(); - - if dependency.len() >= 3 { - Some(QueryDependency { - project_id: match &*dependency[1] { - "0" => None, - _ => match dependency[1].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[2].to_string(), - }) - } else { - None - } + dependencies: dependencies? + .into_iter() + .map(|x| QueryDependency { + project_id: x.mod_dependency_id.map(|x| ProjectId(x)), + version_id: x.dependency_id.map(|x| VersionId(x)), + dependency_type: x.dependency_type, }) - .flatten() .collect(), version_type: v.version_type, })) @@ -742,120 +714,9 @@ impl Version { where E: sqlx::Executor<'a, Database = sqlx::Postgres> + Copy, { - use futures::stream::TryStreamExt; - - let version_ids_parsed: Vec = version_ids.into_iter().map(|x| x.0).collect(); - sqlx::query!( - " - SELECT v.id id, v.mod_id mod_id, v.author_id author_id, v.name version_name, v.version_number version_number, - v.changelog changelog, v.changelog_url changelog_url, v.date_published date_published, v.downloads downloads, - v.version_type version_type, v.featured featured, - ARRAY_AGG(DISTINCT gv.version) game_versions, ARRAY_AGG(DISTINCT l.loader) loaders, - ARRAY_AGG(DISTINCT f.id || ', ' || f.filename || ', ' || f.is_primary || ', ' || f.url) files, - ARRAY_AGG(DISTINCT h.algorithm || ', ' || encode(h.hash, 'escape') || ', ' || h.file_id) hashes, - ARRAY_AGG(DISTINCT COALESCE(d.dependency_id, 0) || ', ' || COALESCE(d.mod_dependency_id, 0) || ', ' || d.dependency_type) dependencies - FROM versions v - LEFT OUTER JOIN game_versions_versions gvv on v.id = gvv.joining_version_id - LEFT OUTER JOIN game_versions gv on gvv.game_version_id = gv.id - LEFT OUTER JOIN loaders_versions lv on v.id = lv.version_id - LEFT OUTER JOIN loaders l on lv.loader_id = l.id - LEFT OUTER JOIN files f on v.id = f.version_id - LEFT OUTER JOIN hashes h on f.id = h.file_id - LEFT OUTER JOIN dependencies d on v.id = d.dependent_id - WHERE v.id = ANY($1) - GROUP BY v.id - ORDER BY v.date_published ASC; - ", - &version_ids_parsed - ) - .fetch_many(exec) - .try_filter_map(|e| async { - Ok(e.right().map(|v| { - let hashes: Vec<(FileId, String, Vec)> = v.hashes.unwrap_or_default().iter().map(|f| { - let hash: Vec<&str> = f.split(", ").collect(); - - 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(); - - QueryVersion { - id: VersionId(v.id), - project_id: ProjectId(v.mod_id), - author_id: UserId(v.author_id), - name: v.version_name, - version_number: v.version_number, - changelog: v.changelog, - changelog_url: v.changelog_url, - date_published: v.date_published, - downloads: v.downloads, - files: v.files.unwrap_or_default().iter().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().iter().map(|x| x.to_string()).collect(), - loaders: v.loaders.unwrap_or_default().iter().map(|x| x.to_string()).collect(), - featured: v.featured, - dependencies: v.dependencies - .unwrap_or_default() - .iter() - .map(|f| { - let dependency: Vec<&str> = f.split(", ").collect(); - - if dependency.len() >= 3 { - Some(QueryDependency { - project_id: match &*dependency[1] { - "0" => None, - _ => match dependency[1].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[2].to_string(), - }) - } else { - None - } - }).flatten().collect(), - version_type: v.version_type - } - })) - }) - .try_collect::>() + futures::future::try_join_all(version_ids.into_iter().map(|id| Self::get_full(id, exec))) .await + .map(|x| x.into_iter().flatten().collect()) } } diff --git a/src/routes/version_creation.rs b/src/routes/version_creation.rs index ae53b1a0a..c9d607c52 100644 --- a/src/routes/version_creation.rs +++ b/src/routes/version_creation.rs @@ -413,6 +413,7 @@ pub async fn upload_file_to_version( let result = upload_file_to_version_inner( req, payload, + client, &mut transaction, &***file_host, &mut uploaded_files, @@ -441,6 +442,7 @@ pub async fn upload_file_to_version( async fn upload_file_to_version_inner( req: HttpRequest, mut payload: Multipart, + client: Data, mut transaction: &mut sqlx::Transaction<'_, sqlx::Postgres>, file_host: &dyn FileHost, uploaded_files: &mut Vec, @@ -453,7 +455,7 @@ async fn upload_file_to_version_inner( let user = get_user_from_headers(req.headers(), &mut *transaction).await?; - let result = models::Version::get_full(version_id, &mut *transaction).await?; + let result = models::Version::get_full(version_id, &**client).await?; let version = match result { Some(v) => v, diff --git a/src/search/indexing/local_import.rs b/src/search/indexing/local_import.rs index 1bd3967da..bd1f07710 100644 --- a/src/search/indexing/local_import.rs +++ b/src/search/indexing/local_import.rs @@ -7,7 +7,7 @@ use crate::models::projects::ProjectStatus; use crate::search::UploadSearchProject; use sqlx::postgres::PgPool; -// TODO: only loaders for recent versions? For projects that have moved from forge to fabric +// TODO: Move this away from STRING_AGG to multiple queries - however this may be more efficient? pub async fn index_local(pool: PgPool) -> Result, IndexingError> { info!("Indexing local projects!"); Ok( @@ -18,8 +18,8 @@ pub async fn index_local(pool: PgPool) -> Result, Index m.updated updated, m.team_id team_id, m.license license, m.slug slug, s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, pt.name project_type_name, u.username username, - ARRAY_AGG(DISTINCT c.category) categories, ARRAY_AGG(DISTINCT lo.loader) loaders, ARRAY_AGG(DISTINCT gv.version) versions, - ARRAY_AGG(DISTINCT mg.image_url) gallery + STRING_AGG(DISTINCT c.category, ',') categories, STRING_AGG(DISTINCT lo.loader, ',') loaders, STRING_AGG(DISTINCT gv.version, ',') versions, + STRING_AGG(DISTINCT mg.image_url, ',') gallery FROM mods m LEFT OUTER JOIN mods_categories mc ON joining_mod_id = m.id LEFT OUTER JOIN categories c ON mc.joining_category_id = c.id @@ -45,10 +45,10 @@ pub async fn index_local(pool: PgPool) -> Result, Index .fetch_many(&pool) .try_filter_map(|e| async { Ok(e.right().map(|m| { - let mut categories = m.categories.map(|x| x.iter().map(|x| x.to_string()).collect::>()).unwrap_or_default(); - categories.append(&mut m.loaders.map(|x| x.iter().map(|x| x.to_string()).collect::>()).unwrap_or_default()); + let mut categories = m.categories.map(|x| x.split(',').map(|x| x.to_string()).collect::>()).unwrap_or_default(); + categories.append(&mut m.loaders.map(|x| x.split(',').map(|x| x.to_string()).collect::>()).unwrap_or_default()); - let versions : Vec = m.versions.map(|x| x.iter().map(|x| x.to_string()).collect()).unwrap_or_default(); + let versions : Vec = m.versions.map(|x| x.split(',').map(|x| x.to_string()).collect()).unwrap_or_default(); let project_id : crate::models::projects::ProjectId = ProjectId(m.id).into(); @@ -72,12 +72,12 @@ pub async fn index_local(pool: PgPool) -> Result, Index server_side: m.server_side_type, slug: m.slug, project_type: m.project_type_name, - gallery: m.gallery.map(|x| x.iter().map(|x| x.to_string()).collect()).unwrap_or_default() + gallery: m.gallery.map(|x| x.split(',').map(|x| x.to_string()).collect()).unwrap_or_default() } })) }) - .try_collect::>() - .await? + .try_collect::>() + .await? ) } @@ -92,8 +92,8 @@ pub async fn query_one( m.updated updated, m.team_id team_id, m.license license, m.slug slug, s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, pt.name project_type_name, u.username username, - ARRAY_AGG(DISTINCT c.category) categories, ARRAY_AGG(DISTINCT lo.loader) loaders, ARRAY_AGG(DISTINCT gv.version) versions, - ARRAY_AGG(DISTINCT mg.image_url) gallery + STRING_AGG(DISTINCT c.category, ',') categories, STRING_AGG(DISTINCT lo.loader, ',') loaders, STRING_AGG(DISTINCT gv.version, ',') versions, + STRING_AGG(DISTINCT mg.image_url, ',') gallery FROM mods m LEFT OUTER JOIN mods_categories mc ON joining_mod_id = m.id LEFT OUTER JOIN categories c ON mc.joining_category_id = c.id @@ -116,23 +116,23 @@ pub async fn query_one( id as ProjectId, crate::models::teams::OWNER_ROLE, ) - .fetch_one(exec) - .await?; + .fetch_one(exec) + .await?; let mut categories = m .categories - .map(|x| x.iter().map(|x| x.to_string()).collect::>()) + .map(|x| x.split(',').map(|x| x.to_string()).collect::>()) .unwrap_or_default(); categories.append( &mut m .loaders - .map(|x| x.iter().map(|x| x.to_string()).collect::>()) + .map(|x| x.split(',').map(|x| x.to_string()).collect::>()) .unwrap_or_default(), ); let versions: Vec = m .versions - .map(|x| x.iter().map(|x| x.to_string()).collect()) + .map(|x| x.split(',').map(|x| x.to_string()).collect()) .unwrap_or_default(); let project_id: crate::models::projects::ProjectId = ProjectId(m.id).into(); @@ -162,7 +162,7 @@ pub async fn query_one( project_type: m.project_type_name, gallery: m .gallery - .map(|x| x.iter().map(|x| x.to_string()).collect()) + .map(|x| x.split(',').map(|x| x.to_string()).collect()) .unwrap_or_default(), }) }