Error in from_char() for field 'D'?

Started by Brendan Jurdabout 19 years ago4 messages
#1Brendan Jurd
direvus@gmail.com

Hey hackers,

I was doing some work in backend/utils/adt/formatting.c, and found the
following:

case DCH_D:
INVALID_FOR_INTERVAL;
if (is_to_char)
{
sprintf(inout, "%d", tm->tm_wday + 1);
if (S_THth(suf))
str_numth(p_inout, inout, S_TH_TYPE(suf));
return strlen(p_inout);
}
else
{
sscanf(inout, "%1d", &tmfc->d);
return strspace_len(inout) + 1 + SKIP_THth(suf);
}

The tm_wday field is internally stored as an integer 0 - 6, with 0
being Sunday. The 'D' formatting field, as per the documentation,
gives 1 - 7 with 1 being Sunday. So to convert tm_wday to 'D' in
to_char(), you add one. This works as expected.

However, in from_char(), the reverse is not true. Looking at the code
snippet above, the digit is scanned straight into tmfc->d unaltered
(this value is later copied directly to tm->tm_wday circa line 3394).

Unless I'm missing something, when converting to text, 'D' yields 1-7,
but when converting back from text, 'D' expects 0-6.

It's not a major problem, since there's not really a use-case for
specifying dates for conversion with the 'D' field, but this behaviour
appears to be incorrect, or at the very least, incorrectly documented.

The fix should be trivial; subtract one from tmfc->d after the call to sscanf()

Regards,
BJ

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Brendan Jurd (#1)
Re: Error in from_char() for field 'D'?

"Brendan Jurd" <direvus@gmail.com> writes:

However, in from_char(), the reverse is not true. Looking at the code
snippet above, the digit is scanned straight into tmfc->d unaltered
(this value is later copied directly to tm->tm_wday circa line 3394).
Unless I'm missing something, when converting to text, 'D' yields 1-7,
but when converting back from text, 'D' expects 0-6.

Although this does look like a bug, I'm not sure it matters, because
AFAICS there is no code path that will look at the value of tm_wday
while constructing a timestamp value from a struct tm. I'm inclined
not to risk messing with it just before RC1 unless a visible fault
can be demonstrated.

regards, tom lane

#3Bruce Momjian
bruce@momjian.us
In reply to: Tom Lane (#2)
Re: Error in from_char() for field 'D'?

This has been saved for the 8.3 release:

http://momjian.postgresql.org/cgi-bin/pgpatches_hold

---------------------------------------------------------------------------

Tom Lane wrote:

"Brendan Jurd" <direvus@gmail.com> writes:

However, in from_char(), the reverse is not true. Looking at the code
snippet above, the digit is scanned straight into tmfc->d unaltered
(this value is later copied directly to tm->tm_wday circa line 3394).
Unless I'm missing something, when converting to text, 'D' yields 1-7,
but when converting back from text, 'D' expects 0-6.

Although this does look like a bug, I'm not sure it matters, because
AFAICS there is no code path that will look at the value of tm_wday
while constructing a timestamp value from a struct tm. I'm inclined
not to risk messing with it just before RC1 unless a visible fault
can be demonstrated.

regards, tom lane

---------------------------(end of broadcast)---------------------------
TIP 9: In versions below 8.0, the planner will ignore your desire to
choose an index scan if your joining column's datatypes do not
match

--
Bruce Momjian bruce@momjian.us
EnterpriseDB http://www.enterprisedb.com

+ If your life is a hard drive, Christ can be your backup. +

#4Bruce Momjian
bruce@momjian.us
In reply to: Tom Lane (#2)
1 attachment(s)
Re: [HACKERS] Error in from_char() for field 'D'?

Tom Lane wrote:

"Brendan Jurd" <direvus@gmail.com> writes:

However, in from_char(), the reverse is not true. Looking at the code
snippet above, the digit is scanned straight into tmfc->d unaltered
(this value is later copied directly to tm->tm_wday circa line 3394).
Unless I'm missing something, when converting to text, 'D' yields 1-7,
but when converting back from text, 'D' expects 0-6.

Although this does look like a bug, I'm not sure it matters, because
AFAICS there is no code path that will look at the value of tm_wday
while constructing a timestamp value from a struct tm. I'm inclined
not to risk messing with it just before RC1 unless a visible fault
can be demonstrated.

Fixed in 8.3, patch attached.

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://www.enterprisedb.com

+ If your life is a hard drive, Christ can be your backup. +

Attachments:

/rtmp/difftext/x-diffDownload
Index: src/backend/utils/adt/formatting.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v
retrieving revision 1.123
diff -c -c -r1.123 formatting.c
*** src/backend/utils/adt/formatting.c	13 Feb 2007 02:00:55 -0000	1.123
--- src/backend/utils/adt/formatting.c	14 Feb 2007 05:07:34 -0000
***************
*** 2484,2489 ****
--- 2484,2490 ----
  			else
  			{
  				sscanf(inout, "%1d", &tmfc->d);
+ 				tmfc->d--;
  				return strspace_len(inout) + 1 + SKIP_THth(suf);
  			}
  			break;