Skip to content

Commit

Permalink
Fix for BUG#22305979, WRONG RECORD UPDATED IF
Browse files Browse the repository at this point in the history
SENDFRACTIONALSECONDS=FALSE AND SMT IS SCROLLABLE.
  • Loading branch information
soklakov committed Jul 19, 2018
1 parent 3647f24 commit df80d95
Show file tree
Hide file tree
Showing 15 changed files with 491 additions and 93 deletions.
2 changes: 2 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

Version 5.1.47

- Fix for BUG#22305979, WRONG RECORD UPDATED IF SENDFRACTIONALSECONDS=FALSE AND SMT IS SCROLLABLE.

- Fix for BUG#90024 (27677574), SOME TESTS FAILED AGAINST MYSQL 8.0.5 BECAUSE OF DEPRECATED FEATURES REMOVAL.

Version 5.1.46
Expand Down
6 changes: 5 additions & 1 deletion src/com/mysql/fabric/jdbc/FabricMySQLConnectionProxy.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
The MySQL Connector/J is licensed under the terms of the GPLv2
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors.
Expand Down Expand Up @@ -3065,4 +3065,8 @@ public void setProfilerEventHandlerInstance(ProfilerEventHandler h) {

public void decachePreparedStatement(ServerPreparedStatement pstmt) throws SQLException {
}

public boolean isServerTruncatesFracSecs() {
return getActiveMySQLConnection().isServerTruncatesFracSecs();
}
}
9 changes: 5 additions & 4 deletions src/com/mysql/jdbc/BufferRow.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
The MySQL Connector/J is licensed under the terms of the GPLv2
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors.
Expand Down Expand Up @@ -544,8 +544,8 @@ public Time getTimeFast(int columnIndex, Calendar targetCalendar, TimeZone tz, b
}

