Skip to content

Commit 1177f29

Browse files
committed
Fix for Bug#102404 (32435618), CONTRIBUTION: ADD TRACK SESSION STATE
CHANGE.
1 parent 60c0119 commit 1177f29

16 files changed

+561
-9
lines changed

CHANGES

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
Version 8.0.26
55

6+
- Fix for Bug#102404 (32435618), CONTRIBUTION: ADD TRACK SESSION STATE CHANGE.
7+
Thanks to William Lee for his contribution.
8+
69
- Fix for Bug#95280 (29757140), DATABASEMETADATA.GETIMPORTEDKEYS RETURNS DOUBLE THE ROWS.
710
Thanks to Miron Balcerzak for his contribution.
811

src/main/core-api/java/com/mysql/cj/MysqlConnection.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2020, Oracle and/or its affiliates.
2+
* Copyright (c) 2015, 2021, Oracle and/or its affiliates.
33
*
44
* This program is free software; you can redistribute it and/or modify it under
55
* the terms of the GNU General Public License, version 2.0, as published by the
@@ -33,6 +33,7 @@
3333

3434
import com.mysql.cj.conf.PropertySet;
3535
import com.mysql.cj.exceptions.ExceptionInterceptor;
36+
import com.mysql.cj.protocol.ServerSessionStateController;
3637

