*** pgsql/src/backend/utils/adt/timestamp.c 2009/03/15 20:31:19 1.197 --- pgsql/src/backend/utils/adt/timestamp.c 2009/04/04 04:53:25 1.198 *************** *** 8,14 **** * * * IDENTIFICATION ! * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.196 2009/01/01 17:23:50 momjian Exp $ * *------------------------------------------------------------------------- */ --- 8,14 ---- * * * IDENTIFICATION ! * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.197 2009/03/15 20:31:19 tgl Exp $ * *------------------------------------------------------------------------- */ *************** timestamptz_cmp_timestamp(PG_FUNCTION_AR *** 2041,2067 **** * * collate invalid interval at the end */ ! static int ! interval_cmp_internal(Interval *interval1, Interval *interval2) { ! TimeOffset span1, ! span2; ! span1 = interval1->time; ! span2 = interval2->time; #ifdef HAVE_INT64_TIMESTAMP ! span1 += interval1->month * INT64CONST(30) * USECS_PER_DAY; ! span1 += interval1->day * INT64CONST(24) * USECS_PER_HOUR; ! span2 += interval2->month * INT64CONST(30) * USECS_PER_DAY; ! span2 += interval2->day * INT64CONST(24) * USECS_PER_HOUR; ! #else ! span1 += interval1->month * ((double) DAYS_PER_MONTH * SECS_PER_DAY); ! span1 += interval1->day * ((double) HOURS_PER_DAY * SECS_PER_HOUR); ! span2 += interval2->month * ((double) DAYS_PER_MONTH * SECS_PER_DAY); ! span2 += interval2->day * ((double) HOURS_PER_DAY * SECS_PER_HOUR); #endif return ((span1 < span2) ? -1 : (span1 > span2) ? 1 : 0); } --- 2041,2070 ---- * * collate invalid interval at the end */ ! static inline TimeOffset ! interval_cmp_value(const Interval *interval) { ! TimeOffset span; ! span = interval->time; #ifdef HAVE_INT64_TIMESTAMP ! span += interval->month * INT64CONST(30) * USECS_PER_DAY; ! span += interval->day * INT64CONST(24) * USECS_PER_HOUR; ! #else ! span += interval->month * ((double) DAYS_PER_MONTH * SECS_PER_DAY); ! span += interval->day * ((double) HOURS_PER_DAY * SECS_PER_HOUR); #endif + return span; + } + + static int + interval_cmp_internal(Interval *interval1, Interval *interval2) + { + TimeOffset span1 = interval_cmp_value(interval1); + TimeOffset span2 = interval_cmp_value(interval2); + return ((span1 < span2) ? -1 : (span1 > span2) ? 1 : 0); } *************** interval_cmp(PG_FUNCTION_ARGS) *** 2128,2159 **** PG_RETURN_INT32(interval_cmp_internal(interval1, interval2)); } Datum interval_hash(PG_FUNCTION_ARGS) { ! Interval *key = PG_GETARG_INTERVAL_P(0); ! uint32 thash; ! uint32 mhash; - /* - * 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. - */ #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. --- 2131,2154 ---- PG_RETURN_INT32(interval_cmp_internal(interval1, interval2)); } + /* + * Hashing for intervals + * + * We must produce equal hashvals for values that interval_cmp_internal() + * considers equal. So, compute the net span the same way it does, + * and then hash that, using either int64 or float8 hashing. + */ Datum interval_hash(PG_FUNCTION_ARGS) { ! Interval *interval = PG_GETARG_INTERVAL_P(0); ! TimeOffset span = interval_cmp_value(interval); #ifdef HAVE_INT64_TIMESTAMP ! return DirectFunctionCall1(hashint8, Int64GetDatumFast(span)); #else ! return DirectFunctionCall1(hashfloat8, Float8GetDatumFast(span)); #endif } /* overlaps_timestamp() --- implements the SQL92 OVERLAPS operator.