Skip to content

Commit b77a9aa

Browse files
tglsfdcpull[bot]
authored andcommitted
Dodge a compiler bug affecting timetz_zone/timetz_izone.
Use a modulo operator instead of implementing the same behavior with a loop. The loop solution is doubtless microscopically faster for the typical case of only wrapping into the very next day, but maybe not so much for large interval values. In any case, timetz is such a backwater that it's doubtful anybody would notice any performance change anyway. This avoids a compiler bug occurring in AIX's xlc, even in pretty late-model revisions. We did not have test coverage for the case where the initial result->time value is negative, so add that. For the moment, install this only in HEAD. My plan is to back-patch the test case, and then the code change assuming that buildfarm testing proves the bug occurs in the back branches. (That seems pretty likely, but let's find out for sure.) Per buildfarm results from commits 97957fd and 2f04720. Thanks to Michael Paquier for the idea to use a modulo operation to replace the faulty loop. Discussion: https://postgr.es/m/CA+hUKGK=DOC+hE-62FKfZy=Ybt5uLkrg3zCZD-jFykM-iPn8yw@mail.gmail.com
1 parent 2cf4b94 commit b77a9aa

File tree

3 files changed

+32
-4
lines changed

3 files changed

+32
-4
lines changed

src/backend/utils/adt/date.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3083,10 +3083,11 @@ timetz_zone(PG_FUNCTION_ARGS)
30833083
result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
30843084

30853085
result->time = t->time + (t->zone - tz) * USECS_PER_SEC;
3086+
/* C99 modulo has the wrong sign convention for negative input */
30863087
while (result->time < INT64CONST(0))
30873088
result->time += USECS_PER_DAY;
3088-
while (result->time >= USECS_PER_DAY)
3089-
result->time -= USECS_PER_DAY;
3089+
if (result->time >= USECS_PER_DAY)
3090+
result->time %= USECS_PER_DAY;
30903091

30913092
result->zone = tz;
30923093

@@ -3116,10 +3117,11 @@ timetz_izone(PG_FUNCTION_ARGS)
31163117
result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
31173118

31183119
result->time = time->time + (time->zone - tz) * USECS_PER_SEC;
3120+
/* C99 modulo has the wrong sign convention for negative input */
31193121
while (result->time < INT64CONST(0))
31203122
result->time += USECS_PER_DAY;
3121-
while (result->time >= USECS_PER_DAY)
3122-
result->time -= USECS_PER_DAY;
3123+
if (result->time >= USECS_PER_DAY)
3124+
result->time %= USECS_PER_DAY;
31233125

31243126
result->zone = tz;
31253127

src/test/regress/expected/timetz.out

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,4 +304,25 @@ TABLE timetz_local_view;
304304
23:59:59.99-07 | 06:59:59.99+00 | 06:59:59.99+00 | 06:59:59.99+00 | 06:59:59.99+00
305305
(12 rows)
306306

307+
SELECT f1 AS dat,
308+
f1 AT TIME ZONE 'UTC+10' AS dat_at_tz,
309+
f1 AT TIME ZONE INTERVAL '-10:00' AS dat_at_int
310+
FROM TIMETZ_TBL
311+
ORDER BY f1;
312+
dat | dat_at_tz | dat_at_int
313+
----------------+----------------+----------------
314+
00:01:00-07 | 21:01:00-10 | 21:01:00-10
315+
01:00:00-07 | 22:00:00-10 | 22:00:00-10
316+
02:03:00-07 | 23:03:00-10 | 23:03:00-10
317+
08:08:00-04 | 02:08:00-10 | 02:08:00-10
318+
07:07:00-08 | 05:07:00-10 | 05:07:00-10
319+
11:59:00-07 | 08:59:00-10 | 08:59:00-10
320+
12:00:00-07 | 09:00:00-10 | 09:00:00-10
321+
12:01:00-07 | 09:01:00-10 | 09:01:00-10
322+
15:36:39-04 | 09:36:39-10 | 09:36:39-10
323+
15:36:39-05 | 10:36:39-10 | 10:36:39-10
324+
23:59:00-07 | 20:59:00-10 | 20:59:00-10
325+
23:59:59.99-07 | 20:59:59.99-10 | 20:59:59.99-10
326+
(12 rows)
327+
307328
ROLLBACK;

src/test/regress/sql/timetz.sql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,4 +100,9 @@ CREATE VIEW timetz_local_view AS
100100
ORDER BY f1;
101101
SELECT pg_get_viewdef('timetz_local_view', true);
102102
TABLE timetz_local_view;
103+
SELECT f1 AS dat,
104+
f1 AT TIME ZONE 'UTC+10' AS dat_at_tz,
105+
f1 AT TIME ZONE INTERVAL '-10:00' AS dat_at_int
106+
FROM TIMETZ_TBL
107+
ORDER BY f1;
103108
ROLLBACK;

0 commit comments

Comments
 (0)