From 0bb51aa96783e8a6c473c2b5e3725e23e95db834 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 16 Aug 2016 20:33:01 -0400 Subject: Improve parsetree representation of special functions such as CURRENT_DATE. We implement a dozen or so parameterless functions that the SQL standard defines special syntax for. Up to now, that was done by converting them into more or less ad-hoc constructs such as "'now'::text::date". That's messy for multiple reasons: it exposes what should be implementation details to users, and performance is worse than it needs to be in several cases. To improve matters, invent a new expression node type SQLValueFunction that can represent any of these parameterless functions. Bump catversion because this changes stored parsetrees for rules. Discussion: <30058.1463091294@sss.pgh.pa.us> --- src/backend/utils/adt/timestamp.c | 60 +++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 8 deletions(-) (limited to 'src/backend/utils/adt/timestamp.c') diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index d7ee865cf75..c1d6f05b5ed 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -72,13 +72,13 @@ static Timestamp dt2local(Timestamp dt, int timezone); static void AdjustTimestampForTypmod(Timestamp *time, int32 typmod); static void AdjustIntervalForTypmod(Interval *interval, int32 typmod); static TimestampTz timestamp2timestamptz(Timestamp timestamp); +static Timestamp timestamptz2timestamp(TimestampTz timestamp); /* common code for timestamptypmodin and timestamptztypmodin */ static int32 anytimestamp_typmodin(bool istz, ArrayType *ta) { - int32 typmod; int32 *tl; int n; @@ -93,22 +93,27 @@ anytimestamp_typmodin(bool istz, ArrayType *ta) (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid type modifier"))); - if (*tl < 0) + return anytimestamp_typmod_check(istz, tl[0]); +} + +/* exported so parse_expr.c can use it */ +int32 +anytimestamp_typmod_check(bool istz, int32 typmod) +{ + if (typmod < 0) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("TIMESTAMP(%d)%s precision must not be negative", - *tl, (istz ? " WITH TIME ZONE" : "")))); - if (*tl > MAX_TIMESTAMP_PRECISION) + typmod, (istz ? " WITH TIME ZONE" : "")))); + if (typmod > MAX_TIMESTAMP_PRECISION) { ereport(WARNING, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("TIMESTAMP(%d)%s precision reduced to maximum allowed, %d", - *tl, (istz ? " WITH TIME ZONE" : ""), + typmod, (istz ? " WITH TIME ZONE" : ""), MAX_TIMESTAMP_PRECISION))); typmod = MAX_TIMESTAMP_PRECISION; } - else - typmod = *tl; return typmod; } @@ -336,6 +341,10 @@ timestamp_scale(PG_FUNCTION_ARGS) PG_RETURN_TIMESTAMP(result); } +/* + * AdjustTimestampForTypmod --- round off a timestamp to suit given typmod + * Works for either timestamp or timestamptz. + */ static void AdjustTimestampForTypmod(Timestamp *time, int32 typmod) { @@ -1686,6 +1695,34 @@ IntegerTimestampToTimestampTz(int64 timestamp) } #endif +/* + * GetSQLCurrentTimestamp -- implements CURRENT_TIMESTAMP, CURRENT_TIMESTAMP(n) + */ +TimestampTz +GetSQLCurrentTimestamp(int32 typmod) +{ + TimestampTz ts; + + ts = GetCurrentTransactionStartTimestamp(); + if (typmod >= 0) + AdjustTimestampForTypmod(&ts, typmod); + return ts; +} + +/* + * GetSQLLocalTimestamp -- implements LOCALTIMESTAMP, LOCALTIMESTAMP(n) + */ +Timestamp +GetSQLLocalTimestamp(int32 typmod) +{ + Timestamp ts; + + ts = timestamptz2timestamp(GetCurrentTransactionStartTimestamp()); + if (typmod >= 0) + AdjustTimestampForTypmod(&ts, typmod); + return ts; +} + /* * TimestampDifference -- convert the difference between two timestamps * into integer seconds and microseconds @@ -5415,6 +5452,13 @@ Datum timestamptz_timestamp(PG_FUNCTION_ARGS) { TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(0); + + PG_RETURN_TIMESTAMP(timestamptz2timestamp(timestamp)); +} + +static Timestamp +timestamptz2timestamp(TimestampTz timestamp) +{ Timestamp result; struct pg_tm tt, *tm = &tt; @@ -5434,7 +5478,7 @@ timestamptz_timestamp(PG_FUNCTION_ARGS) (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); } - PG_RETURN_TIMESTAMP(result); + return result; } /* timestamptz_zone() -- cgit v1.2.3