// Path: src/main/java/com/pgasync/Connection.java
// public interface Connection extends QueryExecutor {
// 
//     CompletableFuture<PreparedStatement> prepareStatement(String sql, Oid... parametersTypes);
// 
//     /**
//      * The typical scenario of using notifications is as follows:
//      * - {@link #subscribe(String, Consumer)}
//      * - Some calls of @onNotification callback
//      * - {@link Listening#unlisten()}
//      *
//      * @param channel Channel name to listen to.
//      * @param onNotification Callback, thar is cinvoked every time notification arrives.
//      * @return CompletableFuture instance, completed when subscription will be registered at the backend.
//      */
//     CompletableFuture<Listening> subscribe(String channel, Consumer<String> onNotification);
// 
//     CompletableFuture<Void> close();
// }
// 
// Path: src/main/java/com/pgasync/NettyConnectibleBuilder.java
// public class NettyConnectibleBuilder {
// 
//     private final ConnectibleProperties properties = new ConnectibleProperties();
//     // TODO: refactor when Netty will support more advanced threading model
//     //new NioEventLoopGroup(0/*Netty defaults will be used*/, futuresExecutor),
//     private static final EventLoopGroup group = new NioEventLoopGroup();
// 
//     private ProtocolStream newProtocolStream(Executor futuresExecutor) {
//         return new NettyProtocolStream(
//                 group,
//                 new InetSocketAddress(properties.getHostname(), properties.getPort()),
//                 properties.getUseSsl(),
//                 Charset.forName(properties.getEncoding()),
//                 futuresExecutor
//         );
//     }
// 
//     /**
//      * @return Pool ready for use
//      */
//     public Connectible pool(Executor futuresExecutor) {
//         return new PgConnectionPool(properties, this::newProtocolStream, futuresExecutor);
//     }
// 
//     public Connectible pool() {
//         return pool(ForkJoinPool.commonPool());
//     }
// 
// 
//     /**
//      * @return Pool ready for use
//      */
//     public Connectible plain(Executor futuresExecutor) {
//         return new PgDatabase(properties, this::newProtocolStream, futuresExecutor);
//     }
// 
//     public Connectible plain() {
//         return plain(ForkJoinPool.commonPool());
//     }
// 
//     public NettyConnectibleBuilder hostname(String hostname) {
//         properties.hostname = hostname;
//         return this;
//     }
// 
//     public NettyConnectibleBuilder port(int port) {
//         properties.port = port;
//         return this;
//     }
// 
//     public NettyConnectibleBuilder username(String username) {
//         properties.username = username;
//         return this;
//     }
// 
//     public NettyConnectibleBuilder password(String password) {
//         properties.password = password;
//         return this;
//     }
// 
//     public NettyConnectibleBuilder database(String database) {
//         properties.database = database;
//         return this;
//     }
// 
//     public NettyConnectibleBuilder maxConnections(int maxConnections) {
//         properties.maxConnections = maxConnections;
//         return this;
//     }
// 
//     public NettyConnectibleBuilder maxStatements(int maxStatements) {
//         properties.maxStatements = maxStatements;
//         return this;
//     }
// 
//     public NettyConnectibleBuilder converters(Converter<?>... converters) {
//         Collections.addAll(properties.converters, converters);
//         return this;
//     }
// 
//     public NettyConnectibleBuilder dataConverter(DataConverter dataConverter) {
//         properties.dataConverter = dataConverter;
//         return this;
//     }
// 
//     public NettyConnectibleBuilder ssl(boolean ssl) {
//         properties.useSsl = ssl;
//         return this;
//     }
// 
//     public NettyConnectibleBuilder validationQuery(String validationQuery) {
//         properties.validationQuery = validationQuery;
//         return this;
//     }
// 
//     public NettyConnectibleBuilder encoding(String value) {
//         properties.encoding = value;
//         return this;
//     }
// 
//     /**
//      * Configuration for a connectible.
//      */
//     public static class ConnectibleProperties {
// 
//         String hostname = "localhost";
//         int port = 5432;
//         String username;
//         String password;
//         String database;
//         int maxConnections = 20;
//         int maxStatements = 20;
//         DataConverter dataConverter;
//         List<Converter<?>> converters = new ArrayList<>();
//         boolean useSsl;
//         String encoding = System.getProperty("pg.async.encoding", "utf-8");
//         String validationQuery;
// 
//         public String getHostname() {
//             return hostname;
//         }
// 
//         public int getPort() {
//             return port;
//         }
// 
//         public String getUsername() {
//             return username;
//         }
// 
//         public String getPassword() {
//             return password;
//         }
// 
//         public String getDatabase() {
//             return database;
//         }
// 
//         public int getMaxConnections() {
//             return maxConnections;
//         }
// 
//         public int getMaxStatements() {
//             return maxStatements;
//         }
// 
//         public boolean getUseSsl() {
//             return useSsl;
//         }
// 
//         public String getEncoding() {
//             return encoding;
//         }
// 
//         public DataConverter getDataConverter() {
//             return dataConverter != null ? dataConverter : new DataConverter(converters, Charset.forName(encoding));
//         }
// 
//         public String getValidationQuery() {
//             return validationQuery;
//         }
//     }
// }


import com.pgasync.Connection;
import com.pgasync.NettyConnectibleBuilder;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.Function;
package com.github.pgasync;



public class PgDatabase extends PgConnectible {

    public PgDatabase(NettyConnectibleBuilder.ConnectibleProperties properties, Function<Executor, ProtocolStream> toStream, Executor futuresExecutor) {
        super(properties, toStream, futuresExecutor);
    }

