fix: rewrite versions queries to hopefully suck less

This commit is contained in:
MiniDigger | Martin 2024-11-16 10:53:52 +01:00
parent df51435da8
commit 723c511337
4 changed files with 36 additions and 90 deletions

View File

@ -5,7 +5,6 @@ import io.papermc.hangar.controller.extras.pagination.annotations.ApplicableFilt
import io.papermc.hangar.controller.extras.pagination.annotations.ConfigurePagination;
import io.papermc.hangar.controller.extras.pagination.filters.versions.VersionChannelFilter;
import io.papermc.hangar.controller.extras.pagination.filters.versions.VersionPlatformFilter;
import io.papermc.hangar.controller.extras.pagination.filters.versions.VersionPlatformVersionFilter;
import io.papermc.hangar.controller.internal.config.VersionControllerConfig;
import io.papermc.hangar.model.api.PaginatedResult;
import io.papermc.hangar.model.api.project.version.UploadedVersion;
@ -70,7 +69,7 @@ public class VersionsController implements IVersionsController {
@Override
@VisibilityRequired(type = VisibilityRequired.Type.PROJECT, args = "{#slug}")
@ApplicableFilters({VersionChannelFilter.class, VersionPlatformFilter.class, VersionPlatformVersionFilter.class})
@ApplicableFilters({VersionChannelFilter.class, VersionPlatformFilter.class})
public PaginatedResult<Version> getVersions(final String slug,
@ConfigurePagination(defaultLimitString = "@hangarConfig.projects.initVersionLoad", maxLimit = 25) final @NotNull RequestPagination pagination,
@RequestParam(required = false, defaultValue = "true") final boolean includeHiddenChannels) {

View File

@ -52,6 +52,12 @@ public class VersionPlatformFilter implements Filter<VersionPlatformFilterInstan
@Override
public void createSql(final StringBuilder sb, final SqlStatement<?> q) {
if (this.platforms.length == Platform.values().length) {
return;
}
q.define("platformfilter", true);
sb.append(" AND (");
for (int i = 0; i < this.platforms.length; i++) {
sb.append(":__platform_").append(i).append(" = ANY(sq.platforms)");

View File

@ -1,63 +0,0 @@
package io.papermc.hangar.controller.extras.pagination.filters.versions;
import io.papermc.hangar.controller.extras.pagination.Filter;
import io.papermc.hangar.controller.extras.pagination.filters.versions.VersionPlatformVersionFilter.VersionPlatformVersionFilterInstance;
import java.util.Arrays;
import java.util.Set;
import org.jdbi.v3.core.statement.SqlStatement;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.NativeWebRequest;
@Component
public class VersionPlatformVersionFilter implements Filter<VersionPlatformVersionFilterInstance, String[]> {
@Override
public Set<String> getQueryParamNames() {
return Set.of("platformVersion");
}
@Override
public String getDescription() {
return "A platform version to filter for";
}
@Override
public String[] getValue(final NativeWebRequest webRequest) {
return webRequest.getParameterValues(this.getSingleQueryParam());
}
@Override
public @NotNull VersionPlatformVersionFilterInstance create(final NativeWebRequest webRequest) {
return new VersionPlatformVersionFilterInstance(this.getValue(webRequest));
}
static class VersionPlatformVersionFilterInstance implements Filter.FilterInstance {
private final String[] platformVersions;
public VersionPlatformVersionFilterInstance(final String[] platformVersions) {
this.platformVersions = platformVersions;
}
@Override
public void createSql(final StringBuilder sb, final SqlStatement<?> q) {
sb.append(" AND (");
for (int i = 0; i < this.platformVersions.length; i++) {
sb.append(":__platform_version_").append(i).append(" = ANY(sq.versions)");
q.bind("__platform_version_" + i, this.platformVersions[i]);
if (i + 1 != this.platformVersions.length) {
sb.append(" OR ");
}
}
sb.append(')');
}
@Override
public String toString() {
return "VersionPlatformVersionFilterInstance{" +
"platformVersions=" + Arrays.toString(this.platformVersions) +
'}';
}
}
}

View File

@ -112,6 +112,12 @@ public interface VersionsApiDAO {
@KeyColumn("id")
@RegisterColumnMapper(VersionStatsMapper.class)
@SqlQuery("""
<if(platformfilter)>
WITH sq AS (SELECT array_agg(DISTINCT plv.platform) platforms, array_agg(DISTINCT plv.version) versions, pvpd.version_id
FROM project_version_platform_dependencies pvpd
JOIN platform_versions plv ON pvpd.platform_version_id = plv.id
GROUP BY pvpd.version_id)
<endif>
SELECT pv.id,
pv.created_at,
pv.version_string,
@ -119,7 +125,7 @@ public interface VersionsApiDAO {
pv.description,
coalesce((SELECT sum(pvd.downloads) FROM project_versions_downloads pvd WHERE p.id = pvd.project_id AND pv.id = pvd.version_id), 0) vs_totalDownloads,
(select array_agg(d) from (SELECT pvd.platform, sum(pvd.downloads) FROM project_versions_downloads pvd WHERE p.id = pvd.project_id AND pv.id = pvd.version_id GROUP BY pvd.platform) d) vs_platformDownloads,
u.name author,
(select u.name from users u where u.id = pv.author_id) as author,
pv.review_state,
pc.created_at pc_created_at,
pc.name pc_name,
@ -134,12 +140,7 @@ public interface VersionsApiDAO {
FROM project_versions pv
JOIN projects p ON pv.project_id = p.id
JOIN project_channels pc ON pv.channel_id = pc.id
LEFT JOIN users u ON pv.author_id = u.id
INNER JOIN (SELECT array_agg(DISTINCT plv.platform) platforms, array_agg(DISTINCT plv.version) versions, pvpd.version_id
FROM project_version_platform_dependencies pvpd
JOIN platform_versions plv ON pvpd.platform_version_id = plv.id
GROUP BY pvpd.version_id
) sq ON pv.id = sq.version_id
<if(platformfilter)>INNER JOIN sq ON pv.id = sq.version_id<endif>
WHERE TRUE <filters>
<if(!canSeeHidden)>
AND (pv.visibility = 0
@ -148,27 +149,30 @@ public interface VersionsApiDAO {
<endif>)
<endif>
AND lower(p.slug) = lower(:slug)
GROUP BY pv.id, p.id, u.name, pc.id, pv.created_at ORDER BY pv.created_at DESC <offsetLimit>
ORDER BY pv.created_at DESC <offsetLimit>
""")
SortedMap<Long, Version> getVersions(String slug, @Define boolean canSeeHidden, @Define Long userId, @BindPagination RequestPagination pagination);
@SqlQuery("SELECT count(DISTINCT pv.id)" +
" FROM project_versions pv" +
" JOIN projects p ON pv.project_id = p.id" +
" JOIN project_channels pc ON pv.channel_id = pc.id" +
" INNER JOIN (SELECT array_agg(DISTINCT plv.platform) platforms, array_agg(DISTINCT plv.version) versions, pvpd.version_id" +
" FROM project_version_platform_dependencies pvpd" +
" JOIN platform_versions plv ON pvpd.platform_version_id = plv.id" +
" GROUP BY pvpd.version_id" +
" ) sq ON pv.id = sq.version_id" +
" WHERE TRUE <filters> " +
" <if(!canSeeHidden)>" +
" AND (pv.visibility = 0 " +
" <if(userId)>" +
" OR (<userId> IN (SELECT pm.user_id FROM project_members_all pm WHERE pm.id = p.id) AND pv.visibility != 4)" +
" <endif>)" +
" <endif> " +
" AND lower(p.slug) = lower(:slug)")
@SqlQuery("""
<if(platformfilter)>
WITH sq AS (SELECT array_agg(DISTINCT plv.platform) platforms, array_agg(DISTINCT plv.version) versions, pvpd.version_id
FROM project_version_platform_dependencies pvpd
JOIN platform_versions plv ON pvpd.platform_version_id = plv.id
GROUP BY pvpd.version_id)
<endif>
SELECT count(DISTINCT pv.id)
FROM project_versions pv
JOIN projects p ON pv.project_id = p.id
JOIN project_channels pc ON pv.channel_id = pc.id
<if(platformfilter)>INNER JOIN sq ON pv.id = sq.version_id<endif>
WHERE TRUE <filters>
<if(!canSeeHidden)>
AND (pv.visibility = 0
<if(userId)>
OR (<userId> IN (SELECT pm.user_id FROM project_members_all pm WHERE pm.id = p.id) AND pv.visibility != 4)
<endif>)
<endif>
AND lower(p.slug) = lower(:slug)""")
Long getVersionCount(String slug, @Define boolean canSeeHidden, @Define Long userId, @BindPagination(isCount = true) RequestPagination pagination);
@SqlQuery("SELECT " +