tupdesc.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:14k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * tupdesc.c
  4.  *   POSTGRES tuple descriptor support code
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.50.2.1 1999/08/02 05:24:26 scrappy Exp $
  11.  *
  12.  * NOTES
  13.  *   some of the executor utility code such as "ExecTypeFromTL" should be
  14.  *   moved here.
  15.  *
  16.  *-------------------------------------------------------------------------
  17.  */
  18. #include "postgres.h"
  19. #include "catalog/pg_type.h"
  20. #include "nodes/parsenodes.h"
  21. #include "parser/parse_type.h"
  22. #include "utils/builtins.h"
  23. #include "utils/syscache.h"
  24. /* ----------------------------------------------------------------
  25.  * CreateTemplateTupleDesc
  26.  *
  27.  * This function allocates and zeros a tuple descriptor structure.
  28.  * ----------------------------------------------------------------
  29.  */
  30. TupleDesc
  31. CreateTemplateTupleDesc(int natts)
  32. {
  33. uint32 size;
  34. TupleDesc desc;
  35. /* ----------------
  36.  * sanity checks
  37.  * ----------------
  38.  */
  39. AssertArg(natts >= 1);
  40. /* ----------------
  41.  * allocate enough memory for the tuple descriptor and
  42.  * zero it as TupleDescInitEntry assumes that the descriptor
  43.  * is filled with NULL pointers.
  44.  * ----------------
  45.  */
  46. size = natts * sizeof(Form_pg_attribute);
  47. desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
  48. desc->attrs = (Form_pg_attribute *) palloc(size);
  49. desc->constr = NULL;
  50. MemSet(desc->attrs, 0, size);
  51. desc->natts = natts;
  52. return desc;
  53. }
  54. /* ----------------------------------------------------------------
  55.  * CreateTupleDesc
  56.  *
  57.  * This function allocates a new TupleDesc from Form_pg_attribute array
  58.  * ----------------------------------------------------------------
  59.  */
  60. TupleDesc
  61. CreateTupleDesc(int natts, Form_pg_attribute *attrs)
  62. {
  63. TupleDesc desc;
  64. /* ----------------
  65.  * sanity checks
  66.  * ----------------
  67.  */
  68. AssertArg(natts >= 1);
  69. desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
  70. desc->attrs = attrs;
  71. desc->natts = natts;
  72. desc->constr = NULL;
  73. return desc;
  74. }
  75. /* ----------------------------------------------------------------
  76.  * CreateTupleDescCopy
  77.  *
  78.  * This function creates a new TupleDesc by copying from an existing
  79.  * TupleDesc
  80.  *
  81.  * !!! Constraints are not copied !!!
  82.  * ----------------------------------------------------------------
  83.  */
  84. TupleDesc
  85. CreateTupleDescCopy(TupleDesc tupdesc)
  86. {
  87. TupleDesc desc;
  88. int i,
  89. size;
  90. desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
  91. desc->natts = tupdesc->natts;
  92. size = desc->natts * sizeof(Form_pg_attribute);
  93. desc->attrs = (Form_pg_attribute *) palloc(size);
  94. for (i = 0; i < desc->natts; i++)
  95. {
  96. desc->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
  97. memmove(desc->attrs[i],
  98. tupdesc->attrs[i],
  99. ATTRIBUTE_TUPLE_SIZE);
  100. desc->attrs[i]->attnotnull = false;
  101. desc->attrs[i]->atthasdef = false;
  102. }
  103. desc->constr = NULL;
  104. return desc;
  105. }
  106. /* ----------------------------------------------------------------
  107.  * CreateTupleDescCopyConstr
  108.  *
  109.  * This function creates a new TupleDesc by copying from an existing
  110.  * TupleDesc (with Constraints)
  111.  *
  112.  * ----------------------------------------------------------------
  113.  */
  114. TupleDesc
  115. CreateTupleDescCopyConstr(TupleDesc tupdesc)
  116. {
  117. TupleDesc desc;
  118. TupleConstr *constr = tupdesc->constr;
  119. int i,
  120. size;
  121. desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
  122. desc->natts = tupdesc->natts;
  123. size = desc->natts * sizeof(Form_pg_attribute);
  124. desc->attrs = (Form_pg_attribute *) palloc(size);
  125. for (i = 0; i < desc->natts; i++)
  126. {
  127. desc->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
  128. memmove(desc->attrs[i],
  129. tupdesc->attrs[i],
  130. ATTRIBUTE_TUPLE_SIZE);
  131. }
  132. if (constr)
  133. {
  134. TupleConstr *cpy = (TupleConstr *) palloc(sizeof(TupleConstr));
  135. cpy->has_not_null = constr->has_not_null;
  136. if ((cpy->num_defval = constr->num_defval) > 0)
  137. {
  138. cpy->defval = (AttrDefault *) palloc(cpy->num_defval * sizeof(AttrDefault));
  139. memcpy(cpy->defval, constr->defval, cpy->num_defval * sizeof(AttrDefault));
  140. for (i = cpy->num_defval - 1; i >= 0; i--)
  141. {
  142. if (constr->defval[i].adbin)
  143. cpy->defval[i].adbin = pstrdup(constr->defval[i].adbin);
  144. if (constr->defval[i].adsrc)
  145. cpy->defval[i].adsrc = pstrdup(constr->defval[i].adsrc);
  146. }
  147. }
  148. if ((cpy->num_check = constr->num_check) > 0)
  149. {
  150. cpy->check = (ConstrCheck *) palloc(cpy->num_check * sizeof(ConstrCheck));
  151. memcpy(cpy->check, constr->check, cpy->num_check * sizeof(ConstrCheck));
  152. for (i = cpy->num_check - 1; i >= 0; i--)
  153. {
  154. if (constr->check[i].ccname)
  155. cpy->check[i].ccname = pstrdup(constr->check[i].ccname);
  156. if (constr->check[i].ccbin)
  157. cpy->check[i].ccbin = pstrdup(constr->check[i].ccbin);
  158. if (constr->check[i].ccsrc)
  159. cpy->check[i].ccsrc = pstrdup(constr->check[i].ccsrc);
  160. }
  161. }
  162. desc->constr = cpy;
  163. }
  164. else
  165. desc->constr = NULL;
  166. return desc;
  167. }
  168. void
  169. FreeTupleDesc(TupleDesc tupdesc)
  170. {
  171. int i;
  172. for (i = 0; i < tupdesc->natts; i++)
  173. pfree(tupdesc->attrs[i]);
  174. pfree(tupdesc->attrs);
  175. if (tupdesc->constr)
  176. {
  177. if (tupdesc->constr->num_defval > 0)
  178. {
  179. AttrDefault *attrdef = tupdesc->constr->defval;
  180. for (i = tupdesc->constr->num_defval - 1; i >= 0; i--)
  181. {
  182. if (attrdef[i].adbin)
  183. pfree(attrdef[i].adbin);
  184. if (attrdef[i].adsrc)
  185. pfree(attrdef[i].adsrc);
  186. }
  187. pfree(attrdef);
  188. }
  189. if (tupdesc->constr->num_check > 0)
  190. {
  191. ConstrCheck *check = tupdesc->constr->check;
  192. for (i = tupdesc->constr->num_check - 1; i >= 0; i--)
  193. {
  194. if (check[i].ccname)
  195. pfree(check[i].ccname);
  196. if (check[i].ccbin)
  197. pfree(check[i].ccbin);
  198. if (check[i].ccsrc)
  199. pfree(check[i].ccsrc);
  200. }
  201. pfree(check);
  202. }
  203. pfree(tupdesc->constr);
  204. }
  205. pfree(tupdesc);
  206. }
  207. /* ----------------------------------------------------------------
  208.  * TupleDescInitEntry
  209.  *
  210.  * This function initializes a single attribute structure in
  211.  * a preallocated tuple descriptor.
  212.  * ----------------------------------------------------------------
  213.  */
  214. bool
  215. TupleDescInitEntry(TupleDesc desc,
  216.    AttrNumber attributeNumber,
  217.    char *attributeName,
  218.    Oid typeid,
  219.    int32 typmod,
  220.    int attdim,
  221.    bool attisset)
  222. {
  223. HeapTuple tuple;
  224. Form_pg_type typeForm;
  225. Form_pg_attribute att;
  226. /* ----------------
  227.  * sanity checks
  228.  * ----------------
  229.  */
  230. AssertArg(PointerIsValid(desc));
  231. AssertArg(attributeNumber >= 1);
  232. /*
  233.  * attributeName's are sometimes NULL, from resdom's.  I don't know
  234.  * why that is, though -- Jolly
  235.  */
  236. /*   AssertArg(NameIsValid(attributeName));*/
  237. AssertArg(!PointerIsValid(desc->attrs[attributeNumber - 1]));
  238. /* ----------------
  239.  * allocate storage for this attribute
  240.  * ----------------
  241.  */
  242. att = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
  243. desc->attrs[attributeNumber - 1] = att;
  244. /* ----------------
  245.  * initialize some of the attribute fields
  246.  * ----------------
  247.  */
  248. att->attrelid = 0; /* dummy value */
  249. if (attributeName != NULL)
  250. namestrcpy(&(att->attname), attributeName);
  251. else
  252. MemSet(att->attname.data, 0, NAMEDATALEN);
  253. att->attdisbursion = 0; /* dummy value */
  254. att->attcacheoff = -1;
  255. att->atttypmod = typmod;
  256. att->attnum = attributeNumber;
  257. att->attnelems = attdim;
  258. att->attisset = attisset;
  259. att->attnotnull = false;
  260. att->atthasdef = false;
  261. /* ----------------
  262.  * search the system cache for the type tuple of the attribute
  263.  * we are creating so that we can get the typeid and some other
  264.  * stuff.
  265.  *
  266.  * Note: in the special case of
  267.  *
  268.  * create EMP (name = text, manager = EMP)
  269.  *
  270.  * RelationNameCreateHeapRelation() calls BuildDesc() which
  271.  * calls this routine and since EMP does not exist yet, the
  272.  * system cache lookup below fails.  That's fine, but rather
  273.  * then doing a elog(ERROR) we just leave that information
  274.  * uninitialized, return false, then fix things up later.
  275.  * -cim 6/14/90
  276.  * ----------------
  277.  */
  278. tuple = SearchSysCacheTuple(TYPOID,
  279. ObjectIdGetDatum(typeid),
  280. 0, 0, 0);
  281. if (!HeapTupleIsValid(tuple))
  282. {
  283. /* ----------------
  284.  *  here type info does not exist yet so we just fill
  285.  *  the attribute with dummy information and return false.
  286.  * ----------------
  287.  */
  288. att->atttypid = InvalidOid;
  289. att->attlen = (int16) 0;
  290. att->attbyval = (bool) 0;
  291. att->attalign = 'i';
  292. return false;
  293. }
  294. /* ----------------
  295.  * type info exists so we initialize our attribute
  296.  * information from the type tuple we found..
  297.  * ----------------
  298.  */
  299. typeForm = (Form_pg_type) GETSTRUCT(tuple);
  300. att->atttypid = tuple->t_data->t_oid;
  301. att->attalign = typeForm->typalign;
  302. /* ------------------------
  303.    If this attribute is a set, what is really stored in the
  304.    attribute is the OID of a tuple in the pg_proc catalog.
  305.    The pg_proc tuple contains the query string which defines
  306.    this set - i.e., the query to run to get the set.
  307.    So the atttypid (just assigned above) refers to the type returned
  308.    by this query, but the actual length of this attribute is the
  309.    length (size) of an OID.
  310.    Why not just make the atttypid point to the OID type, instead
  311.    of the type the query returns?  Because the executor uses the atttypid
  312.    to tell the front end what type will be returned (in BeginCommand),
  313.    and in the end the type returned will be the result of the query, not
  314.    an OID.
  315.    Why not wait until the return type of the set is known (i.e., the
  316.    recursive call to the executor to execute the set has returned)
  317.    before telling the front end what the return type will be?  Because
  318.    the executor is a delicate thing, and making sure that the correct
  319.    order of front-end commands is maintained is messy, especially
  320.    considering that target lists may change as inherited attributes
  321.    are considered, etc.  Ugh.
  322.    -----------------------------------------
  323.    */
  324. if (attisset)
  325. {
  326. Type t = typeidType(OIDOID);
  327. att->attlen = typeLen(t);
  328. att->attbyval = typeByVal(t);
  329. }
  330. else
  331. {
  332. att->attlen = typeForm->typlen;
  333. att->attbyval = typeForm->typbyval;
  334. }
  335. return true;
  336. }
  337. /* ----------------------------------------------------------------
  338.  * TupleDescMakeSelfReference
  339.  *
  340.  * This function initializes a "self-referential" attribute like
  341.  * manager in "create EMP (name=text, manager = EMP)".
  342.  * It calls TypeShellMake() which inserts a "shell" type
  343.  * tuple into pg_type.  A self-reference is one kind of set, so
  344.  * its size and byval are the same as for a set.  See the comments
  345.  * above in TupleDescInitEntry.
  346.  * ----------------------------------------------------------------
  347.  */
  348. static void
  349. TupleDescMakeSelfReference(TupleDesc desc,
  350.    AttrNumber attnum,
  351.    char *relname)
  352. {
  353. Form_pg_attribute att;
  354. Type t = typeidType(OIDOID);
  355. att = desc->attrs[attnum - 1];
  356. att->atttypid = TypeShellMake(relname);
  357. att->attlen = typeLen(t);
  358. att->attbyval = typeByVal(t);
  359. att->attnelems = 0;
  360. }
  361. /* ----------------------------------------------------------------
  362.  * BuildDescForRelation
  363.  *
  364.  * This is a general purpose function identical to BuildDesc
  365.  * but is used by the DefineRelation() code to catch the
  366.  * special case where you
  367.  *
  368.  * create FOO ( ..., x = FOO )
  369.  *
  370.  * here, the initial type lookup for "x = FOO" will fail
  371.  * because FOO isn't in the catalogs yet.  But since we
  372.  * are creating FOO, instead of doing an elog() we add
  373.  * a shell type tuple to pg_type and fix things later
  374.  * in amcreate().
  375.  * ----------------------------------------------------------------
  376.  */
  377. TupleDesc
  378. BuildDescForRelation(List *schema, char *relname)
  379. {
  380. int natts;
  381. AttrNumber attnum;
  382. List    *p;
  383. TupleDesc desc;
  384. AttrDefault *attrdef = NULL;
  385. TupleConstr *constr = (TupleConstr *) palloc(sizeof(TupleConstr));
  386. char    *attname;
  387. char    *typename;
  388. int32 atttypmod;
  389. int attdim;
  390. int ndef = 0;
  391. bool attisset;
  392. /* ----------------
  393.  * allocate a new tuple descriptor
  394.  * ----------------
  395.  */
  396. natts = length(schema);
  397. desc = CreateTemplateTupleDesc(natts);
  398. constr->has_not_null = false;
  399. attnum = 0;
  400. typename = palloc(NAMEDATALEN);
  401. foreach(p, schema)
  402. {
  403. ColumnDef  *entry;
  404. List    *arry;
  405. /* ----------------
  406.  * for each entry in the list, get the name and type
  407.  * information from the list and have TupleDescInitEntry
  408.  * fill in the attribute information we need.
  409.  * ----------------
  410.  */
  411. attnum++;
  412. entry = lfirst(p);
  413. attname = entry->colname;
  414. arry = entry->typename->arrayBounds;
  415. attisset = entry->typename->setof;
  416. atttypmod = entry->typename->typmod;
  417. if (arry != NIL)
  418. {
  419. /* array of XXX is _XXX */
  420. snprintf(typename, NAMEDATALEN,
  421.  "_%.*s", NAMEDATALEN - 2, entry->typename->name);
  422. attdim = length(arry);
  423. }
  424. else
  425. {
  426. StrNCpy(typename, entry->typename->name, NAMEDATALEN);
  427. attdim = 0;
  428. }
  429. if (!TupleDescInitEntry(desc, attnum, attname,
  430. typeTypeId(typenameType(typename)),
  431. atttypmod, attdim, attisset))
  432. {
  433. /* ----------------
  434.  * if TupleDescInitEntry() fails, it means there is
  435.  * no type in the system catalogs.  So now we check if
  436.  * the type name equals the relation name.  If so we
  437.  * have a self reference, otherwise it's an error.
  438.  * ----------------
  439.  */
  440. if (!strcmp(typename, relname))
  441. TupleDescMakeSelfReference(desc, attnum, relname);
  442. else
  443. elog(ERROR, "DefineRelation: no such type %s",
  444.  typename);
  445. }
  446. desc->attrs[attnum - 1]->atttypmod = entry->typename->typmod;
  447. /* This is for constraints */
  448. if (entry->is_not_null)
  449. constr->has_not_null = true;
  450. desc->attrs[attnum - 1]->attnotnull = entry->is_not_null;
  451. if (entry->defval != NULL)
  452. {
  453. if (attrdef == NULL)
  454. attrdef = (AttrDefault *) palloc(natts * sizeof(AttrDefault));
  455. attrdef[ndef].adnum = attnum;
  456. attrdef[ndef].adbin = NULL;
  457. attrdef[ndef].adsrc = entry->defval;
  458. ndef++;
  459. desc->attrs[attnum - 1]->atthasdef = true;
  460. }
  461. }
  462. if (constr->has_not_null || ndef > 0)
  463. {
  464. desc->constr = constr;
  465. if (ndef > 0) /* DEFAULTs */
  466. {
  467. if (ndef < natts)
  468. constr->defval = (AttrDefault *)
  469. repalloc(attrdef, ndef * sizeof(AttrDefault));
  470. else
  471. constr->defval = attrdef;
  472. constr->num_defval = ndef;
  473. }
  474. else
  475. constr->num_defval = 0;
  476. constr->num_check = 0;
  477. }
  478. else
  479. {
  480. pfree(constr);
  481. desc->constr = NULL;
  482. }
  483. return desc;
  484. }