// Path: dalesbred/src/main/java/org/dalesbred/DatabaseSQLException.java
// public class DatabaseSQLException extends DatabaseException {
// 
//     public DatabaseSQLException(@NotNull String message, @NotNull SQLException cause) {
//         super(message, cause);
//     }
// 
//     public DatabaseSQLException(@NotNull SQLException cause) {
//         super(cause);
//     }
// 
//     @Override
//     public synchronized @NotNull SQLException getCause() {
//         return (SQLException) super.getCause();
//     }
// }
// 
// Path: dalesbred/src/main/java/org/dalesbred/internal/jdbc/ResultSetUtils.java
// public final class ResultSetUtils {
// 
//     private ResultSetUtils() { }
// 
//     public static @NotNull NamedTypeList getTypes(@NotNull ResultSetMetaData metaData) throws SQLException {
//         int columns = metaData.getColumnCount();
// 
//         NamedTypeList.Builder result = NamedTypeList.builder(columns);
// 
//         for (int i = 0; i < columns; i++)
//             result.add(metaData.getColumnLabel(i+1), getColumnType(metaData, i + 1));
// 
//         return result.build();
//     }
// 
//     public static @NotNull Type getColumnType(@NotNull ResultSetMetaData metaData, int column) throws SQLException {
//         String className = metaData.getColumnClassName(column);
//         try {
//             return Class.forName(className);
//         } catch (ClassNotFoundException e) {
//             throw new DatabaseException("Could not find class '" + className + "' specified by ResultSet.", e);
//         }
//     }
// }
// 
// Path: dalesbred/src/main/java/org/dalesbred/internal/jdbc/SqlUtils.java
// public final class SqlUtils {
// 
//     private SqlUtils() { }
// 
//     public static void freeArray(@NotNull Array array) throws SQLException {
//         try {
//             array.free();
//         } catch (SQLFeatureNotSupportedException ignored) {
//         }
//     }
// }
// 
// Path: dalesbred/src/main/java/org/dalesbred/internal/utils/TypeUtils.java
// public final class TypeUtils {
// 
//     private TypeUtils() { }
// 
//     public static @NotNull Class<?> rawType(@NotNull Type type) {
//         if (type instanceof Class<?>) {
//             return (Class<?>) type;
// 
//         } else if (type instanceof ParameterizedType) {
//             return rawType(((ParameterizedType) type).getRawType());
// 
//         } else if (type instanceof TypeVariable<?>) {
//             // We could return one of the bounds, but it won't work if there are multiple bounds.
//             // Therefore just return object.
//             return Object.class;
// 
//         } else if (type instanceof WildcardType) {
//             return rawType(((WildcardType) type).getUpperBounds()[0]);
// 
//         } else if (type instanceof GenericArrayType) {
//             return arrayType(rawType(((GenericArrayType) type).getGenericComponentType()));
// 
//         } else {
//             throw new IllegalArgumentException("unexpected type: " + type);
//         }
//     }
// 
//     public static @NotNull Type typeParameter(@NotNull Type type) {
//         if (type instanceof ParameterizedType)
//             return ((ParameterizedType) type).getActualTypeArguments()[0];
// 
//         return Object.class;
//     }
// 
//     public static boolean isEnum(@NotNull Type type) {
//         return (type instanceof Class<?>) && ((Class<?>) type).isEnum();
//     }
// 
//     public static boolean isPrimitive(@NotNull Type type) {
//         return (type instanceof Class<?>) && ((Class<?>) type).isPrimitive();
//     }
// 
//     public static @NotNull Class<?> arrayType(@NotNull Class<?> type) {
//         return Array.newInstance(type, 0).getClass();
//     }
// 
//     public static @Nullable Type genericSuperClass(@NotNull Type type) {
//         return rawType(type).getGenericSuperclass();
//     }
// 
//     public static @NotNull Type[] genericInterfaces(@NotNull Type type) {
//         return rawType(type).getGenericInterfaces();
//     }
// 
//     public static boolean isAssignable(@NotNull Type target, @NotNull Type source) {
//         // TODO: implement proper rules for generic types
//         return isAssignableByBoxing(rawType(target), rawType(source));
//     }
// 
//     private static boolean isAssignableByBoxing(@NotNull Class<?> target, @NotNull Class<?> source) {
//         return Primitives.wrap(target).isAssignableFrom(Primitives.wrap(source));
//     }
// }
// 
// Path: dalesbred/src/main/java/org/dalesbred/result/UnexpectedResultException.java
// public class UnexpectedResultException extends DatabaseException {
//     public UnexpectedResultException(@NotNull String message) {
//         super(message);
//     }
// }


