+static Oid
+oidin_subr(const char *s, char **endloc)
+{
+ unsigned long cvt;
+ char *endptr;
+ Oid result;
+
+ if (*s == '\0')
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input syntax for type oid: \"%s\"",
+ s)));
+
+ errno = 0;
+ cvt = strtoul(s, &endptr, 10);
+
+ /*
+ * strtoul() normally only sets ERANGE. On some systems it also may set
+ * EINVAL, which simply means it couldn't parse the input string. This is
+ * handled by the second "if" consistent across platforms.
+ */
+ if (errno && errno != ERANGE && errno != EINVAL)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input syntax for type oid: \"%s\"",
+ s)));
+
+ if (endptr == s && *s != '\0')
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input syntax for type oid: \"%s\"",
+ s)));
+
+ if (errno == ERANGE)
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("value \"%s\" is out of range for type oid", s)));
+
+ if (endloc)
+ {
+ /* caller wants to deal with rest of string */
+ *endloc = endptr;
+ }
+ else
+ {
+ /* allow only whitespace after number */
+ while (*endptr && isspace((unsigned char) *endptr))
+ endptr++;
+ if (*endptr)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input syntax for type oid: \"%s\"",
+ s)));
+ }
+
+ result = (Oid) cvt;
+
+ /*
+ * Cope with possibility that unsigned long is wider than Oid, in which
+ * case strtoul will not raise an error for some values that are out of
+ * the range of Oid.
+ *
+ * For backwards compatibility, we want to accept inputs that are given
+ * with a minus sign, so allow the input value if it matches after either
+ * signed or unsigned extension to long.
+ *
+ * To ensure consistent results on 32-bit and 64-bit platforms, make sure
+ * the error message is the same as if strtoul() had returned ERANGE.
+ */
+#if OID_MAX != ULONG_MAX
+ if (cvt != (unsigned long) result &&
+ cvt != (unsigned long) ((int) result))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("value \"%s\" is out of range for type oid", s)));
+#endif
+
+ return result;
+}
+
+Datum
+oidin(PG_FUNCTION_ARGS)
+{
+ char *s = PG_GETARG_CSTRING(0);
+ Oid result;
+
+ result = oidin_subr(s, NULL);
+ PG_RETURN_OID(result);
+}
+
+Datum
+oidout(PG_FUNCTION_ARGS)
+{
+ Oid o = PG_GETARG_OID(0);
+ char *result = (char *) palloc(12);
+
+ snprintf(result, 12, "%u", o);
+ PG_RETURN_CSTRING(result);
+}
+
+/*
+ * oidrecv - converts external binary format to oid
+ */
+Datum
+oidrecv(PG_FUNCTION_ARGS)
+{
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+
+ PG_RETURN_OID((Oid) pq_getmsgint(buf, sizeof(Oid)));
+}
+