diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2005-12-22 22:50:22 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2005-12-22 22:50:22 +0000 |
commit | 0862aeaeec46153337df89c9c0d4d25e6d5c7713 (patch) | |
tree | 81c593f13c90b52a494c2ace5eadbb601d52ccfb /src/backend/utils/adt/varlena.c | |
parent | b1ea82fee14c457a76ac65efca58155240dab950 (diff) | |
download | postgresql-0862aeaeec46153337df89c9c0d4d25e6d5c7713.tar.gz postgresql-0862aeaeec46153337df89c9c0d4d25e6d5c7713.zip |
Adjust string comparison so that only bitwise-equal strings are considered
equal: if strcoll claims two strings are equal, check it with strcmp, and
sort according to strcmp if not identical. This fixes inconsistent
behavior under glibc's hu_HU locale, and probably under some other locales
as well. Also, take advantage of the now-well-defined behavior to speed up
texteq, textne, bpchareq, bpcharne: they may as well just do a bitwise
comparison and not bother with strcoll at all.
NOTE: affected databases may need to REINDEX indexes on text columns to be
sure they are self-consistent.
Diffstat (limited to 'src/backend/utils/adt/varlena.c')
-rw-r--r-- | src/backend/utils/adt/varlena.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c index 7b17b50aec4..02721aece84 100644 --- a/src/backend/utils/adt/varlena.c +++ b/src/backend/utils/adt/varlena.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.106.2.4 2004/02/21 00:35:13 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.106.2.5 2005/12/22 22:50:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -868,6 +868,15 @@ varstr_cmp(char *arg1, int len1, char *arg2, int len2) result = strcoll(a1p, a2p); + /* + * In some locales strcoll() can claim that nonidentical strings are + * equal. Believing that would be bad news for a number of reasons, + * so we follow Perl's lead and sort "equal" strings according to + * strcmp(). + */ + if (result == 0) + result = strcmp(a1p, a2p); + if (len1 >= STACKBUFLEN) pfree(a1p); if (len2 >= STACKBUFLEN) @@ -920,11 +929,15 @@ texteq(PG_FUNCTION_ARGS) text *arg2 = PG_GETARG_TEXT_P(1); bool result; - /* fast path for different-length inputs */ + /* + * Since we only care about equality or not-equality, we can avoid all + * the expense of strcoll() here, and just do bitwise comparison. + */ if (VARSIZE(arg1) != VARSIZE(arg2)) result = false; else - result = (text_cmp(arg1, arg2) == 0); + result = (strncmp(VARDATA(arg1), VARDATA(arg2), + VARSIZE(arg1) - VARHDRSZ) == 0); PG_FREE_IF_COPY(arg1, 0); PG_FREE_IF_COPY(arg2, 1); @@ -939,11 +952,15 @@ textne(PG_FUNCTION_ARGS) text *arg2 = PG_GETARG_TEXT_P(1); bool result; - /* fast path for different-length inputs */ + /* + * Since we only care about equality or not-equality, we can avoid all + * the expense of strcoll() here, and just do bitwise comparison. + */ if (VARSIZE(arg1) != VARSIZE(arg2)) result = true; else - result = (text_cmp(arg1, arg2) != 0); + result = (strncmp(VARDATA(arg1), VARDATA(arg2), + VARSIZE(arg1) - VARHDRSZ) != 0); PG_FREE_IF_COPY(arg1, 0); PG_FREE_IF_COPY(arg2, 1); |