1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-19 13:42:17 +03:00

Indexing support for pattern matching operations via separate operator

class when lc_collate is not C.
This commit is contained in:
Peter Eisentraut
2003-05-15 15:50:21 +00:00
parent 2a2f6cfa39
commit 2c0556068f
20 changed files with 489 additions and 208 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtcompare.c,v 1.44 2002/06/20 20:29:25 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtcompare.c,v 1.45 2003/05/15 15:50:18 petere Exp $
*
* NOTES
*
@@ -149,3 +149,12 @@ btnamecmp(PG_FUNCTION_ARGS)
PG_RETURN_INT32(strncmp(NameStr(*a), NameStr(*b), NAMEDATALEN));
}
Datum
btname_pattern_cmp(PG_FUNCTION_ARGS)
{
Name a = PG_GETARG_NAME(0);
Name b = PG_GETARG_NAME(1);
PG_RETURN_INT32(memcmp(NameStr(*a), NameStr(*b), NAMEDATALEN));
}

View File

@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.137 2003/05/13 04:38:58 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.138 2003/05/15 15:50:18 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1797,14 +1797,13 @@ match_special_index_operator(Expr *clause, Oid opclass,
case OID_VARCHAR_LIKE_OP:
case OID_NAME_LIKE_OP:
/* the right-hand const is type text for all of these */
if (locale_is_like_safe())
isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Like,
&prefix, &rest) != Pattern_Prefix_None;
isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Like,
&prefix, &rest) != Pattern_Prefix_None;
break;
case OID_BYTEA_LIKE_OP:
isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Like,
&prefix, &rest) != Pattern_Prefix_None;
&prefix, &rest) != Pattern_Prefix_None;
break;
case OID_TEXT_ICLIKE_OP:
@@ -1812,9 +1811,8 @@ match_special_index_operator(Expr *clause, Oid opclass,
case OID_VARCHAR_ICLIKE_OP:
case OID_NAME_ICLIKE_OP:
/* the right-hand const is type text for all of these */
if (locale_is_like_safe())
isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Like_IC,
&prefix, &rest) != Pattern_Prefix_None;
isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Like_IC,
&prefix, &rest) != Pattern_Prefix_None;
break;
case OID_TEXT_REGEXEQ_OP:
@@ -1822,9 +1820,8 @@ match_special_index_operator(Expr *clause, Oid opclass,
case OID_VARCHAR_REGEXEQ_OP:
case OID_NAME_REGEXEQ_OP:
/* the right-hand const is type text for all of these */
if (locale_is_like_safe())
isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Regex,
&prefix, &rest) != Pattern_Prefix_None;
isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Regex,
&prefix, &rest) != Pattern_Prefix_None;
break;
case OID_TEXT_ICREGEXEQ_OP:
@@ -1832,9 +1829,8 @@ match_special_index_operator(Expr *clause, Oid opclass,
case OID_VARCHAR_ICREGEXEQ_OP:
case OID_NAME_ICREGEXEQ_OP:
/* the right-hand const is type text for all of these */
if (locale_is_like_safe())
isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Regex_IC,
&prefix, &rest) != Pattern_Prefix_None;
isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Regex_IC,
&prefix, &rest) != Pattern_Prefix_None;
break;
case OID_INET_SUB_OP:
@@ -1867,42 +1863,53 @@ match_special_index_operator(Expr *clause, Oid opclass,
case OID_TEXT_ICLIKE_OP:
case OID_TEXT_REGEXEQ_OP:
case OID_TEXT_ICREGEXEQ_OP:
if (!op_in_opclass(find_operator(">=", TEXTOID), opclass) ||
!op_in_opclass(find_operator("<", TEXTOID), opclass))
isIndexable = false;
if (lc_collate_is_c())
isIndexable = (op_in_opclass(find_operator(">=", TEXTOID), opclass)
&& op_in_opclass(find_operator("<", TEXTOID), opclass));
else
isIndexable = (op_in_opclass(find_operator("~>=~", TEXTOID), opclass)
&& op_in_opclass(find_operator("~<~", TEXTOID), opclass));
break;
case OID_BYTEA_LIKE_OP:
if (!op_in_opclass(find_operator(">=", BYTEAOID), opclass) ||
!op_in_opclass(find_operator("<", BYTEAOID), opclass))
isIndexable = false;
isIndexable = (op_in_opclass(find_operator(">=", BYTEAOID), opclass)
&& op_in_opclass(find_operator("<", BYTEAOID), opclass));
break;
case OID_BPCHAR_LIKE_OP:
case OID_BPCHAR_ICLIKE_OP:
case OID_BPCHAR_REGEXEQ_OP:
case OID_BPCHAR_ICREGEXEQ_OP:
if (!op_in_opclass(find_operator(">=", BPCHAROID), opclass) ||
!op_in_opclass(find_operator("<", BPCHAROID), opclass))
isIndexable = false;
if (lc_collate_is_c())
isIndexable = (op_in_opclass(find_operator(">=", BPCHAROID), opclass)
&& op_in_opclass(find_operator("<", BPCHAROID), opclass));
else
isIndexable = (op_in_opclass(find_operator("~>=~", BPCHAROID), opclass)
&& op_in_opclass(find_operator("~<~", BPCHAROID), opclass));
break;
case OID_VARCHAR_LIKE_OP:
case OID_VARCHAR_ICLIKE_OP:
case OID_VARCHAR_REGEXEQ_OP:
case OID_VARCHAR_ICREGEXEQ_OP:
if (!op_in_opclass(find_operator(">=", VARCHAROID), opclass) ||
!op_in_opclass(find_operator("<", VARCHAROID), opclass))
isIndexable = false;
if (lc_collate_is_c())
isIndexable = (op_in_opclass(find_operator(">=", VARCHAROID), opclass)
&& op_in_opclass(find_operator("<", VARCHAROID), opclass));
else
isIndexable = (op_in_opclass(find_operator("~>=~", VARCHAROID), opclass)
&& op_in_opclass(find_operator("~<~", VARCHAROID), opclass));
break;
case OID_NAME_LIKE_OP:
case OID_NAME_ICLIKE_OP:
case OID_NAME_REGEXEQ_OP:
case OID_NAME_ICREGEXEQ_OP:
if (!op_in_opclass(find_operator(">=", NAMEOID), opclass) ||
!op_in_opclass(find_operator("<", NAMEOID), opclass))
isIndexable = false;
if (lc_collate_is_c())
isIndexable = (op_in_opclass(find_operator(">=", NAMEOID), opclass)
&& op_in_opclass(find_operator("<", NAMEOID), opclass));
else
isIndexable = (op_in_opclass(find_operator("~>=~", NAMEOID), opclass)
&& op_in_opclass(find_operator("~<~", NAMEOID), opclass));
break;
case OID_INET_SUB_OP:
@@ -2039,6 +2046,7 @@ prefix_quals(Node *leftop, Oid expr_op,
List *result;
Oid datatype;
Oid oproid;
const char *oprname;
char *prefix;
Const *con;
Expr *expr;
@@ -2098,9 +2106,10 @@ prefix_quals(Node *leftop, Oid expr_op,
*/
if (pstatus == Pattern_Prefix_Exact)
{
oproid = find_operator("=", datatype);
oprname = (datatype == BYTEAOID || lc_collate_is_c() ? "=" : "~=~");
oproid = find_operator(oprname, datatype);
if (oproid == InvalidOid)
elog(ERROR, "prefix_quals: no = operator for type %u", datatype);
elog(ERROR, "prefix_quals: no operator %s for type %u", oprname, datatype);
con = string_to_const(prefix, datatype);
expr = make_opclause(oproid, BOOLOID, false,
(Expr *) leftop, (Expr *) con);
@@ -2113,9 +2122,10 @@ prefix_quals(Node *leftop, Oid expr_op,
*
* We can always say "x >= prefix".
*/
oproid = find_operator(">=", datatype);
oprname = (datatype == BYTEAOID || lc_collate_is_c() ? ">=" : "~>=~");
oproid = find_operator(oprname, datatype);
if (oproid == InvalidOid)
elog(ERROR, "prefix_quals: no >= operator for type %u", datatype);
elog(ERROR, "prefix_quals: no operator %s for type %u", oprname, datatype);
con = string_to_const(prefix, datatype);
expr = make_opclause(oproid, BOOLOID, false,
(Expr *) leftop, (Expr *) con);
@@ -2129,9 +2139,10 @@ prefix_quals(Node *leftop, Oid expr_op,
greaterstr = make_greater_string(con);
if (greaterstr)
{
oproid = find_operator("<", datatype);
oprname = (datatype == BYTEAOID || lc_collate_is_c() ? "<" : "~<~");
oproid = find_operator(oprname, datatype);
if (oproid == InvalidOid)
elog(ERROR, "prefix_quals: no < operator for type %u", datatype);
elog(ERROR, "prefix_quals: no operator %s for type %u", oprname, datatype);
expr = make_opclause(oproid, BOOLOID, false,
(Expr *) leftop, (Expr *) greaterstr);
result = lappend(result, expr);

View File

@@ -14,7 +14,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/name.c,v 1.45 2003/05/09 21:19:49 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/name.c,v 1.46 2003/05/15 15:50:18 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -182,6 +182,65 @@ namege(PG_FUNCTION_ARGS)
}
/*
* comparison routines for LIKE indexing support
*/
Datum
name_pattern_eq(PG_FUNCTION_ARGS)
{
Name arg1 = PG_GETARG_NAME(0);
Name arg2 = PG_GETARG_NAME(1);
PG_RETURN_BOOL(memcmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) == 0);
}
Datum
name_pattern_ne(PG_FUNCTION_ARGS)
{
Name arg1 = PG_GETARG_NAME(0);
Name arg2 = PG_GETARG_NAME(1);
PG_RETURN_BOOL(memcmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) != 0);
}
Datum
name_pattern_lt(PG_FUNCTION_ARGS)
{
Name arg1 = PG_GETARG_NAME(0);
Name arg2 = PG_GETARG_NAME(1);
PG_RETURN_BOOL(memcmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) < 0);
}
Datum
name_pattern_le(PG_FUNCTION_ARGS)
{
Name arg1 = PG_GETARG_NAME(0);
Name arg2 = PG_GETARG_NAME(1);
PG_RETURN_BOOL(memcmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) <= 0);
}
Datum
name_pattern_gt(PG_FUNCTION_ARGS)
{
Name arg1 = PG_GETARG_NAME(0);
Name arg2 = PG_GETARG_NAME(1);
PG_RETURN_BOOL(memcmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) > 0);
}
Datum
name_pattern_ge(PG_FUNCTION_ARGS)
{
Name arg1 = PG_GETARG_NAME(0);
Name arg2 = PG_GETARG_NAME(1);
PG_RETURN_BOOL(memcmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) >= 0);
}
/* (see char.c for comparison/operation routines) */
int

