diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2018-12-19 17:46:07 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2018-12-19 17:46:25 -0500 |
commit | 2ece7c07dc9a14667c64f107686573590b7e45c3 (patch) | |
tree | 8b25e2d875d21defd1cbe3dcc3be9c22134fd002 /src/backend/utils/adt/varlena.c | |
parent | 586b98fdf1aaef4a27744f8b988479aad4bd9a01 (diff) | |
download | postgresql-2ece7c07dc9a14667c64f107686573590b7e45c3.tar.gz postgresql-2ece7c07dc9a14667c64f107686573590b7e45c3.zip |
Add text-vs-name cross-type operators, and unify name_ops with text_ops.
Now that name comparison has effectively the same behavior as text
comparison, we might as well merge the name_ops opfamily into text_ops,
allowing cross-type comparisons to be processed without forcing a
datatype coercion first. We need do little more than add cross-type
operators to make the opfamily complete, and fix one or two places
in the planner that assumed text_ops was a single-datatype opfamily.
I chose to unify hash name_ops into hash text_ops as well, since the
types have compatible hashing semantics. This allows marking the
new cross-type equality operators as oprcanhash.
(Note: this doesn't remove the name_ops opclasses, so there's no
breakage of index definitions. Those opclasses are just reparented
into the text_ops opfamily.)
Discussion: https://postgr.es/m/15938.1544377821@sss.pgh.pa.us
Diffstat (limited to 'src/backend/utils/adt/varlena.c')
-rw-r--r-- | src/backend/utils/adt/varlena.c | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c index a4fb5885c7e..50a157df9fb 100644 --- a/src/backend/utils/adt/varlena.c +++ b/src/backend/utils/adt/varlena.c @@ -2694,6 +2694,167 @@ text_smaller(PG_FUNCTION_ARGS) /* + * Cross-type comparison functions for types text and name. + */ + +Datum +nameeqtext(PG_FUNCTION_ARGS) +{ + Name arg1 = PG_GETARG_NAME(0); + text *arg2 = PG_GETARG_TEXT_PP(1); + size_t len1 = strlen(NameStr(*arg1)); + size_t len2 = VARSIZE_ANY_EXHDR(arg2); + bool result; + + result = (len1 == len2 && + memcmp(NameStr(*arg1), VARDATA_ANY(arg2), len1) == 0); + + PG_FREE_IF_COPY(arg2, 1); + + PG_RETURN_BOOL(result); +} + +Datum +texteqname(PG_FUNCTION_ARGS) +{ + text *arg1 = PG_GETARG_TEXT_PP(0); + Name arg2 = PG_GETARG_NAME(1); + size_t len1 = VARSIZE_ANY_EXHDR(arg1); + size_t len2 = strlen(NameStr(*arg2)); + bool result; + + result = (len1 == len2 && + memcmp(VARDATA_ANY(arg1), NameStr(*arg2), len1) == 0); + + PG_FREE_IF_COPY(arg1, 0); + + PG_RETURN_BOOL(result); +} + +Datum +namenetext(PG_FUNCTION_ARGS) +{ + Name arg1 = PG_GETARG_NAME(0); + text *arg2 = PG_GETARG_TEXT_PP(1); + size_t len1 = strlen(NameStr(*arg1)); + size_t len2 = VARSIZE_ANY_EXHDR(arg2); + bool result; + + result = !(len1 == len2 && + memcmp(NameStr(*arg1), VARDATA_ANY(arg2), len1) == 0); + + PG_FREE_IF_COPY(arg2, 1); + + PG_RETURN_BOOL(result); +} + +Datum +textnename(PG_FUNCTION_ARGS) +{ + text *arg1 = PG_GETARG_TEXT_PP(0); + Name arg2 = PG_GETARG_NAME(1); + size_t len1 = VARSIZE_ANY_EXHDR(arg1); + size_t len2 = strlen(NameStr(*arg2)); + bool result; + + result = !(len1 == len2 && + memcmp(VARDATA_ANY(arg1), NameStr(*arg2), len1) == 0); + + PG_FREE_IF_COPY(arg1, 0); + + PG_RETURN_BOOL(result); +} + +Datum +btnametextcmp(PG_FUNCTION_ARGS) +{ + Name arg1 = PG_GETARG_NAME(0); + text *arg2 = PG_GETARG_TEXT_PP(1); + int32 result; + + result = varstr_cmp(NameStr(*arg1), strlen(NameStr(*arg1)), + VARDATA_ANY(arg2), VARSIZE_ANY_EXHDR(arg2), + PG_GET_COLLATION()); + + PG_FREE_IF_COPY(arg2, 1); + + PG_RETURN_INT32(result); +} + +Datum +bttextnamecmp(PG_FUNCTION_ARGS) +{ + text *arg1 = PG_GETARG_TEXT_PP(0); + Name arg2 = PG_GETARG_NAME(1); + int32 result; + + result = varstr_cmp(VARDATA_ANY(arg1), VARSIZE_ANY_EXHDR(arg1), + NameStr(*arg2), strlen(NameStr(*arg2)), + PG_GET_COLLATION()); + + PG_FREE_IF_COPY(arg1, 0); + + PG_RETURN_INT32(result); +} + +#define CmpCall(cmpfunc) \ + DatumGetInt32(DirectFunctionCall2Coll(cmpfunc, \ + PG_GET_COLLATION(), \ + PG_GETARG_DATUM(0), \ + PG_GETARG_DATUM(1))) + +Datum +namelttext(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL(CmpCall(btnametextcmp) < 0); +} + +Datum +nameletext(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL(CmpCall(btnametextcmp) <= 0); +} + +Datum +namegttext(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL(CmpCall(btnametextcmp) > 0); +} + +Datum +namegetext(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL(CmpCall(btnametextcmp) >= 0); +} + +Datum +textltname(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL(CmpCall(bttextnamecmp) < 0); +} + +Datum +textlename(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL(CmpCall(bttextnamecmp) <= 0); +} + +Datum +textgtname(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL(CmpCall(bttextnamecmp) > 0); +} + +Datum +textgename(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL(CmpCall(bttextnamecmp) >= 0); +} + +#undef CmpCall + + +/* * The following operators support character-by-character comparison * of text datums, to allow building indexes suitable for LIKE clauses. * Note that the regular texteq/textne comparison operators, and regular |