@Override
public Timestamp getTimestampFast(int columnIndex, Calendar targetCalendar, TimeZone tz, boolean rollForward, MySQLConnection conn, ResultSetImpl rs)
throws SQLException {
public Timestamp getTimestampFast(int columnIndex, Calendar targetCalendar, TimeZone tz, boolean rollForward, MySQLConnection conn, ResultSetImpl rs,
boolean useGmtMillis, boolean useJDBCCompliantTimezoneShift) throws SQLException {
if (isNull(columnIndex)) {
return null;
}
Expand All @@ -556,7 +556,8 @@ public Timestamp getTimestampFast(int columnIndex, Calendar targetCalendar, Time

int offset = this.rowFromServer.getPosition();

return getTimestampFast(columnIndex, this.rowFromServer.getByteBuffer(), offset, (int) length, targetCalendar, tz, rollForward, conn, rs);
return getTimestampFast(columnIndex, this.rowFromServer.getByteBuffer(), offset, (int) length, targetCalendar, tz, rollForward, conn, rs, useGmtMillis,
useJDBCCompliantTimezoneShift);
}

@Override
Expand Down
9 changes: 5 additions & 4 deletions src/com/mysql/jdbc/ByteArrayRow.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
The MySQL Connector/J is licensed under the terms of the GPLv2
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors.
Expand Down Expand Up @@ -119,15 +119,16 @@ public long getLong(int columnIndex) {
}

@Override
public Timestamp getTimestampFast(int columnIndex, Calendar targetCalendar, TimeZone tz, boolean rollForward, MySQLConnection conn, ResultSetImpl rs)
throws SQLException {
public Timestamp getTimestampFast(int columnIndex, Calendar targetCalendar, TimeZone tz, boolean rollForward, MySQLConnection conn, ResultSetImpl rs,
boolean useGmtMillis, boolean useJDBCCompliantTimezoneShift) throws SQLException {
byte[] columnValue = this.internalRowData[columnIndex];

if (columnValue == null) {
return null;
}

return getTimestampFast(columnIndex, this.internalRowData[columnIndex], 0, columnValue.length, targetCalendar, tz, rollForward, conn, rs);
return getTimestampFast(columnIndex, this.internalRowData[columnIndex], 0, columnValue.length, targetCalendar, tz, rollForward, conn, rs, useGmtMillis,
useJDBCCompliantTimezoneShift);
}

@Override
Expand Down
7 changes: 7 additions & 0 deletions src/com/mysql/jdbc/ConnectionImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,8 @@ private static boolean nullSafeCompare(String s1, String s2) {

private boolean noBackslashEscapes = false;

private boolean serverTruncatesFracSecs = false;

private long numberOfPreparedExecutes = 0;

private long numberOfPrepares = 0;
Expand Down Expand Up @@ -3303,6 +3305,7 @@ private void initializePropsFromServer() throws SQLException {
} else if (sqlModeAsString != null) {
this.useAnsiQuotes = sqlModeAsString.indexOf("ANSI_QUOTES") != -1;
this.noBackslashEscapes = sqlModeAsString.indexOf("NO_BACKSLASH_ESCAPES") != -1;
this.serverTruncatesFracSecs = sqlModeAsString.indexOf("TIME_TRUNCATE_FRACTIONAL") != -1; // truncate instead of round
}
}
}
Expand Down Expand Up @@ -5501,6 +5504,10 @@ public void setProfilerEventHandlerInstance(ProfilerEventHandler h) {
this.eventSink = h;
}

public boolean isServerTruncatesFracSecs() {
return this.serverTruncatesFracSecs;
}

private static class NetworkTimeoutSetter implements Runnable {
private final WeakReference<ConnectionImpl> connImplRef;
private final WeakReference<MysqlIO> mysqlIoRef;
Expand Down
7 changes: 5 additions & 2 deletions src/com/mysql/jdbc/EscapeProcessor.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
The MySQL Connector/J is licensed under the terms of the GPLv2
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors.
Expand Down Expand Up @@ -373,6 +373,9 @@ private static void processTimestampToken(MySQLConnection conn, StringBuilder ne
try {
if (!conn.getUseLegacyDatetimeCode()) {
Timestamp ts = Timestamp.valueOf(argument);

ts = TimeUtil.adjustTimestampNanosPrecision(ts, 6, !conn.isServerTruncatesFracSecs());

SimpleDateFormat tsdf = new SimpleDateFormat("''yyyy-MM-dd HH:mm:ss", Locale.US);

tsdf.setTimeZone(conn.getServerTimezoneTZ());
Expand All @@ -381,7 +384,7 @@ private static void processTimestampToken(MySQLConnection conn, StringBuilder ne

if (ts.getNanos() > 0 && conn.versionMeetsMinimum(5, 6, 4)) {
newSql.append('.');
newSql.append(TimeUtil.formatNanos(ts.getNanos(), true, true));
newSql.append(TimeUtil.formatNanos(ts.getNanos(), true, 6));
}

newSql.append('\'');
Expand Down
6 changes: 5 additions & 1 deletion src/com/mysql/jdbc/MultiHostMySQLConnection.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
The MySQL Connector/J is licensed under the terms of the GPLv2
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors.
Expand Down Expand Up @@ -2498,4 +2498,8 @@ public void setEnableEscapeProcessing(boolean flag) {
public boolean isUseSSLExplicit() {
return getActiveMySQLConnection().isUseSSLExplicit();
}

public boolean isServerTruncatesFracSecs() {
return getActiveMySQLConnection().isServerTruncatesFracSecs();
}
}
4 changes: 3 additions & 1 deletion src/com/mysql/jdbc/MySQLConnection.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
The MySQL Connector/J is licensed under the terms of the GPLv2
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors.
Expand Down Expand Up @@ -212,4 +212,6 @@ ResultSetInternalMethods execSQL(StatementImpl callingStatement, String sql, int
ProfilerEventHandler getProfilerEventHandlerInstance();

void setProfilerEventHandlerInstance(ProfilerEventHandler h);

public boolean isServerTruncatesFracSecs();
}
54 changes: 40 additions & 14 deletions src/com/mysql/jdbc/PreparedStatement.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
The MySQL Connector/J is licensed under the terms of the GPLv2
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors.
Expand Down Expand Up @@ -2595,8 +2595,8 @@ private final char getSuccessor(char c, int n) {
return ((c == 'y') && (n == 2)) ? 'X'
: (((c == 'y') && (n < 4)) ? 'y' : ((c == 'y') ? 'M' : (((c == 'M') && (n == 2)) ? 'Y'
: (((c == 'M') && (n < 3)) ? 'M' : ((c == 'M') ? 'd' : (((c == 'd') && (n < 2)) ? 'd' : ((c == 'd') ? 'H' : (((c == 'H') && (n < 2))
? 'H' : ((c == 'H') ? 'm'
: (((c == 'm') && (n < 2)) ? 'm' : ((c == 'm') ? 's' : (((c == 's') && (n < 2)) ? 's' : 'W'))))))))))));
? 'H'
: ((c == 'H') ? 'm' : (((c == 'm') && (n < 2)) ? 'm' : ((c == 'm') ? 's' : (((c == 's') && (n < 2)) ? 's' : 'W'))))))))))));
}

