Skip to content

Commit 24699cf

Browse files
authored
Deprecate EnableArrow — Arrow always enabled except on AIX/IBM Power (#1450)
## Summary `EnableArrow` connection property is deprecated and ignored. Arrow serialization is now always enabled. Setting `EnableArrow=0` logs a deprecation warning but has no effect. ### Behavior change | Scenario | Before | After | |----------|--------|-------| | `EnableArrow=0` on Linux/Mac/Windows | Arrow disabled, columnar inline results | Arrow enabled (value ignored), warning logged | | `EnableArrow=0` on AIX / IBM Power (`ppc`) | Arrow disabled | Arrow disabled (honoured — known native library issues) | | `EnableArrow=1` or not set | Arrow enabled | Arrow enabled (no change) | | SEA + CloudFetch disabled | N/A | JSON inline results (via `EnableQueryResultDownload=0`) | ### Changes - `shouldEnableArrow()`: Always returns `true` except on AIX (`os.name` contains `aix`) or IBM Power (`os.arch` contains `ppc`) - Removed client-type check that forced Thrift when Arrow was disabled — no longer needed - Updated `DatabricksJdbcUrlParams` description to indicate deprecation - Updated tests to reflect new behavior - Added breaking change to `NEXT_CHANGELOG.md` ## Test plan - [x] `DatabricksConnectionContextTest` — 120 tests pass (updated `testEnableCloudFetch` + decision matrix) - [x] `DatabricksSessionTest` + `DatabricksSdkClientTest` — 175 total, all pass This pull request was AI-assisted by Isaac. --------- Signed-off-by: Gopal Lal <gopal.lal@databricks.com>
1 parent 7859816 commit 24699cf

10 files changed

Lines changed: 93 additions & 189 deletions

NEXT_CHANGELOG.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
## [Unreleased]
44

5-
### BREAKING CHANGES in 3.4.1 — Metadata JDBC Spec Compliance
5+
### BREAKING CHANGES in 3.4.1
6+
7+
#### Metadata JDBC Spec Compliance
68

79
This release unifies metadata behavior across Thrift and SQL Exec API backends
810
using SQL SHOW commands for all metadata operations on SQL warehouses. Several
@@ -28,11 +30,22 @@ upgrading. These changes do not affect metadata on All-Purpose Clusters.
2830
instead of `0` (`CASCADE`) for Thrift, and `3` instead of `null` for SEA.**
2931
This reflects that Unity Catalog foreign keys are informational and non-enforced.
3032

33+
#### Default Behavior Changes
34+
3135
* **Native geospatial type support (`GEOMETRY` and `GEOGRAPHY`) is now enabled
3236
by default.** `getObject()` now returns `IGeometry`/`IGeography` instances
3337
instead of EWKT strings. Set `EnableGeoSpatialSupport=0` to restore the
3438
previous behavior.
3539

40+
* **`EnableArrow` connection property is deprecated and ignored.** Arrow
41+
serialization is now always enabled. Setting `EnableArrow=0` previously
42+
disabled Arrow and forced columnar/JSON inline results; this value is now
43+
ignored and a deprecation warning is logged. For JSON inline results with
44+
SEA, disable CloudFetch via `EnableQueryResultDownload=0`. Exception: on AIX
45+
platforms and PowerPC architectures (`os.arch` contains `ppc`), `EnableArrow`
46+
is still honoured and defaults to disabled due to known Arrow native library
47+
compatibility issues.
48+
3649
### Added
3750
- Metadata operations now use SQL SHOW commands for both Thrift and SEA backends,
3851
ensuring consistent behavior for SQL warehouses regardless of underlying

src/main/java/com/databricks/jdbc/api/impl/DatabricksConnectionContext.java

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ public class DatabricksConnectionContext implements IDatabricksConnectionContext
5757
private Supplier<DatabricksClientType> clientTypeSupplier;
5858
@VisibleForTesting final ImmutableMap<String, String> parameters;
5959
@VisibleForTesting final String connectionUuid;
60+
private final boolean enableArrow;
6061

6162
private DatabricksConnectionContext(
6263
String connectionURL,
@@ -73,6 +74,7 @@ private DatabricksConnectionContext(
7374
this.customHeaders = parseCustomHeaders(parameters);
7475
this.computeResource = buildCompute();
7576
this.connectionUuid = UUID.randomUUID().toString();
77+
this.enableArrow = resolveEnableArrow();
7678
this.clientTypeSupplier =
7779
new Supplier<>() {
7880
private DatabricksClientType cType;
@@ -97,6 +99,7 @@ private DatabricksConnectionContext(
9799
this.customHeaders = parseCustomHeaders(parameters);
98100
this.computeResource = null;
99101
this.connectionUuid = UUID.randomUUID().toString();
102+
this.enableArrow = resolveEnableArrow();
100103
}
101104

102105
/**
@@ -505,8 +508,8 @@ public DatabricksClientType getClientTypeFromContext() {
505508
remainingMs);
506509
return DatabricksClientType.THRIFT;
507510
}
508-
// Check if Arrow is disabled - Thrift is required for inline mode
509-
if (!Objects.equals(getParameter(DatabricksJdbcUrlParams.ENABLE_ARROW), "1")) {
511+
// On AIX/PowerPC, Arrow may be disabled — check before routing to SEA
512+
if (isAixOrPowerPc() && !shouldEnableArrow()) {
510513
return DatabricksClientType.THRIFT;
511514
}
512515
// Check if CloudFetch is disabled - Thrift is required for inline mode
@@ -669,7 +672,34 @@ public ProxyConfig.ProxyAuthType getCloudFetchProxyAuthType() {
669672

670673
@Override
671674
public Boolean shouldEnableArrow() {
672-
return Objects.equals(getParameter(DatabricksJdbcUrlParams.ENABLE_ARROW), "1");
675+
return enableArrow;
676+
}
677+
678+
/** Evaluates the Arrow enablement once at construction time. */
679+
private boolean resolveEnableArrow() {
680+
// Arrow is always enabled unless running on AIX or IBM Power (which have known
681+
// issues with the Arrow native library). The EnableArrow connection property is
682+
// deprecated and its value is ignored on non-AIX/IBM platforms.
683+
if (isAixOrPowerPc()) {
684+
// On AIX/PowerPC, Arrow native library has known issues — default to disabled.
685+
// Honour explicit EnableArrow=1 if user sets it.
686+
String explicitValue = getParameterIgnoreDefault(DatabricksJdbcUrlParams.ENABLE_ARROW);
687+
if (explicitValue != null) {
688+
return explicitValue.equals("1");
689+
}
690+
return false; // default disabled on AIX/PowerPC
691+
}
692+
693+
// Log deprecation warning once if user explicitly set EnableArrow=0 (ignored)
694+
String explicitValue = getParameterIgnoreDefault(DatabricksJdbcUrlParams.ENABLE_ARROW);
695+
if (explicitValue != null && explicitValue.equals("0")) {
696+
LOGGER.info(
697+
"EnableArrow=0 is deprecated and ignored. Arrow serialization is always enabled. "
698+
+ "To use JSON inline results with SEA, disable CloudFetch via "
699+
+ "EnableQueryResultDownload=0.");
700+
}
701+
702+
return true;
673703
}
674704

675705
@Override
@@ -1198,6 +1228,13 @@ private String getParameterIgnoreDefault(DatabricksJdbcUrlParams key) {
11981228
return this.parameters.getOrDefault(key.getParamName().toLowerCase(), null);
11991229
}
12001230

1231+
/** Returns true if running on AIX or IBM PowerPC architecture. */
1232+
private static boolean isAixOrPowerPc() {
1233+
String osName = System.getProperty("os.name", "").toLowerCase();
1234+
String osArch = System.getProperty("os.arch", "").toLowerCase();
1235+
return osName.contains("aix") || osArch.contains("ppc");
1236+
}
1237+
12011238
/**
12021239
* Resolves a boolean feature flag with client-side priority over server-side.
12031240
*

src/main/java/com/databricks/jdbc/common/DatabricksJdbcUrlParams.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,11 @@ public enum DatabricksJdbcUrlParams {
5555
DISCOVERY_URL("OAuthDiscoveryURL", "OAuth discovery URL"), // Same as OIDC_DISCOVERY_ENDPOINT
5656
IDENTITY_FEDERATION_CLIENT_ID(
5757
"Identity_Federation_Client_Id", "OAuth Client ID for Token Federation"),
58-
ENABLE_ARROW("EnableArrow", "Enable Arrow", "1"),
58+
ENABLE_ARROW(
59+
"EnableArrow",
60+
"Deprecated: Arrow is always enabled. Value ignored except on AIX. "
61+
+ "Use EnableQueryResultDownload=0 for JSON inline results with SEA.",
62+
"1"),
5963
DIRECT_RESULT("EnableDirectResults", "Enable direct results", "1"),
6064
LZ4_COMPRESSION_FLAG(
6165
"EnableQueryResultLZ4Compression", "Enable LZ4 compression"), // Backward compatibility

src/test/java/com/databricks/jdbc/api/impl/DatabricksConnectionContextTest.java

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -351,10 +351,26 @@ public void testEnableCloudFetch() throws DatabricksSQLException {
351351
(DatabricksConnectionContext)
352352
DatabricksConnectionContext.parse(TestConstants.VALID_URL_5, properties);
353353
assertTrue(connectionContext.shouldEnableArrow());
354+
// EnableArrow=0 is deprecated and ignored on non-AIX platforms — always returns true
354355
connectionContext =
355356
(DatabricksConnectionContext)
356357
DatabricksConnectionContext.parse(TestConstants.VALID_URL_7, properties);
357-
assertFalse(connectionContext.shouldEnableArrow());
358+
assertTrue(connectionContext.shouldEnableArrow());
359+
}
360+
361+
@Test
362+
public void testShouldEnableArrow_defaultIsTrue() throws DatabricksSQLException {
363+
// On non-AIX, Arrow is always enabled regardless of EnableArrow setting
364+
IDatabricksConnectionContext ctx =
365+
DatabricksConnectionContext.parse(TestConstants.VALID_URL_1, properties);
366+
assertTrue(ctx.shouldEnableArrow(), "Arrow should be enabled by default");
367+
}
368+
369+
@Test
370+
public void testShouldEnableArrow_explicitDisableIgnoredOnNonAix() throws DatabricksSQLException {
371+
IDatabricksConnectionContext ctx =
372+
DatabricksConnectionContext.parse(TestConstants.VALID_URL_1 + ";EnableArrow=0", properties);
373+
assertTrue(ctx.shouldEnableArrow(), "EnableArrow=0 should be ignored on non-AIX");
358374
}
359375

360376
@Test
@@ -946,7 +962,9 @@ public void testClientTypeWithExplicitUseThriftClientDisabled() throws Databrick
946962
}
947963

948964
@Test
949-
public void testClientTypeWhenArrowDisabled() throws DatabricksSQLException {
965+
public void testClientTypeWhenArrowDisabled_nonAix_ignoredDefaultsToThrift()
966+
throws DatabricksSQLException {
967+
// EnableArrow=0 is ignored on non-AIX — but without SEA feature flag, defaults to THRIFT
950968
String urlWithArrowDisabled =
951969
"jdbc:databricks://sample-host.cloud.databricks.com:9999/default;AuthMech=3;"
952970
+ "httpPath=/sql/1.0/warehouses/9999999999999999;EnableArrow=0";
@@ -968,7 +986,9 @@ public void testClientTypeWhenCloudFetchDisabled() throws DatabricksSQLException
968986
}
969987

970988
@Test
971-
public void testClientTypeWhenBothArrowAndCloudFetchDisabled() throws DatabricksSQLException {
989+
public void testClientTypeWhenBothArrowAndCloudFetchDisabled_nonAix()
990+
throws DatabricksSQLException {
991+
// EnableArrow=0 ignored on non-AIX; CloudFetch disabled → THRIFT
972992
String urlWithBothDisabled =
973993
"jdbc:databricks://sample-host.cloud.databricks.com:9999/default;AuthMech=3;"
974994
+ "httpPath=/sql/1.0/warehouses/9999999999999999;EnableArrow=0;EnableQueryResultDownload=0";
@@ -1104,11 +1124,12 @@ public void testClientTypeWhenFeatureFlagNotFound() throws DatabricksSQLExceptio
11041124
"false, 1, 1, 1, true, THRIFT", // Explicit useThriftClient=1 returns THRIFT
11051125
"false, 0, 1, 1, true, SEA", // Explicit useThriftClient=0 returns SEA
11061126
"false, 0, 1, 1, false, SEA", // Explicit useThriftClient=0 returns SEA (ignores flag)
1107-
"false, null, 0, 1, true, THRIFT", // Arrow disabled returns THRIFT
1127+
"false, null, 0, 1, true, SEA", // Arrow param ignored (deprecated) + CloudFetch enabled +
1128+
// flag=true → SEA
11081129
"false, null, 1, 0, true, THRIFT", // CloudFetch disabled returns THRIFT
11091130
"false, null, 1, 1, true, SEA", // All enabled + flag=true returns SEA
11101131
"false, null, 1, 1, false, THRIFT", // All enabled + flag=false returns THRIFT
1111-
"false, null, 0, 0, true, THRIFT", // Both Arrow and CloudFetch disabled returns THRIFT
1132+
"false, null, 0, 0, true, THRIFT", // CloudFetch disabled returns THRIFT (Arrow param ignored)
11121133
})
11131134
public void testClientTypeDecisionMatrix(
11141135
boolean isCluster,

src/test/java/com/databricks/jdbc/integration/fakeservice/tests/DataTypesIntegrationTests.java

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import com.databricks.jdbc.integration.fakeservice.AbstractFakeServiceIntegrationTests;
99
import com.databricks.jdbc.integration.fakeservice.FakeServiceExtension;
1010
import java.sql.*;
11-
import java.util.Properties;
1211
import java.util.stream.Stream;
1312
import org.junit.jupiter.api.AfterEach;
1413
import org.junit.jupiter.api.Assumptions;
@@ -22,7 +21,6 @@
2221
public class DataTypesIntegrationTests extends AbstractFakeServiceIntegrationTests {
2322

2423
private Connection connection;
25-
private Connection inlineConnection;
2624

2725
private static final String LEADING_TRAILING_SPACES = " leading and trailing spaces ";
2826
private static final String UNICODE_TEXT = "こんにちは";
@@ -32,15 +30,11 @@ public class DataTypesIntegrationTests extends AbstractFakeServiceIntegrationTes
3230
@BeforeEach
3331
void setUp() throws SQLException {
3432
connection = getValidJDBCConnection();
35-
Properties properties = new Properties();
36-
properties.setProperty("enableArrow", "0");
37-
inlineConnection = getValidJDBCConnection(properties);
3833
}
3934

4035
@AfterEach
4136
void cleanUp() throws SQLException {
4237
closeConnection(connection);
43-
closeConnection(inlineConnection);
4438
}
4539

4640
@Test
@@ -63,28 +57,18 @@ void testStringEdgeCases() throws SQLException {
6357
+ ") AS string_edge_cases(id, test_string) "
6458
+ "ORDER BY id";
6559
ResultSet resultSet = executeQuery(connection, query);
66-
ResultSet inlineResultSet = executeQuery(inlineConnection, query);
67-
6860
validateStringResults(resultSet);
69-
validateStringResults(inlineResultSet);
70-
7161
resultSet.close();
72-
inlineResultSet.close();
7362
}
7463

7564
@ParameterizedTest
7665
@MethodSource("nullHandlingProvider")
7766
void testNullHandling(String query, int expectedType) throws SQLException {
7867
ResultSet resultSet = executeQuery(connection, query);
79-
ResultSet inlineResultSet = executeQuery(inlineConnection, query);
8068
assertTrue(resultSet.next());
81-
assertTrue(inlineResultSet.next());
8269
assertNull(resultSet.getObject(1));
83-
assertNull(inlineResultSet.getObject(1));
8470
assertEquals(expectedType, resultSet.getMetaData().getColumnType(1));
85-
assertEquals(expectedType, inlineResultSet.getMetaData().getColumnType(1));
8671
resultSet.close();
87-
inlineResultSet.close();
8872
}
8973

9074
private static Stream<Arguments> nullHandlingProvider() {
@@ -235,9 +219,7 @@ void testTimestamp() throws SQLException {
235219

236220
String query = "SELECT id, ts FROM " + getFullyQualifiedTableName(tableName) + " ORDER BY id";
237221
ResultSet resultSet = executeQuery(connection, query);
238-
ResultSet inlineResultSet = executeQuery(inlineConnection, query);
239222
validateTimestampResults(resultSet);
240-
validateTimestampResults(inlineResultSet);
241223

242224
deleteTable(connection, tableName);
243225
resultSet.close();
Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,12 @@
11
package com.databricks.jdbc.integration.fakeservice.tests;
22

3-
import static com.databricks.jdbc.integration.IntegrationTestUtil.getValidJDBCConnection;
4-
import static org.junit.jupiter.api.Assertions.assertEquals;
5-
63
import com.databricks.jdbc.integration.fakeservice.AbstractFakeServiceIntegrationTests;
7-
import java.sql.Connection;
8-
import java.sql.ResultSet;
9-
import java.sql.SQLException;
10-
import java.sql.Statement;
11-
import java.util.Properties;
12-
import org.junit.jupiter.api.Test;
13-
14-
public class SqlExecApiIntegrationTests extends AbstractFakeServiceIntegrationTests {
15-
16-
@Test
17-
void testJsonInlineChunkedResults_withoutArrow() throws SQLException {
18-
final String table = "samples.tpch.lineitem";
19-
// Limit set such that atleast 2 chunks are present for results
20-
final int maxRows = 64000;
21-
final String sql = "SELECT * FROM " + table + " limit " + maxRows;
22-
23-
Properties properties = new Properties();
24-
properties.setProperty("EnableArrow", "0");
25-
Connection connection = getValidJDBCConnection(properties);
264

27-
final Statement stmt = connection.createStatement();
28-
ResultSet rs = stmt.executeQuery(sql);
29-
int rowCount = 0;
30-
while (rs.next()) {
31-
rowCount++;
32-
}
33-
assertEquals(maxRows, rowCount);
34-
}
35-
}
5+
/**
6+
* SQL Exec API integration tests. The original JSON inline chunked results test
7+
* (testJsonInlineChunkedResults_withoutArrow) was removed because EnableArrow=0 is now deprecated
8+
* and ignored — Arrow is always enabled on non-AIX platforms. The WireMock recordings were captured
9+
* with JSON_ARRAY format which no longer matches the driver's requests. Chunked Arrow results are
10+
* covered by MultiChunkExecutionIntegrationTests and SqlExecApiHybridResultsIntegrationTests.
11+
*/
12+
public class SqlExecApiIntegrationTests extends AbstractFakeServiceIntegrationTests {}

src/test/resources/sqlexecapi/sqlexecapiintegrationtests/testjsoninlinechunkedresults_withoutarrow/mappings/api_2.0_sql_sessions-344861bc-8e95-4d1c-889d-cbd425906d03.json

Lines changed: 0 additions & 35 deletions
This file was deleted.

src/test/resources/sqlexecapi/sqlexecapiintegrationtests/testjsoninlinechunkedresults_withoutarrow/mappings/api_2.0_sql_statements-994cb021-b4be-45d7-9626-3ba0a8911bf0.json

Lines changed: 0 additions & 35 deletions
This file was deleted.

0 commit comments

Comments
 (0)