Building on commit 8f9fe6edce358f7904e0db119416b4d1080a83aa, this adds
protransform functions to the length coercions for numeric, varbit, timestamp,
timestamptz, time, timetz and interval.  This mostly serves to make more ALTER
TABLE ALTER TYPE operations avoid a rewrite, including numeric(10,2) ->
numeric(12,2), varbit(4) -> varbit(8) and timestamptz(2) -> timestamptz(4).
The rules for varbit are exactly the same as for varchar.  Numeric is slightly
more complex:

 * Flatten calls to our length coercion function that solely represent
 * increases in allowable precision.  Scale changes mutate every datum, so
 * they are unoptimizable.  Some values, e.g. 1E-1001, can only fit into an
 * unconstrained numeric, so a change from an unconstrained numeric to any
 * constrained numeric is also unoptimizable.

time{,stamp}{,tz} are similar to varchar for these purposes, except that, for
example, plain "timestamptz" is equivalent to "timestamptz(6)".  interval has
a vastly different typmod format, but the principles applicable to length
coercion remain the same.

Under --disable-integer-datetimes, I'm not positive that timestamp_scale() is
always a no-op when one would logically expect as much.  Does there exist a
timestamp such that v::timestamp(2) differs from v:timestamp(2)::timestamp(4)
due to floating point rounding?  Even if so, I'm fairly comfortable calling it
a feature rather than a bug to avoid perturbing values that way.

After these patches, the only core length coercion casts not having
protransform functions are those for "bpchar" and "bit".  For those, we could
only optimize trivial cases of no length change.  I'm not planning to do so.

Thanks,
nm
diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c
index 3fa8117..e5a03b9 100644
*** a/src/backend/utils/adt/varbit.c
--- b/src/backend/utils/adt/varbit.c
***************
*** 18,23 ****
--- 18,25 ----
  
  #include "access/htup.h"
  #include "libpq/pqformat.h"
+ #include "nodes/nodeFuncs.h"
+ #include "parser/parse_clause.h"
  #include "utils/array.h"
  #include "utils/varbit.h"
  
