diff options
Diffstat (limited to 'src/backend/access/heap/tuptoaster.c')
-rw-r--r-- | src/backend/access/heap/tuptoaster.c | 262 |
1 files changed, 106 insertions, 156 deletions
diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c index d0e60681e77..c271b08f703 100644 --- a/src/backend/access/heap/tuptoaster.c +++ b/src/backend/access/heap/tuptoaster.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.18 2001/03/22 03:59:13 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.19 2001/03/22 06:16:07 momjian Exp $ * * * INTERFACE ROUTINES @@ -81,17 +81,18 @@ heap_tuple_fetch_attr(varattrib *attr) if (VARATT_IS_EXTERNAL(attr)) { - /* ---------- + + /* * This is an external stored plain value - * ---------- */ result = toast_fetch_datum(attr); } else { - /* ---------- - * This is a plain value inside of the main tuple - why am I called? - * ---------- + + /* + * This is a plain value inside of the main tuple - why am I + * called? */ result = attr; } @@ -134,18 +135,18 @@ heap_tuple_untoast_attr(varattrib *attr) } else { - /* ---------- + + /* * This is an external stored plain value - * ---------- */ result = toast_fetch_datum(attr); } } else if (VARATT_IS_COMPRESSED(attr)) { - /* ---------- + + /* * This is a compressed value inside of the main tuple - * ---------- */ result = (varattrib *) palloc(attr->va_content.va_compressed.va_rawsize + VARHDRSZ); @@ -154,9 +155,10 @@ heap_tuple_untoast_attr(varattrib *attr) pglz_decompress((PGLZ_Header *) attr, VARATT_DATA(result)); } else - /* ---------- - * This is a plain value inside of the main tuple - why am I called? - * ---------- + + /* + * This is a plain value inside of the main tuple - why am I + * called? */ return attr; @@ -180,19 +182,16 @@ toast_delete(Relation rel, HeapTuple oldtup) Datum value; bool isnull; - /* ---------- - * Get the tuple descriptor, the number of and attribute - * descriptors. - * ---------- + /* + * Get the tuple descriptor, the number of and attribute descriptors. */ tupleDesc = rel->rd_att; numAttrs = tupleDesc->natts; att = tupleDesc->attrs; - /* ---------- - * Check for external stored attributes and delete them - * from the secondary relation. - * ---------- + /* + * Check for external stored attributes and delete them from the + * secondary relation. */ for (i = 0; i < numAttrs; i++) { @@ -237,10 +236,9 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) bool toast_free[MaxHeapAttributeNumber]; bool toast_delold[MaxHeapAttributeNumber]; - /* ---------- - * Get the tuple descriptor, the number of and attribute - * descriptors and the location of the tuple values. - * ---------- + /* + * Get the tuple descriptor, the number of and attribute descriptors + * and the location of the tuple values. */ tupleDesc = rel->rd_att; numAttrs = tupleDesc->natts; @@ -266,9 +264,9 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) if (oldtup != NULL) { - /* ---------- + + /* * For UPDATE get the old and new values of this attribute - * ---------- */ old_value = (varattrib *) DatumGetPointer( heap_getattr(oldtup, i + 1, tupleDesc, &old_isnull)); @@ -276,10 +274,9 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) heap_getattr(newtup, i + 1, tupleDesc, &new_isnull); new_value = (varattrib *) DatumGetPointer(toast_values[i]); - /* ---------- - * If the old value is an external stored one, check if it - * has changed so we have to delete it later. - * ---------- + /* + * If the old value is an external stored one, check if it has + * changed so we have to delete it later. */ if (!old_isnull && att[i]->attlen == -1 && VARATT_IS_EXTERNAL(old_value)) @@ -290,21 +287,21 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) old_value->va_content.va_external.va_attno != new_value->va_content.va_external.va_attno) { - /* ---------- - * The old external store value isn't needed any - * more after the update - * ---------- + + /* + * The old external store value isn't needed any more + * after the update */ toast_delold[i] = true; need_delold = true; } else { - /* ---------- - * This attribute isn't changed by this update - * so we reuse the original reference to the old - * value in the new tuple. - * ---------- + + /* + * This attribute isn't changed by this update so we + * reuse the original reference to the old value in + * the new tuple. */ toast_action[i] = 'p'; toast_sizes[i] = VARATT_SIZE(toast_values[i]); @@ -314,17 +311,16 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) } else { - /* ---------- + + /* * For INSERT simply get the new value - * ---------- */ toast_values[i] = heap_getattr(newtup, i + 1, tupleDesc, &new_isnull); } - /* ---------- + /* * Handle NULL attributes - * ---------- */ if (new_isnull) { @@ -334,24 +330,22 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) continue; } - /* ---------- + /* * Now look at varsize attributes - * ---------- */ if (att[i]->attlen == -1) { - /* ---------- + + /* * If the table's attribute says PLAIN always, force it so. - * ---------- */ if (att[i]->attstorage == 'p') toast_action[i] = 'p'; - /* ---------- + /* * We took care of UPDATE above, so any external value we find * still in the tuple must be someone else's we cannot reuse. * Expand it to plain (and, probably, toast it again below). - * ---------- */ if (VARATT_IS_EXTERNAL(DatumGetPointer(toast_values[i]))) { @@ -362,17 +356,16 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) need_free = true; } - /* ---------- + /* * Remember the size of this attribute - * ---------- */ toast_sizes[i] = VARATT_SIZE(DatumGetPointer(toast_values[i])); } else { - /* ---------- + + /* * Not a variable size attribute, plain storage always - * ---------- */ toast_action[i] = 'p'; toast_sizes[i] = att[i]->attlen; @@ -393,9 +386,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) maxDataLen += BITMAPLEN(numAttrs); maxDataLen = TOAST_TUPLE_TARGET - MAXALIGN(maxDataLen); - /* ---------- + /* * Look for attributes with attstorage 'x' to compress - * ---------- */ while (MAXALIGN(ComputeDataSize(tupleDesc, toast_values, toast_nulls)) > maxDataLen) @@ -405,9 +397,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) Datum old_value; Datum new_value; - /* ---------- + /* * Search for the biggest yet uncompressed internal attribute - * ---------- */ for (i = 0; i < numAttrs; i++) { @@ -427,9 +418,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) if (biggest_attno < 0) break; - /* ---------- + /* * Attempt to compress it inline - * ---------- */ i = biggest_attno; old_value = toast_values[i]; @@ -457,10 +447,9 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) } } - /* ---------- - * Second we look for attributes of attstorage 'x' or 'e' that - * are still inline. - * ---------- + /* + * Second we look for attributes of attstorage 'x' or 'e' that are + * still inline. */ while (MAXALIGN(ComputeDataSize(tupleDesc, toast_values, toast_nulls)) > maxDataLen && rel->rd_rel->reltoastrelid != InvalidOid) @@ -469,10 +458,9 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) int32 biggest_size = MAXALIGN(sizeof(varattrib)); Datum old_value; - /* ---------- - * Search for the biggest yet inlined attribute with - * attstorage = 'x' or 'e' - * ---------- + /* + * Search for the biggest yet inlined attribute with attstorage = + * 'x' or 'e' */ for (i = 0; i < numAttrs; i++) { @@ -492,9 +480,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) if (biggest_attno < 0) break; - /* ---------- + /* * Store this external - * ---------- */ i = biggest_attno; old_value = toast_values[i]; @@ -513,10 +500,9 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) need_free = true; } - /* ---------- - * Round 3 - this time we take attributes with storage - * 'm' into compression - * ---------- + /* + * Round 3 - this time we take attributes with storage 'm' into + * compression */ while (MAXALIGN(ComputeDataSize(tupleDesc, toast_values, toast_nulls)) > maxDataLen) @@ -526,9 +512,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) Datum old_value; Datum new_value; - /* ---------- + /* * Search for the biggest yet uncompressed internal attribute - * ---------- */ for (i = 0; i < numAttrs; i++) { @@ -548,9 +533,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) if (biggest_attno < 0) break; - /* ---------- + /* * Attempt to compress it inline - * ---------- */ i = biggest_attno; old_value = toast_values[i]; @@ -578,9 +562,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) } } - /* ---------- + /* * Finally we store attributes of type 'm' external - * ---------- */ while (MAXALIGN(ComputeDataSize(tupleDesc, toast_values, toast_nulls)) > maxDataLen && rel->rd_rel->reltoastrelid != InvalidOid) @@ -589,10 +572,9 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) int32 biggest_size = MAXALIGN(sizeof(varattrib)); Datum old_value; - /* ---------- - * Search for the biggest yet inlined attribute with - * attstorage = 'm' - * ---------- + /* + * Search for the biggest yet inlined attribute with attstorage = + * 'm' */ for (i = 0; i < numAttrs; i++) { @@ -612,9 +594,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) if (biggest_attno < 0) break; - /* ---------- + /* * Store this external - * ---------- */ i = biggest_attno; old_value = toast_values[i]; @@ -633,10 +614,9 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) need_free = true; } - /* ---------- - * In the case we toasted any values, we need to build - * a new heap tuple with the changed values. - * ---------- + /* + * In the case we toasted any values, we need to build a new heap + * tuple with the changed values. */ if (need_change) { @@ -645,9 +625,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) MemoryContext oldcxt; HeapTupleHeader olddata; - /* ---------- + /* * Calculate the new size of the tuple - * ---------- */ new_len = offsetof(HeapTupleHeaderData, t_bits); if (has_nulls) @@ -655,19 +634,17 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) new_len = MAXALIGN(new_len); new_len += ComputeDataSize(tupleDesc, toast_values, toast_nulls); - /* ---------- + /* * Remember the old memory location of the tuple (for below), - * switch to the memory context of the HeapTuple structure - * and allocate the new tuple. - * ---------- + * switch to the memory context of the HeapTuple structure and + * allocate the new tuple. */ olddata = newtup->t_data; oldcxt = MemoryContextSwitchTo(newtup->t_datamcxt); new_data = palloc(new_len); - /* ---------- + /* * Put the tuple header and the changed values into place - * ---------- */ memcpy(new_data, newtup->t_data, newtup->t_data->t_hoff); newtup->t_data = (HeapTupleHeader) new_data; @@ -682,33 +659,29 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) &(newtup->t_data->t_infomask), has_nulls ? newtup->t_data->t_bits : NULL); - /* ---------- - * In the case we modified a previously modified tuple again, - * free the memory from the previous run - * ---------- + /* + * In the case we modified a previously modified tuple again, free + * the memory from the previous run */ if ((char *) olddata != ((char *) newtup + HEAPTUPLESIZE)) pfree(olddata); - /* ---------- + /* * Switch back to the old memory context - * ---------- */ MemoryContextSwitchTo(oldcxt); } - /* ---------- + /* * Free allocated temp values - * ---------- */ if (need_free) for (i = 0; i < numAttrs; i++) if (toast_free[i]) pfree(DatumGetPointer(toast_values[i])); - /* ---------- + /* * Delete external values from the old tuple - * ---------- */ if (need_delold) for (i = 0; i < numAttrs; i++) @@ -776,9 +749,8 @@ toast_save_datum(Relation rel, Oid mainoid, int16 attno, Datum value) char *data_p; int32 data_todo; - /* ---------- + /* * Create the varattrib reference - * ---------- */ result = (varattrib *) palloc(sizeof(varattrib)); @@ -802,9 +774,8 @@ toast_save_datum(Relation rel, Oid mainoid, int16 attno, Datum value) result->va_content.va_external.va_rowid = mainoid; result->va_content.va_external.va_attno = attno; - /* ---------- + /* * Initialize constant parts of the tuple data - * ---------- */ t_values[0] = ObjectIdGetDatum(result->va_content.va_external.va_valueid); t_values[2] = PointerGetDatum(chunk_data); @@ -812,36 +783,32 @@ toast_save_datum(Relation rel, Oid mainoid, int16 attno, Datum value) t_nulls[1] = ' '; t_nulls[2] = ' '; - /* ---------- + /* * Get the data to process - * ---------- */ data_p = VARATT_DATA(value); data_todo = VARATT_SIZE(value) - VARHDRSZ; - /* ---------- + /* * Open the toast relation - * ---------- */ toastrel = heap_open(rel->rd_rel->reltoastrelid, RowExclusiveLock); toasttupDesc = toastrel->rd_att; toastidx = index_open(rel->rd_rel->reltoastidxid); - /* ---------- + /* * Split up the item into chunks - * ---------- */ while (data_todo > 0) { - /* ---------- + + /* * Calculate the size of this chunk - * ---------- */ chunk_size = Min(TOAST_MAX_CHUNK_SIZE, data_todo); - /* ---------- + /* * Build a tuple - * ---------- */ t_values[1] = Int32GetDatum(chunk_seq++); VARATT_SIZEP(chunk_data) = chunk_size + VARHDRSZ; @@ -850,9 +817,8 @@ toast_save_datum(Relation rel, Oid mainoid, int16 attno, Datum value) if (!HeapTupleIsValid(toasttup)) elog(ERROR, "Failed to build TOAST tuple"); - /* ---------- + /* * Store it and create the index entry - * ---------- */ heap_insert(toastrel, toasttup); idxres = index_insert(toastidx, t_values, t_nulls, @@ -861,24 +827,21 @@ toast_save_datum(Relation rel, Oid mainoid, int16 attno, Datum value) if (idxres == NULL) elog(ERROR, "Failed to insert index entry for TOAST tuple"); - /* ---------- + /* * Free memory - * ---------- */ heap_freetuple(toasttup); pfree(idxres); - /* ---------- + /* * Move on to next chunk - * ---------- */ data_todo -= chunk_size; data_p += chunk_size; } - /* ---------- + /* * Done - close toast relation and return the reference - * ---------- */ index_close(toastidx); heap_close(toastrel, RowExclusiveLock); @@ -908,17 +871,15 @@ toast_delete_datum(Relation rel, Datum value) if (!VARATT_IS_EXTERNAL(attr)) return; - /* ---------- + /* * Open the toast relation and it's index - * ---------- */ toastrel = heap_open(attr->va_content.va_external.va_toastrelid, RowExclusiveLock); toastidx = index_open(attr->va_content.va_external.va_toastidxid); - /* ---------- + /* * Setup a scan key to fetch from the index by va_valueid - * ---------- */ ScanKeyEntryInitialize(&toastkey, (bits16) 0, @@ -926,9 +887,8 @@ toast_delete_datum(Relation rel, Datum value) (RegProcedure) F_OIDEQ, ObjectIdGetDatum(attr->va_content.va_external.va_valueid)); - /* ---------- + /* * Read the chunks by index - * ---------- */ toastscan = index_beginscan(toastidx, false, 1, &toastkey); while ((indexRes = index_getnext(toastscan, ForwardScanDirection)) != NULL) @@ -940,18 +900,16 @@ toast_delete_datum(Relation rel, Datum value) if (!toasttup.t_data) continue; - /* ---------- + /* * Have a chunk, delete it - * ---------- */ simple_heap_delete(toastrel, &toasttup.t_self); ReleaseBuffer(buffer); } - /* ---------- + /* * End scan and close relations - * ---------- */ index_endscan(toastscan); index_close(toastidx); @@ -1003,18 +961,16 @@ toast_fetch_datum(varattrib *attr) if (VARATT_IS_COMPRESSED(attr)) VARATT_SIZEP(result) |= VARATT_FLAG_COMPRESSED; - /* ---------- + /* * Open the toast relation and it's index - * ---------- */ toastrel = heap_open(attr->va_content.va_external.va_toastrelid, AccessShareLock); toasttupDesc = toastrel->rd_att; toastidx = index_open(attr->va_content.va_external.va_toastidxid); - /* ---------- + /* * Setup a scan key to fetch from the index by va_valueid - * ---------- */ ScanKeyEntryInitialize(&toastkey, (bits16) 0, @@ -1022,11 +978,10 @@ toast_fetch_datum(varattrib *attr) (RegProcedure) F_OIDEQ, ObjectIdGetDatum(attr->va_content.va_external.va_valueid)); - /* ---------- + /* * Read the chunks by index * * Note we will not necessarily see the chunks in sequence-number order. - * ---------- */ toastscan = index_beginscan(toastidx, false, 1, &toastkey); while ((indexRes = index_getnext(toastscan, ForwardScanDirection)) != NULL) @@ -1039,9 +994,8 @@ toast_fetch_datum(varattrib *attr) continue; ttup = &toasttup; - /* ---------- + /* * Have a chunk, extract the sequence number and the data - * ---------- */ residx = DatumGetInt32(heap_getattr(ttup, 2, toasttupDesc, &isnull)); Assert(!isnull); @@ -1049,9 +1003,8 @@ toast_fetch_datum(varattrib *attr) Assert(!isnull); chunksize = VARATT_SIZE(chunk) - VARHDRSZ; - /* ---------- + /* * Some checks on the data we've found - * ---------- */ if (residx < 0 || residx >= numchunks) elog(ERROR, "unexpected chunk number %d for toast value %d", @@ -1076,9 +1029,8 @@ toast_fetch_datum(varattrib *attr) residx, attr->va_content.va_external.va_valueid); - /* ---------- + /* * Copy the data into proper place in our result - * ---------- */ memcpy(((char *) VARATT_DATA(result)) + residx * TOAST_MAX_CHUNK_SIZE, VARATT_DATA(chunk), @@ -1087,9 +1039,8 @@ toast_fetch_datum(varattrib *attr) ReleaseBuffer(buffer); } - /* ---------- + /* * Final checks that we successfully fetched the datum - * ---------- */ if (memcmp(chunks_found, chunks_expected, numchunks) != 0) elog(ERROR, "not all toast chunks found for value %d", @@ -1097,9 +1048,8 @@ toast_fetch_datum(varattrib *attr) pfree(chunks_expected); pfree(chunks_found); - /* ---------- + /* * End scan and close relations - * ---------- */ index_endscan(toastscan); index_close(toastidx); |