* tuple_data_split_internal * * Split raw tuple data taken directly from a page into an array of bytea * elements. This routine does a lookup on NULL values and creates array * elements accordingly. This is a reimplementation of nocachegetattr() * in heaptuple.c simplified for educational purposes. */
| 301 | * in heaptuple.c simplified for educational purposes. |
| 302 | */ |
| 303 | static Datum |
| 304 | tuple_data_split_internal(Oid relid, char *tupdata, |
| 305 | uint16 tupdata_len, uint16 t_infomask, |
| 306 | uint16 t_infomask2, bits8 *t_bits, |
| 307 | bool do_detoast) |
| 308 | { |
| 309 | ArrayBuildState *raw_attrs; |
| 310 | int nattrs; |
| 311 | int i; |
| 312 | int off = 0; |
| 313 | Relation rel; |
| 314 | TupleDesc tupdesc; |
| 315 | |
| 316 | /* Get tuple descriptor from relation OID */ |
| 317 | rel = relation_open(relid, AccessShareLock); |
| 318 | tupdesc = RelationGetDescr(rel); |
| 319 | |
| 320 | raw_attrs = initArrayResult(BYTEAOID, CurrentMemoryContext, false); |
| 321 | nattrs = tupdesc->natts; |
| 322 | |
| 323 | if (rel->rd_rel->relam != HEAP_TABLE_AM_OID) |
| 324 | ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 325 | errmsg("only heap AM is supported"))); |
| 326 | |
| 327 | if (nattrs < (t_infomask2 & HEAP_NATTS_MASK)) |
| 328 | ereport(ERROR, |
| 329 | (errcode(ERRCODE_DATA_CORRUPTED), |
| 330 | errmsg("number of attributes in tuple header is greater than number of attributes in tuple descriptor"))); |
| 331 | |
| 332 | for (i = 0; i < nattrs; i++) |
| 333 | { |
| 334 | Form_pg_attribute attr; |
| 335 | bool is_null; |
| 336 | bytea *attr_data = NULL; |
| 337 | |
| 338 | attr = TupleDescAttr(tupdesc, i); |
| 339 | |
| 340 | /* |
| 341 | * Tuple header can specify fewer attributes than tuple descriptor as |
| 342 | * ALTER TABLE ADD COLUMN without DEFAULT keyword does not actually |
| 343 | * change tuples in pages, so attributes with numbers greater than |
| 344 | * (t_infomask2 & HEAP_NATTS_MASK) should be treated as NULL. |
| 345 | */ |
| 346 | if (i >= (t_infomask2 & HEAP_NATTS_MASK)) |
| 347 | is_null = true; |
| 348 | else |
| 349 | is_null = (t_infomask & HEAP_HASNULL) && att_isnull(i, t_bits); |
| 350 | |
| 351 | if (!is_null) |
| 352 | { |
| 353 | int len; |
| 354 | |
| 355 | if (attr->attlen == -1) |
| 356 | { |
| 357 | off = att_align_pointer(off, attr->attalign, -1, |
| 358 | tupdata + off); |
| 359 | |
| 360 | /* |
no test coverage detected