***************
*** 646,651 **** varbit_send(PG_FUNCTION_ARGS)
--- 648,686 ----
  }
  
  /*
+  * varbit_transform()
+  * Flatten calls to our length coercion function that leave the new maximum
+  * length >= the previous maximum length.  We ignore the isExplicit argument,
+  * which only affects truncation.
+  */
+ Datum
+ varbit_transform(PG_FUNCTION_ARGS)
+ {
+       FuncExpr   *expr = (FuncExpr *) PG_GETARG_POINTER(0);
+       Node       *typmod;
+       Node       *ret = NULL;
+ 
+       if (!IsA(expr, FuncExpr))
+               PG_RETURN_POINTER(ret);
+ 
+       Assert(list_length(expr->args) == 3);
+       typmod = lsecond(expr->args);
+ 
+       if (IsA(typmod, Const))
+       {
+               Node       *source = linitial(expr->args);
+               int32           new_typmod = DatumGetInt32(((Const *) 
typmod)->constvalue);
+               int32           old_max = exprTypmod(source);
+               int32           new_max = new_typmod;
+ 
+               if (new_max <= 0 || (old_max >= 0 && old_max <= new_max))
+                       ret = relabel_to_typmod(source, new_typmod);
+       }
+ 
+       PG_RETURN_POINTER(ret);
+ }
+ 
+ /*
   * varbit()
   * Converts a varbit() type to a specific internal length.
   * len is the maximum bitlength specified in the column definition.
diff --git a/src/include/catalog/pg_pindex c893c3a..2a71f82 100644
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
***************
*** 2005,2011 **** DESCR("convert bitstring to int4");
  
  DATA(insert OID = 1685 (  bit                    PGNSP PGUID 12 1 0 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 = 1687 (  varbit                 PGNSP PGUID 12 1 0 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");
  
  DATA(insert OID = 1698 (  position               PGNSP PGUID 12 1 0 0 0 f f f 
t f i 2 0 23 "1560 1560" _null_ _null_ _null_ _null_ bitposition _null_ _null_ 
_null_ ));
--- 2005,2013 ----
  
  DATA(insert OID = 1685 (  bit                    PGNSP PGUID 12 1 0 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 = 3145 ( varbit_transform  PGNSP PGUID 12 1 0 0 0 f f f t f i 
1 0 2281 "2281" _null_ _null_ _null_ _null_ varbit_transform _null_ _null_ 
_null_ ));
! DESCR("transform a varbit length coercion");
! DATA(insert OID = 1687 (  varbit                 PGNSP PGUID 12 1 0 0 3145 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");
  
  DATA(insert OID = 1698 (  position               PGNSP PGUID 12 1 0 0 0 f f f 
t f i 2 0 23 "1560 1560" _null_ _null_ _null_ _null_ bitposition _null_ _null_ 
_null_ ));
diff --git a/src/include/utils/varbiindex e329d52..5f2d8dd 100644
*** a/src/include/utils/varbit.h
--- b/src/include/utils/varbit.h
***************
*** 72,77 **** extern Datum varbit_send(PG_FUNCTION_ARGS);
--- 72,78 ----
  extern Datum varbittypmodin(PG_FUNCTION_ARGS);
  extern Datum varbittypmodout(PG_FUNCTION_ARGS);
  extern Datum bit(PG_FUNCTION_ARGS);
+ extern Datum varbit_transform(PG_FUNCTION_ARGS);
  extern Datum varbit(PG_FUNCTION_ARGS);
  extern Datum biteq(PG_FUNCTION_ARGS);
  extern Datum bitne(PG_FUNCTION_ARGS);
diff --git a/src/test/regress/expindex 301cc4b..ca83664 100644
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index 6b60a5c..e70230e 100644
*** a/src/backend/utils/adt/numeric.c
--- b/src/backend/utils/adt/numeric.c
***************
*** 30,35 ****
--- 30,37 ----
  #include "catalog/pg_type.h"
  #include "libpq/pqformat.h"
  #include "miscadmin.h"
+ #include "nodes/nodeFuncs.h"
+ #include "parser/parse_clause.h"
  #include "utils/array.h"
  #include "utils/builtins.h"
  #include "utils/int8.h"
***************
*** 713,718 **** numeric_send(PG_FUNCTION_ARGS)
--- 715,762 ----
  
  
  /*
+  * numeric_transform() -
+  *
+  * Flatten calls to our length coercion function that solely represent
+  * increases in allowable precision.  Scale changes mutate every datum, so
+  * they are unoptimizable.  Some values, e.g. 1E-1001, can only fit into an
+  * unconstrained numeric, so a change from an unconstrained numeric to any
+  * constrained numeric is also unoptimizable.
+  */
+ Datum
+ numeric_transform(PG_FUNCTION_ARGS)
+ {
+       FuncExpr   *expr = (FuncExpr *) PG_GETARG_POINTER(0);
+       Node       *typmod;
+       Node       *ret = NULL;
+ 
+       if (!IsA(expr, FuncExpr))
+               PG_RETURN_POINTER(ret);
+ 
+       Assert(list_length(expr->args) == 2);
+       typmod = lsecond(expr->args);
+ 
+       if (IsA(typmod, Const))
+       {
+               Node       *source = linitial(expr->args);
+               int32           old_typmod = exprTypmod(source);
+               int32           new_typmod = DatumGetInt32(((Const *) 
typmod)->constvalue);
+               int32           old_scale = (old_typmod - VARHDRSZ) & 0xffff;
+               int32           new_scale = (new_typmod - VARHDRSZ) & 0xffff;
+               int32           old_precis = (old_typmod - VARHDRSZ) >> 16 & 
0xffff;
+               int32           new_precis = (new_typmod - VARHDRSZ) >> 16 & 
0xffff;
+ 
+               if (new_typmod < VARHDRSZ /* unconstrained destination */ ||
+                       (old_typmod >= VARHDRSZ /* constrained source */ &&
+                        new_scale == old_scale &&
+                        new_precis >= old_precis))
+                       ret = relabel_to_typmod(source, new_typmod);
+       }
+ 
+       PG_RETURN_POINTER(ret);
+ }
+ 
+ /*
   * numeric() -
   *
   *    This is a special function called by the Postgres database system
diff --git a/src/include/catalog/pg_prindex c893c3a..d0d25b8 100644
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
***************
*** 2135,2142 **** DATA(insert OID = 2917 (  numerictypmodin            PGNSP 
PGUID 12 1 0 0 0 f f f t f i 1
  DESCR("I/O typmod");
  DATA(insert OID = 2918 (  numerictypmodout            PGNSP PGUID 12 1 0 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 = 1703 ( numeric                              PGNSP PGUID 12 
1 0 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 0 
f f f t f i 1 0 1700 "1700" _null_ _null_ _null_ _null_ numeric_abs _null_ 
_null_ _null_ ));
  DATA(insert OID = 1705 ( abs                                  PGNSP PGUID 12 
1 0 0 0 f f f t f i 1 0 1700 "1700" _null_ _null_ _null_ _null_ numeric_abs 
_null_ _null_ _null_ ));
  DESCR("absolute value");
--- 2135,2144 ----
  DESCR("I/O typmod");
  DATA(insert OID = 2918 (  numerictypmodout            PGNSP PGUID 12 1 0 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 = 1703 ( numeric                              PGNSP PGUID 12 
1 0 0 3144 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 = 3144 ( numeric_transform            PGNSP PGUID 12 1 0 0 0 
f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ numeric_transform 
_null_ _null_ _null_ ));
+ DESCR("transform a numeric length coercion");
  DATA(insert OID = 1704 ( numeric_abs                  PGNSP PGUID 12 1 0 0 0 
f f f t f i 1 0 1700 "1700" _null_ _null_ _null_ _null_ numeric_abs _null_ 
_null_ _null_ ));
  DATA(insert OID = 1705 ( abs                                  PGNSP PGUID 12 
1 0 0 0 f f f t f i 1 0 1700 "1700" _null_ _null_ _null_ _null_ numeric_abs 
_null_ _null_ _null_ ));
  DESCR("absolute value");
diff --git a/src/include/utils/builtindex aa36db6..63e2844 100644
*** a/src/include/utils/builtins.h
--- b/src/include/utils/builtins.h
***************
*** 910,915 **** extern Datum numeric_recv(PG_FUNCTION_ARGS);
--- 910,916 ----
  extern Datum numeric_send(PG_FUNCTION_ARGS);
  extern Datum numerictypmodin(PG_FUNCTION_ARGS);
  extern Datum numerictypmodout(PG_FUNCTION_ARGS);
+ extern Datum numeric_transform(PG_FUNCTION_ARGS);
  extern Datum numeric (PG_FUNCTION_ARGS);
  extern Datum numeric_abs(PG_FUNCTION_ARGS);
  extern Datum numeric_uminus(PG_FUNCTION_ARGS);
diff --git a/src/test/regress/expecindex 301cc4b..be669b6 100644
diff --git a/configure b/configure
index bfc7a1f..7e1b74f 100755
*** a/configure
--- b/configure
***************
*** 20773,20779 **** LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 
's/-lreadline//g'`
  
  
  
! for ac_func in crypt getopt getrusage inet_aton random rint srandom strdup 
strerror strlcat strlcpy strtol strtoul
  do
  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
  { $as_echo "$as_me:$LINENO: checking for $ac_func" >&5
--- 20773,20780 ----
  
  
  
! 
! for ac_func in crypt fls getopt getrusage inet_aton random rint srandom 
strdup strerror strlcat strlcpy strtol strtoul
  do
  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
  { $as_echo "$as_me:$LINENO: checking for $ac_func" >&5
diff --git a/conindex 54ca820..b684512 100644
*** a/configure.in
--- b/configure.in
***************
*** 1319,1325 **** fi
  pgac_save_LIBS="$LIBS"
  LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
  
! AC_REPLACE_FUNCS([crypt getopt getrusage inet_aton random rint srandom strdup 
strerror strlcat strlcpy strtol strtoul])
  
  case $host_os in
  
--- 1319,1325 ----
  pgac_save_LIBS="$LIBS"
  LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
  
! AC_REPLACE_FUNCS([crypt fls getopt getrusage inet_aton random rint srandom 
strdup strerror strlcat strlcpy strtol strtoul])
  
  case $host_os in
  
diff --git a/src/baindex ff4e304..1c84e87 100644
*** a/src/backend/utils/adt/date.c
--- b/src/backend/utils/adt/date.c
***************
*** 1210,1215 **** timetypmodout(PG_FUNCTION_ARGS)
--- 1210,1226 ----
  }
  
  
+ /* time_transform()
+  * Flatten calls to time_scale() and timetz_scale() that solely represent
+  * increases in allowed precision.
+  */
+ Datum
+ time_transform(PG_FUNCTION_ARGS)
+ {
+       PG_RETURN_POINTER(TemporalTransform(MAX_TIME_PRECISION,
+                                                                               
(Node *) PG_GETARG_POINTER(0)));
+ }
+ 
  /* time_scale()
   * Adjust time type for specified scale factor.
   * Used by PostgreSQL type system to stuff columns.
diff --git a/src/backend/utils/adt/index dad41fc..fd118c4 100644
*** a/src/backend/utils/adt/datetime.c
--- b/src/backend/utils/adt/datetime.c
***************
*** 23,28 ****
--- 23,30 ----
  #include "catalog/pg_type.h"
  #include "funcapi.h"
  #include "miscadmin.h"
+ #include "nodes/nodeFuncs.h"
+ #include "parser/parse_clause.h"
  #include "utils/builtins.h"
  #include "utils/date.h"
  #include "utils/datetime.h"
***************
*** 4142,4147 **** CheckDateTokenTables(void)
--- 4144,4182 ----
  }
  
  /*
+  * Helper for temporal protransform functions.  Types time, timetz, timestamp
+  * and timestamptz each have a range of allowed precisions.  An unspecified
+  * precision is rigorously equivalent to the highest specifiable precision.
+  */
+ Node *
+ TemporalTransform(int32 max_precis, Node *node)
+ {
+       FuncExpr   *expr = (FuncExpr *) node;
+       Node       *typmod;
+       Node       *ret = NULL;
+ 
+       if (!IsA(expr, FuncExpr))
+               return ret;
+ 
+       Assert(list_length(expr->args) == 2);
+       typmod = lsecond(expr->args);
+ 
+       if (IsA(typmod, Const))
+       {
+               Node       *source = linitial(expr->args);
+               int32           old_precis = exprTypmod(source);
+               int32           new_precis = DatumGetInt32(((Const *) 
typmod)->constvalue);
+ 
+               if (new_precis == -1 ||
+                       new_precis == max_precis ||
+                       (old_precis != -1 && new_precis >= old_precis))
+                       ret = relabel_to_typmod(source, new_precis);
+       }
+ 
+       return ret;
+ }
+ 
+ /*
   * This function gets called during timezone config file load or reload
   * to create the final array of timezone tokens.  The argument array
   * is already sorted in name order.  The data is converted to datetkn
diff --git a/src/backend/utils/adt/timeindex 450dcd4..c7bd1e3 100644
*** a/src/backend/utils/adt/timestamp.c
--- b/src/backend/utils/adt/timestamp.c
***************
*** 27,32 ****
--- 27,34 ----
  #include "funcapi.h"
  #include "libpq/pqformat.h"
  #include "miscadmin.h"
+ #include "nodes/nodeFuncs.h"
+ #include "parser/parse_clause.h"
  #include "parser/scansup.h"
  #include "utils/array.h"
  #include "utils/builtins.h"
***************
*** 308,313 **** timestamptypmodout(PG_FUNCTION_ARGS)
--- 310,330 ----
  }
  
  
+ /* timestamp_transform()
+  * Flatten calls to timestamp_scale() and timestamptz_scale() that solely
+  * represent increases in allowed precision.
+  */
+ Datum
+ timestamp_transform(PG_FUNCTION_ARGS)
+ {
+       /*
+        * timestamp_scale throws an error when the typmod is out of range, but 
we
+        * can't get there from a cast: our typmodin will have caught it 
already.
+        */
+       PG_RETURN_POINTER(TemporalTransform(MAX_TIMESTAMP_PRECISION,
+                                                                               
(Node *) PG_GETARG_POINTER(0)));
+ }
+ 
  /* timestamp_scale()
   * Adjust time type for specified scale factor.
   * Used by PostgreSQL type system to stuff columns.
***************
*** 745,750 **** interval_send(PG_FUNCTION_ARGS)
--- 762,779 ----
        PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
  }
  
+ /*
+  * The interval typmod stores a "range" in its high 16 bits and a "precision"
+  * in its low 16 bits.  Both contribute to defining the resolution of the
+  * type.  Range addresses resolution granules larger than one second, and
+  * precision specifies resolution below one second.  This representation can
+  * express all SQL standard resolutions, but we implement them all in terms of
+  * truncating rightward from some position.  Range is a bitmap of permitted
+  * fields, but only the temporally-smallest such field is significant to our
+  * calculations.  Precision is a count of sub-second decimal places to retain.
+  * Setting all bits (INTERVAL_FULL_PRECISION) gives the same truncation
+  * semantics as choosing MAX_INTERVAL_PRECISION.
+  */
  Datum
  intervaltypmodin(PG_FUNCTION_ARGS)
  {
***************
*** 901,906 **** intervaltypmodout(PG_FUNCTION_ARGS)
--- 930,993 ----
  }
  
  
