* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.61 2002/03/06 20:34:54 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.67 2002/03/29 19:06:15 tgl Exp $
*
* NOTES
* Eventually, the index information should go through here, too.
#include "catalog/pg_shadow.h"
#include "catalog/pg_statistic.h"
#include "catalog/pg_type.h"
-#include "parser/parse_coerce.h"
+#include "nodes/makefuncs.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
/* ---------- RELATION CACHE ---------- */
+/*
+ * get_relname_relid
+ * Given name and namespace of a relation, look up the OID.
+ *
+ * Returns InvalidOid if there is no such relation.
+ */
+Oid
+get_relname_relid(const char *relname, Oid relnamespace)
+{
+ return GetSysCacheOid(RELNAMENSP,
+ PointerGetDatum(relname),
+ ObjectIdGetDatum(relnamespace),
+ 0, 0);
+}
+
#ifdef NOT_USED
/*
* get_relnatts
/*
* get_rel_name
- *
* Returns the name of a given relation.
*
- * Note: returns a palloc'd copy of the string, or NULL if no such relation.
+ * Returns a palloc'd copy of the string, or NULL if no such relation.
+ *
+ * NOTE: since relation name is not unique, be wary of code that uses this
+ * for anything except preparing error messages.
*/
char *
get_rel_name(Oid relid)
return NULL;
}
+/*
+ * get_rel_type_id
+ *
+ * Returns the pg_type OID associated with a given relation.
+ *
+ * Note: not all pg_class entries have associated pg_type OIDs; so be
+ * careful to check for InvalidOid result.
+ */
+Oid
+get_rel_type_id(Oid relid)
+{
+ HeapTuple tp;
+
+ tp = SearchSysCache(RELOID,
+ ObjectIdGetDatum(relid),
+ 0, 0, 0);
+ if (HeapTupleIsValid(tp))
+ {
+ Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
+ Oid result;
+
+ result = reltup->reltype;
+ ReleaseSysCache(tp);
+ return result;
+ }
+ else
+ return InvalidOid;
+}
+
/* ---------- TYPE CACHE ---------- */
/*
+ * get_typisdefined
+ *
+ * Given the type OID, determine whether the type is defined
+ * (if not, it's only a shell).
+ */
+bool
+get_typisdefined(Oid typid)
+{
+ HeapTuple tp;
+
+ tp = SearchSysCache(TYPEOID,
+ ObjectIdGetDatum(typid),
+ 0, 0, 0);
+ if (HeapTupleIsValid(tp))
+ {
+ Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
+ bool result;
+
+ result = typtup->typisdefined;
+ ReleaseSysCache(tp);
+ return result;
+ }
+ else
+ return false;
+}
+
+/*
* get_typlen
*
* Given the type OID, return the length of the type.
/*
* get_typdefault
- *
* Given a type OID, return the type's default value, if any.
- * Returns FALSE if there is no default (effectively, default is NULL).
- * The result points to palloc'd storage for pass-by-reference types.
+ *
+ * The result is a palloc'd expression node tree, or NULL if there
+ * is no defined default for the datatype.
+ *
+ * NB: caller should be prepared to coerce result to correct datatype;
+ * the returned expression tree might produce something of the wrong type.
*/
Node *
-get_typdefault(Oid typid, int32 atttypmod)
+get_typdefault(Oid typid)
{
HeapTuple typeTuple;
Form_pg_type type;
- Oid typinput;
- Oid typbasetype;
- char typtype;
Datum datum;
bool isNull;
Node *expr;
typeTuple = SearchSysCache(TYPEOID,
ObjectIdGetDatum(typid),
0, 0, 0);
-
if (!HeapTupleIsValid(typeTuple))
elog(ERROR, "get_typdefault: failed to lookup type %u", typid);
-
type = (Form_pg_type) GETSTRUCT(typeTuple);
- typinput = type->typinput;
- typbasetype = type->typbasetype;
- typtype = type->typtype;
-
/*
- * typdefaultbin is potentially null, so don't try to access it as a
- * struct field. Must do it the hard way with SysCacheGetAttr.
+ * typdefault and typdefaultbin are potentially null, so don't try to
+ * access 'em as struct fields. Must do it the hard way with
+ * SysCacheGetAttr.
*/
datum = SysCacheGetAttr(TYPEOID,
typeTuple,
Anum_pg_type_typdefaultbin,
&isNull);
- ReleaseSysCache(typeTuple);
- if (isNull)
- return (Node *) NULL;
+ if (!isNull)
+ {
+ /* We have an expression default */
+ expr = stringToNode(DatumGetCString(DirectFunctionCall1(textout,
+ datum)));
+ }
+ else
+ {
+ /* Perhaps we have a plain literal default */
+ datum = SysCacheGetAttr(TYPEOID,
+ typeTuple,
+ Anum_pg_type_typdefault,
+ &isNull);
- /* Convert Datum to a Node */
- expr = stringToNode(DatumGetCString(
- DirectFunctionCall1(textout, datum)));
+ if (!isNull)
+ {
+ char *strDefaultVal;
+
+ /* Convert text datum to C string */
+ strDefaultVal = DatumGetCString(DirectFunctionCall1(textout,
+ datum));
+ /* Convert C string to a value of the given type */
+ datum = OidFunctionCall3(type->typinput,
+ CStringGetDatum(strDefaultVal),
+ ObjectIdGetDatum(type->typelem),
+ Int32GetDatum(-1));
+ /* Build a Const node containing the value */
+ expr = (Node *) makeConst(typid,
+ type->typlen,
+ datum,
+ false,
+ type->typbyval,
+ false, /* not a set */
+ false);
+ pfree(strDefaultVal);
+ }
+ else
+ {
+ /* No default */
+ expr = NULL;
+ }
+ }
+ ReleaseSysCache(typeTuple);
+ return expr;
+}
+
+/*
+ * getBaseType
+ * If the given type is a domain, return its base type;
+ * otherwise return the type's own OID.
+ */
+Oid
+getBaseType(Oid typid)
+{
/*
- * Ensure we goto the basetype before the domain type.
- *
- * Prevents scenarios like the below from failing:
- * CREATE DOMAIN dom text DEFAULT random();
- *
+ * We loop to find the bottom base type in a stack of domains.
*/
- if (typbasetype != InvalidOid) {
- expr = coerce_type(NULL, expr, typid,
- typbasetype, atttypmod);
- }
+ for (;;)
+ {
+ HeapTuple tup;
+ Form_pg_type typTup;
+
+ tup = SearchSysCache(TYPEOID,
+ ObjectIdGetDatum(typid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "getBaseType: failed to lookup type %u", typid);
+ typTup = (Form_pg_type) GETSTRUCT(tup);
+ if (typTup->typtype != 'd')
+ {
+ /* Not a domain, so done */
+ ReleaseSysCache(tup);
+ break;
+ }
+ typid = typTup->typbasetype;
+ ReleaseSysCache(tup);
+ }
- return expr;
+ return typid;
}
/*