mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-10-01 21:31:20 +02:00
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.
This commit is contained in:
parent
804b27613b
commit
9aae81527f
@ -42,7 +42,7 @@ static int DecodeTimezone(char *str, int *tzp);
|
|||||||
static const datetkn *datebsearch(const char *key, const datetkn *base, int nel);
|
static const datetkn *datebsearch(const char *key, const datetkn *base, int nel);
|
||||||
static int DecodeDate(char *str, int fmask, int *tmask, bool *is2digits,
|
static int DecodeDate(char *str, int fmask, int *tmask, bool *is2digits,
|
||||||
struct pg_tm * tm);
|
struct pg_tm * tm);
|
||||||
static int ValidateDate(int fmask, bool is2digits, bool bc,
|
static int ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc,
|
||||||
struct pg_tm * tm);
|
struct pg_tm * tm);
|
||||||
static void TrimTrailingZeros(char *str);
|
static void TrimTrailingZeros(char *str);
|
||||||
static void AppendSeconds(char *cp, int sec, fsec_t fsec,
|
static void AppendSeconds(char *cp, int sec, fsec_t fsec,
|
||||||
@ -795,6 +795,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
|||||||
int dterr;
|
int dterr;
|
||||||
int mer = HR24;
|
int mer = HR24;
|
||||||
bool haveTextMonth = FALSE;
|
bool haveTextMonth = FALSE;
|
||||||
|
bool isjulian = FALSE;
|
||||||
bool is2digits = FALSE;
|
bool is2digits = FALSE;
|
||||||
bool bc = FALSE;
|
bool bc = FALSE;
|
||||||
pg_tz *namedTz = NULL;
|
pg_tz *namedTz = NULL;
|
||||||
@ -833,10 +834,12 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
|||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
val = strtoi(field[i], &cp, 10);
|
val = strtoi(field[i], &cp, 10);
|
||||||
if (errno == ERANGE)
|
if (errno == ERANGE || val < 0)
|
||||||
return DTERR_FIELD_OVERFLOW;
|
return DTERR_FIELD_OVERFLOW;
|
||||||
|
|
||||||
j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
|
j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
|
||||||
|
isjulian = TRUE;
|
||||||
|
|
||||||
/* Get the time zone from the end of the string */
|
/* Get the time zone from the end of the string */
|
||||||
dterr = DecodeTimezone(cp, tzp);
|
dterr = DecodeTimezone(cp, tzp);
|
||||||
if (dterr)
|
if (dterr)
|
||||||
@ -1065,11 +1068,13 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case DTK_JULIAN:
|
case DTK_JULIAN:
|
||||||
/***
|
/* previous field was a label for "julian date" */
|
||||||
* previous field was a label for "julian date"?
|
if (val < 0)
|
||||||
***/
|
return DTERR_FIELD_OVERFLOW;
|
||||||
tmask = DTK_DATE_M;
|
tmask = DTK_DATE_M;
|
||||||
j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
|
j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
|
||||||
|
isjulian = TRUE;
|
||||||
|
|
||||||
/* fractional Julian Day? */
|
/* fractional Julian Day? */
|
||||||
if (*cp == '.')
|
if (*cp == '.')
|
||||||
{
|
{
|
||||||
@ -1361,7 +1366,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
|||||||
} /* end loop over fields */
|
} /* end loop over fields */
|
||||||
|
|
||||||
/* do final checking/adjustment of Y/M/D fields */
|
/* do final checking/adjustment of Y/M/D fields */
|
||||||
dterr = ValidateDate(fmask, is2digits, bc, tm);
|
dterr = ValidateDate(fmask, isjulian, is2digits, bc, tm);
|
||||||
if (dterr)
|
if (dterr)
|
||||||
return dterr;
|
return dterr;
|
||||||
|
|
||||||
@ -1564,6 +1569,7 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
|
|||||||
int i;
|
int i;
|
||||||
int val;
|
int val;
|
||||||
int dterr;
|
int dterr;
|
||||||
|
bool isjulian = FALSE;
|
||||||
bool is2digits = FALSE;
|
bool is2digits = FALSE;
|
||||||
bool bc = FALSE;
|
bool bc = FALSE;
|
||||||
int mer = HR24;
|
int mer = HR24;
|
||||||
@ -1795,11 +1801,13 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case DTK_JULIAN:
|
case DTK_JULIAN:
|
||||||
/***
|
/* previous field was a label for "julian date" */
|
||||||
* previous field was a label for "julian date"?
|
if (val < 0)
|
||||||
***/
|
return DTERR_FIELD_OVERFLOW;
|
||||||
tmask = DTK_DATE_M;
|
tmask = DTK_DATE_M;
|
||||||
j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
|
j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
|
||||||
|
isjulian = TRUE;
|
||||||
|
|
||||||
if (*cp == '.')
|
if (*cp == '.')
|
||||||
{
|
{
|
||||||
double time;
|
double time;
|
||||||
@ -2045,7 +2053,7 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
|
|||||||
} /* end loop over fields */
|
} /* end loop over fields */
|
||||||
|
|
||||||
/* do final checking/adjustment of Y/M/D fields */
|
/* do final checking/adjustment of Y/M/D fields */
|
||||||
dterr = ValidateDate(fmask, is2digits, bc, tm);
|
dterr = ValidateDate(fmask, isjulian, is2digits, bc, tm);
|
||||||
if (dterr)
|
if (dterr)
|
||||||
return dterr;
|
return dterr;
|
||||||
|
|
||||||
@ -2247,11 +2255,16 @@ DecodeDate(char *str, int fmask, int *tmask, bool *is2digits,
|
|||||||
* Return 0 if okay, a DTERR code if not.
|
* Return 0 if okay, a DTERR code if not.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
ValidateDate(int fmask, bool is2digits, bool bc, struct pg_tm * tm)
|
ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc,
|
||||||
|
struct pg_tm * tm)
|
||||||
{
|
{
|
||||||
if (fmask & DTK_M(YEAR))
|
if (fmask & DTK_M(YEAR))
|
||||||
{
|
{
|
||||||
if (bc)
|
if (isjulian)
|
||||||
|
{
|
||||||
|
/* tm_year is correct and should not be touched */
|
||||||
|
}
|
||||||
|
else if (bc)
|
||||||
{
|
{
|
||||||
/* there is no year zero in AD/BC notation */
|
/* there is no year zero in AD/BC notation */
|
||||||
if (tm->tm_year <= 0)
|
if (tm->tm_year <= 0)
|
||||||
|
@ -264,6 +264,19 @@ SELECT time with time zone 'T040506.789 -08';
|
|||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SET DateStyle = 'Postgres, MDY';
|
SET DateStyle = 'Postgres, MDY';
|
||||||
|
-- Check Julian dates BC
|
||||||
|
SELECT date 'J1520447' AS "Confucius' Birthday";
|
||||||
|
Confucius' Birthday
|
||||||
|
---------------------
|
||||||
|
09-28-0551 BC
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT date 'J0' AS "Julian Epoch";
|
||||||
|
Julian Epoch
|
||||||
|
---------------
|
||||||
|
11-24-4714 BC
|
||||||
|
(1 row)
|
||||||
|
|
||||||
--
|
--
|
||||||
-- date, time arithmetic
|
-- date, time arithmetic
|
||||||
--
|
--
|
||||||
|
@ -56,6 +56,9 @@ SELECT time with time zone 'T040506.789-08';
|
|||||||
SELECT time with time zone 'T040506.789 +08';
|
SELECT time with time zone 'T040506.789 +08';
|
||||||
SELECT time with time zone 'T040506.789 -08';
|
SELECT time with time zone 'T040506.789 -08';
|
||||||
SET DateStyle = 'Postgres, MDY';
|
SET DateStyle = 'Postgres, MDY';
|
||||||
|
-- Check Julian dates BC
|
||||||
|
SELECT date 'J1520447' AS "Confucius' Birthday";
|
||||||
|
SELECT date 'J0' AS "Julian Epoch";
|
||||||
|
|
||||||
--
|
--
|
||||||
-- date, time arithmetic
|
-- date, time arithmetic
|
||||||
|
Loading…
Reference in New Issue
Block a user