+ /* interval_transform()
+ 
+  * Flatten superfluous calls to interval_scale().  The interval typmod is
+  * complex to permit accepting and regurgitating all SQL standard variations.
+  * For truncation purposes, it boils down to a single, simple granularity.
+  */
+ Datum
+ interval_transform(PG_FUNCTION_ARGS)
+ {
+       FuncExpr   *expr = (FuncExpr *) PG_GETARG_POINTER(0);
+       Node       *typmod;
+       Node       *ret = NULL;
+ 
+       if (!IsA(expr, FuncExpr))
+               PG_RETURN_POINTER(ret);
+ 
+       Assert(list_length(expr->args) == 2);
+       typmod = lsecond(expr->args);
+ 
+       if (IsA(typmod, Const))
+       {
+               Node       *source = linitial(expr->args);
+               int32           old_typmod = exprTypmod(source);
+               int32           new_typmod = DatumGetInt32(((Const *) 
typmod)->constvalue);
+               int                     old_range;
+               int                     old_precis;
+               int                     new_range = INTERVAL_RANGE(new_typmod);
+               int                     new_precis = 
INTERVAL_PRECISION(new_typmod);
+               int                     new_range_fls;
+ 
+               if (old_typmod == -1)
+               {
+                       old_range = INTERVAL_FULL_RANGE;
+                       old_precis = INTERVAL_FULL_PRECISION;
+               }
+               else
+               {
+                       old_range = INTERVAL_RANGE(old_typmod);
+                       old_precis = INTERVAL_PRECISION(old_typmod);
+               }
+ 
+               /*
+                * Temporally-smaller fields occupy higher positions in the 
range
+                * bitmap.  Since only the temporally-smallest bit matters for 
length
+                * coercion purposes, we compare the last-set bits in the 
ranges.
+                */
+               new_range_fls = fls(new_range);
+               if (new_typmod == -1 ||
+                       ((new_range_fls >= SECOND ||
+                         new_range_fls >= fls(old_range)) &&
+                        (new_precis >= MAX_INTERVAL_PRECISION ||
+                         new_precis >= old_precis)))
+                       ret = relabel_to_typmod(source, new_typmod);
+       }
+ 
+       PG_RETURN_POINTER(ret);
+ }
+ 
  /* interval_scale()
   * Adjust interval type for specified fields.
   * Used by PostgreSQL type system to stuff columns.
diff --git a/src/include/catalog/pg_procindex c893c3a..49cde6b 100644
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
***************
*** 1253,1259 **** DESCR("date difference preserving months and years");
  
  /* OIDS 1200 - 1299 */
  