    @Override
// Path: src/main/java/com/pgasync/Connection.java
// public interface Connection extends QueryExecutor {
// 
//     CompletableFuture<PreparedStatement> prepareStatement(String sql, Oid... parametersTypes);
// 
//     /**
//      * The typical scenario of using notifications is as follows:
//      * - {@link #subscribe(String, Consumer)}
//      * - Some calls of @onNotification callback
//      * - {@link Listening#unlisten()}
//      *
//      * @param channel Channel name to listen to.
//      * @param onNotification Callback, thar is cinvoked every time notification arrives.
//      * @return CompletableFuture instance, completed when subscription will be registered at the backend.
//      */
//     CompletableFuture<Listening> subscribe(String channel, Consumer<String> onNotification);
// 
//     CompletableFuture<Void> close();
// }
// 
// Path: src/main/java/com/pgasync/NettyConnectibleBuilder.java
// public class NettyConnectibleBuilder {
// 
//     private final ConnectibleProperties properties = new ConnectibleProperties();
//     // TODO: refactor when Netty will support more advanced threading model
//     //new NioEventLoopGroup(0/*Netty defaults will be used*/, futuresExecutor),
//     private static final EventLoopGroup group = new NioEventLoopGroup();
// 
//     private ProtocolStream newProtocolStream(Executor futuresExecutor) {
//         return new NettyProtocolStream(
//                 group,
//                 new InetSocketAddress(properties.getHostname(), properties.getPort()),
//                 properties.getUseSsl(),
//                 Charset.forName(properties.getEncoding()),
//                 futuresExecutor
//         );
//     }
// 
//     /**
//      * @return Pool ready for use
//      */
//     public Connectible pool(Executor futuresExecutor) {
//         return new PgConnectionPool(properties, this::newProtocolStream, futuresExecutor);
//     }
// 
//     public Connectible pool() {
//         return pool(ForkJoinPool.commonPool());
//     }
// 
// 
//     /**
//      * @return Pool ready for use
//      */
//     public Connectible plain(Executor futuresExecutor) {
//         return new PgDatabase(properties, this::newProtocolStream, futuresExecutor);
//     }
// 
//     public Connectible plain() {
//         return plain(ForkJoinPool.commonPool());
//     }
// 
//     public NettyConnectibleBuilder hostname(String hostname) {
//         properties.hostname = hostname;
//         return this;
//     }
// 
//     public NettyConnectibleBuilder port(int port) {
//         properties.port = port;
//         return this;
//     }
// 
//     public NettyConnectibleBuilder username(String username) {
//         properties.username = username;
//         return this;
//     }
// 
//     public NettyConnectibleBuilder password(String password) {
//         properties.password = password;
//         return this;
//     }
// 
//     public NettyConnectibleBuilder database(String database) {
//         properties.database = database;
//         return this;
//     }
// 
//     public NettyConnectibleBuilder maxConnections(int maxConnections) {
//         properties.maxConnections = maxConnections;
//         return this;
//     }
// 
//     public NettyConnectibleBuilder maxStatements(int maxStatements) {
//         properties.maxStatements = maxStatements;
//         return this;
//     }
// 
//     public NettyConnectibleBuilder converters(Converter<?>... converters) {
//         Collections.addAll(properties.converters, converters);
//         return this;
//     }
// 
//     public NettyConnectibleBuilder dataConverter(DataConverter dataConverter) {
//         properties.dataConverter = dataConverter;
//         return this;
//     }
// 
//     public NettyConnectibleBuilder ssl(boolean ssl) {
//         properties.useSsl = ssl;
//         return this;
//     }
// 
//     public NettyConnectibleBuilder validationQuery(String validationQuery) {
//         properties.validationQuery = validationQuery;
//         return this;
//     }
// 
//     public NettyConnectibleBuilder encoding(String value) {
//         properties.encoding = value;
//         return this;
//     }
// 
//     /**
//      * Configuration for a connectible.
//      */
//     public static class ConnectibleProperties {
// 
//         String hostname = "localhost";
//         int port = 5432;
//         String username;
//         String password;
//         String database;
//         int maxConnections = 20;
//         int maxStatements = 20;
//         DataConverter dataConverter;
//         List<Converter<?>> converters = new ArrayList<>();
//         boolean useSsl;
//         String encoding = System.getProperty("pg.async.encoding", "utf-8");
//         String validationQuery;
// 
//         public String getHostname() {
//             return hostname;
//         }
// 
//         public int getPort() {
//             return port;
//         }
// 
//         public String getUsername() {
//             return username;
//         }
// 
//         public String getPassword() {
//             return password;
//         }
// 
//         public String getDatabase() {
//             return database;
//         }
// 
//         public int getMaxConnections() {
//             return maxConnections;
//         }
// 
//         public int getMaxStatements() {
//             return maxStatements;
//         }
// 
//         public boolean getUseSsl() {
//             return useSsl;
//         }
// 
//         public String getEncoding() {
//             return encoding;
//         }
// 
//         public DataConverter getDataConverter() {
//             return dataConverter != null ? dataConverter : new DataConverter(converters, Charset.forName(encoding));
//         }
// 
//         public String getValidationQuery() {
//             return validationQuery;
//         }
//     }
// }


// Path: src/main/java/com/github/pgasync/PgDatabase.java
import com.pgasync.Connection;
import com.pgasync.NettyConnectibleBuilder;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.Function;

package com.github.pgasync;



public class PgDatabase extends PgConnectible {

    public PgDatabase(NettyConnectibleBuilder.ConnectibleProperties properties, Function<Executor, ProtocolStream> toStream, Executor futuresExecutor) {
        super(properties, toStream, futuresExecutor);
    }

    @Override
    public CompletableFuture<Connection> getConnection() {