text:
package io.debezium.jdbc;

import static io.debezium.util.NumberConversions.BYTE_ZERO;
import static io.debezium.util.NumberConversions.SHORT_FALSE;

import java.math.BigDecimal;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.sql.SQLException;
import java.sql.SQLXML;
import java.sql.Types;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.ZoneOffset;
import java.time.temporal.TemporalAdjuster;
import java.util.BitSet;
import java.util.concurrent.TimeUnit;

import org.apache.kafka.connect.data.Decimal;
import org.apache.kafka.connect.data.Field;
import org.apache.kafka.connect.data.SchemaBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.debezium.annotation.Immutable;
import io.debezium.data.Bits;
import io.debezium.data.Xml;
import io.debezium.relational.Column;
import io.debezium.relational.ValueConverter;
import io.debezium.relational.ValueConverterProvider;
import io.debezium.time.Date;
import io.debezium.time.MicroTime;
import io.debezium.time.MicroTimestamp;
import io.debezium.time.NanoTime;
import io.debezium.time.NanoTimestamp;
import io.debezium.time.Time;
import io.debezium.time.Timestamp;
import io.debezium.time.ZonedTime;
import io.debezium.time.ZonedTimestamp;
import io.debezium.util.NumberConversions;

/**
 * A provider of {@link ValueConverter}s and {@link SchemaBuilder}s for various column types. This implementation is aware
 * of the most common JDBC types and values. Specializations for specific DBMSes can be addressed in subclasses.
 *

 * Although it is more likely that values will correspond pretty closely to the expected JDBC types, this class assumes it is
 * possible for some variation to occur when values originate in libraries that are not JDBC drivers. Specifically, the conversion
 * logic for JDBC temporal types with timezones (e.g., {@link Types#TIMESTAMP_WITH_TIMEZONE}) do support converting values that
 * don't have timezones (e.g., {@link java.sql.Timestamp}) by assuming a default time zone offset for values that don't have
 * (but are expected to have) timezones. Again, when the values are highly-correlated with the expected SQL/JDBC types, this
 * default timezone offset will not be needed.
 *
 * @author Randall Hauch
 */
@Immutable
public class JdbcValueConverters implements ValueConverterProvider {

    public enum DecimalMode {
        PRECISE, DOUBLE;
    }

    public enum BigIntUnsignedMode {
        PRECISE, LONG;
    }

    protected final Logger logger = LoggerFactory.getLogger(getClass());
    private final ZoneOffset defaultOffset;
    protected final boolean adaptiveTimePrecisionMode;
    protected final boolean adaptiveTimeMicrosecondsPrecisionMode;
    protected final DecimalMode decimalMode;
    private final TemporalAdjuster adjuster;
    protected final BigIntUnsignedMode bigIntUnsignedMode;

    /**
     * Create a new instance that always uses UTC for the default time zone when converting values without timezone information
     * to values that require timezones, and uses adapts time and timestamp values based upon the precision of the database
     * columns.
     */
    public JdbcValueConverters() {
        this(null, TemporalPrecisionMode.ADAPTIVE, ZoneOffset.UTC, null, null);
    }

    /**
     * Create a new instance, and specify the time zone offset that should be used only when converting values without timezone
     * information to values that require timezones. This default offset should not be needed when values are highly-correlated
     * with the expected SQL/JDBC types.
     *
     * @param decimalMode how {@code DECIMAL} and {@code NUMERIC} values should be treated; may be null if
     *            {@link DecimalMode#PRECISE} is to be used
     * @param temporalPrecisionMode temporal precision mode based on {@link io.debezium.jdbc.TemporalPrecisionMode}
     * @param defaultOffset the zone offset that is to be used when converting non-timezone related values to values that do
     *            have timezones; may be null if UTC is to be used
     * @param adjuster the optional component that adjusts the local date value before obtaining the epoch day; may be null if no
     *            adjustment is necessary
     * @param bigIntUnsignedMode how {@code BIGINT UNSIGNED} values should be treated; may be null if
     *            {@link BigIntUnsignedMode#PRECISE} is to be used
     */
    public JdbcValueConverters(DecimalMode decimalMode, TemporalPrecisionMode temporalPrecisionMode, ZoneOffset defaultOffset,
                               TemporalAdjuster adjuster, BigIntUnsignedMode bigIntUnsignedMode) {
        this.defaultOffset = defaultOffset != null ? defaultOffset : ZoneOffset.UTC;
        this.adaptiveTimePrecisionMode = temporalPrecisionMode.equals(TemporalPrecisionMode.ADAPTIVE);
        this.adaptiveTimeMicrosecondsPrecisionMode = temporalPrecisionMode.equals(TemporalPrecisionMode.ADAPTIVE_TIME_MICROSECONDS);
        this.decimalMode = decimalMode != null ? decimalMode : DecimalMode.PRECISE;
        this.adjuster = adjuster;
        this.bigIntUnsignedMode = bigIntUnsignedMode != null ? bigIntUnsignedMode : BigIntUnsignedMode.PRECISE;
    }

    @Override
    public SchemaBuilder schemaBuilder(Column column) {
        switch (column.jdbcType()) {
            case Types.NULL:
                logger.warn("Unexpected JDBC type: NULL");
                return null;

            // Single- and multi-bit values ...
            case Types.BIT:
                if (column.length() > 1) {
                    return Bits.builder(column.length());
                }
                // otherwise, it is just one bit so use a boolean ...
            case Types.BOOLEAN:
                return SchemaBuilder.bool();

            // Fixed-length binary values ...
            case Types.BLOB:
            case Types.BINARY:
                return SchemaBuilder.bytes();

            // Variable-length binary values ...
            case Types.VARBINARY:
            case Types.LONGVARBINARY:
                return SchemaBuilder.bytes();

            // Numeric integers
            case Types.TINYINT:
                // values are an 8-bit unsigned integer value between 0 and 255
                return SchemaBuilder.int8();
            case Types.SMALLINT:
                // values are a 16-bit signed integer value between -32768 and 32767
                return SchemaBuilder.int16();
            case Types.INTEGER:
                // values are a 32-bit signed integer value between - 2147483648 and 2147483647
                return SchemaBuilder.int32();
            case Types.BIGINT:
                // values are a 64-bit signed integer value between -9223372036854775808 and 9223372036854775807
                return SchemaBuilder.int64();

            // Numeric decimal numbers
            case Types.REAL:
                // values are single precision floating point number which supports 7 digits of mantissa.
                return SchemaBuilder.float32();
            case Types.FLOAT:
            case Types.DOUBLE:
                // values are double precision floating point number which supports 15 digits of mantissa.
                return SchemaBuilder.float64();
            case Types.NUMERIC:
            case Types.DECIMAL:
                switch (decimalMode) {
                    case DOUBLE:
                        return SchemaBuilder.float64();
                    case PRECISE:
                        // values are fixed-precision decimal values with exact precision.
                        // Use Kafka Connect's arbitrary precision decimal type and use the column's specified scale ...
                        return Decimal.builder(column.scale());
                }

                // Fixed-length string values
            case Types.CHAR:
            case Types.NCHAR:
            case Types.NVARCHAR:
            case Types.LONGNVARCHAR:
            case Types.NCLOB:
                return SchemaBuilder.string();

            // Variable-length string values
            case Types.VARCHAR:
            case Types.LONGVARCHAR:
            case Types.CLOB:
            case Types.DATALINK:
                return SchemaBuilder.string();
            case Types.SQLXML:
                return Xml.builder();
            // Date and time values
            case Types.DATE:
                if (adaptiveTimePrecisionMode || adaptiveTimeMicrosecondsPrecisionMode) {
                    return Date.builder();
                }
                return org.apache.kafka.connect.data.Date.builder();
            case Types.TIME:
                if(adaptiveTimeMicrosecondsPrecisionMode) {
                    return MicroTime.builder();
                }
                if (adaptiveTimePrecisionMode) {
                    if (column.length() <= 3) return Time.builder();
                    if (column.length() <= 6) return MicroTime.builder();
                    return NanoTime.builder();
                }
                return org.apache.kafka.connect.data.Time.builder();
            case Types.TIMESTAMP:
                if (adaptiveTimePrecisionMode || adaptiveTimeMicrosecondsPrecisionMode) {
                    if (column.length() <= 3) return Timestamp.builder();
                    if (column.length() <= 6) return MicroTimestamp.builder();
                    return NanoTimestamp.builder();
                }
                return org.apache.kafka.connect.data.Timestamp.builder();
            case Types.TIME_WITH_TIMEZONE:
                return ZonedTime.builder();
            case Types.TIMESTAMP_WITH_TIMEZONE:
                return ZonedTimestamp.builder();

            // Other types ...
            case Types.ROWID:
                // often treated as a string, but we'll generalize and treat it as a byte array
                return SchemaBuilder.bytes();

            // Unhandled types
            case Types.ARRAY:
            case Types.DISTINCT:
            case Types.JAVA_OBJECT:
            case Types.OTHER:
            case Types.REF:
            case Types.REF_CURSOR:
            case Types.STRUCT:
            default:
                break;
        }
        return null;

    }

