PostgreSQL Source Code: src/backend/access/common/heaptuple.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

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

59

68

69

70

71

72

73

74

75

76

77

78

79

80#define ATT_IS_PACKABLE(att) \

81 ((att)->attlen == -1 && (att)->attstorage != TYPSTORAGE_PLAIN)

82

83#define VARLENA_ATT_IS_PACKABLE(att) \

84 ((att)->attstorage != TYPSTORAGE_PLAIN)

85

86

87#define COMPACT_ATTR_IS_PACKABLE(att) \

88 ((att)->attlen == -1 && (att)->attispackable)

89

90

91

92

93

94

95typedef struct

96{

100

102

105{

107

109}

110

111static int

113{

116

117 if (entry1->len != entry2->len)

118 return entry1->len > entry2->len ? 1 : -1;

119

122 entry1->len);

123}

124

125static void

127{

129

137 32,

138 &hash_ctl,

140}

141

142

143

144

145

146

147

148

149

152 int attnum, bool *isnull)

153{

155

156 Assert(attnum <= tupleDesc->natts);

158

160

162 {

164

167

169

171 {

174 bool found;

176

177 *isnull = false;

178

179

182

183

186

187

191 else

194

196

197 if (!found)

198 {

199

204 }

205

206 return entry->value;

207 }

208 }

209

210 *isnull = true;

212}

213

214

215

216

217

221 const bool *isnull)

222{

223 Size data_length = 0;

224 int i;

225 int numberOfAttributes = tupleDesc->natts;

226

227 for (i = 0; i < numberOfAttributes; i++)

228 {

231

232 if (isnull[i])

233 continue;

234

237

240 {

241

242

243

244

246 }

247 else if (atti->attlen == -1 &&

249 {

250

251

252

253

256 }

257 else

258 {

263 }

264 }

265

266 return data_length;

267}

268

269

270

271

272

273

274static inline void

277 int *bitmask,

278 char **dataP,

281 bool isnull)

282{

283 Size data_length;

284 char *data = *dataP;

285

286

287

288

289

290 if (bit != NULL)

291 {

293 *bitmask <<= 1;

294 else

295 {

296 *bit += 1;

297 **bit = 0x0;

298 *bitmask = 1;

299 }

300

301 if (isnull)

302 {

304 return;

305 }

306

307 **bit |= *bitmask;

308 }

309

310

311

312

313

315 {

316

319 data_length = att->attlen;

320 }

321 else if (att->attlen == -1)

322 {

323

325

328 {

330 {

331

332

333

334

336

340 }

341 else

342 {

344

346 memcpy(data, val, data_length);

347 }

348 }

350 {

351

353 memcpy(data, val, data_length);

354 }

356 {

357

361 }

362 else

363 {

364

367 memcpy(data, val, data_length);

368 }

369 }

370 else if (att->attlen == -2)

371 {

372

377 }

378 else

379 {

380

383 data_length = att->attlen;

385 }

386

387 data += data_length;

388 *dataP = data;

389}

390

391

392

393

394

395

396

397

398

399

400void

405{

407 int bitmask;

408 int i;

409 int numberOfAttributes = tupleDesc->natts;

410

411#ifdef USE_ASSERT_CHECKING

413#endif

414

415 if (bit != NULL)

416 {

417 bitP = &bit[-1];

419 }

420 else

421 {

422

423 bitP = NULL;

424 bitmask = 0;

425 }

426

428

429 for (i = 0; i < numberOfAttributes; i++)

430 {

432

434 bitP ? &bitP : NULL,

435 &bitmask,

437 infomask,

439 isnull ? isnull[i] : true);

440 }

441

443}

444

445

446

447

448

449

450

451

452

453

454

455bool

