@@ -1179,15 +1179,17 @@ check_toast_tuple(HeapTuple toasttup, HeapCheckContext *ctx,
1179
1179
if (isnull )
1180
1180
{
1181
1181
report_toast_corruption (ctx , ta ,
1182
- pstrdup ("toast chunk sequence number is null" ));
1182
+ psprintf ("toast value %u has toast chunk with null sequence number" ,
1183
+ ta -> toast_pointer .va_valueid ));
1183
1184
return ;
1184
1185
}
1185
1186
chunk = DatumGetPointer (fastgetattr (toasttup , 3 ,
1186
1187
ctx -> toast_rel -> rd_att , & isnull ));
1187
1188
if (isnull )
1188
1189
{
1189
1190
report_toast_corruption (ctx , ta ,
1190
- pstrdup ("toast chunk data is null" ));
1191
+ psprintf ("toast value %u chunk %d has null data" ,
1192
+ ta -> toast_pointer .va_valueid , chunkno ));
1191
1193
return ;
1192
1194
}
1193
1195
if (!VARATT_IS_EXTENDED (chunk ))
@@ -1205,8 +1207,9 @@ check_toast_tuple(HeapTuple toasttup, HeapCheckContext *ctx,
1205
1207
uint32 header = ((varattrib_4b * ) chunk )-> va_4byte .va_header ;
1206
1208
1207
1209
report_toast_corruption (ctx , ta ,
1208
- psprintf ("corrupt extended toast chunk has invalid varlena header: %0x (sequence number %d)" ,
1209
- header , curchunk ));
1210
+ psprintf ("toast value %u chunk %d has invalid varlena header %0x" ,
1211
+ ta -> toast_pointer .va_valueid ,
1212
+ chunkno , header ));
1210
1213
return ;
1211
1214
}
1212
1215
@@ -1216,15 +1219,17 @@ check_toast_tuple(HeapTuple toasttup, HeapCheckContext *ctx,
1216
1219
if (curchunk != chunkno )
1217
1220
{
1218
1221
report_toast_corruption (ctx , ta ,
1219
- psprintf ("toast chunk sequence number %u does not match the expected sequence number %u" ,
1220
- curchunk , chunkno ));
1222
+ psprintf ("toast value %u chunk %d has sequence number %d, but expected sequence number %d" ,
1223
+ ta -> toast_pointer .va_valueid ,
1224
+ chunkno , curchunk , chunkno ));
1221
1225
return ;
1222
1226
}
1223
- if (curchunk > endchunk )
1227
+ if (chunkno > endchunk )
1224
1228
{
1225
1229
report_toast_corruption (ctx , ta ,
1226
- psprintf ("toast chunk sequence number %u exceeds the end chunk sequence number %u" ,
1227
- curchunk , endchunk ));
1230
+ psprintf ("toast value %u chunk %d follows last expected chunk %d" ,
1231
+ ta -> toast_pointer .va_valueid ,
1232
+ chunkno , endchunk ));
1228
1233
return ;
1229
1234
}
1230
1235
@@ -1233,8 +1238,9 @@ check_toast_tuple(HeapTuple toasttup, HeapCheckContext *ctx,
1233
1238
1234
1239
if (chunksize != expected_size )
1235
1240
report_toast_corruption (ctx , ta ,
1236
- psprintf ("toast chunk size %u differs from the expected size %u" ,
1237
- chunksize , expected_size ));
1241
+ psprintf ("toast value %u chunk %d has size %u, but expected size %u" ,
1242
+ ta -> toast_pointer .va_valueid ,
1243
+ chunkno , chunksize , expected_size ));
1238
1244
}
1239
1245
1240
1246
/*
@@ -1265,6 +1271,7 @@ check_tuple_attribute(HeapCheckContext *ctx)
1265
1271
char * tp ; /* pointer to the tuple data */
1266
1272
uint16 infomask ;
1267
1273
Form_pg_attribute thisatt ;
1274
+ struct varatt_external toast_pointer ;
1268
1275
1269
1276
infomask = ctx -> tuphdr -> t_infomask ;
1270
1277
thisatt = TupleDescAttr (RelationGetDescr (ctx -> rel ), ctx -> attnum );
@@ -1274,8 +1281,7 @@ check_tuple_attribute(HeapCheckContext *ctx)
1274
1281
if (ctx -> tuphdr -> t_hoff + ctx -> offset > ctx -> lp_len )
1275
1282
{
1276
1283
report_corruption (ctx ,
1277
- psprintf ("attribute %u with length %u starts at offset %u beyond total tuple length %u" ,
1278
- ctx -> attnum ,
1284
+ psprintf ("attribute with length %u starts at offset %u beyond total tuple length %u" ,
1279
1285
thisatt -> attlen ,
1280
1286
ctx -> tuphdr -> t_hoff + ctx -> offset ,
1281
1287
ctx -> lp_len ));
@@ -1295,8 +1301,7 @@ check_tuple_attribute(HeapCheckContext *ctx)
1295
1301
if (ctx -> tuphdr -> t_hoff + ctx -> offset > ctx -> lp_len )
1296
1302
{
1297
1303
report_corruption (ctx ,
1298
- psprintf ("attribute %u with length %u ends at offset %u beyond total tuple length %u" ,
1299
- ctx -> attnum ,
1304
+ psprintf ("attribute with length %u ends at offset %u beyond total tuple length %u" ,
1300
1305
thisatt -> attlen ,
1301
1306
ctx -> tuphdr -> t_hoff + ctx -> offset ,
1302
1307
ctx -> lp_len ));
@@ -1328,8 +1333,7 @@ check_tuple_attribute(HeapCheckContext *ctx)
1328
1333
if (va_tag != VARTAG_ONDISK )
1329
1334
{
1330
1335
report_corruption (ctx ,
1331
- psprintf ("toasted attribute %u has unexpected TOAST tag %u" ,
1332
- ctx -> attnum ,
1336
+ psprintf ("toasted attribute has unexpected TOAST tag %u" ,
1333
1337
va_tag ));
1334
1338
/* We can't know where the next attribute begins */
1335
1339
return false;
@@ -1343,8 +1347,7 @@ check_tuple_attribute(HeapCheckContext *ctx)
1343
1347
if (ctx -> tuphdr -> t_hoff + ctx -> offset > ctx -> lp_len )
1344
1348
{
1345
1349
report_corruption (ctx ,
1346
- psprintf ("attribute %u with length %u ends at offset %u beyond total tuple length %u" ,
1347
- ctx -> attnum ,
1350
+ psprintf ("attribute with length %u ends at offset %u beyond total tuple length %u" ,
1348
1351
thisatt -> attlen ,
1349
1352
ctx -> tuphdr -> t_hoff + ctx -> offset ,
1350
1353
ctx -> lp_len ));
@@ -1371,21 +1374,26 @@ check_tuple_attribute(HeapCheckContext *ctx)
1371
1374
1372
1375
/* It is external, and we're looking at a page on disk */
1373
1376
1377
+ /*
1378
+ * Must copy attr into toast_pointer for alignment considerations
1379
+ */
1380
+ VARATT_EXTERNAL_GET_POINTER (toast_pointer , attr );
1381
+
1374
1382
/* The tuple header better claim to contain toasted values */
1375
1383
if (!(infomask & HEAP_HASEXTERNAL ))
1376
1384
{
1377
1385
report_corruption (ctx ,
1378
- psprintf ("attribute %u is external but tuple header flag HEAP_HASEXTERNAL not set" ,
1379
- ctx -> attnum ));
1386
+ psprintf ("toast value %u is external but tuple header flag HEAP_HASEXTERNAL not set" ,
1387
+ toast_pointer . va_valueid ));
1380
1388
return true;
1381
1389
}
1382
1390
1383
1391
/* The relation better have a toast table */
1384
1392
if (!ctx -> rel -> rd_rel -> reltoastrelid )
1385
1393
{
1386
1394
report_corruption (ctx ,
1387
- psprintf ("attribute %u is external but relation has no toast relation" ,
1388
- ctx -> attnum ));
1395
+ psprintf ("toast value %u is external but relation has no toast relation" ,
1396
+ toast_pointer . va_valueid ));
1389
1397
return true;
1390
1398
}
1391
1399
@@ -1464,12 +1472,13 @@ check_toasted_attribute(HeapCheckContext *ctx, ToastedAttribute *ta)
1464
1472
1465
1473
if (!found_toasttup )
1466
1474
report_toast_corruption (ctx , ta ,
1467
- psprintf ("toasted value for attribute %u missing from toast table" ,
1468
- ta -> attnum ));
1475
+ psprintf ("toast value %u not found in toast table" ,
1476
+ ta -> toast_pointer . va_valueid ));
1469
1477
else if (chunkno != (endchunk + 1 ))
1470
1478
report_toast_corruption (ctx , ta ,
1471
- psprintf ("final toast chunk number %u differs from expected value %u" ,
1472
- chunkno , (endchunk + 1 )));
1479
+ psprintf ("toast value %u was expected to end at chunk %u, but ended at chunk %u" ,
1480
+ ta -> toast_pointer .va_valueid ,
1481
+ (endchunk + 1 ), chunkno ));
1473
1482
}
1474
1483
1475
1484
/*
0 commit comments