aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/access/hash/hashfunc.c17
-rw-r--r--src/backend/access/hash/hashvalidate.c130
-rw-r--r--src/backend/utils/adt/bool.c13
-rw-r--r--src/backend/utils/adt/date.c12
-rw-r--r--src/backend/utils/adt/timestamp.c12
-rw-r--r--src/backend/utils/adt/xid.c37
-rw-r--r--src/include/catalog/catversion.h2
-rw-r--r--src/include/catalog/pg_amproc.dat31
-rw-r--r--src/include/catalog/pg_proc.dat42
9 files changed, 174 insertions, 122 deletions
diff --git a/src/backend/access/hash/hashfunc.c b/src/backend/access/hash/hashfunc.c
index 86f1adecb75..2e3e5b06a61 100644
--- a/src/backend/access/hash/hashfunc.c
+++ b/src/backend/access/hash/hashfunc.c
@@ -376,6 +376,11 @@ hashtextextended(PG_FUNCTION_ARGS)
/*
* hashvarlena() can be used for any varlena datatype in which there are
* no non-significant bits, ie, distinct bitpatterns never compare as equal.
+ *
+ * (However, you need to define an SQL-level wrapper function around it with
+ * the concrete input data type; otherwise hashvalidate() won't accept it.
+ * Moreover, at least for built-in types, a C-level wrapper function is also
+ * recommended; otherwise, the opr_sanity test will get upset.)
*/
Datum
hashvarlena(PG_FUNCTION_ARGS)
@@ -406,3 +411,15 @@ hashvarlenaextended(PG_FUNCTION_ARGS)
return result;
}
+
+Datum
+hashbytea(PG_FUNCTION_ARGS)
+{
+ return hashvarlena(fcinfo);
+}
+
+Datum
+hashbyteaextended(PG_FUNCTION_ARGS)
+{
+ return hashvarlenaextended(fcinfo);
+}
diff --git a/src/backend/access/hash/hashvalidate.c b/src/backend/access/hash/hashvalidate.c
index 40164e2ea2b..66a3b7b49ad 100644
--- a/src/backend/access/hash/hashvalidate.c
+++ b/src/backend/access/hash/hashvalidate.c
@@ -22,19 +22,13 @@
#include "catalog/pg_amproc.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_opfamily.h"
-#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
-#include "parser/parse_coerce.h"
#include "utils/builtins.h"
-#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/regproc.h"
#include "utils/syscache.h"
-static bool check_hash_func_signature(Oid funcid, int16 amprocnum, Oid argtype);
-
-
/*
* Validator for a hash opclass.
*
@@ -90,6 +84,7 @@ hashvalidate(Oid opclassoid)
{
HeapTuple proctup = &proclist->members[i]->tuple;
Form_pg_amproc procform = (Form_pg_amproc) GETSTRUCT(proctup);
+ bool ok;
/*
* All hash functions should be registered with matching left/right
@@ -109,29 +104,15 @@ hashvalidate(Oid opclassoid)
switch (procform->amprocnum)
{
case HASHSTANDARD_PROC:
+ ok = check_amproc_signature(procform->amproc, INT4OID, true,
+ 1, 1, procform->amproclefttype);
+ break;
case HASHEXTENDED_PROC:
- if (!check_hash_func_signature(procform->amproc, procform->amprocnum,
- procform->amproclefttype))
- {
- ereport(INFO,
- (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
- errmsg("operator family \"%s\" of access method %s contains function %s with wrong signature for support number %d",
- opfamilyname, "hash",
- format_procedure(procform->amproc),
- procform->amprocnum)));
- result = false;
- }
- else
- {
- /* Remember which types we can hash */
- hashabletypes =
- list_append_unique_oid(hashabletypes,
- procform->amproclefttype);
- }
+ ok = check_amproc_signature(procform->amproc, INT8OID, true,
+ 2, 2, procform->amproclefttype, INT8OID);
break;
case HASHOPTIONS_PROC:
- if (!check_amoptsproc_signature(procform->amproc))
- result = false;
+ ok = check_amoptsproc_signature(procform->amproc);
break;
default:
ereport(INFO,
@@ -141,7 +122,24 @@ hashvalidate(Oid opclassoid)
format_procedure(procform->amproc),
procform->amprocnum)));
result = false;
- break;
+ continue; /* don't want additional message */
+ }
+
+ if (!ok)
+ {
+ ereport(INFO,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("operator family \"%s\" of access method %s contains function %s with wrong signature for support number %d",
+ opfamilyname, "hash",
+ format_procedure(procform->amproc),
+ procform->amprocnum)));
+ result = false;
+ }
+
+ /* Remember which types we can hash */
+ if (ok && (procform->amprocnum == HASHSTANDARD_PROC || procform->amprocnum == HASHEXTENDED_PROC))
+ {
+ hashabletypes = list_append_unique_oid(hashabletypes, procform->amproclefttype);
}
}
@@ -268,84 +266,6 @@ hashvalidate(Oid opclassoid)
/*
- * We need a custom version of check_amproc_signature because of assorted
- * hacks in the core hash opclass definitions.
- */
-static bool
-check_hash_func_signature(Oid funcid, int16 amprocnum, Oid argtype)
-{
- bool result = true;
- Oid restype;
- int16 nargs;
- HeapTuple tp;
- Form_pg_proc procform;
-
- switch (amprocnum)
- {
- case HASHSTANDARD_PROC:
- restype = INT4OID;
- nargs = 1;
- break;
-
- case HASHEXTENDED_PROC:
- restype = INT8OID;
- nargs = 2;
- break;
-
- default:
- elog(ERROR, "invalid amprocnum");
- }
-
- tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
- if (!HeapTupleIsValid(tp))
- elog(ERROR, "cache lookup failed for function %u", funcid);
- procform = (Form_pg_proc) GETSTRUCT(tp);
-
- if (procform->prorettype != restype || procform->proretset ||
- procform->pronargs != nargs)
- result = false;
-
- if (!IsBinaryCoercible(argtype, procform->proargtypes.values[0]))
- {
- /*
- * Some of the built-in hash opclasses cheat by using hash functions
- * that are different from but physically compatible with the opclass
- * datatype. In some of these cases, even a "binary coercible" check
- * fails because there's no relevant cast. For the moment, fix it by
- * having a list of allowed cases. Test the specific function
- * identity, not just its input type, because hashvarlena() takes
- * INTERNAL and allowing any such function seems too scary.
- */
- if ((funcid == F_HASHINT4 || funcid == F_HASHINT4EXTENDED) &&
- (argtype == DATEOID ||
- argtype == XIDOID || argtype == CIDOID))
- /* okay, allowed use of hashint4() */ ;
- else if ((funcid == F_HASHINT8 || funcid == F_HASHINT8EXTENDED) &&
- (argtype == XID8OID))
- /* okay, allowed use of hashint8() */ ;
- else if ((funcid == F_TIMESTAMP_HASH ||
- funcid == F_TIMESTAMP_HASH_EXTENDED) &&
- argtype == TIMESTAMPTZOID)
- /* okay, allowed use of timestamp_hash() */ ;
- else if ((funcid == F_HASHCHAR || funcid == F_HASHCHAREXTENDED) &&
- argtype == BOOLOID)
- /* okay, allowed use of hashchar() */ ;
- else if ((funcid == F_HASHVARLENA || funcid == F_HASHVARLENAEXTENDED) &&
- argtype == BYTEAOID)
- /* okay, allowed use of hashvarlena() */ ;
- else
- result = false;
- }
-
- /* If function takes a second argument, it must be for a 64-bit salt. */
- if (nargs == 2 && procform->proargtypes.values[1] != INT8OID)
- result = false;
-
- ReleaseSysCache(tp);
- return result;
-}
-
-/*
* Prechecking function for adding operators/functions to a hash opfamily.
*/
void
diff --git a/src/backend/utils/adt/bool.c b/src/backend/utils/adt/bool.c
index 85e6786563e..a68a112d900 100644
--- a/src/backend/utils/adt/bool.c
+++ b/src/backend/utils/adt/bool.c
@@ -17,6 +17,7 @@
#include <ctype.h>
+#include "common/hashfn.h"
#include "libpq/pqformat.h"
#include "utils/builtins.h"
@@ -273,6 +274,18 @@ boolge(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(arg1 >= arg2);
}
+Datum
+hashbool(PG_FUNCTION_ARGS)
+{
+ return hash_uint32((int32) PG_GETARG_BOOL(0));
+}
+
+Datum
+hashboolextended(PG_FUNCTION_ARGS)
+{
+ return hash_uint32_extended((int32) PG_GETARG_BOOL(0), PG_GETARG_INT64(1));
+}
+
/*
* boolean-and and boolean-or aggregates.
*/
diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c
index 9c854e0e5c3..8130f3e8ac0 100644
--- a/src/backend/utils/adt/date.c
+++ b/src/backend/utils/adt/date.c
@@ -456,6 +456,18 @@ date_sortsupport(PG_FUNCTION_ARGS)
}
Datum
+hashdate(PG_FUNCTION_ARGS)
+{
+ return hash_uint32(PG_GETARG_DATEADT(0));
+}
+
+Datum
+hashdateextended(PG_FUNCTION_ARGS)
+{
+ return hash_uint32_extended(PG_GETARG_DATEADT(0), PG_GETARG_INT64(1));
+}
+
+Datum
date_finite(PG_FUNCTION_ARGS)
{
DateADT date = PG_GETARG_DATEADT(0);
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index db9eea90982..e00cd3c9690 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -2298,6 +2298,18 @@ timestamp_hash_extended(PG_FUNCTION_ARGS)
return hashint8extended(fcinfo);
}
+Datum
+timestamptz_hash(PG_FUNCTION_ARGS)
+{
+ return hashint8(fcinfo);
+}
+
+Datum
+timestamptz_hash_extended(PG_FUNCTION_ARGS)
+{
+ return hashint8extended(fcinfo);
+}
+
/*
* Cross-type comparison functions for timestamp vs timestamptz
*/
diff --git a/src/backend/utils/adt/xid.c b/src/backend/utils/adt/xid.c
index ae273b19610..2f34a5dc1f0 100644
--- a/src/backend/utils/adt/xid.c
+++ b/src/backend/utils/adt/xid.c
@@ -19,6 +19,7 @@
#include "access/multixact.h"
#include "access/transam.h"
#include "access/xact.h"
+#include "common/hashfn.h"
#include "common/int.h"
#include "libpq/pqformat.h"
#include "utils/builtins.h"
@@ -97,6 +98,18 @@ xidneq(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(!TransactionIdEquals(xid1, xid2));
}
+Datum
+hashxid(PG_FUNCTION_ARGS)
+{
+ return hash_uint32(PG_GETARG_TRANSACTIONID(0));
+}
+
+Datum
+hashxidextended(PG_FUNCTION_ARGS)
+{
+ return hash_uint32_extended(PG_GETARG_TRANSACTIONID(0), PG_GETARG_INT64(1));
+}
+
/*
* xid_age - compute age of an XID (relative to latest stable xid)
*/
@@ -288,6 +301,18 @@ xid8cmp(PG_FUNCTION_ARGS)
}
Datum
+hashxid8(PG_FUNCTION_ARGS)
+{
+ return hashint8(fcinfo);
+}
+
+Datum
+hashxid8extended(PG_FUNCTION_ARGS)
+{
+ return hashint8extended(fcinfo);
+}
+
+Datum
xid8_larger(PG_FUNCTION_ARGS)
{
FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
@@ -374,3 +399,15 @@ cideq(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(arg1 == arg2);
}
+
+Datum
+hashcid(PG_FUNCTION_ARGS)
+{
+ return hash_uint32(PG_GETARG_COMMANDID(0));
+}
+
+Datum
+hashcidextended(PG_FUNCTION_ARGS)
+{
+ return hash_uint32_extended(PG_GETARG_COMMANDID(0), PG_GETARG_INT64(1));
+}
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 8bace2754c9..d09e47d05fa 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -57,6 +57,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 202409102
+#define CATALOG_VERSION_NO 202409121
#endif
diff --git a/src/include/catalog/pg_amproc.dat b/src/include/catalog/pg_amproc.dat
index f639c3a6a51..1d97e12a050 100644
--- a/src/include/catalog/pg_amproc.dat
+++ b/src/include/catalog/pg_amproc.dat
@@ -304,9 +304,9 @@
{ amprocfamily => 'hash/char_ops', amproclefttype => 'char',
amprocrighttype => 'char', amprocnum => '2', amproc => 'hashcharextended' },
{ amprocfamily => 'hash/date_ops', amproclefttype => 'date',
- amprocrighttype => 'date', amprocnum => '1', amproc => 'hashint4' },
+ amprocrighttype => 'date', amprocnum => '1', amproc => 'hashdate' },
{ amprocfamily => 'hash/date_ops', amproclefttype => 'date',
- amprocrighttype => 'date', amprocnum => '2', amproc => 'hashint4extended' },
+ amprocrighttype => 'date', amprocnum => '2', amproc => 'hashdateextended' },
{ amprocfamily => 'hash/array_ops', amproclefttype => 'anyarray',
amprocrighttype => 'anyarray', amprocnum => '1', amproc => 'hash_array' },
{ amprocfamily => 'hash/array_ops', amproclefttype => 'anyarray',
@@ -376,10 +376,10 @@
amproc => 'hash_numeric_extended' },
{ amprocfamily => 'hash/timestamptz_ops', amproclefttype => 'timestamptz',
amprocrighttype => 'timestamptz', amprocnum => '1',
- amproc => 'timestamp_hash' },
+ amproc => 'timestamptz_hash' },
{ amprocfamily => 'hash/timestamptz_ops', amproclefttype => 'timestamptz',
amprocrighttype => 'timestamptz', amprocnum => '2',
- amproc => 'timestamp_hash_extended' },
+ amproc => 'timestamptz_hash_extended' },
{ amprocfamily => 'hash/timetz_ops', amproclefttype => 'timetz',
amprocrighttype => 'timetz', amprocnum => '1', amproc => 'timetz_hash' },
{ amprocfamily => 'hash/timetz_ops', amproclefttype => 'timetz',
@@ -392,26 +392,25 @@
amprocrighttype => 'timestamp', amprocnum => '2',
amproc => 'timestamp_hash_extended' },
{ amprocfamily => 'hash/bool_ops', amproclefttype => 'bool',
- amprocrighttype => 'bool', amprocnum => '1', amproc => 'hashchar' },
+ amprocrighttype => 'bool', amprocnum => '1', amproc => 'hashbool' },
{ amprocfamily => 'hash/bool_ops', amproclefttype => 'bool',
- amprocrighttype => 'bool', amprocnum => '2', amproc => 'hashcharextended' },
+ amprocrighttype => 'bool', amprocnum => '2', amproc => 'hashboolextended' },
{ amprocfamily => 'hash/bytea_ops', amproclefttype => 'bytea',
- amprocrighttype => 'bytea', amprocnum => '1', amproc => 'hashvarlena' },
+ amprocrighttype => 'bytea', amprocnum => '1', amproc => 'hashbytea' },
{ amprocfamily => 'hash/bytea_ops', amproclefttype => 'bytea',
- amprocrighttype => 'bytea', amprocnum => '2',
- amproc => 'hashvarlenaextended' },
+ amprocrighttype => 'bytea', amprocnum => '2', amproc => 'hashbyteaextended' },
{ amprocfamily => 'hash/xid_ops', amproclefttype => 'xid',
- amprocrighttype => 'xid', amprocnum => '1', amproc => 'hashint4' },
+ amprocrighttype => 'xid', amprocnum => '1', amproc => 'hashxid' },
{ amprocfamily => 'hash/xid_ops', amproclefttype => 'xid',
- amprocrighttype => 'xid', amprocnum => '2', amproc => 'hashint4extended' },
+ amprocrighttype => 'xid', amprocnum => '2', amproc => 'hashxidextended' },
{ amprocfamily => 'hash/xid8_ops', amproclefttype => 'xid8',
- amprocrighttype => 'xid8', amprocnum => '1', amproc => 'hashint8' },
+ amprocrighttype => 'xid8', amprocnum => '1', amproc => 'hashxid8' },
{ amprocfamily => 'hash/xid8_ops', amproclefttype => 'xid8',
- amprocrighttype => 'xid8', amprocnum => '2', amproc => 'hashint8extended' },
+ amprocrighttype => 'xid8', amprocnum => '2', amproc => 'hashxid8extended' },
{ amprocfamily => 'hash/cid_ops', amproclefttype => 'cid',
- amprocrighttype => 'cid', amprocnum => '1', amproc => 'hashint4' },
+ amprocrighttype => 'cid', amprocnum => '1', amproc => 'hashcid' },
{ amprocfamily => 'hash/cid_ops', amproclefttype => 'cid',
- amprocrighttype => 'cid', amprocnum => '2', amproc => 'hashint4extended' },
+ amprocrighttype => 'cid', amprocnum => '2', amproc => 'hashcidextended' },
{ amprocfamily => 'hash/tid_ops', amproclefttype => 'tid',
amprocrighttype => 'tid', amprocnum => '1', amproc => 'hashtid' },
{ amprocfamily => 'hash/tid_ops', amproclefttype => 'tid',
@@ -819,7 +818,7 @@
amprocrighttype => 'bytea', amprocnum => '5',
amproc => 'brin_bloom_options' },
{ amprocfamily => 'brin/bytea_bloom_ops', amproclefttype => 'bytea',
- amprocrighttype => 'bytea', amprocnum => '11', amproc => 'hashvarlena' },
+ amprocrighttype => 'bytea', amprocnum => '11', amproc => 'hashbytea' },
# minmax "char"
{ amprocfamily => 'brin/char_minmax_ops', amproclefttype => 'char',
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index ff5436acacf..9c4f8b58260 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -1225,6 +1225,12 @@
{ oid => '772', descr => 'hash',
proname => 'hashvarlenaextended', prorettype => 'int8',
proargtypes => 'internal int8', prosrc => 'hashvarlenaextended' },
+{ oid => '9708', descr => 'hash',
+ proname => 'hashbytea', prorettype => 'int4', proargtypes => 'bytea',
+ prosrc => 'hashbytea' },
+{ oid => '9709', descr => 'hash',
+ proname => 'hashbyteaextended', prorettype => 'int8',
+ proargtypes => 'bytea int8', prosrc => 'hashbyteaextended' },
{ oid => '457', descr => 'hash',
proname => 'hashoidvector', prorettype => 'int4', proargtypes => 'oidvector',
prosrc => 'hashoidvector' },
@@ -1261,6 +1267,36 @@
{ oid => '781', descr => 'hash',
proname => 'hashmacaddr8extended', prorettype => 'int8',
proargtypes => 'macaddr8 int8', prosrc => 'hashmacaddr8extended' },
+{ oid => '9710', descr => 'hash',
+ proname => 'hashdate', prorettype => 'int4', proargtypes => 'date',
+ prosrc => 'hashdate' },
+{ oid => '9711', descr => 'hash',
+ proname => 'hashdateextended', prorettype => 'int8',
+ proargtypes => 'date int8', prosrc => 'hashdateextended' },
+{ oid => '9712', descr => 'hash',
+ proname => 'hashbool', prorettype => 'int4', proargtypes => 'bool',
+ prosrc => 'hashbool' },
+{ oid => '9713', descr => 'hash',
+ proname => 'hashboolextended', prorettype => 'int8',
+ proargtypes => 'bool int8', prosrc => 'hashboolextended' },
+{ oid => '9714', descr => 'hash',
+ proname => 'hashxid', prorettype => 'int4', proargtypes => 'xid',
+ prosrc => 'hashxid' },
+{ oid => '9715', descr => 'hash',
+ proname => 'hashxidextended', prorettype => 'int8', proargtypes => 'xid int8',
+ prosrc => 'hashxidextended' },
+{ oid => '9716', descr => 'hash',
+ proname => 'hashxid8', prorettype => 'int4', proargtypes => 'xid8',
+ prosrc => 'hashxid8' },
+{ oid => '9717', descr => 'hash',
+ proname => 'hashxid8extended', prorettype => 'int8',
+ proargtypes => 'xid8 int8', prosrc => 'hashxid8extended' },
+{ oid => '9718', descr => 'hash',
+ proname => 'hashcid', prorettype => 'int4', proargtypes => 'cid',
+ prosrc => 'hashcid' },
+{ oid => '9719', descr => 'hash',
+ proname => 'hashcidextended', prorettype => 'int8', proargtypes => 'cid int8',
+ prosrc => 'hashcidextended' },
{ oid => '438', descr => 'count the number of NULL arguments',
proname => 'num_nulls', provariadic => 'any', proisstrict => 'f',
@@ -6180,6 +6216,12 @@
{ oid => '3411', descr => 'hash',
proname => 'timestamp_hash_extended', prorettype => 'int8',
proargtypes => 'timestamp int8', prosrc => 'timestamp_hash_extended' },
+{ oid => '9720', descr => 'hash',
+ proname => 'timestamptz_hash', prorettype => 'int4',
+ proargtypes => 'timestamptz', prosrc => 'timestamptz_hash' },
+{ oid => '9721', descr => 'hash',
+ proname => 'timestamptz_hash_extended', prorettype => 'int8',
+ proargtypes => 'timestamptz int8', prosrc => 'timestamptz_hash_extended' },
{ oid => '2041', descr => 'intervals overlap?',
proname => 'overlaps', proisstrict => 'f', prorettype => 'bool',
proargtypes => 'timestamp timestamp timestamp timestamp',