OSDN Git Service

Fix timezone manipulation code to avoid crashes on some machines.
authorThomas G. Lockhart <lockhart@fourpalms.org>
Sun, 11 May 1997 15:11:47 +0000 (15:11 +0000)
committerThomas G. Lockhart <lockhart@fourpalms.org>
Sun, 11 May 1997 15:11:47 +0000 (15:11 +0000)
Add type conversion functions for floating point numbers.
Check for zero in unary minus floating point code (IEEE allows an
 explicit negative zero which looks ugly in a query result!).
Ensure circle type has non-negative radius.

src/backend/utils/adt/datetime.c
src/backend/utils/adt/dt.c
src/backend/utils/adt/float.c
src/backend/utils/adt/geo_ops.c
src/backend/utils/adt/nabstime.c
src/backend/utils/adt/timestamp.c

index 07113bd..3fa05b5 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.4 1997/04/17 13:50:34 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.5 1997/05/11 15:11:31 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -558,7 +558,8 @@ abstime_date(AbsoluteTime abstime)
 #if FALSE
        GetCurrentTime(tm);
 #endif
-       abstime = GetCurrentTransactionStartTime() + CTimeZone;
+       abstime = GetCurrentTransactionStartTime();
+       abstime2tm(abstime, &CTimeZone, tm);
        date->year = tm->tm_year;
        date->month = tm->tm_mon;
        date->day = tm->tm_mday;
index d700cbd..de0ec56 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.19 1997/04/27 19:20:10 thomas Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.20 1997/05/11 15:11:34 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -32,7 +32,7 @@
 #include "utils/builtins.h"
 
 #define USE_DATE_CACHE 1
-
+#define ROUND_ALL 0
 
 #define isleap(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
 