import java.sql.Array;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import org.dalesbred.DatabaseSQLException;
import org.dalesbred.internal.jdbc.ResultSetUtils;
import org.dalesbred.internal.jdbc.SqlUtils;
import org.dalesbred.internal.utils.TypeUtils;
import org.dalesbred.result.UnexpectedResultException;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Type;
                NamedTypeList types = NamedTypeList.builder(1).add("value", ResultSetUtils.getColumnType(resultSet.getMetaData(), 2)).build();
                Instantiator<?> ctor = instantiatorRegistry.findInstantiator(elementType, types);
                ArrayList<Object> result = new ArrayList<>();

                // For performance reasons we reuse the same arguments-array and InstantiatorArguments-object for all rows.
                // This should be fine as long as the instantiators don't hang on to their arguments for too long.
                Object[] arguments = new Object[1];
                InstantiatorArguments instantiatorArguments = new InstantiatorArguments(types, arguments);

                while (resultSet.next()) {
                    arguments[0] = resultSet.getObject(2);

                    Object value = ctor.instantiate(instantiatorArguments);
                    if (value != null || allowNulls)
                        result.add(value);
                    else
                        throw new UnexpectedResultException("Expected " + elementType + ", but got null");
                }

                return result;

            } finally {
                try {
                    resultSet.close();
                } finally {
                    SqlUtils.freeArray(array);
                }
            }

        } catch (SQLException e) {
// Path: dalesbred/src/main/java/org/dalesbred/DatabaseSQLException.java
// public class DatabaseSQLException extends DatabaseException {
// 
//     public DatabaseSQLException(@NotNull String message, @NotNull SQLException cause) {
//         super(message, cause);
//     }
// 
//     public DatabaseSQLException(@NotNull SQLException cause) {
//         super(cause);
//     }
// 
//     @Override
//     public synchronized @NotNull SQLException getCause() {
//         return (SQLException) super.getCause();
//     }
// }
// 
// Path: dalesbred/src/main/java/org/dalesbred/internal/jdbc/ResultSetUtils.java
// public final class ResultSetUtils {
// 
//     private ResultSetUtils() { }
// 
//     public static @NotNull NamedTypeList getTypes(@NotNull ResultSetMetaData metaData) throws SQLException {
//         int columns = metaData.getColumnCount();
// 
//         NamedTypeList.Builder result = NamedTypeList.builder(columns);
// 
//         for (int i = 0; i < columns; i++)
//             result.add(metaData.getColumnLabel(i+1), getColumnType(metaData, i + 1));
// 
//         return result.build();
//     }
// 
//     public static @NotNull Type getColumnType(@NotNull ResultSetMetaData metaData, int column) throws SQLException {
//         String className = metaData.getColumnClassName(column);
//         try {
//             return Class.forName(className);
//         } catch (ClassNotFoundException e) {
//             throw new DatabaseException("Could not find class '" + className + "' specified by ResultSet.", e);
//         }
//     }
// }
// 
// Path: dalesbred/src/main/java/org/dalesbred/internal/jdbc/SqlUtils.java
// public final class SqlUtils {
// 
//     private SqlUtils() { }
// 
//     public static void freeArray(@NotNull Array array) throws SQLException {
//         try {
//             array.free();
//         } catch (SQLFeatureNotSupportedException ignored) {
//         }
//     }
// }
// 
// Path: dalesbred/src/main/java/org/dalesbred/internal/utils/TypeUtils.java
// public final class TypeUtils {
// 
//     private TypeUtils() { }
// 
//     public static @NotNull Class<?> rawType(@NotNull Type type) {
//         if (type instanceof Class<?>) {
//             return (Class<?>) type;
// 
//         } else if (type instanceof ParameterizedType) {
//             return rawType(((ParameterizedType) type).getRawType());
// 
//         } else if (type instanceof TypeVariable<?>) {
//             // We could return one of the bounds, but it won't work if there are multiple bounds.
//             // Therefore just return object.
//             return Object.class;
// 
//         } else if (type instanceof WildcardType) {
//             return rawType(((WildcardType) type).getUpperBounds()[0]);
// 
//         } else if (type instanceof GenericArrayType) {
//             return arrayType(rawType(((GenericArrayType) type).getGenericComponentType()));
// 
//         } else {
//             throw new IllegalArgumentException("unexpected type: " + type);
//         }
//     }
// 
//     public static @NotNull Type typeParameter(@NotNull Type type) {
//         if (type instanceof ParameterizedType)
//             return ((ParameterizedType) type).getActualTypeArguments()[0];
// 
//         return Object.class;
//     }
// 
//     public static boolean isEnum(@NotNull Type type) {
//         return (type instanceof Class<?>) && ((Class<?>) type).isEnum();
//     }
// 
//     public static boolean isPrimitive(@NotNull Type type) {
//         return (type instanceof Class<?>) && ((Class<?>) type).isPrimitive();
//     }
// 
//     public static @NotNull Class<?> arrayType(@NotNull Class<?> type) {
//         return Array.newInstance(type, 0).getClass();
//     }
// 
//     public static @Nullable Type genericSuperClass(@NotNull Type type) {
//         return rawType(type).getGenericSuperclass();
//     }
// 
//     public static @NotNull Type[] genericInterfaces(@NotNull Type type) {
//         return rawType(type).getGenericInterfaces();
//     }
// 
//     public static boolean isAssignable(@NotNull Type target, @NotNull Type source) {
//         // TODO: implement proper rules for generic types
//         return isAssignableByBoxing(rawType(target), rawType(source));
//     }
// 
//     private static boolean isAssignableByBoxing(@NotNull Class<?> target, @NotNull Class<?> source) {
//         return Primitives.wrap(target).isAssignableFrom(Primitives.wrap(source));
//     }
// }
// 
// Path: dalesbred/src/main/java/org/dalesbred/result/UnexpectedResultException.java
// public class UnexpectedResultException extends DatabaseException {
//     public UnexpectedResultException(@NotNull String message) {
//         super(message);
//     }
// }


// Path: dalesbred/src/main/java/org/dalesbred/internal/instantiation/SqlArrayConversion.java
import java.sql.Array;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import org.dalesbred.DatabaseSQLException;
import org.dalesbred.internal.jdbc.ResultSetUtils;
import org.dalesbred.internal.jdbc.SqlUtils;
import org.dalesbred.internal.utils.TypeUtils;
import org.dalesbred.result.UnexpectedResultException;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Type;

                NamedTypeList types = NamedTypeList.builder(1).add("value", ResultSetUtils.getColumnType(resultSet.getMetaData(), 2)).build();
                Instantiator<?> ctor = instantiatorRegistry.findInstantiator(elementType, types);
                ArrayList<Object> result = new ArrayList<>();

                // For performance reasons we reuse the same arguments-array and InstantiatorArguments-object for all rows.
                // This should be fine as long as the instantiators don't hang on to their arguments for too long.
                Object[] arguments = new Object[1];
                InstantiatorArguments instantiatorArguments = new InstantiatorArguments(types, arguments);

                while (resultSet.next()) {
                    arguments[0] = resultSet.getObject(2);

                    Object value = ctor.instantiate(instantiatorArguments);
                    if (value != null || allowNulls)
                        result.add(value);
                    else
                        throw new UnexpectedResultException("Expected " + elementType + ", but got null");
                }

                return result;

            } finally {
                try {
                    resultSet.close();
                } finally {
                    SqlUtils.freeArray(array);
                }
            }

        } catch (SQLException e) {
            throw new DatabaseSQLException(e);