@@ -4311,6 +4311,83 @@ date2isoyearday(int year, int mon, int mday)
4311
4311
return date2j (year , mon , mday ) - isoweek2j (date2isoyear (year , mon , mday ), 1 ) + 1 ;
4312
4312
}
4313
4313
4314
+ /*
4315
+ * NonFiniteTimestampTzPart
4316
+ *
4317
+ * Used by timestamp_part and timestamptz_part when extracting from infinite
4318
+ * timestamp[tz]. Returns +/-Infinity if that is the appropriate result,
4319
+ * otherwise returns zero (which should be taken as meaning to return NULL).
4320
+ *
4321
+ * Errors thrown here for invalid units should exactly match those that
4322
+ * would be thrown in the calling functions, else there will be unexpected
4323
+ * discrepancies between finite- and infinite-input cases.
4324
+ */
4325
+ static float8
4326
+ NonFiniteTimestampTzPart (int type , int unit , char * lowunits ,
4327
+ bool isNegative , bool isTz )
4328
+ {
4329
+ if ((type != UNITS ) && (type != RESERV ))
4330
+ {
4331
+ if (isTz )
4332
+ ereport (ERROR ,
4333
+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
4334
+ errmsg ("timestamp with time zone units \"%s\" not recognized" ,
4335
+ lowunits )));
4336
+ else
4337
+ ereport (ERROR ,
4338
+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
4339
+ errmsg ("timestamp units \"%s\" not recognized" ,
4340
+ lowunits )));
4341
+ }
4342
+
4343
+ switch (unit )
4344
+ {
4345
+ /* Oscillating units */
4346
+ case DTK_MICROSEC :
4347
+ case DTK_MILLISEC :
4348
+ case DTK_SECOND :
4349
+ case DTK_MINUTE :
4350
+ case DTK_HOUR :
4351
+ case DTK_DAY :
4352
+ case DTK_MONTH :
4353
+ case DTK_QUARTER :
4354
+ case DTK_WEEK :
4355
+ case DTK_DOW :
4356
+ case DTK_ISODOW :
4357
+ case DTK_DOY :
4358
+ case DTK_TZ :
4359
+ case DTK_TZ_MINUTE :
4360
+ case DTK_TZ_HOUR :
4361
+ return 0.0 ;
4362
+
4363
+ /* Monotonically-increasing units */
4364
+ case DTK_YEAR :
4365
+ case DTK_DECADE :
4366
+ case DTK_CENTURY :
4367
+ case DTK_MILLENNIUM :
4368
+ case DTK_JULIAN :
4369
+ case DTK_ISOYEAR :
4370
+ case DTK_EPOCH :
4371
+ if (isNegative )
4372
+ return - get_float8_infinity ();
4373
+ else
4374
+ return get_float8_infinity ();
4375
+
4376
+ default :
4377
+ if (isTz )
4378
+ ereport (ERROR ,
4379
+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
4380
+ errmsg ("timestamp with time zone units \"%s\" not supported" ,
4381
+ lowunits )));
4382
+ else
4383
+ ereport (ERROR ,
4384
+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
4385
+ errmsg ("timestamp units \"%s\" not supported" ,
4386
+ lowunits )));
4387
+ return 0.0 ; /* keep compiler quiet */
4388
+ }
4389
+ }
4390
+
4314
4391
/* timestamp_part()
4315
4392
* Extract specified field from timestamp.
4316
4393
*/
@@ -4327,12 +4404,6 @@ timestamp_part(PG_FUNCTION_ARGS)
4327
4404
struct pg_tm tt ,
4328
4405
* tm = & tt ;
4329
4406
4330
- if (TIMESTAMP_NOT_FINITE (timestamp ))
4331
- {
4332
- result = 0 ;
4333
- PG_RETURN_FLOAT8 (result );
4334
- }
4335
-
4336
4407
lowunits = downcase_truncate_identifier (VARDATA_ANY (units ),
4337
4408
VARSIZE_ANY_EXHDR (units ),
4338
4409
false);
@@ -4341,6 +4412,17 @@ timestamp_part(PG_FUNCTION_ARGS)
4341
4412
if (type == UNKNOWN_FIELD )
4342
4413
type = DecodeSpecial (0 , lowunits , & val );
4343
4414
4415
+ if (TIMESTAMP_NOT_FINITE (timestamp ))
4416
+ {
4417
+ result = NonFiniteTimestampTzPart (type , val , lowunits ,
4418
+ TIMESTAMP_IS_NOBEGIN (timestamp ),
4419
+ false);
4420
+ if (result )
4421
+ PG_RETURN_FLOAT8 (result );
4422
+ else
4423
+ PG_RETURN_NULL ();
4424
+ }
4425
+
4344
4426
if (type == UNITS )
4345
4427
{
4346
4428
if (timestamp2tm (timestamp , NULL , tm , & fsec , NULL , NULL ) != 0 )
@@ -4538,12 +4620,6 @@ timestamptz_part(PG_FUNCTION_ARGS)
4538
4620
struct pg_tm tt ,
4539
4621
* tm = & tt ;
4540
4622
4541
- if (TIMESTAMP_NOT_FINITE (timestamp ))
4542
- {
4543
- result = 0 ;
4544
- PG_RETURN_FLOAT8 (result );
4545
- }
4546
-
4547
4623
lowunits = downcase_truncate_identifier (VARDATA_ANY (units ),
4548
4624
VARSIZE_ANY_EXHDR (units ),
4549
4625
false);
@@ -4552,6 +4628,17 @@ timestamptz_part(PG_FUNCTION_ARGS)
4552
4628
if (type == UNKNOWN_FIELD )
4553
4629
type = DecodeSpecial (0 , lowunits , & val );
4554
4630
4631
+ if (TIMESTAMP_NOT_FINITE (timestamp ))
4632
+ {
4633
+ result = NonFiniteTimestampTzPart (type , val , lowunits ,
4634
+ TIMESTAMP_IS_NOBEGIN (timestamp ),
4635
+ true);
4636
+ if (result )
4637
+ PG_RETURN_FLOAT8 (result );
4638
+ else
4639
+ PG_RETURN_NULL ();
4640
+ }
4641
+
4555
4642
if (type == UNITS )
4556
4643
{
4557
4644
if (timestamp2tm (timestamp , & tz , tm , & fsec , NULL , NULL ) != 0 )
0 commit comments