Skip to Content

Querying & DML

KalamClient.query(...) executes SQL over the KalamDB HTTP API and returns a QueryResponse.

final response = await client.query('SELECT 1'); print(response.success);

Parameterized queries

Use $1, $2, … placeholders in SQL and pass params as a Dart list.

final res = await client.query( r'SELECT * FROM app.messages WHERE conversation_id = $1 AND is_deleted = $2', params: ['conv_42', false], );

params is encoded to JSON and sent to the server, so values should be JSON-compatible (strings, numbers, booleans, null, lists, and maps).

If you need richer server-side typing (timestamps, decimals, JSON columns), keep your SQL explicit (e.g. CAST(...)) and validate the returned values.

Namespaces

KalamDB supports per-tenant namespaces. The SDK exposes this as an optional namespace argument.

final res = await client.query( 'SELECT * FROM messages ORDER BY created_at DESC LIMIT 10', namespace: 'alice', );

This is most useful when your SQL references unqualified tables (e.g. messages instead of alice.messages).

For background, see: SQL Reference: Namespaces.

Reading results

A QueryResponse can contain multiple QueryResult values (one per statement). The most common pattern is to read the first one.

Convenience access

if (!res.success) { print(res.error); return; } // First result set print(res.columns.map((c) => c.name).toList()); print(res.rows); // List<List<dynamic>> print(res.toMaps()); // List<Map<String, dynamic>>

Multiple statements

final res = await client.query('SELECT 1; SELECT 2;'); for (final (i, r) in res.results.indexed) { print('statement[$i] columns=${r.columns.length} rows=${r.rowCount}'); }

DML: INSERT / UPDATE / DELETE

All SQL goes through query(...):

await client.query( r"INSERT INTO app.messages (conversation_id, role, content) VALUES ($1, $2, $3)", params: [42, 'user', 'hello'], ); await client.query( r"UPDATE app.messages SET content = $1 WHERE message_id = $2", params: ['edited', 'msg_123'], ); await client.query( r"DELETE FROM app.messages WHERE message_id = $1", params: ['msg_123'], );

Error handling

When success is false, the server returns an error code/message:

final res = await client.query('SELECT * FROM table_that_does_not_exist'); if (!res.success) { throw StateError('${res.error}'); }

For user-facing apps, prefer mapping error.code to a stable UI message and logging error.details for debugging.

Next

Last updated on