pg: Add dynamic type loading & support enum types

Least efficient way to support enums, really. *shrug*
This commit is contained in:
Yorhel 2025-02-08 17:24:41 +01:00
parent 2aaec6a218
commit 7b76d94719
5 changed files with 114 additions and 29 deletions

View file

@ -24,10 +24,10 @@ struct fupg_recv {
typedef struct {
Oid oid;
char name[16]; /* Postgres has a 64 byte limit on names, but this is sufficient for the core types listed here */
char name[64];
fupg_send_fn send;
fupg_recv_fn recv;
} fupg_core_type;
} fupg_type;
@ -132,9 +132,10 @@ SENDFN(char) {
fustr_write(out, buf, len);
}
/* Works for many text-based column types.
* Assumes client_encoding=utf8, will create a mess otherwise */
/* Works for many text-based column types, including receiving any value in the text format */
RECVFN(text) {
if (!is_c9strict_utf8_string((const U8*)buf, len))
fu_confess("Received invalid UTF-8 for type '%s' (oid %u)", ctx->name, ctx->oid);
return newSVpvn_utf8(buf, len, 1);
}
@ -248,7 +249,7 @@ SENDFN(jsonpath) {
Ordered by oid to support binary search.
(name is only used when formatting error messages, for now) */
#define CORETYPES \
#define BUILTINS \
B( 16, "bool", bool )\
B( 17, "bytea", bytea )\
B( 18, "char", char )\
@ -320,24 +321,28 @@ SENDFN(jsonpath) {
/* 5038 pg_snapshot */\
/* 5069 xid8 */
static const fupg_core_type fupg_core_types[] = {
static const fupg_type fupg_builtin[] = {
#define B(oid, name, fun) { oid, name"\0", fupg_send_##fun, fupg_recv_##fun },
CORETYPES
BUILTINS
#undef B
};
#undef CORETYPES
#undef BUILTINS
#define FUPG_CORE_TYPES (sizeof(fupg_core_types) / sizeof(fupg_core_type))
#define FUPG_BUILTIN (sizeof(fupg_builtin) / sizeof(fupg_type))
static const fupg_core_type *fupg_core_type_byoid(Oid oid) {
int i, b = 0, e = FUPG_CORE_TYPES-1;
static const fupg_type *fupg_type_byoid(const fupg_type *list, int len, Oid oid) {
int i, b = 0, e = len-1;
while (b <= e) {
i = b + (e - b)/2;
if (fupg_core_types[i].oid == oid) return fupg_core_types+i;
if (fupg_core_types[i].oid < oid) b = i+1;
if (list[i].oid == oid) return list+i;
if (list[i].oid < oid) b = i+1;
else e = i-1;
}
return NULL;
}
static const fupg_type *fupg_builtin_byoid(Oid oid) {
return fupg_type_byoid(fupg_builtin, FUPG_BUILTIN, oid);
}