    @Override
    public ValueConverter converter(Column column, Field fieldDefn) {
        switch (column.jdbcType()) {
            case Types.NULL:
                return (data) -> null;
            case Types.BIT:
                return convertBits(column, fieldDefn);
            case Types.BOOLEAN:
                return (data) -> convertBoolean(column, fieldDefn, data);

            // Binary values ...
            case Types.BLOB:
            case Types.BINARY:
            case Types.VARBINARY:
            case Types.LONGVARBINARY:
                return (data) -> convertBinary(column, fieldDefn, data);

            // Numeric integers
            case Types.TINYINT:
                return (data) -> convertTinyInt(column, fieldDefn, data);
            case Types.SMALLINT:
                return (data) -> convertSmallInt(column, fieldDefn, data);
            case Types.INTEGER:
                return (data) -> convertInteger(column, fieldDefn, data);
            case Types.BIGINT:
                return (data) -> convertBigInt(column, fieldDefn, data);

            // Numeric decimal numbers
            case Types.FLOAT:
                return (data) -> convertFloat(column, fieldDefn, data);
            case Types.DOUBLE:
                return (data) -> convertDouble(column, fieldDefn, data);
            case Types.REAL:
                return (data) -> convertReal(column, fieldDefn, data);
            case Types.NUMERIC:
                switch (decimalMode) {
                    case DOUBLE:
                        return (data) -> convertDouble(column, fieldDefn, data);
                    case PRECISE:
                        return (data) -> convertNumeric(column, fieldDefn, data);
                }
            case Types.DECIMAL:
                switch (decimalMode) {
                    case DOUBLE:
                        return (data) -> convertDouble(column, fieldDefn, data);
                    case PRECISE:
                        return (data) -> convertDecimal(column, fieldDefn, data);
                }

                // String values
            case Types.CHAR: // variable-length
            case Types.VARCHAR: // variable-length
            case Types.LONGVARCHAR: // variable-length
            case Types.CLOB: // variable-length
            case Types.NCHAR: // fixed-length
            case Types.NVARCHAR: // fixed-length
            case Types.LONGNVARCHAR: // fixed-length
            case Types.NCLOB: // fixed-length
            case Types.DATALINK:
            case Types.SQLXML:
                return (data) -> convertString(column, fieldDefn, data);

            // Date and time values
            case Types.DATE:
                if (adaptiveTimePrecisionMode || adaptiveTimeMicrosecondsPrecisionMode) {
                    return (data) -> convertDateToEpochDays(column, fieldDefn, data);
                }
                return (data) -> convertDateToEpochDaysAsDate(column, fieldDefn, data);
            case Types.TIME:
                if(adaptiveTimeMicrosecondsPrecisionMode) {
                    return data -> convertTimeToMicrosPastMidnight(column, fieldDefn, data);
                }
                if (adaptiveTimePrecisionMode) {
                    if (column.length() <= 3) return data -> convertTimeToMillisPastMidnight(column, fieldDefn, data);
                    if (column.length() <= 6) return data -> convertTimeToMicrosPastMidnight(column, fieldDefn, data);
                    return (data) -> convertTimeToNanosPastMidnight(column, fieldDefn, data);
                }
                return (data) -> convertTimeToMillisPastMidnightAsDate(column, fieldDefn, data);
            case Types.TIMESTAMP:
                if (adaptiveTimePrecisionMode || adaptiveTimeMicrosecondsPrecisionMode) {
                    if (column.length() <= 3) return data -> convertTimestampToEpochMillis(column, fieldDefn, data);
                    if (column.length() <= 6) return data -> convertTimestampToEpochMicros(column, fieldDefn, data);
                    return (data) -> convertTimestampToEpochNanos(column, fieldDefn, data);
                }
                return (data) -> convertTimestampToEpochMillisAsDate(column, fieldDefn, data);
            case Types.TIME_WITH_TIMEZONE:
                return (data) -> convertTimeWithZone(column, fieldDefn, data);
            case Types.TIMESTAMP_WITH_TIMEZONE:
                return (data) -> convertTimestampWithZone(column, fieldDefn, data);

            // Other types ...
            case Types.ROWID:
                return (data) -> convertRowId(column, fieldDefn, data);

            // Unhandled types
            case Types.ARRAY:
            case Types.DISTINCT:
            case Types.JAVA_OBJECT:
            case Types.OTHER:
            case Types.REF:
            case Types.REF_CURSOR:
            case Types.STRUCT:
            default:
                return null;
        }
    }

