domain_state_setup(Oid domainType, bool binary, MemoryContext mcxt)
{
DomainIOData *my_extra;
+ TypeCacheEntry *typentry;
Oid baseType;
my_extra = (DomainIOData *) MemoryContextAlloc(mcxt, sizeof(DomainIOData));
- /* Find out the base type */
- my_extra->typtypmod = -1;
- baseType = getBaseTypeAndTypmod(domainType, &my_extra->typtypmod);
- if (baseType == domainType)
+ /*
+ * Verify that domainType represents a valid domain type. We need to be
+ * careful here because domain_in and domain_recv can be called from SQL,
+ * possibly with incorrect arguments. We use lookup_type_cache mainly
+ * because it will throw a clean user-facing error for a bad OID.
+ */
+ typentry = lookup_type_cache(domainType, 0);
+ if (typentry->typtype != TYPTYPE_DOMAIN)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("type %s is not a domain",
format_type_be(domainType))));
+ /* Find out the base type */
+ my_extra->typtypmod = -1;
+ baseType = getBaseTypeAndTypmod(domainType, &my_extra->typtypmod);
+
/* Look up underlying I/O function */
if (binary)
getTypeBinaryInputInfo(baseType,
* Fetch the type cache entry for the specified datatype, and make sure that
* all the fields requested by bits in 'flags' are valid.
*
- * The result is never NULL --- we will elog() if the passed type OID is
+ * The result is never NULL --- we will ereport() if the passed type OID is
* invalid. Note however that we may fail to find one or more of the
- * requested opclass-dependent fields; the caller needs to check whether
- * the fields are InvalidOid or not.
+ * values requested by 'flags'; the caller needs to check whether the fields
+ * are InvalidOid or not.
*/
TypeCacheEntry *
lookup_type_cache(Oid type_id, int flags)
/*
* If we didn't find one, we want to make one. But first look up the
* pg_type row, just to make sure we don't make a cache entry for an
- * invalid type OID.
+ * invalid type OID. If the type OID is not valid, present a
+ * user-facing error, since some code paths such as domain_in() allow
+ * this function to be reached with a user-supplied OID.
*/
HeapTuple tp;
Form_pg_type typtup;
tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_id));
if (!HeapTupleIsValid(tp))
- elog(ERROR, "cache lookup failed for type %u", type_id);
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("type with OID %u does not exist", type_id)));
typtup = (Form_pg_type) GETSTRUCT(tp);
if (!typtup->typisdefined)
ereport(ERROR,
*
* Given a typeid/typmod that should describe a known composite type,
* return the tuple descriptor for the type. Will ereport on failure.
+ * (Use ereport because this is reachable with user-specified OIDs,
+ * for example from record_in().)
*
* Note: on success, we increment the refcount of the returned TupleDesc,
* and log the reference in CurrentResourceOwner. Caller should call
Form_pg_language langStruct;
AclResult aclresult;
- /* Get the function's pg_proc entry */
+ /*
+ * Get the function's pg_proc entry. Throw a user-facing error for bad
+ * OID, because validators can be called with user-specified OIDs.
+ */
procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(functionOid));
if (!HeapTupleIsValid(procTup))
- elog(ERROR, "cache lookup failed for function %u", functionOid);
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("function with OID %u does not exist", functionOid)));
procStruct = (Form_pg_proc) GETSTRUCT(procTup);
/*