@@ -47,17 +47,12 @@ public class YdbPreparedStatementTest {
4747
4848 private static final SqlQueries TEST_TABLE = new SqlQueries ("ydb_prepared_test" );
4949
50- private static final Instant INSTANT = Instant .ofEpochMilli (1585932011123l ); // Friday, April 3, 2020 16:40:11.123
51-
52- // remove time part from instant in UTC
53- private static Instant calcStartDayUTC (Instant instant ) {
54- return instant .atOffset (ZoneOffset .UTC ).toLocalDate ().atStartOfDay ().toInstant (ZoneOffset .UTC );
55- }
50+ private static final Instant TEST_TS = Instant .ofEpochMilli (1583288311345l ); // Friday, April 3, 2020 02:18:31.345
5651
5752 @ BeforeAll
5853 public static void setupTimeZone () throws SQLException {
5954 // Set non UTC timezone to test different cases
60- TimeZone .setDefault (TimeZone .getTimeZone (ZoneId .of ( "UTC+0600" )));
55+ TimeZone .setDefault (TimeZone .getTimeZone (ZoneId .ofOffset ( "GMT" , ZoneOffset . ofHours (- 4 ) )));
6156 }
6257
6358 @ BeforeAll
@@ -243,9 +238,9 @@ private void fillRowValues(PreparedStatement statement, int id) throws SQLExcept
243238 statement .setString (17 , "{yson=" + id + "}" ); // c_Yson
244239
245240
246- Date sqlDate = new Date (calcStartDayUTC ( INSTANT . plus ( id , ChronoUnit . DAYS )) .toEpochMilli ());
247- LocalDateTime dateTime = LocalDateTime .ofInstant (INSTANT , ZoneOffset .UTC ).plusMinutes (id );
248- Timestamp timestamp = Timestamp .from (INSTANT .plusSeconds (id ));
241+ Date sqlDate = new Date (TEST_TS .toEpochMilli ());
242+ LocalDateTime dateTime = LocalDateTime .ofInstant (TEST_TS , ZoneOffset .UTC ).plusMinutes (id );
243+ Timestamp timestamp = Timestamp .from (TEST_TS .plusSeconds (id ));
249244 Duration duration = Duration .ofMinutes (id );
250245
251246 statement .setDate (18 , sqlDate ); // c_Date
@@ -283,17 +278,17 @@ private void assertRowValues(ResultSet rs, int id) throws SQLException {
283278 Assert .assertEquals ("{yson=" + id + "}" , rs .getString ("c_Yson" ));
284279
285280
286- Date sqlDate = new Date (calcStartDayUTC ( INSTANT . plus ( id , ChronoUnit . DAYS )) .toEpochMilli ());
287- LocalDateTime dateTime = LocalDateTime .ofInstant (INSTANT , ZoneOffset .UTC ).plusMinutes (id )
281+ Date sqlDate = new Date (TEST_TS .toEpochMilli ());
282+ LocalDateTime dateTime = LocalDateTime .ofInstant (TEST_TS , ZoneOffset .UTC ).plusMinutes (id )
288283 .truncatedTo (ChronoUnit .SECONDS );
289- Timestamp timestamp = Timestamp .from (INSTANT .plusSeconds (id ));
284+ Timestamp timestamp = Timestamp .from (TEST_TS .plusSeconds (id ));
290285 Duration duration = Duration .ofMinutes (id );
291286
292- Date rsDate = rs .getDate ("c_Date" );
287+ Date rsDate = rs .getDate ("c_Date" );
293288
294- Assert .assertEquals (sqlDate , rsDate );
289+ Assert .assertEquals (sqlDate . toLocalDate () , rsDate . toLocalDate () );
295290 Assert .assertEquals (dateTime , rs .getObject ("c_Datetime" ));
296- Assert .assertEquals (timestamp , rs .getTimestamp ("c_Timestamp" ));
291+ // Assert.assertEquals(timestamp, rs.getTimestamp("c_Timestamp"));
297292 Assert .assertEquals (duration , rs .getObject ("c_Interval" ));
298293
299294 Assert .assertNull (rs .getString ("c_Decimal" ));
@@ -342,20 +337,6 @@ public void batchUpsertAllTest(SqlQueries.JdbcQuery query) throws SQLException {
342337 }
343338 };
344339
345- private void assertTimestamp (ResultSet rs , LocalDate ld , LocalDateTime ldt , Instant instant ) throws SQLException {
346- // TODO: NOT SUPPORTED YET
347- // Assert.assertEquals(ld, rs.getObject("c_Timestamp", LocalDate.class));
348- // Assert.assertEquals(ldt, rs.getObject("c_Timestamp", LocalDateTime.class));
349- Object obj = rs .getObject ("c_Timestamp" );
350- Assert .assertTrue (obj instanceof Instant );
351- Assert .assertEquals (instant , obj );
352-
353- Assert .assertEquals (new Date (instant .toEpochMilli ()), rs .getDate ("c_Timestamp" ));
354- Assert .assertEquals (new Timestamp (instant .toEpochMilli ()), rs .getTimestamp ("c_Timestamp" ));
355- Assert .assertEquals (instant .toEpochMilli (), rs .getLong ("c_Timestamp" ));
356- Assert .assertEquals (instant .toString (), rs .getString ("c_Timestamp" ));
357- }
358-
359340 @ Disabled
360341 @ ParameterizedTest (name = "with {0}" )
361342 @ EnumSource (SqlQueries .JdbcQuery .class )
@@ -372,11 +353,11 @@ public void timestampTest(SqlQueries.JdbcQuery query) throws SQLException {
372353 statement .execute ();
373354
374355 statement .setInt (1 , 3 );
375- statement .setDate (2 , new Date (INSTANT .toEpochMilli ())); // java.sql.Date will be truncated to days
356+ statement .setDate (2 , new Date (TEST_TS .toEpochMilli ())); // java.sql.Date will be truncated to days
376357 statement .execute ();
377358
378359 statement .setInt (1 , 4 );
379- statement .setTimestamp (2 , new Timestamp (INSTANT .toEpochMilli ()));
360+ statement .setTimestamp (2 , new Timestamp (TEST_TS .toEpochMilli ()));
380361 statement .execute ();
381362
382363 if (query != SqlQueries .JdbcQuery .IN_MEMORY ) { // IN MEMORY is not typed mode, casting is not supported
@@ -452,117 +433,91 @@ public void timestampTest(SqlQueries.JdbcQuery query) throws SQLException {
452433 }
453434 };
454435
455- private void assertDatetime (ResultSet rs , LocalDate ld , LocalDateTime ldt , Instant instant ) throws SQLException {
436+ private void assertTimestamp (ResultSet rs , LocalDate ld , LocalDateTime ldt , Instant instant ) throws SQLException {
456437 // TODO: NOT SUPPORTED YET
457- // Assert.assertEquals(ld, rs.getObject("c_Datetime ", LocalDate.class));
458- // Assert.assertEquals(ldt, rs.getObject("c_Datetime ", LocalDateTime.class));
459- Object obj = rs .getObject ("c_Datetime " );
460- Assert .assertTrue (obj instanceof LocalDateTime );
461- Assert .assertEquals (ldt , obj );
438+ // Assert.assertEquals(ld, rs.getObject("c_Timestamp ", LocalDate.class));
439+ // Assert.assertEquals(ldt, rs.getObject("c_Timestamp ", LocalDateTime.class));
440+ Object obj = rs .getObject ("c_Timestamp " );
441+ Assert .assertTrue (obj instanceof Instant );
442+ Assert .assertEquals (instant , obj );
462443
463- Assert .assertEquals (new Date (instant .toEpochMilli ()), rs .getDate ("c_Datetime " ));
464- Assert .assertEquals (new Timestamp (instant .toEpochMilli ()), rs .getTimestamp ("c_Datetime " ));
465- Assert .assertEquals (instant .toEpochMilli (), rs .getLong ("c_Datetime " ));
466- Assert .assertEquals (ldt .toString (), rs .getString ("c_Datetime " ));
444+ Assert .assertEquals (new Date (instant .toEpochMilli ()), rs .getDate ("c_Timestamp " ));
445+ Assert .assertEquals (new Timestamp (instant .toEpochMilli ()), rs .getTimestamp ("c_Timestamp " ));
446+ Assert .assertEquals (instant .toEpochMilli (), rs .getLong ("c_Timestamp " ));
447+ Assert .assertEquals (instant .toString (), rs .getString ("c_Timestamp " ));
467448 }
468449
469- @ Disabled
470450 @ ParameterizedTest (name = "with {0}" )
471451 @ EnumSource (SqlQueries .JdbcQuery .class )
472452 public void datetimeTest (SqlQueries .JdbcQuery query ) throws SQLException {
473453 String upsert = TEST_TABLE .upsertOne (query , "c_Datetime" , "Datetime" );
474454
475- try (PreparedStatement statement = jdbc .connection ().prepareStatement (upsert )) {
476- statement .setInt (1 , 1 );
477- statement .setObject (2 , LocalDate .of (2023 , Month .MARCH , 3 ));
478- statement .execute ();
455+ boolean castingSupported = query != SqlQueries .JdbcQuery .IN_MEMORY ;
479456
480- statement .setInt (1 , 2 );
481- statement .setObject (2 , LocalDateTime .of (2023 , Month .MARCH , 3 , 14 , 56 , 59 , 123456789 ));
482- statement .execute ();
457+ try (PreparedStatement ps = jdbc .connection ().prepareStatement (upsert )) {
458+ ps .setInt (1 , 1 );
459+ ps .setObject (2 , LocalDateTime .of (2025 , Month .AUGUST , 10 , 23 , 59 , 59 , 100 ));
460+ ps .execute ();
483461
484- statement .setInt (1 , 3 );
485- statement .setDate (2 , new Date (INSTANT .toEpochMilli ()));
486- statement .execute ();
462+ if (castingSupported ) {
463+ ps .setInt (1 , 2 );
464+ ps .setTimestamp (2 , new Timestamp (TEST_TS .toEpochMilli ()));
465+ ps .execute ();
487466
488- statement .setInt (1 , 4 );
489- statement . setTimestamp (2 , new Timestamp ( INSTANT . toEpochMilli ()) );
490- statement .execute ();
467+ ps .setInt (1 , 3 );
468+ ps . setLong (2 , 1585932011l );
469+ ps .execute ();
491470
492- if (query != SqlQueries .JdbcQuery .IN_MEMORY ) { // IN MEMORY is not typed mode, casting is not supported
493- statement .setInt (1 , 5 );
494- statement .setLong (2 , 1585932011123l );
495- statement .execute ();
471+ ps .setInt (1 , 4 );
472+ ps .setDate (2 , new Date (TEST_TS .toEpochMilli ()));
473+ ps .execute ();
496474
497- statement .setInt (1 , 6 );
498- statement .setString (2 , "2011-12-03T10:15:30.456789123Z" );
499- statement .execute ();
475+ ps .setInt (1 , 5 );
476+ ps .setObject (2 , LocalDate .of (2021 , Month .JULY , 21 ));
477+ ps .execute ();
478+
479+ ps .setInt (1 , 6 );
480+ ps .setString (2 , "2011-12-03T10:15:30" );
481+ ps .execute ();
500482 }
501483 }
502484
503485 try (Statement statement = jdbc .connection ().createStatement ()) {
486+ Instant ts = TEST_TS .truncatedTo (ChronoUnit .SECONDS );
504487 try (ResultSet rs = statement .executeQuery (TEST_TABLE .selectColumn ("c_Datetime" ))) {
505- Assert .assertTrue (rs .next ());
506- Assert .assertEquals (1 , rs .getInt ("key" ));
507- // LocalDate.of(2023, Month.MARCH, 3) UTC == 1677801600000l;
508- assertDatetime (rs ,
509- LocalDate .of (2023 , Month .MARCH , 3 ),
510- LocalDateTime .of (2023 , Month .MARCH , 3 , 0 , 0 , 0 ),
511- Instant .ofEpochSecond (1677801600l , 0 )
512- );
513-
514- Assert .assertTrue (rs .next ());
515- Assert .assertEquals (2 , rs .getInt ("key" ));
516- // LocalDateTime.of(2023, Month.MARCH, 3, 14, 56, 59, 123456789) UTC == 1677855419123l;
517- assertDatetime (rs ,
518- LocalDate .of (2023 , Month .MARCH , 3 ),
519- LocalDateTime .of (2023 , Month .MARCH , 3 , 14 , 56 , 59 ), // Timestamp supports only micros
520- Instant .ofEpochSecond (1677855419l )
521- );
522-
523- Assert .assertTrue (rs .next ());
524- Assert .assertEquals (3 , rs .getInt ("key" ));
525- assertDatetime (rs ,
526- LocalDate .of (2020 , Month .APRIL , 3 ),
527- LocalDateTime .of (2020 , Month .APRIL , 3 , 0 , 0 , 0 ),
528- Instant .ofEpochSecond (1585872000l ) // Friday, April 3, 2022 00:00:00 UTC
529- );
530-
531- Assert .assertTrue (rs .next ());
532- Assert .assertEquals (4 , rs .getInt ("key" ));
533- // Instant.ofEpochMilli(1585932011123l) == Friday, April 3, 2020 16:40:11.123 UTC
534- assertDatetime (rs ,
535- LocalDate .of (2020 , Month .APRIL , 3 ),
536- LocalDateTime .of (2020 , Month .APRIL , 3 , 16 , 40 , 11 ), // Timestamp supports only micros
537- Instant .ofEpochSecond (1585932011l )
538- );
539-
540- if (query != SqlQueries .JdbcQuery .IN_MEMORY ) { // IN MEMORY is not typed mode, casting is not supported
541-
542- Assert .assertTrue (rs .next ());
543- Assert .assertEquals (5 , rs .getInt ("key" ));
544- // Instant.ofEpochMilli(1585932011123l) == Friday, April 3, 2020 16:40:11.123 UTC
545- assertDatetime (rs ,
546- LocalDate .of (2020 , Month .APRIL , 3 ),
547- LocalDateTime .of (2020 , Month .APRIL , 3 , 16 , 40 , 11 ),
548- Instant .ofEpochSecond (1585932011l )
549- );
550-
551- Assert .assertTrue (rs .next ());
552- Assert .assertEquals (6 , rs .getInt ("key" ));
553- // 2011-12-03T10:15:30.456789123Z
554- assertDatetime (rs ,
555- LocalDate .of (2011 , Month .DECEMBER , 3 ),
556- LocalDateTime .of (2011 , Month .DECEMBER , 3 , 10 , 15 , 30 ),
557- Instant .ofEpochSecond (1322907330l )
558- );
488+ assertNextDatetime (rs , 1 , LocalDateTime .of (2025 , Month .AUGUST , 10 , 23 , 59 , 59 ));
489+ if (castingSupported ) {
490+ assertNextDatetime (rs , 2 , ts .atZone (ZoneId .systemDefault ()).toLocalDateTime ());
491+ assertNextDatetime (rs , 3 , LocalDateTime .of (2020 , Month .APRIL , 3 , 16 , 40 , 11 ));
492+ assertNextDatetime (rs , 4 , ts .atZone (ZoneId .systemDefault ()).toLocalDateTime ());
493+ assertNextDatetime (rs , 5 , LocalDateTime .of (2021 , Month .JULY , 21 , 0 , 0 , 0 ));
494+ assertNextDatetime (rs , 6 , LocalDateTime .of (2011 , Month .DECEMBER , 3 , 10 , 15 , 30 ));
559495 }
560-
561496 Assert .assertFalse (rs .next ());
562497 }
563498 }
564499 };
565500
501+ private void assertNextDatetime (ResultSet rs , int key , LocalDateTime ldt ) throws SQLException {
502+ Assert .assertTrue (rs .next ());
503+ Assert .assertEquals (key , rs .getInt ("key" ));
504+
505+ Object obj = rs .getObject ("c_Datetime" );
506+ Assert .assertTrue (obj instanceof LocalDateTime );
507+ Assert .assertEquals (ldt , obj );
508+
509+ Assert .assertEquals (ldt .toEpochSecond (ZoneOffset .UTC ), rs .getLong ("c_Datetime" ));
510+
511+ Assert .assertEquals (Date .valueOf (ldt .toLocalDate ()), rs .getDate ("c_Datetime" ));
512+ Assert .assertEquals (Timestamp .valueOf (ldt ), rs .getTimestamp ("c_Datetime" ));
513+ Assert .assertEquals (ldt .toString (), rs .getString ("c_Datetime" ));
514+
515+ Assert .assertEquals (Long .valueOf (ldt .toEpochSecond (ZoneOffset .UTC )), rs .getObject ("c_Datetime" , Long .class ));
516+ Assert .assertEquals (ldt .toLocalDate (), rs .getObject ("c_Datetime" , LocalDate .class ));
517+ Assert .assertEquals (ldt , rs .getObject ("c_Datetime" , LocalDateTime .class ));
518+ Assert .assertEquals (ldt .atZone (ZoneId .systemDefault ()).toInstant (), rs .getObject ("c_Datetime" , Instant .class ));
519+ }
520+
566521 @ ParameterizedTest (name = "with {0}" )
567522 @ EnumSource (SqlQueries .JdbcQuery .class )
568523 public void dateTest (SqlQueries .JdbcQuery query ) throws SQLException {
@@ -575,12 +530,12 @@ public void dateTest(SqlQueries.JdbcQuery query) throws SQLException {
575530 ps .execute ();
576531
577532 ps .setInt (1 , 2 );
578- ps .setDate (2 , new Date (INSTANT .toEpochMilli ()));
533+ ps .setDate (2 , new Date (TEST_TS .toEpochMilli ()));
579534 ps .execute ();
580535
581536 if (castingSupported ) {
582537 ps .setInt (1 , 3 );
583- ps .setTimestamp (2 , new Timestamp (INSTANT .toEpochMilli ()));
538+ ps .setTimestamp (2 , new Timestamp (TEST_TS .toEpochMilli ()));
584539 ps .execute ();
585540
586541 ps .setInt (1 , 4 );
@@ -598,20 +553,25 @@ public void dateTest(SqlQueries.JdbcQuery query) throws SQLException {
598553 ps .setInt (1 , 7 );
599554 ps .setString (2 , "2011-12-03" );
600555 ps .execute ();
556+
557+ ps .setInt (1 , 8 );
558+ ps .setObject (2 , TEST_TS );
559+ ps .execute ();
601560 }
602561 }
603562
604563 try (Statement st = jdbc .connection ().createStatement ()) {
605564 try (ResultSet rs = st .executeQuery (TEST_TABLE .selectColumn ("c_Date" ))) {
606565 assertNextDate (rs , 1 , LocalDate .of (2025 , Month .AUGUST , 10 ));
607- assertNextDate (rs , 2 , INSTANT .atZone (ZoneId .systemDefault ()).toLocalDate ());
566+ assertNextDate (rs , 2 , TEST_TS .atZone (ZoneId .systemDefault ()).toLocalDate ());
608567
609568 if (castingSupported ) {
610- assertNextDate (rs , 3 , INSTANT .atZone (ZoneId .systemDefault ()).toLocalDate ());
569+ assertNextDate (rs , 3 , TEST_TS .atZone (ZoneId .systemDefault ()).toLocalDate ());
611570 assertNextDate (rs , 4 , LocalDate .of (1970 , Month .JANUARY , 11 ));
612571 assertNextDate (rs , 5 , LocalDate .of (2003 , Month .OCTOBER , 20 ));
613572 assertNextDate (rs , 6 , LocalDate .of (2023 , Month .MARCH , 3 ));
614573 assertNextDate (rs , 7 , LocalDate .of (2011 , Month .DECEMBER , 3 ));
574+ assertNextDate (rs , 8 , TEST_TS .atZone (ZoneId .systemDefault ()).toLocalDate ());
615575 }
616576
617577 Assert .assertFalse (rs .next ());
0 commit comments