1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-07 00:36:50 +03:00

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
This commit is contained in:
Tom Lane
2018-12-19 17:46:07 -05:00
parent 586b98fdf1
commit 2ece7c07dc
13 changed files with 389 additions and 89 deletions

View File

@ -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);