diff --git a/src/backend/utils/adt/datum.c b/src/backend/utils/adt/datum.c index 8832785540f..ef202c83f40 100644 --- a/src/backend/utils/adt/datum.c +++ b/src/backend/utils/adt/datum.c @@ -271,6 +271,27 @@ datum_image_eq(Datum value1, Datum value2, bool typByVal, int typLen) if (typByVal) { + /* + * XXX hack to fix issue with functions such as hash_numeric() not + * returning the correct type. Force sign-extended representation. + */ + switch (typLen) + { + case sizeof(char): + value1 = CharGetDatum(DatumGetChar(value1)); + value2 = CharGetDatum(DatumGetChar(value2)); + break; + case sizeof(int16): + value1 = Int16GetDatum(DatumGetInt16(value1)); + value2 = Int16GetDatum(DatumGetInt16(value2)); + break; + case sizeof(int32): + value1 = Int32GetDatum(DatumGetInt32(value1)); + value2 = Int32GetDatum(DatumGetInt32(value2)); + break; + /* Nothing needs done for 64-bit types */ + } + result = (value1 == value2); } else if (typLen > 0) @@ -341,7 +362,27 @@ datum_image_hash(Datum value, bool typByVal, int typLen) uint32 result; if (typByVal) - result = hash_bytes((unsigned char *) &value, sizeof(Datum)); + { + /* + * XXX hack to fix issue with functions such as hash_numeric() not + * returning the correct type. Force sign-extended representation. + */ + switch (typLen) + { + case sizeof(char): + value = CharGetDatum(DatumGetChar(value)); + break; + case sizeof(int16): + value = Int16GetDatum(DatumGetInt16(value)); + break; + case sizeof(int32): + value = Int32GetDatum(DatumGetInt32(value)); + break; + /* Nothing needs done for 64-bit types */ + } + + result = hash_bytes((unsigned char*) &value, sizeof(Datum)); + } else if (typLen > 0) result = hash_bytes((unsigned char *) DatumGetPointer(value), typLen); else if (typLen == -1)