aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/command.c
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>1997-09-07 05:04:48 +0000
committerBruce Momjian <bruce@momjian.us>1997-09-07 05:04:48 +0000
commit1ccd423235a48739d6f7a4d7889705b5f9ecc69b (patch)
tree8001c4e839dfad8f29ceda7f8c5f5dbb8759b564 /src/backend/commands/command.c
parent8fecd4febf8357f3cc20383ed29ced484877d5ac (diff)
downloadpostgresql-1ccd423235a48739d6f7a4d7889705b5f9ecc69b.tar.gz
postgresql-1ccd423235a48739d6f7a4d7889705b5f9ecc69b.zip
Massive commit to run PGINDENT on all *.c and *.h files.
Diffstat (limited to 'src/backend/commands/command.c')
-rw-r--r--src/backend/commands/command.c827
1 files changed, 426 insertions, 401 deletions
diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c
index 376bd3ae5fa..7af9b37c072 100644
--- a/src/backend/commands/command.c
+++ b/src/backend/commands/command.c
@@ -1,29 +1,29 @@
/*-------------------------------------------------------------------------
*
* command.c--
- * random postgres portal and utility support code
+ * random postgres portal and utility support code
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.13 1997/08/22 14:22:07 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.14 1997/09/07 04:40:38 momjian Exp $
*
* NOTES
- * The PortalExecutorHeapMemory crap needs to be eliminated
- * by designing a better executor / portal processing memory
- * interface.
- *
- * The PerformAddAttribute() code, like most of the relation
- * manipulating code in the commands/ directory, should go
- * someplace closer to the lib/catalog code.
- *
+ * The PortalExecutorHeapMemory crap needs to be eliminated
+ * by designing a better executor / portal processing memory
+ * interface.
+ *
+ * The PerformAddAttribute() code, like most of the relation
+ * manipulating code in the commands/ directory, should go
+ * someplace closer to the lib/catalog code.
+ *
*-------------------------------------------------------------------------
*/
#include <postgres.h>
#include <access/relscan.h>
-#include <utils/portal.h>
+#include <utils/portal.h>
#include <commands/command.h>
#include <utils/mcxt.h>
#include <executor/executor.h>
@@ -31,7 +31,7 @@
#include <catalog/indexing.h>
#include <utils/syscache.h>
#include <catalog/catalog.h>
-#include <access/heapam.h>
+#include <access/heapam.h>
#include <utils/array.h>
#include <utils/acl.h>
#include <optimizer/prep.h>
@@ -41,443 +41,468 @@
#include <utils/builtins.h>
/* ----------------
- * PortalExecutorHeapMemory stuff
+ * PortalExecutorHeapMemory stuff
*
- * This is where the XXXSuperDuperHacky code was. -cim 3/15/90
+ * This is where the XXXSuperDuperHacky code was. -cim 3/15/90
* ----------------
*/
-MemoryContext PortalExecutorHeapMemory = NULL;
+MemoryContext PortalExecutorHeapMemory = NULL;
/* --------------------------------
- * PortalCleanup
+ * PortalCleanup
* --------------------------------
*/
void
PortalCleanup(Portal portal)
{
- MemoryContext context;
-
- /* ----------------
- * sanity checks
- * ----------------
- */
- AssertArg(PortalIsValid(portal));
- AssertArg(portal->cleanup == PortalCleanup);
-
- /* ----------------
- * set proper portal-executor context before calling ExecMain.
- * ----------------
- */
- context = MemoryContextSwitchTo((MemoryContext) PortalGetHeapMemory(portal));
- PortalExecutorHeapMemory = (MemoryContext)
- PortalGetHeapMemory(portal);
-
- /* ----------------
- * tell the executor to shutdown the query
- * ----------------
- */
- ExecutorEnd(PortalGetQueryDesc(portal), PortalGetState(portal));
-
- /* ----------------
- * switch back to previous context
- * ----------------
- */
- MemoryContextSwitchTo(context);
- PortalExecutorHeapMemory = (MemoryContext) NULL;
+ MemoryContext context;
+
+ /* ----------------
+ * sanity checks
+ * ----------------
+ */
+ AssertArg(PortalIsValid(portal));
+ AssertArg(portal->cleanup == PortalCleanup);
+
+ /* ----------------
+ * set proper portal-executor context before calling ExecMain.
+ * ----------------
+ */
+ context = MemoryContextSwitchTo((MemoryContext) PortalGetHeapMemory(portal));
+ PortalExecutorHeapMemory = (MemoryContext)
+ PortalGetHeapMemory(portal);
+
+ /* ----------------
+ * tell the executor to shutdown the query
+ * ----------------
+ */
+ ExecutorEnd(PortalGetQueryDesc(portal), PortalGetState(portal));
+
+ /* ----------------
+ * switch back to previous context
+ * ----------------
+ */
+ MemoryContextSwitchTo(context);
+ PortalExecutorHeapMemory = (MemoryContext) NULL;
}
/* --------------------------------
- * PerformPortalFetch
+ * PerformPortalFetch
* --------------------------------
*/
void
PerformPortalFetch(char *name,
- bool forward,
- int count,
- char *tag,
- CommandDest dest)
+ bool forward,
+ int count,
+ char *tag,
+ CommandDest dest)
{
- Portal portal;
- int feature;
- QueryDesc *queryDesc;
- MemoryContext context;
-
- /* ----------------
- * sanity checks
- * ----------------
- */
- if (name == NULL) {
- elog(NOTICE, "PerformPortalFetch: blank portal unsupported");
- return;
- }
-
- /* ----------------
- * get the portal from the portal name
- * ----------------
- */
- portal = GetPortalByName(name);
- if (! PortalIsValid(portal)) {
- elog(NOTICE, "PerformPortalFetch: portal \"%s\" not found",
- name);
- return;
- }
-
- /* ----------------
- * switch into the portal context
- * ----------------
- */
- context= MemoryContextSwitchTo((MemoryContext)PortalGetHeapMemory(portal));
-
- AssertState(context ==
- (MemoryContext)PortalGetHeapMemory(GetPortalByName(NULL)));
-
- /* ----------------
- * setup "feature" to tell the executor what direction and
- * how many tuples to fetch.
- * ----------------
- */
- if (forward)
- feature = EXEC_FOR;
- else
- feature = EXEC_BACK;
-
- /* ----------------
- * tell the destination to prepare to recieve some tuples
- * ----------------
- */
- queryDesc = PortalGetQueryDesc(portal);
- BeginCommand(name,
- queryDesc->operation,
- portal->attinfo,/* QueryDescGetTypeInfo(queryDesc), */
- false, /* portal fetches don't end up in relations */
- false, /* this is a portal fetch, not a "retrieve portal" */
- tag,
- dest);
-
- /* ----------------
- * execute the portal fetch operation
- * ----------------
- */
- PortalExecutorHeapMemory = (MemoryContext)
- PortalGetHeapMemory(portal);
-
- ExecutorRun(queryDesc, PortalGetState(portal), feature, count);
-
- /* ----------------
- * Note: the "end-of-command" tag is returned by higher-level
- * utility code
- *
- * Return blank portal for now.
- * Otherwise, this named portal will be cleaned.
- * Note: portals will only be supported within a BEGIN...END
- * block in the near future. Later, someone will fix it to
- * do what is possible across transaction boundries.
- * ----------------
- */
- MemoryContextSwitchTo(
- (MemoryContext)PortalGetHeapMemory(GetPortalByName(NULL)));
+ Portal portal;
+ int feature;
+ QueryDesc *queryDesc;
+ MemoryContext context;
+
+ /* ----------------
+ * sanity checks
+ * ----------------
+ */
+ if (name == NULL)
+ {
+ elog(NOTICE, "PerformPortalFetch: blank portal unsupported");
+ return;
+ }
+
+ /* ----------------
+ * get the portal from the portal name
+ * ----------------
+ */
+ portal = GetPortalByName(name);
+ if (!PortalIsValid(portal))
+ {
+ elog(NOTICE, "PerformPortalFetch: portal \"%s\" not found",
+ name);
+ return;
+ }
+
+ /* ----------------
+ * switch into the portal context
+ * ----------------
+ */
+ context = MemoryContextSwitchTo((MemoryContext) PortalGetHeapMemory(portal));
+
+ AssertState(context ==
+ (MemoryContext) PortalGetHeapMemory(GetPortalByName(NULL)));
+
+ /* ----------------
+ * setup "feature" to tell the executor what direction and
+ * how many tuples to fetch.
+ * ----------------
+ */
+ if (forward)
+ feature = EXEC_FOR;
+ else
+ feature = EXEC_BACK;
+
+ /* ----------------
+ * tell the destination to prepare to recieve some tuples
+ * ----------------
+ */
+ queryDesc = PortalGetQueryDesc(portal);
+ BeginCommand(name,
+ queryDesc->operation,
+ portal->attinfo, /* QueryDescGetTypeInfo(queryDesc),
+ * */
+ false, /* portal fetches don't end up in
+ * relations */
+ false, /* this is a portal fetch, not a "retrieve
+ * portal" */
+ tag,
+ dest);
+
+ /* ----------------
+ * execute the portal fetch operation
+ * ----------------
+ */
+ PortalExecutorHeapMemory = (MemoryContext)
+ PortalGetHeapMemory(portal);
+
+ ExecutorRun(queryDesc, PortalGetState(portal), feature, count);
+
+ /* ----------------
+ * Note: the "end-of-command" tag is returned by higher-level
+ * utility code
+ *
+ * Return blank portal for now.
+ * Otherwise, this named portal will be cleaned.
+ * Note: portals will only be supported within a BEGIN...END
+ * block in the near future. Later, someone will fix it to
+ * do what is possible across transaction boundries.
+ * ----------------
+ */
+ MemoryContextSwitchTo(
+ (MemoryContext) PortalGetHeapMemory(GetPortalByName(NULL)));
}
/* --------------------------------
- * PerformPortalClose
+ * PerformPortalClose
* --------------------------------
*/
void
PerformPortalClose(char *name, CommandDest dest)
{
- Portal portal;
-
- /* ----------------
- * sanity checks
- * ----------------
- */
- if (name == NULL) {
- elog(NOTICE, "PerformPortalClose: blank portal unsupported");
- return;
- }
-
- /* ----------------
- * get the portal from the portal name
- * ----------------
- */
- portal = GetPortalByName(name);
- if (! PortalIsValid(portal)) {
- elog(NOTICE, "PerformPortalClose: portal \"%s\" not found",
- name);
- return;
- }
-
- /* ----------------
- * Note: PortalCleanup is called as a side-effect
- * ----------------
- */
- PortalDestroy(&portal);
+ Portal portal;
+
+ /* ----------------
+ * sanity checks
+ * ----------------
+ */
+ if (name == NULL)
+ {
+ elog(NOTICE, "PerformPortalClose: blank portal unsupported");
+ return;
+ }
+
+ /* ----------------
+ * get the portal from the portal name
+ * ----------------
+ */
+ portal = GetPortalByName(name);
+ if (!PortalIsValid(portal))
+ {
+ elog(NOTICE, "PerformPortalClose: portal \"%s\" not found",
+ name);
+ return;
+ }
+
+ /* ----------------
+ * Note: PortalCleanup is called as a side-effect
+ * ----------------
+ */
+ PortalDestroy(&portal);
}
/* ----------------
- * PerformAddAttribute
+ * PerformAddAttribute
*
- * adds an additional attribute to a relation
+ * adds an additional attribute to a relation
*
- * Adds attribute field(s) to a relation. Each new attribute
- * is given attnums in sequential order and is added to the
- * ATTRIBUTE relation. If the AMI fails, defunct tuples will
- * remain in the ATTRIBUTE relation for later vacuuming.
- * Later, there may be some reserved attribute names???
+ * Adds attribute field(s) to a relation. Each new attribute
+ * is given attnums in sequential order and is added to the
+ * ATTRIBUTE relation. If the AMI fails, defunct tuples will
+ * remain in the ATTRIBUTE relation for later vacuuming.
+ * Later, there may be some reserved attribute names???
*
- * (If needed, can instead use elog to handle exceptions.)
+ * (If needed, can instead use elog to handle exceptions.)
*
- * Note:
- * Initial idea of ordering the tuple attributes so that all
- * the variable length domains occured last was scratched. Doing
- * so would not speed access too much (in general) and would create
- * many complications in formtuple, amgetattr, and addattribute.
+ * Note:
+ * Initial idea of ordering the tuple attributes so that all
+ * the variable length domains occured last was scratched. Doing
+ * so would not speed access too much (in general) and would create
+ * many complications in formtuple, amgetattr, and addattribute.
*
- * scan attribute catalog for name conflict (within rel)
- * scan type catalog for absence of data type (if not arg)
- * create attnum magically???
- * create attribute tuple
- * insert attribute in attribute catalog
- * modify reldesc
- * create new relation tuple
- * insert new relation in relation catalog
- * delete original relation from relation catalog
+ * scan attribute catalog for name conflict (within rel)
+ * scan type catalog for absence of data type (if not arg)
+ * create attnum magically???
+ * create attribute tuple
+ * insert attribute in attribute catalog
+ * modify reldesc
+ * create new relation tuple
+ * insert new relation in relation catalog
+ * delete original relation from relation catalog
* ----------------
*/
void
PerformAddAttribute(char *relationName,
- char *userName,
- bool inherits,
- ColumnDef *colDef)
-{
- Relation relrdesc, attrdesc;
- HeapScanDesc attsdesc;
- HeapTuple reltup;
- HeapTuple attributeTuple;
- AttributeTupleForm attribute;
- FormData_pg_attribute attributeD;
- int i;
- int minattnum, maxatts;
- HeapTuple tup;
- ScanKeyData key[2];
- ItemPointerData oldTID;
- Relation idescs[Num_pg_attr_indices];
- Relation ridescs[Num_pg_class_indices];
- bool hasindex;
-
- /*
- * permissions checking. this would normally be done in utility.c,
- * but this particular routine is recursive.
- *
- * normally, only the owner of a class can change its schema.
- */
- if (IsSystemRelationName(relationName))
- elog(WARN, "PerformAddAttribute: class \"%s\" is a system catalog",
- relationName);
+ char *userName,
+ bool inherits,
+ ColumnDef * colDef)
+{
+ Relation relrdesc,
+ attrdesc;
+ HeapScanDesc attsdesc;
+ HeapTuple reltup;
+ HeapTuple attributeTuple;
+ AttributeTupleForm attribute;
+ FormData_pg_attribute attributeD;
+ int i;
+ int minattnum,
+ maxatts;
+ HeapTuple tup;
+ ScanKeyData key[2];
+ ItemPointerData oldTID;
+ Relation idescs[Num_pg_attr_indices];
+ Relation ridescs[Num_pg_class_indices];
+ bool hasindex;
+
+ /*
+ * permissions checking. this would normally be done in utility.c,
+ * but this particular routine is recursive.
+ *
+ * normally, only the owner of a class can change its schema.
+ */
+ if (IsSystemRelationName(relationName))
+ elog(WARN, "PerformAddAttribute: class \"%s\" is a system catalog",
+ relationName);
#ifndef NO_SECURITY
- if (!pg_ownercheck(userName, relationName, RELNAME))
- elog(WARN, "PerformAddAttribute: you do not own class \"%s\"",
- relationName);
+ if (!pg_ownercheck(userName, relationName, RELNAME))
+ elog(WARN, "PerformAddAttribute: you do not own class \"%s\"",
+ relationName);
#endif
- /*
- * we can't add a not null attribute
- */
- if (colDef->is_not_null)
- elog(WARN,"Can't add a not null attribute to a existent relation");
- if (colDef->defval)
- elog(WARN,"ADD ATTRIBUTE: DEFAULT is not implemented, yet");
- /*
- * if the first element in the 'schema' list is a "*" then we are
- * supposed to add this attribute to all classes that inherit from
- * 'relationName' (as well as to 'relationName').
- *
- * any permissions or problems with duplicate attributes will cause
- * the whole transaction to abort, which is what we want -- all or
- * nothing.
- */
- if (colDef != NULL) {
- if (inherits) {
- Oid myrelid, childrelid;
- List *child, *children;
-
- relrdesc = heap_openr(relationName);
- if (!RelationIsValid(relrdesc)) {
- elog(WARN, "PerformAddAttribute: unknown relation: \"%s\"",
- relationName);
- }
- myrelid = relrdesc->rd_id;
- heap_close(relrdesc);
-
- /* this routine is actually in the planner */
- children = find_all_inheritors(lconsi(myrelid,NIL), NIL);
-
- /*
- * find_all_inheritors does the recursive search of the
- * inheritance hierarchy, so all we have to do is process
- * all of the relids in the list that it returns.
- */
- foreach (child, children) {
- childrelid = lfirsti(child);
- if (childrelid == myrelid)
- continue;
- relrdesc = heap_open(childrelid);
- if (!RelationIsValid(relrdesc)) {
- elog(WARN, "PerformAddAttribute: can't find catalog entry for inheriting class with oid %d",
- childrelid);
+
+ /*
+ * we can't add a not null attribute
+ */
+ if (colDef->is_not_null)
+ elog(WARN, "Can't add a not null attribute to a existent relation");
+ if (colDef->defval)
+ elog(WARN, "ADD ATTRIBUTE: DEFAULT is not implemented, yet");
+
+ /*
+ * if the first element in the 'schema' list is a "*" then we are
+ * supposed to add this attribute to all classes that inherit from
+ * 'relationName' (as well as to 'relationName').
+ *
+ * any permissions or problems with duplicate attributes will cause the
+ * whole transaction to abort, which is what we want -- all or
+ * nothing.
+ */
+ if (colDef != NULL)
+ {
+ if (inherits)
+ {
+ Oid myrelid,
+ childrelid;
+ List *child,
+ *children;
+
+ relrdesc = heap_openr(relationName);
+ if (!RelationIsValid(relrdesc))
+ {
+ elog(WARN, "PerformAddAttribute: unknown relation: \"%s\"",
+ relationName);
+ }
+ myrelid = relrdesc->rd_id;
+ heap_close(relrdesc);
+
+ /* this routine is actually in the planner */
+ children = find_all_inheritors(lconsi(myrelid, NIL), NIL);
+
+ /*
+ * find_all_inheritors does the recursive search of the
+ * inheritance hierarchy, so all we have to do is process all
+ * of the relids in the list that it returns.
+ */
+ foreach(child, children)
+ {
+ childrelid = lfirsti(child);
+ if (childrelid == myrelid)
+ continue;
+ relrdesc = heap_open(childrelid);
+ if (!RelationIsValid(relrdesc))
+ {
+ elog(WARN, "PerformAddAttribute: can't find catalog entry for inheriting class with oid %d",
+ childrelid);
+ }
+ PerformAddAttribute((relrdesc->rd_rel->relname).data,
+ userName, false, colDef);
+ heap_close(relrdesc);
+ }
}
- PerformAddAttribute((relrdesc->rd_rel->relname).data,
- userName, false, colDef);
+ }
+
+ relrdesc = heap_openr(RelationRelationName);
+ reltup = ClassNameIndexScan(relrdesc, relationName);
+
+ if (!PointerIsValid(reltup))
+ {
heap_close(relrdesc);
- }
+ elog(WARN, "PerformAddAttribute: relation \"%s\" not found",
+ relationName);
}
- }
-
- relrdesc = heap_openr(RelationRelationName);
- reltup = ClassNameIndexScan(relrdesc, relationName);
-
- if (!PointerIsValid(reltup)) {
- heap_close(relrdesc);
- elog(WARN, "PerformAddAttribute: relation \"%s\" not found",
- relationName);
- }
- /*
- * XXX is the following check sufficient?
- */
- if (((Form_pg_class) GETSTRUCT(reltup))->relkind == RELKIND_INDEX) {
- elog(WARN, "PerformAddAttribute: index relation \"%s\" not changed",
- relationName);
- return;
- }
-
- minattnum = ((Form_pg_class) GETSTRUCT(reltup))->relnatts;
- maxatts = minattnum + 1;
- if (maxatts > MaxHeapAttributeNumber) {
- pfree(reltup); /* XXX temp */
- heap_close(relrdesc); /* XXX temp */
- elog(WARN, "PerformAddAttribute: relations limited to %d attributes",
- MaxHeapAttributeNumber);
- return;
- }
-
- attrdesc = heap_openr(AttributeRelationName);
-
- Assert(attrdesc);
- Assert(RelationGetRelationTupleForm(attrdesc));
-
- /*
- * Open all (if any) pg_attribute indices
- */
- hasindex = RelationGetRelationTupleForm(attrdesc)->relhasindex;
- if (hasindex)
- CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
-
- ScanKeyEntryInitialize(&key[0],
- (bits16) NULL,
- (AttrNumber) Anum_pg_attribute_attrelid,
- (RegProcedure)ObjectIdEqualRegProcedure,
- (Datum) reltup->t_oid);
-
- ScanKeyEntryInitialize(&key[1],
- (bits16) NULL,
- (AttrNumber) Anum_pg_attribute_attname,
- (RegProcedure)NameEqualRegProcedure,
- (Datum) NULL);
-
- attributeD.attrelid = reltup->t_oid;
- attributeD.attdisbursion = 0; /* XXX temporary */
- attributeD.attcacheoff = -1;
-
- attributeTuple = heap_addheader(Natts_pg_attribute,
- sizeof attributeD,
- (char *)&attributeD);
-
- attribute = (AttributeTupleForm)GETSTRUCT(attributeTuple);
-
- i = 1 + minattnum;
-
- {
- HeapTuple typeTuple;
- TypeTupleForm form;
- char *p;
- int attnelems;
-
+
/*
- * XXX use syscache here as an optimization
+ * XXX is the following check sufficient?
*/
- key[1].sk_argument = (Datum)colDef->colname;
- attsdesc = heap_beginscan(attrdesc, 0, NowTimeQual, 2, key);
-
-
- tup = heap_getnext(attsdesc, 0, (Buffer *) NULL);
- if (HeapTupleIsValid(tup)) {
- pfree(reltup); /* XXX temp */
- heap_endscan(attsdesc); /* XXX temp */
- heap_close(attrdesc); /* XXX temp */
- heap_close(relrdesc); /* XXX temp */
- elog(WARN, "PerformAddAttribute: attribute \"%s\" already exists in class \"%s\"",
- key[1].sk_argument,
- relationName);
- return;
+ if (((Form_pg_class) GETSTRUCT(reltup))->relkind == RELKIND_INDEX)
+ {
+ elog(WARN, "PerformAddAttribute: index relation \"%s\" not changed",
+ relationName);
+ return;
+ }
+
+ minattnum = ((Form_pg_class) GETSTRUCT(reltup))->relnatts;
+ maxatts = minattnum + 1;
+ if (maxatts > MaxHeapAttributeNumber)
+ {
+ pfree(reltup); /* XXX temp */
+ heap_close(relrdesc); /* XXX temp */
+ elog(WARN, "PerformAddAttribute: relations limited to %d attributes",
+ MaxHeapAttributeNumber);
+ return;
}
- heap_endscan(attsdesc);
-
+
+ attrdesc = heap_openr(AttributeRelationName);
+
+ Assert(attrdesc);
+ Assert(RelationGetRelationTupleForm(attrdesc));
+
/*
- * check to see if it is an array attribute.
+ * Open all (if any) pg_attribute indices
*/
-
- p = colDef->typename->name;
-
- if (colDef->typename->arrayBounds)
- {
- attnelems = length(colDef->typename->arrayBounds);
- p = makeArrayTypeName(colDef->typename->name);
- }
- else
- attnelems = 0;
-
- typeTuple = SearchSysCacheTuple(TYPNAME,
- PointerGetDatum(p),
- 0,0,0);
- form = (TypeTupleForm)GETSTRUCT(typeTuple);
-
- if (!HeapTupleIsValid(typeTuple)) {
- elog(WARN, "Add: type \"%s\" nonexistent", p);
+ hasindex = RelationGetRelationTupleForm(attrdesc)->relhasindex;
+ if (hasindex)
+ CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
+
+ ScanKeyEntryInitialize(&key[0],
+ (bits16) NULL,
+ (AttrNumber) Anum_pg_attribute_attrelid,
+ (RegProcedure) ObjectIdEqualRegProcedure,
+ (Datum) reltup->t_oid);
+
+ ScanKeyEntryInitialize(&key[1],
+ (bits16) NULL,
+ (AttrNumber) Anum_pg_attribute_attname,
+ (RegProcedure) NameEqualRegProcedure,
+ (Datum) NULL);
+
+ attributeD.attrelid = reltup->t_oid;
+ attributeD.attdisbursion = 0; /* XXX temporary */
+ attributeD.attcacheoff = -1;
+
+ attributeTuple = heap_addheader(Natts_pg_attribute,
+ sizeof attributeD,
+ (char *) &attributeD);
+
+ attribute = (AttributeTupleForm) GETSTRUCT(attributeTuple);
+
+ i = 1 + minattnum;
+
+ {
+ HeapTuple typeTuple;
+ TypeTupleForm form;
+ char *p;
+ int attnelems;
+
+ /*
+ * XXX use syscache here as an optimization
+ */
+ key[1].sk_argument = (Datum) colDef->colname;
+ attsdesc = heap_beginscan(attrdesc, 0, NowTimeQual, 2, key);
+
+
+ tup = heap_getnext(attsdesc, 0, (Buffer *) NULL);
+ if (HeapTupleIsValid(tup))
+ {
+ pfree(reltup); /* XXX temp */
+ heap_endscan(attsdesc); /* XXX temp */
+ heap_close(attrdesc); /* XXX temp */
+ heap_close(relrdesc); /* XXX temp */
+ elog(WARN, "PerformAddAttribute: attribute \"%s\" already exists in class \"%s\"",
+ key[1].sk_argument,
+ relationName);
+ return;
+ }
+ heap_endscan(attsdesc);
+
+ /*
+ * check to see if it is an array attribute.
+ */
+
+ p = colDef->typename->name;
+
+ if (colDef->typename->arrayBounds)
+ {
+ attnelems = length(colDef->typename->arrayBounds);
+ p = makeArrayTypeName(colDef->typename->name);
+ }
+ else
+ attnelems = 0;
+
+ typeTuple = SearchSysCacheTuple(TYPNAME,
+ PointerGetDatum(p),
+ 0, 0, 0);
+ form = (TypeTupleForm) GETSTRUCT(typeTuple);
+
+ if (!HeapTupleIsValid(typeTuple))
+ {
+ elog(WARN, "Add: type \"%s\" nonexistent", p);
+ }
+ namestrcpy(&(attribute->attname), (char *) key[1].sk_argument);
+ attribute->atttypid = typeTuple->t_oid;
+ if (colDef->typename->typlen > 0)
+ attribute->attlen = colDef->typename->typlen;
+ else
+/* bpchar, varchar, text */
+ attribute->attlen = form->typlen;
+ attribute->attnum = i;
+ attribute->attbyval = form->typbyval;
+ attribute->attnelems = attnelems;
+ attribute->attcacheoff = -1;
+ attribute->attisset = (bool) (form->typtype == 'c');
+ attribute->attalign = form->typalign;
+ attribute->attnotnull = false;
+
+ heap_insert(attrdesc, attributeTuple);
+ if (hasindex)
+ CatalogIndexInsert(idescs,
+ Num_pg_attr_indices,
+ attrdesc,
+ attributeTuple);
}
- namestrcpy(&(attribute->attname), (char*) key[1].sk_argument);
- attribute->atttypid = typeTuple->t_oid;
- if (colDef->typename->typlen > 0)
- attribute->attlen = colDef->typename->typlen;
- else /* bpchar, varchar, text */
- attribute->attlen = form->typlen;
- attribute->attnum = i;
- attribute->attbyval = form->typbyval;
- attribute->attnelems = attnelems;
- attribute->attcacheoff = -1;
- attribute->attisset = (bool) (form->typtype == 'c');
- attribute->attalign = form->typalign;
- attribute->attnotnull = false;
-
- heap_insert(attrdesc, attributeTuple);
+
if (hasindex)
- CatalogIndexInsert(idescs,
- Num_pg_attr_indices,
- attrdesc,
- attributeTuple);
- }
-
- if (hasindex)
- CatalogCloseIndices(Num_pg_attr_indices, idescs);
- heap_close(attrdesc);
-
- ((Form_pg_class) GETSTRUCT(reltup))->relnatts = maxatts;
- oldTID = reltup->t_ctid;
- heap_replace(relrdesc, &oldTID, reltup);
-
- /* keep catalog indices current */
- CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);
- CatalogIndexInsert(ridescs, Num_pg_class_indices, relrdesc, reltup);
- CatalogCloseIndices(Num_pg_class_indices, ridescs);
-
- pfree(reltup);
- heap_close(relrdesc);
+ CatalogCloseIndices(Num_pg_attr_indices, idescs);
+ heap_close(attrdesc);
+
+ ((Form_pg_class) GETSTRUCT(reltup))->relnatts = maxatts;
+ oldTID = reltup->t_ctid;
+ heap_replace(relrdesc, &oldTID, reltup);
+
+ /* keep catalog indices current */
+ CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);
+ CatalogIndexInsert(ridescs, Num_pg_class_indices, relrdesc, reltup);
+ CatalogCloseIndices(Num_pg_class_indices, ridescs);
+
+ pfree(reltup);
+ heap_close(relrdesc);
}