This is an automated email from the ASF dual-hosted git repository.

ppa pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new f795b0946f7 IGNITE-25783 Jdbc. Improved formatting of datetime types
f795b0946f7 is described below

commit f795b0946f73d20e99a66ad3564c417db39f04b6
Author: Max Zhuravkov <[email protected]>
AuthorDate: Wed Jul 30 17:24:45 2025 +0300

    IGNITE-25783 Jdbc. Improved formatting of datetime types
---
 .../apache/ignite/internal/jdbc/JdbcResultSet.java | 130 ++++++++++--
 .../ignite/internal/jdbc/JdbcResultSetTest.java    | 225 +++++++++++++++++++--
 2 files changed, 322 insertions(+), 33 deletions(-)

diff --git 
a/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc/JdbcResultSet.java 
b/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc/JdbcResultSet.java
index 1cbee6f433b..b22a85859e9 100644
--- 
a/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc/JdbcResultSet.java
+++ 
b/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc/JdbcResultSet.java
@@ -50,6 +50,10 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
 import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.temporal.ChronoField;
+import java.time.temporal.TemporalAccessor;
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.HashMap;
@@ -387,13 +391,29 @@ public class JdbcResultSet implements ResultSet {
     /** {@inheritDoc} */
     @Override
     public String getString(int colIdx) throws SQLException {
-        Object val = getJdbcValue(colIdx);
-        if (val == null) {
+        Object value = getValue(colIdx);
+
+        if (value == null) {
             return null;
-        } else if (val instanceof byte[]) {
-            return StringUtils.toHexString((byte[]) val);
+        } else if (value instanceof Instant) {
+            LocalDateTime localDateTime = instantWithLocalTimeZone((Instant) 
value);
+            assert jdbcMeta != null;
+
+            return Formatters.formatDateTime(localDateTime, colIdx, jdbcMeta);
+        } else if (value instanceof LocalTime) {
+            assert jdbcMeta != null;
+
+            return Formatters.formatTime((LocalTime) value, colIdx, jdbcMeta);
+        } else if (value instanceof LocalDateTime) {
+            assert jdbcMeta != null;
+
+            return Formatters.formatDateTime((LocalDateTime) value, colIdx, 
jdbcMeta);
+        } else if (value instanceof LocalDate) {
+            return Formatters.formatDate((LocalDate) value);
+        } else if (value instanceof byte[]) {
+            return StringUtils.toHexString((byte[]) value);
         } else {
-            return String.valueOf(val);
+            return String.valueOf(value);
         }
     }
 
@@ -2163,21 +2183,6 @@ public class JdbcResultSet implements ResultSet {
         }
     }
 
-    private Object getJdbcValue(int colIdx) throws SQLException {
-        Object value = getValue(colIdx);
-
-        if (value instanceof Instant) {
-            LocalDateTime localDateTime = instantWithLocalTimeZone((Instant) 
value);
-            return Timestamp.valueOf(localDateTime);
-        } else if (value instanceof LocalTime) {
-            return Time.valueOf((LocalTime) value);
-        } else if (value instanceof LocalDateTime) {
-            return Timestamp.valueOf((LocalDateTime) value);
-        } else {
-            return value;
-        }
-    }
-
     private LocalDateTime instantWithLocalTimeZone(Instant val) throws 
SQLException {
         JdbcConnection connection = (JdbcConnection) stmt.getConnection();
         ZoneId zoneId = 
connection.connectionProperties().getConnectionTimeZone();
@@ -2340,4 +2345,89 @@ public class JdbcResultSet implements ResultSet {
             return row;
         };
     }
+
+    private static class Formatters {
+        static final DateTimeFormatter TIME = new DateTimeFormatterBuilder()
+                .appendValue(ChronoField.HOUR_OF_DAY, 2)
+                .appendLiteral(':')
+                .appendValue(ChronoField.MINUTE_OF_HOUR, 2)
+                .appendLiteral(':')
+                .appendValue(ChronoField.SECOND_OF_MINUTE, 2)
+                .toFormatter();
+
+        static final DateTimeFormatter DATE = new DateTimeFormatterBuilder()
+                .appendValue(ChronoField.YEAR, 4)
+                .appendLiteral('-')
+                .appendValue(ChronoField.MONTH_OF_YEAR, 2)
+                .appendLiteral('-')
+                .appendValue(ChronoField.DAY_OF_MONTH, 2)
+                .toFormatter();
+
+        static final DateTimeFormatter DATE_TIME = new 
DateTimeFormatterBuilder()
+                .appendValue(ChronoField.YEAR, 4)
+                .appendLiteral('-')
+                .appendValue(ChronoField.MONTH_OF_YEAR, 2)
+                .appendLiteral('-')
+                .appendValue(ChronoField.DAY_OF_MONTH, 2)
+                .appendLiteral(' ')
+                .appendValue(ChronoField.HOUR_OF_DAY, 2)
+                .appendLiteral(':')
+                .appendValue(ChronoField.MINUTE_OF_HOUR, 2)
+                .appendLiteral(':')
+                .appendValue(ChronoField.SECOND_OF_MINUTE, 2)
+                .toFormatter();
+
+        static String formatTime(LocalTime value, int colIdx, 
JdbcResultSetMetadata jdbcMeta) throws SQLException {
+            return formatWithPrecision(TIME, value, colIdx, jdbcMeta);
+        }
+
+        static String formatDateTime(LocalDateTime value, int colIdx, 
JdbcResultSetMetadata jdbcMeta) throws SQLException {
+            return formatWithPrecision(DATE_TIME, value, colIdx, jdbcMeta);
+        }
+
+        static String formatDate(LocalDate value) {
+            return DATE.format(value);
+        }
+
+        private static String formatWithPrecision(
+                DateTimeFormatter formatter, 
+                TemporalAccessor value, 
+                int colIdx,
+                JdbcResultSetMetadata jdbcMeta
+        ) throws SQLException {
+
+            StringBuilder sb = new StringBuilder();
+
+            formatter.formatTo(value, sb);
+
+            int precision = jdbcMeta.getPrecision(colIdx);
+            if (precision <= 0) {
+                return sb.toString();
+            }
+
+            assert precision <= 9 : "Precision is out of range. Precision: " + 
precision + ". Column: " + colIdx;
+
+            // Append nano seconds according to the specified precision.
+            long nanos = value.getLong(ChronoField.NANO_OF_SECOND);
+            long scaled  = nanos / (long) Math.pow(10, 9 - precision);
+
+            sb.append('.');
+            for (int i = 0; i < precision; i++) {
+                sb.append('0');
+            }
+
+            int pos = precision - 1;
+            int start = sb.length() - precision;
+
+            do {
+                int digit = (int) (scaled % 10);
+                char c = (char) ('0' + digit);
+                sb.setCharAt(start + pos, c);
+                scaled /= 10;
+                pos--;
+            } while (scaled != 0 && pos >= 0);
+
+            return sb.toString();
+        }
+    }
 }
