Skip to content

Commit 8cf2546

Browse files
committed
use query comment or connection attributes to provide driver metadata
1 parent a1d8080 commit 8cf2546

19 files changed

+333
-365
lines changed

wrapper/src/main/java/software/amazon/jdbc/ConnectionPluginChainBuilder.java

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,34 @@ public class ConnectionPluginChainBuilder {
8585
}
8686
};
8787

88+
protected static final Map<String /* clazz */, String> pluginCodeByPlugin =
89+
new HashMap<String, String>() {
90+
{
91+
put("software.amazon.jdbc.plugin.ExecutionTimeConnectionPlugin", "executionTime");
92+
put("software.amazon.jdbc.plugin.LogQueryConnectionPlugin", "logQuery");
93+
put("software.amazon.jdbc.plugin.DataCacheConnectionPlugin", "dataCache");
94+
put("software.amazon.jdbc.plugin.customendpoint.CustomEndpointPlugin", "customEndpoint");
95+
put("software.amazon.jdbc.plugin.efm.HostMonitoringConnectionPlugin", "efm");
96+
put("software.amazon.jdbc.plugin.efm2.HostMonitoringConnectionPlugin", "efm2");
97+
put("software.amazon.jdbc.plugin.failover.FailoverConnectionPlugin", "failover");
98+
put("software.amazon.jdbc.plugin.failover2.FailoverConnectionPlugin", "failover2");
99+
put("software.amazon.jdbc.plugin.iam.IamAuthConnectionPlugin", "iam");
100+
put("software.amazon.jdbc.plugin.AwsSecretsManagerConnectionPlugin", "awsSecretsManager");
101+
put("software.amazon.jdbc.plugin.federatedauth.FederatedAuthPlugin", "federatedAuth");
102+
put("software.amazon.jdbc.plugin.federatedauth.OktaAuthPlugin", "okta");
103+
put("software.amazon.jdbc.plugin.staledns.AuroraStaleDnsPlugin", "auroraStaleDns");
104+
put("software.amazon.jdbc.plugin.readwritesplitting.ReadWriteSplittingPlugin", "readWriteSplitting");
105+
put("software.amazon.jdbc.plugin.AuroraConnectionTrackerPlugin", "auroraConnectionTracker");
106+
put("software.amazon.jdbc.plugin.DriverMetaDataConnectionPlugin", "driverMetaData");
107+
put("software.amazon.jdbc.plugin.ConnectTimeConnectionPlugin", "connectTime");
108+
put("software.amazon.jdbc.plugin.dev.DeveloperConnectionPlugin", "dev");
109+
put("software.amazon.jdbc.plugin.strategy.fastestresponse.FastestResponseStrategyPlugin",
110+
"fastestResponseStrategy");
111+
put("software.amazon.jdbc.plugin.AuroraInitialConnectionStrategyPlugin", "initialConnection");
112+
put("software.amazon.jdbc.plugin.limitless.LimitlessConnectionPlugin", "limitless");
113+
}
114+
};
115+
88116
/**
89117
* The final list of plugins will be sorted by weight, starting from the lowest values up to
90118
* the highest values. The first plugin of the list will have the lowest weight, and the
@@ -148,7 +176,7 @@ public List<ConnectionPlugin> getPlugins(
148176
pluginFactories = configurationProfile.getPluginFactories();
149177
} else {
150178

151-
final List<String> pluginCodeList = getPluginCodes(props);
179+
final List<String> pluginCodeList = this.getPluginCodes(props);
152180
pluginFactories = new ArrayList<>(pluginCodeList.size());
153181

154182
for (final String pluginCode : pluginCodeList) {
@@ -210,14 +238,23 @@ public List<ConnectionPlugin> getPlugins(
210238
return plugins;
211239
}
212240

213-
public static List<String> getPluginCodes(final Properties props) {
241+
public List<String> getPluginCodes(final Properties props) {
214242
String pluginCodes = PropertyDefinition.PLUGINS.getString(props);
215243
if (pluginCodes == null) {
216244
pluginCodes = DEFAULT_PLUGINS;
217245
}
218246
return StringUtils.split(pluginCodes, ",", true);
219247
}
220248

249+
public String getPluginCodes(final List<ConnectionPlugin> plugins) {
250+
return plugins.stream()
251+
.filter(x -> !(x instanceof DefaultConnectionPlugin))
252+
.map(x -> pluginCodeByPlugin.getOrDefault(x.getClass().getName(), "unknown"))
253+
.distinct()
254+
.sorted()
255+
.collect(Collectors.joining("+"));
256+
}
257+
221258
protected List<Class<? extends ConnectionPluginFactory>> sortPluginFactories(
222259
final List<Class<? extends ConnectionPluginFactory>> unsortedPluginFactories) {
223260

wrapper/src/main/java/software/amazon/jdbc/ConnectionPluginManager.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,15 @@ public class ConnectionPluginManager implements CanReleaseResources, Wrapper {
100100
private static final String INIT_HOST_PROVIDER_METHOD = "initHostProvider";
101101
private static final String NOTIFY_CONNECTION_CHANGED_METHOD = "notifyConnectionChanged";
102102
private static final String NOTIFY_NODE_LIST_CHANGED_METHOD = "notifyNodeListChanged";
103+
104+
public static final String EFFECTIVE_PLUGIN_CODES_PROPERTY = "36377fa6-f016-483f-a78a-02f68c71201a";
103105
private static final SqlMethodAnalyzer sqlMethodAnalyzer = new SqlMethodAnalyzer();
104106

105107
private final ReentrantLock lock = new ReentrantLock();
106108

107109
protected Properties props = new Properties();
108110
protected List<ConnectionPlugin> plugins;
111+
protected String effectivePluginCodes;
109112
protected final @NonNull ConnectionProvider defaultConnProvider;
110113
protected final @Nullable ConnectionProvider effectiveConnProvider;
111114
protected final ConnectionWrapper connectionWrapper;
@@ -204,6 +207,8 @@ public void init(
204207
pluginManagerService,
205208
props,
206209
configurationProfile);
210+
this.effectivePluginCodes = pluginChainBuilder.getPluginCodes(this.plugins);
211+
this.props.setProperty(EFFECTIVE_PLUGIN_CODES_PROPERTY, this.effectivePluginCodes);
207212
}
208213

209214
protected <T, E extends Exception> T executeWithSubscribedPlugins(

wrapper/src/main/java/software/amazon/jdbc/PluginServiceImpl.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -709,13 +709,14 @@ public void updateDialect(final @NonNull Connection connection) throws SQLExcept
709709
this.dialect = this.dialectProvider.getDialect(
710710
this.originalUrl,
711711
this.initialConnectionHostSpec,
712-
connection);
712+
connection,
713+
this.props);
713714
if (originalDialect == this.dialect) {
714715
return;
715716
}
716717

717718
final HostListProviderSupplier supplier = this.dialect.getHostListProvider();
718-
this.setHostListProvider(supplier.getProvider(props, this.originalUrl, this, this));
719+
this.setHostListProvider(supplier.getProvider(this.props, this.originalUrl, this, this));
719720
}
720721

721722
@Override

wrapper/src/main/java/software/amazon/jdbc/PropertyDefinition.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ public static void removeAllExceptCredentials(final Properties props) {
233233
final String password = props.getProperty(PropertyDefinition.PASSWORD.name, null);
234234

235235
removeAll(props);
236+
props.remove(ConnectionPluginManager.EFFECTIVE_PLUGIN_CODES_PROPERTY);
236237

237238
if (user != null) {
238239
props.setProperty(PropertyDefinition.USER.name, user);

wrapper/src/main/java/software/amazon/jdbc/dialect/AuroraMysqlDialect.java

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.sql.Statement;
2323
import java.util.Collections;
2424
import java.util.List;
25+
import java.util.Properties;
2526
import software.amazon.jdbc.hostlistprovider.AuroraHostListProvider;
2627
import software.amazon.jdbc.hostlistprovider.monitoring.MonitoringRdsHostListProvider;
2728
import software.amazon.jdbc.plugin.failover2.FailoverConnectionPlugin;
@@ -43,33 +44,22 @@ public class AuroraMysqlDialect extends MysqlDialect {
4344
private static final String IS_READER_QUERY = "SELECT @@innodb_read_only";
4445

4546
@Override
46-
public boolean isDialect(final Connection connection) {
47-
Statement stmt = null;
48-
ResultSet rs = null;
47+
public boolean isDialect(final Connection connection, final Properties properties) {
48+
if (super.isDialect(connection, properties)) {
49+
// If super.isDialect() returns true then there is no need to check other conditions.
50+
return false;
51+
}
52+
4953
try {
50-
stmt = connection.createStatement();
51-
rs = stmt.executeQuery("SHOW VARIABLES LIKE 'aurora_version'");
52-
if (rs.next()) {
53-
// If variable with such name is presented then it means it's an Aurora cluster
54-
return true;
55-
}
56-
} catch (final SQLException ex) {
57-
// ignore
58-
} finally {
59-
if (stmt != null) {
60-
try {
61-
stmt.close();
62-
} catch (SQLException ex) {
63-
// ignore
64-
}
65-
}
66-
if (rs != null) {
67-
try {
68-
rs.close();
69-
} catch (SQLException ex) {
70-
// ignore
54+
try (Statement stmt = connection.createStatement();
55+
ResultSet rs = stmt.executeQuery("SHOW VARIABLES LIKE 'aurora_version'")) {
56+
if (rs.next()) {
57+
// If variable with such name is presented then it means it's an Aurora cluster
58+
return true;
7159
}
7260
}
61+
} catch (SQLException ex) {
62+
// do nothing
7363
}
7464
return false;
7565
}

wrapper/src/main/java/software/amazon/jdbc/dialect/AuroraPgDialect.java

Lines changed: 20 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.sql.ResultSet;
2121
import java.sql.SQLException;
2222
import java.sql.Statement;
23+
import java.util.Properties;
2324
import java.util.logging.Logger;
2425
import software.amazon.jdbc.hostlistprovider.AuroraHostListProvider;
2526
import software.amazon.jdbc.hostlistprovider.monitoring.MonitoringRdsHostListProvider;
@@ -57,72 +58,36 @@ public class AuroraPgDialect extends PgDialect implements AuroraLimitlessDialect
5758
"select router_endpoint, load from aurora_limitless_router_endpoints()";
5859

5960
@Override
60-
public boolean isDialect(final Connection connection) {
61-
if (!super.isDialect(connection)) {
61+
public boolean isDialect(final Connection connection, final Properties properties) {
62+
if (!super.isDialect(connection, properties)) {
6263
return false;
6364
}
6465

65-
Statement stmt = null;
66-
ResultSet rs = null;
67-
boolean hasExtensions = false;
68-
boolean hasTopology = false;
6966
try {
70-
stmt = connection.createStatement();
71-
rs = stmt.executeQuery(extensionsSql);
72-
if (rs.next()) {
67+
try (Statement stmt = connection.createStatement();
68+
ResultSet rs = stmt.executeQuery(extensionsSql)) {
69+
if (!rs.next()) {
70+
return false;
71+
}
7372
final boolean auroraUtils = rs.getBoolean("aurora_stat_utils");
7473
LOGGER.finest(() -> String.format("auroraUtils: %b", auroraUtils));
75-
if (auroraUtils) {
76-
hasExtensions = true;
77-
}
78-
}
79-
} catch (SQLException ex) {
80-
// ignore
81-
} finally {
82-
if (stmt != null) {
83-
try {
84-
stmt.close();
85-
} catch (SQLException ex) {
86-
// ignore
74+
if (!auroraUtils) {
75+
return false;
8776
}
8877
}
89-
if (rs != null) {
90-
try {
91-
rs.close();
92-
} catch (SQLException ex) {
93-
// ignore
94-
}
95-
}
96-
}
97-
if (!hasExtensions) {
98-
return false;
99-
}
100-
try {
101-
stmt = connection.createStatement();
102-
rs = stmt.executeQuery(topologySql);
103-
if (rs.next()) {
104-
LOGGER.finest(() -> "hasTopology: true");
105-
hasTopology = true;
106-
}
107-
} catch (final SQLException ex) {
108-
// ignore
109-
} finally {
110-
if (stmt != null) {
111-
try {
112-
stmt.close();
113-
} catch (SQLException ex) {
114-
// ignore
115-
}
116-
}
117-
if (rs != null) {
118-
try {
119-
rs.close();
120-
} catch (SQLException ex) {
121-
// ignore
78+
79+
try (Statement stmt = connection.createStatement();
80+
ResultSet rs = stmt.executeQuery(topologySql)) {
81+
if (rs.next()) {
82+
LOGGER.finest(() -> "hasTopology: true");
83+
return true;
12284
}
85+
LOGGER.finest(() -> "hasTopology: false");
12386
}
87+
} catch (SQLException ex) {
88+
// do nothing
12489
}
125-
return hasExtensions && hasTopology;
90+
return false;
12691
}
12792

12893
@Override

wrapper/src/main/java/software/amazon/jdbc/dialect/Dialect.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,23 @@ public interface Dialect {
3232

3333
String getHostAliasQuery();
3434

35-
String getServerVersionQuery();
35+
// The query should return two column:
36+
// - parameter name
37+
// - parameter value with a database version
38+
String getServerVersionQuery(final Properties properties);
3639

37-
boolean isDialect(Connection connection);
40+
boolean isDialect(final Connection connection, final Properties properties);
3841

3942
List</* dialect code */ String> getDialectUpdateCandidates();
4043

