diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index b476a1181ea..19ab896ac4e 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.232 2002/10/21 22:06:18 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.232.2.1 2002/12/16 18:39:56 tgl Exp $ * * * INTERFACE ROUTINES @@ -306,8 +306,8 @@ heap_storage_create(Relation rel) * * this is done in 6 steps: * - * 1) CheckAttributeNames() is used to make certain the tuple - * descriptor contains a valid set of attribute names + * 1) CheckAttributeNamesTypes() is used to make certain the tuple + * descriptor contains a valid set of attribute names and types * * 2) pg_class is opened and get_relname_relid() * performs a scan to ensure that no relation with the @@ -333,20 +333,25 @@ heap_storage_create(Relation rel) */ /* -------------------------------- - * CheckAttributeNames + * CheckAttributeNamesTypes * * this is used to make certain the tuple descriptor contains a - * valid set of attribute names. a problem simply generates - * elog(ERROR) which aborts the current transaction. + * valid set of attribute names and datatypes. a problem simply + * generates elog(ERROR) which aborts the current transaction. * -------------------------------- */ -static void -CheckAttributeNames(TupleDesc tupdesc, char relkind) +void +CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind) { int i; int j; int natts = tupdesc->natts; + /* Sanity check on column count */ + if (natts < 0 || natts > MaxHeapAttributeNumber) + elog(ERROR, "Number of columns is out of range (0 to %d)", + MaxHeapAttributeNumber); + /* * first check for collision with system attribute names * @@ -379,8 +384,29 @@ CheckAttributeNames(TupleDesc tupdesc, char relkind) } /* - * We also do some checking of the attribute types here. - * + * next check the attribute types + */ + for (i = 0; i < natts; i++) + { + CheckAttributeType(NameStr(tupdesc->attrs[i]->attname), + tupdesc->attrs[i]->atttypid); + } +} + +/* -------------------------------- + * CheckAttributeType + * + * Verify that the proposed datatype of an attribute is legal. + * This is needed because there are types (and pseudo-types) + * in the catalogs that we do not support as elements of real tuples. + * -------------------------------- + */ +void +CheckAttributeType(const char *attname, Oid atttypid) +{ + char att_typtype = get_typtype(atttypid); + + /* * Warn user, but don't fail, if column to be created has UNKNOWN type * (usually as a result of a 'retrieve into' - jolly) * @@ -389,28 +415,20 @@ CheckAttributeNames(TupleDesc tupdesc, char relkind) * all references to complex types, but for now there's still some * Berkeley-derived code that thinks it can do this...) */ - for (i = 0; i < natts; i++) + if (atttypid == UNKNOWNOID) + elog(WARNING, "Attribute \"%s\" has an unknown type" + "\n\tProceeding with relation creation anyway", + attname); + else if (att_typtype == 'p') + elog(ERROR, "Attribute \"%s\" has pseudo-type %s", + attname, format_type_be(atttypid)); + else if (att_typtype == 'c') { - Oid att_type = tupdesc->attrs[i]->atttypid; - char att_typtype = get_typtype(att_type); + Oid typrelid = get_typ_typrelid(atttypid); - if (att_type == UNKNOWNOID) - elog(WARNING, "Attribute \"%s\" has an unknown type" - "\n\tProceeding with relation creation anyway", - NameStr(tupdesc->attrs[i]->attname)); - if (att_typtype == 'p') - elog(ERROR, "Attribute \"%s\" has pseudo-type %s", - NameStr(tupdesc->attrs[i]->attname), - format_type_be(att_type)); - if (att_typtype == 'c') - { - Oid typrelid = get_typ_typrelid(att_type); - - if (get_rel_relkind(typrelid) == RELKIND_COMPOSITE_TYPE) - elog(ERROR, "Attribute \"%s\" has composite type %s", - NameStr(tupdesc->attrs[i]->attname), - format_type_be(att_type)); - } + if (get_rel_relkind(typrelid) == RELKIND_COMPOSITE_TYPE) + elog(ERROR, "Attribute \"%s\" has composite type %s", + attname, format_type_be(atttypid)); } } @@ -687,11 +705,8 @@ heap_create_with_catalog(const char *relname, * sanity checks */ Assert(IsNormalProcessingMode() || IsBootstrapProcessingMode()); - if (tupdesc->natts <= 0 || tupdesc->natts > MaxHeapAttributeNumber) - elog(ERROR, "Number of columns is out of range (1 to %d)", - MaxHeapAttributeNumber); - CheckAttributeNames(tupdesc, relkind); + CheckAttributeNamesTypes(tupdesc, relkind); if (get_relname_relid(relname, relnamespace)) elog(ERROR, "Relation '%s' already exists", relname); diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 62d61b315c6..46d9b709398 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.51 2002/11/02 22:02:08 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.51.2.1 2002/12/16 18:39:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -104,7 +104,6 @@ DefineRelation(CreateStmt *stmt, char relkind) char relname[NAMEDATALEN]; Oid namespaceId; List *schema = stmt->tableElts; - int numberOfAttributes; Oid relationId; Relation rel; TupleDesc descriptor; @@ -147,10 +146,6 @@ DefineRelation(CreateStmt *stmt, char relkind) stmt->relation->istemp, &inheritOids, &old_constraints, &parentHasOids); - numberOfAttributes = length(schema); - if (numberOfAttributes <= 0) - elog(ERROR, "DefineRelation: please inherit from a relation or define an attribute"); - /* * Create a relation descriptor from the relation schema and create * the relation. Note that in this stage only inherited (pre-cooked) @@ -1784,6 +1779,9 @@ AlterTableAddColumn(Oid myrelid, typeTuple = typenameType(colDef->typename); tform = (Form_pg_type) GETSTRUCT(typeTuple); + /* make sure datatype is legal for a column */ + CheckAttributeType(colDef->colname, HeapTupleGetOid(typeTuple)); + attributeTuple = heap_addheader(Natts_pg_attribute, false, ATTRIBUTE_TUPLE_SIZE, diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 245c0ba422b..c88ce186e41 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.98 2002/09/18 21:35:22 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.98.2.1 2002/12/16 18:39:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,6 +16,7 @@ #include "postgres.h" #include "access/heapam.h" +#include "catalog/heap.h" #include "nodes/makefuncs.h" #include "optimizer/clauses.h" #include "optimizer/tlist.h" @@ -502,6 +503,18 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r) elog(ERROR, "cannot use aggregate function in FROM function expression"); } + /* + * If a coldeflist is supplied, ensure it defines a legal set of names + * (no duplicates) and datatypes (no pseudo-types, for instance). + */ + if (r->coldeflist) + { + TupleDesc tupdesc; + + tupdesc = BuildDescForRelation(r->coldeflist); + CheckAttributeNamesTypes(tupdesc, RELKIND_COMPOSITE_TYPE); + } + /* * Insist we have a bare function call (explain.c is the only place * that depends on this, I think). If this fails, it's probably diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 29fbd5ec067..2fdbfba5e92 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.177 2002/10/14 16:51:30 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.177.2.1 2002/12/16 18:39:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -570,7 +570,8 @@ RelationBuildTupleDesc(RelationBuildDescInfo buildinfo, * cases for attnum=1 that used to exist in fastgetattr() and * index_getattr(). */ - relation->rd_att->attrs[0]->attcacheoff = 0; + if (relation->rd_rel->relnatts > 0) + relation->rd_att->attrs[0]->attcacheoff = 0; /* * Set up constraint/default info @@ -2041,7 +2042,7 @@ RelationBuildLocalRelation(const char *relname, int natts = tupDesc->natts; int i; - AssertArg(natts > 0); + AssertArg(natts >= 0); /* * switch to the cache context to create the relcache entry. diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h index 7ff705b1dd5..7688c76574b 100644 --- a/src/include/catalog/heap.h +++ b/src/include/catalog/heap.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: heap.h,v 1.57 2002/09/04 20:31:37 momjian Exp $ + * $Id: heap.h,v 1.57.2.1 2002/12/16 18:39:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -73,4 +73,8 @@ extern Form_pg_attribute SystemAttributeDefinition(AttrNumber attno, extern Form_pg_attribute SystemAttributeByName(const char *attname, bool relhasoids); +extern void CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind); + +extern void CheckAttributeType(const char *attname, Oid atttypid); + #endif /* HEAP_H */