diff --git a/c/pgtypes.c b/c/pgtypes.c index 28f9afd..e9b4238 100644 --- a/c/pgtypes.c +++ b/c/pgtypes.c @@ -112,6 +112,16 @@ SENDFN(uint4) { fustr_writebeU(32, out, iv); } +RECVFN(uint8) { + RLEN(8); + return newSVuv(fu_frombeU(64, buf)); +} + +SENDFN(uint8) { + /* Doesn't have the nice input validation of 'SIV', but this type is pretty rare anyway */ + fustr_writebeU(64, out, SvUV(val)); +} + RECVFN(bytea) { return newSVpvn(buf, len); } @@ -375,6 +385,43 @@ SENDFN(inet) { } } +RECVFN(uuid) { + RLEN(16); + char tmp[64]; + char *out = tmp; + unsigned char *in = (unsigned char *)buf; + int i; + for (i=0; i<16; i++) { + if (i == 4 || i == 6 || i == 8 || i == 10) *out++ = '-'; + *out++ = PL_hexdigit[(in[i] >> 4) & 0x0f]; + *out++ = PL_hexdigit[in[i] & 0x0f]; + } + *out = '\0'; + return newSVpv(tmp, 0); +} + +SENDFN(uuid) { + const char *in = SvPV_nolen(val); + int bytes = 0; + unsigned char dig = 0x10; + if (*in == '{') in++; + for (; *in; in++) { + if (*in == '}') break; + if (dig == 0x10 && *in == '-') continue; + unsigned char x = *in; + x = x >= '0' && x <= '9' ? x-'0' : x >= 'A' && x <= 'F' ? x-'A'+10 : x >= 'a' && x <= 'f' ? x-'a'+10 : 0x10; + if (x == 0x10) SERR("invalid UUID"); + if (bytes >= 16) SERR("invalid UUID"); + if (dig == 0x10) dig = x; + else { + fustr_write_ch(out, (dig << 4) + x); + bytes++; + dig = 0x10; + } + } + if (dig != 0x10 || bytes != 16) SERR("invalid UUID"); +} + #undef SIV #undef RLEN #undef RECVFN @@ -508,10 +555,10 @@ SENDFN(inet) { A( 2210, "_regclass", 2205 )\ A( 2211, "_regtype", 2206 )\ A( 2949, "_txid_snapshot", 2970 )\ - /* 2950 uuid */\ + B( 2950, "uuid", uuid )\ A( 2951, "_uuid", 2950 )\ - /* 2970 txid_snapshot */\ - /* 3220 pg_lsn */\ + /* 2970 txid_snapshot: same as pg_snapshot */\ + /* 3220 pg_lsn: uint64 with custom formatting */\ A( 3221, "_pg_lsn", 3220 )\ /* 3361 pg_ndistinct */\ /* 3402 pg_dependencies */\ @@ -538,9 +585,9 @@ SENDFN(inet) { /* 4600 pg_brin_bloom_summary */\ /* 4601 pg_brin_minmax_multi_summary */\ /* 5017 pg_mcv_list */\ - /* 5038 pg_snapshot */\ + /* 5038 pg_snapshot: int4 nxip, int8 xmin, int8 xmax, int8 xip */\ A( 5039, "_pg_snapshot", 5038 )\ - /* 5069 xid8 */ + B( 5069, "xid8", uint8 ) static const fupg_type fupg_builtin[] = { #define B(oid, name, fun) { oid, 0, name"\0", fupg_send_##fun, fupg_recv_##fun }, diff --git a/t/pgtypes.t b/t/pgtypes.t index 091797e..18e7803 100644 --- a/t/pgtypes.t +++ b/t/pgtypes.t @@ -57,6 +57,8 @@ for my $t (qw/regproc oid xid cid regprocedure regoper regoperator regtype regco } v regtype => 17, undef, 'bytea'; # like this +v xid8 => 18446744073709551615; + v bytea => '', undef, '\x'; v bytea => 'hello', undef, '\x68656c6c6f'; v bytea => "\xaf\x90", undef, '\xaf90'; @@ -99,6 +101,12 @@ v cidr => '0.0.0.0', '0.0.0.0/32', undef, '0.0.0.0/32'; v cidr => '::', '::/128', undef, '::/128'; f inet => $_ for ('', [], '0.0.0.0/a', '0.0.0.0/1a', '[::]', '0.0.0.0/33', '::/129', '/1', ':/1'); +v uuid => 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'; +v uuid => '{A0EEBC99-9C0B4EF8BB6D6BB9BD38-0A11}', 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11', '{A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11}', 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'; +f uuid => 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a111'; +f uuid => 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a1'; +f uuid => 'a0egbc99-9c0b-4ef8-bb6d-6bb9bd380a11'; + v 'int[]', [], undef, '{}'; v 'int[]', [1], undef, '{1}'; v 'int[]', [1,-3,undef,3], undef, '{1,-3,NULL,3}';