1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-26 12:21:12 +03:00

Clean up various to-do items associated with system indexes:

pg_database now has unique indexes on oid and on datname.
pg_shadow now has unique indexes on usename and on usesysid.
pg_am now has unique index on oid.
pg_opclass now has unique index on oid.
pg_amproc now has unique index on amid+amopclaid+amprocnum.
Remove pg_rewrite's unnecessary index on oid, delete unused RULEOID syscache.
Remove index on pg_listener and associated syscache for performance reasons
(caching rows that are certain to change before you need 'em again is
rather pointless).
Change pg_attrdef's nonunique index on adrelid into a unique index on
adrelid+adnum.

Fix various incorrect settings of pg_class.relisshared, make that the
primary reference point for whether a relation is shared or not.
IsSharedSystemRelationName() is now only consulted to initialize relisshared
during initial creation of tables and indexes.  In theory we might now
support shared user relations, though it's not clear how one would get
entries for them into pg_class &etc of multiple databases.

Fix recently reported bug that pg_attribute rows created for an index all have
the same OID.  (Proof that non-unique OID doesn't matter unless it's
actually used to do lookups ;-))

There's no need to treat pg_trigger, pg_attrdef, pg_relcheck as bootstrap
relations.  Convert them into plain system catalogs without hardwired
entries in pg_class and friends.

Unify global.bki and template1.bki into a single init script postgres.bki,
since the alleged distinction between them was misleading and pointless.
Not to mention that it didn't work for setting up indexes on shared
system relations.

Rationalize locking of pg_shadow, pg_group, pg_attrdef (no need to use
AccessExclusiveLock where ExclusiveLock or even RowExclusiveLock will do).
Also, hold locks until transaction commit where necessary.
This commit is contained in:
Tom Lane
2001-06-12 05:55:50 +00:00
parent d2c8358188
commit 1d584f97b9
30 changed files with 471 additions and 647 deletions

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.71 2001/03/22 06:16:06 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.72 2001/06/12 05:55:49 tgl Exp $
*
* NOTES
* The old interface functions have been converted to macros
@ -738,44 +738,46 @@ heap_freetuple(HeapTuple htup)
}
/* ----------------------------------------------------------------
* other misc functions
* ----------------------------------------------------------------
/* ----------------
* heap_addheader
*
* This routine forms a HeapTuple by copying the given structure (tuple
* data) and adding a generic header. Note that the tuple data is
* presumed to contain no null fields. It is typically only useful
* for null-free system tables.
* ----------------
*/
HeapTuple
heap_addheader(uint32 natts, /* max domain index */
int structlen, /* its length */
char *structure) /* pointer to the struct */
heap_addheader(int natts, /* max domain index */
Size structlen, /* its length */
void *structure) /* pointer to the struct */
{
HeapTuple tuple;
HeapTupleHeader td; /* tuple data */
unsigned long len;
HeapTupleHeader td;
Size len;
int hoff;
AssertArg(natts > 0);
len = offsetof(HeapTupleHeaderData, t_bits);
/* header needs no null bitmap */
hoff = MAXALIGN(offsetof(HeapTupleHeaderData, t_bits));
len = hoff + structlen;
hoff = len = MAXALIGN(len); /* be conservative */
len += structlen;
tuple = (HeapTuple) palloc(HEAPTUPLESIZE + len);
tuple->t_datamcxt = CurrentMemoryContext;
td = tuple->t_data = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
tuple->t_len = len;
ItemPointerSetInvalid(&(tuple->t_self));
tuple->t_tableOid = InvalidOid;
tuple->t_datamcxt = CurrentMemoryContext;
tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
MemSet((char *) td, 0, len);
td->t_hoff = hoff;
td->t_natts = natts;
td->t_infomask = 0;
td->t_infomask |= HEAP_XMAX_INVALID;
td->t_infomask = HEAP_XMAX_INVALID; /* XXX sufficient? */
if (structlen > 0)
memcpy((char *) td + hoff, structure, (size_t) structlen);
memcpy((char *) td + hoff, structure, structlen);
return tuple;
}

View File

