Skip to content

Commit 83bec93

Browse files
authored
catch IndexOutOfBoundsException when accessing fields from metadata (#3672)
Accessing fields in struct metadata that are actually out of range, used to throw the underlying exception without actually wrapping it into SQLException, as required by the API. This was intrduced by a previous PR that changed the struct and arrays metadata to be backed by Relational's DataType rather than relying on sql type codes. This PR fixes this.
1 parent 9776f36 commit 83bec93

File tree

2 files changed

+22
-14
lines changed

2 files changed

+22
-14
lines changed

fdb-relational-api/src/main/java/com/apple/foundationdb/relational/api/RelationalStructMetaData.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ private DataType.StructType.Field getField(int oneBasedColumn) throws SQLExcepti
165165
try {
166166
int adjustedColPosition = leadingPhantomColumnOffset + (oneBasedColumn - 1);
167167
return type.getFields().get(adjustedColPosition);
168-
} catch (ArrayIndexOutOfBoundsException aie) {
168+
} catch (IndexOutOfBoundsException exception) {
169169
throw new InvalidColumnReferenceException("Position <" + oneBasedColumn + "> is not valid. Struct has " + getColumnCount() + " columns")
170170
.toSqlException();
171171
}

fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/StructDataMetadataTest.java

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,7 @@
2626
import com.apple.foundationdb.relational.api.Options;
2727
import com.apple.foundationdb.relational.api.RelationalResultSet;
2828
import com.apple.foundationdb.relational.api.RelationalStruct;
29-
import com.apple.foundationdb.relational.api.exceptions.RelationalException;
3029
import com.apple.foundationdb.relational.utils.SimpleDatabaseRule;
31-
3230
import org.junit.jupiter.api.Assertions;
3331
import org.junit.jupiter.api.BeforeEach;
3432
import org.junit.jupiter.api.Order;
@@ -40,6 +38,8 @@
4038
import java.sql.SQLException;
4139
import java.util.Set;
4240

41+
import static com.apple.foundationdb.relational.utils.RelationalAssertions.assertThrowsSqlException;
42+
4343
/**
4444
* Tests around using Struct data types in Returned ResultSets.
4545
*/
@@ -77,24 +77,21 @@ public class StructDataMetadataTest {
7777

7878
@BeforeEach
7979
void setUp() throws SQLException {
80-
final var t1 = EmbeddedRelationalStruct.newBuilder();
81-
var m = t1.addString("NAME", "test_record_1")
80+
var m = EmbeddedRelationalStruct.newBuilder()
81+
.addString("NAME", "test_record_1")
8282
.addStruct("ST1", EmbeddedRelationalStruct.newBuilder().addString("A", "Hello").build())
8383
.build();
84-
8584
statement.executeInsert("T", m);
8685

87-
final var ntBuilder = EmbeddedRelationalStruct.newBuilder();
88-
final var stBuilder = EmbeddedRelationalStruct.newBuilder();
89-
m = ntBuilder.addString("T_NAME", "nt_record")
90-
.addStruct("ST1", stBuilder
86+
m = EmbeddedRelationalStruct.newBuilder()
87+
.addString("T_NAME", "nt_record")
88+
.addStruct("ST1", EmbeddedRelationalStruct.newBuilder()
9189
.addLong("C", 1234L)
9290
.addStruct("D", EmbeddedRelationalStruct.newBuilder()
9391
.addString("A", "Goodbye")
9492
.build())
9593
.build())
9694
.build();
97-
9895
statement.executeInsert("NT", m);
9996

10097
final var atBuilder = EmbeddedRelationalStruct.newBuilder();
@@ -110,9 +107,7 @@ void setUp() throws SQLException {
110107
.build())
111108
.build())
112109
.build();
113-
114110
statement.executeInsert("AT", m);
115-
116111
}
117112

118113
@Test
@@ -130,6 +125,19 @@ void canReadSingleStruct() throws Exception {
130125
}
131126
}
132127

128+
@Test
129+
void errorAccessingNonExistentColumn() throws Exception {
130+
try (final RelationalResultSet resultSet = statement.executeGet("T", new KeySet().setKeyColumn("NAME", "test_record_1"), Options.NONE)) {
131+
Assertions.assertTrue(resultSet.next(), "Did not find a record!");
132+
final var actualStruct = resultSet.getStruct("ST1");
133+
Assertions.assertNotNull(actualStruct, "No struct found for column!");
134+
// Directly accessing the value throws SQLException
135+
assertThrowsSqlException(() -> actualStruct.getString(100)).containsInMessage("Invalid column position");
136+
// Accessing info in metadata throws SQLException as well
137+
assertThrowsSqlException(() -> actualStruct.getMetaData().getColumnType(100)).containsInMessage("Position <100> is not valid.");
138+
}
139+
}
140+
133141
@Test
134142
void canReadNestedStruct() throws Exception {
135143
final KeySet key = new KeySet().setKeyColumn("T_NAME", "nt_record");
@@ -190,7 +198,7 @@ void canReadRepeatedStruct() throws Exception {
190198
}
191199

192200
@Test
193-
void canReadRepeatedStructWithArray() throws RelationalException, SQLException {
201+
void canReadRepeatedStructWithArray() throws SQLException {
194202
final KeySet key = new KeySet().setKeyColumn("A_NAME", "a_test_rec");
195203
try (final RelationalResultSet resultSet = statement.executeGet("AT", key, Options.NONE)) {
196204
Assertions.assertTrue(resultSet.next(), "Did not find a record!");

0 commit comments

Comments
 (0)