diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2000-06-09 01:11:16 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2000-06-09 01:11:16 +0000 |
commit | ae526b407039dd743eb318a9f05eba1ee7594738 (patch) | |
tree | 2858f9b0426a2054b81350e36562ea9d2ba0ab39 /src/backend/utils/adt/timestamp.c | |
parent | 20ad43b576d9360b0e9ce9bd868c989443cf9d36 (diff) |
Another round of updates for new fmgr, mostly in the datetime code.
Diffstat (limited to 'src/backend/utils/adt/timestamp.c')
-rw-r--r-- | src/backend/utils/adt/timestamp.c | 1039 |
1 files changed, 450 insertions, 589 deletions
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index a2d8faf05bf..7715942a28a 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.28 2000/06/08 22:37:28 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.29 2000/06/09 01:11:09 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -49,11 +49,11 @@ static int tm2interval(struct tm * tm, double fsec, Interval *span); /* timestamp_in() * Convert a string to internal form. */ -Timestamp * -timestamp_in(char *str) +Datum +timestamp_in(PG_FUNCTION_ARGS) { - Timestamp *result; - + char *str = PG_GETARG_CSTRING(0); + Timestamp result; double fsec; struct tm tt, *tm = &tt; @@ -64,55 +64,52 @@ timestamp_in(char *str) int ftype[MAXDATEFIELDS]; char lowstr[MAXDATELEN + 1]; - if (!PointerIsValid(str)) - elog(ERROR, "Bad (null) timestamp external representation"); - if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) || (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz) != 0)) elog(ERROR, "Bad timestamp external representation '%s'", str); - result = palloc(sizeof(Timestamp)); - switch (dtype) { case DTK_DATE: - if (tm2timestamp(tm, fsec, &tz, result) != 0) + if (tm2timestamp(tm, fsec, &tz, &result) != 0) elog(ERROR, "Timestamp out of range '%s'", str); break; case DTK_EPOCH: - TIMESTAMP_EPOCH(*result); + TIMESTAMP_EPOCH(result); break; case DTK_CURRENT: - TIMESTAMP_CURRENT(*result); + TIMESTAMP_CURRENT(result); break; case DTK_LATE: - TIMESTAMP_NOEND(*result); + TIMESTAMP_NOEND(result); break; case DTK_EARLY: - TIMESTAMP_NOBEGIN(*result); + TIMESTAMP_NOBEGIN(result); break; case DTK_INVALID: - TIMESTAMP_INVALID(*result); + TIMESTAMP_INVALID(result); break; default: elog(ERROR, "Internal coding error, can't input timestamp '%s'", str); + TIMESTAMP_INVALID(result); /* keep compiler quiet */ } - return result; -} /* timestamp_in() */ + PG_RETURN_TIMESTAMP(result); +} /* timestamp_out() * Convert a timestamp to external form. */ -char * -timestamp_out(Timestamp *dt) +Datum +timestamp_out(PG_FUNCTION_ARGS) { + Timestamp dt = PG_GETARG_TIMESTAMP(0); char *result; int tz; struct tm tt, @@ -121,22 +118,16 @@ timestamp_out(Timestamp *dt) char *tzn; char buf[MAXDATELEN + 1]; - if (!PointerIsValid(dt)) - return NULL; - - if (TIMESTAMP_IS_RESERVED(*dt)) - EncodeSpecialTimestamp(*dt, buf); - else if (timestamp2tm(*dt, &tz, tm, &fsec, &tzn) == 0) + if (TIMESTAMP_IS_RESERVED(dt)) + EncodeSpecialTimestamp(dt, buf); + else if (timestamp2tm(dt, &tz, tm, &fsec, &tzn) == 0) EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf); else EncodeSpecialTimestamp(DT_INVALID, buf); - result = palloc(strlen(buf) + 1); - - strcpy(result, buf); - - return result; -} /* timestamp_out() */ + result = pstrdup(buf); + PG_RETURN_CSTRING(result); +} /* interval_in() @@ -145,11 +136,11 @@ timestamp_out(Timestamp *dt) * External format(s): * Uses the generic date/time parsing and decoding routines. */ -Interval * -interval_in(char *str) +Datum +interval_in(PG_FUNCTION_ARGS) { + char *str = PG_GETARG_CSTRING(0); Interval *span; - double fsec; struct tm tt, *tm = &tt; @@ -167,14 +158,11 @@ interval_in(char *str) tm->tm_sec = 0; fsec = 0; - if (!PointerIsValid(str)) - elog(ERROR, "Bad (null) interval external representation"); - if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) || (DecodeDateDelta(field, ftype, nf, &dtype, tm, &fsec) != 0)) elog(ERROR, "Bad interval external representation '%s'", str); - span = palloc(sizeof(Interval)); + span = (Interval *) palloc(sizeof(Interval)); switch (dtype) { @@ -192,36 +180,31 @@ interval_in(char *str) elog(ERROR, "Internal coding error, can't input interval '%s'", str); } - return span; -} /* interval_in() */ + PG_RETURN_INTERVAL_P(span); +} /* interval_out() * Convert a time span to external form. */ -char * -interval_out(Interval *span) +Datum +interval_out(PG_FUNCTION_ARGS) { + Interval *span = PG_GETARG_INTERVAL_P(0); char *result; - struct tm tt, *tm = &tt; double fsec; char buf[MAXDATELEN + 1]; - if (!PointerIsValid(span)) - return NULL; - if (interval2tm(*span, tm, &fsec) != 0) - return NULL; + PG_RETURN_NULL(); if (EncodeTimeSpan(tm, fsec, DateStyle, buf) != 0) elog(ERROR, "Unable to format interval"); - result = palloc(strlen(buf) + 1); - - strcpy(result, buf); - return result; -} /* interval_out() */ + result = pstrdup(buf); + PG_RETURN_CSTRING(result); +} /* EncodeSpecialTimestamp() @@ -250,19 +233,17 @@ EncodeSpecialTimestamp(Timestamp dt, char *str) return FALSE; } /* EncodeSpecialTimestamp() */ -Timestamp * -now(void) +Datum +now(PG_FUNCTION_ARGS) { - Timestamp *result; + Timestamp result; AbsoluteTime sec; - result = palloc(sizeof(Timestamp)); - sec = GetCurrentTransactionStartTime(); - *result = (sec - ((date2j(2000, 1, 1) - date2j(1970, 1, 1)) * 86400)); + result = (sec - ((date2j(2000, 1, 1) - date2j(1970, 1, 1)) * 86400)); - return result; + PG_RETURN_TIMESTAMP(result); } static void @@ -498,23 +479,21 @@ dt2local(Timestamp dt, int tz) *****************************************************************************/ -bool -timestamp_finite(Timestamp *timestamp) +Datum +timestamp_finite(PG_FUNCTION_ARGS) { - if (!PointerIsValid(timestamp)) - return FALSE; + Timestamp timestamp = PG_GETARG_TIMESTAMP(0); - return !TIMESTAMP_NOT_FINITE(*timestamp); -} /* timestamp_finite() */ + PG_RETURN_BOOL(! TIMESTAMP_NOT_FINITE(timestamp)); +} -bool -interval_finite(Interval *interval) +Datum +interval_finite(PG_FUNCTION_ARGS) { - if (!PointerIsValid(interval)) - return FALSE; + Interval *interval = PG_GETARG_INTERVAL_P(0); - return !INTERVAL_NOT_FINITE(*interval); -} /* interval_finite() */ + PG_RETURN_BOOL(! INTERVAL_NOT_FINITE(*interval)); +} /*---------------------------------------------------------- @@ -563,171 +542,128 @@ SetTimestamp(Timestamp dt) return dt; } /* SetTimestamp() */ -/* timestamp_relop - is timestamp1 relop timestamp2 +/* + * timestamp_relop - is timestamp1 relop timestamp2 */ -bool -timestamp_eq(Timestamp *timestamp1, Timestamp *timestamp2) +Datum +timestamp_eq(PG_FUNCTION_ARGS) { - Timestamp dt1, - dt2; - - if (!PointerIsValid(timestamp1) || !PointerIsValid(timestamp2)) - return FALSE; - - dt1 = *timestamp1; - dt2 = *timestamp2; + Timestamp dt1 = PG_GETARG_TIMESTAMP(0); + Timestamp dt2 = PG_GETARG_TIMESTAMP(1); if (TIMESTAMP_IS_INVALID(dt1) || TIMESTAMP_IS_INVALID(dt2)) - return FALSE; + PG_RETURN_BOOL(false); if (TIMESTAMP_IS_RELATIVE(dt1)) dt1 = SetTimestamp(dt1); if (TIMESTAMP_IS_RELATIVE(dt2)) dt2 = SetTimestamp(dt2); - return dt1 == dt2; -} /* timestamp_eq() */ + PG_RETURN_BOOL(dt1 == dt2); +} -bool -timestamp_ne(Timestamp *timestamp1, Timestamp *timestamp2) +Datum +timestamp_ne(PG_FUNCTION_ARGS) { - Timestamp dt1, - dt2; - - if (!PointerIsValid(timestamp1) || !PointerIsValid(timestamp2)) - return FALSE; - - dt1 = *timestamp1; - dt2 = *timestamp2; + Timestamp dt1 = PG_GETARG_TIMESTAMP(0); + Timestamp dt2 = PG_GETARG_TIMESTAMP(1); if (TIMESTAMP_IS_INVALID(dt1) || TIMESTAMP_IS_INVALID(dt2)) - return FALSE; + PG_RETURN_BOOL(false); if (TIMESTAMP_IS_RELATIVE(dt1)) dt1 = SetTimestamp(dt1); if (TIMESTAMP_IS_RELATIVE(dt2)) dt2 = SetTimestamp(dt2); - return dt1 != dt2; -} /* timestamp_ne() */ + PG_RETURN_BOOL(dt1 != dt2); +} -bool -timestamp_lt(Timestamp *timestamp1, Timestamp *timestamp2) +Datum +timestamp_lt(PG_FUNCTION_ARGS) { - Timestamp dt1, - dt2; - - if (!PointerIsValid(timestamp1) || !PointerIsValid(timestamp2)) - return FALSE; - - dt1 = *timestamp1; - dt2 = *timestamp2; + Timestamp dt1 = PG_GETARG_TIMESTAMP(0); + Timestamp dt2 = PG_GETARG_TIMESTAMP(1); if (TIMESTAMP_IS_INVALID(dt1) || TIMESTAMP_IS_INVALID(dt2)) - return FALSE; + PG_RETURN_BOOL(false); if (TIMESTAMP_IS_RELATIVE(dt1)) dt1 = SetTimestamp(dt1); if (TIMESTAMP_IS_RELATIVE(dt2)) dt2 = SetTimestamp(dt2); - return dt1 < dt2; -} /* timestamp_lt() */ + PG_RETURN_BOOL(dt1 < dt2); +} -bool -timestamp_gt(Timestamp *timestamp1, Timestamp *timestamp2) +Datum +timestamp_gt(PG_FUNCTION_ARGS) { - Timestamp dt1, - dt2; - - if (!PointerIsValid(timestamp1) || !PointerIsValid(timestamp2)) - return FALSE; - - dt1 = *timestamp1; - dt2 = *timestamp2; + Timestamp dt1 = PG_GETARG_TIMESTAMP(0); + Timestamp dt2 = PG_GETARG_TIMESTAMP(1); if (TIMESTAMP_IS_INVALID(dt1) || TIMESTAMP_IS_INVALID(dt2)) - return FALSE; + PG_RETURN_BOOL(false); if (TIMESTAMP_IS_RELATIVE(dt1)) dt1 = SetTimestamp(dt1); if (TIMESTAMP_IS_RELATIVE(dt2)) dt2 = SetTimestamp(dt2); - return dt1 > dt2; -} /* timestamp_gt() */ + PG_RETURN_BOOL(dt1 > dt2); +} -bool -timestamp_le(Timestamp *timestamp1, Timestamp *timestamp2) +Datum +timestamp_le(PG_FUNCTION_ARGS) { - Timestamp dt1, - dt2; - - if (!PointerIsValid(timestamp1) || !PointerIsValid(timestamp2)) - return FALSE; - - dt1 = *timestamp1; - dt2 = *timestamp2; + Timestamp dt1 = PG_GETARG_TIMESTAMP(0); + Timestamp dt2 = PG_GETARG_TIMESTAMP(1); if (TIMESTAMP_IS_INVALID(dt1) || TIMESTAMP_IS_INVALID(dt2)) - return FALSE; + PG_RETURN_BOOL(false); if (TIMESTAMP_IS_RELATIVE(dt1)) dt1 = SetTimestamp(dt1); if (TIMESTAMP_IS_RELATIVE(dt2)) dt2 = SetTimestamp(dt2); - return dt1 <= dt2; -} /* timestamp_le() */ + PG_RETURN_BOOL(dt1 <= dt2); +} -bool -timestamp_ge(Timestamp *timestamp1, Timestamp *timestamp2) +Datum +timestamp_ge(PG_FUNCTION_ARGS) { - Timestamp dt1, - dt2; - - if (!PointerIsValid(timestamp1) || !PointerIsValid(timestamp2)) - return FALSE; - - dt1 = *timestamp1; - dt2 = *timestamp2; + Timestamp dt1 = PG_GETARG_TIMESTAMP(0); + Timestamp dt2 = PG_GETARG_TIMESTAMP(1); if (TIMESTAMP_IS_INVALID(dt1) || TIMESTAMP_IS_INVALID(dt2)) - return FALSE; + PG_RETURN_BOOL(false); if (TIMESTAMP_IS_RELATIVE(dt1)) dt1 = SetTimestamp(dt1); if (TIMESTAMP_IS_RELATIVE(dt2)) dt2 = SetTimestamp(dt2); - return dt1 >= dt2; -} /* timestamp_ge() */ + PG_RETURN_BOOL(dt1 >= dt2); +} /* timestamp_cmp - 3-state comparison for timestamp * collate invalid timestamp at the end */ -int -timestamp_cmp(Timestamp *timestamp1, Timestamp *timestamp2) +Datum +timestamp_cmp(PG_FUNCTION_ARGS) { - Timestamp dt1, - dt2; - - if (!PointerIsValid(timestamp1) || !PointerIsValid(timestamp2)) - return 0; - - dt1 = *timestamp1; - dt2 = *timestamp2; + Timestamp dt1 = PG_GETARG_TIMESTAMP(0); + Timestamp dt2 = PG_GETARG_TIMESTAMP(1); if (TIMESTAMP_IS_INVALID(dt1)) { - return (TIMESTAMP_IS_INVALID(dt2) ? 0 : 1); - + PG_RETURN_INT32(TIMESTAMP_IS_INVALID(dt2) ? 0 : 1); } else if (TIMESTAMP_IS_INVALID(dt2)) { - return -1; - + PG_RETURN_INT32(-1); } else { @@ -737,49 +673,49 @@ timestamp_cmp(Timestamp *timestamp1, Timestamp *timestamp2) dt2 = SetTimestamp(dt2); } - return ((dt1 < dt2) ? -1 : ((dt1 > dt2) ? 1 : 0)); -} /* timestamp_cmp() */ + PG_RETURN_INT32((dt1 < dt2) ? -1 : ((dt1 > dt2) ? 1 : 0)); +} -/* interval_relop - is interval1 relop interval2 +/* + * interval_relop - is interval1 relop interval2 */ -bool -interval_eq(Interval *interval1, Interval *interval2) +Datum +interval_eq(PG_FUNCTION_ARGS) { - if (!PointerIsValid(interval1) || !PointerIsValid(interval2)) - return FALSE; + Interval *interval1 = PG_GETARG_INTERVAL_P(0); + Interval *interval2 = PG_GETARG_INTERVAL_P(1); if (INTERVAL_IS_INVALID(*interval1) || INTERVAL_IS_INVALID(*interval2)) - return FALSE; + PG_RETURN_BOOL(false); - return ((interval1->time == interval2->time) - && (interval1->month == interval2->month)); -} /* interval_eq() */ + PG_RETURN_BOOL((interval1->time == interval2->time) && + (interval1->month == interval2->month)); +} -bool -interval_ne(Interval *interval1, Interval *interval2) +Datum +interval_ne(PG_FUNCTION_ARGS) { - if (!PointerIsValid(interval1) || !PointerIsValid(interval2)) - return FALSE; + Interval *interval1 = PG_GETARG_INTERVAL_P(0); + Interval *interval2 = PG_GETARG_INTERVAL_P(1); if (INTERVAL_IS_INVALID(*interval1) || INTERVAL_IS_INVALID(*interval2)) - return FALSE; + PG_RETURN_BOOL(false); - return ((interval1->time != interval2->time) - || (interval1->month != interval2->month)); -} /* interval_ne() */ + PG_RETURN_BOOL((interval1->time != interval2->time) || + (interval1->month != interval2->month)); +} -bool -interval_lt(Interval *interval1, Interval *interval2) +Datum +interval_lt(PG_FUNCTION_ARGS) { + Interval *interval1 = PG_GETARG_INTERVAL_P(0); + Interval *interval2 = PG_GETARG_INTERVAL_P(1); double span1, span2; - if (!PointerIsValid(interval1) || !PointerIsValid(interval2)) - return FALSE; - if (INTERVAL_IS_INVALID(*interval1) || INTERVAL_IS_INVALID(*interval2)) - return FALSE; + PG_RETURN_BOOL(false); span1 = interval1->time; if (interval1->month != 0) @@ -788,20 +724,19 @@ interval_lt(Interval *interval1, Interval *interval2) if (interval2->month != 0) span2 += (interval2->month * (30.0 * 86400)); - return span1 < span2; -} /* interval_lt() */ + PG_RETURN_BOOL(span1 < span2); +} -bool -interval_gt(Interval *interval1, Interval *interval2) +Datum +interval_gt(PG_FUNCTION_ARGS) { + Interval *interval1 = PG_GETARG_INTERVAL_P(0); + Interval *interval2 = PG_GETARG_INTERVAL_P(1); double span1, span2; - if (!PointerIsValid(interval1) || !PointerIsValid(interval2)) - return FALSE; - if (INTERVAL_IS_INVALID(*interval1) || INTERVAL_IS_INVALID(*interval2)) - return FALSE; + PG_RETURN_BOOL(false); span1 = interval1->time; if (interval1->month != 0) @@ -810,20 +745,19 @@ interval_gt(Interval *interval1, Interval *interval2) if (interval2->month != 0) span2 += (interval2->month * (30.0 * 86400)); - return span1 > span2; -} /* interval_gt() */ + PG_RETURN_BOOL(span1 > span2); +} -bool -interval_le(Interval *interval1, Interval *interval2) +Datum +interval_le(PG_FUNCTION_ARGS) { + Interval *interval1 = PG_GETARG_INTERVAL_P(0); + Interval *interval2 = PG_GETARG_INTERVAL_P(1); double span1, span2; - if (!PointerIsValid(interval1) || !PointerIsValid(interval2)) - return FALSE; - if (INTERVAL_IS_INVALID(*interval1) || INTERVAL_IS_INVALID(*interval2)) - return FALSE; + PG_RETURN_BOOL(false); span1 = interval1->time; if (interval1->month != 0) @@ -832,20 +766,19 @@ interval_le(Interval *interval1, Interval *interval2) if (interval2->month != 0) span2 += (interval2->month * (30.0 * 86400)); - return span1 <= span2; -} /* interval_le() */ + PG_RETURN_BOOL(span1 <= span2); +} -bool -interval_ge(Interval *interval1, Interval *interval2) +Datum +interval_ge(PG_FUNCTION_ARGS) { + Interval *interval1 = PG_GETARG_INTERVAL_P(0); + Interval *interval2 = PG_GETARG_INTERVAL_P(1); double span1, span2; - if (!PointerIsValid(interval1) || !PointerIsValid(interval2)) - return FALSE; - if (INTERVAL_IS_INVALID(*interval1) || INTERVAL_IS_INVALID(*interval2)) - return FALSE; + PG_RETURN_BOOL(false); span1 = interval1->time; if (interval1->month != 0) @@ -854,28 +787,24 @@ interval_ge(Interval *interval1, Interval *interval2) if (interval2->month != 0) span2 += (interval2->month * (30.0 * 86400)); - return span1 >= span2; -} /* interval_ge() */ + PG_RETURN_BOOL(span1 >= span2); +} /* interval_cmp - 3-state comparison for interval */ -int -interval_cmp(Interval *interval1, Interval *interval2) +Datum +interval_cmp(PG_FUNCTION_ARGS) { + Interval *interval1 = PG_GETARG_INTERVAL_P(0); + Interval *interval2 = PG_GETARG_INTERVAL_P(1); double span1, span2; - if (!PointerIsValid(interval1) || !PointerIsValid(interval2)) - return 0; - if (INTERVAL_IS_INVALID(*interval1)) - { - return INTERVAL_IS_INVALID(*interval2) ? 0 : 1; - - } + PG_RETURN_INT32(INTERVAL_IS_INVALID(*interval2) ? 0 : 1); else if (INTERVAL_IS_INVALID(*interval2)) - return -1; + PG_RETURN_INT32(-1); span1 = interval1->time; if (interval1->month != 0) @@ -884,36 +813,57 @@ interval_cmp(Interval *interval1, Interval *interval2) if (interval2->month != 0) span2 += (interval2->month * (30.0 * 86400)); - return (span1 < span2) ? -1 : (span1 > span2) ? 1 : 0; -} /* interval_cmp() */ + PG_RETURN_INT32((span1 < span2) ? -1 : (span1 > span2) ? 1 : 0); +} /* overlaps_timestamp() * Implements the SQL92 OVERLAPS operator. * Algorithm from Date and Darwen, 1997 */ -bool -overlaps_timestamp(Timestamp *ts1, Timestamp *te1, Timestamp *ts2, Timestamp *te2) +Datum +overlaps_timestamp(PG_FUNCTION_ARGS) { + /* The arguments are Timestamps, but we leave them as generic Datums + * to avoid unnecessary conversions between value and reference forms... + */ + Datum ts1 = PG_GETARG_DATUM(0); + Datum te1 = PG_GETARG_DATUM(1); + Datum ts2 = PG_GETARG_DATUM(2); + Datum te2 = PG_GETARG_DATUM(3); + +#define TIMESTAMP_GT(t1,t2) \ + DatumGetBool(DirectFunctionCall2(timestamp_gt,t1,t2)) +#define TIMESTAMP_LT(t1,t2) \ + DatumGetBool(DirectFunctionCall2(timestamp_lt,t1,t2)) +#define TIMESTAMP_EQ(t1,t2) \ + DatumGetBool(DirectFunctionCall2(timestamp_eq,t1,t2)) + /* Make sure we have ordered pairs... */ - if (timestamp_gt(ts1, te1)) + if (TIMESTAMP_GT(ts1, te1)) { - Timestamp *tt = ts1; + Datum tt = ts1; ts1 = te1; te1 = tt; } - if (timestamp_gt(ts2, te2)) + if (TIMESTAMP_GT(ts2, te2)) { - Timestamp *tt = ts2; + Datum tt = ts2; ts2 = te2; te2 = tt; } - return ((timestamp_gt(ts1, ts2) && (timestamp_lt(ts1, te2) || timestamp_lt(te1, te2))) - || (timestamp_gt(ts2, ts1) && (timestamp_lt(ts2, te1) || timestamp_lt(te2, te1))) - || timestamp_eq(ts1, ts2)); -} /* overlaps_timestamp() */ + PG_RETURN_BOOL((TIMESTAMP_GT(ts1, ts2) && + (TIMESTAMP_LT(ts1, te2) || TIMESTAMP_LT(te1, te2))) || + (TIMESTAMP_GT(ts2, ts1) && + (TIMESTAMP_LT(ts2, te1) || TIMESTAMP_LT(te2, te1))) || + TIMESTAMP_EQ(ts1, ts2)); + +#undef TIMESTAMP_GT +#undef TIMESTAMP_LT +#undef TIMESTAMP_EQ +} /*---------------------------------------------------------- @@ -924,21 +874,12 @@ overlaps_timestamp(Timestamp *ts1, Timestamp *te1, Timestamp *ts2, Timestamp *te * actual value. *---------------------------------------------------------*/ -Timestamp * -timestamp_smaller(Timestamp *timestamp1, Timestamp *timestamp2) +Datum +timestamp_smaller(PG_FUNCTION_ARGS) { - Timestamp *result; - - Timestamp dt1, - dt2; - - if (!PointerIsValid(timestamp1) || !PointerIsValid(timestamp2)) - return NULL; - - dt1 = *timestamp1; - dt2 = *timestamp2; - - result = palloc(sizeof(Timestamp)); + Timestamp dt1 = PG_GETARG_TIMESTAMP(0); + Timestamp dt2 = PG_GETARG_TIMESTAMP(1); + Timestamp result; if (TIMESTAMP_IS_RELATIVE(dt1)) dt1 = SetTimestamp(dt1); @@ -946,30 +887,21 @@ timestamp_smaller(Timestamp *timestamp1, Timestamp *timestamp2) dt2 = SetTimestamp(dt2); if (TIMESTAMP_IS_INVALID(dt1)) - *result = dt2; + result = dt2; else if (TIMESTAMP_IS_INVALID(dt2)) - *result = dt1; + result = dt1; else - *result = ((dt2 < dt1) ? dt2 : dt1); + result = ((dt2 < dt1) ? dt2 : dt1); - return result; -} /* timestamp_smaller() */ + PG_RETURN_TIMESTAMP(result); +} -Timestamp * -timestamp_larger(Timestamp *timestamp1, Timestamp *timestamp2) +Datum +timestamp_larger(PG_FUNCTION_ARGS) { - Timestamp *result; - - Timestamp dt1, - dt2; - - if (!PointerIsValid(timestamp1) || !PointerIsValid(timestamp2)) - return NULL; - - dt1 = *timestamp1; - dt2 = *timestamp2; - - result = palloc(sizeof(Timestamp)); + Timestamp dt1 = PG_GETARG_TIMESTAMP(0); + Timestamp dt2 = PG_GETARG_TIMESTAMP(1); + Timestamp result; if (TIMESTAMP_IS_RELATIVE(dt1)) dt1 = SetTimestamp(dt1); @@ -977,31 +909,24 @@ timestamp_larger(Timestamp *timestamp1, Timestamp *timestamp2) dt2 = SetTimestamp(dt2); if (TIMESTAMP_IS_INVALID(dt1)) - *result = dt2; + result = dt2; else if (TIMESTAMP_IS_INVALID(dt2)) - *result = dt1; + result = dt1; else - *result = ((dt2 > dt1) ? dt2 : dt1); + result = ((dt2 > dt1) ? dt2 : dt1); - return result; -} /* timestamp_larger() */ + PG_RETURN_TIMESTAMP(result); +} -Interval * -timestamp_mi(Timestamp *timestamp1, Timestamp *timestamp2) +Datum +timestamp_mi(PG_FUNCTION_ARGS) { + Timestamp dt1 = PG_GETARG_TIMESTAMP(0); + Timestamp dt2 = PG_GETARG_TIMESTAMP(1); Interval *result; - Timestamp dt1, - dt2; - - if (!PointerIsValid(timestamp1) || !PointerIsValid(timestamp2)) - return NULL; - - dt1 = *timestamp1; - dt2 = *timestamp2; - - result = palloc(sizeof(Interval)); + result = (Interval *) palloc(sizeof(Interval)); if (TIMESTAMP_IS_RELATIVE(dt1)) dt1 = SetTimestamp(dt1); @@ -1010,16 +935,13 @@ timestamp_mi(Timestamp *timestamp1, Timestamp *timestamp2) if (TIMESTAMP_IS_INVALID(dt1) || TIMESTAMP_IS_INVALID(dt2)) - { TIMESTAMP_INVALID(result->time); - - } else result->time = JROUND(dt1 - dt2); result->month = 0; - return result; -} /* timestamp_mi() */ + PG_RETURN_INTERVAL_P(result); +} /* timestamp_pl_span() @@ -1031,32 +953,23 @@ timestamp_mi(Timestamp *timestamp1, Timestamp *timestamp2) * to the last day of month. * Lastly, add in the "quantitative time". */ -Timestamp * -timestamp_pl_span(Timestamp *timestamp, Interval *span) +Datum +timestamp_pl_span(PG_FUNCTION_ARGS) { - Timestamp *result; + Timestamp timestamp = PG_GETARG_TIMESTAMP(0); + Interval *span = PG_GETARG_INTERVAL_P(1); + Timestamp result; Timestamp dt; int tz; char *tzn; - if ((!PointerIsValid(timestamp)) || (!PointerIsValid(span))) - return NULL; - - result = palloc(sizeof(Timestamp)); - - if (TIMESTAMP_NOT_FINITE(*timestamp)) - { - *result = *timestamp; - - } + if (TIMESTAMP_NOT_FINITE(timestamp)) + result = timestamp; else if (INTERVAL_IS_INVALID(*span)) - { - TIMESTAMP_INVALID(*result); - - } + TIMESTAMP_INVALID(result); else { - dt = (TIMESTAMP_IS_RELATIVE(*timestamp) ? SetTimestamp(*timestamp) : *timestamp); + dt = (TIMESTAMP_IS_RELATIVE(timestamp) ? SetTimestamp(timestamp) : timestamp); if (span->month != 0) { @@ -1096,71 +1009,63 @@ timestamp_pl_span(Timestamp *timestamp, Interval *span) dt += span->time; #endif - *result = dt; + result = dt; } - return result; -} /* timestamp_pl_span() */ + PG_RETURN_TIMESTAMP(result); +} -Timestamp * -timestamp_mi_span(Timestamp *timestamp, Interval *span) +Datum +timestamp_mi_span(PG_FUNCTION_ARGS) { - Timestamp *result; + Timestamp timestamp = PG_GETARG_TIMESTAMP(0); + Interval *span = PG_GETARG_INTERVAL_P(1); Interval tspan; - if (!PointerIsValid(timestamp) || !PointerIsValid(span)) - return NULL; - - tspan.month = -span->month; - tspan.time = -span->time; + tspan.month = - span->month; + tspan.time = - span->time; - result = timestamp_pl_span(timestamp, &tspan); - - return result; -} /* timestamp_mi_span() */ + return DirectFunctionCall2(timestamp_pl_span, + TimestampGetDatum(timestamp), + PointerGetDatum(&tspan)); +} -Interval * -interval_um(Interval *interval) +Datum +interval_um(PG_FUNCTION_ARGS) { + Interval *interval = PG_GETARG_INTERVAL_P(0); Interval *result; - if (!PointerIsValid(interval)) - return NULL; - - result = palloc(sizeof(Interval)); + result = (Interval *) palloc(sizeof(Interval)); result->time = -(interval->time); result->month = -(interval->month); - return result; -} /* interval_um() */ + PG_RETURN_INTERVAL_P(result); +} -Interval * -interval_smaller(Interval *interval1, Interval *interval2) +Datum +interval_smaller(PG_FUNCTION_ARGS) { + Interval *interval1 = PG_GETARG_INTERVAL_P(0); + Interval *interval2 = PG_GETARG_INTERVAL_P(1); Interval *result; - double span1, span2; - if (!PointerIsValid(interval1) || !PointerIsValid(interval2)) - return NULL; - - result = palloc(sizeof(Interval)); + result = (Interval *) palloc(sizeof(Interval)); if (INTERVAL_IS_INVALID(*interval1)) { result->time = interval2->time; result->month = interval2->month; - } else if (INTERVAL_IS_INVALID(*interval2)) { result->time = interval1->time; result->month = interval1->month; - } else { @@ -1175,7 +1080,6 @@ interval_smaller(Interval *interval1, Interval *interval2) { result->time = interval2->time; result->month = interval2->month; - } else { @@ -1184,33 +1088,29 @@ interval_smaller(Interval *interval1, Interval *interval2) } } - return result; -} /* interval_smaller() */ + PG_RETURN_INTERVAL_P(result); +} -Interval * -interval_larger(Interval *interval1, Interval *interval2) +Datum +interval_larger(PG_FUNCTION_ARGS) { + Interval *interval1 = PG_GETARG_INTERVAL_P(0); + Interval *interval2 = PG_GETARG_INTERVAL_P(1); Interval *result; - double span1, span2; - if (!PointerIsValid(interval1) || !PointerIsValid(interval2)) - return NULL; - - result = palloc(sizeof(Interval)); + result = (Interval *) palloc(sizeof(Interval)); if (INTERVAL_IS_INVALID(*interval1)) { result->time = interval2->time; result->month = interval2->month; - } else if (INTERVAL_IS_INVALID(*interval2)) { result->time = interval1->time; result->month = interval1->month; - } else { @@ -1225,7 +1125,6 @@ interval_larger(Interval *interval1, Interval *interval2) { result->time = interval2->time; result->month = interval2->month; - } else { @@ -1234,92 +1133,90 @@ interval_larger(Interval *interval1, Interval *interval2) } } - return result; -} /* interval_larger() */ + PG_RETURN_INTERVAL_P(result); +} -Interval * -interval_pl(Interval *span1, Interval *span2) +Datum +interval_pl(PG_FUNCTION_ARGS) { + Interval *span1 = PG_GETARG_INTERVAL_P(0); + Interval *span2 = PG_GETARG_INTERVAL_P(1); Interval *result; - if ((!PointerIsValid(span1)) || (!PointerIsValid(span2))) - return NULL; - - result = palloc(sizeof(Interval)); + result = (Interval *) palloc(sizeof(Interval)); result->month = (span1->month + span2->month); result->time = JROUND(span1->time + span2->time); - return result; -} /* interval_pl() */ + PG_RETURN_INTERVAL_P(result); +} -Interval * -interval_mi(Interval *span1, Interval *span2) +Datum +interval_mi(PG_FUNCTION_ARGS) { + Interval *span1 = PG_GETARG_INTERVAL_P(0); + Interval *span2 = PG_GETARG_INTERVAL_P(1); Interval *result; - if ((!PointerIsValid(span1)) || (!PointerIsValid(span2))) - return NULL; - - result = palloc(sizeof(Interval)); + result = (Interval *) palloc(sizeof(Interval)); result->month = (span1->month - span2->month); result->time = JROUND(span1->time - span2->time); - return result; -} /* interval_mi() */ + PG_RETURN_INTERVAL_P(result); +} -Interval * -interval_mul(Interval *span1, float8 *factor) +Datum +interval_mul(PG_FUNCTION_ARGS) { + Interval *span1 = PG_GETARG_INTERVAL_P(0); + float8 factor = PG_GETARG_FLOAT8(1); Interval *result; double months; - if ((!PointerIsValid(span1)) || (!PointerIsValid(factor))) - return NULL; + result = (Interval *) palloc(sizeof(Interval)); - if (!PointerIsValid(result = palloc(sizeof(Interval)))) - elog(ERROR, "Memory allocation failed, can't multiply interval"); - - months = (span1->month * *factor); + months = (span1->month * factor); result->month = rint(months); - result->time = JROUND(span1->time * *factor); + result->time = JROUND(span1->time * factor); /* evaluate fractional months as 30 days */ result->time += JROUND((months - result->month) * 30 * 86400); - return result; -} /* interval_mul() */ + PG_RETURN_INTERVAL_P(result); +} -Interval * -mul_d_interval(float8 *factor, Interval *span1) +Datum +mul_d_interval(PG_FUNCTION_ARGS) { - return interval_mul(span1, factor); -} /* mul_d_interval() */ + /* Args are float8 and Interval *, but leave them as generic Datum */ + Datum factor = PG_GETARG_DATUM(0); + Datum span1 = PG_GETARG_DATUM(1); -Interval * -interval_div(Interval *span1, float8 *factor) + return DirectFunctionCall2(interval_mul, span1, factor); +} + +Datum +interval_div(PG_FUNCTION_ARGS) { + Interval *span1 = PG_GETARG_INTERVAL_P(0); + float8 factor = PG_GETARG_FLOAT8(1); Interval *result; double months; - if ((!PointerIsValid(span1)) || (!PointerIsValid(factor))) - return NULL; - - if (!PointerIsValid(result = palloc(sizeof(Interval)))) - elog(ERROR, "Memory allocation failed, can't divide interval"); + result = (Interval *) palloc(sizeof(Interval)); - if (*factor == 0.0) + if (factor == 0.0) elog(ERROR, "interval_div: divide by 0.0 error"); - months = (span1->month / *factor); + months = (span1->month / factor); result->month = rint(months); - result->time = JROUND(span1->time / *factor); + result->time = JROUND(span1->time / factor); /* evaluate fractional months as 30 days */ result->time += JROUND((months - result->month) * 30 * 86400); - return result; -} /* interval_div() */ + PG_RETURN_INTERVAL_P(result); +} /* timestamp_age() * Calculate time difference while retaining year/month fields. @@ -1327,13 +1224,12 @@ interval_div(Interval *span1, float8 *factor) * since year and month are out of context once the arithmetic * is done. */ -Interval * -timestamp_age(Timestamp *timestamp1, Timestamp *timestamp2) +Datum +timestamp_age(PG_FUNCTION_ARGS) { + Timestamp dt1 = PG_GETARG_TIMESTAMP(0); + Timestamp dt2 = PG_GETARG_TIMESTAMP(1); Interval *result; - - Timestamp dt1, - dt2; double fsec, fsec1, fsec2; @@ -1344,13 +1240,7 @@ timestamp_age(Timestamp *timestamp1, Timestamp *timestamp2) struct tm tt2, *tm2 = &tt2; - if (!PointerIsValid(timestamp1) || !PointerIsValid(timestamp2)) - return NULL; - - result = palloc(sizeof(Interval)); - - dt1 = *timestamp1; - dt2 = *timestamp2; + result = (Interval *) palloc(sizeof(Interval)); if (TIMESTAMP_IS_RELATIVE(dt1)) dt1 = SetTimestamp(dt1); @@ -1361,7 +1251,6 @@ timestamp_age(Timestamp *timestamp1, Timestamp *timestamp2) || TIMESTAMP_IS_INVALID(dt2)) { TIMESTAMP_INVALID(result->time); - } else if ((timestamp2tm(dt1, NULL, tm1, &fsec1, NULL) == 0) && (timestamp2tm(dt2, NULL, tm2, &fsec2, NULL) == 0)) @@ -1438,13 +1327,12 @@ timestamp_age(Timestamp *timestamp1, Timestamp *timestamp2) if (tm2interval(tm, fsec, result) != 0) elog(ERROR, "Unable to decode timestamp"); - } else elog(ERROR, "Unable to decode timestamp"); - return result; -} /* timestamp_age() */ + PG_RETURN_INTERVAL_P(result); +} /*---------------------------------------------------------- @@ -1455,20 +1343,16 @@ timestamp_age(Timestamp *timestamp1, Timestamp *timestamp2) /* timestamp_text() * Convert timestamp to text data type. */ -text * -timestamp_text(Timestamp *timestamp) +Datum +timestamp_text(PG_FUNCTION_ARGS) { + /* Input is a Timestamp, but may as well leave it in Datum form */ + Datum timestamp = PG_GETARG_DATUM(0); text *result; char *str; int len; - if (!PointerIsValid(timestamp)) - return NULL; - - str = timestamp_out(timestamp); - - if (!PointerIsValid(str)) - return NULL; + str = DatumGetCString(DirectFunctionCall1(timestamp_out, timestamp)); len = (strlen(str) + VARHDRSZ); @@ -1479,8 +1363,8 @@ timestamp_text(Timestamp *timestamp) pfree(str); - return result; -} /* timestamp_text() */ + PG_RETURN_TEXT_P(result); +} /* text_timestamp() @@ -1488,17 +1372,17 @@ timestamp_text(Timestamp *timestamp) * Text type is not null terminated, so use temporary string * then call the standard input routine. */ -Timestamp * -text_timestamp(text *str) +Datum +text_timestamp(PG_FUNCTION_ARGS) { - Timestamp *result; + text *str = PG_GETARG_TEXT_P(0); int i; char *sp, *dp, dstr[MAXDATELEN + 1]; - if (!PointerIsValid(str)) - return NULL; + if (VARSIZE(str) - VARHDRSZ > MAXDATELEN) + elog(ERROR, "Bad timestamp external representation (too long)"); sp = VARDATA(str); dp = dstr; @@ -1506,29 +1390,24 @@ text_timestamp(text *str) *dp++ = *sp++; *dp = '\0'; - result = timestamp_in(dstr); - - return result; -} /* text_timestamp() */ + return DirectFunctionCall1(timestamp_in, + CStringGetDatum(dstr)); +} /* interval_text() * Convert interval to text data type. */ -text * -interval_text(Interval *interval) +Datum +interval_text(PG_FUNCTION_ARGS) { + Interval *interval = PG_GETARG_INTERVAL_P(0); text *result; char *str; int len; - if (!PointerIsValid(interval)) - return NULL; - - str = interval_out(interval); - - if (!PointerIsValid(str)) - return NULL; + str = DatumGetCString(DirectFunctionCall1(interval_out, + IntervalPGetDatum(interval))); len = (strlen(str) + VARHDRSZ); @@ -1539,8 +1418,8 @@ interval_text(Interval *interval) pfree(str); - return result; -} /* interval_text() */ + PG_RETURN_TEXT_P(result); +} /* text_interval() @@ -1548,37 +1427,35 @@ interval_text(Interval *interval) * Text type may not be null terminated, so copy to temporary string * then call the standard input routine. */ -Interval * -text_interval(text *str) +Datum +text_interval(PG_FUNCTION_ARGS) { - Interval *result; + text *str = PG_GETARG_TEXT_P(0); int i; char *sp, *dp, dstr[MAXDATELEN + 1]; - if (!PointerIsValid(str)) - return NULL; - + if (VARSIZE(str) - VARHDRSZ > MAXDATELEN) + elog(ERROR, "Bad interval external representation (too long)"); sp = VARDATA(str); dp = dstr; for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++) *dp++ = *sp++; *dp = '\0'; - result = interval_in(dstr); - - return result; -} /* text_interval() */ + return DirectFunctionCall1(interval_in, CStringGetDatum(dstr)); +} /* timestamp_trunc() * Extract specified field from timestamp. */ -Timestamp * -timestamp_trunc(text *units, Timestamp *timestamp) +Datum +timestamp_trunc(PG_FUNCTION_ARGS) { - Timestamp *result; - + text *units = PG_GETARG_TEXT_P(0); + Timestamp timestamp = PG_GETARG_TIMESTAMP(1); + Timestamp result; Timestamp dt; int tz; int type, @@ -1592,11 +1469,8 @@ timestamp_trunc(text *units, Timestamp *timestamp) struct tm tt, *tm = &tt; - if ((!PointerIsValid(units)) || (!PointerIsValid(timestamp))) - return NULL; - - result = palloc(sizeof(Timestamp)); - + if (VARSIZE(units) - VARHDRSZ > MAXDATELEN) + elog(ERROR, "Interval units '%s' not recognized", textout(units)); up = VARDATA(units); lp = lowunits; for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++) @@ -1605,18 +1479,18 @@ timestamp_trunc(text *units, Timestamp *timestamp) type = DecodeUnits(0, lowunits, &val); - if (TIMESTAMP_NOT_FINITE(*timestamp)) + if (TIMESTAMP_NOT_FINITE(timestamp)) { #if NOT_USED /* should return null but Postgres doesn't like that currently. - tgl 97/06/12 */ - elog(ERROR, "Timestamp is not finite", NULL); + elog(ERROR, "Timestamp is not finite"); #endif - *result = 0; + result = 0; } else { - dt = (TIMESTAMP_IS_RELATIVE(*timestamp) ? SetTimestamp(*timestamp) : *timestamp); + dt = (TIMESTAMP_IS_RELATIVE(timestamp) ? SetTimestamp(timestamp) : timestamp); if ((type == UNITS) && (timestamp2tm(dt, &tz, tm, &fsec, &tzn) == 0)) { @@ -1654,7 +1528,7 @@ timestamp_trunc(text *units, Timestamp *timestamp) default: elog(ERROR, "Timestamp units '%s' not supported", lowunits); - result = NULL; + result = 0; } if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday)) @@ -1692,36 +1566,35 @@ timestamp_trunc(text *units, Timestamp *timestamp) tz = 0; } - if (tm2timestamp(tm, fsec, &tz, result) != 0) + if (tm2timestamp(tm, fsec, &tz, &result) != 0) elog(ERROR, "Unable to truncate timestamp to '%s'", lowunits); - -#if NOT_USED } +#if NOT_USED else if ((type == RESERV) && (val == DTK_EPOCH)) { - TIMESTAMP_EPOCH(*result); - *result = dt - SetTimestamp(*result); -#endif - + TIMESTAMP_EPOCH(result); + result = dt - SetTimestamp(result); } +#endif else { elog(ERROR, "Timestamp units '%s' not recognized", lowunits); - result = NULL; + result = 0; } } - return result; -} /* timestamp_trunc() */ + PG_RETURN_TIMESTAMP(result); +} /* interval_trunc() * Extract specified field from interval. */ -Interval * -interval_trunc(text *units, Interval *interval) +Datum +interval_trunc(PG_FUNCTION_ARGS) { + text *units = PG_GETARG_TEXT_P(0); + Interval *interval = PG_GETARG_INTERVAL_P(1); Interval *result; - int type, val; int i; @@ -1732,11 +1605,10 @@ interval_trunc(text *units, Interval *interval) struct tm tt, *tm = &tt; - if ((!PointerIsValid(units)) || (!PointerIsValid(interval))) - return NULL; - - result = palloc(sizeof(Interval)); + result = (Interval *) palloc(sizeof(Interval)); + if (VARSIZE(units) - VARHDRSZ > MAXDATELEN) + elog(ERROR, "Interval units '%s' not recognized", textout(units)); up = VARDATA(units); lp = lowunits; for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++) @@ -1748,14 +1620,12 @@ interval_trunc(text *units, Interval *interval) if (INTERVAL_IS_INVALID(*interval)) { #if NOT_USED - elog(ERROR, "Interval is not finite", NULL); + elog(ERROR, "Interval is not finite"); #endif - result = NULL; - + PG_RETURN_NULL(); } else if (type == UNITS) { - if (interval2tm(*interval, tm, &fsec) == 0) { switch (val) @@ -1792,7 +1662,7 @@ interval_trunc(text *units, Interval *interval) default: elog(ERROR, "Interval units '%s' not supported", lowunits); - result = NULL; + PG_RETURN_NULL(); } if (tm2interval(tm, fsec, result) != 0) @@ -1802,11 +1672,11 @@ interval_trunc(text *units, Interval *interval) else { elog(NOTICE, "Interval out of range"); - result = NULL; + PG_RETURN_NULL(); } -#if NOT_USED } +#if NOT_USED else if ((type == RESERV) && (val == DTK_EPOCH)) { *result = interval->time; @@ -1815,27 +1685,27 @@ interval_trunc(text *units, Interval *interval) *result += ((365.25 * 86400) * (interval->month / 12)); *result += ((30 * 86400) * (interval->month % 12)); } -#endif - } +#endif else { elog(ERROR, "Interval units '%s' not recognized", textout(units)); - result = NULL; + PG_RETURN_NULL(); } - return result; -} /* interval_trunc() */ + PG_RETURN_INTERVAL_P(result); +} /* timestamp_part() * Extract specified field from timestamp. */ -float64 -timestamp_part(text *units, Timestamp *timestamp) +Datum +timestamp_part(PG_FUNCTION_ARGS) { - float64 result; - + text *units = PG_GETARG_TEXT_P(0); + Timestamp timestamp = PG_GETARG_TIMESTAMP(1); + float8 result; Timestamp dt; int tz; int type, @@ -1850,11 +1720,8 @@ timestamp_part(text *units, Timestamp *timestamp) struct tm tt, *tm = &tt; - if ((!PointerIsValid(units)) || (!PointerIsValid(timestamp))) - return NULL; - - result = palloc(sizeof(float64data)); - + if (VARSIZE(units) - VARHDRSZ > MAXDATELEN) + elog(ERROR, "Interval units '%s' not recognized", textout(units)); up = VARDATA(units); lp = lowunits; for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++) @@ -1865,67 +1732,66 @@ timestamp_part(text *units, Timestamp *timestamp) if (type == IGNORE) type = DecodeSpecial(0, lowunits, &val); - if (TIMESTAMP_NOT_FINITE(*timestamp)) + if (TIMESTAMP_NOT_FINITE(timestamp)) { #if NOT_USED /* should return null but Postgres doesn't like that currently. - tgl 97/06/12 */ elog(ERROR, "Timestamp is not finite", NULL); #endif - *result = 0; - + PG_RETURN_NULL(); } else { - dt = (TIMESTAMP_IS_RELATIVE(*timestamp) ? SetTimestamp(*timestamp) : *timestamp); + dt = (TIMESTAMP_IS_RELATIVE(timestamp) ? SetTimestamp(timestamp) : timestamp); if ((type == UNITS) && (timestamp2tm(dt, &tz, tm, &fsec, &tzn) == 0)) { switch (val) { case DTK_TZ: - *result = tz; + result = tz; break; case DTK_TZ_MINUTE: - *result = tz / 60; - TMODULO(*result, dummy, 60e0); + result = tz / 60; + TMODULO(result, dummy, 60e0); break; case DTK_TZ_HOUR: dummy = tz; - TMODULO(dummy, *result, 3600e0); + TMODULO(dummy, result, 3600e0); break; case DTK_MICROSEC: - *result = (fsec * 1000000); + result = (fsec * 1000000); break; case DTK_MILLISEC: - *result = (fsec * 1000); + result = (fsec * 1000); break; case DTK_SECOND: - *result = (tm->tm_sec + fsec); + result = (tm->tm_sec + fsec); break; case DTK_MINUTE: - *result = tm->tm_min; + result = tm->tm_min; break; case DTK_HOUR: - *result = tm->tm_hour; + result = tm->tm_hour; break; case DTK_DAY: - *result = tm->tm_mday; + result = tm->tm_mday; break; case DTK_MONTH: - *result = tm->tm_mon; + result = tm->tm_mon; break; case DTK_QUARTER: - *result = (tm->tm_mon / 4) + 1; + result = (tm->tm_mon / 4) + 1; break; case DTK_WEEK: @@ -1945,40 +1811,40 @@ timestamp_part(text *units, Timestamp *timestamp) /* day0 == offset to first day of week (Monday) */ day0 = (j2day(day4 - 1) % 7); } - *result = (((dayn - (day4 - day0)) / 7) + 1); + result = (((dayn - (day4 - day0)) / 7) + 1); /* Sometimes the last few days in a year will fall into * the first week of the next year, so check for this. */ - if (*result >= 53) + if (result >= 53) { day4 = date2j((tm->tm_year + 1), 1, 4); /* day0 == offset to first day of week (Monday) */ day0 = (j2day(day4 - 1) % 7); if (dayn >= (day4 - day0)) - *result = (((dayn - (day4 - day0)) / 7) + 1); + result = (((dayn - (day4 - day0)) / 7) + 1); } } break; case DTK_YEAR: - *result = tm->tm_year; + result = tm->tm_year; break; case DTK_DECADE: - *result = (tm->tm_year / 10); + result = (tm->tm_year / 10); break; case DTK_CENTURY: - *result = (tm->tm_year / 100); + result = (tm->tm_year / 100); break; case DTK_MILLENNIUM: - *result = (tm->tm_year / 1000); + result = (tm->tm_year / 1000); break; default: elog(ERROR, "Timestamp units '%s' not supported", lowunits); - *result = 0; + result = 0; } } @@ -1987,50 +1853,51 @@ timestamp_part(text *units, Timestamp *timestamp) switch (val) { case DTK_EPOCH: - TIMESTAMP_EPOCH(*result); - *result = dt - SetTimestamp(*result); + TIMESTAMP_EPOCH(result); + result = dt - SetTimestamp(result); break; case DTK_DOW: if (timestamp2tm(dt, &tz, tm, &fsec, &tzn) != 0) elog(ERROR, "Unable to encode timestamp"); - *result = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)); + result = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)); break; case DTK_DOY: if (timestamp2tm(dt, &tz, tm, &fsec, &tzn) != 0) elog(ERROR, "Unable to encode timestamp"); - *result = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) + result = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(tm->tm_year, 1, 1) + 1); break; default: elog(ERROR, "Timestamp units '%s' not supported", lowunits); - *result = 0; + result = 0; } } else { elog(ERROR, "Timestamp units '%s' not recognized", lowunits); - *result = 0; + result = 0; } } - return result; -} /* timestamp_part() */ + PG_RETURN_FLOAT8(result); +} /* interval_part() * Extract specified field from interval. */ -float64 -interval_part(text *units, Interval *interval) +Datum +interval_part(PG_FUNCTION_ARGS) { - float64 result; - + text *units = PG_GETARG_TEXT_P(0); + Interval *interval = PG_GETARG_INTERVAL_P(1); + float8 result; int type, val; int i; @@ -2041,11 +1908,8 @@ interval_part(text *units, Interval *interval) struct tm tt, *tm = &tt; - if ((!PointerIsValid(units)) || (!PointerIsValid(interval))) - return NULL; - - result = palloc(sizeof(float64data)); - + if (VARSIZE(units) - VARHDRSZ > MAXDATELEN) + elog(ERROR, "Interval units '%s' not recognized", textout(units)); up = VARDATA(units); lp = lowunits; for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++) @@ -2061,105 +1925,103 @@ interval_part(text *units, Interval *interval) #if NOT_USED elog(ERROR, "Interval is not finite"); #endif - *result = 0; - + result = 0; } else if (type == UNITS) { - if (interval2tm(*interval, tm, &fsec) == 0) { switch (val) { case DTK_MICROSEC: - *result = (fsec * 1000000); + result = (fsec * 1000000); break; case DTK_MILLISEC: - *result = (fsec * 1000); + result = (fsec * 1000); break; case DTK_SECOND: - *result = (tm->tm_sec + fsec); + result = (tm->tm_sec + fsec); break; case DTK_MINUTE: - *result = tm->tm_min; + result = tm->tm_min; break; case DTK_HOUR: - *result = tm->tm_hour; + result = tm->tm_hour; break; case DTK_DAY: - *result = tm->tm_mday; + result = tm->tm_mday; break; case DTK_MONTH: - *result = tm->tm_mon; + result = tm->tm_mon; break; case DTK_QUARTER: - *result = (tm->tm_mon / 4) + 1; + result = (tm->tm_mon / 4) + 1; break; case DTK_YEAR: - *result = tm->tm_year; + result = tm->tm_year; break; case DTK_DECADE: - *result = (tm->tm_year / 10); + result = (tm->tm_year / 10); break; case DTK_CENTURY: - *result = (tm->tm_year / 100); + result = (tm->tm_year / 100); break; case DTK_MILLENNIUM: - *result = (tm->tm_year / 1000); + result = (tm->tm_year / 1000); break; default: - elog(ERROR, "Interval units '%s' not yet supported", textout(units)); - result = NULL; + elog(ERROR, "Interval units '%s' not yet supported", + textout(units)); + result = 0; } } else { elog(NOTICE, "Interval out of range"); - *result = 0; + result = 0; } - } else if ((type == RESERV) && (val == DTK_EPOCH)) { - *result = interval->time; + result = interval->time; if (interval->month != 0) { - *result += ((365.25 * 86400) * (interval->month / 12)); - *result += ((30 * 86400) * (interval->month % 12)); + result += ((365.25 * 86400) * (interval->month / 12)); + result += ((30 * 86400) * (interval->month % 12)); } - } else { elog(ERROR, "Interval units '%s' not recognized", textout(units)); - *result = 0; + result = 0; } - return result; -} /* interval_part() */ + PG_RETURN_FLOAT8(result); +} /* timestamp_zone() * Encode timestamp type with specified time zone. */ -text * -timestamp_zone(text *zone, Timestamp *timestamp) +Datum +timestamp_zone(PG_FUNCTION_ARGS) { + text *zone = PG_GETARG_TEXT_P(0); + Timestamp timestamp = PG_GETARG_TIMESTAMP(1); text *result; - Timestamp dt; int tz; int type, @@ -2176,9 +2038,8 @@ timestamp_zone(text *zone, Timestamp *timestamp) char buf[MAXDATELEN + 1]; int len; - if ((!PointerIsValid(zone)) || (!PointerIsValid(timestamp))) - return NULL; - + if (VARSIZE(zone) - VARHDRSZ > MAXDATELEN) + elog(ERROR, "Time zone '%s' not recognized", textout(zone)); up = VARDATA(zone); lp = lowzone; for (i = 0; i < (VARSIZE(zone) - VARHDRSZ); i++) @@ -2187,23 +2048,24 @@ timestamp_zone(text *zone, Timestamp *timestamp) type = DecodeSpecial(0, lowzone, &val); - if (TIMESTAMP_NOT_FINITE(*timestamp)) + if (TIMESTAMP_NOT_FINITE(timestamp)) { /* * could return null but Postgres doesn't like that currently. - * tgl 97/06/12 + * + * Could do it now if you wanted ... the other tgl 2000/06/08 */ elog(ERROR, "Timestamp is not finite"); result = NULL; - } else if ((type == TZ) || (type == DTZ)) { tm->tm_isdst = ((type == DTZ) ? 1 : 0); tz = val * 60; - dt = (TIMESTAMP_IS_RELATIVE(*timestamp) ? SetTimestamp(*timestamp) : *timestamp); + dt = (TIMESTAMP_IS_RELATIVE(timestamp) ? SetTimestamp(timestamp) : timestamp); dt = dt2local(dt, tz); if (timestamp2tm(dt, NULL, tm, &fsec, NULL) != 0) @@ -2224,7 +2086,6 @@ timestamp_zone(text *zone, Timestamp *timestamp) VARSIZE(result) = len; memmove(VARDATA(result), buf, (len - VARHDRSZ)); - } else { @@ -2232,5 +2093,5 @@ timestamp_zone(text *zone, Timestamp *timestamp) result = NULL; } - return result; -} /* timestamp_zone() */ + PG_RETURN_TEXT_P(result); +} |