// Path: src/main/java/com/github/kokorin/jdbunit/table/Column.java
// public class Column {
//     private final String name;
//     private final Type type;
// 
//     public Column(String name, Type type) {
//         Objects.requireNonNull(name);
//         Objects.requireNonNull(type);
// 
//         if (name.isEmpty()) {
//             throw new IllegalArgumentException("Column name must be non empty");
//         }
// 
//         this.name = name;
//         this.type = type;
//     }
// 
//     public String getName() {
//         return name;
//     }
// 
//     public Type getType() {
//         return type;
//     }
// }
// 
// Path: src/main/java/com/github/kokorin/jdbunit/table/Row.java
// public class Row {
//     private final List<Object> values;
// 
//     public static final Object ANY_VALUE = new Object(){
//         @Override
//         public String toString() {
//             return "ANY_VALUE";
//         }
//     };
// 
//     public Row(List<Object> values) {
//         Objects.requireNonNull(values);
//         if (values.isEmpty()) {
//             throw new IllegalArgumentException("At least one value in a row is required");
//         }
// 
//         values = Collections.unmodifiableList(new ArrayList<>(values));
//         this.values = values;
//     }
// 
//     public List<Object> getValues() {
//         return values;
//     }
// 
//     public static class ValueCaptor {
//         private final String name;
// 
//         public ValueCaptor(String name) {
//             this.name = name;
//         }
// 
//         public String getName() {
//             return name;
//         }
// 
//         @Override
//         public String toString() {
//             return "Cap:" + name + ":";
//         }
//     }
// 
//     public static class ValueReference {
//         private final String name;
// 
//         public ValueReference(String name) {
//             this.name = name;
//         }
// 
//         public String getName() {
//             return name;
//         }
// 
//         @Override
//         public String toString() {
//             return "Ref=" + name + "=";
//         }
//     }
// }
// 
// Path: src/main/java/com/github/kokorin/jdbunit/table/Table.java
// public class Table {
//     private final String name;
//     private final List<Column> columns;
//     private final List<Row> rows;
// 
//     public Table(String name, List<Column> columns, List<Row> rows) {
//         Objects.requireNonNull(name);
//         Objects.requireNonNull(columns);
//         Objects.requireNonNull(rows);
// 
//         if (name.isEmpty()) {
//             throw new IllegalArgumentException("Table name must be non empty");
//         }
//         if (columns.isEmpty() && !rows.isEmpty()) {
//             throw new IllegalArgumentException("At least one column is required for non-empty table");
//         }
// 
//         for (Row row : rows) {
//             if (row.getValues().size() != columns.size()) {
//                 throw new IllegalArgumentException("Every row must have value for every column.");
//             }
//         }
// 
//         this.name = name;
//         this.columns = Collections.unmodifiableList(new ArrayList<>(columns));
//         this.rows = Collections.unmodifiableList(new ArrayList<>(rows));
//     }
// 
//     public String getName() {
//         return name;
//     }
// 
//     public List<Column> getColumns() {
//         return columns;
//     }
// 
//     public List<Row> getRows() {
//         return rows;
//     }
// }
// 
// Path: src/main/java/com/github/kokorin/jdbunit/table/Type.java
// public interface Type {
//     List<String> getAliases();
// 
//     Object parse(String string);
// 
//     void setParameter(PreparedStatement statement, int index, Object value) throws SQLException;
// 
//     Object getValue(ResultSet set, int index) throws SQLException;
// }
// 
// Path: src/main/java/com/github/kokorin/jdbunit/JdbUnitAssert.java
// public static void assertTableEquals(List<Table> expectedTables, List<Table> actualTables) {
//     assertNotNull("No expected table", expectedTables);
//     assertNotNull("No actual table", actualTables);
//     assertEquals(expectedTables.size(), actualTables.size());
// 
//     Map<String, Table> actualMap = new HashMap<>();
//     for (Table actual : actualTables) {
//         actualMap.put(actual.getName(), actual);
//     }
// 
//     Map<String, Object> variables = new HashMap<>();
//     for (Table expected : expectedTables) {
//         Table actual = actualMap.get(expected.getName());
//         assertNotNull("No table among actual: " + expected.getName(), actual);
//         assertColumnsEqual(expected.getColumns(), actual.getColumns());
//         assertContentsEqual(expected.getRows(), actual.getRows(), variables);
//     }
// }