/**
Expand Down Expand Up @@ -4168,7 +4168,15 @@ private void setTimeInternal(int parameterIndex, Time x, Calendar targetCalendar
*/
public void setTimestamp(int parameterIndex, java.sql.Timestamp x, Calendar cal) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
setTimestampInternal(parameterIndex, x, cal, cal.getTimeZone(), true);
int fractLen = -1;
if (!this.sendFractionalSeconds || !this.serverSupportsFracSecs) {
fractLen = 0;
} else if (this.parameterMetaData != null && parameterIndex <= this.parameterMetaData.metadata.fields.length && parameterIndex >= 0
&& this.parameterMetaData.metadata.getField(parameterIndex).getDecimals() > 0) {
fractLen = this.parameterMetaData.metadata.getField(parameterIndex).getDecimals();
}

setTimestampInternal(parameterIndex, x, cal, cal.getTimeZone(), true, fractLen, this.connection.getUseSSPSCompatibleTimezoneShift());
}
}

Expand All @@ -4186,7 +4194,15 @@ public void setTimestamp(int parameterIndex, java.sql.Timestamp x, Calendar cal)
*/
public void setTimestamp(int parameterIndex, Timestamp x) throws java.sql.SQLException {
synchronized (checkClosed().getConnectionMutex()) {
setTimestampInternal(parameterIndex, x, null, this.connection.getDefaultTimeZone(), false);
int fractLen = -1;
if (!this.sendFractionalSeconds || !this.serverSupportsFracSecs) {
fractLen = 0;
} else if (this.parameterMetaData != null && parameterIndex <= this.parameterMetaData.metadata.fields.length && parameterIndex >= 0) {
fractLen = this.parameterMetaData.metadata.getField(parameterIndex).getDecimals();
}

setTimestampInternal(parameterIndex, x, null, this.connection.getDefaultTimeZone(), false, fractLen,
this.connection.getUseSSPSCompatibleTimezoneShift());
}
}

Expand All @@ -4204,16 +4220,26 @@ public void setTimestamp(int parameterIndex, Timestamp x) throws java.sql.SQLExc
* @throws SQLException
* if a database-access error occurs.
*/
private void setTimestampInternal(int parameterIndex, Timestamp x, Calendar targetCalendar, TimeZone tz, boolean rollForward) throws SQLException {
protected void setTimestampInternal(int parameterIndex, Timestamp x, Calendar targetCalendar, TimeZone tz, boolean rollForward, int fractionalLength,
boolean useSSPSCompatibleTimezoneShift) throws SQLException {
if (x == null) {
setNull(parameterIndex, java.sql.Types.TIMESTAMP);
} else {
checkClosed();

if (!this.sendFractionalSeconds) {
x = (Timestamp) x.clone();

if (!this.serverSupportsFracSecs || !this.sendFractionalSeconds && fractionalLength == 0) {
x = TimeUtil.truncateFractionalSeconds(x);
}

if (fractionalLength < 0) {
// default to 6 fractional positions
fractionalLength = 6;
}

x = TimeUtil.adjustTimestampNanosPrecision(x, fractionalLength, !this.connection.isServerTruncatesFracSecs());

if (!this.useLegacyDatetimeCode) {
newSetTimestampInternal(parameterIndex, x, targetCalendar);
} else {
Expand All @@ -4222,8 +4248,8 @@ private void setTimestampInternal(int parameterIndex, Timestamp x, Calendar targ

x = TimeUtil.changeTimezone(this.connection, sessionCalendar, targetCalendar, x, tz, this.connection.getServerTimezoneTZ(), rollForward);

if (this.connection.getUseSSPSCompatibleTimezoneShift()) {
doSSPSCompatibleTimezoneShift(parameterIndex, x);
if (useSSPSCompatibleTimezoneShift) {
doSSPSCompatibleTimezoneShift(parameterIndex, x, fractionalLength);
} else {
synchronized (this) {
if (this.tsdf == null) {
Expand All @@ -4233,12 +4259,12 @@ private void setTimestampInternal(int parameterIndex, Timestamp x, Calendar targ
StringBuffer buf = new StringBuffer();
buf.append(this.tsdf.format(x));

if (this.serverSupportsFracSecs) {
if (fractionalLength > 0) {
int nanos = x.getNanos();

if (nanos != 0) {
buf.append('.');
buf.append(TimeUtil.formatNanos(nanos, this.serverSupportsFracSecs, true));
buf.append(TimeUtil.formatNanos(nanos, this.serverSupportsFracSecs, fractionalLength));
}
}

Expand Down Expand Up @@ -4269,7 +4295,7 @@ private void newSetTimestampInternal(int parameterIndex, Timestamp x, Calendar t
StringBuffer buf = new StringBuffer();
buf.append(this.tsdf.format(x));
buf.append('.');
buf.append(TimeUtil.formatNanos(x.getNanos(), this.serverSupportsFracSecs, true));
buf.append(TimeUtil.formatNanos(x.getNanos(), this.serverSupportsFracSecs, 6));
buf.append('\'');

setInternal(parameterIndex, buf.toString());
Expand Down Expand Up @@ -4310,7 +4336,7 @@ private void newSetDateInternal(int parameterIndex, Date x, Calendar targetCalen
}
}

private void doSSPSCompatibleTimezoneShift(int parameterIndex, Timestamp x) throws SQLException {
private void doSSPSCompatibleTimezoneShift(int parameterIndex, Timestamp x, int fractionalLength) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
Calendar sessionCalendar2 = (this.connection.getUseJDBCCompliantTimezoneShift()) ? this.connection.getUtcCalendar()
: getCalendarInstanceForSessionOrNew();
Expand Down Expand Up @@ -4375,7 +4401,7 @@ private void doSSPSCompatibleTimezoneShift(int parameterIndex, Timestamp x) thro
tsBuf.append(seconds);

tsBuf.append('.');
tsBuf.append(TimeUtil.formatNanos(x.getNanos(), this.serverSupportsFracSecs, true));
tsBuf.append(TimeUtil.formatNanos(x.getNanos(), this.serverSupportsFracSecs, fractionalLength));
tsBuf.append('\'');

setInternal(parameterIndex, tsBuf.toString());
Expand Down
21 changes: 11 additions & 10 deletions src/com/mysql/jdbc/ResultSetImpl.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
The MySQL Connector/J is licensed under the terms of the GPLv2
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors.
Expand Down Expand Up @@ -980,8 +980,8 @@ protected Time fastTimeCreate(Calendar cal, int hour, int minute, int second) th
}
}

protected Timestamp fastTimestampCreate(Calendar cal, int year, int month, int day, int hour, int minute, int seconds, int secondsPart)
throws SQLException {
protected Timestamp fastTimestampCreate(Calendar cal, int year, int month, int day, int hour, int minute, int seconds, int secondsPart,
boolean useGmtMillis) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.useLegacyDatetimeCode) {
return TimeUtil.fastTimestampCreate(cal.getTimeZone(), year, month, day, hour, minute, seconds, secondsPart);
Expand All @@ -991,8 +991,6 @@ protected Timestamp fastTimestampCreate(Calendar cal, int year, int month, int d
cal = getFastDefaultCalendar();
}

boolean useGmtMillis = this.connection.getUseGmtMillisForDatetimes();

return TimeUtil.fastTimestampCreate(useGmtMillis, useGmtMillis ? getGmtCalendar() : null, cal, year, month, day, hour, minute, seconds,
secondsPart);
}
Expand Down Expand Up @@ -5665,6 +5663,8 @@ private Timestamp getTimestampFromString(int columnIndex, Calendar targetCalenda
Calendar sessionCalendar = this.connection.getUseJDBCCompliantTimezoneShift() ? this.connection.getUtcCalendar()
: getCalendarInstanceForSessionOrNew();

boolean useGmtMillis = this.connection.getUseGmtMillisForDatetimes();

if ((length > 0) && (timestampValue.charAt(0) == '0') && (timestampValue.equals("0000-00-00") || timestampValue.equals("0000-00-00 00:00:00")
|| timestampValue.equals("00000000000000") || timestampValue.equals("0"))) {

Expand All @@ -5678,7 +5678,7 @@ private Timestamp getTimestampFromString(int columnIndex, Calendar targetCalenda
}

// We're left with the case of 'round' to a date Java _can_ represent, which is '0001-01-01'.
return fastTimestampCreate(null, 1, 1, 1, 0, 0, 0, 0);
return fastTimestampCreate(null, 1, 1, 1, 0, 0, 0, 0, useGmtMillis);

} else if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {

Expand All @@ -5687,7 +5687,7 @@ private Timestamp getTimestampFromString(int columnIndex, Calendar targetCalenda
}

return TimeUtil.changeTimezone(this.connection, sessionCalendar, targetCalendar,
fastTimestampCreate(sessionCalendar, Integer.parseInt(timestampValue.substring(0, 4)), 1, 1, 0, 0, 0, 0),
fastTimestampCreate(sessionCalendar, Integer.parseInt(timestampValue.substring(0, 4)), 1, 1, 0, 0, 0, 0, useGmtMillis),
this.connection.getServerTimezoneTZ(), tz, rollForward);

} else {
Expand Down Expand Up @@ -5875,8 +5875,8 @@ private Timestamp getTimestampFromString(int columnIndex, Calendar targetCalenda
}

return TimeUtil.changeTimezone(this.connection, sessionCalendar, targetCalendar,
fastTimestampCreate(sessionCalendar, year, month, day, hour, minutes, seconds, nanos), this.connection.getServerTimezoneTZ(), tz,
rollForward);
fastTimestampCreate(sessionCalendar, year, month, day, hour, minutes, seconds, nanos, useGmtMillis),
this.connection.getServerTimezoneTZ(), tz, rollForward);
}
} catch (RuntimeException e) {
SQLException sqlEx = SQLError.createSQLException("Cannot convert value '" + timestampValue + "' from column " + columnIndex + " to TIMESTAMP.",
Expand Down Expand Up @@ -5918,7 +5918,8 @@ private Timestamp getTimestampInternal(int columnIndex, Calendar targetCalendar,
checkRowPos();
checkColumnBounds(columnIndex);

tsVal = this.thisRow.getTimestampFast(columnIndex - 1, targetCalendar, tz, rollForward, this.connection, this);
tsVal = this.thisRow.getTimestampFast(columnIndex - 1, targetCalendar, tz, rollForward, this.connection, this,
this.connection.getUseGmtMillisForDatetimes(), this.connection.getUseJDBCCompliantTimezoneShift());
}

if (tsVal == null) {
Expand Down
Loading

0 comments on commit df80d95

Please sign in to comment.