Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * heapdesc.c
4 : * rmgr descriptor routines for access/heap/heapam.c
5 : *
6 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/backend/access/rmgrdesc/heapdesc.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 : #include "postgres.h"
16 :
17 : #include "access/heapam_xlog.h"
18 : #include "access/rmgrdesc_utils.h"
19 :
20 : static void
3728 alvherre 21 GIC 41 : out_infobits(StringInfo buf, uint8 infobits)
3728 alvherre 22 ECB : {
2 pg 23 GNC 41 : if ((infobits & XLHL_XMAX_IS_MULTI) == 0 &&
24 41 : (infobits & XLHL_XMAX_LOCK_ONLY) == 0 &&
25 30 : (infobits & XLHL_XMAX_EXCL_LOCK) == 0 &&
26 30 : (infobits & XLHL_XMAX_KEYSHR_LOCK) == 0 &&
27 30 : (infobits & XLHL_KEYS_UPDATED) == 0)
28 22 : return;
29 :
30 19 : appendStringInfoString(buf, ", infobits: [");
31 :
3728 alvherre 32 GIC 19 : if (infobits & XLHL_XMAX_IS_MULTI)
2 pg 33 UNC 0 : appendStringInfoString(buf, " IS_MULTI");
3728 alvherre 34 CBC 19 : if (infobits & XLHL_XMAX_LOCK_ONLY)
2 pg 35 GNC 11 : appendStringInfoString(buf, ", LOCK_ONLY");
3728 alvherre 36 CBC 19 : if (infobits & XLHL_XMAX_EXCL_LOCK)
2 pg 37 GNC 11 : appendStringInfoString(buf, ", EXCL_LOCK");
3728 alvherre 38 CBC 19 : if (infobits & XLHL_XMAX_KEYSHR_LOCK)
2 pg 39 UNC 0 : appendStringInfoString(buf, ", KEYSHR_LOCK");
3728 alvherre 40 CBC 19 : if (infobits & XLHL_KEYS_UPDATED)
2 pg 41 GNC 8 : appendStringInfoString(buf, ", KEYS_UPDATED");
42 :
43 19 : appendStringInfoString(buf, " ]");
44 : }
45 :
46 : static void
2 pg 47 UNC 0 : plan_elem_desc(StringInfo buf, void *plan, void *data)
48 : {
49 0 : xl_heap_freeze_plan *new_plan = (xl_heap_freeze_plan *) plan;
50 0 : OffsetNumber **offsets = data;
51 :
52 0 : appendStringInfo(buf, "{ xmax: %u, infomask: %u, infomask2: %u, ntuples: %u",
53 : new_plan->xmax,
54 0 : new_plan->t_infomask, new_plan->t_infomask2,
55 0 : new_plan->ntuples);
56 :
57 0 : appendStringInfoString(buf, ", offsets:");
58 0 : array_desc(buf, *offsets, sizeof(OffsetNumber), new_plan->ntuples,
59 : &offset_elem_desc, NULL);
60 :
61 0 : *offsets += new_plan->ntuples;
62 :
63 0 : appendStringInfo(buf, " }");
3728 alvherre 64 LBC 0 : }
3728 alvherre 65 EUB :
3784 alvherre 66 ECB : void
3062 heikki.linnakangas 67 CBC 30937 : heap_desc(StringInfo buf, XLogReaderState *record)
3784 alvherre 68 ECB : {
3221 heikki.linnakangas 69 CBC 30937 : char *rec = XLogRecGetData(record);
3062 70 30937 : uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
3784 alvherre 71 EUB :
3784 alvherre 72 CBC 30937 : info &= XLOG_HEAP_OPMASK;
73 30937 : if (info == XLOG_HEAP_INSERT)
74 : {
75 30896 : xl_heap_insert *xlrec = (xl_heap_insert *) rec;
76 :
2 pg 77 GNC 30896 : appendStringInfo(buf, "off: %u, flags: 0x%02X",
78 30896 : xlrec->offnum,
1607 michael 79 GIC 30896 : xlrec->flags);
3784 alvherre 80 EUB : }
3784 alvherre 81 GIC 41 : else if (info == XLOG_HEAP_DELETE)
3784 alvherre 82 EUB : {
3784 alvherre 83 GBC 8 : xl_heap_delete *xlrec = (xl_heap_delete *) rec;
84 :
2 pg 85 GNC 8 : appendStringInfo(buf, "off: %u, flags: 0x%02X",
1607 michael 86 GIC 8 : xlrec->offnum,
1607 michael 87 GBC 8 : xlrec->flags);
3728 alvherre 88 8 : out_infobits(buf, xlrec->infobits_set);
89 : }
3784 90 33 : else if (info == XLOG_HEAP_UPDATE)
3784 alvherre 91 EUB : {
3784 alvherre 92 GIC 10 : xl_heap_update *xlrec = (xl_heap_update *) rec;
93 :
2 pg 94 GNC 10 : appendStringInfo(buf, "off: %u, xmax: %u, flags: 0x%02X",
3062 heikki.linnakangas 95 GIC 10 : xlrec->old_offnum,
1607 michael 96 EUB : xlrec->old_xmax,
1607 michael 97 GBC 10 : xlrec->flags);
3728 alvherre 98 GIC 10 : out_infobits(buf, xlrec->old_infobits_set);
2 pg 99 GNC 10 : appendStringInfo(buf, ", new off: %u, xmax %u",
3062 heikki.linnakangas 100 CBC 10 : xlrec->new_offnum,
101 : xlrec->new_xmax);
3784 alvherre 102 ECB : }
3784 alvherre 103 CBC 23 : else if (info == XLOG_HEAP_HOT_UPDATE)
104 : {
105 12 : xl_heap_update *xlrec = (xl_heap_update *) rec;
3784 alvherre 106 ECB :
2 pg 107 GNC 12 : appendStringInfo(buf, "off: %u, xmax: %u, flags: 0x%02X",
3062 heikki.linnakangas 108 CBC 12 : xlrec->old_offnum,
109 : xlrec->old_xmax,
1607 michael 110 12 : xlrec->flags);
3728 alvherre 111 12 : out_infobits(buf, xlrec->old_infobits_set);
2 pg 112 GNC 12 : appendStringInfo(buf, ", new off: %u, xmax: %u",
3062 heikki.linnakangas 113 GIC 12 : xlrec->new_offnum,
3728 alvherre 114 ECB : xlrec->new_xmax);
115 : }
1828 peter_e 116 CBC 11 : else if (info == XLOG_HEAP_TRUNCATE)
117 : {
1828 peter_e 118 LBC 0 : xl_heap_truncate *xlrec = (xl_heap_truncate *) rec;
1828 peter_e 119 ECB :
2 pg 120 UNC 0 : appendStringInfoString(buf, "flags: [");
1828 peter_e 121 LBC 0 : if (xlrec->flags & XLH_TRUNCATE_CASCADE)
2 pg 122 UNC 0 : appendStringInfoString(buf, " CASCADE");
1828 peter_e 123 LBC 0 : if (xlrec->flags & XLH_TRUNCATE_RESTART_SEQS)
2 pg 124 UNC 0 : appendStringInfoString(buf, ", RESTART_SEQS");
125 0 : appendStringInfoString(buf, " ]");
126 :
127 0 : appendStringInfo(buf, ", nrelids: %u", xlrec->nrelids);
128 0 : appendStringInfoString(buf, ", relids:");
129 0 : array_desc(buf, xlrec->relids, sizeof(Oid), xlrec->nrelids,
130 : &relid_desc, NULL);
1828 peter_e 131 ECB : }
2893 andres 132 GIC 11 : else if (info == XLOG_HEAP_CONFIRM)
2893 andres 133 ECB : {
2893 andres 134 LBC 0 : xl_heap_confirm *xlrec = (xl_heap_confirm *) rec;
2893 andres 135 ECB :
2 pg 136 UNC 0 : appendStringInfo(buf, "off: %u", xlrec->offnum);
137 : }
3784 alvherre 138 GIC 11 : else if (info == XLOG_HEAP_LOCK)
3784 alvherre 139 ECB : {
3784 alvherre 140 GIC 11 : xl_heap_lock *xlrec = (xl_heap_lock *) rec;
3784 alvherre 141 ECB :
2 pg 142 GNC 11 : appendStringInfo(buf, "off: %u, xid: %u, flags: 0x%02X",
2456 andres 143 CBC 11 : xlrec->offnum, xlrec->locking_xid, xlrec->flags);
3728 alvherre 144 11 : out_infobits(buf, xlrec->infobits_set);
145 : }
3784 alvherre 146 LBC 0 : else if (info == XLOG_HEAP_INPLACE)
3784 alvherre 147 ECB : {
3784 alvherre 148 LBC 0 : xl_heap_inplace *xlrec = (xl_heap_inplace *) rec;
3784 alvherre 149 ECB :
2 pg 150 UNC 0 : appendStringInfo(buf, "off: %u", xlrec->offnum);
151 : }
3784 alvherre 152 CBC 30937 : }
153 :
154 : void
3062 heikki.linnakangas 155 GBC 63 : heap2_desc(StringInfo buf, XLogReaderState *record)
156 : {
3221 157 63 : char *rec = XLogRecGetData(record);
3062 158 63 : uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
3784 alvherre 159 EUB :
3784 alvherre 160 GBC 63 : info &= XLOG_HEAP_OPMASK;
733 pg 161 63 : if (info == XLOG_HEAP2_PRUNE)
3784 alvherre 162 EUB : {
733 pg 163 GIC 47 : xl_heap_prune *xlrec = (xl_heap_prune *) rec;
3784 alvherre 164 EUB :
2 pg 165 GNC 47 : appendStringInfo(buf, "snapshotConflictHorizon: %u, nredirected: %u, ndead: %u",
166 : xlrec->snapshotConflictHorizon,
733 pg 167 GIC 47 : xlrec->nredirected,
168 47 : xlrec->ndead);
169 :
2 pg 170 GNC 47 : if (!XLogRecHasBlockImage(record, 0))
171 : {
172 : OffsetNumber *end;
173 : OffsetNumber *redirected;
174 : OffsetNumber *nowdead;
175 : OffsetNumber *nowunused;
176 : int nredirected;
177 : int nunused;
178 : Size datalen;
179 :
180 47 : redirected = (OffsetNumber *) XLogRecGetBlockData(record, 0,
181 : &datalen);
182 :
183 47 : nredirected = xlrec->nredirected;
184 47 : end = (OffsetNumber *) ((char *) redirected + datalen);
185 47 : nowdead = redirected + (nredirected * 2);
186 47 : nowunused = nowdead + xlrec->ndead;
187 47 : nunused = (end - nowunused);
188 47 : Assert(nunused >= 0);
189 :
190 47 : appendStringInfo(buf, ", nunused: %u", nunused);
191 :
192 47 : appendStringInfoString(buf, ", redirected:");
193 47 : array_desc(buf, redirected, sizeof(OffsetNumber) * 2,
194 : nredirected, &redirect_elem_desc, NULL);
195 47 : appendStringInfoString(buf, ", dead:");
196 47 : array_desc(buf, nowdead, sizeof(OffsetNumber), xlrec->ndead,
197 : &offset_elem_desc, NULL);
198 47 : appendStringInfoString(buf, ", unused:");
199 47 : array_desc(buf, nowunused, sizeof(OffsetNumber), nunused,
200 : &offset_elem_desc, NULL);
201 : }
733 pg 202 ECB : }
733 pg 203 GIC 16 : else if (info == XLOG_HEAP2_VACUUM)
733 pg 204 EUB : {
733 pg 205 UIC 0 : xl_heap_vacuum *xlrec = (xl_heap_vacuum *) rec;
733 pg 206 EUB :
2 pg 207 UNC 0 : appendStringInfo(buf, "nunused: %u", xlrec->nunused);
208 :
209 0 : if (!XLogRecHasBlockImage(record, 0))
210 : {
211 : OffsetNumber *nowunused;
212 :
213 0 : nowunused = (OffsetNumber *) XLogRecGetBlockData(record, 0, NULL);
214 :
215 0 : appendStringInfoString(buf, ", unused:");
216 0 : array_desc(buf, nowunused, sizeof(OffsetNumber), xlrec->nunused,
217 : &offset_elem_desc, NULL);
218 : }
3784 alvherre 219 ECB : }
3401 alvherre 220 GIC 16 : else if (info == XLOG_HEAP2_FREEZE_PAGE)
3784 alvherre 221 ECB : {
3401 alvherre 222 UIC 0 : xl_heap_freeze_page *xlrec = (xl_heap_freeze_page *) rec;
3784 alvherre 223 ECB :
2 pg 224 UNC 0 : appendStringInfo(buf, "snapshotConflictHorizon: %u, nplans: %u",
143 225 0 : xlrec->snapshotConflictHorizon, xlrec->nplans);
226 :
2 227 0 : if (!XLogRecHasBlockImage(record, 0))
228 : {
229 : xl_heap_freeze_plan *plans;
230 : OffsetNumber *offsets;
231 :
232 0 : plans = (xl_heap_freeze_plan *) XLogRecGetBlockData(record, 0, NULL);
233 0 : offsets = (OffsetNumber *) &plans[xlrec->nplans];
234 0 : appendStringInfoString(buf, ", plans:");
235 0 : array_desc(buf, plans, sizeof(xl_heap_freeze_plan), xlrec->nplans,
236 : &plan_elem_desc, &offsets);
237 : }
238 : }
3784 alvherre 239 GBC 16 : else if (info == XLOG_HEAP2_VISIBLE)
240 : {
3784 alvherre 241 UBC 0 : xl_heap_visible *xlrec = (xl_heap_visible *) rec;
242 :
2 pg 243 UNC 0 : appendStringInfo(buf, "snapshotConflictHorizon: %u, flags: 0x%02X",
143 244 0 : xlrec->snapshotConflictHorizon, xlrec->flags);
3784 alvherre 245 ECB : }
3784 alvherre 246 GIC 16 : else if (info == XLOG_HEAP2_MULTI_INSERT)
247 : {
3784 alvherre 248 CBC 16 : xl_heap_multi_insert *xlrec = (xl_heap_multi_insert *) rec;
2 pg 249 GNC 16 : bool isinit = (XLogRecGetInfo(record) & XLOG_HEAP_INIT_PAGE) != 0;
250 :
251 16 : appendStringInfo(buf, "ntuples: %d, flags: 0x%02X", xlrec->ntuples,
1607 michael 252 CBC 16 : xlrec->flags);
253 :
2 pg 254 GNC 16 : appendStringInfoString(buf, ", offsets:");
255 16 : if (!XLogRecHasBlockImage(record, 0) && !isinit)
256 13 : array_desc(buf, xlrec->offsets, sizeof(OffsetNumber),
257 13 : xlrec->ntuples, &offset_elem_desc, NULL);
258 : }
3728 alvherre 259 LBC 0 : else if (info == XLOG_HEAP2_LOCK_UPDATED)
3728 alvherre 260 ECB : {
3728 alvherre 261 UIC 0 : xl_heap_lock_updated *xlrec = (xl_heap_lock_updated *) rec;
3728 alvherre 262 ECB :
2 pg 263 UNC 0 : appendStringInfo(buf, "off: %u, xmax: %u, flags: 0x%02X",
2456 andres 264 LBC 0 : xlrec->offnum, xlrec->xmax, xlrec->flags);
3009 alvherre 265 UIC 0 : out_infobits(buf, xlrec->infobits_set);
3728 alvherre 266 ECB : }
3407 rhaas 267 LBC 0 : else if (info == XLOG_HEAP2_NEW_CID)
268 : {
269 0 : xl_heap_new_cid *xlrec = (xl_heap_new_cid *) rec;
270 :
2 pg 271 UNC 0 : appendStringInfo(buf, "rel: %u/%u/%u, tid: %u/%u",
272 : xlrec->target_locator.spcOid,
273 : xlrec->target_locator.dbOid,
274 : xlrec->target_locator.relNumber,
3062 heikki.linnakangas 275 UIC 0 : ItemPointerGetBlockNumber(&(xlrec->target_tid)),
276 0 : ItemPointerGetOffsetNumber(&(xlrec->target_tid)));
2 pg 277 UNC 0 : appendStringInfo(buf, ", cmin: %u, cmax: %u, combo: %u",
278 : xlrec->cmin, xlrec->cmax, xlrec->combocid);
3407 rhaas 279 ECB : }
3124 andres 280 GIC 63 : }
281 :
3124 andres 282 ECB : const char *
3124 andres 283 CBC 30937 : heap_identify(uint8 info)
3124 andres 284 ECB : {
3124 andres 285 CBC 30937 : const char *id = NULL;
3124 andres 286 ECB :
3121 andres 287 CBC 30937 : switch (info & ~XLR_INFO_MASK)
288 : {
3124 289 29486 : case XLOG_HEAP_INSERT:
3124 andres 290 GIC 29486 : id = "INSERT";
3124 andres 291 CBC 29486 : break;
3121 292 1410 : case XLOG_HEAP_INSERT | XLOG_HEAP_INIT_PAGE:
3121 andres 293 GIC 1410 : id = "INSERT+INIT";
3121 andres 294 CBC 1410 : break;
3124 295 8 : case XLOG_HEAP_DELETE:
3124 andres 296 GIC 8 : id = "DELETE";
3124 andres 297 CBC 8 : break;
298 9 : case XLOG_HEAP_UPDATE:
3124 andres 299 GIC 9 : id = "UPDATE";
300 9 : break;
3121 301 1 : case XLOG_HEAP_UPDATE | XLOG_HEAP_INIT_PAGE:
3121 andres 302 CBC 1 : id = "UPDATE+INIT";
3121 andres 303 GIC 1 : break;
3124 andres 304 GBC 12 : case XLOG_HEAP_HOT_UPDATE:
3124 andres 305 GIC 12 : id = "HOT_UPDATE";
3124 andres 306 GBC 12 : break;
3121 andres 307 UIC 0 : case XLOG_HEAP_HOT_UPDATE | XLOG_HEAP_INIT_PAGE:
3121 andres 308 UBC 0 : id = "HOT_UPDATE+INIT";
3121 andres 309 UIC 0 : break;
1828 peter_e 310 0 : case XLOG_HEAP_TRUNCATE:
311 0 : id = "TRUNCATE";
1828 peter_e 312 UBC 0 : break;
2893 andres 313 UIC 0 : case XLOG_HEAP_CONFIRM:
2893 andres 314 UBC 0 : id = "HEAP_CONFIRM";
315 0 : break;
3124 andres 316 GIC 11 : case XLOG_HEAP_LOCK:
317 11 : id = "LOCK";
318 11 : break;
3124 andres 319 LBC 0 : case XLOG_HEAP_INPLACE:
3124 andres 320 UIC 0 : id = "INPLACE";
3124 andres 321 UBC 0 : break;
322 : }
3124 andres 323 EUB :
3124 andres 324 GBC 30937 : return id;
325 : }
3124 andres 326 EUB :
327 : const char *
3124 andres 328 GIC 63 : heap2_identify(uint8 info)
329 : {
330 63 : const char *id = NULL;
3124 andres 331 EUB :
3121 andres 332 GBC 63 : switch (info & ~XLR_INFO_MASK)
3124 andres 333 EUB : {
733 pg 334 GBC 47 : case XLOG_HEAP2_PRUNE:
733 pg 335 GIC 47 : id = "PRUNE";
336 47 : break;
733 pg 337 UIC 0 : case XLOG_HEAP2_VACUUM:
733 pg 338 LBC 0 : id = "VACUUM";
3124 andres 339 UIC 0 : break;
3124 andres 340 UBC 0 : case XLOG_HEAP2_FREEZE_PAGE:
3124 andres 341 UIC 0 : id = "FREEZE_PAGE";
3124 andres 342 UBC 0 : break;
343 0 : case XLOG_HEAP2_VISIBLE:
3124 andres 344 UIC 0 : id = "VISIBLE";
3124 andres 345 LBC 0 : break;
3124 andres 346 GIC 16 : case XLOG_HEAP2_MULTI_INSERT:
3124 andres 347 CBC 16 : id = "MULTI_INSERT";
348 16 : break;
3121 andres 349 UIC 0 : case XLOG_HEAP2_MULTI_INSERT | XLOG_HEAP_INIT_PAGE:
3121 andres 350 LBC 0 : id = "MULTI_INSERT+INIT";
351 0 : break;
3124 andres 352 UIC 0 : case XLOG_HEAP2_LOCK_UPDATED:
3124 andres 353 LBC 0 : id = "LOCK_UPDATED";
354 0 : break;
355 0 : case XLOG_HEAP2_NEW_CID:
356 0 : id = "NEW_CID";
3124 andres 357 UIC 0 : break;
3124 andres 358 UBC 0 : case XLOG_HEAP2_REWRITE:
3124 andres 359 UIC 0 : id = "REWRITE";
3124 andres 360 UBC 0 : break;
361 : }
3124 andres 362 EUB :
3124 andres 363 GBC 63 : return id;
3784 alvherre 364 EUB : }
|