2626import java .util .Properties ;
2727import java .util .Set ;
2828import java .util .logging .Logger ;
29+ import software .amazon .jdbc .AwsWrapperProperty ;
2930import software .amazon .jdbc .JdbcCallable ;
3031import software .amazon .jdbc .JdbcMethod ;
3132import software .amazon .jdbc .PluginService ;
33+ import software .amazon .jdbc .PropertyDefinition ;
3234import software .amazon .jdbc .plugin .AbstractConnectionPlugin ;
3335import software .amazon .jdbc .states .SessionStateService ;
3436import software .amazon .jdbc .util .Messages ;
4143
4244public class DataRemoteCachePlugin extends AbstractConnectionPlugin {
4345 private static final Logger LOGGER = Logger .getLogger (DataRemoteCachePlugin .class .getName ());
44- private static final int MAX_CACHEABLE_QUERY_SIZE = 16000 ;
4546 private static final String QUERY_HINT_START_PATTERN = "/*+" ;
4647 private static final String QUERY_HINT_END_PATTERN = "*/" ;
4748 private static final String CACHE_PARAM_PATTERN = "CACHE_PARAM(" ;
@@ -55,6 +56,7 @@ public class DataRemoteCachePlugin extends AbstractConnectionPlugin {
5556 JdbcMethod .CALLABLESTATEMENT_EXECUTE .methodName ,
5657 JdbcMethod .CALLABLESTATEMENT_EXECUTEQUERY .methodName )));
5758
59+ private int maxCacheableQuerySize ;
5860 private PluginService pluginService ;
5961 private TelemetryFactory telemetryFactory ;
6062 private TelemetryCounter cacheHitCounter ;
@@ -63,6 +65,17 @@ public class DataRemoteCachePlugin extends AbstractConnectionPlugin {
6365 private TelemetryCounter malformedHintCounter ;
6466 private TelemetryCounter cacheBypassCounter ;
6567 private CacheConnection cacheConnection ;
68+ private String dbUserName ;
69+
70+ private static final AwsWrapperProperty CACHE_MAX_QUERY_SIZE =
71+ new AwsWrapperProperty (
72+ "cacheMaxQuerySize" ,
73+ "16384" ,
74+ "The max query size for remote caching" );
75+
76+ static {
77+ PropertyDefinition .registerPluginProperties (DataRemoteCachePlugin .class );
78+ }
6679
6780 public DataRemoteCachePlugin (final PluginService pluginService , final Properties properties ) {
6881 try {
@@ -78,7 +91,9 @@ public DataRemoteCachePlugin(final PluginService pluginService, final Properties
7891 this .totalQueryCounter = telemetryFactory .createCounter ("JdbcCacheTotalQueryCount" );
7992 this .malformedHintCounter = telemetryFactory .createCounter ("JdbcCacheMalformedQueryHint" );
8093 this .cacheBypassCounter = telemetryFactory .createCounter ("JdbcCacheBypassCount" );
94+ this .maxCacheableQuerySize = CACHE_MAX_QUERY_SIZE .getInteger (properties );
8195 this .cacheConnection = new CacheConnection (properties );
96+ this .dbUserName = PropertyDefinition .USER .getString (properties );
8297 }
8398
8499 // Used for unit testing purposes only
@@ -93,25 +108,36 @@ public Set<String> getSubscribedMethods() {
93108
94109 private String getCacheQueryKey (String query ) {
95110 // Check some basic session states. The important ones for caching include (but not limited to):
96- // schema name, username which can affect the query result from the DB in addition to the query string
111+ // schema name, username which can affect the query result from the DB in addition to the query string
97112 try {
98113 Connection currentConn = pluginService .getCurrentConnection ();
99114 DatabaseMetaData metadata = currentConn .getMetaData ();
100115 // Fetch and record the schema name if the session state doesn't currently have it
101116 SessionStateService sessionStateService = pluginService .getSessionStateService ();
117+ String catalog = sessionStateService .getCatalog ().orElse (null );
102118 String schema = sessionStateService .getSchema ().orElse (null );
103- if (schema == null ) {
119+ if (catalog == null && schema == null ) {
104120 // Fetch the current schema name and store it in sessionStateService
121+ catalog = currentConn .getCatalog ();
105122 schema = currentConn .getSchema ();
106- sessionStateService .setSchema (schema );
123+ if (catalog != null ) sessionStateService .setCatalog (catalog );
124+ if (schema != null ) sessionStateService .setSchema (schema );
107125 }
108126
127+ if (dbUserName == null ) {
128+ // For MySQL, metadata username is actually <UserName>@<ip>. We just need the part before '@'.
129+ dbUserName = metadata .getUserName ();
130+ int nameIndexEnd = dbUserName .indexOf ('@' );
131+ if (nameIndexEnd > 0 ) {
132+ dbUserName = dbUserName .substring (0 , nameIndexEnd );
133+ }
134+ }
109135 LOGGER .finest ("DB driver protocol " + pluginService .getDriverProtocol ()
110136 + ", database product: " + metadata .getDatabaseProductName () + " " + metadata .getDatabaseProductVersion ()
111- + ", schema: " + schema + ", user: " + metadata . getUserName ()
137+ + ", catalog: " + catalog + ", schema: " + schema + ", user: " + dbUserName
112138 + ", driver: " + metadata .getDriverName () + " " + metadata .getDriverVersion ());
113139 // The cache key contains the schema name, user name, and the query string
114- String [] words = {schema , metadata . getUserName () , query };
140+ String [] words = {catalog , schema , dbUserName , query };
115141 return String .join ("_" , words );
116142 } catch (SQLException e ) {
117143 LOGGER .warning ("Error getting session state: " + e .getMessage ());
@@ -239,11 +265,11 @@ public <T, E extends Exception> T execute(
239265 int endOfQueryHint = 0 ;
240266 Integer configuredQueryTtl = null ;
241267 // Queries longer than 16KB is not cacheable
242- if ((sql .length () < MAX_CACHEABLE_QUERY_SIZE ) && sql .startsWith (QUERY_HINT_START_PATTERN )) {
268+ if ((sql .length () < maxCacheableQuerySize ) && sql .startsWith (QUERY_HINT_START_PATTERN )) {
243269 endOfQueryHint = sql .indexOf (QUERY_HINT_END_PATTERN );
244270 if (endOfQueryHint > 0 ) {
245- configuredQueryTtl = getTtlForQuery (sql .substring (2 , endOfQueryHint ).trim ());
246- mainQuery = sql .substring (endOfQueryHint + 2 ).trim ();
271+ configuredQueryTtl = getTtlForQuery (sql .substring (QUERY_HINT_START_PATTERN . length () , endOfQueryHint ).trim ());
272+ mainQuery = sql .substring (endOfQueryHint + QUERY_HINT_END_PATTERN . length () ).trim ();
247273 }
248274 }
249275
0 commit comments