Extractors.java

package org.itsallcode.jdbc.dialect;

import java.sql.*;
import java.util.Calendar;
import java.util.TimeZone;

final class Extractors {

    @SuppressWarnings({ "java:S2143", "java:S2885" }) // Need to use calendar api; using Calendar in a thread-safe way
    private static final Calendar UTC_CALENDAR = Calendar.getInstance(TimeZone.getTimeZone("UTC"));

    private Extractors() {
    }

    static ColumnValueExtractor timestampToUTCInstant() {
        return nonNull((resultSet, columnIndex) -> resultSet.getTimestamp(columnIndex, UTC_CALENDAR).toInstant());
    }

    public static ColumnValueExtractor timestampToInstant() {
        return nonNull((resultSet, columnIndex) -> resultSet.getTimestamp(columnIndex).toInstant());
    }

    static ColumnValueExtractor dateToLocalDate() {
        return nonNull((resultSet, columnIndex) -> resultSet.getDate(columnIndex, UTC_CALENDAR).toLocalDate());
    }

    private static ColumnValueExtractor nonNull(final ColumnValueExtractor extractor) {
        return (resultSet, columnIndex) -> {
            resultSet.getObject(columnIndex);
            if (resultSet.wasNull()) {
                return null;
            }
            return extractor.getObject(resultSet, columnIndex);
        };
    }

    static ColumnValueExtractor clobToString() {
        return nonNull((resultSet, columnIndex) -> {
            final Clob clob = resultSet.getClob(columnIndex);
            return clob.getSubString(1, (int) clob.length());
        });
    }

    static ColumnValueExtractor blobToBytes() {
        return nonNull((resultSet, columnIndex) -> {
            final Blob blob = resultSet.getBlob(columnIndex);
            return blob.getBytes(1, (int) blob.length());
        });
    }

    static ColumnValueExtractor forType(final Class<?> type) {
        return (resultSet, columnIndex) -> resultSet.getObject(columnIndex, type);
    }

    static ColumnValueExtractor generic() {
        return ResultSet::getObject;
    }
}