PostgreSQL Source Code: src/backend/access/heap/heaptoast.c Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

26

33#include "utils/fmgroids.h"

34

35

36

37

38

39

40

41

42void

44{

48

49

50

51

52

53 Assert(rel->rd_rel->relkind == RELKIND_RELATION ||

54 rel->rd_rel->relkind == RELKIND_MATVIEW);

55

56

57

58

59

60

61

62

63

64

65

66

67 tupleDesc = rel->rd_att;

68

71

72

74}

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

98{

101 int numAttrs;

102

103 Size maxDataLen;

105

112

113

114

115

116

117

118

119 options &= ~HEAP_INSERT_SPECULATIVE;

120

121

122

123

124

125 Assert(rel->rd_rel->relkind == RELKIND_RELATION ||

126 rel->rd_rel->relkind == RELKIND_MATVIEW);

127

128

129

130

131 tupleDesc = rel->rd_att;

132 numAttrs = tupleDesc->natts;

133

135 heap_deform_tuple(newtup, tupleDesc, toast_values, toast_isnull);

136 if (oldtup != NULL)

137 heap_deform_tuple(oldtup, tupleDesc, toast_oldvalues, toast_oldisnull);

138

139

140

141

142

146 if (oldtup == NULL)

147 {

150 }

151 else

152 {

155 }

158

159

160

161

162

163

164

165

166

167

168

169

170

171

176

178

179

180

181

182

183

185 toast_values, toast_isnull) > maxDataLen)

186 {

187 int biggest_attno;

188

190 if (biggest_attno < 0)

191 break;

192

193

194

195

198 else

199 {

200

201

202

203

205 }

206

207

208

209

210

211

212

213

214

215 if (toast_attr[biggest_attno].tai_size > maxDataLen &&

218 }

219

220

221

222

223

224

226 toast_values, toast_isnull) > maxDataLen &&

228 {

229 int biggest_attno;

230

232 if (biggest_attno < 0)

233 break;

235 }

236

237

238

239

240

242 toast_values, toast_isnull) > maxDataLen)

243 {

244 int biggest_attno;

245

247 if (biggest_attno < 0)

248 break;

249

251 }

252

253

254

255

256

257

259

261 toast_values, toast_isnull) > maxDataLen &&

263 {

264 int biggest_attno;

265

267 if (biggest_attno < 0)

268 break;

269

271 }

272

273

274

275

276

278 {

281 int32 new_header_len;

282 int32 new_data_len;

283 int32 new_tuple_len;

284

285

286

287

288

289

290

291

292

293

294

297 new_header_len += BITMAPLEN(numAttrs);

298 new_header_len = MAXALIGN(new_header_len);

300 toast_values, toast_isnull);

301 new_tuple_len = new_header_len + new_data_len;

302

303

304

305

307 result_tuple->t_len = new_tuple_len;

311 result_tuple->t_data = new_data;

312

313

314

315

318 new_data->t_hoff = new_header_len;

319

320

322 toast_values,

323 toast_isnull,

324 (char *) new_data + new_header_len,

325 new_data_len,

328 new_data->t_bits : NULL);

329 }

330 else

331 result_tuple = newtup;

332

334

335 return result_tuple;

336}

337

338

339

340

341

342

343

344

345

346

347

348

351{

353 int numAttrs = tupleDesc->natts;

354 int i;

358

359

360

361

364

365 memset(toast_free, 0, numAttrs * sizeof(bool));

366

367 for (i = 0; i < numAttrs; i++)

368 {

369

370

371

373 {

374 struct varlena *new_value;

375

378 {

381 toast_free[i] = true;

382 }

383 }

384 }

385

386

387

388

389 new_tuple = heap_form_tuple(tupleDesc, toast_values, toast_isnull);

390

391

392

393

394

395

398

407

408

409

410

411 for (i = 0; i < numAttrs; i++)

412 if (toast_free[i])

414

415 return new_tuple;

416}

417

418

419

420

421

422

423

424

425

426

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445

446

447

