pgsql-5672

Version:

8.4.4

Bug Link:

http://archives.postgresql.org/pgsql-bugs/2010-09/msg00190.php

Patch Link:

http://git.postgresql.org/gitweb?p=postgresql.git;a=commitdiff;h=9aae81527f3174b9b6fd6366f04435310903dab2

Symptom:

Can't input julian days BC

Failure type:

Rejecting valid input

Is there any log message?

Yes

How it is diagnosed:

We reproduced the failure.

How to reproduce:

postgres=# create table datetest ( d date );

CREATE TABLE

<--The date down to 0001-01-01 is working

postgres=# INSERT INTO datetest VALUES ('J1721426');

INSERT 0 1

<--The date under 0001-01-01 is not working

postgres=# INSERT INTO datetest VALUES ('J1721425');

ERROR:  date/time field value out of range: "J1721425"

LINE 1: INSERT INTO datetest VALUES ('J1721425');

But Documentation specify that dates can go down to J0, that is 4713BC.

Root Cause:

it’s because of a side-effect of tightening up error checking for other cases. It shouldn’t throw an error for BC dates when Julian notation was used.

ValidateDate(...)
{
        if (fmask & DTK_M(YEAR))
        {
        
-       if (bc)

+       if (isjulian)

+       {

+           /* tm_year is correct and should not be touched */

+       }

+       else if (bc)

                ...
                 else if (is2digits)
                        ...
                 else
                 {
                        /* there is no year zero in AD/BC notation */

                <--in the buggy case, tm->tm_year==0
                        if (tm->tm_year <= 0)
                                return
DTERR_FIELD_OVERFLOW;
                 }
        }

...

}

DecodeDateTime(...)

{

        ...

        dterr = ValidateDate(fmask, is2digits, bc, tm);

        if (dterr)

                return dterr;

        ...

}

date_in(PG_FUNCTION_ARGS)

{

        ...

        if (dterr == 0)

                dterr = DecodeDateTime(...);

        if (dterr != 0)

                DateTimeParseError(dterr, str, "date");

        ...

}

Where the log message is  printed:

DateTimeParseError(int dterr, const char *str, const char *datatype)

{

        switch (dterr)

        {

                case DTERR_FIELD_OVERFLOW:

                        ereport(ERROR,                                                 

(errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),

                                errmsg("date/time field value out of range: \"%s\"",

                                str)));

                …

        }

        

}

Pattern of the failure:

(ValidateDate) return value check