    protected ValueConverter convertBits(Column column, Field fieldDefn) {
        if (column.length() > 1) {
            int numBits = column.length();
            int numBytes = numBits / Byte.SIZE + (numBits % Byte.SIZE == 0 ? 0 : 1);
            return (data) -> convertBits(column, fieldDefn, data, numBytes);
        }
        return (data) -> convertBit(column, fieldDefn, data);
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#TIMESTAMP_WITH_TIMEZONE}.
     * The standard ANSI to Java 8 type
     * mappings specify that the preferred mapping (when using JDBC's {@link java.sql.ResultSet#getObject(int) getObject(...)}
     * methods) in Java 8 is to return {@link OffsetDateTime} for these values.
     *

     * This method handles several types of objects, including {@link OffsetDateTime}, {@link java.sql.Timestamp},
     * {@link java.util.Date}, {@link java.time.LocalTime}, and {@link java.time.LocalDateTime}.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertTimestampWithZone(Column column, Field fieldDefn, Object data) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) return null;
            data = OffsetDateTime.of(LocalDate.ofEpochDay(0), LocalTime.MIDNIGHT, defaultOffset); // return epoch
        }
        try {
            return ZonedTimestamp.toIsoString(data, defaultOffset, adjuster);
        } catch (IllegalArgumentException e) {
            return handleUnknownData(column, fieldDefn, data);
        }
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#TIME_WITH_TIMEZONE}.
     * The standard ANSI to Java 8 type
     * mappings specify that the preferred mapping (when using JDBC's {@link java.sql.ResultSet#getObject(int) getObject(...)}
     * methods) in Java 8 is to return {@link OffsetTime} for these values.
     *

     * This method handles several types of objects, including {@link OffsetTime}, {@link java.sql.Time}, {@link java.util.Date},
     * {@link java.time.LocalTime}, and {@link java.time.LocalDateTime}. If any of the types have date components, those date
     * components are ignored.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertTimeWithZone(Column column, Field fieldDefn, Object data) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) return null;
            data = OffsetTime.of(LocalTime.MIDNIGHT, defaultOffset); // return epoch time
        }
        try {
            return ZonedTime.toIsoString(data, defaultOffset, adjuster);
        } catch (IllegalArgumentException e) {
            return handleUnknownData(column, fieldDefn, data);
        }
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#TIMESTAMP} to {@link Timestamp} values, or milliseconds
     * past epoch.
     *

     * Per the JDBC specification, databases should return {@link java.sql.Timestamp} instances, which have date and time info
     * but no time zone info. This method handles {@link java.sql.Date} objects plus any other standard date-related objects such
     * as {@link java.util.Date}, {@link java.time.LocalTime}, and {@link java.time.LocalDateTime}.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertTimestampToEpochMillis(Column column, Field fieldDefn, Object data) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) return null;
            return 0L; // return epoch
        }
        try {
            return Timestamp.toEpochMillis(data, adjuster);
        } catch (IllegalArgumentException e) {
            return handleUnknownData(column, fieldDefn, data);
        }
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#TIMESTAMP} to {@link MicroTimestamp} values, or
     * microseconds past epoch.
     *

     * Per the JDBC specification, databases should return {@link java.sql.Timestamp} instances, which have date and time info
     * but no time zone info. This method handles {@link java.sql.Date} objects plus any other standard date-related objects such
     * as {@link java.util.Date}, {@link java.time.LocalTime}, and {@link java.time.LocalDateTime}.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertTimestampToEpochMicros(Column column, Field fieldDefn, Object data) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) return null;
            return 0L; // return epoch
        }
        try {
            return MicroTimestamp.toEpochMicros(data, adjuster);
        } catch (IllegalArgumentException e) {
            return handleUnknownData(column, fieldDefn, data);
        }
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#TIMESTAMP} to {@link NanoTimestamp} values, or
     * nanoseconds past epoch.
     *

     * Per the JDBC specification, databases should return {@link java.sql.Timestamp} instances, which have date and time info
     * but no time zone info. This method handles {@link java.sql.Date} objects plus any other standard date-related objects such
     * as {@link java.util.Date}, {@link java.time.LocalTime}, and {@link java.time.LocalDateTime}.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertTimestampToEpochNanos(Column column, Field fieldDefn, Object data) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) return null;
            return 0L; // return epoch
        }
        try {
            return NanoTimestamp.toEpochNanos(data, adjuster);
        } catch (IllegalArgumentException e) {
            return handleUnknownData(column, fieldDefn, data);
        }
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#TIMESTAMP} to {@link java.util.Date} values representing
     * milliseconds past epoch.
     *

     * Per the JDBC specification, databases should return {@link java.sql.Timestamp} instances, which have date and time info
     * but no time zone info. This method handles {@link java.sql.Date} objects plus any other standard date-related objects such
     * as {@link java.util.Date}, {@link java.time.LocalTime}, and {@link java.time.LocalDateTime}.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertTimestampToEpochMillisAsDate(Column column, Field fieldDefn, Object data) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) return null;
            return new java.util.Date(0L); // return epoch
        }
        try {
            return new java.util.Date(Timestamp.toEpochMillis(data, adjuster));
        } catch (IllegalArgumentException e) {
            return handleUnknownData(column, fieldDefn, data);
        }
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#TIME} to {@link Time} values, or milliseconds past
     * midnight.
     *

     * Per the JDBC specification, databases should return {@link java.sql.Time} instances that have no notion of date or
     * time zones. This method handles {@link java.sql.Date} objects plus any other standard date-related objects such as
     * {@link java.util.Date}, {@link java.time.LocalTime}, and {@link java.time.LocalDateTime}. If any of the types might
     * have date components, those date components are ignored.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertTimeToMillisPastMidnight(Column column, Field fieldDefn, Object data) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) return null;
            return 0; // return epoch
        }
        try {
            return Time.toMilliOfDay(data, adjuster);
        } catch (IllegalArgumentException e) {
            return handleUnknownData(column, fieldDefn, data);
        }
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#TIME} to {@link MicroTime} values, or microseconds past
     * midnight.
     *

     * Per the JDBC specification, databases should return {@link java.sql.Time} instances that have no notion of date or
     * time zones. This method handles {@link java.sql.Date} objects plus any other standard date-related objects such as
     * {@link java.util.Date}, {@link java.time.LocalTime}, and {@link java.time.LocalDateTime}. If any of the types might
     * have date components, those date components are ignored.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertTimeToMicrosPastMidnight(Column column, Field fieldDefn, Object data) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) return null;
            return 0L; // return epoch
        }
        try {
            return MicroTime.toMicroOfDay(data, adjuster);
        } catch (IllegalArgumentException e) {
            return handleUnknownData(column, fieldDefn, data);
        }
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#TIME} to {@link NanoTime} values, or nanoseconds past
     * midnight.
     *

     * Per the JDBC specification, databases should return {@link java.sql.Time} instances that have no notion of date or
     * time zones. This method handles {@link java.sql.Date} objects plus any other standard date-related objects such as
     * {@link java.util.Date}, {@link java.time.LocalTime}, and {@link java.time.LocalDateTime}. If any of the types might
     * have date components, those date components are ignored.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertTimeToNanosPastMidnight(Column column, Field fieldDefn, Object data) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) return null;
            return 0L; // return epoch
        }
        try {
            return NanoTime.toNanoOfDay(data, adjuster);
        } catch (IllegalArgumentException e) {
            return handleUnknownData(column, fieldDefn, data);
        }
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#TIME} to {@link java.util.Date} values representing
     * the milliseconds past midnight on the epoch day.
     *

     * Per the JDBC specification, databases should return {@link java.sql.Time} instances that have no notion of date or
     * time zones. This method handles {@link java.sql.Date} objects plus any other standard date-related objects such as
     * {@link java.util.Date}, {@link java.time.LocalTime}, and {@link java.time.LocalDateTime}. If any of the types might
     * have date components, those date components are ignored.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertTimeToMillisPastMidnightAsDate(Column column, Field fieldDefn, Object data) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) return null;
            return 0L; // return epoch
        }
        try {
            return new java.util.Date(Time.toMilliOfDay(data, adjuster));
        } catch (IllegalArgumentException e) {
            return handleUnknownData(column, fieldDefn, data);
        }
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#DATE} to the number of days past epoch.
     *

     * Per the JDBC specification, databases should return {@link java.sql.Date} instances that have no notion of time or
     * time zones. This method handles {@link java.sql.Date} objects plus any other standard date-related objects such as
     * {@link java.util.Date}, {@link java.time.LocalDate}, and {@link java.time.LocalDateTime}. If any of the types might
     * have time components, those time components are ignored.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertDateToEpochDays(Column column, Field fieldDefn, Object data) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) return null;
            return 0; // return epoch
        }
        try {
            return Date.toEpochDay(data, adjuster);
        } catch (IllegalArgumentException e) {
            logger.warn("Unexpected JDBC DATE value for field {} with schema {}: class={}, value={}", fieldDefn.name(),
                        fieldDefn.schema(), data.getClass(), data);
            return handleUnknownData(column, fieldDefn, data);
        }
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#DATE} to the number of days past epoch, but represented
     * as a {@link java.util.Date} value at midnight on the date.
     *

     * Per the JDBC specification, databases should return {@link java.sql.Date} instances that have no notion of time or
     * time zones. This method handles {@link java.sql.Date} objects plus any other standard date-related objects such as
     * {@link java.util.Date}, {@link java.time.LocalDate}, and {@link java.time.LocalDateTime}. If any of the types might
     * have time components, those time components are ignored.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertDateToEpochDaysAsDate(Column column, Field fieldDefn, Object data) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) return null;
            return new java.util.Date(0L); // return epoch
        }
        try {
            int epochDay = Date.toEpochDay(data, adjuster);
            long epochMillis = TimeUnit.DAYS.toMillis(epochDay);
            return new java.util.Date(epochMillis);
        } catch (IllegalArgumentException e) {
            logger.warn("Unexpected JDBC DATE value for field {} with schema {}: class={}, value={}", fieldDefn.name(),
                        fieldDefn.schema(), data.getClass(), data);
            return null;
        }
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#BLOB}, {@link Types#BINARY},
     * {@link Types#VARBINARY}, {@link Types#LONGVARBINARY}.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertBinary(Column column, Field fieldDefn, Object data) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) return null;
            data = BYTE_ZERO;
        }
        if (data instanceof char[]) {
            data = new String((char[]) data); // convert to string
        }
        if (data instanceof String) {
            // This was encoded as a hexadecimal string, but we receive it as a normal string ...
            data = ((String) data).getBytes();
        }
        if (data instanceof byte[]) {
            return convertByteArray(column, (byte[]) data);
        }

        // An unexpected value
        return unexpectedBinary(data, fieldDefn);
    }

    /**
     * Converts the given byte array value into a byte buffer as preferred by Kafka Connect. Specific connectors
     * can perform value adjustments based on the column definition, e.g. right-pad with 0x00 bytes in case of
     * fixed length BINARY in MySQL.
     */
    protected ByteBuffer convertByteArray(Column column, byte[] data) {
        // Kafka Connect would support raw byte arrays, too, but byte buffers are recommended
        return ByteBuffer.wrap(data);
    }

    /**
     * Handle the unexpected value from a row with a column type of {@link Types#BLOB}, {@link Types#BINARY},
     * {@link Types#VARBINARY}, {@link Types#LONGVARBINARY}.
     *
     * @param value the binary value for which no conversion was found; never null
     * @param fieldDefn the field definition in the Kafka Connect schema; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     * @see #convertBinary(Column, Field, Object)
     */
    protected byte[] unexpectedBinary(Object value, Field fieldDefn) {
        logger.warn("Unexpected JDBC BINARY value for field {} with schema {}: class={}, value={}", fieldDefn.name(),
                    fieldDefn.schema(), value.getClass(), value);
        return null;
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#TINYINT}.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertTinyInt(Column column, Field fieldDefn, Object data) {
        return convertSmallInt(column, fieldDefn, data);
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#SMALLINT}.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertSmallInt(Column column, Field fieldDefn, Object data) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) return null;
            return SHORT_FALSE;
        }
        if (data instanceof Short) return data;
        if (data instanceof Number) {
            Number value = (Number) data;
            return new Short(value.shortValue());
        }
        if (data instanceof Boolean) {
            return NumberConversions.getShort((Boolean) data);
        }
        return handleUnknownData(column, fieldDefn, data);
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#INTEGER}.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertInteger(Column column, Field fieldDefn, Object data) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) return null;
            return 0;
        }
        if (data instanceof Integer) return data;
        if (data instanceof Number) {
            Number value = (Number) data;
            return new Integer(value.intValue());
        }
        if (data instanceof Boolean) {
            return NumberConversions.getInteger((Boolean) data);
        }
        return handleUnknownData(column, fieldDefn, data);
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#INTEGER}.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertBigInt(Column column, Field fieldDefn, Object data) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) return null;
            return 0L;
        }
        if (data instanceof Long) return data;
        if (data instanceof Number) {
            Number value = (Number) data;
            return new Long(value.longValue());
        }
        if (data instanceof Boolean) {
            return NumberConversions.getLong((Boolean) data);
        }
        return handleUnknownData(column, fieldDefn, data);
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#FLOAT}.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertFloat(Column column, Field fieldDefn, Object data) {
        return convertDouble(column, fieldDefn, data);
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#DOUBLE}.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertDouble(Column column, Field fieldDefn, Object data) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) return null;
            return 0.0d;
        }
        if (data instanceof Double) return data;
        if (data instanceof Number) {
            // Includes BigDecimal and other numeric values ...
            Number value = (Number) data;
            return new Double(value.doubleValue());
        }
        if (data instanceof Boolean) {
            return NumberConversions.getDouble((Boolean) data);
        }
        return handleUnknownData(column, fieldDefn, data);
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#REAL}.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertReal(Column column, Field fieldDefn, Object data) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) return null;
            return 0.0f;
        }
        if (data instanceof Float) return data;
        if (data instanceof Number) {
            // Includes BigDecimal and other numeric values ...
            Number value = (Number) data;
            return new Float(value.floatValue());
        }
        if (data instanceof Boolean) {
            return NumberConversions.getFloat((Boolean) data);
        }
        return handleUnknownData(column, fieldDefn, data);
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#NUMERIC}.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertNumeric(Column column, Field fieldDefn, Object data) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) {
                return null;
            }
            else {
                return BigDecimal.ZERO;
            }
        }
        BigDecimal decimal = null;
        if (data instanceof BigDecimal)
            decimal = (BigDecimal) data;
        else if (data instanceof Boolean)
            decimal = NumberConversions.getBigDecimal((Boolean) data);
        else if (data instanceof Short)
            decimal = new BigDecimal(((Short) data).intValue());
        else if (data instanceof Integer)
            decimal = new BigDecimal(((Integer) data).intValue());
        else if (data instanceof Long)
            decimal = BigDecimal.valueOf(((Long) data).longValue());
        else if (data instanceof Float)
            decimal = BigDecimal.valueOf(((Float) data).doubleValue());
        else if (data instanceof Double)
            decimal = BigDecimal.valueOf(((Double) data).doubleValue());
        else {
            return handleUnknownData(column, fieldDefn, data);
        }
        return decimal;
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#NUMERIC}.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertDecimal(Column column, Field fieldDefn, Object data) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) {
                return null;
            }
            else {
                return BigDecimal.ZERO;
            }
        }
        BigDecimal decimal = null;
        if (data instanceof BigDecimal)
            decimal = (BigDecimal) data;
        else if (data instanceof Boolean)
            decimal = NumberConversions.getBigDecimal((Boolean) data);
        else if (data instanceof Short)
            decimal = new BigDecimal(((Short) data).intValue());
        else if (data instanceof Integer)
            decimal = new BigDecimal(((Integer) data).intValue());
        else if (data instanceof Long)
            decimal = BigDecimal.valueOf(((Long) data).longValue());
        else if (data instanceof Float)
            decimal = BigDecimal.valueOf(((Float) data).doubleValue());
        else if (data instanceof Double)
            decimal = BigDecimal.valueOf(((Double) data).doubleValue());
        else {
            return handleUnknownData(column, fieldDefn, data);
        }
        return decimal;
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#CHAR}, {@link Types#VARCHAR},
     * {@link Types#LONGVARCHAR}, {@link Types#CLOB}, {@link Types#NCHAR}, {@link Types#NVARCHAR}, {@link Types#LONGNVARCHAR},
     * {@link Types#NCLOB}, {@link Types#DATALINK}, and {@link Types#SQLXML}.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertString(Column column, Field fieldDefn, Object data) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) return null;
            return "";
        }
        if (data instanceof SQLXML) {
            try {
                return ((SQLXML) data).getString();
            } catch (SQLException e) {
                throw new RuntimeException("Error processing data from " + column.jdbcType() + " and column " + column +
                        ": class=" + data.getClass(), e);
            }
        }
        return data.toString();
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#ROWID}.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertRowId(Column column, Field fieldDefn, Object data) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) return null;
            return ByteBuffer.wrap(new byte[0]);
        }
        if (data instanceof java.sql.RowId) {
            java.sql.RowId row = (java.sql.RowId) data;
            return ByteBuffer.wrap(row.getBytes());
        }
        return handleUnknownData(column, fieldDefn, data);
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#BIT}.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertBit(Column column, Field fieldDefn, Object data) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) return null;
            return false;
        }
        if (data instanceof Boolean) return data;
        if (data instanceof Short) return ((Short) data).intValue() == 0 ? Boolean.FALSE : Boolean.TRUE;
        if (data instanceof Integer) return ((Integer) data).intValue() == 0 ? Boolean.FALSE : Boolean.TRUE;
        if (data instanceof Long) return ((Long) data).intValue() == 0 ? Boolean.FALSE : Boolean.TRUE;
        if (data instanceof BitSet) {
            BitSet value = (BitSet) data;
            return value.get(0);
        }
        return handleUnknownData(column, fieldDefn, data);
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#BIT} of length 2+.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @param numBytes the number of bytes that should be included in the resulting byte[]
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertBits(Column column, Field fieldDefn, Object data, int numBytes) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) return null;
            return false;
        }
        if (data instanceof Boolean) {
            Boolean value = (Boolean) data;
            return new byte[] { value.booleanValue() ? (byte) 1 : (byte) 0 };
        }
        if (data instanceof Short) {
            Short value = (Short) data;
            ByteBuffer buffer = ByteBuffer.allocate(Short.BYTES);
            buffer.order(ByteOrder.LITTLE_ENDIAN);
            buffer.putShort(value.shortValue());
            return buffer.array();
        }
        if (data instanceof Integer) {
            Integer value = (Integer) data;
            ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES);
            buffer.order(ByteOrder.LITTLE_ENDIAN);
            buffer.putInt(value.intValue());
            return buffer.array();
        }
        if (data instanceof Long) {
            Long value = (Long) data;
            ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
            buffer.order(ByteOrder.LITTLE_ENDIAN);
            buffer.putLong(value.longValue());
            return buffer.array();
        }
        if (data instanceof byte[]) {
            byte[] bytes = (byte[]) data;
            if (bytes.length == 1) {
                return bytes;
            }
            if (byteOrderOfBitType() == ByteOrder.BIG_ENDIAN) {
                // Reverse it to little endian ...
                int i = 0;
                int j = bytes.length - 1;
                byte tmp;
                while (j > i) {
                    tmp = bytes[j];
                    bytes[j] = bytes[i];
                    bytes[i] = tmp;
                    ++i;
                    --j;
                }
            }
            return padLittleEndian(numBytes, bytes);
        }
        if (data instanceof BitSet) {
            byte[] bytes = ((BitSet) data).toByteArray();
            return padLittleEndian(numBytes, bytes);
        }
        return handleUnknownData(column, fieldDefn, data);
    }

    protected byte[] padLittleEndian(int numBytes, byte[] data) {
        if (data.length < numBytes) {
            byte[] padded = new byte[numBytes];
            System.arraycopy(data, 0, padded, 0, data.length);
            for (int i = data.length; i != numBytes; ++i) {
                padded[i] = 0;
            }
            return padded;
        }
        return data;
    }

    /**
     * Determine whether the {@code byte[]} values for columns of type {@code BIT(n)} are {@link ByteOrder#BIG_ENDIAN big-endian}
     * or {@link ByteOrder#LITTLE_ENDIAN little-endian}. All values for {@code BIT(n)} columns are to be returned in
     * {@link ByteOrder#LITTLE_ENDIAN little-endian}.
     *

     * By default, this method returns {@link ByteOrder#LITTLE_ENDIAN}.
     *
     * @return little endian or big endian; never null
     */
    protected ByteOrder byteOrderOfBitType() {
        return ByteOrder.LITTLE_ENDIAN;
    }

    /**
     * Converts a value object for an expected JDBC type of {@link Types#BOOLEAN}.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object convertBoolean(Column column, Field fieldDefn, Object data) {
        if (data == null) {
            data = fieldDefn.schema().defaultValue();
        }
        if (data == null) {
            if (column.isOptional()) return null;
            return false;
        }
        if (data instanceof Boolean) return data;
        if (data instanceof Short) return ((Short) data).intValue() == 0 ? Boolean.FALSE : Boolean.TRUE;
        if (data instanceof Integer) return ((Integer) data).intValue() == 0 ? Boolean.FALSE : Boolean.TRUE;
        if (data instanceof Long) return ((Long) data).intValue() == 0 ? Boolean.FALSE : Boolean.TRUE;
        return handleUnknownData(column, fieldDefn, data);
    }

    /**
     * Convert an unknown data value.
     *
     * @param column the column definition describing the {@code data} value; never null
     * @param fieldDefn the field definition; never null
     * @param data the data object to be converted into a {@link Date Kafka Connect date} type; never null
     * @return the converted value, or null if the conversion could not be made and the column allows nulls
     * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls
     */
    protected Object handleUnknownData(Column column, Field fieldDefn, Object data) {
        if (column.isOptional() || fieldDefn.schema().isOptional()) {
            Class<?> dataClass = data.getClass();
            logger.warn("Unexpected value for JDBC type {} and column {}: class={}", column.jdbcType(), column,
                        dataClass.isArray() ? dataClass.getSimpleName() : dataClass.getName()); // don't include value in case its
                                                                                // sensitive
            return null;
        }
        throw new IllegalArgumentException("Unexpected value for JDBC type " + column.jdbcType() + " and column " + column +
                ": class=" + data.getClass()); // don't include value in case its sensitive
    }
}

