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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * heaptuple.c
  4.  *   This file contains heap tuple accessor and mutator routines, as well
  5.  *   as a few various tuple utilities.
  6.  *
  7.  * Copyright (c) 1994, Regents of the University of California
  8.  *
  9.  *
  10.  * IDENTIFICATION
  11.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.53.2.1 1999/08/02 05:24:25 scrappy Exp $
  12.  *
  13.  * NOTES
  14.  *   The old interface functions have been converted to macros
  15.  *   and moved to heapam.h
  16.  *
  17.  *-------------------------------------------------------------------------
  18.  */
  19. #include "postgres.h"
  20. #include "access/heapam.h"
  21. #include "catalog/pg_type.h"
  22. /* Used by heap_getattr() macro, for speed */
  23. long heap_sysoffset[] = {
  24. /* Only the first one is pass-by-ref, and is handled specially in the macro */
  25. offsetof(HeapTupleHeaderData, t_ctid),
  26. offsetof(HeapTupleHeaderData, t_oid),
  27. offsetof(HeapTupleHeaderData, t_xmin),
  28. offsetof(HeapTupleHeaderData, t_cmin),
  29. offsetof(HeapTupleHeaderData, t_xmax),
  30. offsetof(HeapTupleHeaderData, t_cmax)
  31. };
  32. /* ----------------------------------------------------------------
  33.  * misc support routines
  34.  * ----------------------------------------------------------------
  35.  */
  36. /* ----------------
  37.  * ComputeDataSize
  38.  * ----------------
  39.  */
  40. Size
  41. ComputeDataSize(TupleDesc tupleDesc,
  42. Datum *value,
  43. char *nulls)
  44. {
  45. uint32 data_length;
  46. int i;
  47. int numberOfAttributes = tupleDesc->natts;
  48. Form_pg_attribute *att = tupleDesc->attrs;
  49. for (data_length = 0, i = 0; i < numberOfAttributes; i++)
  50. {
  51. if (nulls[i] != ' ')
  52. continue;
  53. data_length = att_align(data_length, att[i]->attlen, att[i]->attalign);
  54. data_length = att_addlength(data_length, att[i]->attlen, value[i]);
  55. }
  56. return data_length;
  57. }
  58. /* ----------------
  59.  * DataFill
  60.  * ----------------
  61.  */
  62. void
  63. DataFill(char *data,
  64.  TupleDesc tupleDesc,
  65.  Datum *value,
  66.  char *nulls,
  67.  uint16 *infomask,
  68.  bits8 *bit)
  69. {
  70. bits8    *bitP = 0;
  71. int bitmask = 0;
  72. uint32 data_length;
  73. int i;
  74. int numberOfAttributes = tupleDesc->natts;
  75. Form_pg_attribute *att = tupleDesc->attrs;
  76. if (bit != NULL)
  77. {
  78. bitP = &bit[-1];
  79. bitmask = CSIGNBIT;
  80. }
  81. *infomask = 0;
  82. for (i = 0; i < numberOfAttributes; i++)
  83. {
  84. if (bit != NULL)
  85. {
  86. if (bitmask != CSIGNBIT)
  87. bitmask <<= 1;
  88. else
  89. {
  90. bitP += 1;
  91. *bitP = 0x0;
  92. bitmask = 1;
  93. }
  94. if (nulls[i] == 'n')
  95. {
  96. *infomask |= HEAP_HASNULL;
  97. continue;
  98. }
  99. *bitP |= bitmask;
  100. }
  101. data = (char *) att_align((long) data, att[i]->attlen, att[i]->attalign);
  102. switch (att[i]->attlen)
  103. {
  104. case -1:
  105. *infomask |= HEAP_HASVARLENA;
  106. data_length = VARSIZE(DatumGetPointer(value[i]));
  107. memmove(data, DatumGetPointer(value[i]), data_length);
  108. break;
  109. case sizeof(char):
  110. *data = att[i]->attbyval ?
  111. DatumGetChar(value[i]) : *((char *) value[i]);
  112. break;
  113. case sizeof(int16):
  114. *(short *) data = (att[i]->attbyval ?
  115.    DatumGetInt16(value[i]) :
  116.    *((short *) value[i]));
  117. break;
  118. case sizeof(int32):
  119. *(int32 *) data = (att[i]->attbyval ?
  120.    DatumGetInt32(value[i]) :
  121.    *((int32 *) value[i]));
  122. break;
  123. default:
  124. memmove(data, DatumGetPointer(value[i]),
  125. att[i]->attlen);
  126. break;
  127. }
  128. data = (char *) att_addlength((long) data, att[i]->attlen, value[i]);
  129. }
  130. }
  131. /* ----------------------------------------------------------------
  132.  * heap tuple interface
  133.  * ----------------------------------------------------------------
  134.  */
  135. /* ----------------
  136.  * heap_attisnull - returns 1 iff tuple attribute is not present
  137.  * ----------------
  138.  */
  139. int
  140. heap_attisnull(HeapTuple tup, int attnum)
  141. {
  142. if (attnum > (int) tup->t_data->t_natts)
  143. return 1;
  144. if (HeapTupleNoNulls(tup))
  145. return 0;
  146. if (attnum > 0)
  147. return att_isnull(attnum - 1, tup->t_data->t_bits);
  148. else
  149. switch (attnum)
  150. {
  151. case SelfItemPointerAttributeNumber:
  152. case ObjectIdAttributeNumber:
  153. case MinTransactionIdAttributeNumber:
  154. case MinCommandIdAttributeNumber:
  155. case MaxTransactionIdAttributeNumber:
  156. case MaxCommandIdAttributeNumber:
  157. break;
  158. case 0:
  159. elog(ERROR, "heap_attisnull: zero attnum disallowed");
  160. default:
  161. elog(ERROR, "heap_attisnull: undefined negative attnum");
  162. }
  163. return 0;
  164. }
  165. /* ----------------------------------------------------------------
  166.  *  system attribute heap tuple support
  167.  * ----------------------------------------------------------------
  168.  */
  169. /* ----------------
  170.  * heap_sysattrlen
  171.  *
  172.  * This routine returns the length of a system attribute.
  173.  * ----------------
  174.  */
  175. int
  176. heap_sysattrlen(AttrNumber attno)
  177. {
  178. HeapTupleHeader f = NULL;
  179. switch (attno)
  180. {
  181. case SelfItemPointerAttributeNumber:
  182. return sizeof f->t_ctid;
  183. case ObjectIdAttributeNumber:
  184. return sizeof f->t_oid;
  185. case MinTransactionIdAttributeNumber:
  186. return sizeof f->t_xmin;
  187. case MinCommandIdAttributeNumber:
  188. return sizeof f->t_cmin;
  189. case MaxTransactionIdAttributeNumber:
  190. return sizeof f->t_xmax;
  191. case MaxCommandIdAttributeNumber:
  192. return sizeof f->t_cmax;
  193. default:
  194. elog(ERROR, "sysattrlen: System attribute number %d unknown.", attno);
  195. return 0;
  196. }
  197. }
  198. /* ----------------
  199.  * heap_sysattrbyval
  200.  *
  201.  * This routine returns the "by-value" property of a system attribute.
  202.  * ----------------
  203.  */
  204. bool
  205. heap_sysattrbyval(AttrNumber attno)
  206. {
  207. bool byval;
  208. switch (attno)
  209. {
  210. case SelfItemPointerAttributeNumber:
  211. byval = false;
  212. break;
  213. case ObjectIdAttributeNumber:
  214. byval = true;
  215. break;
  216. case MinTransactionIdAttributeNumber:
  217. byval = true;
  218. break;
  219. case MinCommandIdAttributeNumber:
  220. byval = true;
  221. break;
  222. case MaxTransactionIdAttributeNumber:
  223. byval = true;
  224. break;
  225. case MaxCommandIdAttributeNumber:
  226. byval = true;
  227. break;
  228. default:
  229. byval = true;
  230. elog(ERROR, "sysattrbyval: System attribute number %d unknown.",
  231.  attno);
  232. break;
  233. }
  234. return byval;
  235. }
  236. #ifdef NOT_USED
  237. /* ----------------
  238.  * heap_getsysattr
  239.  * ----------------
  240.  */
  241. Datum
  242. heap_getsysattr(HeapTuple tup, Buffer b, int attnum)
  243. {
  244. switch (attnum)
  245. {
  246. case SelfItemPointerAttributeNumber:
  247. return (Datum) &tup->t_ctid;
  248. case ObjectIdAttributeNumber:
  249. return (Datum) (long) tup->t_oid;
  250. case MinTransactionIdAttributeNumber:
  251. return (Datum) (long) tup->t_xmin;
  252. case MinCommandIdAttributeNumber:
  253. return (Datum) (long) tup->t_cmin;
  254. case MaxTransactionIdAttributeNumber:
  255. return (Datum) (long) tup->t_xmax;
  256. case MaxCommandIdAttributeNumber:
  257. return (Datum) (long) tup->t_cmax;
  258. default:
  259. elog(ERROR, "heap_getsysattr: undefined attnum %d", attnum);
  260. }
  261. return (Datum) NULL;
  262. }
  263. #endif
  264. /* ----------------
  265.  * nocachegetattr
  266.  *
  267.  * This only gets called from fastgetattr() macro, in cases where
  268.  * we can't use a cacheoffset and the value is not null.
  269.  *
  270.  * This caches attribute offsets in the attribute descriptor.
  271.  *
  272.  * An alternate way to speed things up would be to cache offsets
  273.  * with the tuple, but that seems more difficult unless you take
  274.  * the storage hit of actually putting those offsets into the
  275.  * tuple you send to disk.  Yuck.
  276.  *
  277.  * This scheme will be slightly slower than that, but should
  278.  * perform well for queries which hit large #'s of tuples.  After
  279.  * you cache the offsets once, examining all the other tuples using
  280.  * the same attribute descriptor will go much quicker. -cim 5/4/91
  281.  * ----------------
  282.  */
  283. Datum
  284. nocachegetattr(HeapTuple tuple,
  285.    int attnum,
  286.    TupleDesc tupleDesc,
  287.    bool *isnull)
  288. {
  289. char    *tp; /* ptr to att in tuple */
  290. HeapTupleHeader tup = tuple->t_data;
  291. bits8    *bp = tup->t_bits; /* ptr to att in tuple */
  292. Form_pg_attribute *att = tupleDesc->attrs;
  293. int slow = 0; /* do we have to walk nulls? */
  294. #if IN_MACRO
  295. /* This is handled in the macro */
  296. Assert(attnum > 0);
  297. if (isnull)
  298. *isnull = false;
  299. #endif
  300. attnum--;
  301. /* ----------------
  302.  *  Three cases:
  303.  *
  304.  *  1: No nulls and no variable length attributes.
  305.  *  2: Has a null or a varlena AFTER att.
  306.  *  3: Has nulls or varlenas BEFORE att.
  307.  * ----------------
  308.  */
  309. if (HeapTupleNoNulls(tuple))
  310. {
  311. #if IN_MACRO
  312. /* This is handled in the macro */
  313. if (att[attnum]->attcacheoff != -1)
  314. {
  315. return (Datum)
  316. fetchatt(&(att[attnum]),
  317.   (char *) tup + tup->t_hoff + att[attnum]->attcacheoff);
  318. }
  319. else if (attnum == 0)
  320. {
  321. /*
  322.  * first attribute is always at position zero
  323.  */
  324. return (Datum) fetchatt(&(att[0]), (char *) tup + tup->t_hoff);
  325. }
  326. #endif
  327. }
  328. else
  329. {
  330. /*
  331.  * there's a null somewhere in the tuple
  332.  */
  333. /* ----------------
  334.  * check to see if desired att is null
  335.  * ----------------
  336.  */
  337. #if IN_MACRO
  338. /* This is handled in the macro */
  339. if (att_isnull(attnum, bp))
  340. {
  341. if (isnull)
  342. *isnull = true;
  343. return (Datum) NULL;
  344. }
  345. #endif
  346. /* ----------------
  347.  * Now check to see if any preceding bits are null...
  348.  * ----------------
  349.  */
  350. {
  351. int byte = attnum >> 3;
  352. int finalbit = attnum & 0x07;
  353. /* check for nulls "before" final bit of last byte */
  354. if ((~bp[byte]) & ((1 << finalbit) - 1))
  355. slow = 1;
  356. else
  357. {
  358. /* check for nulls in any "earlier" bytes */
  359. int i;
  360. for (i = 0; i < byte; i++)
  361. {
  362. if (bp[i] != 0xFF)
  363. {
  364. slow = 1;
  365. break;
  366. }
  367. }
  368. }
  369. }
  370. }
  371. tp = (char *) tup + tup->t_hoff;
  372. /*
  373.  * now check for any non-fixed length attrs before our attribute
  374.  */
  375. if (!slow)
  376. {
  377. if (att[attnum]->attcacheoff != -1)
  378. {
  379. return (Datum) fetchatt(&(att[attnum]),
  380. tp + att[attnum]->attcacheoff);
  381. }
  382. else if (attnum == 0)
  383. return (Datum) fetchatt(&(att[0]), tp);
  384. else if (!HeapTupleAllFixed(tuple))
  385. {
  386. int j;
  387. /*
  388.  * In for(), we make this <= and not < because we want to test
  389.  * if we can go past it in initializing offsets.
  390.  */
  391. for (j = 0; j <= attnum; j++)
  392. {
  393. if (att[j]->attlen < 1 && !VARLENA_FIXED_SIZE(att[j]))
  394. {
  395. slow = 1;
  396. break;
  397. }
  398. }
  399. }
  400. }
  401. /*
  402.  * If slow is zero, and we got here, we know that we have a tuple with
  403.  * no nulls or varlenas before the target attribute. If possible, we
  404.  * also want to initialize the remainder of the attribute cached
  405.  * offset values.
  406.  */
  407. if (!slow)
  408. {
  409. int j = 1;
  410. long off;
  411. /*
  412.  * need to set cache for some atts
  413.  */
  414. att[0]->attcacheoff = 0;
  415. while (att[j]->attcacheoff > 0)
  416. j++;
  417. if (!VARLENA_FIXED_SIZE(att[j - 1]))
  418. off = att[j - 1]->attcacheoff + att[j - 1]->attlen;
  419. else
  420. off = att[j - 1]->attcacheoff + att[j - 1]->atttypmod;
  421. for (; j <= attnum ||
  422. /* Can we compute more?  We will probably need them */
  423.  (j < tup->t_natts &&
  424.   att[j]->attcacheoff == -1 &&
  425.   (HeapTupleNoNulls(tuple) || !att_isnull(j, bp)) &&
  426.   (HeapTupleAllFixed(tuple) ||
  427.    att[j]->attlen > 0 || VARLENA_FIXED_SIZE(att[j]))); j++)
  428. {
  429. /*
  430.  * Fix me when going to a machine with more than a four-byte
  431.  * word!
  432.  */
  433. off = att_align(off, att[j]->attlen, att[j]->attalign);
  434. att[j]->attcacheoff = off;
  435. off = att_addlength(off, att[j]->attlen, tp + off);
  436. }
  437. return (Datum) fetchatt(&(att[attnum]), tp + att[attnum]->attcacheoff);
  438. }
  439. else
  440. {
  441. bool usecache = true;
  442. int off = 0;
  443. int i;
  444. /*
  445.  * Now we know that we have to walk the tuple CAREFULLY.
  446.  *
  447.  * Note - This loop is a little tricky.  On iteration i we first set
  448.  * the offset for attribute i and figure out how much the offset
  449.  * should be incremented.  Finally, we need to align the offset
  450.  * based on the size of attribute i+1 (for which the offset has
  451.  * been computed). -mer 12 Dec 1991
  452.  */
  453. for (i = 0; i < attnum; i++)
  454. {
  455. if (!HeapTupleNoNulls(tuple))
  456. {
  457. if (att_isnull(i, bp))
  458. {
  459. usecache = false;
  460. continue;
  461. }
  462. }
  463. /* If we know the next offset, we can skip the rest */
  464. if (usecache && att[i]->attcacheoff != -1)
  465. off = att[i]->attcacheoff;
  466. else
  467. {
  468. off = att_align(off, att[i]->attlen, att[i]->attalign);
  469. if (usecache)
  470. att[i]->attcacheoff = off;
  471. }
  472. off = att_addlength(off, att[i]->attlen, tp + off);
  473. if (usecache &&
  474. att[i]->attlen == -1 && !VARLENA_FIXED_SIZE(att[i]))
  475. usecache = false;
  476. }
  477. off = att_align(off, att[attnum]->attlen, att[attnum]->attalign);
  478. return (Datum) fetchatt(&(att[attnum]), tp + off);
  479. }
  480. }
  481. /* ----------------
  482.  * heap_copytuple
  483.  *
  484.  * returns a copy of an entire tuple
  485.  * ----------------
  486.  */
  487. HeapTuple
  488. heap_copytuple(HeapTuple tuple)
  489. {
  490. HeapTuple newTuple;
  491. if (!HeapTupleIsValid(tuple) || tuple->t_data == NULL)
  492. return NULL;
  493. newTuple = (HeapTuple) palloc(HEAPTUPLESIZE + tuple->t_len);
  494. newTuple->t_len = tuple->t_len;
  495. newTuple->t_self = tuple->t_self;
  496. newTuple->t_data = (HeapTupleHeader) ((char *) newTuple + HEAPTUPLESIZE);
  497. memmove((char *) newTuple->t_data,
  498. (char *) tuple->t_data, (int) tuple->t_len);
  499. return newTuple;
  500. }
  501. /* ----------------
  502.  * heap_copytuple_with_tuple
  503.  *
  504.  * returns a copy of an tuple->t_data
  505.  * ----------------
  506.  */
  507. void
  508. heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest)
  509. {
  510. if (!HeapTupleIsValid(src) || src->t_data == NULL)
  511. {
  512. dest->t_data = NULL;
  513. return;
  514. }
  515. dest->t_len = src->t_len;
  516. dest->t_self = src->t_self;
  517. dest->t_data = (HeapTupleHeader) palloc(src->t_len);
  518. memmove((char *) dest->t_data,
  519. (char *) src->t_data, (int) src->t_len);
  520. return;
  521. }
  522. #ifdef NOT_USED
  523. /* ----------------
  524.  * heap_deformtuple
  525.  *
  526.  * the inverse of heap_formtuple (see below)
  527.  * ----------------
  528.  */
  529. void
  530. heap_deformtuple(HeapTuple tuple,
  531.  TupleDesc tdesc,
  532.  Datum *values,
  533.  char *nulls)
  534. {
  535. int i;
  536. int natts;
  537. Assert(HeapTupleIsValid(tuple));
  538. natts = tuple->t_natts;
  539. for (i = 0; i < natts; i++)
  540. {
  541. bool isnull;
  542. values[i] = heap_getattr(tuple,
  543.  i + 1,
  544.  tdesc,
  545.  &isnull);
  546. if (isnull)
  547. nulls[i] = 'n';
  548. else
  549. nulls[i] = ' ';
  550. }
  551. }
  552. #endif
  553. /* ----------------
  554.  * heap_formtuple
  555.  *
  556.  * constructs a tuple from the given *value and *null arrays
  557.  *
  558.  * old comments
  559.  * Handles alignment by aligning 2 byte attributes on short boundries
  560.  * and 3 or 4 byte attributes on long word boundries on a vax; and
  561.  * aligning non-byte attributes on short boundries on a sun.  Does
  562.  * not properly align fixed length arrays of 1 or 2 byte types (yet).
  563.  *
  564.  * Null attributes are indicated by a 'n' in the appropriate byte
  565.  * of the *null. Non-null attributes are indicated by a ' ' (space).
  566.  *
  567.  * Fix me.  (Figure that must keep context if debug--allow give oid.)
  568.  * Assumes in order.
  569.  * ----------------
  570.  */
  571. HeapTuple
  572. heap_formtuple(TupleDesc tupleDescriptor,
  573.    Datum *value,
  574.    char *nulls)
  575. {
  576. HeapTuple tuple; /* return tuple */
  577. HeapTupleHeader td; /* tuple data */
  578. int bitmaplen;
  579. long len;
  580. int hoff;
  581. bool hasnull = false;
  582. int i;
  583. int numberOfAttributes = tupleDescriptor->natts;
  584. len = offsetof(HeapTupleHeaderData, t_bits);
  585. for (i = 0; i < numberOfAttributes && !hasnull; i++)
  586. {
  587. if (nulls[i] != ' ')
  588. hasnull = true;
  589. }
  590. if (numberOfAttributes > MaxHeapAttributeNumber)
  591. elog(ERROR, "heap_formtuple: numberOfAttributes of %d > %d",
  592.  numberOfAttributes, MaxHeapAttributeNumber);
  593. if (hasnull)
  594. {
  595. bitmaplen = BITMAPLEN(numberOfAttributes);
  596. len += bitmaplen;
  597. }
  598. hoff = len = MAXALIGN(len); /* be conservative here */
  599. len += ComputeDataSize(tupleDescriptor, value, nulls);
  600. tuple = (HeapTuple) palloc(HEAPTUPLESIZE + len);
  601. td = tuple->t_data = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
  602. MemSet((char *) td, 0, (int) len);
  603. tuple->t_len = len;
  604. ItemPointerSetInvalid(&(tuple->t_self));
  605. td->t_natts = numberOfAttributes;
  606. td->t_hoff = hoff;
  607. DataFill((char *) td + td->t_hoff,
  608.  tupleDescriptor,
  609.  value,
  610.  nulls,
  611.  &td->t_infomask,
  612.  (hasnull ? td->t_bits : NULL));
  613. td->t_infomask |= HEAP_XMAX_INVALID;
  614. return tuple;
  615. }
  616. /* ----------------
  617.  * heap_modifytuple
  618.  *
  619.  * forms a new tuple from an old tuple and a set of replacement values.
  620.  * returns a new palloc'ed tuple.
  621.  * ----------------
  622.  */
  623. HeapTuple
  624. heap_modifytuple(HeapTuple tuple,
  625.  Relation relation,
  626.  Datum *replValue,
  627.  char *replNull,
  628.  char *repl)
  629. {
  630. int attoff;
  631. int numberOfAttributes;
  632. Datum    *value;
  633. char    *nulls;
  634. bool isNull;
  635. HeapTuple newTuple;
  636. uint8 infomask;
  637. /* ----------------
  638.  * sanity checks
  639.  * ----------------
  640.  */
  641. Assert(HeapTupleIsValid(tuple));
  642. Assert(RelationIsValid(relation));
  643. Assert(PointerIsValid(replValue));
  644. Assert(PointerIsValid(replNull));
  645. Assert(PointerIsValid(repl));
  646. numberOfAttributes = RelationGetForm(relation)->relnatts;
  647. /* ----------------
  648.  * allocate and fill *value and *nulls arrays from either
  649.  * the tuple or the repl information, as appropriate.
  650.  * ----------------
  651.  */
  652. value = (Datum *) palloc(numberOfAttributes * sizeof *value);
  653. nulls = (char *) palloc(numberOfAttributes * sizeof *nulls);
  654. for (attoff = 0;
  655.  attoff < numberOfAttributes;
  656.  attoff += 1)
  657. {
  658. if (repl[attoff] == ' ')
  659. {
  660. value[attoff] = heap_getattr(tuple,
  661.  AttrOffsetGetAttrNumber(attoff),
  662.  RelationGetDescr(relation),
  663.  &isNull);
  664. nulls[attoff] = (isNull) ? 'n' : ' ';
  665. }
  666. else if (repl[attoff] != 'r')
  667. elog(ERROR, "heap_modifytuple: repl is \%3d", repl[attoff]);
  668. else
  669. { /* == 'r' */
  670. value[attoff] = replValue[attoff];
  671. nulls[attoff] = replNull[attoff];
  672. }
  673. }
  674. /* ----------------
  675.  * create a new tuple from the *values and *nulls arrays
  676.  * ----------------
  677.  */
  678. newTuple = heap_formtuple(RelationGetDescr(relation),
  679.   value,
  680.   nulls);
  681. /* ----------------
  682.  * copy the header except for t_len, t_natts, t_hoff, t_bits, t_infomask
  683.  * ----------------
  684.  */
  685. infomask = newTuple->t_data->t_infomask;
  686. memmove((char *) &newTuple->t_data->t_oid, /* XXX */
  687. (char *) &tuple->t_data->t_oid,
  688. ((char *) &tuple->t_data->t_hoff -
  689.  (char *) &tuple->t_data->t_oid)); /* XXX */
  690. newTuple->t_data->t_infomask = infomask;
  691. newTuple->t_data->t_natts = numberOfAttributes;
  692. newTuple->t_self = tuple->t_self;
  693. return newTuple;
  694. }
  695. /* ----------------------------------------------------------------
  696.  * other misc functions
  697.  * ----------------------------------------------------------------
  698.  */
  699. HeapTuple
  700. heap_addheader(uint32 natts, /* max domain index */
  701.    int structlen, /* its length */
  702.    char *structure) /* pointer to the struct */
  703. {
  704. HeapTuple tuple;
  705. HeapTupleHeader td; /* tuple data */
  706. long len;
  707. int hoff;
  708. AssertArg(natts > 0);
  709. len = offsetof(HeapTupleHeaderData, t_bits);
  710. hoff = len = MAXALIGN(len); /* be conservative */
  711. len += structlen;
  712. tuple = (HeapTuple) palloc(HEAPTUPLESIZE + len);
  713. td = tuple->t_data = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
  714. MemSet((char *) td, 0, (int) len);
  715. tuple->t_len = len;
  716. ItemPointerSetInvalid(&(tuple->t_self));
  717. td->t_hoff = hoff;
  718. td->t_natts = natts;
  719. td->t_infomask = 0;
  720. td->t_infomask |= HEAP_XMAX_INVALID;
  721. memmove((char *) td + hoff, structure, structlen);
  722. return tuple;
  723. }