diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2007-07-06 04:16:00 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2007-07-06 04:16:00 +0000 |
commit | 7af3a6fc6f9e2486df37eeac0d61addba09a3551 (patch) | |
tree | 1b21c8aa49a58a479fff5912ef125a19b38b3524 /src/backend/utils/adt/timestamp.c | |
parent | ad9a99c24f7084d2511e84efbac3a807b14656f3 (diff) |
Fix up hash functions for datetime datatypes so that they don't take
unwarranted liberties with int8 vs float8 values for these types.
Specifically, be sure to apply either hashint8 or hashfloat8 depending
on HAVE_INT64_TIMESTAMP. Per my gripe of even date.
Diffstat (limited to 'src/backend/utils/adt/timestamp.c')
-rw-r--r-- | src/backend/utils/adt/timestamp.c | 40 |
1 files changed, 31 insertions, 9 deletions
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index d2019351168..04eaa81140d 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.178 2007/06/15 20:56:50 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.179 2007/07/06 04:15:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1839,6 +1839,17 @@ timestamp_cmp(PG_FUNCTION_ARGS) PG_RETURN_INT32(timestamp_cmp_internal(dt1, dt2)); } +Datum +timestamp_hash(PG_FUNCTION_ARGS) +{ + /* We can use either hashint8 or hashfloat8 directly */ +#ifdef HAVE_INT64_TIMESTAMP + return hashint8(fcinfo); +#else + return hashfloat8(fcinfo); +#endif +} + /* * Crosstype comparison functions for timestamp vs timestamptz @@ -2110,21 +2121,32 @@ interval_cmp(PG_FUNCTION_ARGS) PG_RETURN_INT32(interval_cmp_internal(interval1, interval2)); } -/* - * interval, being an unusual size, needs a specialized hash function. - */ Datum interval_hash(PG_FUNCTION_ARGS) { Interval *key = PG_GETARG_INTERVAL_P(0); + uint32 thash; + uint32 mhash; /* - * Specify hash length as sizeof(double) + sizeof(int4), not as - * sizeof(Interval), so that any garbage pad bytes in the structure won't - * be included in the hash! + * To avoid any problems with padding bytes in the struct, + * we figure the field hashes separately and XOR them. This also + * provides a convenient framework for dealing with the fact that + * the time field might be either double or int64. */ - return hash_any((unsigned char *) key, - sizeof(key->time) + sizeof(key->day) + sizeof(key->month)); +#ifdef HAVE_INT64_TIMESTAMP + thash = DatumGetUInt32(DirectFunctionCall1(hashint8, + Int64GetDatumFast(key->time))); +#else + thash = DatumGetUInt32(DirectFunctionCall1(hashfloat8, + Float8GetDatumFast(key->time))); +#endif + thash ^= DatumGetUInt32(hash_uint32(key->day)); + /* Shift so "k days" and "k months" don't hash to the same thing */ + mhash = DatumGetUInt32(hash_uint32(key->month)); + thash ^= mhash << 24; + thash ^= mhash >> 8; + PG_RETURN_UINT32(thash); } /* overlaps_timestamp() --- implements the SQL92 OVERLAPS operator. |