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.28 1997/11/24 05:07:42 momjian Exp $
13 * some of the executor utility code such as "ExecTypeFromTL" should be
16 *-------------------------------------------------------------------------
23 #include <parser/catalog_utils.h>
24 #include <nodes/parsenodes.h>
25 #include <utils/builtins.h>
26 #include <utils/fcache.h>
27 #include <utils/syscache.h>
30 #include <regex/utils.h>
35 /* ----------------------------------------------------------------
36 * CreateTemplateTupleDesc
38 * This function allocates and zeros a tuple descriptor structure.
39 * ----------------------------------------------------------------
42 CreateTemplateTupleDesc(int natts)
51 AssertArg(natts >= 1);
54 * allocate enough memory for the tuple descriptor and
55 * zero it as TupleDescInitEntry assumes that the descriptor
56 * is filled with NULL pointers.
59 size = natts * sizeof(AttributeTupleForm);
60 desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
61 desc->attrs = (AttributeTupleForm *) palloc(size);
63 MemSet(desc->attrs, 0, size);
70 /* ----------------------------------------------------------------
73 * This function allocates a new TupleDesc from AttributeTupleForm array
74 * ----------------------------------------------------------------
77 CreateTupleDesc(int natts, AttributeTupleForm *attrs)
85 AssertArg(natts >= 1);
87 desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
95 /* ----------------------------------------------------------------
98 * This function creates a new TupleDesc by copying from an existing
101 * !!! Constraints are not copied !!!
102 * ----------------------------------------------------------------
105 CreateTupleDescCopy(TupleDesc tupdesc)
111 desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
112 desc->natts = tupdesc->natts;
113 size = desc->natts * sizeof(AttributeTupleForm);
114 desc->attrs = (AttributeTupleForm *) palloc(size);
115 for (i = 0; i < desc->natts; i++)
118 (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE);
119 memmove(desc->attrs[i],
121 ATTRIBUTE_TUPLE_SIZE);
122 desc->attrs[i]->attnotnull = false;
123 desc->attrs[i]->atthasdef = false;
130 /* ----------------------------------------------------------------
131 * CreateTupleDescCopyConstr
133 * This function creates a new TupleDesc by copying from an existing
134 * TupleDesc (with Constraints)
136 * ----------------------------------------------------------------
139 CreateTupleDescCopyConstr(TupleDesc tupdesc)
142 TupleConstr *constr = tupdesc->constr;
146 desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
147 desc->natts = tupdesc->natts;
148 size = desc->natts * sizeof(AttributeTupleForm);
149 desc->attrs = (AttributeTupleForm *) palloc(size);
150 for (i = 0; i < desc->natts; i++)
153 (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE);
154 memmove(desc->attrs[i],
156 ATTRIBUTE_TUPLE_SIZE);
160 TupleConstr *cpy = (TupleConstr *) palloc(sizeof(TupleConstr));
162 cpy->has_not_null = constr->has_not_null;
164 if ((cpy->num_defval = constr->num_defval) > 0)
166 cpy->defval = (AttrDefault *) palloc(cpy->num_defval * sizeof(AttrDefault));
167 memcpy(cpy->defval, constr->defval, cpy->num_defval * sizeof(AttrDefault));
168 for (i = cpy->num_defval - 1; i >= 0; i--)
170 if (constr->defval[i].adbin)
171 cpy->defval[i].adbin = pstrdup(constr->defval[i].adbin);
172 if (constr->defval[i].adsrc)
173 cpy->defval[i].adsrc = pstrdup(constr->defval[i].adsrc);
177 if ((cpy->num_check = constr->num_check) > 0)
179 cpy->check = (ConstrCheck *) palloc(cpy->num_check * sizeof(ConstrCheck));
180 memcpy(cpy->check, constr->check, cpy->num_check * sizeof(ConstrCheck));
181 for (i = cpy->num_check - 1; i >= 0; i--)
183 if (constr->check[i].ccname)
184 cpy->check[i].ccname = pstrdup(constr->check[i].ccname);
185 if (constr->check[i].ccbin)
186 cpy->check[i].ccbin = pstrdup(constr->check[i].ccbin);
187 if (constr->check[i].ccsrc)
188 cpy->check[i].ccsrc = pstrdup(constr->check[i].ccsrc);
201 FreeTupleDesc(TupleDesc tupdesc)
205 for (i = 0; i < tupdesc->natts; i++)
206 pfree(tupdesc->attrs[i]);
207 pfree(tupdesc->attrs);
210 if (tupdesc->constr->num_defval > 0)
212 AttrDefault *attrdef = tupdesc->constr->defval;
214 for (i = tupdesc->constr->num_defval - 1; i >= 0; i--)
216 if (attrdef[i].adbin)
217 pfree(attrdef[i].adbin);
218 if (attrdef[i].adsrc)
219 pfree(attrdef[i].adsrc);
223 if (tupdesc->constr->num_check > 0)
225 ConstrCheck *check = tupdesc->constr->check;
227 for (i = tupdesc->constr->num_check - 1; i >= 0; i--)
230 pfree(check[i].ccname);
232 pfree(check[i].ccbin);
234 pfree(check[i].ccsrc);
238 pfree(tupdesc->constr);
245 /* ----------------------------------------------------------------
248 * This function initializes a single attribute structure in
249 * a preallocated tuple descriptor.
250 * ----------------------------------------------------------------
253 TupleDescInitEntry(TupleDesc desc,
254 AttrNumber attributeNumber,
261 TypeTupleForm typeForm;
262 AttributeTupleForm att;
268 AssertArg(PointerIsValid(desc));
269 AssertArg(attributeNumber >= 1);
272 * attributeName's are sometimes NULL, from resdom's. I don't know
273 * why that is, though -- Jolly
275 /* AssertArg(NameIsValid(attributeName));*/
276 /* AssertArg(NameIsValid(typeName));*/
278 AssertArg(!PointerIsValid(desc->attrs[attributeNumber - 1]));
282 * allocate storage for this attribute
286 att = (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE);
287 desc->attrs[attributeNumber - 1] = att;
290 * initialize some of the attribute fields
293 att->attrelid = 0; /* dummy value */
295 if (attributeName != NULL)
296 namestrcpy(&(att->attname), attributeName);
298 MemSet(att->attname.data, 0, NAMEDATALEN);
301 att->attdisbursion = 0; /* dummy value */
302 att->attcacheoff = -1;
304 att->attnum = attributeNumber;
305 att->attnelems = attdim;
306 att->attisset = attisset;
308 att->attnotnull = false;
309 att->atthasdef = false;
312 * search the system cache for the type tuple of the attribute
313 * we are creating so that we can get the typeid and some other
316 * Note: in the special case of
318 * create EMP (name = char16, manager = EMP)
320 * RelationNameCreateHeapRelation() calls BuildDesc() which
321 * calls this routine and since EMP does not exist yet, the
322 * system cache lookup below fails. That's fine, but rather
323 * then doing a elog(WARN) we just leave that information
324 * uninitialized, return false, then fix things up later.
328 tuple = SearchSysCacheTuple(TYPNAME, PointerGetDatum(typeName),
330 if (!HeapTupleIsValid(tuple))
333 * here type info does not exist yet so we just fill
334 * the attribute with dummy information and return false.
337 att->atttypid = InvalidOid;
338 att->attlen = (int16) 0;
339 att->attbyval = (bool) 0;
345 * type info exists so we initialize our attribute
346 * information from the type tuple we found..
349 typeForm = (TypeTupleForm) GETSTRUCT(tuple);
351 att->atttypid = tuple->t_oid;
352 att->attalign = typeForm->typalign;
354 /* ------------------------
355 If this attribute is a set, what is really stored in the
356 attribute is the OID of a tuple in the pg_proc catalog.
357 The pg_proc tuple contains the query string which defines
358 this set - i.e., the query to run to get the set.
359 So the atttypid (just assigned above) refers to the type returned
360 by this query, but the actual length of this attribute is the
361 length (size) of an OID.
363 Why not just make the atttypid point to the OID type, instead
364 of the type the query returns? Because the executor uses the atttypid
365 to tell the front end what type will be returned (in BeginCommand),
366 and in the end the type returned will be the result of the query, not
369 Why not wait until the return type of the set is known (i.e., the
370 recursive call to the executor to execute the set has returned)
371 before telling the front end what the return type will be? Because
372 the executor is a delicate thing, and making sure that the correct
373 order of front-end commands is maintained is messy, especially
374 considering that target lists may change as inherited attributes
375 are considered, etc. Ugh.
376 -----------------------------------------
380 Type t = type("oid");
382 att->attlen = tlen(t);
383 att->attbyval = tbyval(t);
387 att->attlen = typeForm->typlen;
388 att->attbyval = typeForm->typbyval;
396 /* ----------------------------------------------------------------
397 * TupleDescMakeSelfReference
399 * This function initializes a "self-referential" attribute like
400 * manager in "create EMP (name=text, manager = EMP)".
401 * It calls TypeShellMake() which inserts a "shell" type
402 * tuple into pg_type. A self-reference is one kind of set, so
403 * its size and byval are the same as for a set. See the comments
404 * above in TupleDescInitEntry.
405 * ----------------------------------------------------------------
408 TupleDescMakeSelfReference(TupleDesc desc,
412 AttributeTupleForm att;
413 Type t = type("oid");
415 att = desc->attrs[attnum - 1];
416 att->atttypid = TypeShellMake(relname);
417 att->attlen = tlen(t);
418 att->attbyval = tbyval(t);
422 /* ----------------------------------------------------------------
423 * BuildDescForRelation
425 * This is a general purpose function identical to BuildDesc
426 * but is used by the DefineRelation() code to catch the
427 * special case where you
429 * create FOO ( ..., x = FOO )
431 * here, the initial type lookup for "x = FOO" will fail
432 * because FOO isn't in the catalogs yet. But since we
433 * are creating FOO, instead of doing an elog() we add
434 * a shell type tuple to pg_type and fix things later
436 * ----------------------------------------------------------------
439 BuildDescForRelation(List *schema, char *relname)
445 AttrDefault *attrdef = NULL;
446 TupleConstr *constr = (TupleConstr *) palloc(sizeof(TupleConstr));
454 * allocate a new tuple descriptor
457 natts = length(schema);
458 desc = CreateTemplateTupleDesc(natts);
459 constr->has_not_null = false;
463 typename = palloc(NAMEDATALEN);
471 * for each entry in the list, get the name and type
472 * information from the list and have TupleDescInitEntry
473 * fill in the attribute information we need.
479 attname = entry->colname;
480 arry = entry->typename->arrayBounds;
481 attisset = entry->typename->setof;
485 /* array of XXX is _XXX */
486 sprintf(typename, "_%.*s", NAMEDATALEN-2,entry->typename->name);
487 attdim = length(arry);
491 StrNCpy(typename, entry->typename->name, NAMEDATALEN);
495 if (!TupleDescInitEntry(desc, attnum, attname,
496 typename, attdim, attisset))
499 * if TupleDescInitEntry() fails, it means there is
500 * no type in the system catalogs. So now we check if
501 * the type name equals the relation name. If so we
502 * have a self reference, otherwise it's an error.
505 if (!strcmp(typename, relname))
507 TupleDescMakeSelfReference(desc, attnum, relname);
510 elog(WARN, "DefineRelation: no such type %s",
515 * this is for char() and varchar(). When an entry is of type
516 * char() or varchar(), typlen is set to the appropriate length,
517 * which we'll use here instead. (The catalog lookup only returns
518 * the length of bpchar and varchar which is not what we want!) -
521 if (entry->typename->typlen > 0)
523 desc->attrs[attnum - 1]->attlen = entry->typename->typlen;
526 /* This is for constraints */
527 if (entry->is_not_null)
528 constr->has_not_null = true;
529 desc->attrs[attnum - 1]->attnotnull = entry->is_not_null;
531 if (entry->defval != NULL)
534 attrdef = (AttrDefault *) palloc(natts * sizeof(AttrDefault));
535 attrdef[ndef].adnum = attnum;
536 attrdef[ndef].adbin = NULL;
537 attrdef[ndef].adsrc = entry->defval;
539 desc->attrs[attnum - 1]->atthasdef = true;
543 if (constr->has_not_null || ndef > 0)
545 desc->constr = constr;
547 if (ndef > 0) /* DEFAULTs */
550 constr->defval = (AttrDefault *)
551 repalloc(attrdef, ndef * sizeof(AttrDefault));
553 constr->defval = attrdef;
554 constr->num_defval = ndef;
557 constr->num_defval = 0;
558 constr->num_check = 0;