mirror of
https://github.com/postgres/postgres.git
synced 2025-06-26 12:21:12 +03:00
Avoid detoast in texteq/textne/byteaeq/byteane for unequal-length strings.
We can get the length of a compressed or out-of-line datum without actually detoasting it. If the lengths of two strings are unequal, we can then conclude they are unequal without detoasting. That saves considerable work in an admittedly less-common case, without costing anything much when the optimization doesn't apply. Noah Misch
This commit is contained in:
@ -1451,22 +1451,34 @@ text_cmp(text *arg1, text *arg2)
|
|||||||
Datum
|
Datum
|
||||||
texteq(PG_FUNCTION_ARGS)
|
texteq(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
text *arg1 = PG_GETARG_TEXT_PP(0);
|
Datum arg1 = PG_GETARG_DATUM(0);
|
||||||
text *arg2 = PG_GETARG_TEXT_PP(1);
|
Datum arg2 = PG_GETARG_DATUM(1);
|
||||||
bool result;
|
bool result;
|
||||||
|
Size len1,
|
||||||
|
len2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Since we only care about equality or not-equality, we can avoid all the
|
* Since we only care about equality or not-equality, we can avoid all the
|
||||||
* expense of strcoll() here, and just do bitwise comparison.
|
* expense of strcoll() here, and just do bitwise comparison. In fact,
|
||||||
|
* we don't even have to do a bitwise comparison if we can show the
|
||||||
|
* lengths of the strings are unequal; which might save us from having
|
||||||
|
* to detoast one or both values.
|
||||||
*/
|
*/
|
||||||
if (VARSIZE_ANY_EXHDR(arg1) != VARSIZE_ANY_EXHDR(arg2))
|
len1 = toast_raw_datum_size(arg1);
|
||||||
|
len2 = toast_raw_datum_size(arg2);
|
||||||
|
if (len1 != len2)
|
||||||
result = false;
|
result = false;
|
||||||
else
|
else
|
||||||
result = (memcmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2),
|
{
|
||||||
VARSIZE_ANY_EXHDR(arg1)) == 0);
|
text *targ1 = DatumGetTextPP(arg1);
|
||||||
|
text *targ2 = DatumGetTextPP(arg2);
|
||||||
|
|
||||||
PG_FREE_IF_COPY(arg1, 0);
|
result = (memcmp(VARDATA_ANY(targ1), VARDATA_ANY(targ2),
|
||||||
PG_FREE_IF_COPY(arg2, 1);
|
len1 - VARHDRSZ) == 0);
|
||||||
|
|
||||||
|
PG_FREE_IF_COPY(targ1, 0);
|
||||||
|
PG_FREE_IF_COPY(targ2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
PG_RETURN_BOOL(result);
|
PG_RETURN_BOOL(result);
|
||||||
}
|
}
|
||||||
@ -1474,22 +1486,28 @@ texteq(PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
textne(PG_FUNCTION_ARGS)
|
textne(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
text *arg1 = PG_GETARG_TEXT_PP(0);
|
Datum arg1 = PG_GETARG_DATUM(0);
|
||||||
text *arg2 = PG_GETARG_TEXT_PP(1);
|
Datum arg2 = PG_GETARG_DATUM(1);
|
||||||
bool result;
|
bool result;
|
||||||
|
Size len1,
|
||||||
|
len2;
|
||||||
|
|
||||||
/*
|
/* See comment in texteq() */
|
||||||
* Since we only care about equality or not-equality, we can avoid all the
|
len1 = toast_raw_datum_size(arg1);
|
||||||
* expense of strcoll() here, and just do bitwise comparison.
|
len2 = toast_raw_datum_size(arg2);
|
||||||
*/
|
if (len1 != len2)
|
||||||
if (VARSIZE_ANY_EXHDR(arg1) != VARSIZE_ANY_EXHDR(arg2))
|
|
||||||
result = true;
|
result = true;
|
||||||
else
|
else
|
||||||
result = (memcmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2),
|
{
|
||||||
VARSIZE_ANY_EXHDR(arg1)) != 0);
|
text *targ1 = DatumGetTextPP(arg1);
|
||||||
|
text *targ2 = DatumGetTextPP(arg2);
|
||||||
|
|
||||||
PG_FREE_IF_COPY(arg1, 0);
|
result = (memcmp(VARDATA_ANY(targ1), VARDATA_ANY(targ2),
|
||||||
PG_FREE_IF_COPY(arg2, 1);
|
len1 - VARHDRSZ) != 0);
|
||||||
|
|
||||||
|
PG_FREE_IF_COPY(targ1, 0);
|
||||||
|
PG_FREE_IF_COPY(targ2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
PG_RETURN_BOOL(result);
|
PG_RETURN_BOOL(result);
|
||||||
}
|
}
|
||||||
@ -2358,23 +2376,31 @@ SplitIdentifierString(char *rawstring, char separator,
|
|||||||
Datum
|
Datum
|
||||||
byteaeq(PG_FUNCTION_ARGS)
|
byteaeq(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
bytea *arg1 = PG_GETARG_BYTEA_PP(0);
|
Datum arg1 = PG_GETARG_DATUM(0);
|
||||||
bytea *arg2 = PG_GETARG_BYTEA_PP(1);
|
Datum arg2 = PG_GETARG_DATUM(1);
|
||||||
int len1,
|
|
||||||
len2;
|
|
||||||
bool result;
|
bool result;
|
||||||
|
Size len1,
|
||||||
|
len2;
|
||||||
|
|
||||||
len1 = VARSIZE_ANY_EXHDR(arg1);
|
/*
|
||||||
len2 = VARSIZE_ANY_EXHDR(arg2);
|
* We can use a fast path for unequal lengths, which might save us from
|
||||||
|
* having to detoast one or both values.
|
||||||
/* fast path for different-length inputs */
|
*/
|
||||||
|
len1 = toast_raw_datum_size(arg1);
|
||||||
|
len2 = toast_raw_datum_size(arg2);
|
||||||
if (len1 != len2)
|
if (len1 != len2)
|
||||||
result = false;
|
result = false;
|
||||||
else
|
else
|
||||||
result = (memcmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), len1) == 0);
|
{
|
||||||
|
bytea *barg1 = DatumGetByteaPP(arg1);
|
||||||
|
bytea *barg2 = DatumGetByteaPP(arg2);
|
||||||
|
|
||||||
PG_FREE_IF_COPY(arg1, 0);
|
result = (memcmp(VARDATA_ANY(barg1), VARDATA_ANY(barg2),
|
||||||
PG_FREE_IF_COPY(arg2, 1);
|
len1 - VARHDRSZ) == 0);
|
||||||
|
|
||||||
|
PG_FREE_IF_COPY(barg1, 0);
|
||||||
|
PG_FREE_IF_COPY(barg2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
PG_RETURN_BOOL(result);
|
PG_RETURN_BOOL(result);
|
||||||
}
|
}
|
||||||
@ -2382,23 +2408,31 @@ byteaeq(PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
byteane(PG_FUNCTION_ARGS)
|
byteane(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
bytea *arg1 = PG_GETARG_BYTEA_PP(0);
|
Datum arg1 = PG_GETARG_DATUM(0);
|
||||||
bytea *arg2 = PG_GETARG_BYTEA_PP(1);
|
Datum arg2 = PG_GETARG_DATUM(1);
|
||||||
int len1,
|
|
||||||
len2;
|
|
||||||
bool result;
|
bool result;
|
||||||
|
Size len1,
|
||||||
|
len2;
|
||||||
|
|
||||||
len1 = VARSIZE_ANY_EXHDR(arg1);
|
/*
|
||||||
len2 = VARSIZE_ANY_EXHDR(arg2);
|
* We can use a fast path for unequal lengths, which might save us from
|
||||||
|
* having to detoast one or both values.
|
||||||
/* fast path for different-length inputs */
|
*/
|
||||||
|
len1 = toast_raw_datum_size(arg1);
|
||||||
|
len2 = toast_raw_datum_size(arg2);
|
||||||
if (len1 != len2)
|
if (len1 != len2)
|
||||||
result = true;
|
result = true;
|
||||||
else
|
else
|
||||||
result = (memcmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), len1) != 0);
|
{
|
||||||
|
bytea *barg1 = DatumGetByteaPP(arg1);
|
||||||
|
bytea *barg2 = DatumGetByteaPP(arg2);
|
||||||
|
|
||||||
PG_FREE_IF_COPY(arg1, 0);
|
result = (memcmp(VARDATA_ANY(barg1), VARDATA_ANY(barg2),
|
||||||
PG_FREE_IF_COPY(arg2, 1);
|
len1 - VARHDRSZ) != 0);
|
||||||
|
|
||||||
|
PG_FREE_IF_COPY(barg1, 0);
|
||||||
|
PG_FREE_IF_COPY(barg2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
PG_RETURN_BOOL(result);
|
PG_RETURN_BOOL(result);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user