From 8803af8bf68513b40b912f0e4acad0135bff00d8 Mon Sep 17 00:00:00 2001 From: labkey-nicka Date: Fri, 11 Jul 2025 13:49:19 -0700 Subject: [PATCH 1/2] Query optimization for plate set unique samples --- .../src/org/labkey/assay/plate/PlateManager.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/assay/src/org/labkey/assay/plate/PlateManager.java b/assay/src/org/labkey/assay/plate/PlateManager.java index 7bf7085075b..e6ca02f0623 100644 --- a/assay/src/org/labkey/assay/plate/PlateManager.java +++ b/assay/src/org/labkey/assay/plate/PlateManager.java @@ -3387,17 +3387,18 @@ public void validatePrimaryPlateSetUniqueSamples(Set wellRowIds, BatchV TableInfo wellTable = dbSchema.getTableInfoWell(); // Determines the set of primary plate sets that are being touched from the collection of well rowIds - SQLFragment primaryPlateSetsFromWellRowIdsSQL = new SQLFragment("SELECT PS.RowId FROM ").append(wellTable, "W") + // From the set of primary plate sets determine if any sample exists in more than one well within the entire plate set + SQLFragment nonUniqueSamplesPerPrimaryPlateSetSQL = new SQLFragment("WITH PlateSetFilter AS (") + .append("SELECT DISTINCT PS.RowId FROM ").append(wellTable, "W") .append(" INNER JOIN ").append(plateTable, "P").append(" ON P.RowId = W.PlateId") .append(" INNER JOIN ").append(plateSetTable, "PS").append(" ON PS.RowId = P.PlateSet") - .append(" WHERE PS.Type = ?").add("primary").append(" AND W.RowId ").appendInClause(wellRowIds, dialect); - - // From the set of primary plate sets determine if any sample exists in more than one well within the entire plate set - SQLFragment nonUniqueSamplesPerPrimaryPlateSetSQL = new SQLFragment("SELECT PS.Name AS PlateSetName, W.SampleId FROM ") - .append(wellTable, "W") + .append(" WHERE PS.Type = ?").add("primary").append(" AND W.RowId ").appendInClause(wellRowIds, dialect) + .append(" )") + .append(" SELECT PS.Name AS PlateSetName, W.SampleId FROM ").append(wellTable, "W") .append(" INNER JOIN ").append(plateTable, "P").append(" ON P.RowId = W.PlateId") .append(" INNER JOIN ").append(plateSetTable, "PS").append(" ON PS.RowId = P.PlateSet") - .append(" WHERE W.SampleId IS NOT NULL AND PS.RowId IN (").append(primaryPlateSetsFromWellRowIdsSQL).append(")") + .append(" INNER JOIN PlateSetFilter PSF ON PSF.RowId = PS.RowId") + .append(" WHERE W.SampleId IS NOT NULL") .append(" GROUP BY PS.RowId, W.SampleId, PS.Name HAVING COUNT(W.SampleId) > 1"); var duplicates = new SqlSelector(dbSchema.getSchema(), nonUniqueSamplesPerPrimaryPlateSetSQL).getMapCollection(); From 8b6d4083489c931583764c42e9e59e7514855f87 Mon Sep 17 00:00:00 2001 From: labkey-nicka Date: Fri, 11 Jul 2025 14:05:06 -0700 Subject: [PATCH 2/2] Issue 53446: A misconfigured assay design could be missing required fields --- .../org/labkey/assay/plate/PlateManager.java | 40 ++++++++++++------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/assay/src/org/labkey/assay/plate/PlateManager.java b/assay/src/org/labkey/assay/plate/PlateManager.java index e6ca02f0623..907bfd5dba1 100644 --- a/assay/src/org/labkey/assay/plate/PlateManager.java +++ b/assay/src/org/labkey/assay/plate/PlateManager.java @@ -609,29 +609,39 @@ private int getRunCountUsingPlateInResults(@NotNull Container c, @NotNull User u // get the runIds for each protocol, query against its assay results table List fragments = new ArrayList<>(); + Set requiredFields = Set.of(FieldKey.fromParts("DataId"), FieldKey.fromParts("Plate")); + + protocolLoop: for (ExpProtocol protocol : protocols) { AssayProtocolSchema assayProtocolSchema = provider.createProtocolSchema(user, protocol.getContainer(), protocol, null); TableInfo assayDataTable = assayProtocolSchema.createDataTable(ContainerFilter.getUnsafeEverythingFilter(), false); if (assayDataTable != null) { - ColumnInfo dataIdCol = assayDataTable.getColumn("DataId"); - if (dataIdCol != null) + // Issue 53446: A misconfigured assay design could be missing required fields. + // This is not expected. Don't let that stop the run counting but do log an error with more context. + for (FieldKey requiredFieldKey : requiredFields) { - SQLFragment subSelectSql = new SQLFragment("SELECT DISTINCT AD.DataId FROM ") - .append(assayDataTable.getFromSQL("AD", Set.of(FieldKey.fromParts("DataId"), FieldKey.fromParts("Plate")))) - .append(" WHERE AD.Plate = ?") - .add(plate.getRowId()); - - SQLFragment sql = new SQLFragment("SELECT COUNT(DISTINCT D.RunId) AS RunCount FROM\n") - .append(ExperimentService.get().getTinfoData(), "D") - .append(" INNER JOIN ") - .append(ExperimentService.get().getTinfoExperimentRun(), "R") - .append(" ON D.RunId = R.RowId\n") - .append(" WHERE R.ReplacedByRunId IS NULL AND D.RowId IN (").append(subSelectSql).append(")\n"); - - fragments.add(sql); + if (assayDataTable.getColumn(requiredFieldKey) == null) + { + LOG.error("Required field \"{}\" not found in plate-based assay results domain for protocol \"{}\" in {}.", requiredFieldKey.getName(), protocol.getName(), protocol.getContainer().getPath()); + continue protocolLoop; + } } + + SQLFragment subSelectSql = new SQLFragment("SELECT DISTINCT AD.DataId FROM ") + .append(assayDataTable.getFromSQL("AD", requiredFields)) + .append(" WHERE AD.Plate = ?") + .add(plate.getRowId()); + + SQLFragment sql = new SQLFragment("SELECT COUNT(DISTINCT D.RunId) AS RunCount FROM\n") + .append(ExperimentService.get().getTinfoData(), "D") + .append(" INNER JOIN ") + .append(ExperimentService.get().getTinfoExperimentRun(), "R") + .append(" ON D.RunId = R.RowId\n") + .append(" WHERE R.ReplacedByRunId IS NULL AND D.RowId IN (").append(subSelectSql).append(")\n"); + + fragments.add(sql); } }