Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 9aae815

Browse files
committed
Re-allow input of Julian dates prior to 0001-01-01 AD.
This was unintentionally broken in 8.4 while tightening up checking of ordinary non-Julian date inputs to forbid references to "year zero". Per bug #5672 from Benjamin Gigot.
1 parent 804b276 commit 9aae815

File tree

3 files changed

+41
-12
lines changed

3 files changed

+41
-12
lines changed

src/backend/utils/adt/datetime.c

+25-12
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ static int DecodeTimezone(char *str, int *tzp);
4242
static const datetkn *datebsearch(const char *key, const datetkn *base, int nel);
4343
static int DecodeDate(char *str, int fmask, int *tmask, bool *is2digits,
4444
struct pg_tm * tm);
45-
static int ValidateDate(int fmask, bool is2digits, bool bc,
45+
static int ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc,
4646
struct pg_tm * tm);
4747
static void TrimTrailingZeros(char *str);
4848
static void AppendSeconds(char *cp, int sec, fsec_t fsec,
@@ -795,6 +795,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
795795
int dterr;
796796
int mer = HR24;
797797
bool haveTextMonth = FALSE;
798+
bool isjulian = FALSE;
798799
bool is2digits = FALSE;
799800
bool bc = FALSE;
800801
pg_tz *namedTz = NULL;
@@ -833,10 +834,12 @@ DecodeDateTime(char **field, int *ftype, int nf,
833834

834835
errno = 0;
835836
val = strtoi(field[i], &cp, 10);
836-
if (errno == ERANGE)
837+
if (errno == ERANGE || val < 0)
837838
return DTERR_FIELD_OVERFLOW;
838839

839840
j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
841+
isjulian = TRUE;
842+
840843
/* Get the time zone from the end of the string */
841844
dterr = DecodeTimezone(cp, tzp);
842845
if (dterr)
@@ -1065,11 +1068,13 @@ DecodeDateTime(char **field, int *ftype, int nf,
10651068
break;
10661069

10671070
case DTK_JULIAN:
1068-
/***
1069-
* previous field was a label for "julian date"?
1070-
***/
1071+
/* previous field was a label for "julian date" */
1072+
if (val < 0)
1073+
return DTERR_FIELD_OVERFLOW;
10711074
tmask = DTK_DATE_M;
10721075
j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
1076+
isjulian = TRUE;
1077+
10731078
/* fractional Julian Day? */
10741079
if (*cp == '.')
10751080
{
@@ -1361,7 +1366,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
13611366
} /* end loop over fields */
13621367

13631368
/* do final checking/adjustment of Y/M/D fields */
1364-
dterr = ValidateDate(fmask, is2digits, bc, tm);
1369+
dterr = ValidateDate(fmask, isjulian, is2digits, bc, tm);
13651370
if (dterr)
13661371
return dterr;
13671372

@@ -1564,6 +1569,7 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
15641569
int i;
15651570
int val;
15661571
int dterr;
1572+
bool isjulian = FALSE;
15671573
bool is2digits = FALSE;
15681574
bool bc = FALSE;
15691575
int mer = HR24;
@@ -1795,11 +1801,13 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
17951801
break;
17961802

17971803
case DTK_JULIAN:
1798-
/***
1799-
* previous field was a label for "julian date"?
1800-
***/
1804+
/* previous field was a label for "julian date" */
1805+
if (val < 0)
1806+
return DTERR_FIELD_OVERFLOW;
18011807
tmask = DTK_DATE_M;
18021808
j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
1809+
isjulian = TRUE;
1810+
18031811
if (*cp == '.')
18041812
{
18051813
double time;
@@ -2045,7 +2053,7 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
20452053
} /* end loop over fields */
20462054

20472055
/* do final checking/adjustment of Y/M/D fields */
2048-
dterr = ValidateDate(fmask, is2digits, bc, tm);
2056+
dterr = ValidateDate(fmask, isjulian, is2digits, bc, tm);
20492057
if (dterr)
20502058
return dterr;
20512059

@@ -2247,11 +2255,16 @@ DecodeDate(char *str, int fmask, int *tmask, bool *is2digits,
22472255
* Return 0 if okay, a DTERR code if not.
22482256
*/
22492257
static int
2250-
ValidateDate(int fmask, bool is2digits, bool bc, struct pg_tm * tm)
2258+
ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc,
2259+
struct pg_tm * tm)
22512260
{
22522261
if (fmask & DTK_M(YEAR))
22532262
{
2254-
if (bc)
2263+
if (isjulian)
2264+
{
2265+
/* tm_year is correct and should not be touched */
2266+
}
2267+
else if (bc)
22552268
{
22562269
/* there is no year zero in AD/BC notation */
22572270
if (tm->tm_year <= 0)

src/test/regress/expected/horology.out

+13
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,19 @@ SELECT time with time zone 'T040506.789 -08';
264264
(1 row)
265265

266266
SET DateStyle = 'Postgres, MDY';
267+
-- Check Julian dates BC
268+
SELECT date 'J1520447' AS "Confucius' Birthday";
269+
Confucius' Birthday
270+
---------------------
271+
09-28-0551 BC
272+
(1 row)
273+
274+
SELECT date 'J0' AS "Julian Epoch";
275+
Julian Epoch
276+
---------------
277+
11-24-4714 BC
278+
(1 row)
279+
267280
--
268281
-- date, time arithmetic
269282
--

src/test/regress/sql/horology.sql

+3
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ SELECT time with time zone 'T040506.789-08';
5656
SELECT time with time zone 'T040506.789 +08';
5757
SELECT time with time zone 'T040506.789 -08';
5858
SET DateStyle = 'Postgres, MDY';
59+
-- Check Julian dates BC
60+
SELECT date 'J1520447' AS "Confucius' Birthday";
61+
SELECT date 'J0' AS "Julian Epoch";
5962

6063
--
6164
-- date, time arithmetic

0 commit comments

Comments
 (0)