// Path: dalesbred/src/main/java/org/dalesbred/DatabaseException.java
// public class DatabaseException extends RuntimeException {
// 
//     private final @Nullable SqlQuery query = DebugContext.getCurrentQuery();
// 
//     public DatabaseException(@NotNull String message) {
//         super(message);
//     }
// 
//     public DatabaseException(@NotNull Throwable cause) {
//         super(cause);
//     }
//     
//     public DatabaseException(@NotNull String message, @NotNull Throwable cause) {
//         super(message, cause);
//     }
// 
//     /**
//      * If this exception was thrown during an execution of a query, returns the query. Otherwise
//      * returns {@code null}.
//      */
//     public @Nullable SqlQuery getQuery() {
//         return query;
//     }
// 
//     @Override
//     public @NotNull String toString() {
//         String basicToString = super.toString();
//         if (query != null)
//             return basicToString + " (query: " + query + ')';
//         else
//             return basicToString;
//     }
// }
// 
// Path: dalesbred/src/main/java/org/dalesbred/internal/instantiation/NamedTypeList.java
// public final class NamedTypeList {
// 
//     private final @NotNull List<String> names;
// 
//     private final @NotNull List<Type> types;
// 
//     private NamedTypeList(@NotNull List<String> names, @NotNull List<Type> types) {
//         assert names.size() == types.size();
//         this.names = unmodifiableList(names);
//         this.types = types;
//     }
// 
//     public int size() {
//         return types.size();
//     }
// 
//     public @NotNull String getName(int index) {
//         return names.get(index);
//     }
// 
//     public @NotNull Type getType(int index) {
//         return types.get(index);
//     }
// 
//     public @NotNull List<String> getNames() {
//         return names;
//     }
// 
//     public @NotNull NamedTypeList subList(int fromIndex, int toIndex) {
//         return new NamedTypeList(names.subList(fromIndex, toIndex), types.subList(fromIndex, toIndex));
//     }
// 
//     @Override
//     public @NotNull String toString() {
//         int size = types.size();
// 
//         @SuppressWarnings("MagicNumber")
//         StringBuilder sb = new StringBuilder(10 + size * 30);
// 
//         sb.append('[');
// 
//         for (int i = 0; i < size; i++) {
//             if (i != 0) sb.append(", ");
// 
//             sb.append(names.get(i)).append(": ").append(types.get(i).getTypeName());
//         }
// 
//         sb.append(']');
// 
//         return sb.toString();
//     }
// 
//     public static @NotNull Builder builder(int size) {
//         return new Builder(size);
//     }
// 
//     /**
//      * Builder for {@link NamedTypeList}s.
//      */
//     public static class Builder {
// 
//         private boolean built = false;
// 
//         private final @NotNull List<String> names;
// 
//         private final @NotNull List<Type> types;
// 
//         private Builder(int size) {
//             this.names = new ArrayList<>(size);
//             this.types = new ArrayList<>(size);
//         }
// 
//         public Builder add(@NotNull String name, @NotNull Type type) {
//             if (built) throw new IllegalStateException("can't add items to builder that has been built");
// 
//             names.add(requireNonNull(name));
//             types.add(requireNonNull(type));
//             return this;
//         }
// 
//         public @NotNull NamedTypeList build() {
//             built = true;
//             return new NamedTypeList(names, types);
//         }
//     }
// }


import org.dalesbred.DatabaseException;
import org.dalesbred.internal.instantiation.NamedTypeList;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Type;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
/*
 * Copyright (c) 2017 Evident Solutions Oy
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package org.dalesbred.internal.jdbc;



/**
 * Utilities for processing {@link java.sql.ResultSet}s.
 */
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) {
// Path: dalesbred/src/main/java/org/dalesbred/DatabaseException.java
// public class DatabaseException extends RuntimeException {
// 
//     private final @Nullable SqlQuery query = DebugContext.getCurrentQuery();
// 
//     public DatabaseException(@NotNull String message) {
//         super(message);
//     }
// 
//     public DatabaseException(@NotNull Throwable cause) {
//         super(cause);
//     }
//     
//     public DatabaseException(@NotNull String message, @NotNull Throwable cause) {
//         super(message, cause);
//     }
// 
//     /**
//      * If this exception was thrown during an execution of a query, returns the query. Otherwise
//      * returns {@code null}.
//      */
//     public @Nullable SqlQuery getQuery() {
//         return query;
//     }
// 
//     @Override
//     public @NotNull String toString() {
//         String basicToString = super.toString();
//         if (query != null)
//             return basicToString + " (query: " + query + ')';
//         else
//             return basicToString;
//     }
// }
// 
// Path: dalesbred/src/main/java/org/dalesbred/internal/instantiation/NamedTypeList.java
// public final class NamedTypeList {
// 
//     private final @NotNull List<String> names;
// 
//     private final @NotNull List<Type> types;
// 
//     private NamedTypeList(@NotNull List<String> names, @NotNull List<Type> types) {
//         assert names.size() == types.size();
//         this.names = unmodifiableList(names);
//         this.types = types;
//     }
// 
//     public int size() {
//         return types.size();
//     }
// 
//     public @NotNull String getName(int index) {
//         return names.get(index);
//     }
// 
//     public @NotNull Type getType(int index) {
//         return types.get(index);
//     }
// 
//     public @NotNull List<String> getNames() {
//         return names;
//     }
// 
//     public @NotNull NamedTypeList subList(int fromIndex, int toIndex) {
//         return new NamedTypeList(names.subList(fromIndex, toIndex), types.subList(fromIndex, toIndex));
//     }
// 
//     @Override
//     public @NotNull String toString() {
//         int size = types.size();
// 
//         @SuppressWarnings("MagicNumber")
//         StringBuilder sb = new StringBuilder(10 + size * 30);
// 
//         sb.append('[');
// 
//         for (int i = 0; i < size; i++) {
//             if (i != 0) sb.append(", ");
// 
//             sb.append(names.get(i)).append(": ").append(types.get(i).getTypeName());
//         }
// 
//         sb.append(']');
// 
//         return sb.toString();
//     }
// 
//     public static @NotNull Builder builder(int size) {
//         return new Builder(size);
//     }
// 
//     /**
//      * Builder for {@link NamedTypeList}s.
//      */
//     public static class Builder {
// 
//         private boolean built = false;
// 
//         private final @NotNull List<String> names;
// 
//         private final @NotNull List<Type> types;
// 
//         private Builder(int size) {
//             this.names = new ArrayList<>(size);
//             this.types = new ArrayList<>(size);
//         }
// 
//         public Builder add(@NotNull String name, @NotNull Type type) {
//             if (built) throw new IllegalStateException("can't add items to builder that has been built");
// 
//             names.add(requireNonNull(name));
//             types.add(requireNonNull(type));
//             return this;
//         }
// 
//         public @NotNull NamedTypeList build() {
//             built = true;
//             return new NamedTypeList(names, types);
//         }
//     }
// }


// Path: dalesbred/src/main/java/org/dalesbred/internal/jdbc/ResultSetUtils.java
import org.dalesbred.DatabaseException;
import org.dalesbred.internal.instantiation.NamedTypeList;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Type;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;

/*
 * Copyright (c) 2017 Evident Solutions Oy
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package org.dalesbred.internal.jdbc;



/**
 * Utilities for processing {@link java.sql.ResultSet}s.
 */
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);