redpajama_set_name: RedPajamaGithub


text:
Donnie Iris
Donnie Iris is an American rock musician best known for his 80s hits "Ah, Leah!" and "Love is Like a Rock", both inspired by contemporary new wave and power pop music. Born Dominic Ierace in middle class Pennsylvania, he got his first real start as a member of the pop group The Jaggerz (the one-hit-wonder responsible for 1970's #2 hit "The Rapper"). After the Jaggerz broke up, Iris toured with funk rock group Wild Cherry, whose 1976 smash "Play That Funky Music" had made them a hot property into the end of the decade.
It was during this period that he became acquainted with his future partner Mark Avsec, a musician then playing keyboards for Wild Cherry. Unfortunately, Wild Cherry ended up being regarded as another one-hit-wonder, and Iris was out of a job by 1980. But Iris and Avsec, and their new band, titled "The Cruisers", returned to the charts several times in the 80s. Iris particularly scored hits with the songs "Ah, Leah!" (a track from 'Back to the Streets' that reached #29 on the Billboard Hot 100), "Love is Like a Rock" (reaching #37 on that Billboard chart), and "My Girl" (reaching #25 on that Billboard chart). "Ah, Leah!" has became known as Iris' 'signature song' and has been included in many multi-artist compilation albums.
According to reporting by D. X. Ferris in the Cleveland Scene, "Ah, Leah!" was the topic of an (apparently frivolous) lawsuit claiming that certain lyrics were stolen from a demo provided by an amateur songwriter. Iris and producer Mark Avsec prevailed, but incurred significant legal fees.
Born in Ellwood City, Pennsylvania, Iris first began singing at weddings at age five, and, by age eight, he was performing on local television and entering talent contests. When his voice changed, he took up the drums but later got back into singing while in high school. A self-taught guitarist, he formed "Donnie & the Donnells" while in college.
Aside from his initial hits, with "Ah, Leah!" particularly getting big attention nationwide as an 80s classic, Iris and the Cruisers were unable to achieve major success outside of the Pennsylvania area. Yet they still have recorded and performed in the Ohio Valley for a great many years, being known for their classic rock n roll inspired live performances. Donnie Iris and the Cruisers released their most recent album, titled 'Ah! Leluiah!', on November 18, 2010. That release is the artist's first Christmas album.
His official website is at http://www.donnieiris.com/ but the most recent news there dates from 2010. Read more about Donnie Iris on Last.fm. User-contributed text is available under the Creative Commons By-SA License; additional terms may apply.
Gear used by Donnie Iris
Donnie Iris links
Dominic Ierace
Donnie Iris & The Cruisers
The Jaggerz
Donnie Iris discogs
Donnie Iris free streaming
Donnie Iris official homepage
Donnie Iris other databases
Donnie Iris social network
Donnie Iris songkick
Donnie Iris VIAF
Donnie Iris wikidata

redpajama_set_name: RedPajamaCommonCrawl


text:
#ifndef BLUEALSA_AT_H_
#define BLUEALSA_AT_H_

#pragma once
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#include "hfp.h"

enum bt_at_type {
	AT_TYPE_RAW,
	AT_TYPE_CMD,
	AT_TYPE_CMD_GET,
	AT_TYPE_CMD_SET,
	AT_TYPE_CMD_TEST,
	AT_TYPE_RESP,
	__AT_TYPE_MAX
};

struct bt_at {
	enum bt_at_type type;
	char command[256];
	char *value;
};

const char *at_type2str(enum bt_at_type type);

char *at_build(char *buffer, size_t size, enum bt_at_type type,
		const char *command, const char *value);

char *at_parse(const char *str, struct bt_at *at);
int at_parse_set_bia(const char *str, bool state[__HFP_IND_MAX]);
int at_parse_get_cind(const char *str, enum hfp_ind map[20]);
int at_parse_set_cmer(const char *str, unsigned int map[5]);
int at_parse_set_xapl(const char *str, uint16_t *vendor, uint16_t *product,
		uint16_t *version, uint8_t *features);

#endif


Although Jill's biological father is Kate's former husband, Sam loves Jill and regards her as his own child.
Jessica Simpson feat. The band garnered interest from Columbia Records, but on the verge of signing, they broke up.
Justin Timberlake - Cry me a river remix. Miranda Cosgrove discography topic American singer Miranda Cosgrove has released one studio album, two extended plays, two soundtracks, six singles, and three promotional singles. Most of the music on this list can be found on YouTube as the only music allowed in the group are from YouTube or Facebook Video.
Wyclef Jean - We trying to stay alive remix. Member feedback about Bonga Wanga: Member feedback about List of best-selling albums of the 1980s Japan: Broadcast times On all but two of the 26 TBS broadcasting channels, the show is aired on Sundays at 12: But we find that the tonality is actually the relative major of the key implied by the tune, and the harmonies consist of the tonic with a free-floating sixth and dominant ninth.
Member feedback about After the Rain Comes Sunshine: His woman has just left him, and he wishes that it would start raining, to hide the tears falling down his face because "a man ain't supposed to cry".
Melanie Fiona - No cigarette smoking in my room.
Baddest or The Baddest may refer to: Queen Latifah - Set it off 18: Boyz II Men". Damian "Jr. Both 1974 and 1975 hold the Hot 100 record for the year with the most 1 hits with 35 songs reaching the 1 spot.
It contains 15 songs and 3 remixes.


text:
Vox downplays attacks on Republican senator
by Accuracy in Media Staff on May 27, 2021
In the latest exhibit of hostility to Kentucky Sen. Rand Paul (R), the Warren County Sheriff's Office was alerted in response to a "suspicious package" that was sent to the senator's home.
This comes after Paul suffered a brutal assault from his neighbor leaving him with six broken ribs and lung damage – a pair of events that the media has largely downplayed.
Vox reported that the incident was the result of a "yard dispute," a claim that has been dismissed by Paul's office. Vox contradicted Paul's claims, which say the attack was much more serious than a "yard dispute." Instead, Vox used a quote insulting the attacker and victim.
"Either way, neighbors in the upscale neighborhood weren't thrilled about how the incident brought scrutiny on their block. One person, talking to GQ, called the attacker and the victim 'two little shits.'"
In contrast, after the January 6 riot at the Capitol, Vox reported on Rep. Alexandria Ocasio-Cortez's (D-N.Y.) "harrowing experience," calling the event a "devastating blow to democracy".
Ocasio-Cortez was not hurt, nor was she in a building with any rioters, according to another representative two doors down. She sustained no injuries, and Vox reiterated her trauma with no skepticism, unlike what they did to Paul.
Had Vox had put up a piece with a quote calling the rioters and Ocasio-Cortez the same insult, or had downplayed Ocasio-Cortez if she had suffered severe injuries in the Capitol riot, there would surely be intense backlash.
Paul's wife, Kelley, called out this difference in a tweet, saying, "Rand assaulted in blindside attack, six broken ribs and lung damage: media calls it a "dispute." Rand and I held hostage for 9 minutes by mob spitting on and threatening to kill us: media says we were "yelled at." Rand calmly questions gov authorities: "Rand ATTACKS Fauci!""
Rand assaulted in blindside attack, six broken ribs and lung damage: media calls it a "dispute." Rand and I held hostage for 9 minutes by mob spitting on and threatening to kill us: media says we were "yelled at." Rand calmly questions gov authorities: "Rand ATTACKS Fauci!"
— Kelley Paul (@KelleyAshbyPaul) May 25, 2021
Accuracy in Media Staff


This hidden gem of the South Carolina lowcountry is just a short drive away from Charleston and is a must see if you are in the area! From dense, old growth Live Oak forest draped in Spanish Moss to the incredible boneyard beaches littered with palmetto groves along miles of pristine beaches. Not to mention the beach front campsites that provide a perfect view of sunrise over the ocean each morning..what more do you need to hear!?
There are a few different access trails throughout the park and all are equally impressive with scenery and ease of hike but starting from the Hunting Island Campground take the beach access near the campground store and you have miles of boneyard beaches, dunes and groves of palmetto trees littered throughout the hike. The beach is fairly flat and walkable except for the sections of boneyard trees scattered like a maze across the sand that can be tricky to navigate at high tide. A few remaining trees still stand battling the surf and rising sea levels offering incredible photo opportunities of this super unique island!
From the park office just a minute drive down Hwy 21 from the campground is where the rest of the trailheads start with many connecting and intersecting short trails no longer than 2.3 miles throughout the park that can be looped together for a longer hike. The Lighthouse Magnolia Forest trail offers dense, moss draped, old growth forest path leading to the palmetto groves and sandy beaches surrounding the historic lighthouse and shoreline...from there you have access to an endless beach and connecting trails winding through the maritime forest and marshes littered across the island. Each trail offers something different and you won't be disappointed. Grab a free map at the park office and have a blast exploring this low country gem!
Be sure to book a site before you go the campground gets booked very quickly during the warmer months. The weather can change quickly so bring clothing that will keep you warm and dry as nights can get chilly with the winds off the ocean.
Awesome Multi sport Camping Spot.
Hunting Island has been a "secret" spot for years but is now pretty well found out. Nevertheless, it's a great spot anytime of year w/ the exception of deep summer. Camping in Spring and Fall is heavenly. Features several walk-in backcountry sites, great bike trails, excellent kayaking and fishing potential.


London Coin Galleries in Newport Beach CA is Orange County's most referred coin dealer with a variety of U.S. Coins, silver coins, gold coins, buy, sell or value your USA coin collection with us.
Due to our longevity in the industry, we get fresh inventory on a daily basis. If you're looking for an experienced coin dealer in Orange County that understands numismatic value of coins minted in the United States, contact us for an appointment and enjoy the wide selection we have to offer.
United State Coins vary in prices based on the type of coin they are. Material, condition, and many other factors are considered when assigning value.
We have helped many estates with a few coins or an entire collection of United States Coins.
London Coin Galleries has been serving the community for over 30 years. We bring coin buyers, collectors, and sellers together.
How Much are My U.S. Coins Worth?
Due to security and our high quality service standards, we operate by appointment only in order to provide you with the ample time you need when you meet with us.
If interested in purchasing, selling, trading, or learning more about U.S. coin and collections. We look forward to helping you, please schedule an appointment today.


text:
Appleton in Outagamie County, Wisconsin — The American Midwest (Great Lakes)
By Keith L, August 17, 2011
1. 9-11 Memorial Marker
9-11 Memorial. . In memory of those who lost their lives in New York City, Washington, D.C., and Pennsylvania on 11 September 2001. . This memorial is in Appleton in Outagamie County Wisconsin
In memory of those
who lost their lives
in New York City,
Washington, D.C.,
and Pennsylvania on
Topics. This historical marker memorial is listed in this topic list: Notable Events.
Location. 44° 15.394′ N, 88° 23.788′ W. Marker is in Appleton, Wisconsin, in Outagamie County. Marker is on South Lawe Street north of East South Island Street, on the right when traveling south. Marker is on the grounds of Neenah Paper, Appleton Mill. Touch for map. Marker is at or near this postal address: 600 South Vulcan Street, Appleton WI 54915, United States of America. Touch for directions.
Other nearby markers. At least 8 other markers are within one mile of this marker, measured as the crow flies. First Edison Hydroelectric System in America (about 500 feet away, measured in a direct line); Vulcan Street Plant Replica (about 500 feet away); The Merging of Milwaukee-Downer and Lawrence Colleges (approx. 0.4 miles away); Lawrence University (approx. 0.4 miles away); First Commercially Successful Electric Street Railway (approx. 0.4 miles away); Henry James and Cremora Rogers Residence
(approx. 0.9 miles away); Number 736 (approx. 0.9 miles away); Soldiers and Sailors Memorial Bridge (approx. one mile away). Touch for a list and map of all markers in Appleton.
3. 9-11 Memorial
Credits. This page was last revised on June 16, 2016. It was originally submitted on September 11, 2011, by Keith L of Wisconsin Rapids, Wisconsin. This page has been viewed 599 times since then and 2 times this year. Photos: 1, 2, 3. submitted on September 11, 2011, by Keith L of Wisconsin Rapids, Wisconsin.


text:
Take The Long Way Home - SUPERTRAMP
I DON'T WANNA FIGHT - TINA TURNER
HOLDING BACK THE YEARS - SIMPLY RED
WONDERFUL TONIGHT - ERIC CLAPTON
I CAN'T GO FOR THAT - HALL & OATES
IT'S TOO LATE - CAROLE KING
BLACK VELVET - ALANNAH MYLES
REMINISCING - LITTLE RIVER BAND
Right Time Of The Night - JENNIFER WARNES
YOUR MAMA DON'T DANCE - LOGGINS & MESSINA
LOST IN LOVE - AIR SUPPLY
BABY BABY - AMY GRANT
SUMMER OF 69 - BRYAN ADAMS
BAKER STREET - GERRY RAFFERTY
(I've Had) THE TIME OF MY LIFE - Bill Medley / Jennifer Warnes
STAYIN' ALIVE - BEE GEES
YOU GOTTA BE - DES'REE
DRIFT AWAY - DOBIE GRAY
STOP YOUR FUSSIN' - TONI CHILDS
PART TIME LOVE - ELTON JOHN
Watch Kelly Clarkson's incredible cover of Lady Gaga and Bradley Cooper's 'Shallow'
Kelly covers Shallow
Videos,
Tuesday, 19 February 2019, 11:35AM
Kelly Clarkson has taken on Lady Gaga and Bradley Cooper's mega-hit 'Shallow' - and it will give you CHILLS!
Surprising fans at her Wisconsin concert on Friday, the American Idol winner launched into a show-stopping rendition of the A Star Is Born song after sharing her admiration for Lady Gaga.
"I know there's a lot of competition always with artists in the industry, but there's a lot of us that just dig each other," Clarkson told the crowd.
"And we really get inspired by each other and what they're doing. And this chick is amazing. We're really different, but at the same time, we're really similar in the fact that she just loves music and that's why she's doing what she's doing."
Young busker wows crowd with an amazing cover of Shallow
Watch Lady Gaga bring Bradley Cooper out for an incredible performance of Shallow
"It's cool to know that someone that talented is also really nice," Clarkson added. "This song, I just love it."
"I hope I don't suck," she said. "And if I do, I hope she doesn't see it."
Well, we hope Lady Gaga does see the performance because it's safe to say Clarkson absolutely crushed the performance!
Talk about goosebumps!
See all the photos from Lorna Subritzky's trip to New Caledonia!
Lady Gaga and Bradley Cooper are in talks to play love interests again in a new film
Bay Bites: Brian Kelly reviews Fire Mount Maunganui
America's Got Talent singer's cover of John Lennon's 'Imagine'...
Renée Zellweger impresses with amazing Judy...
Rowan Atkinson shares HILARIOUS story about...


Life happens to all of us. If we are lucky, things go along smoothly each day just as we planned, but sometimes that isn't the case. You work hard to pay your bills and manage your credit responsibly, then something entirely unexpected happens, and you become sick or injured, and your life is suddenly in turmoil. To help ease the financial burden of your loan obligation in the event of an unexpected life event, injury or illness, we offer optional Credit Life and Disability insurance.
Claims may be filed by contact your credit union. If you have questions regarding your claim status, contact CMFG Life at 800.621.6323. California Department of Insurance Consumer Hotline: 1.800.927.4357.


text:
No matching items found
Gulf Today
Most searched related results
Ronaldo at centre stage but Portugal's stars ready to shine
Portuguese players attend a training session at the Bessa stadium in Porto on Tuesday. Associated Presse
Cristiano Ronaldo has ended his international exile to spearhead Portugal's hopes of winning the inaugural Nations League on home soil this week, but gone are the days when he was the European champions' only man to fear.
A five-time Ballon d'Or and Champions League winner, who has delivered league titles to his clubs in England, Spain and Italy, there is little left for Ronaldo to prove.
But after his tears as a teenager when losing a home final at Euro 2004, Ronaldo can avenge that defeat by lifting the second international trophy of his career in front of an adoring Portuguese crowd.
"We have the privilege of having the best player in the world, who is a scoring machine," said Portugal defender Pepe, who spent many seasons alongside Ronaldo at Real Madrid.
"Cristiano is our leader and it's always better to have the best player in the world with us," added veteran centre-back Jose Fonte.
Portugal, though, made it to the final four of the first ever Nations League without their all-time record goalscorer.
Ronaldo took a break from international football after the World Cup and only returned for Portugal's first two Euro 2020 qualifiers in March.
His return did not go to plan as Fernando Santos's men were held at home by Ukraine and Serbia, while the Juventus forward limped off injured just 30 minutes into the second fixture of a double header.
In his absence, Bernardo Silva has come to the fore with the Manchester City midfielder, who was hailed by club boss Pep Guardiola as the outstanding player in the Premier League this season, also becoming the principal creative force for his country.
City may soon have another Portuguese star on their books with the English champions among a host of clubs chasing Joao Felix.
The 19-year-old is in line for his international debut in Wednesday's semi-final against Switzerland after a stellar season with Benfica.
Felix scored 20 goals in all competitions, including a Europa League quarter-final hat-trick against Eintracht Frankfurt, with Benfica fearing his 120 million euro ($134 million) buyout clause will be activated this summer.
That would make him the most expensive Portuguese player ever, even ahead of Ronaldo, but Felix admitted to being star struck on his first few days training alongside the five-time world player of the year.
"It was weird, I had never seen him live so close," Felix told Benfica's website.
"I said to my colleagues and best friends later when I got home that it looked like it was in career mode on PlayStation."
Switzerland do not possess the same star power, although Xherdan Shaqiri will arrive in Porto as a newly crowned European champion at club level with Liverpool.
However, Vladimir Petkovic's men have shown their ability to spring a huge surprise just to make it to the last four.
Needing to beat the number one ranked side in the world, Belgium, by two goals in their final Nations League group game, Switzerland trailed 2-0 before roaring back for a thrilling 5-2 win.
soccer Cristiano Ronaldo
Ronaldo stretches Torino's 24-year wait for win at Juve
Cristiano Ronaldo headed in a late equaliser to spoil Torino's dream of a first win at city rivals Juventus in nearly a quarter of a century on Friday and frustrate their bid to move into the Champions League places. Sasa Lukic had fired Torino ahead after 17 minutes in a match brought forward
Portugal down Netherlands to win first Nations League
Portugal added the inaugural Nations League title to their Euro 2016 triumph as Goncalo Guedes's strike on the hour won an underwhelming final 1-0 against the Netherlands in Porto on Sunday.
Ronaldo back to lead Juventus against Ajax young guns
'Cristiano has trained with the team and is available. As long as nothing happens tonight or tomorrow morning, he will start'
Torino aim to honour past heroes in derby clash with Juve
With Barcelona already crowned champions, the focus in Spain has shifted to a thrilling three-way battle for La Liga's final Champions League berth, with Getafe, Sevilla and Valencia eyeing game-changing prize money worth at least 30 million euros (£25.7 million). With three games to go, little-known Getafe have 55 points along with Sevilla
UAE Cabinet amends law to boost family-owned businesses
Father arrested for raping four minor daughters in Kerala
'Dolittle' fails to tickle the funny bone
Share stories with us securely and confidentially
Azizi Developments crowns winners of Dubai World Cup Carnival races
'We are delighted to sponsor the Dubai World Cup for the third consecutive year, in line with our pillar partnership with Meydan," says Farhad Azizi.
VIDEO: Al Nasr beat Shabab Al Ahli to lift second Arabian Gulf Cup
Skipper Alvaro Negredo and Toze scored a goal each as a clinical Al Nasr defeated defending champions Shabab Al Ahli 2-1 to lift the Arabian Gulf Cup on Friday.
India post 36-run win to draw level, set up thrilling Australia ODI series decider
India beat Australia by 36 runs in the second ODI at the SCA stadium in Rajkot to level the three-match series between the two sides 1-1. Shikhar Dhawan, KL Rahul and Virat Kohli helped
Reds aim to carry on relentless march as City chase Cup glory
Liverpool can widen the chasm between themselves and the rest of the English Premier League with a win in their battle against Manchester United at Anfield on Sunday.


text:
Q: Evaluate $\int^0_1 \frac{\ln(t)}{1-t^2}dt$
Evaluate: $$\int^0_1 \dfrac{\ln(t)}{1-t^2}dt$$

This actually came up while solving another integral. It was suggested that I use a binomial series, but unfortunately I do not understand how to use this. Can anyone help me out?

A: First consider the operation
\begin{align}
\partial_{n} \, t^{n} = \frac{d}{dn} \, e^{n \ln(t)} = \ln(t) \, e^{n \ln(t)} = t^{n} \, \ln(t).
\end{align}
Now consider the integral, where the operation just presented will be used,
\begin{align}
I_{n} = \int_{0}^{1} \ln(t) \, t^{n} \, dt = \partial_{n} \, \int_{0}^{1} t^{n} \, dt = \partial_{n} \left[ \frac{t^{n+1}}{n+1} \right]_{0}^{1} = \partial_{n} \left(\frac{1}{n+1}\right) = - \frac{1}{(n+1)^{2}}
\end{align}
Now letting $n \to 2n$ and then summing over $n$ it is seen that:
\begin{align}
\sum_{n=0}^{\infty} I_{2n} = \int_{0}^{1} \frac{\ln(t) \, dt}{1-t^{2}} &= - \sum_{n=0}^{\infty} \frac{1}{(2n+1)^{2}} \\
&= - \left(\sum_{n=0}^{\infty} \frac{1}{(2n+1)^{2}} + \sum_{n=1}^{\infty} \frac{1}{(2n)^{2}} \right) + \frac{1}{4} \sum_{n=1}^{\infty} \frac{1}{n^{2}} \\
&= - \sum_{n=1}^{\infty} \frac{1}{n^{2}} + \frac{1}{4} \sum_{n=1}^{\infty} \frac{1}{n^{2}}  = - \zeta(2) + \frac{1}{4} \, \zeta(2) \\
&= - \frac{3}{4} \zeta(2) = - \frac{\pi^{2}}{8}.
\end{align}
The integral desired is:
\begin{align}
\int_{0}^{1} \frac{\ln(t) \, dt}{1-t^{2}} = - \frac{\pi^{2}}{8}.
\end{align}

A: The geometric series formula tells you that
$$\frac{1}{1-r}=\sum_{n=0}^\infty r^n$$
if $|r|<1$. Applying this to $r=t^2$ you get that your integral is
$$\int_1^0 \sum_{n=0}^\infty \ln(t) t^{2n} dt.$$
You can interchange the sum and integral, for example using monotone convergence (since the integrands are all negative), so you have
$$\sum_{n=0}^\infty \int_1^0 \ln(t) t^{2n} dt.$$
Each of these integrals can be done using integration by parts with $u=\ln(t)$ and $dv=t^{2n} dt$. They are improper at the endpoint of $0$, but this is no real obstacle, because the log term in each antiderivative is getting multiplied with a monomial, so the log terms in the definite integrals all vanish.

A: Substitute $t\mapsto e^{-t}$:
$$
\begin{align}
\int_1^0\frac{\log(t)}{1-t^2}\,\mathrm{d}t
&=\int_0^\infty\frac{t}{1-e^{-2t}}e^{-t}\,\mathrm{d}t\\
&=\sum_{k=0}^\infty\int_0^\infty te^{-(2k+1)t}\,\mathrm{d}t\\
&=\Gamma(2)\sum_{k=0}^\infty\frac1{(2k+1)^2}\\
&=\frac{\pi^2}8
\end{align}
$$

redpajama_set_name: RedPajamaStackExchange


text:
Personal wind farm
July 28th, 2006 @ 5:17 PM City Life
The conventional wind farm comprises turbines that generate electrical power from wind-turned blades; mine employs battery-supplied electrical power to generate wind. My first Squeeze Breeze cost a dollar and was found on an Albertsons remainder table. Now, thanks to Academy Sports & Outdoors, I enjoy the gale-force effects of an array of Squeeze Breeze water misting fans. These take two AA batteries and use them very efficiently. The William Cannon store stocks them currently in three lurid color combinations. There's a carrying strap, the trigger when pressed releases a spray of cooling water (broken into a mist if the fan's in operation), and the aperture for filling is large enough to admit ice cubes for additional chill. In this household, where there's no air-conditioning, we especially prize them because they stand up on their own and are really good (and quiet) personal fans for use, for instance, on a cluttered computer desk. We like them also when we're outdoors reading in the screen tent after supper, and they're great to have along at the bus stop. These are invaluable accessories for hot outdoor events. If they're not sold on the grounds at the ACL music festival this year, somebody can make a fortune waylaying those afoot and headed for the entry gates, complete with a 100% markup over retail.
The old ads used to say, "It's fun to shop at Academy." And at least at this store, it certainly is. I truly hate to shop. The employees at William Cannon know their stock and know where it's to be found. They assist the shopper and one another. They're cheerful. Because I dislike shopping so, I want the sought-after to be found, and found fast. If it's not available, I want to know that right away as well. I was there in search of a particular sort of footgear. It was carried in a broad range of sizes. There are places to sit and mirrors for viewing shoes. Members of the staff find the styles and sizes, bring them to the customer, and assist in lacing where necessary and in putting them on and taking them off the foot. They were helpful with impatient children getting ready for the new school year. I saw no Brannock measuring device, but I've been in dedicated shoe stores selling much dressier and more expensive shoes with service not half so good.
Members of the staff know their fishing tackle and sporting goods and are not condescending to their female customers. It really was fun to shop at Academy. The Squeeze Breeze mister fans were located in the camping department.
Misting Fans (unregistered) on August 10th, 2006 @ 10:26 am
It's amazing how much little things like that can help. It's one of the greatest feelings in the world when you're in 98 degree heat.


Göteborg : Chalmers tekniska högskola, 2016. 153 s.
Future solar cells need to be cheaper, more efficient and produced in an environmental friendly way to be a competitive and sustainable alternative for solar energy conversion. The emerging dye sensitized solar cells (DSSCs) might be able to meet future demands regarding price, structural flexibility and environmental issues, but for the time being, their potential as a competitive and viable alternative is hampered by low energy conversion efficiencies and stability issues. A most central process in the conversion of sunlight energy directly into electric energy, is the photon to charge carrier conversion which takes place in the photoactive part of the solarcell. To achieve a high incident photon to charge carrier efficiency (IPCE), efficient absorption of incoming sunlight over a wide range of wavelenghts is needed. The use of plasmonic effects generated by metal nanoparticles (MNP) in combination with a sensitizing dye is an interesting approach to increase the IPCE for DSSCs. In this work, effects on cell energy conversion efficiency of adding gold nanoparticles (GNPs) have been studied. Spherical GNPs of diameter 5, 10 and 40 nm, embedded in the photoactive layers have been studied in combination with three different sensitizing dyes; Ruthenizer 455-PF6, Ruthenizer 620-1H3BTA and Sensidizer SQ2. Cells without dye were also included in the study. TiO2 was used as semiconductor material in thin(< 1μm ) photoactive layers. Complete DSSCs containing gel electrolyte have been built and characterized with I-V graphs using different light intensities of 0.11, 0.55, 0.79 and 1.0 sun. The results clearly show that the cell efficiency can be improved by using GNPs this way, it was also shown that certain combinations of dye and GNP sizes affected cell efficiency more positive than others while addition of GNPs to cells without dye sensitizer affected the efficiency negatively. Most positive results were achieved using the organic dye Ruthenizer 455-PF6 in combination with 40 nm GNPs, showing relative efficiency increase well above 25 %.
AB Future solar cells need to be cheaper, more efficient and produced in an environmental friendly way to be a competitive and sustainable alternative for solar energy conversion. The emerging dye sensitized solar cells (DSSCs) might be able to meet future demands regarding price, structural flexibility and environmental issues, but for the time being, their potential as a competitive and viable alternative is hampered by low energy conversion efficiencies and stability issues. A most central process in the conversion of sunlight energy directly into electric energy, is the photon to charge carrier conversion which takes place in the photoactive part of the solarcell. To achieve a high incident photon to charge carrier efficiency (IPCE), efficient absorption of incoming sunlight over a wide range of wavelenghts is needed. The use of plasmonic effects generated by metal nanoparticles (MNP) in combination with a sensitizing dye is an interesting approach to increase the IPCE for DSSCs. In this work, effects on cell energy conversion efficiency of adding gold nanoparticles (GNPs) have been studied. Spherical GNPs of diameter 5, 10 and 40 nm, embedded in the photoactive layers have been studied in combination with three different sensitizing dyes; Ruthenizer 455-PF6, Ruthenizer 620-1H3BTA and Sensidizer SQ2. Cells without dye were also included in the study. TiO2 was used as semiconductor material in thin(< 1μm ) photoactive layers. Complete DSSCs containing gel electrolyte have been built and characterized with I-V graphs using different light intensities of 0.11, 0.55, 0.79 and 1.0 sun. The results clearly show that the cell efficiency can be improved by using GNPs this way, it was also shown that certain combinations of dye and GNP sizes affected cell efficiency more positive than others while addition of GNPs to cells without dye sensitizer affected the efficiency negatively. Most positive results were achieved using the organic dye Ruthenizer 455-PF6 in combination with 40 nm GNPs, showing relative efficiency increase well above 25 %.


Cloud disasters can and will happen. Are you prepared?
Imagine what would happen to your organization in the event of a prolonged cloud outage. Are you prepared to handle it?
It's going to happen, and happen to you and your organization. No, I'm not a salesguy, otherwise bereft of booth babes at RSA. I'm a systems engineer going back to the days of SNA, DSLAMs, CSU/DSUs, ARCNet over NetWare, and other ancient interconnect. Stuff happens.
So, whatchya gonna do? What is your plan?
Did you notice how none of this cloud stuff talks to none of this cloud stuff among competing vendors? Even the mighty Open Data Center Alliance can't help you if you don't have a plan, and haven't tried to do a failover successfully.
This year, thankfully, we dodged a number of hurricanes and tornadoes. The snows were gruesome, but it was rare to see data centers go down because of it. The cloud usually kept on ticking.
But need I remind you of the Chicago River Flood? Katrina? The Oklahoma and Alabama tornadoes? The Nepal Earthquake? Go ahead and fight all of the malware bad guys, crackers, Rumanian spear fishermen, Chinese armies, all you want. Mother Nature is bigger. Trust me on this.
Last weekend, I drove to Chicago and watched the last remnants of several bouts of tornadoes on Indiana Hwy 37 as it's being transformed into Interstate 69. The treetops, once mangled several times by untold windforce, are now largely gone from the sides of the highway as you approach Indianapolis from the south. I can remember when whole rows of homes and buildings for several miles were sucked into the tornado. They've recovered, the traces largely gone, the insurance paid.
But as I think of the cloud, and the seeming inherent lack of data exchange—especially at the consumer level—I shudder to think of what a fault-line fiber cable break could do. BGP and other OSPF protocols would go berserk trying to find new routes. Online video streams of prize fights could be interrupted, after all.
People couldn't get their Facebooks. Twitter wouldn't tweet. OMG—no Snapchat or Pinterest. Salespeople would fall asleep, without trolling LinkedIn for leads. You'd have to pay cash. Everywhere. Imagine that. Celltowers wouldn't be able to transfer phone calls or let you play Angry Birds. Perhaps cars on the freeway would glide to a gentle stop, unable to get maps from their GPS coordinates. Apple Watches would be unsure what time it was. Imagine: No Netflix.
And your organization, likely very dependent on cloud resources, would need to execute a backup plan. And it had better be successful. What would five days of lost revenue do to $yourcompany?
I used to message to my friends once a month like clockwork: Do your damn backups. That was in the days when hard disk reliability was equal to the timeliness of a tax refund check in a good year. Now it's a bit better, both ways. What's unknown is what happens when your critical links go dark.


This page contains thorough information on how to uninstall NVIDIA Control Panel 311.70 for Windows. The Windows version was developed by NVIDIA Corporation. Further information on NVIDIA Corporation can be found here. Usually the NVIDIA Control Panel 311.70 program is found in the C:\Program Files\NVIDIA Corporation\Control Panel Client folder, depending on the user's option during setup. nvcplui.exe is the programs's main file and it takes about 6.55 MB (6865184 bytes) on disk.
The following executables are installed along with NVIDIA Control Panel 311.70. They take about 6.55 MB (6865184 bytes) on disk.
This info is about NVIDIA Control Panel 311.70 version 311.70 alone.
1. If you don't have Advanced Uninstaller PRO already installed on your Windows PC, add it. This is a good step because Advanced Uninstaller PRO is a very potent uninstaller and all around utility to clean your Windows system.
2. Start Advanced Uninstaller PRO. It's recommended to take your time to get familiar with Advanced Uninstaller PRO's interface and number of features available. Advanced Uninstaller PRO is a very good PC management program.
Star rating (in the left lower corner). This tells you the opinion other users have regarding NVIDIA Control Panel 311.70, from "Highly recommended" to "Very dangerous".
7. Click the Uninstall button. A confirmation dialog will show up. accept the removal by clicking Uninstall. Advanced Uninstaller PRO will then remove NVIDIA Control Panel 311.70.
8. After removing NVIDIA Control Panel 311.70, Advanced Uninstaller PRO will ask you to run a cleanup. Press Next to go ahead with the cleanup. All the items that belong NVIDIA Control Panel 311.70 that have been left behind will be detected and you will be asked if you want to delete them. By uninstalling NVIDIA Control Panel 311.70 using Advanced Uninstaller PRO, you are assured that no Windows registry items, files or directories are left behind on your disk.
This page is not a recommendation to remove NVIDIA Control Panel 311.70 by NVIDIA Corporation from your computer, we are not saying that NVIDIA Control Panel 311.70 by NVIDIA Corporation is not a good application for your PC. This text only contains detailed instructions on how to remove NVIDIA Control Panel 311.70 supposing you want to. Here you can find registry and disk entries that Advanced Uninstaller PRO stumbled upon and classified as "leftovers" on other users' computers.


text:
Our Response to Charlottesville
The white supremacist rhetoric of the 2016 election cycle exploded into violence and murder this weekend in Charlottesville. Chicago Lawyers' Committee mourns the loss of life and joins the cries of our nation. Let us be clear. This was not merely an exercise of First Amendment freedom of speech and assembly. This was hate crime at its worst.
Sadly, hate crime is not new in America, and Chicago Lawyers' Committee has been fighting hate crime – a cornerstone civil rights violation - since our founding in the 1960s. The images of violent, emboldened young white men on the television screens over the weekend were eerily similar to photographs from the 1966 Chicago Freedom Movement march in Marquette Park on the southwest side of Chicago. Our President's refusal to name and condemn white supremacy will only intensify the renewed violent bigotry that drove a car into a crowd of people and murdered 32-year-old Heather Heyer.
Building on our long history of legal action to reduce hate crime, Chicago Lawyers' Committee relaunched our Hate Crime Project in 2016 to respond to the spike in hate crime in Illinois and across the country, and the broadening of targeted groups, including Muslims, immigrants, and LGBTQ people.
As one of the oldest and largest racial justice organizations in Illinois, Chicago Lawyers' Committee has recommitted to advancing racial equity as central to our mission as a modern-day civil rights organization. The struggle to fight hatred and discrimination is far from over. Join us and our community partners as we continue to work for equity and justice in our city and state.
FOR INFORMATION ABOUT OUR HATE CRIME PROJECT OR TO REPORT A HATE INCIDENT, CALL OUR HATE CRIME HELPLINE AT 312-202-3663.
To bolster our legal efforts to stop hate crime in Illinois, donate here.
Hate Crime ProjectTimna Axel August 14, 2017
Chicago Lawyers' Committee Applauds Attorney General Madigan for Lawsuit Seeking Consent Decree
Police AccountabilityTimna Axel August 29, 2017
Chicago Lawyers' Committee joins Jefferson Park faith leaders and community advocates in supporting affordable family housing
Fair HousingTimna Axel June 1, 2017 Fair Housing, segregation, affordable housing, Jefferson Park