You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fix/bind column value parameters also if null (#6)
* fix(sync): always bind column value parameters in merge_insert_col
Fix parameter binding bug in merge_insert_col that caused SQLite-to-PostgreSQL sync to fail with "there is no parameter $3" when NULL values were synced before non-NULL values for the same column.
* fix(network): fix the value of the seq variable in cloudsync_payload_get when the last db_version is not related to a local change
* test(postgres): new test for null value
* fix(postgres): ensure NULL values use consistent decoded types for SPI plan caching
When syncing NULL values first, PostgreSQL's SPI caches the prepared plan with the NULL's type. If a subsequent non-NULL value decodes to a different type, the plan fails. The fix maps column types to their decoded equivalents so NULL and non-NULL values always use consistent types (e.g., all integers use INT8OID, all floats use FLOAT8OID, most others use TEXTOID).
Add map_column_oid_to_decoded_oid() to map column types to their decoded equivalents (INT2/4/8 → INT8, FLOAT4/8/NUMERIC → FLOAT8, BYTEA → BYTEA, others → TEXT). This ensures NULL and non-NULL values bind with the same type, preventing "there is no parameter $N" errors when NULL is synced before non-NULL values for the same column.
Add tests 23 and 24 for UUID columns and comprehensive nullable type coverage (INT2/4/8, FLOAT4/8, NUMERIC, BYTEA, TEXT, VARCHAR, CHAR, UUID, JSON, JSONB, DATE, TIMESTAMP).
* fix(postgres): add bigint to boolean cast for BOOLEAN column sync
BOOLEAN values are encoded as INT8 in sync payloads for SQLite interoperability, but PostgreSQL has no built-in cast from bigint to boolean. Add a custom ASSIGNMENT cast that enables BOOLEAN columns to sync correctly.
The cast uses ASSIGNMENT context (not IMPLICIT) to avoid unintended conversions in WHERE clauses while still enabling INSERT/UPDATE operations used by merge_insert.
The write direction (BOOL → INT encoding flow) "just works" because DatumGetBool() naturally returns 0 or 1. The problem was only on the read side where PostgreSQL refused to cast the decoded INT8 back to BOOLEAN without our custom cast.
* feat(commands): add sync roundtrip RLS test guide
* bump version
* ci: add postgres-test job to main workflow
* ci(Makefile.postgresql): replaced all docker-compose commands with docker compose (v2 plugin syntax)
Fix the execution in the github actions runner: The GitHub Actions runner has docker compose (v2 plugin) but not the standalone docker-compose (v1)
* ci: fix the "run postgresql tests" step
if (rc==DBRES_OK) rc=databasevm_bind_value(vm, table->npks+2, col_value);
1211
-
if (rc!=DBRES_OK) {
1212
-
cloudsync_set_dberror(data);
1213
-
dbvm_reset(vm);
1214
-
returnrc;
1215
-
}
1216
-
1211
+
} else {
1212
+
rc=databasevm_bind_null(vm, table->npks+1);
1213
+
if (rc==DBRES_OK) rc=databasevm_bind_null(vm, table->npks+2);
1217
1214
}
1218
-
1215
+
if (rc!=DBRES_OK) {
1216
+
cloudsync_set_dberror(data);
1217
+
dbvm_reset(vm);
1218
+
returnrc;
1219
+
}
1220
+
1219
1221
// perform real operation and disable triggers
1220
1222
1221
1223
// in case of GOS we reused the table->col_merge_stmt statement
@@ -2442,8 +2444,8 @@ int cloudsync_payload_get (cloudsync_context *data, char **blob, int *blob_size,
2442
2444
2443
2445
// retrieve BLOB
2444
2446
charsql[1024];
2445
-
snprintf(sql, sizeof(sql), "WITH max_db_version AS (SELECT MAX(db_version) AS max_db_version FROM cloudsync_changes) "
2446
-
"SELECT * FROM (SELECT cloudsync_payload_encode(tbl, pk, col_name, col_value, col_version, db_version, site_id, cl, seq) AS payload, max_db_version AS max_db_version, MAX(IIF(db_version = max_db_version, seq, NULL)) FROM cloudsync_changes, max_db_version WHERE site_id=cloudsync_siteid() AND (db_version>%d OR (db_version=%d AND seq>%d))) WHERE payload IS NOT NULL", *db_version, *db_version, *seq);
2447
+
snprintf(sql, sizeof(sql), "WITH max_db_version AS (SELECT MAX(db_version) AS max_db_version FROM cloudsync_changes WHERE site_id=cloudsync_siteid()) "
2448
+
"SELECT * FROM (SELECT cloudsync_payload_encode(tbl, pk, col_name, col_value, col_version, db_version, site_id, cl, seq) AS payload, max_db_version AS max_db_version, MAX(IIF(db_version = max_db_version, seq, 0)) FROM cloudsync_changes, max_db_version WHERE site_id=cloudsync_siteid() AND (db_version>%d OR (db_version=%d AND seq>%d))) WHERE payload IS NOT NULL", *db_version, *db_version, *seq);
0 commit comments