Commit 5be94a9e authored by Robert Haas's avatar Robert Haas

Be a bit more rigorous about how we cache strcoll and strxfrm results.

Commit 0e57b4d8 contained some clever
logic that attempted to make sure that we couldn't get confused about
whether the last thing we cached was a strcoll() result or a strxfrm()
result, but it wasn't quite clever enough, because we can perform
further abbreviations after having already performed some comparisons.
Introduce an explicit flag in the hopes of making this watertight.

Peter Geoghegan, reviewed by me.
parent d53f808e
...@@ -65,6 +65,7 @@ typedef struct ...@@ -65,6 +65,7 @@ typedef struct
int last_len1; /* Length of last buf1 string/strxfrm() blob */ int last_len1; /* Length of last buf1 string/strxfrm() blob */
int last_len2; /* Length of last buf2 string/strxfrm() blob */ int last_len2; /* Length of last buf2 string/strxfrm() blob */
int last_returned; /* Last comparison result (cache) */ int last_returned; /* Last comparison result (cache) */
bool cache_blob; /* Does buf2 contain strxfrm() blob, etc? */
bool collate_c; bool collate_c;
hyperLogLogState abbr_card; /* Abbreviated key cardinality state */ hyperLogLogState abbr_card; /* Abbreviated key cardinality state */
hyperLogLogState full_card; /* Full key cardinality state */ hyperLogLogState full_card; /* Full key cardinality state */
...@@ -1838,17 +1839,26 @@ btsortsupport_worker(SortSupport ssup, Oid collid) ...@@ -1838,17 +1839,26 @@ btsortsupport_worker(SortSupport ssup, Oid collid)
/* Start with invalid values */ /* Start with invalid values */
tss->last_len1 = -1; tss->last_len1 = -1;
tss->last_len2 = -1; tss->last_len2 = -1;
/* Initialize */
tss->last_returned = 0;
#ifdef HAVE_LOCALE_T #ifdef HAVE_LOCALE_T
tss->locale = locale; tss->locale = locale;
#endif #endif
/* /*
* To avoid somehow confusing a strxfrm() blob and an original string * To avoid somehow confusing a strxfrm() blob and an original string,
* within bttextfastcmp_locale(), initialize last returned cache to a * constantly keep track of the variety of data that buf1 and buf2
* sentinel value. A platform-specific actual strcoll() return value * currently contain.
* of INT_MIN seems unlikely, but if that occurs it will not cause *
* wrong answers. * Comparisons may be interleaved with conversion calls. Frequently,
* conversions and comparisons are batched into two distinct phases,
* but the correctness of caching cannot hinge upon this. For
* comparison caching, buffer state is only trusted if cache_blob is
* found set to false, whereas strxfrm() caching only trusts the state
* when cache_blob is found set to true.
*
* Arbitrarily initialize cache_blob to true.
*/ */
tss->last_returned = INT_MIN; tss->cache_blob = true;
tss->collate_c = collate_c; tss->collate_c = collate_c;
ssup->ssup_extra = tss; ssup->ssup_extra = tss;
...@@ -1983,7 +1993,7 @@ bttextfastcmp_locale(Datum x, Datum y, SortSupport ssup) ...@@ -1983,7 +1993,7 @@ bttextfastcmp_locale(Datum x, Datum y, SortSupport ssup)
tss->buf2[len2] = '\0'; tss->buf2[len2] = '\0';
tss->last_len2 = len2; tss->last_len2 = len2;
} }
else if (arg1_match && tss->last_returned != INT_MIN) else if (arg1_match && !tss->cache_blob)
{ {
/* Use result cached following last actual strcoll() call */ /* Use result cached following last actual strcoll() call */
result = tss->last_returned; result = tss->last_returned;
...@@ -2006,6 +2016,7 @@ bttextfastcmp_locale(Datum x, Datum y, SortSupport ssup) ...@@ -2006,6 +2016,7 @@ bttextfastcmp_locale(Datum x, Datum y, SortSupport ssup)
result = strcmp(tss->buf1, tss->buf2); result = strcmp(tss->buf1, tss->buf2);
/* Cache result, perhaps saving an expensive strcoll() call next time */ /* Cache result, perhaps saving an expensive strcoll() call next time */
tss->cache_blob = false;
tss->last_returned = result; tss->last_returned = result;
done: done:
/* We can't afford to leak memory here. */ /* We can't afford to leak memory here. */
...@@ -2086,7 +2097,7 @@ bttext_abbrev_convert(Datum original, SortSupport ssup) ...@@ -2086,7 +2097,7 @@ bttext_abbrev_convert(Datum original, SortSupport ssup)
} }
/* Might be able to reuse strxfrm() blob from last call */ /* Might be able to reuse strxfrm() blob from last call */
if (tss->last_len1 == len && if (tss->last_len1 == len && tss->cache_blob &&
memcmp(tss->buf1, authoritative_data, len) == 0) memcmp(tss->buf1, authoritative_data, len) == 0)
{ {
memcpy(pres, tss->buf2, Min(sizeof(Datum), tss->last_len2)); memcpy(pres, tss->buf2, Min(sizeof(Datum), tss->last_len2));
...@@ -2167,6 +2178,8 @@ bttext_abbrev_convert(Datum original, SortSupport ssup) ...@@ -2167,6 +2178,8 @@ bttext_abbrev_convert(Datum original, SortSupport ssup)
addHyperLogLog(&tss->abbr_card, hash); addHyperLogLog(&tss->abbr_card, hash);
/* Cache result, perhaps saving an expensive strxfrm() call next time */
tss->cache_blob = true;
done: done:
/* /*
* Byteswap on little-endian machines. * Byteswap on little-endian machines.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment