Skip to content

Commit 6da0099

Browse files
authored
Merge pull request #362 from entur/refactor/farezone-query-search-builder
Fix fareZones query timeout by replacing correlated subquery with JOIN
2 parents 81bf6a6 + d4710d9 commit 6da0099

3 files changed

Lines changed: 44 additions & 4 deletions

File tree

src/main/java/org/rutebanken/tiamat/repository/search/FareZoneQueryFromSearchBuilder.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,18 @@ public class FareZoneQueryFromSearchBuilder {
3737

3838
public Pair<String, Map<String, Object>> buildQueryFromSearch(FareZoneSearch search) {
3939

40-
StringBuilder queryString = new StringBuilder("select f.* from fare_zone f ");
40+
StringBuilder queryString = new StringBuilder("""
41+
SELECT f.*
42+
FROM fare_zone f
43+
INNER JOIN (
44+
SELECT fv.netex_id, MAX(fv.version) AS max_version
45+
FROM fare_zone fv
46+
WHERE (fv.to_date IS NULL OR fv.to_date > NOW())
47+
AND (fv.from_date IS NULL OR fv.from_date < NOW())
48+
GROUP BY fv.netex_id
49+
) latest_fv ON f.netex_id = latest_fv.netex_id
50+
AND f.version = latest_fv.max_version
51+
""");
4152
List<String> wheres = new ArrayList<>();
4253
List<String> operators = new ArrayList<>();
4354
List<String> orderByStatements = new ArrayList<>();
@@ -69,9 +80,6 @@ public Pair<String, Map<String, Object>> buildQueryFromSearch(FareZoneSearch sea
6980
parameters.put("zoneTopology",search.getZoneTopologyEnumeration().name());
7081
}
7182

72-
operators.add("and");
73-
wheres.add("f.version = (select max(fv.version) from fare_zone fv where fv.netex_id = f.netex_id and (fv.to_date is null or fv.to_date > now()) and (fv.from_date is null or fv.from_date < now()))");
74-
7583
searchHelper.addWheres(queryString, wheres, operators);
7684
searchHelper.addOrderByStatements(queryString, orderByStatements);
7785
final String generatedSql = searchHelper.format(queryString.toString());
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CREATE INDEX idx_fare_zone_netex_id ON fare_zone (netex_id);
2+
CREATE INDEX idx_fare_zone_netex_id_version ON fare_zone (netex_id, version);
3+
CREATE INDEX idx_fare_zone_validity ON fare_zone (netex_id, version, from_date, to_date);

src/test/java/org/rutebanken/tiamat/repository/FareZoneRepositoryImplTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,35 @@ public void findFareZonesByIdPrefix() throws Exception {
141141
.containsOnly(fareZone2V.getNetexId());
142142
}
143143

144+
@Test
145+
public void findFareZonesReturnsOnlyCurrentVersionWhenMultipleVersionsExist() {
146+
String netexId = "RUT:FareZone:MultiVersion";
147+
Instant past = Instant.now().minusSeconds(3600);
148+
149+
FareZone v1 = new FareZone();
150+
v1.setNetexId(netexId);
151+
v1.setVersion(1L);
152+
v1.setName(new EmbeddableMultilingualString("Old"));
153+
v1.setValidBetween(new ValidBetween(past, past.plusSeconds(60)));
154+
fareZoneRepository.save(v1);
155+
156+
FareZone v2 = new FareZone();
157+
v2.setNetexId(netexId);
158+
v2.setVersion(2L);
159+
v2.setName(new EmbeddableMultilingualString("Current"));
160+
v2.setValidBetween(new ValidBetween(past, null));
161+
fareZoneRepository.save(v2);
162+
163+
FareZoneSearch search = FareZoneSearch.newFareZoneSearchBuilder().build();
164+
List<FareZone> result = fareZoneRepository.findFareZones(search);
165+
166+
assertThat(result)
167+
.filteredOn(fz -> netexId.equals(fz.getNetexId()))
168+
.hasSize(1)
169+
.extracting(FareZone::getVersion)
170+
.containsOnly(2L);
171+
}
172+
144173
@Test
145174
public void getFareZonesFromStopPlaceIds() throws Exception {
146175

0 commit comments

Comments
 (0)