Skip to content

Commit 3f79c2c

Browse files
authored
Fix back-reference index in AndroidCalendar.addEvent (#59)
* Make `BackReference` a data class to see the back reference value * Add test for problem * Fix back-reference index in AndroidCalendar event addition - Modify `addEvent` method in `AndroidCalendar` to use the correct back-reference index for event rows. - Update `withValueBackReference` function to include documentation about proper usage.
1 parent 34cdc3c commit 3f79c2c

File tree

3 files changed

+51
-3
lines changed

3 files changed

+51
-3
lines changed

lib/src/androidTest/kotlin/at/bitfire/synctools/storage/calendar/AndroidCalendarTest.kt

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package at.bitfire.synctools.storage.calendar
88

99
import android.accounts.Account
1010
import android.content.ContentProviderClient
11+
import android.content.ContentUris
1112
import android.content.ContentValues
1213
import android.content.Entity
1314
import android.provider.CalendarContract
@@ -17,6 +18,7 @@ import androidx.core.content.contentValuesOf
1718
import androidx.test.platform.app.InstrumentationRegistry
1819
import at.bitfire.ical4android.impl.TestCalendar
1920
import at.bitfire.ical4android.util.MiscUtils.closeCompat
21+
import at.bitfire.synctools.storage.BatchOperation
2022
import at.bitfire.synctools.test.InitCalendarProviderRule
2123
import at.bitfire.synctools.test.assertContentValuesEqual
2224
import org.junit.After
@@ -84,6 +86,44 @@ class AndroidCalendarTest {
8486
assertEquals(123, result.reminders.first().getAsInteger(Reminders.MINUTES))
8587
}
8688

89+
@Test
90+
fun testAddEvent_toBatch_AsSecondOperation() {
91+
val batch = CalendarBatchOperation(client)
92+
93+
// first operation: no-op
94+
batch += BatchOperation.CpoBuilder
95+
.newUpdate(calendar.eventsUri)
96+
.withValue(Events._SYNC_ID, "won't happen")
97+
.withSelection("${Events._SYNC_ID}=?", arrayOf("testAddEvent_toBatch_AsSecondOperation"))
98+
99+
// second operation (event row index > 0)
100+
val values = contentValuesOf(
101+
Events.CALENDAR_ID to calendar.id,
102+
Events.DTSTART to now,
103+
Events.DTEND to now + 3600000,
104+
Events.TITLE to "Some Event"
105+
)
106+
val entity = Entity(values)
107+
val reminder = contentValuesOf(
108+
Reminders.MINUTES to 123
109+
)
110+
entity.subValues.add(Entity.NamedContentValues(Reminders.CONTENT_URI, reminder))
111+
val idx = batch.nextBackrefIdx()
112+
calendar.addEvent(entity, batch)
113+
114+
batch.commit()
115+
val id = ContentUris.parseId(batch.getResult(idx)!!.uri!!)
116+
117+
// verify that event has been inserted
118+
val result = calendar.getEvent(id)!!
119+
assertEquals(id, result.id)
120+
assertEquals(now, result.dtStart)
121+
assertEquals(now + 3600000, result.dtEnd)
122+
assertEquals("Some Event", result.title)
123+
assertEquals(1, result.reminders.size)
124+
assertEquals(123, result.reminders.first().getAsInteger(Reminders.MINUTES))
125+
}
126+
87127
@Test
88128
fun testFindEvents() {
89129
calendar.addEvent(Entity(contentValuesOf(

lib/src/main/kotlin/at/bitfire/synctools/storage/BatchOperation.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,13 @@ open class BatchOperation internal constructor(
249249
return this
250250
}
251251

252+
/**
253+
* Creates a back-reference to the result of a previous INSERT in the batch.
254+
*
255+
* - Only reference INSERT operations (not UPDATE)!
256+
* - Don't assume an index value, especially if it's possible that previous operations could
257+
* have added operations to the batch. Instead, get the index from [at.bitfire.synctools.storage.BatchOperation.nextBackrefIdx].
258+
*/
252259
fun withValueBackReference(key: String, index: Int): CpoBuilder {
253260
valueBackrefs[key] = BackReference(index)
254261
return this

lib/src/main/kotlin/at/bitfire/synctools/storage/calendar/AndroidCalendar.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,14 +96,15 @@ class AndroidCalendar(
9696
}
9797

9898
internal fun addEvent(entity: Entity, batch: CalendarBatchOperation) {
99-
// insert main row
99+
// insert event row
100+
val eventRowIdx = batch.nextBackrefIdx()
100101
batch += CpoBuilder.newInsert(eventsUri).withValues(entity.entityValues)
101102

102-
// insert data rows (with reference to main row ID)
103+
// insert data rows (with reference to event row ID)
103104
for (row in entity.subValues)
104105
batch += CpoBuilder.newInsert(row.uri.asSyncAdapter(account))
105106
.withValues(row.values)
106-
.withValueBackReference(AndroidEvent2.DATA_ROW_EVENT_ID, /* result of first operation with index = */ 0)
107+
.withValueBackReference(AndroidEvent2.DATA_ROW_EVENT_ID, eventRowIdx)
107108
}
108109

109110
/**

0 commit comments

Comments
 (0)