452{

454 int32 new_header_len;

455 int32 new_data_len;

456 int32 new_tuple_len;

458 int numAttrs = tupleDesc->natts;

459 int i;

460 bool has_nulls = false;

464

465

466 tmptup.t_len = tup_len;

470

471

472

473

475 heap_deform_tuple(&tmptup, tupleDesc, toast_values, toast_isnull);

476

477 memset(toast_free, 0, numAttrs * sizeof(bool));

478

479 for (i = 0; i < numAttrs; i++)

480 {

481

482

483

484 if (toast_isnull[i])

485 has_nulls = true;

487 {

488 struct varlena *new_value;

489

493 {

496 toast_free[i] = true;

497 }

498 }

499 }

500

501

502

503

504

505

506

508 if (has_nulls)

509 new_header_len += BITMAPLEN(numAttrs);

510 new_header_len = MAXALIGN(new_header_len);

512 toast_values, toast_isnull);

513 new_tuple_len = new_header_len + new_data_len;

514

516

517

518

519

522 new_data->t_hoff = new_header_len;

523

524

528

529

531 toast_values,

532 toast_isnull,

533 (char *) new_data + new_header_len,

534 new_data_len,

536 has_nulls ? new_data->t_bits : NULL);

537

538

539

540

541 for (i = 0; i < numAttrs; i++)

542 if (toast_free[i])

544

546}

547

548

549

550

551

552

553

554

555

556

557

558

559

560

561

565 bool *isnull)

566{

568 int numAttrs = tupleDesc->natts;

569 int num_to_free;

570 int i;

573

574

575

576

577

579 memcpy(new_values, values, numAttrs * sizeof(Datum));

580

581 num_to_free = 0;

582 for (i = 0; i < numAttrs; i++)

583 {

584

585

586

588 {

589 struct varlena *new_value;

590

593 {

596 freeable_values[num_to_free++] = (Pointer) new_value;

597 }

598 }

599 }

600

601

602

603

604 new_tuple = heap_form_tuple(tupleDesc, new_values, isnull);

605

606

607

608

609 for (i = 0; i < num_to_free; i++)

610 pfree(freeable_values[i]);

611

612 return new_tuple;

613}

614

615

616

617

618

619

620

621

622

623

624

625void

627 int32 sliceoffset, int32 slicelength,

629{

633 int nscankeys;

636 int32 expectedchunk;

638 int startchunk;

639 int endchunk;

640 int num_indexes;

641 int validIndex;

642

643

646 &toastidxs,

647 &num_indexes);

648

651 Assert(endchunk <= totalchunks);

652

653

658

659

660

661

662

663 if (startchunk == 0 && endchunk == totalchunks - 1)

664 nscankeys = 1;

665 else if (startchunk == endchunk)

666 {

671 nscankeys = 2;

672 }

673 else

674 {

683 nscankeys = 3;

684 }

685

686

689

690

691

692

693

694

695 expectedchunk = startchunk;