View File

@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.136 2003/04/16 04:37:58 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.137 2003/05/15 15:50:18 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -180,8 +180,6 @@ static void get_join_vars(List *args, Var **var1, Var **var2);
static Selectivity prefix_selectivity(Query *root, Var *var, Oid vartype,
Const *prefix);
static Selectivity pattern_selectivity(Const *patt, Pattern_Type ptype);
static bool string_lessthan(const char *str1, const char *str2,
Oid datatype);
static Oid find_operator(const char *opname, Oid datatype);
static Datum string_to_datum(const char *str, Oid datatype);
static Const *string_to_const(const char *str, Oid datatype);
@@ -3619,51 +3617,21 @@ pattern_selectivity(Const *patt, Pattern_Type ptype)
/*
* We want to test whether the database's LC_COLLATE setting is safe for
* LIKE/regexp index optimization.
* Try to generate a string greater than the given string or any
* string it is a prefix of. If successful, return a palloc'd string;
* else return NULL.
*
* The key requirement here is that given a prefix string, say "foo",
* we must be able to generate another string "fop" that is greater
* than all strings "foobar" starting with "foo". Unfortunately, a
* non-C locale may have arbitrary collation rules in which "fop" >
* "foo" is not sufficient to ensure "fop" > "foobar". Until we can
* come up with a more bulletproof way of generating the upper-bound
* string, the optimization is disabled in all non-C locales.
* than all strings "foobar" starting with "foo".
*
* (In theory, locales other than C may be LIKE-safe so this function
* could be different from lc_collate_is_c(), but in a different
* theory, non-C locales are completely unpredictable so it's unlikely
* to happen.)
* If we max out the righthand byte, truncate off the last character
* and start incrementing the next. For example, if "z" were the last
* character in the sort order, then we could produce "foo" as a
* string greater than "fonz".
*
* Be sure to maintain the correspondence with the code in initdb.
*/
bool
locale_is_like_safe(void)
{
return lc_collate_is_c();
}
/*
* Try to generate a string greater than the given string or any string it is
* a prefix of. If successful, return a palloc'd string; else return NULL.
*
* To work correctly in non-ASCII locales with weird collation orders,
* we cannot simply increment "foo" to "fop" --- we have to check whether
* we actually produced a string greater than the given one. If not,
* increment the righthand byte again and repeat. If we max out the righthand
* byte, truncate off the last character and start incrementing the next.
* For example, if "z" were the last character in the sort order, then we
* could produce "foo" as a string greater than "fonz".
*
* This could be rather slow in the worst case, but in most cases we won't
* have to try more than one or two strings before succeeding.
*
* XXX this is actually not sufficient, since it only copes with the case
* where individual characters collate in an order different from their
* numeric code assignments. It does not handle cases where there are
* cross-character effects, such as specially sorted digraphs, multiple
* sort passes, etc. For now, we just shut down the whole thing in locales
* that do such things :-(
* This could be rather slow in the worst case, but in most cases we
* won't have to try more than one or two strings before succeeding.
*/
Const *
make_greater_string(const Const *str_const)
@@ -3699,18 +3667,16 @@ make_greater_string(const Const *str_const)
/*
* Try to generate a larger string by incrementing the last byte.
*/
while (*lastchar < (unsigned char) 255)
if (*lastchar < (unsigned char) 255)
{
(*lastchar)++;
if (string_lessthan(str, workstr, datatype))
{
/* Success! */
Const *workstr_const = string_to_const(workstr, datatype);
Const *workstr_const;
pfree(str);
pfree(workstr);
return workstr_const;
}
(*lastchar)++;
workstr_const = string_to_const(workstr, datatype);
pfree(str);
pfree(workstr);
return workstr_const;
}
/* restore last byte so we don't confuse pg_mbcliplen */
@@ -3736,57 +3702,6 @@ make_greater_string(const Const *str_const)
return (Const *) NULL;
}
/*
* Test whether two strings are "<" according to the rules of the given
* datatype. We do this the hard way, ie, actually calling the type's
* "<" operator function, to ensure we get the right result...
*/
static bool
string_lessthan(const char *str1, const char *str2, Oid datatype)
{
Datum datum1 = string_to_datum(str1, datatype);
Datum datum2 = string_to_datum(str2, datatype);
bool result;
switch (datatype)
{
case TEXTOID:
result = DatumGetBool(DirectFunctionCall2(text_lt,
datum1, datum2));
break;
case BPCHAROID:
result = DatumGetBool(DirectFunctionCall2(bpcharlt,
datum1, datum2));
break;
case VARCHAROID:
result = DatumGetBool(DirectFunctionCall2(varcharlt,
datum1, datum2));
break;
case NAMEOID:
result = DatumGetBool(DirectFunctionCall2(namelt,
datum1, datum2));
break;
case BYTEAOID:
result = DatumGetBool(DirectFunctionCall2(bytealt,
datum1, datum2));
break;
default:
elog(ERROR, "string_lessthan: unexpected datatype %u", datatype);
result = false;
break;
}
pfree(DatumGetPointer(datum1));
pfree(DatumGetPointer(datum2));
return result;
}
/* See if there is a binary op of the given name for the given datatype */
/* NB: we assume that only built-in system operators are searched for */
static Oid

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.97 2003/05/09 15:44:40 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.98 2003/05/15 15:50:19 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1050,6 +1050,149 @@ text_smaller(PG_FUNCTION_ARGS)
PG_RETURN_TEXT_P(result);
}
/*
* The following operators support character-by-character comparison
* of text data types, to allow building indexes suitable for LIKE
* clauses.
*/
static int
internal_text_pattern_compare(text *arg1, text *arg2)
{
int result;
result = memcmp(VARDATA(arg1), VARDATA(arg2),
Min(VARSIZE(arg1), VARSIZE(arg2)) - VARHDRSZ);
if (result != 0)
return result;
else if (VARSIZE(arg1) < VARSIZE(arg2))
return -1;
else if (VARSIZE(arg1) > VARSIZE(arg2))
return 1;
else
return 0;
}
Datum
text_pattern_lt(PG_FUNCTION_ARGS)
{
text *arg1 = PG_GETARG_TEXT_P(0);
text *arg2 = PG_GETARG_TEXT_P(1);
int result;
result = internal_text_pattern_compare(arg1, arg2);
PG_FREE_IF_COPY(arg1, 0);
PG_FREE_IF_COPY(arg2, 1);
PG_RETURN_BOOL(result < 0);
}
Datum
text_pattern_le(PG_FUNCTION_ARGS)
{
text *arg1 = PG_GETARG_TEXT_P(0);
text *arg2 = PG_GETARG_TEXT_P(1);
int result;
result = internal_text_pattern_compare(arg1, arg2);
PG_FREE_IF_COPY(arg1, 0);
PG_FREE_IF_COPY(arg2, 1);
PG_RETURN_BOOL(result <= 0);
}
Datum
text_pattern_eq(PG_FUNCTION_ARGS)
{
text *arg1 = PG_GETARG_TEXT_P(0);
text *arg2 = PG_GETARG_TEXT_P(1);
int result;
if (VARSIZE(arg1) != VARSIZE(arg2))
result = 1;
else
result = internal_text_pattern_compare(arg1, arg2);
PG_FREE_IF_COPY(arg1, 0);
PG_FREE_IF_COPY(arg2, 1);
PG_RETURN_BOOL(result == 0);
}
Datum
text_pattern_ge(PG_FUNCTION_ARGS)
{
text *arg1 = PG_GETARG_TEXT_P(0);
text *arg2 = PG_GETARG_TEXT_P(1);
int result;
result = internal_text_pattern_compare(arg1, arg2);
PG_FREE_IF_COPY(arg1, 0);
PG_FREE_IF_COPY(arg2, 1);
PG_RETURN_BOOL(result >= 0);
}
Datum
text_pattern_gt(PG_FUNCTION_ARGS)
{
text *arg1 = PG_GETARG_TEXT_P(0);
text *arg2 = PG_GETARG_TEXT_P(1);
int result;
result = internal_text_pattern_compare(arg1, arg2);
PG_FREE_IF_COPY(arg1, 0);
PG_FREE_IF_COPY(arg2, 1);
PG_RETURN_BOOL(result > 0);
}
Datum
text_pattern_ne(PG_FUNCTION_ARGS)
{
text *arg1 = PG_GETARG_TEXT_P(0);
text *arg2 = PG_GETARG_TEXT_P(1);
int result;
if (VARSIZE(arg1) != VARSIZE(arg2))
result = 1;
else
result = internal_text_pattern_compare(arg1, arg2);
PG_FREE_IF_COPY(arg1, 0);
PG_FREE_IF_COPY(arg2, 1);
PG_RETURN_BOOL(result != 0);
}
Datum
bttext_pattern_cmp(PG_FUNCTION_ARGS)
{
text *arg1 = PG_GETARG_TEXT_P(0);
text *arg2 = PG_GETARG_TEXT_P(1);
int result;
result = internal_text_pattern_compare(arg1, arg2);
PG_FREE_IF_COPY(arg1, 0);
PG_FREE_IF_COPY(arg2, 1);
PG_RETURN_INT32(result);
}
/*-------------------------------------------------------------
* byteaoctetlen
*

View File

@@ -27,7 +27,7 @@
# Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
# Portions Copyright (c) 1994, Regents of the University of California
#
# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.188 2003/04/04 03:03:53 tgl Exp $
# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.189 2003/05/15 15:50:19 petere Exp $
#
#-------------------------------------------------------------------------
@@ -478,13 +478,6 @@ else
echo " COLLATE: `pg_getlocale COLLATE`${TAB}CTYPE: `pg_getlocale CTYPE`${TAB}MESSAGES: `pg_getlocale MESSAGES`"
echo " MONETARY: `pg_getlocale MONETARY`${TAB}NUMERIC: `pg_getlocale NUMERIC`${TAB}TIME: `pg_getlocale TIME`"
fi
# (Be sure to maintain the correspondence with locale_is_like_safe() in selfuncs.c.)
if test x`pg_getlocale COLLATE` != xC && test x`pg_getlocale COLLATE` != xPOSIX; then
echo "This locale setting will prevent the use of indexes for pattern matching"
echo "operations. If that is a concern, rerun $CMDNAME with the collation order"
echo "set to \"C\". For more information see the documentation."
fi
echo

View File

@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: catversion.h,v 1.193 2003/05/13 18:03:07 tgl Exp $
* $Id: catversion.h,v 1.194 2003/05/15 15:50:19 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200305131
#define CATALOG_VERSION_NO 200305151
#endif

View File

@@ -16,7 +16,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_amop.h,v 1.47 2003/03/10 22:28:19 tgl Exp $
* $Id: pg_amop.h,v 1.48 2003/05/15 15:50:19 petere Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@@ -378,6 +378,46 @@ DATA(insert ( 2002 3 f 1804 ));
DATA(insert ( 2002 4 f 1809 ));
DATA(insert ( 2002 5 f 1807 ));
/*
* btree text pattern
*/
DATA(insert ( 2095 1 f 2314 ));
DATA(insert ( 2095 2 f 2315 ));
DATA(insert ( 2095 3 f 2316 ));
DATA(insert ( 2095 4 f 2317 ));
DATA(insert ( 2095 5 f 2318 ));
/*
* btree varchar pattern
*/
DATA(insert ( 2096 1 f 2320 ));
DATA(insert ( 2096 2 f 2321 ));
DATA(insert ( 2096 3 f 2322 ));
DATA(insert ( 2096 4 f 2323 ));
DATA(insert ( 2096 5 f 2324 ));
/*
* btree bpchar pattern
*/
DATA(insert ( 2097 1 f 2326 ));
DATA(insert ( 2097 2 f 2327 ));
DATA(insert ( 2097 3 f 2328 ));
DATA(insert ( 2097 4 f 2329 ));
DATA(insert ( 2097 5 f 2330 ));
/*
* btree name pattern
*/
DATA(insert ( 2098 1 f 2332 ));
DATA(insert ( 2098 2 f 2333 ));
DATA(insert ( 2098 3 f 2334 ));
DATA(insert ( 2098 4 f 2335 ));
DATA(insert ( 2098 5 f 2336 ));
/*
* hash index _ops

View File

@@ -14,7 +14,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_amproc.h,v 1.35 2002/06/20 20:29:44 momjian Exp $
* $Id: pg_amproc.h,v 1.36 2003/05/15 15:50:19 petere Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@@ -105,6 +105,10 @@ DATA(insert ( 2000 1 1358 ));
DATA(insert ( 2002 1 1672 ));
DATA(insert ( 2003 1 1079 ));
DATA(insert ( 2039 1 1314 ));
DATA(insert ( 2095 1 2166 ));
DATA(insert ( 2096 1 2173 ));
DATA(insert ( 2097 1 2180 ));
DATA(insert ( 2098 1 2187 ));
/* hash */

