diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c index f173f30211..6a6f3d44af 100644 --- a/src/backend/utils/adt/numeric.c +++ b/src/backend/utils/adt/numeric.c @@ -14,7 +14,7 @@ * Copyright (c) 1998-2007, PostgreSQL Global Development Group * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.101 2007/02/27 23:48:08 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.102 2007/05/08 18:56:47 neilc Exp $ * *------------------------------------------------------------------------- */ @@ -26,6 +26,7 @@ #include #include +#include "access/hash.h" #include "catalog/pg_type.h" #include "libpq/pqformat.h" #include "utils/array.h" @@ -1149,6 +1150,81 @@ cmp_numerics(Numeric num1, Numeric num2) return result; } +Datum +hash_numeric(PG_FUNCTION_ARGS) +{ + Numeric key = PG_GETARG_NUMERIC(0); + Datum digit_hash; + Datum result; + int weight; + int start_offset; + int end_offset; + int i; + int hash_len; + + /* If it's NaN, don't try to hash the rest of the fields */ + if (NUMERIC_IS_NAN(key)) + PG_RETURN_UINT32(0); + + weight = key->n_weight; + start_offset = 0; + end_offset = 0; + + /* + * Omit any leading or trailing zeros from the input to the + * hash. The numeric implementation *should* guarantee that + * leading and trailing zeros are suppressed, but we're + * paranoid. Note that we measure the starting and ending offsets + * in units of NumericDigits, not bytes. + */ + for (i = 0; i < NUMERIC_NDIGITS(key); i++) + { + if (NUMERIC_DIGITS(key)[i] != (NumericDigit) 0) + break; + + start_offset++; + /* + * The weight is effectively the # of digits before the + * decimal point, so decrement it for each leading zero we + * skip. + */ + weight--; + } + + /* + * If there are no non-zero digits, then the value of the number + * is zero, regardless of any other fields. + */ + if (NUMERIC_NDIGITS(key) == start_offset) + PG_RETURN_UINT32(-1); + + for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--) + { + if (NUMERIC_DIGITS(key)[i] != (NumericDigit) 0) + break; + + end_offset++; + } + + /* If we get here, there should be at least one non-zero digit */ + Assert(start_offset + end_offset < NUMERIC_NDIGITS(key)); + + /* + * Note that we don't hash on the Numeric's scale, since two + * numerics can compare equal but have different scales. We also + * don't hash on the sign, although we could: since a sign + * difference implies inequality, this shouldn't affect correctness. + */ + hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset; + digit_hash = hash_any((unsigned char *) (NUMERIC_DIGITS(key) + start_offset), + hash_len * sizeof(NumericDigit)); + + /* Mix in the weight, via XOR */ + result = digit_hash ^ weight; + + PG_RETURN_DATUM(result); +} + /* ---------------------------------------------------------------------- * diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index f614001d37..69ef260ad3 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.404 2007/04/15 10:56:27 ishii Exp $ + * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.405 2007/05/08 18:56:47 neilc Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200704151 +#define CATALOG_VERSION_NO 200705081 #endif diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h index 2b85264599..26b2ffe4ed 100644 --- a/src/include/catalog/pg_amop.h +++ b/src/include/catalog/pg_amop.h @@ -29,7 +29,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_amop.h,v 1.80 2007/04/02 03:49:40 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_amop.h,v 1.81 2007/05/08 18:56:47 neilc Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -568,6 +568,8 @@ DATA(insert ( 2232 19 19 1 f 2334 405 )); DATA(insert ( 2235 1033 1033 1 f 974 405 )); /* uuid_ops */ DATA(insert ( 2969 2950 2950 1 f 2972 405 )); +/* numeric_ops */ +DATA(insert ( 1998 1700 1700 1 f 1752 405 )); /* diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h index d535e615c8..2645e89d66 100644 --- a/src/include/catalog/pg_amproc.h +++ b/src/include/catalog/pg_amproc.h @@ -22,7 +22,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_amproc.h,v 1.64 2007/04/02 03:49:40 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_amproc.h,v 1.65 2007/05/08 18:56:47 neilc Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -148,6 +148,7 @@ DATA(insert ( 1990 26 26 1 453 )); DATA(insert ( 1992 30 30 1 457 )); DATA(insert ( 1995 25 25 1 400 )); DATA(insert ( 1997 1083 1083 1 452 )); +DATA(insert ( 1998 1700 1700 1 432 )); DATA(insert ( 1999 1184 1184 1 452 )); DATA(insert ( 2001 1266 1266 1 1696 )); DATA(insert ( 2040 1114 1114 1 452 )); diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h index 2df9b8241a..28fed11301 100644 --- a/src/include/catalog/pg_opclass.h +++ b/src/include/catalog/pg_opclass.h @@ -28,7 +28,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_opclass.h,v 1.75 2007/04/02 03:49:40 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_opclass.h,v 1.76 2007/05/08 18:56:47 neilc Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -129,6 +129,7 @@ DATA(insert ( 405 macaddr_ops PGNSP PGUID 1985 829 t 0 )); DATA(insert ( 403 name_ops PGNSP PGUID 1986 19 t 0 )); DATA(insert ( 405 name_ops PGNSP PGUID 1987 19 t 0 )); DATA(insert ( 403 numeric_ops PGNSP PGUID 1988 1700 t 0 )); +DATA(insert ( 405 numeric_ops PGNSP PGUID 1998 1700 t 0 )); DATA(insert OID = 1981 ( 403 oid_ops PGNSP PGUID 1989 26 t 0 )); #define OID_BTREE_OPS_OID 1981 DATA(insert ( 405 oid_ops PGNSP PGUID 1990 26 t 0 )); diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h index 2591b1ff7b..6848b274e4 100644 --- a/src/include/catalog/pg_operator.h +++ b/src/include/catalog/pg_operator.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.151 2007/04/02 03:49:40 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.152 2007/05/08 18:56:47 neilc Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -675,7 +675,7 @@ DATA(insert OID = 1630 ( "!~~*" PGNSP PGUID b f f 1042 25 16 0 1629 bpcharicn /* NUMERIC type - OID's 1700-1799 */ DATA(insert OID = 1751 ( "-" PGNSP PGUID l f f 0 1700 1700 0 0 numeric_uminus - - )); -DATA(insert OID = 1752 ( "=" PGNSP PGUID b t f 1700 1700 16 1752 1753 numeric_eq eqsel eqjoinsel )); +DATA(insert OID = 1752 ( "=" PGNSP PGUID b t t 1700 1700 16 1752 1753 numeric_eq eqsel eqjoinsel )); DATA(insert OID = 1753 ( "<>" PGNSP PGUID b f f 1700 1700 16 1753 1752 numeric_ne neqsel neqjoinsel )); DATA(insert OID = 1754 ( "<" PGNSP PGUID b f f 1700 1700 16 1756 1757 numeric_lt scalarltsel scalarltjoinsel )); DATA(insert OID = 1755 ( "<=" PGNSP PGUID b f f 1700 1700 16 1757 1756 numeric_le scalarltsel scalarltjoinsel )); diff --git a/src/include/catalog/pg_opfamily.h b/src/include/catalog/pg_opfamily.h index 3d4c0a41d0..a39e28c632 100644 --- a/src/include/catalog/pg_opfamily.h +++ b/src/include/catalog/pg_opfamily.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_opfamily.h,v 1.4 2007/04/02 03:49:40 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_opfamily.h,v 1.5 2007/05/08 18:56:47 neilc Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -93,6 +93,7 @@ DATA(insert OID = 1986 ( 403 name_ops PGNSP PGUID )); #define NAME_BTREE_FAM_OID 1986 DATA(insert OID = 1987 ( 405 name_ops PGNSP PGUID )); DATA(insert OID = 1988 ( 403 numeric_ops PGNSP PGUID )); +DATA(insert OID = 1998 ( 405 numeric_ops PGNSP PGUID )); DATA(insert OID = 1989 ( 403 oid_ops PGNSP PGUID )); #define OID_BTREE_FAM_OID 1989 DATA(insert OID = 1990 ( 405 oid_ops PGNSP PGUID )); diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index d7b048b07f..b300f9b92c 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.454 2007/04/02 03:49:40 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.455 2007/05/08 18:56:48 neilc Exp $ * * NOTES * The script catalog/genbki.sh reads this file and generates .bki @@ -838,6 +838,8 @@ DATA(insert OID = 399 ( hashmacaddr PGNSP PGUID 12 1 0 f f t f i 1 23 "829" DESCR("hash"); DATA(insert OID = 422 ( hashinet PGNSP PGUID 12 1 0 f f t f i 1 23 "869" _null_ _null_ _null_ hashinet - _null_ )); DESCR("hash"); +DATA(insert OID = 432 ( hash_numeric PGNSP PGUID 12 1 0 f f t f i 1 23 "1700" _null_ _null_ _null_ hash_numeric - _null_ )); +DESCR("hash"); DATA(insert OID = 458 ( text_larger PGNSP PGUID 12 1 0 f f t f i 2 25 "25 25" _null_ _null_ _null_ text_larger - _null_ )); DESCR("larger of two"); DATA(insert OID = 459 ( text_smaller PGNSP PGUID 12 1 0 f f t f i 2 25 "25 25" _null_ _null_ _null_ text_smaller - _null_ )); diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index d93599a9ae..22b10841c6 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.291 2007/04/02 03:49:41 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.292 2007/05/08 18:56:48 neilc Exp $ * *------------------------------------------------------------------------- */ @@ -883,6 +883,7 @@ extern Datum int2_avg_accum(PG_FUNCTION_ARGS); extern Datum int4_avg_accum(PG_FUNCTION_ARGS); extern Datum int8_avg(PG_FUNCTION_ARGS); extern Datum width_bucket_numeric(PG_FUNCTION_ARGS); +extern Datum hash_numeric(PG_FUNCTION_ARGS); /* ri_triggers.c */ extern Datum RI_FKey_check_ins(PG_FUNCTION_ARGS);