Categories:
Audio (13)
Biotech (29)
Bytecode (36)
Database (77)
Framework (7)
Game (7)
General (507)
Graphics (53)
I/O (35)
IDE (2)
JAR Tools (102)
JavaBeans (21)
JDBC (121)
JDK (426)
JSP (20)
Logging (108)
Mail (58)
Messaging (8)
Network (84)
PDF (97)
Report (7)
Scripting (84)
Security (32)
Server (121)
Servlet (26)
SOAP (24)
Testing (54)
Web (15)
XML (322)
Collections:
Other Resources:
Source Code for Connector/J 8.0.31 - User Impl
Where to get the Java source code for Connector/J 8.0 User Impl module?
✍: FYIcenter.com
Java source code files for Connector/J 8.0 User Impl module are:
⏎ com/mysql/cj/jdbc/result/UpdatableResultSet.java
/*
* Copyright (c) 2002, 2022, 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.jdbc.result;
import java.io.InputStream;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.sql.Clob;
import java.sql.JDBCType;
import java.sql.NClob;
import java.sql.SQLException;
import java.sql.SQLType;
import java.sql.SQLXML;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import com.mysql.cj.Messages;
import com.mysql.cj.MysqlType;
import com.mysql.cj.conf.PropertyDefinitions.DatabaseTerm;
import com.mysql.cj.conf.PropertyKey;
import com.mysql.cj.exceptions.AssertionFailedException;
import com.mysql.cj.exceptions.ExceptionFactory;
import com.mysql.cj.exceptions.FeatureNotAvailableException;
import com.mysql.cj.exceptions.MysqlErrorNumbers;
import com.mysql.cj.jdbc.ClientPreparedStatement;
import com.mysql.cj.jdbc.JdbcConnection;
import com.mysql.cj.jdbc.MysqlSQLXML;
import com.mysql.cj.jdbc.StatementImpl;
import com.mysql.cj.jdbc.exceptions.NotUpdatable;
import com.mysql.cj.jdbc.exceptions.SQLError;
import com.mysql.cj.log.ProfilerEvent;
import com.mysql.cj.protocol.ResultsetRow;
import com.mysql.cj.protocol.ResultsetRows;
import com.mysql.cj.protocol.a.result.ByteArrayRow;
import com.mysql.cj.result.Field;
import com.mysql.cj.result.Row;
import com.mysql.cj.util.StringUtils;
/**
* A result set that is updatable.
*/
public class UpdatableResultSet extends ResultSetImpl {
/** Marker for 'stream' data when doing INSERT rows */
final static byte[] STREAM_DATA_MARKER = StringUtils.getBytes("** STREAM DATA **");
private String charEncoding;
/** What is the default value for the column? */
private byte[][] defaultColumnValue;
/** PreparedStatement used to delete data */
private ClientPreparedStatement deleter = null;
private String deleteSQL = null;
/** PreparedStatement used to insert data */
protected ClientPreparedStatement inserter = null;
private String insertSQL = null;
/** Is this result set updatable? */
private boolean isUpdatable = false;
/** Reason the result set is not updatable */
private String notUpdatableReason = null;
/** List of primary keys */
private List<Integer> primaryKeyIndicies = null;
private String qualifiedAndQuotedTableName;
private String quotedIdChar = null;
/** PreparedStatement used to refresh data */
private ClientPreparedStatement refresher;
private String refreshSQL = null;
/** The binary data for the 'current' row */
private Row savedCurrentRow;
/** PreparedStatement used to delete data */
protected ClientPreparedStatement updater = null;
/** SQL for in-place modifcation */
private String updateSQL = null;
private boolean populateInserterWithDefaultValues = false;
private boolean pedantic;
private boolean hasLongColumnInfo = false;
private Map<String, Map<String, Map<String, Integer>>> databasesUsedToTablesUsed = null;
/** Are we on the insert row? */
private boolean onInsertRow = false;
/** Are we in the middle of doing updates to the current row? */
protected boolean doingUpdates = false;
/**
* Creates a new ResultSet object.
*
* @param tuples
* actual row data
* @param conn
* the Connection that created us.
* @param creatorStmt
* statement owning this result set
*
* @throws SQLException
* if an error occurs
*/
public UpdatableResultSet(ResultsetRows tuples, JdbcConnection conn, StatementImpl creatorStmt) throws SQLException {
super(tuples, conn, creatorStmt);
checkUpdatability();
this.charEncoding = this.session.getPropertySet().getStringProperty(PropertyKey.characterEncoding).getValue();
this.populateInserterWithDefaultValues = this.getSession().getPropertySet().getBooleanProperty(PropertyKey.populateInsertRowWithDefaultValues)
.getValue();
this.pedantic = this.getSession().getPropertySet().getBooleanProperty(PropertyKey.pedantic).getValue();
this.hasLongColumnInfo = this.getSession().getServerSession().hasLongColumnInfo();
}
@Override
public boolean absolute(int row) throws SQLException {
boolean ret = super.absolute(row);
if (this.onInsertRow) {
this.onInsertRow = false;
}
if (this.doingUpdates) {
this.doingUpdates = false;
}
return ret;
}
@Override
public void afterLast() throws SQLException {
super.afterLast();
if (this.onInsertRow) {
this.onInsertRow = false;
}
if (this.doingUpdates) {
this.doingUpdates = false;
}
}
@Override
public void beforeFirst() throws SQLException {
super.beforeFirst();
if (this.onInsertRow) {
this.onInsertRow = false;
}
if (this.doingUpdates) {
this.doingUpdates = false;
}
}
@Override
public void cancelRowUpdates() throws SQLException {
if (this.doingUpdates) {
this.doingUpdates = false;
this.updater.clearParameters();
}
}
@Override
protected void checkRowPos() throws SQLException {
if (!this.onInsertRow) {
super.checkRowPos();
}
}
/**
* Is this ResultSet updatable?
*
* @throws SQLException
* if an error occurs
*/
public void checkUpdatability() throws SQLException {
try {
if (this.getMetadata() == null) {
// we've been created to be populated with cached metadata, and we don't have the metadata yet, we'll be called again by
// Connection.initializeResultsMetadataFromCache() when the metadata has been made available
return;
}
String singleTableName = null;
String dbName = null;
int primaryKeyCount = 0;
Field[] fields = this.getMetadata().getFields();
// We can only do this if we know that there is a currently selected database, or if we're talking to a > 4.1 version of MySQL server (as it returns
// database names in field info)
if ((this.db == null) || (this.db.length() == 0)) {
this.db = fields[0].getDatabaseName();
if ((this.db == null) || (this.db.length() == 0)) {
throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.43"), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT,
getExceptionInterceptor());
}
}
if (fields.length > 0) {
singleTableName = fields[0].getOriginalTableName();
dbName = fields[0].getDatabaseName();
if (singleTableName == null) {
singleTableName = fields[0].getTableName();
dbName = this.db;
}
if (singleTableName == null) {
this.isUpdatable = false;
this.notUpdatableReason = Messages.getString("NotUpdatableReason.3");
return;
}
if (fields[0].isPrimaryKey()) {
primaryKeyCount++;
}
//
// References only one table?
//
for (int i = 1; i < fields.length; i++) {
String otherTableName = fields[i].getOriginalTableName();
String otherDbName = fields[i].getDatabaseName();
if (otherTableName == null) {
otherTableName = fields[i].getTableName();
otherDbName = this.db;
}
if (otherTableName == null) {
this.isUpdatable = false;
this.notUpdatableReason = Messages.getString("NotUpdatableReason.3");
return;
}
if (!otherTableName.equals(singleTableName)) {
this.isUpdatable = false;
this.notUpdatableReason = Messages.getString("NotUpdatableReason.0");
return;
}
// Can't reference more than one database
if ((dbName == null) || !dbName.equals(otherDbName)) {
this.isUpdatable = false;
this.notUpdatableReason = Messages.getString("NotUpdatableReason.1");
return;
}
if (fields[i].isPrimaryKey()) {
primaryKeyCount++;
}
}
} else {
this.isUpdatable = false;
this.notUpdatableReason = Messages.getString("NotUpdatableReason.3");
return;
}
if (this.getSession().getPropertySet().getBooleanProperty(PropertyKey.strictUpdates).getValue()) {
java.sql.DatabaseMetaData dbmd = this.getConnection().getMetaData();
java.sql.ResultSet rs = null;
HashMap<String, String> primaryKeyNames = new HashMap<>();
try {
rs = this.session.getPropertySet().<DatabaseTerm>getEnumProperty(PropertyKey.databaseTerm).getValue() == DatabaseTerm.SCHEMA
? dbmd.getPrimaryKeys(null, dbName, singleTableName)
: dbmd.getPrimaryKeys(dbName, null, singleTableName);
while (rs.next()) {
String keyName = rs.getString(4);
keyName = keyName.toUpperCase();
primaryKeyNames.put(keyName, keyName);
}
} finally {
if (rs != null) {
try {
rs.close();
} catch (Exception ex) {
AssertionFailedException.shouldNotHappen(ex);
}
rs = null;
}
}
int existingPrimaryKeysCount = primaryKeyNames.size();
if (existingPrimaryKeysCount == 0) {
this.isUpdatable = false;
this.notUpdatableReason = Messages.getString("NotUpdatableReason.5");
return; // we can't update tables w/o keys
}
//
// Contains all primary keys?
//
for (int i = 0; i < fields.length; i++) {
if (fields[i].isPrimaryKey()) {
String columnNameUC = fields[i].getName().toUpperCase();
if (primaryKeyNames.remove(columnNameUC) == null) {
// try original name
String originalName = fields[i].getOriginalName();
if (originalName != null) {
if (primaryKeyNames.remove(originalName.toUpperCase()) == null) {
// we don't know about this key, so give up :(
this.isUpdatable = false;
this.notUpdatableReason = Messages.getString("NotUpdatableReason.6", new Object[] { originalName });
return;
}
}
}
}
}
this.isUpdatable = primaryKeyNames.isEmpty();
if (!this.isUpdatable) {
this.notUpdatableReason = existingPrimaryKeysCount > 1 ? Messages.getString("NotUpdatableReason.7")
: Messages.getString("NotUpdatableReason.4");
return;
}
}
//
// Must have at least one primary key
//
if (primaryKeyCount == 0) {
this.isUpdatable = false;
this.notUpdatableReason = Messages.getString("NotUpdatableReason.4");
return;
}
this.isUpdatable = true;
this.notUpdatableReason = null;
return;
} catch (SQLException sqlEx) {
this.isUpdatable = false;
this.notUpdatableReason = sqlEx.getMessage();
}
}
@Override
public void deleteRow() throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.isUpdatable) {
throw new NotUpdatable(this.notUpdatableReason);
}
if (this.onInsertRow) {
throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.1"), getExceptionInterceptor());
} else if (this.rowData.size() == 0) {
throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.2"), getExceptionInterceptor());
} else if (isBeforeFirst()) {
throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.3"), getExceptionInterceptor());
} else if (isAfterLast()) {
throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.4"), getExceptionInterceptor());
}
if (this.deleter == null) {
if (this.deleteSQL == null) {
generateStatements();
}
this.deleter = (ClientPreparedStatement) this.connection.clientPrepareStatement(this.deleteSQL);
}
this.deleter.clearParameters();
int numKeys = this.primaryKeyIndicies.size();
for (int i = 0; i < numKeys; i++) {
int index = this.primaryKeyIndicies.get(i).intValue();
this.setParamValue(this.deleter, i + 1, this.thisRow, index, this.getMetadata().getFields()[index]);
}
this.deleter.executeUpdate();
this.rowData.remove();
prev(); // position on previous row - Bug#27431
}
}
private void setParamValue(ClientPreparedStatement ps, int psIdx, Row row, int rsIdx, Field field) throws SQLException {
byte[] val = row.getBytes(rsIdx);
if (val == null) {
ps.setNull(psIdx, MysqlType.NULL);
return;
}
switch (field.getMysqlType()) {
case NULL:
ps.setNull(psIdx, MysqlType.NULL);
break;
case TINYINT:
case TINYINT_UNSIGNED:
case SMALLINT:
case SMALLINT_UNSIGNED:
case MEDIUMINT:
case MEDIUMINT_UNSIGNED:
case INT:
case INT_UNSIGNED:
case YEAR:
ps.setInt(psIdx, getInt(rsIdx + 1));
break;
case BIGINT:
ps.setLong(psIdx, getLong(rsIdx + 1));
break;
case BIGINT_UNSIGNED:
ps.setBigInteger(psIdx, getBigInteger(rsIdx + 1));
break;
case CHAR:
case ENUM:
case SET:
case VARCHAR:
case JSON:
case TINYTEXT:
case TEXT:
case MEDIUMTEXT:
case LONGTEXT:
case DECIMAL:
case DECIMAL_UNSIGNED:
ps.setString(psIdx, getString(rsIdx + 1));
break;
case DATE:
ps.setDate(psIdx, getDate(rsIdx + 1));
break;
case TIMESTAMP:
ps.setObject(psIdx, getObject(rsIdx + 1, Timestamp.class), MysqlType.TIMESTAMP, field.getDecimals());
ps.getQueryBindings().getBinding(psIdx - 1, false).setKeepOrigNanos(true);
break;
case DATETIME:
ps.setObject(psIdx, getObject(rsIdx + 1, LocalDateTime.class), MysqlType.DATETIME, field.getDecimals());
ps.getQueryBindings().getBinding(psIdx - 1, false).setKeepOrigNanos(true);
break;
case TIME:
ps.setTime(psIdx, getTime(rsIdx + 1));
ps.getQueryBindings().getBinding(psIdx - 1, false).setKeepOrigNanos(true);
break;
case DOUBLE:
case DOUBLE_UNSIGNED:
case FLOAT:
case FLOAT_UNSIGNED:
case BOOLEAN:
case BIT:
ps.setBytes(psIdx, val, false);
break;
/*
* default, but also explicitly for following types:
* case Types.BINARY:
* case Types.BLOB:
*/
default:
ps.setBytes(psIdx, val);
break;
}
}
private void extractDefaultValues() throws SQLException {
java.sql.DatabaseMetaData dbmd = this.getConnection().getMetaData();
this.defaultColumnValue = new byte[this.getMetadata().getFields().length][];
java.sql.ResultSet columnsResultSet = null;
for (Map.Entry<String, Map<String, Map<String, Integer>>> dbEntry : this.databasesUsedToTablesUsed.entrySet()) {
for (Map.Entry<String, Map<String, Integer>> tableEntry : dbEntry.getValue().entrySet()) {
String tableName = tableEntry.getKey();
Map<String, Integer> columnNamesToIndices = tableEntry.getValue();
try {
columnsResultSet = this.session.getPropertySet().<DatabaseTerm>getEnumProperty(PropertyKey.databaseTerm).getValue() == DatabaseTerm.SCHEMA
? dbmd.getColumns(null, this.db, tableName, "%")
: dbmd.getColumns(this.db, null, tableName, "%");
while (columnsResultSet.next()) {
String columnName = columnsResultSet.getString("COLUMN_NAME");
byte[] defaultValue = columnsResultSet.getBytes("COLUMN_DEF");
if (columnNamesToIndices.containsKey(columnName)) {
int localColumnIndex = columnNamesToIndices.get(columnName).intValue();
this.defaultColumnValue[localColumnIndex] = defaultValue;
} // else assert?
}
} finally {
if (columnsResultSet != null) {
columnsResultSet.close();
columnsResultSet = null;
}
}
}
}
}
@Override
public boolean first() throws SQLException {
boolean ret = super.first();
if (this.onInsertRow) {
this.onInsertRow = false;
}
if (this.doingUpdates) {
this.doingUpdates = false;
}
return ret;
}
/**
* Figure out whether or not this ResultSet is updatable, and if so,
* generate the PreparedStatements to support updates.
*
* @throws SQLException
* if an error occurs
* @throws NotUpdatable
* if result set was marked as not updatable
*/
protected void generateStatements() throws SQLException {
if (!this.isUpdatable) {
this.doingUpdates = false;
this.onInsertRow = false;
throw new NotUpdatable(this.notUpdatableReason);
}
String quotedId = getQuotedIdChar();
Map<String, String> tableNamesSoFar = null;
if (this.session.getServerSession().isLowerCaseTableNames()) {
tableNamesSoFar = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
this.databasesUsedToTablesUsed = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
} else {
tableNamesSoFar = new TreeMap<>();
this.databasesUsedToTablesUsed = new TreeMap<>();
}
this.primaryKeyIndicies = new ArrayList<>();
StringBuilder fieldValues = new StringBuilder();
StringBuilder keyValues = new StringBuilder();
StringBuilder columnNames = new StringBuilder();
StringBuilder insertPlaceHolders = new StringBuilder();
StringBuilder allTablesBuf = new StringBuilder();
Map<Integer, String> columnIndicesToTable = new HashMap<>();
Field[] fields = this.getMetadata().getFields();
for (int i = 0; i < fields.length; i++) {
Map<String, Integer> updColumnNameToIndex = null;
// FIXME: What about no table?
if (fields[i].getOriginalTableName() != null) {
String databaseName = fields[i].getDatabaseName();
String tableOnlyName = fields[i].getOriginalTableName();
String fqTableName = StringUtils.getFullyQualifiedName(databaseName, tableOnlyName, quotedId, this.pedantic);
if (!tableNamesSoFar.containsKey(fqTableName)) {
if (!tableNamesSoFar.isEmpty()) {
allTablesBuf.append(',');
}
allTablesBuf.append(fqTableName);
tableNamesSoFar.put(fqTableName, fqTableName);
}
columnIndicesToTable.put(Integer.valueOf(i), fqTableName);
updColumnNameToIndex = getColumnsToIndexMapForTableAndDB(databaseName, tableOnlyName);
} else {
String tableOnlyName = fields[i].getTableName();
if (tableOnlyName != null) {
String fqTableName = StringUtils.quoteIdentifier(tableOnlyName, quotedId, this.pedantic);
if (!tableNamesSoFar.containsKey(fqTableName)) {
if (!tableNamesSoFar.isEmpty()) {
allTablesBuf.append(',');
}
allTablesBuf.append(fqTableName);
tableNamesSoFar.put(fqTableName, fqTableName);
}
columnIndicesToTable.put(Integer.valueOf(i), fqTableName);
updColumnNameToIndex = getColumnsToIndexMapForTableAndDB(this.db, tableOnlyName);
}
}
String originalColumnName = fields[i].getOriginalName();
String columnName = this.hasLongColumnInfo && originalColumnName != null && originalColumnName.length() > 0 ? originalColumnName
: fields[i].getName();
if (updColumnNameToIndex != null && columnName != null) {
updColumnNameToIndex.put(columnName, Integer.valueOf(i));
}
String originalTableName = fields[i].getOriginalTableName();
String tableName = this.hasLongColumnInfo && originalTableName != null && originalTableName.length() > 0 ? originalTableName
: fields[i].getTableName();
String databaseName = fields[i].getDatabaseName();
String qualifiedColumnName = new StringBuilder() //
.append(StringUtils.getFullyQualifiedName(databaseName, tableName, quotedId, this.pedantic)) //
.append('.') //
.append(StringUtils.quoteIdentifier(columnName, quotedId, this.pedantic)).toString();
if (fields[i].isPrimaryKey()) {
this.primaryKeyIndicies.add(Integer.valueOf(i));
if (keyValues.length() > 0) {
keyValues.append(" AND ");
}
keyValues.append(qualifiedColumnName);
keyValues.append("<=>");
keyValues.append("?");
}
if (fieldValues.length() == 0) {
fieldValues.append("SET ");
} else {
fieldValues.append(",");
columnNames.append(",");
insertPlaceHolders.append(",");
}
insertPlaceHolders.append("?");
columnNames.append(qualifiedColumnName);
fieldValues.append(qualifiedColumnName);
fieldValues.append("=?");
}
this.qualifiedAndQuotedTableName = allTablesBuf.toString();
this.updateSQL = "UPDATE " + this.qualifiedAndQuotedTableName + " " + fieldValues.toString() + " WHERE " + keyValues.toString();
this.insertSQL = "INSERT INTO " + this.qualifiedAndQuotedTableName + " (" + columnNames.toString() + ") VALUES (" + insertPlaceHolders.toString() + ")";
this.refreshSQL = "SELECT " + columnNames.toString() + " FROM " + this.qualifiedAndQuotedTableName + " WHERE " + keyValues.toString();
this.deleteSQL = "DELETE FROM " + this.qualifiedAndQuotedTableName + " WHERE " + keyValues.toString();
}
private Map<String, Integer> getColumnsToIndexMapForTableAndDB(String databaseName, String tableName) {
Map<String, Integer> nameToIndex;
Map<String, Map<String, Integer>> tablesUsedToColumnsMap = this.databasesUsedToTablesUsed.get(databaseName);
if (tablesUsedToColumnsMap == null) {
tablesUsedToColumnsMap = this.session.getServerSession().isLowerCaseTableNames() ? new TreeMap<>(String.CASE_INSENSITIVE_ORDER) : new TreeMap<>();
this.databasesUsedToTablesUsed.put(databaseName, tablesUsedToColumnsMap);
}
nameToIndex = tablesUsedToColumnsMap.get(tableName);
if (nameToIndex == null) {
nameToIndex = new HashMap<>();
tablesUsedToColumnsMap.put(tableName, nameToIndex);
}
return nameToIndex;
}
@Override
public int getConcurrency() throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
return (this.isUpdatable ? CONCUR_UPDATABLE : CONCUR_READ_ONLY);
}
}
private String getQuotedIdChar() throws SQLException {
if (this.quotedIdChar == null) {
this.quotedIdChar = this.session.getIdentifierQuoteString();
}
return this.quotedIdChar;
}
@Override
public void insertRow() throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.onInsertRow) {
throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.7"), getExceptionInterceptor());
}
this.inserter.executeUpdate();
long autoIncrementId = this.inserter.getLastInsertID();
Field[] fields = this.getMetadata().getFields();
byte[][] newRow = new byte[fields.length][];
for (int i = 0; i < fields.length; i++) {
if (this.inserter.isNull(i + 1)) {
newRow[i] = null;
}
// WARN: This non-variant only holds if MySQL never allows more than one auto-increment key (which is the way it is _today_)
if (fields[i].isAutoIncrement() && autoIncrementId > 0) {
newRow[i] = StringUtils.getBytes(String.valueOf(autoIncrementId));
this.inserter.setBytes(i + 1, newRow[i], false);
}
}
Row resultSetRow = new ByteArrayRow(newRow, getExceptionInterceptor());
// inserter is always a client-side prepared statement, so it's safe to use it with ByteArrayRow for server-side prepared statement too
refreshRow(this.inserter, resultSetRow);
this.rowData.addRow(resultSetRow);
resetInserter();
}
}
@Override
public boolean isAfterLast() throws SQLException {
return super.isAfterLast();
}
@Override
public boolean isBeforeFirst() throws SQLException {
return super.isBeforeFirst();
}
@Override
public boolean isFirst() throws SQLException {
return super.isFirst();
}
@Override
public boolean isLast() throws SQLException {
return super.isLast();
}
boolean isUpdatable() {
return this.isUpdatable;
}
@Override
public boolean last() throws SQLException {
boolean ret = super.last();
if (this.onInsertRow) {
this.onInsertRow = false;
}
if (this.doingUpdates) {
this.doingUpdates = false;
}
return ret;
}
@Override
public void moveToCurrentRow() throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.isUpdatable) {
throw new NotUpdatable(this.notUpdatableReason);
}
if (this.onInsertRow) {
this.onInsertRow = false;
this.thisRow = this.savedCurrentRow;
}
}
}
@Override
public void moveToInsertRow() throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.isUpdatable) {
throw new NotUpdatable(this.notUpdatableReason);
}
if (this.inserter == null) {
if (this.insertSQL == null) {
generateStatements();
}
this.inserter = (ClientPreparedStatement) this.getConnection().clientPrepareStatement(this.insertSQL);
this.inserter.getQueryBindings().setColumnDefinition(this.getMetadata());
if (this.populateInserterWithDefaultValues) {
extractDefaultValues();
}
}
resetInserter();
Field[] fields = this.getMetadata().getFields();
int numFields = fields.length;
this.onInsertRow = true;
this.doingUpdates = false;
this.savedCurrentRow = this.thisRow;
byte[][] newRowData = new byte[numFields][];
this.thisRow = new ByteArrayRow(newRowData, getExceptionInterceptor());
this.thisRow.setMetadata(this.getMetadata());
for (int i = 0; i < numFields; i++) {
if (!this.populateInserterWithDefaultValues) {
this.inserter.setBytes(i + 1, StringUtils.getBytes("DEFAULT"), false);
newRowData = null;
} else {
if (this.defaultColumnValue[i] != null) {
Field f = fields[i];
switch (f.getMysqlTypeId()) {
case MysqlType.FIELD_TYPE_DATE:
case MysqlType.FIELD_TYPE_DATETIME:
case MysqlType.FIELD_TYPE_TIME:
case MysqlType.FIELD_TYPE_TIMESTAMP:
if (this.defaultColumnValue[i].length > 7 && this.defaultColumnValue[i][0] == (byte) 'C'
&& this.defaultColumnValue[i][1] == (byte) 'U' && this.defaultColumnValue[i][2] == (byte) 'R'
&& this.defaultColumnValue[i][3] == (byte) 'R' && this.defaultColumnValue[i][4] == (byte) 'E'
&& this.defaultColumnValue[i][5] == (byte) 'N' && this.defaultColumnValue[i][6] == (byte) 'T'
&& this.defaultColumnValue[i][7] == (byte) '_') {
this.inserter.setBytes(i + 1, this.defaultColumnValue[i], false);
} else {
this.inserter.setBytes(i + 1, this.defaultColumnValue[i]);
}
break;
default:
this.inserter.setBytes(i + 1, this.defaultColumnValue[i]);
}
// This value _could_ be changed from a getBytes(), so we need a copy....
byte[] defaultValueCopy = new byte[this.defaultColumnValue[i].length];
System.arraycopy(this.defaultColumnValue[i], 0, defaultValueCopy, 0, defaultValueCopy.length);
newRowData[i] = defaultValueCopy;
} else {
this.inserter.setNull(i + 1, MysqlType.NULL);
newRowData[i] = null;
}
}
}
}
}
@Override
public boolean next() throws SQLException {
boolean ret = super.next();
if (this.onInsertRow) {
this.onInsertRow = false;
}
if (this.doingUpdates) {
this.doingUpdates = false;
}
return ret;
}
@Override
public boolean prev() throws SQLException {
boolean ret = super.prev();
if (this.onInsertRow) {
this.onInsertRow = false;
}
if (this.doingUpdates) {
this.doingUpdates = false;
}
return ret;
}
@Override
public boolean previous() throws SQLException {
boolean ret = super.previous();
if (this.onInsertRow) {
this.onInsertRow = false;
}
if (this.doingUpdates) {
this.doingUpdates = false;
}
return ret;
}
@Override
public void realClose(boolean calledExplicitly) throws SQLException {
if (this.isClosed) {
return;
}
synchronized (checkClosed().getConnectionMutex()) {
SQLException sqlEx = null;
if (this.useUsageAdvisor) {
if ((this.deleter == null) && (this.inserter == null) && (this.refresher == null) && (this.updater == null)) {
this.eventSink.processEvent(ProfilerEvent.TYPE_USAGE, this.session, this.getOwningStatement(), this, 0, new Throwable(),
Messages.getString("UpdatableResultSet.34"));
}
}
try {
if (this.deleter != null) {
this.deleter.close();
}
} catch (SQLException ex) {
sqlEx = ex;
}
try {
if (this.inserter != null) {
this.inserter.close();
}
} catch (SQLException ex) {
sqlEx = ex;
}
try {
if (this.refresher != null) {
this.refresher.close();
}
} catch (SQLException ex) {
sqlEx = ex;
}
try {
if (this.updater != null) {
this.updater.close();
}
} catch (SQLException ex) {
sqlEx = ex;
}
super.realClose(calledExplicitly);
if (sqlEx != null) {
throw sqlEx;
}
}
}
@Override
public void refreshRow() throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (isStrictlyForwardOnly()) {
throw ExceptionFactory.createException(Messages.getString("ResultSet.ForwardOnly"));
}
if (!this.isUpdatable) {
throw new NotUpdatable(Messages.getString("NotUpdatable.0"));
}
if (this.onInsertRow) {
throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.8"), getExceptionInterceptor());
} else if (this.rowData.size() == 0) {
throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.9"), getExceptionInterceptor());
} else if (isBeforeFirst()) {
throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.10"), getExceptionInterceptor());
} else if (isAfterLast()) {
throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.11"), getExceptionInterceptor());
}
refreshRow(this.updater, this.thisRow);
}
}
private void refreshRow(ClientPreparedStatement updateInsertStmt, Row rowToRefresh) throws SQLException {
if (this.refresher == null) {
if (this.refreshSQL == null) {
generateStatements();
}
// We're going to copy bytes from refresher results to rowToRefresh, thus we need them to have the same protocol encoding
this.refresher = ((ResultsetRow) this.thisRow).isBinaryEncoded()
? (ClientPreparedStatement) this.getConnection().serverPrepareStatement(this.refreshSQL)
: (ClientPreparedStatement) this.getConnection().clientPrepareStatement(this.refreshSQL);
this.refresher.getQueryBindings().setColumnDefinition(this.getMetadata());
}
this.refresher.clearParameters();
int numKeys = this.primaryKeyIndicies.size();
for (int i = 0; i < numKeys; i++) {
byte[] dataFrom = null;
int index = this.primaryKeyIndicies.get(i).intValue();
if (!this.doingUpdates && !this.onInsertRow) {
this.setParamValue(this.refresher, i + 1, this.thisRow, index, this.getMetadata().getFields()[index]);
continue;
}
dataFrom = updateInsertStmt.getBytesRepresentation(index + 1);
// Primary keys not set?
if (updateInsertStmt.isNull(index + 1) || (dataFrom.length == 0)) {
this.setParamValue(this.refresher, i + 1, this.thisRow, index, this.getMetadata().getFields()[index]);
continue;
}
this.refresher.getQueryBindings().setFromBindValue(i, updateInsertStmt.getQueryBindings().getBindValues()[index]);
}
java.sql.ResultSet rs = null;
try {
rs = this.refresher.executeQuery();
int numCols = rs.getMetaData().getColumnCount();
if (rs.next()) {
for (int i = 0; i < numCols; i++) {
byte[] val = rs.getBytes(i + 1);
rowToRefresh.setBytes(i, (val == null) || rs.wasNull() ? null : val);
}
} else {
throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.12"), MysqlErrorNumbers.SQL_STATE_GENERAL_ERROR,
getExceptionInterceptor());
}
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException ex) {
// ignore
}
}
}
}
@Override
public boolean relative(int rows) throws SQLException {
boolean ret = super.relative(rows);
if (this.onInsertRow) {
this.onInsertRow = false;
}
if (this.doingUpdates) {
this.doingUpdates = false;
}
return ret;
}
private void resetInserter() throws SQLException {
this.inserter.clearParameters();
for (int i = 0; i < this.getMetadata().getFields().length; i++) {
this.inserter.setNull(i + 1, 0);
}
}
@Override
public boolean rowDeleted() throws SQLException {
throw SQLError.createSQLFeatureNotSupportedException();
}
@Override
public boolean rowInserted() throws SQLException {
throw SQLError.createSQLFeatureNotSupportedException();
}
@Override
public boolean rowUpdated() throws SQLException {
throw SQLError.createSQLFeatureNotSupportedException();
}
@Override
public void setResultSetConcurrency(int concurrencyFlag) {
super.setResultSetConcurrency(concurrencyFlag);
// TODO: FIXME: Issue warning when asked for updatable result set, but result set is not updatable
//
// if ((concurrencyFlag == CONCUR_UPDATABLE) && !isUpdatable()) {
// java.sql.SQLWarning warning = new java.sql.SQLWarning(
// NotUpdatable.NOT_UPDATABLE_MESSAGE);
// }
}
/**
* Reset UPDATE prepared statement to value in current row. This_Row MUST
* point to current, valid row.
*
* @throws SQLException
* if an error occurs
*/
protected void syncUpdate() throws SQLException {
if (this.updater == null) {
if (this.updateSQL == null) {
generateStatements();
}
this.updater = (ClientPreparedStatement) this.getConnection().clientPrepareStatement(this.updateSQL);
this.updater.getQueryBindings().setColumnDefinition(this.getMetadata());
}
Field[] fields = this.getMetadata().getFields();
int numFields = fields.length;
this.updater.clearParameters();
for (int i = 0; i < numFields; i++) {
if (this.thisRow.getBytes(i) != null) {
switch (fields[i].getMysqlType()) {
case DATE:
case DATETIME:
case TIME:
case TIMESTAMP:
// TODO this is a temporary workaround until Bug#71143 "Calling ResultSet.updateRow should not set all field values in UPDATE" is fixed.
// We handle these types separately to avoid fractional seconds truncation (when sendFractionalSeconds=true)
// that happens for fields we don't touch with ResultSet.updateNN(). For those fields we should pass the value as is or,
// better don't put them into final updater statement as requested by Bug#71143.
this.updater.setString(i + 1, getString(i + 1));
break;
default:
this.updater.setObject(i + 1, getObject(i + 1), fields[i].getMysqlType());
break;
}
} else {
this.updater.setNull(i + 1, 0);
}
}
int numKeys = this.primaryKeyIndicies.size();
for (int i = 0; i < numKeys; i++) {
int idx = this.primaryKeyIndicies.get(i).intValue();
this.setParamValue(this.updater, numFields + i + 1, this.thisRow, idx, fields[idx]);
}
}
@Override
public void updateRow() throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.isUpdatable) {
throw new NotUpdatable(this.notUpdatableReason);
}
if (this.doingUpdates) {
this.updater.executeUpdate();
refreshRow(this.updater, this.thisRow);
this.doingUpdates = false;
} else if (this.onInsertRow) {
throw SQLError.createSQLException(Messages.getString("UpdatableResultSet.44"), getExceptionInterceptor());
}
// fixes calling updateRow() and then doing more updates on same row...
syncUpdate();
}
}
@Override
public int getHoldability() throws SQLException {
throw SQLError.createSQLFeatureNotSupportedException();
}
@Override
public void updateAsciiStream(String columnLabel, java.io.InputStream x, int length) throws SQLException {
updateAsciiStream(findColumn(columnLabel), x, length);
}
@Override
public void updateAsciiStream(int columnIndex, java.io.InputStream x, int length) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setAsciiStream(columnIndex, x, length);
} else {
this.inserter.setAsciiStream(columnIndex, x, length);
this.thisRow.setBytes(columnIndex - 1, STREAM_DATA_MARKER);
}
}
}
@Override
public void updateBigDecimal(String columnLabel, BigDecimal x) throws SQLException {
updateBigDecimal(findColumn(columnLabel), x);
}
@Override
public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setBigDecimal(columnIndex, x);
} else {
this.inserter.setBigDecimal(columnIndex, x);
this.thisRow.setBytes(columnIndex - 1, x == null ? null : StringUtils.getBytes(x.toString()));
}
}
}
@Override
public void updateBinaryStream(String columnLabel, java.io.InputStream x, int length) throws SQLException {
updateBinaryStream(findColumn(columnLabel), x, length);
}
@Override
public void updateBinaryStream(int columnIndex, java.io.InputStream x, int length) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setBinaryStream(columnIndex, x, length);
} else {
this.inserter.setBinaryStream(columnIndex, x, length);
this.thisRow.setBytes(columnIndex - 1, x == null ? null : STREAM_DATA_MARKER);
}
}
}
@Override
public void updateBlob(String columnLabel, java.sql.Blob blob) throws SQLException {
updateBlob(findColumn(columnLabel), blob);
}
@Override
public void updateBlob(int columnIndex, java.sql.Blob blob) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setBlob(columnIndex, blob);
} else {
this.inserter.setBlob(columnIndex, blob);
this.thisRow.setBytes(columnIndex - 1, blob == null ? null : STREAM_DATA_MARKER);
}
}
}
@Override
public void updateBoolean(String columnLabel, boolean x) throws SQLException {
updateBoolean(findColumn(columnLabel), x);
}
@Override
public void updateBoolean(int columnIndex, boolean x) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setBoolean(columnIndex, x);
} else {
this.inserter.setBoolean(columnIndex, x);
this.thisRow.setBytes(columnIndex - 1, this.inserter.getBytesRepresentation(columnIndex));
}
}
}
@Override
public void updateByte(String columnLabel, byte x) throws SQLException {
updateByte(findColumn(columnLabel), x);
}
@Override
public void updateByte(int columnIndex, byte x) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setByte(columnIndex, x);
} else {
this.inserter.setByte(columnIndex, x);
this.thisRow.setBytes(columnIndex - 1, this.inserter.getBytesRepresentation(columnIndex));
}
}
}
@Override
public void updateBytes(String columnLabel, byte[] x) throws SQLException {
updateBytes(findColumn(columnLabel), x);
}
@Override
public void updateBytes(int columnIndex, byte[] x) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setBytes(columnIndex, x);
} else {
this.inserter.setBytes(columnIndex, x);
this.thisRow.setBytes(columnIndex - 1, x);
}
}
}
@Override
public void updateCharacterStream(String columnLabel, java.io.Reader reader, int length) throws SQLException {
updateCharacterStream(findColumn(columnLabel), reader, length);
}
@Override
public void updateCharacterStream(int columnIndex, java.io.Reader x, int length) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setCharacterStream(columnIndex, x, length);
} else {
this.inserter.setCharacterStream(columnIndex, x, length);
this.thisRow.setBytes(columnIndex - 1, x == null ? null : STREAM_DATA_MARKER);
}
}
}
@Override
public void updateClob(String columnLabel, Clob clob) throws SQLException {
updateClob(findColumn(columnLabel), clob);
}
@Override
public void updateClob(int columnIndex, java.sql.Clob clob) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (clob == null) {
updateNull(columnIndex);
} else {
updateCharacterStream(columnIndex, clob.getCharacterStream(), (int) clob.length());
}
}
}
@Override
public void updateDate(String columnLabel, java.sql.Date x) throws SQLException {
updateDate(findColumn(columnLabel), x);
}
@Override
public void updateDate(int columnIndex, java.sql.Date x) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setDate(columnIndex, x);
} else {
this.inserter.setDate(columnIndex, x);
this.thisRow.setBytes(columnIndex - 1, this.inserter.getBytesRepresentation(columnIndex));
}
}
}
@Override
public void updateDouble(String columnLabel, double x) throws SQLException {
updateDouble(findColumn(columnLabel), x);
}
@Override
public void updateDouble(int columnIndex, double x) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setDouble(columnIndex, x);
} else {
this.inserter.setDouble(columnIndex, x);
this.thisRow.setBytes(columnIndex - 1, this.inserter.getBytesRepresentation(columnIndex));
}
}
}
@Override
public void updateFloat(String columnLabel, float x) throws SQLException {
updateFloat(findColumn(columnLabel), x);
}
@Override
public void updateFloat(int columnIndex, float x) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setFloat(columnIndex, x);
} else {
this.inserter.setFloat(columnIndex, x);
this.thisRow.setBytes(columnIndex - 1, this.inserter.getBytesRepresentation(columnIndex));
}
}
}
@Override
public void updateInt(String columnLabel, int x) throws SQLException {
updateInt(findColumn(columnLabel), x);
}
@Override
public void updateInt(int columnIndex, int x) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setInt(columnIndex, x);
} else {
this.inserter.setInt(columnIndex, x);
this.thisRow.setBytes(columnIndex - 1, this.inserter.getBytesRepresentation(columnIndex));
}
}
}
@Override
public void updateLong(String columnLabel, long x) throws SQLException {
updateLong(findColumn(columnLabel), x);
}
@Override
public void updateLong(int columnIndex, long x) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setLong(columnIndex, x);
} else {
this.inserter.setLong(columnIndex, x);
this.thisRow.setBytes(columnIndex - 1, this.inserter.getBytesRepresentation(columnIndex));
}
}
}
@Override
public void updateNull(String columnLabel) throws SQLException {
updateNull(findColumn(columnLabel));
}
@Override
public void updateNull(int columnIndex) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setNull(columnIndex, 0);
} else {
this.inserter.setNull(columnIndex, 0);
this.thisRow.setBytes(columnIndex - 1, null);
}
}
}
@Override
public void updateObject(String columnLabel, Object x) throws SQLException {
updateObject(findColumn(columnLabel), x);
}
@Override
public void updateObject(int columnIndex, Object x) throws SQLException {
updateObjectInternal(columnIndex, x, (Integer) null, 0);
}
@Override
public void updateObject(String columnLabel, Object x, int scale) throws SQLException {
updateObject(findColumn(columnLabel), x, scale);
}
@Override
public void updateObject(int columnIndex, Object x, int scale) throws SQLException {
updateObjectInternal(columnIndex, x, (Integer) null, scale);
}
/**
* Internal setObject implementation. Although targetType is not part of default ResultSet methods signatures, it is used for type conversions from
* JDBC42UpdatableResultSet new JDBC 4.2 updateObject() methods.
*
* @param columnIndex
* column index
* @param x
* value
* @param targetType
* target type
* @param scaleOrLength
* scale or length, depending on target type
* @throws SQLException
* if an error occurs
*/
protected void updateObjectInternal(int columnIndex, Object x, Integer targetType, int scaleOrLength) throws SQLException {
try {
MysqlType targetMysqlType = targetType == null ? null : MysqlType.getByJdbcType(targetType);
updateObjectInternal(columnIndex, x, targetMysqlType, scaleOrLength);
} catch (FeatureNotAvailableException nae) {
throw SQLError.createSQLFeatureNotSupportedException(Messages.getString("Statement.UnsupportedSQLType") + JDBCType.valueOf(targetType),
MysqlErrorNumbers.SQL_STATE_DRIVER_NOT_CAPABLE, getExceptionInterceptor());
}
}
/**
* Internal setObject implementation.
*
* @param columnIndex
* column index
* @param x
* value
* @param targetType
* target type
* @param scaleOrLength
* scale or length, depending on target type
* @throws SQLException
* if an error occurs
*/
protected void updateObjectInternal(int columnIndex, Object x, SQLType targetType, int scaleOrLength) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
if (targetType == null) {
this.updater.setObject(columnIndex, x);
} else {
this.updater.setObject(columnIndex, x, targetType);
}
} else {
if (targetType == null) {
this.inserter.setObject(columnIndex, x);
} else {
this.inserter.setObject(columnIndex, x, targetType);
}
this.thisRow.setBytes(columnIndex - 1, this.inserter.getBytesRepresentation(columnIndex));
}
}
}
@Override
public void updateObject(String columnLabel, Object x, SQLType targetSqlType) throws SQLException {
updateObject(findColumn(columnLabel), x, targetSqlType);
}
@Override
public void updateObject(int columnIndex, Object x, SQLType targetSqlType) throws SQLException {
updateObjectInternal(columnIndex, x, targetSqlType, 0);
}
@Override
public void updateObject(String columnLabel, Object x, SQLType targetSqlType, int scaleOrLength) throws SQLException {
updateObject(findColumn(columnLabel), x, targetSqlType, scaleOrLength);
}
@Override
public void updateObject(int columnIndex, Object x, SQLType targetSqlType, int scaleOrLength) throws SQLException {
updateObjectInternal(columnIndex, x, targetSqlType, scaleOrLength);
}
@Override
public void updateShort(String columnLabel, short x) throws SQLException {
updateShort(findColumn(columnLabel), x);
}
@Override
public void updateShort(int columnIndex, short x) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setShort(columnIndex, x);
} else {
this.inserter.setShort(columnIndex, x);
this.thisRow.setBytes(columnIndex - 1, this.inserter.getBytesRepresentation(columnIndex));
}
}
}
@Override
public void updateString(String columnLabel, String x) throws SQLException {
updateString(findColumn(columnLabel), x);
}
@Override
public void updateString(int columnIndex, String x) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setString(columnIndex, x);
} else {
this.inserter.setString(columnIndex, x);
this.thisRow.setBytes(columnIndex - 1, x == null ? null : StringUtils.getBytes(x, this.charEncoding));
}
}
}
@Override
public void updateTime(String columnLabel, java.sql.Time x) throws SQLException {
updateTime(findColumn(columnLabel), x);
}
@Override
public void updateTime(int columnIndex, java.sql.Time x) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setTime(columnIndex, x);
} else {
this.inserter.setTime(columnIndex, x);
this.thisRow.setBytes(columnIndex - 1, this.inserter.getBytesRepresentation(columnIndex));
}
}
}
@Override
public void updateTimestamp(String columnLabel, java.sql.Timestamp x) throws SQLException {
updateTimestamp(findColumn(columnLabel), x);
}
@Override
public void updateTimestamp(int columnIndex, java.sql.Timestamp x) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setTimestamp(columnIndex, x);
} else {
this.inserter.setTimestamp(columnIndex, x);
this.thisRow.setBytes(columnIndex - 1, this.inserter.getBytesRepresentation(columnIndex));
}
}
}
@Override
public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException {
updateAsciiStream(findColumn(columnLabel), x);
}
@Override
public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setAsciiStream(columnIndex, x);
} else {
this.inserter.setAsciiStream(columnIndex, x);
this.thisRow.setBytes(columnIndex - 1, STREAM_DATA_MARKER);
}
}
@Override
public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException {
updateAsciiStream(findColumn(columnLabel), x, length);
}
@Override
public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setAsciiStream(columnIndex, x, length);
} else {
this.inserter.setAsciiStream(columnIndex, x, length);
this.thisRow.setBytes(columnIndex - 1, STREAM_DATA_MARKER);
}
}
@Override
public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException {
updateBinaryStream(findColumn(columnLabel), x);
}
@Override
public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setBinaryStream(columnIndex, x);
} else {
this.inserter.setBinaryStream(columnIndex, x);
this.thisRow.setBytes(columnIndex - 1, x == null ? null : STREAM_DATA_MARKER);
}
}
@Override
public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException {
updateBinaryStream(findColumn(columnLabel), x, length);
}
@Override
public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setBinaryStream(columnIndex, x, length);
} else {
this.inserter.setBinaryStream(columnIndex, x, length);
this.thisRow.setBytes(columnIndex - 1, x == null ? null : STREAM_DATA_MARKER);
}
}
@Override
public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException {
updateBlob(findColumn(columnLabel), inputStream);
}
@Override
public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setBlob(columnIndex, inputStream);
} else {
this.inserter.setBlob(columnIndex, inputStream);
this.thisRow.setBytes(columnIndex - 1, inputStream == null ? null : STREAM_DATA_MARKER);
}
}
@Override
public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException {
updateBlob(findColumn(columnLabel), inputStream, length);
}
@Override
public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setBlob(columnIndex, inputStream, length);
} else {
this.inserter.setBlob(columnIndex, inputStream, length);
this.thisRow.setBytes(columnIndex - 1, inputStream == null ? null : STREAM_DATA_MARKER);
}
}
@Override
public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException {
updateCharacterStream(findColumn(columnLabel), reader);
}
@Override
public void updateCharacterStream(int columnIndex, Reader x) throws SQLException {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setCharacterStream(columnIndex, x);
} else {
this.inserter.setCharacterStream(columnIndex, x);
this.thisRow.setBytes(columnIndex - 1, x == null ? null : STREAM_DATA_MARKER);
}
}
@Override
public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException {
updateCharacterStream(findColumn(columnLabel), reader, length);
}
@Override
public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException {
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setCharacterStream(columnIndex, x, length);
} else {
this.inserter.setCharacterStream(columnIndex, x, length);
this.thisRow.setBytes(columnIndex - 1, x == null ? null : STREAM_DATA_MARKER);
}
}
@Override
public void updateClob(String columnLabel, Reader reader) throws SQLException {
updateClob(findColumn(columnLabel), reader);
}
@Override
public void updateClob(int columnIndex, Reader reader) throws SQLException {
updateCharacterStream(columnIndex, reader);
}
@Override
public void updateClob(String columnLabel, Reader reader, long length) throws SQLException {
updateClob(findColumn(columnLabel), reader, length);
}
@Override
public void updateClob(int columnIndex, Reader reader, long length) throws SQLException {
updateCharacterStream(columnIndex, reader, length);
}
@Override
public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException {
updateNCharacterStream(findColumn(columnLabel), reader);
}
@Override
public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException {
String fieldEncoding = this.getMetadata().getFields()[columnIndex - 1].getEncoding();
if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) {
throw new SQLException(Messages.getString("ResultSet.16"));
}
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setNCharacterStream(columnIndex, x);
} else {
this.inserter.setNCharacterStream(columnIndex, x);
this.thisRow.setBytes(columnIndex - 1, x == null ? null : STREAM_DATA_MARKER);
}
}
@Override
public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException {
updateNCharacterStream(findColumn(columnLabel), reader, length);
}
@Override
public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
String fieldEncoding = this.getMetadata().getFields()[columnIndex - 1].getEncoding();
if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) {
throw new SQLException(Messages.getString("ResultSet.16"));
}
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setNCharacterStream(columnIndex, x, length);
} else {
this.inserter.setNCharacterStream(columnIndex, x, length);
this.thisRow.setBytes(columnIndex - 1, x == null ? null : STREAM_DATA_MARKER);
}
}
}
@Override
public void updateNClob(String columnLabel, Reader reader) throws SQLException {
updateNClob(findColumn(columnLabel), reader);
}
@Override
public void updateNClob(int columnIndex, Reader reader) throws SQLException {
String fieldEncoding = this.getMetadata().getFields()[columnIndex - 1].getEncoding();
if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) {
throw new SQLException(Messages.getString("ResultSet.17"));
}
updateCharacterStream(columnIndex, reader);
}
@Override
public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException {
updateNClob(findColumn(columnLabel), reader, length);
}
@Override
public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException {
String fieldEncoding = this.getMetadata().getFields()[columnIndex - 1].getEncoding();
if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) {
throw new SQLException(Messages.getString("ResultSet.17"));
}
updateCharacterStream(columnIndex, reader, length);
}
@Override
public void updateNClob(String columnLabel, java.sql.NClob nClob) throws SQLException {
updateNClob(findColumn(columnLabel), nClob);
}
@Override
public void updateNClob(int columnIndex, java.sql.NClob nClob) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
String fieldEncoding = this.getMetadata().getFields()[columnIndex - 1].getEncoding();
if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) {
throw new SQLException(Messages.getString("ResultSet.17"));
}
if (nClob == null) {
updateNull(columnIndex);
} else {
updateNCharacterStream(columnIndex, nClob.getCharacterStream(), (int) nClob.length());
}
}
}
@Override
public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException {
updateSQLXML(findColumn(columnLabel), xmlObject);
}
@Override
public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException {
updateString(columnIndex, ((MysqlSQLXML) xmlObject).getString());
}
@Override
public void updateNString(String columnLabel, String x) throws SQLException {
updateNString(findColumn(columnLabel), x);
}
@Override
public void updateNString(int columnIndex, String x) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
String fieldEncoding = this.getMetadata().getFields()[columnIndex - 1].getEncoding();
if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) {
throw new SQLException(Messages.getString("ResultSet.18"));
}
if (!this.onInsertRow) {
if (!this.doingUpdates) {
this.doingUpdates = true;
syncUpdate();
}
this.updater.setNString(columnIndex, x);
} else {
this.inserter.setNString(columnIndex, x);
this.thisRow.setBytes(columnIndex - 1, x == null ? null : StringUtils.getBytes(x, fieldEncoding));
}
}
}
@Override
public Reader getNCharacterStream(String columnLabel) throws SQLException {
return getNCharacterStream(findColumn(columnLabel));
}
@Override
public Reader getNCharacterStream(int columnIndex) throws SQLException {
String fieldEncoding = this.getMetadata().getFields()[columnIndex - 1].getEncoding();
if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) {
throw new SQLException(Messages.getString("ResultSet.11"));
}
return getCharacterStream(columnIndex);
}
@Override
public NClob getNClob(String columnLabel) throws SQLException {
return getNClob(findColumn(columnLabel));
}
@Override
public NClob getNClob(int columnIndex) throws SQLException {
String fieldEncoding = this.getMetadata().getFields()[columnIndex - 1].getEncoding();
if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) {
throw new SQLException("Can not call getNClob() when field's charset isn't UTF-8");
}
String asString = getStringForNClob(columnIndex);
if (asString == null) {
return null;
}
return new com.mysql.cj.jdbc.NClob(asString, getExceptionInterceptor());
}
@Override
public String getNString(String columnLabel) throws SQLException {
return getNString(findColumn(columnLabel));
}
@Override
public String getNString(int columnIndex) throws SQLException {
String fieldEncoding = this.getMetadata().getFields()[columnIndex - 1].getEncoding();
if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) {
throw new SQLException("Can not call getNString() when field's charset isn't UTF-8");
}
return getString(columnIndex);
}
@Override
public SQLXML getSQLXML(String columnLabel) throws SQLException {
return getSQLXML(findColumn(columnLabel));
}
@Override
public SQLXML getSQLXML(int columnIndex) throws SQLException {
return new MysqlSQLXML(this, columnIndex, getExceptionInterceptor());
}
private String getStringForNClob(int columnIndex) throws SQLException {
String asString = null;
String forcedEncoding = "UTF-8";
try {
byte[] asBytes = null;
asBytes = getBytes(columnIndex);
if (asBytes != null) {
asString = new String(asBytes, forcedEncoding);
}
} catch (UnsupportedEncodingException uee) {
throw SQLError.createSQLException("Unsupported character encoding " + forcedEncoding, MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT,
getExceptionInterceptor());
}
return asString;
}
@Override
public boolean isClosed() throws SQLException {
return this.isClosed;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
checkClosed();
// This works for classes that aren't actually wrapping anything
return iface.isInstance(this);
}
@Override
public <T> T unwrap(java.lang.Class<T> iface) throws java.sql.SQLException {
try {
// This works for classes that aren't actually wrapping anything
return iface.cast(this);
} catch (ClassCastException cce) {
throw SQLError.createSQLException("Unable to unwrap to " + iface.toString(), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT,
getExceptionInterceptor());
}
}
}
⏎ com/mysql/cj/jdbc/result/UpdatableResultSet.java
Or download all of them as a single archive file:
File name: mysql-connector-java-user-impl-8.0.31.zip File size: 429580 bytes Release date: 2022-09-03 Download
⇒ Downloading mysql-connector-java-5.1.40.zip
⇐ Source Code for Connector/J 8.0.31 - User API
2023-05-09, ≈61🔥, 0💬
Popular Posts:
JDK 11 jdk.charsets.jmod is the JMOD file for JDK 11 Charsets module. JDK 11 Charsets module compile...
What Is ojdbc5.jar for Oracle 11g R1? ojdbc5.jar for Oracle 11g R1 is the JAR files of ojdbc.jar, JD...
JDK 11 java.security.jgss.jmod is the JMOD file for JDK 11 Security JGSS (Java Generic Security Serv...
How to download and install javamail-1_2.zip? The JavaMail API is a set of abstract APIs that model ...
Where Can I get source code files of jsse.jar? You can get source code files of jsse.jar (JSSE) from...