457{

458

459

460

461

462 Assert(!tupleDesc || attnum <= tupleDesc->natts);

464 {

465 if (tupleDesc &&

467 return false;

468 else

469 return true;

470 }

471

473 {

475 return false;

477 }

478

480 {

487

488 break;

489

490 default:

492 }

493

494 return false;

495}

496

497

498

499

500

501

502

503

504

505

506

507

508

509

510

511

512

513

514

515

516

517

518

519

524{

526 char *tp;

527 bits8 *bp = td->t_bits;

528 bool slow = false;

529 int off;

530

531

532

533

534

535

536

537

538

539

541

543 {

544

545

546

547

548

549 int byte = attnum >> 3;

550 int finalbit = attnum & 0x07;

551

552

553 if ((~bp[byte]) & ((1 << finalbit) - 1))

554 slow = true;

555 else

556 {

557

558 int i;

559

560 for (i = 0; i < byte; i++)

561 {

562 if (bp[i] != 0xFF)

563 {

564 slow = true;

565 break;

566 }

567 }

568 }

569 }

570

571 tp = (char *) td + td->t_hoff;

572

573 if (!slow)

574 {

576

577

578

579

580

584

585

586

587

588

589

591 {

592 int j;

593

595 {

597 {

598 slow = true;

599 break;

600 }

601 }

602 }

603 }

604

605 if (!slow)

606 {

607 int natts = tupleDesc->natts;

608 int j = 1;

609

610

611

612

613

614

615

616

617

618

620

621

623 j++;

624

627

628 for (; j < natts; j++)

629 {

631

632 if (att->attlen <= 0)

633 break;

634

636

638

640 }

641

643

645 }

646 else

647 {

648 bool usecache = true;

649 int i;

650

651

652

653

654

655

656

657

658

659

660

661 off = 0;

662 for (i = 0;; i++)

663 {

665

667 {

668 usecache = false;

669 continue;

670 }

671

672

675 else if (att->attlen == -1)

676 {

677

678

679

680

681

682

683 if (usecache &&

686 else

687 {

689 tp + off);

690 usecache = false;

691 }

692 }

693 else

694 {

695

697

698 if (usecache)

700 }

701

703 break;

704

706

707 if (usecache && att->attlen <= 0)

708 usecache = false;

709 }

710 }

711

713}

714

715

716

717

718

719

720

721

722

723

726{

728

730

731

732 *isnull = false;

733

735 {

737

739 break;

742 break;

745 break;

748

749

750

751

752

753

754

756 break;

759 break;

760 default:

762 result = 0;

763 break;

764 }

765 return result;

766}

767

768

769

770

771

772

773

774

775

776

779{

781

783 return NULL;

784

791 return newTuple;

792}

793

794

795

796

797

798

799

800

801

802

803void

805{

807 {

808 dest->t_data = NULL;

809 return;

810 }

811

817}

818

819

820

821

822

823

824

825

826

827

828

829static void

834{

837 int firstmissingnum;

842 int natts = tupleDesc->natts;

843 int sourceNullLen;

844 int targetNullLen;

845 Size sourceDataLen = sourceTuple->t_len - sourceTHeader->t_hoff;

846 Size targetDataLen;

848 int hoff;

849 bits8 *nullBits = NULL;

850 int bitMask = 0;

851 char *targetData;

853

854 Assert((targetHeapTuple && !targetMinimalTuple)

855 || (!targetHeapTuple && targetMinimalTuple));

856

857 Assert(sourceNatts < natts);

858

859 sourceNullLen = (hasNulls ? BITMAPLEN(sourceNatts) : 0);

860

861 targetDataLen = sourceDataLen;

862

863 if (tupleDesc->constr &&

865 {

866

867

868

869

870

872

873

874

875

876

877 for (firstmissingnum = sourceNatts;

878 firstmissingnum < natts;

879 firstmissingnum++)

880 {

881 if (attrmiss[firstmissingnum].am_present)

882 break;

883 else

884 hasNulls = true;

885 }

886

887

888

889

890

891 for (attnum = firstmissingnum;

894 {

895 if (attrmiss[attnum].am_present)

896 {

898

903

907 }

908 else

909 {

910

911 hasNulls = true;

912 }

913 }

914 }

915 else

916 {

917

918

919

920

921 hasNulls = true;

922 }

923

925

926 if (hasNulls)

927 {

928 targetNullLen = BITMAPLEN(natts);

929 len += targetNullLen;

930 }

931 else

932 targetNullLen = 0;

933

934

935

936

937

938 if (targetHeapTuple)

939 {

941 hoff = len = MAXALIGN(len);

942 len += targetDataLen;

943

945 (*targetHeapTuple)->t_data

946 = targetTHeader

948 (*targetHeapTuple)->t_len = len;

949 (*targetHeapTuple)->t_tableOid = sourceTuple->t_tableOid;

950 (*targetHeapTuple)->t_self = sourceTuple->t_self;

951

953 targetTHeader->t_hoff = hoff;

958

960 if (targetNullLen > 0)

961 nullBits = (bits8 *) ((char *) (*targetHeapTuple)->t_data

963 targetData = (char *) (*targetHeapTuple)->t_data + hoff;

964 infoMask = &(targetTHeader->t_infomask);

965 }

966 else

967 {

969 hoff = len = MAXALIGN(len);

970 len += targetDataLen;

971

973 (*targetMinimalTuple)->t_len = len;

975 (*targetMinimalTuple)->t_infomask = sourceTHeader->t_infomask;

976

978 if (targetNullLen > 0)

979 nullBits = (bits8 *) ((char *) *targetMinimalTuple

981 targetData = (char *) *targetMinimalTuple + hoff;

982 infoMask = &((*targetMinimalTuple)->t_infomask);

983 }

984

985 if (targetNullLen > 0)

986 {

987 if (sourceNullLen > 0)

988 {

989

990 memcpy(nullBits,

991 ((char *) sourceTHeader)

993 sourceNullLen);

994 nullBits += sourceNullLen - 1;

995 }

996 else

997 {

998 sourceNullLen = BITMAPLEN(sourceNatts);

999

1000 memset(nullBits, 0xff, sourceNullLen);

1001

1002 nullBits += sourceNullLen - 1;

1003

1004 if (sourceNatts & 0x07)

1005 {

1006

1007 bitMask = 0xff << (sourceNatts & 0x07);

1008

1009 *nullBits = ~bitMask;

1010 }

1011 }

1012

1013 bitMask = (1 << ((sourceNatts - 1) & 0x07));

1014 }

1015

1016 memcpy(targetData,

1017 ((char *) sourceTuple->t_data) + sourceTHeader->t_hoff,

1018 sourceDataLen);

1019

1020 targetData += sourceDataLen;

1021

1022

1024 {

1026

1027 if (attrmiss && attrmiss[attnum].am_present)

1028 {

1030 nullBits ? &nullBits : NULL,

1031 &bitMask,

1032 &targetData,

1033 infoMask,

1034 attrmiss[attnum].am_value,

1035 false);

1036 }

1037 else

1038 {

1040 &nullBits,

1041 &bitMask,

1042 &targetData,

1043 infoMask,

1045 true);

1046 }

1047 }

1048}

1049

1050

1051

1052

1055{

1057

1058 expand_tuple(NULL, &minimalTuple, sourceTuple, tupleDesc);

1059 return minimalTuple;

1060}

1061

1062

1063

1064

1067{

1069

1070 expand_tuple(&heapTuple, NULL, sourceTuple, tupleDesc);

1071 return heapTuple;

1072}

1073

1074

1075

1076

1077

1078

1079

1082{

1084

1085

1086

1087

1088

1092 tupleDesc);

1093

1094

1095

1096

1097

1098

1100 memcpy(td, tuple->t_data, tuple->t_len);

1101

1105

1107}

1108

1109

1110

1111

1112

1113

1114

1115

1119 const bool *isnull)

1120{

1121 HeapTuple tuple;

1124 data_len;

1125 int hoff;

1126 bool hasnull = false;

1127 int numberOfAttributes = tupleDescriptor->natts;

1128 int i;

1129

1132 (errcode(ERRCODE_TOO_MANY_COLUMNS),

1133 errmsg("number of columns (%d) exceeds limit (%d)",

1135

1136

1137

1138

1139 for (i = 0; i < numberOfAttributes; i++)

1140 {

1141 if (isnull[i])

1142 {

1143 hasnull = true;

1144 break;

1145 }

1146 }

1147

1148

1149

1150

1152

1153 if (hasnull)

1155

1156 hoff = len = MAXALIGN(len);

1157

1159

1160 len += data_len;

1161

1162

1163

1164

1165

1168

1169

1170

1171

1172

1173

1177

1181

1183

1186

1189 isnull,

1190 (char *) td + hoff,

1191 data_len,

1193 (hasnull ? td->t_bits : NULL));

1194

1195 return tuple;

1196}

1197

1198

1199

1200

1201

1202

1203

1204

1205

1206

1207

1208

1212 const Datum *replValues,

1213 const bool *replIsnull,

1214 const bool *doReplace)

1215{

1216 int numberOfAttributes = tupleDesc->natts;

1217 int attoff;

1219 bool *isnull;

1221

1222

1223

1224

1225

1226

1227

1228

1229

1230

1231

1232

1234 isnull = palloc_array(bool, numberOfAttributes);

1235

1237

1238 for (attoff = 0; attoff < numberOfAttributes; attoff++)

1239 {

1240 if (doReplace[attoff])

1241 {

1242 values[attoff] = replValues[attoff];

1243 isnull[attoff] = replIsnull[attoff];

1244 }

1245 }

1246

1247

1248

1249

1251

1254

1255

1256

1257

1261

1262 return newTuple;

1263}

1264

1265

1266

1267

1268

1269

1270

1271

1272

1273

1274

1275

1276

1280 int nCols,

1281 const int *replCols,

1282 const Datum *replValues,

1283 const bool *replIsnull)

