io.vertx.pgclient.impl.PgSocketConnection Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of vertx-pg-client Show documentation
Show all versions of vertx-pg-client Show documentation
The Reactive PostgreSQL Client
/*
* Copyright (C) 2017 Julien Viet
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package io.vertx.pgclient.impl;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.DecoderException;
import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.Promise;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.impl.EventLoopContext;
import io.vertx.core.net.impl.NetSocketInternal;
import io.vertx.pgclient.PgException;
import io.vertx.pgclient.impl.codec.NoticeResponse;
import io.vertx.pgclient.impl.codec.PgCodec;
import io.vertx.pgclient.impl.codec.TxFailedEvent;
import io.vertx.sqlclient.impl.*;
import io.vertx.sqlclient.impl.command.*;
import io.vertx.sqlclient.spi.DatabaseMetadata;
import java.util.Map;
import java.util.function.Predicate;
/**
* @author Julien Viet
*/
public class PgSocketConnection extends SocketConnectionBase {
private PgCodec codec;
public int processId;
public int secretKey;
public PgDatabaseMetadata dbMetaData;
public PgSocketConnection(NetSocketInternal socket,
boolean cachePreparedStatements,
int preparedStatementCacheSize,
Predicate preparedStatementCacheSqlFilter,
int pipeliningLimit,
EventLoopContext context) {
super(socket, cachePreparedStatements, preparedStatementCacheSize, preparedStatementCacheSqlFilter, pipeliningLimit, context);
}
@Override
public void init() {
codec = new PgCodec();
ChannelPipeline pipeline = socket.channelHandlerContext().pipeline();
pipeline.addBefore("handler", "codec", codec);
super.init();
}
// TODO RETURN FUTURE ???
void sendStartupMessage(String username, String password, String database, Map properties, Promise completionHandler) {
InitCommand cmd = new InitCommand(this, username, password, database, properties);
schedule(context, cmd).onComplete(completionHandler);
}
void sendCancelRequestMessage(int processId, int secretKey, Handler> handler) {
Buffer buffer = Buffer.buffer(16);
buffer.appendInt(16);
// cancel request code
buffer.appendInt(80877102);
buffer.appendInt(processId);
buffer.appendInt(secretKey);
socket.write(buffer, ar -> {
if (ar.succeeded()) {
// directly close this connection
if (status == Status.CONNECTED) {
status = Status.CLOSING;
socket.close();
}
handler.handle(Future.succeededFuture());
} else {
handler.handle(Future.failedFuture(ar.cause()));
}
});
}
@Override
protected void handleMessage(Object msg) {
super.handleMessage(msg);
if (msg instanceof Notification || msg instanceof TxFailedEvent || msg instanceof NoticeResponse) {
handleEvent(msg);
}
}
@Override
protected void handleException(Throwable t) {
if (t instanceof PgException) {
reportException(t);
} else {
super.handleException(t);
}
}
@Override
public int getProcessId() {
return processId;
}
@Override
public int getSecretKey() {
return secretKey;
}
@Override
public DatabaseMetadata getDatabaseMetaData() {
return dbMetaData;
}
void upgradeToSSLConnection(Handler> completionHandler) {
ChannelPipeline pipeline = socket.channelHandlerContext().pipeline();
Promise upgradePromise = Promise.promise();
upgradePromise.future().onComplete(ar->{
if (ar.succeeded()) {
completionHandler.handle(Future.succeededFuture());
} else {
Throwable cause = ar.cause();
if (cause instanceof DecoderException) {
DecoderException err = (DecoderException) cause;
cause = err.getCause();
}
completionHandler.handle(Future.failedFuture(cause));
}
});
pipeline.addBefore("handler", "initiate-ssl-handler", new InitiateSslHandler(this, upgradePromise));
}
@Override
protected void doSchedule(CommandBase cmd, Handler> handler) {
if (cmd instanceof TxCommand) {
TxCommand tx = (TxCommand) cmd;
SimpleQueryCommand cmd2 = new SimpleQueryCommand<>(
tx.kind.sql,
false,
false,
QueryCommandBase.NULL_COLLECTOR,
QueryResultHandler.NOOP_HANDLER);
super.doSchedule(cmd2, ar -> handler.handle(ar.map(tx.result)));
} else {
super.doSchedule(cmd, handler);
}
}
@Override
public boolean isIndeterminatePreparedStatementError(Throwable error) {
if (error instanceof PgException) {
String code = ((PgException) error).getCode();
return "42P18".equals(code) || "42804".equals(code) || "42P08".equals(code);
}
return false;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy