aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2011-01-18 14:09:22 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2011-01-18 14:11:54 -0500
commit1b393f4e5db4fd6bbc86a4e88785b6945a1541d0 (patch)
tree3351618fc9ed842cf1f3f2d301594ec261565836
parent6e1726d082b5a9c305ed44a69ff50bc3407d01a2 (diff)
downloadpostgresql-1b393f4e5db4fd6bbc86a4e88785b6945a1541d0.tar.gz
postgresql-1b393f4e5db4fd6bbc86a4e88785b6945a1541d0.zip
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
-rw-r--r--src/backend/utils/adt/varlena.c116
1 files changed, 75 insertions, 41 deletions
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index ed57685a182..e111d2650b4 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -1451,22 +1451,34 @@ text_cmp(text *arg1, text *arg2)
Datum
texteq(PG_FUNCTION_ARGS)
{
- text *arg1 = PG_GETARG_TEXT_PP(0);
- text *arg2 = PG_GETARG_TEXT_PP(1);
+ Datum arg1 = PG_GETARG_DATUM(0);
+ Datum arg2 = PG_GETARG_DATUM(1);
bool result;
+ Size len1,
+ len2;
/*
* 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;
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);
- PG_FREE_IF_COPY(arg2, 1);
+ result = (memcmp(VARDATA_ANY(targ1), VARDATA_ANY(targ2),
+ len1 - VARHDRSZ) == 0);
+
+ PG_FREE_IF_COPY(targ1, 0);
+ PG_FREE_IF_COPY(targ2, 1);
+ }
PG_RETURN_BOOL(result);
}
@@ -1474,22 +1486,28 @@ texteq(PG_FUNCTION_ARGS)
Datum
textne(PG_FUNCTION_ARGS)
{
- text *arg1 = PG_GETARG_TEXT_PP(0);
- text *arg2 = PG_GETARG_TEXT_PP(1);
+ Datum arg1 = PG_GETARG_DATUM(0);
+ Datum arg2 = PG_GETARG_DATUM(1);
bool result;
+ Size len1,
+ len2;
- /*
- * 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_ANY_EXHDR(arg1) != VARSIZE_ANY_EXHDR(arg2))
+ /* See comment in texteq() */
+ len1 = toast_raw_datum_size(arg1);
+ len2 = toast_raw_datum_size(arg2);
+ if (len1 != len2)
result = true;
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);
- PG_FREE_IF_COPY(arg2, 1);
+ result = (memcmp(VARDATA_ANY(targ1), VARDATA_ANY(targ2),
+ len1 - VARHDRSZ) != 0);
+
+ PG_FREE_IF_COPY(targ1, 0);
+ PG_FREE_IF_COPY(targ2, 1);
+ }
PG_RETURN_BOOL(result);
}
@@ -2358,23 +2376,31 @@ SplitIdentifierString(char *rawstring, char separator,
Datum
byteaeq(PG_FUNCTION_ARGS)
{
- bytea *arg1 = PG_GETARG_BYTEA_PP(0);
- bytea *arg2 = PG_GETARG_BYTEA_PP(1);
- int len1,
- len2;
+ Datum arg1 = PG_GETARG_DATUM(0);
+ Datum arg2 = PG_GETARG_DATUM(1);
bool result;
+ Size len1,
+ len2;
- len1 = VARSIZE_ANY_EXHDR(arg1);
- len2 = VARSIZE_ANY_EXHDR(arg2);
-
- /* fast path for different-length inputs */
+ /*
+ * We can use a fast path for unequal lengths, which might save us from
+ * having to detoast one or both values.
+ */
+ len1 = toast_raw_datum_size(arg1);
+ len2 = toast_raw_datum_size(arg2);
if (len1 != len2)
result = false;
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);
- PG_FREE_IF_COPY(arg2, 1);
+ result = (memcmp(VARDATA_ANY(barg1), VARDATA_ANY(barg2),
+ len1 - VARHDRSZ) == 0);
+
+ PG_FREE_IF_COPY(barg1, 0);
+ PG_FREE_IF_COPY(barg2, 1);
+ }
PG_RETURN_BOOL(result);
}
@@ -2382,23 +2408,31 @@ byteaeq(PG_FUNCTION_ARGS)
Datum
byteane(PG_FUNCTION_ARGS)
{
- bytea *arg1 = PG_GETARG_BYTEA_PP(0);
- bytea *arg2 = PG_GETARG_BYTEA_PP(1);
- int len1,
- len2;
+ Datum arg1 = PG_GETARG_DATUM(0);
+ Datum arg2 = PG_GETARG_DATUM(1);
bool result;
+ Size len1,
+ len2;
- len1 = VARSIZE_ANY_EXHDR(arg1);
- len2 = VARSIZE_ANY_EXHDR(arg2);
-
- /* fast path for different-length inputs */
+ /*
+ * We can use a fast path for unequal lengths, which might save us from
+ * having to detoast one or both values.
+ */
+ len1 = toast_raw_datum_size(arg1);
+ len2 = toast_raw_datum_size(arg2);
if (len1 != len2)
result = true;
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);
- PG_FREE_IF_COPY(arg2, 1);
+ result = (memcmp(VARDATA_ANY(barg1), VARDATA_ANY(barg2),
+ len1 - VARHDRSZ) != 0);
+
+ PG_FREE_IF_COPY(barg1, 0);
+ PG_FREE_IF_COPY(barg2, 1);
+ }
PG_RETURN_BOOL(result);
}