*** a/src/backend/utils/adt/varbit.c --- b/src/backend/utils/adt/varbit.c *************** *** 18,23 **** --- 18,24 ---- #include "access/htup.h" #include "libpq/pqformat.h" + #include "nodes/primnodes.h" #include "utils/array.h" #include "utils/varbit.h" *************** *** 337,342 **** bit_send(PG_FUNCTION_ARGS) --- 338,359 ---- } /* + * bit_exemptor() + * Identify superfluous calls to our length coercion function. + */ + Datum + bit_exemptor(PG_FUNCTION_ARGS) + { + bool isExplicit = PG_GETARG_BOOL(2); + + /* + * We could add COERCE_EXEMPT_NOERROR when the old and new lengths are + * identical, but that has zero practical value. + */ + PG_RETURN_INT32(isExplicit ? 0 : COERCE_EXEMPT_NOCHANGE); + } + + /* * bit() * Converts a bit() type to a specific internal length. * len is the bitlength specified in the column definition. *************** *** 645,650 **** varbit_send(PG_FUNCTION_ARGS) --- 662,683 ---- } /* + * varbit_exemptor() + * Identify superfluous calls to our length coercion function. + */ + Datum + varbit_exemptor(PG_FUNCTION_ARGS) + { + int32 old_max = PG_GETARG_INT32(0); + int32 new_max = PG_GETARG_INT32(1); + bool isExplicit = PG_GETARG_BOOL(2); + + if (new_max <= 0 || (old_max > 0 && new_max >= old_max)) + PG_RETURN_INT32(COERCE_EXEMPT_NOCHANGE | COERCE_EXEMPT_NOERROR); + PG_RETURN_INT32(isExplicit ? 0 : COERCE_EXEMPT_NOCHANGE); + } + + /* * varbit() * Converts a varbit() type to a specific internal length. * len is the maximum bitlength specified in the column definition. *** a/src/include/catalog/catversion.h --- b/src/include/catalog/catversion.h *************** *** 53,58 **** */ /* yyyymmddN */ ! #define CATALOG_VERSION_NO 201101102 #endif --- 53,58 ---- */ /* yyyymmddN */ ! #define CATALOG_VERSION_NO 201101103 #endif *** a/src/include/catalog/pg_cast.h --- b/src/include/catalog/pg_cast.h *************** *** 355,362 **** DATA(insert ( 1114 1114 1961 3542 i f )); DATA(insert ( 1184 1184 1967 3542 i f )); DATA(insert ( 1186 1186 1200 3543 i f )); DATA(insert ( 1266 1266 1969 3541 i f )); ! DATA(insert ( 1560 1560 1685 0 i f )); ! DATA(insert ( 1562 1562 1687 0 i f )); DATA(insert ( 1700 1700 1703 0 i f )); #endif /* PG_CAST_H */ --- 355,362 ---- DATA(insert ( 1184 1184 1967 3542 i f )); 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 */ *** a/src/include/catalog/pg_proc.h --- b/src/include/catalog/pg_proc.h *************** *** 2433,2440 **** DESCR("int4 to bitstring"); --- 2433,2444 ---- DATA(insert OID = 1684 ( int4 PGNSP PGUID 12 1 0 0 f f f t f i 1 0 23 "1560" _null_ _null_ _null_ _null_ bittoint4 _null_ _null_ _null_ )); DESCR("bitstring to int4"); + DATA(insert OID = 3817 ( bit_exemptor PGNSP PGUID 12 1 0 0 f f f t f i 3 0 23 "23 23 16" _null_ _null_ _null_ _null_ bit_exemptor _null_ _null_ _null_ )); + DESCR("bit cast exemptor"); DATA(insert OID = 1685 ( bit PGNSP PGUID 12 1 0 0 f f f t f i 3 0 1560 "1560 23 16" _null_ _null_ _null_ _null_ bit _null_ _null_ _null_ )); DESCR("adjust bit() to typmod length"); + DATA(insert OID = 3819 ( varbit_exemptor PGNSP PGUID 12 1 0 0 f f f t f i 3 0 23 "23 23 16" _null_ _null_ _null_ _null_ varbit_exemptor _null_ _null_ _null_ )); + DESCR("varbit cast exemptor"); DATA(insert OID = 1687 ( varbit PGNSP PGUID 12 1 0 0 f f f t f i 3 0 1562 "1562 23 16" _null_ _null_ _null_ _null_ varbit _null_ _null_ _null_ )); DESCR("adjust varbit() to typmod length"); *** a/src/include/utils/varbit.h --- b/src/include/utils/varbit.h *************** *** 71,77 **** extern Datum varbit_recv(PG_FUNCTION_ARGS); --- 71,79 ---- extern Datum varbit_send(PG_FUNCTION_ARGS); extern Datum varbittypmodin(PG_FUNCTION_ARGS); extern Datum varbittypmodout(PG_FUNCTION_ARGS); + extern Datum bit_exemptor(PG_FUNCTION_ARGS); extern Datum bit(PG_FUNCTION_ARGS); + extern Datum varbit_exemptor(PG_FUNCTION_ARGS); extern Datum varbit(PG_FUNCTION_ARGS); extern Datum biteq(PG_FUNCTION_ARGS); extern Datum bitne(PG_FUNCTION_ARGS); *** a/src/test/regress/expected/alter_table.out --- b/src/test/regress/expected/alter_table.out *************** *** 2454,2478 **** DEBUG: Rebuilding index "t_timegap_key" ALTER TABLE t ALTER timegap TYPE interval(2); -- noop DEBUG: Rebuilding index "t_timegap_key" ALTER TABLE t ALTER bits TYPE bit(6); -- verify - DEBUG: Rewriting table "t" - DEBUG: Rebuilding index "t_network_key" - 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" - DEBUG: Rebuilding index "t_string_idx1" - DEBUG: Rebuilding index "t_string_idx" - 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" ALTER TABLE t ALTER bits TYPE bit(7); -- verify-e ! DEBUG: Rewriting table "t" ERROR: bit string length 6 does not match type bit(7) ALTER TABLE t ALTER bits TYPE bit(7) USING bits::bit(7); -- rewrite DEBUG: Rewriting table "t" --- 2454,2464 ---- ALTER TABLE t ALTER timegap TYPE interval(2); -- noop DEBUG: Rebuilding index "t_timegap_key" ALTER TABLE t ALTER bits TYPE bit(6); -- verify DEBUG: Rebuilding index "t_bits_key" + DEBUG: Verifying table "t" ALTER TABLE t ALTER bits TYPE bit(7); -- verify-e ! DEBUG: Rebuilding index "t_bits_key" ! DEBUG: Verifying table "t" ERROR: bit string length 6 does not match type bit(7) ALTER TABLE t ALTER bits TYPE bit(7) USING bits::bit(7); -- rewrite DEBUG: Rewriting table "t" *************** *** 2494,2536 **** DEBUG: Rebuilding index "t_timegap_key" DEBUG: Rebuilding index "t_bits_key" -- Next one could be a made a noop with an added cast. ALTER TABLE t ALTER bits TYPE varbit(8); -- verify - DEBUG: Rewriting table "t" - DEBUG: Rebuilding index "t_network_key" - 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" - DEBUG: Rebuilding index "t_string_idx1" - DEBUG: Rebuilding index "t_string_idx" - 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" ALTER TABLE t ALTER bits TYPE varbit(7); -- verify - DEBUG: Rewriting table "t" - DEBUG: Rebuilding index "t_network_key" - 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" - DEBUG: Rebuilding index "t_string_idx1" - DEBUG: Rebuilding index "t_string_idx" - 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" ALTER TABLE t ALTER bits TYPE varbit(5); -- verify-e ! DEBUG: Rewriting table "t" ERROR: bit string too long for type bit varying(5) ALTER TABLE t ALTER bits TYPE varbit(5) USING bits::varbit(5); -- rewrite DEBUG: Rewriting table "t" --- 2480,2493 ---- DEBUG: Rebuilding index "t_bits_key" -- Next one could be a made a noop with an added cast. ALTER TABLE t ALTER bits TYPE varbit(8); -- verify DEBUG: Rebuilding index "t_bits_key" + DEBUG: Verifying table "t" ALTER TABLE t ALTER bits TYPE varbit(7); -- verify DEBUG: Rebuilding index "t_bits_key" + DEBUG: Verifying table "t" ALTER TABLE t ALTER bits TYPE varbit(5); -- verify-e ! DEBUG: Rebuilding index "t_bits_key" ! DEBUG: Verifying table "t" ERROR: bit string too long for type bit varying(5) ALTER TABLE t ALTER bits TYPE varbit(5) USING bits::varbit(5); -- rewrite DEBUG: Rewriting table "t" *************** *** 2551,2572 **** DEBUG: Rebuilding index "t_stamp_key" DEBUG: Rebuilding index "t_timegap_key" DEBUG: Rebuilding index "t_bits_key" ALTER TABLE t ALTER bits TYPE varbit(8); -- noop - DEBUG: Rewriting table "t" - DEBUG: Rebuilding index "t_network_key" - 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" - DEBUG: Rebuilding index "t_string_idx1" - DEBUG: Rebuilding index "t_string_idx" - 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" ALTER TABLE t ALTER network TYPE inet; -- noop DEBUG: Rebuilding index "t_network_key" --- 2508,2513 ----