Skip to content

Commit 508b4c7

Browse files
committed
docs: remove NOT NULL requirement from primary key definitions
The extension now enforces NULL primary key rejection at runtime, so the explicit NOT NULL constraint on PK columns is no longer a schema requirement. Replace the "must be NOT NULL" guidance with a note about runtime enforcement.
1 parent 47acb91 commit 508b4c7

File tree

9 files changed

+29
-29
lines changed

9 files changed

+29
-29
lines changed

.claude/commands/test-sync-roundtrip-postgres-local.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Ask the user to provide a DDL query for the table(s) to test. It can be in Postg
1616
**Option 1: Simple TEXT primary key**
1717
```sql
1818
CREATE TABLE test_sync (
19-
id TEXT PRIMARY KEY NOT NULL,
19+
id TEXT PRIMARY KEY,
2020
name TEXT,
2121
value INTEGER
2222
);
@@ -34,13 +34,13 @@ CREATE TABLE test_uuid (
3434
**Option 3: Two tables scenario (tests multi-table sync)**
3535
```sql
3636
CREATE TABLE authors (
37-
id TEXT PRIMARY KEY NOT NULL,
37+
id TEXT PRIMARY KEY,
3838
name TEXT,
3939
email TEXT
4040
);
4141

4242
CREATE TABLE books (
43-
id TEXT PRIMARY KEY NOT NULL,
43+
id TEXT PRIMARY KEY,
4444
title TEXT,
4545
author_id TEXT,
4646
published_year INTEGER

.claude/commands/test-sync-roundtrip-postrges-local-rls.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Ask the user to provide a DDL query for the table(s) to test. It can be in Postg
1616
**Option 1: Simple TEXT primary key with user_id for RLS**
1717
```sql
1818
CREATE TABLE test_sync (
19-
id TEXT PRIMARY KEY NOT NULL,
19+
id TEXT PRIMARY KEY,
2020
user_id UUID NOT NULL,
2121
name TEXT,
2222
value INTEGER
@@ -36,14 +36,14 @@ CREATE TABLE test_uuid (
3636
**Option 3: Two tables scenario with user ownership**
3737
```sql
3838
CREATE TABLE authors (
39-
id TEXT PRIMARY KEY NOT NULL,
39+
id TEXT PRIMARY KEY,
4040
user_id UUID NOT NULL,
4141
name TEXT,
4242
email TEXT
4343
);
4444

4545
CREATE TABLE books (
46-
id TEXT PRIMARY KEY NOT NULL,
46+
id TEXT PRIMARY KEY,
4747
user_id UUID NOT NULL,
4848
title TEXT,
4949
author_id TEXT,

.claude/commands/test-sync-roundtrip-sqlitecloud-rls.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Ask the user to provide a DDL query for the table(s) to test. It can be in Postg
1616
**Option 1: Simple TEXT primary key with user_id for RLS**
1717
```sql
1818
CREATE TABLE test_sync (
19-
id TEXT PRIMARY KEY NOT NULL,
19+
id TEXT PRIMARY KEY,
2020
user_id TEXT NOT NULL,
2121
name TEXT,
2222
value INTEGER
@@ -26,14 +26,14 @@ CREATE TABLE test_sync (
2626
**Option 2: Two tables scenario with user ownership**
2727
```sql
2828
CREATE TABLE authors (
29-
id TEXT PRIMARY KEY NOT NULL,
29+
id TEXT PRIMARY KEY,
3030
user_id TEXT NOT NULL,
3131
name TEXT,
3232
email TEXT
3333
);
3434

3535
CREATE TABLE books (
36-
id TEXT PRIMARY KEY NOT NULL,
36+
id TEXT PRIMARY KEY,
3737
user_id TEXT NOT NULL,
3838
title TEXT,
3939
author_id TEXT,

API.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ This document provides a reference for the SQLite functions provided by the `sql
4141

4242
Before initialization, `cloudsync_init` performs schema sanity checks to ensure compatibility with CRDT requirements and best practices. These checks include:
4343
- Primary keys should not be auto-incrementing integers; GUIDs (UUIDs, ULIDs) are highly recommended to prevent multi-node collisions.
44-
- All primary key columns must be `NOT NULL`.
4544
- All non-primary key `NOT NULL` columns must have a `DEFAULT` value.
45+
- **Note:** Any write operation that includes a NULL value for a primary key column will be rejected with an error, even if SQLite would normally allow it due to a legacy behavior.
4646

4747
**Schema Design Considerations:**
4848

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ sqlite3 myapp.db
264264

265265
-- Create a table (primary key MUST be TEXT for global uniqueness)
266266
CREATE TABLE IF NOT EXISTS my_data (
267-
id TEXT PRIMARY KEY NOT NULL,
267+
id TEXT PRIMARY KEY,
268268
value TEXT NOT NULL DEFAULT '',
269269
created_at TEXT DEFAULT CURRENT_TIMESTAMP
270270
);
@@ -313,7 +313,7 @@ SELECT cloudsync_terminate();
313313
-- Load extension and create identical table structure
314314
.load ./cloudsync
315315
CREATE TABLE IF NOT EXISTS my_data (
316-
id TEXT PRIMARY KEY NOT NULL,
316+
id TEXT PRIMARY KEY,
317317
value TEXT NOT NULL DEFAULT '',
318318
created_at TEXT DEFAULT CURRENT_TIMESTAMP
319319
);
@@ -372,12 +372,12 @@ When designing your database schema for SQLite Sync, follow these best practices
372372
- **Use globally unique identifiers**: Always use TEXT primary keys with UUIDs, ULIDs, or similar globally unique identifiers
373373
- **Avoid auto-incrementing integers**: Integer primary keys can cause conflicts across multiple devices
374374
- **Use `cloudsync_uuid()`**: The built-in function generates UUIDv7 identifiers optimized for distributed systems
375-
- **All primary keys must be explicitly declared as `NOT NULL`**.
375+
- **Note:** Any write operation that includes a NULL value for a primary key column will be rejected with an error, even if SQLite would normally allow it due to a legacy behavior.
376376

377377
```sql
378378
-- ✅ Recommended: Globally unique TEXT primary key
379379
CREATE TABLE users (
380-
id TEXT PRIMARY KEY NOT NULL, -- Use cloudsync_uuid()
380+
id TEXT PRIMARY KEY, -- Use cloudsync_uuid()
381381
name TEXT NOT NULL,
382382
email TEXT UNIQUE NOT NULL
383383
);

docs/postgresql/CLIENT.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,26 +34,26 @@ so CloudSync can sync between a PostgreSQL server and SQLite clients.
3434

3535
### 1) Primary Keys
3636

37-
- Use **TEXT NOT NULL** primary keys in SQLite.
38-
- PostgreSQL primary keys can be **TEXT NOT NULL** or **UUID**. If the PK type
37+
- Use **TEXT** primary keys in SQLite.
38+
- PostgreSQL primary keys can be **TEXT** or **UUID**. If the PK type
3939
isn't explicitly mapped to a DBTYPE (like UUID), it will be converted to TEXT
4040
in the payload so it remains compatible with the SQLite extension.
4141
- Generate IDs with `cloudsync_uuid()` on both sides.
4242
- Avoid INTEGER auto-increment PKs.
4343

4444
SQLite:
4545
```sql
46-
id TEXT PRIMARY KEY NOT NULL
46+
id TEXT PRIMARY KEY
4747
```
4848

4949
PostgreSQL:
5050
```sql
51-
id TEXT PRIMARY KEY NOT NULL
51+
id TEXT PRIMARY KEY
5252
```
5353

5454
PostgreSQL (UUID):
5555
```sql
56-
id UUID PRIMARY KEY NOT NULL
56+
id UUID PRIMARY KEY
5757
```
5858

5959
### 2) NOT NULL Columns Must Have DEFAULTs
@@ -99,7 +99,7 @@ Use defaults that serialize the same on both sides:
9999
SQLite:
100100
```sql
101101
CREATE TABLE notes (
102-
id TEXT PRIMARY KEY NOT NULL,
102+
id TEXT PRIMARY KEY,
103103
title TEXT NOT NULL DEFAULT '',
104104
body TEXT DEFAULT '',
105105
views INTEGER NOT NULL DEFAULT 0,
@@ -111,7 +111,7 @@ CREATE TABLE notes (
111111
PostgreSQL:
112112
```sql
113113
CREATE TABLE notes (
114-
id TEXT PRIMARY KEY NOT NULL,
114+
id TEXT PRIMARY KEY,
115115
title TEXT NOT NULL DEFAULT '',
116116
body TEXT DEFAULT '',
117117
views INTEGER NOT NULL DEFAULT 0,
@@ -136,7 +136,7 @@ SELECT cloudsync_init('notes');
136136

137137
### Checklist
138138

139-
- [ ] PKs are TEXT + NOT NULL
139+
- [ ] PKs are TEXT (or UUID in PostgreSQL)
140140
- [ ] All NOT NULL columns have DEFAULT
141141
- [ ] Only INTEGER/FLOAT/TEXT/BLOB-compatible types
142142
- [ ] Same column names and order

docs/postgresql/RLS.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Given a table with an ownership column (`user_id`):
3131

3232
```sql
3333
CREATE TABLE documents (
34-
id TEXT PRIMARY KEY NOT NULL,
34+
id TEXT PRIMARY KEY,
3535
user_id UUID,
3636
title TEXT,
3737
content TEXT
@@ -68,13 +68,13 @@ This example shows the complete flow of syncing data between two databases where
6868
```sql
6969
-- Source database (DB A) — no RLS, represents the sync server
7070
CREATE TABLE documents (
71-
id TEXT PRIMARY KEY NOT NULL, user_id UUID, title TEXT, content TEXT
71+
id TEXT PRIMARY KEY, user_id UUID, title TEXT, content TEXT
7272
);
7373
SELECT cloudsync_init('documents');
7474

7575
-- Target database (DB B) — RLS enforced
7676
CREATE TABLE documents (
77-
id TEXT PRIMARY KEY NOT NULL, user_id UUID, title TEXT, content TEXT
77+
id TEXT PRIMARY KEY, user_id UUID, title TEXT, content TEXT
7878
);
7979
SELECT cloudsync_init('documents');
8080
ALTER TABLE documents ENABLE ROW LEVEL SECURITY;

docs/postgresql/SUPABASE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ SELECT cloudsync_version();
7676

7777
```sql
7878
CREATE TABLE notes (
79-
id TEXT PRIMARY KEY NOT NULL,
79+
id TEXT PRIMARY KEY,
8080
body TEXT DEFAULT ''
8181
);
8282

examples/simple-todo-db/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ Tables must be created on both the local database and SQLite Cloud with identica
5959
-- Create the main tasks table
6060
-- Note: Primary key MUST be TEXT (not INTEGER) for global uniqueness
6161
CREATE TABLE IF NOT EXISTS tasks (
62-
id TEXT PRIMARY KEY NOT NULL,
62+
id TEXT PRIMARY KEY,
6363
userid TEXT NOT NULL DEFAULT '',
6464
title TEXT NOT NULL DEFAULT '',
6565
description TEXT DEFAULT '',
@@ -84,7 +84,7 @@ SELECT cloudsync_is_enabled('tasks');
8484
- Execute the same CREATE TABLE statement:
8585
```sql
8686
CREATE TABLE IF NOT EXISTS tasks (
87-
id TEXT PRIMARY KEY NOT NULL,
87+
id TEXT PRIMARY KEY,
8888
userid TEXT NOT NULL DEFAULT '',
8989
title TEXT NOT NULL DEFAULT '',
9090
description TEXT DEFAULT '',
@@ -149,7 +149,7 @@ sqlite3 todo_device_b.db
149149
```sql
150150
-- Create identical table structure
151151
CREATE TABLE IF NOT EXISTS tasks (
152-
id TEXT PRIMARY KEY NOT NULL,
152+
id TEXT PRIMARY KEY,
153153
userid TEXT NOT NULL DEFAULT '',
154154
title TEXT NOT NULL DEFAULT '',
155155
description TEXT DEFAULT '',

0 commit comments

Comments
 (0)