3738
public interface MysqlConnection {
3839

@@ -76,4 +77,6 @@ public interface MysqlConnection {
7677
* exception caused the connection clean up
7778
*/
7879
void cleanup(Throwable whyCleanedUp);
80+
81+
ServerSessionStateController getServerSessionStateController();
7982
}

src/main/core-api/java/com/mysql/cj/conf/PropertyDefinitions.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,9 @@ public enum DatabaseTerm {
265265
new StringPropertyDefinition(PropertyKey.sessionVariables, DEFAULT_VALUE_NULL_STRING, RUNTIME_MODIFIABLE,
266266
Messages.getString("ConnectionProperties.sessionVariables"), "3.1.8", CATEGORY_SESSION, Integer.MAX_VALUE),
267267

268+
new BooleanPropertyDefinition(PropertyKey.trackSessionState, DEFAULT_VALUE_FALSE, RUNTIME_MODIFIABLE,
269+
Messages.getString("ConnectionProperties.trackSessionState"), "8.0.26", CATEGORY_SESSION, Integer.MIN_VALUE),
270+
268271
//
269272
// CATEGORY_NETWORK
270273
//

src/main/core-api/java/com/mysql/cj/conf/PropertyKey.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ public enum PropertyKey {
206206
serverConfigCacheFactory("serverConfigCacheFactory", true), //
207207
serverRSAPublicKeyFile("serverRSAPublicKeyFile", true), //
208208
sessionVariables("sessionVariables", true), //
209+
trackSessionState("trackSessionState", true), //
209210
slowQueryThresholdMillis("slowQueryThresholdMillis", true), //
210211
slowQueryThresholdNanos("slowQueryThresholdNanos", true), //
211212
socketFactory("socketFactory", true), //

src/main/core-api/java/com/mysql/cj/protocol/ServerSession.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
import java.util.TimeZone;
3434

3535
import com.mysql.cj.ServerVersion;
36+
import com.mysql.cj.exceptions.CJOperationNotSupportedException;
37+
import com.mysql.cj.exceptions.ExceptionFactory;
3638

3739
/**
3840
* Keeps the effective states of server/session variables,
@@ -248,4 +250,9 @@ public interface ServerSession {
248250
* @return The default JVM time zone
249251
*/
250252
TimeZone getDefaultTimeZone();
253+
254+
default ServerSessionStateController getServerSessionStateController() {
255+
throw ExceptionFactory.createException(CJOperationNotSupportedException.class, "Not supported");
256+
}
257+
251258
}
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates.
3+
*
4+
* This program is free software; you can redistribute it and/or modify it under
5+
* the terms of the GNU General Public License, version 2.0, as published by the
6+
* Free Software Foundation.
7+
*
8+
* This program is also distributed with certain software (including but not
9+
* limited to OpenSSL) that is licensed under separate terms, as designated in a
10+
* particular file or component or in included license documentation. The
11+
* authors of MySQL hereby grant you an additional permission to link the
12+
* program and your derivative works with the separately licensed software that
13+
* they have included with MySQL.
14+
*
15+
* Without limiting anything contained in the foregoing, this file, which is
16+
* part of MySQL Connector/J, is also subject to the Universal FOSS Exception,
17+
* version 1.0, a copy of which can be found at
18+
* http://oss.oracle.com/licenses/universal-foss-exception.
19+
*
20+
* This program is distributed in the hope that it will be useful, but WITHOUT
21+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
22+
* FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
23+
* for more details.
24+
*
25+
* You should have received a copy of the GNU General Public License along with
26+
* this program; if not, write to the Free Software Foundation, Inc.,
27+
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28+
*/
29+
30+
package com.mysql.cj.protocol;
31+
32+
import java.util.ArrayList;
33+
import java.util.List;
34+
35+
import com.mysql.cj.exceptions.CJOperationNotSupportedException;
36+
import com.mysql.cj.exceptions.ExceptionFactory;
37+
38+
public interface ServerSessionStateController {
39+
40+
public static int SESSION_TRACK_SYSTEM_VARIABLES = 0x00;
41+
public static int SESSION_TRACK_SCHEMA = 0x01;
42+
public static int SESSION_TRACK_STATE_CHANGE = 0x02;
43+
public static int SESSION_TRACK_GTIDS = 0x03;
44+
public static int SESSION_TRACK_TRANSACTION_CHARACTERISTICS = 0x04;
45+
public static int SESSION_TRACK_TRANSACTION_STATE = 0x05;
46+
47+
/**
48+
* Set the object containing server session changes collected from the latest query execution. Used internally.
49+
*
50+
* @param changes
51+
* {@link ServerSessionStateChanges} object.
52+
*
53+
*/
54+
default void setSessionStateChanges(ServerSessionStateChanges changes) {
55+
throw ExceptionFactory.createException(CJOperationNotSupportedException.class, "Not supported");
56+
}
57+
58+
/**
59+
* Get the object containing server session changes collected from the latest query execution.
60+
* <p>
61+
* Please note that the driver could issue some queries internally. With that there is no guarantee that all session changes are reflected in the
62+
* {@link ServerSessionStateChanges} object after the recent user's query. If this is an issue, a {@link SessionStateChangesListener} can be added via
63+
* {@link #addSessionStateChangesListener(SessionStateChangesListener)} to catch all session changes.
64+
* </p>
65+
*
66+
* @return {@link ServerSessionStateChanges} object.
67+
*/
68+
default ServerSessionStateChanges getSessionStateChanges() {
69+
throw ExceptionFactory.createException(CJOperationNotSupportedException.class, "Not supported");
70+
}
71+
72+
@FunctionalInterface
73+
public static interface SessionStateChangesListener {
74+
void handleSessionStateChanges(ServerSessionStateChanges changes);
75+
}
76+
77+
/**
78+
* Add the {@link SessionStateChangesListener} that will process {@link ServerSessionStateChanges} on it's arrival.
79+
*
80+
* @param l
81+
* {@link SessionStateChangesListener} object.
82+
*/
83+
default void addSessionStateChangesListener(SessionStateChangesListener l) {
84+
throw ExceptionFactory.createException(CJOperationNotSupportedException.class, "Not supported");
85+
}
86+
87+
/**
88+
* Remove {@link SessionStateChangesListener}.
89+
*
90+
* @param l
91+
* {@link SessionStateChangesListener} object.
92+
*/
93+
default void removeSessionStateChangesListener(SessionStateChangesListener l) {
94+
throw ExceptionFactory.createException(CJOperationNotSupportedException.class, "Not supported");
95+
}
96+
97+
/**
98+
* The object containing server session changes collected from the latest query execution.
99+
* <p>
100+
* Driver is getting these changes when connection property trackSessionState=true and server supports session tracking.
101+
* </p>
102+
*
103+
*/
104+
public static interface ServerSessionStateChanges {
105+
List<SessionStateChange> getSessionStateChangesList();
106+
}
107+
108+
/**
109+
* A single server session change record.
110+
* <p>
111+
* The server messages about session changes are parsed according to their known types:
112+
* <ul>
113+
* <li>{@link #SESSION_TRACK_SYSTEM_VARIABLES} - two values, the system variable name and it's new value;</li>
114+
* <li>{@link #SESSION_TRACK_SCHEMA} - single value, the new schema name;</li>
115+
* <li>{@link #SESSION_TRACK_STATE_CHANGE} - single value, "1" or "0";</li>
116+
* <li>{@link #SESSION_TRACK_GTIDS} - single value, list of GTIDs as reported by server;</li>
117+
* <li>{@link #SESSION_TRACK_TRANSACTION_CHARACTERISTICS} - single value, transaction characteristics statement;</li>
118+
* <li>{@link #SESSION_TRACK_TRANSACTION_STATE} - single value, transaction state record.</li>
119+
* </ul>
120+
* For the unknown change type the raw payload is written into the single value.
121+
* </p>
122+
* <p>
123+
* See more details in the <a href="https://dev.mysql.com/doc/refman/8.0/en/session-state-tracking.html">server documentation</a>.
124+
* </p>
125+
*/
126+
public static class SessionStateChange {
127+
private int type;
128+
private List<String> values = new ArrayList<>();
129+
130+
public SessionStateChange(int type) {
131+
this.type = type;
132+
}
133+
134+
public int getType() {
135+
return this.type;
136+
}
137+
138+
public List<String> getValues() {
139+
return this.values;
140+
}
141+
142+
public SessionStateChange addValue(String value) {
143+
this.values.add(value);
144+
return this;
145+
}
146+
}
147+
}

src/main/protocol-impl/java/com/mysql/cj/protocol/a/NativeAuthenticationProvider.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,11 +193,10 @@ public void connect(ServerSession sessState, String user, String pass, String db
193193
: (capabilityFlags & NativeServerSession.CLIENT_CONNECT_ATTRS))
194194
| (this.propertySet.<SslMode>getEnumProperty(PropertyKey.sslMode).getValue() != SslMode.DISABLED
195195
? (capabilityFlags & NativeServerSession.CLIENT_SSL)
196+
: 0)
197+
| (this.propertySet.getBooleanProperty(PropertyKey.trackSessionState).getValue() ? (capabilityFlags & NativeServerSession.CLIENT_SESSION_TRACK)
196198
: 0);
197199

198-
// TODO MYSQLCONNJ-437
199-
// clientParam |= (capabilityFlags & NativeServerSession.CLIENT_SESSION_TRACK);
200-
201200
sessState.setClientParam(clientParam);
202201

203202
/* First, negotiate SSL connection */
@@ -467,6 +466,7 @@ private void proceedHandshakeWithPluggableAuthentication(ServerSession serverSes
467466
// read OK packet
468467
OkPacket ok = OkPacket.parse(last_received, null);
469468
serverSession.setStatusFlags(ok.getStatusFlags(), true);
469+
serverSession.getServerSessionStateController().setSessionStateChanges(ok.getSessionStateChanges());
470470

471471
// if OK packet then finish handshake
472472
plugin.destroy();

src/main/protocol-impl/java/com/mysql/cj/protocol/a/NativeProtocol.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1747,6 +1747,7 @@ public final <T> T readServerStatusForResultSets(NativePacketPayload rowPacket,
17471747
result = (T) ok;
17481748

17491749
this.serverSession.setStatusFlags(ok.getStatusFlags(), saveOldStatus);
1750+
this.serverSession.getServerSessionStateController().setSessionStateChanges(ok.getSessionStateChanges());
17501751
checkTransactionState();
17511752

17521753
this.warningCount = ok.getWarningCount();

src/main/protocol-impl/java/com/mysql/cj/protocol/a/NativeServerSession.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import com.mysql.cj.exceptions.WrongArgumentException;
4444
import com.mysql.cj.protocol.ServerCapabilities;
4545
import com.mysql.cj.protocol.ServerSession;
46+
import com.mysql.cj.protocol.ServerSessionStateController;
4647
import com.mysql.cj.util.StringUtils;
4748
import com.mysql.cj.util.TimeUtil;
4849

@@ -86,6 +87,7 @@ public class NativeServerSession implements ServerSession {
8687
private int statusFlags = 0;
8788
private int serverDefaultCollationIndex;
8889
private long clientParam = 0;
90+
private NativeServerSessionStateController serverSessionStateController;
8991

9092
/** The map of server variables that we retrieve at connection init. */
9193
private Map<String, String> serverVariables = new HashMap<>();
@@ -125,6 +127,7 @@ public class NativeServerSession implements ServerSession {
125127
public NativeServerSession(PropertySet propertySet) {
126128
this.propertySet = propertySet;
127129
this.cacheDefaultTimeZone = this.propertySet.getBooleanProperty(PropertyKey.cacheDefaultTimeZone);
130+
this.serverSessionStateController = new NativeServerSessionStateController();
128131

129132
// preconfigure some server variables which are consulted before their initialization from server
130133
this.serverVariables.put("character_set_server", "utf8");
@@ -570,4 +573,10 @@ public TimeZone getDefaultTimeZone() {
570573
}
571574
return TimeZone.getDefault();
572575
}
576+
577+
@Override
578+
public ServerSessionStateController getServerSessionStateController() {
579+
return this.serverSessionStateController;
580+
}
581+
573582
}

0 commit comments

Comments
 (0)