! DATA(insert OID = 1200 (  interval                    PGNSP PGUID 12 1 0 0 0 
f f f t f i 2 0 1186 "1186 23" _null_ _null_ _null_ _null_ interval_scale 
_null_ _null_ _null_ ));
  DESCR("adjust interval precision");
  
  DATA(insert OID = 1215 (  obj_description     PGNSP PGUID 14 100 0 0 0 f f f 
t f s 2 0 25 "26 19" _null_ _null_ _null_ _null_ "select description from 
pg_catalog.pg_description where objoid = $1 and classoid = (select oid from 
pg_catalog.pg_class where relname = $2 and relnamespace = PGNSP) and objsubid = 
0" _null_ _null_ _null_ ));
--- 1253,1261 ----
  
  /* OIDS 1200 - 1299 */
  
! DATA(insert OID = 3148 (  interval_transform PGNSP PGUID 12 1 0 0 0 f f f t f 
i 1 0 2281 "2281" _null_ _null_ _null_ _null_ interval_transform _null_ _null_ 
_null_ ));
! DESCR("transform an interval length coercion");
! DATA(insert OID = 1200 (  interval                    PGNSP PGUID 12 1 0 0 
3148 f f f t f i 2 0 1186 "1186 23" _null_ _null_ _null_ _null_ interval_scale 
_null_ _null_ _null_ ));
  DESCR("adjust interval precision");
  
  DATA(insert OID = 1215 (  obj_description     PGNSP PGUID 14 100 0 0 0 f f f 
t f s 2 0 25 "26 19" _null_ _null_ _null_ _null_ "select description from 
pg_catalog.pg_description where objoid = $1 and classoid = (select oid from 
pg_catalog.pg_class where relname = $2 and relnamespace = PGNSP) and objsubid = 
0" _null_ _null_ _null_ ));
***************
*** 2712,2718 **** DATA(insert OID = 1953 (  byteane               PGNSP PGUID 
12 1 0 0 0 f f f t f i 2 0 16
  DATA(insert OID = 1954 (  byteacmp               PGNSP PGUID 12 1 0 0 0 f f f 
t f i 2 0 23 "17 17" _null_ _null_ _null_ _null_ byteacmp _null_ _null_ _null_ 
));
  DESCR("less-equal-greater");
  
! DATA(insert OID = 1961 (  timestamp              PGNSP PGUID 12 1 0 0 0 f f f 
t f i 2 0 1114 "1114 23" _null_ _null_ _null_ _null_ timestamp_scale _null_ 
_null_ _null_ ));
  DESCR("adjust timestamp precision");
  
  DATA(insert OID = 1965 (  oidlarger              PGNSP PGUID 12 1 0 0 0 f f f 
t f i 2 0 26 "26 26" _null_ _null_ _null_ _null_ oidlarger _null_ _null_ _null_ 
));
--- 2714,2722 ----
  DATA(insert OID = 1954 (  byteacmp               PGNSP PGUID 12 1 0 0 0 f f f 
t f i 2 0 23 "17 17" _null_ _null_ _null_ _null_ byteacmp _null_ _null_ _null_ 
));
  DESCR("less-equal-greater");
  
! DATA(insert OID = 3147 (  timestamp_transform PGNSP PGUID 12 1 0 0 0 f f f t 
f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ timestamp_transform _null_ 
_null_ _null_ ));
! DESCR("transform a timestamp length coercion");
! DATA(insert OID = 1961 (  timestamp              PGNSP PGUID 12 1 0 0 3147 f 
f f t f i 2 0 1114 "1114 23" _null_ _null_ _null_ _null_ timestamp_scale _null_ 
_null_ _null_ ));
  DESCR("adjust timestamp precision");
  
  DATA(insert OID = 1965 (  oidlarger              PGNSP PGUID 12 1 0 0 0 f f f 
t f i 2 0 26 "26 26" _null_ _null_ _null_ _null_ oidlarger _null_ _null_ _null_ 
));
***************
*** 2720,2730 **** DESCR("larger of two");
  DATA(insert OID = 1966 (  oidsmaller     PGNSP PGUID 12 1 0 0 0 f f f t f i 2 
0 26 "26 26" _null_ _null_ _null_ _null_ oidsmaller _null_ _null_ _null_ ));
  DESCR("smaller of two");
  
! DATA(insert OID = 1967 (  timestamptz    PGNSP PGUID 12 1 0 0 0 f f f t f i 2 
0 1184 "1184 23" _null_ _null_ _null_ _null_ timestamptz_scale _null_ _null_ 
_null_ ));
  DESCR("adjust timestamptz precision");
! DATA(insert OID = 1968 (  time                           PGNSP PGUID 12 1 0 0 
0 f f f t f i 2 0 1083 "1083 23" _null_ _null_ _null_ _null_ time_scale _null_ 
_null_ _null_ ));
  DESCR("adjust time precision");
! DATA(insert OID = 1969 (  timetz                 PGNSP PGUID 12 1 0 0 0 f f f 
t f i 2 0 1266 "1266 23" _null_ _null_ _null_ _null_ timetz_scale _null_ _null_ 
_null_ ));
  DESCR("adjust time with time zone precision");
  
  DATA(insert OID = 2003 (  textanycat     PGNSP PGUID 14 1 0 0 0 f f f t f v 2 
0 25 "25 2776" _null_ _null_ _null_ _null_ "select $1 || $2::pg_catalog.text" 
_null_ _null_ _null_ ));
--- 2724,2736 ----
  DATA(insert OID = 1966 (  oidsmaller     PGNSP PGUID 12 1 0 0 0 f f f t f i 2 
0 26 "26 26" _null_ _null_ _null_ _null_ oidsmaller _null_ _null_ _null_ ));
  DESCR("smaller of two");
  
! DATA(insert OID = 1967 (  timestamptz    PGNSP PGUID 12 1 0 0 3147 f f f t f 
i 2 0 1184 "1184 23" _null_ _null_ _null_ _null_ timestamptz_scale _null_ 
_null_ _null_ ));
  DESCR("adjust timestamptz precision");
! DATA(insert OID = 3146 (  time_transform   PGNSP PGUID 12 1 0 0 0 f f f t f i 
1 0 2281 "2281" _null_ _null_ _null_ _null_ time_transform _null_ _null_ _null_ 
));
! DESCR("transform a time length coercion");
! DATA(insert OID = 1968 (  time                           PGNSP PGUID 12 1 0 0 
3146 f f f t f i 2 0 1083 "1083 23" _null_ _null_ _null_ _null_ time_scale 
_null_ _null_ _null_ ));
  DESCR("adjust time precision");
! DATA(insert OID = 1969 (  timetz                 PGNSP PGUID 12 1 0 0 3146 f 
f f t f i 2 0 1266 "1266 23" _null_ _null_ _null_ _null_ timetz_scale _null_ 
_null_ _null_ ));
  DESCR("adjust time with time zone precision");
  
  DATA(insert OID = 2003 (  textanycat     PGNSP PGUID 14 1 0 0 0 f f f t f v 2 
0 25 "25 2776" _null_ _null_ _null_ _null_ "select $1 || $2::pg_catalog.text" 
_null_ _null_ _null_ ));
diff --git a/src/include/pg_config.hindex ef467b7..0411716 100644
*** a/src/include/pg_config.h.in
--- b/src/include/pg_config.h.in
***************
*** 158,163 ****
--- 158,166 ----
  /* Define to 1 if you have the `fdatasync' function. */
  #undef HAVE_FDATASYNC
  
+ /* Define to 1 if you have the `fls' function. */
+ #undef HAVE_FLS
+ 
  /* Define to 1 if you have the `fpclass' function. */
  #undef HAVE_FPCLASS
  
diff --git a/src/include/port.h bindex eceb4bf..edcc41f 100644
*** a/src/include/port.h
--- b/src/include/port.h
***************
*** 396,401 **** extern double pg_erand48(unsigned short xseed[3]);
--- 396,405 ----
  extern long pg_lrand48(void);
  extern void pg_srand48(long seed);
  
+ #ifndef HAVE_FLS
+ extern int fls(int mask);
+ #endif
+ 
  #ifndef HAVE_FSEEKO
  #define fseeko(a, b, c) fseek(a, b, c)
  #define ftello(a)             ftell(a)
diff --git a/src/include/index 13e0db4..cc6f381 100644
*** a/src/include/utils/date.h
--- b/src/include/utils/date.h
***************
*** 154,159 **** extern Datum time_recv(PG_FUNCTION_ARGS);
--- 154,160 ----
  extern Datum time_send(PG_FUNCTION_ARGS);
  extern Datum timetypmodin(PG_FUNCTION_ARGS);
  extern Datum timetypmodout(PG_FUNCTION_ARGS);
+ extern Datum time_transform(PG_FUNCTION_ARGS);
  extern Datum time_scale(PG_FUNCTION_ARGS);
  extern Datum time_eq(PG_FUNCTION_ARGS);
  extern Datum time_ne(PG_FUNCTION_ARGS);
diff --git a/src/include/utils/index cd9edda..a3d90fe 100644
*** a/src/include/utils/datetime.h
--- b/src/include/utils/datetime.h
***************
*** 16,21 ****
--- 16,22 ----
  #ifndef DATETIME_H
  #define DATETIME_H
  
+ #include "nodes/nodes.h"
  #include "utils/timestamp.h"
  
  /* this struct is declared in utils/tzparser.h: */
***************
*** 298,303 **** extern int     DecodeUnits(int field, char *lowtoken, int 
*val);
--- 299,306 ----
  
  extern int    j2day(int jd);
  
+ extern Node *TemporalTransform(int32 max_precis, Node *node);
+ 
  extern bool CheckDateTokenTables(void);
  
  extern void ConvertTimeZoneAbbrevs(TimeZoneAbbrevTable *tbl,
diff --git a/src/include/utils/timeindex 7661744..4006504 100644
*** a/src/include/utils/timestamp.h
--- b/src/include/utils/timestamp.h
***************
*** 100,105 **** extern Datum timestamp_recv(PG_FUNCTION_ARGS);
--- 100,106 ----
  extern Datum timestamp_send(PG_FUNCTION_ARGS);
  extern Datum timestamptypmodin(PG_FUNCTION_ARGS);
  extern Datum timestamptypmodout(PG_FUNCTION_ARGS);
+ extern Datum timestamp_transform(PG_FUNCTION_ARGS);
  extern Datum timestamp_scale(PG_FUNCTION_ARGS);
  extern Datum timestamp_eq(PG_FUNCTION_ARGS);
  extern Datum timestamp_ne(PG_FUNCTION_ARGS);
***************
*** 136,141 **** extern Datum interval_recv(PG_FUNCTION_ARGS);
--- 137,143 ----
  extern Datum interval_send(PG_FUNCTION_ARGS);
  extern Datum intervaltypmodin(PG_FUNCTION_ARGS);
  extern Datum intervaltypmodout(PG_FUNCTION_ARGS);
+ extern Datum interval_transform(PG_FUNCTION_ARGS);
  extern Datum interval_scale(PG_FUNCTION_ARGS);
  extern Datum interval_eq(PG_FUNCTION_ARGS);
  extern Datum interval_ne(PG_FUNCTION_ARGS);
diff --git a/src/port/fls.c b/src/ponew file mode 100644
index 0000000..53b2b15
*** /dev/null
--- b/src/port/fls.c
***************
*** 0 ****
--- 1,51 ----
+ /*
+  * src/port/fls.c
+  *
+  *    $FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/lib/libc/string/fls.c,v 
1.3 2007/01/09 00:28:12 imp Exp $
+  */
+ 
+ /*-
+  * Copyright (c) 1990, 1993
+  *    The Regents of the University of California.  All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+  * are met:
+  * 1. Redistributions of source code must retain the above copyright
+  *    notice, this list of conditions and the following disclaimer.
+  * 2. Redistributions in binary form must reproduce the above copyright
+  *    notice, this list of conditions and the following disclaimer in the
+  *    documentation and/or other materials provided with the distribution.
+  * 4. Neither the name of the University nor the names of its contributors
+  *    may be used to endorse or promote products derived from this software
+  *    without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+  * SUCH DAMAGE.
+  */
+ 
+ #include "c.h"
+ 
+ /*
+  * Find Last Set bit
+  */
+ int
+ fls(int mask)
+ {
+       int bit;
+ 
+       if (mask == 0)
+               return (0);
+       for (bit = 1; mask != 1; bit++)
+               mask = (unsigned int)mask >> 1;
+       return (bit);
+ }
diff --git a/src/testindex 301cc4b..323db24 100644
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to