697 {

700 bool isnull;

701 char *chunkdata;

703 int32 expected_size;

706

707

708

709

715 {

717 chunkdata = VARDATA(chunk);

718 }

720 {

721

724 }

725 else

726 {

727

728 elog(ERROR, "found toasted toast chunk for toast value %u in %s",

730 chunksize = 0;

731 chunkdata = NULL;

732 }

733

734

735

736

737 if (curchunk != expectedchunk)

740 errmsg_internal("unexpected chunk number %d (expected %d) for toast value %u in %s",

741 curchunk, expectedchunk, valueid,

743 if (curchunk > endchunk)

746 errmsg_internal("unexpected chunk number %d (out of range %d..%d) for toast value %u in %s",

747 curchunk,

748 startchunk, endchunk, valueid,

752 if (chunksize != expected_size)

755 errmsg_internal("unexpected chunk size %d (expected %d) in chunk %d of %d for toast value %u in %s",

756 chunksize, expected_size,

757 curchunk, totalchunks, valueid,

759

760

761

762

763 chcpystrt = 0;

764 chcpyend = chunksize - 1;

765 if (curchunk == startchunk)

767 if (curchunk == endchunk)

769

772 chunkdata + chcpystrt,

773 (chcpyend - chcpystrt) + 1);

774

775 expectedchunk++;

776 }

777

778

779

780

781 if (expectedchunk != (endchunk + 1))

784 errmsg_internal("missing chunk number %d for toast value %u in %s",

785 expectedchunk, valueid,

787

788

791}

static Datum values[MAXATTR]

struct varlena * detoast_attr(struct varlena *attr)

struct varlena * detoast_external_attr(struct varlena *attr)

int errmsg_internal(const char *fmt,...)

int errcode(int sqlerrcode)

#define ereport(elevel,...)

SysScanDesc systable_beginscan_ordered(Relation heapRelation, Relation indexRelation, Snapshot snapshot, int nkeys, ScanKey key)

void systable_endscan_ordered(SysScanDesc sysscan)

HeapTuple systable_getnext_ordered(SysScanDesc sysscan, ScanDirection direction)

Assert(PointerIsAligned(start, uint64))

void heap_fetch_toast_slice(Relation toastrel, Oid valueid, int32 attrsize, int32 sliceoffset, int32 slicelength, struct varlena *result)

void heap_toast_delete(Relation rel, HeapTuple oldtup, bool is_speculative)

HeapTuple heap_toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, int options)

HeapTuple toast_build_flattened_tuple(TupleDesc tupleDesc, Datum *values, bool *isnull)

HeapTuple toast_flatten_tuple(HeapTuple tup, TupleDesc tupleDesc)

Datum toast_flatten_tuple_to_datum(HeapTupleHeader tup, uint32 tup_len, TupleDesc tupleDesc)

#define TOAST_TUPLE_TARGET

#define TOAST_TUPLE_TARGET_MAIN

#define TOAST_MAX_CHUNK_SIZE

Size heap_compute_data_size(TupleDesc tupleDesc, const Datum *values, const bool *isnull)

HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)

void heap_fill_tuple(TupleDesc tupleDesc, const Datum *values, const bool *isnull, char *data, Size data_size, uint16 *infomask, bits8 *bit)

void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)

HeapTupleData * HeapTuple

HeapTupleHeaderData * HeapTupleHeader

#define SizeofHeapTupleHeader

static void HeapTupleHeaderSetTypMod(HeapTupleHeaderData *tup, int32 typmod)

static int BITMAPLEN(int NATTS)

static void HeapTupleHeaderSetTypeId(HeapTupleHeaderData *tup, Oid datum_typeid)

#define MaxTupleAttributeNumber

static void HeapTupleHeaderSetDatumLength(HeapTupleHeaderData *tup, uint32 len)

#define HeapTupleHeaderSetNatts(tup, natts)

#define MaxHeapAttributeNumber

static Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)

static void ItemPointerSetInvalid(ItemPointerData *pointer)

void pfree(void *pointer)

void * palloc0(Size size)

#define ERRCODE_DATA_CORRUPTED

static Datum PointerGetDatum(const void *X)

static Datum ObjectIdGetDatum(Oid X)

static Pointer DatumGetPointer(Datum X)

static Datum Int32GetDatum(int32 X)

static int32 DatumGetInt32(Datum X)

#define RelationGetRelationName(relation)

#define RelationGetToastTupleTarget(relation, defaulttarg)

void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)

#define BTEqualStrategyNumber

#define BTLessEqualStrategyNumber

#define BTGreaterEqualStrategyNumber

void toast_tuple_init(ToastTupleContext *ttc)

void toast_delete_external(Relation rel, const Datum *values, const bool *isnull, bool is_speculative)

void toast_tuple_try_compression(ToastTupleContext *ttc, int attribute)

void toast_tuple_externalize(ToastTupleContext *ttc, int attribute, int options)

void toast_tuple_cleanup(ToastTupleContext *ttc)

int toast_tuple_find_biggest_attribute(ToastTupleContext *ttc, bool for_compression, bool check_main)

#define TOAST_NEEDS_CHANGE

#define TOASTCOL_INCOMPRESSIBLE

void toast_close_indexes(Relation *toastidxs, int num_indexes, LOCKMODE lock)

int toast_open_indexes(Relation toastrel, LOCKMODE lock, Relation **toastidxs, int *num_indexes)

Snapshot get_toast_snapshot(void)

static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)

static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)

#define VARSIZE_SHORT(PTR)

#define VARATT_IS_EXTENDED(PTR)

#define VARATT_IS_SHORT(PTR)

#define VARATT_IS_COMPRESSED(PTR)

#define VARATT_IS_EXTERNAL(PTR)

#define VARDATA_SHORT(PTR)