@@ -4620,9 +4620,6 @@ timestamp_trunc(PG_FUNCTION_ARGS)
46204620 struct pg_tm tt ,
46214621 * tm = & tt ;
46224622
4623- if (TIMESTAMP_NOT_FINITE (timestamp ))
4624- PG_RETURN_TIMESTAMP (timestamp );
4625-
46264623 lowunits = downcase_truncate_identifier (VARDATA_ANY (units ),
46274624 VARSIZE_ANY_EXHDR (units ),
46284625 false);
@@ -4631,6 +4628,39 @@ timestamp_trunc(PG_FUNCTION_ARGS)
46314628
46324629 if (type == UNITS )
46334630 {
4631+ if (TIMESTAMP_NOT_FINITE (timestamp ))
4632+ {
4633+ /*
4634+ * Errors thrown here for invalid units should exactly match those
4635+ * below, else there will be unexpected discrepancies between
4636+ * finite- and infinite-input cases.
4637+ */
4638+ switch (val )
4639+ {
4640+ case DTK_WEEK :
4641+ case DTK_MILLENNIUM :
4642+ case DTK_CENTURY :
4643+ case DTK_DECADE :
4644+ case DTK_YEAR :
4645+ case DTK_QUARTER :
4646+ case DTK_MONTH :
4647+ case DTK_DAY :
4648+ case DTK_HOUR :
4649+ case DTK_MINUTE :
4650+ case DTK_SECOND :
4651+ case DTK_MILLISEC :
4652+ case DTK_MICROSEC :
4653+ PG_RETURN_TIMESTAMP (timestamp );
4654+ break ;
4655+ default :
4656+ ereport (ERROR ,
4657+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
4658+ errmsg ("unit \"%s\" not supported for type %s" ,
4659+ lowunits , format_type_be (TIMESTAMPOID ))));
4660+ result = 0 ;
4661+ }
4662+ }
4663+
46344664 if (timestamp2tm (timestamp , NULL , tm , & fsec , NULL , NULL ) != 0 )
46354665 ereport (ERROR ,
46364666 (errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
@@ -4836,6 +4866,40 @@ timestamptz_trunc_internal(text *units, TimestampTz timestamp, pg_tz *tzp)
48364866
48374867 if (type == UNITS )
48384868 {
4869+ if (TIMESTAMP_NOT_FINITE (timestamp ))
4870+ {
4871+ /*
4872+ * Errors thrown here for invalid units should exactly match those
4873+ * below, else there will be unexpected discrepancies between
4874+ * finite- and infinite-input cases.
4875+ */
4876+ switch (val )
4877+ {
4878+ case DTK_WEEK :
4879+ case DTK_MILLENNIUM :
4880+ case DTK_CENTURY :
4881+ case DTK_DECADE :
4882+ case DTK_YEAR :
4883+ case DTK_QUARTER :
4884+ case DTK_MONTH :
4885+ case DTK_DAY :
4886+ case DTK_HOUR :
4887+ case DTK_MINUTE :
4888+ case DTK_SECOND :
4889+ case DTK_MILLISEC :
4890+ case DTK_MICROSEC :
4891+ PG_RETURN_TIMESTAMPTZ (timestamp );
4892+ break ;
4893+
4894+ default :
4895+ ereport (ERROR ,
4896+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
4897+ errmsg ("unit \"%s\" not supported for type %s" ,
4898+ lowunits , format_type_be (TIMESTAMPTZOID ))));
4899+ result = 0 ;
4900+ }
4901+ }
4902+
48394903 if (timestamp2tm (timestamp , & tz , tm , & fsec , NULL , tzp ) != 0 )
48404904 ereport (ERROR ,
48414905 (errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
@@ -4966,9 +5030,6 @@ timestamptz_trunc(PG_FUNCTION_ARGS)
49665030 TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ (1 );
49675031 TimestampTz result ;
49685032
4969- if (TIMESTAMP_NOT_FINITE (timestamp ))
4970- PG_RETURN_TIMESTAMPTZ (timestamp );
4971-
49725033 result = timestamptz_trunc_internal (units , timestamp , session_timezone );
49735034
49745035 PG_RETURN_TIMESTAMPTZ (result );
@@ -4986,13 +5047,6 @@ timestamptz_trunc_zone(PG_FUNCTION_ARGS)
49865047 TimestampTz result ;
49875048 pg_tz * tzp ;
49885049
4989- /*
4990- * timestamptz_zone() doesn't look up the zone for infinite inputs, so we
4991- * don't do so here either.
4992- */
4993- if (TIMESTAMP_NOT_FINITE (timestamp ))
4994- PG_RETURN_TIMESTAMP (timestamp );
4995-
49965050 /*
49975051 * Look up the requested timezone.
49985052 */
@@ -5020,12 +5074,6 @@ interval_trunc(PG_FUNCTION_ARGS)
50205074
50215075 result = (Interval * ) palloc (sizeof (Interval ));
50225076
5023- if (INTERVAL_NOT_FINITE (interval ))
5024- {
5025- memcpy (result , interval , sizeof (Interval ));
5026- PG_RETURN_INTERVAL_P (result );
5027- }
5028-
50295077 lowunits = downcase_truncate_identifier (VARDATA_ANY (units ),
50305078 VARSIZE_ANY_EXHDR (units ),
50315079 false);
@@ -5034,6 +5082,41 @@ interval_trunc(PG_FUNCTION_ARGS)
50345082
50355083 if (type == UNITS )
50365084 {
5085+ if (INTERVAL_NOT_FINITE (interval ))
5086+ {
5087+ /*
5088+ * Errors thrown here for invalid units should exactly match those
5089+ * below, else there will be unexpected discrepancies between
5090+ * finite- and infinite-input cases.
5091+ */
5092+ switch (val )
5093+ {
5094+ case DTK_MILLENNIUM :
5095+ case DTK_CENTURY :
5096+ case DTK_DECADE :
5097+ case DTK_YEAR :
5098+ case DTK_QUARTER :
5099+ case DTK_MONTH :
5100+ case DTK_DAY :
5101+ case DTK_HOUR :
5102+ case DTK_MINUTE :
5103+ case DTK_SECOND :
5104+ case DTK_MILLISEC :
5105+ case DTK_MICROSEC :
5106+ memcpy (result , interval , sizeof (Interval ));
5107+ PG_RETURN_INTERVAL_P (result );
5108+ break ;
5109+
5110+ default :
5111+ ereport (ERROR ,
5112+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
5113+ errmsg ("unit \"%s\" not supported for type %s" ,
5114+ lowunits , format_type_be (INTERVALOID )),
5115+ (val == DTK_WEEK ) ? errdetail ("Months usually have fractional weeks." ) : 0 ));
5116+ result = 0 ;
5117+ }
5118+ }
5119+
50375120 interval2itm (* interval , tm );
50385121 switch (val )
50395122 {
0 commit comments