View File

@@ -26,7 +26,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_opclass.h,v 1.47 2003/03/10 22:28:19 tgl Exp $
* $Id: pg_opclass.h,v 1.48 2003/05/15 15:50:19 petere Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@@ -140,5 +140,9 @@ DATA(insert OID = 2003 ( 403 varchar_ops PGNSP PGUID 1043 t 0 ));
DATA(insert OID = 2004 ( 405 varchar_ops PGNSP PGUID 1043 t 0 ));
DATA(insert OID = 2039 ( 403 timestamp_ops PGNSP PGUID 1114 t 0 ));
DATA(insert OID = 2040 ( 405 timestamp_ops PGNSP PGUID 1114 t 0 ));
DATA(insert OID = 2095 ( 403 text_pattern_ops PGNSP PGUID 25 f 0 ));
DATA(insert OID = 2096 ( 403 varchar_pattern_ops PGNSP PGUID 1043 f 0 ));
DATA(insert OID = 2097 ( 403 bpchar_pattern_ops PGNSP PGUID 1042 f 0 ));
DATA(insert OID = 2098 ( 403 name_pattern_ops PGNSP PGUID 19 f 0 ));
#endif /* PG_OPCLASS_H */

View File

@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_operator.h,v 1.112 2003/04/08 23:20:03 tgl Exp $
* $Id: pg_operator.h,v 1.113 2003/05/15 15:50:19 petere Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@@ -814,6 +814,37 @@ DATA(insert OID = 2066 ( "+" PGNSP PGUID b f 1114 1186 1114 0 0 0 0 0 0 tim
DATA(insert OID = 2067 ( "-" PGNSP PGUID b f 1114 1114 1186 0 0 0 0 0 0 timestamp_mi - - ));
DATA(insert OID = 2068 ( "-" PGNSP PGUID b f 1114 1186 1114 0 0 0 0 0 0 timestamp_mi_span - - ));
/* character-by-character (not collation order) comparison operators for character types */
DATA(insert OID = 2314 ( "~<~" PGNSP PGUID b f 25 25 16 2318 2317 0 0 0 0 text_pattern_lt scalarltsel scalarltjoinsel ));
DATA(insert OID = 2315 ( "~<=~" PGNSP PGUID b f 25 25 16 2317 2318 0 0 0 0 text_pattern_le scalarltsel scalarltjoinsel ));
DATA(insert OID = 2316 ( "~=~" PGNSP PGUID b t 25 25 16 2316 2319 2314 2314 2314 2318 text_pattern_eq eqsel eqjoinsel ));
DATA(insert OID = 2317 ( "~>=~" PGNSP PGUID b f 25 25 16 2315 2314 0 0 0 0 text_pattern_ge scalargtsel scalargtjoinsel ));
DATA(insert OID = 2318 ( "~>~" PGNSP PGUID b f 25 25 16 2314 2315 0 0 0 0 text_pattern_gt scalargtsel scalargtjoinsel ));
DATA(insert OID = 2319 ( "~<>~" PGNSP PGUID b f 25 25 16 2319 2316 0 0 0 0 text_pattern_ne neqsel neqjoinsel ));
DATA(insert OID = 2320 ( "~<~" PGNSP PGUID b f 1043 1043 16 2324 2323 0 0 0 0 varchar_pattern_lt scalarltsel scalarltjoinsel ));
DATA(insert OID = 2321 ( "~<=~" PGNSP PGUID b f 1043 1043 16 2323 2324 0 0 0 0 varchar_pattern_le scalarltsel scalarltjoinsel ));
DATA(insert OID = 2322 ( "~=~" PGNSP PGUID b t 1043 1043 16 2322 2325 2320 2320 2320 2324 varchar_pattern_eq eqsel eqjoinsel ));
DATA(insert OID = 2323 ( "~>=~" PGNSP PGUID b f 1043 1043 16 2321 2320 0 0 0 0 varchar_pattern_ge scalargtsel scalargtjoinsel ));
DATA(insert OID = 2324 ( "~>~" PGNSP PGUID b f 1043 1043 16 2320 2321 0 0 0 0 varchar_pattern_gt scalargtsel scalargtjoinsel ));
DATA(insert OID = 2325 ( "~<>~" PGNSP PGUID b f 1043 1043 16 2325 2322 0 0 0 0 varchar_pattern_ne neqsel neqjoinsel ));
DATA(insert OID = 2326 ( "~<~" PGNSP PGUID b f 1042 1042 16 2330 2329 0 0 0 0 bpchar_pattern_lt scalarltsel scalarltjoinsel ));
DATA(insert OID = 2327 ( "~<=~" PGNSP PGUID b f 1042 1042 16 2329 2330 0 0 0 0 bpchar_pattern_le scalarltsel scalarltjoinsel ));
DATA(insert OID = 2328 ( "~=~" PGNSP PGUID b t 1042 1042 16 2328 2331 2326 2326 2326 2330 bpchar_pattern_eq eqsel eqjoinsel ));
DATA(insert OID = 2329 ( "~>=~" PGNSP PGUID b f 1042 1042 16 2327 2326 0 0 0 0 bpchar_pattern_ge scalargtsel scalargtjoinsel ));
DATA(insert OID = 2330 ( "~>~" PGNSP PGUID b f 1042 1042 16 2326 2327 0 0 0 0 bpchar_pattern_gt scalargtsel scalargtjoinsel ));
DATA(insert OID = 2331 ( "~<>~" PGNSP PGUID b f 1042 1042 16 2331 2328 0 0 0 0 bpchar_pattern_ne neqsel neqjoinsel ));
DATA(insert OID = 2332 ( "~<~" PGNSP PGUID b f 19 19 16 2336 2335 0 0 0 0 name_pattern_lt scalarltsel scalarltjoinsel ));
DATA(insert OID = 2333 ( "~<=~" PGNSP PGUID b f 19 19 16 2335 2336 0 0 0 0 name_pattern_le scalarltsel scalarltjoinsel ));
DATA(insert OID = 2334 ( "~=~" PGNSP PGUID b t 19 19 16 2334 2337 2332 2332 2332 2336 name_pattern_eq eqsel eqjoinsel ));
DATA(insert OID = 2335 ( "~>=~" PGNSP PGUID b f 19 19 16 2333 2332 0 0 0 0 name_pattern_ge scalargtsel scalargtjoinsel ));
DATA(insert OID = 2336 ( "~>~" PGNSP PGUID b f 19 19 16 2332 2333 0 0 0 0 name_pattern_gt scalargtsel scalargtjoinsel ));
DATA(insert OID = 2337 ( "~<>~" PGNSP PGUID b f 19 19 16 2337 2334 0 0 0 0 name_pattern_ne neqsel neqjoinsel ));
/*
* function prototypes

View File

@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_proc.h,v 1.299 2003/05/13 18:03:07 tgl Exp $
* $Id: pg_proc.h,v 1.300 2003/05/15 15:50:19 petere Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
@@ -3024,6 +3024,39 @@ DATA(insert OID = 2157 ( stddev PGNSP PGUID 12 t f f f i 1 701 "700" aggrega
DATA(insert OID = 2158 ( stddev PGNSP PGUID 12 t f f f i 1 701 "701" aggregate_dummy - _null_ ));
DATA(insert OID = 2159 ( stddev PGNSP PGUID 12 t f f f i 1 1700 "1700" aggregate_dummy - _null_ ));
DATA(insert OID = 2160 ( text_pattern_lt PGNSP PGUID 12 f f t f i 2 16 "25 25" text_pattern_lt - _null_ ));
DATA(insert OID = 2161 ( text_pattern_le PGNSP PGUID 12 f f t f i 2 16 "25 25" text_pattern_le - _null_ ));
DATA(insert OID = 2162 ( text_pattern_eq PGNSP PGUID 12 f f t f i 2 16 "25 25" text_pattern_eq - _null_ ));
DATA(insert OID = 2163 ( text_pattern_ge PGNSP PGUID 12 f f t f i 2 16 "25 25" text_pattern_ge - _null_ ));
DATA(insert OID = 2164 ( text_pattern_gt PGNSP PGUID 12 f f t f i 2 16 "25 25" text_pattern_gt - _null_ ));
DATA(insert OID = 2165 ( text_pattern_ne PGNSP PGUID 12 f f t f i 2 16 "25 25" text_pattern_ne - _null_ ));
DATA(insert OID = 2166 ( bttext_pattern_cmp PGNSP PGUID 12 f f t f i 2 23 "25 25" bttext_pattern_cmp - _null_ ));
/* We use the same procedures here as above since the types are binary compatible. */
DATA(insert OID = 2167 ( varchar_pattern_lt PGNSP PGUID 12 f f t f i 2 16 "1043 1043" text_pattern_lt - _null_ ));
DATA(insert OID = 2168 ( varchar_pattern_le PGNSP PGUID 12 f f t f i 2 16 "1043 1043" text_pattern_le - _null_ ));
DATA(insert OID = 2169 ( varchar_pattern_eq PGNSP PGUID 12 f f t f i 2 16 "1043 1043" text_pattern_eq - _null_ ));
DATA(insert OID = 2170 ( varchar_pattern_ge PGNSP PGUID 12 f f t f i 2 16 "1043 1043" text_pattern_ge - _null_ ));
DATA(insert OID = 2171 ( varchar_pattern_gt PGNSP PGUID 12 f f t f i 2 16 "1043 1043" text_pattern_gt - _null_ ));
DATA(insert OID = 2172 ( varchar_pattern_ne PGNSP PGUID 12 f f t f i 2 16 "1043 1043" text_pattern_ne - _null_ ));
DATA(insert OID = 2173 ( btvarchar_pattern_cmp PGNSP PGUID 12 f f t f i 2 23 "1043 1043" bttext_pattern_cmp - _null_ ));
DATA(insert OID = 2174 ( bpchar_pattern_lt PGNSP PGUID 12 f f t f i 2 16 "1042 1042" text_pattern_lt - _null_ ));
DATA(insert OID = 2175 ( bpchar_pattern_le PGNSP PGUID 12 f f t f i 2 16 "1042 1042" text_pattern_le - _null_ ));
DATA(insert OID = 2176 ( bpchar_pattern_eq PGNSP PGUID 12 f f t f i 2 16 "1042 1042" text_pattern_eq - _null_ ));
DATA(insert OID = 2177 ( bpchar_pattern_ge PGNSP PGUID 12 f f t f i 2 16 "1042 1042" text_pattern_ge - _null_ ));
DATA(insert OID = 2178 ( bpchar_pattern_gt PGNSP PGUID 12 f f t f i 2 16 "1042 1042" text_pattern_gt - _null_ ));
DATA(insert OID = 2179 ( bpchar_pattern_ne PGNSP PGUID 12 f f t f i 2 16 "1042 1042" text_pattern_ne - _null_ ));
DATA(insert OID = 2180 ( btbpchar_pattern_cmp PGNSP PGUID 12 f f t f i 2 23 "1042 1042" bttext_pattern_cmp - _null_ ));
DATA(insert OID = 2181 ( name_pattern_lt PGNSP PGUID 12 f f t f i 2 16 "19 19" name_pattern_lt - _null_ ));
DATA(insert OID = 2182 ( name_pattern_le PGNSP PGUID 12 f f t f i 2 16 "19 19" name_pattern_le - _null_ ));
DATA(insert OID = 2183 ( name_pattern_eq PGNSP PGUID 12 f f t f i 2 16 "19 19" name_pattern_eq - _null_ ));
DATA(insert OID = 2184 ( name_pattern_ge PGNSP PGUID 12 f f t f i 2 16 "19 19" name_pattern_ge - _null_ ));
DATA(insert OID = 2185 ( name_pattern_gt PGNSP PGUID 12 f f t f i 2 16 "19 19" name_pattern_gt - _null_ ));
DATA(insert OID = 2186 ( name_pattern_ne PGNSP PGUID 12 f f t f i 2 16 "19 19" name_pattern_ne - _null_ ));
DATA(insert OID = 2187 ( btname_pattern_cmp PGNSP PGUID 12 f f t f i 2 23 "19 19" btname_pattern_cmp - _null_ ));
DATA(insert OID = 2212 ( regprocedurein PGNSP PGUID 12 f f t f s 1 2202 "2275" regprocedurein - _null_ ));
DESCR("I/O");

View File

@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: builtins.h,v 1.216 2003/05/13 18:03:08 tgl Exp $
* $Id: builtins.h,v 1.217 2003/05/15 15:50:20 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -190,6 +190,12 @@ extern Datum namelt(PG_FUNCTION_ARGS);
extern Datum namele(PG_FUNCTION_ARGS);
extern Datum namegt(PG_FUNCTION_ARGS);
extern Datum namege(PG_FUNCTION_ARGS);
extern Datum name_pattern_eq(PG_FUNCTION_ARGS);
extern Datum name_pattern_ne(PG_FUNCTION_ARGS);
extern Datum name_pattern_lt(PG_FUNCTION_ARGS);
extern Datum name_pattern_le(PG_FUNCTION_ARGS);
extern Datum name_pattern_gt(PG_FUNCTION_ARGS);
extern Datum name_pattern_ge(PG_FUNCTION_ARGS);
extern int namecpy(Name n1, Name n2);
extern int namestrcpy(Name name, const char *str);
extern int namestrcmp(Name name, const char *str);
@@ -219,6 +225,8 @@ extern Datum btabstimecmp(PG_FUNCTION_ARGS);
extern Datum btcharcmp(PG_FUNCTION_ARGS);
extern Datum btnamecmp(PG_FUNCTION_ARGS);
extern Datum bttextcmp(PG_FUNCTION_ARGS);
extern Datum btname_pattern_cmp(PG_FUNCTION_ARGS);
extern Datum bttext_pattern_cmp(PG_FUNCTION_ARGS);
/* float.c */
extern int extra_float_digits;
@@ -512,6 +520,12 @@ extern Datum text_gt(PG_FUNCTION_ARGS);
extern Datum text_ge(PG_FUNCTION_ARGS);
extern Datum text_larger(PG_FUNCTION_ARGS);
extern Datum text_smaller(PG_FUNCTION_ARGS);
extern Datum text_pattern_eq(PG_FUNCTION_ARGS);
extern Datum text_pattern_ne(PG_FUNCTION_ARGS);
extern Datum text_pattern_lt(PG_FUNCTION_ARGS);
extern Datum text_pattern_le(PG_FUNCTION_ARGS);
extern Datum text_pattern_gt(PG_FUNCTION_ARGS);
extern Datum text_pattern_ge(PG_FUNCTION_ARGS);
extern Datum textlen(PG_FUNCTION_ARGS);
extern Datum textoctetlen(PG_FUNCTION_ARGS);
extern Datum textpos(PG_FUNCTION_ARGS);

View File

@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: selfuncs.h,v 1.12 2003/01/28 22:13:41 tgl Exp $
* $Id: selfuncs.h,v 1.13 2003/05/15 15:50:20 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -37,7 +37,6 @@ extern Pattern_Prefix_Status pattern_fixed_prefix(Const *patt,
Pattern_Type ptype,
Const **prefix,
Const **rest);
extern bool locale_is_like_safe(void);
extern Const *make_greater_string(const Const *str_const);
extern Datum eqsel(PG_FUNCTION_ARGS);

View File

@@ -103,11 +103,13 @@ WHERE p1.oid != p2.oid AND
(p1.proargtypes[0] < p2.proargtypes[0]);
proargtypes | proargtypes
-------------+-------------
25 | 1042
25 | 1043
1042 | 1043
1114 | 1184
1560 | 1562
2277 | 2283
(4 rows)
(6 rows)
SELECT DISTINCT p1.proargtypes[1], p2.proargtypes[1]
FROM pg_proc AS p1, pg_proc AS p2
@@ -118,10 +120,13 @@ WHERE p1.oid != p2.oid AND
(p1.proargtypes[1] < p2.proargtypes[1]);
proargtypes | proargtypes
-------------+-------------
25 | 1042
25 | 1043
1042 | 1043
1114 | 1184
1560 | 1562
2277 | 2283
(3 rows)
(6 rows)
SELECT DISTINCT p1.proargtypes[2], p2.proargtypes[2]
FROM pg_proc AS p1, pg_proc AS p2
@@ -332,7 +337,7 @@ WHERE p1.oprnegate = p2.oid AND
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
FROM pg_operator AS p1, pg_operator AS p2
WHERE p1.oprlsortop = p2.oid AND
(p1.oprname != '=' OR p2.oprname != '<' OR
(p1.oprname NOT IN ('=', '~=~') OR p2.oprname NOT IN ('<', '~<~') OR
p1.oprkind != 'b' OR p2.oprkind != 'b' OR
p1.oprleft != p2.oprleft OR
p1.oprleft != p2.oprright OR
@@ -345,7 +350,7 @@ WHERE p1.oprlsortop = p2.oid AND
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
FROM pg_operator AS p1, pg_operator AS p2
WHERE p1.oprrsortop = p2.oid AND
(p1.oprname != '=' OR p2.oprname != '<' OR
(p1.oprname NOT IN ('=', '~=~') OR p2.oprname NOT IN ('<', '~<~') OR
p1.oprkind != 'b' OR p2.oprkind != 'b' OR
p1.oprright != p2.oprleft OR
p1.oprright != p2.oprright OR
@@ -358,7 +363,7 @@ WHERE p1.oprrsortop = p2.oid AND
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
FROM pg_operator AS p1, pg_operator AS p2
WHERE p1.oprltcmpop = p2.oid AND
(p1.oprname != '=' OR p2.oprname != '<' OR
(p1.oprname NOT IN ('=', '~=~') OR p2.oprname NOT IN ('<', '~<~') OR
p1.oprkind != 'b' OR p2.oprkind != 'b' OR
p1.oprleft != p2.oprleft OR
p1.oprright != p2.oprright OR
@@ -371,7 +376,7 @@ WHERE p1.oprltcmpop = p2.oid AND
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
FROM pg_operator AS p1, pg_operator AS p2
WHERE p1.oprgtcmpop = p2.oid AND
(p1.oprname != '=' OR p2.oprname != '>' OR
(p1.oprname NOT IN ('=', '~=~') OR p2.oprname NOT IN ('>', '~>~') OR
p1.oprkind != 'b' OR p2.oprkind != 'b' OR
p1.oprleft != p2.oprleft OR
p1.oprright != p2.oprright OR
@@ -427,7 +432,7 @@ SELECT p1.oid, p1.oprname
FROM pg_operator AS p1
WHERE p1.oprcanhash AND NOT
(p1.oprkind = 'b' AND p1.oprresult = 'bool'::regtype AND
p1.oprleft = p1.oprright AND p1.oprname = '=' AND p1.oprcom = p1.oid);
p1.oprleft = p1.oprright AND p1.oprname IN ('=', '~=~') AND p1.oprcom = p1.oid);
oid | oprname
-----+---------
353 | =

View File

@@ -276,7 +276,7 @@ WHERE p1.oprnegate = p2.oid AND
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
FROM pg_operator AS p1, pg_operator AS p2
WHERE p1.oprlsortop = p2.oid AND
(p1.oprname != '=' OR p2.oprname != '<' OR
(p1.oprname NOT IN ('=', '~=~') OR p2.oprname NOT IN ('<', '~<~') OR
p1.oprkind != 'b' OR p2.oprkind != 'b' OR
p1.oprleft != p2.oprleft OR
p1.oprleft != p2.oprright OR
@@ -286,7 +286,7 @@ WHERE p1.oprlsortop = p2.oid AND
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
FROM pg_operator AS p1, pg_operator AS p2
WHERE p1.oprrsortop = p2.oid AND
(p1.oprname != '=' OR p2.oprname != '<' OR
(p1.oprname NOT IN ('=', '~=~') OR p2.oprname NOT IN ('<', '~<~') OR
p1.oprkind != 'b' OR p2.oprkind != 'b' OR
p1.oprright != p2.oprleft OR
p1.oprright != p2.oprright OR
@@ -296,7 +296,7 @@ WHERE p1.oprrsortop = p2.oid AND
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
FROM pg_operator AS p1, pg_operator AS p2
WHERE p1.oprltcmpop = p2.oid AND
(p1.oprname != '=' OR p2.oprname != '<' OR
(p1.oprname NOT IN ('=', '~=~') OR p2.oprname NOT IN ('<', '~<~') OR
p1.oprkind != 'b' OR p2.oprkind != 'b' OR
p1.oprleft != p2.oprleft OR
p1.oprright != p2.oprright OR
@@ -306,7 +306,7 @@ WHERE p1.oprltcmpop = p2.oid AND
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
FROM pg_operator AS p1, pg_operator AS p2
WHERE p1.oprgtcmpop = p2.oid AND
(p1.oprname != '=' OR p2.oprname != '>' OR
(p1.oprname NOT IN ('=', '~=~') OR p2.oprname NOT IN ('>', '~>~') OR
p1.oprkind != 'b' OR p2.oprkind != 'b' OR
p1.oprleft != p2.oprleft OR
p1.oprright != p2.oprright OR
@@ -355,7 +355,7 @@ SELECT p1.oid, p1.oprname
FROM pg_operator AS p1
WHERE p1.oprcanhash AND NOT
(p1.oprkind = 'b' AND p1.oprresult = 'bool'::regtype AND
p1.oprleft = p1.oprright AND p1.oprname = '=' AND p1.oprcom = p1.oid);
p1.oprleft = p1.oprright AND p1.oprname IN ('=', '~=~') AND p1.oprcom = p1.oid);
-- In 6.5 we accepted hashable array equality operators when the array element
-- type is hashable. However, what we actually need to make hashjoin work on