1616 *
1717 *
1818 * IDENTIFICATION
19- * $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.106 2006/03/05 15:58:20 momjian Exp $
19+ * $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.107 2006/06/27 02:51:39 tgl Exp $
2020 *
2121 *-------------------------------------------------------------------------
2222 */
@@ -1295,6 +1295,8 @@ slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
12951295{
12961296if (tuple == NULL )/* internal error */
12971297elog (ERROR ,"cannot extract system attribute from virtual tuple" );
1298+ if (slot -> tts_mintuple )/* internal error */
1299+ elog (ERROR ,"cannot extract system attribute from minimal tuple" );
12981300return heap_getsysattr (tuple ,attnum ,tupleDesc ,isnull );
12991301}
13001302
@@ -1479,6 +1481,8 @@ slot_attisnull(TupleTableSlot *slot, int attnum)
14791481{
14801482if (tuple == NULL )/* internal error */
14811483elog (ERROR ,"cannot extract system attribute from virtual tuple" );
1484+ if (slot -> tts_mintuple )/* internal error */
1485+ elog (ERROR ,"cannot extract system attribute from minimal tuple" );
14821486return heap_attisnull (tuple ,attnum );
14831487}
14841488
@@ -1505,9 +1509,8 @@ slot_attisnull(TupleTableSlot *slot, int attnum)
15051509return heap_attisnull (tuple ,attnum );
15061510}
15071511
1508- /* ----------------
1509- *heap_freetuple
1510- * ----------------
1512+ /*
1513+ * heap_freetuple
15111514 */
15121515void
15131516heap_freetuple (HeapTuple htup )
@@ -1516,6 +1519,173 @@ heap_freetuple(HeapTuple htup)
15161519}
15171520
15181521
1522+ /*
1523+ * heap_form_minimal_tuple
1524+ *construct a MinimalTuple from the given values[] and isnull[] arrays,
1525+ *which are of the length indicated by tupleDescriptor->natts
1526+ *
1527+ * This is exactly like heap_form_tuple() except that the result is a
1528+ * "minimal" tuple lacking a HeapTupleData header as well as room for system
1529+ * columns.
1530+ *
1531+ * The result is allocated in the current memory context.
1532+ */
1533+ MinimalTuple
1534+ heap_form_minimal_tuple (TupleDesc tupleDescriptor ,
1535+ Datum * values ,
1536+ bool * isnull )
1537+ {
1538+ MinimalTuple tuple ;/* return tuple */
1539+ unsigned long len ;
1540+ int hoff ;
1541+ bool hasnull = false;
1542+ Form_pg_attribute * att = tupleDescriptor -> attrs ;
1543+ int numberOfAttributes = tupleDescriptor -> natts ;
1544+ int i ;
1545+
1546+ if (numberOfAttributes > MaxTupleAttributeNumber )
1547+ ereport (ERROR ,
1548+ (errcode (ERRCODE_TOO_MANY_COLUMNS ),
1549+ errmsg ("number of columns (%d) exceeds limit (%d)" ,
1550+ numberOfAttributes ,MaxTupleAttributeNumber )));
1551+
1552+ /*
1553+ * Check for nulls and embedded tuples; expand any toasted attributes in
1554+ * embedded tuples. This preserves the invariant that toasting can only
1555+ * go one level deep.
1556+ *
1557+ * We can skip calling toast_flatten_tuple_attribute() if the attribute
1558+ * couldn't possibly be of composite type. All composite datums are
1559+ * varlena and have alignment 'd'; furthermore they aren't arrays. Also,
1560+ * if an attribute is already toasted, it must have been sent to disk
1561+ * already and so cannot contain toasted attributes.
1562+ */
1563+ for (i = 0 ;i < numberOfAttributes ;i ++ )
1564+ {
1565+ if (isnull [i ])
1566+ hasnull = true;
1567+ else if (att [i ]-> attlen == -1 &&
1568+ att [i ]-> attalign == 'd' &&
1569+ att [i ]-> attndims == 0 &&
1570+ !VARATT_IS_EXTENDED (values [i ]))
1571+ {
1572+ values [i ]= toast_flatten_tuple_attribute (values [i ],
1573+ att [i ]-> atttypid ,
1574+ att [i ]-> atttypmod );
1575+ }
1576+ }
1577+
1578+ /*
1579+ * Determine total space needed
1580+ */
1581+ len = offsetof(MinimalTupleData ,t_bits );
1582+
1583+ if (hasnull )
1584+ len += BITMAPLEN (numberOfAttributes );
1585+
1586+ if (tupleDescriptor -> tdhasoid )
1587+ len += sizeof (Oid );
1588+
1589+ hoff = len = MAXALIGN (len );/* align user data safely */
1590+
1591+ len += heap_compute_data_size (tupleDescriptor ,values ,isnull );
1592+
1593+ /*
1594+ * Allocate and zero the space needed.
1595+ */
1596+ tuple = (MinimalTuple )palloc0 (len );
1597+
1598+ /*
1599+ * And fill in the information.
1600+ */
1601+ tuple -> t_len = len ;
1602+ tuple -> t_natts = numberOfAttributes ;
1603+ tuple -> t_hoff = hoff + MINIMAL_TUPLE_OFFSET ;
1604+
1605+ if (tupleDescriptor -> tdhasoid )/* else leave infomask = 0 */
1606+ tuple -> t_infomask = HEAP_HASOID ;
1607+
1608+ heap_fill_tuple (tupleDescriptor ,
1609+ values ,
1610+ isnull ,
1611+ (char * )tuple + hoff ,
1612+ & tuple -> t_infomask ,
1613+ (hasnull ?tuple -> t_bits :NULL ));
1614+
1615+ return tuple ;
1616+ }
1617+
1618+ /*
1619+ * heap_free_minimal_tuple
1620+ */
1621+ void
1622+ heap_free_minimal_tuple (MinimalTuple mtup )
1623+ {
1624+ pfree (mtup );
1625+ }
1626+
1627+ /*
1628+ * heap_copy_minimal_tuple
1629+ *copy a MinimalTuple
1630+ *
1631+ * The result is allocated in the current memory context.
1632+ */
1633+ MinimalTuple
1634+ heap_copy_minimal_tuple (MinimalTuple mtup )
1635+ {
1636+ MinimalTuple result ;
1637+
1638+ result = (MinimalTuple )palloc (mtup -> t_len );
1639+ memcpy (result ,mtup ,mtup -> t_len );
1640+ return result ;
1641+ }
1642+
1643+ /*
1644+ * heap_tuple_from_minimal_tuple
1645+ *create a HeapTuple by copying from a MinimalTuple;
1646+ *system columns are filled with zeroes
1647+ *
1648+ * The result is allocated in the current memory context.
1649+ * The HeapTuple struct, tuple header, and tuple data are all allocated
1650+ * as a single palloc() block.
1651+ */
1652+ HeapTuple
1653+ heap_tuple_from_minimal_tuple (MinimalTuple mtup )
1654+ {
1655+ HeapTuple result ;
1656+ uint32 len = mtup -> t_len + MINIMAL_TUPLE_OFFSET ;
1657+
1658+ result = (HeapTuple )palloc (HEAPTUPLESIZE + len );
1659+ result -> t_len = len ;
1660+ ItemPointerSetInvalid (& (result -> t_self ));
1661+ result -> t_tableOid = InvalidOid ;
1662+ result -> t_data = (HeapTupleHeader ) ((char * )result + HEAPTUPLESIZE );
1663+ memcpy ((char * )result -> t_data + MINIMAL_TUPLE_OFFSET ,mtup ,mtup -> t_len );
1664+ memset (result -> t_data ,0 , offsetof(HeapTupleHeaderData ,t_natts ));
1665+ return result ;
1666+ }
1667+
1668+ /*
1669+ * minimal_tuple_from_heap_tuple
1670+ *create a MinimalTuple by copying from a HeapTuple
1671+ *
1672+ * The result is allocated in the current memory context.
1673+ */
1674+ MinimalTuple
1675+ minimal_tuple_from_heap_tuple (HeapTuple htup )
1676+ {
1677+ MinimalTuple result ;
1678+ uint32 len ;
1679+
1680+ Assert (htup -> t_len > MINIMAL_TUPLE_OFFSET );
1681+ len = htup -> t_len - MINIMAL_TUPLE_OFFSET ;
1682+ result = (MinimalTuple )palloc (len );
1683+ memcpy (result , (char * )htup -> t_data + MINIMAL_TUPLE_OFFSET ,len );
1684+ result -> t_len = len ;
1685+ return result ;
1686+ }
1687+
1688+
15191689/* ----------------
15201690 *heap_addheader
15211691 *