Bug #72609 setDate() not using a proleptic Gregorian calendar

Submitted: 10 May 2014 21:16 Modified: 31 Jul 2018 14:08
Reporter: Alan Egerton Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / J Severity:S2 (Serious)
Version: OS:Any
Assigned to: Alexander Soklakov CPU Architecture:Any

[10 May 2014 21:16] Alan Egerton
Description:
Following standard SQL, MySQL uses a proleptic Gregorian calendar - see <http://dev.mysql.com/doc/en/mysql-calendar.html>.

However, when a Java Date value is bound to a prepared statement parameter, it is converted to a string format using the default calendar of the US locale (which has Julian/Gregorian cutover and therefore is not proleptic).

Thus attempting to bind date values prior to the cutover causes the wrong value to be stored.

How to repeat:
See <http://stackoverflow.com/q/23584810> for a case in point.

Suggested fix:
In com.mysql.jdbc.PreparedStatement.newSetDateInternal(int, Date, Calendar):

	if (this.ddf == null) {
		this.ddf = new SimpleDateFormat("''yyyy-MM-dd''", Locale.US); //$NON-NLS-1$

		// now set the dateformat's calendar to be proleptic
		final GregorianCalendar proleptic = new GregorianCalendar();
		proleptic.setGregorianChange(new Date(Long.MIN_VALUE));
		this.ddf.setCalendar(proleptic);
	}
[11 May 2014 11:49] Ravi Shankar
The proposed fix should work.
Could be safer to insert the following line

proleptic.clear();

after the fix line

final GregorianCalendar proleptic = new GregorianCalendar();   

to reset all time fields? 

Please, consider also to fix the portion of code 

else
      {
        SimpleDateFormat dateFormatter = new SimpleDateFormat("''yyyy-MM-dd''", Locale.US);

        setInternal(parameterIndex, dateFormatter.format(x));

        this.parameterTypes[(parameterIndex - 1 + getParameterIndexOffset())] = 91;
      }

in
public void setDate(int parameterIndex, java.sql.Date x, Calendar cal)
    throws SQLException
[13 May 2014 8:08] Alexander Soklakov
Hi Alan,

Thank you for this interesting report.
Verified by code review.
[13 May 2014 10:03] Alan Egerton
Proposed pathfile

Attachment: patch.txt (text/plain), 12.13 KiB.

[13 May 2014 10:05] Alan Egerton
I think this problem was a little more serious than first imagined: Connector/J does not appear to be using a proleptic Gregorian calendar at all.

The patch I submitted above should, I think, correct this throughout the library: i.e. for both data modification and retrieval.  Hopefully it's useful?
[5 Jun 2014 12:59] Ravi Shankar
Can you make some prediction about when the fix will be released?
Thank you very much.
[31 Jul 2018 14:08] Daniel So
Posted by developer:
 
Added the following entry to the Connector/J 5.1.47 changelog:

"When a Java Date value was bound to a PreparedStatement parameter, attempts to format the value by a proleptic GregorianCalendar failed to make the dates proleptic, so that dates before the Julian-Gregorian cutover (October 15, 1582) were stored wrongly. With this fix, a proleptic calendar is properly used if supplied to the setDate() method. Note that when trying to retrieve dates stored that way, a proleptic GregorianCalendar must also be explicitly supplied to the getDate() method."
[2 Aug 2018 15:46] Daniel So
Posted by developer:
 
Corrected chagnelog entry to the following:

"When a Java Date value was bound to a PreparedStatement parameter, attempts to format the value by a proleptic GregorianCalendar failed to make the dates proleptic, so that dates before the Julian-Gregorian cutover (October 15, 1582) were stored wrongly. With this fix, a proleptic calendar is properly used if supplied to the setDate() method.

Note that when trying to set or retrieve dates with PreparedSatement methods, a proleptic GregorianCalendar should always be explicitly supplied to the setDate() and getDate() method. See the discussion here for details."

The entry also added to the Connector/J 8.0.13 changelog.

Related information has been added to the Connector/J 8.0 and 5.1 Developer Guides.

Portions of this website are copyright © 2001, 2002 The PHP Group

Page generated in 0.041 sec. using MySQL 8.4.7-u6-cloud

Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the respective copyright holders.
It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.