Fix interval_transform so it doesn't throw away non-no-op casts.
authorTom Lane
Tue, 27 Dec 2016 20:43:54 +0000 (15:43 -0500)
committerTom Lane
Tue, 27 Dec 2016 20:43:54 +0000 (15:43 -0500)
commit4efe7aa2d8df98dc56d74042b25abf77b4e5bb61
tree4de37274f62183ed48e37dc41f90f565a7744453
parent29e28134fa47ea6041dd89a1f7c0d34b6d0fc136
Fix interval_transform so it doesn't throw away non-no-op casts.

interval_transform() contained two separate bugs that caused it to
sometimes mistakenly decide that a cast from interval to restricted
interval is a no-op and throw it away.

First, it was wrong to rely on dt.h's field type macros to have an
ordering consistent with the field's significance; in one case they do
not.  This led to mistakenly treating YEAR as less significant than MONTH,
so that a cast from INTERVAL MONTH to INTERVAL YEAR was incorrectly
discarded.

Second, fls(1< to SECOND was wrong.  This led to supposing that a cast to INTERVAL
MINUTE was really a cast to INTERVAL SECOND and so could be discarded.

To fix, get rid of the use of fls(), and make a function based on
intervaltypmodout to produce a field ID code adapted to the need here.

Per bug #14479 from Piotr Stefaniak.  Back-patch to 9.2 where transform
functions were introduced, because this code was born broken.

Discussion: https://postgr.es/m/20161227172307[email protected]
src/backend/utils/adt/timestamp.c
src/test/regress/expected/interval.out
src/test/regress/sql/interval.sql