Docs Client library reference Kotlin
v0.2.6-alpha.3Kotlin: Insert data
from(table).insert(columns) writes the row into the local database and queues one outbox mutation for the next sync run, minting a uuid primary key when the table is keyed by id and columns carry none. apply(table, pk, op, ...) is the same write at the low level, for a call site that already has its own primary key or needs mutationId.
Examples#
Basic#
// app/src/main/kotlin/com/example/todo/TodoScreen.kt (excerpt)
kizunasync.from("todos").insert(
mapOf("title" to "works on a plane", "done" to false),
)With your own primary key#
// app/src/main/kotlin/com/example/todo/TodoScreen.kt (excerpt)
import java.util.UUID
kizunasync.from("todos").insert(
mapOf(
"id" to UUID.randomUUID().toString(),
"title" to "works on a plane",
"done" to false,
),
)Low-level: apply#
// app/src/main/kotlin/com/example/todo/TodoScreen.kt (excerpt)
import com.kizunasync.kizunasync.KizunaSyncOp
import java.util.UUID
val mutationId = UUID.randomUUID().toString()
kizunasync.apply(
table = "todos",
pk = todoId,
op = KizunaSyncOp.Insert,
columns = mapOf("title" to "works on a plane", "done" to false),
mutationId = mutationId,
)The id you pass as mutationId is the one the server's verdict and any journal entry carry, so a screen can match a rejection back to the write that caused it. from(table).insert(columns) has no mutationId parameter; use apply when you need to pass one.
Read the inserted row back#
// app/src/main/kotlin/com/example/todo/TodoScreen.kt (excerpt)
import java.util.UUID
val todoId = UUID.randomUUID().toString()
kizunasync.from("todos").insert(mapOf("id" to todoId, "title" to "works on a plane", "done" to false))
val todo = kizunasync.from("todos").select("id, title").eq("id", todoId).single()insert(columns) writes the row at once and answers nothing. Pass the id, then read the row back by it, with any column the engine filled.
Parameters#
from(table).insert(columns)#
| Name | Type | Required | Description |
|---|---|---|---|
columns | Map<String, Any?> | No | Column values for the row. On a table keyed by id alone, a row without "id" gets a minted lowercase UUID. Every other row names each column of the table's row key with a non-empty string or an integer, and the engine derives the primary key from them. A uuid-shaped key value is stored and pushed in lowercase, whatever case you pass. Default: empty. |
apply(table, pk, op, columns, mutationId, transforms, precondition)#
| Name | Type | Required | Description |
|---|---|---|---|
table | String | Yes | Table name, which must be one of the keys of tables in Initializing. |
pk | String | Yes | Primary key of the new row. It must be non-empty: the client refuses an empty value before the engine is reached. On a table keyed by id whose columns leave id out, it is the row's id, a UUID string or the decimal text of an integer. Otherwise it must be the key text the key columns in columns spell, described in Row keys. The engine lowercases a uuid-shaped key value and spells a composite key in canonical form before it compares the two. |
op | KizunaSyncOp | Yes | Set to KizunaSyncOp.Insert, whose column payload is the one Supabase documents for insert(). |
columns | Map<String, Any?> | No | Column values for the row, encoded to a JSONObject. Default: empty. |
mutationId | String? | No | Client-side id of this mutation, echoed in the server verdict and in the journal. Default: null, which makes the engine generate a UUID. |
transforms | Map<String, Any?>? | No | Field transforms, keyed by column. The local insert path writes columns only, so a transform changes nothing locally on an insert. See Using transforms. Default: null. |
precondition | Map<String, Any?>? | No | Column values the server compares against the row it can see before it applies the mutation. A mismatch is rejected with reason PRECONDITION instead of applied. Default: null. |
Returns#
Unit. Both functions suspend on Dispatchers.IO, so neither ever blocks the Android main thread.
Errors#
| Code | Condition |
|---|---|
UNKNOWN_TABLE | table is not one of the tables the client was created with. |
LOCAL_CONSTRAINT | A key column is missing, null, or neither a string nor an integer, and the message names it; pk spells another primary key than the key columns in columns; or a live row already holds this key in this table. |
JSON | The engine cannot parse the encoded mutation. |
ENGINE_UNAVAILABLE | The client has no engine because Initializing has not run. |
apply throws KizunaSyncError.Engine("LOCAL_UNSUPPORTED", "apply requires table and pk") inside the client when table or pk is empty, before the engine is reached. A value org.json refuses never reaches the engine: the client raises a JSONException while encoding, so it surfaces as that exception rather than an engine code.
Notes#
Supabase documents the column payload and its parameters on insert(); this page adds only what local-first changes. The write lands in local SQLite first and its verdict arrives with a later Sync, which is the path Offline writes walks through. A successful insert raises LOCAL_CHANGED and then QUEUE_DEPTH on Subscribe to events, so a list can refresh itself without polling. Until a run delivers it, the row is counted by Outbox depth. The Host scheduler wakes on that QUEUE_DEPTH event, so the write goes out without waiting for its timer.
On a table whose bucket is KizunaSyncBucket.ByOwner(column), an insert that leaves that column out is written with the owner's id: the user the first session token named, at create or through Set access token, which the local database keeps across launches. The outbox entry carries the filled column too. An insert that names the column keeps its value, null included, and an update or a delete is never filled. Before any token has named an owner, the insert keeps only the columns you passed.
Row Level Security judges the insert when the push reaches the server, not when this function returns. When a policy refuses the row, the engine reverts it after the fact and journals the rejection. Supabase describes the policy side under Row Level Security.
Related reference#
Found a problem? Edit this page on GitHub