@ -2,7 +2,7 @@
#
# Makefile for catalog
#
# $Header: /cvsroot/pgsql/src/backend/catalog/Makefile,v 1.34 2001/05/14 21:58:10 momjian Exp $
# $Header: /cvsroot/pgsql/src/backend/catalog/Makefile,v 1.35 2001/06/12 05:55:49 tgl Exp $
#
#-------------------------------------------------------------------------
@ -14,42 +14,36 @@ OBJS = catalog.o heap.o index.o indexing.o aclchk.o \
pg_aggregate.o pg_largeobject.o pg_operator.o pg_proc.o \
pg_type.o
BKIFILES = global.bki template1.bki global.description template1.description
BKIFILES = postgres.bki postgres.description
all: SUBSYS.o $(BKIFILES)
SUBSYS.o: $(OBJS)
$(LD) $(LDREL) $(LDOUT) SUBSYS.o $(OBJS)
# Note: there are some undocumented dependencies on the ordering in which
# the catalog header files are assembled into postgres.bki. In particular,
# indexing.h had better be last.
GLOBAL_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/,\
pg_database.h pg_shadow.h pg_group.h pg_log.h \
)
TEMPLATE1_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/,\
POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/,\
pg_proc.h pg_type.h pg_attribute.h pg_class.h \
pg_inherits.h pg_index.h pg_statistic.h \
pg_attrdef.h pg_relcheck.h pg_inherits.h pg_index.h \
pg_operator.h pg_opclass.h pg_am.h pg_amop.h pg_amproc.h \
pg_language.h pg_largeobject.h pg_aggregate.h \
pg_rewrite.h pg_listener.h pg_description.h indexing.h \
pg_language.h pg_largeobject.h pg_aggregate.h pg_statistic.h \
pg_rewrite.h pg_trigger.h pg_listener.h pg_description.h \
pg_database.h pg_shadow.h pg_group.h pg_log.h indexing.h \
)
pg_includes := $(sort -I$(top_srcdir)/src/include -I$(top_builddir)/src/include)
global.bki global.description: genbki.sh $(GLOBAL_BKI_SRCS) $(top_srcdir)/src/include/catalog/indexing.h \
postgres.bki postgres.description: genbki.sh $(POSTGRES_BKI_SRCS) \
$(top_srcdir)/src/include/postgres_ext.h $(top_builddir)/src/include/config.h
CPP='$(CPP)' AWK='$(AWK)' $(SHELL) $< $(BKIOPTS) -o global $(pg_includes) $(GLOBAL_BKI_SRCS) --set-version=$(VERSION)
template1.bki template1.description: genbki.sh $(TEMPLATE1_BKI_SRCS) \
$(top_srcdir)/src/include/postgres_ext.h $(top_builddir)/src/include/config.h
CPP='$(CPP)' AWK='$(AWK)' $(SHELL) $< $(BKIOPTS) -o template1 $(pg_includes) $(TEMPLATE1_BKI_SRCS) --set-version=$(VERSION)
CPP='$(CPP)' AWK='$(AWK)' $(SHELL) $< $(BKIOPTS) -o postgres $(pg_includes) $(POSTGRES_BKI_SRCS) --set-version=$(VERSION)
.PHONY: install-bki
install-bki: $(BKIFILES) installdirs
$(INSTALL_DATA) global.bki $(DESTDIR)$(datadir)/global.bki
$(INSTALL_DATA) global.description $(DESTDIR)$(datadir)/global.description
$(INSTALL_DATA) template1.bki $(DESTDIR)$(datadir)/template1.bki
$(INSTALL_DATA) template1.description $(DESTDIR)$(datadir)/template1.description
$(INSTALL_DATA) postgres.bki $(DESTDIR)$(datadir)/postgres.bki
$(INSTALL_DATA) postgres.description $(DESTDIR)$(datadir)/postgres.description
installdirs:
$(mkinstalldirs) $(DESTDIR)$(datadir)

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.166 2001/05/30 12:57:36 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.167 2001/06/12 05:55:49 tgl Exp $
*
*
* INTERFACE ROUTINES
@ -218,8 +218,9 @@ heap_create(char *relname,
}
/*
* real ugly stuff to assign the proper relid in the relation
* descriptor follows.
* Real ugly stuff to assign the proper relid in the relation
* descriptor follows. Note that only "bootstrapped" relations
* whose OIDs are hard-coded in pg_class.h need be listed here.
*/
if (relname && IsSystemRelationName(relname))
{
@ -263,12 +264,6 @@ heap_create(char *relname,
tblNode = InvalidOid;
relid = RelOid_pg_log;
}
else if (strcmp(AttrDefaultRelationName, relname) == 0)
relid = RelOid_pg_attrdef;
else if (strcmp(RelCheckRelationName, relname) == 0)
relid = RelOid_pg_relcheck;
else if (strcmp(TriggerRelationName, relname) == 0)
relid = RelOid_pg_trigger;
else
{
relid = newoid();
@ -566,7 +561,7 @@ AddNewAttributeTuples(Oid new_rel_oid,
tup = heap_addheader(Natts_pg_attribute,
ATTRIBUTE_TUPLE_SIZE,
(char *) *dpp);
(void *) *dpp);
heap_insert(rel, tup);
@ -583,16 +578,18 @@ AddNewAttributeTuples(Oid new_rel_oid,
dpp = SysAtt;
for (i = 0; i < -1 - FirstLowInvalidHeapAttributeNumber; i++)
{
/* Fill in the correct relation OID */
/* HACK: we are writing on static data here */
(*dpp)->attrelid = new_rel_oid;
/* Unneeded since they should be OK in the constant data anyway */
/* (*dpp)->attstattarget = 0; */
/* (*dpp)->attcacheoff = -1; */
Form_pg_attribute attStruct;
tup = heap_addheader(Natts_pg_attribute,
ATTRIBUTE_TUPLE_SIZE,
(char *) *dpp);
(void *) *dpp);
/* Fill in the correct relation OID in the copied tuple */
attStruct = (Form_pg_attribute) GETSTRUCT(tup);
attStruct->attrelid = new_rel_oid;
/* Unneeded since they should be OK in the constant data anyway */
/* attStruct->attstattarget = 0; */
/* attStruct->attcacheoff = -1; */
heap_insert(rel, tup);
@ -603,13 +600,13 @@ AddNewAttributeTuples(Oid new_rel_oid,
dpp++;
}
heap_close(rel, RowExclusiveLock);
/*
* close pg_attribute indices
*/
if (hasindex)
CatalogCloseIndices(Num_pg_attr_indices, idescs);
heap_close(rel, RowExclusiveLock);
}
/* --------------------------------
@ -686,7 +683,7 @@ AddNewRelationTuple(Relation pg_class_desc,
*/
tup = heap_addheader(Natts_pg_class_fixed,
CLASS_TUPLE_SIZE,
(char *) new_rel_reltup);
(void *) new_rel_reltup);
/* force tuple to have the desired OID */
tup->t_data->t_oid = new_rel_oid;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.153 2001/06/01 02:41:35 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.154 2001/06/12 05:55:49 tgl Exp $
*
*
* INTERFACE ROUTINES
@ -343,17 +343,19 @@ AccessMethodObjectIdGetForm(Oid accessMethodObjectId,
static void
ConstructIndexReldesc(Relation indexRelation, Oid amoid)
{
indexRelation->rd_am = AccessMethodObjectIdGetForm(amoid,
CacheMemoryContext);
/*
* XXX missing the initialization of some other fields
* Fill in a copy of relevant pg_am entry
*/
indexRelation->rd_am = AccessMethodObjectIdGetForm(amoid,
CacheMemoryContext);
/*
* Set up some additional fields of the index' pg_class entry.
* In particular, initialize knowledge of whether the index is shared.
*/
indexRelation->rd_rel->relowner = GetUserId();
indexRelation->rd_rel->relam = amoid;
indexRelation->rd_rel->reltuples = 1; /* XXX */
indexRelation->rd_rel->relisshared =
IsSharedSystemRelationName(RelationGetPhysicalRelationName(indexRelation));
indexRelation->rd_rel->relkind = RELKIND_INDEX;
}
@ -374,7 +376,7 @@ UpdateRelationRelation(Relation indexRelation, char *temp_relname)
/* XXX Natts_pg_class_fixed is a hack - see pg_class.h */
tuple = heap_addheader(Natts_pg_class_fixed,
CLASS_TUPLE_SIZE,
(char *) indexRelation->rd_rel);
(void *) indexRelation->rd_rel);
/*
* the new tuple must have the same oid as the relcache entry for the
@ -428,23 +430,16 @@ InitializeAttributeOids(Relation indexRelation,
/* ----------------------------------------------------------------
* AppendAttributeTuples
*
* XXX For now, only change the ATTNUM attribute value
* ----------------------------------------------------------------
*/
static void
AppendAttributeTuples(Relation indexRelation, int numatts)
{
Relation pg_attribute;
HeapTuple init_tuple,
cur_tuple = NULL,
new_tuple;
bool hasind;
Relation idescs[Num_pg_attr_indices];
Datum value[Natts_pg_attribute];
char nullv[Natts_pg_attribute];
char replace[Natts_pg_attribute];
TupleDesc indexTupDesc;
HeapTuple new_tuple;
int i;
/*
@ -452,27 +447,6 @@ AppendAttributeTuples(Relation indexRelation, int numatts)
*/
pg_attribute = heap_openr(AttributeRelationName, RowExclusiveLock);
/*
* initialize *null, *replace and *value
*/
MemSet(nullv, ' ', Natts_pg_attribute);
MemSet(replace, ' ', Natts_pg_attribute);
/* ----------
* create the first attribute tuple.
* XXX For now, only change the ATTNUM attribute value
* ----------
*/
replace[Anum_pg_attribute_attnum - 1] = 'r';
replace[Anum_pg_attribute_attcacheoff - 1] = 'r';
value[Anum_pg_attribute_attnum - 1] = Int16GetDatum(1);
value[Anum_pg_attribute_attcacheoff - 1] = Int32GetDatum(-1);
init_tuple = heap_addheader(Natts_pg_attribute,
ATTRIBUTE_TUPLE_SIZE,
(char *) (indexRelation->rd_att->attrs[0]));
hasind = false;
if (!IsIgnoringSystemIndexes() && pg_attribute->rd_rel->relhasindex)
{
@ -481,60 +455,35 @@ AppendAttributeTuples(Relation indexRelation, int numatts)
}
/*
* insert the first attribute tuple.
*/
cur_tuple = heap_modifytuple(init_tuple,
pg_attribute,
value,
nullv,
replace);
heap_freetuple(init_tuple);
heap_insert(pg_attribute, cur_tuple);
if (hasind)
CatalogIndexInsert(idescs, Num_pg_attr_indices, pg_attribute, cur_tuple);
/*
* now we use the information in the index cur_tuple descriptor to
* form the remaining attribute tuples.
* insert data from new index's tupdesc into pg_attribute
*/
indexTupDesc = RelationGetDescr(indexRelation);
for (i = 1; i < numatts; i += 1)
for (i = 0; i < numatts; i++)
{
/*
* process the remaining attributes...
* There used to be very grotty code here to set these fields,
* but I think it's unnecessary. They should be set already.
*/
memmove(GETSTRUCT(cur_tuple),
(char *) indexTupDesc->attrs[i],
ATTRIBUTE_TUPLE_SIZE);
Assert(indexTupDesc->attrs[i]->attnum == i+1);
Assert(indexTupDesc->attrs[i]->attcacheoff == -1);
value[Anum_pg_attribute_attnum - 1] = Int16GetDatum(i + 1);
new_tuple = heap_modifytuple(cur_tuple,
pg_attribute,
value,
nullv,
replace);
heap_freetuple(cur_tuple);
new_tuple = heap_addheader(Natts_pg_attribute,
ATTRIBUTE_TUPLE_SIZE,
(void *) indexTupDesc->attrs[i]);
heap_insert(pg_attribute, new_tuple);
if (hasind)
CatalogIndexInsert(idescs, Num_pg_attr_indices, pg_attribute, new_tuple);
/*
* ModifyHeapTuple returns a new copy of a cur_tuple so we free
* the original and use the copy..
*/
cur_tuple = new_tuple;
heap_freetuple(new_tuple);
}
if (cur_tuple)
heap_freetuple(cur_tuple);
heap_close(pg_attribute, RowExclusiveLock);
if (hasind)
CatalogCloseIndices(Num_pg_attr_indices, idescs);
heap_close(pg_attribute, RowExclusiveLock);
}
/* ----------------------------------------------------------------
@ -613,7 +562,7 @@ UpdateIndexRelation(Oid indexoid,
*/
tuple = heap_addheader(Natts_pg_index,
itupLen,
(char *) indexForm);
(void *) indexForm);
/*
* insert the tuple into the pg_index
@ -1994,7 +1943,7 @@ reindex_index(Oid indexId, bool force, bool inplace)
if (!inplace)
{
inplace = IsSharedSystemRelationName(NameStr(iRel->rd_rel->relname));
inplace = iRel->rd_rel->relisshared;
if (!inplace)
setNewRelfilenode(iRel);
}
@ -2114,7 +2063,7 @@ reindex_relation(Oid relid, bool force)
* Shared system indexes must be overwritten because it's impossible
* to update pg_class tuples of all databases.
*/
if (IsSharedSystemRelationName(NameStr(rel->rd_rel->relname)))
if (rel->rd_rel->relisshared)
{
if (IsIgnoringSystemIndexes())
{

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.77 2001/03/22 03:59:20 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.78 2001/06/12 05:55:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -28,21 +28,25 @@
#include "utils/syscache.h"
/*
* Names of indices - they match all system caches
* Names of indices for each system catalog.
*/
char *Name_pg_aggregate_indices[Num_pg_aggregate_indices] =
{AggregateNameTypeIndex};
char *Name_pg_am_indices[Num_pg_am_indices] =
{AmNameIndex};
{AmNameIndex, AmOidIndex};
char *Name_pg_amop_indices[Num_pg_amop_indices] =
{AccessMethodOpidIndex, AccessMethodStrategyIndex};
char *Name_pg_amproc_indices[Num_pg_amproc_indices] =
{AccessProcedureIndex};
char *Name_pg_attr_indices[Num_pg_attr_indices] =
{AttributeRelidNameIndex, AttributeRelidNumIndex};
char *Name_pg_attrdef_indices[Num_pg_attrdef_indices] =
{AttrDefaultIndex};
char *Name_pg_class_indices[Num_pg_class_indices] =
{ClassNameIndex, ClassOidIndex};
char *Name_pg_database_indices[Num_pg_database_indices] =
{DatabaseNameIndex, DatabaseOidIndex};
char *Name_pg_group_indices[Num_pg_group_indices] =
{GroupNameIndex, GroupSysidIndex};
char *Name_pg_index_indices[Num_pg_index_indices] =
@ -53,10 +57,8 @@ char *Name_pg_language_indices[Num_pg_language_indices] =
{LanguageOidIndex, LanguageNameIndex};
char *Name_pg_largeobject_indices[Num_pg_largeobject_indices] =
{LargeObjectLOidPNIndex};
char *Name_pg_listener_indices[Num_pg_listener_indices] =
{ListenerPidRelnameIndex};
char *Name_pg_opclass_indices[Num_pg_opclass_indices] =
{OpclassNameIndex, OpclassDeftypeIndex};
{OpclassDeftypeIndex, OpclassNameIndex, OpclassOidIndex};
char *Name_pg_operator_indices[Num_pg_operator_indices] =
{OperatorOidIndex, OperatorNameIndex};
char *Name_pg_proc_indices[Num_pg_proc_indices] =
@ -64,7 +66,7 @@ char *Name_pg_proc_indices[Num_pg_proc_indices] =
char *Name_pg_relcheck_indices[Num_pg_relcheck_indices] =
{RelCheckIndex};
char *Name_pg_rewrite_indices[Num_pg_rewrite_indices] =
{RewriteOidIndex, RewriteRulenameIndex};
{RewriteRulenameIndex};
char *Name_pg_shadow_indices[Num_pg_shadow_indices] =
{ShadowNameIndex, ShadowSysidIndex};
char *Name_pg_statistic_indices[Num_pg_statistic_indices] =

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.77 2001/03/22 03:59:21 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.78 2001/06/12 05:55:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -80,7 +80,6 @@
#include "access/heapam.h"
#include "catalog/catname.h"
#include "catalog/indexing.h"
#include "catalog/pg_listener.h"
#include "commands/async.h"
#include "lib/dllist.h"
@ -195,11 +194,12 @@ void
Async_Listen(char *relname, int pid)
{
Relation lRel;
HeapScanDesc scan;
HeapTuple tuple;
Datum values[Natts_pg_listener];
char nulls[Natts_pg_listener];
int i;
TupleDesc tupDesc;
bool alreadyListener = false;
if (Trace_notify)
elog(DEBUG, "Async_Listen: %s", relname);
@ -207,12 +207,23 @@ Async_Listen(char *relname, int pid)
lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
/* Detect whether we are already listening on this relname */
if (SearchSysCacheExists(LISTENREL,
Int32GetDatum(pid),
PointerGetDatum(relname),
0, 0))
scan = heap_beginscan(lRel, 0, SnapshotNow, 0, (ScanKey) NULL);
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
{
Form_pg_listener listener = (Form_pg_listener) GETSTRUCT(tuple);
if (listener->listenerpid == pid &&
strncmp(NameStr(listener->relname), relname, NAMEDATALEN) == 0)
{
alreadyListener = true;
/* No need to scan the rest of the table */
break;
}
}
heap_endscan(scan);
if (alreadyListener)
{
/* No need to scan the rest of the table */
heap_close(lRel, AccessExclusiveLock);
elog(NOTICE, "Async_Listen: We are already listening on %s", relname);
return;
@ -233,9 +244,10 @@ Async_Listen(char *relname, int pid)
values[i++] = (Datum) pid;
values[i++] = (Datum) 0; /* no notifies pending */
tupDesc = lRel->rd_att;
tuple = heap_formtuple(tupDesc, values, nulls);
tuple = heap_formtuple(RelationGetDescr(lRel), values, nulls);
heap_insert(lRel, tuple);
#ifdef NOT_USED /* currently there are no indexes */
if (RelationGetForm(lRel)->relhasindex)
{
Relation idescs[Num_pg_listener_indices];
@ -244,6 +256,7 @@ Async_Listen(char *relname, int pid)
CatalogIndexInsert(idescs, Num_pg_listener_indices, lRel, tuple);
CatalogCloseIndices(Num_pg_listener_indices, idescs);
}
#endif
heap_freetuple(tuple);
@ -280,7 +293,8 @@ void
Async_Unlisten(char *relname, int pid)
{
Relation lRel;
HeapTuple lTuple;
HeapScanDesc scan;
HeapTuple tuple;
/* Handle specially the `unlisten "*"' command */
if ((!relname) || (*relname == '\0') || (strcmp(relname, "*") == 0))
@ -293,16 +307,26 @@ Async_Unlisten(char *relname, int pid)
elog(DEBUG, "Async_Unlisten %s", relname);
lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
/* Note we assume there can be only one matching tuple. */
lTuple = SearchSysCache(LISTENREL,
Int32GetDatum(pid),
PointerGetDatum(relname),
0, 0);
if (HeapTupleIsValid(lTuple))
scan = heap_beginscan(lRel, 0, SnapshotNow, 0, (ScanKey) NULL);
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
{
simple_heap_delete(lRel, &lTuple->t_self);
ReleaseSysCache(lTuple);
Form_pg_listener listener = (Form_pg_listener) GETSTRUCT(tuple);
if (listener->listenerpid == pid &&
strncmp(NameStr(listener->relname), relname, NAMEDATALEN) == 0)
{
/* Found the matching tuple, delete it */
simple_heap_delete(lRel, &tuple->t_self);
/*
* We assume there can be only one match, so no need
* to scan the rest of the table
*/
break;
}
}
heap_endscan(scan);
heap_close(lRel, AccessExclusiveLock);
/*
@ -332,7 +356,7 @@ Async_UnlistenAll()
{
Relation lRel;
TupleDesc tdesc;
HeapScanDesc sRel;
HeapScanDesc scan;
HeapTuple lTuple;
ScanKeyData key[1];
@ -347,12 +371,12 @@ Async_UnlistenAll()
Anum_pg_listener_pid,
F_INT4EQ,
Int32GetDatum(MyProcPid));
sRel = heap_beginscan(lRel, 0, SnapshotNow, 1, key);
scan = heap_beginscan(lRel, 0, SnapshotNow, 1, key);
while (HeapTupleIsValid(lTuple = heap_getnext(sRel, 0)))
while (HeapTupleIsValid(lTuple = heap_getnext(scan, 0)))
simple_heap_delete(lRel, &lTuple->t_self);
heap_endscan(sRel);
heap_endscan(scan);
heap_close(lRel, AccessExclusiveLock);
}
@ -418,16 +442,12 @@ AtCommit_Notify()
{
Relation lRel;
TupleDesc tdesc;
HeapScanDesc sRel;
HeapScanDesc scan;
HeapTuple lTuple,
rTuple;
Datum d,
value[Natts_pg_listener];
Datum value[Natts_pg_listener];
char repl[Natts_pg_listener],
nulls[Natts_pg_listener];
bool isnull;
char *relname;
int32 listenerPID;
if (!pendingNotifies)
return; /* no NOTIFY statements in this
@ -446,10 +466,6 @@ AtCommit_Notify()
if (Trace_notify)
elog(DEBUG, "AtCommit_Notify");
lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
tdesc = RelationGetDescr(lRel);
sRel = heap_beginscan(lRel, 0, SnapshotNow, 0, (ScanKey) NULL);
/* preset data to update notify column to MyProcPid */
nulls[0] = nulls[1] = nulls[2] = ' ';
repl[0] = repl[1] = repl[2] = ' ';
@ -457,83 +473,81 @@ AtCommit_Notify()
value[0] = value[1] = value[2] = (Datum) 0;
value[Anum_pg_listener_notify - 1] = Int32GetDatum(MyProcPid);
while (HeapTupleIsValid(lTuple = heap_getnext(sRel, 0)))
lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
tdesc = RelationGetDescr(lRel);
scan = heap_beginscan(lRel, 0, SnapshotNow, 0, (ScanKey) NULL);
while (HeapTupleIsValid(lTuple = heap_getnext(scan, 0)))
{
d = heap_getattr(lTuple, Anum_pg_listener_relname, tdesc, &isnull);
relname = (char *) DatumGetPointer(d);
Form_pg_listener listener = (Form_pg_listener) GETSTRUCT(lTuple);
char *relname = NameStr(listener->relname);
int32 listenerPID = listener->listenerpid;
if (AsyncExistsPendingNotify(relname))
if (! AsyncExistsPendingNotify(relname))
continue;
if (listenerPID == MyProcPid)
{
d = heap_getattr(lTuple, Anum_pg_listener_pid, tdesc, &isnull);
listenerPID = DatumGetInt32(d);
/*
* Self-notify: no need to bother with table update.
* Indeed, we *must not* clear the notification field in
* this path, or we could lose an outside notify, which'd
* be bad for applications that ignore self-notify messages.
*/
if (listenerPID == MyProcPid)
if (Trace_notify)
elog(DEBUG, "AtCommit_Notify: notifying self");
NotifyMyFrontEnd(relname, listenerPID);
}
else
{
if (Trace_notify)
elog(DEBUG, "AtCommit_Notify: notifying pid %d",
listenerPID);
/*
* If someone has already notified this listener, we don't
* bother modifying the table, but we do still send a
* SIGUSR2 signal, just in case that backend missed the
* earlier signal for some reason. It's OK to send the
* signal first, because the other guy can't read
* pg_listener until we unlock it.
*/
if (kill(listenerPID, SIGUSR2) < 0)
{
/*
* Self-notify: no need to bother with table update.
* Indeed, we *must not* clear the notification field in
* this path, or we could lose an outside notify, which'd
* be bad for applications that ignore self-notify
* messages.
* Get rid of pg_listener entry if it refers to a PID
* that no longer exists. Presumably, that backend
* crashed without deleting its pg_listener entries.
* This code used to only delete the entry if
* errno==ESRCH, but as far as I can see we should
* just do it for any failure (certainly at least for
* EPERM too...)
*/
if (Trace_notify)
elog(DEBUG, "AtCommit_Notify: notifying self");
NotifyMyFrontEnd(relname, listenerPID);
simple_heap_delete(lRel, &lTuple->t_self);
}
else
else if (listener->notification == 0)
{
if (Trace_notify)
elog(DEBUG, "AtCommit_Notify: notifying pid %d", listenerPID);
rTuple = heap_modifytuple(lTuple, lRel,
value, nulls, repl);
simple_heap_update(lRel, &lTuple->t_self, rTuple);
/*
* If someone has already notified this listener, we don't
* bother modifying the table, but we do still send a
* SIGUSR2 signal, just in case that backend missed the
* earlier signal for some reason. It's OK to send the
* signal first, because the other guy can't read
* pg_listener until we unlock it.
*/
if (kill(listenerPID, SIGUSR2) < 0)
#ifdef NOT_USED /* currently there are no indexes */
if (RelationGetForm(lRel)->relhasindex)
{
Relation idescs[Num_pg_listener_indices];
/*
* Get rid of pg_listener entry if it refers to a PID
* that no longer exists. Presumably, that backend
* crashed without deleting its pg_listener entries.
* This code used to only delete the entry if
* errno==ESRCH, but as far as I can see we should
* just do it for any failure (certainly at least for
* EPERM too...)
*/
simple_heap_delete(lRel, &lTuple->t_self);
}
else
{
d = heap_getattr(lTuple, Anum_pg_listener_notify,
tdesc, &isnull);
if (DatumGetInt32(d) == 0)
{
rTuple = heap_modifytuple(lTuple, lRel,
value, nulls, repl);
simple_heap_update(lRel, &lTuple->t_self, rTuple);
if (RelationGetForm(lRel)->relhasindex)
{
Relation idescs[Num_pg_listener_indices];
CatalogOpenIndices(Num_pg_listener_indices, Name_pg_listener_indices, idescs);
CatalogIndexInsert(idescs, Num_pg_listener_indices, lRel, rTuple);
CatalogCloseIndices(Num_pg_listener_indices, idescs);
}
}
CatalogOpenIndices(Num_pg_listener_indices, Name_pg_listener_indices, idescs);
CatalogIndexInsert(idescs, Num_pg_listener_indices, lRel, rTuple);
CatalogCloseIndices(Num_pg_listener_indices, idescs);
}
#endif
}
}
}
heap_endscan(sRel);
heap_endscan(scan);
/*
* We do NOT release the lock on pg_listener here; we need to hold it
@ -745,16 +759,12 @@ ProcessIncomingNotify(void)
Relation lRel;
TupleDesc tdesc;
ScanKeyData key[1];
HeapScanDesc sRel;
HeapScanDesc scan;
HeapTuple lTuple,
rTuple;
Datum d,
value[Natts_pg_listener];
Datum value[Natts_pg_listener];
char repl[Natts_pg_listener],
nulls[Natts_pg_listener];
bool isnull;
char *relname;
int32 sourcePID;
if (Trace_notify)
elog(DEBUG, "ProcessIncomingNotify");
@ -773,7 +783,7 @@ ProcessIncomingNotify(void)
Anum_pg_listener_pid,
F_INT4EQ,
Int32GetDatum(MyProcPid));
sRel = heap_beginscan(lRel, 0, SnapshotNow, 1, key);
scan = heap_beginscan(lRel, 0, SnapshotNow, 1, key);
/* Prepare data for rewriting 0 into notification field */
nulls[0] = nulls[1] = nulls[2] = ' ';
@ -782,14 +792,14 @@ ProcessIncomingNotify(void)
value[0] = value[1] = value[2] = (Datum) 0;
value[Anum_pg_listener_notify - 1] = Int32GetDatum(0);
while (HeapTupleIsValid(lTuple = heap_getnext(sRel, 0)))
while (HeapTupleIsValid(lTuple = heap_getnext(scan, 0)))
{
d = heap_getattr(lTuple, Anum_pg_listener_notify, tdesc, &isnull);
sourcePID = DatumGetInt32(d);
Form_pg_listener listener = (Form_pg_listener) GETSTRUCT(lTuple);
char *relname = NameStr(listener->relname);
int32 sourcePID = listener->notification;
if (sourcePID != 0)
{
d = heap_getattr(lTuple, Anum_pg_listener_relname, tdesc, &isnull);
relname = (char *) DatumGetPointer(d);
/* Notify the frontend */
if (Trace_notify)
@ -800,6 +810,8 @@ ProcessIncomingNotify(void)
/* Rewrite the tuple with 0 in notification column */
rTuple = heap_modifytuple(lTuple, lRel, value, nulls, repl);
simple_heap_update(lRel, &lTuple->t_self, rTuple);
#ifdef NOT_USED /* currently there are no indexes */
if (RelationGetForm(lRel)->relhasindex)
{
Relation idescs[Num_pg_listener_indices];
@ -808,9 +820,10 @@ ProcessIncomingNotify(void)
CatalogIndexInsert(idescs, Num_pg_listener_indices, lRel, rTuple);
CatalogCloseIndices(Num_pg_listener_indices, idescs);
}
#endif
}
}
heap_endscan(sRel);
heap_endscan(scan);
/*
* We do NOT release the lock on pg_listener here; we need to hold it
@ -876,7 +889,7 @@ AsyncExistsPendingNotify(char *relname)
p = DLGetSucc(p))
{
/* Use NAMEDATALEN for relname comparison. DZ - 26-08-1996 */
if (!strncmp((const char *) DLE_VAL(p), relname, NAMEDATALEN))
if (strncmp((const char *) DLE_VAL(p), relname, NAMEDATALEN) == 0)
return 1;
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.132 2001/06/07 00:09:28 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.133 2001/06/12 05:55:49 tgl Exp $
*
* NOTES
* The PerformAddAttribute() code, like most of the relation
@ -411,8 +411,8 @@ AlterTableAddColumn(const char *relationName,
attributeD.attrelid = reltup->t_data->t_oid;
attributeTuple = heap_addheader(Natts_pg_attribute,
sizeof attributeD,
(char *) &attributeD);
ATTRIBUTE_TUPLE_SIZE,
(void *) &attributeD);
attribute = (Form_pg_attribute) GETSTRUCT(attributeTuple);
@ -481,7 +481,7 @@ AlterTableAddColumn(const char *relationName,
if (hasindex)
CatalogCloseIndices(Num_pg_attr_indices, idescs);
heap_close(attrdesc, RowExclusiveLock);
heap_close(attrdesc, NoLock);
/*
* Update number of attributes in pg_class tuple
@ -580,17 +580,15 @@ AlterTableAlterColumnDefault(const char *relationName,
PointerGetDatum(colName),
0, 0);
if (!HeapTupleIsValid(tuple))
{
heap_close(rel, AccessExclusiveLock);
elog(ERROR, "ALTER TABLE: relation \"%s\" has no column \"%s\"",
relationName, colName);
}
attnum = ((Form_pg_attribute) GETSTRUCT(tuple))->attnum;
ReleaseSysCache(tuple);
if (newDefault) /* SET DEFAULT */
if (newDefault)
{
/* SET DEFAULT */
List *rawDefaults = NIL;
RawColumnDefault *rawEnt;
@ -608,15 +606,14 @@ AlterTableAlterColumnDefault(const char *relationName,
*/
AddRelationRawConstraints(rel, rawDefaults, NIL);
}
else
/* DROP DEFAULT */
{
/* DROP DEFAULT */
Relation attr_rel;
ScanKeyData scankeys[3];
HeapScanDesc scan;
attr_rel = heap_openr(AttributeRelationName, AccessExclusiveLock);
attr_rel = heap_openr(AttributeRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&scankeys[0], 0x0,
Anum_pg_attribute_attrelid, F_OIDEQ,
ObjectIdGetDatum(myrelid));
@ -665,7 +662,7 @@ drop_default(Oid relid, int16 attnum)
Relation attrdef_rel;
HeapTuple tuple;
attrdef_rel = heap_openr(AttrDefaultRelationName, AccessExclusiveLock);
attrdef_rel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&scankeys[0], 0x0,
Anum_pg_attrdef_adrelid, F_OIDEQ,
ObjectIdGetDatum(relid));
@ -778,7 +775,7 @@ AlterTableAlterColumnStatistics(const char *relationName,
}
heap_freetuple(tuple);
heap_close(attrelation, RowExclusiveLock);
heap_close(attrelation, NoLock);
}
@ -1010,8 +1007,7 @@ AlterTableDropColumn(const char *relationName,
{
#ifdef _DROP_COLUMN_HACK__
Relation rel,
attrdesc,
adrel;
attrdesc;
Oid myrelid,
attoid;
HeapTuple reltup;
@ -1023,8 +1019,6 @@ AlterTableDropColumn(const char *relationName,
int attnum;
bool hasindex;
char dropColname[32];
void *sysscan;
ScanKeyData scankeys[2];
if (inh)
elog(ERROR, "ALTER TABLE / DROP COLUMN with inherit option is not supported yet");
@ -1136,30 +1130,9 @@ AlterTableDropColumn(const char *relationName,
/* delete comments */
DeleteComments(attoid);
/* delete attrdef */
adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&scankeys[0], 0x0, Anum_pg_attrdef_adrelid,
F_OIDEQ, ObjectIdGetDatum(myrelid));
/*--------
* Oops pg_attrdef doesn't have (adrelid,adnum) index
*
* ScanKeyEntryInitialize(&scankeys[1], 0x0, Anum_pg_attrdef_adnum,
* F_INT2EQ, Int16GetDatum(attnum));
* sysscan = systable_beginscan(adrel, AttrDefaultIndex, 2, scankeys);
*--------
*/
sysscan = systable_beginscan(adrel, AttrDefaultIndex, 1, scankeys);
while (HeapTupleIsValid(tup = systable_getnext(sysscan)))
{
if (((Form_pg_attrdef) GETSTRUCT(tup))->adnum == attnum)
{
simple_heap_delete(adrel, &tup->t_self);
break;
}
}
systable_endscan(sysscan);
heap_close(adrel, NoLock);
/* delete attrdef */
drop_default(myrelid, attnum);
/*
* Remove objects which reference this column
@ -1318,10 +1291,7 @@ AlterTableAddConstraint(char *relationName,
heap_endscan(scan);
if (!successful)
{
heap_close(rel, NoLock);
elog(ERROR, "AlterTableAddConstraint: rejected due to CHECK constraint %s", name);
}
/*
* Call AddRelationRawConstraints to do the
@ -1768,7 +1738,7 @@ AlterTableOwner(const char *relationName, const char *newOwnerName)
* unlock everything and return
*/
heap_freetuple(tuple);
heap_close(class_rel, RowExclusiveLock);
heap_close(class_rel, NoLock);
}

View File

@ -1,6 +1,7 @@
/*-------------------------------------------------------------------------
*
* dbcommands.c
* Database management commands (create/drop database).
*
*
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
@ -8,7 +9,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.74 2001/03/22 03:59:22 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.75 2001/06/12 05:55:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -25,6 +26,7 @@
#include "catalog/catalog.h"
#include "catalog/pg_database.h"
#include "catalog/pg_shadow.h"
#include "catalog/indexing.h"
#include "commands/comment.h"
#include "commands/dbcommands.h"
#include "miscadmin.h"
@ -241,9 +243,8 @@ createdb(const char *dbname, const char *dbpath,
heap_insert(pg_database_rel, tuple);
/*
* Update indexes (there aren't any currently)
* Update indexes
*/
#ifdef Num_pg_database_indices
if (RelationGetForm(pg_database_rel)->relhasindex)
{
Relation idescs[Num_pg_database_indices];
@ -254,7 +255,6 @@ createdb(const char *dbname, const char *dbpath,
tuple);
CatalogCloseIndices(Num_pg_database_indices, idescs);
}
#endif
/* Close pg_database, but keep lock till commit */
heap_close(pg_database_rel, NoLock);
@ -333,7 +333,7 @@ dropdb(const char *dbname)
elog(ERROR, "DROP DATABASE: database \"%s\" is being accessed by other users", dbname);
/*
* Find the database's tuple by OID (should be unique, we trust).
* Find the database's tuple by OID (should be unique).
*/
ScanKeyEntryInitialize(&key, 0, ObjectIdAttributeNumber,
F_OIDEQ, ObjectIdGetDatum(db_id));
@ -343,7 +343,6 @@ dropdb(const char *dbname)
tup = heap_getnext(pgdbscan, 0);
if (!HeapTupleIsValid(tup))
{
/*
* This error should never come up since the existence of the
* database is checked earlier

View File

@ -6,17 +6,17 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.75 2001/03/22 06:16:12 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.76 2001/06/12 05:55:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "postgres.h"
#include "access/heapam.h"
#include "catalog/catname.h"
#include "catalog/pg_database.h"
@ -31,9 +31,9 @@
#include "utils/fmgroids.h"
#include "utils/syscache.h"
static void CheckPgUserAclNotNull(void);
#define SQL_LENGTH 512
/*---------------------------------------------------------------------
* write_password_file / update_pg_pwd
@ -121,8 +121,7 @@ write_password_file(Relation rel)
"%s"
CRYPT_PWD_FILE_SEPSTR
"%s\n",
DatumGetCString(DirectFunctionCall1(nameout,
NameGetDatum(DatumGetName(datum_n)))),
DatumGetCString(DirectFunctionCall1(nameout, datum_n)),
null_p ? "" :
DatumGetCString(DirectFunctionCall1(textout, datum_p)),
null_v ? "\\N" :
@ -168,10 +167,16 @@ write_password_file(Relation rel)
Datum
update_pg_pwd(PG_FUNCTION_ARGS)
{
Relation rel = heap_openr(ShadowRelationName, AccessExclusiveLock);
/*
* ExclusiveLock ensures no one modifies pg_shadow while we read it,
* and that only one backend rewrites the flat file at a time. It's
* OK to allow normal reads of pg_shadow in parallel, however.
*/
Relation rel = heap_openr(ShadowRelationName, ExclusiveLock);
write_password_file(rel);
heap_close(rel, AccessExclusiveLock);
/* OK to release lock, since we did not modify the relation */
heap_close(rel, ExclusiveLock);
return PointerGetDatum(NULL);
}
@ -210,39 +215,41 @@ CreateUser(CreateUserStmt *stmt)
* to be sure of what the next usesysid should be, and we need to
* protect our update of the flat password file.
*/
pg_shadow_rel = heap_openr(ShadowRelationName, AccessExclusiveLock);
pg_shadow_rel = heap_openr(ShadowRelationName, ExclusiveLock);
pg_shadow_dsc = RelationGetDescr(pg_shadow_rel);
scan = heap_beginscan(pg_shadow_rel, false, SnapshotNow, 0, NULL);
while (!user_exists && !sysid_exists && HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
while (!user_exists && !sysid_exists &&
HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
{
Datum datum;
bool null;
datum = heap_getattr(tuple, Anum_pg_shadow_usename, pg_shadow_dsc, &null);
user_exists = datum && !null && (strcmp((char *) datum, stmt->user) == 0);
datum = heap_getattr(tuple, Anum_pg_shadow_usename,
pg_shadow_dsc, &null);
Assert(!null);
user_exists = (strcmp((char *) DatumGetName(datum), stmt->user) == 0);
datum = heap_getattr(tuple, Anum_pg_shadow_usesysid, pg_shadow_dsc, &null);
datum = heap_getattr(tuple, Anum_pg_shadow_usesysid,
pg_shadow_dsc, &null);
Assert(!null);
if (havesysid) /* customized id wanted */
sysid_exists = datum && !null && ((int) datum == stmt->sysid);
sysid_exists = (DatumGetInt32(datum) == stmt->sysid);
else
/* pick 1 + max */
{
if ((int) datum > max_id)
max_id = (int) datum;
/* pick 1 + max */
if (DatumGetInt32(datum) > max_id)
max_id = DatumGetInt32(datum);
}
}
heap_endscan(scan);
if (user_exists || sysid_exists)
{
heap_close(pg_shadow_rel, AccessExclusiveLock);
if (user_exists)
elog(ERROR, "CREATE USER: user name \"%s\" already exists", stmt->user);
else
elog(ERROR, "CREATE USER: sysid %d is already assigned", stmt->sysid);
return;
}
if (user_exists)
elog(ERROR, "CREATE USER: user name \"%s\" already exists",
stmt->user);
if (sysid_exists)
elog(ERROR, "CREATE USER: sysid %d is already assigned",
stmt->sysid);
/*
* Build a tuple to insert
@ -252,12 +259,12 @@ CreateUser(CreateUserStmt *stmt)
new_record[Anum_pg_shadow_usesysid - 1] = Int32GetDatum(havesysid ? stmt->sysid : max_id + 1);
AssertState(BoolIsValid(stmt->createdb));
new_record[Anum_pg_shadow_usecreatedb - 1] = (Datum) (stmt->createdb);
new_record[Anum_pg_shadow_usetrace - 1] = (Datum) (false);
new_record[Anum_pg_shadow_usecreatedb - 1] = BoolGetDatum(stmt->createdb);
new_record[Anum_pg_shadow_usetrace - 1] = BoolGetDatum(false);
AssertState(BoolIsValid(stmt->createuser));
new_record[Anum_pg_shadow_usesuper - 1] = (Datum) (stmt->createuser);
new_record[Anum_pg_shadow_usesuper - 1] = BoolGetDatum(stmt->createuser);
/* superuser gets catupd right by default */
new_record[Anum_pg_shadow_usecatupd - 1] = (Datum) (stmt->createuser);
new_record[Anum_pg_shadow_usecatupd - 1] = BoolGetDatum(stmt->createuser);
if (stmt->password)
new_record[Anum_pg_shadow_passwd - 1] =
@ -278,13 +285,11 @@ CreateUser(CreateUserStmt *stmt)
new_record_nulls[Anum_pg_shadow_valuntil - 1] = stmt->validUntil ? ' ' : 'n';
tuple = heap_formtuple(pg_shadow_dsc, new_record, new_record_nulls);
Assert(tuple);
/*
* Insert a new record in the pg_shadow table
* Insert new record in the pg_shadow table
*/
if (heap_insert(pg_shadow_rel, tuple) == InvalidOid)
elog(ERROR, "CREATE USER: heap_insert failed");
heap_insert(pg_shadow_rel, tuple);
/*
* Update indexes
@ -322,9 +327,9 @@ CreateUser(CreateUserStmt *stmt)
write_password_file(pg_shadow_rel);
/*
* Now we can clean up.
* Now we can clean up; but keep lock until commit.
*/
heap_close(pg_shadow_rel, AccessExclusiveLock);
heap_close(pg_shadow_rel, NoLock);
}
@ -348,8 +353,11 @@ AlterUser(AlterUserStmt *stmt)
/* must be superuser or just want to change your own password */
if (!superuser() &&
!(stmt->createdb == 0 && stmt->createuser == 0 && !stmt->validUntil
&& stmt->password && strcmp(GetUserName(GetUserId()), stmt->user) == 0))
!(stmt->createdb == 0 &&
stmt->createuser == 0 &&
!stmt->validUntil &&
stmt->password &&
strcmp(GetUserName(GetUserId()), stmt->user) == 0))
elog(ERROR, "ALTER USER: permission denied");
/* changes to the flat password file cannot be rolled back */
@ -361,17 +369,14 @@ AlterUser(AlterUserStmt *stmt)
* secure exclusive lock to protect our update of the flat password
* file.
*/
pg_shadow_rel = heap_openr(ShadowRelationName, AccessExclusiveLock);
pg_shadow_rel = heap_openr(ShadowRelationName, ExclusiveLock);
pg_shadow_dsc = RelationGetDescr(pg_shadow_rel);
tuple = SearchSysCache(SHADOWNAME,
PointerGetDatum(stmt->user),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
{
heap_close(pg_shadow_rel, AccessExclusiveLock);
elog(ERROR, "ALTER USER: user \"%s\" does not exist", stmt->user);
}
/*
* Build a tuple to update, perusing the information just obtained
@ -483,8 +488,7 @@ AlterUser(AlterUserStmt *stmt)
/*
* Now we can clean up.
*/
heap_close(pg_shadow_rel, AccessExclusiveLock);
heap_close(pg_shadow_rel, NoLock);
}
@ -510,7 +514,7 @@ DropUser(DropUserStmt *stmt)
* deleted. Note we secure exclusive lock, because we need to protect
* our update of the flat password file.
*/
pg_shadow_rel = heap_openr(ShadowRelationName, AccessExclusiveLock);
pg_shadow_rel = heap_openr(ShadowRelationName, ExclusiveLock);
pg_shadow_dsc = RelationGetDescr(pg_shadow_rel);
foreach(item, stmt->users)
@ -530,11 +534,8 @@ DropUser(DropUserStmt *stmt)
PointerGetDatum(user),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
{
heap_close(pg_shadow_rel, AccessExclusiveLock);
elog(ERROR, "DROP USER: user \"%s\" does not exist%s", user,
(length(stmt->users) > 1) ? " (no users removed)" : "");
}
usesysid = DatumGetInt32(heap_getattr(tuple, Anum_pg_shadow_usesysid, pg_shadow_dsc, &null));
@ -546,28 +547,30 @@ DropUser(DropUserStmt *stmt)
* don't read the manual, it doesn't seem to be the behaviour one
* would expect either.) -- petere 2000/01/14)
*/
pg_rel = heap_openr(DatabaseRelationName, AccessExclusiveLock);
pg_rel = heap_openr(DatabaseRelationName, AccessShareLock);
pg_dsc = RelationGetDescr(pg_rel);
ScanKeyEntryInitialize(&scankey, 0x0, Anum_pg_database_datdba, F_INT4EQ,
ScanKeyEntryInitialize(&scankey, 0x0,
Anum_pg_database_datdba, F_INT4EQ,
Int32GetDatum(usesysid));
scan = heap_beginscan(pg_rel, false, SnapshotNow, 1, &scankey);
if (HeapTupleIsValid(tmp_tuple = heap_getnext(scan, 0)))
{
datum = heap_getattr(tmp_tuple, Anum_pg_database_datname, pg_dsc, &null);
heap_close(pg_shadow_rel, AccessExclusiveLock);
char *dbname;
datum = heap_getattr(tmp_tuple, Anum_pg_database_datname,
pg_dsc, &null);
Assert(!null);
dbname = DatumGetCString(DirectFunctionCall1(nameout, datum));
elog(ERROR, "DROP USER: user \"%s\" owns database \"%s\", cannot be removed%s",
user,
DatumGetCString(DirectFunctionCall1(nameout,
NameGetDatum(DatumGetName(datum)))),
(length(stmt->users) > 1) ? " (no users removed)" : ""
);
user, dbname,
(length(stmt->users) > 1) ? " (no users removed)" : "");
}
heap_endscan(scan);
heap_close(pg_rel, AccessExclusiveLock);
heap_close(pg_rel, AccessShareLock);
/*
* Somehow we'd have to check for tables, views, etc. owned by the
@ -587,7 +590,7 @@ DropUser(DropUserStmt *stmt)
*
* try calling alter group drop user for every group
*/
pg_rel = heap_openr(GroupRelationName, AccessExclusiveLock);
pg_rel = heap_openr(GroupRelationName, ExclusiveLock);
pg_dsc = RelationGetDescr(pg_rel);
scan = heap_beginscan(pg_rel, false, SnapshotNow, 0, NULL);
while (HeapTupleIsValid(tmp_tuple = heap_getnext(scan, 0)))
@ -602,7 +605,7 @@ DropUser(DropUserStmt *stmt)
AlterGroup(&ags, "DROP USER");
}
heap_endscan(scan);
heap_close(pg_rel, AccessExclusiveLock);
heap_close(pg_rel, ExclusiveLock);
/*
* Advance command counter so that later iterations of this loop
@ -622,7 +625,7 @@ DropUser(DropUserStmt *stmt)
/*
* Now we can clean up.
*/
heap_close(pg_shadow_rel, AccessExclusiveLock);
heap_close(pg_shadow_rel, NoLock);
}
@ -681,38 +684,41 @@ CreateGroup(CreateGroupStmt *stmt)
if (!superuser())
elog(ERROR, "CREATE GROUP: permission denied");
pg_group_rel = heap_openr(GroupRelationName, AccessExclusiveLock);
pg_group_rel = heap_openr(GroupRelationName, ExclusiveLock);
pg_group_dsc = RelationGetDescr(pg_group_rel);
scan = heap_beginscan(pg_group_rel, false, SnapshotNow, 0, NULL);
while (!group_exists && !sysid_exists && HeapTupleIsValid(tuple = heap_getnext(scan, false)))
while (!group_exists && !sysid_exists &&
HeapTupleIsValid(tuple = heap_getnext(scan, false)))
{
Datum datum;
bool null;
datum = heap_getattr(tuple, Anum_pg_group_groname, pg_group_dsc, &null);
group_exists = datum && !null && (strcmp((char *) datum, stmt->name) == 0);
datum = heap_getattr(tuple, Anum_pg_group_groname,
pg_group_dsc, &null);
Assert(!null);
group_exists = (strcmp((char *) DatumGetName(datum), stmt->name) == 0);
datum = heap_getattr(tuple, Anum_pg_group_grosysid, pg_group_dsc, &null);
datum = heap_getattr(tuple, Anum_pg_group_grosysid,
pg_group_dsc, &null);
Assert(!null);
if (stmt->sysid >= 0) /* customized id wanted */
sysid_exists = datum && !null && ((int) datum == stmt->sysid);
sysid_exists = (DatumGetInt32(datum) == stmt->sysid);
else
/* pick 1 + max */
{
if ((int) datum > max_id)
max_id = (int) datum;
/* pick 1 + max */
if (DatumGetInt32(datum) > max_id)
max_id = DatumGetInt32(datum);
}
}
heap_endscan(scan);
if (group_exists || sysid_exists)
{
heap_close(pg_group_rel, AccessExclusiveLock);
if (group_exists)
elog(ERROR, "CREATE GROUP: group name \"%s\" already exists", stmt->name);
else
elog(ERROR, "CREATE GROUP: group sysid %d is already assigned", stmt->sysid);
}
if (group_exists)
elog(ERROR, "CREATE GROUP: group name \"%s\" already exists",
stmt->name);
if (sysid_exists)
elog(ERROR, "CREATE GROUP: group sysid %d is already assigned",
stmt->sysid);
/*
* Translate the given user names to ids
@ -790,7 +796,7 @@ CreateGroup(CreateGroupStmt *stmt)
CatalogCloseIndices(Num_pg_group_indices, idescs);
}
heap_close(pg_group_rel, AccessExclusiveLock);
heap_close(pg_group_rel, NoLock);
}
@ -811,7 +817,7 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag)
if (!superuser())
elog(ERROR, "%s: permission denied", tag);
pg_group_rel = heap_openr(GroupRelationName, AccessExclusiveLock);
pg_group_rel = heap_openr(GroupRelationName, ExclusiveLock);
pg_group_dsc = RelationGetDescr(pg_group_rel);
/*
@ -1052,7 +1058,7 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag)
ReleaseSysCache(group_tuple);
heap_close(pg_group_rel, AccessExclusiveLock);
heap_close(pg_group_rel, NoLock);
}
@ -1078,7 +1084,7 @@ DropGroup(DropGroupStmt *stmt)
/*
* Scan the pg_group table and delete all matching groups.
*/
pg_group_rel = heap_openr(GroupRelationName, AccessExclusiveLock);
pg_group_rel = heap_openr(GroupRelationName, ExclusiveLock);
pg_group_dsc = RelationGetDescr(pg_group_rel);
scan = heap_beginscan(pg_group_rel, false, SnapshotNow, 0, NULL);
@ -1087,8 +1093,9 @@ DropGroup(DropGroupStmt *stmt)
Datum datum;
bool null;
datum = heap_getattr(tuple, Anum_pg_group_groname, pg_group_dsc, &null);
if (datum && !null && strcmp((char *) datum, stmt->name) == 0)
datum = heap_getattr(tuple, Anum_pg_group_groname,
pg_group_dsc, &null);
if (!null && strcmp((char *) DatumGetName(datum), stmt->name) == 0)
{
gro_exists = true;
simple_heap_delete(pg_group_rel, &tuple->t_self);
@ -1101,10 +1108,7 @@ DropGroup(DropGroupStmt *stmt)
* Did we find any?
*/
if (!gro_exists)
{
heap_close(pg_group_rel, AccessExclusiveLock);
elog(ERROR, "DROP GROUP: group \"%s\" does not exist", stmt->name);
}
heap_close(pg_group_rel, AccessExclusiveLock);
heap_close(pg_group_rel, NoLock);
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.45 2001/03/22 03:59:46 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.46 2001/06/12 05:55:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -107,16 +107,12 @@ InitLockTable(int maxBackends)
void
RelationInitLockInfo(Relation relation)
{
char *relname;
Assert(RelationIsValid(relation));
Assert(OidIsValid(RelationGetRelid(relation)));
relname = (char *) RelationGetPhysicalRelationName(relation);
relation->rd_lockInfo.lockRelId.relId = RelationGetRelid(relation);
if (IsSharedSystemRelationName(relname))
if (relation->rd_rel->relisshared)
relation->rd_lockInfo.lockRelId.dbId = InvalidOid;
else
relation->rd_lockInfo.lockRelId.dbId = MyDatabaseId;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.136 2001/06/01 02:41:36 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.137 2001/06/12 05:55:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1116,7 +1116,7 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
*/
RelationInitLockInfo(relation); /* see lmgr.c */
if (IsSharedSystemRelationName(NameStr(relation->rd_rel->relname)))
if (relation->rd_rel->relisshared)
relation->rd_node.tblNode = InvalidOid;
else
relation->rd_node.tblNode = MyDatabaseId;
@ -1201,7 +1201,6 @@ IndexedAccessMethodInitialize(Relation relation)
* catalogs...
*
* NOTE: we assume we are already switched into CacheMemoryContext.
*
*/
static void
formrdesc(char *relationName,
@ -1245,15 +1244,10 @@ formrdesc(char *relationName,
strcpy(RelationGetPhysicalRelationName(relation), relationName);
/*
* For debugging purposes, it's important to distinguish between
* shared and non-shared relations, even at bootstrap time. There's
* code in the buffer manager that traces allocations that has to know
* about this.
* It's important to distinguish between shared and non-shared relations,
* even at bootstrap time, to make sure we know where they are stored.
*/
if (IsSystemRelationName(relationName))
relation->rd_rel->relisshared = IsSharedSystemRelationName(relationName);
else
relation->rd_rel->relisshared = false;
relation->rd_rel->relisshared = IsSharedSystemRelationName(relationName);
relation->rd_rel->relpages = 1;
relation->rd_rel->reltuples = 1;
@ -1286,7 +1280,7 @@ formrdesc(char *relationName,
*/
RelationInitLockInfo(relation); /* see lmgr.c */
if (IsSharedSystemRelationName(relationName))
if (relation->rd_rel->relisshared)
relation->rd_node.tblNode = InvalidOid;
else
relation->rd_node.tblNode = MyDatabaseId;
@ -1301,14 +1295,15 @@ formrdesc(char *relationName,
/* In bootstrap mode, we have no indexes */
if (!IsBootstrapProcessingMode())
{
for (i = 0; IndexedCatalogNames[i] != NULL; i++)
{
if (strcmp(IndexedCatalogNames[i], relationName) == 0)
{
relation->rd_rel->relhasindex = true;
break;
}
}
/*
* This list is incomplete, but it only has to work for the
* set of rels that formrdesc is used for ...
*/
if (strcmp(relationName, RelationRelationName) == 0 ||
strcmp(relationName, AttributeRelationName) == 0 ||
strcmp(relationName, ProcedureRelationName) == 0 ||
strcmp(relationName, TypeRelationName) == 0)
relation->rd_rel->relhasindex = true;
}
/*
@ -1323,7 +1318,6 @@ formrdesc(char *relationName,
*
* Update the phony data inserted by formrdesc() with real info
* from pg_class.
*
*/
static void
fixrdesc(char *relationName)

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.61 2001/05/07 00:43:24 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.62 2001/06/12 05:55:49 tgl Exp $
*
* NOTES
* These routines allow the parser/planner/executor to perform
@ -31,7 +31,6 @@
#include "catalog/pg_index.h"
#include "catalog/pg_inherits.h"
#include "catalog/pg_language.h"
#include "catalog/pg_listener.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_proc.h"
@ -214,15 +213,6 @@ static struct cachedesc cacheinfo[] = {
0,
0
}},
{ListenerRelationName, /* LISTENREL */
ListenerPidRelnameIndex,
2,
{
Anum_pg_listener_pid,
Anum_pg_listener_relname,
0,
0
}},
{OperatorRelationName, /* OPERNAME */
OperatorNameIndex,
4,
@ -277,7 +267,7 @@ static struct cachedesc cacheinfo[] = {
0,
0
}},
{RewriteRelationName, /* REWRITENAME */
{RewriteRelationName, /* RULENAME */
RewriteRulenameIndex,
1,
{
@ -286,15 +276,6 @@ static struct cachedesc cacheinfo[] = {
0,
0
}},
{RewriteRelationName, /* RULEOID */
RewriteOidIndex,
1,
{
ObjectIdAttributeNumber,
0,
0,
0
}},
{ShadowRelationName, /* SHADOWNAME */
ShadowNameIndex,
1,

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.57 2001/05/14 20:30:21 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.58 2001/06/12 05:55:50 tgl Exp $
*
* NOTES
* Globals used all over the place should be declared here and not
@ -30,6 +30,7 @@
#include "miscadmin.h"
#include "storage/backendid.h"
ProtocolVersion FrontendProtocol = PG_PROTOCOL_LATEST;
bool Noversion = false;
@ -84,36 +85,26 @@ int SortMem = 512;
int NBuffers = DEF_NBUFFERS;
char *IndexedCatalogNames[] = {
AttributeRelationName,
ProcedureRelationName,
TypeRelationName,
RelationRelationName,
0
};
/* ----------------
* we just do a linear search now so there's no requirement that the list
* List of relations that are shared across all databases in an installation.
*
* This used to be binary-searched, requiring that it be kept in sorted order.
* We just do a linear search now so there's no requirement that the list
* be ordered. The list is so small it shouldn't make much difference.
* make sure the list is null-terminated
* - jolly 8/19/95
*
* OLD COMMENT
* WARNING WARNING WARNING WARNING WARNING WARNING
*
* keep SharedSystemRelationNames[] in SORTED order! A binary search
* is done on it in catalog.c!
*
* XXX this is a serious hack which should be fixed -cim 1/26/90
* ----------------
*/
char *SharedSystemRelationNames[] = {
DatabaseRelationName,
DatabaseNameIndex,
DatabaseOidIndex,
GroupRelationName,
GroupNameIndex,
GroupSysidIndex,
LogRelationName,
ShadowRelationName,
0
ShadowNameIndex,
ShadowSysidIndex,
NULL
};