Skip to content

Commit

Permalink
fix: interval bounds in temporal queries (#1220)
Browse files Browse the repository at this point in the history
Co-authored-by: Benoit Orihuela <[email protected]>
  • Loading branch information
ranim-n and bobeal authored Aug 15, 2024
1 parent 1a61d8a commit a740e14
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ class ScopeService(

when (temporalQuery.timerel) {
TemporalQuery.Timerel.BEFORE -> sqlQueryBuilder.append(" AND time < '${temporalQuery.timeAt}'")
TemporalQuery.Timerel.AFTER -> sqlQueryBuilder.append(" AND time > '${temporalQuery.timeAt}'")
TemporalQuery.Timerel.AFTER -> sqlQueryBuilder.append(" AND time >= '${temporalQuery.timeAt}'")
TemporalQuery.Timerel.BETWEEN -> sqlQueryBuilder.append(
" AND time > '${temporalQuery.timeAt}' AND time < '${temporalQuery.endTimeAt}'"
" AND time >= '${temporalQuery.timeAt}' AND time < '${temporalQuery.endTimeAt}'"
)
null -> Unit
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,9 @@ class AttributeInstanceService(

when (temporalQuery.timerel) {
Timerel.BEFORE -> sqlQueryBuilder.append(" AND time < '${temporalQuery.timeAt}'")
Timerel.AFTER -> sqlQueryBuilder.append(" AND time > '${temporalQuery.timeAt}'")
Timerel.AFTER -> sqlQueryBuilder.append(" AND time >= '${temporalQuery.timeAt}'")
Timerel.BETWEEN -> sqlQueryBuilder.append(
" AND time > '${temporalQuery.timeAt}' AND time < '${temporalQuery.endTimeAt}'"
" AND time >= '${temporalQuery.timeAt}' AND time < '${temporalQuery.endTimeAt}'"
)
null -> Unit
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate
import org.springframework.test.context.ActiveProfiles
import java.time.ZonedDateTime
import java.util.stream.Stream

@SpringBootTest
Expand Down Expand Up @@ -320,6 +321,98 @@ class ScopeServiceTests : WithTimescaleContainer, WithKafkaContainer {
}
}

@Test
fun `it should include lower bound of interval with after timerel`() = runTest {
loadSampleData("beehive_with_scope.jsonld")
.sampleDataToNgsiLdEntity()
.map { entityPayloadService.createEntityPayload(it.second, it.first, ngsiLdDateTime()) }
scopeService.addHistoryEntry(
beehiveTestCId,
listOf("/A", "/B/C"),
TemporalProperty.MODIFIED_AT,
ZonedDateTime.parse("2024-08-13T00:00:00Z")
).shouldSucceed()
scopeService.addHistoryEntry(
beehiveTestCId,
listOf("/B/C"),
TemporalProperty.MODIFIED_AT,
ZonedDateTime.parse("2024-08-14T00:00:00Z")
).shouldSucceed()

scopeService.retrieveHistory(
listOf(beehiveTestCId),
TemporalEntitiesQuery(
EntitiesQuery(
paginationQuery = PaginationQuery(limit = 100, offset = 0),
contexts = APIC_COMPOUND_CONTEXTS
),
buildDefaultTestTemporalQuery(
timeproperty = TemporalProperty.MODIFIED_AT,
timerel = TemporalQuery.Timerel.AFTER,
timeAt = ZonedDateTime.parse("2024-08-13T00:00:00Z"),
instanceLimit = 5
),
withTemporalValues = false,
withAudit = false,
withAggregatedValues = false
),
ngsiLdDateTime().minusHours(1)
).shouldSucceedWith {
assertEquals(2, it.size)
}
}

@Test
fun `it should exclude upper bound of interval with between timerel`() = runTest {
loadSampleData("beehive_with_scope.jsonld")
.sampleDataToNgsiLdEntity()
.map { entityPayloadService.createEntityPayload(it.second, it.first, ngsiLdDateTime()) }
scopeService.addHistoryEntry(
beehiveTestCId,
listOf("/A", "/B/C"),
TemporalProperty.MODIFIED_AT,
ZonedDateTime.parse("2024-08-13T00:00:00Z")
).shouldSucceed()
scopeService.addHistoryEntry(
beehiveTestCId,
listOf("/B/C"),
TemporalProperty.MODIFIED_AT,
ZonedDateTime.parse("2024-08-14T00:00:00Z")
).shouldSucceed()
scopeService.addHistoryEntry(
beehiveTestCId,
listOf("/C/D"),
TemporalProperty.MODIFIED_AT,
ZonedDateTime.parse("2024-08-15T00:00:00Z")
).shouldSucceed()

scopeService.retrieveHistory(
listOf(beehiveTestCId),
TemporalEntitiesQuery(
EntitiesQuery(
paginationQuery = PaginationQuery(limit = 100, offset = 0),
contexts = APIC_COMPOUND_CONTEXTS
),
buildDefaultTestTemporalQuery(
timeproperty = TemporalProperty.MODIFIED_AT,
timerel = TemporalQuery.Timerel.BETWEEN,
timeAt = ZonedDateTime.parse("2024-08-13T00:00:00Z"),
endTimeAt = ZonedDateTime.parse("2024-08-15T00:00:00Z"),
instanceLimit = 5
),
withTemporalValues = false,
withAudit = false,
withAggregatedValues = false
),
ngsiLdDateTime().minusHours(1)
).shouldSucceedWith {
assertEquals(2, it.size)
(it as List<FullScopeInstanceResult>).forEach { result ->
assertNotEquals(ZonedDateTime.parse("2024-08-15T00:00:00Z"), result.time)
}
}
}

@Test
fun `it should delete scope and its history`() = runTest {
loadSampleData("beehive_with_scope.jsonld")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import org.springframework.test.context.ActiveProfiles
import java.time.Instant
import java.time.ZoneOffset
import java.time.ZonedDateTime
import java.util.*
import java.util.UUID

@SpringBootTest
@ActiveProfiles("test")
Expand Down Expand Up @@ -346,6 +346,60 @@ class AttributeInstanceServiceTests : WithTimescaleContainer, WithKafkaContainer
assertEquals(ZonedDateTime.parse("2022-07-01T00:00:00Z"), origin)
}

@Test
fun `it should include lower bound of interval with after timerel`() = runTest {
(1..5).forEachIndexed { index, _ ->
val attributeInstance =
gimmeNumericPropertyAttributeInstance(incomingTemporalEntityAttribute.id)
.copy(
measuredValue = index.toDouble(),
time = ZonedDateTime.parse("2022-07-0${index + 1}T00:00:00Z")
)
attributeInstanceService.create(attributeInstance)
}
val temporalEntitiesQuery = gimmeTemporalEntitiesQuery(
buildDefaultTestTemporalQuery(
timerel = Timerel.AFTER,
timeAt = ZonedDateTime.parse("2022-07-01T00:00:00Z"),
instanceLimit = 5
)
)

attributeInstanceService.search(temporalEntitiesQuery, incomingTemporalEntityAttribute)
.shouldSucceedWith {
assertEquals(5, it.size)
}
}

@Test
fun `it should exclude upper bound of interval with between timerel`() = runTest {
(1..5).forEachIndexed { index, _ ->
val attributeInstance =
gimmeNumericPropertyAttributeInstance(incomingTemporalEntityAttribute.id)
.copy(
measuredValue = index.toDouble(),
time = ZonedDateTime.parse("2022-07-0${index + 1}T00:00:00Z")
)
attributeInstanceService.create(attributeInstance)
}
val temporalEntitiesQuery = gimmeTemporalEntitiesQuery(
buildDefaultTestTemporalQuery(
timerel = Timerel.BETWEEN,
timeAt = ZonedDateTime.parse("2022-07-01T00:00:00Z"),
endTimeAt = ZonedDateTime.parse("2022-07-05T00:00:00Z"),
instanceLimit = 5
)
)

attributeInstanceService.search(temporalEntitiesQuery, incomingTemporalEntityAttribute)
.shouldSucceedWith {
assertEquals(4, it.size)
(it as List<FullAttributeInstanceResult>).forEach { result ->
assertNotEquals(ZonedDateTime.parse("2022-07-05T00:00:00Z"), result.time)
}
}
}

@Test
fun `it should only return the limited instances asked in the temporal query`() = runTest {
(1..10).forEach { _ ->
Expand Down

0 comments on commit a740e14

Please sign in to comment.