1212import com .google .common .annotations .VisibleForTesting ;
1313import java .io .IOException ;
1414import java .sql .ResultSet ;
15+ import java .util .concurrent .ConcurrentHashMap ;
16+ import java .util .concurrent .ConcurrentMap ;
1517
1618/**
1719 * Utility class for operations related to the Databricks JDBC driver.
2224public class DriverUtil {
2325
2426 private static final JdbcLogger LOGGER = JdbcLoggerFactory .getLogger (DriverUtil .class );
27+ public static final String DBSQL_VERSION_SQL = "SELECT current_version().dbsql_version" ;
2528 private static final String VERSION = "0.9.7-oss" ;
26- private static final String DBSQL_VERSION_SQL = "SELECT current_version().dbsql_version" ;
27- public static final int DBSQL_MIN_MAJOR_VERSION_FOR_SEA_SUPPORT = 2024 ;
28- public static final int DBSQL_MIN_MINOR_VERSION_FOR_SEA_SUPPORT = 30 ;
29+ private static final int DBSQL_MIN_MAJOR_VERSION_FOR_SEA_SUPPORT = 2024 ;
30+ private static final int DBSQL_MIN_MINOR_VERSION_FOR_SEA_SUPPORT = 30 ;
31+
32+ /** Cached DBSQL version mapped by HTTP path to avoid repeated queries to the cluster. */
33+ private static final ConcurrentMap <String , String > cachedDBSQLVersions =
34+ new ConcurrentHashMap <>();
35+
2936 private static final String [] VERSION_PARTS = VERSION .split ("[.-]" );
3037
3138 public static String getVersion () {
@@ -46,7 +53,7 @@ public static void resolveMetadataClient(IDatabricksConnection connection)
4653 LOGGER .warn ("Empty metadata client is being used." );
4754 connection .getSession ().setEmptyMetadataClient ();
4855 }
49- ensureUpdatedDBRVersionInUse (connection );
56+ ensureUpdatedDBSQLVersionInUse (connection );
5057 }
5158
5259 public static void setUpLogging (IDatabricksConnectionContext connectionContext )
@@ -73,6 +80,13 @@ public static String getRootCauseMessage(Throwable e) {
7380 : e .getMessage ();
7481 }
7582
83+ /**
84+ * Returns whether the driver is running against fake services based on request/response stubs.
85+ */
86+ public static boolean isRunningAgainstFake () {
87+ return Boolean .parseBoolean (System .getProperty (IS_FAKE_SERVICE_TEST_PROP ));
88+ }
89+
7690 private static Throwable getRootCause (Throwable throwable ) {
7791 Throwable cause ;
7892 while ((cause = throwable .getCause ()) != null && cause != throwable ) {
@@ -82,38 +96,58 @@ private static Throwable getRootCause(Throwable throwable) {
8296 }
8397
8498 @ VisibleForTesting
85- static void ensureUpdatedDBRVersionInUse (IDatabricksConnection connection )
99+ static void ensureUpdatedDBSQLVersionInUse (IDatabricksConnection connection )
86100 throws DatabricksValidationException {
87101 if (connection .getConnectionContext ().getClientType () != DatabricksClientType .SQL_EXEC
88102 || isRunningAgainstFake ()) {
89103 // Check applicable only for SEA flow
90104 return ;
91105 }
92- String dbrVersion = getDBRVersion (connection );
93- if (!doesDriverSupportSEA (dbrVersion )) {
106+ String dbsqlVersion = getDBSQLVersionCached (connection );
107+ if (!doesDriverSupportSEA (dbsqlVersion )) {
94108 String errorMessage =
95109 String .format (
96- "Unsupported DBR version %s. Please update your compute to use the latest DBR version." ,
97- dbrVersion );
110+ "Unsupported DBSQL version %s. Please update your compute to use the latest DBSQL version." ,
111+ dbsqlVersion );
98112 LOGGER .error (errorMessage );
99113 throw new DatabricksValidationException (errorMessage );
100114 }
101115 }
102116
103- private static String getDBRVersion (IDatabricksConnection connection ) {
117+ private static String getDBSQLVersionCached (IDatabricksConnection connection ) {
118+ String httpPath = connection .getConnectionContext ().getHttpPath ();
119+ String version = cachedDBSQLVersions .get (httpPath );
120+ if (version != null ) {
121+ LOGGER .debug ("Using cached DBSQL Version for path %s: %s" , httpPath , version );
122+ return version ;
123+ }
124+
125+ synchronized (DriverUtil .class ) {
126+ version = cachedDBSQLVersions .get (httpPath );
127+ if (version != null ) {
128+ return version ;
129+ }
130+
131+ version = queryDBSQLVersion (connection );
132+ cachedDBSQLVersions .put (httpPath , version );
133+ return version ;
134+ }
135+ }
136+
137+ private static String queryDBSQLVersion (IDatabricksConnection connection ) {
104138 try (ResultSet resultSet = connection .createStatement ().executeQuery (DBSQL_VERSION_SQL )) {
105139 resultSet .next ();
106- String dbrVersion = resultSet .getString (1 );
107- LOGGER .debug ("DBR Version in use: %s" , dbrVersion );
108- return dbrVersion ;
140+ String dbsqlVersion = resultSet .getString (1 );
141+ LOGGER .debug ("DBSQL Version in use: %s" , dbsqlVersion );
142+ return dbsqlVersion ;
109143 } catch (Exception e ) {
110144 LOGGER .info (
111- "Error retrieving DBR version: {%s}. Defaulting to minimum supported version." , e );
112- return getDefaultDBRVersion ();
145+ "Error retrieving DBSQL version: {%s}. Defaulting to minimum supported version." , e );
146+ return getDefaultDBSQLVersion ();
113147 }
114148 }
115149
116- private static String getDefaultDBRVersion () {
150+ private static String getDefaultDBSQLVersion () {
117151 return DBSQL_MIN_MAJOR_VERSION_FOR_SEA_SUPPORT + "." + DBSQL_MIN_MINOR_VERSION_FOR_SEA_SUPPORT ;
118152 }
119153
@@ -127,7 +161,8 @@ private static boolean doesDriverSupportSEA(String dbsqlVersion) {
127161 return majorVersion > DBSQL_MIN_MAJOR_VERSION_FOR_SEA_SUPPORT ;
128162 }
129163
130- public static boolean isRunningAgainstFake () {
131- return Boolean .parseBoolean (System .getProperty (IS_FAKE_SERVICE_TEST_PROP ));
164+ @ VisibleForTesting
165+ static void clearDBSQLVersionCache () {
166+ cachedDBSQLVersions .clear ();
132167 }
133168}
0 commit comments