Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.mysql.cj.ServerPreparedQueryBindings Maven / Gradle / Ivy
/*
* Copyright (c) 2017, 2020, Oracle and/or its affiliates.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 2.0, as published by the
* Free Software Foundation.
*
* This program is also distributed with certain software (including but not
* limited to OpenSSL) that is licensed under separate terms, as designated in a
* particular file or component or in included license documentation. The
* authors of MySQL hereby grant you an additional permission to link the
* program and your derivative works with the separately licensed software that
* they have included with MySQL.
*
* Without limiting anything contained in the foregoing, this file, which is
* part of MySQL Connector/J, is also subject to the Universal FOSS Exception,
* version 1.0, a copy of which can be found at
* http://oss.oracle.com/licenses/universal-foss-exception.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
* for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.mysql.cj;
import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Date;
import java.sql.NClob;
import java.sql.Time;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Calendar;
import java.util.concurrent.atomic.AtomicBoolean;
import com.mysql.cj.conf.PropertyKey;
import com.mysql.cj.exceptions.ExceptionFactory;
import com.mysql.cj.exceptions.WrongArgumentException;
import com.mysql.cj.util.StringUtils;
import com.mysql.cj.util.TimeUtil;
//TODO should not be protocol-specific
public class ServerPreparedQueryBindings extends AbstractQueryBindings {
/** Do we need to send/resend types to the server? */
private AtomicBoolean sendTypesToServer = new AtomicBoolean(false);
/**
* Flag indicating whether or not the long parameters have been 'switched' back to normal parameters.
* We cannot execute() if clearParameters() has not been called in this case.
*/
private boolean longParameterSwitchDetected = false;
public ServerPreparedQueryBindings(int parameterCount, Session sess) {
super(parameterCount, sess);
}
@Override
protected void initBindValues(int parameterCount) {
this.bindValues = new ServerPreparedQueryBindValue[parameterCount];
for (int i = 0; i < parameterCount; i++) {
this.bindValues[i] = new ServerPreparedQueryBindValue(this.session.getServerSession().getDefaultTimeZone(),
this.session.getServerSession().getServerTimeZone(), this.session.getPropertySet());
}
}
@Override
public ServerPreparedQueryBindings clone() {
ServerPreparedQueryBindings newBindings = new ServerPreparedQueryBindings(this.bindValues.length, this.session);
ServerPreparedQueryBindValue[] bvs = new ServerPreparedQueryBindValue[this.bindValues.length];
for (int i = 0; i < this.bindValues.length; i++) {
bvs[i] = this.bindValues[i].clone();
}
newBindings.bindValues = bvs;
newBindings.sendTypesToServer = this.sendTypesToServer;
newBindings.longParameterSwitchDetected = this.longParameterSwitchDetected;
newBindings.isLoadDataQuery = this.isLoadDataQuery;
return newBindings;
}
/**
* Returns the structure representing the value that (can be)/(is)
* bound at the given parameter index.
*
* @param parameterIndex
* 0-based
* @param forLongData
* is this for a stream?
* @return ServerPreparedQueryBindValue
*/
public ServerPreparedQueryBindValue getBinding(int parameterIndex, boolean forLongData) {
if (this.bindValues[parameterIndex] == null) {
// this.bindValues[parameterIndex] = new ServerPreparedQueryBindValue();
} else {
if (this.bindValues[parameterIndex].isStream && !forLongData) {
this.longParameterSwitchDetected = true;
}
}
return this.bindValues[parameterIndex];
}
@Override
public void checkParameterSet(int columnIndex) {
if (!this.bindValues[columnIndex].isSet()) {
throw ExceptionFactory.createException(WrongArgumentException.class,
Messages.getString("ServerPreparedStatement.13") + (columnIndex + 1) + Messages.getString("ServerPreparedStatement.14"));
}
}
public AtomicBoolean getSendTypesToServer() {
return this.sendTypesToServer;
}
public boolean isLongParameterSwitchDetected() {
return this.longParameterSwitchDetected;
}
public void setLongParameterSwitchDetected(boolean longParameterSwitchDetected) {
this.longParameterSwitchDetected = longParameterSwitchDetected;
}
@Override
public void setAsciiStream(int parameterIndex, InputStream x) {
setAsciiStream(parameterIndex, x, -1);
}
@Override
public void setAsciiStream(int parameterIndex, InputStream x, int length) {
if (x == null) {
setNull(parameterIndex);
} else {
ServerPreparedQueryBindValue binding = getBinding(parameterIndex, true);
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_BLOB, this.numberOfExecutions));
binding.value = x;
binding.isStream = true;
binding.streamLength = this.useStreamLengthsInPrepStmts.getValue() ? length : -1;
}
}
@Override
public void setAsciiStream(int parameterIndex, InputStream x, long length) {
setAsciiStream(parameterIndex, x, (int) length);
this.bindValues[parameterIndex].setMysqlType(MysqlType.TEXT); // TODO was Types.CLOB, check; use length to find right TEXT type
}
@Override
public void setBigDecimal(int parameterIndex, BigDecimal x) {
if (x == null) {
setNull(parameterIndex);
} else {
ServerPreparedQueryBindValue binding = getBinding(parameterIndex, false);
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_NEWDECIMAL, this.numberOfExecutions));
binding.value = StringUtils.fixDecimalExponent(x.toPlainString());
binding.parameterType = MysqlType.DECIMAL;
}
}
@Override
public void setBigInteger(int parameterIndex, BigInteger x) {
setValue(parameterIndex, x.toString(), MysqlType.BIGINT_UNSIGNED);
}
@Override
public void setBinaryStream(int parameterIndex, InputStream x) {
setBinaryStream(parameterIndex, x, -1);
}
@Override
public void setBinaryStream(int parameterIndex, InputStream x, int length) {
if (x == null) {
setNull(parameterIndex);
} else {
ServerPreparedQueryBindValue binding = getBinding(parameterIndex, true);
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_BLOB, this.numberOfExecutions));
binding.value = x;
binding.isStream = true;
binding.streamLength = this.useStreamLengthsInPrepStmts.getValue() ? length : -1;
binding.parameterType = MysqlType.BLOB; // TODO use length to find the right BLOB type
}
}
@Override
public void setBinaryStream(int parameterIndex, InputStream x, long length) {
setBinaryStream(parameterIndex, x, (int) length);
}
@Override
public void setBlob(int parameterIndex, InputStream inputStream) {
setBinaryStream(parameterIndex, inputStream);
}
@Override
public void setBlob(int parameterIndex, InputStream inputStream, long length) {
setBinaryStream(parameterIndex, inputStream, (int) length);
}
@Override
public void setBlob(int parameterIndex, Blob x) {
if (x == null) {
setNull(parameterIndex);
} else {
try {
ServerPreparedQueryBindValue binding = getBinding(parameterIndex, true);
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_BLOB, this.numberOfExecutions));
binding.value = x;
binding.isStream = true;
binding.streamLength = this.useStreamLengthsInPrepStmts.getValue() ? x.length() : -1;
binding.parameterType = MysqlType.BLOB;
} catch (Throwable t) {
throw ExceptionFactory.createException(t.getMessage(), t);
}
}
}
@Override
public void setBoolean(int parameterIndex, boolean x) {
ServerPreparedQueryBindValue binding = getBinding(parameterIndex, false);
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_TINY, this.numberOfExecutions));
binding.value = Long.valueOf(x ? (byte) 1 : (byte) 0);
binding.parameterType = MysqlType.BOOLEAN;
}
@Override
public void setByte(int parameterIndex, byte x) {
ServerPreparedQueryBindValue binding = getBinding(parameterIndex, false);
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_TINY, this.numberOfExecutions));
binding.value = Long.valueOf(x);
binding.parameterType = MysqlType.TINYINT;
}
@Override
public void setBytes(int parameterIndex, byte[] x) {
if (x == null) {
setNull(parameterIndex);
} else {
ServerPreparedQueryBindValue binding = getBinding(parameterIndex, false);
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_VAR_STRING, this.numberOfExecutions));
binding.value = x;
binding.parameterType = MysqlType.BINARY; // TODO VARBINARY ?
}
}
@Override
public void setBytes(int parameterIndex, byte[] x, boolean checkForIntroducer, boolean escapeForMBChars) {
setBytes(parameterIndex, x);
}
@Override
public void setBytesNoEscape(int parameterIndex, byte[] parameterAsBytes) {
setBytes(parameterIndex, parameterAsBytes);
}
@Override
public void setBytesNoEscapeNoQuotes(int parameterIndex, byte[] parameterAsBytes) {
setBytes(parameterIndex, parameterAsBytes);
}
@Override
public void setCharacterStream(int parameterIndex, Reader reader) {
setCharacterStream(parameterIndex, reader, -1);
}
@Override
public void setCharacterStream(int parameterIndex, Reader reader, int length) {
if (reader == null) {
setNull(parameterIndex);
} else {
ServerPreparedQueryBindValue binding = getBinding(parameterIndex, true);
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_BLOB, this.numberOfExecutions));
binding.value = reader;
binding.isStream = true;
binding.streamLength = this.useStreamLengthsInPrepStmts.getValue() ? length : -1;
binding.parameterType = MysqlType.TEXT;
}
}
@Override
public void setCharacterStream(int parameterIndex, Reader reader, long length) {
setCharacterStream(parameterIndex, reader, (int) length);
}
@Override
public void setClob(int parameterIndex, Reader reader) {
setCharacterStream(parameterIndex, reader);
}
@Override
public void setClob(int parameterIndex, Reader reader, long length) {
setCharacterStream(parameterIndex, reader, length);
}
@Override
public void setClob(int parameterIndex, Clob x) {
if (x == null) {
setNull(parameterIndex);
} else {
try {
ServerPreparedQueryBindValue binding = getBinding(parameterIndex, true);
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_BLOB, this.numberOfExecutions));
binding.value = x.getCharacterStream();
binding.isStream = true;
binding.streamLength = this.useStreamLengthsInPrepStmts.getValue() ? x.length() : -1;
binding.parameterType = MysqlType.TEXT;
} catch (Throwable t) {
throw ExceptionFactory.createException(t.getMessage(), t);
}
}
}
@Override
public void setDate(int parameterIndex, Date x) {
setDate(parameterIndex, x, null);
}
@Override
public void setDate(int parameterIndex, Date x, Calendar cal) {
if (x == null) {
setNull(parameterIndex);
} else {
ServerPreparedQueryBindValue binding = getBinding(parameterIndex, false);
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_DATE, this.numberOfExecutions));
binding.value = x;
binding.calendar = cal == null ? null : (Calendar) cal.clone();
binding.parameterType = MysqlType.DATE;
}
}
@Override
public void setDouble(int parameterIndex, double x) {
if (!this.session.getPropertySet().getBooleanProperty(PropertyKey.allowNanAndInf).getValue()
&& (x == Double.POSITIVE_INFINITY || x == Double.NEGATIVE_INFINITY || Double.isNaN(x))) {
throw ExceptionFactory.createException(WrongArgumentException.class, Messages.getString("PreparedStatement.64", new Object[] { x }),
this.session.getExceptionInterceptor());
}
ServerPreparedQueryBindValue binding = getBinding(parameterIndex, false);
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_DOUBLE, this.numberOfExecutions));
binding.value = Double.valueOf(x);
binding.parameterType = MysqlType.DOUBLE;
}
@Override
public void setFloat(int parameterIndex, float x) {
ServerPreparedQueryBindValue binding = getBinding(parameterIndex, false);
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_FLOAT, this.numberOfExecutions));
binding.value = Float.valueOf(x);
binding.parameterType = MysqlType.FLOAT; // TODO check; was Types.FLOAT but should be Types.REAL to map to SQL FLOAT
}
@Override
public void setInt(int parameterIndex, int x) {
ServerPreparedQueryBindValue binding = getBinding(parameterIndex, false);
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_LONG, this.numberOfExecutions));
binding.value = Long.valueOf(x);
binding.parameterType = MysqlType.INT;
}
@Override
public void setLocalDate(int parameterIndex, LocalDate x, MysqlType targetMysqlType) {
ServerPreparedQueryBindValue binding = getBinding(parameterIndex, false);
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_DATE, this.numberOfExecutions));
binding.parameterType = targetMysqlType;
binding.value = x;
}
@Override
public void setLocalTime(int parameterIndex, LocalTime x, MysqlType targetMysqlType) {
ServerPreparedQueryBindValue binding = getBinding(parameterIndex, false);
if (targetMysqlType == MysqlType.DATE) {
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_DATE, this.numberOfExecutions));
binding.parameterType = targetMysqlType;
binding.value = DEFAULT_DATE;
} else {
int fractLen = 6; // max supported length (i.e. microsecond)
if (this.columnDefinition != null && parameterIndex <= this.columnDefinition.getFields().length && parameterIndex >= 0) {
// use the column definition if available
fractLen = this.columnDefinition.getFields()[parameterIndex].getDecimals();
}
if (!this.sendFractionalSeconds.getValue() || !this.session.getServerSession().getCapabilities().serverSupportsFracSecs()) {
x = x.withNano(0); // truncate nanoseconds
} else {
x = TimeUtil.adjustNanosPrecision(x, fractLen, !this.session.getServerSession().isServerTruncatesFracSecs());
}
if (targetMysqlType == MysqlType.TIME) {
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_TIME, this.numberOfExecutions));
} else {
// DATETIME or TIMESTAMP
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_DATETIME, this.numberOfExecutions));
}
binding.parameterType = targetMysqlType;
binding.value = x;
}
}
@Override
public void setLocalDateTime(int parameterIndex, LocalDateTime x, MysqlType targetMysqlType) {
ServerPreparedQueryBindValue binding = getBinding(parameterIndex, false);
if (targetMysqlType == MysqlType.DATE) {
x = LocalDateTime.of(x.toLocalDate(), DEFAULT_TIME);
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_DATE, this.numberOfExecutions));
} else {
int fractLen = 6; // max supported length (i.e. microsecond)
if (this.columnDefinition != null && parameterIndex <= this.columnDefinition.getFields().length && parameterIndex >= 0) {
// use the column definition if available
fractLen = this.columnDefinition.getFields()[parameterIndex].getDecimals();
}
if (!this.sendFractionalSeconds.getValue() || !this.session.getServerSession().getCapabilities().serverSupportsFracSecs()) {
x = x.withNano(0); // truncate nanoseconds
} else {
x = TimeUtil.adjustNanosPrecision(x, fractLen, !this.session.getServerSession().isServerTruncatesFracSecs());
}
if (targetMysqlType == MysqlType.TIME) {
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_TIME, this.numberOfExecutions));
} else {
// DATETIME or TIMESTAMP
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_DATETIME, this.numberOfExecutions));
}
}
binding.parameterType = targetMysqlType;
binding.value = x;
}
@Override
public void setLong(int parameterIndex, long x) {
ServerPreparedQueryBindValue binding = getBinding(parameterIndex, false);
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_LONGLONG, this.numberOfExecutions));
binding.value = Long.valueOf(x);
binding.parameterType = MysqlType.BIGINT;
}
@Override
public void setNCharacterStream(int parameterIndex, Reader value) {
setNCharacterStream(parameterIndex, value, -1);
}
@Override
public void setNCharacterStream(int parameterIndex, Reader reader, long length) {
if (!this.charEncoding.equalsIgnoreCase("UTF-8") && !this.charEncoding.equalsIgnoreCase("utf8")) {
throw ExceptionFactory.createException(Messages.getString("ServerPreparedStatement.28"), this.session.getExceptionInterceptor());
}
if (reader == null) {
setNull(parameterIndex);
} else {
ServerPreparedQueryBindValue binding = getBinding(parameterIndex, true);
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_BLOB, this.numberOfExecutions));
binding.value = reader;
binding.isStream = true;
binding.streamLength = this.useStreamLengthsInPrepStmts.getValue() ? length : -1;
binding.parameterType = MysqlType.TEXT;
}
}
@Override
public void setNClob(int parameterIndex, Reader reader) {
setNCharacterStream(parameterIndex, reader);
}
@Override
public void setNClob(int parameterIndex, Reader reader, long length) {
if (!this.charEncoding.equalsIgnoreCase("UTF-8") && !this.charEncoding.equalsIgnoreCase("utf8")) {
throw ExceptionFactory.createException(Messages.getString("ServerPreparedStatement.29"), this.session.getExceptionInterceptor());
}
setNCharacterStream(parameterIndex, reader, length);
}
@Override
public void setNClob(int parameterIndex, NClob value) {
try {
setNClob(parameterIndex, value.getCharacterStream(), this.useStreamLengthsInPrepStmts.getValue() ? value.length() : -1);
} catch (Throwable t) {
throw ExceptionFactory.createException(t.getMessage(), t, this.session.getExceptionInterceptor());
}
}
@Override
public void setNString(int parameterIndex, String x) {
if (this.charEncoding.equalsIgnoreCase("UTF-8") || this.charEncoding.equalsIgnoreCase("utf8")) {
setString(parameterIndex, x);
} else {
throw ExceptionFactory.createException(Messages.getString("ServerPreparedStatement.30"), this.session.getExceptionInterceptor());
}
}
@Override
public void setNull(int parameterIndex) {
ServerPreparedQueryBindValue binding = getBinding(parameterIndex, false);
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_NULL, this.numberOfExecutions));
binding.setNull(true);
}
@Override
public void setShort(int parameterIndex, short x) {
ServerPreparedQueryBindValue binding = getBinding(parameterIndex, false);
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_SHORT, this.numberOfExecutions));
binding.value = Long.valueOf(x);
binding.parameterType = MysqlType.SMALLINT;
}
@Override
public void setString(int parameterIndex, String x) {
if (x == null) {
setNull(parameterIndex);
} else {
ServerPreparedQueryBindValue binding = getBinding(parameterIndex, false);
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_VAR_STRING, this.numberOfExecutions));
binding.value = x;
binding.charEncoding = this.charEncoding;
binding.parameterType = MysqlType.VARCHAR;
}
}
public void setTime(int parameterIndex, Time x, Calendar cal) {
if (x == null) {
setNull(parameterIndex);
} else {
ServerPreparedQueryBindValue binding = getBinding(parameterIndex, false);
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_TIME, this.numberOfExecutions));
binding.value = x;
binding.calendar = cal == null ? null : (Calendar) cal.clone();
binding.parameterType = MysqlType.TIME;
}
}
public void setTime(int parameterIndex, Time x) {
setTime(parameterIndex, x, null);
}
@Override
public void setTimestamp(int parameterIndex, Timestamp x) {
int fractLen = -1;
if (!this.sendFractionalSeconds.getValue() || !this.session.getServerSession().getCapabilities().serverSupportsFracSecs()) {
fractLen = 0;
} else if (this.columnDefinition != null && parameterIndex <= this.columnDefinition.getFields().length && parameterIndex >= 0) {
fractLen = this.columnDefinition.getFields()[parameterIndex].getDecimals();
}
setTimestamp(parameterIndex, x, null, fractLen);
}
@Override
public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) {
int fractLen = -1;
if (!this.sendFractionalSeconds.getValue() || !this.session.getServerSession().getCapabilities().serverSupportsFracSecs()) {
fractLen = 0;
} else if (this.columnDefinition != null && parameterIndex <= this.columnDefinition.getFields().length && parameterIndex >= 0
&& this.columnDefinition.getFields()[parameterIndex].getDecimals() > 0) {
fractLen = this.columnDefinition.getFields()[parameterIndex].getDecimals();
}
setTimestamp(parameterIndex, x, cal, fractLen);
}
@Override
public void setTimestamp(int parameterIndex, Timestamp x, Calendar targetCalendar, int fractionalLength) {
if (x == null) {
setNull(parameterIndex);
} else {
ServerPreparedQueryBindValue binding = getBinding(parameterIndex, false);
this.sendTypesToServer.compareAndSet(false, binding.resetToType(MysqlType.FIELD_TYPE_DATETIME, this.numberOfExecutions));
if (!this.session.getServerSession().getCapabilities().serverSupportsFracSecs()
|| !this.sendFractionalSeconds.getValue() && fractionalLength == 0) {
x = TimeUtil.truncateFractionalSeconds(x);
}
if (fractionalLength < 0) {
// default to 6 fractional positions
fractionalLength = 6;
}
x = TimeUtil.adjustNanosPrecision(x, fractionalLength, !this.session.getServerSession().isServerTruncatesFracSecs());
binding.value = x;
binding.calendar = targetCalendar == null ? null : (Calendar) targetCalendar.clone();
binding.parameterType = MysqlType.TIMESTAMP;
}
}
}