public final class CallableResultSet1<T1> {

    private final List<Object> outs;
    private final Flowable<T1> results;

    public CallableResultSet1(List<Object> outs, Flowable<T1> results) {
        this.outs = outs;
        this.results = results;
    }

    public Flowable<T1> results() {
        return results;
    }

    public List<Object> outs() {
        return outs;
    }

} public final class CallableResultSet2<T1, T2> {

    private final List<Object> outs;
    private final Flowable<T1> results1;
    private final Flowable<T2> results2;

    public CallableResultSet2(List<Object> outs, Flowable<T1> results1, Flowable<T2> results2) {
        this.outs = outs;
        this.results1 = results1;
        this.results2 = results2;
    }

    public Flowable<T1> results1() {
        return results1;
    }

    public Flowable<T2> results2() {
        return results2;
    }

    public List<Object> outs() {
        return outs;
    }
} public final class CallableResultSet3<T1, T2, T3> {

    private final List<Object> outs;
    private final Flowable<T1> results1;
    private final Flowable<T2> results2;
    private final Flowable<T3> results3;

    public CallableResultSet3(List<Object> outs, Flowable<T1> query1, Flowable<T2> query2, Flowable<T3> query3) {
        this.outs = outs;
        this.results1 = query1;
        this.results2 = query2;
        this.results3 = query3;
    }

    public Flowable<T1> results1() {
        return results1;
    }

    public Flowable<T2> results2() {
        return results2;
    }

    public Flowable<T3> results3() {
        return results3;
    }

    public List<Object> outs() {
        return outs;
    }
} public final class CallableResultSet4<T1, T2, T3, T4> {

    private final List<Object> outs;
    private final Flowable<T1> results1;
    private final Flowable<T2> results2;
    private final Flowable<T3> results3;
    private final Flowable<T4> results4;

    public CallableResultSet4(List<Object> outs, Flowable<T1> query1, Flowable<T2> query2, Flowable<T3> query3,
            Flowable<T4> query4) {
        this.outs = outs;
        this.results1 = query1;
        this.results2 = query2;
        this.results3 = query3;
        this.results4 = query4;
    }

    public Flowable<T1> results1() {
        return results1;
    }

    public Flowable<T2> results2() {
        return results2;
    }

    public Flowable<T3> results3() {
        return results3;
    }

    public Flowable<T4> results4() {
        return results4;
    }

    public List<Object> outs() {
        return outs;
    }
} public final class CallableResultSetN {

    private final List<Object> outs;
    private final List<Flowable<?>> flowables;

    public CallableResultSetN(List<Object> outs, List<Flowable<?>> flowables) {
        this.outs = outs;
        this.flowables = flowables;
    }

    public List<Flowable<?>> results() {
        return flowables;
    }

    public Flowable<?> results(int index) {
        return flowables.get(index);
    }

    public List<Object> outs() {
        return outs;
    }
} public interface Getter1 {

    <T> CallableResultSets1Builder<T> get(Function<? super ResultSet, ? extends T> function);

    default <T> CallableResultSets1Builder<T> getAs(@Nonnull Class<T> cls) {
        Preconditions.checkNotNull(cls, "cls cannot be null");
        return get(rs -> Util.mapObject(rs, cls, 1));
    }

    default <T1, T2> CallableResultSets1Builder<Tuple2<T1, T2>> getAs(@Nonnull Class<T1> cls1,
            @Nonnull Class<T2> cls2) {
        return get(Tuples.tuple(cls1, cls2));
    }

    default <T1, T2, T3> CallableResultSets1Builder<Tuple3<T1, T2, T3>> getAs(@Nonnull Class<T1> cls1,
            @Nonnull Class<T2> cls2, @Nonnull Class<T3> cls3) {
        return get(Tuples.tuple(cls1, cls2, cls3));
    }

    default <T1, T2, T3, T4> CallableResultSets1Builder<Tuple4<T1, T2, T3, T4>> getAs(@Nonnull Class<T1> cls1,
            @Nonnull Class<T2> cls2, @Nonnull Class<T3> cls3, @Nonnull Class<T4> cls4) {
        return get(Tuples.tuple(cls1, cls2, cls3, cls4));
    }

    default <T1, T2, T3, T4, T5> CallableResultSets1Builder<Tuple5<T1, T2, T3, T4, T5>> getAs(@Nonnull Class<T1> cls1,
            @Nonnull Class<T2> cls2, @Nonnull Class<T3> cls3, @Nonnull Class<T4> cls4, @Nonnull Class<T5> cls5) {
        return get(Tuples.tuple(cls1, cls2, cls3, cls4, cls5));
    }

    default <T1, T2, T3, T4, T5, T6> CallableResultSets1Builder<Tuple6<T1, T2, T3, T4, T5, T6>> getAs(
            @Nonnull Class<T1> cls1, @Nonnull Class<T2> cls2, @Nonnull Class<T3> cls3, @Nonnull Class<T4> cls4,
            @Nonnull Class<T5> cls5, @Nonnull Class<T6> cls6) {
        return get(Tuples.tuple(cls1, cls2, cls3, cls4, cls5, cls6));
    }

    default <T1, T2, T3, T4, T5, T6, T7> CallableResultSets1Builder<Tuple7<T1, T2, T3, T4, T5, T6, T7>> getAs(
            @Nonnull Class<T1> cls1, @Nonnull Class<T2> cls2, @Nonnull Class<T3> cls3, @Nonnull Class<T4> cls4,
            @Nonnull Class<T5> cls5, @Nonnull Class<T6> cls6, @Nonnull Class<T7> cls7) {
        return get(Tuples.tuple(cls1, cls2, cls3, cls4, cls5, cls6, cls7));
    }

} public interface Getter2<T1> {

    <T2> CallableResultSets2Builder<T1, T2> get(Function<? super ResultSet, ? extends T2> function);

    default <T2> CallableResultSets2Builder<T1, T2> getAs(@Nonnull Class<T2> cls) {
        Preconditions.checkNotNull(cls, "cls cannot be null");
        return get(rs -> Util.mapObject(rs, cls, 1));
    }

    default <A, B> CallableResultSets2Builder<T1, Tuple2<A, B>> getAs(@Nonnull Class<A> cls1, @Nonnull Class<B> cls2) {
        return get(Tuples.tuple(cls1, cls2));
    }

    default <A, B, C> CallableResultSets2Builder<T1, Tuple3<A, B, C>> getAs(@Nonnull Class<A> cls1,
            @Nonnull Class<B> cls2, @Nonnull Class<C> cls3) {
        return get(Tuples.tuple(cls1, cls2, cls3));
    }

    default <A, B, C, D> CallableResultSets2Builder<T1, Tuple4<A, B, C, D>> getAs(@Nonnull Class<A> cls1,
            @Nonnull Class<B> cls2, @Nonnull Class<C> cls3, @Nonnull Class<D> cls4) {
        return get(Tuples.tuple(cls1, cls2, cls3, cls4));
    }

    default <A, B, C, D, E> CallableResultSets2Builder<T1, Tuple5<A, B, C, D, E>> getAs(@Nonnull Class<A> cls1,
            @Nonnull Class<B> cls2, @Nonnull Class<C> cls3, @Nonnull Class<D> cls4, @Nonnull Class<E> cls5) {
        return get(Tuples.tuple(cls1, cls2, cls3, cls4, cls5));
    }

    default <A, B, C, D, E, F> CallableResultSets2Builder<T1, Tuple6<A, B, C, D, E, F>> getAs(@Nonnull Class<A> cls1,
            @Nonnull Class<B> cls2, @Nonnull Class<C> cls3, @Nonnull Class<D> cls4, @Nonnull Class<E> cls5,
            @Nonnull Class<F> cls6) {
        return get(Tuples.tuple(cls1, cls2, cls3, cls4, cls5, cls6));
    }

    default <A, B, C, D, E, F, G> CallableResultSets2Builder<T1, Tuple7<A, B, C, D, E, F, G>> getAs(
            @Nonnull Class<A> cls1, @Nonnull Class<B> cls2, @Nonnull Class<C> cls3, @Nonnull Class<D> cls4,
            @Nonnull Class<E> cls5, @Nonnull Class<F> cls6, @Nonnull Class<G> cls7) {
        return get(Tuples.tuple(cls1, cls2, cls3, cls4, cls5, cls6, cls7));
    }

} public interface Getter3<T1, T2> {

    <T3> CallableResultSets3Builder<T1, T2, T3> get(Function<? super ResultSet, ? extends T3> function);

    default <T3> CallableResultSets3Builder<T1, T2, T3> getAs(@Nonnull Class<T3> cls) {
        Preconditions.checkNotNull(cls, "cls cannot be null");
        return get(rs -> Util.mapObject(rs, cls, 1));
    }

    default <A, B> CallableResultSets3Builder<T1, T2, Tuple2<A, B>> getAs(@Nonnull Class<A> cls1,
            @Nonnull Class<B> cls2) {
        return get(Tuples.tuple(cls1, cls2));
    }

    default <A, B, C> CallableResultSets3Builder<T1, T2, Tuple3<A, B, C>> getAs(@Nonnull Class<A> cls1,
            @Nonnull Class<B> cls2, @Nonnull Class<C> cls3) {
        return get(Tuples.tuple(cls1, cls2, cls3));
    }

    default <A, B, C, D> CallableResultSets3Builder<T1, T2, Tuple4<A, B, C, D>> getAs(@Nonnull Class<A> cls1,
            @Nonnull Class<B> cls2, @Nonnull Class<C> cls3, @Nonnull Class<D> cls4) {
        return get(Tuples.tuple(cls1, cls2, cls3, cls4));
    }

    default <A, B, C, D, E> CallableResultSets3Builder<T1, T2, Tuple5<A, B, C, D, E>> getAs(@Nonnull Class<A> cls1,
            @Nonnull Class<B> cls2, @Nonnull Class<C> cls3, @Nonnull Class<D> cls4, @Nonnull Class<E> cls5) {
        return get(Tuples.tuple(cls1, cls2, cls3, cls4, cls5));
    }

    default <A, B, C, D, E, F> CallableResultSets3Builder<T1, T2, Tuple6<A, B, C, D, E, F>> getAs(
            @Nonnull Class<A> cls1, @Nonnull Class<B> cls2, @Nonnull Class<C> cls3, @Nonnull Class<D> cls4,
            @Nonnull Class<E> cls5, @Nonnull Class<F> cls6) {
        return get(Tuples.tuple(cls1, cls2, cls3, cls4, cls5, cls6));
    }

    default <A, B, C, D, E, F, G> CallableResultSets3Builder<T1, T2, Tuple7<A, B, C, D, E, F, G>> getAs(
            @Nonnull Class<A> cls1, @Nonnull Class<B> cls2, @Nonnull Class<C> cls3, @Nonnull Class<D> cls4,
            @Nonnull Class<E> cls5, @Nonnull Class<F> cls6, @Nonnull Class<G> cls7) {
        return get(Tuples.tuple(cls1, cls2, cls3, cls4, cls5, cls6, cls7));
    }

} public interface Getter4<T1, T2, T3> {

    <T4> CallableResultSets4Builder<T1, T2, T3, T4> get(Function<? super ResultSet, ? extends T4> function);

    default <T4> CallableResultSets4Builder<T1, T2, T3, T4> getAs(@Nonnull Class<T4> cls) {
        Preconditions.checkNotNull(cls, "cls cannot be null");
        return get(rs -> Util.mapObject(rs, cls, 1));
    }

    default <A, B> CallableResultSets4Builder<T1, T2, T3, Tuple2<A, B>> getAs(@Nonnull Class<A> cls1,
            @Nonnull Class<B> cls2) {
        return get(Tuples.tuple(cls1, cls2));
    }

    default <A, B, C> CallableResultSets4Builder<T1, T2, T3, Tuple3<A, B, C>> getAs(@Nonnull Class<A> cls1,
            @Nonnull Class<B> cls2, @Nonnull Class<C> cls3) {
        return get(Tuples.tuple(cls1, cls2, cls3));
    }

    default <A, B, C, D> CallableResultSets4Builder<T1, T2, T3, Tuple4<A, B, C, D>> getAs(@Nonnull Class<A> cls1,
            @Nonnull Class<B> cls2, @Nonnull Class<C> cls3, @Nonnull Class<D> cls4) {
        return get(Tuples.tuple(cls1, cls2, cls3, cls4));
    }

    default <A, B, C, D, E> CallableResultSets4Builder<T1, T2, T3, Tuple5<A, B, C, D, E>> getAs(@Nonnull Class<A> cls1,
            @Nonnull Class<B> cls2, @Nonnull Class<C> cls3, @Nonnull Class<D> cls4, @Nonnull Class<E> cls5) {
        return get(Tuples.tuple(cls1, cls2, cls3, cls4, cls5));
    }

    default <A, B, C, D, E, F> CallableResultSets4Builder<T1, T2, T3, Tuple6<A, B, C, D, E, F>> getAs(
            @Nonnull Class<A> cls1, @Nonnull Class<B> cls2, @Nonnull Class<C> cls3, @Nonnull Class<D> cls4,
            @Nonnull Class<E> cls5, @Nonnull Class<F> cls6) {
        return get(Tuples.tuple(cls1, cls2, cls3, cls4, cls5, cls6));
    }

    default <A, B, C, D, E, F, G> CallableResultSets4Builder<T1, T2, T3, Tuple7<A, B, C, D, E, F, G>> getAs(
            @Nonnull Class<A> cls1, @Nonnull Class<B> cls2, @Nonnull Class<C> cls3, @Nonnull Class<D> cls4,
            @Nonnull Class<E> cls5, @Nonnull Class<F> cls6, @Nonnull Class<G> cls7) {
        return get(Tuples.tuple(cls1, cls2, cls3, cls4, cls5, cls6, cls7));
    }

} public interface GetterN {

    CallableResultSetsNBuilder get(Function<? super ResultSet, ?> function);

    default <T> CallableResultSetsNBuilder getAs(@Nonnull Class<T> cls) {
        Preconditions.checkNotNull(cls, "cls cannot be null");
        return get(rs -> Util.mapObject(rs, cls, 1));
    }

    default <T1, T2> CallableResultSetsNBuilder getAs(@Nonnull Class<T1> cls1,
            @Nonnull Class<T2> cls2) {
        return get(Tuples.tuple(cls1, cls2));
    }

    default <T1, T2, T3> CallableResultSetsNBuilder getAs(@Nonnull Class<T1> cls1,
            @Nonnull Class<T2> cls2, @Nonnull Class<T3> cls3) {
        return get(Tuples.tuple(cls1, cls2, cls3));
    }

    default <T1, T2, T3, T4> CallableResultSetsNBuilder getAs(@Nonnull Class<T1> cls1,
            @Nonnull Class<T2> cls2, @Nonnull Class<T3> cls3, @Nonnull Class<T4> cls4) {
        return get(Tuples.tuple(cls1, cls2, cls3, cls4));
    }

    default <T1, T2, T3, T4, T5> CallableResultSetsNBuilder getAs(@Nonnull Class<T1> cls1,
            @Nonnull Class<T2> cls2, @Nonnull Class<T3> cls3, @Nonnull Class<T4> cls4, @Nonnull Class<T5> cls5) {
        return get(Tuples.tuple(cls1, cls2, cls3, cls4, cls5));
    }

    default <T1, T2, T3, T4, T5, T6> CallableResultSetsNBuilder getAs(
            @Nonnull Class<T1> cls1, @Nonnull Class<T2> cls2, @Nonnull Class<T3> cls3, @Nonnull Class<T4> cls4,
            @Nonnull Class<T5> cls5, @Nonnull Class<T6> cls6) {
        return get(Tuples.tuple(cls1, cls2, cls3, cls4, cls5, cls6));
    }

    default <T1, T2, T3, T4, T5, T6, T7> CallableResultSetsNBuilder getAs(
            @Nonnull Class<T1> cls1, @Nonnull Class<T2> cls2, @Nonnull Class<T3> cls3, @Nonnull Class<T4> cls4,
            @Nonnull Class<T5> cls5, @Nonnull Class<T6> cls6, @Nonnull Class<T7> cls7) {
        return get(Tuples.tuple(cls1, cls2, cls3, cls4, cls5, cls6, cls7));
    }
} public final class In implements InParameterPlaceholder {

    // singleton instance of In
    public static final In IN = new In();
} public final class InOut implements InParameterPlaceholder, OutParameterPlaceholder {
    final Type type;
    final Class<?> cls;

    public InOut(Type type, Class<?> cls) {
        this.type = type;
        this.cls = cls;
    }

    @Override
    public Type type() {
        return type;
    }
} public interface InParameterPlaceholder extends ParameterPlaceholder {
} public final class Out implements OutParameterPlaceholder {
    final Type type;
    final Class<?> cls;

    public Out(Type type, Class<?> cls) {
        this.type = type;
        this.cls = cls;
    }

    @Override
    public Type type() {
        return type;
    }
} public interface ParameterPlaceholder {
} public class Tuple2<T1, T2> {

    private final T1 value1;
    private final T2 value2;

    /**
     * Constructor.
     * 
     * @param value1
     *            first element
     * @param value2
     *            second element
     */
    public Tuple2(T1 value1, T2 value2) {
        this.value1 = value1;
        this.value2 = value2;
    }

    /**
     * Returns a new instance.
     * 
     * @param r
     *            first element
     * @param s
     *            second element 
     * @param <R> type of first element
     * @param <S>
     *            type of second element
     * 
     * @return tuple
     */
    public static <R, S> Tuple2<R, S> create(R r, S s) {
        return new Tuple2<R, S>(r, s);
    }

    /**
     * Returns the first element of the tuple.
     * 
     * @return first element
     */
    public T1 value1() {
        return value1;
    }

    /**
     * Returns the first element of the tuple.
     * 
     * @return first element
     */
    public T1 _1() {
        return value1;
    }

    /**
     * Returns the 2nd element of the tuple.
     * 
     * @return second element
     */
    public T2 value2() {
        return value2;
    }

    /**
     * Returns the 2nd element of the tuple.
     * 
     * @return second element
     */
    public T2 _2() {
        return value2;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((value1 == null) ? 0 : value1.hashCode());
        result = prime * result + ((value2 == null) ? 0 : value2.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Tuple2<?, ?> other = (Tuple2<?, ?>) obj;
        if (value1 == null) {
            if (other.value1 != null)
                return false;
        } else if (!value1.equals(other.value1))
            return false;
        if (value2 == null) {
            if (other.value2 != null)
                return false;
        } else if (!value2.equals(other.value2))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "Tuple2 [value1=" + value1 + ", value2=" + value2 + "]";
    }

} public class Tuple3<T1, T2, T3> {

    private final T1 value1;
    private final T2 value2;
    private final T3 value3;

    /**
     * Constructor.
     * 
     * @param value1 first element 
     * @param value2 second element
     * @param value3 third element
     */
    public Tuple3(T1 value1, T2 value2, T3 value3) {
        this.value1 = value1;
        this.value2 = value2;
        this.value3 = value3;
    }
    
    public static <T1,T2,T3> Tuple3<T1,T2,T3> create(T1 value1, T2 value2, T3 value3) {
        return new Tuple3<T1,T2,T3>(value1, value2, value3);
    }

    public T1 value1() {
        return value1;
    }

    public T2 value2() {
        return value2;
    }

    public T3 value3() {
        return value3;
    }

    public T1 _1() {
        return value1;
    }

    public T2 _2() {
        return value2;
    }

    public T3 _3() {
        return value3;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((value1 == null) ? 0 : value1.hashCode());
        result = prime * result + ((value2 == null) ? 0 : value2.hashCode());
        result = prime * result + ((value3 == null) ? 0 : value3.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Tuple3<?, ?, ?> other = (Tuple3<?, ?, ?>) obj;
        if (value1 == null) {
            if (other.value1 != null)
                return false;
        } else if (!value1.equals(other.value1))
            return false;
        if (value2 == null) {
            if (other.value2 != null)
                return false;
        } else if (!value2.equals(other.value2))
            return false;
        if (value3 == null) {
            if (other.value3 != null)
                return false;
        } else if (!value3.equals(other.value3))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "Tuple3 [value1=" + value1 + ", value2=" + value2 + ", value3=" + value3 + "]";
    }

} public class Tuple4<T1, T2, T3, T4> {

    private final T1 value1;
    private final T2 value2;
    private final T3 value3;
    private final T4 value4;

    /**
     * Constructor.
     * 
     * @param value1 first element
     * @param value2 second element
     * @param value3 third element
     * @param value4 fourth element
     */
    public Tuple4(T1 value1, T2 value2, T3 value3, T4 value4) {
        this.value1 = value1;
        this.value2 = value2;
        this.value3 = value3;
        this.value4 = value4;
    }

    public static <T1, T2, T3, T4> Tuple4<T1, T2, T3, T4> create(T1 value1, T2 value2, T3 value3, T4 value4) {
        return new Tuple4<T1, T2, T3, T4>(value1, value2, value3, value4);
    }

    public T1 value1() {
        return value1;
    }

    public T2 value2() {
        return value2;
    }

    public T3 value3() {
        return value3;
    }

    public T4 value4() {
        return value4;
    }

    public T1 _1() {
        return value1;
    }

    public T2 _2() {
        return value2;
    }

    public T3 _3() {
        return value3;
    }

    public T4 _4() {
        return value4;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((value1 == null) ? 0 : value1.hashCode());
        result = prime * result + ((value2 == null) ? 0 : value2.hashCode());
        result = prime * result + ((value3 == null) ? 0 : value3.hashCode());
        result = prime * result + ((value4 == null) ? 0 : value4.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Tuple4<?, ?, ?, ?> other = (Tuple4<?, ?, ?, ?>) obj;
        if (value1 == null) {
            if (other.value1 != null)
                return false;
        } else if (!value1.equals(other.value1))
            return false;
        if (value2 == null) {
            if (other.value2 != null)
                return false;
        } else if (!value2.equals(other.value2))
            return false;
        if (value3 == null) {
            if (other.value3 != null)
                return false;
        } else if (!value3.equals(other.value3))
            return false;
        if (value4 == null) {
            if (other.value4 != null)
                return false;
        } else if (!value4.equals(other.value4))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "Tuple4 [value1=" + value1 + ", value2=" + value2 + ", value3=" + value3 + ", value4=" + value4 + "]";
    }

} public class TupleN<T> {

    private final List<T> list;

    /**
     * Constructor.
     * 
     * @param list
     *            values of the elements in the tuple
     */
    public TupleN(List<T> list) {
        this.list = list;
    }

    @SafeVarargs
    public static <T> TupleN<T> create(T... array) {
        return new TupleN<T>(Arrays.asList(array));
    }

    public List<T> values() {
        // defensive copy
        return new ArrayList<T>(list);
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((list == null) ? 0 : list.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        TupleN<?> other = (TupleN<?>) obj;
        if (list == null) {
            if (other.list != null)
                return false;
        } else if (!list.equals(other.list))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "TupleN [values=" + list + "]";
    }

}
import java.sql.Connection;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.davidmoten.rx.jdbc.callable.CallableResultSet1;
import org.davidmoten.rx.jdbc.callable.CallableResultSet2;
import org.davidmoten.rx.jdbc.callable.CallableResultSet3;
import org.davidmoten.rx.jdbc.callable.CallableResultSet4;
import org.davidmoten.rx.jdbc.callable.CallableResultSetN;
import org.davidmoten.rx.jdbc.callable.internal.Getter1;
import org.davidmoten.rx.jdbc.callable.internal.Getter2;
import org.davidmoten.rx.jdbc.callable.internal.Getter3;
import org.davidmoten.rx.jdbc.callable.internal.Getter4;
import org.davidmoten.rx.jdbc.callable.internal.GetterN;
import org.davidmoten.rx.jdbc.callable.internal.In;
import org.davidmoten.rx.jdbc.callable.internal.InOut;
import org.davidmoten.rx.jdbc.callable.internal.InParameterPlaceholder;
import org.davidmoten.rx.jdbc.callable.internal.Out;
import org.davidmoten.rx.jdbc.callable.internal.ParameterPlaceholder;
import org.davidmoten.rx.jdbc.tuple.Tuple2;
import org.davidmoten.rx.jdbc.tuple.Tuple3;
import org.davidmoten.rx.jdbc.tuple.Tuple4;
import org.davidmoten.rx.jdbc.tuple.TupleN;
import com.github.davidmoten.guavamini.Lists;
import com.github.davidmoten.guavamini.Preconditions;
import io.reactivex.Completable;
import io.reactivex.Flowable;
import io.reactivex.Single;
import io.reactivex.functions.Function;
        private Flowable<Tuple4<T1, T2, T3, T4>> build() {
            return Call
                    .createWithFourOutParameters(b.connection, b.sql, b.parameterGroups(), b.params, cls1, cls2, cls3,
                            cls4) //
                    .dematerialize();
        }
    }

    public static final class CallableBuilderN implements Getter1 {

        private final CallableBuilder b;
        private final List<Class<?>> outClasses;

        public CallableBuilderN(CallableBuilder b, List<Class<?>> outClasses) {
            this.b = b;
            this.outClasses = outClasses;
        }

        public Flowable<TupleN<Object>> input(Flowable<?> f) {
            b.input(f);
            return build();
        }

        public CallableBuilderN in() {
            b.in();
            return this;
        }

        public Flowable<TupleN<Object>> input(Object... objects) {
            return input(Flowable.fromArray(objects));
        }

        public CallableBuilderN out(Type type, Class<?> cls) {
            b.out(type, cls);
            return new CallableBuilderN(b, createList(outClasses, cls));
        }

        @Override
        public <T> CallableResultSets1Builder<T> get(Function<? super ResultSet, ? extends T> function) {
            return new CallableResultSets1Builder<T>(b, function);
        }

        public <T> CallableResultSets1Builder<T> autoMap(Class<T> cls) {
            return get(Util.autoMap(cls));
        }

        private Flowable<TupleN<Object>> build() {
            return Call.createWithNParameters(b.connection, b.sql, b.parameterGroups(), b.params, outClasses) //
                    .dematerialize();
        }

    }

    public static final class CallableResultSets1Builder<T1> implements Getter2<T1> {

        private final CallableBuilder b;
        private final Function<? super ResultSet, ? extends T1> f1;

        CallableResultSets1Builder(CallableBuilder b, Function<? super ResultSet, ? extends T1> function) {
            this.b = b;
            this.f1 = function;
        }

        public CallableResultSets1Builder<T1> out(Type type, Class<?> cls5) {
            b.out(type, cls5);
            return this;
        }

        public <T2> CallableResultSets2Builder<T1, T2> autoMap(Class<T2> cls) {
            return get(Util.autoMap(cls));
        }

        public <T2> CallableResultSets2Builder<T1, T2> get(Function<? super ResultSet, ? extends T2> f2) {
            return new CallableResultSets2Builder<T1, T2>(b, f1, f2);
        }

        public Flowable<CallableResultSet1<T1>> input(Flowable<?> f) {
            b.input(f);
            return build();
        }

        public CallableResultSets1Builder<T1> in() {
            b.in();
            return this;
        }

        public Flowable<CallableResultSet1<T1>> input(Object... objects) {
            return input(Flowable.fromArray(objects));
        }

        public CallableResultSets1Builder<T1> inOut(Type type, Class<?> cls) {
            b.inOut(type, cls);
            return this;
        }

        private Flowable<CallableResultSet1<T1>> build() {
            return Call.createWithOneResultSet(b.connection, b.sql, b.parameterGroups(), b.params, f1, 0) //
                    .dematerialize();
        }

    }

    public static final class CallableResultSets2Builder<T1, T2> implements Getter3<T1, T2> {

        private final CallableBuilder b;
        private final Function<? super ResultSet, ? extends T1> f1;
        private final Function<? super ResultSet, ? extends T2> f2;

        CallableResultSets2Builder(CallableBuilder b, Function<? super ResultSet, ? extends T1> f1,
                Function<? super ResultSet, ? extends T2> f2) {
            this.b = b;
            this.f1 = f1;
            this.f2 = f2;
        }

        public CallableResultSets2Builder<T1, T2> out(Type type, Class<?> cls5) {
            b.out(type, cls5);
            return this;
        }

        public Flowable<CallableResultSet2<T1, T2>> input(Flowable<?> f) {