Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 5be94a9

Browse files
committed
Be a bit more rigorous about how we cache strcoll and strxfrm results.
Commit 0e57b4d 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.
1 parent d53f808 commit 5be94a9

File tree

1 file changed

+21
-8
lines changed

1 file changed

+21
-8
lines changed

src/backend/utils/adt/varlena.c

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ typedef struct
6565
int last_len1; /* Length of last buf1 string/strxfrm() blob */
6666
int last_len2; /* Length of last buf2 string/strxfrm() blob */
6767
int last_returned; /* Last comparison result (cache) */
68+
bool cache_blob; /* Does buf2 contain strxfrm() blob, etc? */
6869
bool collate_c;
6970
hyperLogLogState abbr_card; /* Abbreviated key cardinality state */
7071
hyperLogLogState full_card; /* Full key cardinality state */
@@ -1838,17 +1839,26 @@ btsortsupport_worker(SortSupport ssup, Oid collid)
18381839
/* Start with invalid values */
18391840
tss->last_len1 = -1;
18401841
tss->last_len2 = -1;
1842+
/* Initialize */
1843+
tss->last_returned = 0;
18411844
#ifdef HAVE_LOCALE_T
18421845
tss->locale = locale;
18431846
#endif
18441847
/*
1845-
* To avoid somehow confusing a strxfrm() blob and an original string
1846-
* within bttextfastcmp_locale(), initialize last returned cache to a
1847-
* sentinel value. A platform-specific actual strcoll() return value
1848-
* of INT_MIN seems unlikely, but if that occurs it will not cause
1849-
* wrong answers.
1848+
* To avoid somehow confusing a strxfrm() blob and an original string,
1849+
* constantly keep track of the variety of data that buf1 and buf2
1850+
* currently contain.
1851+
*
1852+
* Comparisons may be interleaved with conversion calls. Frequently,
1853+
* conversions and comparisons are batched into two distinct phases,
1854+
* but the correctness of caching cannot hinge upon this. For
1855+
* comparison caching, buffer state is only trusted if cache_blob is
1856+
* found set to false, whereas strxfrm() caching only trusts the state
1857+
* when cache_blob is found set to true.
1858+
*
1859+
* Arbitrarily initialize cache_blob to true.
18501860
*/
1851-
tss->last_returned = INT_MIN;
1861+
tss->cache_blob = true;
18521862
tss->collate_c = collate_c;
18531863
ssup->ssup_extra = tss;
18541864

@@ -1983,7 +1993,7 @@ bttextfastcmp_locale(Datum x, Datum y, SortSupport ssup)
19831993
tss->buf2[len2] = '\0';
19841994
tss->last_len2 = len2;
19851995
}
1986-
else if (arg1_match && tss->last_returned != INT_MIN)
1996+
else if (arg1_match && !tss->cache_blob)
19871997
{
19881998
/* Use result cached following last actual strcoll() call */
19891999
result = tss->last_returned;
@@ -2006,6 +2016,7 @@ bttextfastcmp_locale(Datum x, Datum y, SortSupport ssup)
20062016
result = strcmp(tss->buf1, tss->buf2);
20072017

20082018
/* Cache result, perhaps saving an expensive strcoll() call next time */
2019+
tss->cache_blob = false;
20092020
tss->last_returned = result;
20102021
done:
20112022
/* We can't afford to leak memory here. */
@@ -2086,7 +2097,7 @@ bttext_abbrev_convert(Datum original, SortSupport ssup)
20862097
}
20872098

20882099
/* Might be able to reuse strxfrm() blob from last call */
2089-
if (tss->last_len1 == len &&
2100+
if (tss->last_len1 == len && tss->cache_blob &&
20902101
memcmp(tss->buf1, authoritative_data, len) == 0)
20912102
{
20922103
memcpy(pres, tss->buf2, Min(sizeof(Datum), tss->last_len2));
@@ -2167,6 +2178,8 @@ bttext_abbrev_convert(Datum original, SortSupport ssup)
21672178

21682179
addHyperLogLog(&tss->abbr_card, hash);
21692180

2181+
/* Cache result, perhaps saving an expensive strxfrm() call next time */
2182+
tss->cache_blob = true;
21702183
done:
21712184
/*
21722185
* Byteswap on little-endian machines.

0 commit comments

Comments
 (0)