2828import com .amazonaws .athena .connector .lambda .data .SchemaBuilder ;
2929import com .amazonaws .athena .connector .lambda .data .SpillConfig ;
3030import com .amazonaws .athena .connector .lambda .data .writers .extractors .*;
31+ import com .amazonaws .athena .connector .lambda .data .writers .holders .NullableVarBinaryHolder ;
32+ import com .amazonaws .athena .connector .lambda .data .writers .holders .NullableVarCharHolder ;
3133import com .amazonaws .athena .connector .lambda .domain .Split ;
3234import com .amazonaws .athena .connector .lambda .domain .TableName ;
3335import com .amazonaws .athena .connector .lambda .domain .predicate .ConstraintEvaluator ;
3941import com .amazonaws .athena .connectors .jdbc .connection .DatabaseConnectionConfig ;
4042import com .amazonaws .athena .connectors .jdbc .connection .JdbcConnectionFactory ;
4143import com .amazonaws .athena .connector .credentials .CredentialsProvider ;
44+ import org .apache .arrow .vector .holders .NullableBigIntHolder ;
45+ import org .apache .arrow .vector .holders .NullableBitHolder ;
46+ import org .apache .arrow .vector .holders .NullableDateDayHolder ;
47+ import org .apache .arrow .vector .holders .NullableDateMilliHolder ;
48+ import org .apache .arrow .vector .holders .NullableFloat4Holder ;
4249import org .apache .arrow .vector .holders .NullableFloat8Holder ;
50+ import org .apache .arrow .vector .holders .NullableIntHolder ;
51+ import org .apache .arrow .vector .holders .NullableSmallIntHolder ;
52+ import org .apache .arrow .vector .holders .NullableTinyIntHolder ;
4353import org .apache .arrow .vector .types .pojo .Schema ;
4454import org .junit .Assert ;
4555import org .junit .Before ;
5969import java .nio .charset .StandardCharsets ;
6070import java .sql .Connection ;
6171import java .sql .DatabaseMetaData ;
72+ import java .sql .Date ;
6273import java .sql .PreparedStatement ;
6374import java .sql .ResultSet ;
6475import java .sql .SQLException ;
76+ import java .sql .Timestamp ;
6577import java .sql .Types ;
78+ import java .time .LocalDate ;
79+ import java .time .LocalDateTime ;
6680import java .util .Collections ;
6781import java .util .Map ;
6882import java .util .concurrent .atomic .AtomicInteger ;
6983
7084import static org .mockito .ArgumentMatchers .any ;
85+ import static org .mockito .ArgumentMatchers .anyString ;
7186import static org .mockito .ArgumentMatchers .nullable ;
87+ import static org .mockito .Mockito .verify ;
88+ import static org .mockito .Mockito .when ;
7289
7390public class JdbcRecordHandlerTest
7491 extends TestBase
@@ -90,15 +107,15 @@ public void setup()
90107 {
91108 this .connection = Mockito .mock (Connection .class , Mockito .RETURNS_DEEP_STUBS );
92109 this .jdbcConnectionFactory = Mockito .mock (JdbcConnectionFactory .class );
93- Mockito . when (this .jdbcConnectionFactory .getConnection (nullable (CredentialsProvider .class ))).thenReturn (this .connection );
110+ when (this .jdbcConnectionFactory .getConnection (nullable (CredentialsProvider .class ))).thenReturn (this .connection );
94111 this .amazonS3 = Mockito .mock (S3Client .class );
95112 this .secretsManager = Mockito .mock (SecretsManagerClient .class );
96113 this .athena = Mockito .mock (AthenaClient .class );
97114 this .queryStatusChecker = Mockito .mock (QueryStatusChecker .class );
98- Mockito . when (this .queryStatusChecker .isQueryRunning ()).thenReturn (true );
99- Mockito . when (this .secretsManager .getSecretValue (Mockito .eq (GetSecretValueRequest .builder ().secretId ("testSecret" ).build ()))).thenReturn (GetSecretValueResponse .builder ().secretString ("{\" username\" : \" testUser\" , \" password\" : \" testPassword\" }" ).build ());
115+ when (this .queryStatusChecker .isQueryRunning ()).thenReturn (true );
116+ when (this .secretsManager .getSecretValue (Mockito .eq (GetSecretValueRequest .builder ().secretId ("testSecret" ).build ()))).thenReturn (GetSecretValueResponse .builder ().secretString ("{\" username\" : \" testUser\" , \" password\" : \" testPassword\" }" ).build ());
100117 this .preparedStatement = Mockito .mock (PreparedStatement .class );
101- Mockito . when (this .connection .prepareStatement ("someSql" )).thenReturn (this .preparedStatement );
118+ when (this .connection .prepareStatement ("someSql" )).thenReturn (this .preparedStatement );
102119 DatabaseConnectionConfig databaseConnectionConfig = new DatabaseConnectionConfig ("testCatalog" , "fakedatabase" ,
103120 "fakedatabase://jdbc:fakedatabase://hostname/${testSecret}" , "testSecret" );
104121 this .jdbcRecordHandler = new JdbcRecordHandler (this .amazonS3 , this .secretsManager , this .athena , databaseConnectionConfig , this .jdbcConnectionFactory , com .google .common .collect .ImmutableMap .of ())
@@ -117,7 +134,7 @@ public void readWithConstraint()
117134 throws Exception
118135 {
119136 ConstraintEvaluator constraintEvaluator = Mockito .mock (ConstraintEvaluator .class );
120- Mockito . when (constraintEvaluator .apply (nullable (String .class ), any ())).thenReturn (true );
137+ when (constraintEvaluator .apply (nullable (String .class ), any ())).thenReturn (true );
121138
122139 TableName inputTableName = new TableName ("testSchema" , "testTable" );
123140 SchemaBuilder expectedSchemaBuilder = SchemaBuilder .newBuilder ();
@@ -139,19 +156,19 @@ public void readWithConstraint()
139156 Object [][] values = {{1 , "testVal1" }, {2 , "testVal2" }};
140157 AtomicInteger rowNumber = new AtomicInteger (-1 );
141158 ResultSet resultSet = mockResultSet (schema , columnTypes , values , rowNumber );
142- Mockito . when (this .preparedStatement .executeQuery ()).thenReturn (resultSet );
159+ when (this .preparedStatement .executeQuery ()).thenReturn (resultSet );
143160
144161 // Mocking database metadata to return a non-ClickHouse database name eg:MySQL
145162 DatabaseMetaData metaData = Mockito .mock (DatabaseMetaData .class );
146- Mockito . when (metaData .getDatabaseProductName ()).thenReturn ("MySQL" );
147- Mockito . when (this .connection .getMetaData ()).thenReturn (metaData );
163+ when (metaData .getDatabaseProductName ()).thenReturn ("MySQL" );
164+ when (this .connection .getMetaData ()).thenReturn (metaData );
148165
149166 SpillConfig spillConfig = Mockito .mock (SpillConfig .class );
150- Mockito . when (spillConfig .getSpillLocation ()).thenReturn (s3SpillLocation );
167+ when (spillConfig .getSpillLocation ()).thenReturn (s3SpillLocation );
151168 BlockSpiller s3Spiller = new S3BlockSpiller (this .amazonS3 , spillConfig , allocator , fieldSchema , constraintEvaluator , com .google .common .collect .ImmutableMap .of ());
152169 ReadRecordsRequest readRecordsRequest = new ReadRecordsRequest (this .federatedIdentity , "testCatalog" , "testQueryId" , inputTableName , fieldSchema , splitBuilder .build (), constraints , 1024 , 1024 );
153170
154- Mockito . when (amazonS3 .putObject (any (PutObjectRequest .class ), any (RequestBody .class )))
171+ when (amazonS3 .putObject (any (PutObjectRequest .class ), any (RequestBody .class )))
155172 .thenAnswer ((InvocationOnMock invocationOnMock ) -> {
156173 ByteArrayInputStream inputStream = (ByteArrayInputStream ) ((RequestBody ) invocationOnMock .getArguments ()[1 ]).contentStreamProvider ().newStream ();
157174 int n = inputStream .available ();
@@ -174,7 +191,7 @@ public void makeExtractor()
174191 AtomicInteger rowNumber = new AtomicInteger (0 );
175192
176193 ResultSet resultSet = mockResultSet (schema , columnTypes , values , rowNumber );
177- Mockito . when (this .preparedStatement .executeQuery ()).thenReturn (resultSet );
194+ when (this .preparedStatement .executeQuery ()).thenReturn (resultSet );
178195 Map <String ,String > partitionMap = Collections .singletonMap ("testPartitionCol" ,"testPartitionValue" );
179196
180197 Extractor actualInt = this .jdbcRecordHandler .makeExtractor (FieldBuilder .newBuilder ("testCol1" , org .apache .arrow .vector .types .Types .MinorType .INT .getType ()).build (),resultSet ,partitionMap );
@@ -205,4 +222,78 @@ public void makeExtractor()
205222 ((Float8Extractor ) actualFloat8 ).extract (null , dollarValue );
206223 Assert .assertEquals (dollarValue .value , 1000.5 , 0.0 );
207224 }
225+
226+ @ Test
227+ public void testMakeExtractor ()
228+ throws Exception
229+ {
230+ Map <String ,String > partitionMap = Collections .singletonMap ("testPartitionCol" ,"testPartitionValue" );
231+ byte [] bytes = "test" .getBytes ();
232+ Date date = Date .valueOf (LocalDate .of (2025 , 4 , 22 ));
233+ Timestamp time = Timestamp .valueOf (LocalDateTime .of (2025 , 4 , 22 , 5 , 30 ));
234+
235+ ResultSet resultSet = Mockito .mock (ResultSet .class , Mockito .RETURNS_DEEP_STUBS );
236+
237+ when (resultSet .getInt ("testCol1" )).thenReturn (10 );
238+ when (resultSet .getString ("testCol2" )).thenReturn ("test" );
239+ when (resultSet .getBoolean ("testCol3" )).thenReturn (true );
240+ when (resultSet .getByte ("testCol4" )).thenReturn ((byte ) 100 );
241+ when (resultSet .getShort ("testCol5" )).thenReturn ((short ) 1234 );
242+ when (resultSet .getBytes ("testCol6" )).thenReturn (bytes );
243+ when (resultSet .getLong ("testCol8" )).thenReturn (10000L );
244+ when (resultSet .getFloat ("testCol9" )).thenReturn (123f );
245+ when (resultSet .getDate ("testCol11" )).thenReturn (date );
246+ when (resultSet .getTimestamp ("testCol12" )).thenReturn (time );
247+
248+ Extractor actualInt = this .jdbcRecordHandler .makeExtractor (FieldBuilder .newBuilder ("testCol1" , org .apache .arrow .vector .types .Types .MinorType .INT .getType ()).build (),resultSet ,partitionMap );
249+ Extractor actualVarchar = this .jdbcRecordHandler .makeExtractor (FieldBuilder .newBuilder ("testCol2" , org .apache .arrow .vector .types .Types .MinorType .VARCHAR .getType ()).build (),resultSet ,partitionMap );
250+ Extractor actualBit = this .jdbcRecordHandler .makeExtractor (FieldBuilder .newBuilder ("testCol3" , org .apache .arrow .vector .types .Types .MinorType .BIT .getType ()).build (),resultSet ,partitionMap );
251+ Extractor actualTinyInt = this .jdbcRecordHandler .makeExtractor (FieldBuilder .newBuilder ("testCol4" , org .apache .arrow .vector .types .Types .MinorType .TINYINT .getType ()).build (),resultSet ,partitionMap );
252+ Extractor actualSmallInt = this .jdbcRecordHandler .makeExtractor (FieldBuilder .newBuilder ("testCol5" , org .apache .arrow .vector .types .Types .MinorType .SMALLINT .getType ()).build (),resultSet ,partitionMap );
253+ Extractor actualVarbinary = this .jdbcRecordHandler .makeExtractor (FieldBuilder .newBuilder ("testCol6" , org .apache .arrow .vector .types .Types .MinorType .VARBINARY .getType ()).build (),resultSet ,partitionMap );
254+ Extractor actualBigInt = this .jdbcRecordHandler .makeExtractor (FieldBuilder .newBuilder ("testCol8" , org .apache .arrow .vector .types .Types .MinorType .BIGINT .getType ()).build (),resultSet ,partitionMap );
255+ Extractor actualFloat4 = this .jdbcRecordHandler .makeExtractor (FieldBuilder .newBuilder ("testCol9" , org .apache .arrow .vector .types .Types .MinorType .FLOAT4 .getType ()).build (),resultSet ,partitionMap );
256+ Extractor actualDateDay = this .jdbcRecordHandler .makeExtractor (FieldBuilder .newBuilder ("testCol11" , org .apache .arrow .vector .types .Types .MinorType .DATEDAY .getType ()).build (),resultSet ,partitionMap );
257+ Extractor actualDateMilli = this .jdbcRecordHandler .makeExtractor (FieldBuilder .newBuilder ("testCol12" , org .apache .arrow .vector .types .Types .MinorType .DATEMILLI .getType ()).build (),resultSet ,partitionMap );
258+
259+ NullableIntHolder intHolder = new NullableIntHolder ();
260+ ((IntExtractor ) actualInt ).extract (null , intHolder );
261+ Assert .assertEquals (10 , intHolder .value );
262+
263+ NullableVarCharHolder varHolder = new NullableVarCharHolder ();
264+ ((VarCharExtractor ) actualVarchar ).extract (null , varHolder );
265+ Assert .assertEquals ("test" , varHolder .value );
266+
267+ NullableBitHolder bitHolder = new NullableBitHolder ();
268+ ((BitExtractor ) actualBit ).extract (null , bitHolder );
269+ Assert .assertEquals (1 , bitHolder .value );
270+
271+ NullableTinyIntHolder tinyIntHolder = new NullableTinyIntHolder ();
272+ ((TinyIntExtractor ) actualTinyInt ).extract (null , tinyIntHolder );
273+ Assert .assertEquals (100 , tinyIntHolder .value );
274+
275+ NullableSmallIntHolder smallIntHolder = new NullableSmallIntHolder ();
276+ ((SmallIntExtractor ) actualSmallInt ).extract (null , smallIntHolder );
277+ Assert .assertEquals (1234 , smallIntHolder .value );
278+
279+ NullableVarBinaryHolder varBinaryHolder = new NullableVarBinaryHolder ();
280+ ((VarBinaryExtractor ) actualVarbinary ).extract (null , varBinaryHolder );
281+ Assert .assertEquals (bytes , varBinaryHolder .value );
282+
283+ NullableBigIntHolder bigIntHolder = new NullableBigIntHolder ();
284+ ((BigIntExtractor ) actualBigInt ).extract (null , bigIntHolder );
285+ Assert .assertEquals (10000L , bigIntHolder .value );
286+
287+ NullableFloat4Holder float4Holder = new NullableFloat4Holder ();
288+ ((Float4Extractor ) actualFloat4 ).extract (null , float4Holder );
289+ Assert .assertEquals (123f , float4Holder .value , 0.0 );
290+
291+ NullableDateDayHolder dateDayHolder = new NullableDateDayHolder ();
292+ ((DateDayExtractor ) actualDateDay ).extract (null , dateDayHolder );
293+ verify (resultSet , Mockito .times (2 )).getDate (anyString ());
294+
295+ NullableDateMilliHolder dateMilliHolder = new NullableDateMilliHolder ();
296+ ((DateMilliExtractor ) actualDateMilli ).extract (null , dateMilliHolder );
297+ verify (resultSet , Mockito .times (2 )).getTimestamp (anyString ());
298+ }
208299}
0 commit comments