4144
HostListProviderSupplier getHostListProvider();
4245

4346
void prepareConnectProperties(
44-
final @NonNull Properties connectProperties, final @NonNull String protocol, final @NonNull HostSpec hostSpec);
47+
final @NonNull Properties connectProperties,
48+
final @NonNull String protocol,
49+
final @NonNull HostSpec hostSpec);
4550

4651
EnumSet<FailoverRestriction> getFailoverRestrictions();
52+
53+
void reportMetadata(final @NonNull Connection connection, final @NonNull Properties properties);
4754
}

wrapper/src/main/java/software/amazon/jdbc/dialect/DialectManager.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ public class DialectManager implements DialectProvider {
7979
private final RdsUtils rdsHelper = new RdsUtils();
8080
private final ConnectionUrlParser connectionUrlParser = new ConnectionUrlParser();
8181
private boolean canUpdate = false;
82+
private boolean shouldReportMetadata = false;
8283
private Dialect dialect = null;
8384
private String dialectCode;
8485

@@ -131,6 +132,7 @@ public Dialect getDialect(
131132
this.dialectCode = DialectCodes.CUSTOM;
132133
this.dialect = customDialect;
133134
this.logCurrentDialect();
135+
this.shouldReportMetadata = true;
134136
return this.dialect;
135137
}
136138

@@ -145,6 +147,7 @@ public Dialect getDialect(
145147
this.dialectCode = dialectCode;
146148
this.dialect = userDialect;
147149
this.logCurrentDialect();
150+
this.shouldReportMetadata = true;
148151
return userDialect;
149152
} else {
150153
throw new SQLException(
@@ -157,8 +160,8 @@ public Dialect getDialect(
157160
}
158161

159162
String host = url;
160-
final List<HostSpec> hosts = this.connectionUrlParser.getHostsFromConnectionUrl(url, true,
161-
() -> pluginService.getHostSpecBuilder());
163+
final List<HostSpec> hosts = this.connectionUrlParser.getHostsFromConnectionUrl(
164+
url, true, pluginService::getHostSpecBuilder);
162165
if (!Utils.isNullOrEmpty(hosts)) {
163166
host = hosts.get(0).getHost();
164167
}
@@ -232,10 +235,15 @@ public Dialect getDialect(
232235
public Dialect getDialect(
233236
final @NonNull String originalUrl,
234237
final @NonNull HostSpec hostSpec,
235-
final @NonNull Connection connection) throws SQLException {
238+
final @NonNull Connection connection,
239+
final @NonNull Properties properties) throws SQLException {
236240

237241
if (!this.canUpdate) {
238242
this.logCurrentDialect();
243+
if (this.shouldReportMetadata) {
244+
this.dialect.reportMetadata(connection, properties);
245+
this.shouldReportMetadata = false;
246+
}
239247
return this.dialect;
240248
}
241249

@@ -247,7 +255,7 @@ public Dialect getDialect(
247255
throw new SQLException(
248256
Messages.get("DialectManager.unknownDialectCode", new Object[] {dialectCandidateCode}));
249257
}
250-
boolean isDialect = dialectCandidate.isDialect(connection);
258+
boolean isDialect = dialectCandidate.isDialect(connection, properties);
251259
if (isDialect) {
252260
this.canUpdate = false;
253261
this.dialectCode = dialectCandidateCode;

wrapper/src/main/java/software/amazon/jdbc/dialect/DialectProvider.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,6 @@ Dialect getDialect(
3131
Dialect getDialect(
3232
final @NonNull String originalUrl,
3333
final @NonNull HostSpec hostSpec,
34-
final @NonNull Connection connection) throws SQLException;
34+
final @NonNull Connection connection,
35+
final @NonNull Properties properties) throws SQLException;
3536
}

0 commit comments

Comments
 (0)