Skip to content

Commit d9982a5

Browse files
committed
fix(postgres): return uuid type from cloudsync_uuid() for cross-database sync
1 parent 9ae4364 commit d9982a5

File tree

3 files changed

+46
-13
lines changed

3 files changed

+46
-13
lines changed

src/postgresql/cloudsync--1.0.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ LANGUAGE C STABLE;
2222

2323
-- Generate a new UUID
2424
CREATE OR REPLACE FUNCTION cloudsync_uuid()
25-
RETURNS bytea
25+
RETURNS uuid
2626
AS 'MODULE_PATHNAME', 'cloudsync_uuid'
2727
LANGUAGE C VOLATILE;
2828

src/postgresql/cloudsync_postgresql.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -176,15 +176,17 @@ PG_FUNCTION_INFO_V1(cloudsync_uuid);
176176
Datum cloudsync_uuid (PG_FUNCTION_ARGS) {
177177
UNUSED_PARAMETER(fcinfo);
178178

179-
uint8_t uuid[UUID_LEN];
180-
cloudsync_uuid_v7(uuid);
179+
uint8_t uuid_bytes[UUID_LEN];
180+
cloudsync_uuid_v7(uuid_bytes);
181181

182-
// Return as bytea
183-
bytea *result = (bytea *)palloc(VARHDRSZ + UUID_LEN);
184-
SET_VARSIZE(result, VARHDRSZ + UUID_LEN);
185-
memcpy(VARDATA(result), uuid, UUID_LEN);
182+
// Format as text with dashes (matches SQLite implementation)
183+
char uuid_str[UUID_STR_MAXLEN];
184+
cloudsync_uuid_v7_stringify(uuid_bytes, uuid_str, true);
186185

187-
PG_RETURN_BYTEA_P(result);
186+
// Parse into PostgreSQL UUID type
187+
Datum uuid_datum = DirectFunctionCall1(uuid_in, CStringGetDatum(uuid_str));
188+
189+
PG_RETURN_DATUM(uuid_datum);
188190
}
189191

190192
// cloudsync_db_version() - Get current database version

test/postgresql/01_unittest.sql

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,43 @@ CREATE EXTENSION IF NOT EXISTS cloudsync;
1919
SELECT cloudsync_version() AS version \gset
2020
\echo [PASS] (:testid) Test cloudsync_version: :version
2121

22-
-- 'Test uuid generation'
23-
SELECT (length(cloudsync_uuid()) > 0) AS uuid_ok \gset
24-
\if :uuid_ok
25-
\echo [PASS] (:testid) Test uuid generation
22+
-- Test uuid generation
23+
SELECT cloudsync_uuid() AS uuid1 \gset
24+
SELECT cloudsync_uuid() AS uuid2 \gset
25+
26+
-- Test 1: Format check (UUID v7 has standard format: xxxxxxxx-xxxx-7xxx-xxxx-xxxxxxxxxxxx)
27+
SELECT (:'uuid1' ~ '^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$') AS uuid_format_ok \gset
28+
\if :uuid_format_ok
29+
\echo [PASS] (:testid) UUID format valid (UUIDv7 pattern)
30+
\else
31+
\echo [FAIL] (:testid) UUID format invalid - Got: :uuid1
32+
SELECT (:fail::int + 1) AS fail \gset
33+
\endif
34+
35+
-- Test 2: Uniqueness check
36+
SELECT (:'uuid1' != :'uuid2') AS uuid_unique_ok \gset
37+
\if :uuid_unique_ok
38+
\echo [PASS] (:testid) UUID uniqueness (two calls generated different UUIDs)
39+
\else
40+
\echo [FAIL] (:testid) UUID uniqueness - Both calls returned: :uuid1
41+
SELECT (:fail::int + 1) AS fail \gset
42+
\endif
43+
44+
-- Test 3: Monotonicity check (UUIDv7 should be sortable by timestamp)
45+
SELECT (:'uuid1' < :'uuid2') AS uuid_monotonic_ok \gset
46+
\if :uuid_monotonic_ok
47+
\echo [PASS] (:testid) UUID monotonicity (UUIDs are time-ordered)
48+
\else
49+
\echo [FAIL] (:testid) UUID monotonicity - uuid1: :uuid1, uuid2: :uuid2
50+
SELECT (:fail::int + 1) AS fail \gset
51+
\endif
52+
53+
-- Test 4: Type check (ensure it's actually UUID type, not text)
54+
SELECT (pg_typeof(cloudsync_uuid())::text = 'uuid') AS uuid_type_ok \gset
55+
\if :uuid_type_ok
56+
\echo [PASS] (:testid) UUID type is correct (uuid, not text or bytea)
2657
\else
27-
\echo [FAIL] (:testid) Test uuid generation
58+
\echo [FAIL] (:testid) UUID type incorrect - Got: (pg_typeof(cloudsync_uuid())::text)
2859
SELECT (:fail::int + 1) AS fail \gset
2960
\endif
3061

0 commit comments

Comments
 (0)