From bff041a0c36d2eb3d842ffa77f366f76b40c51ff Mon Sep 17 00:00:00 2001 From: "Charles Graham, SWT" Date: Wed, 26 Aug 2026 13:57:23 -0500 Subject: [PATCH] Fix direct time-series response unit validation Signed-off-by: Charles Graham, SWT --- .../cwms/cda/data/dao/TimeSeriesDaoImpl.java | 45 +++++-------------- .../cda/api/TimeSeriesDirectReadParityIT.java | 18 ++++++++ 2 files changed, 30 insertions(+), 33 deletions(-) diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesDaoImpl.java b/cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesDaoImpl.java index 0a34c2b21..0ed796f1f 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesDaoImpl.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesDaoImpl.java @@ -24,7 +24,6 @@ import static org.jooq.impl.DSL.partitionBy; import static org.jooq.impl.DSL.select; import static org.jooq.impl.DSL.selectDistinct; -import static org.jooq.impl.DSL.selectOne; import static org.jooq.impl.DSL.table; import static usace.cwms.db.jooq.codegen.tables.AV_CWMS_TS_ID2.AV_CWMS_TS_ID2; import static usace.cwms.db.jooq.codegen.tables.AV_TS_EXTENTS_UTC.AV_TS_EXTENTS_UTC; @@ -941,8 +940,6 @@ private TimeSeries getRequestedTimeSeriesDirect(String page, int pageSize, if (shouldFetchVerticalDatum(parmPart)) { verticalDatumInfo = fetchVerticalDatumInfoSeparately(locPart, requestedUnits, office); } - validateRequestedUnits(nativeUnits, metadataUnits); - VersionType finalDateVersionType = getDirectReadVersionType( metadata.versionFlag, versionDate != null); @@ -1000,8 +997,6 @@ private DirectReadMetadata fetchRequestedTimeSeriesMetadataRecord(DSLContext met final Field tsId = CWMS_TS_PACKAGE.call_GET_TS_ID__2(DSL.val(names), officeId); final Field tsCode = CWMS_TS_PACKAGE.call_GET_TS_CODE__2(DSL.val(names), officeId); - validateUnits(units, tsCode, officeId, names); - Table> validTs = select(tsCode.as("tscode"), tsId.as("tsid"), @@ -1049,7 +1044,7 @@ private DirectReadMetadata fetchRequestedTimeSeriesMetadataRecord(DSLContext met logger.atFine().log("%s", lazy(() -> metadataQuery.getSQL(ParamType.INLINED))); - return metadataQuery.fetchOne(record -> new DirectReadMetadata( + DirectReadMetadata metadata = metadataQuery.fetchOne(record -> new DirectReadMetadata( record.getValue("tscode", BigDecimal.class).longValue(), record.getValue("tsid", String.class), record.getValue("office_id", String.class), @@ -1065,32 +1060,10 @@ private DirectReadMetadata fetchRequestedTimeSeriesMetadataRecord(DSLContext met ? UTC : record.getValue("time_zone_id", String.class), record.getValue("version_flag", String.class))); - } - - private void validateUnits(String units, Field tsCode, Field officeId, String name) { - if(!units.equalsIgnoreCase("SI") && !units.equalsIgnoreCase("EN")) { - - boolean tsExists = dsl.fetchExists( - selectOne() - .from(AV_TSV_DQU.AV_TSV_DQU) - .where(AV_TSV_DQU.AV_TSV_DQU.TS_CODE.eq(tsCode.cast(Long.class))) - .and(AV_TSV_DQU.AV_TSV_DQU.OFFICE_ID.eq(officeId)) - ); - if(tsExists) { - boolean unitRequestedExists = dsl.fetchExists( - selectOne() - .from(AV_TSV_DQU.AV_TSV_DQU) - .where(AV_TSV_DQU.AV_TSV_DQU.TS_CODE.eq(tsCode.cast(Long.class))) - .and(AV_TSV_DQU.AV_TSV_DQU.OFFICE_ID.eq(officeId)) - .and(AV_TSV_DQU.AV_TSV_DQU.UNIT_ID.equalIgnoreCase(units)) - ); - - if (!unitRequestedExists) { - String msg = sanitizeOrNull(units + " is not a valid unit for time series " + name); - throw new InvalidItemException(msg, new IllegalArgumentException(msg)); - } - } + if (metadata != null) { + validateRequestedUnits(metadata.nativeUnits, metadata.units, names); } + return metadata; } private List fetchRequestedTimeSeriesRows(long tsCode, String officeId, @@ -1187,9 +1160,15 @@ private ResultQuery> buildMaxV .orderBy(dateTimeCol.asc()); } - private void validateRequestedUnits(String nativeUnits, String requestedUnits) { + private void validateRequestedUnits(String nativeUnits, String requestedUnits, String name) { if (nativeUnits != null && requestedUnits != null) { - CWMS_UTIL_PACKAGE.call_CONVERT_UNITS(dsl.configuration(), 0.0D, nativeUnits, requestedUnits); + try { + CWMS_UTIL_PACKAGE.call_CONVERT_UNITS(dsl.configuration(), 0.0D, nativeUnits, requestedUnits); + } catch (InvalidItemException ex) { + String message = sanitizeOrNull(requestedUnits + + " is not a valid unit for time series " + name); + throw new InvalidItemException(message, new IllegalArgumentException(message, ex)); + } } } diff --git a/cwms-data-api/src/test/java/cwms/cda/api/TimeSeriesDirectReadParityIT.java b/cwms-data-api/src/test/java/cwms/cda/api/TimeSeriesDirectReadParityIT.java index bff0e217b..fe37b05e7 100644 --- a/cwms-data-api/src/test/java/cwms/cda/api/TimeSeriesDirectReadParityIT.java +++ b/cwms-data-api/src/test/java/cwms/cda/api/TimeSeriesDirectReadParityIT.java @@ -70,6 +70,24 @@ void denseRegularReadMatchesRetrieveTs() throws Exception { ); } + @Test + void convertedUnitReadMatchesRetrieveTs() throws Exception { + assertDirectReadMatchesOracle( + "ITPARUNIT", + "ITPARUNIT.Stage.Inst.1Minute.0.BENCH", + "m", + Instant.parse("2024-01-01T00:00:00Z"), + Instant.parse("2024-01-01T00:05:00Z"), + denseRows(), + false, + false, + VersionType.UNVERSIONED, + Duration.ofMinutes(1), + 0L, + null + ); + } + @Test void denseRegularEntryDateReadMatchesRetrieveTs() throws Exception { assertDirectReadMatchesOracle(