import com.github.kokorin.jdbunit.table.Column;
import com.github.kokorin.jdbunit.table.Row;
import com.github.kokorin.jdbunit.table.Table;
import com.github.kokorin.jdbunit.table.Type;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;
import static com.github.kokorin.jdbunit.JdbUnitAssert.assertTableEquals;
            }
        }
    }

    List<Row> readRows(ResultSet set, List<Column> columns) throws SQLException {
        List<Row> result = new ArrayList<>();

        int count = columns.size();
        while (set.next()) {
            List<Object> values = new ArrayList<>(count);
            for (int i = 0; i < count; ++i) {
                Type type = columns.get(i).getType();
                Object value = type.getValue(set, i + 1);
                values.add(value);
            }
            result.add(new Row(values));
        }

        return result;
    }

    static List<Table> combineAll(List<Table> tables) {
        Map<String, Integer> index = new HashMap<>();
        List<Table> result = new ArrayList<>();

        for (Table table : tables) {
            Integer i = index.get(table.getName());
            if (i == null) {
                index.put(table.getName(), result.size());
                result.add(table);
// Path: src/main/java/com/github/kokorin/jdbunit/table/Column.java
// public class Column {
//     private final String name;
//     private final Type type;
// 
//     public Column(String name, Type type) {
//         Objects.requireNonNull(name);
//         Objects.requireNonNull(type);
// 
//         if (name.isEmpty()) {
//             throw new IllegalArgumentException("Column name must be non empty");
//         }
// 
//         this.name = name;
//         this.type = type;
//     }
// 
//     public String getName() {
//         return name;
//     }
// 
//     public Type getType() {
//         return type;
//     }
// }
// 
// Path: src/main/java/com/github/kokorin/jdbunit/table/Row.java
// public class Row {
//     private final List<Object> values;
// 
//     public static final Object ANY_VALUE = new Object(){
//         @Override
//         public String toString() {
//             return "ANY_VALUE";
//         }
//     };
// 
//     public Row(List<Object> values) {
//         Objects.requireNonNull(values);
//         if (values.isEmpty()) {
//             throw new IllegalArgumentException("At least one value in a row is required");
//         }
// 
//         values = Collections.unmodifiableList(new ArrayList<>(values));
//         this.values = values;
//     }
// 
//     public List<Object> getValues() {
//         return values;
//     }
// 
//     public static class ValueCaptor {
//         private final String name;
// 
//         public ValueCaptor(String name) {
//             this.name = name;
//         }
// 
//         public String getName() {
//             return name;
//         }
// 
//         @Override
//         public String toString() {
//             return "Cap:" + name + ":";
//         }
//     }
// 
//     public static class ValueReference {
//         private final String name;
// 
//         public ValueReference(String name) {
//             this.name = name;
//         }
// 
//         public String getName() {
//             return name;
//         }
// 
//         @Override
//         public String toString() {
//             return "Ref=" + name + "=";
//         }
//     }
// }
// 
// Path: src/main/java/com/github/kokorin/jdbunit/table/Table.java
// public class Table {
//     private final String name;
//     private final List<Column> columns;
//     private final List<Row> rows;
// 
//     public Table(String name, List<Column> columns, List<Row> rows) {
//         Objects.requireNonNull(name);
//         Objects.requireNonNull(columns);
//         Objects.requireNonNull(rows);
// 
//         if (name.isEmpty()) {
//             throw new IllegalArgumentException("Table name must be non empty");
//         }
//         if (columns.isEmpty() && !rows.isEmpty()) {
//             throw new IllegalArgumentException("At least one column is required for non-empty table");
//         }
// 
//         for (Row row : rows) {
//             if (row.getValues().size() != columns.size()) {
//                 throw new IllegalArgumentException("Every row must have value for every column.");
//             }
//         }
// 
//         this.name = name;
//         this.columns = Collections.unmodifiableList(new ArrayList<>(columns));
//         this.rows = Collections.unmodifiableList(new ArrayList<>(rows));
//     }
// 
//     public String getName() {
//         return name;
//     }
// 
//     public List<Column> getColumns() {
//         return columns;
//     }
// 
//     public List<Row> getRows() {
//         return rows;
//     }
// }
// 
// Path: src/main/java/com/github/kokorin/jdbunit/table/Type.java
// public interface Type {
//     List<String> getAliases();
// 
//     Object parse(String string);
// 
//     void setParameter(PreparedStatement statement, int index, Object value) throws SQLException;
// 
//     Object getValue(ResultSet set, int index) throws SQLException;
// }
// 
// Path: src/main/java/com/github/kokorin/jdbunit/JdbUnitAssert.java
// public static void assertTableEquals(List<Table> expectedTables, List<Table> actualTables) {
//     assertNotNull("No expected table", expectedTables);
//     assertNotNull("No actual table", actualTables);
//     assertEquals(expectedTables.size(), actualTables.size());
// 
//     Map<String, Table> actualMap = new HashMap<>();
//     for (Table actual : actualTables) {
//         actualMap.put(actual.getName(), actual);
//     }
// 
//     Map<String, Object> variables = new HashMap<>();
//     for (Table expected : expectedTables) {
//         Table actual = actualMap.get(expected.getName());
//         assertNotNull("No table among actual: " + expected.getName(), actual);
//         assertColumnsEqual(expected.getColumns(), actual.getColumns());
//         assertContentsEqual(expected.getRows(), actual.getRows(), variables);
//     }
// }


// Path: src/main/java/com/github/kokorin/jdbunit/operation/Verify.java
import com.github.kokorin.jdbunit.table.Column;
import com.github.kokorin.jdbunit.table.Row;
import com.github.kokorin.jdbunit.table.Table;
import com.github.kokorin.jdbunit.table.Type;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;
import static com.github.kokorin.jdbunit.JdbUnitAssert.assertTableEquals;

            }
        }
    }

    List<Row> readRows(ResultSet set, List<Column> columns) throws SQLException {
        List<Row> result = new ArrayList<>();

        int count = columns.size();
        while (set.next()) {
            List<Object> values = new ArrayList<>(count);
            for (int i = 0; i < count; ++i) {
                Type type = columns.get(i).getType();
                Object value = type.getValue(set, i + 1);
                values.add(value);
            }
            result.add(new Row(values));
        }

        return result;
    }

    static List<Table> combineAll(List<Table> tables) {
        Map<String, Integer> index = new HashMap<>();
        List<Table> result = new ArrayList<>();

        for (Table table : tables) {
            Integer i = index.get(table.getName());
            if (i == null) {
                index.put(table.getName(), result.size());
                result.add(table);
                continue;