aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/timestamp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/timestamp.c')
-rw-r--r--src/backend/utils/adt/timestamp.c121
1 files changed, 102 insertions, 19 deletions
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 18d7d8a108a..1b33eb6ea8d 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -4620,9 +4620,6 @@ timestamp_trunc(PG_FUNCTION_ARGS)
struct pg_tm tt,
*tm = &tt;
- if (TIMESTAMP_NOT_FINITE(timestamp))
- PG_RETURN_TIMESTAMP(timestamp);
-
lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
VARSIZE_ANY_EXHDR(units),
false);
@@ -4631,6 +4628,39 @@ timestamp_trunc(PG_FUNCTION_ARGS)
if (type == UNITS)
{
+ if (TIMESTAMP_NOT_FINITE(timestamp))
+ {
+ /*
+ * Errors thrown here for invalid units should exactly match those
+ * below, else there will be unexpected discrepancies between
+ * finite- and infinite-input cases.
+ */
+ switch (val)
+ {
+ case DTK_WEEK:
+ case DTK_MILLENNIUM:
+ case DTK_CENTURY:
+ case DTK_DECADE:
+ case DTK_YEAR:
+ case DTK_QUARTER:
+ case DTK_MONTH:
+ case DTK_DAY:
+ case DTK_HOUR:
+ case DTK_MINUTE:
+ case DTK_SECOND:
+ case DTK_MILLISEC:
+ case DTK_MICROSEC:
+ PG_RETURN_TIMESTAMP(timestamp);
+ break;
+ default:
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("unit \"%s\" not supported for type %s",
+ lowunits, format_type_be(TIMESTAMPOID))));
+ result = 0;
+ }
+ }
+
if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
@@ -4836,6 +4866,40 @@ timestamptz_trunc_internal(text *units, TimestampTz timestamp, pg_tz *tzp)
if (type == UNITS)
{
+ if (TIMESTAMP_NOT_FINITE(timestamp))
+ {
+ /*
+ * Errors thrown here for invalid units should exactly match those
+ * below, else there will be unexpected discrepancies between
+ * finite- and infinite-input cases.
+ */
+ switch (val)
+ {
+ case DTK_WEEK:
+ case DTK_MILLENNIUM:
+ case DTK_CENTURY:
+ case DTK_DECADE:
+ case DTK_YEAR:
+ case DTK_QUARTER:
+ case DTK_MONTH:
+ case DTK_DAY:
+ case DTK_HOUR:
+ case DTK_MINUTE:
+ case DTK_SECOND:
+ case DTK_MILLISEC:
+ case DTK_MICROSEC:
+ PG_RETURN_TIMESTAMPTZ(timestamp);
+ break;
+
+ default:
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("unit \"%s\" not supported for type %s",
+ lowunits, format_type_be(TIMESTAMPTZOID))));
+ result = 0;
+ }
+ }
+
if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, tzp) != 0)
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
@@ -4966,9 +5030,6 @@ timestamptz_trunc(PG_FUNCTION_ARGS)
TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(1);
TimestampTz result;
- if (TIMESTAMP_NOT_FINITE(timestamp))
- PG_RETURN_TIMESTAMPTZ(timestamp);
-
result = timestamptz_trunc_internal(units, timestamp, session_timezone);
PG_RETURN_TIMESTAMPTZ(result);
@@ -4987,13 +5048,6 @@ timestamptz_trunc_zone(PG_FUNCTION_ARGS)
pg_tz *tzp;
/*
- * timestamptz_zone() doesn't look up the zone for infinite inputs, so we
- * don't do so here either.
- */
- if (TIMESTAMP_NOT_FINITE(timestamp))
- PG_RETURN_TIMESTAMP(timestamp);
-
- /*
* Look up the requested timezone.
*/
tzp = lookup_timezone(zone);
@@ -5020,12 +5074,6 @@ interval_trunc(PG_FUNCTION_ARGS)
result = (Interval *) palloc(sizeof(Interval));
- if (INTERVAL_NOT_FINITE(interval))
- {
- memcpy(result, interval, sizeof(Interval));
- PG_RETURN_INTERVAL_P(result);
- }
-
lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
VARSIZE_ANY_EXHDR(units),
false);
@@ -5034,6 +5082,41 @@ interval_trunc(PG_FUNCTION_ARGS)
if (type == UNITS)
{
+ if (INTERVAL_NOT_FINITE(interval))
+ {
+ /*
+ * Errors thrown here for invalid units should exactly match those
+ * below, else there will be unexpected discrepancies between
+ * finite- and infinite-input cases.
+ */
+ switch (val)
+ {
+ case DTK_MILLENNIUM:
+ case DTK_CENTURY:
+ case DTK_DECADE:
+ case DTK_YEAR:
+ case DTK_QUARTER:
+ case DTK_MONTH:
+ case DTK_DAY:
+ case DTK_HOUR:
+ case DTK_MINUTE:
+ case DTK_SECOND:
+ case DTK_MILLISEC:
+ case DTK_MICROSEC:
+ memcpy(result, interval, sizeof(Interval));
+ PG_RETURN_INTERVAL_P(result);
+ break;
+
+ default:
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("unit \"%s\" not supported for type %s",
+ lowunits, format_type_be(INTERVALOID)),
+ (val == DTK_WEEK) ? errdetail("Months usually have fractional weeks.") : 0));
+ result = 0;
+ }
+ }
+
interval2itm(*interval, tm);
switch (val)
{