1 /*-------------------------------------------------------------------------
4 * POSTGRES tuple descriptor support code
6 * Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.55 1999/10/03 23:55:25 tgl Exp $
13 * some of the executor utility code such as "ExecTypeFromTL" should be
16 *-------------------------------------------------------------------------
21 #include "catalog/pg_type.h"
22 #include "nodes/parsenodes.h"
23 #include "parser/parse_type.h"
24 #include "utils/builtins.h"
25 #include "utils/syscache.h"
28 /* ----------------------------------------------------------------
29 * CreateTemplateTupleDesc
31 * This function allocates and zeros a tuple descriptor structure.
32 * ----------------------------------------------------------------
35 CreateTemplateTupleDesc(int natts)
44 AssertArg(natts >= 1);
47 * allocate enough memory for the tuple descriptor and
48 * zero it as TupleDescInitEntry assumes that the descriptor
49 * is filled with NULL pointers.
52 size = natts * sizeof(Form_pg_attribute);
53 desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
54 desc->attrs = (Form_pg_attribute *) palloc(size);
56 MemSet(desc->attrs, 0, size);
63 /* ----------------------------------------------------------------
66 * This function allocates a new TupleDesc from Form_pg_attribute array
67 * ----------------------------------------------------------------
70 CreateTupleDesc(int natts, Form_pg_attribute *attrs)
78 AssertArg(natts >= 1);
80 desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
88 /* ----------------------------------------------------------------
91 * This function creates a new TupleDesc by copying from an existing
94 * !!! Constraints are not copied !!!
95 * ----------------------------------------------------------------
98 CreateTupleDescCopy(TupleDesc tupdesc)
104 desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
105 desc->natts = tupdesc->natts;
106 size = desc->natts * sizeof(Form_pg_attribute);
107 desc->attrs = (Form_pg_attribute *) palloc(size);
108 for (i = 0; i < desc->natts; i++)
110 desc->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
111 memmove(desc->attrs[i],
113 ATTRIBUTE_TUPLE_SIZE);
114 desc->attrs[i]->attnotnull = false;
115 desc->attrs[i]->atthasdef = false;
122 /* ----------------------------------------------------------------
123 * CreateTupleDescCopyConstr
125 * This function creates a new TupleDesc by copying from an existing
126 * TupleDesc (with Constraints)
128 * ----------------------------------------------------------------
131 CreateTupleDescCopyConstr(TupleDesc tupdesc)
134 TupleConstr *constr = tupdesc->constr;
138 desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
139 desc->natts = tupdesc->natts;
140 size = desc->natts * sizeof(Form_pg_attribute);
141 desc->attrs = (Form_pg_attribute *) palloc(size);
142 for (i = 0; i < desc->natts; i++)
144 desc->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
145 memmove(desc->attrs[i],
147 ATTRIBUTE_TUPLE_SIZE);
151 TupleConstr *cpy = (TupleConstr *) palloc(sizeof(TupleConstr));
153 cpy->has_not_null = constr->has_not_null;
155 if ((cpy->num_defval = constr->num_defval) > 0)
157 cpy->defval = (AttrDefault *) palloc(cpy->num_defval * sizeof(AttrDefault));
158 memcpy(cpy->defval, constr->defval, cpy->num_defval * sizeof(AttrDefault));
159 for (i = cpy->num_defval - 1; i >= 0; i--)
161 if (constr->defval[i].adbin)
162 cpy->defval[i].adbin = pstrdup(constr->defval[i].adbin);
166 if ((cpy->num_check = constr->num_check) > 0)
168 cpy->check = (ConstrCheck *) palloc(cpy->num_check * sizeof(ConstrCheck));
169 memcpy(cpy->check, constr->check, cpy->num_check * sizeof(ConstrCheck));
170 for (i = cpy->num_check - 1; i >= 0; i--)
172 if (constr->check[i].ccname)
173 cpy->check[i].ccname = pstrdup(constr->check[i].ccname);
174 if (constr->check[i].ccbin)
175 cpy->check[i].ccbin = pstrdup(constr->check[i].ccbin);
188 FreeTupleDesc(TupleDesc tupdesc)
192 for (i = 0; i < tupdesc->natts; i++)
193 pfree(tupdesc->attrs[i]);
194 pfree(tupdesc->attrs);
197 if (tupdesc->constr->num_defval > 0)
199 AttrDefault *attrdef = tupdesc->constr->defval;
201 for (i = tupdesc->constr->num_defval - 1; i >= 0; i--)
203 if (attrdef[i].adbin)
204 pfree(attrdef[i].adbin);
208 if (tupdesc->constr->num_check > 0)
210 ConstrCheck *check = tupdesc->constr->check;
212 for (i = tupdesc->constr->num_check - 1; i >= 0; i--)
215 pfree(check[i].ccname);
217 pfree(check[i].ccbin);
221 pfree(tupdesc->constr);
228 /* ----------------------------------------------------------------
231 * This function initializes a single attribute structure in
232 * a preallocated tuple descriptor.
233 * ----------------------------------------------------------------
236 TupleDescInitEntry(TupleDesc desc,
237 AttrNumber attributeNumber,
245 Form_pg_type typeForm;
246 Form_pg_attribute att;
252 AssertArg(PointerIsValid(desc));
253 AssertArg(attributeNumber >= 1);
256 * attributeName's are sometimes NULL, from resdom's. I don't know
257 * why that is, though -- Jolly
259 /* AssertArg(NameIsValid(attributeName));*/
261 AssertArg(!PointerIsValid(desc->attrs[attributeNumber - 1]));
265 * allocate storage for this attribute
269 att = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
270 desc->attrs[attributeNumber - 1] = att;
273 * initialize some of the attribute fields
276 att->attrelid = 0; /* dummy value */
278 if (attributeName != NULL)
279 namestrcpy(&(att->attname), attributeName);
281 MemSet(att->attname.data, 0, NAMEDATALEN);
284 att->attdisbursion = 0; /* dummy value */
285 att->attcacheoff = -1;
286 att->atttypmod = typmod;
288 att->attnum = attributeNumber;
289 att->attnelems = attdim;
290 att->attisset = attisset;
292 att->attnotnull = false;
293 att->atthasdef = false;
296 * search the system cache for the type tuple of the attribute
297 * we are creating so that we can get the typeid and some other
300 * Note: in the special case of
302 * create EMP (name = text, manager = EMP)
304 * RelationNameCreateHeapRelation() calls BuildDesc() which
305 * calls this routine and since EMP does not exist yet, the
306 * system cache lookup below fails. That's fine, but rather
307 * then doing a elog(ERROR) we just leave that information
308 * uninitialized, return false, then fix things up later.
312 tuple = SearchSysCacheTuple(TYPOID,
313 ObjectIdGetDatum(typeid),
315 if (!HeapTupleIsValid(tuple))
318 * here type info does not exist yet so we just fill
319 * the attribute with dummy information and return false.
322 att->atttypid = InvalidOid;
323 att->attlen = (int16) 0;
324 att->attbyval = (bool) 0;
330 * type info exists so we initialize our attribute
331 * information from the type tuple we found..
334 typeForm = (Form_pg_type) GETSTRUCT(tuple);
336 att->atttypid = tuple->t_data->t_oid;
337 att->attalign = typeForm->typalign;
339 /* ------------------------
340 If this attribute is a set, what is really stored in the
341 attribute is the OID of a tuple in the pg_proc catalog.
342 The pg_proc tuple contains the query string which defines
343 this set - i.e., the query to run to get the set.
344 So the atttypid (just assigned above) refers to the type returned
345 by this query, but the actual length of this attribute is the
346 length (size) of an OID.
348 Why not just make the atttypid point to the OID type, instead
349 of the type the query returns? Because the executor uses the atttypid
350 to tell the front end what type will be returned (in BeginCommand),
351 and in the end the type returned will be the result of the query, not
354 Why not wait until the return type of the set is known (i.e., the
355 recursive call to the executor to execute the set has returned)
356 before telling the front end what the return type will be? Because
357 the executor is a delicate thing, and making sure that the correct
358 order of front-end commands is maintained is messy, especially
359 considering that target lists may change as inherited attributes
360 are considered, etc. Ugh.
361 -----------------------------------------
365 Type t = typeidType(OIDOID);
367 att->attlen = typeLen(t);
368 att->attbyval = typeByVal(t);
372 att->attlen = typeForm->typlen;
373 att->attbyval = typeForm->typbyval;
381 /* ----------------------------------------------------------------
382 * TupleDescMakeSelfReference
384 * This function initializes a "self-referential" attribute like
385 * manager in "create EMP (name=text, manager = EMP)".
386 * It calls TypeShellMake() which inserts a "shell" type
387 * tuple into pg_type. A self-reference is one kind of set, so
388 * its size and byval are the same as for a set. See the comments
389 * above in TupleDescInitEntry.
390 * ----------------------------------------------------------------
393 TupleDescMakeSelfReference(TupleDesc desc,
397 Form_pg_attribute att;
398 Type t = typeidType(OIDOID);
400 att = desc->attrs[attnum - 1];
401 att->atttypid = TypeShellMake(relname);
402 att->attlen = typeLen(t);
403 att->attbyval = typeByVal(t);
407 /* ----------------------------------------------------------------
408 * BuildDescForRelation
410 * This is a general purpose function identical to BuildDesc
411 * but is used by the DefineRelation() code to catch the
412 * special case where you
414 * create FOO ( ..., x = FOO )
416 * here, the initial type lookup for "x = FOO" will fail
417 * because FOO isn't in the catalogs yet. But since we
418 * are creating FOO, instead of doing an elog() we add
419 * a shell type tuple to pg_type and fix things later
421 * ----------------------------------------------------------------
424 BuildDescForRelation(List *schema, char *relname)
430 AttrDefault *attrdef = NULL;
431 TupleConstr *constr = (TupleConstr *) palloc(sizeof(TupleConstr));
433 char typename[NAMEDATALEN];
440 * allocate a new tuple descriptor
443 natts = length(schema);
444 desc = CreateTemplateTupleDesc(natts);
445 constr->has_not_null = false;
451 ColumnDef *entry = lfirst(p);
455 * for each entry in the list, get the name and type
456 * information from the list and have TupleDescInitEntry
457 * fill in the attribute information we need.
462 attname = entry->colname;
463 arry = entry->typename->arrayBounds;
464 attisset = entry->typename->setof;
465 atttypmod = entry->typename->typmod;
469 /* array of XXX is _XXX */
470 snprintf(typename, NAMEDATALEN,
471 "_%.*s", NAMEDATALEN - 2, entry->typename->name);
472 attdim = length(arry);
476 StrNCpy(typename, entry->typename->name, NAMEDATALEN);
480 if (!TupleDescInitEntry(desc, attnum, attname,
481 typeTypeId(typenameType(typename)),
482 atttypmod, attdim, attisset))
485 * if TupleDescInitEntry() fails, it means there is
486 * no type in the system catalogs. So now we check if
487 * the type name equals the relation name. If so we
488 * have a self reference, otherwise it's an error.
491 if (!strcmp(typename, relname))
492 TupleDescMakeSelfReference(desc, attnum, relname);
494 elog(ERROR, "DefineRelation: no such type %s",
498 desc->attrs[attnum - 1]->atttypmod = entry->typename->typmod;
500 /* This is for constraints */
501 if (entry->is_not_null)
502 constr->has_not_null = true;
503 desc->attrs[attnum - 1]->attnotnull = entry->is_not_null;
505 /* Note we copy only pre-cooked default expressions.
506 * Digestion of raw ones is someone else's problem.
508 if (entry->cooked_default != NULL)
511 attrdef = (AttrDefault *) palloc(natts * sizeof(AttrDefault));
512 attrdef[ndef].adnum = attnum;
513 attrdef[ndef].adbin = pstrdup(entry->cooked_default);
515 desc->attrs[attnum - 1]->atthasdef = true;
519 if (constr->has_not_null || ndef > 0)
521 desc->constr = constr;
523 if (ndef > 0) /* DEFAULTs */
526 constr->defval = (AttrDefault *)
527 repalloc(attrdef, ndef * sizeof(AttrDefault));
529 constr->defval = attrdef;
530 constr->num_defval = ndef;
534 constr->defval = NULL;
535 constr->num_defval = 0;
537 constr->check = NULL;
538 constr->num_check = 0;