io.vertx.mssqlclient.impl.codec.ExtendedQueryCommandBaseCodec Maven / Gradle / Ivy
/*
* Copyright (c) 2011-2022 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*/
package io.vertx.mssqlclient.impl.codec;
import io.netty.buffer.ByteBuf;
import io.vertx.sqlclient.data.NullValue;
import io.vertx.sqlclient.impl.TupleInternal;
import io.vertx.sqlclient.impl.command.ExtendedQueryCommand;
import static io.vertx.mssqlclient.impl.codec.DataType.*;
import static io.vertx.mssqlclient.impl.codec.MessageType.RPC;
abstract class ExtendedQueryCommandBaseCodec extends QueryCommandBaseCodec> {
final MSSQLPreparedStatement ps;
ExtendedQueryCommandBaseCodec(TdsMessageCodec tdsMessageCodec, ExtendedQueryCommand cmd) {
super(tdsMessageCodec, cmd);
ps = (MSSQLPreparedStatement) this.cmd.preparedStatement();
}
public static MSSQLCommandCodec, ?> create(TdsMessageCodec tdsMessageCodec, ExtendedQueryCommand queryCmd) {
if (queryCmd.isBatch()) {
return new ExtendedBatchQueryCommandCodec<>(tdsMessageCodec, queryCmd);
} else if (queryCmd.cursorId() != null) {
return new ExtendedCursorQueryCommandCodec<>(tdsMessageCodec, queryCmd);
} else {
return new ExtendedQueryCommandCodec<>(tdsMessageCodec, queryCmd);
}
}
@Override
void encode() {
if (ps.handle > 0) {
sendExecRequest();
} else {
sendPrepexecRequest();
}
}
@Override
protected void handleDone(short tokenType) {
if (tokenType == TokenType.DONEPROC) {
handleResultSetDone();
}
}
@Override
protected void handleResultSetDone() {
super.handleResultSetDone();
rowCount = 0;
}
@Override
protected void handleReturnValue(ByteBuf payload) {
short paramNameLength = payload.getUnsignedByte(payload.readerIndex() + 2);
payload.skipBytes(12 + 2 * paramNameLength);
Number value = (Number) INTN.decodeValue(payload, null);
if (ps.handle == 0 && value != null) {
ps.handle = value.intValue();
}
}
private void sendPrepexecRequest() {
ByteBuf content = tdsMessageCodec.alloc().ioBuffer();
tdsMessageCodec.encoder().encodeHeaders(content);
// RPCReqBatch
content.writeShortLE(0xFFFF);
content.writeShortLE(ProcId.Sp_PrepExec);
// Option flags
content.writeShortLE(0x0000);
// Parameter
// OUT Parameter
INTN.encodeParam(content, null, true, ps.handle);
TupleInternal params = prepexecRequestParams();
// Param definitions
String paramDefinitions = parseParamDefinitions(params);
NVARCHAR.encodeParam(content, null, false, paramDefinitions);
// SQL text
NVARCHAR.encodeParam(content, null, false, cmd.sql());
// Param values
encodeParams(content, params);
tdsMessageCodec.encoder().writeTdsMessage(RPC, content);
}
protected abstract TupleInternal prepexecRequestParams();
void sendExecRequest() {
ByteBuf content = tdsMessageCodec.alloc().ioBuffer();
tdsMessageCodec.encoder().encodeHeaders(content);
writeRpcRequestBatch(content);
tdsMessageCodec.encoder().writeTdsMessage(RPC, content);
}
protected void writeRpcRequestBatch(ByteBuf packet) {
// RPCReqBatch
packet.writeShortLE(0xFFFF);
packet.writeShortLE(ProcId.Sp_Execute);
// Option flags
packet.writeShortLE(0x0000);
// Parameter
// OUT Parameter
INTN.encodeParam(packet, null, true, ps.handle);
// Param values
encodeParams(packet, execRequestParams());
}
protected abstract TupleInternal execRequestParams();
protected String parseParamDefinitions(TupleInternal params) {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < params.size(); i++) {
if (i > 0) {
stringBuilder.append(",");
}
stringBuilder.append("@P").append(i + 1).append(" ");
Object param = params.getValueInternal(i);
if (param == null) {
stringBuilder.append(NULL.paramDefinition(null));
} else if (param instanceof NullValue) {
Class> valueClass = ((NullValue) param).type();
DataType dataType = forValueClass(valueClass);
stringBuilder.append(dataType.paramDefinition(null));
} else {
Class> valueClass = param.getClass();
DataType dataType = forValueClass(valueClass);
stringBuilder.append(dataType.paramDefinition(param));
}
}
return stringBuilder.toString();
}
protected void encodeParams(ByteBuf buffer, TupleInternal params) {
for (int i = 0; i < params.size(); i++) {
String name = "@P" + (i + 1);
Object value = params.getValue(i);
if (value == null) {
NULL.encodeParam(buffer, name, false, null);
} else {
DataType dataType = DataType.forValueClass(value.getClass());
dataType.encodeParam(buffer, name, false, value);
}
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy