From 9758e6f0d3a209b81613421e36b46a9051a19864 Mon Sep 17 00:00:00 2001 From: KwonNam Son Date: Sun, 14 Jun 2015 20:55:15 +0900 Subject: [PATCH] Add 'truncateFractionalSeconds=true|false' property --- src/com/mysql/jdbc/ConnectionProperties.java | 4 ++++ src/com/mysql/jdbc/ConnectionPropertiesImpl.java | 11 +++++++++++ src/com/mysql/jdbc/LocalizedErrorMessages.properties | 1 + src/com/mysql/jdbc/MultiHostMySQLConnection.java | 8 ++++++++ src/com/mysql/jdbc/PreparedStatement.java | 8 ++++++++ src/com/mysql/jdbc/ReplicationConnection.java | 9 +++++++++ src/com/mysql/jdbc/ServerPreparedStatement.java | 4 ++++ src/com/mysql/jdbc/StatementImpl.java | 3 +++ src/com/mysql/jdbc/TimeUtil.java | 6 ++++++ src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java | 8 ++++++++ 10 files changed, 62 insertions(+) diff --git a/src/com/mysql/jdbc/ConnectionProperties.java b/src/com/mysql/jdbc/ConnectionProperties.java index 3909102..3832cdb 100644 --- a/src/com/mysql/jdbc/ConnectionProperties.java +++ b/src/com/mysql/jdbc/ConnectionProperties.java @@ -1248,6 +1248,10 @@ public abstract void setUseLegacyDatetimeCode(boolean flag); + public abstract boolean getTruncateFractionalSeconds(); + + public abstract void setTruncateFractionalSeconds(boolean flag); + public abstract int getSelfDestructOnPingSecondsLifetime(); public abstract void setSelfDestructOnPingSecondsLifetime(int seconds) throws SQLException; diff --git a/src/com/mysql/jdbc/ConnectionPropertiesImpl.java b/src/com/mysql/jdbc/ConnectionPropertiesImpl.java index 6b64929..8d6b40e 100644 --- a/src/com/mysql/jdbc/ConnectionPropertiesImpl.java +++ b/src/com/mysql/jdbc/ConnectionPropertiesImpl.java @@ -1167,6 +1167,9 @@ public ExceptionInterceptor getExceptionInterceptor() { private BooleanConnectionProperty useLegacyDatetimeCode = new BooleanConnectionProperty("useLegacyDatetimeCode", true, Messages.getString("ConnectionProperties.useLegacyDatetimeCode"), "5.1.6", MISC_CATEGORY, Integer.MIN_VALUE); + private BooleanConnectionProperty truncateFractionalSeconds = new BooleanConnectionProperty("truncateFractionalSeconds", false, + Messages.getString("ConnectionProperties.truncateFractionalSeconds"), "5.1.36", MISC_CATEGORY, Integer.MIN_VALUE); + private BooleanConnectionProperty useNanosForElapsedTime = new BooleanConnectionProperty("useNanosForElapsedTime", false, Messages.getString("ConnectionProperties.useNanosForElapsedTime"), "5.0.7", DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); @@ -4514,6 +4517,14 @@ public void setUseLegacyDatetimeCode(boolean flag) { this.useLegacyDatetimeCode.setValue(flag); } + public boolean getTruncateFractionalSeconds() { + return this.truncateFractionalSeconds.getValueAsBoolean(); + } + + public void setTruncateFractionalSeconds(boolean flag) { + this.truncateFractionalSeconds.setValue(flag); + } + public int getSelfDestructOnPingSecondsLifetime() { return this.selfDestructOnPingSecondsLifetime.getValueAsInt(); } diff --git a/src/com/mysql/jdbc/LocalizedErrorMessages.properties b/src/com/mysql/jdbc/LocalizedErrorMessages.properties index 963944e..b8103f5 100644 --- a/src/com/mysql/jdbc/LocalizedErrorMessages.properties +++ b/src/com/mysql/jdbc/LocalizedErrorMessages.properties @@ -645,6 +645,7 @@ ConnectionProperties.useBlobToStoreUTF8OutsideBMP=Tells the driver to treat [MED ConnectionProperties.utf8OutsideBmpExcludedColumnNamePattern=When "useBlobToStoreUTF8OutsideBMP" is set to "true", column names matching the given regex will still be treated as BLOBs unless they match the regex specified for "utf8OutsideBmpIncludedColumnNamePattern". The regex must follow the patterns used for the java.util.regex package. ConnectionProperties.utf8OutsideBmpIncludedColumnNamePattern=Used to specify exclusion rules to "utf8OutsideBmpExcludedColumnNamePattern". The regex must follow the patterns used for the java.util.regex package. ConnectionProperties.useLegacyDatetimeCode=Use code for DATE/TIME/DATETIME/TIMESTAMP handling in result sets and statements that consistently handles time zone conversions from client to server and back again, or use the legacy code for these datatypes that has been in the driver for backwards-compatibility? Setting this property to 'false' voids the effects of "useTimezone," "useJDBCCompliantTimezoneShift," "useGmtMillisForDatetimes," and "useFastDateParsing." +ConnectionProperties.truncateFractionalSeconds=Truncate fractional seconds(nanos) of TIMESTAMP (default false). If this is true, timestamp's nanos will be set as 0. This only applies to PreparedStatement. ConnectionProperties.useColumnNamesInFindColumn=Prior to JDBC-4.0, the JDBC specification had a bug related to what could be given as a "column name" to ResultSet methods like findColumn(), or getters that took a String property. JDBC-4.0 clarified "column name" to mean the label, as given in an "AS" clause and returned by ResultSetMetaData.getColumnLabel(), and if no AS clause, the column name. Setting this property to "true" will give behavior that is congruent to JDBC-3.0 and earlier versions of the JDBC specification, but which because of the specification bug could give unexpected results. This property is preferred over "useOldAliasMetadataBehavior" unless you need the specific behavior that it provides with respect to ResultSetMetadata. ConnectionProperties.useAffectedRows=Don't set the CLIENT_FOUND_ROWS flag when connecting to the server (not JDBC-compliant, will break most applications that rely on "found" rows vs. "affected rows" for DML statements), but does cause "correct" update counts from "INSERT ... ON DUPLICATE KEY UPDATE" statements to be returned by the server. ConnectionProperties.passwordCharacterEncoding=What character encoding is used for passwords? Leaving this set to the default value (null), uses the platform character set, which works for ISO8859_1 (i.e. "latin1") passwords. For passwords in other character encodings, the encoding will have to be specified with this property, as it's not possible for the driver to auto-detect this. diff --git a/src/com/mysql/jdbc/MultiHostMySQLConnection.java b/src/com/mysql/jdbc/MultiHostMySQLConnection.java index 767074a..3999334 100644 --- a/src/com/mysql/jdbc/MultiHostMySQLConnection.java +++ b/src/com/mysql/jdbc/MultiHostMySQLConnection.java @@ -787,6 +787,10 @@ public boolean getUseLegacyDatetimeCode() { return getActiveMySQLConnection().getUseLegacyDatetimeCode(); } + public boolean getTruncateFractionalSeconds() { + return getActiveMySQLConnection().getTruncateFractionalSeconds(); + } + public boolean getUseLocalSessionState() { return getActiveMySQLConnection().getUseLocalSessionState(); } @@ -1531,6 +1535,10 @@ public void setUseLegacyDatetimeCode(boolean flag) { getActiveMySQLConnection().setUseLegacyDatetimeCode(flag); } + public void setTruncateFractionalSeconds(boolean flag) { + getActiveMySQLConnection().setTruncateFractionalSeconds(flag); + } + public void setUseLocalSessionState(boolean flag) { getActiveMySQLConnection().setUseLocalSessionState(flag); } diff --git a/src/com/mysql/jdbc/PreparedStatement.java b/src/com/mysql/jdbc/PreparedStatement.java index b73e28d..0cf9113 100644 --- a/src/com/mysql/jdbc/PreparedStatement.java +++ b/src/com/mysql/jdbc/PreparedStatement.java @@ -4299,6 +4299,10 @@ private void setTimestampInternal(int parameterIndex, Timestamp x, Calendar targ Calendar sessionCalendar = this.connection.getUseJDBCCompliantTimezoneShift() ? this.connection.getUtcCalendar() : getCalendarInstanceForSessionOrNew(); + if (this.truncateFractionalSeconds) { + x = TimeUtil.truncateFractionalSeconds(x); + } + x = TimeUtil.changeTimezone(this.connection, sessionCalendar, targetCalendar, x, tz, this.connection.getServerTimezoneTZ(), rollForward); if (this.connection.getUseSSPSCompatibleTimezoneShift()) { @@ -4335,6 +4339,10 @@ private void setTimestampInternal(int parameterIndex, Timestamp x, Calendar targ private void newSetTimestampInternal(int parameterIndex, Timestamp x, Calendar targetCalendar) throws SQLException { synchronized (checkClosed().getConnectionMutex()) { + if (this.truncateFractionalSeconds) { + x = TimeUtil.truncateFractionalSeconds(x); + } + if (this.tsdf == null) { this.tsdf = new SimpleDateFormat("''yyyy-MM-dd HH:mm:ss", Locale.US); } diff --git a/src/com/mysql/jdbc/ReplicationConnection.java b/src/com/mysql/jdbc/ReplicationConnection.java index d3004f2..8065593 100644 --- a/src/com/mysql/jdbc/ReplicationConnection.java +++ b/src/com/mysql/jdbc/ReplicationConnection.java @@ -1624,6 +1624,10 @@ public boolean getUseLegacyDatetimeCode() { return getCurrentConnection().getUseLegacyDatetimeCode(); } + public boolean getTruncateFractionalSeconds() { + return getCurrentConnection().getTruncateFractionalSeconds(); + } + public boolean getUseLocalSessionState() { return getCurrentConnection().getUseLocalSessionState(); } @@ -2482,6 +2486,11 @@ public void setUseLocalSessionState(boolean flag) { } + public void setTruncateFractionalSeconds(boolean flag) { + // not runtime configurable + + } + public void setUseNanosForElapsedTime(boolean flag) { // not runtime configurable diff --git a/src/com/mysql/jdbc/ServerPreparedStatement.java b/src/com/mysql/jdbc/ServerPreparedStatement.java index 1de2ba3..598a7e9 100644 --- a/src/com/mysql/jdbc/ServerPreparedStatement.java +++ b/src/com/mysql/jdbc/ServerPreparedStatement.java @@ -2159,6 +2159,10 @@ private void setTimestampInternal(int parameterIndex, java.sql.Timestamp x, Cale BindValue binding = getBinding(parameterIndex, false); setType(binding, MysqlDefs.FIELD_TYPE_DATETIME); + if (this.truncateFractionalSeconds) { + x = TimeUtil.truncateFractionalSeconds(x); + } + if (!this.useLegacyDatetimeCode) { binding.value = x; } else { diff --git a/src/com/mysql/jdbc/StatementImpl.java b/src/com/mysql/jdbc/StatementImpl.java index 6524987..f65ae20 100644 --- a/src/com/mysql/jdbc/StatementImpl.java +++ b/src/com/mysql/jdbc/StatementImpl.java @@ -285,6 +285,8 @@ public void run() { protected boolean useLegacyDatetimeCode; + protected boolean truncateFractionalSeconds; + private ExceptionInterceptor exceptionInterceptor; /** Whether or not the last query was of the form ON DUPLICATE KEY UPDATE */ @@ -320,6 +322,7 @@ public StatementImpl(MySQLConnection c, String catalog) throws SQLException { this.pedantic = this.connection.getPedantic(); this.continueBatchOnError = this.connection.getContinueBatchOnError(); this.useLegacyDatetimeCode = this.connection.getUseLegacyDatetimeCode(); + this.truncateFractionalSeconds = this.connection.getTruncateFractionalSeconds(); if (!this.connection.getDontTrackOpenResources()) { this.connection.registerStatement(this); diff --git a/src/com/mysql/jdbc/TimeUtil.java b/src/com/mysql/jdbc/TimeUtil.java index f65275e..aea4874 100644 --- a/src/com/mysql/jdbc/TimeUtil.java +++ b/src/com/mysql/jdbc/TimeUtil.java @@ -533,4 +533,10 @@ private static void loadTimeZoneMappings(ExceptionInterceptor exceptionIntercept } } } + + public static Timestamp truncateFractionalSeconds(Timestamp timestamp) { + Timestamp truncatedTimestamp = new Timestamp(timestamp.getTime()); + truncatedTimestamp.setNanos(0); + return truncatedTimestamp; + } } diff --git a/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java b/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java index 7a6961a..e012798 100644 --- a/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java +++ b/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java @@ -2429,6 +2429,14 @@ public void setUseLegacyDatetimeCode(boolean flag) { this.mc.setUseLegacyDatetimeCode(flag); } + public boolean getTruncateFractionalSeconds() { + return this.mc.getTruncateFractionalSeconds(); + } + + public void setTruncateFractionalSeconds(boolean flag) { + this.mc.setTruncateFractionalSeconds(flag); + } + public int getSelfDestructOnPingMaxOperations() { return this.mc.getSelfDestructOnPingMaxOperations(); }