aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils')
-rw-r--r--src/backend/utils/adt/acl.c18
-rw-r--r--src/backend/utils/adt/arrayfuncs.c9
-rw-r--r--src/backend/utils/adt/format_type.c18
-rw-r--r--src/backend/utils/adt/regproc.c20
-rw-r--r--src/backend/utils/adt/ri_triggers.c18
-rw-r--r--src/backend/utils/adt/ruleutils.c98
-rw-r--r--src/backend/utils/adt/selfuncs.c56
-rw-r--r--src/backend/utils/adt/sets.c40
-rw-r--r--src/backend/utils/cache/catcache.c391
-rw-r--r--src/backend/utils/cache/lsyscache.c349
-rw-r--r--src/backend/utils/cache/syscache.c187
-rw-r--r--src/backend/utils/cache/temprel.c3
-rw-r--r--src/backend/utils/fmgr/dfmgr.c10
-rw-r--r--src/backend/utils/fmgr/fmgr.c20
-rw-r--r--src/backend/utils/init/miscinit.c23
-rw-r--r--src/backend/utils/init/postinit.c7
-rw-r--r--src/backend/utils/misc/superuser.c18
-rw-r--r--src/backend/utils/sort/tuplesort.c12
18 files changed, 738 insertions, 559 deletions
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index 1a2b2ef953e..a8bc5e349a3 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.52 2000/11/03 19:01:36 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.53 2000/11/16 22:30:31 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -174,12 +174,13 @@ aclparse(char *s, AclItem *aip, unsigned *modechg)
switch (aip->ai_idtype)
{
case ACL_IDTYPE_UID:
- htup = SearchSysCacheTuple(SHADOWNAME,
- PointerGetDatum(name),
- 0, 0, 0);
+ htup = SearchSysCache(SHADOWNAME,
+ PointerGetDatum(name),
+ 0, 0, 0);
if (!HeapTupleIsValid(htup))
elog(ERROR, "aclparse: non-existent user \"%s\"", name);
aip->ai_id = ((Form_pg_shadow) GETSTRUCT(htup))->usesysid;
+ ReleaseSysCache(htup);
break;
case ACL_IDTYPE_GID:
aip->ai_id = get_grosysid(name);
@@ -272,9 +273,9 @@ aclitemout(PG_FUNCTION_ARGS)
switch (aip->ai_idtype)
{
case ACL_IDTYPE_UID:
- htup = SearchSysCacheTuple(SHADOWSYSID,
- ObjectIdGetDatum(aip->ai_id),
- 0, 0, 0);
+ htup = SearchSysCache(SHADOWSYSID,
+ ObjectIdGetDatum(aip->ai_id),
+ 0, 0, 0);
if (!HeapTupleIsValid(htup))
{
/* Generate numeric UID if we don't find an entry */
@@ -286,9 +287,12 @@ aclitemout(PG_FUNCTION_ARGS)
pfree(tmp);
}
else
+ {
strncat(p, (char *) &((Form_pg_shadow)
GETSTRUCT(htup))->usename,
sizeof(NameData));
+ ReleaseSysCache(htup);
+ }
break;
case ACL_IDTYPE_GID:
strcat(p, "group ");
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 44f58840c36..47c1b814c4d 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.65 2000/11/14 23:28:13 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.66 2000/11/16 22:30:31 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1590,9 +1590,9 @@ system_cache_lookup(Oid element_type,
HeapTuple typeTuple;
Form_pg_type typeStruct;
- typeTuple = SearchSysCacheTuple(TYPEOID,
- ObjectIdGetDatum(element_type),
- 0, 0, 0);
+ typeTuple = SearchSysCache(TYPEOID,
+ ObjectIdGetDatum(element_type),
+ 0, 0, 0);
if (!HeapTupleIsValid(typeTuple))
elog(ERROR, "array_out: Cache lookup failed for type %u",
element_type);
@@ -1607,6 +1607,7 @@ system_cache_lookup(Oid element_type,
*proc = typeStruct->typinput;
else
*proc = typeStruct->typoutput;
+ ReleaseSysCache(typeTuple);
}
/*
diff --git a/src/backend/utils/adt/format_type.c b/src/backend/utils/adt/format_type.c
index f32122173d8..6022dc78519 100644
--- a/src/backend/utils/adt/format_type.c
+++ b/src/backend/utils/adt/format_type.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.5 2000/08/26 21:53:41 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.6 2000/11/16 22:30:31 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -98,9 +98,9 @@ format_type_internal(Oid type_oid, int32 typemod)
if (type_oid == InvalidOid)
return pstrdup("-");
- tuple = SearchSysCacheTuple(TYPEOID, ObjectIdGetDatum(type_oid),
- 0, 0, 0);
-
+ tuple = SearchSysCache(TYPEOID,
+ ObjectIdGetDatum(type_oid),
+ 0, 0, 0);
if (!HeapTupleIsValid(tuple))
return pstrdup("???");
@@ -108,9 +108,11 @@ format_type_internal(Oid type_oid, int32 typemod)
typlen = ((Form_pg_type) GETSTRUCT(tuple))->typlen;
if (array_base_type != 0 && typlen < 0)
{
- tuple = SearchSysCacheTuple(TYPEOID,
- ObjectIdGetDatum(array_base_type),
- 0, 0, 0);
+ /* Switch our attention to the array element type */
+ ReleaseSysCache(tuple);
+ tuple = SearchSysCache(TYPEOID,
+ ObjectIdGetDatum(array_base_type),
+ 0, 0, 0);
if (!HeapTupleIsValid(tuple))
return pstrdup("???[]");
is_array = true;
@@ -211,6 +213,8 @@ format_type_internal(Oid type_oid, int32 typemod)
if (is_array)
buf = psnprintf(strlen(buf) + 3, "%s[]", buf);
+ ReleaseSysCache(tuple);
+
return buf;
}
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c
index 84c4694115d..4a2bb3c4fd6 100644
--- a/src/backend/utils/adt/regproc.c
+++ b/src/backend/utils/adt/regproc.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.58 2000/07/09 21:30:12 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.59 2000/11/16 22:30:31 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -55,13 +55,12 @@ regprocin(PG_FUNCTION_ARGS)
if (pro_name_or_oid[0] >= '0' &&
pro_name_or_oid[0] <= '9')
{
- proctup = SearchSysCacheTuple(PROCOID,
- DirectFunctionCall1(oidin,
+ result = (RegProcedure)
+ GetSysCacheOid(PROCOID,
+ DirectFunctionCall1(oidin,
CStringGetDatum(pro_name_or_oid)),
- 0, 0, 0);
- if (HeapTupleIsValid(proctup))
- result = (RegProcedure) proctup->t_data->t_oid;
- else
+ 0, 0, 0);
+ if (!RegProcedureIsValid(result))
elog(ERROR, "No procedure with oid %s", pro_name_or_oid);
}
else
@@ -176,9 +175,9 @@ regprocout(PG_FUNCTION_ARGS)
if (!IsBootstrapProcessingMode())
{
- proctup = SearchSysCacheTuple(PROCOID,
- ObjectIdGetDatum(proid),
- 0, 0, 0);
+ proctup = SearchSysCache(PROCOID,
+ ObjectIdGetDatum(proid),
+ 0, 0, 0);
if (HeapTupleIsValid(proctup))
{
@@ -186,6 +185,7 @@ regprocout(PG_FUNCTION_ARGS)
s = NameStr(((Form_pg_proc) GETSTRUCT(proctup))->proname);
StrNCpy(result, s, NAMEDATALEN);
+ ReleaseSysCache(proctup);
}
else
{
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index 723adcda35c..5bfea0ff42f 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -6,7 +6,7 @@
*
* 1999 Jan Wieck
*
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.17 2000/09/25 22:34:20 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.18 2000/11/16 22:30:31 tgl Exp $
*
* ----------
*/
@@ -3300,24 +3300,26 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue)
HeapTuple opr_tup;
Form_pg_operator opr_struct;
- opr_tup = SearchSysCacheTuple(OPERNAME,
- PointerGetDatum("="),
- ObjectIdGetDatum(typeid),
- ObjectIdGetDatum(typeid),
- CharGetDatum('b'));
-
+ opr_tup = SearchSysCache(OPERNAME,
+ PointerGetDatum("="),
+ ObjectIdGetDatum(typeid),
+ ObjectIdGetDatum(typeid),
+ CharGetDatum('b'));
if (!HeapTupleIsValid(opr_tup))
elog(ERROR, "ri_AttributesEqual(): cannot find '=' operator "
"for type %u", typeid);
opr_struct = (Form_pg_operator) GETSTRUCT(opr_tup);
entry = (RI_OpreqHashEntry *) hash_search(ri_opreq_cache,
- (char *) &typeid, HASH_ENTER, &found);
+ (char *) &typeid,
+ HASH_ENTER,
+ &found);
if (entry == NULL)
elog(FATAL, "can't insert into RI operator cache");
entry->typeid = typeid;
fmgr_info(opr_struct->oprcode, &(entry->oprfmgrinfo));
+ ReleaseSysCache(opr_tup);
}
/* ----------
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index cc25a5a026a..3cd543b5e68 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -3,7 +3,7 @@
* back to source text
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.68 2000/11/05 00:15:53 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.69 2000/11/16 22:30:31 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -374,8 +374,9 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
* Fetch the pg_index tuple by the Oid of the index
* ----------
*/
- ht_idx = SearchSysCacheTuple(INDEXRELID,
- ObjectIdGetDatum(indexrelid), 0, 0, 0);
+ ht_idx = SearchSysCache(INDEXRELID,
+ ObjectIdGetDatum(indexrelid),
+ 0, 0, 0);
if (!HeapTupleIsValid(ht_idx))
elog(ERROR, "syscache lookup for index %u failed", indexrelid);
idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
@@ -384,8 +385,9 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
* Fetch the pg_class tuple of the index relation
* ----------
*/
- ht_idxrel = SearchSysCacheTuple(RELOID,
- ObjectIdGetDatum(idxrec->indexrelid), 0, 0, 0);
+ ht_idxrel = SearchSysCache(RELOID,
+ ObjectIdGetDatum(idxrec->indexrelid),
+ 0, 0, 0);
if (!HeapTupleIsValid(ht_idxrel))
elog(ERROR, "syscache lookup for relid %u failed", idxrec->indexrelid);
idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
@@ -394,8 +396,9 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
* Fetch the pg_class tuple of the indexed relation
* ----------
*/
- ht_indrel = SearchSysCacheTuple(RELOID,
- ObjectIdGetDatum(idxrec->indrelid), 0, 0, 0);
+ ht_indrel = SearchSysCache(RELOID,
+ ObjectIdGetDatum(idxrec->indrelid),
+ 0, 0, 0);
if (!HeapTupleIsValid(ht_indrel))
elog(ERROR, "syscache lookup for relid %u failed", idxrec->indrelid);
indrelrec = (Form_pg_class) GETSTRUCT(ht_indrel);
@@ -484,12 +487,13 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
HeapTuple proctup;
Form_pg_proc procStruct;
- proctup = SearchSysCacheTuple(PROCOID,
- ObjectIdGetDatum(idxrec->indproc), 0, 0, 0);
+ proctup = SearchSysCache(PROCOID,
+ ObjectIdGetDatum(idxrec->indproc),
+ 0, 0, 0);
if (!HeapTupleIsValid(proctup))
elog(ERROR, "cache lookup for proc %u failed", idxrec->indproc);
-
procStruct = (Form_pg_proc) GETSTRUCT(proctup);
+
appendStringInfo(&buf, "%s(%s) ",
quote_identifier(pstrdup(NameStr(procStruct->proname))),
keybuf.data);
@@ -508,6 +512,7 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
appendStringInfo(&buf, "%s",
quote_identifier(SPI_getvalue(spi_tup, spi_ttc,
spi_fno)));
+ ReleaseSysCache(proctup);
}
else
/* ----------
@@ -523,15 +528,19 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
appendStringInfo(&buf, ")");
/* ----------
- * Create the result in upper executor memory
+ * Create the result in upper executor memory, and free objects
* ----------
*/
len = buf.len + VARHDRSZ;
indexdef = SPI_palloc(len);
VARATT_SIZEP(indexdef) = len;
memcpy(VARDATA(indexdef), buf.data, buf.len);
+
pfree(buf.data);
pfree(keybuf.data);
+ ReleaseSysCache(ht_idx);
+ ReleaseSysCache(ht_idxrel);
+ ReleaseSysCache(ht_indrel);
/* ----------
* Disconnect from SPI manager
@@ -568,13 +577,14 @@ pg_get_userbyid(PG_FUNCTION_ARGS)
* Get the pg_shadow entry and print the result
* ----------
*/
- usertup = SearchSysCacheTuple(SHADOWSYSID,
- ObjectIdGetDatum(uid),
- 0, 0, 0);
+ usertup = SearchSysCache(SHADOWSYSID,
+ ObjectIdGetDatum(uid),
+ 0, 0, 0);
if (HeapTupleIsValid(usertup))
{
user_rec = (Form_pg_shadow) GETSTRUCT(usertup);
StrNCpy(NameStr(*result), NameStr(user_rec->usename), NAMEDATALEN);
+ ReleaseSysCache(usertup);
}
else
sprintf(NameStr(*result), "unknown (UID=%d)", uid);
@@ -1392,10 +1402,11 @@ get_rule_expr(Node *node, deparse_context *context)
HeapTuple tp;
Form_pg_operator optup;
- tp = SearchSysCacheTuple(OPEROID,
- ObjectIdGetDatum(opno),
- 0, 0, 0);
- Assert(HeapTupleIsValid(tp));
+ tp = SearchSysCache(OPEROID,
+ ObjectIdGetDatum(opno),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tp))
+ elog(ERROR, "cache lookup for operator %u failed", opno);
optup = (Form_pg_operator) GETSTRUCT(tp);
switch (optup->oprkind)
{
@@ -1414,6 +1425,7 @@ get_rule_expr(Node *node, deparse_context *context)
default:
elog(ERROR, "get_rule_expr: bogus oprkind");
}
+ ReleaseSysCache(tp);
}
appendStringInfoChar(buf, ')');
break;
@@ -1524,9 +1536,9 @@ get_rule_expr(Node *node, deparse_context *context)
/* we do NOT parenthesize the arg expression, for now */
get_rule_expr(fselect->arg, context);
- typetup = SearchSysCacheTuple(TYPEOID,
- ObjectIdGetDatum(exprType(fselect->arg)),
- 0, 0, 0);
+ typetup = SearchSysCache(TYPEOID,
+ ObjectIdGetDatum(exprType(fselect->arg)),
+ 0, 0, 0);
if (!HeapTupleIsValid(typetup))
elog(ERROR, "cache lookup of type %u failed",
exprType(fselect->arg));
@@ -1538,6 +1550,7 @@ get_rule_expr(Node *node, deparse_context *context)
fieldname = get_relid_attribute_name(typrelid,
fselect->fieldnum);
appendStringInfo(buf, ".%s", quote_identifier(fieldname));
+ ReleaseSysCache(typetup);
}
break;
@@ -1550,9 +1563,9 @@ get_rule_expr(Node *node, deparse_context *context)
appendStringInfoChar(buf, '(');
get_rule_expr(relabel->arg, context);
- typetup = SearchSysCacheTuple(TYPEOID,
+ typetup = SearchSysCache(TYPEOID,
ObjectIdGetDatum(relabel->resulttype),
- 0, 0, 0);
+ 0, 0, 0);
if (!HeapTupleIsValid(typetup))
elog(ERROR, "cache lookup of type %u failed",
relabel->resulttype);
@@ -1560,6 +1573,7 @@ get_rule_expr(Node *node, deparse_context *context)
extval = pstrdup(NameStr(typeStruct->typname));
appendStringInfo(buf, ")::%s", quote_identifier(extval));
pfree(extval);
+ ReleaseSysCache(typetup);
}
break;
@@ -1616,14 +1630,14 @@ get_func_expr(Expr *expr, deparse_context *context)
/*
* Get the functions pg_proc tuple
*/
- proctup = SearchSysCacheTuple(PROCOID,
- ObjectIdGetDatum(func->funcid),
- 0, 0, 0);
+ proctup = SearchSysCache(PROCOID,
+ ObjectIdGetDatum(func->funcid),
+ 0, 0, 0);
if (!HeapTupleIsValid(proctup))
elog(ERROR, "cache lookup for proc %u failed", func->funcid);
procStruct = (Form_pg_proc) GETSTRUCT(proctup);
- proname = pstrdup(NameStr(procStruct->proname));
+ proname = NameStr(procStruct->proname);
/*
* nullvalue() and nonnullvalue() should get turned into special
@@ -1636,6 +1650,7 @@ get_func_expr(Expr *expr, deparse_context *context)
appendStringInfoChar(buf, '(');
get_rule_expr((Node *) lfirst(expr->args), context);
appendStringInfo(buf, " ISNULL)");
+ ReleaseSysCache(proctup);
return;
}
if (strcmp(proname, "nonnullvalue") == 0)
@@ -1643,6 +1658,7 @@ get_func_expr(Expr *expr, deparse_context *context)
appendStringInfoChar(buf, '(');
get_rule_expr((Node *) lfirst(expr->args), context);
appendStringInfo(buf, " NOTNULL)");
+ ReleaseSysCache(proctup);
return;
}
}
@@ -1657,8 +1673,9 @@ get_func_expr(Expr *expr, deparse_context *context)
/*
* Strip off any RelabelType on the input, so we don't print
- * redundancies like x::bpchar::char(8). XXX Are there any cases
- * where this is a bad idea?
+ * redundancies like x::bpchar::char(8).
+ *
+ * XXX Are there any cases where this is a bad idea?
*/
if (IsA(arg, RelabelType))
arg = ((RelabelType *) arg)->arg;
@@ -1696,6 +1713,8 @@ get_func_expr(Expr *expr, deparse_context *context)
}
else
appendStringInfo(buf, "%s", quote_identifier(proname));
+
+ ReleaseSysCache(proctup);
return;
}
@@ -1711,6 +1730,8 @@ get_func_expr(Expr *expr, deparse_context *context)
get_rule_expr((Node *) lfirst(l), context);
}
appendStringInfoChar(buf, ')');
+
+ ReleaseSysCache(proctup);
}
@@ -1766,9 +1787,9 @@ get_const_expr(Const *constval, deparse_context *context)
char *extval;
char *valptr;
- typetup = SearchSysCacheTuple(TYPEOID,
- ObjectIdGetDatum(constval->consttype),
- 0, 0, 0);
+ typetup = SearchSysCache(TYPEOID,
+ ObjectIdGetDatum(constval->consttype),
+ 0, 0, 0);
if (!HeapTupleIsValid(typetup))
elog(ERROR, "cache lookup of type %u failed", constval->consttype);
@@ -1785,6 +1806,7 @@ get_const_expr(Const *constval, deparse_context *context)
extval = pstrdup(NameStr(typeStruct->typname));
appendStringInfo(buf, "NULL::%s", quote_identifier(extval));
pfree(extval);
+ ReleaseSysCache(typetup);
return;
}
@@ -1843,6 +1865,8 @@ get_const_expr(Const *constval, deparse_context *context)
pfree(extval);
break;
}
+
+ ReleaseSysCache(typetup);
}
@@ -2198,14 +2222,18 @@ get_relation_name(Oid relid)
{
HeapTuple classtup;
Form_pg_class classStruct;
+ char *result;
- classtup = SearchSysCacheTuple(RELOID,
- ObjectIdGetDatum(relid), 0, 0, 0);
+ classtup = SearchSysCache(RELOID,
+ ObjectIdGetDatum(relid),
+ 0, 0, 0);
if (!HeapTupleIsValid(classtup))
elog(ERROR, "cache lookup of relation %u failed", relid);
classStruct = (Form_pg_class) GETSTRUCT(classtup);
- return pstrdup(NameStr(classStruct->relname));
+ result = pstrdup(NameStr(classStruct->relname));
+ ReleaseSysCache(classtup);
+ return result;
}
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 818bc6ab082..63e4d9b46d2 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.81 2000/11/10 09:38:21 inoue Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.82 2000/11/16 22:30:31 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -324,12 +324,15 @@ scalarltsel(PG_FUNCTION_ARGS)
* Get left and right datatypes of the operator so we know what
* type the constant is.
*/
- oprtuple = get_operator_tuple(opid);
+ oprtuple = SearchSysCache(OPEROID,
+ ObjectIdGetDatum(opid),
+ 0, 0, 0);
if (!HeapTupleIsValid(oprtuple))
elog(ERROR, "scalarltsel: no tuple for operator %u", opid);
ltype = ((Form_pg_operator) GETSTRUCT(oprtuple))->oprleft;
rtype = ((Form_pg_operator) GETSTRUCT(oprtuple))->oprright;
contype = (flag & SEL_RIGHT) ? rtype : ltype;
+ ReleaseSysCache(oprtuple);
/* Now get info and stats about the attribute */
getattproperties(relid, attno,
@@ -482,11 +485,14 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
* Get left and right datatypes of the operator so we know what
* type the attribute is.
*/
- oprtuple = get_operator_tuple(opid);
+ oprtuple = SearchSysCache(OPEROID,
+ ObjectIdGetDatum(opid),
+ 0, 0, 0);
if (!HeapTupleIsValid(oprtuple))
elog(ERROR, "patternsel: no tuple for operator %u", opid);
ltype = ((Form_pg_operator) GETSTRUCT(oprtuple))->oprleft;
rtype = ((Form_pg_operator) GETSTRUCT(oprtuple))->oprright;
+ ReleaseSysCache(oprtuple);
/* the right-hand const is type text for all supported operators */
Assert(rtype == TEXTOID);
@@ -1189,10 +1195,10 @@ getattproperties(Oid relid, AttrNumber attnum,
HeapTuple atp;
Form_pg_attribute att_tup;
- atp = SearchSysCacheTuple(ATTNUM,
- ObjectIdGetDatum(relid),
- Int16GetDatum(attnum),
- 0, 0);
+ atp = SearchSysCache(ATTNUM,
+ ObjectIdGetDatum(relid),
+ Int16GetDatum(attnum),
+ 0, 0);
if (!HeapTupleIsValid(atp))
elog(ERROR, "getattproperties: no attribute tuple %u %d",
relid, (int) attnum);
@@ -1202,6 +1208,8 @@ getattproperties(Oid relid, AttrNumber attnum,
*typlen = att_tup->attlen;
*typbyval = att_tup->attbyval;
*typmod = att_tup->atttypmod;
+
+ ReleaseSysCache(atp);
}
/*
@@ -1250,11 +1258,10 @@ getattstatistics(Oid relid,
* have at hand! (For example, we might have a '>' operator rather
* than the '<' operator that will appear in staop.)
*/
- tuple = SearchSysCacheTupleCopy(STATRELID,
- ObjectIdGetDatum(relid),
- Int16GetDatum((int16) attnum),
- 0,
- 0);
+ tuple = SearchSysCache(STATRELID,
+ ObjectIdGetDatum(relid),
+ Int16GetDatum((int16) attnum),
+ 0, 0);
if (!HeapTupleIsValid(tuple))
{
/* no such stats entry */
@@ -1267,14 +1274,15 @@ getattstatistics(Oid relid,
*commonfrac = ((Form_pg_statistic) GETSTRUCT(tuple))->stacommonfrac;
/* Get the type input proc for the column datatype */
- typeTuple = SearchSysCacheTuple(TYPEOID,
- ObjectIdGetDatum(typid),
- 0, 0, 0);
+ typeTuple = SearchSysCache(TYPEOID,
+ ObjectIdGetDatum(typid),
+ 0, 0, 0);
if (!HeapTupleIsValid(typeTuple))
elog(ERROR, "getattstatistics: Cache lookup failed for type %u",
typid);
fmgr_info(((Form_pg_type) GETSTRUCT(typeTuple))->typinput, &inputproc);
typelem = ((Form_pg_type) GETSTRUCT(typeTuple))->typelem;
+ ReleaseSysCache(typeTuple);
/*
* Values are variable-length fields, so cannot access as struct
@@ -1351,7 +1359,8 @@ getattstatistics(Oid relid,
pfree(strval);
}
}
- heap_freetuple(tuple);
+
+ ReleaseSysCache(tuple);
return true;
}
@@ -1966,16 +1975,11 @@ string_lessthan(const char *str1, const char *str2, Oid datatype)
static Oid
find_operator(const char *opname, Oid datatype)
{
- HeapTuple optup;
-
- optup = SearchSysCacheTuple(OPERNAME,
- PointerGetDatum(opname),
- ObjectIdGetDatum(datatype),
- ObjectIdGetDatum(datatype),
- CharGetDatum('b'));
- if (!HeapTupleIsValid(optup))
- return InvalidOid;
- return optup->t_data->t_oid;
+ return GetSysCacheOid(OPERNAME,
+ PointerGetDatum(opname),
+ ObjectIdGetDatum(datatype),
+ ObjectIdGetDatum(datatype),
+ CharGetDatum('b'));
}
/*
diff --git a/src/backend/utils/adt/sets.c b/src/backend/utils/adt/sets.c
index 9a5f05134cd..6f64847dcab 100644
--- a/src/backend/utils/adt/sets.c
+++ b/src/backend/utils/adt/sets.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.33 2000/08/24 03:29:06 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.34 2000/11/16 22:30:31 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -77,9 +77,11 @@ SetDefine(char *querystr, char *typename)
*/
CommandCounterIncrement();
- tup = SearchSysCacheTuple(PROCOID,
- ObjectIdGetDatum(setoid),
- 0, 0, 0);
+ procrel = heap_openr(ProcedureRelationName, RowExclusiveLock);
+
+ tup = SearchSysCache(PROCOID,
+ ObjectIdGetDatum(setoid),
+ 0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(ERROR, "SetDefine: unable to define set %s", querystr);
@@ -105,25 +107,15 @@ SetDefine(char *querystr, char *typename)
replNull[i] = ' ';
/* change the pg_proc tuple */
- procrel = heap_openr(ProcedureRelationName, RowExclusiveLock);
+ newtup = heap_modifytuple(tup,
+ procrel,
+ replValue,
+ replNull,
+ repl);
- tup = SearchSysCacheTuple(PROCOID,
- ObjectIdGetDatum(setoid),
- 0, 0, 0);
- if (HeapTupleIsValid(tup))
- {
- newtup = heap_modifytuple(tup,
- procrel,
- replValue,
- replNull,
- repl);
+ heap_update(procrel, &newtup->t_self, newtup, NULL);
- heap_update(procrel, &tup->t_self, newtup, NULL);
-
- setoid = newtup->t_data->t_oid;
- }
- else
- elog(ERROR, "SetDefine: could not find new set oid tuple");
+ setoid = newtup->t_data->t_oid;
if (RelationGetForm(procrel)->relhasindex)
{
@@ -133,9 +125,13 @@ SetDefine(char *querystr, char *typename)
CatalogIndexInsert(idescs, Num_pg_proc_indices, procrel, newtup);
CatalogCloseIndices(Num_pg_proc_indices, idescs);
}
- heap_close(procrel, RowExclusiveLock);
+ heap_freetuple(newtup);
}
+ ReleaseSysCache(tup);
+
+ heap_close(procrel, RowExclusiveLock);
+
return setoid;
}
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index 39e05d0fb09..3d8e7d80ba8 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.71 2000/11/10 00:33:10 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.72 2000/11/16 22:30:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -28,7 +28,8 @@
#include "utils/catcache.h"
#include "utils/syscache.h"
-static void CatCacheRemoveCTup(CatCache *cache, Dlelem *e);
+
+static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct);
static Index CatalogCacheComputeHashIndex(CatCache *cache,
ScanKey cur_skey);
static Index CatalogCacheComputeTupleHashIndex(CatCache *cache,
@@ -388,28 +389,17 @@ CatalogCacheComputeTupleHashIndex(CatCache *cache,
* --------------------------------
*/
static void
-CatCacheRemoveCTup(CatCache *cache, Dlelem *elt)
+CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
{
- CatCTup *ct;
- CatCTup *other_ct;
- Dlelem *other_elt;
-
- if (!elt) /* probably-useless safety check */
- return;
-
- /* We need to zap both linked-list elements as well as the tuple */
+ Assert(ct->refcount == 0);
- ct = (CatCTup *) DLE_VAL(elt);
- other_elt = ct->ct_node;
- other_ct = (CatCTup *) DLE_VAL(other_elt);
+ /* delink from linked lists */
+ DLRemove(&ct->lrulist_elem);
+ DLRemove(&ct->cache_elem);
- heap_freetuple(ct->ct_tup);
-
- DLRemove(other_elt);
- DLFreeElem(other_elt);
- pfree(other_ct);
- DLRemove(elt);
- DLFreeElem(elt);
+ /* free associated tuple data */
+ if (ct->tuple.t_data != NULL)
+ pfree(ct->tuple.t_data);
pfree(ct);
--cache->cc_ntup;
@@ -425,13 +415,11 @@ CatCacheRemoveCTup(CatCache *cache, Dlelem *elt)
* --------------------------------
*/
void
-CatalogCacheIdInvalidate(int cacheId, /* XXX */
+CatalogCacheIdInvalidate(int cacheId,
Index hashIndex,
ItemPointer pointer)
{
CatCache *ccp;
- CatCTup *ct;
- Dlelem *elt;
/* ----------------
* sanity checks
@@ -442,54 +430,101 @@ CatalogCacheIdInvalidate(int cacheId, /* XXX */
CACHE1_elog(DEBUG, "CatalogCacheIdInvalidate: called");
/* ----------------
- * inspect every cache that could contain the tuple
+ * inspect caches to find the proper cache
* ----------------
*/
for (ccp = Caches; ccp; ccp = ccp->cc_next)
{
+ Dlelem *elt,
+ *nextelt;
+
if (cacheId != ccp->id)
continue;
/* ----------------
* inspect the hash bucket until we find a match or exhaust
* ----------------
*/
- for (elt = DLGetHead(ccp->cc_cache[hashIndex]);
- elt;
- elt = DLGetSucc(elt))
+ for (elt = DLGetHead(&ccp->cc_cache[hashIndex]); elt; elt = nextelt)
{
- ct = (CatCTup *) DLE_VAL(elt);
- if (ItemPointerEquals(pointer, &ct->ct_tup->t_self))
- break;
- }
-
- /* ----------------
- * if we found a matching tuple, invalidate it.
- * ----------------
- */
+ CatCTup *ct = (CatCTup *) DLE_VAL(elt);
- if (elt)
- {
- CatCacheRemoveCTup(ccp, elt);
+ nextelt = DLGetSucc(elt);
- CACHE1_elog(DEBUG, "CatalogCacheIdInvalidate: invalidated");
+ if (ItemPointerEquals(pointer, &ct->tuple.t_self))
+ {
+ if (ct->refcount > 0)
+ ct->dead = true;
+ else
+ CatCacheRemoveCTup(ccp, ct);
+ CACHE1_elog(DEBUG, "CatalogCacheIdInvalidate: invalidated");
+ /* could be multiple matches, so keep looking! */
+ }
}
-
- if (cacheId != InvalidCatalogCacheId)
- break;
+ break; /* need only search this one cache */
}
}
/* ----------------------------------------------------------------
* public functions
*
+ * AtEOXact_CatCache
* ResetSystemCache
- * InitSysCache
- * SearchSysCache
+ * InitCatCache
+ * SearchCatCache
+ * ReleaseCatCache
* RelationInvalidateCatalogCacheTuple
* ----------------------------------------------------------------
*/
+
+
+/* --------------------------------
+ * AtEOXact_CatCache
+ *
+ * Clean up catcaches at end of transaction (either commit or abort)
+ *
+ * We scan the caches to reset refcounts to zero. This is of course
+ * necessary in the abort case, since elog() may have interrupted routines.
+ * In the commit case, any nonzero counts indicate failure to call
+ * ReleaseSysCache, so we put out a notice for debugging purposes.
+ * --------------------------------
+ */
+void
+AtEOXact_CatCache(bool isCommit)
+{
+ CatCache *cache;
+
+ for (cache = Caches; cache; cache = cache->cc_next)
+ {
+ Dlelem *elt,
+ *nextelt;
+
+ for (elt = DLGetHead(&cache->cc_lrulist); elt; elt = nextelt)
+ {
+ CatCTup *ct = (CatCTup *) DLE_VAL(elt);
+
+ nextelt = DLGetSucc(elt);
+
+ if (ct->refcount != 0)
+ {
+ if (isCommit)
+ elog(NOTICE, "Cache reference leak: cache %s (%d), tuple %u has count %d",
+ cache->cc_relname, cache->id,
+ ct->tuple.t_data->t_oid,
+ ct->refcount);
+ ct->refcount = 0;
+ }
+
+ /* Clean up any now-deletable dead entries */
+ if (ct->dead)
+ CatCacheRemoveCTup(cache, ct);
+ }
+ }
+}
+
/* --------------------------------
* ResetSystemCache
+ *
+ * Reset caches when a shared cache inval event forces it
* --------------------------------
*/
void
@@ -503,34 +538,25 @@ ResetSystemCache(void)
* here we purge the contents of all the caches
*
* for each system cache
- * for each hash bucket
- * for each tuple in hash bucket
- * remove the tuple
+ * for each tuple
+ * remove the tuple, or at least mark it dead
* ----------------
*/
- for (cache = Caches; PointerIsValid(cache); cache = cache->cc_next)
+ for (cache = Caches; cache; cache = cache->cc_next)
{
- int hash;
+ Dlelem *elt,
+ *nextelt;
- for (hash = 0; hash < NCCBUCK; hash += 1)
+ for (elt = DLGetHead(&cache->cc_lrulist); elt; elt = nextelt)
{
- Dlelem *elt,
- *nextelt;
+ CatCTup *ct = (CatCTup *) DLE_VAL(elt);
- for (elt = DLGetHead(cache->cc_cache[hash]); elt; elt = nextelt)
- {
- nextelt = DLGetSucc(elt);
- CatCacheRemoveCTup(cache, elt);
- }
- }
+ nextelt = DLGetSucc(elt);
- /* double-check that ntup is now zero */
- if (cache->cc_ntup != 0)
- {
- elog(NOTICE,
- "ResetSystemCache: cache %d has cc_ntup = %d, should be 0",
- cache->id, cache->cc_ntup);
- cache->cc_ntup = 0;
+ if (ct->refcount > 0)
+ ct->dead = true;
+ else
+ CatCacheRemoveCTup(cache, ct);
}
}
@@ -572,7 +598,7 @@ SystemCacheRelationFlushed(Oid relId)
}
/* --------------------------------
- * InitSysCache
+ * InitCatCache
*
* This allocates and initializes a cache for a system catalog relation.
* Actually, the cache is only partially initialized to avoid opening the
@@ -581,18 +607,18 @@ SystemCacheRelationFlushed(Oid relId)
* --------------------------------
*/
#ifdef CACHEDEBUG
-#define InitSysCache_DEBUG1 \
+#define InitCatCache_DEBUG1 \
do { \
- elog(DEBUG, "InitSysCache: rel=%s id=%d nkeys=%d size=%d\n", \
+ elog(DEBUG, "InitCatCache: rel=%s id=%d nkeys=%d size=%d\n", \
cp->cc_relname, cp->id, cp->cc_nkeys, cp->cc_size); \
} while(0)
#else
-#define InitSysCache_DEBUG1
+#define InitCatCache_DEBUG1
#endif
CatCache *
-InitSysCache(int id,
+InitCatCache(int id,
char *relname,
char *indname,
int nkeys,
@@ -624,25 +650,9 @@ InitSysCache(int id,
* and the LRU tuple list
* ----------------
*/
- {
-
- /*
- * We can only do this optimization because the number of hash
- * buckets never changes. Without it, we call palloc() too much.
- * We could move this to dllist.c, but the way we do this is not
- * dynamic/portable, so why allow other routines to use it.
- */
- Dllist *cache_begin = palloc((NCCBUCK + 1) * sizeof(Dllist));
-
- for (i = 0; i <= NCCBUCK; ++i)
- {
- cp->cc_cache[i] = &cache_begin[i];
- cp->cc_cache[i]->dll_head = 0;
- cp->cc_cache[i]->dll_tail = 0;
- }
- }
-
- cp->cc_lrulist = DLNewList();
+ DLInitList(&cp->cc_lrulist);
+ for (i = 0; i < NCCBUCK; ++i)
+ DLInitList(&cp->cc_cache[i]);
/* ----------------
* Caches is the pointer to the head of the list of all the
@@ -673,7 +683,7 @@ InitSysCache(int id,
* information, if appropriate.
* ----------------
*/
- InitSysCache_DEBUG1;
+ InitCatCache_DEBUG1;
/* ----------------
* back to the old context before we return...
@@ -742,14 +752,14 @@ IndexScanOK(CatCache *cache, ScanKey cur_skey)
}
/* --------------------------------
- * SearchSysCache
+ * SearchCatCache
*
* This call searches a system cache for a tuple, opening the relation
* if necessary (the first access to a particular cache).
* --------------------------------
*/
HeapTuple
-SearchSysCache(CatCache *cache,
+SearchCatCache(CatCache *cache,
Datum v1,
Datum v2,
Datum v3,
@@ -757,10 +767,8 @@ SearchSysCache(CatCache *cache,
{
ScanKeyData cur_skey[4];
Index hash;
- CatCTup *ct = NULL;
- CatCTup *nct;
- CatCTup *nct2;
Dlelem *elt;
+ CatCTup *ct;
HeapTuple ntp;
Relation relation;
MemoryContext oldcxt;
@@ -792,48 +800,50 @@ SearchSysCache(CatCache *cache,
* scan the hash bucket until we find a match or exhaust our tuples
* ----------------
*/
- for (elt = DLGetHead(cache->cc_cache[hash]);
+ for (elt = DLGetHead(&cache->cc_cache[hash]);
elt;
elt = DLGetSucc(elt))
{
bool res;
ct = (CatCTup *) DLE_VAL(elt);
+
+ if (ct->dead)
+ continue; /* ignore dead entries */
+
/* ----------------
* see if the cached tuple matches our key.
* (should we be worried about time ranges? -cim 10/2/90)
* ----------------
*/
- HeapKeyTest(ct->ct_tup,
+ HeapKeyTest(&ct->tuple,
cache->cc_tupdesc,
cache->cc_nkeys,
cur_skey,
res);
- if (res)
- break;
- }
+ if (! res)
+ continue;
- /* ----------------
- * if we found a tuple in the cache, move it to the top of the
- * lru list, and return it. We also move it to the front of the
- * list for its hashbucket, in order to speed subsequent searches.
- * (The most frequently accessed elements in any hashbucket will
- * tend to be near the front of the hashbucket's list.)
- * ----------------
- */
- if (elt)
- {
- Dlelem *old_lru_elt = ((CatCTup *) DLE_VAL(elt))->ct_node;
+ /* ----------------
+ * we found a tuple in the cache: bump its refcount, move it to
+ * the front of the LRU list, and return it. We also move it
+ * to the front of the list for its hashbucket, in order to speed
+ * subsequent searches. (The most frequently accessed elements
+ * in any hashbucket will tend to be near the front of the
+ * hashbucket's list.)
+ * ----------------
+ */
+ ct->refcount++;
- DLMoveToFront(old_lru_elt);
- DLMoveToFront(elt);
+ DLMoveToFront(&ct->lrulist_elem);
+ DLMoveToFront(&ct->cache_elem);
#ifdef CACHEDEBUG
- CACHE3_elog(DEBUG, "SearchSysCache(%s): found in bucket %d",
+ CACHE3_elog(DEBUG, "SearchCatCache(%s): found in bucket %d",
cache->cc_relname, hash);
#endif /* CACHEDEBUG */
- return ct->ct_tup;
+ return &ct->tuple;
}
/* ----------------
@@ -864,7 +874,7 @@ SearchSysCache(CatCache *cache,
* if it's safe to do so, use the index. Else do a heap scan.
* ----------------
*/
- ntp = NULL;
+ ct = NULL;
if ((RelationGetForm(relation))->relhasindex &&
!IsIgnoringSystemIndexes() &&
@@ -876,7 +886,7 @@ SearchSysCache(CatCache *cache,
HeapTupleData tuple;
Buffer buffer;
- CACHE2_elog(DEBUG, "SearchSysCache(%s): performing index scan",
+ CACHE2_elog(DEBUG, "SearchCatCache(%s): performing index scan",
cache->cc_relname);
idesc = index_openr(cache->cc_indname);
@@ -892,7 +902,8 @@ SearchSysCache(CatCache *cache,
{
/* Copy tuple into our context */
oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
- ntp = heap_copytuple(&tuple);
+ ct = (CatCTup *) palloc(sizeof(CatCTup));
+ heap_copytuple_with_tuple(&tuple, &ct->tuple);
MemoryContextSwitchTo(oldcxt);
ReleaseBuffer(buffer);
break;
@@ -906,7 +917,7 @@ SearchSysCache(CatCache *cache,
HeapScanDesc sd;
int i;
- CACHE2_elog(DEBUG, "SearchSysCache(%s): performing heap scan",
+ CACHE2_elog(DEBUG, "SearchCatCache(%s): performing heap scan",
cache->cc_relname);
/*
@@ -925,7 +936,8 @@ SearchSysCache(CatCache *cache,
{
/* Copy tuple into our context */
oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
- ntp = heap_copytuple(ntp);
+ ct = (CatCTup *) palloc(sizeof(CatCTup));
+ heap_copytuple_with_tuple(ntp, &ct->tuple);
MemoryContextSwitchTo(oldcxt);
/* We should not free the result of heap_getnext... */
}
@@ -934,77 +946,102 @@ SearchSysCache(CatCache *cache,
}
/* ----------------
- * scan is complete. if tup is valid, we can add it to the cache.
- * note we have already copied it into the cache memory context.
+ * close the relation
* ----------------
*/
- if (HeapTupleIsValid(ntp))
- {
- /* ----------------
- * allocate a new cache tuple holder, store the pointer
- * to the heap tuple there and initialize the list pointers.
- * ----------------
- */
- Dlelem *lru_elt;
-
- CACHE1_elog(DEBUG, "SearchSysCache: found tuple");
+ heap_close(relation, AccessShareLock);
- oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
+ /* ----------------
+ * scan is complete. if tup was found, we can add it to the cache.
+ * ----------------
+ */
+ if (ct == NULL)
+ return NULL;
- /*
- * this is a little cumbersome here because we want the Dlelem's
- * in both doubly linked lists to point to one another. That makes
- * it easier to remove something from both the cache bucket and
- * the lru list at the same time
- */
- nct = (CatCTup *) palloc(sizeof(CatCTup));
- nct->ct_tup = ntp;
- elt = DLNewElem(nct);
- nct2 = (CatCTup *) palloc(sizeof(CatCTup));
- nct2->ct_tup = ntp;
- lru_elt = DLNewElem(nct2);
- nct2->ct_node = elt;
- nct->ct_node = lru_elt;
+ /* ----------------
+ * Finish initializing the CatCTup header, and add it to the
+ * linked lists.
+ * ----------------
+ */
+ CACHE1_elog(DEBUG, "SearchCatCache: found tuple");
- DLAddHead(cache->cc_lrulist, lru_elt);
- DLAddHead(cache->cc_cache[hash], elt);
+ ct->ct_magic = CT_MAGIC;
+ DLInitElem(&ct->lrulist_elem, (void *) ct);
+ DLInitElem(&ct->cache_elem, (void *) ct);
+ ct->refcount = 1; /* count this first reference */
+ ct->dead = false;
- MemoryContextSwitchTo(oldcxt);
+ DLAddHead(&cache->cc_lrulist, &ct->lrulist_elem);
+ DLAddHead(&cache->cc_cache[hash], &ct->cache_elem);
- /* ----------------
- * If we've exceeded the desired size of this cache,
- * throw away the least recently used entry.
- * ----------------
- */
- if (++cache->cc_ntup > cache->cc_maxtup)
+ /* ----------------
+ * If we've exceeded the desired size of this cache,
+ * try to throw away the least recently used entry.
+ * ----------------
+ */
+ if (++cache->cc_ntup > cache->cc_maxtup)
+ {
+ for (elt = DLGetTail(&cache->cc_lrulist);
+ elt;
+ elt = DLGetPred(elt))
{
- CatCTup *ct;
+ CatCTup *oldct = (CatCTup *) DLE_VAL(elt);
- elt = DLGetTail(cache->cc_lrulist);
- ct = (CatCTup *) DLE_VAL(elt);
-
- if (ct != nct) /* shouldn't be possible, but be safe... */
+ if (oldct->refcount == 0)
{
- CACHE2_elog(DEBUG, "SearchSysCache(%s): Overflow, LRU removal",
+ CACHE2_elog(DEBUG, "SearchCatCache(%s): Overflow, LRU removal",
cache->cc_relname);
-
- CatCacheRemoveCTup(cache, elt);
+ CatCacheRemoveCTup(cache, oldct);
+ break;
}
}
-
- CACHE4_elog(DEBUG, "SearchSysCache(%s): Contains %d/%d tuples",
- cache->cc_relname, cache->cc_ntup, cache->cc_maxtup);
- CACHE3_elog(DEBUG, "SearchSysCache(%s): put in bucket %d",
- cache->cc_relname, hash);
}
- /* ----------------
- * close the relation and return the tuple we found (or NULL)
- * ----------------
- */
- heap_close(relation, AccessShareLock);
+ CACHE4_elog(DEBUG, "SearchCatCache(%s): Contains %d/%d tuples",
+ cache->cc_relname, cache->cc_ntup, cache->cc_maxtup);
+ CACHE3_elog(DEBUG, "SearchCatCache(%s): put in bucket %d",
+ cache->cc_relname, hash);
+
+ return &ct->tuple;
+}
- return ntp;
+/* --------------------------------
+ * ReleaseCatCache()
+ *
+ * Decrement the reference count of a catcache entry (releasing the
+ * hold grabbed by a successful SearchCatCache).
+ *
+ * NOTE: if compiled with -DCATCACHE_FORCE_RELEASE then catcache entries
+ * will be freed as soon as their refcount goes to zero. In combination
+ * with aset.c's CLOBBER_FREED_MEMORY option, this provides a good test
+ * to catch references to already-released catcache entries.
+ * --------------------------------
+ */
+void
+ReleaseCatCache(HeapTuple tuple)
+{
+ CatCTup *ct = (CatCTup *) (((char *) tuple) -
+ offsetof(CatCTup, tuple));
+
+ /* Safety checks to ensure we were handed a cache entry */
+ Assert(ct->ct_magic == CT_MAGIC);
+ Assert(ct->refcount > 0);
+
+ ct->refcount--;
+
+ if (ct->refcount == 0
+#ifndef CATCACHE_FORCE_RELEASE
+ && ct->dead
+#endif
+ )
+ {
+ /* We can find the associated cache using the dllist pointers */
+ Dllist *lru = DLGetListHdr(&ct->lrulist_elem);
+ CatCache *cache = (CatCache *) (((char *) lru) -
+ offsetof(CatCache, cc_lrulist));
+
+ CatCacheRemoveCTup(cache, ct);
+ }
}
/* --------------------------------
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index b9bd9f8b9e9..e07445837a5 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.46 2000/10/05 19:48:29 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.47 2000/11/16 22:30:33 tgl Exp $
*
* NOTES
* Eventually, the index information should go through here, too.
@@ -32,14 +32,11 @@
bool
op_class(Oid opno, Oid opclass, Oid amopid)
{
- if (HeapTupleIsValid(SearchSysCacheTuple(AMOPOPID,
- ObjectIdGetDatum(opclass),
- ObjectIdGetDatum(opno),
- ObjectIdGetDatum(amopid),
- 0)))
- return true;
- else
- return false;
+ return SearchSysCacheExists(AMOPOPID,
+ ObjectIdGetDatum(opclass),
+ ObjectIdGetDatum(opno),
+ ObjectIdGetDatum(amopid),
+ 0);
}
/* ---------- ATTRIBUTE CACHES ---------- */
@@ -49,21 +46,26 @@ op_class(Oid opno, Oid opclass, Oid amopid)
*
* Given the relation id and the attribute number,
* return the "attname" field from the attribute relation.
+ *
+ * Note: returns a palloc'd copy of the string, or NULL if no such operator.
*/
char *
get_attname(Oid relid, AttrNumber attnum)
{
HeapTuple tp;
- tp = SearchSysCacheTuple(ATTNUM,
- ObjectIdGetDatum(relid),
- Int16GetDatum(attnum),
- 0, 0);
+ tp = SearchSysCache(ATTNUM,
+ ObjectIdGetDatum(relid),
+ Int16GetDatum(attnum),
+ 0, 0);
if (HeapTupleIsValid(tp))
{
Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
+ char *result;
- return pstrdup(NameStr(att_tup->attname));
+ result = pstrdup(NameStr(att_tup->attname));
+ ReleaseSysCache(tp);
+ return result;
}
else
return NULL;
@@ -80,15 +82,18 @@ get_attnum(Oid relid, char *attname)
{
HeapTuple tp;
- tp = SearchSysCacheTuple(ATTNAME,
- ObjectIdGetDatum(relid),
- PointerGetDatum(attname),
- 0, 0);
+ tp = SearchSysCache(ATTNAME,
+ ObjectIdGetDatum(relid),
+ PointerGetDatum(attname),
+ 0, 0);
if (HeapTupleIsValid(tp))
{
Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
+ AttrNumber result;
- return att_tup->attnum;
+ result = att_tup->attnum;
+ ReleaseSysCache(tp);
+ return result;
}
else
return InvalidAttrNumber;
@@ -105,15 +110,18 @@ get_atttype(Oid relid, AttrNumber attnum)
{
HeapTuple tp;
- tp = SearchSysCacheTuple(ATTNUM,
- ObjectIdGetDatum(relid),
- Int16GetDatum(attnum),
- 0, 0);
+ tp = SearchSysCache(ATTNUM,
+ ObjectIdGetDatum(relid),
+ Int16GetDatum(attnum),
+ 0, 0);
if (HeapTupleIsValid(tp))
{
Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
+ Oid result;
- return att_tup->atttypid;
+ result = att_tup->atttypid;
+ ReleaseSysCache(tp);
+ return result;
}
else
return InvalidOid;
@@ -128,15 +136,18 @@ get_attisset(Oid relid, char *attname)
{
HeapTuple tp;
- tp = SearchSysCacheTuple(ATTNAME,
- ObjectIdGetDatum(relid),
- PointerGetDatum(attname),
- 0, 0);
+ tp = SearchSysCache(ATTNAME,
+ ObjectIdGetDatum(relid),
+ PointerGetDatum(attname),
+ 0, 0);
if (HeapTupleIsValid(tp))
{
Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
+ bool result;
- return att_tup->attisset;
+ result = att_tup->attisset;
+ ReleaseSysCache(tp);
+ return result;
}
else
return false;
@@ -153,15 +164,18 @@ get_atttypmod(Oid relid, AttrNumber attnum)
{
HeapTuple tp;
- tp = SearchSysCacheTuple(ATTNUM,
- ObjectIdGetDatum(relid),
- Int16GetDatum(attnum),
- 0, 0);
+ tp = SearchSysCache(ATTNUM,
+ ObjectIdGetDatum(relid),
+ Int16GetDatum(attnum),
+ 0, 0);
if (HeapTupleIsValid(tp))
{
Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
+ int32 result;
- return att_tup->atttypmod;
+ result = att_tup->atttypmod;
+ ReleaseSysCache(tp);
+ return result;
}
else
return -1;
@@ -185,12 +199,13 @@ get_attdispersion(Oid relid, AttrNumber attnum, double min_estimate)
HeapTuple atp;
Form_pg_attribute att_tup;
double dispersion;
+ Oid atttypid;
int32 ntuples;
- atp = SearchSysCacheTuple(ATTNUM,
- ObjectIdGetDatum(relid),
- Int16GetDatum(attnum),
- 0, 0);
+ atp = SearchSysCache(ATTNUM,
+ ObjectIdGetDatum(relid),
+ Int16GetDatum(attnum),
+ 0, 0);
if (!HeapTupleIsValid(atp))
{
/* this should not happen */
@@ -198,9 +213,14 @@ get_attdispersion(Oid relid, AttrNumber attnum, double min_estimate)
relid, attnum);
return min_estimate;
}
+
att_tup = (Form_pg_attribute) GETSTRUCT(atp);
dispersion = att_tup->attdispersion;
+ atttypid = att_tup->atttypid;
+
+ ReleaseSysCache(atp);
+
if (dispersion > 0.0)
return dispersion; /* we have a specific estimate from VACUUM */
@@ -211,7 +231,7 @@ get_attdispersion(Oid relid, AttrNumber attnum, double min_estimate)
*
* Are there any other cases we should wire in special estimates for?
*/
- if (att_tup->atttypid == BOOLOID)
+ if (atttypid == BOOLOID)
return 0.5;
/*
@@ -219,9 +239,9 @@ get_attdispersion(Oid relid, AttrNumber attnum, double min_estimate)
* 1/numtuples). Either way, we need the relation size.
*/
- atp = SearchSysCacheTuple(RELOID,
- ObjectIdGetDatum(relid),
- 0, 0, 0);
+ atp = SearchSysCache(RELOID,
+ ObjectIdGetDatum(relid),
+ 0, 0, 0);
if (!HeapTupleIsValid(atp))
{
/* this should not happen */
@@ -231,6 +251,8 @@ get_attdispersion(Oid relid, AttrNumber attnum, double min_estimate)
ntuples = ((Form_pg_class) GETSTRUCT(atp))->reltuples;
+ ReleaseSysCache(atp);
+
if (ntuples == 0)
return min_estimate; /* no data available */
@@ -277,14 +299,17 @@ get_opcode(Oid opno)
{
HeapTuple tp;
- tp = SearchSysCacheTuple(OPEROID,
- ObjectIdGetDatum(opno),
- 0, 0, 0);
+ tp = SearchSysCache(OPEROID,
+ ObjectIdGetDatum(opno),
+ 0, 0, 0);
if (HeapTupleIsValid(tp))
{
Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
+ RegProcedure result;
- return optup->oprcode;
+ result = optup->oprcode;
+ ReleaseSysCache(tp);
+ return result;
}
else
return (RegProcedure) InvalidOid;
@@ -301,14 +326,17 @@ get_opname(Oid opno)
{
HeapTuple tp;
- tp = SearchSysCacheTuple(OPEROID,
- ObjectIdGetDatum(opno),
- 0, 0, 0);
+ tp = SearchSysCache(OPEROID,
+ ObjectIdGetDatum(opno),
+ 0, 0, 0);
if (HeapTupleIsValid(tp))
{
Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
+ char *result;
- return pstrdup(NameStr(optup->oprname));
+ result = pstrdup(NameStr(optup->oprname));
+ ReleaseSysCache(tp);
+ return result;
}
else
return NULL;
@@ -324,10 +352,11 @@ bool
op_mergejoinable(Oid opno, Oid ltype, Oid rtype, Oid *leftOp, Oid *rightOp)
{
HeapTuple tp;
+ bool result = false;
- tp = SearchSysCacheTuple(OPEROID,
- ObjectIdGetDatum(opno),
- 0, 0, 0);
+ tp = SearchSysCache(OPEROID,
+ ObjectIdGetDatum(opno),
+ 0, 0, 0);
if (HeapTupleIsValid(tp))
{
Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
@@ -339,10 +368,11 @@ op_mergejoinable(Oid opno, Oid ltype, Oid rtype, Oid *leftOp, Oid *rightOp)
{
*leftOp = optup->oprlsortop;
*rightOp = optup->oprrsortop;
- return true;
+ result = true;
}
+ ReleaseSysCache(tp);
}
- return false;
+ return result;
}
/*
@@ -355,10 +385,11 @@ Oid
op_hashjoinable(Oid opno, Oid ltype, Oid rtype)
{
HeapTuple tp;
+ Oid result = InvalidOid;
- tp = SearchSysCacheTuple(OPEROID,
- ObjectIdGetDatum(opno),
- 0, 0, 0);
+ tp = SearchSysCache(OPEROID,
+ ObjectIdGetDatum(opno),
+ 0, 0, 0);
if (HeapTupleIsValid(tp))
{
Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
@@ -366,9 +397,10 @@ op_hashjoinable(Oid opno, Oid ltype, Oid rtype)
if (optup->oprcanhash &&
optup->oprleft == ltype &&
optup->oprright == rtype)
- return opno;
+ result = opno;
+ ReleaseSysCache(tp);
}
- return InvalidOid;
+ return result;
}
/*
@@ -387,14 +419,6 @@ op_iscachable(Oid opno)
return func_iscachable((Oid) funcid);
}
-HeapTuple
-get_operator_tuple(Oid opno)
-{
- return SearchSysCacheTuple(OPEROID,
- ObjectIdGetDatum(opno),
- 0, 0, 0);
-}
-
/*
* get_commutator
*
@@ -405,14 +429,17 @@ get_commutator(Oid opno)
{
HeapTuple tp;
- tp = SearchSysCacheTuple(OPEROID,
- ObjectIdGetDatum(opno),
- 0, 0, 0);
+ tp = SearchSysCache(OPEROID,
+ ObjectIdGetDatum(opno),
+ 0, 0, 0);
if (HeapTupleIsValid(tp))
{
Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
+ Oid result;
- return optup->oprcom;
+ result = optup->oprcom;
+ ReleaseSysCache(tp);
+ return result;
}
else
return InvalidOid;
@@ -428,14 +455,17 @@ get_negator(Oid opno)
{
HeapTuple tp;
- tp = SearchSysCacheTuple(OPEROID,
- ObjectIdGetDatum(opno),
- 0, 0, 0);
+ tp = SearchSysCache(OPEROID,
+ ObjectIdGetDatum(opno),
+ 0, 0, 0);
if (HeapTupleIsValid(tp))
{
Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
+ Oid result;
- return optup->oprnegate;
+ result = optup->oprnegate;
+ ReleaseSysCache(tp);
+ return result;
}
else
return InvalidOid;
@@ -451,14 +481,17 @@ get_oprrest(Oid opno)
{
HeapTuple tp;
- tp = SearchSysCacheTuple(OPEROID,
- ObjectIdGetDatum(opno),
- 0, 0, 0);
+ tp = SearchSysCache(OPEROID,
+ ObjectIdGetDatum(opno),
+ 0, 0, 0);
if (HeapTupleIsValid(tp))
{
Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
+ RegProcedure result;
- return optup->oprrest;
+ result = optup->oprrest;
+ ReleaseSysCache(tp);
+ return result;
}
else
return (RegProcedure) InvalidOid;
@@ -474,14 +507,17 @@ get_oprjoin(Oid opno)
{
HeapTuple tp;
- tp = SearchSysCacheTuple(OPEROID,
- ObjectIdGetDatum(opno),
- 0, 0, 0);
+ tp = SearchSysCache(OPEROID,
+ ObjectIdGetDatum(opno),
+ 0, 0, 0);
if (HeapTupleIsValid(tp))
{
Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
+ RegProcedure result;
- return optup->oprjoin;
+ result = optup->oprjoin;
+ ReleaseSysCache(tp);
+ return result;
}
else
return (RegProcedure) InvalidOid;
@@ -496,15 +532,18 @@ get_oprjoin(Oid opno)
Oid
get_func_rettype(Oid funcid)
{
- HeapTuple func_tuple;
+ HeapTuple tp;
+ Oid result;
- func_tuple = SearchSysCacheTuple(PROCOID,
- ObjectIdGetDatum(funcid),
- 0, 0, 0);
- if (!HeapTupleIsValid(func_tuple))
+ tp = SearchSysCache(PROCOID,
+ ObjectIdGetDatum(funcid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tp))
elog(ERROR, "Function OID %u does not exist", funcid);
- return ((Form_pg_proc) GETSTRUCT(func_tuple))->prorettype;
+ result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
+ ReleaseSysCache(tp);
+ return result;
}
/*
@@ -514,15 +553,18 @@ get_func_rettype(Oid funcid)
bool
func_iscachable(Oid funcid)
{
- HeapTuple func_tuple;
+ HeapTuple tp;
+ bool result;
- func_tuple = SearchSysCacheTuple(PROCOID,
- ObjectIdGetDatum(funcid),
- 0, 0, 0);
- if (!HeapTupleIsValid(func_tuple))
+ tp = SearchSysCache(PROCOID,
+ ObjectIdGetDatum(funcid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tp))
elog(ERROR, "Function OID %u does not exist", funcid);
- return ((Form_pg_proc) GETSTRUCT(func_tuple))->proiscachable;
+ result = ((Form_pg_proc) GETSTRUCT(tp))->proiscachable;
+ ReleaseSysCache(tp);
+ return result;
}
/* ---------- RELATION CACHE ---------- */
@@ -538,14 +580,17 @@ get_relnatts(Oid relid)
{
HeapTuple tp;
- tp = SearchSysCacheTuple(RELOID,
- ObjectIdGetDatum(relid),
- 0, 0, 0);
+ tp = SearchSysCache(RELOID,
+ ObjectIdGetDatum(relid),
+ 0, 0, 0);
if (HeapTupleIsValid(tp))
{
Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
+ int result;
- return reltup->relnatts;
+ result = reltup->relnatts;
+ ReleaseSysCache(tp);
+ return result;
}
else
return InvalidAttrNumber;
@@ -556,20 +601,25 @@ get_relnatts(Oid relid)
* get_rel_name
*
* Returns the name of a given relation.
+ *
+ * Note: returns a palloc'd copy of the string, or NULL if no such operator.
*/
char *
get_rel_name(Oid relid)
{
HeapTuple tp;
- tp = SearchSysCacheTuple(RELOID,
- ObjectIdGetDatum(relid),
- 0, 0, 0);
+ tp = SearchSysCache(RELOID,
+ ObjectIdGetDatum(relid),
+ 0, 0, 0);
if (HeapTupleIsValid(tp))
{
Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
+ char *result;
- return pstrdup(NameStr(reltup->relname));
+ result = pstrdup(NameStr(reltup->relname));
+ ReleaseSysCache(tp);
+ return result;
}
else
return NULL;
@@ -587,14 +637,17 @@ get_typlen(Oid typid)
{
HeapTuple tp;
- tp = SearchSysCacheTuple(TYPEOID,
- ObjectIdGetDatum(typid),
- 0, 0, 0);
+ tp = SearchSysCache(TYPEOID,
+ ObjectIdGetDatum(typid),
+ 0, 0, 0);
if (HeapTupleIsValid(tp))
{
Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
+ int16 result;
- return typtup->typlen;
+ result = typtup->typlen;
+ ReleaseSysCache(tp);
+ return result;
}
else
return 0;
@@ -611,33 +664,66 @@ get_typbyval(Oid typid)
{
HeapTuple tp;
- tp = SearchSysCacheTuple(TYPEOID,
- ObjectIdGetDatum(typid),
- 0, 0, 0);
+ tp = SearchSysCache(TYPEOID,
+ ObjectIdGetDatum(typid),
+ 0, 0, 0);
if (HeapTupleIsValid(tp))
{
Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
+ bool result;
- return typtup->typbyval;
+ result = typtup->typbyval;
+ ReleaseSysCache(tp);
+ return result;
}
else
return false;
}
+/*
+ * get_typlenbyval
+ *
+ * A two-fer: given the type OID, return both typlen and typbyval.
+ *
+ * Since both pieces of info are needed to know how to copy a Datum,
+ * many places need both. Might as well get them with one cache lookup
+ * instead of two. Also, this routine raises an error instead of
+ * returning a bogus value when given a bad type OID.
+ */
+void
+get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
+{
+ HeapTuple tp;
+ Form_pg_type typtup;
+
+ tp = SearchSysCache(TYPEOID,
+ ObjectIdGetDatum(typid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tp))
+ elog(ERROR, "cache lookup failed for type %u", typid);
+ typtup = (Form_pg_type) GETSTRUCT(tp);
+ *typlen = typtup->typlen;
+ *typbyval = typtup->typbyval;
+ ReleaseSysCache(tp);
+}
+
#ifdef NOT_USED
char
get_typalign(Oid typid)
{
HeapTuple tp;
- tp = SearchSysCacheTuple(TYPEOID,
- ObjectIdGetDatum(typid),
- 0, 0, 0);
+ tp = SearchSysCache(TYPEOID,
+ ObjectIdGetDatum(typid),
+ 0, 0, 0);
if (HeapTupleIsValid(tp))
{
Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
+ char result;
- return typtup->typalign;
+ result = typtup->typalign;
+ ReleaseSysCache(tp);
+ return result;
}
else
return 'i';
@@ -666,9 +752,9 @@ get_typdefault(Oid typid)
bool typByVal;
Datum returnValue;
- typeTuple = SearchSysCacheTuple(TYPEOID,
- ObjectIdGetDatum(typid),
- 0, 0, 0);
+ typeTuple = SearchSysCache(TYPEOID,
+ ObjectIdGetDatum(typid),
+ 0, 0, 0);
if (!HeapTupleIsValid(typeTuple))
elog(ERROR, "get_typdefault: failed to lookup type %u", typid);
@@ -679,13 +765,17 @@ get_typdefault(Oid typid)
* First, see if there is a non-null typdefault field (usually there
* isn't)
*/
- typDefault = (struct varlena *) SysCacheGetAttr(TYPEOID,
- typeTuple,
- Anum_pg_type_typdefault,
- &isNull);
+ typDefault = (struct varlena *)
+ DatumGetPointer(SysCacheGetAttr(TYPEOID,
+ typeTuple,
+ Anum_pg_type_typdefault,
+ &isNull));
if (isNull)
+ {
+ ReleaseSysCache(typeTuple);
return PointerGetDatum(NULL);
+ }
/*
* Otherwise, extract/copy the value.
@@ -748,6 +838,8 @@ get_typdefault(Oid typid)
}
}
+ ReleaseSysCache(typeTuple);
+
return returnValue;
}
@@ -764,14 +856,17 @@ get_typtype(Oid typid)
{
HeapTuple tp;
- tp = SearchSysCacheTuple(TYPEOID,
- ObjectIdGetDatum(typid),
- 0, 0, 0);
+ tp = SearchSysCache(TYPEOID,
+ ObjectIdGetDatum(typid),
+ 0, 0, 0);
if (HeapTupleIsValid(tp))
{
Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
+ char result;
- return typtup->typtype;
+ result = typtup->typtype;
+ ReleaseSysCache(tp);
+ return result;
}
else
return '\0';
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index 7f35f192089..bb9a55b869a 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.56 2000/11/10 00:33:10 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.57 2000/11/16 22:30:33 tgl Exp $
*
* NOTES
* These routines allow the parser/planner/executor to perform
@@ -343,7 +343,7 @@ static struct cachedesc cacheinfo[] = {
};
static CatCache *SysCache[lengthof(cacheinfo)];
-static int32 SysCacheSize = lengthof(cacheinfo);
+static int SysCacheSize = lengthof(cacheinfo);
static bool CacheInitialized = false;
@@ -355,98 +355,67 @@ IsCacheInitialized(void)
/*
- * zerocaches
+ * InitCatalogCache - initialize the caches
*
- * Make sure the SysCache structure is zero'd.
+ * Note that no database access is done here; we only allocate memory
+ * and initialize the cache structure. Interrogation of the database
+ * to complete initialization of a cache happens only upon first use
+ * of that cache.
*/
void
-zerocaches()
+InitCatalogCache(void)
{
- MemSet((char *) SysCache, 0, SysCacheSize * sizeof(CatCache *));
-}
+ int cacheId;
+ Assert(!CacheInitialized);
-/*
- * InitCatalogCache - initialize the caches
- */
-void
-InitCatalogCache()
-{
- int cacheId; /* XXX type */
+ MemSet((char *) SysCache, 0, sizeof(SysCache));
- if (!AMI_OVERRIDE)
+ for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
{
- for (cacheId = 0; cacheId < SysCacheSize; cacheId += 1)
- {
- Assert(!PointerIsValid(SysCache[cacheId]));
-
- SysCache[cacheId] = InitSysCache(cacheId,
- cacheinfo[cacheId].name,
- cacheinfo[cacheId].indname,
- cacheinfo[cacheId].nkeys,
- cacheinfo[cacheId].key);
- if (!PointerIsValid(SysCache[cacheId]))
- {
- elog(ERROR,
- "InitCatalogCache: Can't init cache %s (%d)",
- cacheinfo[cacheId].name,
- cacheId);
- }
-
- }
+ SysCache[cacheId] = InitCatCache(cacheId,
+ cacheinfo[cacheId].name,
+ cacheinfo[cacheId].indname,
+ cacheinfo[cacheId].nkeys,
+ cacheinfo[cacheId].key);
+ if (!PointerIsValid(SysCache[cacheId]))
+ elog(ERROR, "InitCatalogCache: Can't init cache %s (%d)",
+ cacheinfo[cacheId].name, cacheId);
}
CacheInitialized = true;
}
/*
- * SearchSysCacheTuple
+ * SearchSysCache
*
- * A layer on top of SearchSysCache that does the initialization and
+ * A layer on top of SearchCatCache that does the initialization and
* key-setting for you.
*
* Returns the cache copy of the tuple if one is found, NULL if not.
- * The tuple is the 'cache' copy.
- *
- * CAUTION: The tuple that is returned must NOT be freed by the caller!
+ * The tuple is the 'cache' copy and must NOT be modified!
*
- * CAUTION: The returned tuple may be flushed from the cache during
- * subsequent cache lookup operations, or by shared cache invalidation.
- * Callers should not expect the pointer to remain valid for long.
+ * When the caller is done using the tuple, call ReleaseSysCache()
+ * to release the reference count grabbed by SearchSysCache(). If this
+ * is not done, the tuple will remain locked in cache until end of
+ * transaction, which is tolerable but not desirable.
*
- * XXX we ought to have some kind of referencecount mechanism for
- * cache entries, to ensure entries aren't deleted while in use.
+ * CAUTION: The tuple that is returned must NOT be freed by the caller!
*/
HeapTuple
-SearchSysCacheTuple(int cacheId,/* cache selection code */
- Datum key1,
- Datum key2,
- Datum key3,
- Datum key4)
+SearchSysCache(int cacheId,
+ Datum key1,
+ Datum key2,
+ Datum key3,
+ Datum key4)
{
- HeapTuple tp;
-
if (cacheId < 0 || cacheId >= SysCacheSize)
{
- elog(ERROR, "SearchSysCacheTuple: Bad cache id %d", cacheId);
+ elog(ERROR, "SearchSysCache: Bad cache id %d", cacheId);
return (HeapTuple) NULL;
}
- Assert(AMI_OVERRIDE || PointerIsValid(SysCache[cacheId]));
-
- if (!PointerIsValid(SysCache[cacheId]))
- {
- SysCache[cacheId] = InitSysCache(cacheId,
- cacheinfo[cacheId].name,
- cacheinfo[cacheId].indname,
- cacheinfo[cacheId].nkeys,
- cacheinfo[cacheId].key);
- if (!PointerIsValid(SysCache[cacheId]))
- elog(ERROR,
- "InitCatalogCache: Can't init cache %s(%d)",
- cacheinfo[cacheId].name,
- cacheId);
- }
+ Assert(PointerIsValid(SysCache[cacheId]));
/*
* If someone tries to look up a relname, translate temp relation
@@ -464,51 +433,75 @@ SearchSysCacheTuple(int cacheId,/* cache selection code */
key1 = CStringGetDatum(nontemp_relname);
}
- tp = SearchSysCache(SysCache[cacheId], key1, key2, key3, key4);
- if (!HeapTupleIsValid(tp))
- {
-#ifdef CACHEDEBUG
- elog(DEBUG,
- "SearchSysCacheTuple: Search %s(%d) %d %d %d %d failed",
- cacheinfo[cacheId].name,
- cacheId, key1, key2, key3, key4);
-#endif
- return (HeapTuple) NULL;
- }
- return tp;
+ return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
}
+/*
+ * ReleaseSysCache
+ * Release previously grabbed reference count on a tuple
+ */
+void
+ReleaseSysCache(HeapTuple tuple)
+{
+ ReleaseCatCache(tuple);
+}
/*
- * SearchSysCacheTupleCopy
+ * SearchSysCacheCopy
*
- * This is like SearchSysCacheTuple, except it returns a palloc'd copy of
- * the tuple. The caller should heap_freetuple() the returned copy when
- * done with it. This routine should be used when the caller intends to
- * continue to access the tuple for more than a very short period of time.
+ * A convenience routine that does SearchSysCache and (if successful)
+ * returns a modifiable copy of the syscache entry. The original
+ * syscache entry is released before returning. The caller should
+ * heap_freetuple() the result when done with it.
*/
HeapTuple
-SearchSysCacheTupleCopy(int cacheId, /* cache selection code */
- Datum key1,
- Datum key2,
- Datum key3,
- Datum key4)
+SearchSysCacheCopy(int cacheId,
+ Datum key1,
+ Datum key2,
+ Datum key3,
+ Datum key4)
{
- HeapTuple cachetup;
-
- cachetup = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
- if (PointerIsValid(cachetup))
- return heap_copytuple(cachetup);
- else
- return cachetup; /* NULL */
+ HeapTuple tuple,
+ newtuple;
+
+ tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
+ if (!HeapTupleIsValid(tuple))
+ return tuple;
+ newtuple = heap_copytuple(tuple);
+ ReleaseSysCache(tuple);
+ return newtuple;
}
+/*
+ * GetSysCacheOid
+ *
+ * A convenience routine that does SearchSysCache and returns the OID
+ * of the found tuple, or InvalidOid if no tuple could be found.
+ * No lock is retained on the syscache entry.
+ */
+Oid
+GetSysCacheOid(int cacheId,
+ Datum key1,
+ Datum key2,
+ Datum key3,
+ Datum key4)
+{
+ HeapTuple tuple;
+ Oid result;
+
+ tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
+ if (!HeapTupleIsValid(tuple))
+ return InvalidOid;
+ result = tuple->t_data->t_oid;
+ ReleaseSysCache(tuple);
+ return result;
+}
/*
* SysCacheGetAttr
*
- * Given a tuple previously fetched by SearchSysCacheTuple() or
- * SearchSysCacheTupleCopy(), extract a specific attribute.
+ * Given a tuple previously fetched by SearchSysCache(),
+ * extract a specific attribute.
*
* This is equivalent to using heap_getattr() on a tuple fetched
* from a non-cached relation. Usually, this is only used for attributes
diff --git a/src/backend/utils/cache/temprel.c b/src/backend/utils/cache/temprel.c
index 31591663cee..0134b47a0f9 100644
--- a/src/backend/utils/cache/temprel.c
+++ b/src/backend/utils/cache/temprel.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/temprel.c,v 1.30 2000/11/08 22:10:01 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/temprel.c,v 1.31 2000/11/16 22:30:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -34,7 +34,6 @@
#include "catalog/heap.h"
#include "catalog/index.h"
#include "miscadmin.h"
-#include "utils/catcache.h"
#include "utils/temprel.h"
diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c
index 3913dddeec2..2dfddebd0a8 100644
--- a/src/backend/utils/fmgr/dfmgr.c
+++ b/src/backend/utils/fmgr/dfmgr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.44 2000/07/05 23:11:40 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.45 2000/11/16 22:30:34 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -59,9 +59,9 @@ fmgr_dynamic(Oid functionId)
PGFunction user_fn;
bool isnull;
- procedureTuple = SearchSysCacheTuple(PROCOID,
- ObjectIdGetDatum(functionId),
- 0, 0, 0);
+ procedureTuple = SearchSysCache(PROCOID,
+ ObjectIdGetDatum(functionId),
+ 0, 0, 0);
if (!HeapTupleIsValid(procedureTuple))
elog(ERROR, "fmgr_dynamic: function %u: cache lookup failed",
functionId);
@@ -88,6 +88,8 @@ fmgr_dynamic(Oid functionId)
pfree(prosrcstring);
pfree(probinstring);
+ ReleaseSysCache(procedureTuple);
+
return user_fn;
}
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index c7fbf251f9d..5287615eea0 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.46 2000/08/24 03:29:07 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.47 2000/11/16 22:30:34 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -134,9 +134,9 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
}
/* Otherwise we need the pg_proc entry */
- procedureTuple = SearchSysCacheTuple(PROCOID,
- ObjectIdGetDatum(functionId),
- 0, 0, 0);
+ procedureTuple = SearchSysCache(PROCOID,
+ ObjectIdGetDatum(functionId),
+ 0, 0, 0);
if (!HeapTupleIsValid(procedureTuple))
elog(ERROR, "fmgr_info: function %u: cache lookup failed",
functionId);
@@ -149,6 +149,7 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
if (!procedureStruct->proistrusted)
{
finfo->fn_addr = fmgr_untrusted;
+ ReleaseSysCache(procedureTuple);
return;
}
@@ -202,14 +203,12 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
/*
* Might be a created procedural language; try to look it up.
*/
- languageTuple = SearchSysCacheTuple(LANGOID,
- ObjectIdGetDatum(language),
- 0, 0, 0);
+ languageTuple = SearchSysCache(LANGOID,
+ ObjectIdGetDatum(language),
+ 0, 0, 0);
if (!HeapTupleIsValid(languageTuple))
- {
elog(ERROR, "fmgr_info: cache lookup for language %u failed",
language);
- }
languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
if (languageStruct->lanispl)
{
@@ -231,8 +230,11 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
elog(ERROR, "fmgr_info: function %u: unsupported language %u",
functionId, language);
}
+ ReleaseSysCache(languageTuple);
break;
}
+
+ ReleaseSysCache(procedureTuple);
}
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 026f2cc8114..ec223157c4b 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.56 2000/11/04 12:43:24 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.57 2000/11/16 22:30:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -340,12 +340,15 @@ SetSessionUserIdFromUserName(const char *username)
*/
AssertState(!IsBootstrapProcessingMode());
- userTup = SearchSysCacheTuple(SHADOWNAME,
- PointerGetDatum(username),
- 0, 0, 0);
+ userTup = SearchSysCache(SHADOWNAME,
+ PointerGetDatum(username),
+ 0, 0, 0);
if (!HeapTupleIsValid(userTup))
elog(FATAL, "user \"%s\" does not exist", username);
+
SetSessionUserId( ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid );
+
+ ReleaseSysCache(userTup);
}
@@ -355,13 +358,19 @@ SetSessionUserIdFromUserName(const char *username)
char *
GetUserName(Oid userid)
{
- HeapTuple tuple;
+ HeapTuple tuple;
+ char *result;
- tuple = SearchSysCacheTuple(SHADOWSYSID, ObjectIdGetDatum(userid), 0, 0, 0);
+ tuple = SearchSysCache(SHADOWSYSID,
+ ObjectIdGetDatum(userid),
+ 0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "invalid user id %u", (unsigned) userid);
- return pstrdup( NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename) );
+ result = pstrdup( NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename) );
+
+ ReleaseSysCache(tuple);
+ return result;
}
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 3a9e5a1797b..bee4f7e9219 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.71 2000/11/14 18:37:44 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.72 2000/11/16 22:30:39 tgl Exp $
*
*
*-------------------------------------------------------------------------
@@ -320,10 +320,7 @@ InitPostgres(const char *dbname, const char *username)
/*
* Initialize all the system catalog caches.
- */
- zerocaches();
-
- /*
+ *
* Does not touch files since all routines are builtins (?) - thomas
* 1997-11-01
*/
diff --git a/src/backend/utils/misc/superuser.c b/src/backend/utils/misc/superuser.c
index 1852b35e465..5139247291d 100644
--- a/src/backend/utils/misc/superuser.c
+++ b/src/backend/utils/misc/superuser.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/misc/superuser.c,v 1.15 2000/09/06 14:15:22 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/misc/superuser.c,v 1.16 2000/11/16 22:30:40 tgl Exp $
*
* DESCRIPTION
* See superuser().
@@ -29,10 +29,16 @@ superuser(void)
privileges.
--------------------------------------------------------------------------*/
HeapTuple utup;
+ bool result;
- utup = SearchSysCacheTuple(SHADOWSYSID,
- ObjectIdGetDatum(GetUserId()),
- 0, 0, 0);
- Assert(utup != NULL);
- return ((Form_pg_shadow) GETSTRUCT(utup))->usesuper;
+ utup = SearchSysCache(SHADOWSYSID,
+ ObjectIdGetDatum(GetUserId()),
+ 0, 0, 0);
+ if (HeapTupleIsValid(utup))
+ {
+ result = ((Form_pg_shadow) GETSTRUCT(utup))->usesuper;
+ ReleaseSysCache(utup);
+ return result;
+ }
+ return false;
}
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index 1a0781dd921..a3c0784786d 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -78,7 +78,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplesort.c,v 1.10 2000/05/30 04:24:54 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplesort.c,v 1.11 2000/11/16 22:30:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -88,7 +88,6 @@
#include "access/heapam.h"
#include "access/nbtree.h"
#include "miscadmin.h"
-#include "parser/parse_type.h"
#include "utils/logtape.h"
#include "utils/lsyscache.h"
#include "utils/tuplesort.h"
@@ -506,7 +505,8 @@ tuplesort_begin_datum(Oid datumType,
bool randomAccess)
{
Tuplesortstate *state = tuplesort_begin_common(randomAccess);
- Type typeInfo;
+ int16 typlen;
+ bool typbyval;
state->comparetup = comparetup_datum;
state->copytup = copytup_datum;
@@ -519,9 +519,9 @@ tuplesort_begin_datum(Oid datumType,
/* lookup the function that implements the sort operator */
fmgr_info(get_opcode(sortOperator), &state->sortOpFn);
/* lookup necessary attributes of the datum type */
- typeInfo = typeidType(datumType);
- state->datumTypeLen = typeLen(typeInfo);
- state->datumTypeByVal = typeByVal(typeInfo);
+ get_typlenbyval(datumType, &typlen, &typbyval);
+ state->datumTypeLen = typlen;
+ state->datumTypeByVal = typbyval;
return state;
}