From 4cb2b9a15401501f3fb93ac9ef6cab69b72a448f Mon Sep 17 00:00:00 2001 From: Andrew Dunstan Date: Tue, 4 Sep 2007 16:41:43 +0000 Subject: [PATCH] Provide for binary input/output of enums, to fix complaint from Merlin Moncure. This just provides text values, we're not exposing the underlying Oid representation. Catalog version bumped. --- src/backend/commands/typecmds.c | 4 +- src/backend/utils/adt/enum.c | 69 ++++++++++++++++++++++++++++++++ src/include/catalog/catversion.h | 2 +- src/include/catalog/pg_proc.h | 2 + src/include/utils/builtins.h | 2 + 5 files changed, 76 insertions(+), 3 deletions(-) diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index cc52761ee8..08d24de1d4 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -1039,8 +1039,8 @@ DefineEnum(CreateEnumStmt *stmt) DEFAULT_TYPDELIM, /* array element delimiter */ F_ENUM_IN, /* input procedure */ F_ENUM_OUT, /* output procedure */ - InvalidOid, /* receive procedure - none */ - InvalidOid, /* send procedure - none */ + F_ENUM_RECV, /* receive procedure */ + F_ENUM_SEND, /* send procedure */ InvalidOid, /* typmodin procedure - none */ InvalidOid, /* typmodout procedure - none */ InvalidOid, /* analyze procedure - default */ diff --git a/src/backend/utils/adt/enum.c b/src/backend/utils/adt/enum.c index 57da560206..258a734c1f 100644 --- a/src/backend/utils/adt/enum.c +++ b/src/backend/utils/adt/enum.c @@ -19,6 +19,8 @@ #include "utils/builtins.h" #include "utils/lsyscache.h" #include "utils/syscache.h" +#include "libpq/pqformat.h" +#include "miscadmin.h" static ArrayType *enum_range_internal(Oid enumtypoid, Oid lower, Oid upper); @@ -86,6 +88,73 @@ enum_out(PG_FUNCTION_ARGS) PG_RETURN_CSTRING(result); } +/* Binary I/O support */ +Datum +enum_recv(PG_FUNCTION_ARGS) +{ + StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); + Oid enumtypoid = PG_GETARG_OID(1); + Oid enumoid; + HeapTuple tup; + char *name; + int nbytes; + + name = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes); + + /* must check length to prevent Assert failure within SearchSysCache */ + if (strlen(name) >= NAMEDATALEN) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input value for enum %s: \"%s\"", + format_type_be(enumtypoid), + name))); + + tup = SearchSysCache(ENUMTYPOIDNAME, + ObjectIdGetDatum(enumtypoid), + CStringGetDatum(name), + 0, 0); + if (!HeapTupleIsValid(tup)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input value for enum %s: \"%s\"", + format_type_be(enumtypoid), + name))); + + enumoid = HeapTupleGetOid(tup); + + ReleaseSysCache(tup); + + pfree(name); + + PG_RETURN_OID(enumoid); +} + +Datum +enum_send(PG_FUNCTION_ARGS) +{ + Oid enumval = PG_GETARG_OID(0); + StringInfoData buf; + HeapTuple tup; + Form_pg_enum en; + + tup = SearchSysCache(ENUMOID, + ObjectIdGetDatum(enumval), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), + errmsg("invalid internal value for enum: %u", + enumval))); + en = (Form_pg_enum) GETSTRUCT(tup); + + pq_begintypsend(&buf); + pq_sendtext(&buf, NameStr(en->enumlabel), strlen(NameStr(en->enumlabel))); + + ReleaseSysCache(tup); + + PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); +} + /* Comparison functions and related */ Datum diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 0094f52289..400c73e8ab 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200709021 +#define CATALOG_VERSION_NO 200709041 #endif diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 80fa8474b1..617b0cdab9 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -4136,6 +4136,8 @@ DATA(insert OID = 3528 ( enum_first PGNSP PGUID 12 1 0 f f f f s 1 3500 "3500" DATA(insert OID = 3529 ( enum_last PGNSP PGUID 12 1 0 f f f f s 1 3500 "3500" _null_ _null_ _null_ enum_last - _null_ _null_ )); DATA(insert OID = 3530 ( enum_range PGNSP PGUID 12 1 0 f f f f s 2 2277 "3500 3500" _null_ _null_ _null_ enum_range_bounds - _null_ _null_ )); DATA(insert OID = 3531 ( enum_range PGNSP PGUID 12 1 0 f f f f s 1 2277 "3500" _null_ _null_ _null_ enum_range_all - _null_ _null_ )); +DATA(insert OID = 3532 ( enum_recv PGNSP PGUID 12 1 0 f f t f s 2 3500 "2275 26" _null_ _null_ _null_ enum_recv - _null_ _null_ )); +DATA(insert OID = 3533 ( enum_send PGNSP PGUID 12 1 0 f f t f s 1 17 "3500" _null_ _null_ _null_ enum_send - _null_ _null_ )); /* text search stuff */ DATA(insert OID = 3610 ( tsvectorin PGNSP PGUID 12 1 0 f f t f i 1 3614 "2275" _null_ _null_ _null_ tsvectorin - _null_ _null_ )); diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index fb46ec1d71..13862d08a9 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -107,6 +107,8 @@ extern Datum domain_recv(PG_FUNCTION_ARGS); /* enum.c */ extern Datum enum_in(PG_FUNCTION_ARGS); extern Datum enum_out(PG_FUNCTION_ARGS); +extern Datum enum_recv(PG_FUNCTION_ARGS); +extern Datum enum_send(PG_FUNCTION_ARGS); extern Datum enum_lt(PG_FUNCTION_ARGS); extern Datum enum_le(PG_FUNCTION_ARGS); extern Datum enum_eq(PG_FUNCTION_ARGS); -- 2.39.5