This repository was archived by the owner on Jul 22, 2026. It is now read-only.
Tags: sqliteai/sqlite-sync-dev
Toggle 0.9.203's commit message
fix(ci): use macos-15 for PostgreSQL x86_64 build with cross-compilation
macos-13 runners are deprecated. Cross-compile x86_64 on macos-15 ARM
runner via -arch x86_64 passed through PG_EXTRA_CFLAGS. Also pass
PG_EXTRA_CFLAGS to linker for arch flag propagation.
Toggle 0.9.202's commit message
fix: update schema hash on extension version change
When upgrading from an older version, the schema hash algorithm may
differ. Call cloudsync_update_schema_hash before updating the stored
version to ensure hash compatibility across synced devices.
Toggle 0.9.201's commit message
refactor: move all savepoint management from shared layer to platform…
… wrappers (#17)
* refactor: move all savepoint management from shared layer to platform wrappers
Move database_begin_savepoint, database_commit_savepoint, and
database_rollback_savepoint calls out of cloudsync_begin_alter and
cloudsync_commit_alter (shared CRDT logic) into the platform-specific
wrappers in cloudsync_sqlite.c and cloudsync_postgresql.c.
This fixes the PostgreSQL "subtransaction left non-empty SPI stack"
warning by ensuring SPI_connect() is called before the savepoint
boundary, and creates architectural symmetry where shared code is
pure business logic and all transaction management lives in platform
wrappers.
Toggle 0.9.200's commit message
fix(ci): remove artifact size increase check to be less than 5% from …
…previous release
Toggle 0.9.118's commit message
Dev (#14)
* fix(network): cloudsync_network_check_changes must not return the nrows value in case of error
`SELECT cloudysnc_network_check_changes();` was returning "Runtime error: 0" in case of error response from the cloudsync microservice instead of the real error message
* feat(rls): add complete support for RLS with batch merge in cloudsync_payload_apply
* Feat/add support for status endpoint (#10)
* feat(network): add support for new status endpoint
* refactor(network): structured JSON responses for sync functions.
Example: {"send":{"status":"synced","localVersion":5,"serverVersion":5},"receive":{"rows":3,"tables":["tasks"]}}
* Feat/network support for multi org cloudsync (#11)
* Disable notnull prikey constraints (#12)
* The cloudsync extension now enforces NULL primary key rejection at runtime (any write with a NULL PK returns an error), so the explicit NOT NULL constraint on primary key columns is no longer a schema requirement
* test: add null primary key rejection tests for SQLite and PostgreSQL
* 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.
* docs: add first draft of PERFORMANCE.md and CHANGELOG.md
* fix(postgresql): resolve commit_alter crash and BYTEA handling in column_text
Guard savepoint commit/rollback against missing subtransactions to prevent
segfault in autocommit mode. Add BYTEA support to database_column_text so encoded PKs are readable during refill_metatable after ALTER TABLE.
Enable alter table sync test (31).
* test: new alter table test for postgres
* feat: update endpoints to use databaseMangedId for /v2/cloudsync api
* feat(network)!: replace URL connection string with a UUID (managedDatabaseId)
BREAKING CHANGE: cloudsync_network_init now accepts a UUID string instead of the previous URL string. URL connection strings are no longer accepted. The managed database identifier returned by the CloudSync service when a new database is registered for sync. For SQLiteCloud projects, this value can be obtained from the project's OffSync page on the dashboard.
* docs: update docs for the new managedDatabaseId arg for cloudsync_network_init
* docs(examples): update example for the new managedDatabaseId arg for cloudsync_network_init
Toggle 0.9.112's commit message
fix(sqlite): PRIVATE functions used inside triggers require SQLITE_IN…
…NOCUOUS
... otherwise the cloudsync_init function returns this error:
table_add_stmts error: 1 unsafe use of cloudsync_is_sync()
Runtime error: An error occurred while adding test_sync table information to global context (unsafe use of cloudsync_is_sync()) (21)
Toggle 0.9.111's commit message
Fix 35 bugs and bump version to 0.9.111 (#9)
* Fix 35 bugs across CloudSync SQLite/PostgreSQL sync extension
Comprehensive audit identified and fixed 35 bugs (1 CRITICAL, 7 HIGH,
18 MEDIUM, 9 LOW) across the entire codebase. All 84 SQLite tests and
26 PostgreSQL tests pass with 0 failures and 0 memory leaks.
## src/cloudsync.c (13 fixes)
- [HIGH] Guard NULL db_version_stmt in cloudsync_dbversion_rerun —
set db_version = CLOUDSYNC_MIN_DB_VERSION and return 0 when stmt
is NULL, preventing NULL dereference after schema rebuild failure
- [MEDIUM] Add early return for NULL stmt in dbvm_execute to prevent
crash when called with uninitialized statement pointer
- [MEDIUM] Change (bool)dbvm_count() to (dbvm_count() > 0) in
table_pk_exists — prevents negative return values being cast to
true, giving false positive "pk exists" results
- [MEDIUM] Add NULL check on database_column_text result in
cloudsync_refill_metatable before calling strlen — prevents crash
on corrupted or empty column data
- [MEDIUM] Route early returns in cloudsync_payload_apply through
goto cleanup so CLEANUP callback and vm finalize always run —
prevents resource leaks and callback contract violation
- [MEDIUM] Change return false to goto abort_add_table when
ROWIDONLY rejected — ensures table_free runs on the partially
allocated table, preventing memory leak
- [MEDIUM] Initialize *persistent = false at top of
cloudsync_colvalue_stmt — prevents use of uninitialized value
when table_lookup returns NULL
- [LOW] Add NULL check on database_column_blob in merge_did_cid_win
— prevents memcmp with NULL pointer on corrupted cloudsync table
- [LOW] Handle partial failure in table_add_to_context_cb — clean
up col_name, col_merge_stmt, col_value_stmt at index on error
instead of leaving dangling pointers
- [LOW] Remove unused pragma_checked field from cloudsync_context
- [LOW] Change pointer comparison to strcmp in cloudsync_set_schema
— pointer equality missed cases where different string pointers
had identical content
- [LOW] Fix cloudsync_payload_get NULL check: blob == NULL (always
false for char** arg) changed to *blob == NULL
- [LOW] Pass extra meta_ref args to SQL_CLOUDSYNC_UPSERT_COL_INIT_OR_BUMP_VERSION
mprintf call to match updated PostgreSQL format string
## src/sqlite/cloudsync_sqlite.c (5 fixes)
- [HIGH] Split DEFAULT_FLAGS into FLAGS_PURE (SQLITE_UTF8 |
SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC) and FLAGS_VOLATILE
(SQLITE_UTF8). Pure functions: cloudsync_version, cloudsync_pk_encode,
cloudsync_pk_decode. All others volatile — fixes cloudsync_uuid()
returning identical values within the same query when SQLite cached
deterministic results
- [HIGH] Fix realloc inconsistency in dbsync_update_payload_append:
on second realloc failure, state was inconsistent (new_values
resized, old_values not, capacity not updated). Both reallocs now
checked before updating pointers and capacity
- [MEDIUM] Move payload->count++ after all database_value_dup NULL
checks in dbsync_update_payload_append — prevents count increment
when allocation failed, which would cause use-after-free on cleanup
- [MEDIUM] Add dbsync_update_payload_free(payload) before 3 early
returns in dbsync_update_final — prevents memory leak of entire
aggregate payload on error paths
- [MEDIUM] Clean up partial database_value_dup allocations on OOM in
dbsync_update_payload_append — free dup'd values at current index
when count is not incremented to prevent leak
## src/sqlite/database_sqlite.c (6 fixes)
- [MEDIUM] Replace fixed 4096-byte trigger WHEN clause buffers with
dynamic cloudsync_memory_mprintf — prevents silent truncation for
tables with long filter expressions
- [MEDIUM] Check cloudsync_memory_mprintf return for NULL before
storing in col_names[] in database_build_trigger_when — prevents
strlen(NULL) crash in filter_is_column under OOM
- [LOW] Use consistent PRId64 format with (int64_t) cast for schema
hash in database_check_schema_hash and database_update_schema_hash
— prevents format string mismatch on platforms where uint64_t and
int64_t have different printf specifiers
- [LOW] Fix DEBUG_DBFUNCTION using undeclared variable 'table'
instead of 'table_name' in database_create_metatable (line 568)
and database_create_triggers (line 782) — compile error when
debug macros enabled
- [LOW] Remove dead else branch in database_pk_rowid — unreachable
code after sqlite3_prepare_v2 success check
## src/sqlite/sql_sqlite.c (1 fix)
- [MEDIUM] Change %s to %q in SQL_INSERT_SETTINGS_STR_FORMAT —
prevents SQL injection via malformed setting key/value strings
## src/dbutils.c (1 fix)
- [MEDIUM] Change snprintf to cloudsync_memory_mprintf for settings
insert using the new %q format — ensures proper SQL escaping
## src/utils.c (1 fix)
- [MEDIUM] Fix integer overflow in cloudsync_blob_compare:
(int)(size1 - size2) overflows for large size_t values, changed
to (size1 > size2) ? 1 : -1
## src/network.c (1 fix)
- [MEDIUM] Remove trailing semicolon from savepoint name
"cloudsync_logout_savepoint;" — semicolon in name caused
savepoint/release mismatch
## src/postgresql/sql_postgresql.c (1 fix)
- [CRITICAL] Replace EXCLUDED.col_version with %s.col_version
(table reference) in SQL_CLOUDSYNC_UPSERT_COL_INIT_OR_BUMP_VERSION
— PostgreSQL EXCLUDED refers to the proposed INSERT row (always
col_version=1), not the existing row. This caused col_version to
never increment correctly on conflict, breaking CRDT merge logic
## src/postgresql/cloudsync_postgresql.c (4 fixes)
- [HIGH] Change PG_RETURN_INT32(rc) to PG_RETURN_BOOL(rc == DBRES_OK)
in pg_cloudsync_terminate — SQL declaration returns BOOLEAN but code
returned raw integer, causing protocol mismatch
- [HIGH] Copy blob data with palloc+memcpy before databasevm_reset in
cloudsync_col_value, and fix PG_RETURN_CSTRING to PG_RETURN_BYTEA_P
— reset invalidates SPI tuple memory, causing use-after-free; wrong
return type caused type mismatch with SQL declaration
- [MEDIUM] Use palloc0 instead of cloudsync_memory_alloc+memset in
aggregate context — palloc0 is lifetime-safe in PG aggregate memory
context; cloudsync_memory_alloc uses wrong allocator
- [MEDIUM] Free SPI_tuptable in all paths of get_column_oid — prevents
SPI tuple table leak on early return
## src/postgresql/database_postgresql.c (3 fixes)
- [MEDIUM] Use sql_escape_identifier for table_name/schema in CREATE
INDEX — prevents SQL injection via specially crafted table names
- [MEDIUM] Use sql_escape_literal for table_name in trigger WHEN
clause — prevents SQL injection in trigger condition
- [LOW] Use SPI_getvalue instead of DatumGetName for type safety in
database_pk_names — DatumGetName assumes Name type which may not
match the actual column type from information_schema
## test/unit.c (3 new tests)
- do_test_blob_compare_large_sizes: verifies overflow fix for large
size_t values in cloudsync_blob_compare
- do_test_deterministic_flags: verifies cloudsync_uuid() returns
different values in same query (non-deterministic flag working)
- do_test_schema_hash_consistency: verifies int64 hash format
roundtrip through cloudsync_schema_versions table
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Bump version to 0.9.111
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Update .gitignore
Toggle 0.9.110's commit message
Merge pull request #8 from sqliteai/dev
release version 0.9.110
- fix/schema-hash
- fix/bind-column-value-parameters-also-if-null
- feat/sync-filter
Toggle 0.9.101's commit message
perf(postgres): use SQL template casting for non-PK column types (#4)
* perf(postgres): use SQL template casting for non-PK column types
Refactor type conversion for non-PK columns to use SQL template casting ($n::typename) instead of per-value SPI_execute_with_args("SELECT $1::typename") calls. This matches the pattern already used for primary key columns.
Changes:
- sql_postgresql.c: Add format_type() lookup and $n::coltype casting to SQL_BUILD_UPSERT_PK_AND_COL for non-PK column values
- cloudsync_postgresql.c: Simplify cloudsync_decode_bytea_to_pgvalue() to return base types only (INT8, FLOAT8, TEXT, BYTEA) without SPI casting
- cloudsync_postgresql.c: Remove lookup_column_type_oid() function
- Add test 19 (19_uuid_pk_with_unmapped_cols.sql) covering UUID PK with unmapped non-PK types (JSONB, UUID, INET, CIDR) and all CRUD operations: INSERT, UPDATE non-PK, UPDATE mapped cols, DELETE, RESURRECT, UPDATE PK
Performance benefit: Eliminates one SPI_execute call per non-PK column value during payload application, reducing overhead for unmapped PostgreSQL types.
* test(postgres): new tests
Toggle 0.9.100's commit message
feat: add support for UUID primary keys in PG (#3)
* Fix for PG UUID used as PK
* build(postgres): update test target for the current test files
* docs(docs/postgresql/CLIENT.md): clarify primary key requirements for PostgreSQL and SQLite, added support for UUID primary keys
* test(claude): add custom command for claude code to run sqlite-to-pg tests for the specified table schema
---------
Co-authored-by: Marco Bambini <marco@creolabs.com>