1284{

1285 int numberOfAttributes = tupleDesc->natts;

1287 bool *isnull;

1289 int i;

1290

1291

1292

1293

1294

1296 isnull = palloc_array(bool, numberOfAttributes);

1297

1299

1300 for (i = 0; i < nCols; i++)

1301 {

1302 int attnum = replCols[i];

1303

1304 if (attnum <= 0 || attnum > numberOfAttributes)

1307 isnull[attnum - 1] = replIsnull[i];

1308 }

1309

1310

1311

1312

1314

1317

1318

1319

1320

1324

1325 return newTuple;

1326}

1327

1328

1329

1330

1331

1332

1333

1334

1335

1336

1337

1338

1339

1340

1341

1342

1343

1344

1345void

1348{

1351 int tdesc_natts = tupleDesc->natts;

1352 int natts;

1354 char *tp;

1355 uint32 off;

1356 bits8 *bp = tup->t_bits;

1357 bool slow = false;

1358

1360

1361

1362

1363

1364

1365

1366 natts = Min(natts, tdesc_natts);

1367

1368 tp = (char *) tup + tup->t_hoff;

1369

1370 off = 0;

1371

1373 {

1375

1377 {

1379 isnull[attnum] = true;

1380 slow = true;

1381 continue;

1382 }

1383

1384 isnull[attnum] = false;

1385

1388 else if (thisatt->attlen == -1)

1389 {

1390

1391

1392

1393

1394

1395

1396 if (!slow &&

1399 else

1400 {

1402 tp + off);

1403 slow = true;

1404 }

1405 }

1406 else

1407 {

1408

1410

1411 if (!slow)

1412 thisatt->attcacheoff = off;

1413 }

1414

1416

1418

1419 if (thisatt->attlen <= 0)

1420 slow = true;

1421 }

1422

1423

1424

1425

1426

1429}