diff --git 
a/modules/jdbc/src/test/java/org/apache/ignite/internal/jdbc/JdbcResultSetTest.java
 
b/modules/jdbc/src/test/java/org/apache/ignite/internal/jdbc/JdbcResultSetTest.java
index b5ce177e063..30b99fa9785 100644
--- 
a/modules/jdbc/src/test/java/org/apache/ignite/internal/jdbc/JdbcResultSetTest.java
+++ 
b/modules/jdbc/src/test/java/org/apache/ignite/internal/jdbc/JdbcResultSetTest.java
@@ -43,16 +43,20 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
 import java.time.ZoneId;
-import java.time.format.DateTimeFormatter;
+import java.time.ZoneOffset;
 import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
 import java.util.EnumMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Random;
 import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
 import java.util.function.Consumer;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
 import org.apache.ignite.internal.binarytuple.BinaryTupleBuilder;
 import org.apache.ignite.internal.binarytuple.BinaryTupleReader;
 import org.apache.ignite.internal.jdbc.proto.JdbcQueryCursorHandler;
@@ -68,7 +72,9 @@ import org.jetbrains.annotations.Nullable;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.CsvSource;
+import org.junit.jupiter.params.provider.MethodSource;
 import org.junit.jupiter.params.provider.ValueSource;
 import org.mockito.ArgumentCaptor;
 import org.mockito.junit.jupiter.MockitoExtension;
@@ -310,15 +316,23 @@ public class JdbcResultSetTest extends 
BaseIgniteAbstractTest {
 
     @ParameterizedTest
     @CsvSource({
-            "Europe/Paris,        2009-02-14 00:31:38.765",
-            "America/Los_Angeles, 2009-02-13 15:31:38.765",
-            "Asia/Tokyo,          2009-02-14 08:31:38.765"
+            "1234567898765, Europe/Paris,        2009-02-14 00:31:38.765, 
2009-02-14, 00:31:38.765",
+            "1234567898765, America/Los_Angeles, 2009-02-13 15:31:38.765, 
2009-02-13, 15:31:38.765",
+            "1234567898765, Asia/Tokyo,          2009-02-14 08:31:38.765, 
2009-02-14, 08:31:38.765",
+
+            "-1234567894, Europe/Paris,          1969-12-17 18:03:52.106, 
1969-12-17, 18:03:52.106",
+            "-1234567894, America/Los_Angeles,   1969-12-17 09:03:52.106, 
1969-12-17, 09:03:52.106",
+            "-1234567894, Asia/Tokyo,            1969-12-18 02:03:52.106, 
1969-12-18, 02:03:52.106",
     })
-    public void getStringDateTimeTypes(String zone, String localDateTime) 
throws SQLException {
+    public void getStringDateTimeTypes(
+            long input,  String zone, 
+            String localDateTimeStr, String dateStr, String timeStr
+    ) throws SQLException {
         ZoneId zoneId = ZoneId.of(zone);
+        int precision = 3;
 
-        Instant now = Instant.ofEpochMilli(1234567898765L);
-        Clock clock = Clock.fixed(now, ZoneId.of(zone));
+        Instant now = Instant.ofEpochMilli(input);
+        Clock clock = Clock.fixed(now, zoneId);
         Instant instant = clock.instant();
         LocalDate date = LocalDate.now(clock);
         LocalDateTime dateTime = LocalDateTime.now(clock);
@@ -326,7 +340,11 @@ public class JdbcResultSetTest extends 
BaseIgniteAbstractTest {
 
         List<ColumnType> columns = List.of(ColumnType.TIME, ColumnType.DATE, 
ColumnType.DATETIME, ColumnType.TIMESTAMP);
 
-        try (ResultSet resultSet = createResultSet(zoneId, columns, (row) -> {
+        Map<Integer, Integer> precisions = IntStream.range(0, columns.size())
+                .mapToObj(i -> Map.entry(i + 1, precision))
+                .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); 
+
+        try (ResultSet resultSet = createResultSet(zoneId, columns, 
precisions, (row) -> {
             row.appendTime(time);
             row.appendDate(date);
             row.appendDateTime(dateTime);
@@ -339,11 +357,170 @@ public class JdbcResultSetTest extends 
BaseIgniteAbstractTest {
                     + " | " + resultSet.getString(3)
                     + " | " + resultSet.getString(4);
 
-            String expected = 
time.format(DateTimeFormatter.ofPattern("HH:mm:ss"))
-                    + " | " + 
date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
-                    + " | " + 
dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"))
-                    + " | " + localDateTime;
+            String expected = timeStr
+                    + " | " + dateStr
+                    + " | " + localDateTimeStr
+                    + " | " + localDateTimeStr;
+
+            assertEquals(expected, actual);
+        }
+    }
 
+    private static Stream<Arguments> getStringDateValues() {
+        return Stream.of(
+                Arguments.of(LocalDate.of(2100, 1, 4), "2100-01-04"),
+                Arguments.of(LocalDate.of(2000, 1, 4), "2000-01-04"),
+                Arguments.of(LocalDate.of(1000, 1, 4), "1000-01-04"),
+                Arguments.of(LocalDate.of(200, 1, 4), "0200-01-04")
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("getStringDateValues")
+    public void getStringDate(LocalDate date, String expected) throws 
SQLException {
+        List<ColumnType> columns = List.of(ColumnType.DATE);
+
+        try (ResultSet resultSet = createResultSet(null, columns, (row) -> {
+            row.appendDate(date);
+        })) {
+            resultSet.next();
+            String actual = resultSet.getString(1);
+            assertEquals(expected, actual);
+        }
+    }
+
+    private static Stream<Arguments> getStringTimeValues() {
+        return Stream.of(
+                Arguments.of(LocalTime.of(0, 0, 0, 0), 0, "00:00:00"),
+                Arguments.of(LocalTime.of(0, 0, 0, 0), 1, "00:00:00.0"),
+                Arguments.of(LocalTime.of(0, 0, 0, 0), 2, "00:00:00.00"),
+                Arguments.of(LocalTime.of(0, 0, 0, 0), 3, "00:00:00.000"),
+                Arguments.of(LocalTime.of(0, 0, 0, 0), 6, "00:00:00.000000"),
+                Arguments.of(LocalTime.of(0, 0, 0, 0), 9, 
"00:00:00.000000000"),
+
+                Arguments.of(LocalTime.of(13, 5, 2, 123_456), 0, "13:05:02"),
+                Arguments.of(LocalTime.of(13, 5, 2, 123_456), 1, "13:05:02.0"),
+                Arguments.of(LocalTime.of(13, 5, 2, 123_456), 2, 
"13:05:02.00"),
+                Arguments.of(LocalTime.of(13, 5, 2, 123_456), 3, 
"13:05:02.000"),
+                Arguments.of(LocalTime.of(13, 5, 2, 123_456), 5, 
"13:05:02.00012"),
+                Arguments.of(LocalTime.of(13, 5, 2, 123_456), 6, 
"13:05:02.000123"),
+                Arguments.of(LocalTime.of(13, 5, 2, 123_456), 9, 
"13:05:02.000123456"),
+
+                Arguments.of(LocalTime.of(13, 5, 2, 12345600), 0, "13:05:02"),
+                Arguments.of(LocalTime.of(13, 5, 2, 12345600), 1, 
"13:05:02.0"),
+                Arguments.of(LocalTime.of(13, 5, 2, 12345600), 2, 
"13:05:02.01"),
+                Arguments.of(LocalTime.of(13, 5, 2, 12345600), 3, 
"13:05:02.012"),
+                Arguments.of(LocalTime.of(13, 5, 2, 12345600), 5, 
"13:05:02.01234"),
+                Arguments.of(LocalTime.of(13, 5, 2, 12345600), 6, 
"13:05:02.012345"),
+                Arguments.of(LocalTime.of(13, 5, 2, 12345600), 9, 
"13:05:02.012345600"),
+
+                Arguments.of(LocalTime.of(13, 5, 2, 123_000_000), 0, 
"13:05:02"),
+                Arguments.of(LocalTime.of(13, 5, 2, 123_000_000), 1, 
"13:05:02.1"),
+                Arguments.of(LocalTime.of(13, 5, 2, 123_000_000), 2, 
"13:05:02.12"),
+                Arguments.of(LocalTime.of(13, 5, 2, 123_000_000), 3, 
"13:05:02.123"),
+                Arguments.of(LocalTime.of(13, 5, 2, 123_000_000), 6, 
"13:05:02.123000"),
+                Arguments.of(LocalTime.of(13, 5, 2, 123_000_000), 9, 
"13:05:02.123000000"),
+
+                Arguments.of(LocalTime.of(13, 5, 2, 123456789), 0, "13:05:02"),
+                Arguments.of(LocalTime.of(13, 5, 2, 123456789), 1, 
"13:05:02.1"),
+                Arguments.of(LocalTime.of(13, 5, 2, 123456789), 2, 
"13:05:02.12"),
+                Arguments.of(LocalTime.of(13, 5, 2, 123456789), 3, 
"13:05:02.123"),
+                Arguments.of(LocalTime.of(13, 5, 2, 123456789), 6, 
"13:05:02.123456"),
+                Arguments.of(LocalTime.of(13, 5, 2, 123456789), 9, 
"13:05:02.123456789")
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("getStringTimeValues")
+    public void getStringTimeWithPrecision(LocalTime time, int precision, 
String expected) throws SQLException {
+        List<ColumnType> columns = List.of(ColumnType.TIME);
+        Map<Integer, Integer> precisions = Map.of(1, precision);
+
+        try (ResultSet resultSet = createResultSet(null, columns, precisions, 
(row) -> {
+            row.appendTime(time);
+        })) {
+            resultSet.next();
+            String actual = resultSet.getString(1);
+            assertEquals(expected, actual);
+        }
+    }
+
+    private static Stream<Arguments> getStringDateTimeValues() {
+        LocalTime time = LocalTime.of(13, 5, 2, 12345600);
+
+        LocalDate date2 = LocalDate.of(2, 5, 17);
+        LocalDate date20 = LocalDate.of(20, 5, 17);
+        LocalDate date200 = LocalDate.of(200, 5, 17);
+        LocalDate date2000 = LocalDate.of(2000, 5, 17);
+
+        return Stream.of(
+                // 2
+                Arguments.of(LocalDateTime.of(date2, time), 0, "0002-05-17 
13:05:02"),
+                Arguments.of(LocalDateTime.of(date2, time), 1, "0002-05-17 
13:05:02.0"),
+                Arguments.of(LocalDateTime.of(date2, time), 2, "0002-05-17 
13:05:02.01"),
+                Arguments.of(LocalDateTime.of(date2, time), 3, "0002-05-17 
13:05:02.012"),
+                Arguments.of(LocalDateTime.of(date2, time), 5, "0002-05-17 
13:05:02.01234"),
+                Arguments.of(LocalDateTime.of(date2, time), 6, "0002-05-17 
13:05:02.012345"),
+                Arguments.of(LocalDateTime.of(date2, time), 9, "0002-05-17 
13:05:02.012345600"),
+
+                // 20
+                Arguments.of(LocalDateTime.of(date20, time), 0, "0020-05-17 
13:05:02"),
+                Arguments.of(LocalDateTime.of(date20, time), 1, "0020-05-17 
13:05:02.0"),
+                Arguments.of(LocalDateTime.of(date20, time), 2, "0020-05-17 
13:05:02.01"),
+                Arguments.of(LocalDateTime.of(date20, time), 3, "0020-05-17 
13:05:02.012"),
+                Arguments.of(LocalDateTime.of(date20, time), 5, "0020-05-17 
13:05:02.01234"),
+                Arguments.of(LocalDateTime.of(date20, time), 6, "0020-05-17 
13:05:02.012345"),
+                Arguments.of(LocalDateTime.of(date20, time), 9, "0020-05-17 
13:05:02.012345600"),
+
+                // 200
+                Arguments.of(LocalDateTime.of(date200, time), 0, "0200-05-17 
13:05:02"),
+                Arguments.of(LocalDateTime.of(date200, time), 1, "0200-05-17 
13:05:02.0"),
+                Arguments.of(LocalDateTime.of(date200, time), 2, "0200-05-17 
13:05:02.01"),
+                Arguments.of(LocalDateTime.of(date200, time), 3, "0200-05-17 
13:05:02.012"),
+                Arguments.of(LocalDateTime.of(date200, time), 5, "0200-05-17 
13:05:02.01234"),
+                Arguments.of(LocalDateTime.of(date200, time), 6, "0200-05-17 
13:05:02.012345"),
+                Arguments.of(LocalDateTime.of(date200, time), 9, "0200-05-17 
13:05:02.012345600"),
+
+                // 2000
+                Arguments.of(LocalDateTime.of(date2000, time), 0, "2000-05-17 
13:05:02"),
+                Arguments.of(LocalDateTime.of(date2000, time), 1, "2000-05-17 
13:05:02.0"),
+                Arguments.of(LocalDateTime.of(date2000, time), 2, "2000-05-17 
13:05:02.01"),
+                Arguments.of(LocalDateTime.of(date2000, time), 3, "2000-05-17 
13:05:02.012"),
+                Arguments.of(LocalDateTime.of(date2000, time), 5, "2000-05-17 
13:05:02.01234"),
+                Arguments.of(LocalDateTime.of(date2000, time), 6, "2000-05-17 
13:05:02.012345"),
+                Arguments.of(LocalDateTime.of(date2000, time), 9, "2000-05-17 
13:05:02.012345600")
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("getStringDateTimeValues")
+    public void getStringDateTimeWithPrecision(LocalDateTime value, int 
precision, String expected) throws SQLException {
+        List<ColumnType> columns = List.of(ColumnType.DATETIME);
+        Map<Integer, Integer> precisions = Map.of(1, precision);
+
+        try (ResultSet resultSet = createResultSet(null, columns, precisions, 
(row) -> {
+            row.appendDateTime(value);
+        })) {
+            resultSet.next();
+            String actual = resultSet.getString(1);
+            assertEquals(expected, actual);
+        }
+    }
+
+    @ParameterizedTest
+    @MethodSource("getStringDateTimeValues")
+    public void getStringTimestampWithPrecision(LocalDateTime value, int 
precision, String expected) throws SQLException {
+        ZoneOffset zoneOffset = ZoneOffset.ofHoursMinutes(3, 30);
+
+        List<ColumnType> columns = List.of(ColumnType.TIMESTAMP);
+        Map<Integer, Integer> precisions = Map.of(1, precision);
+
+        try (ResultSet resultSet = createResultSet(zoneOffset, columns, 
precisions, (row) -> {
+            Instant instant = value.toInstant(zoneOffset);
+            row.appendTimestamp(instant);
+        })) {
+            resultSet.next();
+            String actual = resultSet.getString(1);
             assertEquals(expected, actual);
         }
     }
@@ -534,6 +711,15 @@ public class JdbcResultSetTest extends 
BaseIgniteAbstractTest {
             @Nullable ZoneId zoneId,
             List<ColumnType> columnTypes,
             Consumer<BinaryTupleBuilder> row
+    ) throws SQLException {
+        return createResultSet(zoneId, columnTypes, Map.of(), row);
+    }
+
+    private static JdbcResultSet createResultSet(
+            @Nullable ZoneId zoneId,
+            List<ColumnType> columnTypes,
+            Map<Integer, Integer> precisions,
+            Consumer<BinaryTupleBuilder> row
     ) throws SQLException {
         JdbcQueryCursorHandler handler = mock(JdbcQueryCursorHandler.class);
         JdbcStatement stmt = mock(JdbcStatement.class);
@@ -551,7 +737,20 @@ public class JdbcResultSetTest extends 
BaseIgniteAbstractTest {
 
         List<JdbcColumnMeta> columns = new ArrayList<>();
         for (ColumnType columnType : columnTypes) {
-            columns.add(new JdbcColumnMeta("C" + columns.size(), columnType));
+            String columnName = "C" + columns.size();
+            int precision = precisions.getOrDefault(columns.size() + 1, -1);
+
+            JdbcColumnMeta columnMeta = new JdbcColumnMeta(
+                    columnName, 
+                    "Schema", 
+                    "Table",
+                    columnName,
+                    columnType,
+                    precision, 
+                    -1,
+                    true
+            );
+            columns.add(columnMeta);
         }
 
         BinaryTupleBuilder builder = new 
BinaryTupleBuilder(columnTypes.size());

Reply via email to