88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.145 2005/07/23 14:53:21 momjian Exp $
11+ * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.146 2005/07/24 04:37:07 momjian Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -2244,38 +2244,37 @@ interval_mi(PG_FUNCTION_ARGS)
22442244Datum
22452245interval_mul (PG_FUNCTION_ARGS )
22462246{
2247- Interval * span1 = PG_GETARG_INTERVAL_P (0 );
2247+ Interval * span = PG_GETARG_INTERVAL_P (0 );
22482248float8 factor = PG_GETARG_FLOAT8 (1 );
2249+ double month_remainder ,day_remainder ;
22492250Interval * result ;
22502251
2251- #ifdef HAVE_INT64_TIMESTAMP
2252- int64 months ;
2253- int64 days ;
2254- #else
2255- double months ;
2256- double days ;
2257- #endif
2258-
22592252result = (Interval * )palloc (sizeof (Interval ));
22602253
2261- months = span1 -> month * factor ;
2262- days = span1 -> day * factor ;
2254+ result -> month = span -> month * factor ;
2255+ result -> day = span -> day * factor ;
2256+
2257+ /* Compute remainders */
2258+ month_remainder = span -> month * factor - result -> month ;
2259+ day_remainder = span -> day * factor - result -> day ;
2260+
2261+ /* Cascade fractions to lower units */
2262+ /* fractional months full days into days */
2263+ result -> day += month_remainder * DAYS_PER_MONTH ;
2264+ /* fractional months partial days into time */
2265+ day_remainder += (month_remainder * DAYS_PER_MONTH )-
2266+ (int )(month_remainder * DAYS_PER_MONTH );
2267+
22632268#ifdef HAVE_INT64_TIMESTAMP
2264- result -> month = months ;
2265- result -> day = days ;
2266- result -> time = span1 -> time * factor ;
2267- result -> time += (months - result -> month )* INT64CONST (30 )* USECS_PER_DAY ;
2268- result -> time += (days - result -> day )* INT64CONST (24 )* USECS_PER_HOUR ;
2269+ result -> time = rint (span -> time * factor +
2270+ day_remainder * USECS_PER_DAY );
22692271#else
2270- result -> month = (int )months ;
2271- result -> day = (int )days ;
2272- result -> time = JROUND (span1 -> time * factor );
2273- /* evaluate fractional months as 30 days */
2274- result -> time += JROUND ((months - result -> month )* DAYS_PER_MONTH * SECS_PER_DAY );
2275- /* evaluate fractional days as 24 hours */
2276- result -> time += JROUND ((days - result -> day )* HOURS_PER_DAY * SECS_PER_HOUR );
2272+ result -> time = JROUND (span -> time * factor +
2273+ day_remainder * SECS_PER_DAY );
22772274#endif
22782275
2276+ result = DatumGetIntervalP (DirectFunctionCall1 (interval_justify_hours ,
2277+ IntervalPGetDatum (result )));
22792278PG_RETURN_INTERVAL_P (result );
22802279}
22812280
@@ -2284,9 +2283,9 @@ mul_d_interval(PG_FUNCTION_ARGS)
22842283{
22852284/* Args are float8 and Interval *, but leave them as generic Datum */
22862285Datum factor = PG_GETARG_DATUM (0 );
2287- Datum span1 = PG_GETARG_DATUM (1 );
2286+ Datum span = PG_GETARG_DATUM (1 );
22882287
2289- return DirectFunctionCall2 (interval_mul ,span1 ,factor );
2288+ return DirectFunctionCall2 (interval_mul ,span ,factor );
22902289}
22912290
22922291Datum
@@ -2316,10 +2315,11 @@ interval_div(PG_FUNCTION_ARGS)
23162315/* fractional months full days into days */
23172316result -> day += month_remainder * DAYS_PER_MONTH ;
23182317/* fractional months partial days into time */
2319- day_remainder += (month_remainder * DAYS_PER_MONTH )- (int )(month_remainder * DAYS_PER_MONTH );
2318+ day_remainder += (month_remainder * DAYS_PER_MONTH )-
2319+ (int )(month_remainder * DAYS_PER_MONTH );
23202320
23212321#ifdef HAVE_INT64_TIMESTAMP
2322- result -> time += day_remainder * USECS_PER_DAY ;
2322+ result -> time += rint ( day_remainder * USECS_PER_DAY ) ;
23232323#else
23242324result -> time += day_remainder * SECS_PER_DAY ;
23252325result -> time = JROUND (result -> time );