Skip to content

Commit 9a2fed1

Browse files
committed
GH-44: Clear signature columns before re-populating in ArrowFlightStatement#executeFlightInfoQuery
ArrowFlightStatement#executeFlightInfoQuery appended the dataset schema columns to the statement's reused Meta.Signature without first clearing them, doubling the column list on every invocation. When the FlightInfo has at least one endpoint, ArrowFlightJdbcVectorSchemaRootResultSet overwrites signature.columns from the actual stream schema and hides the duplication. With an empty endpoint list — reported against both Rust- and Denodo-based Flight SQL servers — that overwrite never runs and ResultSetMetaData#getColumnCount() reports 2x the schema width. Regression introduced in 15.0.0 (GH-33475 prepared-statement parameter binding) when handle.signature became mutable across executions. Adds a regression test that registers a mock query with no endpoints and asserts ResultSetMetaData#getColumnCount() matches the schema. Closes #44.
1 parent 0f0a584 commit 9a2fed1

3 files changed

Lines changed: 32 additions & 0 deletions

File tree

flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/ArrowFlightStatement.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public FlightInfo executeFlightInfoQuery() throws SQLException {
5252
}
5353

5454
final Schema resultSetSchema = preparedStatement.getDataSetSchema();
55+
signature.columns.clear();
5556
signature.columns.addAll(
5657
ConvertUtils.convertArrowFieldsToColumnMetaDataList(resultSetSchema.getFields()));
5758
setSignature(signature);

flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/ResultSetMetadataTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,4 +220,23 @@ public void testShouldIsSearchable() throws SQLException {
220220
public void testShouldGetColumnTypesFromOutOfBoundIndex() {
221221
assertThrows(IndexOutOfBoundsException.class, () -> metadata.getColumnType(4));
222222
}
223+
224+
/**
225+
* Regression test for <a href="https://github.com/apache/arrow-java/issues/44">issue #44</a>:
226+
* {@code ArrowFlightStatement#executeFlightInfoQuery} appends schema columns to the reused {@code
227+
* Meta.Signature} without clearing the existing list. When the result has at least one endpoint,
228+
* the {@code FlightStream} consumption path overwrites {@code signature.columns} from the actual
229+
* stream schema and hides the duplication. With an empty endpoint list — the scenario reported
230+
* against both Rust- and Denodo-based Flight SQL servers — that overwrite never runs and {@code
231+
* ResultSetMetaData#getColumnCount()} reports double the schema width.
232+
*/
233+
@Test
234+
public void testShouldNotDuplicateColumnsWhenFlightInfoHasNoEndpoints() throws SQLException {
235+
try (Connection conn = FLIGHT_SERVER_TEST_EXTENSION.getConnection(false);
236+
Statement st = conn.createStatement();
237+
ResultSet rs =
238+
st.executeQuery(CoreMockedSqlProducers.LEGACY_REGULAR_NO_ENDPOINTS_SQL_CMD)) {
239+
assertThat(rs.getMetaData().getColumnCount(), equalTo(1));
240+
}
241+
}
223242
}

flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/utils/CoreMockedSqlProducers.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ public final class CoreMockedSqlProducers {
6767
public static final String LEGACY_METADATA_SQL_CMD = "SELECT * FROM METADATA";
6868
public static final String LEGACY_CANCELLATION_SQL_CMD = "SELECT * FROM TAKES_FOREVER";
6969
public static final String LEGACY_REGULAR_WITH_EMPTY_SQL_CMD = "SELECT * FROM TEST_EMPTIES";
70+
public static final String LEGACY_REGULAR_NO_ENDPOINTS_SQL_CMD =
71+
"SELECT * FROM TEST_NO_ENDPOINTS";
7072

7173
public static final String UUID_SQL_CMD = "SELECT * FROM UUID_TABLE";
7274
public static final String UUID_PREPARED_SELECT_SQL_CMD =
@@ -100,12 +102,22 @@ public static MockFlightSqlProducer getLegacyProducer() {
100102
addLegacyMetadataSqlCmdSupport(producer);
101103
addLegacyCancellationSqlCmdSupport(producer);
102104
addQueryWithEmbeddedEmptyRoot(producer);
105+
addQueryWithNoEndpoints(producer);
103106
addUuidSqlCmdSupport(producer);
104107
addUuidPreparedSelectSqlCmdSupport(producer);
105108
addUuidPreparedUpdateSqlCmdSupport(producer);
106109
return producer;
107110
}
108111

112+
private static void addQueryWithNoEndpoints(final MockFlightSqlProducer producer) {
113+
final Schema querySchema =
114+
new Schema(
115+
ImmutableList.of(
116+
new Field("ID", new FieldType(true, new ArrowType.Int(64, true), null), null)));
117+
producer.addSelectQuery(
118+
LEGACY_REGULAR_NO_ENDPOINTS_SQL_CMD, querySchema, Collections.emptyList());
119+
}
120+
109121
/**
110122
* Gets a {@link MockFlightSqlProducer} configured with UUID test data.
111123
*

0 commit comments

Comments
 (0)