1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-13 16:22:44 +03:00

Massive commit to run PGINDENT on all *.c and *.h files.

This commit is contained in:
Bruce Momjian
1997-09-07 05:04:48 +00:00
parent 8fecd4febf
commit 1ccd423235
687 changed files with 150775 additions and 136888 deletions

View File

@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* catalog.c--
*
*
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/catalog.c,v 1.7 1997/08/18 20:51:59 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/catalog.c,v 1.8 1997/09/07 04:40:00 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -15,7 +15,7 @@
#include <postgres.h>
#include <miscadmin.h> /* for DataDir */
#include <miscadmin.h> /* for DataDir */
#include <utils/syscache.h>
#include <catalog/catname.h> /* NameIs{,Shared}SystemRelationName */
#include <catalog/pg_type.h>
@@ -23,175 +23,188 @@
#include <access/transam.h>
/*
* relpath - path to the relation
* Perhaps this should be in-line code in relopen().
* relpath - path to the relation
* Perhaps this should be in-line code in relopen().
*/
char *
char *
relpath(char relname[])
{
char *path;
if (IsSharedSystemRelationName(relname)) {
path = (char *) palloc(strlen(DataDir) + sizeof(NameData) + 2);
sprintf(path, "%s/%s", DataDir, relname);
return (path);
}
return(relname);
char *path;
if (IsSharedSystemRelationName(relname))
{
path = (char *) palloc(strlen(DataDir) + sizeof(NameData) + 2);
sprintf(path, "%s/%s", DataDir, relname);
return (path);
}
return (relname);
}
#ifdef NOT_USED
/*
* issystem - returns non-zero iff relname is a system catalog
* issystem - returns non-zero iff relname is a system catalog
*
* We now make a new requirement where system catalog relns must begin
* with pg_ while user relns are forbidden to do so. Make the test
* trivial and instantaneous.
* We now make a new requirement where system catalog relns must begin
* with pg_ while user relns are forbidden to do so. Make the test
* trivial and instantaneous.
*
* XXX this is way bogus. -- pma
* XXX this is way bogus. -- pma
*/
bool
issystem(char relname[])
{
if (relname[0] && relname[1] && relname[2])
return (relname[0] == 'p' &&
relname[1] == 'g' &&
relname[2] == '_');
else
return FALSE;
if (relname[0] && relname[1] && relname[2])
return (relname[0] == 'p' &&
relname[1] == 'g' &&
relname[2] == '_');
else
return FALSE;
}
#endif
/*
* IsSystemRelationName --
* True iff name is the name of a system catalog relation.
* True iff name is the name of a system catalog relation.
*
* We now make a new requirement where system catalog relns must begin
* with pg_ while user relns are forbidden to do so. Make the test
* trivial and instantaneous.
* We now make a new requirement where system catalog relns must begin
* with pg_ while user relns are forbidden to do so. Make the test
* trivial and instantaneous.
*
* XXX this is way bogus. -- pma
* XXX this is way bogus. -- pma
*/
bool
IsSystemRelationName(char *relname)
{
if (relname[0] && relname[1] && relname[2])
return (relname[0] == 'p' &&
relname[1] == 'g' &&
relname[2] == '_');
else
return FALSE;
if (relname[0] && relname[1] && relname[2])
return (relname[0] == 'p' &&
relname[1] == 'g' &&
relname[2] == '_');
else
return FALSE;
}
/*
* IsSharedSystemRelationName --
* True iff name is the name of a shared system catalog relation.
* True iff name is the name of a shared system catalog relation.
*/
bool
IsSharedSystemRelationName(char *relname)
{
int i;
/*
* Quick out: if it's not a system relation, it can't be a shared
* system relation.
*/
if (!IsSystemRelationName(relname))
int i;
/*
* Quick out: if it's not a system relation, it can't be a shared
* system relation.
*/
if (!IsSystemRelationName(relname))
return FALSE;
i = 0;
while (SharedSystemRelationNames[i] != NULL)
{
if (strcmp(SharedSystemRelationNames[i], relname) == 0)
return TRUE;
i++;
}
return FALSE;
i = 0;
while ( SharedSystemRelationNames[i] != NULL) {
if (strcmp(SharedSystemRelationNames[i],relname) == 0)
return TRUE;
i++;
}
return FALSE;
}
/*
* newoid - returns a unique identifier across all catalogs.
* newoid - returns a unique identifier across all catalogs.
*
* Object Id allocation is now done by GetNewObjectID in
* access/transam/varsup.c. oids are now allocated correctly.
* Object Id allocation is now done by GetNewObjectID in
* access/transam/varsup.c. oids are now allocated correctly.
*
* old comments:
* This needs to change soon, it fails if there are too many more
* than one call per second when postgres restarts after it dies.
* This needs to change soon, it fails if there are too many more
* than one call per second when postgres restarts after it dies.
*
* The distribution of OID's should be done by the POSTMASTER.
* Also there needs to be a facility to preallocate OID's. Ie.,
* for a block of OID's to be declared as invalid ones to allow
* user programs to use them for temporary object identifiers.
* The distribution of OID's should be done by the POSTMASTER.
* Also there needs to be a facility to preallocate OID's. Ie.,
* for a block of OID's to be declared as invalid ones to allow
* user programs to use them for temporary object identifiers.
*/
Oid newoid()
Oid
newoid()
{
Oid lastoid;
GetNewObjectId(&lastoid);
if (! OidIsValid(lastoid))
elog(WARN, "newoid: GetNewObjectId returns invalid oid");
return lastoid;
Oid lastoid;
GetNewObjectId(&lastoid);
if (!OidIsValid(lastoid))
elog(WARN, "newoid: GetNewObjectId returns invalid oid");
return lastoid;
}
/*
* fillatt - fills the ATTRIBUTE relation fields from the TYP
* fillatt - fills the ATTRIBUTE relation fields from the TYP
*
* Expects that the atttypid domain is set for each att[].
* Returns with the attnum, and attlen domains set.
* attnum, attproc, atttyparg, ... should be set by the user.
* Expects that the atttypid domain is set for each att[].
* Returns with the attnum, and attlen domains set.
* attnum, attproc, atttyparg, ... should be set by the user.
*
* In the future, attnum may not be set?!? or may be passed as an arg?!?
* In the future, attnum may not be set?!? or may be passed as an arg?!?
*
* Current implementation is very inefficient--should cashe the
* information if this is at all possible.
* Current implementation is very inefficient--should cashe the
* information if this is at all possible.
*
* Check to see if this is really needed, and especially in the case
* of index tuples.
* Check to see if this is really needed, and especially in the case
* of index tuples.
*/
void
fillatt(TupleDesc tupleDesc)
{
AttributeTupleForm *attributeP;
register TypeTupleForm typp;
HeapTuple tuple;
int i;
int natts = tupleDesc->natts;
AttributeTupleForm *att = tupleDesc->attrs;
AttributeTupleForm *attributeP;
register TypeTupleForm typp;
HeapTuple tuple;
int i;
int natts = tupleDesc->natts;
AttributeTupleForm *att = tupleDesc->attrs;
if (natts < 0 || natts > MaxHeapAttributeNumber)
elog(WARN, "fillatt: %d attributes is too large", natts);
if (natts == 0) {
elog(DEBUG, "fillatt: called with natts == 0");
return;
}
attributeP = &att[0];
for (i = 0; i < natts;) {
tuple = SearchSysCacheTuple(TYPOID,
Int32GetDatum((*attributeP)->atttypid),
0,0,0);
if (!HeapTupleIsValid(tuple)) {
elog(WARN, "fillatt: unknown atttypid %ld",
(*attributeP)->atttypid);
} else {
(*attributeP)->attnum = (int16) ++i;
/* Check if the attr is a set before messing with the length
and byval, since those were already set in
TupleDescInitEntry. In fact, this seems redundant
here, but who knows what I'll break if I take it out...
same for char() and varchar() stuff. I share the same
sentiments. This function is poorly written anyway. -ay 6/95
*/
if (!(*attributeP)->attisset &&
(*attributeP)->atttypid!=BPCHAROID &&
(*attributeP)->atttypid!=VARCHAROID) {
typp = (TypeTupleForm) GETSTRUCT(tuple); /* XXX */
(*attributeP)->attlen = typp->typlen;
(*attributeP)->attbyval = typp->typbyval;
}
if (natts < 0 || natts > MaxHeapAttributeNumber)
elog(WARN, "fillatt: %d attributes is too large", natts);
if (natts == 0)
{
elog(DEBUG, "fillatt: called with natts == 0");
return;
}
attributeP = &att[0];
for (i = 0; i < natts;)
{
tuple = SearchSysCacheTuple(TYPOID,
Int32GetDatum((*attributeP)->atttypid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
{
elog(WARN, "fillatt: unknown atttypid %ld",
(*attributeP)->atttypid);
}
else
{
(*attributeP)->attnum = (int16)++ i;
/*
* Check if the attr is a set before messing with the length
* and byval, since those were already set in
* TupleDescInitEntry. In fact, this seems redundant here,
* but who knows what I'll break if I take it out...
*
* same for char() and varchar() stuff. I share the same
* sentiments. This function is poorly written anyway. -ay
* 6/95
*/
if (!(*attributeP)->attisset &&
(*attributeP)->atttypid != BPCHAROID &&
(*attributeP)->atttypid != VARCHAROID)
{
typp = (TypeTupleForm) GETSTRUCT(tuple); /* XXX */
(*attributeP)->attlen = typp->typlen;
(*attributeP)->attbyval = typp->typbyval;
}
}
attributeP += 1;
}
attributeP += 1;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,14 @@
/*-------------------------------------------------------------------------
*
* indexing.c--
* This file contains routines to support indices defined on system
* catalogs.
* This file contains routines to support indices defined on system
* catalogs.
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.11 1997/08/31 09:56:18 vadim Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.12 1997/09/07 04:40:21 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -34,36 +34,37 @@
/*
* Names of indices on the following system catalogs:
*
* pg_attribute
* pg_proc
* pg_type
* pg_naming
* pg_class
* pg_attrdef
* pg_relcheck
* pg_trigger
* pg_attribute
* pg_proc
* pg_type
* pg_naming
* pg_class
* pg_attrdef
* pg_relcheck
* pg_trigger
*/
char *Name_pg_attr_indices[Num_pg_attr_indices] = {AttributeNameIndex,
AttributeNumIndex,
AttributeRelidIndex};
char *Name_pg_proc_indices[Num_pg_proc_indices] = { ProcedureNameIndex,
ProcedureOidIndex,
ProcedureSrcIndex};
char *Name_pg_type_indices[Num_pg_type_indices] = { TypeNameIndex,
TypeOidIndex};
char *Name_pg_class_indices[Num_pg_class_indices]= { ClassNameIndex,
ClassOidIndex};
char *Name_pg_attrdef_indices[Num_pg_attrdef_indices]= { AttrDefaultIndex };
char *Name_pg_attr_indices[Num_pg_attr_indices] = {AttributeNameIndex,
AttributeNumIndex,
AttributeRelidIndex};
char *Name_pg_proc_indices[Num_pg_proc_indices] = {ProcedureNameIndex,
ProcedureOidIndex,
ProcedureSrcIndex};
char *Name_pg_type_indices[Num_pg_type_indices] = {TypeNameIndex,
TypeOidIndex};
char *Name_pg_class_indices[Num_pg_class_indices] = {ClassNameIndex,
ClassOidIndex};
char *Name_pg_attrdef_indices[Num_pg_attrdef_indices] = {AttrDefaultIndex};
char *Name_pg_relcheck_indices[Num_pg_relcheck_indices]= { RelCheckIndex };
char *Name_pg_relcheck_indices[Num_pg_relcheck_indices] = {RelCheckIndex};
char *Name_pg_trigger_indices[Num_pg_trigger_indices]= { TriggerRelidIndex };
char *Name_pg_trigger_indices[Num_pg_trigger_indices] = {TriggerRelidIndex};
static HeapTuple CatalogIndexFetchTuple(Relation heapRelation,
Relation idesc,
ScanKey skey);
static HeapTuple
CatalogIndexFetchTuple(Relation heapRelation,
Relation idesc,
ScanKey skey);
/*
@@ -75,11 +76,11 @@ static HeapTuple CatalogIndexFetchTuple(Relation heapRelation,
void
CatalogOpenIndices(int nIndices, char *names[], Relation idescs[])
{
int i;
for (i=0; i<nIndices; i++)
int i;
for (i = 0; i < nIndices; i++)
{
idescs[i] = index_openr(names[i]);
idescs[i] = index_openr(names[i]);
}
}
@@ -87,83 +88,84 @@ CatalogOpenIndices(int nIndices, char *names[], Relation idescs[])
* This is the inverse routine to CatalogOpenIndices()
*/
void
CatalogCloseIndices(int nIndices, Relation *idescs)
CatalogCloseIndices(int nIndices, Relation * idescs)
{
int i;
for (i=0; i<nIndices; i++)
index_close(idescs[i]);
int i;
for (i = 0; i < nIndices; i++)
index_close(idescs[i]);
}
/*
* For the same reasons outlined above CatalogOpenIndices() we need a routine
* that takes a new catalog tuple and inserts an associated index tuple into
* that takes a new catalog tuple and inserts an associated index tuple into
* each catalog index.
*/
void
CatalogIndexInsert(Relation *idescs,
int nIndices,
Relation heapRelation,
HeapTuple heapTuple)
CatalogIndexInsert(Relation * idescs,
int nIndices,
Relation heapRelation,
HeapTuple heapTuple)
{
HeapTuple pgIndexTup;
TupleDesc heapDescriptor;
IndexTupleForm pgIndexP;
Datum datum;
int natts;
AttrNumber *attnumP;
FuncIndexInfo finfo, *finfoP;
char nulls[INDEX_MAX_KEYS];
int i;
heapDescriptor = RelationGetTupleDescriptor(heapRelation);
for (i=0; i<nIndices; i++)
HeapTuple pgIndexTup;
TupleDesc heapDescriptor;
IndexTupleForm pgIndexP;
Datum datum;
int natts;
AttrNumber *attnumP;
FuncIndexInfo finfo,
*finfoP;
char nulls[INDEX_MAX_KEYS];
int i;
heapDescriptor = RelationGetTupleDescriptor(heapRelation);
for (i = 0; i < nIndices; i++)
{
TupleDesc indexDescriptor;
InsertIndexResult indexRes;
indexDescriptor = RelationGetTupleDescriptor(idescs[i]);
pgIndexTup = SearchSysCacheTuple(INDEXRELID,
Int32GetDatum(idescs[i]->rd_id),
0,0,0);
Assert(pgIndexTup);
pgIndexP = (IndexTupleForm)GETSTRUCT(pgIndexTup);
/*
* Compute the number of attributes we are indexing upon.
* very important - can't assume one if this is a functional
* index.
*/
for (attnumP=(&pgIndexP->indkey[0]), natts=0;
*attnumP != InvalidAttrNumber;
attnumP++, natts++)
;
if (pgIndexP->indproc != InvalidOid)
TupleDesc indexDescriptor;
InsertIndexResult indexRes;
indexDescriptor = RelationGetTupleDescriptor(idescs[i]);
pgIndexTup = SearchSysCacheTuple(INDEXRELID,
Int32GetDatum(idescs[i]->rd_id),
0, 0, 0);
Assert(pgIndexTup);
pgIndexP = (IndexTupleForm) GETSTRUCT(pgIndexTup);
/*
* Compute the number of attributes we are indexing upon. very
* important - can't assume one if this is a functional index.
*/
for (attnumP = (&pgIndexP->indkey[0]), natts = 0;
*attnumP != InvalidAttrNumber;
attnumP++, natts++)
;
if (pgIndexP->indproc != InvalidOid)
{
FIgetnArgs(&finfo) = natts;
natts = 1;
FIgetProcOid(&finfo) = pgIndexP->indproc;
*(FIgetname(&finfo)) = '\0';
finfoP = &finfo;
FIgetnArgs(&finfo) = natts;
natts = 1;
FIgetProcOid(&finfo) = pgIndexP->indproc;
*(FIgetname(&finfo)) = '\0';
finfoP = &finfo;
}
else
finfoP = (FuncIndexInfo *)NULL;
FormIndexDatum(natts,
(AttrNumber *)&pgIndexP->indkey[0],
heapTuple,
heapDescriptor,
InvalidBuffer,
&datum,
nulls,
finfoP);
indexRes = index_insert(idescs[i], &datum, nulls,
&(heapTuple->t_ctid), heapRelation);
if (indexRes) pfree(indexRes);
else
finfoP = (FuncIndexInfo *) NULL;
FormIndexDatum(natts,
(AttrNumber *) & pgIndexP->indkey[0],
heapTuple,
heapDescriptor,
InvalidBuffer,
&datum,
nulls,
finfoP);
indexRes = index_insert(idescs[i], &datum, nulls,
&(heapTuple->t_ctid), heapRelation);
if (indexRes)
pfree(indexRes);
}
}
@@ -174,81 +176,88 @@ CatalogIndexInsert(Relation *idescs,
bool
CatalogHasIndex(char *catName, Oid catId)
{
Relation pg_class;
HeapTuple htup;
Form_pg_class pgRelP;
int i;
Assert(IsSystemRelationName(catName));
/*
* If we're bootstraping we don't have pg_class (or any indices).
*/
if (IsBootstrapProcessingMode())
return false;
if (IsInitProcessingMode()) {
for (i = 0; IndexedCatalogNames[i] != NULL; i++) {
if ( strcmp(IndexedCatalogNames[i], catName) == 0)
return (true);
Relation pg_class;
HeapTuple htup;
Form_pg_class pgRelP;
int i;
Assert(IsSystemRelationName(catName));
/*
* If we're bootstraping we don't have pg_class (or any indices).
*/
if (IsBootstrapProcessingMode())
return false;
if (IsInitProcessingMode())
{
for (i = 0; IndexedCatalogNames[i] != NULL; i++)
{
if (strcmp(IndexedCatalogNames[i], catName) == 0)
return (true);
}
return (false);
}
return (false);
}
pg_class = heap_openr(RelationRelationName);
htup = ClassOidIndexScan(pg_class, catId);
heap_close(pg_class);
if (! HeapTupleIsValid(htup)) {
elog(NOTICE, "CatalogHasIndex: no relation with oid %d", catId);
return false;
}
pgRelP = (Form_pg_class)GETSTRUCT(htup);
return (pgRelP->relhasindex);
pg_class = heap_openr(RelationRelationName);
htup = ClassOidIndexScan(pg_class, catId);
heap_close(pg_class);
if (!HeapTupleIsValid(htup))
{
elog(NOTICE, "CatalogHasIndex: no relation with oid %d", catId);
return false;
}
pgRelP = (Form_pg_class) GETSTRUCT(htup);
return (pgRelP->relhasindex);
}
/*
* CatalogIndexFetchTuple() -- Get a tuple that satisfies a scan key
* from a catalog relation.
* CatalogIndexFetchTuple() -- Get a tuple that satisfies a scan key
* from a catalog relation.
*
* Since the index may contain pointers to dead tuples, we need to
* iterate until we find a tuple that's valid and satisfies the scan
* key.
* Since the index may contain pointers to dead tuples, we need to
* iterate until we find a tuple that's valid and satisfies the scan
* key.
*/
static HeapTuple
static HeapTuple
CatalogIndexFetchTuple(Relation heapRelation,
Relation idesc,
ScanKey skey)
Relation idesc,
ScanKey skey)
{
IndexScanDesc sd;
RetrieveIndexResult indexRes;
HeapTuple tuple;
Buffer buffer;
sd = index_beginscan(idesc, false, 1, skey);
tuple = (HeapTuple)NULL;
do {
indexRes = index_getnext(sd, ForwardScanDirection);
if (indexRes) {
ItemPointer iptr;
iptr = &indexRes->heap_iptr;
tuple = heap_fetch(heapRelation, NowTimeQual, iptr, &buffer);
pfree(indexRes);
} else
break;
} while (!HeapTupleIsValid(tuple));
if (HeapTupleIsValid(tuple)) {
tuple = heap_copytuple(tuple);
ReleaseBuffer(buffer);
}
index_endscan(sd);
pfree(sd);
return (tuple);
IndexScanDesc sd;
RetrieveIndexResult indexRes;
HeapTuple tuple;
Buffer buffer;
sd = index_beginscan(idesc, false, 1, skey);
tuple = (HeapTuple) NULL;
do
{
indexRes = index_getnext(sd, ForwardScanDirection);
if (indexRes)
{
ItemPointer iptr;
iptr = &indexRes->heap_iptr;
tuple = heap_fetch(heapRelation, NowTimeQual, iptr, &buffer);
pfree(indexRes);
}
else
break;
} while (!HeapTupleIsValid(tuple));
if (HeapTupleIsValid(tuple))
{
tuple = heap_copytuple(tuple);
ReleaseBuffer(buffer);
}
index_endscan(sd);
pfree(sd);
return (tuple);
}
/*
@@ -259,276 +268,295 @@ CatalogIndexFetchTuple(Relation heapRelation,
*/
HeapTuple
AttributeNameIndexScan(Relation heapRelation,
Oid relid,
char *attname)
Oid relid,
char *attname)
{
Relation idesc;
ScanKeyData skey;
OidName keyarg;
HeapTuple tuple;
keyarg = mkoidname(relid, attname);
ScanKeyEntryInitialize(&skey,
(bits16)0x0,
(AttrNumber)1,
(RegProcedure)OidNameEqRegProcedure,
(Datum)keyarg);
idesc = index_openr(AttributeNameIndex);
tuple = CatalogIndexFetchTuple(heapRelation, idesc, &skey);
index_close(idesc);
pfree(keyarg);
return tuple;
Relation idesc;
ScanKeyData skey;
OidName keyarg;
HeapTuple tuple;
keyarg = mkoidname(relid, attname);
ScanKeyEntryInitialize(&skey,
(bits16) 0x0,
(AttrNumber) 1,
(RegProcedure) OidNameEqRegProcedure,
(Datum) keyarg);
idesc = index_openr(AttributeNameIndex);
tuple = CatalogIndexFetchTuple(heapRelation, idesc, &skey);
index_close(idesc);
pfree(keyarg);
return tuple;
}
HeapTuple
AttributeNumIndexScan(Relation heapRelation,
Oid relid,
AttrNumber attnum)
Oid relid,
AttrNumber attnum)
{
Relation idesc;
ScanKeyData skey;
OidInt2 keyarg;
HeapTuple tuple;
keyarg = mkoidint2(relid, (uint16)attnum);
ScanKeyEntryInitialize(&skey,
(bits16)0x0,
(AttrNumber)1,
(RegProcedure)OidInt2EqRegProcedure,
(Datum)keyarg);
idesc = index_openr(AttributeNumIndex);
tuple = CatalogIndexFetchTuple(heapRelation, idesc, &skey);
index_close(idesc);
pfree(keyarg);
return tuple;
Relation idesc;
ScanKeyData skey;
OidInt2 keyarg;
HeapTuple tuple;
keyarg = mkoidint2(relid, (uint16) attnum);
ScanKeyEntryInitialize(&skey,
(bits16) 0x0,
(AttrNumber) 1,
(RegProcedure) OidInt2EqRegProcedure,
(Datum) keyarg);
idesc = index_openr(AttributeNumIndex);
tuple = CatalogIndexFetchTuple(heapRelation, idesc, &skey);
index_close(idesc);
pfree(keyarg);
return tuple;
}
HeapTuple
ProcedureOidIndexScan(Relation heapRelation, Oid procId)
{
Relation idesc;
ScanKeyData skey;
HeapTuple tuple;
ScanKeyEntryInitialize(&skey,
(bits16)0x0,
(AttrNumber)1,
(RegProcedure)ObjectIdEqualRegProcedure,
(Datum)procId);
idesc = index_openr(ProcedureOidIndex);
tuple = CatalogIndexFetchTuple(heapRelation, idesc, &skey);
index_close(idesc);
return tuple;
Relation idesc;
ScanKeyData skey;
HeapTuple tuple;
ScanKeyEntryInitialize(&skey,
(bits16) 0x0,
(AttrNumber) 1,
(RegProcedure) ObjectIdEqualRegProcedure,
(Datum) procId);
idesc = index_openr(ProcedureOidIndex);
tuple = CatalogIndexFetchTuple(heapRelation, idesc, &skey);
index_close(idesc);
return tuple;
}
HeapTuple
ProcedureNameIndexScan(Relation heapRelation,
char *procName,
int nargs,
Oid *argTypes)
char *procName,
int nargs,
Oid * argTypes)
{
Relation idesc;
ScanKeyData skey;
HeapTuple tuple; /* tuple being tested */
HeapTuple return_tuple; /* The tuple pointer we eventually return */
IndexScanDesc sd;
RetrieveIndexResult indexRes;
Buffer buffer;
Form_pg_proc pgProcP;
bool ScanComplete;
/* The index scan is complete, i.e. we've scanned everything there
is to scan.
*/
bool FoundMatch;
/* In scanning pg_proc, we have found a row that meets our search
criteria.
*/
ScanKeyEntryInitialize(&skey,
(bits16)0x0,
(AttrNumber)1,
(RegProcedure)NameEqualRegProcedure,
(Datum)procName);
idesc = index_openr(ProcedureNameIndex);
sd = index_beginscan(idesc, false, 1, &skey);
/*
* for now, we do the work usually done by CatalogIndexFetchTuple
* by hand, so that we can check that the other keys match. when
* multi-key indices are added, they will be used here.
*/
tuple = (HeapTuple) NULL; /* initial value */
ScanComplete = false; /* Scan hasn't begun yet */
FoundMatch = false; /* No match yet; haven't even looked. */
while (!FoundMatch && !ScanComplete) {
indexRes = index_getnext(sd, ForwardScanDirection);
if (indexRes) {
ItemPointer iptr;
iptr = &indexRes->heap_iptr;
tuple = heap_fetch(heapRelation, NowTimeQual, iptr, &buffer);
pfree(indexRes);
if (HeapTupleIsValid(tuple)) {
/* Here's a row for a procedure that has the sought procedure
name. To be a match, though, we need it to have the
right number and type of arguments too, so we check that
now.
*/
pgProcP = (Form_pg_proc)GETSTRUCT(tuple);
if (pgProcP->pronargs == nargs &&
oid8eq(&(pgProcP->proargtypes[0]), argTypes))
FoundMatch = true;
else ReleaseBuffer(buffer);
}
} else ScanComplete = true;
}
Relation idesc;
ScanKeyData skey;
HeapTuple tuple; /* tuple being tested */
HeapTuple return_tuple; /* The tuple pointer we eventually
* return */
IndexScanDesc sd;
RetrieveIndexResult indexRes;
Buffer buffer;
Form_pg_proc pgProcP;
bool ScanComplete;
if (FoundMatch) {
Assert(HeapTupleIsValid(tuple));
return_tuple = heap_copytuple(tuple);
ReleaseBuffer(buffer);
} else return_tuple = (HeapTuple)NULL;
index_endscan(sd);
index_close(idesc);
return return_tuple;
/*
* The index scan is complete, i.e. we've scanned everything there is
* to scan.
*/
bool FoundMatch;
/*
* In scanning pg_proc, we have found a row that meets our search
* criteria.
*/
ScanKeyEntryInitialize(&skey,
(bits16) 0x0,
(AttrNumber) 1,
(RegProcedure) NameEqualRegProcedure,
(Datum) procName);
idesc = index_openr(ProcedureNameIndex);
sd = index_beginscan(idesc, false, 1, &skey);
/*
* for now, we do the work usually done by CatalogIndexFetchTuple by
* hand, so that we can check that the other keys match. when
* multi-key indices are added, they will be used here.
*/
tuple = (HeapTuple) NULL; /* initial value */
ScanComplete = false; /* Scan hasn't begun yet */
FoundMatch = false; /* No match yet; haven't even looked. */
while (!FoundMatch && !ScanComplete)
{
indexRes = index_getnext(sd, ForwardScanDirection);
if (indexRes)
{
ItemPointer iptr;
iptr = &indexRes->heap_iptr;
tuple = heap_fetch(heapRelation, NowTimeQual, iptr, &buffer);
pfree(indexRes);
if (HeapTupleIsValid(tuple))
{
/*
* Here's a row for a procedure that has the sought
* procedure name. To be a match, though, we need it to
* have the right number and type of arguments too, so we
* check that now.
*/
pgProcP = (Form_pg_proc) GETSTRUCT(tuple);
if (pgProcP->pronargs == nargs &&
oid8eq(&(pgProcP->proargtypes[0]), argTypes))
FoundMatch = true;
else
ReleaseBuffer(buffer);
}
}
else
ScanComplete = true;
}
if (FoundMatch)
{
Assert(HeapTupleIsValid(tuple));
return_tuple = heap_copytuple(tuple);
ReleaseBuffer(buffer);
}
else
return_tuple = (HeapTuple) NULL;
index_endscan(sd);
index_close(idesc);
return return_tuple;
}
HeapTuple
ProcedureSrcIndexScan(Relation heapRelation, text *procSrc)
ProcedureSrcIndexScan(Relation heapRelation, text * procSrc)
{
Relation idesc;
IndexScanDesc sd;
ScanKeyData skey;
RetrieveIndexResult indexRes;
HeapTuple tuple;
Buffer buffer;
ScanKeyEntryInitialize(&skey,
(bits16)0x0,
(AttrNumber)Anum_pg_proc_prosrc,
(RegProcedure)TextEqualRegProcedure,
(Datum)procSrc);
idesc = index_openr(ProcedureSrcIndex);
sd = index_beginscan(idesc, false, 1, &skey);
indexRes = index_getnext(sd, ForwardScanDirection);
if (indexRes) {
ItemPointer iptr;
iptr = &indexRes->heap_iptr;
tuple = heap_fetch(heapRelation, NowTimeQual, iptr, &buffer);
pfree(indexRes);
} else
tuple = (HeapTuple)NULL;
if (HeapTupleIsValid(tuple)) {
tuple = heap_copytuple(tuple);
ReleaseBuffer(buffer);
}
index_endscan(sd);
return tuple;
Relation idesc;
IndexScanDesc sd;
ScanKeyData skey;
RetrieveIndexResult indexRes;
HeapTuple tuple;
Buffer buffer;
ScanKeyEntryInitialize(&skey,
(bits16) 0x0,
(AttrNumber) Anum_pg_proc_prosrc,
(RegProcedure) TextEqualRegProcedure,
(Datum) procSrc);
idesc = index_openr(ProcedureSrcIndex);
sd = index_beginscan(idesc, false, 1, &skey);
indexRes = index_getnext(sd, ForwardScanDirection);
if (indexRes)
{
ItemPointer iptr;
iptr = &indexRes->heap_iptr;
tuple = heap_fetch(heapRelation, NowTimeQual, iptr, &buffer);
pfree(indexRes);
}
else
tuple = (HeapTuple) NULL;
if (HeapTupleIsValid(tuple))
{
tuple = heap_copytuple(tuple);
ReleaseBuffer(buffer);
}
index_endscan(sd);
return tuple;
}
HeapTuple
TypeOidIndexScan(Relation heapRelation, Oid typeId)
{
Relation idesc;
ScanKeyData skey;
HeapTuple tuple;
ScanKeyEntryInitialize(&skey,
(bits16)0x0,
(AttrNumber)1,
(RegProcedure)ObjectIdEqualRegProcedure,
(Datum)typeId);
idesc = index_openr(TypeOidIndex);
tuple = CatalogIndexFetchTuple(heapRelation, idesc, &skey);
index_close(idesc);
return tuple;
Relation idesc;
ScanKeyData skey;
HeapTuple tuple;
ScanKeyEntryInitialize(&skey,
(bits16) 0x0,
(AttrNumber) 1,
(RegProcedure) ObjectIdEqualRegProcedure,
(Datum) typeId);
idesc = index_openr(TypeOidIndex);
tuple = CatalogIndexFetchTuple(heapRelation, idesc, &skey);
index_close(idesc);
return tuple;
}
HeapTuple
TypeNameIndexScan(Relation heapRelation, char *typeName)
{
Relation idesc;
ScanKeyData skey;
HeapTuple tuple;
ScanKeyEntryInitialize(&skey,
(bits16)0x0,
(AttrNumber)1,
(RegProcedure)NameEqualRegProcedure,
(Datum)typeName);
idesc = index_openr(TypeNameIndex);
tuple = CatalogIndexFetchTuple(heapRelation, idesc, &skey);
index_close(idesc);
return tuple;
Relation idesc;
ScanKeyData skey;
HeapTuple tuple;
ScanKeyEntryInitialize(&skey,
(bits16) 0x0,
(AttrNumber) 1,
(RegProcedure) NameEqualRegProcedure,
(Datum) typeName);
idesc = index_openr(TypeNameIndex);
tuple = CatalogIndexFetchTuple(heapRelation, idesc, &skey);
index_close(idesc);
return tuple;
}
HeapTuple
ClassNameIndexScan(Relation heapRelation, char *relName)
{
Relation idesc;
ScanKeyData skey;
HeapTuple tuple;
ScanKeyEntryInitialize(&skey,
(bits16)0x0,
(AttrNumber)1,
(RegProcedure)NameEqualRegProcedure,
(Datum)relName);
idesc = index_openr(ClassNameIndex);
tuple = CatalogIndexFetchTuple(heapRelation, idesc, &skey);
index_close(idesc);
return tuple;
Relation idesc;
ScanKeyData skey;
HeapTuple tuple;
ScanKeyEntryInitialize(&skey,
(bits16) 0x0,
(AttrNumber) 1,
(RegProcedure) NameEqualRegProcedure,
(Datum) relName);
idesc = index_openr(ClassNameIndex);
tuple = CatalogIndexFetchTuple(heapRelation, idesc, &skey);
index_close(idesc);
return tuple;
}
HeapTuple
ClassOidIndexScan(Relation heapRelation, Oid relId)
{
Relation idesc;
ScanKeyData skey;
HeapTuple tuple;
ScanKeyEntryInitialize(&skey,
(bits16)0x0,
(AttrNumber)1,
(RegProcedure)ObjectIdEqualRegProcedure,
(Datum)relId);
idesc = index_openr(ClassOidIndex);
tuple = CatalogIndexFetchTuple(heapRelation, idesc, &skey);
index_close(idesc);
return tuple;
Relation idesc;
ScanKeyData skey;
HeapTuple tuple;
ScanKeyEntryInitialize(&skey,
(bits16) 0x0,
(AttrNumber) 1,
(RegProcedure) ObjectIdEqualRegProcedure,
(Datum) relId);
idesc = index_openr(ClassOidIndex);
tuple = CatalogIndexFetchTuple(heapRelation, idesc, &skey);
index_close(idesc);
return tuple;
}

View File

@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* pg_aggregate.c--
* routines to support manipulation of the pg_aggregate relation
* routines to support manipulation of the pg_aggregate relation
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.5 1997/07/24 20:11:47 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.6 1997/09/07 04:40:24 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -24,9 +24,9 @@
#include <catalog/pg_aggregate.h>
#include <miscadmin.h>
#ifndef HAVE_MEMMOVE
# include <regex/utils.h>
#include <regex/utils.h>
#else
# include <string.h>
#include <string.h>
#endif
/* ----------------
@@ -34,288 +34,303 @@
*
* aggregates overloading has been added. Instead of the full
* overload support we have for functions, aggregate overloading only
* applies to exact basetype matches. That is, we don't check the
* applies to exact basetype matches. That is, we don't check the
* the inheritance hierarchy
*
* OLD COMMENTS:
* Currently, redefining aggregates using the same name is not
* supported. In such a case, a warning is printed that the
* aggregate already exists. If such is not the case, a new tuple
* is created and inserted in the aggregate relation. The fields
* of this tuple are aggregate name, owner id, 2 transition functions
* (called aggtransfn1 and aggtransfn2), final function (aggfinalfn),
* type of data on which aggtransfn1 operates (aggbasetype), return
* types of the two transition functions (aggtranstype1 and
* aggtranstype2), final return type (aggfinaltype), and initial values
* for the two state transition functions (agginitval1 and agginitval2).
* All types and functions must have been defined
* prior to defining the aggregate.
*
* Currently, redefining aggregates using the same name is not
* supported. In such a case, a warning is printed that the
* aggregate already exists. If such is not the case, a new tuple
* is created and inserted in the aggregate relation. The fields
* of this tuple are aggregate name, owner id, 2 transition functions
* (called aggtransfn1 and aggtransfn2), final function (aggfinalfn),
* type of data on which aggtransfn1 operates (aggbasetype), return
* types of the two transition functions (aggtranstype1 and
* aggtranstype2), final return type (aggfinaltype), and initial values
* for the two state transition functions (agginitval1 and agginitval2).
* All types and functions must have been defined
* prior to defining the aggregate.
*
* ---------------
*/
void
AggregateCreate(char *aggName,
char *aggtransfn1Name,
char *aggtransfn2Name,
char *aggfinalfnName,
char *aggbasetypeName,
char *aggtransfn1typeName,
char *aggtransfn2typeName,
char *agginitval1,
char *agginitval2)
char *aggtransfn1Name,
char *aggtransfn2Name,
char *aggfinalfnName,
char *aggbasetypeName,
char *aggtransfn1typeName,
char *aggtransfn2typeName,
char *agginitval1,
char *agginitval2)
{
register i;
Relation aggdesc;
HeapTuple tup;
char nulls[Natts_pg_aggregate];
Datum values[Natts_pg_aggregate];
Form_pg_proc proc;
Oid xfn1 = InvalidOid;
Oid xfn2 = InvalidOid;
Oid ffn = InvalidOid;
Oid xbase = InvalidOid;
Oid xret1 = InvalidOid;
Oid xret2 = InvalidOid;
Oid fret = InvalidOid;
Oid fnArgs[8];
TupleDesc tupDesc;
memset(fnArgs, 0, 8 * sizeof(Oid));
/* sanity checks */
if (!aggName)
elog(WARN, "AggregateCreate: no aggregate name supplied");
if (!aggtransfn1Name && !aggtransfn2Name)
elog(WARN, "AggregateCreate: aggregate must have at least one transition function");
tup = SearchSysCacheTuple(TYPNAME,
PointerGetDatum(aggbasetypeName),
0,0,0);
if(!HeapTupleIsValid(tup))
elog(WARN, "AggregateCreate: Type '%s' undefined",aggbasetypeName);
xbase = tup->t_oid;
register i;
Relation aggdesc;
HeapTuple tup;
char nulls[Natts_pg_aggregate];
Datum values[Natts_pg_aggregate];
Form_pg_proc proc;
Oid xfn1 = InvalidOid;
Oid xfn2 = InvalidOid;
Oid ffn = InvalidOid;
Oid xbase = InvalidOid;
Oid xret1 = InvalidOid;
Oid xret2 = InvalidOid;
Oid fret = InvalidOid;
Oid fnArgs[8];
TupleDesc tupDesc;
if (aggtransfn1Name) {
tup = SearchSysCacheTuple(TYPNAME,
PointerGetDatum(aggtransfn1typeName),
0,0,0);
if(!HeapTupleIsValid(tup))
elog(WARN, "AggregateCreate: Type '%s' undefined",
aggtransfn1typeName);
xret1 = tup->t_oid;
fnArgs[0] = xret1;
fnArgs[1] = xbase;
tup = SearchSysCacheTuple(PRONAME,
PointerGetDatum(aggtransfn1Name),
Int32GetDatum(2),
PointerGetDatum(fnArgs),
0);
if(!HeapTupleIsValid(tup))
elog(WARN, "AggregateCreate: '%s('%s', '%s') does not exist",
aggtransfn1Name, aggtransfn1typeName, aggbasetypeName);
if (((Form_pg_proc) GETSTRUCT(tup))->prorettype != xret1)
elog(WARN, "AggregateCreate: return type of '%s' is not '%s'",
aggtransfn1Name,
aggtransfn1typeName);
xfn1 = tup->t_oid;
if (!OidIsValid(xfn1) || !OidIsValid(xret1) ||
!OidIsValid(xbase))
elog(WARN, "AggregateCreate: bogus function '%s'", aggfinalfnName);
}
if (aggtransfn2Name) {
tup = SearchSysCacheTuple(TYPNAME,
PointerGetDatum(aggtransfn2typeName),
0,0,0);
if(!HeapTupleIsValid(tup))
elog(WARN, "AggregateCreate: Type '%s' undefined",
aggtransfn2typeName);
xret2 = tup->t_oid;
fnArgs[0] = xret2;
fnArgs[1] = 0;
tup = SearchSysCacheTuple(PRONAME,
PointerGetDatum(aggtransfn2Name),
Int32GetDatum(1),
PointerGetDatum(fnArgs),
0);
if(!HeapTupleIsValid(tup))
elog(WARN, "AggregateCreate: '%s'('%s') does not exist",
aggtransfn2Name, aggtransfn2typeName);
if (((Form_pg_proc) GETSTRUCT(tup))->prorettype != xret2)
elog(WARN, "AggregateCreate: return type of '%s' is not '%s'",
aggtransfn2Name, aggtransfn2typeName);
xfn2 = tup->t_oid;
if (!OidIsValid(xfn2) || !OidIsValid(xret2))
elog(WARN, "AggregateCreate: bogus function '%s'",aggfinalfnName);
}
tup = SearchSysCacheTuple(AGGNAME, PointerGetDatum(aggName),
ObjectIdGetDatum(xbase),
0,0);
if (HeapTupleIsValid(tup))
elog(WARN,
"AggregateCreate: aggregate '%s' with base type '%s' already exists",
aggName, aggbasetypeName);
memset(fnArgs, 0, 8 * sizeof(Oid));
/* more sanity checks */
if (aggtransfn1Name && aggtransfn2Name && !aggfinalfnName)
elog(WARN, "AggregateCreate: Aggregate must have final function with both transition functions");
if ((!aggtransfn1Name || !aggtransfn2Name) && aggfinalfnName)
elog(WARN, "AggregateCreate: Aggregate cannot have final function without both transition functions");
if (aggfinalfnName) {
fnArgs[0] = xret1;
fnArgs[1] = xret2;
tup = SearchSysCacheTuple(PRONAME,
PointerGetDatum(aggfinalfnName),
Int32GetDatum(2),
PointerGetDatum(fnArgs),
0);
if(!HeapTupleIsValid(tup))
elog(WARN, "AggregateCreate: '%s'('%s','%s') does not exist",
aggfinalfnName, aggtransfn1typeName, aggtransfn2typeName);
ffn = tup->t_oid;
proc = (Form_pg_proc) GETSTRUCT(tup);
fret = proc->prorettype;
if (!OidIsValid(ffn) || !OidIsValid(fret))
elog(WARN, "AggregateCreate: bogus function '%s'", aggfinalfnName);
}
/*
* If transition function 2 is defined, it must have an initial value,
* whereas transition function 1 does not, which allows man and min
* aggregates to return NULL if they are evaluated on empty sets.
*/
if (OidIsValid(xfn2) && !agginitval2)
elog(WARN, "AggregateCreate: transition function 2 MUST have an initial value");
/* initialize nulls and values */
for(i=0; i < Natts_pg_aggregate; i++) {
nulls[i] = ' ';
values[i] = (Datum)NULL;
}
values[Anum_pg_aggregate_aggname-1] = PointerGetDatum(aggName);
values[Anum_pg_aggregate_aggowner-1] =
Int32GetDatum(GetUserId());
values[Anum_pg_aggregate_aggtransfn1-1] =
ObjectIdGetDatum(xfn1);
values[Anum_pg_aggregate_aggtransfn2-1] =
ObjectIdGetDatum(xfn2);
values[Anum_pg_aggregate_aggfinalfn-1] =
ObjectIdGetDatum(ffn);
values[Anum_pg_aggregate_aggbasetype-1] =
ObjectIdGetDatum(xbase);
if (!OidIsValid(xfn1)) {
values[Anum_pg_aggregate_aggtranstype1-1] =
ObjectIdGetDatum(InvalidOid);
values[Anum_pg_aggregate_aggtranstype2-1] =
ObjectIdGetDatum(xret2);
values[Anum_pg_aggregate_aggfinaltype-1] =
ObjectIdGetDatum(xret2);
}
else if (!OidIsValid(xfn2)) {
values[Anum_pg_aggregate_aggtranstype1-1] =
ObjectIdGetDatum(xret1);
values[Anum_pg_aggregate_aggtranstype2-1] =
ObjectIdGetDatum(InvalidOid);
values[Anum_pg_aggregate_aggfinaltype-1] =
ObjectIdGetDatum(xret1);
}
else {
values[Anum_pg_aggregate_aggtranstype1-1] =
ObjectIdGetDatum(xret1);
values[Anum_pg_aggregate_aggtranstype2-1] =
ObjectIdGetDatum(xret2);
values[Anum_pg_aggregate_aggfinaltype-1] =
ObjectIdGetDatum(fret);
}
if (agginitval1)
values[Anum_pg_aggregate_agginitval1-1] = PointerGetDatum(textin(agginitval1));
else
nulls[Anum_pg_aggregate_agginitval1-1] = 'n';
if (agginitval2)
values[Anum_pg_aggregate_agginitval2-1] = PointerGetDatum(textin(agginitval2));
else
nulls[Anum_pg_aggregate_agginitval2-1] = 'n';
if (!RelationIsValid(aggdesc = heap_openr(AggregateRelationName)))
elog(WARN, "AggregateCreate: could not open '%s'",
AggregateRelationName);
/* sanity checks */
if (!aggName)
elog(WARN, "AggregateCreate: no aggregate name supplied");
tupDesc = aggdesc->rd_att;
if (!HeapTupleIsValid(tup = heap_formtuple(tupDesc,
values,
nulls)))
elog(WARN, "AggregateCreate: heap_formtuple failed");
if (!OidIsValid(heap_insert(aggdesc, tup)))
elog(WARN, "AggregateCreate: heap_insert failed");
heap_close(aggdesc);
if (!aggtransfn1Name && !aggtransfn2Name)
elog(WARN, "AggregateCreate: aggregate must have at least one transition function");
tup = SearchSysCacheTuple(TYPNAME,
PointerGetDatum(aggbasetypeName),
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(WARN, "AggregateCreate: Type '%s' undefined", aggbasetypeName);
xbase = tup->t_oid;
if (aggtransfn1Name)
{
tup = SearchSysCacheTuple(TYPNAME,
PointerGetDatum(aggtransfn1typeName),
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(WARN, "AggregateCreate: Type '%s' undefined",
aggtransfn1typeName);
xret1 = tup->t_oid;
fnArgs[0] = xret1;
fnArgs[1] = xbase;
tup = SearchSysCacheTuple(PRONAME,
PointerGetDatum(aggtransfn1Name),
Int32GetDatum(2),
PointerGetDatum(fnArgs),
0);
if (!HeapTupleIsValid(tup))
elog(WARN, "AggregateCreate: '%s('%s', '%s') does not exist",
aggtransfn1Name, aggtransfn1typeName, aggbasetypeName);
if (((Form_pg_proc) GETSTRUCT(tup))->prorettype != xret1)
elog(WARN, "AggregateCreate: return type of '%s' is not '%s'",
aggtransfn1Name,
aggtransfn1typeName);
xfn1 = tup->t_oid;
if (!OidIsValid(xfn1) || !OidIsValid(xret1) ||
!OidIsValid(xbase))
elog(WARN, "AggregateCreate: bogus function '%s'", aggfinalfnName);
}
if (aggtransfn2Name)
{
tup = SearchSysCacheTuple(TYPNAME,
PointerGetDatum(aggtransfn2typeName),
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(WARN, "AggregateCreate: Type '%s' undefined",
aggtransfn2typeName);
xret2 = tup->t_oid;
fnArgs[0] = xret2;
fnArgs[1] = 0;
tup = SearchSysCacheTuple(PRONAME,
PointerGetDatum(aggtransfn2Name),
Int32GetDatum(1),
PointerGetDatum(fnArgs),
0);
if (!HeapTupleIsValid(tup))
elog(WARN, "AggregateCreate: '%s'('%s') does not exist",
aggtransfn2Name, aggtransfn2typeName);
if (((Form_pg_proc) GETSTRUCT(tup))->prorettype != xret2)
elog(WARN, "AggregateCreate: return type of '%s' is not '%s'",
aggtransfn2Name, aggtransfn2typeName);
xfn2 = tup->t_oid;
if (!OidIsValid(xfn2) || !OidIsValid(xret2))
elog(WARN, "AggregateCreate: bogus function '%s'", aggfinalfnName);
}
tup = SearchSysCacheTuple(AGGNAME, PointerGetDatum(aggName),
ObjectIdGetDatum(xbase),
0, 0);
if (HeapTupleIsValid(tup))
elog(WARN,
"AggregateCreate: aggregate '%s' with base type '%s' already exists",
aggName, aggbasetypeName);
/* more sanity checks */
if (aggtransfn1Name && aggtransfn2Name && !aggfinalfnName)
elog(WARN, "AggregateCreate: Aggregate must have final function with both transition functions");
if ((!aggtransfn1Name || !aggtransfn2Name) && aggfinalfnName)
elog(WARN, "AggregateCreate: Aggregate cannot have final function without both transition functions");
if (aggfinalfnName)
{
fnArgs[0] = xret1;
fnArgs[1] = xret2;
tup = SearchSysCacheTuple(PRONAME,
PointerGetDatum(aggfinalfnName),
Int32GetDatum(2),
PointerGetDatum(fnArgs),
0);
if (!HeapTupleIsValid(tup))
elog(WARN, "AggregateCreate: '%s'('%s','%s') does not exist",
aggfinalfnName, aggtransfn1typeName, aggtransfn2typeName);
ffn = tup->t_oid;
proc = (Form_pg_proc) GETSTRUCT(tup);
fret = proc->prorettype;
if (!OidIsValid(ffn) || !OidIsValid(fret))
elog(WARN, "AggregateCreate: bogus function '%s'", aggfinalfnName);
}
/*
* If transition function 2 is defined, it must have an initial value,
* whereas transition function 1 does not, which allows man and min
* aggregates to return NULL if they are evaluated on empty sets.
*/
if (OidIsValid(xfn2) && !agginitval2)
elog(WARN, "AggregateCreate: transition function 2 MUST have an initial value");
/* initialize nulls and values */
for (i = 0; i < Natts_pg_aggregate; i++)
{
nulls[i] = ' ';
values[i] = (Datum) NULL;
}
values[Anum_pg_aggregate_aggname - 1] = PointerGetDatum(aggName);
values[Anum_pg_aggregate_aggowner - 1] =
Int32GetDatum(GetUserId());
values[Anum_pg_aggregate_aggtransfn1 - 1] =
ObjectIdGetDatum(xfn1);
values[Anum_pg_aggregate_aggtransfn2 - 1] =
ObjectIdGetDatum(xfn2);
values[Anum_pg_aggregate_aggfinalfn - 1] =
ObjectIdGetDatum(ffn);
values[Anum_pg_aggregate_aggbasetype - 1] =
ObjectIdGetDatum(xbase);
if (!OidIsValid(xfn1))
{
values[Anum_pg_aggregate_aggtranstype1 - 1] =
ObjectIdGetDatum(InvalidOid);
values[Anum_pg_aggregate_aggtranstype2 - 1] =
ObjectIdGetDatum(xret2);
values[Anum_pg_aggregate_aggfinaltype - 1] =
ObjectIdGetDatum(xret2);
}
else if (!OidIsValid(xfn2))
{
values[Anum_pg_aggregate_aggtranstype1 - 1] =
ObjectIdGetDatum(xret1);
values[Anum_pg_aggregate_aggtranstype2 - 1] =
ObjectIdGetDatum(InvalidOid);
values[Anum_pg_aggregate_aggfinaltype - 1] =
ObjectIdGetDatum(xret1);
}
else
{
values[Anum_pg_aggregate_aggtranstype1 - 1] =
ObjectIdGetDatum(xret1);
values[Anum_pg_aggregate_aggtranstype2 - 1] =
ObjectIdGetDatum(xret2);
values[Anum_pg_aggregate_aggfinaltype - 1] =
ObjectIdGetDatum(fret);
}
if (agginitval1)
values[Anum_pg_aggregate_agginitval1 - 1] = PointerGetDatum(textin(agginitval1));
else
nulls[Anum_pg_aggregate_agginitval1 - 1] = 'n';
if (agginitval2)
values[Anum_pg_aggregate_agginitval2 - 1] = PointerGetDatum(textin(agginitval2));
else
nulls[Anum_pg_aggregate_agginitval2 - 1] = 'n';
if (!RelationIsValid(aggdesc = heap_openr(AggregateRelationName)))
elog(WARN, "AggregateCreate: could not open '%s'",
AggregateRelationName);
tupDesc = aggdesc->rd_att;
if (!HeapTupleIsValid(tup = heap_formtuple(tupDesc,
values,
nulls)))
elog(WARN, "AggregateCreate: heap_formtuple failed");
if (!OidIsValid(heap_insert(aggdesc, tup)))
elog(WARN, "AggregateCreate: heap_insert failed");
heap_close(aggdesc);
}
char *
AggNameGetInitVal(char *aggName, Oid basetype, int xfuncno, bool *isNull)
char *
AggNameGetInitVal(char *aggName, Oid basetype, int xfuncno, bool * isNull)
{
HeapTuple tup;
Relation aggRel;
int initValAttno;
Oid transtype;
text *textInitVal;
char *strInitVal, *initVal;
Assert(PointerIsValid(aggName));
Assert(PointerIsValid(isNull));
Assert(xfuncno == 1 || xfuncno == 2);
HeapTuple tup;
Relation aggRel;
int initValAttno;
Oid transtype;
text *textInitVal;
char *strInitVal,
*initVal;
tup = SearchSysCacheTuple(AGGNAME,
PointerGetDatum(aggName),
PointerGetDatum(basetype),
0,0);
if (!HeapTupleIsValid(tup))
elog(WARN, "AggNameGetInitVal: cache lookup failed for aggregate '%s'",
aggName);
if (xfuncno == 1) {
transtype = ((Form_pg_aggregate) GETSTRUCT(tup))->aggtranstype1;
initValAttno = Anum_pg_aggregate_agginitval1;
}
else /* can only be 1 or 2 */ {
transtype = ((Form_pg_aggregate) GETSTRUCT(tup))->aggtranstype2;
initValAttno = Anum_pg_aggregate_agginitval2;
}
aggRel = heap_openr(AggregateRelationName);
if (!RelationIsValid(aggRel))
elog(WARN, "AggNameGetInitVal: could not open \"%-.*s\"",
AggregateRelationName);
/*
* must use fastgetattr in case one or other of the init values is NULL
*/
textInitVal = (text *) fastgetattr(tup, initValAttno,
RelationGetTupleDescriptor(aggRel),
isNull);
if (!PointerIsValid(textInitVal))
*isNull = true;
if (*isNull) {
Assert(PointerIsValid(aggName));
Assert(PointerIsValid(isNull));
Assert(xfuncno == 1 || xfuncno == 2);
tup = SearchSysCacheTuple(AGGNAME,
PointerGetDatum(aggName),
PointerGetDatum(basetype),
0, 0);
if (!HeapTupleIsValid(tup))
elog(WARN, "AggNameGetInitVal: cache lookup failed for aggregate '%s'",
aggName);
if (xfuncno == 1)
{
transtype = ((Form_pg_aggregate) GETSTRUCT(tup))->aggtranstype1;
initValAttno = Anum_pg_aggregate_agginitval1;
}
else
/* can only be 1 or 2 */
{
transtype = ((Form_pg_aggregate) GETSTRUCT(tup))->aggtranstype2;
initValAttno = Anum_pg_aggregate_agginitval2;
}
aggRel = heap_openr(AggregateRelationName);
if (!RelationIsValid(aggRel))
elog(WARN, "AggNameGetInitVal: could not open \"%-.*s\"",
AggregateRelationName);
/*
* must use fastgetattr in case one or other of the init values is
* NULL
*/
textInitVal = (text *) fastgetattr(tup, initValAttno,
RelationGetTupleDescriptor(aggRel),
isNull);
if (!PointerIsValid(textInitVal))
*isNull = true;
if (*isNull)
{
heap_close(aggRel);
return ((char *) NULL);
}
strInitVal = textout(textInitVal);
heap_close(aggRel);
return((char *) NULL);
}
strInitVal = textout(textInitVal);
heap_close(aggRel);
tup = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(transtype),
0,0,0);
if (!HeapTupleIsValid(tup)) {
tup = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(transtype),
0, 0, 0);
if (!HeapTupleIsValid(tup))
{
pfree(strInitVal);
elog(WARN, "AggNameGetInitVal: cache lookup failed on aggregate transition function return type");
}
initVal = fmgr(((TypeTupleForm) GETSTRUCT(tup))->typinput, strInitVal, -1);
pfree(strInitVal);
elog(WARN, "AggNameGetInitVal: cache lookup failed on aggregate transition function return type");
}
initVal = fmgr(((TypeTupleForm) GETSTRUCT(tup))->typinput, strInitVal, -1);
pfree(strInitVal);
return(initVal);
return (initVal);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* pg_proc.c--
* routines to support manipulation of the pg_proc relation
* routines to support manipulation of the pg_proc relation
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.5 1996/11/08 00:44:34 scrappy Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.6 1997/09/07 04:40:30 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -30,231 +30,252 @@
#include <utils/lsyscache.h>
#include <miscadmin.h>
#ifndef HAVE_MEMMOVE
# include <regex/utils.h>
#include <regex/utils.h>
#else
# include <string.h>
#include <string.h>
#endif
/* ----------------------------------------------------------------
* ProcedureDefine
* ProcedureDefine
* ----------------------------------------------------------------
*/
Oid
ProcedureCreate(char *procedureName,
bool returnsSet,
char *returnTypeName,
char *languageName,
char *prosrc,
char *probin,
bool canCache,
bool trusted,
int32 byte_pct,
int32 perbyte_cpu,
int32 percall_cpu,
int32 outin_ratio,
List *argList,
CommandDest dest)
bool returnsSet,
char *returnTypeName,
char *languageName,
char *prosrc,
char *probin,
bool canCache,
bool trusted,
int32 byte_pct,
int32 perbyte_cpu,
int32 percall_cpu,
int32 outin_ratio,
List * argList,
CommandDest dest)
{
register i;
Relation rdesc;
HeapTuple tup;
bool defined;
uint16 parameterCount;
char nulls[ Natts_pg_proc ];
Datum values[ Natts_pg_proc ];
Oid languageObjectId;
Oid typeObjectId;
List *x;
QueryTreeList *querytree_list;
List *plan_list;
Oid typev[8];
Oid relid;
Oid toid;
text *prosrctext;
TupleDesc tupDesc;
/* ----------------
* sanity checks
* ----------------
*/
Assert(PointerIsValid(prosrc));
Assert(PointerIsValid(probin));
parameterCount = 0;
memset(typev, 0, 8 * sizeof(Oid));
foreach (x, argList) {
Value *t = lfirst(x);
if (parameterCount == 8)
elog(WARN, "Procedures cannot take more than 8 arguments");
if (strcmp(strVal(t), "opaque") == 0) {
if (strcmp(languageName, "sql") == 0) {
elog(WARN, "ProcedureDefine: sql functions cannot take type \"opaque\"");
}
toid = 0;
} else {
toid = TypeGet(strVal(t), &defined);
if (!OidIsValid(toid)) {
elog(WARN, "ProcedureCreate: arg type '%s' is not defined",
strVal(t));
}
if (!defined) {
elog(NOTICE, "ProcedureCreate: arg type '%s' is only a shell",
strVal(t));
}
}
typev[parameterCount++] = toid;
}
tup = SearchSysCacheTuple(PRONAME,
PointerGetDatum(procedureName),
UInt16GetDatum(parameterCount),
PointerGetDatum(typev),
0);
if (HeapTupleIsValid(tup))
elog(WARN, "ProcedureCreate: procedure %s already exists with same arguments",
procedureName);
if (!strcmp(languageName, "sql")) {
/* If this call is defining a set, check if the set is already
* defined by looking to see whether this call's function text
* matches a function already in pg_proc. If so just return the
* OID of the existing set.
*/
if (!strcmp(procedureName, GENERICSETNAME)) {
prosrctext = textin(prosrc);
tup = SearchSysCacheTuple(PROSRC,
PointerGetDatum(prosrctext),
0,0,0);
if (HeapTupleIsValid(tup))
return tup->t_oid;
}
}
tup = SearchSysCacheTuple(LANNAME,
PointerGetDatum(languageName),
0,0,0);
if (!HeapTupleIsValid(tup))
elog(WARN, "ProcedureCreate: no such language %s",
languageName);
languageObjectId = tup->t_oid;
if (strcmp(returnTypeName, "opaque") == 0) {
if (strcmp(languageName, "sql") == 0) {
elog(WARN, "ProcedureCreate: sql functions cannot return type \"opaque\"");
}
typeObjectId = 0;
}
else {
typeObjectId = TypeGet(returnTypeName, &defined);
if (!OidIsValid(typeObjectId)) {
elog(NOTICE, "ProcedureCreate: type '%s' is not yet defined",
returnTypeName);
#if 0
elog(NOTICE, "ProcedureCreate: creating a shell for type '%s'",
returnTypeName);
#endif
typeObjectId = TypeShellMake(returnTypeName);
if (!OidIsValid(typeObjectId)) {
elog(WARN, "ProcedureCreate: could not create type '%s'",
returnTypeName);
}
}
else if (!defined) {
elog(NOTICE, "ProcedureCreate: return type '%s' is only a shell",
returnTypeName);
}
}
/* don't allow functions of complex types that have the same name as
existing attributes of the type */
if (parameterCount == 1 &&
(toid = TypeGet(strVal(lfirst(argList)), &defined)) &&
defined &&
(relid = typeid_get_relid(toid)) != 0 &&
get_attnum(relid, procedureName) != InvalidAttrNumber)
elog(WARN, "method %s already an attribute of type %s",
procedureName, strVal(lfirst(argList)));
/*
* If this is a postquel procedure, we parse it here in order to
* be sure that it contains no syntax errors. We should store
* the plan in an Inversion file for use later, but for now, we
* just store the procedure's text in the prosrc attribute.
*/
if (strcmp(languageName, "sql") == 0) {
plan_list = pg_plan(prosrc, typev, parameterCount,
&querytree_list, dest);
/* typecheck return value */
pg_checkretval(typeObjectId, querytree_list);
}
for (i = 0; i < Natts_pg_proc; ++i) {
nulls[i] = ' ';
values[i] = (Datum)NULL;
}
i = 0;
values[i++] = PointerGetDatum(procedureName);
values[i++] = Int32GetDatum(GetUserId());
values[i++] = ObjectIdGetDatum(languageObjectId);
/* XXX isinherited is always false for now */
values[i++] = Int8GetDatum((bool) 0);
/* XXX istrusted is always false for now */
values[i++] = Int8GetDatum(trusted);
values[i++] = Int8GetDatum(canCache);
values[i++] = UInt16GetDatum(parameterCount);
values[i++] = Int8GetDatum(returnsSet);
values[i++] = ObjectIdGetDatum(typeObjectId);
values[i++] = (Datum) typev;
/*
* The following assignments of constants are made. The real values
* will have to be extracted from the arglist someday soon.
*/
values[i++] = Int32GetDatum(byte_pct); /* probyte_pct */
values[i++] = Int32GetDatum(perbyte_cpu); /* properbyte_cpu */
values[i++] = Int32GetDatum(percall_cpu); /* propercall_cpu */
values[i++] = Int32GetDatum(outin_ratio); /* prooutin_ratio */
values[i++] = (Datum)fmgr(TextInRegProcedure, prosrc); /* prosrc */
values[i++] = (Datum)fmgr(TextInRegProcedure, probin); /* probin */
rdesc = heap_openr(ProcedureRelationName);
tupDesc = rdesc->rd_att;
tup = heap_formtuple(tupDesc,
values,
nulls);
heap_insert(rdesc, tup);
if (RelationGetRelationTupleForm(rdesc)->relhasindex)
{
Relation idescs[Num_pg_proc_indices];
CatalogOpenIndices(Num_pg_proc_indices, Name_pg_proc_indices, idescs);
CatalogIndexInsert(idescs, Num_pg_proc_indices, rdesc, tup);
CatalogCloseIndices(Num_pg_proc_indices, idescs);
}
heap_close(rdesc);
return tup->t_oid;
}
register i;
Relation rdesc;
HeapTuple tup;
bool defined;
uint16 parameterCount;
char nulls[Natts_pg_proc];
Datum values[Natts_pg_proc];
Oid languageObjectId;
Oid typeObjectId;
List *x;
QueryTreeList *querytree_list;
List *plan_list;
Oid typev[8];
Oid relid;
Oid toid;
text *prosrctext;
TupleDesc tupDesc;
/* ----------------
* sanity checks
* ----------------
*/
Assert(PointerIsValid(prosrc));
Assert(PointerIsValid(probin));
parameterCount = 0;
memset(typev, 0, 8 * sizeof(Oid));
foreach(x, argList)
{
Value *t = lfirst(x);
if (parameterCount == 8)
elog(WARN, "Procedures cannot take more than 8 arguments");
if (strcmp(strVal(t), "opaque") == 0)
{
if (strcmp(languageName, "sql") == 0)
{
elog(WARN, "ProcedureDefine: sql functions cannot take type \"opaque\"");
}
toid = 0;
}
else
{
toid = TypeGet(strVal(t), &defined);
if (!OidIsValid(toid))
{
elog(WARN, "ProcedureCreate: arg type '%s' is not defined",
strVal(t));
}
if (!defined)
{
elog(NOTICE, "ProcedureCreate: arg type '%s' is only a shell",
strVal(t));
}
}
typev[parameterCount++] = toid;
}
tup = SearchSysCacheTuple(PRONAME,
PointerGetDatum(procedureName),
UInt16GetDatum(parameterCount),
PointerGetDatum(typev),
0);
if (HeapTupleIsValid(tup))
elog(WARN, "ProcedureCreate: procedure %s already exists with same arguments",
procedureName);
if (!strcmp(languageName, "sql"))
{
/*
* If this call is defining a set, check if the set is already
* defined by looking to see whether this call's function text
* matches a function already in pg_proc. If so just return the
* OID of the existing set.
*/
if (!strcmp(procedureName, GENERICSETNAME))
{
prosrctext = textin(prosrc);
tup = SearchSysCacheTuple(PROSRC,
PointerGetDatum(prosrctext),
0, 0, 0);
if (HeapTupleIsValid(tup))
return tup->t_oid;
}
}
tup = SearchSysCacheTuple(LANNAME,
PointerGetDatum(languageName),
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(WARN, "ProcedureCreate: no such language %s",
languageName);
languageObjectId = tup->t_oid;
if (strcmp(returnTypeName, "opaque") == 0)
{
if (strcmp(languageName, "sql") == 0)
{
elog(WARN, "ProcedureCreate: sql functions cannot return type \"opaque\"");
}
typeObjectId = 0;
}
else
{
typeObjectId = TypeGet(returnTypeName, &defined);
if (!OidIsValid(typeObjectId))
{
elog(NOTICE, "ProcedureCreate: type '%s' is not yet defined",
returnTypeName);
#if 0
elog(NOTICE, "ProcedureCreate: creating a shell for type '%s'",
returnTypeName);
#endif
typeObjectId = TypeShellMake(returnTypeName);
if (!OidIsValid(typeObjectId))
{
elog(WARN, "ProcedureCreate: could not create type '%s'",
returnTypeName);
}
}
else if (!defined)
{
elog(NOTICE, "ProcedureCreate: return type '%s' is only a shell",
returnTypeName);
}
}
/*
* don't allow functions of complex types that have the same name as
* existing attributes of the type
*/
if (parameterCount == 1 &&
(toid = TypeGet(strVal(lfirst(argList)), &defined)) &&
defined &&
(relid = typeid_get_relid(toid)) != 0 &&
get_attnum(relid, procedureName) != InvalidAttrNumber)
elog(WARN, "method %s already an attribute of type %s",
procedureName, strVal(lfirst(argList)));
/*
* If this is a postquel procedure, we parse it here in order to be
* sure that it contains no syntax errors. We should store the plan
* in an Inversion file for use later, but for now, we just store the
* procedure's text in the prosrc attribute.
*/
if (strcmp(languageName, "sql") == 0)
{
plan_list = pg_plan(prosrc, typev, parameterCount,
&querytree_list, dest);
/* typecheck return value */
pg_checkretval(typeObjectId, querytree_list);
}
for (i = 0; i < Natts_pg_proc; ++i)
{
nulls[i] = ' ';
values[i] = (Datum) NULL;
}
i = 0;
values[i++] = PointerGetDatum(procedureName);
values[i++] = Int32GetDatum(GetUserId());
values[i++] = ObjectIdGetDatum(languageObjectId);
/* XXX isinherited is always false for now */
values[i++] = Int8GetDatum((bool) 0);
/* XXX istrusted is always false for now */
values[i++] = Int8GetDatum(trusted);
values[i++] = Int8GetDatum(canCache);
values[i++] = UInt16GetDatum(parameterCount);
values[i++] = Int8GetDatum(returnsSet);
values[i++] = ObjectIdGetDatum(typeObjectId);
values[i++] = (Datum) typev;
/*
* The following assignments of constants are made. The real values
* will have to be extracted from the arglist someday soon.
*/
values[i++] = Int32GetDatum(byte_pct); /* probyte_pct */
values[i++] = Int32GetDatum(perbyte_cpu); /* properbyte_cpu */
values[i++] = Int32GetDatum(percall_cpu); /* propercall_cpu */
values[i++] = Int32GetDatum(outin_ratio); /* prooutin_ratio */
values[i++] = (Datum) fmgr(TextInRegProcedure, prosrc); /* prosrc */
values[i++] = (Datum) fmgr(TextInRegProcedure, probin); /* probin */
rdesc = heap_openr(ProcedureRelationName);
tupDesc = rdesc->rd_att;
tup = heap_formtuple(tupDesc,
values,
nulls);
heap_insert(rdesc, tup);
if (RelationGetRelationTupleForm(rdesc)->relhasindex)
{
Relation idescs[Num_pg_proc_indices];
CatalogOpenIndices(Num_pg_proc_indices, Name_pg_proc_indices, idescs);
CatalogIndexInsert(idescs, Num_pg_proc_indices, rdesc, tup);
CatalogCloseIndices(Num_pg_proc_indices, idescs);
}
heap_close(rdesc);
return tup->t_oid;
}

File diff suppressed because it is too large Load Diff