diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/optimizer/path/indxpath.c | 36 | ||||
-rw-r--r-- | src/backend/utils/adt/selfuncs.c | 4 | ||||
-rw-r--r-- | src/backend/utils/adt/varlena.c | 161 |
3 files changed, 177 insertions, 24 deletions
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index 965d9648e5d..ca46fb7525a 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -25,6 +25,7 @@ #include "catalog/pg_opfamily.h" #include "catalog/pg_type.h" #include "nodes/makefuncs.h" +#include "nodes/nodeFuncs.h" #include "optimizer/clauses.h" #include "optimizer/cost.h" #include "optimizer/pathnode.h" @@ -3518,6 +3519,10 @@ match_special_index_operator(Expr *clause, Oid opfamily, Oid idxcollation, case OID_TEXT_ICLIKE_OP: case OID_TEXT_REGEXEQ_OP: case OID_TEXT_ICREGEXEQ_OP: + case OID_NAME_LIKE_OP: + case OID_NAME_ICLIKE_OP: + case OID_NAME_REGEXEQ_OP: + case OID_NAME_ICREGEXEQ_OP: isIndexable = (opfamily == TEXT_PATTERN_BTREE_FAM_OID) || (opfamily == TEXT_SPGIST_FAM_OID) || @@ -3537,14 +3542,6 @@ match_special_index_operator(Expr *clause, Oid opfamily, Oid idxcollation, lc_collate_is_c(idxcollation))); break; - case OID_NAME_LIKE_OP: - case OID_NAME_ICLIKE_OP: - case OID_NAME_REGEXEQ_OP: - case OID_NAME_ICREGEXEQ_OP: - /* name uses locale-insensitive sorting */ - isIndexable = (opfamily == NAME_BTREE_FAM_OID); - break; - case OID_BYTEA_LIKE_OP: isIndexable = (opfamily == BYTEA_BTREE_FAM_OID); break; @@ -4097,7 +4094,8 @@ prefix_quals(Node *leftop, Oid opfamily, Oid collation, Const *prefix_const, Pattern_Prefix_Status pstatus) { List *result; - Oid datatype; + Oid ldatatype = exprType(leftop); + Oid rdatatype; Oid oproid; Expr *expr; FmgrInfo ltproc; @@ -4110,20 +4108,16 @@ prefix_quals(Node *leftop, Oid opfamily, Oid collation, case TEXT_BTREE_FAM_OID: case TEXT_PATTERN_BTREE_FAM_OID: case TEXT_SPGIST_FAM_OID: - datatype = TEXTOID; + rdatatype = TEXTOID; break; case BPCHAR_BTREE_FAM_OID: case BPCHAR_PATTERN_BTREE_FAM_OID: - datatype = BPCHAROID; - break; - - case NAME_BTREE_FAM_OID: - datatype = NAMEOID; + rdatatype = BPCHAROID; break; case BYTEA_BTREE_FAM_OID: - datatype = BYTEAOID; + rdatatype = BYTEAOID; break; default: @@ -4136,7 +4130,7 @@ prefix_quals(Node *leftop, Oid opfamily, Oid collation, * If necessary, coerce the prefix constant to the right type. The given * prefix constant is either text or bytea type. */ - if (prefix_const->consttype != datatype) + if (prefix_const->consttype != rdatatype) { char *prefix; @@ -4154,7 +4148,7 @@ prefix_quals(Node *leftop, Oid opfamily, Oid collation, prefix_const->consttype); return NIL; } - prefix_const = string_to_const(prefix, datatype); + prefix_const = string_to_const(prefix, rdatatype); pfree(prefix); } @@ -4163,7 +4157,7 @@ prefix_quals(Node *leftop, Oid opfamily, Oid collation, */ if (pstatus == Pattern_Prefix_Exact) { - oproid = get_opfamily_member(opfamily, datatype, datatype, + oproid = get_opfamily_member(opfamily, ldatatype, rdatatype, BTEqualStrategyNumber); if (oproid == InvalidOid) elog(ERROR, "no = operator for opfamily %u", opfamily); @@ -4179,7 +4173,7 @@ prefix_quals(Node *leftop, Oid opfamily, Oid collation, * * We can always say "x >= prefix". */ - oproid = get_opfamily_member(opfamily, datatype, datatype, + oproid = get_opfamily_member(opfamily, ldatatype, rdatatype, BTGreaterEqualStrategyNumber); if (oproid == InvalidOid) elog(ERROR, "no >= operator for opfamily %u", opfamily); @@ -4196,7 +4190,7 @@ prefix_quals(Node *leftop, Oid opfamily, Oid collation, * using a C-locale index collation. *------- */ - oproid = get_opfamily_member(opfamily, datatype, datatype, + oproid = get_opfamily_member(opfamily, ldatatype, rdatatype, BTLessStrategyNumber); if (oproid == InvalidOid) elog(ERROR, "no < operator for opfamily %u", opfamily); diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index ebedb269832..7155dc90875 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -1292,14 +1292,12 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate) switch (vartype) { case TEXTOID: + case NAMEOID: opfamily = TEXT_BTREE_FAM_OID; break; case BPCHAROID: opfamily = BPCHAR_BTREE_FAM_OID; break; - case NAMEOID: - opfamily = NAME_BTREE_FAM_OID; - break; case BYTEAOID: opfamily = BYTEA_BTREE_FAM_OID; break; 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 |