@@ -78,7 +78,8 @@ datetime_in(char *str)
 
     switch (dtype) {
     case DTK_DATE:
-       *result = tm2datetime( tm, fsec, &tz);
+       if (tm2datetime( tm, fsec, &tz, result) != 0)
+           elog(WARN,"Datetime out of range %s",str);
 
 #ifdef DATEDEBUG
 printf( "datetime_in- date is %f\n", *result);
@@ -123,6 +124,7 @@ datetime_out(DateTime *dt)
     int tz;
     struct tm tt, *tm = &tt;
     double fsec;
+    char *tzn;
     char buf[MAXDATELEN+1];
 
     if (!PointerIsValid(dt))
@@ -131,8 +133,8 @@ datetime_out(DateTime *dt)
     if (DATETIME_IS_RESERVED(*dt)) {
        EncodeSpecialDateTime(*dt, buf);
 
-    } else if (datetime2tm( *dt, &tz, tm, &fsec) == 0) {
-       EncodeDateTime(tm, fsec, &tz, DateStyle, buf);
+    } else if (datetime2tm( *dt, &tz, tm, &fsec, &tzn) == 0) {
+       EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf);
 
     } else {
        EncodeSpecialDateTime(DT_INVALID, buf);
@@ -179,7 +181,7 @@ timespan_in(char *str)
 
     if ((ParseDateTime( str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
       || (DecodeDateDelta( field, ftype, nf, &dtype, tm, &fsec) != 0))
-       elog(WARN,"Bad timespan external representation %s",str);
+       elog(WARN,"Bad timespan external representation '%s'",str);
 
     if (!PointerIsValid(span = PALLOCTYPE(TimeSpan)))
        elog(WARN,"Memory allocation failed, can't input timespan '%s'",str);
@@ -190,6 +192,7 @@ timespan_in(char *str)
 #if FALSE
            TIMESPAN_INVALID(span);
 #endif
+           elog(WARN,"Bad timespan external representation %s",str);
        };
        break;
 
@@ -292,14 +295,14 @@ SetDateTime( DateTime dt) {
 
     if (DATETIME_IS_CURRENT(dt)) {
        GetCurrentTime(&tt);
-       dt = tm2datetime( &tt, 0, NULL);
+       tm2datetime( &tt, 0, NULL, &dt);
 
 #ifdef DATEDEBUG
 printf( "SetDateTime- current time is %f\n", dt);
 #endif
     } else { /* if (DATETIME_IS_EPOCH(dt1)) */
        GetEpochTime(&tt);
-       dt = tm2datetime( &tt, 0, NULL);
+       tm2datetime( &tt, 0, NULL, &dt);
 #ifdef DATEDEBUG
 printf( "SetDateTime- epoch time is %f\n", dt);
 #endif
@@ -629,7 +632,7 @@ TimeSpan *datetime_sub(DateTime *datetime1, DateTime *datetime2)
        DATETIME_INVALID( result->time);
 
     } else {
-       result->time = (dt1 - dt2);
+       result->time = JROUND(dt1 - dt2);
     };
     result->month = 0;
 
@@ -649,11 +652,6 @@ DateTime *datetime_add_span(DateTime *datetime, TimeSpan *span)
 {
     DateTime *result;
 
-#if FALSE
-    double date, time;
-    int year, mon, mday;
-#endif
-
     if ((!PointerIsValid(datetime)) || (!PointerIsValid(span)))
        return NULL;
 
@@ -677,7 +675,7 @@ printf( "datetime_add_span- add %f to %d %f\n", *datetime, span->month, span->ti
            struct tm tt, *tm = &tt;
            double fsec;
 
-           if (datetime2tm( *result, NULL, tm, &fsec) == 0) {
+           if (datetime2tm( *result, NULL, tm, &fsec, NULL) == 0) {
 #ifdef DATEDEBUG
 printf( "datetime_add_span- date was %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday);
 #endif
@@ -702,17 +700,18 @@ printf( "datetime_add_span- date was %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, t
 #ifdef DATEDEBUG
 printf( "datetime_add_span- date becomes %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday);
 #endif
-               *result = tm2datetime( tm, fsec, NULL);
+               tm2datetime( tm, fsec, NULL, result);
 
            } else {
                DATETIME_INVALID(*result);
            };
        };
 
-#if FALSE
+#ifdef ROUND_ALL
        *result = JROUND(*result + span->time);
-#endif
+#else
        *result += span->time;
+#endif
     };
 
     return(result);
@@ -1009,6 +1008,7 @@ datetime_part(text *units, DateTime *datetime)
     int i;
     char *up, *lp, lowunits[MAXDATELEN+1];
     double fsec;
+    char *tzn;
     struct tm tt, *tm = &tt;
 
     if ((!PointerIsValid(units)) || (!PointerIsValid(datetime)))
@@ -1039,7 +1039,7 @@ printf( "datetime_part- units %s type=%d value=%d\n", lowunits, type, val);
 
        dt = (DATETIME_IS_RELATIVE(*datetime)? SetDateTime(*datetime): *datetime); 
 
-       if (datetime2tm( dt, &tz, tm, &fsec) == 0) {
+       if (datetime2tm( dt, &tz, tm, &fsec, &tzn) == 0) {
            switch (val) {
            case DTK_TZ:
                *result = tz;
@@ -1473,40 +1473,51 @@ datetkn *deltacache[MAXDATEFIELDS] = {NULL};
  * Ref: Explanatory Supplement to the Astronomical Almanac, 1992.
  *  University Science Books, 20 Edgehill Rd. Mill Valley CA 94941.
  *
+ * Use the algorithm by Henry Fliegel, a former NASA/JPL colleague
+ *  now at Aerospace Corp. (hi, Henry!)
+ *
  * These routines will be used by other date/time packages - tgl 97/02/25
  */
 
-#define USE_FLIEGEL 1
+/* Set the minimum year to one greater than the year of the first valid day
+ *  to avoid having to check year and day both. - tgl 97/05/08
+ */
+
+#define UTIME_MINYEAR (1901)
+#define UTIME_MINMONTH (12)
+#define UTIME_MINDAY (14)
+#define UTIME_MAXYEAR (2038)
+#define UTIME_MAXMONTH (01)
+#define UTIME_MAXDAY (18)
+
+#define IS_VALID_UTIME(y,m,d) (((y > UTIME_MINYEAR) \
+ || ((y == UTIME_MINYEAR) && ((m > UTIME_MINMONTH) \
+  || ((m == UTIME_MINMONTH) && (d >= UTIME_MINDAY))))) \
+ && ((y < UTIME_MAXYEAR) \
+ || ((y == UTIME_MAXYEAR) && ((m < UTIME_MAXMONTH) \
+  || ((m == UTIME_MAXMONTH) && (d <= UTIME_MAXDAY))))))
+
+#define JULIAN_MINYEAR (-4713)
+#define JULIAN_MINMONTH (11)
+#define JULIAN_MINDAY (23)
+
+#define IS_VALID_JULIAN(y,m,d) ((y > JULIAN_MINYEAR) \
+ || ((y == JULIAN_MINYEAR) && ((m > JULIAN_MINMONTH) \
+  || ((m == JULIAN_MINMONTH) && (d >= JULIAN_MINDAY)))))
 
 int
 date2j(int y, int m, int d)
 {
-#if USE_FLIEGEL
     int m12 = (m-14)/12;
 
     return((1461*(y+4800+m12))/4 + (367*(m-2-12*(m12)))/12
      - (3*((y+4900+m12)/100))/4 + d - 32075);
-
-#else
-    int c, ya;
-
-    if (m > 2) {
-       m -= 3;
-    } else {
-       m += 9;
-       y--;
-    };
-    c = y/100;
-    ya = y - 100*c;
-    return((146097*c)/4+(1461*ya)/4+(153*m+2)/5+d+1721119);
-#endif
 } /* date2j() */
 
 void j2date( int jd, int *year, int *month, int *day)
 {
     int j, y, m, d;
 
-#if USE_FLIEGEL
     int i, l, n;
 
     l = jd + 68569;
@@ -1520,26 +1531,6 @@ void j2date( int jd, int *year, int *month, int *day)
     m = (j+2) - (12*l);
     y = 100*(n-49)+i+l;
 
-#else
-    j = jd - 1721119;
-    y = (4*j-1)/146097;
-    j = 4*j-1-146097*y;
-    d = j/4;
-    j = (4*d+3)/1461;
-    d = 4*d+3-1461*j;
-    d = (d+4)/4;
-    m = (5*d-3)/153;
-    d = 5*d-3-153*m;
-    d = (d+5)/5;
-    y = 100*y+j;
-    if (m < 10) {
-       m += 3;
-    } else {
-       m -= 9;
-       y++;
-    };
-#endif
-
     *year = y;
     *month = m;
     *day = d;
@@ -1560,25 +1551,34 @@ int j2day( int date)
  * Convert datetime data type to POSIX time structure.
  * Note that year is _not_ 1900-based, but is an explicit full value.
  * Also, month is one-based, _not_ zero-based.
+ * Returns:
+ *   0 on success
+ *  -1 on out of range
  */
 int
-datetime2tm( DateTime dt, int *tzp, struct tm *tm, double *fsec)
+datetime2tm( DateTime dt, int *tzp, struct tm *tm, double *fsec, char **tzn)
 {
-    double date, time, sec;
+    double date, date0, time, sec;
     time_t utime;
 #ifdef USE_POSIX_TIME
     struct tm *tx;
 #endif
 
+
+    date0 = date2j(2000,1,1);
     time = (modf( dt/86400, &date)*86400);
-    date += date2j(2000,1,1);
+
     if (time < 0) {
            time += 86400;
            date -= 1;
     };
 
     /* Julian day routine does not work for negative Julian days */
-    if (date < 0) return -1;
+    if (date < -date0)
+       return -1;
+
+    /* add offset to go from J2000 back to standard Julian date */
+    date += date0;
 
 #ifdef DATEDEBUG
 printf( "datetime2tm- date is %f (%f %f)\n", dt, date, time);
@@ -1601,8 +1601,9 @@ printf( "datetime2tm- time is %02d:%02d:%02d %.7f\n", tm->tm_hour, tm->tm_min, t
 
     if (tzp != NULL) {
        /* XXX HACK to get time behavior compatible with Postgres v6.0 - tgl 97/04/07 */
-       if ((tm->tm_year >= 1902) && (tm->tm_year < 2038)) {
-           utime = (dt + (date2j(2000,1,1)-date2j(1970,1,1))*86400);
+       if (IS_VALID_UTIME( tm->tm_year, tm->tm_mon, tm->tm_mday)) {
+           utime = (dt + (date0-date2j(1970,1,1))*86400);
+
 #ifdef USE_POSIX_TIME
            tx = localtime(&utime);
 #ifdef DATEDEBUG
@@ -1617,32 +1618,31 @@ printf( "datetime2tm- (localtime) %d.%02d.%02d %02d:%02d:%02.0f %s %s dst=%d\n",
            tm->tm_min = tx->tm_min;
            tm->tm_sec = tx->tm_sec;
            tm->tm_isdst = tx->tm_isdst;
+
 #ifdef HAVE_INT_TIMEZONE
            *tzp = (tm->tm_isdst? (timezone - 3600): timezone);
+           if (tzn != NULL) *tzn = tzname[(tm->tm_isdst > 0)];
+
 #else /* !HAVE_INT_TIMEZONE */
            *tzp = (tm->tm_isdst? (tm->tm_gmtoff - 3600): tm->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */
+           if (tzn != NULL) *tzn = tm->tm_zone;
 #endif
+
 #else /* !USE_POSIX_TIME */
            *tzp = CTimeZone;   /* V7 conventions; don't know timezone? */
+           if (tzn != NULL) *tzn = CTZName;
 #endif
        } else {
            *tzp = 0;
            tm->tm_isdst = 0;
-#ifdef USE_POSIX_TIME
-#ifdef HAVE_INT_TIMEZONE
-           tzname[0] = "GMT";
-#else /* !HAVE_INT_TIMEZONE */
-           tm->tm_zone = "GMT";
-#endif
-#else /* !USE_POSIX_TIME */
-           strcpy( CTZName, "GMT");
-#endif
+           if (tzn != NULL) *tzn = NULL;
        };
 
        dt = dt2local( dt, *tzp);
 
     } else {
        tm->tm_isdst = 0;
+       if (tzn != NULL) *tzn = NULL;
     };
 
 #ifdef DATEDEBUG
@@ -1666,26 +1666,25 @@ printf( "datetime2tm- timezone is %s; offset is %d (%d); daylight is %d\n",
  * Note that year is _not_ 1900-based, but is an explicit full value.
  * Also, month is one-based, _not_ zero-based.
  */
-DateTime
-tm2datetime( struct tm *tm, double fsec, int *tzp) {
+int
+tm2datetime( struct tm *tm, double fsec, int *tzp, DateTime *result) {
 
-    DateTime result;
     double date, time;
 
     /* Julian day routines are not correct for negative Julian days */
-    if ((date = date2j(tm->tm_year,tm->tm_mon,tm->tm_mday)) < 0)
+    if (! IS_VALID_JULIAN( tm->tm_year, tm->tm_mon, tm->tm_mday))
        return(DT_INVALID);
 
-    date -= date2j(2000,1,1);
+    date = date2j(tm->tm_year,tm->tm_mon,tm->tm_mday) - date2j(2000,1,1);
     time = time2t(tm->tm_hour,tm->tm_min,(tm->tm_sec + fsec));
-    result = (date*86400+time);
+    *result = (date*86400+time);
 #ifdef DATEDEBUG
-printf( "tm2datetime- date is %f (%f %f %d)\n", result, date, time, (((tm->tm_hour*60)+tm->tm_min)*60+tm->tm_sec));
+printf( "tm2datetime- date is %f (%f %f %d)\n", *result, date, time, (((tm->tm_hour*60)+tm->tm_min)*60+tm->tm_sec));
 printf( "tm2datetime- time is %f %02d:%02d:%02d %f\n", time, tm->tm_hour, tm->tm_min, tm->tm_sec, fsec);
 #endif
-    if (tzp != NULL) result = dt2local(result, -(*tzp));
+    if (tzp != NULL) *result = dt2local(*result, -(*tzp));
 
-    return(result);
+    return 0;
 } /* tm2datetime() */
 
 
@@ -1703,10 +1702,11 @@ timespan2tm(TimeSpan span, struct tm *tm, float8 *fsec)
        tm->tm_mon = 0;
     };
 
-#if FALSE
+#ifdef ROUND_ALL
     time = JROUND(span.time);
-#endif
+#else
     time = span.time;
+#endif
 
     funit = modf( (time / 86400), &iunit);
     tm->tm_mday = iunit;
@@ -1743,7 +1743,7 @@ printf( "tm2timespan- %d %f = %04d-%02d-%02d %02d:%02d:%02d %.2f\n", span->month
  tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, fsec);
 #endif
 
-    return 1;
+    return 0;
 } /* tm2timespan() */
 
 
@@ -2092,7 +2092,7 @@ printf( " %02d:%02d:%02d\n", tm->tm_hour, tm->tm_min, tm->tm_sec);
     if ((*dtype == DTK_DATE) && ((fmask & DTK_DATE_M) == DTK_DATE_M)
       && (tzp != NULL) && (! (fmask & DTK_M(TZ)))) {
 
-       if ((tm->tm_year >= 1902) && (tm->tm_year < 2038)) {
+       if (IS_VALID_UTIME( tm->tm_year, tm->tm_mon, tm->tm_mday)) {
 #ifdef USE_POSIX_TIME
            tm->tm_year -= 1900;
            tm->tm_mon -= 1;
@@ -2667,6 +2667,7 @@ printf( "DecodeDateDelta- field[%d] is %s (type %d)\n", i, field[i], ftype[i]);
 #endif
        switch (ftype[i]) {
        case DTK_TIME:
+           /* already read in forward-scan above so return error */
 #if FALSE
            if (DecodeTime(field[i], fmask, &tmask, tm, fsec) != 0) return -1;
 #endif
@@ -2916,47 +2917,27 @@ printf( "EncodeSpecialDateTime- unrecognized date\n");
 /* EncodeDateTime()
  * Encode date and time interpreted as local time.
  */
-int EncodeDateTime(struct tm *tm, double fsec, int *tzp, int style, char *str)
+int EncodeDateTime(struct tm *tm, double fsec, int *tzp, char **tzn, int style, char *str)
 {
     char mabbrev[4], dabbrev[4];
     int day, hour, min;
     double sec;
-#if defined(DATEDEBUG) && FALSE
-    char buf[MAXDATELEN+1];
-#endif
 
     sec = (tm->tm_sec + fsec);
 
-#if FALSE
-    tm->tm_isdst = -1;
-#endif
-
 #ifdef DATEDEBUG
 #ifdef USE_POSIX_TIME
 #ifdef HAVE_INT_TIMEZONE
 printf( "EncodeDateTime- timezone is %s (%s); offset is %d (%d); daylight is %d (%d)\n",
tzname[0], CTZName, *tzp, CTimeZone, tm->tm_isdst, CDayLight);
*tzn, tzname[0], *tzp, CTimeZone, tm->tm_isdst, CDayLight);
 #else
 printf( "EncodeDateTime- timezone is %s (%s); offset is %ld (%d); daylight is %d (%d)\n",
tm->tm_zone, CTZName, (- tm->tm_gmtoff), CTimeZone, tm->tm_isdst, CDayLight);
*tzn, tm->tm_zone, (- tm->tm_gmtoff), CTimeZone, tm->tm_isdst, CDayLight);
 #endif
 #else
-printf( "EncodeDateTime- timezone is %s; offset is %d; daylight is %d\n",
- CTZName, CTimeZone, CDayLight);
-#endif
+printf( "EncodeDateTime- timezone is %s (%s); offset is %d; daylight is %d\n",
+ *tzn, CTZName, CTimeZone, CDayLight);
 #endif
-
-#ifdef USE_POSIX_TIME
-    /* XXX HACK to get time behavior compatible with Postgres v6.0 - tgl 97/04/07 */
-    if ((tm->tm_year >= 1902) && (tm->tm_year < 2038)) {
-       tm->tm_year -= 1900;
-       tm->tm_mon -= 1;
-       mktime(tm);
-       tm->tm_year += 1900;
-       tm->tm_mon += 1;
-    } else {
-       tm->tm_isdst = -1;
-    };
 #endif
 
     day = date2j( tm->tm_year, tm->tm_mon, tm->tm_mday);
@@ -2980,7 +2961,7 @@ printf( "EncodeDateTime- day is %d\n", day);
              tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min);
            sprintf( (str+17), ((fsec != 0)? "%05.2f": "%02.0f"), sec);
 
-           if (tm->tm_isdst >= 0) {
+           if ((*tzn != NULL) && (tm->tm_isdst >= 0)) {
                if (tzp != NULL) {
                    hour = -(*tzp / 3600);
                    min = ((abs(*tzp) / 60) % 60);
@@ -3012,16 +2993,9 @@ printf( "EncodeDateTime- day is %d\n", day);
            sprintf( (str+5), "/%04d %02d:%02d:%05.2f",
              tm->tm_year, tm->tm_hour, tm->tm_min, sec);
 
-           if (tm->tm_isdst >= 0) {
-#ifdef USE_POSIX_TIME
-#ifdef HAVE_INT_TIMEZONE
-               sprintf( (str+22), " %s", tzname[(tm->tm_isdst > 0)]);
-#else /* !HAVE_INT_TIMEZONE */
-               sprintf( (str+22), " %s", tm->tm_zone);
-#endif
-#else /* !USE_POSIX_TIME */
-               sprintf( (str+22), " %s", CTZName);
-#endif
+           if ((*tzn != NULL) && (tm->tm_isdst >= 0)) {
+               strcpy( (str+22), " ");
+               strcpy( (str+23), *tzn);
            };
 
        } else {
@@ -3041,16 +3015,9 @@ printf( "EncodeDateTime- day is %d\n", day);
            sprintf( (str+10), " %02d:%02d:%05.2f %04d",
              tm->tm_hour, tm->tm_min, sec, tm->tm_year);
 
-           if (tm->tm_isdst >= 0) {
-#ifdef USE_POSIX_TIME
-#ifdef HAVE_INT_TIMEZONE
-               sprintf( (str+27), " %s", tzname[(tm->tm_isdst > 0)]);
-#else
-               sprintf( (str+27), " %s", tm->tm_zone);
-#endif
-#else
-               sprintf( (str+27), " %s", CTZName);
-#endif
+           if ((*tzn != NULL) && (tm->tm_isdst >= 0)) {
+               strcpy( (str+27), " ");
+               strcpy( (str+28), *tzn);
            };
 
        } else {
@@ -3063,13 +3030,6 @@ printf( "EncodeDateTime- day is %d\n", day);
 printf( "EncodeDateTime- date result is %s\n", str);
 #endif
 
-#if defined(DATEDEBUG) && FALSE
-    if (tm->tm_year >= 1000) tm->tm_year -= 1900;
-    tm->tm_mon -= 1;
-    strftime( buf, sizeof(buf), "%y.%m.%d %H:%M:%S %Z", tm);
-printf( "EncodeDateTime- strftime result is %s\n", buf);
-#endif
-
     return(TRUE);
 } /* EncodeDateTime() */
 
index 509ce6c..aece1cd 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.13 1997/03/12 21:09:11 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.14 1997/05/11 15:11:38 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -24,7 +24,7 @@
  *      float4eq, float4ne, float4lt, float4le, float4gt, float4ge
  *      float8eq, float8ne, float8lt, float8le, float8gt, float8ge
  *     Conversion routines:
- *      ftod, dtof
+ *      ftod, dtof, itod, dtoi, i2tod, dtoi2, itof, ftoi, i2tof, ftoi2
  *
  *     Random float8 ops:
  *      dround, dtrunc, dsqrt, dcbrt, dpow, dexp, dlog1
  *      routines, but then you pay the overhead of converting...)
  *
  * XXX GLUESOME STUFF. FIX IT! -AY '94
+ *
+ *     Added some additional conversion routines and cleaned up
+ *      a bit of the existing code. Need to change the error checking
+ *      for calls to pow(), exp() since on some machines (my Linux box
+ *      included) these routines do not set errno. - tgl 97/05/10
  */
 #include <stdio.h>             /* for sprintf() */
 #include <string.h>
 #include <math.h>
 
 #include "postgres.h"
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#endif
 #include "fmgr.h"
 #include "utils/builtins.h"    /* for ftod() prototype */
 #include "utils/palloc.h"
 
 
+#ifndef SHRT_MAX
+#define SHRT_MAX 32767
+#endif
+#ifndef SHRT_MIN
+#define SHRT_MIN (-32768)
+#endif
+
 #define FORMAT                 'g'     /* use "g" output format as standard format */
 /* not sure what the following should be, but better to make it over-sufficient */
 #define        MAXFLOATWIDTH   64
@@ -289,7 +304,7 @@ float32 float4um(float32 arg1)
     if (!arg1)
        return (float32)NULL;
     
-    val = -(*arg1);
+    val = ((*arg1 != 0) ? -(*arg1): *arg1);
     CheckFloat4Val(val);
 
     result = (float32) palloc(sizeof(float32data));
@@ -360,7 +375,7 @@ float64 float8um(float64 arg1)
     if (!arg1)
        return (float64)NULL;
     
-    val = -(*arg1);
+    val = ((*arg1 != 0)? -(*arg1): *arg1);
     
     CheckFloat8Val(val);
     result = (float64) palloc(sizeof(float64data));
@@ -585,50 +600,50 @@ float64 float8inc(float64 arg1)
 /*
  *     float4{eq,ne,lt,le,gt,ge}       - float4/float4 comparison operations
  */
-long float4eq(float32 arg1, float32 arg2)
+bool float4eq(float32 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-       return (long)NULL;
-    
+       return 0;
+
     return(*arg1 == *arg2);
 }
 
-long float4ne(float32 arg1, float32 arg2)
+bool float4ne(float32 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-       return (long)NULL;
+       return 0;
     
     return(*arg1 != *arg2);
 }
 
-long float4lt(float32 arg1, float32 arg2)
+bool float4lt(float32 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-       return (long)NULL;
+       return 0;
     
     return(*arg1 < *arg2);
 }
 
-long float4le(float32 arg1, float32 arg2)
+bool float4le(float32 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-       return (long)NULL;
+       return 0;
     
     return(*arg1 <= *arg2);
 }
 
-long float4gt(float32 arg1, float32 arg2)
+bool float4gt(float32 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-       return (long)NULL;
+       return 0;
     
     return(*arg1 > *arg2);
 }
 
-long float4ge(float32 arg1, float32 arg2)
+bool float4ge(float32 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-       return (long)NULL;
+       return 0;
     
     return(*arg1 >= *arg2);
 }
@@ -636,50 +651,50 @@ long float4ge(float32 arg1, float32 arg2)
 /*
  *     float8{eq,ne,lt,le,gt,ge}       - float8/float8 comparison operations
  */
-long float8eq(float64 arg1, float64 arg2)
+bool float8eq(float64 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-       return (long)NULL;
+       return 0;
     
     return(*arg1 == *arg2);
 }
 
-long float8ne(float64 arg1, float64 arg2)
+bool float8ne(float64 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-       return (long)NULL;
+       return 0;
     
     return(*arg1 != *arg2);
 }
 
-long float8lt(float64 arg1, float64 arg2)
+bool float8lt(float64 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-       return (long)NULL;
+       return 0;
     
     return(*arg1 < *arg2);
 }
 
-long float8le(float64 arg1, float64 arg2)
+bool float8le(float64 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-       return (long)NULL;
+       return 0;
     
     return(*arg1 <= *arg2);
 }
 
-long float8gt(float64 arg1, float64 arg2)
+bool float8gt(float64 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-       return (long)NULL;
+       return 0;
     
     return(*arg1 > *arg2);
 }
 
-long float8ge(float64 arg1, float64 arg2)
+bool float8ge(float64 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-       return (long)NULL;
+       return 0;
     
     return(*arg1 >= *arg2);
 }
@@ -700,7 +715,7 @@ float64 ftod(float32 num)
     
     if (!num)
        return (float64)NULL;
-    
+
     result = (float64) palloc(sizeof(float64data));
     
     *result = *num;
@@ -717,10 +732,140 @@ float32 dtof(float64 num)
     
     if (!num)
        return (float32)NULL;
+
+    CheckFloat4Val(*num);
+
+    result = (float32) palloc(sizeof(float32data));
+
+    *result = *num;
+    return(result);
+}
+
+
+/*
+ *     dtoi            - converts a float8 number to an int4 number
+ */
+int32 dtoi(float64 num)
+{
+    int32      result;
+    
+    if (!num)
+       elog(WARN,"dtoi:  unable to convert null",NULL);
+
+    if ((*num < INT_MIN) || (*num > INT_MAX))
+       elog(WARN,"dtoi:  integer out of range",NULL);
+
+    result = rint(*num);
+    return(result);
+}
+
+
+/*
+ *     dtoi2           - converts a float8 number to an int2 number
+ */
+int16 dtoi2(float64 num)
+{
+    int16      result;
+    
+    if (!num)
+       elog(WARN,"dtoi2:  unable to convert null",NULL);
+
+    if ((*num < SHRT_MIN) || (*num > SHRT_MAX))
+       elog(WARN,"dtoi2:  integer out of range",NULL);
+
+    result = rint(*num);
+    return(result);
+}
+
+
+/*
+ *     itod            - converts an int4 number to a float8 number
+ */
+float64 itod(int32 num)
+{
+    float64    result;
+    
+    result = (float64) palloc(sizeof(float64data));
+    
+    *result = num;
+    return(result);
+}
+
+
+/*
+ *     i2tod           - converts an int2 number to a float8 number
+ */
+float64 i2tod(int16 num)
+{
+    float64    result;
+    
+    result = (float64) palloc(sizeof(float64data));
+    
+    *result = num;
+    return(result);
+}
+
+
+/*
+ *     ftoi            - converts a float8 number to an int4 number
+ */
+int32 ftoi(float32 num)
+{
+    int32      result;
+    
+    if (!num)
+       elog(WARN,"ftoi:  unable to convert null",NULL);
+
+    if ((*num < INT_MIN) || (*num > INT_MAX))
+       elog(WARN,"ftoi:  integer out of range",NULL);
+
+    result = rint(*num);
+    return(result);
+}
+
+
+/*
+ *     ftoi2           - converts a float8 number to an int2 number
+ */
+int16 ftoi2(float32 num)
+{
+    int16      result;
+    
+    if (!num)
+       elog(WARN,"ftoi2:  unable to convert null",NULL);
+
+    if ((*num < SHRT_MIN) || (*num > SHRT_MAX))
+       elog(WARN,"ftoi2:  integer out of range",NULL);
+
+    result = rint(*num);
+    return(result);
+}
+
+
+/*
+ *     itof            - converts an int4 number to a float8 number
+ */
+float32 itof(int32 num)
+{
+    float32    result;
     
     result = (float32) palloc(sizeof(float32data));
     
-    *result = *num;
+    *result = num;
+    return(result);
+}
+
+
+/*
+ *     i2tof           - converts an int2 number to a float8 number
+ */
+float32 i2tof(int16 num)
+{
+    float32    result;
+    
+    result = (float32) palloc(sizeof(float32data));
+    
+    *result = num;
     return(result);
 }
 
@@ -1035,50 +1180,50 @@ float64 float84div(float64 arg1, float32 arg2)
 /*
  *     float48{eq,ne,lt,le,gt,ge}      - float4/float8 comparison operations
  */
-long float48eq(float32 arg1, float64 arg2)
+bool float48eq(float32 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-       return (long)NULL;
+       return 0;
     
     return(*arg1 == (float)*arg2);
 }
 
-long float48ne(float32 arg1, float64 arg2)
+bool float48ne(float32 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-       return (long)NULL;
+       return 0;
     
     return(*arg1 != (float)*arg2);
 }
 
-long float48lt(float32 arg1, float64 arg2)
+bool float48lt(float32 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-       return (long)NULL;
+       return 0;
     
     return(*arg1 < (float)*arg2);
 }
 
-long float48le(float32 arg1, float64 arg2)
+bool float48le(float32 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-       return (long)NULL;
+       return 0;
     
     return(*arg1 <= (float)*arg2);
 }
 
-long float48gt(float32 arg1, float64 arg2)
+bool float48gt(float32 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-       return (long)NULL;
+       return 0;
     
     return(*arg1 > (float)*arg2);
 }
 
-long float48ge(float32 arg1, float64 arg2)
+bool float48ge(float32 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-       return (long)NULL;
+       return 0;
     
     return(*arg1 >= (float)*arg2);
 }
@@ -1086,50 +1231,50 @@ long float48ge(float32 arg1, float64 arg2)
 /*
  *     float84{eq,ne,lt,le,gt,ge}      - float4/float8 comparison operations
  */
-long float84eq(float64 arg1, float32 arg2)
+bool float84eq(float64 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-       return (long)NULL;
+       return 0;
     
     return((float)*arg1 == *arg2);
 }
 
-long float84ne(float64 arg1, float32 arg2)
+bool float84ne(float64 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-       return (long)NULL;
+       return 0;
     
     return((float)*arg1 != *arg2);
 }
 
-long float84lt(float64 arg1, float32 arg2)
+bool float84lt(float64 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-       return (long)NULL;
+       return 0;
     
     return((float)*arg1 < *arg2);
 }
 
-long float84le(float64 arg1, float32 arg2)
+bool float84le(float64 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-       return (long)NULL;
+       return 0;
     
     return((float)*arg1 <= *arg2);
 }
 
-long float84gt(float64 arg1, float32 arg2)
+bool float84gt(float64 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-       return (long)NULL;
+       return 0;
     
     return((float)*arg1 > *arg2);
 }
 
-long float84ge(float64 arg1, float32 arg2)
+bool float84ge(float64 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-       return (long)NULL;
+       return 0;
     
     return((float)*arg1 >= *arg2);
 }
index 3489f6c..0b48500 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.5 1997/05/06 07:27:51 thomas Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.6 1997/05/11 15:11:41 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2639,7 +2639,7 @@ poly_path(POLYGON *poly)
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.5 1997/05/06 07:27:51 thomas Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.6 1997/05/11 15:11:41 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2722,7 +2722,7 @@ CIRCLE *circle_in(char *str)
     if (*s == DELIM) s++;
     while (isspace( *s)) s++;
 
-    if (! single_decode( s, &circle->radius, &s))
+    if ((! single_decode( s, &circle->radius, &s)) || (circle->radius < 0))
       elog (WARN, "Bad circle external representation '%s'",str);
 
     while (depth > 0) {
index 881206f..f091932 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.25 1997/04/25 18:40:33 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.26 1997/05/11 15:11:45 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -519,10 +519,10 @@ datetime_abstime(DateTime *datetime)
 
     } else {
        if (DATETIME_IS_RELATIVE(*datetime)) {
-           datetime2tm( SetDateTime(*datetime), NULL, tm, &fsec);
+           datetime2tm( SetDateTime(*datetime), NULL, tm, &fsec, NULL);
            result = tm2abstime( tm, 0);
 
-       } else if (datetime2tm( *datetime, NULL, tm, &fsec) == 0) {
+       } else if (datetime2tm( *datetime, NULL, tm, &fsec, NULL) == 0) {
            result = tm2abstime( tm, 0);
 
        } else {
index d4fb075..e884f7e 100644 (file)
@@ -184,7 +184,8 @@ timestamp_datetime(time_t timestamp)
     tm->tm_year += 1900;
     tm->tm_mon += 1;
 
-    *result = tm2datetime(tm, fsec, NULL);
+    if (tm2datetime(tm, fsec, NULL, result) != 0)
+       elog(WARN,"Unable to convert timestamp to datetime",timestamp_out(timestamp));
 
     return(result);
 } /* timestamp_datetime() */