From fc646475c8464a4edae9bee53602cb6a1f3a1ad5 Mon Sep 17 00:00:00 2001 From: Vagisha Sharma Date: Sat, 25 Apr 2026 18:00:37 -0700 Subject: [PATCH 1/5] Added container filtering on test results tables. --- .../testresults/TestResultsController.java | 9 +- .../labkey/testresults/TestResultsSchema.java | 69 +++++++++++- .../src/org/labkey/testresults/view/user.jsp | 2 +- .../tests/testresults/TestResultsTest.java | 106 +++++++++++++++++- 4 files changed, 178 insertions(+), 8 deletions(-) diff --git a/testresults/src/org/labkey/testresults/TestResultsController.java b/testresults/src/org/labkey/testresults/TestResultsController.java index aeebef33..d7d467fa 100644 --- a/testresults/src/org/labkey/testresults/TestResultsController.java +++ b/testresults/src/org/labkey/testresults/TestResultsController.java @@ -410,10 +410,15 @@ public static void ensureRunDataCached(RunDetail[] runs, boolean keepObjData) { public static User[] getUsers(Container trainingDataContainer, String username) { SQLFragment sqlFragment = new SQLFragment(); - sqlFragment.append("SELECT id, username FROM testresults.user"); + sqlFragment.append("SELECT id, username FROM testresults.user WHERE 1=1"); + if (trainingDataContainer != null) + { + sqlFragment.append(" AND id IN (SELECT userid FROM testresults.testruns WHERE container = ?)"); + sqlFragment.add(trainingDataContainer.getEntityId()); + } if (username != null && !username.isEmpty()) { - sqlFragment.append(" WHERE username = ?"); + sqlFragment.append(" AND username = ?"); sqlFragment.add(username); } sqlFragment.append(" ORDER BY id"); diff --git a/testresults/src/org/labkey/testresults/TestResultsSchema.java b/testresults/src/org/labkey/testresults/TestResultsSchema.java index d76d5ae9..ee0107ab 100644 --- a/testresults/src/org/labkey/testresults/TestResultsSchema.java +++ b/testresults/src/org/labkey/testresults/TestResultsSchema.java @@ -24,10 +24,12 @@ import org.labkey.api.data.DbSchema; import org.labkey.api.data.DbSchemaType; import org.labkey.api.data.ForeignKey; +import org.labkey.api.data.SQLFragment; import org.labkey.api.data.TableInfo; import org.labkey.api.data.dialect.SqlDialect; import org.labkey.api.module.Module; import org.labkey.api.query.DefaultSchema; +import org.labkey.api.query.FieldKey; import org.labkey.api.query.FilteredTable; import org.labkey.api.query.QueryForeignKey; import org.labkey.api.query.QuerySchema; @@ -86,7 +88,8 @@ public static SqlDialect getSqlDialect() @Override public @Nullable TableInfo createTable(@NotNull String name, @NotNull ContainerFilter cf) { - TableInfo dbTable = switch (name.toLowerCase()) + String lower = name.toLowerCase(); + TableInfo dbTable = switch (lower) { case TABLE_TEST_RUNS -> getTableInfoTestRuns(); case TABLE_USER -> getTableInfoUser(); @@ -102,12 +105,74 @@ public static SqlDialect getSqlDialect() }; if (dbTable == null) return null; - FilteredTable table = new FilteredTable<>(dbTable, this, cf); + FilteredTable table = switch (lower) + { + case TABLE_HANGS, TABLE_MEMORY_LEAKS, TABLE_HANDLE_LEAKS, TABLE_TEST_PASSES, TABLE_TEST_FAILS -> + createRunChildTable(dbTable, cf, "testrunid"); + case TABLE_TRAIN_RUNS -> + createRunChildTable(dbTable, cf, "runid"); + case TABLE_USER -> + createUserTable(dbTable, cf); + default -> + new FilteredTable<>(dbTable, this, cf); + }; table.wrapAllColumns(true); resolveSchemaForeignKeys(table, cf); return table; } + /** + * Filters a table that has no container column of its own by joining to testruns + * via fkColumn and applying the container filter to testruns.container. + */ + private FilteredTable createRunChildTable(TableInfo dbTable, ContainerFilter cf, String fkColumn) + { + return new FilteredTable<>(dbTable, this, cf) + { + @Override + public FieldKey getContainerFieldKey() + { + return FieldKey.fromParts(fkColumn, "container"); + } + + @Override + protected void applyContainerFilter(ContainerFilter filter) + { + FieldKey containerFieldKey = FieldKey.fromParts("container"); + clearConditions(containerFieldKey); + SQLFragment sql = new SQLFragment().appendIdentifier(fkColumn).append(" IN (SELECT tr.id FROM "); + sql.append(getTableInfoTestRuns(), "tr"); + sql.append(" WHERE "); + sql.append(filter.getSQLFragment(getSchema(), new SQLFragment("tr.container"))); + sql.append(")"); + addCondition(sql, containerFieldKey); + } + }; + } + + /** + * The user table has no container column and no FK to testruns. Filter it to users + * referenced by at least one testrun in an allowed container. + */ + private FilteredTable createUserTable(TableInfo dbTable, ContainerFilter cf) + { + return new FilteredTable<>(dbTable, this, cf) + { + @Override + protected void applyContainerFilter(ContainerFilter filter) + { + FieldKey containerFieldKey = FieldKey.fromParts("container"); + clearConditions(containerFieldKey); + SQLFragment sql = new SQLFragment("id IN (SELECT tr.userid FROM "); + sql.append(getTableInfoTestRuns(), "tr"); + sql.append(" WHERE "); + sql.append(filter.getSQLFragment(getSchema(), new SQLFragment("tr.container"))); + sql.append(")"); + addCondition(sql, containerFieldKey); + } + }; + } + /** * Converts DbSchema-level FKs (propagated by wrapAllColumns()) into UserSchema-level FKs * so the Query Schema Browser renders hyperlinks and can navigate to target query grids. diff --git a/testresults/src/org/labkey/testresults/view/user.jsp b/testresults/src/org/labkey/testresults/view/user.jsp index 7396e469..954d7f22 100644 --- a/testresults/src/org/labkey/testresults/view/user.jsp +++ b/testresults/src/org/labkey/testresults/view/user.jsp @@ -86,7 +86,7 @@ <%-- This form is meant to parse and store xml files into the database--%> <%-- --%> <% - User[] users = TestResultsController.getUsers(null, null); + User[] users = TestResultsController.getUsers(getViewContext().getContainer(), null); Arrays.sort(users, Comparator.comparing(User::getUsername)); %>
This form is meant to parse and store xml files into the database--%> <%-- --%> <% - User[] users = TestResultsController.getUsers(getViewContext().getContainer(), null); + User[] users = TestResultsController.getUsers(getViewContext().getUser(), getViewContext().getContainer(), null); Arrays.sort(users, Comparator.comparing(User::getUsername)); %>