retval = palloc(sizeof(GISTENTRY));
/* We are using the time + zone only to compress */
-#ifdef HAVE_INT64_TIMESTAMP
tmp = tz->time + (tz->zone * INT64CONST(1000000));
-#else
- tmp = (tz->time + tz->zone);
-#endif
r->lower = r->upper = tmp;
gistentryinit(*retval, PointerGetDatum(r),
entry->rel, entry->page,
/* All cases served by this function are inexact */
*recheck = true;
-#ifdef HAVE_INT64_TIMESTAMP
qqq = query->time + (query->zone * INT64CONST(1000000));
-#else
- qqq = (query->time + query->zone);
-#endif
key.lower = (GBT_NUMKEY *) &kkk->lower;
key.upper = (GBT_NUMKEY *) &kkk->upper;
p->day = INT_MAX;
p->month = INT_MAX;
-#ifdef HAVE_INT64_TIMESTAMP
p->time = PG_INT64_MAX;
-#else
- p->time = DBL_MAX;
-#endif
PG_RETURN_INTERVAL_P(p);
}
else
p->day = INT_MAX;
p->month = INT_MAX;
-#ifdef HAVE_INT64_TIMESTAMP
p->time = PG_INT64_MAX;
-#else
- p->time = DBL_MAX;
-#endif
PG_RETURN_INTERVAL_P(p);
}
* (as a double). Here because we need it for time/timetz as well as
* interval. See interval_cmp_internal for comparison.
*/
-#ifdef HAVE_INT64_TIMESTAMP
#define INTERVAL_TO_SEC(ivp) \
(((double) (ivp)->time) / ((double) USECS_PER_SEC) + \
(ivp)->day * (24.0 * SECS_PER_HOUR) + \
(ivp)->month * (30.0 * SECS_PER_DAY))
-#else
-#define INTERVAL_TO_SEC(ivp) \
- ((ivp)->time + \
- (ivp)->day * (24.0 * SECS_PER_HOUR) + \
- (ivp)->month * (30.0 * SECS_PER_DAY))
-#endif
#define GET_FLOAT_DISTANCE(t, arg1, arg2) Abs( ((float8) *((const t *) (arg1))) - ((float8) *((const t *) (arg2))) )
}
/* Here we change from SQL to Unix sign convention */
-#ifdef HAVE_INT64_TIMESTAMP
gmtoffset = -(interval->time / USECS_PER_SEC);
-#else
- gmtoffset = -interval->time;
-#endif
new_tz = pg_tzset_offset(gmtoffset);
pfree(interval);
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("date out of range for timestamp")));
-#ifdef HAVE_INT64_TIMESTAMP
+
/* date is days since 2000, timestamp is microseconds since same... */
result = dateVal * USECS_PER_DAY;
-#else
- /* date is days since 2000, timestamp is seconds since same... */
- result = dateVal * (double) SECS_PER_DAY;
-#endif
}
return result;
tm->tm_sec = 0;
tz = DetermineTimeZoneOffset(tm, session_timezone);
-#ifdef HAVE_INT64_TIMESTAMP
result = dateVal * USECS_PER_DAY + tz * USECS_PER_SEC;
-#else
- result = dateVal * (double) SECS_PER_DAY + tz;
-#endif
/*
* Since it is possible to go beyond allowed timestamptz range because
result = DBL_MAX;
else
{
-#ifdef HAVE_INT64_TIMESTAMP
/* date is days since 2000, timestamp is microseconds since same... */
result = dateVal * (double) USECS_PER_DAY;
-#else
- /* date is days since 2000, timestamp is seconds since same... */
- result = dateVal * (double) SECS_PER_DAY;
-#endif
}
return result;
static int
tm2time(struct pg_tm * tm, fsec_t fsec, TimeADT *result)
{
-#ifdef HAVE_INT64_TIMESTAMP
*result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec)
* USECS_PER_SEC) + fsec;
-#else
- *result = ((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec + fsec;
-#endif
return 0;
}
static int
time2tm(TimeADT time, struct pg_tm * tm, fsec_t *fsec)
{
-#ifdef HAVE_INT64_TIMESTAMP
tm->tm_hour = time / USECS_PER_HOUR;
time -= tm->tm_hour * USECS_PER_HOUR;
tm->tm_min = time / USECS_PER_MINUTE;
tm->tm_sec = time / USECS_PER_SEC;
time -= tm->tm_sec * USECS_PER_SEC;
*fsec = time;
-#else
- double trem;
-
-recalc:
- trem = time;
- TMODULO(trem, tm->tm_hour, (double) SECS_PER_HOUR);
- TMODULO(trem, tm->tm_min, (double) SECS_PER_MINUTE);
- TMODULO(trem, tm->tm_sec, 1.0);
- trem = TIMEROUND(trem);
- /* roundoff may need to propagate to higher-order fields */
- if (trem >= 1.0)
- {
- time = ceil(time);
- goto recalc;
- }
- *fsec = trem;
-#endif
-
return 0;
}
/*
* time_recv - converts external binary format to time
- *
- * We make no attempt to provide compatibility between int and float
- * time representations ...
*/
Datum
time_recv(PG_FUNCTION_ARGS)
int32 typmod = PG_GETARG_INT32(2);
TimeADT result;
-#ifdef HAVE_INT64_TIMESTAMP
result = pq_getmsgint64(buf);
if (result < INT64CONST(0) || result > USECS_PER_DAY)
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("time out of range")));
-#else
- result = pq_getmsgfloat8(buf);
-
- if (result < 0 || result > (double) SECS_PER_DAY)
- ereport(ERROR,
- (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
- errmsg("time out of range")));
-#endif
AdjustTimeForTypmod(&result, typmod);
StringInfoData buf;
pq_begintypsend(&buf);
-#ifdef HAVE_INT64_TIMESTAMP
pq_sendint64(&buf, time);
-#else
- pq_sendfloat8(&buf, time);
-#endif
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}
tm_hour, tm_min, sec)));
/* This should match tm2time */
-#ifdef HAVE_INT64_TIMESTAMP
time = (((tm_hour * MINS_PER_HOUR + tm_min) * SECS_PER_MINUTE)
* USECS_PER_SEC) + rint(sec * USECS_PER_SEC);
-#else
- time = ((tm_hour * MINS_PER_HOUR + tm_min) * SECS_PER_MINUTE) + sec;
-#endif
PG_RETURN_TIMEADT(time);
}
static void
AdjustTimeForTypmod(TimeADT *time, int32 typmod)
{
-#ifdef HAVE_INT64_TIMESTAMP
static const int64 TimeScales[MAX_TIME_PRECISION + 1] = {
INT64CONST(1000000),
INT64CONST(100000),
INT64CONST(5),
INT64CONST(0)
};
-#else
- /* note MAX_TIME_PRECISION differs in this case */
- static const double TimeScales[MAX_TIME_PRECISION + 1] = {
- 1.0,
- 10.0,
- 100.0,
- 1000.0,
- 10000.0,
- 100000.0,
- 1000000.0,
- 10000000.0,
- 100000000.0,
- 1000000000.0,
- 10000000000.0
- };
-#endif
if (typmod >= 0 && typmod <= MAX_TIME_PRECISION)
{
- /*
- * Note: this round-to-nearest code is not completely consistent about
- * rounding values that are exactly halfway between integral values.
- * On most platforms, rint() will implement round-to-nearest-even, but
- * the integer code always rounds up (away from zero). Is it worth
- * trying to be consistent?
- */
-#ifdef HAVE_INT64_TIMESTAMP
if (*time >= INT64CONST(0))
*time = ((*time + TimeOffsets[typmod]) / TimeScales[typmod]) *
TimeScales[typmod];
else
*time = -((((-*time) + TimeOffsets[typmod]) / TimeScales[typmod]) *
TimeScales[typmod]);
-#else
- *time = rint((double) *time * TimeScales[typmod]) / TimeScales[typmod];
-#endif
}
}
Datum
time_hash(PG_FUNCTION_ARGS)
{
- /* We can use either hashint8 or hashfloat8 directly */
-#ifdef HAVE_INT64_TIMESTAMP
return hashint8(fcinfo);
-#else
- return hashfloat8(fcinfo);
-#endif
}
Datum
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("timestamp out of range")));
-#ifdef HAVE_INT64_TIMESTAMP
-
/*
* Could also do this with time = (timestamp / USECS_PER_DAY *
* USECS_PER_DAY) - timestamp;
*/
result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) *
USECS_PER_SEC) + fsec;
-#else
- result = ((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec + fsec;
-#endif
PG_RETURN_TIMEADT(result);
}
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("timestamp out of range")));
-#ifdef HAVE_INT64_TIMESTAMP
-
/*
* Could also do this with time = (timestamp / USECS_PER_DAY *
* USECS_PER_DAY) - timestamp;
*/
result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) *
USECS_PER_SEC) + fsec;
-#else
- result = ((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec + fsec;
-#endif
PG_RETURN_TIMEADT(result);
}
{
Interval *span = PG_GETARG_INTERVAL_P(0);
TimeADT result;
-
-#ifdef HAVE_INT64_TIMESTAMP
int64 days;
result = span->time;
days = (-result + USECS_PER_DAY - 1) / USECS_PER_DAY;
result += days * USECS_PER_DAY;
}
-#else
- result = span->time;
- if (result >= (double) SECS_PER_DAY || result < 0)
- result -= floor(result / (double) SECS_PER_DAY) * (double) SECS_PER_DAY;
-#endif
PG_RETURN_TIMEADT(result);
}
Interval *span = PG_GETARG_INTERVAL_P(1);
TimeADT result;
-#ifdef HAVE_INT64_TIMESTAMP
result = time + span->time;
result -= result / USECS_PER_DAY * USECS_PER_DAY;
if (result < INT64CONST(0))
result += USECS_PER_DAY;
-#else
- TimeADT time1;
-
- result = time + span->time;
- TMODULO(result, time1, (double) SECS_PER_DAY);
- if (result < 0)
- result += SECS_PER_DAY;
-#endif
PG_RETURN_TIMEADT(result);
}
Interval *span = PG_GETARG_INTERVAL_P(1);
TimeADT result;
-#ifdef HAVE_INT64_TIMESTAMP
result = time - span->time;
result -= result / USECS_PER_DAY * USECS_PER_DAY;
if (result < INT64CONST(0))
result += USECS_PER_DAY;
-#else
- TimeADT time1;
-
- result = time - span->time;
- TMODULO(result, time1, (double) SECS_PER_DAY);
- if (result < 0)
- result += SECS_PER_DAY;
-#endif
PG_RETURN_TIMEADT(result);
}
switch (val)
{
case DTK_MICROSEC:
-#ifdef HAVE_INT64_TIMESTAMP
result = tm->tm_sec * 1000000.0 + fsec;
-#else
- result = (tm->tm_sec + fsec) * 1000000;
-#endif
break;
case DTK_MILLISEC:
-#ifdef HAVE_INT64_TIMESTAMP
result = tm->tm_sec * 1000.0 + fsec / 1000.0;
-#else
- result = (tm->tm_sec + fsec) * 1000;
-#endif
break;
case DTK_SECOND:
-#ifdef HAVE_INT64_TIMESTAMP
result = tm->tm_sec + fsec / 1000000.0;
-#else
- result = tm->tm_sec + fsec;
-#endif
break;
case DTK_MINUTE:
}
else if (type == RESERV && val == DTK_EPOCH)
{
-#ifdef HAVE_INT64_TIMESTAMP
result = time / 1000000.0;
-#else
- result = time;
-#endif
}
else
{
static int
tm2timetz(struct pg_tm * tm, fsec_t fsec, int tz, TimeTzADT *result)
{
-#ifdef HAVE_INT64_TIMESTAMP
result->time = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) *
USECS_PER_SEC) + fsec;
-#else
- result->time = ((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec + fsec;
-#endif
result->zone = tz;
return 0;
result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
-#ifdef HAVE_INT64_TIMESTAMP
result->time = pq_getmsgint64(buf);
if (result->time < INT64CONST(0) || result->time > USECS_PER_DAY)
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("time out of range")));
-#else
- result->time = pq_getmsgfloat8(buf);
-
- if (result->time < 0 || result->time > (double) SECS_PER_DAY)
- ereport(ERROR,
- (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
- errmsg("time out of range")));
-#endif
result->zone = pq_getmsgint(buf, sizeof(result->zone));
StringInfoData buf;
pq_begintypsend(&buf);
-#ifdef HAVE_INT64_TIMESTAMP
pq_sendint64(&buf, time->time);
-#else
- pq_sendfloat8(&buf, time->time);
-#endif
pq_sendint(&buf, time->zone, sizeof(time->zone));
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}
{
TimeOffset trem = time->time;
-#ifdef HAVE_INT64_TIMESTAMP
tm->tm_hour = trem / USECS_PER_HOUR;
trem -= tm->tm_hour * USECS_PER_HOUR;
tm->tm_min = trem / USECS_PER_MINUTE;
trem -= tm->tm_min * USECS_PER_MINUTE;
tm->tm_sec = trem / USECS_PER_SEC;
*fsec = trem - tm->tm_sec * USECS_PER_SEC;
-#else
-recalc:
- TMODULO(trem, tm->tm_hour, (double) SECS_PER_HOUR);
- TMODULO(trem, tm->tm_min, (double) SECS_PER_MINUTE);
- TMODULO(trem, tm->tm_sec, 1.0);
- trem = TIMEROUND(trem);
- /* roundoff may need to propagate to higher-order fields */
- if (trem >= 1.0)
- {
- trem = ceil(time->time);
- goto recalc;
- }
- *fsec = trem;
-#endif
if (tzp != NULL)
*tzp = time->zone;
t2;
/* Primary sort is by true (GMT-equivalent) time */
-#ifdef HAVE_INT64_TIMESTAMP
t1 = time1->time + (time1->zone * USECS_PER_SEC);
t2 = time2->time + (time2->zone * USECS_PER_SEC);
-#else
- t1 = time1->time + time1->zone;
- t2 = time2->time + time2->zone;
-#endif
if (t1 > t2)
return 1;
/*
* To avoid any problems with padding bytes in the struct, we figure the
- * field hashes separately and XOR them. This also provides a convenient
- * framework for dealing with the fact that the time field might be either
- * double or int64.
+ * field hashes separately and XOR them.
*/
-#ifdef HAVE_INT64_TIMESTAMP
thash = DatumGetUInt32(DirectFunctionCall1(hashint8,
Int64GetDatumFast(key->time)));
-#else
- thash = DatumGetUInt32(DirectFunctionCall1(hashfloat8,
- Float8GetDatumFast(key->time)));
-#endif
thash ^= DatumGetUInt32(hash_uint32(key->zone));
PG_RETURN_UINT32(thash);
}
Interval *span = PG_GETARG_INTERVAL_P(1);
TimeTzADT *result;
-#ifndef HAVE_INT64_TIMESTAMP
- TimeTzADT time1;
-#endif
-
result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
-#ifdef HAVE_INT64_TIMESTAMP
result->time = time->time + span->time;
result->time -= result->time / USECS_PER_DAY * USECS_PER_DAY;
if (result->time < INT64CONST(0))
result->time += USECS_PER_DAY;
-#else
- result->time = time->time + span->time;
- TMODULO(result->time, time1.time, (double) SECS_PER_DAY);
- if (result->time < 0)
- result->time += SECS_PER_DAY;
-#endif
result->zone = time->zone;
Interval *span = PG_GETARG_INTERVAL_P(1);
TimeTzADT *result;
-#ifndef HAVE_INT64_TIMESTAMP
- TimeTzADT time1;
-#endif
-
result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
-#ifdef HAVE_INT64_TIMESTAMP
result->time = time->time - span->time;
result->time -= result->time / USECS_PER_DAY * USECS_PER_DAY;
if (result->time < INT64CONST(0))
result->time += USECS_PER_DAY;
-#else
- result->time = time->time - span->time;
- TMODULO(result->time, time1.time, (double) SECS_PER_DAY);
- if (result->time < 0)
- result->time += SECS_PER_DAY;
-#endif
result->zone = time->zone;
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("date out of range for timestamp")));
-#ifdef HAVE_INT64_TIMESTAMP
result = date * USECS_PER_DAY + time->time + time->zone * USECS_PER_SEC;
-#else
- result = date * (double) SECS_PER_DAY + time->time + time->zone;
-#endif
/*
* Since it is possible to go beyond allowed timestamptz range because
break;
case DTK_MICROSEC:
-#ifdef HAVE_INT64_TIMESTAMP
result = tm->tm_sec * 1000000.0 + fsec;
-#else
- result = (tm->tm_sec + fsec) * 1000000;
-#endif
break;
case DTK_MILLISEC:
-#ifdef HAVE_INT64_TIMESTAMP
result = tm->tm_sec * 1000.0 + fsec / 1000.0;
-#else
- result = (tm->tm_sec + fsec) * 1000;
-#endif
break;
case DTK_SECOND:
-#ifdef HAVE_INT64_TIMESTAMP
result = tm->tm_sec + fsec / 1000000.0;
-#else
- result = tm->tm_sec + fsec;
-#endif
break;
case DTK_MINUTE:
}
else if (type == RESERV && val == DTK_EPOCH)
{
-#ifdef HAVE_INT64_TIMESTAMP
result = time->time / 1000000.0 + time->zone;
-#else
- result = time->time + time->zone;
-#endif
}
else
{
result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
-#ifdef HAVE_INT64_TIMESTAMP
result->time = t->time + (t->zone - tz) * USECS_PER_SEC;
while (result->time < INT64CONST(0))
result->time += USECS_PER_DAY;
while (result->time >= USECS_PER_DAY)
result->time -= USECS_PER_DAY;
-#else
- result->time = t->time + (t->zone - tz);
- while (result->time < 0)
- result->time += SECS_PER_DAY;
- while (result->time >= SECS_PER_DAY)
- result->time -= SECS_PER_DAY;
-#endif
result->zone = tz;
DatumGetCString(DirectFunctionCall1(interval_out,
PointerGetDatum(zone))))));
-#ifdef HAVE_INT64_TIMESTAMP
tz = -(zone->time / USECS_PER_SEC);
-#else
- tz = -(zone->time);
-#endif
result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
-#ifdef HAVE_INT64_TIMESTAMP
result->time = time->time + (time->zone - tz) * USECS_PER_SEC;
while (result->time < INT64CONST(0))
result->time += USECS_PER_DAY;
while (result->time >= USECS_PER_DAY)
result->time -= USECS_PER_DAY;
-#else
- result->time = time->time + (time->zone - tz);
- while (result->time < 0)
- result->time += SECS_PER_DAY;
- while (result->time >= SECS_PER_DAY)
- result->time -= SECS_PER_DAY;
-#endif
result->zone = tz;
static const datetkn *datebsearch(const char *key, const datetkn *base, int nel);
static int DecodeDate(char *str, int fmask, int *tmask, bool *is2digits,
struct pg_tm * tm);
-
-#ifndef HAVE_INT64_TIMESTAMP
-static char *TrimTrailingZeros(char *str);
-#endif /* HAVE_INT64_TIMESTAMP */
-
static char *AppendSeconds(char *cp, int sec, fsec_t fsec,
int precision, bool fillzeros);
static void AdjustFractSeconds(double frac, struct pg_tm * tm, fsec_t *fsec,
}
-/* TrimTrailingZeros()
- * ... resulting from printing numbers with full precision.
- *
- * Returns a pointer to the new end of string. No NUL terminator is put
- * there; callers are responsible for NUL terminating str themselves.
- *
- * Before Postgres 8.4, this always left at least 2 fractional digits,
- * but conversations on the lists suggest this isn't desired
- * since showing '0.10' is misleading with values of precision(1).
- */
-#ifndef HAVE_INT64_TIMESTAMP
-static char *
-TrimTrailingZeros(char *str)
-{
- int len = strlen(str);
-
- while (len > 1 && *(str + len - 1) == '0' && *(str + len - 2) != '.')
- len--;
- return str + len;
-}
-#endif /* HAVE_INT64_TIMESTAMP */
-
/*
* Append seconds and fractional seconds (if any) at *cp.
*
{
Assert(precision >= 0);
-#ifdef HAVE_INT64_TIMESTAMP
- /* fsec_t is just an int32 */
-
if (fillzeros)
cp = pg_ltostr_zeropad(cp, Abs(sec), 2);
else
cp = pg_ltostr(cp, Abs(sec));
+ /* fsec_t is just an int32 */
if (fsec != 0)
{
int32 value = Abs(fsec);
}
else
return cp;
-#else
- /* fsec_t is a double */
-
- if (fsec == 0)
- {
- if (fillzeros)
- return pg_ltostr_zeropad(cp, Abs(sec), 2);
- else
- return pg_ltostr(cp, Abs(sec));
- }
- else
- {
- if (fillzeros)
- sprintf(cp, "%0*.*f", precision + 3, precision, fabs(sec + fsec));
- else
- sprintf(cp, "%.*f", precision, fabs(sec + fsec));
- return TrimTrailingZeros(cp);
- }
-#endif /* HAVE_INT64_TIMESTAMP */
}
static char *
AppendTimestampSeconds(char *cp, struct pg_tm * tm, fsec_t fsec)
{
- /*
- * In float mode, don't print fractional seconds before 1 AD, since it's
- * unlikely there's any precision left ...
- */
-#ifndef HAVE_INT64_TIMESTAMP
- if (tm->tm_year <= 0)
- fsec = 0;
-#endif
return AppendSeconds(cp, tm->tm_sec, fsec, MAX_TIMESTAMP_PRECISION, true);
}
sec = (int) frac;
tm->tm_sec += sec;
frac -= sec;
-#ifdef HAVE_INT64_TIMESTAMP
*fsec += rint(frac * 1000000);
-#else
- *fsec += frac;
-#endif
}
/* As above, but initial scale produces days */
/* check for parse failure */
if (*cp != '\0' || errno != 0)
return DTERR_BAD_FORMAT;
-#ifdef HAVE_INT64_TIMESTAMP
*fsec = rint(frac * 1000000);
-#else
- *fsec = frac;
-#endif
return 0;
}
time = strtod(cp, &cp);
if (*cp != '\0' || errno != 0)
return DTERR_BAD_FORMAT;
-
-#ifdef HAVE_INT64_TIMESTAMP
time *= USECS_PER_DAY;
-#else
- time *= SECS_PER_DAY;
-#endif
dt2time(time,
&tm->tm_hour, &tm->tm_min,
&tm->tm_sec, fsec);
time = strtod(cp, &cp);
if (*cp != '\0' || errno != 0)
return DTERR_BAD_FORMAT;
-
-#ifdef HAVE_INT64_TIMESTAMP
time *= USECS_PER_DAY;
-#else
- time *= SECS_PER_DAY;
-#endif
dt2time(time,
&tm->tm_hour, &tm->tm_min,
&tm->tm_sec, fsec);
/* test for > 24:00:00 */
(tm->tm_hour == HOURS_PER_DAY &&
(tm->tm_min > 0 || tm->tm_sec > 0 || *fsec > 0)) ||
-#ifdef HAVE_INT64_TIMESTAMP
- *fsec < INT64CONST(0) || *fsec > USECS_PER_SEC
-#else
- *fsec < 0 || *fsec > 1
-#endif
- )
+ *fsec < INT64CONST(0) || *fsec > USECS_PER_SEC)
return DTERR_FIELD_OVERFLOW;
if ((fmask & DTK_TIME_M) != DTK_TIME_M)
return DTERR_BAD_FORMAT;
/* do a sanity check */
-#ifdef HAVE_INT64_TIMESTAMP
if (tm->tm_hour < 0 || tm->tm_min < 0 || tm->tm_min > MINS_PER_HOUR - 1 ||
tm->tm_sec < 0 || tm->tm_sec > SECS_PER_MINUTE ||
*fsec < INT64CONST(0) ||
*fsec > USECS_PER_SEC)
return DTERR_FIELD_OVERFLOW;
-#else
- if (tm->tm_hour < 0 || tm->tm_min < 0 || tm->tm_min > MINS_PER_HOUR - 1 ||
- tm->tm_sec < 0 || tm->tm_sec > SECS_PER_MINUTE ||
- *fsec < 0 || *fsec > 1)
- return DTERR_FIELD_OVERFLOW;
-#endif
return 0;
}
frac = strtod(cp, NULL);
if (errno != 0)
return DTERR_BAD_FORMAT;
-#ifdef HAVE_INT64_TIMESTAMP
*fsec = rint(frac * 1000000);
-#else
- *fsec = frac;
-#endif
/* Now truncate off the fraction for further processing */
*cp = '\0';
len = strlen(str);
switch (type)
{
case DTK_MICROSEC:
-#ifdef HAVE_INT64_TIMESTAMP
*fsec += rint(val + fval);
-#else
- *fsec += (val + fval) * 1e-6;
-#endif
tmask = DTK_M(MICROSECOND);
break;
/* avoid overflowing the fsec field */
tm->tm_sec += val / 1000;
val -= (val / 1000) * 1000;
-#ifdef HAVE_INT64_TIMESTAMP
*fsec += rint((val + fval) * 1000);
-#else
- *fsec += (val + fval) * 1e-3;
-#endif
tmask = DTK_M(MILLISECOND);
break;
case DTK_SECOND:
tm->tm_sec += val;
-#ifdef HAVE_INT64_TIMESTAMP
*fsec += rint(fval * 1000000);
-#else
- *fsec += fval;
-#endif
/*
* If any subseconds were specified, consider this
{
int sec;
-#ifdef HAVE_INT64_TIMESTAMP
sec = *fsec / USECS_PER_SEC;
*fsec -= sec * USECS_PER_SEC;
-#else
- TMODULO(*fsec, sec, 1.0);
-#endif
tm->tm_sec += sec;
}
s += strlen(s);
break;
case DCH_MS: /* millisecond */
-#ifdef HAVE_INT64_TIMESTAMP
sprintf(s, "%03d", (int) (in->fsec / INT64CONST(1000)));
-#else
- /* No rint() because we can't overflow and we might print US */
- sprintf(s, "%03d", (int) (in->fsec * 1000));
-#endif
if (S_THth(n->suffix))
str_numth(s, s, S_TH_TYPE(n->suffix));
s += strlen(s);
break;
case DCH_US: /* microsecond */
-#ifdef HAVE_INT64_TIMESTAMP
sprintf(s, "%06d", (int) in->fsec);
-#else
- /* don't use rint() because we can't overflow 1000 */
- sprintf(s, "%06d", (int) (in->fsec * 1000000));
-#endif
if (S_THth(n->suffix))
str_numth(s, s, S_TH_TYPE(n->suffix));
s += strlen(s);
}
}
-#ifdef HAVE_INT64_TIMESTAMP
if (tmfc.ms)
*fsec += tmfc.ms * 1000;
if (tmfc.us)
*fsec += tmfc.us;
-#else
- if (tmfc.ms)
- *fsec += (double) tmfc.ms / 1000;
- if (tmfc.us)
- *fsec += (double) tmfc.us / 1000000;
-#endif
/* Range-check date fields according to bit mask computed above */
if (fmask != 0)
if (tm->tm_hour < 0 || tm->tm_hour >= HOURS_PER_DAY ||
tm->tm_min < 0 || tm->tm_min >= MINS_PER_HOUR ||
tm->tm_sec < 0 || tm->tm_sec >= SECS_PER_MINUTE ||
-#ifdef HAVE_INT64_TIMESTAMP
- *fsec < INT64CONST(0) || *fsec >= USECS_PER_SEC
-#else
- *fsec < 0 || *fsec >= 1
-#endif
- )
+ *fsec < INT64CONST(0) || *fsec >= USECS_PER_SEC)
DateTimeParseError(DTERR_FIELD_OVERFLOW, date_str, "timestamp");
DEBUG_TM(tm);
* less than the specified time when WaitLatch is terminated early by a
* non-query-canceling signal such as SIGHUP.
*/
-
-#ifdef HAVE_INT64_TIMESTAMP
#define GetNowFloat() ((float8) GetCurrentTimestamp() / 1000000.0)
-#else
-#define GetNowFloat() GetCurrentTimestamp()
-#endif
endtime = GetNowFloat() + secs;
month = interval->month % MONTHS_PER_YEAR;
day = interval->day;
-#ifdef HAVE_INT64_TIMESTAMP
span = ((INT64CONST(365250000) * year + INT64CONST(30000000) * month +
INT64CONST(1000000) * day) * INT64CONST(86400)) +
interval->time;
span /= USECS_PER_SEC;
-#else
- span = (DAYS_PER_YEAR * year + (double) DAYS_PER_MONTH * month + day) * SECS_PER_DAY + interval->time;
-#endif
if (span < INT_MIN || span > INT_MAX)
time = INVALID_RELTIME;
break;
default:
-#ifdef HAVE_INT64_TIMESTAMP
year = reltime / SECS_PER_YEAR;
reltime -= year * SECS_PER_YEAR;
month = reltime / (DAYS_PER_MONTH * SECS_PER_DAY);
reltime -= day * SECS_PER_DAY;
result->time = (reltime * USECS_PER_SEC);
-#else
- TMODULO(reltime, year, SECS_PER_YEAR);
- TMODULO(reltime, month, DAYS_PER_MONTH * SECS_PER_DAY);
- TMODULO(reltime, day, SECS_PER_DAY);
-
- result->time = reltime;
-#endif
result->month = MONTHS_PER_YEAR * year + month;
result->day = day;
break;
Timestamp v2 = PG_GETARG_TIMESTAMP(1);
float8 result;
-#ifdef HAVE_INT64_TIMESTAMP
result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
-#else
- result = v1 - v2;
-#endif
-
PG_RETURN_FLOAT8(result);
}
Timestamp v2 = PG_GETARG_TIMESTAMP(1);
float8 result;
-#ifdef HAVE_INT64_TIMESTAMP
result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
-#else
- result = v1 - v2;
-#endif
-
PG_RETURN_FLOAT8(result);
}
* average month length of 365.25/12.0 days. Not too
* accurate, but plenty good enough for our purposes.
*/
-#ifdef HAVE_INT64_TIMESTAMP
return interval->time + interval->day * (double) USECS_PER_DAY +
interval->month * ((DAYS_PER_YEAR / (double) MONTHS_PER_YEAR) * USECS_PER_DAY);
-#else
- return interval->time + interval->day * SECS_PER_DAY +
- interval->month * ((DAYS_PER_YEAR / (double) MONTHS_PER_YEAR) * (double) SECS_PER_DAY);
-#endif
}
case RELTIMEOID:
-#ifdef HAVE_INT64_TIMESTAMP
return (DatumGetRelativeTime(value) * 1000000.0);
-#else
- return DatumGetRelativeTime(value);
-#endif
case TINTERVALOID:
{
TimeInterval tinterval = DatumGetTimeInterval(value);
-#ifdef HAVE_INT64_TIMESTAMP
if (tinterval->status != 0)
return ((tinterval->data[1] - tinterval->data[0]) * 1000000.0);
-#else
- if (tinterval->status != 0)
- return tinterval->data[1] - tinterval->data[0];
-#endif
return 0; /* for lack of a better idea */
}
case TIMEOID:
TimeTzADT *timetz = DatumGetTimeTzADTP(value);
/* use GMT-equivalent time */
-#ifdef HAVE_INT64_TIMESTAMP
return (double) (timetz->time + (timetz->zone * 1000000.0));
-#else
- return (double) (timetz->time + timetz->zone);
-#endif
}
}
/*
* timestamp_recv - converts external binary format to timestamp
- *
- * We make no attempt to provide compatibility between int and float
- * timestamp representations ...
*/
Datum
timestamp_recv(PG_FUNCTION_ARGS)
*tm = &tt;
fsec_t fsec;
-#ifdef HAVE_INT64_TIMESTAMP
timestamp = (Timestamp) pq_getmsgint64(buf);
-#else
- timestamp = (Timestamp) pq_getmsgfloat8(buf);
-
- if (isnan(timestamp))
- ereport(ERROR,
- (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
- errmsg("timestamp cannot be NaN")));
-#endif
/* range check: see if timestamp_out would like it */
if (TIMESTAMP_NOT_FINITE(timestamp))
StringInfoData buf;
pq_begintypsend(&buf);
-#ifdef HAVE_INT64_TIMESTAMP
pq_sendint64(&buf, timestamp);
-#else
- pq_sendfloat8(&buf, timestamp);
-#endif
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}
static void
AdjustTimestampForTypmod(Timestamp *time, int32 typmod)
{
-#ifdef HAVE_INT64_TIMESTAMP
static const int64 TimestampScales[MAX_TIMESTAMP_PRECISION + 1] = {
INT64CONST(1000000),
INT64CONST(100000),
INT64CONST(5),
INT64CONST(0)
};
-#else
- static const double TimestampScales[MAX_TIMESTAMP_PRECISION + 1] = {
- 1,
- 10,
- 100,
- 1000,
- 10000,
- 100000,
- 1000000
- };
-#endif
if (!TIMESTAMP_NOT_FINITE(*time)
&& (typmod != -1) && (typmod != MAX_TIMESTAMP_PRECISION))
errmsg("timestamp(%d) precision must be between %d and %d",
typmod, 0, MAX_TIMESTAMP_PRECISION)));
- /*
- * Note: this round-to-nearest code is not completely consistent about
- * rounding values that are exactly halfway between integral values.
- * On most platforms, rint() will implement round-to-nearest-even, but
- * the integer code always rounds up (away from zero). Is it worth
- * trying to be consistent?
- */
-#ifdef HAVE_INT64_TIMESTAMP
if (*time >= INT64CONST(0))
{
*time = ((*time + TimestampOffsets[typmod]) / TimestampScales[typmod]) *
*time = -((((-*time) + TimestampOffsets[typmod]) / TimestampScales[typmod])
* TimestampScales[typmod]);
}
-#else
- *time = rint((double) *time * TimestampScales[typmod]) / TimestampScales[typmod];
-#endif
}
}
hour, min, sec)));
/* This should match tm2time */
-#ifdef HAVE_INT64_TIMESTAMP
time = (((hour * MINS_PER_HOUR + min) * SECS_PER_MINUTE)
* USECS_PER_SEC) + rint(sec * USECS_PER_SEC);
errmsg("timestamp out of range: %d-%02d-%02d %d:%02d:%02g",
year, month, day,
hour, min, sec)));
-#else
- time = ((hour * MINS_PER_HOUR + min) * SECS_PER_MINUTE) + sec;
- result = date * SECS_PER_DAY + time;
-#endif
/* final range check catches just-out-of-range timestamps */
if (!IS_VALID_TIMESTAMP(result))
/* Convert UNIX epoch to Postgres epoch */
seconds -= ((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);
-#ifdef HAVE_INT64_TIMESTAMP
seconds = rint(seconds * USECS_PER_SEC);
result = (int64) seconds;
-#else
- result = seconds;
-#endif
/* Recheck in case roundoff produces something just out of range */
if (!IS_VALID_TIMESTAMP(result))
/*
* timestamptz_recv - converts external binary format to timestamptz
- *
- * We make no attempt to provide compatibility between int and float
- * timestamp representations ...
*/
Datum
timestamptz_recv(PG_FUNCTION_ARGS)
*tm = &tt;
fsec_t fsec;
-#ifdef HAVE_INT64_TIMESTAMP
timestamp = (TimestampTz) pq_getmsgint64(buf);
-#else
- timestamp = (TimestampTz) pq_getmsgfloat8(buf);
-#endif
/* range check: see if timestamptz_out would like it */
if (TIMESTAMP_NOT_FINITE(timestamp))
StringInfoData buf;
pq_begintypsend(&buf);
-#ifdef HAVE_INT64_TIMESTAMP
pq_sendint64(&buf, timestamp);
-#else
- pq_sendfloat8(&buf, timestamp);
-#endif
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}
interval = (Interval *) palloc(sizeof(Interval));
-#ifdef HAVE_INT64_TIMESTAMP
interval->time = pq_getmsgint64(buf);
-#else
- interval->time = pq_getmsgfloat8(buf);
-#endif
interval->day = pq_getmsgint(buf, sizeof(interval->day));
interval->month = pq_getmsgint(buf, sizeof(interval->month));
StringInfoData buf;
pq_begintypsend(&buf);
-#ifdef HAVE_INT64_TIMESTAMP
pq_sendint64(&buf, interval->time);
-#else
- pq_sendfloat8(&buf, interval->time);
-#endif
pq_sendint(&buf, interval->day, sizeof(interval->day));
pq_sendint(&buf, interval->month, sizeof(interval->month));
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
static void
AdjustIntervalForTypmod(Interval *interval, int32 typmod)
{
-#ifdef HAVE_INT64_TIMESTAMP
static const int64 IntervalScales[MAX_INTERVAL_PRECISION + 1] = {
INT64CONST(1000000),
INT64CONST(100000),
INT64CONST(5),
INT64CONST(0)
};
-#else
- static const double IntervalScales[MAX_INTERVAL_PRECISION + 1] = {
- 1,
- 10,
- 100,
- 1000,
- 10000,
- 100000,
- 1000000
- };
-#endif
/*
* Unspecified range and precision? Then not necessary to adjust. Setting
}
else if (range == INTERVAL_MASK(HOUR))
{
-#ifdef HAVE_INT64_TIMESTAMP
interval->time = (interval->time / USECS_PER_HOUR) *
USECS_PER_HOUR;
-#else
- interval->time = ((int) (interval->time / SECS_PER_HOUR)) * (double) SECS_PER_HOUR;
-#endif
}
else if (range == INTERVAL_MASK(MINUTE))
{
-#ifdef HAVE_INT64_TIMESTAMP
interval->time = (interval->time / USECS_PER_MINUTE) *
USECS_PER_MINUTE;
-#else
- interval->time = ((int) (interval->time / SECS_PER_MINUTE)) * (double) SECS_PER_MINUTE;
-#endif
}
else if (range == INTERVAL_MASK(SECOND))
{
else if (range == (INTERVAL_MASK(DAY) |
INTERVAL_MASK(HOUR)))
{
-#ifdef HAVE_INT64_TIMESTAMP
interval->time = (interval->time / USECS_PER_HOUR) *
USECS_PER_HOUR;
-#else
- interval->time = ((int) (interval->time / SECS_PER_HOUR)) * (double) SECS_PER_HOUR;
-#endif
}
/* DAY TO MINUTE */
else if (range == (INTERVAL_MASK(DAY) |
INTERVAL_MASK(HOUR) |
INTERVAL_MASK(MINUTE)))
{
-#ifdef HAVE_INT64_TIMESTAMP
interval->time = (interval->time / USECS_PER_MINUTE) *
USECS_PER_MINUTE;
-#else
- interval->time = ((int) (interval->time / SECS_PER_MINUTE)) * (double) SECS_PER_MINUTE;
-#endif
}
/* DAY TO SECOND */
else if (range == (INTERVAL_MASK(DAY) |
else if (range == (INTERVAL_MASK(HOUR) |
INTERVAL_MASK(MINUTE)))
{
-#ifdef HAVE_INT64_TIMESTAMP
interval->time = (interval->time / USECS_PER_MINUTE) *
USECS_PER_MINUTE;
-#else
- interval->time = ((int) (interval->time / SECS_PER_MINUTE)) * (double) SECS_PER_MINUTE;
-#endif
}
/* HOUR TO SECOND */
else if (range == (INTERVAL_MASK(HOUR) |
errmsg("interval(%d) precision must be between %d and %d",
precision, 0, MAX_INTERVAL_PRECISION)));
- /*
- * Note: this round-to-nearest code is not completely consistent
- * about rounding values that are exactly halfway between integral
- * values. On most platforms, rint() will implement
- * round-to-nearest-even, but the integer code always rounds up
- * (away from zero). Is it worth trying to be consistent?
- */
-#ifdef HAVE_INT64_TIMESTAMP
if (interval->time >= INT64CONST(0))
{
interval->time = ((interval->time +
IntervalScales[precision]) *
IntervalScales[precision]);
}
-#else
- interval->time = rint(((double) interval->time) *
- IntervalScales[precision]) /
- IntervalScales[precision];
-#endif
}
}
}
result->month = years * MONTHS_PER_YEAR + months;
result->day = weeks * 7 + days;
-#ifdef HAVE_INT64_TIMESTAMP
secs = rint(secs * USECS_PER_SEC);
result->time = hours * ((int64) SECS_PER_HOUR * USECS_PER_SEC) +
mins * ((int64) SECS_PER_MINUTE * USECS_PER_SEC) +
(int64) secs;
-#else
- result->time = hours * (double) SECS_PER_HOUR +
- mins * (double) SECS_PER_MINUTE +
- secs;
-#endif
PG_RETURN_INTERVAL_P(result);
}
result = (TimestampTz) tp.tv_sec -
((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);
-
-#ifdef HAVE_INT64_TIMESTAMP
- result = (result * USECS_PER_SEC) + tp.tv_usec;
-#else
- result = result + (tp.tv_usec / 1000000.0);
-#endif
-
- return result;
-}
-
-/*
- * GetCurrentIntegerTimestamp -- get the current operating system time as int64
- *
- * Result is the number of microseconds since the Postgres epoch. If compiled
- * with --enable-integer-datetimes, this is identical to GetCurrentTimestamp(),
- * and is implemented as a macro.
- */
-#ifndef HAVE_INT64_TIMESTAMP
-int64
-GetCurrentIntegerTimestamp(void)
-{
- int64 result;
- struct timeval tp;
-
- gettimeofday(&tp, NULL);
-
- result = (int64) tp.tv_sec -
- ((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);
-
result = (result * USECS_PER_SEC) + tp.tv_usec;
return result;
}
-#endif
-
-/*
- * IntegerTimestampToTimestampTz -- convert an int64 timestamp to native format
- *
- * When compiled with --enable-integer-datetimes, this is implemented as a
- * no-op macro.
- */
-#ifndef HAVE_INT64_TIMESTAMP
-TimestampTz
-IntegerTimestampToTimestampTz(int64 timestamp)
-{
- TimestampTz result;
-
- result = timestamp / USECS_PER_SEC;
- result += (timestamp % USECS_PER_SEC) / 1000000.0;
-
- return result;
-}
-#endif
/*
* GetSQLCurrentTimestamp -- implements CURRENT_TIMESTAMP, CURRENT_TIMESTAMP(n)
}
else
{
-#ifdef HAVE_INT64_TIMESTAMP
*secs = (long) (diff / USECS_PER_SEC);
*microsecs = (int) (diff % USECS_PER_SEC);
-#else
- *secs = (long) diff;
- *microsecs = (int) ((diff - *secs) * 1000000.0);
-#endif
}
}
{
TimestampTz diff = stop_time - start_time;
-#ifdef HAVE_INT64_TIMESTAMP
return (diff >= msec * INT64CONST(1000));
-#else
- return (diff * 1000.0 >= msec);
-#endif
}
/*
result = (TimestampTz) tm -
((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);
-
-#ifdef HAVE_INT64_TIMESTAMP
result *= USECS_PER_SEC;
-#endif
return result;
}
{
pg_time_t result;
-#ifdef HAVE_INT64_TIMESTAMP
result = (pg_time_t) (t / USECS_PER_SEC +
((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY));
-#else
- result = (pg_time_t) (t +
- ((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY));
-#endif
return result;
}
time = jd;
-#ifdef HAVE_INT64_TIMESTAMP
*hour = time / USECS_PER_HOUR;
time -= (*hour) * USECS_PER_HOUR;
*min = time / USECS_PER_MINUTE;
time -= (*min) * USECS_PER_MINUTE;
*sec = time / USECS_PER_SEC;
*fsec = time - (*sec * USECS_PER_SEC);
-#else
- *hour = time / SECS_PER_HOUR;
- time -= (*hour) * SECS_PER_HOUR;
- *min = time / SECS_PER_MINUTE;
- time -= (*min) * SECS_PER_MINUTE;
- *sec = time;
- *fsec = time - *sec;
-#endif
} /* dt2time() */
if (attimezone == NULL)
attimezone = session_timezone;
-#ifdef HAVE_INT64_TIMESTAMP
time = dt;
TMODULO(time, date, USECS_PER_DAY);
j2date((int) date, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
dt2time(time, &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
-#else
- time = dt;
- TMODULO(time, date, (double) SECS_PER_DAY);
-
- if (time < 0)
- {
- time += SECS_PER_DAY;
- date -= 1;
- }
-
- /* add offset to go from J2000 back to standard Julian date */
- date += POSTGRES_EPOCH_JDATE;
-
-recalc_d:
- /* Julian day routine does not work for negative Julian days */
- if (date < 0 || date > (Timestamp) INT_MAX)
- return -1;
-
- j2date((int) date, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
-recalc_t:
- dt2time(time, &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
-
- *fsec = TSROUND(*fsec);
- /* roundoff may need to propagate to higher-order fields */
- if (*fsec >= 1.0)
- {
- time = ceil(time);
- if (time >= (double) SECS_PER_DAY)
- {
- time = 0;
- date += 1;
- goto recalc_d;
- }
- goto recalc_t;
- }
-#endif
/* Done if no TZ conversion wanted */
if (tzp == NULL)
* coding avoids hardwiring any assumptions about the width of pg_time_t,
* so it should behave sanely on machines without int64.
*/
-#ifdef HAVE_INT64_TIMESTAMP
dt = (dt - *fsec) / USECS_PER_SEC +
(POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY;
-#else
- dt = rint(dt - *fsec +
- (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);
-#endif
utime = (pg_time_t) dt;
if ((Timestamp) utime == dt)
{
date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;
time = time2t(tm->tm_hour, tm->tm_min, tm->tm_sec, fsec);
-#ifdef HAVE_INT64_TIMESTAMP
*result = date * USECS_PER_DAY + time;
/* check for major overflow */
if ((*result - time) / USECS_PER_DAY != date)
*result = 0; /* keep compiler quiet */
return -1;
}
-#else
- *result = date * SECS_PER_DAY + time;
-#endif
if (tzp != NULL)
*result = dt2local(*result, -(*tzp));
tm->tm_mday = span.day;
time = span.time;
-#ifdef HAVE_INT64_TIMESTAMP
tfrac = time / USECS_PER_HOUR;
time -= tfrac * USECS_PER_HOUR;
tm->tm_hour = tfrac;
tfrac = time / USECS_PER_SEC;
*fsec = time - (tfrac * USECS_PER_SEC);
tm->tm_sec = tfrac;
-#else
-recalc:
- TMODULO(time, tfrac, (double) SECS_PER_HOUR);
- tm->tm_hour = tfrac; /* could overflow ... */
- TMODULO(time, tfrac, (double) SECS_PER_MINUTE);
- tm->tm_min = tfrac;
- TMODULO(time, tfrac, 1.0);
- tm->tm_sec = tfrac;
- time = TSROUND(time);
- /* roundoff may need to propagate to higher-order fields */
- if (time >= 1.0)
- {
- time = ceil(span.time);
- goto recalc;
- }
- *fsec = time;
-#endif
return 0;
}
return -1;
span->month = total_months;
span->day = tm->tm_mday;
-#ifdef HAVE_INT64_TIMESTAMP
span->time = (((((tm->tm_hour * INT64CONST(60)) +
tm->tm_min) * INT64CONST(60)) +
tm->tm_sec) * USECS_PER_SEC) + fsec;
-#else
- span->time = (((tm->tm_hour * (double) MINS_PER_HOUR) +
- tm->tm_min) * (double) SECS_PER_MINUTE) +
- tm->tm_sec + fsec;
-#endif
return 0;
}
static TimeOffset
time2t(const int hour, const int min, const int sec, const fsec_t fsec)
{
-#ifdef HAVE_INT64_TIMESTAMP
return (((((hour * MINS_PER_HOUR) + min) * SECS_PER_MINUTE) + sec) * USECS_PER_SEC) + fsec;
-#else
- return (((hour * MINS_PER_HOUR) + min) * SECS_PER_MINUTE) + sec + fsec;
-#endif
}
static Timestamp
dt2local(Timestamp dt, int tz)
{
-#ifdef HAVE_INT64_TIMESTAMP
dt -= (tz * USECS_PER_SEC);
-#else
- dt -= tz;
-#endif
return dt;
}
* The comparison functions are among them. - thomas 2001-09-25
*
* timestamp_relop - is timestamp1 relop timestamp2
- *
- * collate invalid timestamp at the end
*/
int
timestamp_cmp_internal(Timestamp dt1, Timestamp dt2)
{
-#ifdef HAVE_INT64_TIMESTAMP
return (dt1 < dt2) ? -1 : ((dt1 > dt2) ? 1 : 0);
-#else
-
- /*
- * When using float representation, we have to be wary of NaNs.
- *
- * We consider all NANs to be equal and larger than any non-NAN. This is
- * somewhat arbitrary; the important thing is to have a consistent sort
- * order.
- */
- if (isnan(dt1))
- {
- if (isnan(dt2))
- return 0; /* NAN = NAN */
- else
- return 1; /* NAN > non-NAN */
- }
- else if (isnan(dt2))
- {
- return -1; /* non-NAN < NAN */
- }
- else
- {
- if (dt1 > dt2)
- return 1;
- else if (dt1 < dt2)
- return -1;
- else
- return 0;
- }
-#endif
}
Datum
Datum
timestamp_hash(PG_FUNCTION_ARGS)
{
- /* We can use either hashint8 or hashfloat8 directly */
-#ifdef HAVE_INT64_TIMESTAMP
return hashint8(fcinfo);
-#else
- return hashfloat8(fcinfo);
-#endif
}
/*
* interval_relop - is interval1 relop interval2
- *
- * collate invalid interval at the end
*/
static inline TimeOffset
interval_cmp_value(const Interval *interval)
TimeOffset span;
span = interval->time;
-
-#ifdef HAVE_INT64_TIMESTAMP
span += interval->month * INT64CONST(30) * USECS_PER_DAY;
span += interval->day * INT64CONST(24) * USECS_PER_HOUR;
-#else
- span += interval->month * ((double) DAYS_PER_MONTH * SECS_PER_DAY);
- span += interval->day * ((double) HOURS_PER_DAY * SECS_PER_HOUR);
-#endif
return span;
}
*
* We must produce equal hashvals for values that interval_cmp_internal()
* considers equal. So, compute the net span the same way it does,
- * and then hash that, using either int64 or float8 hashing.
+ * and then hash that.
*/
Datum
interval_hash(PG_FUNCTION_ARGS)
Interval *interval = PG_GETARG_INTERVAL_P(0);
TimeOffset span = interval_cmp_value(interval);
-#ifdef HAVE_INT64_TIMESTAMP
return DirectFunctionCall1(hashint8, Int64GetDatumFast(span));
-#else
- return DirectFunctionCall1(hashfloat8, Float8GetDatumFast(span));
-#endif
}
/* overlaps_timestamp() --- implements the SQL OVERLAPS operator.
result->day = span->day;
result->time = span->time;
-#ifdef HAVE_INT64_TIMESTAMP
TMODULO(result->time, wholeday, USECS_PER_DAY);
-#else
- TMODULO(result->time, wholeday, (double) SECS_PER_DAY);
-#endif
result->day += wholeday; /* could overflow... */
wholemonth = result->day / DAYS_PER_MONTH;
if (result->day > 0 && result->time < 0)
{
-#ifdef HAVE_INT64_TIMESTAMP
result->time += USECS_PER_DAY;
-#else
- result->time += (double) SECS_PER_DAY;
-#endif
result->day--;
}
else if (result->day < 0 && result->time > 0)
{
-#ifdef HAVE_INT64_TIMESTAMP
result->time -= USECS_PER_DAY;
-#else
- result->time -= (double) SECS_PER_DAY;
-#endif
result->day++;
}
result->day = span->day;
result->time = span->time;
-#ifdef HAVE_INT64_TIMESTAMP
TMODULO(result->time, wholeday, USECS_PER_DAY);
-#else
- TMODULO(result->time, wholeday, (double) SECS_PER_DAY);
-#endif
result->day += wholeday; /* could overflow... */
if (result->day > 0 && result->time < 0)
{
-#ifdef HAVE_INT64_TIMESTAMP
result->time += USECS_PER_DAY;
-#else
- result->time += (double) SECS_PER_DAY;
-#endif
result->day--;
}
else if (result->day < 0 && result->time > 0)
{
-#ifdef HAVE_INT64_TIMESTAMP
result->time -= USECS_PER_DAY;
-#else
- result->time -= (double) SECS_PER_DAY;
-#endif
result->day++;
}
/* cascade units down */
result->day += (int32) month_remainder_days;
-#ifdef HAVE_INT64_TIMESTAMP
result_double = rint(span->time * factor + sec_remainder * USECS_PER_SEC);
if (result_double > PG_INT64_MAX || result_double < PG_INT64_MIN)
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("interval out of range")));
result->time = (int64) result_double;
-#else
- result->time = span->time * factor + sec_remainder;
-#endif
PG_RETURN_INTERVAL_P(result);
}
/* cascade units down */
result->day += (int32) month_remainder_days;
-#ifdef HAVE_INT64_TIMESTAMP
result->time = rint(span->time / factor + sec_remainder * USECS_PER_SEC);
-#else
- /* See TSROUND comment in interval_mul(). */
- result->time = span->time / factor + sec_remainder;
-#endif
PG_RETURN_INTERVAL_P(result);
}
* intervals, where the first is the running sum and the second contains
* the number of values so far in its 'time' field. This is a bit ugly
* but it beats inventing a specialized datatype for the purpose.
- *
- * NOTE: The inverse transition function cannot guarantee exact results
- * when using float8 timestamps. However, int8 timestamps are now the
- * norm, and the probable range of values is not so wide that disastrous
- * cancellation is likely even with float8, so we'll ignore the risk.
*/
Datum
/* propagate any negative fields into the next higher field */
while (fsec < 0)
{
-#ifdef HAVE_INT64_TIMESTAMP
fsec += USECS_PER_SEC;
-#else
- fsec += 1.0;
-#endif
tm->tm_sec--;
}
/* propagate any negative fields into the next higher field */
while (fsec < 0)
{
-#ifdef HAVE_INT64_TIMESTAMP
fsec += USECS_PER_SEC;
-#else
- fsec += 1.0;
-#endif
tm->tm_sec--;
}
break;
case DTK_MILLISEC:
-#ifdef HAVE_INT64_TIMESTAMP
fsec = (fsec / 1000) * 1000;
-#else
- fsec = floor(fsec * 1000) / 1000;
-#endif
break;
case DTK_MICROSEC:
-#ifndef HAVE_INT64_TIMESTAMP
- fsec = floor(fsec * 1000000) / 1000000;
-#endif
break;
default:
case DTK_SECOND:
fsec = 0;
break;
-
case DTK_MILLISEC:
-#ifdef HAVE_INT64_TIMESTAMP
fsec = (fsec / 1000) * 1000;
-#else
- fsec = floor(fsec * 1000) / 1000;
-#endif
break;
case DTK_MICROSEC:
-#ifndef HAVE_INT64_TIMESTAMP
- fsec = floor(fsec * 1000000) / 1000000;
-#endif
break;
default:
case DTK_SECOND:
fsec = 0;
break;
-
case DTK_MILLISEC:
-#ifdef HAVE_INT64_TIMESTAMP
fsec = (fsec / 1000) * 1000;
-#else
- fsec = floor(fsec * 1000) / 1000;
-#endif
break;
case DTK_MICROSEC:
-#ifndef HAVE_INT64_TIMESTAMP
- fsec = floor(fsec * 1000000) / 1000000;
-#endif
break;
default:
switch (val)
{
case DTK_MICROSEC:
-#ifdef HAVE_INT64_TIMESTAMP
result = tm->tm_sec * 1000000.0 + fsec;
-#else
- result = (tm->tm_sec + fsec) * 1000000;
-#endif
break;
case DTK_MILLISEC:
-#ifdef HAVE_INT64_TIMESTAMP
result = tm->tm_sec * 1000.0 + fsec / 1000.0;
-#else
- result = (tm->tm_sec + fsec) * 1000;
-#endif
break;
case DTK_SECOND:
-#ifdef HAVE_INT64_TIMESTAMP
result = tm->tm_sec + fsec / 1000000.0;
-#else
- result = tm->tm_sec + fsec;
-#endif
break;
case DTK_MINUTE:
case DTK_JULIAN:
result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
-#ifdef HAVE_INT64_TIMESTAMP
result += ((((tm->tm_hour * MINS_PER_HOUR) + tm->tm_min) * SECS_PER_MINUTE) +
tm->tm_sec + (fsec / 1000000.0)) / (double) SECS_PER_DAY;
-#else
- result += ((((tm->tm_hour * MINS_PER_HOUR) + tm->tm_min) * SECS_PER_MINUTE) +
- tm->tm_sec + fsec) / (double) SECS_PER_DAY;
-#endif
break;
case DTK_ISOYEAR:
{
case DTK_EPOCH:
epoch = SetEpochTimestamp();
-#ifdef HAVE_INT64_TIMESTAMP
/* try to avoid precision loss in subtraction */
if (timestamp < (PG_INT64_MAX + epoch))
result = (timestamp - epoch) / 1000000.0;
else
result = ((float8) timestamp - epoch) / 1000000.0;
-#else
- result = timestamp - epoch;
-#endif
break;
default:
break;
case DTK_MICROSEC:
-#ifdef HAVE_INT64_TIMESTAMP
result = tm->tm_sec * 1000000.0 + fsec;
-#else
- result = (tm->tm_sec + fsec) * 1000000;
-#endif
break;
case DTK_MILLISEC:
-#ifdef HAVE_INT64_TIMESTAMP
result = tm->tm_sec * 1000.0 + fsec / 1000.0;
-#else
- result = (tm->tm_sec + fsec) * 1000;
-#endif
break;
case DTK_SECOND:
-#ifdef HAVE_INT64_TIMESTAMP
result = tm->tm_sec + fsec / 1000000.0;
-#else
- result = tm->tm_sec + fsec;
-#endif
break;
case DTK_MINUTE:
case DTK_JULIAN:
result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
-#ifdef HAVE_INT64_TIMESTAMP
result += ((((tm->tm_hour * MINS_PER_HOUR) + tm->tm_min) * SECS_PER_MINUTE) +
tm->tm_sec + (fsec / 1000000.0)) / (double) SECS_PER_DAY;
-#else
- result += ((((tm->tm_hour * MINS_PER_HOUR) + tm->tm_min) * SECS_PER_MINUTE) +
- tm->tm_sec + fsec) / (double) SECS_PER_DAY;
-#endif
break;
case DTK_ISOYEAR:
{
case DTK_EPOCH:
epoch = SetEpochTimestamp();
-#ifdef HAVE_INT64_TIMESTAMP
/* try to avoid precision loss in subtraction */
if (timestamp < (PG_INT64_MAX + epoch))
result = (timestamp - epoch) / 1000000.0;
else
result = ((float8) timestamp - epoch) / 1000000.0;
-#else
- result = timestamp - epoch;
-#endif
break;
default:
switch (val)
{
case DTK_MICROSEC:
-#ifdef HAVE_INT64_TIMESTAMP
result = tm->tm_sec * 1000000.0 + fsec;
-#else
- result = (tm->tm_sec + fsec) * 1000000;
-#endif
break;
case DTK_MILLISEC:
-#ifdef HAVE_INT64_TIMESTAMP
result = tm->tm_sec * 1000.0 + fsec / 1000.0;
-#else
- result = (tm->tm_sec + fsec) * 1000;
-#endif
break;
case DTK_SECOND:
-#ifdef HAVE_INT64_TIMESTAMP
result = tm->tm_sec + fsec / 1000000.0;
-#else
- result = tm->tm_sec + fsec;
-#endif
break;
case DTK_MINUTE:
}
else if (type == RESERV && val == DTK_EPOCH)
{
-#ifdef HAVE_INT64_TIMESTAMP
result = interval->time / 1000000.0;
-#else
- result = interval->time;
-#endif
result += ((double) DAYS_PER_YEAR * SECS_PER_DAY) * (interval->month / MONTHS_PER_YEAR);
result += ((double) DAYS_PER_MONTH * SECS_PER_DAY) * (interval->month % MONTHS_PER_YEAR);
result += ((double) SECS_PER_DAY) * interval->day;
DatumGetCString(DirectFunctionCall1(interval_out,
PointerGetDatum(zone))))));
-#ifdef HAVE_INT64_TIMESTAMP
tz = zone->time / USECS_PER_SEC;
-#else
- tz = zone->time;
-#endif
result = dt2local(timestamp, tz);
DatumGetCString(DirectFunctionCall1(interval_out,
PointerGetDatum(zone))))));
-#ifdef HAVE_INT64_TIMESTAMP
tz = -(zone->time / USECS_PER_SEC);
-#else
- tz = -zone->time;
-#endif
result = dt2local(timestamp, tz);
GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
},
&integer_datetimes,
-#ifdef HAVE_INT64_TIMESTAMP
true,
-#else
- false,
-#endif
NULL, NULL, NULL
},
PQconninfoFree(conn_opts);
/*
- * Ensure we have the same value of integer timestamps as the server we
- * are connecting to.
+ * Ensure we have the same value of integer_datetimes (now always "on") as
+ * the server we are connecting to.
*/
tmpparam = PQparameterStatus(tmpconn, "integer_datetimes");
if (!tmpparam)
exit(1);
}
-#ifdef HAVE_INT64_TIMESTAMP
if (strcmp(tmpparam, "on") != 0)
-#else
- if (strcmp(tmpparam, "off") != 0)
-#endif
{
fprintf(stderr,
_("%s: integer_datetimes compile flag does not match server\n"),
{
pg_time_t result;
-#ifdef HAVE_INT64_TIMESTAMP
result = (pg_time_t) (t / USECS_PER_SEC +
((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY));
-#else
- result = (pg_time_t) (t +
- ((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY));
-#endif
return result;
}
strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S", ltime);
strftime(zone, sizeof(zone), "%Z", ltime);
-#ifdef HAVE_INT64_TIMESTAMP
sprintf(buf, "%s.%06d %s", ts, (int) (dt % USECS_PER_SEC), zone);
-#else
- sprintf(buf, "%s.%.6f %s", ts, fabs(dt - floor(dt)), zone);
-#endif
return buf;
}
* Note that Postgres uses "time interval" to mean a bounded interval,
* consisting of a beginning and ending time, not a time span - thomas 97/03/20
*
- * We have two implementations, one that uses int64 values with units of
- * microseconds, and one that uses double values with units of seconds.
+ * Timestamps, as well as the h/m/s fields of intervals, are stored as
+ * int64 values with units of microseconds. (Once upon a time they were
+ * double values with units of seconds.)
*
- * TimeOffset and fsec_t are convenience typedefs for temporary variables
- * that are of different types in the two cases. Do not use fsec_t in values
- * stored on-disk, since it is not the same size in both implementations.
+ * TimeOffset and fsec_t are convenience typedefs for temporary variables.
+ * Do not use fsec_t in values stored on-disk.
* Also, fsec_t is only meant for *fractional* seconds; beware of overflow
* if the value you need to store could be many seconds.
*/
-#ifdef HAVE_INT64_TIMESTAMP
-
typedef int64 Timestamp;
typedef int64 TimestampTz;
typedef int64 TimeOffset;
typedef int32 fsec_t; /* fractional seconds (in microseconds) */
-#else
-
-typedef double Timestamp;
-typedef double TimestampTz;
-typedef double TimeOffset;
-typedef double fsec_t; /* fractional seconds (in seconds) */
-#endif
typedef struct
{
} Interval;
+/* Limits on the "precision" option (typmod) for these data types */
#define MAX_TIMESTAMP_PRECISION 6
#define MAX_INTERVAL_PRECISION 6
/*
* DT_NOBEGIN represents timestamp -infinity; DT_NOEND represents +infinity
*/
-#ifdef HAVE_INT64_TIMESTAMP
#define DT_NOBEGIN PG_INT64_MIN
#define DT_NOEND PG_INT64_MAX
-#else /* !HAVE_INT64_TIMESTAMP */
-#ifdef HUGE_VAL
-#define DT_NOBEGIN (-HUGE_VAL)
-#define DT_NOEND (HUGE_VAL)
-#else
-#define DT_NOBEGIN (-DBL_MAX)
-#define DT_NOEND (DBL_MAX)
-#endif
-#endif /* HAVE_INT64_TIMESTAMP */
#define TIMESTAMP_NOBEGIN(j) \
do {(j) = DT_NOBEGIN;} while (0)
* so that is the lower bound for both dates and timestamps.
*
* The upper limit for dates is 5874897-12-31, which is a bit less than what
- * the Julian-date code can allow. We use that same limit for timestamps when
- * using floating-point timestamps (so that the timezone offset problem would
- * exist here too if there were no slop). For integer timestamps, the upper
- * limit is 294276-12-31. The int64 overflow limit would be a few days later;
- * again, leaving some slop avoids worries about corner-case overflow, and
- * provides a simpler user-visible definition.
+ * the Julian-date code can allow. For timestamps, the upper limit is
+ * 294276-12-31. The int64 overflow limit would be a few days later; again,
+ * leaving some slop avoids worries about corner-case overflow, and provides
+ * a simpler user-visible definition.
*/
/* First allowed date, and first disallowed date, in Julian-date form */
#define DATETIME_MIN_JULIAN (0)
#define DATE_END_JULIAN (2147483494) /* == date2j(JULIAN_MAXYEAR, 1, 1) */
-#ifdef HAVE_INT64_TIMESTAMP
#define TIMESTAMP_END_JULIAN (109203528) /* == date2j(294277, 1, 1) */
-#else
-#define TIMESTAMP_END_JULIAN DATE_END_JULIAN
-#endif
/* Timestamp limits */
-#ifdef HAVE_INT64_TIMESTAMP
#define MIN_TIMESTAMP INT64CONST(-211813488000000000)
/* == (DATETIME_MIN_JULIAN - POSTGRES_EPOCH_JDATE) * USECS_PER_DAY */
#define END_TIMESTAMP INT64CONST(9223371331200000000)
/* == (TIMESTAMP_END_JULIAN - POSTGRES_EPOCH_JDATE) * USECS_PER_DAY */
-#else
-#define MIN_TIMESTAMP (-211813488000.0)
-/* == (DATETIME_MIN_JULIAN - POSTGRES_EPOCH_JDATE) * SECS_PER_DAY */
-#define END_TIMESTAMP 185330760393600.0
-/* == (TIMESTAMP_END_JULIAN - POSTGRES_EPOCH_JDATE) * SECS_PER_DAY */
-#endif
/* Range-check a date (given in Postgres, not Julian, numbering) */
#define IS_VALID_DATE(d) \
typedef int32 DateADT;
-#ifdef HAVE_INT64_TIMESTAMP
typedef int64 TimeADT;
-#else
-typedef float8 TimeADT;
-#endif
typedef struct
{
/*
* Macros for fmgr-callable functions.
*
- * For TimeADT, we make use of the same support routines as for float8 or int64.
- * Therefore TimeADT is pass-by-reference if and only if float8 or int64 is!
+ * For TimeADT, we make use of the same support routines as for int64.
+ * Therefore TimeADT is pass-by-reference if and only if int64 is!
*/
-#ifdef HAVE_INT64_TIMESTAMP
-
#define MAX_TIME_PRECISION 6
#define DatumGetDateADT(X) ((DateADT) DatumGetInt32(X))
#define DateADTGetDatum(X) Int32GetDatum(X)
#define TimeADTGetDatum(X) Int64GetDatum(X)
#define TimeTzADTPGetDatum(X) PointerGetDatum(X)
-#else /* !HAVE_INT64_TIMESTAMP */
-
-#define MAX_TIME_PRECISION 10
-
-/* round off to MAX_TIME_PRECISION decimal places */
-#define TIME_PREC_INV 10000000000.0
-#define TIMEROUND(j) (rint(((double) (j)) * TIME_PREC_INV) / TIME_PREC_INV)
-
-#define DatumGetDateADT(X) ((DateADT) DatumGetInt32(X))
-#define DatumGetTimeADT(X) ((TimeADT) DatumGetFloat8(X))
-#define DatumGetTimeTzADTP(X) ((TimeTzADT *) DatumGetPointer(X))
-
-#define DateADTGetDatum(X) Int32GetDatum(X)
-#define TimeADTGetDatum(X) Float8GetDatum(X)
-#define TimeTzADTPGetDatum(X) PointerGetDatum(X)
-#endif /* HAVE_INT64_TIMESTAMP */
#define PG_GETARG_DATEADT(n) DatumGetDateADT(PG_GETARG_DATUM(n))
#define PG_GETARG_TIMEADT(n) DatumGetTimeADT(PG_GETARG_DATUM(n))
} while(0)
/* TMODULO()
- * Like FMODULO(), but work on the timestamp datatype (either int64 or float8).
+ * Like FMODULO(), but work on the timestamp datatype (now always int64).
* We assume that int64 follows the C99 semantics for division (negative
* quotients truncate towards zero).
*/
-#ifdef HAVE_INT64_TIMESTAMP
#define TMODULO(t,q,u) \
do { \
(q) = ((t) / (u)); \
if ((q) != 0) (t) -= ((q) * (u)); \
} while(0)
-#else
-#define TMODULO(t,q,u) \
-do { \
- (q) = (((t) < 0) ? ceil((t) / (u)) : floor((t) / (u))); \
- if ((q) != 0) (t) -= rint((q) * (u)); \
-} while(0)
-#endif
/*
* Date/time validation
/*
* Macros for fmgr-callable functions.
*
- * For Timestamp, we make use of the same support routines as for int64
- * or float8. Therefore Timestamp is pass-by-reference if and only if
- * int64 or float8 is!
+ * For Timestamp, we make use of the same support routines as for int64.
+ * Therefore Timestamp is pass-by-reference if and only if int64 is!
*/
-#ifdef HAVE_INT64_TIMESTAMP
-
#define DatumGetTimestamp(X) ((Timestamp) DatumGetInt64(X))
#define DatumGetTimestampTz(X) ((TimestampTz) DatumGetInt64(X))
#define DatumGetIntervalP(X) ((Interval *) DatumGetPointer(X))
#define PG_RETURN_TIMESTAMP(x) return TimestampGetDatum(x)
#define PG_RETURN_TIMESTAMPTZ(x) return TimestampTzGetDatum(x)
#define PG_RETURN_INTERVAL_P(x) return IntervalPGetDatum(x)
-#else /* !HAVE_INT64_TIMESTAMP */
-
-#define DatumGetTimestamp(X) ((Timestamp) DatumGetFloat8(X))
-#define DatumGetTimestampTz(X) ((TimestampTz) DatumGetFloat8(X))
-#define DatumGetIntervalP(X) ((Interval *) DatumGetPointer(X))
-
-#define TimestampGetDatum(X) Float8GetDatum(X)
-#define TimestampTzGetDatum(X) Float8GetDatum(X)
-#define IntervalPGetDatum(X) PointerGetDatum(X)
-
-#define PG_GETARG_TIMESTAMP(n) DatumGetTimestamp(PG_GETARG_DATUM(n))
-#define PG_GETARG_TIMESTAMPTZ(n) DatumGetTimestampTz(PG_GETARG_DATUM(n))
-#define PG_GETARG_INTERVAL_P(n) DatumGetIntervalP(PG_GETARG_DATUM(n))
-
-#define PG_RETURN_TIMESTAMP(x) return TimestampGetDatum(x)
-#define PG_RETURN_TIMESTAMPTZ(x) return TimestampTzGetDatum(x)
-#define PG_RETURN_INTERVAL_P(x) return IntervalPGetDatum(x)
-#endif /* HAVE_INT64_TIMESTAMP */
#define TIMESTAMP_MASK(b) (1 << (b))
#define INTERVAL_PRECISION(t) ((t) & INTERVAL_PRECISION_MASK)
#define INTERVAL_RANGE(t) (((t) >> 16) & INTERVAL_RANGE_MASK)
-#ifdef HAVE_INT64_TIMESTAMP
#define TimestampTzPlusMilliseconds(tz,ms) ((tz) + ((ms) * (int64) 1000))
-#else
-#define TimestampTzPlusMilliseconds(tz,ms) ((tz) + ((ms) / 1000.0))
-#endif
/* Set at postmaster start */
* Prototypes for functions to deal with integer timestamps, when the native
* format is float timestamps.
*/
-#ifndef HAVE_INT64_TIMESTAMP
-extern int64 GetCurrentIntegerTimestamp(void);
-extern TimestampTz IntegerTimestampToTimestampTz(int64 timestamp);
-#else
#define GetCurrentIntegerTimestamp() GetCurrentTimestamp()
#define IntegerTimestampToTimestampTz(timestamp) (timestamp)
-#endif
extern TimestampTz time_t_to_timestamptz(pg_time_t tm);
extern pg_time_t timestamptz_to_time_t(TimestampTz t);
typedef struct
{
-#ifdef HAVE_INT64_TIMESTAMP
int64 time; /* all time units other than months and years */
-#else
- double time; /* all time units other than months and years */
-#endif
long month; /* months and years, after time for alignment */
} interval;
/* pgtypes_interval.h includes ecpg_config.h */
#include <pgtypes_interval.h>
-#ifdef HAVE_INT64_TIMESTAMP
typedef int64 timestamp;
typedef int64 TimestampTz;
-#else
-typedef double timestamp;
-typedef double TimestampTz;
-#endif
#ifdef __cplusplus
extern "C"
if (!TIMESTAMP_NOT_FINITE(dt))
{
-#ifdef HAVE_INT64_TIMESTAMP
/* Microseconds to days */
dDate = (dt / USECS_PER_DAY);
-#else
- /* Seconds to days */
- dDate = (dt / (double) SECS_PER_DAY);
-#endif
}
return dDate;
#define MAXTZLEN 10
-#ifdef HAVE_INT64_TIMESTAMP
-
typedef int32 fsec_t;
-#else
-
-typedef double fsec_t;
-
-/* round off to MAX_TIMESTAMP_PRECISION decimal places */
-/* note: this is also used for rounding off intervals */
-#define TS_PREC_INV 1000000.0
-#define TSROUND(j) (rint(((double) (j)) * TS_PREC_INV) / TS_PREC_INV)
-#endif
#define USE_POSTGRES_DATES 0
#define USE_ISO_DATES 1
} while(0)
/* TMODULO()
- * Like FMODULO(), but work on the timestamp datatype (either int64 or float8).
+ * Like FMODULO(), but work on the timestamp datatype (now always int64).
* We assume that int64 follows the C99 semantics for division (negative
* quotients truncate towards zero).
*/
-#ifdef HAVE_INT64_TIMESTAMP
#define TMODULO(t,q,u) \
do { \
(q) = ((t) / (u)); \
if ((q) != 0) (t) -= ((q) * (u)); \
} while(0)
-#else
-#define TMODULO(t,q,u) \
-do { \
- (q) = (((t) < 0) ? ceil((t) / (u)): floor((t) / (u))); \
- if ((q) != 0) (t) -= rint((q) * (u)); \
-} while(0)
-#endif
/* in both timestamp.h and ecpg/dt.h */
#define DAYS_PER_YEAR 365.25 /* assumes leap year every four years */
#define SECS_PER_MINUTE 60
#define MINS_PER_HOUR 60
-#ifdef HAVE_INT64_TIMESTAMP
#define USECS_PER_DAY INT64CONST(86400000000)
#define USECS_PER_HOUR INT64CONST(3600000000)
#define USECS_PER_MINUTE INT64CONST(60000000)
#define USECS_PER_SEC INT64CONST(1000000)
-#endif
/*
* Date/time validation
((y) < JULIAN_MAXYEAR || \
((y) == JULIAN_MAXYEAR && ((m) < JULIAN_MAXMONTH))))
-#ifdef HAVE_INT64_TIMESTAMP
#define MIN_TIMESTAMP INT64CONST(-211813488000000000)
#define END_TIMESTAMP INT64CONST(9223371331200000000)
-#else
-#define MIN_TIMESTAMP (-211813488000.0)
-#define END_TIMESTAMP 185330760393600.0
-#endif
#define IS_VALID_TIMESTAMP(t) (MIN_TIMESTAMP <= (t) && (t) < END_TIMESTAMP)
|| (((y) == UTIME_MAXYEAR) && (((m) < UTIME_MAXMONTH) \
|| (((m) == UTIME_MAXMONTH) && ((d) <= UTIME_MAXDAY))))))
-#ifdef HAVE_INT64_TIMESTAMP
-
#define DT_NOBEGIN (-INT64CONST(0x7fffffffffffffff) - 1)
#define DT_NOEND (INT64CONST(0x7fffffffffffffff))
-#else
-
-#ifdef HUGE_VAL
-#define DT_NOBEGIN (-HUGE_VAL)
-#define DT_NOEND (HUGE_VAL)
-#else
-#define DT_NOBEGIN (-DBL_MAX)
-#define DT_NOEND (DBL_MAX)
-#endif
-#endif /* HAVE_INT64_TIMESTAMP */
#define TIMESTAMP_NOBEGIN(j) do {(j) = DT_NOBEGIN;} while (0)
#define TIMESTAMP_NOEND(j) do {(j) = DT_NOEND;} while (0)
/*
* Print fractional seconds if any. The field widths here should
* be at least equal to MAX_TIMESTAMP_PRECISION.
- *
- * In float mode, don't print fractional seconds before 1 AD,
- * since it's unlikely there's any precision left ...
*/
-#ifdef HAVE_INT64_TIMESTAMP
if (fsec != 0)
{
sprintf(str + strlen(str), ":%02d.%06d", tm->tm_sec, fsec);
-#else
- if ((fsec != 0) && (tm->tm_year > 0))
- {
- sprintf(str + strlen(str), ":%09.6f", tm->tm_sec + fsec);
-#endif
TrimTrailingZeros(str);
}
else
/*
* Print fractional seconds if any. The field widths here should
* be at least equal to MAX_TIMESTAMP_PRECISION.
- *
- * In float mode, don't print fractional seconds before 1 AD,
- * since it's unlikely there's any precision left ...
*/
-#ifdef HAVE_INT64_TIMESTAMP
if (fsec != 0)
{
sprintf(str + strlen(str), ":%02d.%06d", tm->tm_sec, fsec);
-#else
- if (fsec != 0 && tm->tm_year > 0)
- {
- sprintf(str + strlen(str), ":%09.6f", tm->tm_sec + fsec);
-#endif
TrimTrailingZeros(str);
}
else
/*
* Print fractional seconds if any. The field widths here should
* be at least equal to MAX_TIMESTAMP_PRECISION.
- *
- * In float mode, don't print fractional seconds before 1 AD,
- * since it's unlikely there's any precision left ...
*/
-#ifdef HAVE_INT64_TIMESTAMP
if (fsec != 0)
{
sprintf(str + strlen(str), ":%02d.%06d", tm->tm_sec, fsec);
-#else
- if (fsec != 0 && tm->tm_year > 0)
- {
- sprintf(str + strlen(str), ":%09.6f", tm->tm_sec + fsec);
-#endif
TrimTrailingZeros(str);
}
else
/*
* Print fractional seconds if any. The field widths here should
* be at least equal to MAX_TIMESTAMP_PRECISION.
- *
- * In float mode, don't print fractional seconds before 1 AD,
- * since it's unlikely there's any precision left ...
*/
-#ifdef HAVE_INT64_TIMESTAMP
if (fsec != 0)
{
sprintf(str + strlen(str), ":%02d.%06d", tm->tm_sec, fsec);
-#else
- if (fsec != 0 && tm->tm_year > 0)
- {
- sprintf(str + strlen(str), ":%09.6f", tm->tm_sec + fsec);
-#endif
TrimTrailingZeros(str);
}
else
void
dt2time(double jd, int *hour, int *min, int *sec, fsec_t *fsec)
{
-#ifdef HAVE_INT64_TIMESTAMP
int64 time;
-#else
- double time;
-#endif
time = jd;
-#ifdef HAVE_INT64_TIMESTAMP
*hour = time / USECS_PER_HOUR;
time -= (*hour) * USECS_PER_HOUR;
*min = time / USECS_PER_MINUTE;
time -= (*min) * USECS_PER_MINUTE;
*sec = time / USECS_PER_SEC;
*fsec = time - (*sec * USECS_PER_SEC);
-#else
- *hour = time / SECS_PER_HOUR;
- time -= (*hour) * SECS_PER_HOUR;
- *min = time / SECS_PER_MINUTE;
- time -= (*min) * SECS_PER_MINUTE;
- *sec = time;
- *fsec = time - *sec;
-#endif
} /* dt2time() */
*/
if ((cp = strchr(str, '.')) != NULL)
{
-#ifdef HAVE_INT64_TIMESTAMP
char fstr[7];
int i;
* string with those digits, zero-padded on the right, and then do the
* conversion to an integer.
*
- * XXX This truncates the seventh digit, unlike rounding it as do the
- * backend and the !HAVE_INT64_TIMESTAMP case.
+ * XXX This truncates the seventh digit, unlike rounding it as the
+ * backend does.
*/
for (i = 0; i < 6; i++)
fstr[i] = *cp != '\0' ? *cp++ : '0';
fstr[i] = '\0';
*fsec = strtol(fstr, NULL, 10);
-#else
- *fsec = strtod(cp, NULL);
-#endif
*cp = '\0';
len = strlen(str);
}
*fsec = 0;
else if (*cp == '.')
{
-#ifdef HAVE_INT64_TIMESTAMP
char fstr[7];
int i;
* string with those digits, zero-padded on the right, and then do
* the conversion to an integer.
*
- * XXX This truncates the seventh digit, unlike rounding it as do
- * the backend and the !HAVE_INT64_TIMESTAMP case.
+ * XXX This truncates the seventh digit, unlike rounding it as the
+ * backend does.
*/
for (i = 0; i < 6; i++)
fstr[i] = *cp != '\0' ? *cp++ : '0';
fstr[i] = '\0';
*fsec = strtol(fstr, &cp, 10);
-#else
- str = cp;
- *fsec = strtod(str, &cp);
-#endif
if (*cp != '\0')
return -1;
}
}
/* do a sanity check */
-#ifdef HAVE_INT64_TIMESTAMP
if (tm->tm_hour < 0 || tm->tm_min < 0 || tm->tm_min > 59 ||
tm->tm_sec < 0 || tm->tm_sec > 59 || *fsec >= USECS_PER_SEC)
return -1;
-#else
- if (tm->tm_hour < 0 || tm->tm_min < 0 || tm->tm_min > 59 ||
- tm->tm_sec < 0 || tm->tm_sec > 59 || *fsec >= 1)
- return -1;
-#endif
return 0;
} /* DecodeTime() */
frac = strtod(cp, &cp);
if (*cp != '\0')
return -1;
-#ifdef HAVE_INT64_TIMESTAMP
*fsec = frac * 1000000;
-#else
- *fsec = frac;
-#endif
}
break;
return -1;
tmask |= DTK_TIME_M;
-#ifdef HAVE_INT64_TIMESTAMP
dt2time((time * USECS_PER_DAY), &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
-#else
- dt2time((time * SECS_PER_DAY), &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
-#endif
}
break;
sec = (int) frac;
tm->tm_sec += sec;
frac -= sec;
-#ifdef HAVE_INT64_TIMESTAMP
*fsec += rint(frac * 1000000);
-#else
- *fsec += frac;
-#endif
}
switch (type)
{
case DTK_MICROSEC:
-#ifdef HAVE_INT64_TIMESTAMP
*fsec += rint(val + fval);
-#else
- *fsec += (val + fval) * 1e-6;
-#endif
tmask = DTK_M(MICROSECOND);
break;
case DTK_MILLISEC:
-#ifdef HAVE_INT64_TIMESTAMP
*fsec += rint((val + fval) * 1000);
-#else
- *fsec += (val + fval) * 1e-3;
-#endif
tmask = DTK_M(MILLISECOND);
break;
case DTK_SECOND:
tm->tm_sec += val;
-#ifdef HAVE_INT64_TIMESTAMP
*fsec += rint(fval * 1000000);
-#else
- *fsec += fval;
-#endif
/*
* If any subseconds were specified, consider this
{
int sec;
-#ifdef HAVE_INT64_TIMESTAMP
sec = *fsec / USECS_PER_SEC;
*fsec -= sec * USECS_PER_SEC;
-#else
- TMODULO(*fsec, sec, 1.0);
-#endif
tm->tm_sec += sec;
}
}
else
{
-#ifdef HAVE_INT64_TIMESTAMP
if (fillzeros)
sprintf(cp, "%02d.%0*d", abs(sec), precision, (int) Abs(fsec));
else
sprintf(cp, "%d.%0*d", abs(sec), precision, (int) Abs(fsec));
-#else
- if (fillzeros)
- sprintf(cp, "%0*.*f", precision + 3, precision, fabs(sec + fsec));
- else
- sprintf(cp, "%.*f", precision, fabs(sec + fsec));
-#endif
TrimTrailingZeros(cp);
}
}
static int
interval2tm(interval span, struct tm * tm, fsec_t *fsec)
{
-#ifdef HAVE_INT64_TIMESTAMP
int64 time;
-#else
- double time;
-#endif
if (span.month != 0)
{
time = span.time;
-#ifdef HAVE_INT64_TIMESTAMP
tm->tm_mday = time / USECS_PER_DAY;
time -= tm->tm_mday * USECS_PER_DAY;
tm->tm_hour = time / USECS_PER_HOUR;
time -= tm->tm_min * USECS_PER_MINUTE;
tm->tm_sec = time / USECS_PER_SEC;
*fsec = time - (tm->tm_sec * USECS_PER_SEC);
-#else
-recalc:
- TMODULO(time, tm->tm_mday, (double) SECS_PER_DAY);
- TMODULO(time, tm->tm_hour, (double) SECS_PER_HOUR);
- TMODULO(time, tm->tm_min, (double) SECS_PER_MINUTE);
- TMODULO(time, tm->tm_sec, 1.0);
- time = TSROUND(time);
- /* roundoff may need to propagate to higher-order fields */
- if (time >= 1.0)
- {
- time = ceil(span.time);
- goto recalc;
- }
- *fsec = time;
-#endif
return 0;
} /* interval2tm() */
(double) tm->tm_year * MONTHS_PER_YEAR + tm->tm_mon < INT_MIN)
return -1;
span->month = tm->tm_year * MONTHS_PER_YEAR + tm->tm_mon;
-#ifdef HAVE_INT64_TIMESTAMP
span->time = (((((((tm->tm_mday * INT64CONST(24)) +
tm->tm_hour) * INT64CONST(60)) +
tm->tm_min) * INT64CONST(60)) +
tm->tm_sec) * USECS_PER_SEC) + fsec;
-#else
- span->time = (((((tm->tm_mday * (double) HOURS_PER_DAY) +
- tm->tm_hour) * (double) MINS_PER_HOUR) +
- tm->tm_min) * (double) SECS_PER_MINUTE) +
- tm->tm_sec + fsec;
-#endif
return 0;
} /* tm2interval() */
#include "pgtypes_date.h"
-#ifdef HAVE_INT64_TIMESTAMP
static int64
time2t(const int hour, const int min, const int sec, const fsec_t fsec)
{
return (((((hour * MINS_PER_HOUR) + min) * SECS_PER_MINUTE) + sec) * USECS_PER_SEC) + fsec;
} /* time2t() */
-#else
-static double
-time2t(const int hour, const int min, const int sec, const fsec_t fsec)
-{
- return (((hour * MINS_PER_HOUR) + min) * SECS_PER_MINUTE) + sec + fsec;
-} /* time2t() */
-#endif
static timestamp
dt2local(timestamp dt, int tz)
{
-#ifdef HAVE_INT64_TIMESTAMP
dt -= (tz * USECS_PER_SEC);
-#else
- dt -= tz;
-#endif
return dt;
} /* dt2local() */
int
tm2timestamp(struct tm * tm, fsec_t fsec, int *tzp, timestamp * result)
{
-#ifdef HAVE_INT64_TIMESTAMP
int dDate;
int64 time;
-#else
- double dDate,
- time;
-#endif
/* Prevent overflow in Julian-day routines */
if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday))
dDate = 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);
-#ifdef HAVE_INT64_TIMESTAMP
*result = (dDate * USECS_PER_DAY) + time;
/* check for major overflow */
if ((*result - time) / USECS_PER_DAY != dDate)
if ((*result < 0 && dDate > 0) ||
(*result > 0 && dDate < -1))
return -1;
-#else
- *result = dDate * SECS_PER_DAY + time;
-#endif
if (tzp != NULL)
*result = dt2local(*result, -(*tzp));
static timestamp
SetEpochTimestamp(void)
{
-#ifdef HAVE_INT64_TIMESTAMP
int64 noresult = 0;
-#else
- double noresult = 0.0;
-#endif
timestamp dt;
struct tm tt,
*tm = &tt;
static int
timestamp2tm(timestamp dt, int *tzp, struct tm * tm, fsec_t *fsec, const char **tzn)
{
-#ifdef HAVE_INT64_TIMESTAMP
int64 dDate,
date0;
int64 time;
-#else
- double dDate,
- date0;
- double time;
-#endif
#if defined(HAVE_TM_ZONE) || defined(HAVE_INT_TIMEZONE)
time_t utime;
struct tm *tx;
date0 = date2j(2000, 1, 1);
-#ifdef HAVE_INT64_TIMESTAMP
time = dt;
TMODULO(time, dDate, USECS_PER_DAY);
j2date((int) dDate, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
dt2time(time, &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
-#else
- time = dt;
- TMODULO(time, dDate, (double) SECS_PER_DAY);
-
- if (time < 0)
- {
- time += SECS_PER_DAY;
- dDate -= 1;
- }
-
- /* add offset to go from J2000 back to standard Julian date */
- dDate += date0;
-
-recalc_d:
- /* Julian day routine does not work for negative Julian days */
- if (dDate < 0 || dDate > (timestamp) INT_MAX)
- return -1;
-
- j2date((int) dDate, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
-recalc_t:
- dt2time(time, &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
-
- *fsec = TSROUND(*fsec);
- /* roundoff may need to propagate to higher-order fields */
- if (*fsec >= 1.0)
- {
- time = ceil(time);
- if (time >= (double) SECS_PER_DAY)
- {
- time = 0;
- dDate += 1;
- goto recalc_d;
- }
- goto recalc_t;
- }
-#endif
if (tzp != NULL)
{
{
#if defined(HAVE_TM_ZONE) || defined(HAVE_INT_TIMEZONE)
-#ifdef HAVE_INT64_TIMESTAMP
utime = dt / USECS_PER_SEC +
((date0 - date2j(1970, 1, 1)) * INT64CONST(86400));
-#else
- utime = dt + (date0 - date2j(1970, 1, 1)) * SECS_PER_DAY;
-#endif
tx = localtime(&utime);
tm->tm_year = tx->tm_year + 1900;
PGTYPEStimestamp_from_asc(char *str, char **endptr)
{
timestamp result;
-
-#ifdef HAVE_INT64_TIMESTAMP
int64 noresult = 0;
-#else
- double noresult = 0.0;
-#endif
fsec_t fsec;
struct tm tt,
*tm = &tt;
break;
/* The number of seconds since the Epoch (1970-01-01) */
case 's':
-#ifdef HAVE_INT64_TIMESTAMP
replace_val.int64_val = (*ts - SetEpochTimestamp()) / 1000000.0;
replace_type = PGTYPES_TYPE_INT64;
-#else
- replace_val.double_val = *ts - SetEpochTimestamp();
- replace_type = PGTYPES_TYPE_DOUBLE_NF;
-#endif
break;
/* seconds as a decimal number with leading zeroes */
case 'S':