1430

1431

1432

1433

1434void

1436{

1438}

1439

1440

1441

1442

1443

1444

1445

1446

1447

1448

1449

1450

1451

1455 const bool *isnull,

1457{

1459 char *mem;

1461 data_len;

1462 int hoff;

1463 bool hasnull = false;

1464 int numberOfAttributes = tupleDescriptor->natts;

1465 int i;

1466

1468

1471 (errcode(ERRCODE_TOO_MANY_COLUMNS),

1472 errmsg("number of columns (%d) exceeds limit (%d)",

1474

1475

1476

1477

1478 for (i = 0; i < numberOfAttributes; i++)

1479 {

1480 if (isnull[i])

1481 {

1482 hasnull = true;

1483 break;

1484 }

1485 }

1486

1487

1488

1489

1491

1492 if (hasnull)

1494

1495 hoff = len = MAXALIGN(len);

1496

1498

1499 len += data_len;

1500

1501

1502

1503

1506

1507

1508

1509

1513

1516 isnull,

1517 (char *) tuple + hoff,

1518 data_len,

1520 (hasnull ? tuple->t_bits : NULL));

1521

1522 return tuple;

1523}

1524

1525

1526

1527

1528void

1530{

1532}

1533

1534

1535

1536

1537

1538

1539

1542{

1544 char *mem;

1545

1548 memset(mem, 0, extra);

1550 memcpy(result, mtup, mtup->t_len);

1551 return result;

1552}

1553

1554

1555

1556

1557

1558

1559

1560

1561

1562

1565{

1568

1576 return result;

1577}

1578

1579

1580

1581

1582

1583

1584

1587{

1589 char *mem;

1591

1596 memset(mem, 0, extra);

1599

1601 return result;

1602}

1603

1604

1605

1606

1607

1608size_t

1610{

1612}

static Datum values[MAXATTR]

Datum datumCopy(Datum value, bool typByVal, int typLen)

void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)

HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)

int errcode(int sqlerrcode)

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

#define ereport(elevel,...)

ExpandedObjectHeader * DatumGetEOHP(Datum d)

void EOH_flatten_into(ExpandedObjectHeader *eohptr, void *result, Size allocated_size)

Size EOH_get_flat_size(ExpandedObjectHeader *eohptr)

#define palloc_array(type, count)

uint32 hash_bytes(const unsigned char *k, int keylen)

Assert(PointerIsAligned(start, uint64))

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

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

static uint32 missing_hash(const void *key, Size keysize)

HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)

void heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest)

HeapTuple heap_copytuple(HeapTuple tuple)

size_t varsize_any(void *p)

MinimalTuple heap_copy_minimal_tuple(MinimalTuple mtup, Size extra)

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

MinimalTuple heap_form_minimal_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull, Size extra)

HeapTuple heap_modify_tuple_by_cols(HeapTuple tuple, TupleDesc tupleDesc, int nCols, const int *replCols, const Datum *replValues, const bool *replIsnull)

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

void heap_free_minimal_tuple(MinimalTuple mtup)

bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)

Datum nocachegetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc)

Datum getmissingattr(TupleDesc tupleDesc, int attnum, bool *isnull)

MinimalTuple minimal_tuple_from_heap_tuple(HeapTuple htup, Size extra)

HeapTuple heap_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc)

static void fill_val(CompactAttribute *att, bits8 **bit, int *bitmask, char **dataP, uint16 *infomask, Datum datum, bool isnull)

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

#define COMPACT_ATTR_IS_PACKABLE(att)

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

static void init_missing_cache(void)

static int missing_match(const void *key1, const void *key2, Size keysize)

Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)

static HTAB * missing_cache

static void expand_tuple(HeapTuple *targetHeapTuple, MinimalTuple *targetMinimalTuple, HeapTuple sourceTuple, TupleDesc tupleDesc)

