Skip to content

incremental watch queries (wip) #199

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
17 changes: 2 additions & 15 deletions client-sdk-references/dotnet.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
---

import DotNetInstallation from '/snippets/dotnet/installation.mdx';
import DotNetWatch from '/snippets/dotnet/basic-watch-query.mdx';

<CardGroup>
<Card title="PowerSync SDK on NuGet" icon="nuget" href="https://www.nuget.org/packages/PowerSync.Common/">
Expand Down Expand Up @@ -38,7 +39,7 @@
* **WPF**: Windows desktop applications

**Current Limitations**:
* Blazor (web) platforms are not yet supported.

Check warning on line 42 in client-sdk-references/dotnet.mdx

View check run for this annotation

Mintlify / Mintlify Validation (powersync) - vale-spellcheck

client-sdk-references/dotnet.mdx#L42

Did you really mean 'Blazor'?

For more details, please refer to the package [README](https://github.com/powersync-ja/powersync-dotnet/tree/main?tab=readme-ov-file).

Expand Down Expand Up @@ -154,7 +155,7 @@

public class MyConnector : IPowerSyncBackendConnector
{
private readonly HttpClient _httpClient;

Check warning on line 158 in client-sdk-references/dotnet.mdx

View check run for this annotation

Mintlify / Mintlify Validation (powersync) - vale-spellcheck

client-sdk-references/dotnet.mdx#L158

Did you really mean 'readonly'?

Check warning on line 158 in client-sdk-references/dotnet.mdx

View check run for this annotation

Mintlify / Mintlify Validation (powersync) - vale-spellcheck

client-sdk-references/dotnet.mdx#L158

Did you really mean '_httpClient'?

// User credentials for the current session
public string UserId { get; private set; }
Expand Down Expand Up @@ -276,21 +277,7 @@
Console.WriteLine(await db.GetAll<ListResult>("SELECT * FROM lists;"));

// Use db.Watch() to watch queries for changes (await is used to wait for initialization):
await db.Watch("select * from lists", null, new WatchHandler<ListResult>
{
OnResult = (results) =>
{
Console.WriteLine("Results: ");
foreach (var result in results)
{
Console.WriteLine(result.id + ":" + result.name);
}
},
OnError = (error) =>
{
Console.WriteLine("Error: " + error.Message);
}
});
<DotNetWatch />

// And db.Execute for inserts, updates and deletes:
await db.Execute(
Expand Down
32 changes: 2 additions & 30 deletions client-sdk-references/flutter.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import SdkFeatures from '/snippets/sdk-features.mdx';
import FlutterInstallation from '/snippets/flutter/installation.mdx';
import FlutterWatch from '/snippets/flutter/basic-watch-query.mdx';

<CardGroup>
<Card title="PowerSync SDK on pub.dev" icon="cube" href="https://pub.dev/packages/powersync">
Expand Down Expand Up @@ -74,7 +75,7 @@
Similar functionality exists in the [CLI](/usage/tools/cli).

</Info>
The types available are `text`, `integer` and `real`. These should map directly to the values produced by the [Sync Rules](/usage/sync-rules). If a value doesn't match, it is cast automatically. For details on how Postgres types are mapped to the types below, see the section on [Types](/usage/sync-rules/types) in the _Sync Rules_ documentation.

Check warning on line 78 in client-sdk-references/flutter.mdx

View check run for this annotation

Mintlify / Mintlify Validation (powersync) - vale-spellcheck

client-sdk-references/flutter.mdx#L78

Did you really mean '_Sync'?

Check warning on line 78 in client-sdk-references/flutter.mdx

View check run for this annotation

Mintlify / Mintlify Validation (powersync) - vale-spellcheck

client-sdk-references/flutter.mdx#L78

Did you really mean 'Rules_'?

**Example**:

Expand Down Expand Up @@ -327,36 +328,7 @@

The [watch](https://pub.dev/documentation/powersync/latest/sqlite_async/SqliteQueries/watch.html) method executes a read query whenever a change to a dependent table is made.

```dart lib/widgets/todos_widget.dart {13-17}
import 'package:flutter/material.dart';
import '../main.dart';
import '../models/todolist.dart';

// Example Todos widget
class TodosWidget extends StatelessWidget {
const TodosWidget({super.key});

@override
Widget build(BuildContext context) {
return StreamBuilder(
// You can watch any SQL query
stream: db
.watch('SELECT * FROM lists ORDER BY created_at, id')
.map((results) {
return results.map(TodoList.fromRow).toList(growable: false);
}),
builder: (context, snapshot) {
if (snapshot.hasData) {
// TODO: implement your own UI here based on the result set
return ...;
} else {
return const Center(child: CircularProgressIndicator());
}
},
);
}
}
```
<FlutterWatch />

### Mutations (PowerSync.execute)

Expand Down
17 changes: 3 additions & 14 deletions client-sdk-references/flutter/usage-examples.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ title: "Usage Examples"
description: "Code snippets and guidelines for common scenarios"
---

import FlutterWatch from '/snippets/flutter/basic-watch-query.mdx';

## Using transactions to group changes

Read and write transactions present a context where multiple changes can be made then finally committed to the DB or rolled back. This ensures that either all the changes get persisted, or no change is made to the DB (in the case of a rollback or exception).
Expand All @@ -26,20 +28,7 @@ Also see [readTransaction(callback)](https://pub.dev/documentation/powersync/lat

Use [watch](https://pub.dev/documentation/powersync/latest/sqlite_async/SqliteQueries/watch.html) to watch for changes to the dependent tables of any SQL query.

```dart
StreamBuilder(
// You can watch any SQL query
stream: db.watch('SELECT * FROM customers order by id asc'),
builder: (context, snapshot) {
if (snapshot.hasData) {
// TODO: implement your own UI here based on the result set
return ...;
} else {
return const Center(child: CircularProgressIndicator());
}
},
)
```
<FlutterWatch />

## Insert, update, and delete data in the local database

Expand Down
27 changes: 12 additions & 15 deletions client-sdk-references/javascript-web.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ sidebarTitle: "Overview"

import SdkFeatures from '/snippets/sdk-features.mdx';
import JavaScriptWebInstallation from '/snippets/javascript-web/installation.mdx';
import JavaScriptAsyncWatch from '/snippets/basic-watch-query-javascript-async.mdx';
import JavaScriptCallbackWatch from '/snippets/basic-watch-query-javascript-callback.mdx';

<CardGroup cols={2}>
<Card title="PowerSync SDK on NPM" icon="npm" href="https://www.npmjs.com/package/@powersync/web">
Expand Down Expand Up @@ -219,21 +221,16 @@ export const getLists = async () => {

The [watch](https://powersync-ja.github.io/powersync-js/web-sdk/classes/PowerSyncDatabase#watch) method executes a read query whenever a change to a dependent table is made.

```js
// Watch changes to lists
const abortController = new AbortController();

export const function watchLists = (onUpdate) => {
for await (const update of PowerSync.watch(
'SELECT * from lists',
[],
{ signal: abortController.signal }
)
) {
onUpdate(update);
}
}
```
<Tabs>
<Tab title="AsyncIterator approach">
<JavaScriptAsyncWatch />
</Tab>
<Tab title="Callback approach">
<JavaScriptCallbackWatch />
</Tab>
</Tabs>

For advanced watch query features like incremental updates and differential results, see [Live Queries / Watch Queries](/usage/use-case-examples/watch-queries).

### Mutations (PowerSync.execute, PowerSync.writeTransaction)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ The main hooks available are:

* `useSuspenseQuery`: This hook also allows you to access the results of a watched query, but its loading and fetching states are handled through [Suspense](https://react.dev/reference/react/Suspense). It automatically converts certain loading/fetching states into Suspense signals, triggering Suspense boundaries in parent components.

<Info>
For advanced watch query features like incremental updates and differential results for React Hooks, see [Live Queries / Watch Queries](/usage/use-case-examples/watch-queries).
</Info>

The full API Reference and example code can be found here:

<Card title="React hooks for PowerSync | PowerSync JavaScript SDK Docs" icon="book" href="https://powersync-ja.github.io/powersync-js/react-sdk" horizontal />
Expand Down Expand Up @@ -93,6 +97,10 @@ The main hooks available are:

* `useStatus`: Access the PowerSync connectivity status. This can be used to update the UI based on whether the client is connected or not.

<Info>
For advanced watch query features like incremental updates and differential results for Vue Hooks, see [Live Queries / Watch Queries](/usage/use-case-examples/watch-queries).
</Info>

The full API Reference and example code can be found here:

<Card title="Vue composables for PowerSync | PowerSync JavaScript SDK Docs" icon="book" href="https://powersync-ja.github.io/powersync-js/vue-sdk" horizontal />
39 changes: 12 additions & 27 deletions client-sdk-references/javascript-web/usage-examples.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ title: "Usage Examples"
description: "Code snippets and guidelines for common scenarios"
---

import JavaScriptAsyncWatch from '/snippets/basic-watch-query-javascript-async.mdx';
import JavaScriptCallbackWatch from '/snippets/basic-watch-query-javascript-callback.mdx';

## Multiple Tab Support

<Warning>
Expand Down Expand Up @@ -108,34 +111,16 @@ Also see [PowerSyncDatabase.readTransaction(callback)](https://powersync-ja.gith

Use [PowerSyncDatabase.watch](https://powersync-ja.github.io/powersync-js/web-sdk/classes/PowerSyncDatabase#watch) to watch for changes in source tables.

The `watch` method can be used with a `AsyncIterable` signature as follows:

```js
async *attachmentIds(): AsyncIterable<string[]> {
for await (const result of this.powersync.watch(
`SELECT photo_id as id FROM ${TODO_TABLE} WHERE photo_id IS NOT NULL`,
[]
)) {
yield result.rows?._array.map((r) => r.id) ?? [];
}
}
```

As of version **1.3.3** of the SDK, the `watch` method can also be used with a callback:
<Tabs>
<Tab title="AsyncIterator approach">
<JavaScriptAsyncWatch />
</Tab>
<Tab title="Callback approach">
<JavaScriptCallbackWatch />
</Tab>
</Tabs>

```js
attachmentIds(onResult: (ids: string[]) => void): void {
this.powersync.watch(
`SELECT photo_id as id FROM ${TODO_TABLE} WHERE photo_id IS NOT NULL`,
[],
{
onResult: (result) => {
onResult(result.rows?._array.map((r) => r.id) ?? []);
}
}
);
}
```
For advanced watch query features like incremental updates and differential results, see [Live Queries / Watch Queries](/usage/use-case-examples/watch-queries).

## Insert, update, and delete data in the local database

Expand Down
17 changes: 2 additions & 15 deletions client-sdk-references/kotlin-multiplatform.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ sidebarTitle: Overview

import SdkFeatures from '/snippets/sdk-features.mdx';
import KotlinMultiplatformInstallation from '/snippets/kotlin-multiplatform/installation.mdx';
import KotlinWatch from '/snippets/kotlin-multiplatform/basic-watch-query.mdx';

<CardGroup>
<Card title="PowerSync SDK on Maven Central" icon="npm" href="https://central.sonatype.com/artifact/com.powersync/core">
Expand Down Expand Up @@ -242,21 +243,7 @@ suspend fun getLists(): List<String> {

The `watch` method executes a read query whenever a change to a dependent table is made.

```kotlin
// You can watch any SQL query
fun watchCustomers(): Flow<List<User>> {
// TODO: implement your UI based on the result set
return database.watch(
"SELECT * FROM customers"
) { cursor ->
User(
id = cursor.getString("id"),
name = cursor.getString("name"),
email = cursor.getString("email")
)
}
}
```
<KotlinWatch />

### Mutations (PowerSync.execute)

Expand Down
16 changes: 3 additions & 13 deletions client-sdk-references/kotlin-multiplatform/usage-examples.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ title: "Usage Examples"
description: "Code snippets and guidelines for common scenarios"
---

import KotlinWatch from '/snippets/kotlin-multiplatform/basic-watch-query.mdx';

## Using transactions to group changes

Use `writeTransaction` to group statements that can write to the database.
Expand All @@ -24,19 +26,7 @@ database.writeTransaction {

Use the `watch` method to watch for changes to the dependent tables of any SQL query.

```kotlin
// You can watch any SQL query
fun watchCustomers(): Flow<List<User>> {
// TODO: implement your UI based on the result set
return database.watch("SELECT * FROM customers", mapper = { cursor ->
User(
id = cursor.getString("id"),
name = cursor.getString("name"),
email = cursor.getString("email")
)
})
}
```
<KotlinWatch />

## Insert, update, and delete data in the local database

Expand Down
31 changes: 20 additions & 11 deletions client-sdk-references/node.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@

import SdkFeatures from '/snippets/sdk-features.mdx';
import NodeInstallation from '/snippets/node/installation.mdx';
import JavaScriptAsyncWatch from '/snippets/basic-watch-query-javascript-async.mdx';
import JavaScriptCallbackWatch from '/snippets/basic-watch-query-javascript-callback.mdx';

<Note>
This page describes the PowerSync _client_ SDK for Node.js.

Check warning on line 13 in client-sdk-references/node.mdx

View check run for this annotation

Mintlify / Mintlify Validation (powersync) - vale-spellcheck

client-sdk-references/node.mdx#L13

Did you really mean '_client_'?
If you're interested in using PowerSync for your Node.js backend, no special package is required.
Instead, follow our guides on [app backend setup](/installation/app-backend-setup).
</Note>
Expand Down Expand Up @@ -147,7 +149,7 @@
## Usage

After connecting the client database, it is ready to be used. The API to run queries and updates is identical to our
[web SDK](/client-sdk-references/javascript-web#using-powersync%3A-crud-functions):
[JavaScript/Web SDK](/client-sdk-references/javascript-web#using-powersync%3A-crud-functions):

```js
// Use db.get() to fetch a single row:
Expand All @@ -156,23 +158,30 @@
// Or db.getAll() to fetch all:
console.log(await db.getAll('SELECT * FROM lists;'));

// Use db.watch() to watch queries for changes:
const watchLists = async () => {
for await (const rows of db.watch('SELECT * FROM lists;')) {
console.log('Has todo lists', rows.rows!._array);
}
};
watchLists();

// And db.execute for inserts, updates and deletes:
await db.execute(
"INSERT INTO lists (id, created_at, name, owner_id) VALUEs (uuid(), datetime('now'), ?, uuid());",
['My new list']
);
```

PowerSync runs queries asynchronously on a background pool of workers and automatically configures WAL to
allow a writer and multiple readers to operate in parallel.
### Watch Queries

The `db.watch()` method executes a read query whenever a change to a dependent table is made.

<Tabs>
<Tab title="AsyncIterator approach">
<JavaScriptAsyncWatch />
</Tab>
<Tab title="Callback approach">
<JavaScriptCallbackWatch />
</Tab>
</Tabs>

For advanced watch query features like incremental updates and differential results, see [Live Queries / Watch Queries](/usage/use-case-examples/watch-queries).


PowerSync runs queries asynchronously on a background pool of workers and automatically configures WAL to allow a writer and multiple readers to operate in parallel.

## Configure Logging

Expand Down
Loading