diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/access/hash/hashfunc.c | 17 | ||||
-rw-r--r-- | src/backend/access/hash/hashvalidate.c | 130 | ||||
-rw-r--r-- | src/backend/utils/adt/bool.c | 13 | ||||
-rw-r--r-- | src/backend/utils/adt/date.c | 12 | ||||
-rw-r--r-- | src/backend/utils/adt/timestamp.c | 12 | ||||
-rw-r--r-- | src/backend/utils/adt/xid.c | 37 |
6 files changed, 116 insertions, 105 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)); +} |