diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2016-08-16 20:33:01 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2016-08-16 20:33:01 -0400 |
commit | 0bb51aa96783e8a6c473c2b5e3725e23e95db834 (patch) | |
tree | f4d4077257f5a4937fefafd0fe6f914f5e4027fd /src/backend/utils/adt/date.c | |
parent | 4bc4cfe3bd186b4a1d1b01279bfd0e6ab11268b2 (diff) | |
download | postgresql-0bb51aa96783e8a6c473c2b5e3725e23e95db834.tar.gz postgresql-0bb51aa96783e8a6c473c2b5e3725e23e95db834.zip |
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>
Diffstat (limited to 'src/backend/utils/adt/date.c')
-rw-r--r-- | src/backend/utils/adt/date.c | 93 |
1 files changed, 86 insertions, 7 deletions
diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c index 420f383a804..bc7d190210a 100644 --- a/src/backend/utils/adt/date.c +++ b/src/backend/utils/adt/date.c @@ -21,6 +21,7 @@ #include <time.h> #include "access/hash.h" +#include "access/xact.h" #include "libpq/pqformat.h" #include "miscadmin.h" #include "parser/scansup.h" @@ -51,7 +52,6 @@ static void AdjustTimeForTypmod(TimeADT *time, int32 typmod); static int32 anytime_typmodin(bool istz, ArrayType *ta) { - int32 typmod; int32 *tl; int n; @@ -66,22 +66,27 @@ anytime_typmodin(bool istz, ArrayType *ta) (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid type modifier"))); - if (*tl < 0) + return anytime_typmod_check(istz, tl[0]); +} + +/* exported so parse_expr.c can use it */ +int32 +anytime_typmod_check(bool istz, int32 typmod) +{ + if (typmod < 0) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("TIME(%d)%s precision must not be negative", - *tl, (istz ? " WITH TIME ZONE" : "")))); - if (*tl > MAX_TIME_PRECISION) + typmod, (istz ? " WITH TIME ZONE" : "")))); + if (typmod > MAX_TIME_PRECISION) { ereport(WARNING, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("TIME(%d)%s precision reduced to maximum allowed, %d", - *tl, (istz ? " WITH TIME ZONE" : ""), + typmod, (istz ? " WITH TIME ZONE" : ""), MAX_TIME_PRECISION))); typmod = MAX_TIME_PRECISION; } - else - typmod = *tl; return typmod; } @@ -299,6 +304,80 @@ EncodeSpecialDate(DateADT dt, char *str) /* + * GetSQLCurrentDate -- implements CURRENT_DATE + */ +DateADT +GetSQLCurrentDate(void) +{ + TimestampTz ts; + struct pg_tm tt, + *tm = &tt; + fsec_t fsec; + int tz; + + ts = GetCurrentTransactionStartTimestamp(); + + if (timestamp2tm(ts, &tz, tm, &fsec, NULL, NULL) != 0) + ereport(ERROR, + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), + errmsg("timestamp out of range"))); + + return date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE; +} + +/* + * GetSQLCurrentTime -- implements CURRENT_TIME, CURRENT_TIME(n) + */ +TimeTzADT * +GetSQLCurrentTime(int32 typmod) +{ + TimeTzADT *result; + TimestampTz ts; + struct pg_tm tt, + *tm = &tt; + fsec_t fsec; + int tz; + + ts = GetCurrentTransactionStartTimestamp(); + + if (timestamp2tm(ts, &tz, tm, &fsec, NULL, NULL) != 0) + ereport(ERROR, + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), + errmsg("timestamp out of range"))); + + result = (TimeTzADT *) palloc(sizeof(TimeTzADT)); + tm2timetz(tm, fsec, tz, result); + AdjustTimeForTypmod(&(result->time), typmod); + return result; +} + +/* + * GetSQLLocalTime -- implements LOCALTIME, LOCALTIME(n) + */ +TimeADT +GetSQLLocalTime(int32 typmod) +{ + TimeADT result; + TimestampTz ts; + struct pg_tm tt, + *tm = &tt; + fsec_t fsec; + int tz; + + ts = GetCurrentTransactionStartTimestamp(); + + if (timestamp2tm(ts, &tz, tm, &fsec, NULL, NULL) != 0) + ereport(ERROR, + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), + errmsg("timestamp out of range"))); + + tm2time(tm, fsec, &result); + AdjustTimeForTypmod(&result, typmod); + return result; +} + + +/* * Comparison functions for dates */ |