diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c index fb52bfba3e..f0f84699c5 100644 --- a/src/backend/access/heap/tuptoaster.c +++ b/src/backend/access/heap/tuptoaster.c @@ -375,18 +375,14 @@ DetoastIterator create_detoast_iterator(struct varlena *attr) { /* If it's compressed, prepare buffer for raw data */ iterator->buf = (ToastBuffer *) palloc0(sizeof(ToastBuffer)); init_toast_buffer(iterator->buf, toast_pointer.va_rawsize, false); - iterator->source = NULL; iterator->ctrlc = 0; iterator->compressed = true; - iterator->done = false; } else { iterator->buf = iterator->fetch_datum_iterator->buf; - iterator->source = NULL; iterator->ctrlc = 0; iterator->compressed = false; - iterator->done = false; } } else if (VARATT_IS_EXTERNAL_INDIRECT(attr)) @@ -410,21 +406,9 @@ DetoastIterator create_detoast_iterator(struct varlena *attr) { { /* * This is a compressed value inside of the main tuple + * Skip the iterator and just decompress the whole thing. */ - iterator = (DetoastIterator) palloc0(sizeof(DetoastIteratorData)); - iterator->fetch_datum_iterator = NULL; - iterator->source = palloc0(sizeof(ToastBuffer)); - iterator->source->buf = (const char*) attr; - iterator->source->position = TOAST_COMPRESS_RAWDATA(attr); - iterator->source->limit = (char *)attr + VARSIZE(attr); - iterator->source->capacity = iterator->source->limit; - - iterator->buf = palloc0(sizeof(ToastBuffer)); - init_toast_buffer(iterator->buf, TOAST_COMPRESS_RAWSIZE(attr) + VARHDRSZ, false); - - iterator->ctrlc = 0; - iterator->compressed = true; - iterator->done = false; + return NULL; } return iterator; @@ -447,7 +431,6 @@ bool free_detoast_iterator(DetoastIterator iter) { free_toast_buffer(iter->buf); } free_fetch_datum_iterator(iter->fetch_datum_iterator); - free_toast_buffer(iter->source); pfree(iter); return true; } @@ -463,34 +446,26 @@ bool free_detoast_iterator(DetoastIterator iter) { * Return -1 when no more data. * ---------- */ -extern int32 detoast_iterate(int32 length, DetoastIterator iter) +extern int32 detoast_iterate(DetoastIterator iter) { if (iter == NULL) { elog(ERROR, "detoast_iterate shouln't be called for NULL iterator"); } - if (iter->buf->limit - iter->buf->position >= length || iter->done) - { - return iter->buf->limit - iter->buf->position; - } - - if (iter->fetch_datum_iterator != NULL) - { - ToastBuffer *buf = iter->fetch_datum_iterator->buf; - FetchDatumIterator fetch_iter = iter->fetch_datum_iterator; - while(iter->buf->limit - iter->buf->position < length && !fetch_iter->done) { - fetch_datum_iterate(fetch_iter); - if (iter->compressed) - { - pglz_decompress_iterate(buf, iter->buf, iter, -1); - } - } + FetchDatumIterator fetch_iter = iter->fetch_datum_iterator; + Assert(fetch_iter != NULL); + fetch_datum_iterate(fetch_iter); + if (fetch_iter->done) + /* XXX should this an error? */ return iter->buf->limit - iter->buf->position; - } - return pglz_decompress_iterate(iter->source, iter->buf, iter, length); + if (iter->compressed) + pglz_decompress_iterate(fetch_iter->buf, iter->buf, iter, -1); + + /* XXX Can the caller do any error checking with this? If not, just return void */ + return iter->buf->limit - iter->buf->position; } @@ -2665,6 +2640,7 @@ fetch_datum_iterate(FetchDatumIterator iter) { elog(ERROR, "fetch_datum_iterate shouln't be called for NULL iterator"); } + /* XXX maybe should be an assert? */ if (iter->done) { return -1; @@ -2763,6 +2739,8 @@ fetch_datum_iterate(FetchDatumIterator iter) { iter->buf->limit += chunksize; iter->nextidx++; + + /* XXX Can the caller do error checking with this? */ return chunksize; } @@ -2821,7 +2799,8 @@ pglz_decompress_iterate(ToastBuffer *source, ToastBuffer *dest, DetoastIterator dp = (unsigned char *) dest->limit; destend = (unsigned char *) dest->capacity; - decompress_all = need_len < 0 ? true : false; + /* TODO: remove need_len parameter */ + decompress_all = true; while (sp + 1 < srcend && dp < destend && (decompress_all || ((char *)dp - dest->position) < need_len)) diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c index 72e10a3664..ff2a01b2b1 100644 --- a/src/backend/utils/adt/varlena.c +++ b/src/backend/utils/adt/varlena.c @@ -1368,9 +1368,9 @@ text_position_next_internal(char *start_ptr, TextPositionState *state, DetoastIt hptr = start_ptr; while (hptr < haystack_end) { - if (iter != NULL) { - detoast_iterate(hptr - iter->buf->position + 1, iter); - } + if (iter != NULL && hptr >= iter->buf->limit) + detoast_iterate(iter); + if (*hptr == nchar) return (char *) hptr; hptr++; @@ -1388,8 +1388,14 @@ text_position_next_internal(char *start_ptr, TextPositionState *state, DetoastIt const char *nptr; const char *p; - if (iter != NULL) { - detoast_iterate(hptr - iter->buf->position + 1, iter); + if (iter != NULL) + { + /* + * The needle could be long enough that we need + * to detoast more than one chunk each time. + */ + while (hptr >= iter->buf->limit) + detoast_iterate(iter); } nptr = needle_last; diff --git a/src/include/access/tuptoaster.h b/src/include/access/tuptoaster.h index e60815d2fd..3dbddd6c70 100644 --- a/src/include/access/tuptoaster.h +++ b/src/include/access/tuptoaster.h @@ -69,11 +69,9 @@ typedef struct DetoastIteratorData { ToastBuffer *buf; FetchDatumIterator fetch_datum_iterator; - ToastBuffer *source; unsigned char ctrl; int ctrlc; bool compressed; /* toast value is compressed? */ - bool done; /* iterator exhausted? */ } DetoastIteratorData; typedef struct DetoastIteratorData *DetoastIterator; @@ -104,7 +102,7 @@ extern bool free_detoast_iterator(DetoastIterator iter); * Return -1 when no more data. * ---------- */ -extern int32 detoast_iterate(int32 length, DetoastIterator iter); +extern int32 detoast_iterate(DetoastIterator iter); #endif