use of com.mysql.cj.protocol.a.ValueEncoder in project aws-mysql-jdbc by awslabs.
the class ServerPreparedQuery method prepareExecutePacket.
public NativePacketPayload prepareExecutePacket() {
ServerPreparedQueryBindValue[] parameterBindings = this.queryBindings.getBindValues();
if (this.queryBindings.isLongParameterSwitchDetected()) {
// Check when values were bound
boolean firstFound = false;
long boundTimeToCheck = 0;
for (int i = 0; i < this.parameterCount - 1; i++) {
if (parameterBindings[i].isStream()) {
if (firstFound && boundTimeToCheck != parameterBindings[i].boundBeforeExecutionNum) {
throw ExceptionFactory.createException(Messages.getString("ServerPreparedStatement.11") + Messages.getString("ServerPreparedStatement.12"), MysqlErrorNumbers.SQL_STATE_DRIVER_NOT_CAPABLE, 0, true, null, this.session.getExceptionInterceptor());
}
firstFound = true;
boundTimeToCheck = parameterBindings[i].boundBeforeExecutionNum;
}
}
// Okay, we've got all "newly"-bound streams, so reset server-side state to clear out previous bindings
serverResetStatement();
}
this.queryBindings.checkAllParametersSet();
//
for (int i = 0; i < this.parameterCount; i++) {
if (parameterBindings[i].isStream()) {
serverLongData(i, parameterBindings[i]);
}
}
//
// store the parameter values
//
NativePacketPayload packet = this.session.getSharedSendPacket();
packet.writeInteger(IntegerDataType.INT1, NativeConstants.COM_STMT_EXECUTE);
packet.writeInteger(IntegerDataType.INT4, this.serverStatementId);
boolean supportsQueryAttributes = this.session.getServerSession().supportsQueryAttributes();
boolean sendQueryAttributes = false;
if (supportsQueryAttributes) {
// Servers between 8.0.23 8.0.25 are affected by Bug#103102, Bug#103268 and Bug#103377. Query attributes cannot be sent to these servers.
sendQueryAttributes = this.session.getServerSession().getServerVersion().meetsMinimum(new ServerVersion(8, 0, 26));
} else if (this.queryAttributesBindings.getCount() > 0) {
this.session.getLog().logWarn(Messages.getString("QueryAttributes.SetButNotSupported"));
}
byte flags = 0;
if (this.resultFields != null && this.resultFields.getFields() != null && this.useCursorFetch && this.resultSetType == Type.FORWARD_ONLY && this.fetchSize > 0) {
// we only create cursor-backed result sets if
// a) The query is a SELECT
// b) The server supports it
// c) We know it is forward-only (note this doesn't preclude updatable result sets)
// d) The user has set a fetch size
flags |= OPEN_CURSOR_FLAG;
}
if (sendQueryAttributes) {
flags |= PARAMETER_COUNT_AVAILABLE;
}
packet.writeInteger(IntegerDataType.INT1, flags);
// placeholder for parameter iterations
packet.writeInteger(IntegerDataType.INT4, 1);
int parametersAndAttributesCount = this.parameterCount;
if (supportsQueryAttributes) {
if (sendQueryAttributes) {
parametersAndAttributesCount += this.queryAttributesBindings.getCount();
}
if (sendQueryAttributes || parametersAndAttributesCount > 0) {
// Servers between 8.0.23 and 8.0.25 don't expect a 'parameter_count' value if the statement was prepared without parameters.
packet.writeInteger(IntegerDataType.INT_LENENC, parametersAndAttributesCount);
}
}
if (parametersAndAttributesCount > 0) {
/* Reserve place for null-marker bytes */
int nullCount = (parametersAndAttributesCount + 7) / 8;
int nullBitsPosition = packet.getPosition();
for (int i = 0; i < nullCount; i++) {
packet.writeInteger(IntegerDataType.INT1, 0);
}
byte[] nullBitsBuffer = new byte[nullCount];
// In case if buffers (type) changed or there are query attributes to send.
if (this.queryBindings.getSendTypesToServer().get() || sendQueryAttributes && this.queryAttributesBindings.getCount() > 0) {
packet.writeInteger(IntegerDataType.INT1, 1);
// Store types of parameters in the first package that is sent to the server.
for (int i = 0; i < this.parameterCount; i++) {
packet.writeInteger(IntegerDataType.INT2, parameterBindings[i].bufferType);
if (supportsQueryAttributes) {
// Parameters have no names.
packet.writeBytes(StringSelfDataType.STRING_LENENC, "".getBytes());
}
}
if (sendQueryAttributes) {
this.queryAttributesBindings.runThroughAll(a -> {
packet.writeInteger(IntegerDataType.INT2, a.getType());
packet.writeBytes(StringSelfDataType.STRING_LENENC, a.getName().getBytes());
});
}
} else {
packet.writeInteger(IntegerDataType.INT1, 0);
}
// Store the parameter values.
for (int i = 0; i < this.parameterCount; i++) {
if (!parameterBindings[i].isStream()) {
if (!parameterBindings[i].isNull()) {
parameterBindings[i].storeBinding(packet, this.queryBindings.isLoadDataQuery(), this.charEncoding, this.session.getExceptionInterceptor());
} else {
nullBitsBuffer[i >>> 3] |= (1 << (i & 7));
}
}
}
if (sendQueryAttributes) {
for (int i = 0; i < this.queryAttributesBindings.getCount(); i++) {
if (this.queryAttributesBindings.getAttributeValue(i).isNull()) {
int b = i + this.parameterCount;
nullBitsBuffer[b >>> 3] |= 1 << (b & 7);
}
}
ValueEncoder valueEncoder = new ValueEncoder(packet, this.charEncoding, this.session.getServerSession().getDefaultTimeZone());
this.queryAttributesBindings.runThroughAll(a -> valueEncoder.encodeValue(a.getValue(), a.getType()));
}
// Go back and write the NULL flags to the beginning of the packet
int endPosition = packet.getPosition();
packet.setPosition(nullBitsPosition);
packet.writeBytes(StringLengthDataType.STRING_FIXED, nullBitsBuffer);
packet.setPosition(endPosition);
}
return packet;
}
use of com.mysql.cj.protocol.a.ValueEncoder in project aws-mysql-jdbc by awslabs.
the class AbstractPreparedQuery method fillSendPacket.
/**
* Creates the packet that contains the query to be sent to the server.
*
* @param bindings
* values
*
* @return a Buffer filled with the query that represents this statement
*/
@SuppressWarnings("unchecked")
@Override
public <M extends Message> M fillSendPacket(QueryBindings<?> bindings) {
synchronized (this) {
BindValue[] bindValues = bindings.getBindValues();
NativePacketPayload sendPacket = this.session.getSharedSendPacket();
sendPacket.writeInteger(IntegerDataType.INT1, NativeConstants.COM_QUERY);
if (getSession().getServerSession().supportsQueryAttributes()) {
if (this.queryAttributesBindings.getCount() > 0) {
sendPacket.writeInteger(IntegerDataType.INT_LENENC, this.queryAttributesBindings.getCount());
// parameter_set_count (always 1)
sendPacket.writeInteger(IntegerDataType.INT_LENENC, 1);
byte[] nullBitsBuffer = new byte[(this.queryAttributesBindings.getCount() + 7) / 8];
for (int i = 0; i < this.queryAttributesBindings.getCount(); i++) {
if (this.queryAttributesBindings.getAttributeValue(i).isNull()) {
nullBitsBuffer[i >>> 3] |= 1 << (i & 7);
}
}
sendPacket.writeBytes(StringLengthDataType.STRING_VAR, nullBitsBuffer);
// new_params_bind_flag (always 1)
sendPacket.writeInteger(IntegerDataType.INT1, 1);
this.queryAttributesBindings.runThroughAll(a -> {
sendPacket.writeInteger(IntegerDataType.INT2, a.getType());
sendPacket.writeBytes(StringSelfDataType.STRING_LENENC, a.getName().getBytes());
});
ValueEncoder valueEncoder = new ValueEncoder(sendPacket, this.charEncoding, this.session.getServerSession().getDefaultTimeZone());
this.queryAttributesBindings.runThroughAll(a -> valueEncoder.encodeValue(a.getValue(), a.getType()));
} else {
sendPacket.writeInteger(IntegerDataType.INT_LENENC, 0);
// parameter_set_count (always 1)
sendPacket.writeInteger(IntegerDataType.INT_LENENC, 1);
}
} else if (this.queryAttributesBindings.getCount() > 0) {
this.session.getLog().logWarn(Messages.getString("QueryAttributes.SetButNotSupported"));
}
sendPacket.setTag("QUERY");
boolean useStreamLengths = this.useStreamLengthsInPrepStmts.getValue();
//
// Try and get this allocation as close as possible for BLOBs
//
int ensurePacketSize = 0;
String statementComment = this.session.getProtocol().getQueryComment();
byte[] commentAsBytes = null;
if (statementComment != null) {
commentAsBytes = StringUtils.getBytes(statementComment, this.charEncoding);
ensurePacketSize += commentAsBytes.length;
// for /*[space] [space]*/
ensurePacketSize += 6;
}
for (int i = 0; i < bindValues.length; i++) {
if (bindValues[i].isStream() && useStreamLengths) {
ensurePacketSize += bindValues[i].getStreamLength();
}
}
if (ensurePacketSize != 0) {
sendPacket.ensureCapacity(ensurePacketSize);
}
if (commentAsBytes != null) {
sendPacket.writeBytes(StringLengthDataType.STRING_FIXED, Constants.SLASH_STAR_SPACE_AS_BYTES);
sendPacket.writeBytes(StringLengthDataType.STRING_FIXED, commentAsBytes);
sendPacket.writeBytes(StringLengthDataType.STRING_FIXED, Constants.SPACE_STAR_SLASH_SPACE_AS_BYTES);
}
byte[][] staticSqlStrings = this.parseInfo.getStaticSql();
for (int i = 0; i < bindValues.length; i++) {
bindings.checkParameterSet(i);
sendPacket.writeBytes(StringLengthDataType.STRING_FIXED, staticSqlStrings[i]);
if (bindValues[i].isStream()) {
streamToBytes(sendPacket, bindValues[i].getStreamValue(), true, bindValues[i].getStreamLength(), useStreamLengths);
} else {
sendPacket.writeBytes(StringLengthDataType.STRING_FIXED, bindValues[i].getByteValue());
}
}
sendPacket.writeBytes(StringLengthDataType.STRING_FIXED, staticSqlStrings[bindValues.length]);
return (M) sendPacket;
}
}
Aggregations