{"kind": "storage", "major": "18", "item": {"slug": "tuple-layout", "name": "Table row layout", "name_zh": "", "category": "Physical structures", "summary": "Physical row headers, null bitmap, alignment and column data.", "aliases": [], "content_hash": "d5a72f482bf43cb255bd9db27433f977d58f113d28d0d3a7d6a571464b14dda2", "versions": {"11": {"facts": [], "tables": [{"key": "layout-2", "rows": [{"c0": "t_xmin", "c1": "TransactionId", "c2": "4 bytes", "c3": "insert XID stamp"}, {"c0": "t_xmax", "c1": "TransactionId", "c2": "4 bytes", "c3": "delete XID stamp"}, {"c0": "t_cid", "c1": "CommandId", "c2": "4 bytes", "c3": "insert and/or delete CID stamp (overlays with t_xvac)"}, {"c0": "t_xvac", "c1": "TransactionId", "c2": "4 bytes", "c3": "XID for VACUUM operation moving a row version"}, {"c0": "t_ctid", "c1": "ItemPointerData", "c2": "6 bytes", "c3": "current TID of this or newer row version"}, {"c0": "t_infomask2", "c1": "uint16", "c2": "2 bytes", "c3": "number of attributes, plus various flag bits"}, {"c0": "t_infomask", "c1": "uint16", "c2": "2 bytes", "c3": "various flag bits"}, {"c0": "t_hoff", "c1": "uint8", "c2": "1 byte", "c3": "offset to user data"}], "title": "HeapTupleHeaderData Layout", "columns": [{"key": "c0", "label": "Field"}, {"key": "c1", "label": "Type"}, {"key": "c2", "label": "Length"}, {"key": "c3", "label": "Description"}]}], "related": [], "release": {"ref": "https://ftp.postgresql.org/pub/source/v11.22/postgresql-11.22.tar.bz2", "label": "11.22", "major": "11", "channel": "stable", "revision": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0"}, "sources": [{"url": "/docs/11/storage-page-layout.html#STORAGE-TUPLE-LAYOUT", "path": "storage-page-layout.html", "label": "PostgreSQL 11 English manual", "sha256": "89ae53d52323261bb09214babd110c76bde78e92234cbea4a8e51c5548a1073b"}], "sections": [], "signature": "", "description": ["Physical row headers, null bitmap, alignment and column data."], "manual_html": "<div class=\"sect2\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">69.6.1.\u00a0Table Row Layout</h3>\n</div>\n</div>\n</div>\n<p>All table rows are structured in the same way. There is a fixed-size header (occupying 23 bytes on most machines), followed by an optional null bitmap, an optional object ID field, and the user data. The header is detailed in <a class=\"xref\" href=\"/docs/11/storage-page-layout.html#HEAPTUPLEHEADERDATA-TABLE\" title=\"Table\u00a069.4.\u00a0HeapTupleHeaderData Layout\">Table\u00a069.4</a>. The actual user data (columns of the row) begins at the offset indicated by <code class=\"structfield\">t_hoff</code>, which must always be a multiple of the MAXALIGN distance for the platform. The null bitmap is only present if the <em class=\"firstterm\">HEAP_HASNULL</em> bit is set in <code class=\"structfield\">t_infomask</code>. If it is present it begins just after the fixed header and occupies enough bytes to have one bit per data column (that is, <code class=\"structfield\">t_natts</code> bits altogether). In this list of bits, a 1 bit indicates not-null, a 0 bit is a null. When the bitmap is not present, all columns are assumed not-null. The object ID is only present if the <em class=\"firstterm\">HEAP_HASOID</em> bit is set in <code class=\"structfield\">t_infomask</code>. If present, it appears just before the <code class=\"structfield\">t_hoff</code> boundary. Any padding needed to make <code class=\"structfield\">t_hoff</code> a MAXALIGN multiple will appear between the null bitmap and the object ID. (This in turn ensures that the object ID is suitably aligned.)</p>\n<div class=\"table\">\n<p class=\"title\"><strong>Table\u00a069.4.\u00a0HeapTupleHeaderData Layout</strong></p>\n<div class=\"table-contents\">\n<table class=\"table\">\n\n\n\n\n\n\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Length</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>t_xmin</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>insert XID stamp</td>\n</tr>\n<tr>\n<td>t_xmax</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>delete XID stamp</td>\n</tr>\n<tr>\n<td>t_cid</td>\n<td>CommandId</td>\n<td>4 bytes</td>\n<td>insert and/or delete CID stamp (overlays with t_xvac)</td>\n</tr>\n<tr>\n<td>t_xvac</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>XID for VACUUM operation moving a row version</td>\n</tr>\n<tr>\n<td>t_ctid</td>\n<td>ItemPointerData</td>\n<td>6 bytes</td>\n<td>current TID of this or newer row version</td>\n</tr>\n<tr>\n<td>t_infomask2</td>\n<td>uint16</td>\n<td>2 bytes</td>\n<td>number of attributes, plus various flag bits</td>\n</tr>\n<tr>\n<td>t_infomask</td>\n<td>uint16</td>\n<td>2 bytes</td>\n<td>various flag bits</td>\n</tr>\n<tr>\n<td>t_hoff</td>\n<td>uint8</td>\n<td>1 byte</td>\n<td>offset to user data</td>\n</tr>\n</tbody>\n</table>\n</div>\n</div><br class=\"table-break\">\n<p>All the details can be found in <code class=\"filename\">src/include/access/htup_details.h</code>.</p>\n<p>Interpreting the actual data can only be done with information obtained from other tables, mostly <code class=\"structname\">pg_attribute</code>. The key values needed to identify field locations are <code class=\"structfield\">attlen</code> and <code class=\"structfield\">attalign</code>. There is no way to directly get a particular attribute, except when there are only fixed width fields and no null values. All this trickery is wrapped up in the functions <em class=\"firstterm\">heap_getattr</em>, <em class=\"firstterm\">fastgetattr</em> and <em class=\"firstterm\">heap_getsysattr</em>.</p>\n<p>To read the data you need to examine each attribute in turn. First check whether the field is NULL according to the null bitmap. If it is, go to the next. Then make sure you have the right alignment. If the field is a fixed width field, then all the bytes are simply placed. If it's a variable length field (attlen = -1) then it's a bit more complicated. All variable-length data types share the common header structure <code class=\"type\">struct varlena</code>, which includes the total length of the stored value and some flag bits. Depending on the flags, the data can be either inline or in a TOAST table; it might be compressed, too (see <a class=\"xref\" href=\"/docs/11/storage-toast.html\" title=\"69.2.\u00a0TOAST\">Section\u00a069.2</a>).</p>\n</div>", "manual_path": "/docs/11/storage-page-layout.html", "comparison_data": {"layouts": [{"key": "layout-2", "rows": [{"c0": "t_xmin", "c1": "TransactionId", "c2": "4 bytes", "c3": "insert XID stamp"}, {"c0": "t_xmax", "c1": "TransactionId", "c2": "4 bytes", "c3": "delete XID stamp"}, {"c0": "t_cid", "c1": "CommandId", "c2": "4 bytes", "c3": "insert and/or delete CID stamp (overlays with t_xvac)"}, {"c0": "t_xvac", "c1": "TransactionId", "c2": "4 bytes", "c3": "XID for VACUUM operation moving a row version"}, {"c0": "t_ctid", "c1": "ItemPointerData", "c2": "6 bytes", "c3": "current TID of this or newer row version"}, {"c0": "t_infomask2", "c1": "uint16", "c2": "2 bytes", "c3": "number of attributes, plus various flag bits"}, {"c0": "t_infomask", "c1": "uint16", "c2": "2 bytes", "c3": "various flag bits"}, {"c0": "t_hoff", "c1": "uint8", "c2": "1 byte", "c3": "offset to user data"}], "title": "HeapTupleHeaderData Layout", "columns": [{"key": "c0", "label": "Field"}, {"key": "c1", "label": "Type"}, {"key": "c2", "label": "Length"}, {"key": "c3", "label": "Description"}]}]}, "comparison_hash": "7f6e968716966dae8869d6c14f0a6aa229d745d4d4bde899b61eeec58c8d7ea0"}, "12": {"facts": [], "tables": [{"key": "layout-2", "rows": [{"c0": "t_xmin", "c1": "TransactionId", "c2": "4 bytes", "c3": "insert XID stamp"}, {"c0": "t_xmax", "c1": "TransactionId", "c2": "4 bytes", "c3": "delete XID stamp"}, {"c0": "t_cid", "c1": "CommandId", "c2": "4 bytes", "c3": "insert and/or delete CID stamp (overlays with t_xvac)"}, {"c0": "t_xvac", "c1": "TransactionId", "c2": "4 bytes", "c3": "XID for VACUUM operation moving a row version"}, {"c0": "t_ctid", "c1": "ItemPointerData", "c2": "6 bytes", "c3": "current TID of this or newer row version"}, {"c0": "t_infomask2", "c1": "uint16", "c2": "2 bytes", "c3": "number of attributes, plus various flag bits"}, {"c0": "t_infomask", "c1": "uint16", "c2": "2 bytes", "c3": "various flag bits"}, {"c0": "t_hoff", "c1": "uint8", "c2": "1 byte", "c3": "offset to user data"}], "title": "HeapTupleHeaderData Layout", "columns": [{"key": "c0", "label": "Field"}, {"key": "c1", "label": "Type"}, {"key": "c2", "label": "Length"}, {"key": "c3", "label": "Description"}]}], "related": [], "release": {"ref": "https://ftp.postgresql.org/pub/source/v12.22/postgresql-12.22.tar.bz2", "label": "12.22", "major": "12", "channel": "stable", "revision": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b"}, "sources": [{"url": "/docs/12/storage-page-layout.html#STORAGE-TUPLE-LAYOUT", "path": "storage-page-layout.html", "label": "PostgreSQL 12 English manual", "sha256": "f485389ef7d0b5fd0a2ba4d0199308aac99fa413f8bdca01c3dab726841ee224"}], "sections": [], "signature": "", "description": ["Physical row headers, null bitmap, alignment and column data."], "manual_html": "<div class=\"sect2\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">69.6.1.\u00a0Table Row Layout</h3>\n</div>\n</div>\n</div>\n<p>All table rows are structured in the same way. There is a fixed-size header (occupying 23 bytes on most machines), followed by an optional null bitmap, an optional object ID field, and the user data. The header is detailed in <a class=\"xref\" href=\"/docs/12/storage-page-layout.html#HEAPTUPLEHEADERDATA-TABLE\" title=\"Table\u00a069.4.\u00a0HeapTupleHeaderData Layout\">Table\u00a069.4</a>. The actual user data (columns of the row) begins at the offset indicated by <code class=\"structfield\">t_hoff</code>, which must always be a multiple of the MAXALIGN distance for the platform. The null bitmap is only present if the <em class=\"firstterm\">HEAP_HASNULL</em> bit is set in <code class=\"structfield\">t_infomask</code>. If it is present it begins just after the fixed header and occupies enough bytes to have one bit per data column (that is, the number of bits that equals the attribute count in <code class=\"structfield\">t_infomask2</code>). In this list of bits, a 1 bit indicates not-null, a 0 bit is a null. When the bitmap is not present, all columns are assumed not-null. The object ID is only present if the <em class=\"firstterm\">HEAP_HASOID_OLD</em> bit is set in <code class=\"structfield\">t_infomask</code>. If present, it appears just before the <code class=\"structfield\">t_hoff</code> boundary. Any padding needed to make <code class=\"structfield\">t_hoff</code> a MAXALIGN multiple will appear between the null bitmap and the object ID. (This in turn ensures that the object ID is suitably aligned.)</p>\n<div class=\"table\">\n<p class=\"title\"><strong>Table\u00a069.4.\u00a0HeapTupleHeaderData Layout</strong></p>\n<div class=\"table-contents\">\n<table class=\"table\">\n\n\n\n\n\n\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Length</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>t_xmin</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>insert XID stamp</td>\n</tr>\n<tr>\n<td>t_xmax</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>delete XID stamp</td>\n</tr>\n<tr>\n<td>t_cid</td>\n<td>CommandId</td>\n<td>4 bytes</td>\n<td>insert and/or delete CID stamp (overlays with t_xvac)</td>\n</tr>\n<tr>\n<td>t_xvac</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>XID for VACUUM operation moving a row version</td>\n</tr>\n<tr>\n<td>t_ctid</td>\n<td>ItemPointerData</td>\n<td>6 bytes</td>\n<td>current TID of this or newer row version</td>\n</tr>\n<tr>\n<td>t_infomask2</td>\n<td>uint16</td>\n<td>2 bytes</td>\n<td>number of attributes, plus various flag bits</td>\n</tr>\n<tr>\n<td>t_infomask</td>\n<td>uint16</td>\n<td>2 bytes</td>\n<td>various flag bits</td>\n</tr>\n<tr>\n<td>t_hoff</td>\n<td>uint8</td>\n<td>1 byte</td>\n<td>offset to user data</td>\n</tr>\n</tbody>\n</table>\n</div>\n</div><br class=\"table-break\">\n<p>All the details can be found in <code class=\"filename\">src/include/access/htup_details.h</code>.</p>\n<p>Interpreting the actual data can only be done with information obtained from other tables, mostly <code class=\"structname\">pg_attribute</code>. The key values needed to identify field locations are <code class=\"structfield\">attlen</code> and <code class=\"structfield\">attalign</code>. There is no way to directly get a particular attribute, except when there are only fixed width fields and no null values. All this trickery is wrapped up in the functions <em class=\"firstterm\">heap_getattr</em>, <em class=\"firstterm\">fastgetattr</em> and <em class=\"firstterm\">heap_getsysattr</em>.</p>\n<p>To read the data you need to examine each attribute in turn. First check whether the field is NULL according to the null bitmap. If it is, go to the next. Then make sure you have the right alignment. If the field is a fixed width field, then all the bytes are simply placed. If it's a variable length field (attlen = -1) then it's a bit more complicated. All variable-length data types share the common header structure <code class=\"type\">struct varlena</code>, which includes the total length of the stored value and some flag bits. Depending on the flags, the data can be either inline or in a TOAST table; it might be compressed, too (see <a class=\"xref\" href=\"/docs/12/storage-toast.html\" title=\"69.2.\u00a0TOAST\">Section\u00a069.2</a>).</p>\n</div>", "manual_path": "/docs/12/storage-page-layout.html", "comparison_data": {"layouts": [{"key": "layout-2", "rows": [{"c0": "t_xmin", "c1": "TransactionId", "c2": "4 bytes", "c3": "insert XID stamp"}, {"c0": "t_xmax", "c1": "TransactionId", "c2": "4 bytes", "c3": "delete XID stamp"}, {"c0": "t_cid", "c1": "CommandId", "c2": "4 bytes", "c3": "insert and/or delete CID stamp (overlays with t_xvac)"}, {"c0": "t_xvac", "c1": "TransactionId", "c2": "4 bytes", "c3": "XID for VACUUM operation moving a row version"}, {"c0": "t_ctid", "c1": "ItemPointerData", "c2": "6 bytes", "c3": "current TID of this or newer row version"}, {"c0": "t_infomask2", "c1": "uint16", "c2": "2 bytes", "c3": "number of attributes, plus various flag bits"}, {"c0": "t_infomask", "c1": "uint16", "c2": "2 bytes", "c3": "various flag bits"}, {"c0": "t_hoff", "c1": "uint8", "c2": "1 byte", "c3": "offset to user data"}], "title": "HeapTupleHeaderData Layout", "columns": [{"key": "c0", "label": "Field"}, {"key": "c1", "label": "Type"}, {"key": "c2", "label": "Length"}, {"key": "c3", "label": "Description"}]}]}, "comparison_hash": "7f6e968716966dae8869d6c14f0a6aa229d745d4d4bde899b61eeec58c8d7ea0"}, "13": {"facts": [], "tables": [{"key": "layout-2", "rows": [{"c0": "t_xmin", "c1": "TransactionId", "c2": "4 bytes", "c3": "insert XID stamp"}, {"c0": "t_xmax", "c1": "TransactionId", "c2": "4 bytes", "c3": "delete XID stamp"}, {"c0": "t_cid", "c1": "CommandId", "c2": "4 bytes", "c3": "insert and/or delete CID stamp (overlays with t_xvac)"}, {"c0": "t_xvac", "c1": "TransactionId", "c2": "4 bytes", "c3": "XID for VACUUM operation moving a row version"}, {"c0": "t_ctid", "c1": "ItemPointerData", "c2": "6 bytes", "c3": "current TID of this or newer row version"}, {"c0": "t_infomask2", "c1": "uint16", "c2": "2 bytes", "c3": "number of attributes, plus various flag bits"}, {"c0": "t_infomask", "c1": "uint16", "c2": "2 bytes", "c3": "various flag bits"}, {"c0": "t_hoff", "c1": "uint8", "c2": "1 byte", "c3": "offset to user data"}], "title": "HeapTupleHeaderData Layout", "columns": [{"key": "c0", "label": "Field"}, {"key": "c1", "label": "Type"}, {"key": "c2", "label": "Length"}, {"key": "c3", "label": "Description"}]}], "related": [], "release": {"ref": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "label": "13.23", "major": "13", "channel": "stable", "revision": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}, "sources": [{"url": "/docs/13/storage-page-layout.html#STORAGE-TUPLE-LAYOUT", "path": "storage-page-layout.html", "label": "PostgreSQL 13 English manual", "sha256": "80fe3b574871fad132942884c7d87a14369d6abc77a38aba7ba3fa84abca6a37"}], "sections": [], "signature": "", "description": ["Physical row headers, null bitmap, alignment and column data."], "manual_html": "<div class=\"sect2\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">69.6.1.\u00a0Table Row Layout</h3>\n</div>\n</div>\n</div>\n<p>All table rows are structured in the same way. There is a fixed-size header (occupying 23 bytes on most machines), followed by an optional null bitmap, an optional object ID field, and the user data. The header is detailed in <a class=\"xref\" href=\"/docs/13/storage-page-layout.html#HEAPTUPLEHEADERDATA-TABLE\" title=\"Table\u00a069.4.\u00a0HeapTupleHeaderData Layout\">Table\u00a069.4</a>. The actual user data (columns of the row) begins at the offset indicated by <code class=\"structfield\">t_hoff</code>, which must always be a multiple of the MAXALIGN distance for the platform. The null bitmap is only present if the <em class=\"firstterm\">HEAP_HASNULL</em> bit is set in <code class=\"structfield\">t_infomask</code>. If it is present it begins just after the fixed header and occupies enough bytes to have one bit per data column (that is, the number of bits that equals the attribute count in <code class=\"structfield\">t_infomask2</code>). In this list of bits, a 1 bit indicates not-null, a 0 bit is a null. When the bitmap is not present, all columns are assumed not-null. The object ID is only present if the <em class=\"firstterm\">HEAP_HASOID_OLD</em> bit is set in <code class=\"structfield\">t_infomask</code>. If present, it appears just before the <code class=\"structfield\">t_hoff</code> boundary. Any padding needed to make <code class=\"structfield\">t_hoff</code> a MAXALIGN multiple will appear between the null bitmap and the object ID. (This in turn ensures that the object ID is suitably aligned.)</p>\n<div class=\"table\">\n<p class=\"title\"><strong>Table\u00a069.4.\u00a0HeapTupleHeaderData Layout</strong></p>\n<div class=\"table-contents\">\n<table class=\"table\">\n\n\n\n\n\n\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Length</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>t_xmin</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>insert XID stamp</td>\n</tr>\n<tr>\n<td>t_xmax</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>delete XID stamp</td>\n</tr>\n<tr>\n<td>t_cid</td>\n<td>CommandId</td>\n<td>4 bytes</td>\n<td>insert and/or delete CID stamp (overlays with t_xvac)</td>\n</tr>\n<tr>\n<td>t_xvac</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>XID for VACUUM operation moving a row version</td>\n</tr>\n<tr>\n<td>t_ctid</td>\n<td>ItemPointerData</td>\n<td>6 bytes</td>\n<td>current TID of this or newer row version</td>\n</tr>\n<tr>\n<td>t_infomask2</td>\n<td>uint16</td>\n<td>2 bytes</td>\n<td>number of attributes, plus various flag bits</td>\n</tr>\n<tr>\n<td>t_infomask</td>\n<td>uint16</td>\n<td>2 bytes</td>\n<td>various flag bits</td>\n</tr>\n<tr>\n<td>t_hoff</td>\n<td>uint8</td>\n<td>1 byte</td>\n<td>offset to user data</td>\n</tr>\n</tbody>\n</table>\n</div>\n</div><br class=\"table-break\">\n<p>All the details can be found in <code class=\"filename\">src/include/access/htup_details.h</code>.</p>\n<p>Interpreting the actual data can only be done with information obtained from other tables, mostly <code class=\"structname\">pg_attribute</code>. The key values needed to identify field locations are <code class=\"structfield\">attlen</code> and <code class=\"structfield\">attalign</code>. There is no way to directly get a particular attribute, except when there are only fixed width fields and no null values. All this trickery is wrapped up in the functions <em class=\"firstterm\">heap_getattr</em>, <em class=\"firstterm\">fastgetattr</em> and <em class=\"firstterm\">heap_getsysattr</em>.</p>\n<p>To read the data you need to examine each attribute in turn. First check whether the field is NULL according to the null bitmap. If it is, go to the next. Then make sure you have the right alignment. If the field is a fixed width field, then all the bytes are simply placed. If it's a variable length field (attlen = -1) then it's a bit more complicated. All variable-length data types share the common header structure <code class=\"type\">struct varlena</code>, which includes the total length of the stored value and some flag bits. Depending on the flags, the data can be either inline or in a TOAST table; it might be compressed, too (see <a class=\"xref\" href=\"/docs/13/storage-toast.html\" title=\"69.2.\u00a0TOAST\">Section\u00a069.2</a>).</p>\n</div>", "manual_path": "/docs/13/storage-page-layout.html", "comparison_data": {"layouts": [{"key": "layout-2", "rows": [{"c0": "t_xmin", "c1": "TransactionId", "c2": "4 bytes", "c3": "insert XID stamp"}, {"c0": "t_xmax", "c1": "TransactionId", "c2": "4 bytes", "c3": "delete XID stamp"}, {"c0": "t_cid", "c1": "CommandId", "c2": "4 bytes", "c3": "insert and/or delete CID stamp (overlays with t_xvac)"}, {"c0": "t_xvac", "c1": "TransactionId", "c2": "4 bytes", "c3": "XID for VACUUM operation moving a row version"}, {"c0": "t_ctid", "c1": "ItemPointerData", "c2": "6 bytes", "c3": "current TID of this or newer row version"}, {"c0": "t_infomask2", "c1": "uint16", "c2": "2 bytes", "c3": "number of attributes, plus various flag bits"}, {"c0": "t_infomask", "c1": "uint16", "c2": "2 bytes", "c3": "various flag bits"}, {"c0": "t_hoff", "c1": "uint8", "c2": "1 byte", "c3": "offset to user data"}], "title": "HeapTupleHeaderData Layout", "columns": [{"key": "c0", "label": "Field"}, {"key": "c1", "label": "Type"}, {"key": "c2", "label": "Length"}, {"key": "c3", "label": "Description"}]}]}, "comparison_hash": "7f6e968716966dae8869d6c14f0a6aa229d745d4d4bde899b61eeec58c8d7ea0"}, "14": {"facts": [], "tables": [{"key": "layout-2", "rows": [{"c0": "t_xmin", "c1": "TransactionId", "c2": "4 bytes", "c3": "insert XID stamp"}, {"c0": "t_xmax", "c1": "TransactionId", "c2": "4 bytes", "c3": "delete XID stamp"}, {"c0": "t_cid", "c1": "CommandId", "c2": "4 bytes", "c3": "insert and/or delete CID stamp (overlays with t_xvac)"}, {"c0": "t_xvac", "c1": "TransactionId", "c2": "4 bytes", "c3": "XID for VACUUM operation moving a row version"}, {"c0": "t_ctid", "c1": "ItemPointerData", "c2": "6 bytes", "c3": "current TID of this or newer row version"}, {"c0": "t_infomask2", "c1": "uint16", "c2": "2 bytes", "c3": "number of attributes, plus various flag bits"}, {"c0": "t_infomask", "c1": "uint16", "c2": "2 bytes", "c3": "various flag bits"}, {"c0": "t_hoff", "c1": "uint8", "c2": "1 byte", "c3": "offset to user data"}], "title": "HeapTupleHeaderData Layout", "columns": [{"key": "c0", "label": "Field"}, {"key": "c1", "label": "Type"}, {"key": "c2", "label": "Length"}, {"key": "c3", "label": "Description"}]}], "related": [], "release": {"ref": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "label": "14.24", "major": "14", "channel": "stable", "revision": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}, "sources": [{"url": "/docs/14/storage-page-layout.html#STORAGE-TUPLE-LAYOUT", "path": "storage-page-layout.html", "label": "PostgreSQL 14 English manual", "sha256": "0086151fad97655a71308a5389066374e3e178c423cb855b4084e7a2c3b078c5"}], "sections": [], "signature": "", "description": ["Physical row headers, null bitmap, alignment and column data."], "manual_html": "<div class=\"sect2\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">70.6.1.\u00a0Table Row Layout</h3>\n</div>\n</div>\n</div>\n<p>All table rows are structured in the same way. There is a fixed-size header (occupying 23 bytes on most machines), followed by an optional null bitmap, an optional object ID field, and the user data. The header is detailed in <a class=\"xref\" href=\"/docs/14/storage-page-layout.html#HEAPTUPLEHEADERDATA-TABLE\" title=\"Table\u00a070.4.\u00a0HeapTupleHeaderData Layout\">Table\u00a070.4</a>. The actual user data (columns of the row) begins at the offset indicated by <code class=\"structfield\">t_hoff</code>, which must always be a multiple of the MAXALIGN distance for the platform. The null bitmap is only present if the <em class=\"firstterm\">HEAP_HASNULL</em> bit is set in <code class=\"structfield\">t_infomask</code>. If it is present it begins just after the fixed header and occupies enough bytes to have one bit per data column (that is, the number of bits that equals the attribute count in <code class=\"structfield\">t_infomask2</code>). In this list of bits, a 1 bit indicates not-null, a 0 bit is a null. When the bitmap is not present, all columns are assumed not-null. The object ID is only present if the <em class=\"firstterm\">HEAP_HASOID_OLD</em> bit is set in <code class=\"structfield\">t_infomask</code>. If present, it appears just before the <code class=\"structfield\">t_hoff</code> boundary. Any padding needed to make <code class=\"structfield\">t_hoff</code> a MAXALIGN multiple will appear between the null bitmap and the object ID. (This in turn ensures that the object ID is suitably aligned.)</p>\n<div class=\"table\">\n<p class=\"title\"><strong>Table\u00a070.4.\u00a0HeapTupleHeaderData Layout</strong></p>\n<div class=\"table-contents\">\n<table class=\"table\">\n\n\n\n\n\n\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Length</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>t_xmin</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>insert XID stamp</td>\n</tr>\n<tr>\n<td>t_xmax</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>delete XID stamp</td>\n</tr>\n<tr>\n<td>t_cid</td>\n<td>CommandId</td>\n<td>4 bytes</td>\n<td>insert and/or delete CID stamp (overlays with t_xvac)</td>\n</tr>\n<tr>\n<td>t_xvac</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>XID for VACUUM operation moving a row version</td>\n</tr>\n<tr>\n<td>t_ctid</td>\n<td>ItemPointerData</td>\n<td>6 bytes</td>\n<td>current TID of this or newer row version</td>\n</tr>\n<tr>\n<td>t_infomask2</td>\n<td>uint16</td>\n<td>2 bytes</td>\n<td>number of attributes, plus various flag bits</td>\n</tr>\n<tr>\n<td>t_infomask</td>\n<td>uint16</td>\n<td>2 bytes</td>\n<td>various flag bits</td>\n</tr>\n<tr>\n<td>t_hoff</td>\n<td>uint8</td>\n<td>1 byte</td>\n<td>offset to user data</td>\n</tr>\n</tbody>\n</table>\n</div>\n</div><br class=\"table-break\">\n<p>All the details can be found in <code class=\"filename\">src/include/access/htup_details.h</code>.</p>\n<p>Interpreting the actual data can only be done with information obtained from other tables, mostly <code class=\"structname\">pg_attribute</code>. The key values needed to identify field locations are <code class=\"structfield\">attlen</code> and <code class=\"structfield\">attalign</code>. There is no way to directly get a particular attribute, except when there are only fixed width fields and no null values. All this trickery is wrapped up in the functions <em class=\"firstterm\">heap_getattr</em>, <em class=\"firstterm\">fastgetattr</em> and <em class=\"firstterm\">heap_getsysattr</em>.</p>\n<p>To read the data you need to examine each attribute in turn. First check whether the field is NULL according to the null bitmap. If it is, go to the next. Then make sure you have the right alignment. If the field is a fixed width field, then all the bytes are simply placed. If it's a variable length field (attlen = -1) then it's a bit more complicated. All variable-length data types share the common header structure <code class=\"type\">struct varlena</code>, which includes the total length of the stored value and some flag bits. Depending on the flags, the data can be either inline or in a TOAST table; it might be compressed, too (see <a class=\"xref\" href=\"/docs/14/storage-toast.html\" title=\"70.2.\u00a0TOAST\">Section\u00a070.2</a>).</p>\n</div>", "manual_path": "/docs/14/storage-page-layout.html", "comparison_data": {"layouts": [{"key": "layout-2", "rows": [{"c0": "t_xmin", "c1": "TransactionId", "c2": "4 bytes", "c3": "insert XID stamp"}, {"c0": "t_xmax", "c1": "TransactionId", "c2": "4 bytes", "c3": "delete XID stamp"}, {"c0": "t_cid", "c1": "CommandId", "c2": "4 bytes", "c3": "insert and/or delete CID stamp (overlays with t_xvac)"}, {"c0": "t_xvac", "c1": "TransactionId", "c2": "4 bytes", "c3": "XID for VACUUM operation moving a row version"}, {"c0": "t_ctid", "c1": "ItemPointerData", "c2": "6 bytes", "c3": "current TID of this or newer row version"}, {"c0": "t_infomask2", "c1": "uint16", "c2": "2 bytes", "c3": "number of attributes, plus various flag bits"}, {"c0": "t_infomask", "c1": "uint16", "c2": "2 bytes", "c3": "various flag bits"}, {"c0": "t_hoff", "c1": "uint8", "c2": "1 byte", "c3": "offset to user data"}], "title": "HeapTupleHeaderData Layout", "columns": [{"key": "c0", "label": "Field"}, {"key": "c1", "label": "Type"}, {"key": "c2", "label": "Length"}, {"key": "c3", "label": "Description"}]}]}, "comparison_hash": "7f6e968716966dae8869d6c14f0a6aa229d745d4d4bde899b61eeec58c8d7ea0"}, "15": {"facts": [], "tables": [{"key": "layout-2", "rows": [{"c0": "t_xmin", "c1": "TransactionId", "c2": "4 bytes", "c3": "insert XID stamp"}, {"c0": "t_xmax", "c1": "TransactionId", "c2": "4 bytes", "c3": "delete XID stamp"}, {"c0": "t_cid", "c1": "CommandId", "c2": "4 bytes", "c3": "insert and/or delete CID stamp (overlays with t_xvac)"}, {"c0": "t_xvac", "c1": "TransactionId", "c2": "4 bytes", "c3": "XID for VACUUM operation moving a row version"}, {"c0": "t_ctid", "c1": "ItemPointerData", "c2": "6 bytes", "c3": "current TID of this or newer row version"}, {"c0": "t_infomask2", "c1": "uint16", "c2": "2 bytes", "c3": "number of attributes, plus various flag bits"}, {"c0": "t_infomask", "c1": "uint16", "c2": "2 bytes", "c3": "various flag bits"}, {"c0": "t_hoff", "c1": "uint8", "c2": "1 byte", "c3": "offset to user data"}], "title": "HeapTupleHeaderData Layout", "columns": [{"key": "c0", "label": "Field"}, {"key": "c1", "label": "Type"}, {"key": "c2", "label": "Length"}, {"key": "c3", "label": "Description"}]}], "related": [], "release": {"ref": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "label": "15.19", "major": "15", "channel": "stable", "revision": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}, "sources": [{"url": "/docs/15/storage-page-layout.html#STORAGE-TUPLE-LAYOUT", "path": "storage-page-layout.html", "label": "PostgreSQL 15 English manual", "sha256": "88f0ede4c4e120bd501055521215dd74f073965c658098e4b694f28e5fb427b5"}], "sections": [], "signature": "", "description": ["Physical row headers, null bitmap, alignment and column data."], "manual_html": "<div class=\"sect2\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">73.6.1.\u00a0Table Row Layout</h3>\n</div>\n</div>\n</div>\n<p>All table rows are structured in the same way. There is a fixed-size header (occupying 23 bytes on most machines), followed by an optional null bitmap, an optional object ID field, and the user data. The header is detailed in <a class=\"xref\" href=\"/docs/15/storage-page-layout.html#HEAPTUPLEHEADERDATA-TABLE\" title=\"Table\u00a073.4.\u00a0HeapTupleHeaderData Layout\">Table\u00a073.4</a>. The actual user data (columns of the row) begins at the offset indicated by <code class=\"structfield\">t_hoff</code>, which must always be a multiple of the MAXALIGN distance for the platform. The null bitmap is only present if the <em class=\"firstterm\">HEAP_HASNULL</em> bit is set in <code class=\"structfield\">t_infomask</code>. If it is present it begins just after the fixed header and occupies enough bytes to have one bit per data column (that is, the number of bits that equals the attribute count in <code class=\"structfield\">t_infomask2</code>). In this list of bits, a 1 bit indicates not-null, a 0 bit is a null. When the bitmap is not present, all columns are assumed not-null. The object ID is only present if the <em class=\"firstterm\">HEAP_HASOID_OLD</em> bit is set in <code class=\"structfield\">t_infomask</code>. If present, it appears just before the <code class=\"structfield\">t_hoff</code> boundary. Any padding needed to make <code class=\"structfield\">t_hoff</code> a MAXALIGN multiple will appear between the null bitmap and the object ID. (This in turn ensures that the object ID is suitably aligned.)</p>\n<div class=\"table\">\n<p class=\"title\"><strong>Table\u00a073.4.\u00a0HeapTupleHeaderData Layout</strong></p>\n<div class=\"table-contents\">\n<table class=\"table\">\n\n\n\n\n\n\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Length</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>t_xmin</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>insert XID stamp</td>\n</tr>\n<tr>\n<td>t_xmax</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>delete XID stamp</td>\n</tr>\n<tr>\n<td>t_cid</td>\n<td>CommandId</td>\n<td>4 bytes</td>\n<td>insert and/or delete CID stamp (overlays with t_xvac)</td>\n</tr>\n<tr>\n<td>t_xvac</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>XID for VACUUM operation moving a row version</td>\n</tr>\n<tr>\n<td>t_ctid</td>\n<td>ItemPointerData</td>\n<td>6 bytes</td>\n<td>current TID of this or newer row version</td>\n</tr>\n<tr>\n<td>t_infomask2</td>\n<td>uint16</td>\n<td>2 bytes</td>\n<td>number of attributes, plus various flag bits</td>\n</tr>\n<tr>\n<td>t_infomask</td>\n<td>uint16</td>\n<td>2 bytes</td>\n<td>various flag bits</td>\n</tr>\n<tr>\n<td>t_hoff</td>\n<td>uint8</td>\n<td>1 byte</td>\n<td>offset to user data</td>\n</tr>\n</tbody>\n</table>\n</div>\n</div><br class=\"table-break\">\n<p>All the details can be found in <code class=\"filename\">src/include/access/htup_details.h</code>.</p>\n<p>Interpreting the actual data can only be done with information obtained from other tables, mostly <code class=\"structname\">pg_attribute</code>. The key values needed to identify field locations are <code class=\"structfield\">attlen</code> and <code class=\"structfield\">attalign</code>. There is no way to directly get a particular attribute, except when there are only fixed width fields and no null values. All this trickery is wrapped up in the functions <em class=\"firstterm\">heap_getattr</em>, <em class=\"firstterm\">fastgetattr</em> and <em class=\"firstterm\">heap_getsysattr</em>.</p>\n<p>To read the data you need to examine each attribute in turn. First check whether the field is NULL according to the null bitmap. If it is, go to the next. Then make sure you have the right alignment. If the field is a fixed width field, then all the bytes are simply placed. If it's a variable length field (attlen = -1) then it's a bit more complicated. All variable-length data types share the common header structure <code class=\"type\">struct varlena</code>, which includes the total length of the stored value and some flag bits. Depending on the flags, the data can be either inline or in a TOAST table; it might be compressed, too (see <a class=\"xref\" href=\"/docs/15/storage-toast.html\" title=\"73.2.\u00a0TOAST\">Section\u00a073.2</a>).</p>\n</div>", "manual_path": "/docs/15/storage-page-layout.html", "comparison_data": {"layouts": [{"key": "layout-2", "rows": [{"c0": "t_xmin", "c1": "TransactionId", "c2": "4 bytes", "c3": "insert XID stamp"}, {"c0": "t_xmax", "c1": "TransactionId", "c2": "4 bytes", "c3": "delete XID stamp"}, {"c0": "t_cid", "c1": "CommandId", "c2": "4 bytes", "c3": "insert and/or delete CID stamp (overlays with t_xvac)"}, {"c0": "t_xvac", "c1": "TransactionId", "c2": "4 bytes", "c3": "XID for VACUUM operation moving a row version"}, {"c0": "t_ctid", "c1": "ItemPointerData", "c2": "6 bytes", "c3": "current TID of this or newer row version"}, {"c0": "t_infomask2", "c1": "uint16", "c2": "2 bytes", "c3": "number of attributes, plus various flag bits"}, {"c0": "t_infomask", "c1": "uint16", "c2": "2 bytes", "c3": "various flag bits"}, {"c0": "t_hoff", "c1": "uint8", "c2": "1 byte", "c3": "offset to user data"}], "title": "HeapTupleHeaderData Layout", "columns": [{"key": "c0", "label": "Field"}, {"key": "c1", "label": "Type"}, {"key": "c2", "label": "Length"}, {"key": "c3", "label": "Description"}]}]}, "comparison_hash": "7f6e968716966dae8869d6c14f0a6aa229d745d4d4bde899b61eeec58c8d7ea0"}, "16": {"facts": [], "tables": [{"key": "layout-2", "rows": [{"c0": "t_xmin", "c1": "TransactionId", "c2": "4 bytes", "c3": "insert XID stamp"}, {"c0": "t_xmax", "c1": "TransactionId", "c2": "4 bytes", "c3": "delete XID stamp"}, {"c0": "t_cid", "c1": "CommandId", "c2": "4 bytes", "c3": "insert and/or delete CID stamp (overlays with t_xvac)"}, {"c0": "t_xvac", "c1": "TransactionId", "c2": "4 bytes", "c3": "XID for VACUUM operation moving a row version"}, {"c0": "t_ctid", "c1": "ItemPointerData", "c2": "6 bytes", "c3": "current TID of this or newer row version"}, {"c0": "t_infomask2", "c1": "uint16", "c2": "2 bytes", "c3": "number of attributes, plus various flag bits"}, {"c0": "t_infomask", "c1": "uint16", "c2": "2 bytes", "c3": "various flag bits"}, {"c0": "t_hoff", "c1": "uint8", "c2": "1 byte", "c3": "offset to user data"}], "title": "HeapTupleHeaderData Layout", "columns": [{"key": "c0", "label": "Field"}, {"key": "c1", "label": "Type"}, {"key": "c2", "label": "Length"}, {"key": "c3", "label": "Description"}]}], "related": [], "release": {"ref": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "label": "16.15", "major": "16", "channel": "stable", "revision": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}, "sources": [{"url": "/docs/16/storage-page-layout.html#STORAGE-TUPLE-LAYOUT", "path": "storage-page-layout.html", "label": "PostgreSQL 16 English manual", "sha256": "8575d1a8e8bb10ffdccc043783fce8d53e59bd6e98f1cd66b3761a90d4d77c27"}], "sections": [], "signature": "", "description": ["Physical row headers, null bitmap, alignment and column data."], "manual_html": "<div class=\"sect2\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">73.6.1.\u00a0Table Row Layout </h3>\n</div>\n</div>\n</div>\n<p>All table rows are structured in the same way. There is a fixed-size header (occupying 23 bytes on most machines), followed by an optional null bitmap, an optional object ID field, and the user data. The header is detailed in <a class=\"xref\" href=\"/docs/16/storage-page-layout.html#HEAPTUPLEHEADERDATA-TABLE\" title=\"Table\u00a073.4.\u00a0HeapTupleHeaderData Layout\">Table\u00a073.4</a>. The actual user data (columns of the row) begins at the offset indicated by <code class=\"structfield\">t_hoff</code>, which must always be a multiple of the MAXALIGN distance for the platform. The null bitmap is only present if the <em class=\"firstterm\">HEAP_HASNULL</em> bit is set in <code class=\"structfield\">t_infomask</code>. If it is present it begins just after the fixed header and occupies enough bytes to have one bit per data column (that is, the number of bits that equals the attribute count in <code class=\"structfield\">t_infomask2</code>). In this list of bits, a 1 bit indicates not-null, a 0 bit is a null. When the bitmap is not present, all columns are assumed not-null. The object ID is only present if the <em class=\"firstterm\">HEAP_HASOID_OLD</em> bit is set in <code class=\"structfield\">t_infomask</code>. If present, it appears just before the <code class=\"structfield\">t_hoff</code> boundary. Any padding needed to make <code class=\"structfield\">t_hoff</code> a MAXALIGN multiple will appear between the null bitmap and the object ID. (This in turn ensures that the object ID is suitably aligned.)</p>\n<div class=\"table\">\n<p class=\"title\"><strong>Table\u00a073.4.\u00a0HeapTupleHeaderData Layout</strong></p>\n<div class=\"table-contents\">\n<table class=\"table\">\n\n\n\n\n\n\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Length</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>t_xmin</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>insert XID stamp</td>\n</tr>\n<tr>\n<td>t_xmax</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>delete XID stamp</td>\n</tr>\n<tr>\n<td>t_cid</td>\n<td>CommandId</td>\n<td>4 bytes</td>\n<td>insert and/or delete CID stamp (overlays with t_xvac)</td>\n</tr>\n<tr>\n<td>t_xvac</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>XID for VACUUM operation moving a row version</td>\n</tr>\n<tr>\n<td>t_ctid</td>\n<td>ItemPointerData</td>\n<td>6 bytes</td>\n<td>current TID of this or newer row version</td>\n</tr>\n<tr>\n<td>t_infomask2</td>\n<td>uint16</td>\n<td>2 bytes</td>\n<td>number of attributes, plus various flag bits</td>\n</tr>\n<tr>\n<td>t_infomask</td>\n<td>uint16</td>\n<td>2 bytes</td>\n<td>various flag bits</td>\n</tr>\n<tr>\n<td>t_hoff</td>\n<td>uint8</td>\n<td>1 byte</td>\n<td>offset to user data</td>\n</tr>\n</tbody>\n</table>\n</div>\n</div><br class=\"table-break\">\n<p>All the details can be found in <code class=\"filename\">src/include/access/htup_details.h</code>.</p>\n<p>Interpreting the actual data can only be done with information obtained from other tables, mostly <code class=\"structname\">pg_attribute</code>. The key values needed to identify field locations are <code class=\"structfield\">attlen</code> and <code class=\"structfield\">attalign</code>. There is no way to directly get a particular attribute, except when there are only fixed width fields and no null values. All this trickery is wrapped up in the functions <em class=\"firstterm\">heap_getattr</em>, <em class=\"firstterm\">fastgetattr</em> and <em class=\"firstterm\">heap_getsysattr</em>.</p>\n<p>To read the data you need to examine each attribute in turn. First check whether the field is NULL according to the null bitmap. If it is, go to the next. Then make sure you have the right alignment. If the field is a fixed width field, then all the bytes are simply placed. If it's a variable length field (attlen = -1) then it's a bit more complicated. All variable-length data types share the common header structure <code class=\"type\">struct varlena</code>, which includes the total length of the stored value and some flag bits. Depending on the flags, the data can be either inline or in a TOAST table; it might be compressed, too (see <a class=\"xref\" href=\"/docs/16/storage-toast.html\" title=\"73.2.\u00a0TOAST\">Section\u00a073.2</a>).</p>\n</div>", "manual_path": "/docs/16/storage-page-layout.html", "comparison_data": {"layouts": [{"key": "layout-2", "rows": [{"c0": "t_xmin", "c1": "TransactionId", "c2": "4 bytes", "c3": "insert XID stamp"}, {"c0": "t_xmax", "c1": "TransactionId", "c2": "4 bytes", "c3": "delete XID stamp"}, {"c0": "t_cid", "c1": "CommandId", "c2": "4 bytes", "c3": "insert and/or delete CID stamp (overlays with t_xvac)"}, {"c0": "t_xvac", "c1": "TransactionId", "c2": "4 bytes", "c3": "XID for VACUUM operation moving a row version"}, {"c0": "t_ctid", "c1": "ItemPointerData", "c2": "6 bytes", "c3": "current TID of this or newer row version"}, {"c0": "t_infomask2", "c1": "uint16", "c2": "2 bytes", "c3": "number of attributes, plus various flag bits"}, {"c0": "t_infomask", "c1": "uint16", "c2": "2 bytes", "c3": "various flag bits"}, {"c0": "t_hoff", "c1": "uint8", "c2": "1 byte", "c3": "offset to user data"}], "title": "HeapTupleHeaderData Layout", "columns": [{"key": "c0", "label": "Field"}, {"key": "c1", "label": "Type"}, {"key": "c2", "label": "Length"}, {"key": "c3", "label": "Description"}]}]}, "comparison_hash": "7f6e968716966dae8869d6c14f0a6aa229d745d4d4bde899b61eeec58c8d7ea0"}, "17": {"facts": [], "tables": [{"key": "layout-2", "rows": [{"c0": "t_xmin", "c1": "TransactionId", "c2": "4 bytes", "c3": "insert XID stamp"}, {"c0": "t_xmax", "c1": "TransactionId", "c2": "4 bytes", "c3": "delete XID stamp"}, {"c0": "t_cid", "c1": "CommandId", "c2": "4 bytes", "c3": "insert and/or delete CID stamp (overlays with t_xvac)"}, {"c0": "t_xvac", "c1": "TransactionId", "c2": "4 bytes", "c3": "XID for VACUUM operation moving a row version"}, {"c0": "t_ctid", "c1": "ItemPointerData", "c2": "6 bytes", "c3": "current TID of this or newer row version"}, {"c0": "t_infomask2", "c1": "uint16", "c2": "2 bytes", "c3": "number of attributes, plus various flag bits"}, {"c0": "t_infomask", "c1": "uint16", "c2": "2 bytes", "c3": "various flag bits"}, {"c0": "t_hoff", "c1": "uint8", "c2": "1 byte", "c3": "offset to user data"}], "title": "HeapTupleHeaderData Layout", "columns": [{"key": "c0", "label": "Field"}, {"key": "c1", "label": "Type"}, {"key": "c2", "label": "Length"}, {"key": "c3", "label": "Description"}]}], "related": [], "release": {"ref": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "label": "17.11", "major": "17", "channel": "stable", "revision": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}, "sources": [{"url": "/docs/17/storage-page-layout.html#STORAGE-TUPLE-LAYOUT", "path": "storage-page-layout.html", "label": "PostgreSQL 17 English manual", "sha256": "4ce2b67f1bce18b942c991f7f9ea2c9e048b128ca179967c5e5ae26336262876"}], "sections": [], "signature": "", "description": ["Physical row headers, null bitmap, alignment and column data."], "manual_html": "<div class=\"sect2\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">65.6.1.\u00a0Table Row Layout </h3>\n</div>\n</div>\n</div>\n<p>All table rows are structured in the same way. There is a fixed-size header (occupying 23 bytes on most machines), followed by an optional null bitmap, an optional object ID field, and the user data. The header is detailed in <a class=\"xref\" href=\"/docs/17/storage-page-layout.html#HEAPTUPLEHEADERDATA-TABLE\" title=\"Table\u00a065.4.\u00a0HeapTupleHeaderData Layout\">Table\u00a065.4</a>. The actual user data (columns of the row) begins at the offset indicated by <code class=\"structfield\">t_hoff</code>, which must always be a multiple of the MAXALIGN distance for the platform. The null bitmap is only present if the <em class=\"firstterm\">HEAP_HASNULL</em> bit is set in <code class=\"structfield\">t_infomask</code>. If it is present it begins just after the fixed header and occupies enough bytes to have one bit per data column (that is, the number of bits that equals the attribute count in <code class=\"structfield\">t_infomask2</code>). In this list of bits, a 1 bit indicates not-null, a 0 bit is a null. When the bitmap is not present, all columns are assumed not-null. The object ID is only present if the <em class=\"firstterm\">HEAP_HASOID_OLD</em> bit is set in <code class=\"structfield\">t_infomask</code>. If present, it appears just before the <code class=\"structfield\">t_hoff</code> boundary. Any padding needed to make <code class=\"structfield\">t_hoff</code> a MAXALIGN multiple will appear between the null bitmap and the object ID. (This in turn ensures that the object ID is suitably aligned.)</p>\n<div class=\"table\">\n<p class=\"title\"><strong>Table\u00a065.4.\u00a0HeapTupleHeaderData Layout</strong></p>\n<div class=\"table-contents\">\n<table class=\"table\">\n\n\n\n\n\n\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Length</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>t_xmin</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>insert XID stamp</td>\n</tr>\n<tr>\n<td>t_xmax</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>delete XID stamp</td>\n</tr>\n<tr>\n<td>t_cid</td>\n<td>CommandId</td>\n<td>4 bytes</td>\n<td>insert and/or delete CID stamp (overlays with t_xvac)</td>\n</tr>\n<tr>\n<td>t_xvac</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>XID for VACUUM operation moving a row version</td>\n</tr>\n<tr>\n<td>t_ctid</td>\n<td>ItemPointerData</td>\n<td>6 bytes</td>\n<td>current TID of this or newer row version</td>\n</tr>\n<tr>\n<td>t_infomask2</td>\n<td>uint16</td>\n<td>2 bytes</td>\n<td>number of attributes, plus various flag bits</td>\n</tr>\n<tr>\n<td>t_infomask</td>\n<td>uint16</td>\n<td>2 bytes</td>\n<td>various flag bits</td>\n</tr>\n<tr>\n<td>t_hoff</td>\n<td>uint8</td>\n<td>1 byte</td>\n<td>offset to user data</td>\n</tr>\n</tbody>\n</table>\n</div>\n</div><br class=\"table-break\">\n<p>All the details can be found in <code class=\"filename\">src/include/access/htup_details.h</code>.</p>\n<p>Interpreting the actual data can only be done with information obtained from other tables, mostly <code class=\"structname\">pg_attribute</code>. The key values needed to identify field locations are <code class=\"structfield\">attlen</code> and <code class=\"structfield\">attalign</code>. There is no way to directly get a particular attribute, except when there are only fixed width fields and no null values. All this trickery is wrapped up in the functions <em class=\"firstterm\">heap_getattr</em>, <em class=\"firstterm\">fastgetattr</em> and <em class=\"firstterm\">heap_getsysattr</em>.</p>\n<p>To read the data you need to examine each attribute in turn. First check whether the field is NULL according to the null bitmap. If it is, go to the next. Then make sure you have the right alignment. If the field is a fixed width field, then all the bytes are simply placed. If it's a variable length field (attlen = -1) then it's a bit more complicated. All variable-length data types share the common header structure <code class=\"type\">struct varlena</code>, which includes the total length of the stored value and some flag bits. Depending on the flags, the data can be either inline or in a TOAST table; it might be compressed, too (see <a class=\"xref\" href=\"/docs/17/storage-toast.html\" title=\"65.2.\u00a0TOAST\">Section\u00a065.2</a>).</p>\n</div>", "manual_path": "/docs/17/storage-page-layout.html", "comparison_data": {"layouts": [{"key": "layout-2", "rows": [{"c0": "t_xmin", "c1": "TransactionId", "c2": "4 bytes", "c3": "insert XID stamp"}, {"c0": "t_xmax", "c1": "TransactionId", "c2": "4 bytes", "c3": "delete XID stamp"}, {"c0": "t_cid", "c1": "CommandId", "c2": "4 bytes", "c3": "insert and/or delete CID stamp (overlays with t_xvac)"}, {"c0": "t_xvac", "c1": "TransactionId", "c2": "4 bytes", "c3": "XID for VACUUM operation moving a row version"}, {"c0": "t_ctid", "c1": "ItemPointerData", "c2": "6 bytes", "c3": "current TID of this or newer row version"}, {"c0": "t_infomask2", "c1": "uint16", "c2": "2 bytes", "c3": "number of attributes, plus various flag bits"}, {"c0": "t_infomask", "c1": "uint16", "c2": "2 bytes", "c3": "various flag bits"}, {"c0": "t_hoff", "c1": "uint8", "c2": "1 byte", "c3": "offset to user data"}], "title": "HeapTupleHeaderData Layout", "columns": [{"key": "c0", "label": "Field"}, {"key": "c1", "label": "Type"}, {"key": "c2", "label": "Length"}, {"key": "c3", "label": "Description"}]}]}, "comparison_hash": "7f6e968716966dae8869d6c14f0a6aa229d745d4d4bde899b61eeec58c8d7ea0"}, "18": {"facts": [], "tables": [{"key": "layout-2", "rows": [{"c0": "t_xmin", "c1": "TransactionId", "c2": "4 bytes", "c3": "insert XID stamp"}, {"c0": "t_xmax", "c1": "TransactionId", "c2": "4 bytes", "c3": "delete XID stamp"}, {"c0": "t_cid", "c1": "CommandId", "c2": "4 bytes", "c3": "insert and/or delete CID stamp (overlays with t_xvac)"}, {"c0": "t_xvac", "c1": "TransactionId", "c2": "4 bytes", "c3": "XID for VACUUM operation moving a row version"}, {"c0": "t_ctid", "c1": "ItemPointerData", "c2": "6 bytes", "c3": "current TID of this or newer row version"}, {"c0": "t_infomask2", "c1": "uint16", "c2": "2 bytes", "c3": "number of attributes, plus various flag bits"}, {"c0": "t_infomask", "c1": "uint16", "c2": "2 bytes", "c3": "various flag bits"}, {"c0": "t_hoff", "c1": "uint8", "c2": "1 byte", "c3": "offset to user data"}], "title": "HeapTupleHeaderData Layout", "columns": [{"key": "c0", "label": "Field"}, {"key": "c1", "label": "Type"}, {"key": "c2", "label": "Length"}, {"key": "c3", "label": "Description"}]}], "related": [], "release": {"ref": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "label": "18.6", "major": "18", "channel": "stable", "revision": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, "sources": [{"url": "/docs/18/storage-page-layout.html#STORAGE-TUPLE-LAYOUT", "path": "storage-page-layout.html", "label": "PostgreSQL 18 English manual", "sha256": "0d9f99e4cef5ea0a6741a74cab87052b929f7001730853c85d5e60d72179d355"}], "sections": [], "signature": "", "description": ["Physical row headers, null bitmap, alignment and column data."], "manual_html": "<div class=\"sect2\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">66.6.1.\u00a0Table Row Layout </h3>\n</div>\n</div>\n</div>\n<p>All table rows are structured in the same way. There is a fixed-size header (occupying 23 bytes on most machines), followed by an optional null bitmap, an optional object ID field, and the user data. The header is detailed in <a class=\"xref\" href=\"/docs/18/storage-page-layout.html#HEAPTUPLEHEADERDATA-TABLE\" title=\"Table\u00a066.4.\u00a0HeapTupleHeaderData Layout\">Table\u00a066.4</a>. The actual user data (columns of the row) begins at the offset indicated by <code class=\"structfield\">t_hoff</code>, which must always be a multiple of the MAXALIGN distance for the platform. The null bitmap is only present if the <em class=\"firstterm\">HEAP_HASNULL</em> bit is set in <code class=\"structfield\">t_infomask</code>. If it is present it begins just after the fixed header and occupies enough bytes to have one bit per data column (that is, the number of bits that equals the attribute count in <code class=\"structfield\">t_infomask2</code>). In this list of bits, a 1 bit indicates not-null, a 0 bit is a null. When the bitmap is not present, all columns are assumed not-null. The object ID is only present if the <em class=\"firstterm\">HEAP_HASOID_OLD</em> bit is set in <code class=\"structfield\">t_infomask</code>. If present, it appears just before the <code class=\"structfield\">t_hoff</code> boundary. Any padding needed to make <code class=\"structfield\">t_hoff</code> a MAXALIGN multiple will appear between the null bitmap and the object ID. (This in turn ensures that the object ID is suitably aligned.)</p>\n<div class=\"table\">\n<p class=\"title\"><strong>Table\u00a066.4.\u00a0HeapTupleHeaderData Layout</strong></p>\n<div class=\"table-contents\">\n<table class=\"table\">\n\n\n\n\n\n\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Length</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>t_xmin</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>insert XID stamp</td>\n</tr>\n<tr>\n<td>t_xmax</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>delete XID stamp</td>\n</tr>\n<tr>\n<td>t_cid</td>\n<td>CommandId</td>\n<td>4 bytes</td>\n<td>insert and/or delete CID stamp (overlays with t_xvac)</td>\n</tr>\n<tr>\n<td>t_xvac</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>XID for VACUUM operation moving a row version</td>\n</tr>\n<tr>\n<td>t_ctid</td>\n<td>ItemPointerData</td>\n<td>6 bytes</td>\n<td>current TID of this or newer row version</td>\n</tr>\n<tr>\n<td>t_infomask2</td>\n<td>uint16</td>\n<td>2 bytes</td>\n<td>number of attributes, plus various flag bits</td>\n</tr>\n<tr>\n<td>t_infomask</td>\n<td>uint16</td>\n<td>2 bytes</td>\n<td>various flag bits</td>\n</tr>\n<tr>\n<td>t_hoff</td>\n<td>uint8</td>\n<td>1 byte</td>\n<td>offset to user data</td>\n</tr>\n</tbody>\n</table>\n</div>\n</div><br class=\"table-break\">\n<p>All the details can be found in <code class=\"filename\">src/include/access/htup_details.h</code>.</p>\n<p>Interpreting the actual data can only be done with information obtained from other tables, mostly <code class=\"structname\">pg_attribute</code>. The key values needed to identify field locations are <code class=\"structfield\">attlen</code> and <code class=\"structfield\">attalign</code>. There is no way to directly get a particular attribute, except when there are only fixed width fields and no null values. All this trickery is wrapped up in the functions <em class=\"firstterm\">heap_getattr</em>, <em class=\"firstterm\">fastgetattr</em> and <em class=\"firstterm\">heap_getsysattr</em>.</p>\n<p>To read the data you need to examine each attribute in turn. First check whether the field is NULL according to the null bitmap. If it is, go to the next. Then make sure you have the right alignment. If the field is a fixed width field, then all the bytes are simply placed. If it's a variable length field (attlen = -1) then it's a bit more complicated. All variable-length data types share the common header structure <code class=\"type\">struct varlena</code>, which includes the total length of the stored value and some flag bits. Depending on the flags, the data can be either inline or in a TOAST table; it might be compressed, too (see <a class=\"xref\" href=\"/docs/18/storage-toast.html\" title=\"66.2.\u00a0TOAST\">Section\u00a066.2</a>).</p>\n</div>", "manual_path": "/docs/18/storage-page-layout.html", "comparison_data": {"layouts": [{"key": "layout-2", "rows": [{"c0": "t_xmin", "c1": "TransactionId", "c2": "4 bytes", "c3": "insert XID stamp"}, {"c0": "t_xmax", "c1": "TransactionId", "c2": "4 bytes", "c3": "delete XID stamp"}, {"c0": "t_cid", "c1": "CommandId", "c2": "4 bytes", "c3": "insert and/or delete CID stamp (overlays with t_xvac)"}, {"c0": "t_xvac", "c1": "TransactionId", "c2": "4 bytes", "c3": "XID for VACUUM operation moving a row version"}, {"c0": "t_ctid", "c1": "ItemPointerData", "c2": "6 bytes", "c3": "current TID of this or newer row version"}, {"c0": "t_infomask2", "c1": "uint16", "c2": "2 bytes", "c3": "number of attributes, plus various flag bits"}, {"c0": "t_infomask", "c1": "uint16", "c2": "2 bytes", "c3": "various flag bits"}, {"c0": "t_hoff", "c1": "uint8", "c2": "1 byte", "c3": "offset to user data"}], "title": "HeapTupleHeaderData Layout", "columns": [{"key": "c0", "label": "Field"}, {"key": "c1", "label": "Type"}, {"key": "c2", "label": "Length"}, {"key": "c3", "label": "Description"}]}]}, "comparison_hash": "7f6e968716966dae8869d6c14f0a6aa229d745d4d4bde899b61eeec58c8d7ea0"}, "19": {"facts": [], "tables": [{"key": "layout-2", "rows": [{"c0": "t_xmin", "c1": "TransactionId", "c2": "4 bytes", "c3": "insert XID stamp"}, {"c0": "t_xmax", "c1": "TransactionId", "c2": "4 bytes", "c3": "delete XID stamp"}, {"c0": "t_cid", "c1": "CommandId", "c2": "4 bytes", "c3": "insert and/or delete CID stamp (overlays with t_xvac)"}, {"c0": "t_xvac", "c1": "TransactionId", "c2": "4 bytes", "c3": "XID for VACUUM operation moving a row version"}, {"c0": "t_ctid", "c1": "ItemPointerData", "c2": "6 bytes", "c3": "current TID of this or newer row version"}, {"c0": "t_infomask2", "c1": "uint16", "c2": "2 bytes", "c3": "number of attributes, plus various flag bits"}, {"c0": "t_infomask", "c1": "uint16", "c2": "2 bytes", "c3": "various flag bits"}, {"c0": "t_hoff", "c1": "uint8", "c2": "1 byte", "c3": "offset to user data"}], "title": "HeapTupleHeaderData Layout", "columns": [{"key": "c0", "label": "Field"}, {"key": "c1", "label": "Type"}, {"key": "c2", "label": "Length"}, {"key": "c3", "label": "Description"}]}], "related": [], "release": {"ref": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "label": "19beta4", "major": "19", "channel": "preview", "revision": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}, "sources": [{"url": "/docs/19/storage-page-layout.html#STORAGE-TUPLE-LAYOUT", "path": "storage-page-layout.html", "label": "PostgreSQL 19 English manual", "sha256": "4ef53402590510fe17440d51323824cca73b5cd6a17df88b2ef076c204de2126"}], "sections": [], "signature": "", "description": ["Physical row headers, null bitmap, alignment and column data."], "manual_html": "<div class=\"sect2\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">66.6.1.\u00a0Table Row Layout </h3>\n</div>\n</div>\n</div>\n<p>All table rows are structured in the same way. There is a fixed-size header (occupying 23 bytes on most machines), followed by an optional null bitmap, an optional object ID field, and the user data. The header is detailed in <a class=\"xref\" href=\"/docs/19/storage-page-layout.html#HEAPTUPLEHEADERDATA-TABLE\" title=\"Table\u00a066.4.\u00a0HeapTupleHeaderData Layout\">Table\u00a066.4</a>. The actual user data (columns of the row) begins at the offset indicated by <code class=\"structfield\">t_hoff</code>, which must always be a multiple of the MAXALIGN distance for the platform. The null bitmap is only present if the <em class=\"firstterm\">HEAP_HASNULL</em> bit is set in <code class=\"structfield\">t_infomask</code>. If it is present it begins just after the fixed header and occupies enough bytes to have one bit per data column (that is, the number of bits that equals the attribute count in <code class=\"structfield\">t_infomask2</code>). In this list of bits, a 1 bit indicates not-null, a 0 bit is a null. When the bitmap is not present, all columns are assumed not-null. The object ID is only present if the <em class=\"firstterm\">HEAP_HASOID_OLD</em> bit is set in <code class=\"structfield\">t_infomask</code>. If present, it appears just before the <code class=\"structfield\">t_hoff</code> boundary. Any padding needed to make <code class=\"structfield\">t_hoff</code> a MAXALIGN multiple will appear between the null bitmap and the object ID. (This in turn ensures that the object ID is suitably aligned.)</p>\n<div class=\"table\">\n<p class=\"title\"><strong>Table\u00a066.4.\u00a0HeapTupleHeaderData Layout</strong></p>\n<div class=\"table-contents\">\n<table class=\"table\">\n\n\n\n\n\n\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Length</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>t_xmin</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>insert XID stamp</td>\n</tr>\n<tr>\n<td>t_xmax</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>delete XID stamp</td>\n</tr>\n<tr>\n<td>t_cid</td>\n<td>CommandId</td>\n<td>4 bytes</td>\n<td>insert and/or delete CID stamp (overlays with t_xvac)</td>\n</tr>\n<tr>\n<td>t_xvac</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>XID for VACUUM operation moving a row version</td>\n</tr>\n<tr>\n<td>t_ctid</td>\n<td>ItemPointerData</td>\n<td>6 bytes</td>\n<td>current TID of this or newer row version</td>\n</tr>\n<tr>\n<td>t_infomask2</td>\n<td>uint16</td>\n<td>2 bytes</td>\n<td>number of attributes, plus various flag bits</td>\n</tr>\n<tr>\n<td>t_infomask</td>\n<td>uint16</td>\n<td>2 bytes</td>\n<td>various flag bits</td>\n</tr>\n<tr>\n<td>t_hoff</td>\n<td>uint8</td>\n<td>1 byte</td>\n<td>offset to user data</td>\n</tr>\n</tbody>\n</table>\n</div>\n</div><br class=\"table-break\">\n<p>All the details can be found in <code class=\"filename\">src/include/access/htup_details.h</code>.</p>\n<p>Interpreting the actual data can only be done with information obtained from other tables, mostly <code class=\"structname\">pg_attribute</code>. The key values needed to identify field locations are <code class=\"structfield\">attlen</code> and <code class=\"structfield\">attalign</code>. There is no way to directly get a particular attribute, except when there are only fixed width fields and no null values. All this trickery is wrapped up in the functions <em class=\"firstterm\">heap_getattr</em>, <em class=\"firstterm\">fastgetattr</em> and <em class=\"firstterm\">heap_getsysattr</em>.</p>\n<p>To read the data you need to examine each attribute in turn. First check whether the field is NULL according to the null bitmap. If it is, go to the next. Then make sure you have the right alignment. If the field is a fixed width field, then all the bytes are simply placed. If it's a variable length field (attlen = -1) then it's a bit more complicated. All variable-length data types share the common header structure <code class=\"type\">varlena</code>, which includes the total length of the stored value and some flag bits. Depending on the flags, the data can be either inline or in a TOAST table; it might be compressed, too (see <a class=\"xref\" href=\"/docs/19/storage-toast.html\" title=\"66.2.\u00a0TOAST\">Section\u00a066.2</a>).</p>\n</div>", "manual_path": "/docs/19/storage-page-layout.html", "comparison_data": {"layouts": [{"key": "layout-2", "rows": [{"c0": "t_xmin", "c1": "TransactionId", "c2": "4 bytes", "c3": "insert XID stamp"}, {"c0": "t_xmax", "c1": "TransactionId", "c2": "4 bytes", "c3": "delete XID stamp"}, {"c0": "t_cid", "c1": "CommandId", "c2": "4 bytes", "c3": "insert and/or delete CID stamp (overlays with t_xvac)"}, {"c0": "t_xvac", "c1": "TransactionId", "c2": "4 bytes", "c3": "XID for VACUUM operation moving a row version"}, {"c0": "t_ctid", "c1": "ItemPointerData", "c2": "6 bytes", "c3": "current TID of this or newer row version"}, {"c0": "t_infomask2", "c1": "uint16", "c2": "2 bytes", "c3": "number of attributes, plus various flag bits"}, {"c0": "t_infomask", "c1": "uint16", "c2": "2 bytes", "c3": "various flag bits"}, {"c0": "t_hoff", "c1": "uint8", "c2": "1 byte", "c3": "offset to user data"}], "title": "HeapTupleHeaderData Layout", "columns": [{"key": "c0", "label": "Field"}, {"key": "c1", "label": "Type"}, {"key": "c2", "label": "Length"}, {"key": "c3", "label": "Description"}]}]}, "comparison_hash": "7f6e968716966dae8869d6c14f0a6aa229d745d4d4bde899b61eeec58c8d7ea0"}, "20": {"facts": [], "tables": [{"key": "layout-2", "rows": [{"c0": "t_xmin", "c1": "TransactionId", "c2": "4 bytes", "c3": "insert XID stamp"}, {"c0": "t_xmax", "c1": "TransactionId", "c2": "4 bytes", "c3": "delete XID stamp"}, {"c0": "t_cid", "c1": "CommandId", "c2": "4 bytes", "c3": "insert and/or delete CID stamp (overlays with t_xvac)"}, {"c0": "t_xvac", "c1": "TransactionId", "c2": "4 bytes", "c3": "XID for VACUUM operation moving a row version"}, {"c0": "t_ctid", "c1": "ItemPointerData", "c2": "6 bytes", "c3": "current TID of this or newer row version"}, {"c0": "t_infomask2", "c1": "uint16", "c2": "2 bytes", "c3": "number of attributes, plus various flag bits"}, {"c0": "t_infomask", "c1": "uint16", "c2": "2 bytes", "c3": "various flag bits"}, {"c0": "t_hoff", "c1": "uint8", "c2": "1 byte", "c3": "offset to user data"}], "title": "HeapTupleHeaderData Layout", "columns": [{"key": "c0", "label": "Field"}, {"key": "c1", "label": "Type"}, {"key": "c2", "label": "Length"}, {"key": "c3", "label": "Description"}]}], "related": [], "release": {"ref": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "label": "20devel", "major": "20", "channel": "devel", "revision": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}, "sources": [{"url": "/docs/devel/storage-page-layout.html#STORAGE-TUPLE-LAYOUT", "path": "storage-page-layout.html", "label": "PostgreSQL 20 English manual", "sha256": "4e487a076f789ae63b2d33f89a8b13837d6589937dd3f00bf0a30e9eb9e2ec13"}], "sections": [], "signature": "", "description": ["Physical row headers, null bitmap, alignment and column data."], "manual_html": "<div class=\"sect2\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">66.6.1.\u00a0Table Row Layout </h3>\n</div>\n</div>\n</div>\n<p>All table rows are structured in the same way. There is a fixed-size header (occupying 23 bytes on most machines), followed by an optional null bitmap, an optional object ID field, and the user data. The header is detailed in <a class=\"xref\" href=\"/docs/devel/storage-page-layout.html#HEAPTUPLEHEADERDATA-TABLE\" title=\"Table\u00a066.4.\u00a0HeapTupleHeaderData Layout\">Table\u00a066.4</a>. The actual user data (columns of the row) begins at the offset indicated by <code class=\"structfield\">t_hoff</code>, which must always be a multiple of the MAXALIGN distance for the platform. The null bitmap is only present if the <em class=\"firstterm\">HEAP_HASNULL</em> bit is set in <code class=\"structfield\">t_infomask</code>. If it is present it begins just after the fixed header and occupies enough bytes to have one bit per data column (that is, the number of bits that equals the attribute count in <code class=\"structfield\">t_infomask2</code>). In this list of bits, a 1 bit indicates not-null, a 0 bit is a null. When the bitmap is not present, all columns are assumed not-null. The object ID is only present if the <em class=\"firstterm\">HEAP_HASOID_OLD</em> bit is set in <code class=\"structfield\">t_infomask</code>. If present, it appears just before the <code class=\"structfield\">t_hoff</code> boundary. Any padding needed to make <code class=\"structfield\">t_hoff</code> a MAXALIGN multiple will appear between the null bitmap and the object ID. (This in turn ensures that the object ID is suitably aligned.)</p>\n<div class=\"table\">\n<p class=\"title\"><strong>Table\u00a066.4.\u00a0HeapTupleHeaderData Layout</strong></p>\n<div class=\"table-contents\">\n<table class=\"table\">\n\n\n\n\n\n\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Length</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>t_xmin</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>insert XID stamp</td>\n</tr>\n<tr>\n<td>t_xmax</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>delete XID stamp</td>\n</tr>\n<tr>\n<td>t_cid</td>\n<td>CommandId</td>\n<td>4 bytes</td>\n<td>insert and/or delete CID stamp (overlays with t_xvac)</td>\n</tr>\n<tr>\n<td>t_xvac</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>XID for VACUUM operation moving a row version</td>\n</tr>\n<tr>\n<td>t_ctid</td>\n<td>ItemPointerData</td>\n<td>6 bytes</td>\n<td>current TID of this or newer row version</td>\n</tr>\n<tr>\n<td>t_infomask2</td>\n<td>uint16</td>\n<td>2 bytes</td>\n<td>number of attributes, plus various flag bits</td>\n</tr>\n<tr>\n<td>t_infomask</td>\n<td>uint16</td>\n<td>2 bytes</td>\n<td>various flag bits</td>\n</tr>\n<tr>\n<td>t_hoff</td>\n<td>uint8</td>\n<td>1 byte</td>\n<td>offset to user data</td>\n</tr>\n</tbody>\n</table>\n</div>\n</div><br class=\"table-break\">\n<p>All the details can be found in <code class=\"filename\">src/include/access/htup_details.h</code>.</p>\n<p>Interpreting the actual data can only be done with information obtained from other tables, mostly <code class=\"structname\">pg_attribute</code>. The key values needed to identify field locations are <code class=\"structfield\">attlen</code> and <code class=\"structfield\">attalign</code>. There is no way to directly get a particular attribute, except when there are only fixed width fields and no null values. All this trickery is wrapped up in the functions <em class=\"firstterm\">heap_getattr</em>, <em class=\"firstterm\">fastgetattr</em> and <em class=\"firstterm\">heap_getsysattr</em>.</p>\n<p>To read the data you need to examine each attribute in turn. First check whether the field is NULL according to the null bitmap. If it is, go to the next. Then make sure you have the right alignment. If the field is a fixed width field, then all the bytes are simply placed. If it's a variable length field (attlen = -1) then it's a bit more complicated. All variable-length data types share the common header structure <code class=\"type\">varlena</code>, which includes the total length of the stored value and some flag bits. Depending on the flags, the data can be either inline or in a TOAST table; it might be compressed, too (see <a class=\"xref\" href=\"/docs/devel/storage-toast.html\" title=\"66.2.\u00a0TOAST\">Section\u00a066.2</a>).</p>\n</div>", "manual_path": "/docs/devel/storage-page-layout.html", "comparison_data": {"layouts": [{"key": "layout-2", "rows": [{"c0": "t_xmin", "c1": "TransactionId", "c2": "4 bytes", "c3": "insert XID stamp"}, {"c0": "t_xmax", "c1": "TransactionId", "c2": "4 bytes", "c3": "delete XID stamp"}, {"c0": "t_cid", "c1": "CommandId", "c2": "4 bytes", "c3": "insert and/or delete CID stamp (overlays with t_xvac)"}, {"c0": "t_xvac", "c1": "TransactionId", "c2": "4 bytes", "c3": "XID for VACUUM operation moving a row version"}, {"c0": "t_ctid", "c1": "ItemPointerData", "c2": "6 bytes", "c3": "current TID of this or newer row version"}, {"c0": "t_infomask2", "c1": "uint16", "c2": "2 bytes", "c3": "number of attributes, plus various flag bits"}, {"c0": "t_infomask", "c1": "uint16", "c2": "2 bytes", "c3": "various flag bits"}, {"c0": "t_hoff", "c1": "uint8", "c2": "1 byte", "c3": "offset to user data"}], "title": "HeapTupleHeaderData Layout", "columns": [{"key": "c0", "label": "Field"}, {"key": "c1", "label": "Type"}, {"key": "c2", "label": "Length"}, {"key": "c3", "label": "Description"}]}]}, "comparison_hash": "7f6e968716966dae8869d6c14f0a6aa229d745d4d4bde899b61eeec58c8d7ea0"}}}, "snapshot": {"facts": [], "tables": [{"key": "layout-2", "rows": [{"c0": "t_xmin", "c1": "TransactionId", "c2": "4 bytes", "c3": "insert XID stamp"}, {"c0": "t_xmax", "c1": "TransactionId", "c2": "4 bytes", "c3": "delete XID stamp"}, {"c0": "t_cid", "c1": "CommandId", "c2": "4 bytes", "c3": "insert and/or delete CID stamp (overlays with t_xvac)"}, {"c0": "t_xvac", "c1": "TransactionId", "c2": "4 bytes", "c3": "XID for VACUUM operation moving a row version"}, {"c0": "t_ctid", "c1": "ItemPointerData", "c2": "6 bytes", "c3": "current TID of this or newer row version"}, {"c0": "t_infomask2", "c1": "uint16", "c2": "2 bytes", "c3": "number of attributes, plus various flag bits"}, {"c0": "t_infomask", "c1": "uint16", "c2": "2 bytes", "c3": "various flag bits"}, {"c0": "t_hoff", "c1": "uint8", "c2": "1 byte", "c3": "offset to user data"}], "title": "HeapTupleHeaderData Layout", "columns": [{"key": "c0", "label": "Field"}, {"key": "c1", "label": "Type"}, {"key": "c2", "label": "Length"}, {"key": "c3", "label": "Description"}]}], "related": [], "release": {"ref": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "label": "18.6", "major": "18", "channel": "stable", "revision": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, "sources": [{"url": "/docs/18/storage-page-layout.html#STORAGE-TUPLE-LAYOUT", "path": "storage-page-layout.html", "label": "PostgreSQL 18 English manual", "sha256": "0d9f99e4cef5ea0a6741a74cab87052b929f7001730853c85d5e60d72179d355"}], "sections": [], "signature": "", "description": ["Physical row headers, null bitmap, alignment and column data."], "manual_html": "<div class=\"sect2\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">66.6.1.\u00a0Table Row Layout </h3>\n</div>\n</div>\n</div>\n<p>All table rows are structured in the same way. There is a fixed-size header (occupying 23 bytes on most machines), followed by an optional null bitmap, an optional object ID field, and the user data. The header is detailed in <a class=\"xref\" href=\"/docs/18/storage-page-layout.html#HEAPTUPLEHEADERDATA-TABLE\" title=\"Table\u00a066.4.\u00a0HeapTupleHeaderData Layout\">Table\u00a066.4</a>. The actual user data (columns of the row) begins at the offset indicated by <code class=\"structfield\">t_hoff</code>, which must always be a multiple of the MAXALIGN distance for the platform. The null bitmap is only present if the <em class=\"firstterm\">HEAP_HASNULL</em> bit is set in <code class=\"structfield\">t_infomask</code>. If it is present it begins just after the fixed header and occupies enough bytes to have one bit per data column (that is, the number of bits that equals the attribute count in <code class=\"structfield\">t_infomask2</code>). In this list of bits, a 1 bit indicates not-null, a 0 bit is a null. When the bitmap is not present, all columns are assumed not-null. The object ID is only present if the <em class=\"firstterm\">HEAP_HASOID_OLD</em> bit is set in <code class=\"structfield\">t_infomask</code>. If present, it appears just before the <code class=\"structfield\">t_hoff</code> boundary. Any padding needed to make <code class=\"structfield\">t_hoff</code> a MAXALIGN multiple will appear between the null bitmap and the object ID. (This in turn ensures that the object ID is suitably aligned.)</p>\n<div class=\"table\">\n<p class=\"title\"><strong>Table\u00a066.4.\u00a0HeapTupleHeaderData Layout</strong></p>\n<div class=\"table-contents\">\n<table class=\"table\">\n\n\n\n\n\n\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Length</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>t_xmin</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>insert XID stamp</td>\n</tr>\n<tr>\n<td>t_xmax</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>delete XID stamp</td>\n</tr>\n<tr>\n<td>t_cid</td>\n<td>CommandId</td>\n<td>4 bytes</td>\n<td>insert and/or delete CID stamp (overlays with t_xvac)</td>\n</tr>\n<tr>\n<td>t_xvac</td>\n<td>TransactionId</td>\n<td>4 bytes</td>\n<td>XID for VACUUM operation moving a row version</td>\n</tr>\n<tr>\n<td>t_ctid</td>\n<td>ItemPointerData</td>\n<td>6 bytes</td>\n<td>current TID of this or newer row version</td>\n</tr>\n<tr>\n<td>t_infomask2</td>\n<td>uint16</td>\n<td>2 bytes</td>\n<td>number of attributes, plus various flag bits</td>\n</tr>\n<tr>\n<td>t_infomask</td>\n<td>uint16</td>\n<td>2 bytes</td>\n<td>various flag bits</td>\n</tr>\n<tr>\n<td>t_hoff</td>\n<td>uint8</td>\n<td>1 byte</td>\n<td>offset to user data</td>\n</tr>\n</tbody>\n</table>\n</div>\n</div><br class=\"table-break\">\n<p>All the details can be found in <code class=\"filename\">src/include/access/htup_details.h</code>.</p>\n<p>Interpreting the actual data can only be done with information obtained from other tables, mostly <code class=\"structname\">pg_attribute</code>. The key values needed to identify field locations are <code class=\"structfield\">attlen</code> and <code class=\"structfield\">attalign</code>. There is no way to directly get a particular attribute, except when there are only fixed width fields and no null values. All this trickery is wrapped up in the functions <em class=\"firstterm\">heap_getattr</em>, <em class=\"firstterm\">fastgetattr</em> and <em class=\"firstterm\">heap_getsysattr</em>.</p>\n<p>To read the data you need to examine each attribute in turn. First check whether the field is NULL according to the null bitmap. If it is, go to the next. Then make sure you have the right alignment. If the field is a fixed width field, then all the bytes are simply placed. If it's a variable length field (attlen = -1) then it's a bit more complicated. All variable-length data types share the common header structure <code class=\"type\">struct varlena</code>, which includes the total length of the stored value and some flag bits. Depending on the flags, the data can be either inline or in a TOAST table; it might be compressed, too (see <a class=\"xref\" href=\"/docs/18/storage-toast.html\" title=\"66.2.\u00a0TOAST\">Section\u00a066.2</a>).</p>\n</div>", "manual_path": "/docs/18/storage-page-layout.html", "comparison_data": {"layouts": [{"key": "layout-2", "rows": [{"c0": "t_xmin", "c1": "TransactionId", "c2": "4 bytes", "c3": "insert XID stamp"}, {"c0": "t_xmax", "c1": "TransactionId", "c2": "4 bytes", "c3": "delete XID stamp"}, {"c0": "t_cid", "c1": "CommandId", "c2": "4 bytes", "c3": "insert and/or delete CID stamp (overlays with t_xvac)"}, {"c0": "t_xvac", "c1": "TransactionId", "c2": "4 bytes", "c3": "XID for VACUUM operation moving a row version"}, {"c0": "t_ctid", "c1": "ItemPointerData", "c2": "6 bytes", "c3": "current TID of this or newer row version"}, {"c0": "t_infomask2", "c1": "uint16", "c2": "2 bytes", "c3": "number of attributes, plus various flag bits"}, {"c0": "t_infomask", "c1": "uint16", "c2": "2 bytes", "c3": "various flag bits"}, {"c0": "t_hoff", "c1": "uint8", "c2": "1 byte", "c3": "offset to user data"}], "title": "HeapTupleHeaderData Layout", "columns": [{"key": "c0", "label": "Field"}, {"key": "c1", "label": "Type"}, {"key": "c2", "label": "Length"}, {"key": "c3", "label": "Description"}]}]}, "comparison_hash": "7f6e968716966dae8869d6c14f0a6aa229d745d4d4bde899b61eeec58c8d7ea0"}, "comparison": {"left": "17", "right": "18", "status": "unchanged", "diff": ""}}