diff --git a/.github/workflows/aisearch.yaml b/.github/workflows/aisearch.yaml index a850b67..e7f02f0 100644 --- a/.github/workflows/aisearch.yaml +++ b/.github/workflows/aisearch.yaml @@ -16,7 +16,7 @@ jobs: steps: - uses: actions/checkout@v4 - + - uses: sqliteai/sqlite-aisearch-action@v1 with: connection_string: ${{ secrets.PROJECT_STRING }} diff --git a/sqlite-cloud/_nav.ts b/sqlite-cloud/_nav.ts index f6a267d..2480a32 100644 --- a/sqlite-cloud/_nav.ts +++ b/sqlite-cloud/_nav.ts @@ -7,7 +7,41 @@ const sidebarNav: SidebarNavStruct = [ { title: "Overview", filePath: "ai-overview", type: "inner", level: 0 }, { title: "SQLite-AI", filePath: "sqlite-ai", type: "inner", level: 0 }, { title: "SQLite-JS", filePath: "sqlite-js", type: "inner", level: 0 }, - { title: "SQLite-Sync", filePath: "sqlite-sync", type: "inner", level: 0 }, + { title: "SQLite-Sync", type: "inner", level: 0 }, + { title: "Introduction", filePath: "sqlite-sync-introduction", type: "inner", level: 1 }, + { title: "Getting Started", filePath: "sqlite-sync-getting-started", type: "inner", level: 1 }, + { title: "Best Practices", filePath: "sqlite-sync-best-practices", type: "inner", level: 1 }, + { title: "Quick Starts", type: "inner", level: 1 }, + { title: "Android", filePath: "sqlite-sync-quick-start-android", type: "inner", level: 2 }, + { title: "iOS", filePath: "sqlite-sync-quick-start-ios", type: "inner", level: 2 }, + { title: "Linux", filePath: "sqlite-sync-quick-start-linux", type: "inner", level: 2 }, + { title: "macOS", filePath: "sqlite-sync-quick-start-macos", type: "inner", level: 2 }, + { title: "React Native Expo", filePath: "sqlite-sync-quick-start-expo", type: "inner", level: 2 }, + { title: "WASM", filePath: "sqlite-sync-quick-start-wasm", type: "inner", level: 2 }, + { title: "Windows", filePath: "sqlite-sync-quick-start-windows", type: "inner", level: 2 }, + { title: "API Reference", type: "inner", level: 1 }, + { title: "cloudsync_init", filePath: "sqlite-sync-api-cloudsync-init", type: "inner", level: 2 }, + { title: "cloudsync_enable", filePath: "sqlite-sync-api-cloudsync-enable", type: "inner", level: 2 }, + { title: "cloudsync_disable", filePath: "sqlite-sync-api-cloudsync-disable", type: "inner", level: 2 }, + { title: "cloudsync_is_enabled", filePath: "sqlite-sync-api-cloudsync-is-enabled", type: "inner", level: 2 }, + { title: "cloudsync_cleanup", filePath: "sqlite-sync-api-cloudsync-cleanup", type: "inner", level: 2 }, + { title: "cloudsync_terminate", filePath: "sqlite-sync-api-cloudsync-terminate", type: "inner", level: 2 }, + { title: "cloudsync_version", filePath: "sqlite-sync-api-cloudsync-version", type: "inner", level: 2 }, + { title: "cloudsync_siteid", filePath: "sqlite-sync-api-cloudsync-siteid", type: "inner", level: 2 }, + { title: "cloudsync_db_version", filePath: "sqlite-sync-api-cloudsync-db-version", type: "inner", level: 2 }, + { title: "cloudsync_uuid", filePath: "sqlite-sync-api-cloudsync-uuid", type: "inner", level: 2 }, + { title: "cloudsync_begin_alter", filePath: "sqlite-sync-api-cloudsync-begin-alter", type: "inner", level: 2 }, + { title: "cloudsync_commit_alter", filePath: "sqlite-sync-api-cloudsync-commit-alter", type: "inner", level: 2 }, + { title: "cloudsync_network_init", filePath: "sqlite-sync-api-cloudsync-network-init", type: "inner", level: 2 }, + { title: "cloudsync_network_cleanup", filePath: "sqlite-sync-api-cloudsync-network-cleanup", type: "inner", level: 2 }, + { title: "cloudsync_network_set_token", filePath: "sqlite-sync-api-cloudsync-network-set-token", type: "inner", level: 2 }, + { title: "cloudsync_network_set_apikey", filePath: "sqlite-sync-api-cloudsync-network-set-apikey", type: "inner", level: 2 }, + { title: "cloudsync_network_has_unsent_changes", filePath: "sqlite-sync-api-cloudsync-network-has-unsent-changes", type: "inner", level: 2 }, + { title: "cloudsync_network_send_changes", filePath: "sqlite-sync-api-cloudsync-network-send-changes", type: "inner", level: 2 }, + { title: "cloudsync_network_check_changes", filePath: "sqlite-sync-api-cloudsync-network-check-changes", type: "inner", level: 2 }, + { title: "cloudsync_network_sync", filePath: "sqlite-sync-api-cloudsync-network-sync", type: "inner", level: 2 }, + { title: "cloudsync_network_reset_sync_version", filePath: "sqlite-sync-api-cloudsync-network-reset-sync-version", type: "inner", level: 2 }, + { title: "cloudsync_network_logout", filePath: "sqlite-sync-api-cloudsync-network-logout", type: "inner", level: 2 }, { title: "SQLite-Vector", filePath: "sqlite-vector", type: "inner", level: 0 }, { title: "MCP (Model Context Protocol)", filePath: "mcp-server", type: "inner", level: 0 }, diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync.mdx b/sqlite-cloud/sqlite-ai/sqlite-sync.mdx deleted file mode 100644 index 5815c48..0000000 --- a/sqlite-cloud/sqlite-ai/sqlite-sync.mdx +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: SQLite-Sync -description: SQLite Cloud is a distributed relational database system built on top of the SQLite database engine. -category: platform -status: publish -slug: sqlite-sync ---- - -[SQLite-Sync](https://website-stage.sqlitecloud.io/sqlite-sync) is a cross-platform extension that adds built-in offline support and automatic synchronization to standard SQLite databases, enabling a **true local-first experience with zero latency**. Applications can operate fully offline, with each device maintaining its own copy of the database - -When reconnected, all changes are seamlessly synchronized across devices. Developers can continue using the familiar simplicity and performance of SQLite while easily building distributed, collaborative applications without complex infrastructure. - -SQLite Sync is powered by CRDTs (Conflict-free Replicated Data Types), a class of algorithms designed for real-time collaboration and distributed systems. CRDTs ensure that changes made on different devices are merged automatically and without conflicts, even when made offline. This means no data loss, no overwrites, and no need for manual conflict resolution. Whether it's a multi-user app or a fleet of devices operating in the field, SQLite Sync keeps everything consistent and in sync automatically. - -**SQLite-Sync** is an open-source project available on [GitHub](https://github.com/sqliteai/sqlite-sync). \ No newline at end of file diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_begin_alter.md b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_begin_alter.md new file mode 100644 index 0000000..e5ce51e --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_begin_alter.md @@ -0,0 +1,25 @@ +--- +title: "cloudsync_begin_alter(table_name)" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-api-cloudsync-begin-alter +--- + +**Description:** Prepares a synchronized table for schema changes. This function must be called before altering the table. Failure to use `cloudsync_begin_alter` and `cloudsync_commit_alter` can lead to synchronization errors and data divergence. + +**Parameters:** + +- `table_name` (TEXT): The name of the table that will be altered. + +**Returns:** None. + +**Example:** + +```sql +SELECT cloudsync_init('my_table'); +-- ... later +SELECT cloudsync_begin_alter('my_table'); +ALTER TABLE my_table ADD COLUMN new_column TEXT; +SELECT cloudsync_commit_alter('my_table'); +``` diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_cleanup.md b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_cleanup.md new file mode 100644 index 0000000..8d364d8 --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_cleanup.md @@ -0,0 +1,23 @@ +--- +title: "cloudsync_cleanup(table_name)" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-api-cloudsync-cleanup +--- + +**Description:** Removes the `sqlite-sync` synchronization mechanism from a specified table or all tables. This operation drops the associated `_cloudsync` metadata table and removes triggers from the target table(s). Use this function when synchronization is no longer desired for a table. + +**Parameters:** + +- `table_name` (TEXT): The name of the table to clean up. + +**Returns:** None. + +**Example:** + +```sql +-- Clean up a single table +SELECT cloudsync_cleanup('my_table'); + +``` diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_commit_alter.md b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_commit_alter.md new file mode 100644 index 0000000..73e56d7 --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_commit_alter.md @@ -0,0 +1,25 @@ +--- +title: "cloudsync_commit_alter(table_name)" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-api-cloudsync-commit-alter +--- + +**Description:** Finalizes schema changes for a synchronized table. This function must be called after altering the table's schema, completing the process initiated by `cloudsync_begin_alter` and ensuring CRDT data consistency. + +**Parameters:** + +- `table_name` (TEXT): The name of the table that was altered. + +**Returns:** None. + +**Example:** + +```sql +SELECT cloudsync_init('my_table'); +-- ... later +SELECT cloudsync_begin_alter('my_type'); +ALTER TABLE my_table ADD COLUMN new_column TEXT; +SELECT cloudsync_commit_alter('my_table'); +``` diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_db_version.md b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_db_version.md new file mode 100644 index 0000000..cdef894 --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_db_version.md @@ -0,0 +1,19 @@ +--- +title: "cloudsync_db_version()" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-api-cloudsync-db-version +--- + +**Description:** Returns the current database version. + +**Parameters:** None. + +**Returns:** The database version as an INTEGER. + +**Example:** + +```sql +SELECT cloudsync_db_version(); +``` diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_disable.md b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_disable.md new file mode 100644 index 0000000..0c13f8b --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_disable.md @@ -0,0 +1,21 @@ +--- +title: "cloudsync_disable(table_name)" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-api-cloudsync-disable +--- + +**Description:** Disables synchronization for the specified table. + +**Parameters:** + +- `table_name` (TEXT): The name of the table to disable. + +**Returns:** None. + +**Example:** + +```sql +SELECT cloudsync_disable('my_table'); +``` diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_enable.md b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_enable.md new file mode 100644 index 0000000..d13c31e --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_enable.md @@ -0,0 +1,21 @@ +--- +title: "cloudsync_enable(table_name)" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-api-cloudsync-enable +--- + +**Description:** Enables synchronization for the specified table. + +**Parameters:** + +- `table_name` (TEXT): The name of the table to enable. + +**Returns:** None. + +**Example:** + +```sql +SELECT cloudsync_enable('my_table'); +``` diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_init.md b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_init.md new file mode 100644 index 0000000..16b0d7f --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_init.md @@ -0,0 +1,52 @@ +--- +title: "cloudsync_init(table_name, [crdt_algo], [force])" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-api-cloudsync-init +--- + +**Description:** Initializes a table for `sqlite-sync` synchronization. This function is idempotent and needs to be called only once per table on each site; configurations are stored in the database and automatically loaded with the extension. + +Before initialization, `cloudsync_init` performs schema sanity checks to ensure compatibility with CRDT requirements and best practices. These checks include: + +- Primary keys should not be auto-incrementing integers; GUIDs (UUIDs, ULIDs) are highly recommended to prevent multi-node collisions. +- All primary key columns must be `NOT NULL`. +- All non-primary key `NOT NULL` columns must have a `DEFAULT` value. + +**Schema Design Considerations:** + +When designing your database schema for SQLite Sync, follow these essential requirements: + +- **Primary Keys**: Use TEXT primary keys with `cloudsync_uuid()` for globally unique identifiers. Avoid auto-incrementing integers. +- **Column Constraints**: All NOT NULL columns (except primary keys) must have DEFAULT values to prevent synchronization errors. +- **UNIQUE Constraints**: In multi-tenant scenarios, use composite UNIQUE constraints (e.g., `UNIQUE(tenant_id, email)`) instead of global uniqueness. +- **Foreign Key Compatibility**: Be aware of potential conflicts during CRDT merge operations and RLS policy interactions. +- **Trigger Compatibility**: Triggers may cause duplicate operations or be called multiple times due to column-by-column processing. + +For comprehensive guidelines, see the [Database Schema Recommendations](/docs/sqlite-sync-best-practices) section. + +The function supports three overloads: + +- `cloudsync_init(table_name)`: Uses the default 'cls' CRDT algorithm. +- `cloudsync_init(table_name, crdt_algo)`: Specifies a CRDT algorithm ('cls', 'dws', 'aws', 'gos'). +- `cloudsync_init(table_name, crdt_algo, force)`: Specifies an algorithm and, if `force` is `true` (or `1`), skips the integer primary key check (use with caution, GUIDs are strongly recommended). + +**Parameters:** + +- `table_name` (TEXT): The name of the table to initialize. +- `crdt_algo` (TEXT, optional): The CRDT algorithm to use. Can be "cls", "dws", "aws", "gos". Defaults to "cls". +- `force` (BOOLEAN, optional): If `true` (or `1`), it skips the check that prevents the use of a single-column INTEGER primary key. Defaults to `false`. It is strongly recommended to use globally unique primary keys instead of integers. + +**Returns:** None. + +**Example:** + +```sql +-- Initialize a single table for synchronization with the Causal-Length Set (CLS) Algorithm (default) +SELECT cloudsync_init('my_table'); + +-- Initialize a single table for synchronization with a different algorithm Delete-Wins Set (DWS) +SELECT cloudsync_init('my_table', 'dws'); + +``` diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_is_enabled.md b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_is_enabled.md new file mode 100644 index 0000000..3f72554 --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_is_enabled.md @@ -0,0 +1,21 @@ +--- +title: "cloudsync_is_enabled(table_name)" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-api-cloudsync-is-enabled +--- + +**Description:** Checks if synchronization is enabled for the specified table. + +**Parameters:** + +- `table_name` (TEXT): The name of the table to check. + +**Returns:** 1 if enabled, 0 otherwise. + +**Example:** + +```sql +SELECT cloudsync_is_enabled('my_table'); +``` diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_check_changes.md b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_check_changes.md new file mode 100644 index 0000000..5e3b809 --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_check_changes.md @@ -0,0 +1,29 @@ +--- +title: "cloudsync_network_check_changes()" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-api-cloudsync-network-check-changes +--- + +**Description:** Checks the remote server for new changes and applies them to the local database. + +If a package of new changes is already available for the local site, the server returns it immediately, and the changes are applied. If no package is ready, the server returns an empty response and starts an asynchronous process to prepare a new package. This new package can be retrieved with a subsequent call to this function. + +This function is designed to be called periodically to keep the local database in sync. +To force an update and wait for changes (with a timeout), use `cloudsync_network_sync(wait_ms, max_retries)`. + +If the network is misconfigured or the remote server is unreachable, the function returns an error. +On success, it returns `SQLITE_OK`, and the return value indicates how many changes were downloaded and applied. + +**Parameters:** None. + +**Returns:** The number of changes downloaded. Errors are reported via the SQLite return code. + +**Errors:** See [Network Errors](#network-errors) for common error conditions. + +**Example:** + +```sql +SELECT cloudsync_network_check_changes(); +``` diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_cleanup.md b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_cleanup.md new file mode 100644 index 0000000..bf1dbc0 --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_cleanup.md @@ -0,0 +1,19 @@ +--- +title: "cloudsync_network_cleanup()" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-api-cloudsync-network-cleanup +--- + +**Description:** Cleans up the `sqlite-sync` network component, releasing all resources allocated by `cloudsync_network_init` (memory, cURL handles). + +**Parameters:** None. + +**Returns:** None. + +**Example:** + +```sql +SELECT cloudsync_network_cleanup(); +``` diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_has_unsent_changes.md b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_has_unsent_changes.md new file mode 100644 index 0000000..fcbad04 --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_has_unsent_changes.md @@ -0,0 +1,19 @@ +--- +title: "cloudsync_network_has_unsent_changes()" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-api-cloudsync-network-has-unsent-changes +--- + +**Description:** Checks if there are any local changes that have not yet been sent to the remote server. + +**Parameters:** None. + +**Returns:** 1 if there are unsent changes, 0 otherwise. + +**Example:** + +```sql +SELECT cloudsync_network_has_unsent_changes(); +``` diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_init.md b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_init.md new file mode 100644 index 0000000..52bda2d --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_init.md @@ -0,0 +1,21 @@ +--- +title: "cloudsync_network_init(connection_string)" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-api-cloudsync-network-init +--- + +**Description:** Initializes the `sqlite-sync` network component. This function parses the connection string to configure change checking and upload endpoints, and initializes the cURL library. + +**Parameters:** + +- `connection_string` (TEXT): The connection string for the remote synchronization server. The format is `sqlitecloud://:/?`. + +**Returns:** None. + +**Example:** + +```sql +SELECT cloudsync_network_init('.sqlite.cloud/.sqlite'); +``` diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_logout.md b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_logout.md new file mode 100644 index 0000000..ba565d9 --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_logout.md @@ -0,0 +1,19 @@ +--- +title: "cloudsync_network_logout()" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-api-cloudsync-network-logout +--- + +**Description:** Logs out the current user and cleans up all local data from synchronized tables. This function deletes and then re-initializes synchronized tables, useful for switching users or resetting the local database. **Warning:** This function deletes all data from synchronized tables. Use with caution. + +**Parameters:** None. + +**Returns:** None. + +**Example:** + +```sql +SELECT cloudsync_network_logout(); +``` diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_reset_sync_version.md b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_reset_sync_version.md new file mode 100644 index 0000000..ff92454 --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_reset_sync_version.md @@ -0,0 +1,19 @@ +--- +title: "cloudsync_network_reset_sync_version()" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-api-cloudsync-network-reset-sync-version +--- + +**Description:** Resets local synchronization version numbers, forcing the next sync to fetch all changes from the server. + +**Parameters:** None. + +**Returns:** None. + +**Example:** + +```sql +SELECT cloudsync_network_reset_sync_version(); +``` diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_send_changes.md b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_send_changes.md new file mode 100644 index 0000000..45e8d1b --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_send_changes.md @@ -0,0 +1,19 @@ +--- +title: "cloudsync_network_send_changes()" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-api-cloudsync-network-send-changes +--- + +**Description:** Sends all unsent local changes to the remote server. + +**Parameters:** None. + +**Returns:** None. + +**Example:** + +```sql +SELECT cloudsync_network_send_changes(); +``` diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_set_apikey.md b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_set_apikey.md new file mode 100644 index 0000000..ed47ee2 --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_set_apikey.md @@ -0,0 +1,21 @@ +--- +title: "cloudsync_network_set_apikey(apikey)" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-api-cloudsync-network-set-apikey +--- + +**Description:** Sets the API key for network requests. This key is included in the `Authorization` header of all subsequent requests. + +**Parameters:** + +- `apikey` (TEXT): The API key. + +**Returns:** None. + +**Example:** + +```sql +SELECT cloudsync_network_set_apikey('your_api_key'); +``` diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_set_token.md b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_set_token.md new file mode 100644 index 0000000..fdc0bb0 --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_set_token.md @@ -0,0 +1,21 @@ +--- +title: "cloudsync_network_set_token(token)" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-api-cloudsync-network-set-token +--- + +**Description:** Sets the authentication token to be used for network requests. This token will be included in the `Authorization` header of all subsequent requests. For more information, refer to the [Access Tokens documentation](/docs/access-tokens). + +**Parameters:** + +- `token` (TEXT): The authentication token. + +**Returns:** None. + +**Example:** + +```sql +SELECT cloudsync_network_set_token('your_auth_token'); +``` diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_sync.md b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_sync.md new file mode 100644 index 0000000..0761156 --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_network_sync.md @@ -0,0 +1,29 @@ +--- +title: "cloudsync_network_sync([wait_ms], [max_retries])" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-api-cloudsync-network-sync +--- + +**Description:** Performs a full synchronization cycle. This function has two overloads: + +- `cloudsync_network_sync()`: Performs one send operation and one check operation. +- `cloudsync_network_sync(wait_ms, max_retries)`: Performs one send operation and then repeatedly tries to download remote changes until at least one change is downloaded or `max_retries` times has been reached, waiting `wait_ms` between retries. + +**Parameters:** + +- `wait_ms` (INTEGER, optional): The time to wait in milliseconds between retries. Defaults to 100. +- `max_retries` (INTEGER, optional): The maximum number of times to retry the synchronization. Defaults to 1. + +**Returns:** The number of changes downloaded. Errors are reported via the SQLite return code. + +**Example:** + +```sql +-- Perform a single synchronization cycle +SELECT cloudsync_network_sync(); + +-- Perform a synchronization cycle with custom retry settings +SELECT cloudsync_network_sync(500, 3); +``` diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_siteid.md b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_siteid.md new file mode 100644 index 0000000..49e6c30 --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_siteid.md @@ -0,0 +1,19 @@ +--- +title: "cloudsync_siteid()" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-api-cloudsync-siteid +--- + +**Description:** Returns the unique ID of the local site. + +**Parameters:** None. + +**Returns:** The site ID as a BLOB. + +**Example:** + +```sql +SELECT cloudsync_siteid(); +``` diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_terminate.md b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_terminate.md new file mode 100644 index 0000000..a8e646e --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_terminate.md @@ -0,0 +1,20 @@ +--- +title: "cloudsync_terminate()" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-api-cloudsync-terminate +--- + +**Description:** Releases all internal resources used by the `sqlite-sync` extension for the current database connection. This function should be called before closing the database connection to ensure that all prepared statements and allocated memory are freed. Failing to call this function can result in memory leaks or a failed `sqlite3_close` operation due to pending statements. + +**Parameters:** None. + +**Returns:** None. + +**Example:** + +```sql +-- Before closing the database connection +SELECT cloudsync_terminate(); +``` diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_uuid.md b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_uuid.md new file mode 100644 index 0000000..fa976bb --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_uuid.md @@ -0,0 +1,19 @@ +--- +title: "cloudsync_uuid()" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-api-cloudsync-uuid +--- + +**Description:** Generates a new universally unique identifier (UUIDv7). This is useful for creating globally unique primary keys for new records, which is a best practice for CRDTs. + +**Parameters:** None. + +**Returns:** A new UUID as a TEXT value. + +**Example:** + +```sql +INSERT INTO products (id, name) VALUES (cloudsync_uuid(), 'New Product'); +``` \ No newline at end of file diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_version.md b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_version.md new file mode 100644 index 0000000..f1033e6 --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/api-reference/cloudsync_version.md @@ -0,0 +1,20 @@ +--- +title: "cloudsync_version()" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-api-cloudsync-version +--- + +**Description:** Returns the version of the `sqlite-sync` library. + +**Parameters:** None. + +**Returns:** The library version as a string. + +**Example:** + +```sql +SELECT cloudsync_version(); +-- e.g., '1.0.0' +``` diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/best-practices.md b/sqlite-cloud/sqlite-ai/sqlite-sync/best-practices.md new file mode 100644 index 0000000..5e77af8 --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/best-practices.md @@ -0,0 +1,117 @@ +--- +title: SQLite-Sync Best Practices +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-best-practices +--- + +## Database Schema Recommendations + +When designing your database schema for SQLite Sync, follow these best practices to ensure optimal CRDT performance and conflict resolution: + +### Primary Key Requirements + +- **Use globally unique identifiers**: Always use TEXT primary keys with UUIDs, ULIDs, or similar globally unique identifiers +- **Avoid auto-incrementing integers**: Integer primary keys can cause conflicts across multiple devices +- **Use `cloudsync_uuid()`**: The built-in function generates UUIDv7 identifiers optimized for distributed systems +- **All primary keys must be explicitly declared as `NOT NULL`**. + +```sql +-- ✅ Recommended: Globally unique TEXT primary key +CREATE TABLE users ( + id TEXT PRIMARY KEY NOT NULL, -- Use cloudsync_uuid() + name TEXT NOT NULL, + email TEXT UNIQUE NOT NULL +); + +-- ❌ Avoid: Auto-incrementing integer primary key +CREATE TABLE users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, -- Causes conflicts + name TEXT NOT NULL, + email TEXT UNIQUE NOT NULL +); +``` + +### Column Constraint Guidelines + +- **Provide DEFAULT values**: All `NOT NULL` columns (except primary keys) must have `DEFAULT` values +- **Consider nullable columns**: For optional data, use nullable columns instead of empty strings + +```sql +-- ✅ Recommended: Proper constraints and defaults +CREATE TABLE tasks ( + id TEXT PRIMARY KEY, + title TEXT NOT NULL DEFAULT '', + status TEXT NOT NULL DEFAULT 'pending', + priority INTEGER NOT NULL DEFAULT 1, + created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')), + assigned_to TEXT -- Nullable for optional assignment +); +``` + +### UNIQUE Constraint Considerations + +When converting from single-tenant to multi-tenant database schemas with Row-Level Security, **UNIQUE constraints must be globally unique** across all tenants in the cloud database. For columns that should only be unique within a tenant, use composite UNIQUE constraints. + +```sql +-- ❌ Single-tenant: Unique email per database +CREATE TABLE users ( + id TEXT PRIMARY KEY, + email TEXT UNIQUE NOT NULL -- Problem: Not unique across tenants +); + +-- ✅ Multi-tenant: Composite unique constraint +CREATE TABLE users ( + id TEXT PRIMARY KEY, + tenant_id TEXT NOT NULL, + email TEXT NOT NULL, + UNIQUE(tenant_id, email) -- Unique email per tenant +); +``` + +### Foreign Key Compatibility + +When using foreign key constraints with SQLite Sync, be aware that interactions with the CRDT merge algorithm and Row-Level Security policies may cause constraint violations. + +#### Potential Conflicts + +**CRDT Merge Algorithm and DEFAULT Values** + +- CRDT changes are applied column-by-column during synchronization +- Columns may be temporarily assigned DEFAULT values during the merge process +- If a foreign key column has a DEFAULT value, that value must exist in the referenced table + +**Row-Level Security and CASCADE Actions** + +- RLS policies may block operations required for maintaining referential integrity +- CASCADE DELETE/UPDATE operations may fail if RLS prevents access to related rows + +#### Recommendations + +**Database Design Patterns** + +- Prefer application-level cascade logic over database-level CASCADE actions +- Design RLS policies to accommodate referential integrity operations +- Use nullable foreign keys where appropriate to avoid DEFAULT value issues +- Alternatively, ensure DEFAULT values for foreign key columns exist in their referenced tables + +**Testing and Validation** + +- Test synchronization scenarios with foreign key constraints enabled +- Monitor for constraint violations during sync operations in development + +### Trigger Compatibility + +Be aware that certain types of triggers can cause errors during synchronization due to SQLite Sync's merge logic. + +**Duplicate Operations** + +- If a trigger modifies a table that is also synchronized with SQLite Sync, changes performed by the trigger may be applied twice during the merge operation +- This can lead to constraint violations or unexpected data states depending on the table's constraints + +**Column-by-Column Processing** + +- SQLite Sync applies changes column-by-column during synchronization +- UPDATE triggers may be called multiple times for a single row as each column is processed +- This can result in unexpected trigger behavior diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/getting-started.md b/sqlite-cloud/sqlite-ai/sqlite-sync/getting-started.md new file mode 100644 index 0000000..9850493 --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/getting-started.md @@ -0,0 +1,126 @@ +--- +title: "Getting Started" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-getting-started +--- + +Here's a quick example to get started with SQLite Sync: + +### Prerequisites + +1. **SQLite Cloud Account**: Sign up at [SQLite Cloud](https://sqlitecloud.io/) +2. **SQLite Sync Extension**: Download from [Releases](https://github.com/sqliteai/sqlite-sync/releases) + +### SQLite Cloud Setup + +1. Create a new project and database in your [SQLite Cloud Dashboard](https://dashboard.sqlitecloud.io/) +2. Copy your connection string and API key from the dashboard +3. Create tables with identical schema in both local and cloud databases +4. [Enable synchronization](/docs/offsync#:~:text=in%20the%20cloud.-,Configuring%20OffSync,-You%20can%20enable): go to Databases > Offsync page and select each table you want to synchronize in your database + +### Local Database Setup + +```bash +# Start SQLite CLI +sqlite3 myapp.db +``` + +```sql +-- Load the extension +.load ./cloudsync + +-- Create a table (primary key MUST be TEXT for global uniqueness) +CREATE TABLE IF NOT EXISTS my_data ( + id TEXT PRIMARY KEY NOT NULL, + value TEXT NOT NULL DEFAULT '', + created_at TEXT DEFAULT CURRENT_TIMESTAMP +); + +-- Initialize table for synchronization +SELECT cloudsync_init('my_data'); + +-- Use your local database normally: read and write data using standard SQL queries +-- The CRDT system automatically tracks all changes for synchronization + +-- Example: Insert data (always use cloudsync_uuid() for globally unique IDs) +INSERT INTO my_data (id, value) VALUES + (cloudsync_uuid(), 'Hello from device A!'), + (cloudsync_uuid(), 'Working offline is seamless!'); + +-- Example: Update and delete operations work normally +UPDATE my_data SET value = 'Updated: Hello from device A!' WHERE value LIKE 'Hello from device A!'; + +-- View your data +SELECT * FROM my_data ORDER BY created_at; + +-- Configure network connection before using the network sync functions +SELECT cloudsync_network_init('sqlitecloud://your-project-id.sqlite.cloud/database.sqlite'); +SELECT cloudsync_network_set_apikey('your-api-key-here'); +-- Or use token authentication (required for Row-Level Security) +-- SELECT cloudsync_network_set_token('your_auth_token'); + +-- Sync with cloud: send local changes, then check the remote server for new changes +-- and, if a package with changes is ready to be downloaded, applies them to the local database +SELECT cloudsync_network_sync(); +-- Keep calling periodically. The function returns > 0 if data was received +-- In production applications, you would typically call this periodically +-- rather than manually (e.g., every few seconds) +SELECT cloudsync_network_sync(); + +-- Before closing the database connection +SELECT cloudsync_terminate(); +-- Close the database connection +.quit +``` + +```sql +-- On another device (or create another database for testing: sqlite3 myapp_2.db) +-- Follow the same setup steps: load extension, create table, init sync, configure network + +-- Load extension and create identical table structure +.load ./cloudsync +CREATE TABLE IF NOT EXISTS my_data ( + id TEXT PRIMARY KEY NOT NULL, + value TEXT NOT NULL DEFAULT '', + created_at TEXT DEFAULT CURRENT_TIMESTAMP +); +SELECT cloudsync_init('my_data'); + +-- Connect to the same cloud database +SELECT cloudsync_network_init('sqlitecloud://your-project-id.sqlite.cloud/database.sqlite'); +SELECT cloudsync_network_set_apikey('your-api-key-here'); + +-- Sync to get data from the first device +SELECT cloudsync_network_sync(); +-- repeat until data is received (returns > 0) +SELECT cloudsync_network_sync(); + +-- View synchronized data +SELECT * FROM my_data ORDER BY created_at; + +-- Add data from this device to test bidirectional sync +INSERT INTO my_data (id, value) VALUES + (cloudsync_uuid(), 'Hello from device B!'); + +-- Sync again to send this device's changes +SELECT cloudsync_network_sync(); + +-- The CRDT system ensures all devices eventually have the same data, +-- with automatic conflict resolution and no data loss + +-- Before closing the database connection +SELECT cloudsync_terminate(); +-- Close the database connection +.quit +``` + +### For a Complete Example + +See the [examples](https://github.com/sqliteai/sqlite-sync/blob/main/examples/simple-todo-db/README.md) directory for a comprehensive walkthrough including: + +- Multi-device collaboration +- Offline scenarios +- Row-level security setup +- Conflict resolution demonstrations diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/introduction.md b/sqlite-cloud/sqlite-ai/sqlite-sync/introduction.md new file mode 100644 index 0000000..cc4a012 --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/introduction.md @@ -0,0 +1,97 @@ +--- +title: "Introduction to SQLite Sync" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-introduction +--- + +[SQLite Sync](https://github.com/sqliteai/sqlite-sync) is a multi-platform extension that brings a true **local-first experience** to your applications with minimal effort. It extends standard SQLite tables with built-in support for offline work and automatic synchronization, allowing multiple devices to operate independently—even without a network connection—and seamlessly stay in sync. With SQLite Sync, developers can easily build **distributed, collaborative applications** while continuing to rely on the **simplicity, reliability, and performance of SQLite**. + +Under the hood, SQLite Sync uses advanced **CRDT (Conflict-free Replicated Data Type)** algorithms and data structures designed specifically for **collaborative, distributed systems**. This means: + +- Devices can update data independently, even without a network connection. +- When they reconnect, all changes are **merged automatically and without conflicts**. +- **No data loss. No overwrites. No manual conflict resolution.** + +In simple terms, CRDTs make it possible for multiple users to **edit shared data at the same time**, from anywhere, and everything just works. + +## Key Features + +- **Offline-First by Design**: Works seamlessly even when devices are offline. Changes are queued locally and synced automatically when connectivity is restored. +- **CRDT-Based Conflict Resolution**: Merges updates deterministically and efficiently, ensuring eventual consistency across all replicas without the need for complex merge logic. +- **Embedded Network Layer**: No external libraries or sync servers required. SQLiteSync handles connection setup, message encoding, retries, and state reconciliation internally. +- **Drop-in Simplicity**: Just load the extension into SQLite and start syncing. No need to implement custom protocols or state machines. +- **Efficient and Resilient**: Optimized binary encoding, automatic batching, and robust retry logic make synchronization fast and reliable even on flaky networks. + +Whether you're building a mobile app, IoT device, or desktop tool, SQLite Sync simplifies distributed data management and unlocks the full potential of SQLite in decentralized environments. + +## Built-in Network Layer + +Unlike traditional sync systems that require you to build and maintain a complex backend, **SQLite Sync includes a built-in network layer** that works out of the box: + +- Sync your database with the cloud using **a single function call**. +- Compatible with **any language or framework** that supports SQLite. +- **No backend setup required** — SQLite Sync handles networking, change tracking, and conflict resolution for you. + +The sync layer is tightly integrated with [**SQLite Cloud**](https://sqlitecloud.io/), enabling seamless and secure data sharing across devices, users, and platforms. You get the power of cloud sync without the complexity. + +## Row-Level Security + +Thanks to the underlying SQLite Cloud infrastructure, **SQLite Sync supports Row-Level Security (RLS)**—allowing you to define **precise access control at the row level**: + +- Control not just who can read or write a table, but **which specific rows** they can access. +- Enforce security policies on the server—no need for client-side filtering. + +For example: + +- User A can only see and edit their own data. +- User B can access a different set of rows—even within the same shared table. + +**Benefits of RLS**: + +- **Data isolation**: Ensure users only access what they’re authorized to see. +- **Built-in privacy**: Security policies are enforced at the database level. +- **Simplified development**: Reduce or eliminate complex permission logic in your application code. + +## What Can You Build with SQLite Sync? + +SQLite Sync is ideal for building collaborative and distributed apps across web, mobile, desktop, and edge platforms. Some example use cases include: + +#### 📋 Productivity & Collaboration + +- **Shared To-Do Lists**: Users independently update tasks and sync effortlessly. +- **Note-Taking Apps**: Real-time collaboration with offline editing. +- **Markdown Editors**: Work offline, sync when back online—no conflicts. + +#### 📱 Mobile & Edge + +- **Field Data Collection**: For remote inspections, agriculture, or surveys. +- **Point-of-Sale Systems**: Offline-first retail solutions with synced inventory. +- **Health & Fitness Apps**: Sync data across devices with strong privacy controls. + +#### 🏢 Enterprise Workflows + +- **CRM Systems**: Sync leads and clients per user with row-level access control. +- **Project Management Tools**: Offline-friendly planning and task management. +- **Expense Trackers**: Sync team expenses securely and automatically. + +#### 🧠 Personal Apps + +- **Journaling & Diaries**: Private, encrypted entries that sync across devices. +- **Bookmarks & Reading Lists**: Personal or collaborative content management. +- **Habit Trackers**: Sync progress with data security and consistency. + +#### 🌍 Multi-User, Multi-Tenant Systems + +- **SaaS Platforms**: Row-level access for each user or team. +- **Collaborative Design Tools**: Merge visual edits and annotations offline. +- **Educational Apps**: Shared learning content with per-student access controls. + +## Integrations + +Use SQLite-Sync alongside: + +- **[SQLite-AI](https://github.com/sqliteai/sqlite-ai)** – on-device inference, embedding generation, and model interaction directly into your database +- **[SQLite-Vector](https://github.com/sqliteai/sqlite-vector)** – vector search from SQL +- **[SQLite-JS](https://github.com/sqliteai/sqlite-js)** – define SQLite functions in JavaScript diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/quick-starts/android.md b/sqlite-cloud/sqlite-ai/sqlite-sync/quick-starts/android.md new file mode 100644 index 0000000..d403a34 --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/quick-starts/android.md @@ -0,0 +1,187 @@ +--- +title: "Android Quick Start Guide" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-quick-start-android +--- + +This guide shows how to integrate sqlite-sync extension into your Android application. + +### 1. Add Dependencies + +You can [add sqlite-sync as a dependency to your Android project](https://central.sonatype.com/artifact/ai.sqlite/sync). + +
+Groovy DSL + +```groovy +repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } +} +dependencies { + // ... + // Use requery's SQLite instead of Android's built-in SQLite to support loading custom extensions + implementation 'com.github.requery:sqlite-android:3.49.0' + // Both packages below are identical - use either one + implementation 'ai.sqlite:sync:0.8.39' // Maven Central + // implementation 'com.github.sqliteai:sqlite-sync:0.8.39' // JitPack (alternative) +} +``` +
+ +
+Kotlin DSL + +```kotlin +repositories { + google() + mavenCentral() + maven(url = "https://jitpack.io") +} +dependencies { + // ... + // Use requery's SQLite instead of Android's built-in SQLite to support loading custom extensions + implementation("com.github.requery:sqlite-android:3.49.0") + // Both packages below are identical - use either one + implementation("ai.sqlite:sync:0.8.39") // Maven Central + // implementation("com.github.sqliteai:sqlite-sync:0.8.39") // JitPack (alternative) +} +``` +
+ +### 2. Update AndroidManifest.xml + +Add `android:extractNativeLibs="true"` to your `` tag: + +```xml + +``` + +### 3. Basic Integration + +Here’s a complete example showing how to load the extension, create a table, initialize CloudSync, and perform network sync. + +> **Important:** Replace the following placeholders with your actual values: +> +> - `database_name` - Your database name +> - `table_name` - Your table name +> - `` - Your SQLiteCloud connection string +> - `` - Your SQLiteCloud API key + +```kotlin +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.lifecycle.lifecycleScope +import io.requery.android.database.sqlite.SQLiteCustomExtension +import io.requery.android.database.sqlite.SQLiteDatabase +import io.requery.android.database.sqlite.SQLiteDatabaseConfiguration +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext + +class MainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + // --- Create extension configuration --- + val cloudsyncExtension = SQLiteCustomExtension(applicationInfo.nativeLibraryDir + "/cloudsync", null) + + // --- Configure database with extension --- + val config = SQLiteDatabaseConfiguration( + cacheDir.path + "/database_name.db", + SQLiteDatabase.CREATE_IF_NECESSARY or SQLiteDatabase.OPEN_READWRITE, + emptyList(), + emptyList(), + listOf(cloudsyncExtension) + ) + + // --- Open database --- + val db = SQLiteDatabase.openDatabase(config, null, null) + val tableName = "table_name" + + lifecycleScope.launch { + withContext(Dispatchers.IO) { + // --- Check CloudSync version --- + val version = db.rawQuery("SELECT cloudsync_version();", null).use { cursor -> + if (cursor.moveToFirst()) cursor.getString(0) else null + } + + if (version == null) { + println("CLOUDSYNC-TEST: Failed to load SQLite Sync extension") + return@withContext + } + + println("CLOUDSYNC-TEST: SQLite Sync loaded successfully. Version: $version") + + try { + // --- Create test table --- + val createTableSQL = """ + CREATE TABLE IF NOT EXISTS $tableName ( + id TEXT PRIMARY KEY NOT NULL, + value TEXT NOT NULL DEFAULT '', + created_at TEXT DEFAULT CURRENT_TIMESTAMP + ); + """.trimIndent() + db.execSQL(createTableSQL) + + // --- Initialize CloudSync for table --- + val initResult = db.rawQuery("SELECT cloudsync_init('$tableName');", null).use { it.moveToFirst() } + + // --- Insert sample data --- + db.execSQL(""" + INSERT INTO $tableName (id, value) VALUES + (cloudsync_uuid(), 'test1'), + (cloudsync_uuid(), 'test2'); + """.trimIndent()) + + // --- Initialize network connection --- + db.rawQuery( + "SELECT cloudsync_network_init('');", + null + ).use { it.moveToFirst() } + + // --- Set API key --- + db.rawQuery( + "SELECT cloudsync_network_set_apikey('');", + null + ).use { it.moveToFirst() } + + // --- Run network sync multiple times --- + // Note: cloudsync_network_sync() returns > 0 if data was sent/received. + // It should ideally be called periodically to ensure both sending local + // changes and receiving remote changes work reliably. + repeat(2) { attempt -> + try { + val syncResult = db.rawQuery("SELECT cloudsync_network_sync();", null).use { cursor -> + if (cursor.moveToFirst()) cursor.getInt(0) else 0 + } + println("CLOUDSYNC-TEST: Network sync attempt ${attempt + 1}: result = $syncResult") + } catch (e: Exception) { + println("CLOUDSYNC-TEST: Sync attempt ${attempt + 1} failed: ${e.message}") + } + } + } catch (e: Exception) { + println("CLOUDSYNC-TEST: Error - ${e.message}") + } finally { + // --- Terminate CloudSync --- + db.rawQuery("SELECT cloudsync_terminate();", null).use { it.moveToFirst() } + + // Close the database + db.close() + } + } + } + } +} +``` + +### 4. Notes on SQLite Usage in Android + +CloudSync functions must be executed with `SELECT`. In Android, use `rawQuery()` to call them, and always call `moveToFirst()` (or `moveToNext()`) on the cursor to ensure the query actually executes. + +For detailed SQLite Sync API documentation, see the main [documentation](https://github.com/sqliteai/sqlite-sync/blob/main/README.md). diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/quick-starts/ios.md b/sqlite-cloud/sqlite-ai/sqlite-sync/quick-starts/ios.md new file mode 100644 index 0000000..19f7f7f --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/quick-starts/ios.md @@ -0,0 +1,208 @@ +--- +title: "iOS Quick Start Guide" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-quick-start-ios +--- + +This guide will walk you through setting up SQLite in Swift to load CloudsSync extensions. + +## 1. Create a New Swift Project + +1. Open Xcode +2. Create a new project +3. Select **Multiplatform** → **App** + +## 2. Download and Add CloudSync Framework + +1. Download the latest version of `cloudsync-apple-xcframework` from: + https://github.com/sqliteai/sqlite-sync/releases + +2. In Xcode, click on your project name in the source tree (top left with the Xcode logo) + +3. In the new tab that opens, navigate to the left column under the **Targets** section and click on the first target + +4. You should now be in the **General** tab. Scroll down to **"Frameworks, Libraries, and Embedded Content"** + +5. Click the **+** button → **Add Other...** → **Add Files...** + +6. Select the downloaded `CloudSync.xcframework` folder + +7. Switch to the **Build Phases** tab and verify that `CloudSync.xcframework` appears under **Embedded Frameworks** + +## 3. Handle Security Permissions (macOS) + +When you return to the main ContentView file, you may encounter an Apple security error: + +1. Click **Done** when the security dialog appears +2. Open **System Settings** → **Privacy & Security** +3. Scroll to the bottom and find the message "Mac blocked CloudSync" +4. Click **Allow Anyway** +5. Close and reopen ContentView in Xcode +6. The same error should appear but now with a third button **Open Anyway** - click it +7. If errors persist, try reopening and closing ContentView multiple times or repeat the security steps above + +## 4. Set Up SQLite with Extension Loading + +You need a version of SQLite that supports loading extensions. You have two options: + +### Option A: Download SQLite Amalgamation (Recommended) + +1. Download the amalgamation from: https://sqlite.org/download.html +2. Create a new folder called **SQLite** in your Swift project in Xcode +3. Copy `sqlite3.c` and `sqlite3.h` into this folder by dragging them in +4. Enable all targets and confirm + +### Option B: Use CocoaPods + +## 5. Configure Objective-C Bridging Header + +1. When you add the SQLite files, a popup will appear asking **"Would you like to configure an Objective-C bridging header?"** +2. Click **Create Bridging Header** +3. In the newly created bridging header file, import the SQLite headers: + ```objc + #import "sqlite3.h" + ``` + +## 6. Test the Setup + +To verify that the extension loads correctly in your Swift project, replace your ContentView.swift content with this test code: + +```swift +import SwiftUI + +struct ContentView: View { + @State private var statusLines: [String] = [] + private var statusText: String { statusLines.joined(separator: "\n") } + + var body: some View { + VStack(spacing: 12) { + Image(systemName: "globe") + .imageScale(.large) + .foregroundStyle(.tint) + Text("Hello, world!") + + Divider() + + Text("Status") + .font(.headline) + + ScrollView { + Text(statusText.isEmpty ? "No status yet." : statusText) + .font(.system(.footnote, design: .monospaced)) + .frame(maxWidth: .infinity, alignment: .leading) + .textSelection(.enabled) + .padding(.vertical, 4) + } + .frame(maxHeight: 260) + } + .padding() + .task { + log("Starting...") + var db: OpaquePointer? + + // Open an in-memory database just for demonstrating status updates. + // Replace with your own URL/path if needed. + var rc = sqlite3_open(":memory:", &db) + if rc != SQLITE_OK { + let msg = db.flatMap { sqlite3_errmsg($0) }.map { String(cString: $0) } ?? "Unknown error" + log("sqlite3_open failed (\(rc)): \(msg)") + if let db { sqlite3_close(db) } + return + } + log("Database opened.") + + // Enable loadable extensions + rc = sqlite3_enable_load_extension(db, 1) + log("sqlite3_enable_load_extension rc=\(rc)") + + // Locate the extension in the bundle (adjust as needed) + let vendorBundle = Bundle(identifier: "ai.sqlite.cloudsync") + let candidatePaths: [String?] = [ + vendorBundle?.path(forResource: "CloudSync", ofType: "dylib"), + vendorBundle?.path(forResource: "CloudSync", ofType: ""), + Bundle.main.path(forResource: "CloudSync", ofType: "dylib"), + Bundle.main.path(forResource: "CloudSync", ofType: "") + ] + let cloudsyncPath = candidatePaths.compactMap { $0 }.first + log("cloudsyncPath: \(cloudsyncPath ?? "Not found")") + + var loaded = false + if let path = cloudsyncPath { + var errMsg: UnsafeMutablePointer? = nil + rc = sqlite3_load_extension(db, path, nil, &errMsg) + if rc != SQLITE_OK { + let message = errMsg.map { String(cString: $0) } ?? String(cString: sqlite3_errmsg(db)) + if let e = errMsg { sqlite3_free(e) } + log("sqlite3_load_extension failed rc=\(rc): \(message)") + } else { + loaded = true + log("sqlite3_load_extension succeeded.") + } + + // Optionally disable further extension loading + _ = sqlite3_enable_load_extension(db, 0) + } else { + log("Skipping load: extension file not found in bundle.") + } + + // Run SELECT cloudsync_version() and log the result + if loaded { + let sql = "SELECT cloudsync_version()" + log("Running query: \(sql)") + var stmt: OpaquePointer? + rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nil) + if rc != SQLITE_OK { + let msg = String(cString: sqlite3_errmsg(db)) + log("sqlite3_prepare_v2 failed (\(rc)): \(msg)") + } else { + defer { sqlite3_finalize(stmt) } + rc = sqlite3_step(stmt) + if rc == SQLITE_ROW { + if let cstr = sqlite3_column_text(stmt, 0) { + let version = String(cString: cstr) + log("cloudsync_version(): \(version)") + } else { + log("cloudsync_version(): (null)") + } + } else if rc == SQLITE_DONE { + log("cloudsync_version() returned no rows") + } else { + let msg = String(cString: sqlite3_errmsg(db)) + log("sqlite3_step failed (\(rc)): \(msg)") + } + } + } else { + log("Extension not loaded; skipping cloudsync_version() query.") + } + + if let db { sqlite3_close(db) } + log("Done.") + } + } + + @MainActor + private func log(_ line: String) { + statusLines.append(line) + } +} + +#Preview { + ContentView() +} +``` + +## Expected Results + +When you run the test app, you should see status messages in the UI indicating: + +- Database connection success +- Extension loading status +- CloudSync version information (if successfully loaded) + +This confirms that CloudSync is properly integrated and functional in your Swift project. + +## Usage Example + +Check out the [Swift Multiplatform app](https://github.com/sqliteai/sqlite-sync/tree/main/examples/swift-multiplatform-app) for a complete implementation of using the SQLite CloudSync extension to sync data across devices. diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/quick-starts/linux.md b/sqlite-cloud/sqlite-ai/sqlite-sync/quick-starts/linux.md new file mode 100644 index 0000000..f0299ec --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/quick-starts/linux.md @@ -0,0 +1,66 @@ +--- +title: Linux Quick Start +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-quick-start-linux +--- + +SQLite on Linux supports dynamic extension loading via `.so` shared libraries. + +This guide walks through how to load an extension named `cloudsync.so` on common Linux distributions via SQLite3 Command Line. + +--- + +## 1. Install SQLite (Per Distribution) + +### Ubuntu / Debian + +```bash +sudo apt install sqlite3 +``` + +### Fedora + +```bash +sudo dnf install sqlite +``` + +### Arch Linux + +```bash +pacman -Sy sqlite3 +``` + +### Alpine Linux + +```bash +apk add sqlite +``` + +## 2. Download the Extension + +Go to [sqlite-sync releases](https://github.com/sqliteai/sqlite-sync/releases) and download the extension. + +> For Alpine Linux: ensure to download the extension specifically for `musl-x86_64` or `musl-arm64` targets. + +## 3. Load Extension from CLI + +```bash +sqlite3 +``` + +```sql +.load ./cloudsync.so +SELECT cloudsync_version(); +``` + +--- + +## Troubleshooting + +| Problem | Solution | +| -------------------------------------------- | ----------------------------------------------------------------- | +| `no such file or directory` | Ensure path to `.so` is correct and matches your platform. | +| `incompatible architecture` | Download extension for your Linux system (e.g., x86_64 vs arm64). | +| `Failed to load extension: symbol not found` | Download the extension for `musl-x86_64` or `musl-arm64` targets | diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/quick-starts/macos.md b/sqlite-cloud/sqlite-ai/sqlite-sync/quick-starts/macos.md new file mode 100644 index 0000000..48e3706 --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/quick-starts/macos.md @@ -0,0 +1,107 @@ +--- +title: "MacOS Quick Start Guide" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-quick-start-macos +--- + +This guide explains how to install SQLite on macOS with support for loading extensions. + +## macOS and xcframework + +On recent versions of macOS, the recommended way to load a SQLite extension is through the [.xcframework](https://github.com/sqliteai/sqlite-extensions-guide/blob/main/platforms/ios.md) approach, the same method used on iOS. + +## macOS and dylib + +On macOS, dynamic libraries (`.dylib`) can be loaded at runtime using SQLite’s `sqlite3_load_extension` API. + +### Step 1: Add Bridging Header (if using Swift only) + +Create a `bridging-header.h` file: + +```c +#include +``` + +Set it in your Xcode project under **Build Settings → Objective-C Bridging Header**. + +### Step 2: Swift Code to Load Extension + +```swift +import Foundation +import SQLite3 + +let dbPath = ":memory:" // or a real file path +var db: OpaquePointer? + +if sqlite3_open(dbPath, &db) != SQLITE_OK { + fatalError("Failed to open database") +} + +// Enable loading extensions +if sqlite3_enable_load_extension(db, 1) != SQLITE_OK { + let err = String(cString: sqlite3_errmsg(db)) + fatalError("Enable extension loading failed: \(err)") +} + +// Load the extension +let extensionPath = Bundle.main.path(forResource: "my_extension", ofType: "dylib")! +if sqlite3_load_extension(db, extensionPath, nil, nil) != SQLITE_OK { + let err = String(cString: sqlite3_errmsg(db)) + fatalError("Extension loading failed: \(err)") +} + +print("Extension loaded successfully.") +``` + +> ⚠️ Gatekeeper may block unsigned `.dylib` files. You might need to codesign or use `spctl --add`. + +## Python on macOS + +The default Python on macOS doesn't support loading SQLite extensions. +Install Python from the [official package](https://www.python.org/downloads/macos/) or use Homebrew Python instead: + +```bash +brew install python +``` + +Verify that you are using the Homebrew-installed `python3` by running: + +```bash +which python3 + +# /opt/homebrew/bin/python3 +``` + +After installing Python with Homebrew, the `python` command now uses the Homebrew version. +You can now load SQLite extensions in Python as shown here. + +``` +import sqlite3 +import os + +# Path to your compiled extension (.dylib for macOS/iOS) +EXTENSION_PATH = os.path.abspath("cloudsync") + +# Connect to SQLite and enable extension loading +conn = sqlite3.connect(":memory:") +conn.enable_load_extension(True) + +# Load the extension +try: + conn.load_extension(EXTENSION_PATH) + print("Extension loaded successfully.") +except sqlite3.OperationalError as e: + print(f"Failed to load extension: {e}") + +conn.enable_load_extension(False) + +# Optionally test it (e.g., call a custom SQL function) +cursor = conn.execute("SELECT cloudsync_version();") +print(cursor.fetchone()) +``` + +## Usage Example + +Check out the [Swift Multiplatform app](https://github.com/sqliteai/sqlite-sync/tree/main/examples/swift-multiplatform-app) for a complete implementation of using the SQLite CloudSync extension to sync data across devices. diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/quick-starts/react-native-expo.md b/sqlite-cloud/sqlite-ai/sqlite-sync/quick-starts/react-native-expo.md new file mode 100644 index 0000000..c13237f --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/quick-starts/react-native-expo.md @@ -0,0 +1,169 @@ +--- +title: "React Native - Expo Quick Start Guide" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-quick-start-expo +--- + +This guide shows how to integrate CloudSync extensions in Expo and React Native applications using OP-SQLite. + +## Getting Started + +Before setting up SQLite extensions, you'll need to create and initialize your project: + +### Create a New Expo Project + +```bash +# Create a new project +npx create-expo-app MyApp + +# Or use our pre-configured template with SQLite extensions +npx create-expo-app MyApp --template @sqliteai/todoapp +``` + +### Initialize for Native Code + +Since SQLite extensions require native code, you must initialize your project: + +```bash +cd MyApp +npx expo prebuild +``` + +> **Important**: This setup requires native code generation. Run `npx expo prebuild` after any changes to native dependencies or extension files. + +## Android Setup + +### Step 1: Download Android Extension + +1. Go to [sqlite-sync releases](https://github.com/sqliteai/sqlite-sync/releases) +2. Download your preferred .zip architecture releases: + - arm64-v8a - Modern 64-bit ARM devices (recommended for most users) + - x86_64 - 64-bit x86 emulators and Intel-based devices + +### Step 2: Place Extension Files + +Extract the `.so` files in the following directory structure: + +``` +/android + /app + /src + /main + /jniLibs + /arm64-v8a + cloudsync.so + /x86_64 + cloudsync.so +``` + +> **Note:** Create the `jniLibs` directory structure if it doesn't exist. + +## iOS Setup + +### Step 1: Download iOS Extension + +1. Go to [sqlite-sync releases](https://github.com/sqliteai/sqlite-sync/releases) +2. Download the `cloudsync-apple-xcframework-*.zip` +3. Extract `CloudSync.xcframework` + +### Step 2: Add Framework to Project + +1. Place the framework in your project: + + ``` + /ios + /[app-name] + /Frameworks + /CloudSync.xcframework + ``` + +2. **Open Xcode:** + + - Open Existing Project → Select your Expo app's `ios` folder + - Click on your app name (top left, with Xcode logo) + +3. **Configure Target:** + + - Go to **Targets** → **[app-name]** → **General** tab + - Scroll down to **"Frameworks, Libraries, and Embedded Content"** + - Click **"+"** → **"Add Other…"** → **"Add Files…"** + - Select `/ios/[app-name]/Frameworks/CloudSync.xcframework` + +4. **Set Embed Options:** + + - Ensure the **"Embed"** column shows either: + - **"Embed & Sign"** (recommended) + - **"Embed Without Signing"** + +5. **Verify Build Phases:** + + - Go to **"Build Phases"** tab + - Check that **"Embed Frameworks"** section contains **CloudSync** + +6. Close Xcode + +## Install OP-SQLite + +### For React Native: + +```bash +npm install @op-engineering/op-sqlite +npx pod-install +``` + +### For Expo: + +```bash +npx expo install @op-engineering/op-sqlite +npx expo prebuild +``` + +## Implementation + +### Basic Setup + +```javascript +import { getDylibPath, open } from "@op-engineering/op-sqlite"; +import { Platform } from "react-native"; + +// Open database connection +const db = open({ name: "to-do-app" }); +``` + +### Load Extension + +```javascript +const loadCloudSyncExtension = async () => { + let extensionPath; + + console.log("Loading CloudSync extension..."); + + try { + if (Platform.OS === "ios") { + extensionPath = getDylibPath("ai.sqlite.cloudsync", "CloudSync"); + } else { + extensionPath = "cloudsync"; + } + + // Load the extension + db.loadExtension(extensionPath); + + // Verify extension loaded successfully + const version = await db.execute("SELECT cloudsync_version();"); + console.log( + `CloudSync extension loaded successfully, version: ${version.rows[0]["cloudsync_version()"]}` + ); + + return true; + } catch (error) { + console.error("Error loading CloudSync extension:", error); + return false; + } +}; +``` + +## Usage Example + +Check out the [Expo to-do-app](https://github.com/sqliteai/sqlite-sync/tree/main/examples/to-do-app) for comprehensive usage examples and best practices. diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/quick-starts/wasm.md b/sqlite-cloud/sqlite-ai/sqlite-sync/quick-starts/wasm.md new file mode 100644 index 0000000..fbbefda --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/quick-starts/wasm.md @@ -0,0 +1,100 @@ +--- +title: "WASM Quick Start Guide" +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-quick-start-wasm +--- + +1. Install the WebAssembly (WASM) version of SQLite with the SQLite Sync extension enabled from npm: + + ``` + npm install @sqliteai/sqlite-wasm + ``` + +2. Create an HTML file that imports the SQLite WASM module using an import map and references the JavaScript loader: + + ``` + + + + + + SQLite WASM Extension Example + + +

SQLite WASM with SQLite Sync Example

+

Open the directory in the terminal and type: npx serve .

+

Check the browser console for output.

+ + + + + + ``` + +3. Create the JavaScript file (load_extension.js) that initializes the SQLite WASM worker and verifies the extension is loaded: + + ``` + /** + * This example uses the package `@sqliteai/sqlite-wasm`. + * This version of SQLite WASM is bundled with SQLite Sync and SQLite Vector extensions. + * Extensions cannot be loaded at runtime in the browser environment. + * + * Run: `npx serve .` + */ + + import { sqlite3Worker1Promiser } from '@sqliteai/sqlite-wasm'; + + const log = console.log; + const error = console.error; + + const initializeSQLite = async () => { + try { + log('Loading and initializing SQLite3 module with sqlite-sync extension...'); + + const promiser = await new Promise((resolve) => { + const _promiser = sqlite3Worker1Promiser({ + onready: () => resolve(_promiser), + }); + }); + + const configResponse = await promiser('config-get', {}); + log('Running SQLite3 version', configResponse.result.version.libVersion); + + const openResponse = await promiser('open', { + filename: 'file:mydb.sqlite3', + }); + const { dbId } = openResponse; + + await promiser('exec', { + dbId, + sql: 'SELECT cloudsync_version();', // or vector_version() + callback: (result) => { + if (!result.row) { + return; + } + log('Include SQLite Sync version: ', result.row[0]); + } + }); + + } catch (err) { + if (!(err instanceof Error)) { + err = new Error(err.result.message); + } + error(err.name, err.message); + } + }; + + initializeSQLite(); + ``` + +## Usage Example + +Check out the [React/Vite app](https://github.com/sqliteai/sqlite-sync/tree/main/examples/sport-tracker-app) for a complete implementation of using the SQLite CloudSync extension to sync data across devices. diff --git a/sqlite-cloud/sqlite-ai/sqlite-sync/quick-starts/windows.md b/sqlite-cloud/sqlite-ai/sqlite-sync/quick-starts/windows.md new file mode 100644 index 0000000..ec78376 --- /dev/null +++ b/sqlite-cloud/sqlite-ai/sqlite-sync/quick-starts/windows.md @@ -0,0 +1,226 @@ +--- +title: Windows Quick Start +description: SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. +category: platform +status: publish +slug: sqlite-sync-quick-start-windows +--- + +This guide explains how to install SQLite on Windows with support for loading extensions. + +## Using SQLite with Python + +1. **Download Python** + Get the latest Python for Windows from [python.org](https://www.python.org/downloads/windows/). + +2. **Install Python** + + - Run the installer. + - Make sure to check **"Add Python to PATH"**. + - SQLite comes bundled with Python, no extra steps needed. + +3. **Check your installation** + Open Command Prompt and run: + + ```bash + python --version + python -c "import sqlite3; print('SQLite version:', sqlite3.sqlite_version)" + ``` + +4. **Download the Extension** + Go to [sqlite-sync releases](https://github.com/sqliteai/sqlite-sync/releases) and download the extension. + +5. **Load Extension** + + ``` + import sqlite3 + import os + + # Path to your compiled extension (.dll for Windows) + EXTENSION_PATH = os.path.abspath("cloudsync") + + # Connect to SQLite and enable extension loading + conn = sqlite3.connect(":memory:") + conn.enable_load_extension(True) + + # Load the extension + try: + conn.load_extension(EXTENSION_PATH) + print("Extension loaded successfully.") + except sqlite3.OperationalError as e: + print(f"Failed to load extension: {e}") + + conn.enable_load_extension(False) + + # Optionally test it (e.g., call a custom SQL function) + cursor = conn.execute("SELECT cloudsync_version();") + print(cursor.fetchone()) + ``` + +## Using SQLite with C# + +This guide shows how to load a native SQLite extension (e.g., **`cloudsync.dll`**) from a C# app on **Windows** using **`Microsoft.Data.Sqlite`**. + +### Prerequisites + +- Windows x64 +- .NET 6+ SDK +- [NuGet package manager](https://learn.microsoft.com/en-us/nuget/install-nuget-client-tools?tabs=windows) +- The native extension file: `cloudsync.dll` (x64 build) - download from [sqlite-sync releases](https://github.com/sqliteai/sqlite-sync/releases) + +> **Important:** Your app, `e_sqlite3.dll` (bundled by `Microsoft.Data.Sqlite`), and `cloudsync.dll` must all be the **same architecture** (typically x64). + +--- + +### 1. Install the SQLite package + +Install the [`Microsoft.Data.Sqlite`](https://www.nuget.org/packages/Microsoft.Data.Sqlite) NuGet package: + +```bash +dotnet add package Microsoft.Data.Sqlite +``` + +### 2. Set up your project structure + +Place `cloudsync.dll` in your project and configure it to copy to the output folder. + +Example directory structure: + +``` +MyApp/ + Program.cs + Native/ + cloudsync.dll + MyApp.csproj +``` + +Configure your `MyApp.csproj` file: + +```xml + + + Exe + net8.0 + enable + enable + + + + + + + + + + PreserveNewest + + + +``` + +### 3. Load the extension in your code + +Create your `Program.cs` file to initialize SQLite and load the extension: + +```csharp +using System; +using Microsoft.Data.Sqlite; + +class Program +{ + static void Main() + { + // Configure the database connection + var cs = new SqliteConnectionStringBuilder + { + DataSource = "example.db", + Mode = SqliteOpenMode.ReadWriteCreate + }.ToString(); + + using var conn = new SqliteConnection(cs); + conn.Open(); + + // Enable extension loading + conn.EnableExtensions(); + + // Load the native extension (DLL must be next to the EXE or on PATH) + // You can pass an absolute path if you prefer + conn.LoadExtension("cloudsync"); + + // Verify SQLite is working + using var cmd = conn.CreateCommand(); + cmd.CommandText = "SELECT sqlite_version();"; + Console.WriteLine("SQLite version: " + cmd.ExecuteScalar()); + + // Verify the extension is loaded + cmd.CommandText = "SELECT cloudsync_version();"; + Console.WriteLine("cloudsync_version(): " + cmd.ExecuteScalar()); + } +} +``` + +### 4. Run your application + +Build and run your application: + +```bash +dotnet build +dotnet run +``` + +You should see output similar to: + +``` +SQLite version: 3.45.0 +cloudsync_version(): 1.0.0 +``` + +#### Extension search locations + +SQLite searches for extensions in this order: + +1. Process working directory +2. Application base directory (where your .exe lives) +3. PATH environment variable directories +4. Full path provided to `LoadExtension(...)` + +> **Tip:** For most apps, simply copying the DLL to the output folder (next to your .exe) is sufficient. + +--- + +### Common issues and solutions + +**SqliteException: not authorized** + +- **Cause:** Extension loading not enabled +- **Fix:** Call `conn.EnableExtensions()` before loading + +**SqliteException: The specified module could not be found** + +- **Cause:** DLL not in search path or missing dependencies +- **Fix:** Place DLL next to .exe, use absolute path, or ensure dependencies are available + +**BadImageFormatException** + +- **Cause:** Architecture mismatch (e.g., mixing x86 and x64) +- **Fix:** Ensure app, `e_sqlite3.dll`, and `cloudsync.dll` are all the same architecture + +**EntryPointNotFoundException** + +- **Cause:** DLL is not a valid SQLite extension +- **Fix:** Verify the extension exports `sqlite3_extension_init` + +**Windows "blocked" DLL** + +- **Cause:** Downloaded DLL is blocked by Windows +- **Fix:** Right-click → Properties → Check "Unblock" → OK + +--- + +### Deployment + +When publishing your app, ensure the extension is included: + +```bash +dotnet publish -c Release -r win-x64 --self-contained false +```