HeapTuple heap_tuple_from_minimal_tuple(MinimalTuple mtup)

MinimalTuple minimal_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc)

void heap_freetuple(HeapTuple htup)

HeapTupleData * HeapTuple

MinimalTupleData * MinimalTuple

HeapTupleHeaderData * HeapTupleHeader

#define HeapTupleIsValid(tuple)

#define MINIMAL_TUPLE_OFFSET

#define HeapTupleHeaderGetNatts(tup)

static void HeapTupleHeaderSetTypMod(HeapTupleHeaderData *tup, int32 typmod)

static bool HeapTupleHasNulls(const HeapTupleData *tuple)

static int BITMAPLEN(int NATTS)

static bool HeapTupleHasExternal(const HeapTupleData *tuple)

#define SizeofMinimalTupleHeader

static void HeapTupleHeaderSetTypeId(HeapTupleHeaderData *tup, Oid datum_typeid)

static CommandId HeapTupleHeaderGetRawCommandId(const HeapTupleHeaderData *tup)

static TransactionId HeapTupleHeaderGetRawXmax(const HeapTupleHeaderData *tup)

#define MaxTupleAttributeNumber

static bool HeapTupleNoNulls(const HeapTupleData *tuple)

static void HeapTupleHeaderSetDatumLength(HeapTupleHeaderData *tup, uint32 len)

static TransactionId HeapTupleHeaderGetRawXmin(const HeapTupleHeaderData *tup)

#define HeapTupleHeaderSetNatts(tup, natts)

static bool HeapTupleHasVarWidth(const HeapTupleData *tuple)

if(TABLE==NULL||TABLE_index==NULL)

static void ItemPointerSetInvalid(ItemPointerData *pointer)

void pfree(void *pointer)

void * palloc0(Size size)

MemoryContext TopMemoryContext

static MemoryContext MemoryContextSwitchTo(MemoryContext context)

static Datum PointerGetDatum(const void *X)

static Datum TransactionIdGetDatum(TransactionId X)

static Datum CommandIdGetDatum(CommandId X)

static Datum ObjectIdGetDatum(Oid X)

static char * DatumGetCString(Datum X)

static Pointer DatumGetPointer(Datum X)

bits8 t_bits[FLEXIBLE_ARRAY_MEMBER]

struct AttrMissing * missing

#define MinTransactionIdAttributeNumber

#define MaxCommandIdAttributeNumber

#define MaxTransactionIdAttributeNumber

#define TableOidAttributeNumber

#define SelfItemPointerAttributeNumber

#define MinCommandIdAttributeNumber

static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)

#define att_nominal_alignby(cur_offset, attalignby)

#define att_datum_alignby(cur_offset, attalignby, attlen, attdatum)

static bool att_isnull(int ATT, const bits8 *BITS)

#define att_addlength_pointer(cur_offset, attlen, attptr)

#define att_pointer_alignby(cur_offset, attalignby, attlen, attptr)

#define att_addlength_datum(cur_offset, attlen, attdatum)

static void store_att_byval(void *T, Datum newdatum, int attlen)

static bool VARATT_IS_SHORT(const void *PTR)

static Size VARSIZE_ANY(const void *PTR)

static bool VARATT_CAN_MAKE_SHORT(const void *PTR)

static bool VARATT_IS_EXTERNAL(const void *PTR)

static Size VARSIZE(const void *PTR)

static char * VARDATA(const void *PTR)

static Size VARATT_CONVERTED_SHORT_SIZE(const void *PTR)

static Size VARSIZE_EXTERNAL(const void *PTR)

static bool VARATT_IS_EXTERNAL_EXPANDED(const void *PTR)

static void SET_VARSIZE_SHORT(void *PTR, Size len)

static Size VARSIZE_SHORT(const void *PTR)

Datum bit(PG_FUNCTION_ARGS)