diff options
Diffstat (limited to 'src/backend/access/common/tupdesc.c')
-rw-r--r-- | src/backend/access/common/tupdesc.c | 890 |
1 files changed, 453 insertions, 437 deletions
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c index a38a5229f28..e616702a8ea 100644 --- a/src/backend/access/common/tupdesc.c +++ b/src/backend/access/common/tupdesc.c @@ -1,17 +1,17 @@ /*------------------------------------------------------------------------- * * tupdesc.c-- - * POSTGRES tuple descriptor support code + * POSTGRES tuple descriptor support code * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.19 1997/08/22 02:55:39 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.20 1997/09/07 04:37:41 momjian Exp $ * * NOTES - * some of the executor utility code such as "ExecTypeFromTL" should be - * moved here. + * some of the executor utility code such as "ExecTypeFromTL" should be + * moved here. * *------------------------------------------------------------------------- */ @@ -28,518 +28,534 @@ #include <utils/syscache.h> #ifndef HAVE_MEMMOVE -# include <regex/utils.h> +#include <regex/utils.h> #else -# include <string.h> +#include <string.h> #endif /* ---------------------------------------------------------------- - * CreateTemplateTupleDesc + * CreateTemplateTupleDesc * - * This function allocates and zeros a tuple descriptor structure. + * This function allocates and zeros a tuple descriptor structure. * ---------------------------------------------------------------- */ TupleDesc CreateTemplateTupleDesc(int natts) { - uint32 size; - TupleDesc desc; - - /* ---------------- - * sanity checks - * ---------------- - */ - AssertArg(natts >= 1); - - /* ---------------- - * allocate enough memory for the tuple descriptor and - * zero it as TupleDescInitEntry assumes that the descriptor - * is filled with NULL pointers. - * ---------------- - */ - size = natts * sizeof (AttributeTupleForm); - desc = (TupleDesc) palloc(sizeof(struct tupleDesc)); - desc->attrs = (AttributeTupleForm*) palloc(size); - desc->constr = NULL; - memset(desc->attrs, 0, size); - - desc->natts = natts; - - return (desc); + uint32 size; + TupleDesc desc; + + /* ---------------- + * sanity checks + * ---------------- + */ + AssertArg(natts >= 1); + + /* ---------------- + * allocate enough memory for the tuple descriptor and + * zero it as TupleDescInitEntry assumes that the descriptor + * is filled with NULL pointers. + * ---------------- + */ + size = natts * sizeof(AttributeTupleForm); + desc = (TupleDesc) palloc(sizeof(struct tupleDesc)); + desc->attrs = (AttributeTupleForm *) palloc(size); + desc->constr = NULL; + memset(desc->attrs, 0, size); + + desc->natts = natts; + + return (desc); } /* ---------------------------------------------------------------- - * CreateTupleDesc + * CreateTupleDesc * - * This function allocates a new TupleDesc from AttributeTupleForm array + * This function allocates a new TupleDesc from AttributeTupleForm array * ---------------------------------------------------------------- */ TupleDesc -CreateTupleDesc(int natts, AttributeTupleForm* attrs) +CreateTupleDesc(int natts, AttributeTupleForm * attrs) { - TupleDesc desc; - - /* ---------------- - * sanity checks - * ---------------- - */ - AssertArg(natts >= 1); - - desc = (TupleDesc) palloc(sizeof(struct tupleDesc)); - desc->attrs = attrs; - desc->natts = natts; - desc->constr = NULL; - - return (desc); + TupleDesc desc; + + /* ---------------- + * sanity checks + * ---------------- + */ + AssertArg(natts >= 1); + + desc = (TupleDesc) palloc(sizeof(struct tupleDesc)); + desc->attrs = attrs; + desc->natts = natts; + desc->constr = NULL; + + return (desc); } /* ---------------------------------------------------------------- - * CreateTupleDescCopy + * CreateTupleDescCopy * - * This function creates a new TupleDesc by copying from an existing - * TupleDesc - * - * !!! Constraints are not copied !!! + * This function creates a new TupleDesc by copying from an existing + * TupleDesc + * + * !!! Constraints are not copied !!! * ---------------------------------------------------------------- */ TupleDesc CreateTupleDescCopy(TupleDesc tupdesc) { - TupleDesc desc; - int i, size; - - desc = (TupleDesc) palloc(sizeof(struct tupleDesc)); - desc->natts = tupdesc->natts; - size = desc->natts * sizeof (AttributeTupleForm); - desc->attrs = (AttributeTupleForm*) palloc(size); - for (i=0;i<desc->natts;i++) { - desc->attrs[i] = - (AttributeTupleForm)palloc(ATTRIBUTE_TUPLE_SIZE); - memmove(desc->attrs[i], - tupdesc->attrs[i], - ATTRIBUTE_TUPLE_SIZE); - desc->attrs[i]->attnotnull = false; - desc->attrs[i]->atthasdef = false; - } - desc->constr = NULL; - - return desc; + TupleDesc desc; + int i, + size; + + desc = (TupleDesc) palloc(sizeof(struct tupleDesc)); + desc->natts = tupdesc->natts; + size = desc->natts * sizeof(AttributeTupleForm); + desc->attrs = (AttributeTupleForm *) palloc(size); + for (i = 0; i < desc->natts; i++) + { + desc->attrs[i] = + (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE); + memmove(desc->attrs[i], + tupdesc->attrs[i], + ATTRIBUTE_TUPLE_SIZE); + desc->attrs[i]->attnotnull = false; + desc->attrs[i]->atthasdef = false; + } + desc->constr = NULL; + + return desc; } /* ---------------------------------------------------------------- - * CreateTupleDescCopyConstr + * CreateTupleDescCopyConstr + * + * This function creates a new TupleDesc by copying from an existing + * TupleDesc (with Constraints) * - * This function creates a new TupleDesc by copying from an existing - * TupleDesc (with Constraints) - * * ---------------------------------------------------------------- */ TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc) { - TupleDesc desc; - TupleConstr *constr = tupdesc->constr; - int i, size; - - desc = (TupleDesc) palloc(sizeof(struct tupleDesc)); - desc->natts = tupdesc->natts; - size = desc->natts * sizeof (AttributeTupleForm); - desc->attrs = (AttributeTupleForm*) palloc(size); - for (i=0;i<desc->natts;i++) { - desc->attrs[i] = - (AttributeTupleForm)palloc(ATTRIBUTE_TUPLE_SIZE); - memmove(desc->attrs[i], - tupdesc->attrs[i], - ATTRIBUTE_TUPLE_SIZE); - } - if (constr) - { - TupleConstr *cpy = (TupleConstr *) palloc(sizeof(TupleConstr)); - - cpy->has_not_null = constr->has_not_null; - - if ( ( cpy->num_defval = constr->num_defval ) > 0 ) - { - cpy->defval = (AttrDefault *) palloc (cpy->num_defval * sizeof (AttrDefault)); - memcpy (cpy->defval, constr->defval, cpy->num_defval * sizeof (AttrDefault)); - for (i = cpy->num_defval - 1; i >= 0; i--) - { - if ( constr->defval[i].adbin ) - cpy->defval[i].adbin = pstrdup (constr->defval[i].adbin); - if ( constr->defval[i].adsrc ) - cpy->defval[i].adsrc = pstrdup (constr->defval[i].adsrc); - } - } - - if ( ( cpy->num_check = constr->num_check ) > 0 ) - { - cpy->check = (ConstrCheck *) palloc (cpy->num_check * sizeof (ConstrCheck)); - memcpy (cpy->check, constr->check, cpy->num_check * sizeof (ConstrCheck)); - for (i = cpy->num_check - 1; i >= 0; i--) - { - if ( constr->check[i].ccname ) - cpy->check[i].ccname = pstrdup (constr->check[i].ccname); - if ( constr->check[i].ccbin ) - cpy->check[i].ccbin = pstrdup (constr->check[i].ccbin); - if ( constr->check[i].ccsrc ) - cpy->check[i].ccsrc = pstrdup (constr->check[i].ccsrc); - } - } - - desc->constr = cpy; - } - else - desc->constr = NULL; - - return desc; + TupleDesc desc; + TupleConstr *constr = tupdesc->constr; + int i, + size; + + desc = (TupleDesc) palloc(sizeof(struct tupleDesc)); + desc->natts = tupdesc->natts; + size = desc->natts * sizeof(AttributeTupleForm); + desc->attrs = (AttributeTupleForm *) palloc(size); + for (i = 0; i < desc->natts; i++) + { + desc->attrs[i] = + (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE); + memmove(desc->attrs[i], + tupdesc->attrs[i], + ATTRIBUTE_TUPLE_SIZE); + } + if (constr) + { + TupleConstr *cpy = (TupleConstr *) palloc(sizeof(TupleConstr)); + + cpy->has_not_null = constr->has_not_null; + + if ((cpy->num_defval = constr->num_defval) > 0) + { + cpy->defval = (AttrDefault *) palloc(cpy->num_defval * sizeof(AttrDefault)); + memcpy(cpy->defval, constr->defval, cpy->num_defval * sizeof(AttrDefault)); + for (i = cpy->num_defval - 1; i >= 0; i--) + { + if (constr->defval[i].adbin) + cpy->defval[i].adbin = pstrdup(constr->defval[i].adbin); + if (constr->defval[i].adsrc) + cpy->defval[i].adsrc = pstrdup(constr->defval[i].adsrc); + } + } + + if ((cpy->num_check = constr->num_check) > 0) + { + cpy->check = (ConstrCheck *) palloc(cpy->num_check * sizeof(ConstrCheck)); + memcpy(cpy->check, constr->check, cpy->num_check * sizeof(ConstrCheck)); + for (i = cpy->num_check - 1; i >= 0; i--) + { + if (constr->check[i].ccname) + cpy->check[i].ccname = pstrdup(constr->check[i].ccname); + if (constr->check[i].ccbin) + cpy->check[i].ccbin = pstrdup(constr->check[i].ccbin); + if (constr->check[i].ccsrc) + cpy->check[i].ccsrc = pstrdup(constr->check[i].ccsrc); + } + } + + desc->constr = cpy; + } + else + desc->constr = NULL; + + return desc; } void -FreeTupleDesc (TupleDesc tupdesc) +FreeTupleDesc(TupleDesc tupdesc) { - int i; - - for (i = 0; i < tupdesc->natts; i++) - pfree (tupdesc->attrs[i]); - pfree (tupdesc->attrs); - if ( tupdesc->constr ) - { - if ( tupdesc->constr->num_defval > 0 ) - { - AttrDefault *attrdef = tupdesc->constr->defval; - - for (i = tupdesc->constr->num_defval - 1; i >= 0; i--) - { - if ( attrdef[i].adbin ) - pfree (attrdef[i].adbin); - if ( attrdef[i].adsrc ) - pfree (attrdef[i].adsrc); - } - pfree (attrdef); - } - if ( tupdesc->constr->num_check > 0 ) - { - ConstrCheck *check = tupdesc->constr->check; - - for (i = tupdesc->constr->num_check - 1; i >= 0; i--) - { - if ( check[i].ccname ) - pfree (check[i].ccname); - if ( check[i].ccbin ) - pfree (check[i].ccbin); - if ( check[i].ccsrc ) - pfree (check[i].ccsrc); - } - pfree (check); - } - pfree (tupdesc->constr); - } - - pfree (tupdesc); + int i; + + for (i = 0; i < tupdesc->natts; i++) + pfree(tupdesc->attrs[i]); + pfree(tupdesc->attrs); + if (tupdesc->constr) + { + if (tupdesc->constr->num_defval > 0) + { + AttrDefault *attrdef = tupdesc->constr->defval; + + for (i = tupdesc->constr->num_defval - 1; i >= 0; i--) + { + if (attrdef[i].adbin) + pfree(attrdef[i].adbin); + if (attrdef[i].adsrc) + pfree(attrdef[i].adsrc); + } + pfree(attrdef); + } + if (tupdesc->constr->num_check > 0) + { + ConstrCheck *check = tupdesc->constr->check; + + for (i = tupdesc->constr->num_check - 1; i >= 0; i--) + { + if (check[i].ccname) + pfree(check[i].ccname); + if (check[i].ccbin) + pfree(check[i].ccbin); + if (check[i].ccsrc) + pfree(check[i].ccsrc); + } + pfree(check); + } + pfree(tupdesc->constr); + } + + pfree(tupdesc); } /* ---------------------------------------------------------------- - * TupleDescInitEntry + * TupleDescInitEntry * - * This function initializes a single attribute structure in - * a preallocated tuple descriptor. + * This function initializes a single attribute structure in + * a preallocated tuple descriptor. * ---------------------------------------------------------------- */ bool TupleDescInitEntry(TupleDesc desc, - AttrNumber attributeNumber, - char *attributeName, - char *typeName, - int attdim, - bool attisset) + AttrNumber attributeNumber, + char *attributeName, + char *typeName, + int attdim, + bool attisset) { - HeapTuple tuple; - TypeTupleForm typeForm; - AttributeTupleForm att; - - /* ---------------- - * sanity checks - * ---------------- - */ - AssertArg(PointerIsValid(desc)); - AssertArg(attributeNumber >= 1); - /* attributeName's are sometimes NULL, - from resdom's. I don't know why that is, though -- Jolly */ -/* AssertArg(NameIsValid(attributeName));*/ -/* AssertArg(NameIsValid(typeName));*/ - - AssertArg(!PointerIsValid(desc->attrs[attributeNumber - 1])); - - - /* ---------------- - * allocate storage for this attribute - * ---------------- - */ - - att = (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE); - desc->attrs[attributeNumber - 1] = att; - - /* ---------------- - * initialize some of the attribute fields - * ---------------- - */ - att->attrelid = 0; /* dummy value */ - - if (attributeName != NULL) - namestrcpy(&(att->attname), attributeName); - else - memset(att->attname.data,0,NAMEDATALEN); - - - att->attdisbursion = 0; /* dummy value */ - att->attcacheoff = -1; - - att->attnum = attributeNumber; - att->attnelems = attdim; - att->attisset = attisset; - - att->attnotnull = false; - att->atthasdef = false; - - /* ---------------- - * search the system cache for the type tuple of the attribute - * we are creating so that we can get the typeid and some other - * stuff. - * - * Note: in the special case of - * - * create EMP (name = char16, manager = EMP) - * - * RelationNameCreateHeapRelation() calls BuildDesc() which - * calls this routine and since EMP does not exist yet, the - * system cache lookup below fails. That's fine, but rather - * then doing a elog(WARN) we just leave that information - * uninitialized, return false, then fix things up later. - * -cim 6/14/90 - * ---------------- - */ - tuple = SearchSysCacheTuple(TYPNAME, PointerGetDatum(typeName), - 0,0,0); - if (! HeapTupleIsValid(tuple)) { + HeapTuple tuple; + TypeTupleForm typeForm; + AttributeTupleForm att; + /* ---------------- - * here type info does not exist yet so we just fill - * the attribute with dummy information and return false. + * sanity checks * ---------------- */ - att->atttypid = InvalidOid; - att->attlen = (int16) 0; - att->attbyval = (bool) 0; - att->attalign = 'i'; - return false; - } - - /* ---------------- - * type info exists so we initialize our attribute - * information from the type tuple we found.. - * ---------------- - */ - typeForm = (TypeTupleForm) GETSTRUCT(tuple); - - att->atttypid = tuple->t_oid; - att->attalign = typeForm->typalign; - - /* ------------------------ - If this attribute is a set, what is really stored in the - attribute is the OID of a tuple in the pg_proc catalog. - The pg_proc tuple contains the query string which defines - this set - i.e., the query to run to get the set. - So the atttypid (just assigned above) refers to the type returned - by this query, but the actual length of this attribute is the - length (size) of an OID. - - Why not just make the atttypid point to the OID type, instead - of the type the query returns? Because the executor uses the atttypid - to tell the front end what type will be returned (in BeginCommand), - and in the end the type returned will be the result of the query, not - an OID. - - Why not wait until the return type of the set is known (i.e., the - recursive call to the executor to execute the set has returned) - before telling the front end what the return type will be? Because - the executor is a delicate thing, and making sure that the correct - order of front-end commands is maintained is messy, especially - considering that target lists may change as inherited attributes - are considered, etc. Ugh. - ----------------------------------------- - */ - if (attisset) { - Type t = type("oid"); - att->attlen = tlen(t); - att->attbyval = tbyval(t); - } else { - att->attlen = typeForm->typlen; - att->attbyval = typeForm->typbyval; - } - - - return true; + AssertArg(PointerIsValid(desc)); + AssertArg(attributeNumber >= 1); + + /* + * attributeName's are sometimes NULL, from resdom's. I don't know + * why that is, though -- Jolly + */ +/* AssertArg(NameIsValid(attributeName));*/ +/* AssertArg(NameIsValid(typeName));*/ + + AssertArg(!PointerIsValid(desc->attrs[attributeNumber - 1])); + + + /* ---------------- + * allocate storage for this attribute + * ---------------- + */ + + att = (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE); + desc->attrs[attributeNumber - 1] = att; + + /* ---------------- + * initialize some of the attribute fields + * ---------------- + */ + att->attrelid = 0; /* dummy value */ + + if (attributeName != NULL) + namestrcpy(&(att->attname), attributeName); + else + memset(att->attname.data, 0, NAMEDATALEN); + + + att->attdisbursion = 0; /* dummy value */ + att->attcacheoff = -1; + + att->attnum = attributeNumber; + att->attnelems = attdim; + att->attisset = attisset; + + att->attnotnull = false; + att->atthasdef = false; + + /* ---------------- + * search the system cache for the type tuple of the attribute + * we are creating so that we can get the typeid and some other + * stuff. + * + * Note: in the special case of + * + * create EMP (name = char16, manager = EMP) + * + * RelationNameCreateHeapRelation() calls BuildDesc() which + * calls this routine and since EMP does not exist yet, the + * system cache lookup below fails. That's fine, but rather + * then doing a elog(WARN) we just leave that information + * uninitialized, return false, then fix things up later. + * -cim 6/14/90 + * ---------------- + */ + tuple = SearchSysCacheTuple(TYPNAME, PointerGetDatum(typeName), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + { + /* ---------------- + * here type info does not exist yet so we just fill + * the attribute with dummy information and return false. + * ---------------- + */ + att->atttypid = InvalidOid; + att->attlen = (int16) 0; + att->attbyval = (bool) 0; + att->attalign = 'i'; + return false; + } + + /* ---------------- + * type info exists so we initialize our attribute + * information from the type tuple we found.. + * ---------------- + */ + typeForm = (TypeTupleForm) GETSTRUCT(tuple); + + att->atttypid = tuple->t_oid; + att->attalign = typeForm->typalign; + + /* ------------------------ + If this attribute is a set, what is really stored in the + attribute is the OID of a tuple in the pg_proc catalog. + The pg_proc tuple contains the query string which defines + this set - i.e., the query to run to get the set. + So the atttypid (just assigned above) refers to the type returned + by this query, but the actual length of this attribute is the + length (size) of an OID. + + Why not just make the atttypid point to the OID type, instead + of the type the query returns? Because the executor uses the atttypid + to tell the front end what type will be returned (in BeginCommand), + and in the end the type returned will be the result of the query, not + an OID. + + Why not wait until the return type of the set is known (i.e., the + recursive call to the executor to execute the set has returned) + before telling the front end what the return type will be? Because + the executor is a delicate thing, and making sure that the correct + order of front-end commands is maintained is messy, especially + considering that target lists may change as inherited attributes + are considered, etc. Ugh. + ----------------------------------------- + */ + if (attisset) + { + Type t = type("oid"); + + att->attlen = tlen(t); + att->attbyval = tbyval(t); + } + else + { + att->attlen = typeForm->typlen; + att->attbyval = typeForm->typbyval; + } + + + return true; } /* ---------------------------------------------------------------- - * TupleDescMakeSelfReference + * TupleDescMakeSelfReference * - * This function initializes a "self-referential" attribute like - * manager in "create EMP (name=text, manager = EMP)". - * It calls TypeShellMake() which inserts a "shell" type - * tuple into pg_type. A self-reference is one kind of set, so - * its size and byval are the same as for a set. See the comments - * above in TupleDescInitEntry. + * This function initializes a "self-referential" attribute like + * manager in "create EMP (name=text, manager = EMP)". + * It calls TypeShellMake() which inserts a "shell" type + * tuple into pg_type. A self-reference is one kind of set, so + * its size and byval are the same as for a set. See the comments + * above in TupleDescInitEntry. * ---------------------------------------------------------------- */ static void TupleDescMakeSelfReference(TupleDesc desc, - AttrNumber attnum, - char *relname) + AttrNumber attnum, + char *relname) { - AttributeTupleForm att; - Type t = type("oid"); - - att = desc->attrs[attnum-1]; - att->atttypid = TypeShellMake(relname); - att->attlen = tlen(t); - att->attbyval = tbyval(t); - att->attnelems = 0; + AttributeTupleForm att; + Type t = type("oid"); + + att = desc->attrs[attnum - 1]; + att->atttypid = TypeShellMake(relname); + att->attlen = tlen(t); + att->attbyval = tbyval(t); + att->attnelems = 0; } /* ---------------------------------------------------------------- - * BuildDescForRelation + * BuildDescForRelation * - * This is a general purpose function identical to BuildDesc - * but is used by the DefineRelation() code to catch the - * special case where you + * This is a general purpose function identical to BuildDesc + * but is used by the DefineRelation() code to catch the + * special case where you * - * create FOO ( ..., x = FOO ) + * create FOO ( ..., x = FOO ) * - * here, the initial type lookup for "x = FOO" will fail - * because FOO isn't in the catalogs yet. But since we - * are creating FOO, instead of doing an elog() we add - * a shell type tuple to pg_type and fix things later - * in amcreate(). + * here, the initial type lookup for "x = FOO" will fail + * because FOO isn't in the catalogs yet. But since we + * are creating FOO, instead of doing an elog() we add + * a shell type tuple to pg_type and fix things later + * in amcreate(). * ---------------------------------------------------------------- */ TupleDesc -BuildDescForRelation(List *schema, char *relname) +BuildDescForRelation(List * schema, char *relname) { - int natts; - AttrNumber attnum; - List *p; - TupleDesc desc; - AttrDefault *attrdef = NULL; - TupleConstr *constr = (TupleConstr *) palloc(sizeof(TupleConstr)); - char *attname; - char *typename; - int attdim; - int ndef = 0; - bool attisset; - - /* ---------------- - * allocate a new tuple descriptor - * ---------------- - */ - natts = length(schema); - desc = CreateTemplateTupleDesc(natts); - constr->has_not_null = false; - - attnum = 0; - - typename = palloc(NAMEDATALEN); - - foreach(p, schema) { - ColumnDef *entry; - List *arry; + int natts; + AttrNumber attnum; + List *p; + TupleDesc desc; + AttrDefault *attrdef = NULL; + TupleConstr *constr = (TupleConstr *) palloc(sizeof(TupleConstr)); + char *attname; + char *typename; + int attdim; + int ndef = 0; + bool attisset; /* ---------------- - * for each entry in the list, get the name and type - * information from the list and have TupleDescInitEntry - * fill in the attribute information we need. + * allocate a new tuple descriptor * ---------------- - */ - attnum++; - - entry = lfirst(p); - attname = entry->colname; - arry = entry->typename->arrayBounds; - attisset = entry->typename->setof; - - strNcpy(typename, entry->typename->name,NAMEDATALEN-1); - if (arry != NIL) - attdim = length(arry); - else - attdim = 0; - - if (! TupleDescInitEntry(desc, attnum, attname, - typename, attdim, attisset)) { - /* ---------------- - * if TupleDescInitEntry() fails, it means there is - * no type in the system catalogs. So now we check if - * the type name equals the relation name. If so we - * have a self reference, otherwise it's an error. - * ---------------- - */ - if (!strcmp(typename, relname)) { - TupleDescMakeSelfReference(desc, attnum, relname); - } else - elog(WARN, "DefineRelation: no such type %s", - typename); - } - - /* - * this is for char() and varchar(). When an entry is of type - * char() or varchar(), typlen is set to the appropriate length, - * which we'll use here instead. (The catalog lookup only returns - * the length of bpchar and varchar which is not what we want!) - * - ay 6/95 */ - if (entry->typename->typlen > 0) { - desc->attrs[attnum - 1]->attlen = entry->typename->typlen; - } + natts = length(schema); + desc = CreateTemplateTupleDesc(natts); + constr->has_not_null = false; - /* This is for constraints */ - if (entry->is_not_null) - constr->has_not_null = true; - desc->attrs[attnum-1]->attnotnull = entry->is_not_null; - - if ( entry->defval != NULL ) + attnum = 0; + + typename = palloc(NAMEDATALEN); + + foreach(p, schema) { - if ( attrdef == NULL ) - attrdef = (AttrDefault*) palloc (natts * sizeof (AttrDefault)); - attrdef[ndef].adnum = attnum; - attrdef[ndef].adbin = NULL; - attrdef[ndef].adsrc = entry->defval; - ndef++; - desc->attrs[attnum-1]->atthasdef = true; + ColumnDef *entry; + List *arry; + + /* ---------------- + * for each entry in the list, get the name and type + * information from the list and have TupleDescInitEntry + * fill in the attribute information we need. + * ---------------- + */ + attnum++; + + entry = lfirst(p); + attname = entry->colname; + arry = entry->typename->arrayBounds; + attisset = entry->typename->setof; + + strNcpy(typename, entry->typename->name, NAMEDATALEN - 1); + if (arry != NIL) + attdim = length(arry); + else + attdim = 0; + + if (!TupleDescInitEntry(desc, attnum, attname, + typename, attdim, attisset)) + { + /* ---------------- + * if TupleDescInitEntry() fails, it means there is + * no type in the system catalogs. So now we check if + * the type name equals the relation name. If so we + * have a self reference, otherwise it's an error. + * ---------------- + */ + if (!strcmp(typename, relname)) + { + TupleDescMakeSelfReference(desc, attnum, relname); + } + else + elog(WARN, "DefineRelation: no such type %s", + typename); + } + + /* + * this is for char() and varchar(). When an entry is of type + * char() or varchar(), typlen is set to the appropriate length, + * which we'll use here instead. (The catalog lookup only returns + * the length of bpchar and varchar which is not what we want!) - + * ay 6/95 + */ + if (entry->typename->typlen > 0) + { + desc->attrs[attnum - 1]->attlen = entry->typename->typlen; + } + + /* This is for constraints */ + if (entry->is_not_null) + constr->has_not_null = true; + desc->attrs[attnum - 1]->attnotnull = entry->is_not_null; + + if (entry->defval != NULL) + { + if (attrdef == NULL) + attrdef = (AttrDefault *) palloc(natts * sizeof(AttrDefault)); + attrdef[ndef].adnum = attnum; + attrdef[ndef].adbin = NULL; + attrdef[ndef].adsrc = entry->defval; + ndef++; + desc->attrs[attnum - 1]->atthasdef = true; + } + } + if (constr->has_not_null || ndef > 0) + { + desc->constr = constr; - } - if ( constr->has_not_null || ndef > 0 ) - { - desc->constr = constr; - - if ( ndef > 0 ) /* DEFAULTs */ - { - if ( ndef < natts ) - constr->defval = (AttrDefault*) - repalloc (attrdef, ndef * sizeof (AttrDefault)); - else - constr->defval = attrdef; - constr->num_defval = ndef; - } - else - constr->num_defval = 0; - constr->num_check = 0; - } - else - { - pfree (constr); - desc->constr = NULL; - } - return desc; + if (ndef > 0) /* DEFAULTs */ + { + if (ndef < natts) + constr->defval = (AttrDefault *) + repalloc(attrdef, ndef * sizeof(AttrDefault)); + else + constr->defval = attrdef; + constr->num_defval = ndef; + } + else + constr->num_defval = 0; + constr->num_check = 0; + } + else + { + pfree(constr); + desc->constr = NULL; + } + return desc; } - |