*** a/src/backend/utils/adt/numeric.c --- b/src/backend/utils/adt/numeric.c *************** *** 712,717 **** numeric_send(PG_FUNCTION_ARGS) --- 712,754 ---- } + Datum + numeric_exemptor(PG_FUNCTION_ARGS) + { + int32 old_typmod = PG_GETARG_INT32(0); + int32 new_typmod = PG_GETARG_INT32(1); + int old_scale; + int new_scale; + int old_precis; + int new_precis; + + /* Destination is unconstrained: never any work to do. */ + if (new_typmod < VARHDRSZ) + PG_RETURN_INT32(COERCE_EXEMPT_NOCHANGE | COERCE_EXEMPT_NOERROR); + + /* + * Source is unconstrained, and destination is constrained. A value like + * 10^-1001 will always get truncated in this situation, so we can't help. + */ + if (old_typmod < VARHDRSZ) + PG_RETURN_INT32(0); + + /* Each value stores its scale. If the scale changes, we can't help. */ + old_scale = (old_typmod - VARHDRSZ) & 0xffff; + new_scale = (new_typmod - VARHDRSZ) & 0xffff; + if (old_scale != new_scale) + PG_RETURN_INT32(0); + + old_precis = (old_typmod - VARHDRSZ) >> 16 & 0xffff; + new_precis = (new_typmod - VARHDRSZ) >> 16 & 0xffff; + if (new_precis >= old_precis) + /* Precision increases with scale unchanged: never any work to do. */ + PG_RETURN_INT32(COERCE_EXEMPT_NOCHANGE | COERCE_EXEMPT_NOERROR); + + /* Precision falls with scale unchanged: might error, never changes data. */ + PG_RETURN_INT32(COERCE_EXEMPT_NOCHANGE); + } + /* * numeric() - * *** a/src/include/catalog/catversion.h --- b/src/include/catalog/catversion.h *************** *** 53,58 **** */ /* yyyymmddN */ ! #define CATALOG_VERSION_NO 201101103 #endif --- 53,58 ---- */ /* yyyymmddN */ ! #define CATALOG_VERSION_NO 201101104 #endif *** a/src/include/catalog/pg_cast.h --- b/src/include/catalog/pg_cast.h *************** *** 357,362 **** DATA(insert ( 1186 1186 1200 3543 i f )); DATA(insert ( 1266 1266 1969 3541 i f )); DATA(insert ( 1560 1560 1685 3817 i f )); DATA(insert ( 1562 1562 1687 3819 i f )); ! DATA(insert ( 1700 1700 1703 0 i f )); #endif /* PG_CAST_H */ --- 357,362 ---- DATA(insert ( 1266 1266 1969 3541 i f )); DATA(insert ( 1560 1560 1685 3817 i f )); DATA(insert ( 1562 1562 1687 3819 i f )); ! DATA(insert ( 1700 1700 1703 3818 i f )); #endif /* PG_CAST_H */ *** a/src/include/catalog/pg_proc.h --- b/src/include/catalog/pg_proc.h *************** *** 2595,2600 **** DATA(insert OID = 2917 ( numerictypmodin PGNSP PGUID 12 1 0 0 f f f t f i 1 0 --- 2595,2602 ---- DESCR("I/O typmod"); DATA(insert OID = 2918 ( numerictypmodout PGNSP PGUID 12 1 0 0 f f f t f i 1 0 2275 "23" _null_ _null_ _null_ _null_ numerictypmodout _null_ _null_ _null_ )); DESCR("I/O typmod"); + DATA(insert OID = 3818 ( numeric_exemptor PGNSP PGUID 12 1 0 0 f f f t f i 3 0 23 "23 23 16" _null_ _null_ _null_ _null_ numeric_exemptor _null_ _null_ _null_ )); + DESCR("numeric cast exemptor"); DATA(insert OID = 1703 ( numeric PGNSP PGUID 12 1 0 0 f f f t f i 2 0 1700 "1700 23" _null_ _null_ _null_ _null_ numeric _null_ _null_ _null_ )); DESCR("adjust numeric to typmod precision/scale"); DATA(insert OID = 1704 ( numeric_abs PGNSP PGUID 12 1 0 0 f f f t f i 1 0 1700 "1700" _null_ _null_ _null_ _null_ numeric_abs _null_ _null_ _null_ )); *** a/src/include/utils/builtins.h --- b/src/include/utils/builtins.h *************** *** 878,883 **** extern Datum numeric_recv(PG_FUNCTION_ARGS); --- 878,884 ---- extern Datum numeric_send(PG_FUNCTION_ARGS); extern Datum numerictypmodin(PG_FUNCTION_ARGS); extern Datum numerictypmodout(PG_FUNCTION_ARGS); + extern Datum numeric_exemptor(PG_FUNCTION_ARGS); extern Datum numeric (PG_FUNCTION_ARGS); extern Datum numeric_abs(PG_FUNCTION_ARGS); extern Datum numeric_uminus(PG_FUNCTION_ARGS); *** a/src/test/regress/expected/alter_table.out --- b/src/test/regress/expected/alter_table.out *************** *** 1804,1845 **** DEBUG: Rebuilding index "t_touchy_f_idx" DEBUG: Rebuilding index "t_expr_idx" DEBUG: Validating foreign key constraint "t_constraint3_fkey" ALTER TABLE t ALTER constraint3 TYPE numeric(7,2); -- verify; FK noop ! DEBUG: Rewriting table "t" ! DEBUG: Rebuilding index "t_constraint4_key" ! DEBUG: Rebuilding index "t_integral_key" ! DEBUG: Rebuilding index "t_rational_key" ! DEBUG: Rebuilding index "t_daytimetz_key" ! DEBUG: Rebuilding index "t_daytime_key" ! DEBUG: Rebuilding index "t_stamptz_key" ! DEBUG: Rebuilding index "t_stamp_key" ! DEBUG: Rebuilding index "t_timegap_key" ! DEBUG: Rebuilding index "t_bits_key" ! DEBUG: Rebuilding index "t_network_key" ! DEBUG: Rebuilding index "t_string_idx" ! DEBUG: Rebuilding index "t_string_idx1" ! DEBUG: Rebuilding index "t_strarr_idx" ! DEBUG: Rebuilding index "t_square_idx" ! DEBUG: Rebuilding index "t_touchy_f_idx" ! DEBUG: Rebuilding index "t_expr_idx" DEBUG: Validating foreign key constraint "t_constraint3_fkey" ALTER TABLE t ALTER constraint3 TYPE numeric(9,2); -- noop; FK noop - DEBUG: Rewriting table "t" - DEBUG: Rebuilding index "t_constraint4_key" - DEBUG: Rebuilding index "t_integral_key" - DEBUG: Rebuilding index "t_rational_key" - DEBUG: Rebuilding index "t_daytimetz_key" - DEBUG: Rebuilding index "t_daytime_key" - DEBUG: Rebuilding index "t_stamptz_key" - DEBUG: Rebuilding index "t_stamp_key" - DEBUG: Rebuilding index "t_timegap_key" - DEBUG: Rebuilding index "t_bits_key" - DEBUG: Rebuilding index "t_network_key" - DEBUG: Rebuilding index "t_string_idx" - DEBUG: Rebuilding index "t_string_idx1" - DEBUG: Rebuilding index "t_strarr_idx" - DEBUG: Rebuilding index "t_square_idx" - DEBUG: Rebuilding index "t_touchy_f_idx" - DEBUG: Rebuilding index "t_expr_idx" DEBUG: Validating foreign key constraint "t_constraint3_fkey" -- Change a column with an incoming foreign key constraint. ALTER TABLE t ALTER constraint4 TYPE numeric(8,1); -- rewrite; FK error --- 1804,1812 ---- DEBUG: Rebuilding index "t_expr_idx" DEBUG: Validating foreign key constraint "t_constraint3_fkey" ALTER TABLE t ALTER constraint3 TYPE numeric(7,2); -- verify; FK noop ! DEBUG: Verifying table "t" DEBUG: Validating foreign key constraint "t_constraint3_fkey" ALTER TABLE t ALTER constraint3 TYPE numeric(9,2); -- noop; FK noop DEBUG: Validating foreign key constraint "t_constraint3_fkey" -- Change a column with an incoming foreign key constraint. ALTER TABLE t ALTER constraint4 TYPE numeric(8,1); -- rewrite; FK error *************** *** 1883,1923 **** DEBUG: Rebuilding index "t_expr_idx" DEBUG: Rebuilding index "t_constraint4_key" DEBUG: Validating foreign key constraint "child_keycol_fkey" ALTER TABLE t ALTER constraint4 TYPE numeric(7,2); -- verify; FK noop - DEBUG: Rewriting table "t" - DEBUG: Rebuilding index "t_integral_key" - DEBUG: Rebuilding index "t_rational_key" - DEBUG: Rebuilding index "t_daytimetz_key" - DEBUG: Rebuilding index "t_daytime_key" - DEBUG: Rebuilding index "t_stamptz_key" - DEBUG: Rebuilding index "t_stamp_key" - DEBUG: Rebuilding index "t_timegap_key" - DEBUG: Rebuilding index "t_bits_key" - DEBUG: Rebuilding index "t_network_key" - DEBUG: Rebuilding index "t_string_idx" - DEBUG: Rebuilding index "t_string_idx1" - DEBUG: Rebuilding index "t_strarr_idx" - DEBUG: Rebuilding index "t_square_idx" - DEBUG: Rebuilding index "t_touchy_f_idx" - DEBUG: Rebuilding index "t_expr_idx" DEBUG: Rebuilding index "t_constraint4_key" DEBUG: Validating foreign key constraint "child_keycol_fkey" ALTER TABLE t ALTER constraint4 TYPE numeric(9,2); -- noop; FK noop - DEBUG: Rewriting table "t" - DEBUG: Rebuilding index "t_integral_key" - DEBUG: Rebuilding index "t_rational_key" - DEBUG: Rebuilding index "t_daytimetz_key" - DEBUG: Rebuilding index "t_daytime_key" - DEBUG: Rebuilding index "t_stamptz_key" - DEBUG: Rebuilding index "t_stamp_key" - DEBUG: Rebuilding index "t_timegap_key" - DEBUG: Rebuilding index "t_bits_key" - DEBUG: Rebuilding index "t_network_key" - DEBUG: Rebuilding index "t_string_idx" - DEBUG: Rebuilding index "t_string_idx1" - DEBUG: Rebuilding index "t_strarr_idx" - DEBUG: Rebuilding index "t_square_idx" - DEBUG: Rebuilding index "t_touchy_f_idx" - DEBUG: Rebuilding index "t_expr_idx" DEBUG: Rebuilding index "t_constraint4_key" DEBUG: Validating foreign key constraint "child_keycol_fkey" -- Type-specific tests. --- 1850,1859 ---- DEBUG: Rebuilding index "t_constraint4_key" DEBUG: Validating foreign key constraint "child_keycol_fkey" ALTER TABLE t ALTER constraint4 TYPE numeric(7,2); -- verify; FK noop DEBUG: Rebuilding index "t_constraint4_key" + DEBUG: Verifying table "t" DEBUG: Validating foreign key constraint "child_keycol_fkey" ALTER TABLE t ALTER constraint4 TYPE numeric(9,2); -- noop; FK noop DEBUG: Rebuilding index "t_constraint4_key" DEBUG: Validating foreign key constraint "child_keycol_fkey" -- Type-specific tests. *************** *** 2000,2040 **** DEBUG: Rebuilding index "t_constraint4_key" DEBUG: Rebuilding index "t_integral_key" DEBUG: Rebuilding index "t_rational_key" ALTER TABLE t ALTER rational TYPE numeric(13,4); -- noop - DEBUG: Rewriting table "t" - DEBUG: Rebuilding index "t_daytimetz_key" - DEBUG: Rebuilding index "t_daytime_key" - DEBUG: Rebuilding index "t_stamptz_key" - DEBUG: Rebuilding index "t_stamp_key" - DEBUG: Rebuilding index "t_timegap_key" - DEBUG: Rebuilding index "t_bits_key" - DEBUG: Rebuilding index "t_network_key" - DEBUG: Rebuilding index "t_string_idx" - DEBUG: Rebuilding index "t_string_idx1" - DEBUG: Rebuilding index "t_strarr_idx" - DEBUG: Rebuilding index "t_square_idx" - DEBUG: Rebuilding index "t_touchy_f_idx" - DEBUG: Rebuilding index "t_expr_idx" - DEBUG: Rebuilding index "t_constraint4_key" - DEBUG: Rebuilding index "t_integral_key" DEBUG: Rebuilding index "t_rational_key" ALTER TABLE t ALTER rational TYPE numeric(11,4); -- verify - DEBUG: Rewriting table "t" - DEBUG: Rebuilding index "t_daytimetz_key" - DEBUG: Rebuilding index "t_daytime_key" - DEBUG: Rebuilding index "t_stamptz_key" - DEBUG: Rebuilding index "t_stamp_key" - DEBUG: Rebuilding index "t_timegap_key" - DEBUG: Rebuilding index "t_bits_key" - DEBUG: Rebuilding index "t_network_key" - DEBUG: Rebuilding index "t_string_idx" - DEBUG: Rebuilding index "t_string_idx1" - DEBUG: Rebuilding index "t_strarr_idx" - DEBUG: Rebuilding index "t_square_idx" - DEBUG: Rebuilding index "t_touchy_f_idx" - DEBUG: Rebuilding index "t_expr_idx" - DEBUG: Rebuilding index "t_constraint4_key" - DEBUG: Rebuilding index "t_integral_key" DEBUG: Rebuilding index "t_rational_key" ALTER TABLE t ALTER rational TYPE numeric; -- noop DEBUG: Rebuilding index "t_rational_key" ALTER TABLE t ALTER rational TYPE numeric(5,4); -- verify-e --- 1936,1945 ---- DEBUG: Rebuilding index "t_integral_key" DEBUG: Rebuilding index "t_rational_key" ALTER TABLE t ALTER rational TYPE numeric(13,4); -- noop DEBUG: Rebuilding index "t_rational_key" ALTER TABLE t ALTER rational TYPE numeric(11,4); -- verify DEBUG: Rebuilding index "t_rational_key" + DEBUG: Verifying table "t" ALTER TABLE t ALTER rational TYPE numeric; -- noop DEBUG: Rebuilding index "t_rational_key" ALTER TABLE t ALTER rational TYPE numeric(5,4); -- verify-e