📄 mysqlio.java
字号:
if (database != null) {
databaseLength = database.length();
}
int packLength = (userLength + passwordLength + databaseLength) + 7
+ HEADER_LENGTH;
Buffer packet = null;
if (!connection.useSSL()) {
if ((serverCapabilities & CLIENT_SECURE_CONNECTION) != 0) {
clientParam |= CLIENT_SECURE_CONNECTION;
if (versionMeetsMinimum(4, 1, 1)) {
secureAuth411(packLength, serverCapabilities, clientParam,
user, password, database);
} else {
secureAuth(packLength, serverCapabilities, clientParam,
user, password, database);
}
} else {
packet = new Buffer(packLength);
if ((clientParam & CLIENT_RESERVED) != 0) {
if (versionMeetsMinimum(4, 1, 1)) {
packet.writeLong(clientParam);
packet.writeLong(this.maxThreeBytes);
// charset, JDBC will connect as 'latin1',
// and use 'SET NAMES' to change to the desired
// charset after the connection is established.
packet.writeByte((byte) 8);
// Set of bytes reserved for future use.
packet.writeBytesNoNull(new byte[23]);
} else {
packet.writeLong(clientParam);
packet.writeLong(this.maxThreeBytes);
}
} else {
packet.writeInt((int) clientParam);
packet.writeLongInt(this.maxThreeBytes);
}
// User/Password data
packet.writeString(user);
if (this.protocolVersion > 9) {
packet.writeString(Util.newCrypt(password, this.seed));
} else {
packet.writeString(Util.oldCrypt(password, this.seed));
}
if (((serverCapabilities & CLIENT_CONNECT_WITH_DB) != 0)
&& (database != null) && (database.length() > 0)) {
packet.writeString(database);
}
send(packet);
}
} else {
boolean doSecureAuth = false;
if ((serverCapabilities & CLIENT_SECURE_CONNECTION) != 0) {
clientParam |= CLIENT_SECURE_CONNECTION;
doSecureAuth = true;
}
clientParam |= CLIENT_SSL;
packet = new Buffer(packLength);
if ((clientParam & CLIENT_RESERVED) != 0) {
packet.writeLong(clientParam);
} else {
packet.writeInt((int) clientParam);
}
send(packet);
javax.net.ssl.SSLSocketFactory sslFact = (javax.net.ssl.SSLSocketFactory) javax.net.ssl.SSLSocketFactory
.getDefault();
try {
this.mysqlConnection = sslFact.createSocket(this.mysqlConnection,
this.host, this.port, true);
// need to force TLSv1, or else JSSE tries to do a SSLv2 handshake
// which MySQL doesn't understand
((javax.net.ssl.SSLSocket) this.mysqlConnection)
.setEnabledProtocols(new String[] { "TLSv1" });
((javax.net.ssl.SSLSocket) this.mysqlConnection).startHandshake();
this.mysqlInput = new BufferedInputStream(this.mysqlConnection
.getInputStream(), 16384);
this.mysqlOutput = new BufferedOutputStream(this.mysqlConnection
.getOutputStream(), 16384);
this.mysqlOutput.flush();
} catch (IOException ioEx) {
StringBuffer message = new StringBuffer(SQLError.get(
SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE));
message.append(": ");
message.append(ioEx.getClass().getName());
message.append(", underlying cause: ");
message.append(ioEx.getMessage());
if (!this.connection.useParanoidErrorMessages()) {
message.append(Util.stackTraceToString(ioEx));
}
throw new java.sql.SQLException(message.toString(),
SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE, 0);
}
packet.clear();
if (doSecureAuth) {
if (versionMeetsMinimum(4, 1, 1)) {
secureAuth411(packLength, serverCapabilities, clientParam,
user, password, database);
} else {
secureAuth(packLength, serverCapabilities, clientParam,
user, password, database);
}
} else {
if ((clientParam & CLIENT_RESERVED) != 0) {
packet.writeLong(clientParam);
packet.writeLong(this.maxThreeBytes);
} else {
packet.writeInt((int) clientParam);
packet.writeLongInt(this.maxThreeBytes);
}
// User/Password data
packet.writeString(user);
if (this.protocolVersion > 9) {
packet.writeString(Util.newCrypt(password, seed));
} else {
packet.writeString(Util.oldCrypt(password, seed));
}
if (((serverCapabilities & CLIENT_CONNECT_WITH_DB) != 0)
&& (database != null) && (database.length() > 0)) {
packet.writeString(database);
}
send(packet);
}
}
// Check for errors, not for 4.1.1 or newer,
// as the new auth protocol doesn't work that way
// (see secureAuth411() for more details...)
if (!versionMeetsMinimum(4, 1, 1)) {
checkErrorPacket();
}
//
// Can't enable compression until after handshake
//
if (((serverCapabilities & CLIENT_COMPRESS) != 0)
&& this.connection.useCompression()) {
// The following matches with ZLIB's
// compress()
this.deflater = new Deflater();
this.useCompression = true;
this.mysqlInput = new CompressedInputStream(this.mysqlInput);
}
if (((serverCapabilities & CLIENT_CONNECT_WITH_DB) == 0)
&& (database != null) && (database.length() > 0)) {
try {
sendCommand(MysqlDefs.INIT_DB, database, null);
} catch (Exception ex) {
throw new SQLException(ex.toString(),
SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE);
}
}
}
/**
* Retrieve one row from the MySQL server. Note: this method is not
* thread-safe, but it is only called from methods that are guarded by
* synchronizing on this object.
*
* @param columnCount DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws Exception DOCUMENT ME!
*/
final byte[][] nextRow(int columnCount) throws Exception {
// Get the next incoming packet, re-using the packet because
// all the data we need gets copied out of it.
Buffer rowPacket = checkErrorPacket();
//
// Didn't read an error, so re-position to beginning
// of packet in order to read result set data
//
int offset = 0;
//if (rowPacket.wasMultiPacket()) {
// if (this.useNewLargePackets) {
// offset = HEADER_LENGTH;
// } else {
// offset = HEADER_LENGTH + 1;
// }
//}
rowPacket.setPosition(rowPacket.getPosition() - 1);
byte[][] rowData = new byte[columnCount][];
if (!rowPacket.isLastDataPacket()) {
for (int i = 0; i < columnCount; i++) {
rowData[i] = rowPacket.readLenByteArray(offset);
if (Driver.TRACE) {
if (rowData[i] == null) {
Debug.msg(this, "Field value: NULL");
} else {
Debug.msg(this, "Field value: " + rowData[i].toString());
}
}
}
return rowData;
}
return null;
}
/**
* Log-off of the MySQL server and close the socket.
*
* @throws SQLException DOCUMENT ME!
*/
final void quit() throws SQLException {
Buffer packet = new Buffer(6);
this.packetSequence = -1;
packet.writeByte((byte) MysqlDefs.QUIT);
send(packet);
forceClose();
}
/**
* Returns the packet used for sending data (used by PreparedStatement)
* Guarded by external synchronization on a mutex.
*
* @return A packet to send data with
*/
Buffer getSharedSendPacket() {
if (this.sharedSendPacket == null) {
this.sharedSendPacket = new Buffer(this.connection
.getNetBufferLength());
}
return this.sharedSendPacket;
}
void closeStreamer(RowData streamer) throws SQLException {
if (this.streamingData == null) {
throw new SQLException("Attempt to close streaming result set "
+ streamer
+ " when no streaming result set was registered. This is an internal error.");
}
if (streamer != this.streamingData) {
throw new SQLException("Attempt to close streaming result set "
+ streamer + " that was not registered."
+ " Only one streaming result set may be open and in use per-connection. Ensure that you have called .close() on "
+ " any active result sets before attempting more queries.");
}
this.streamingData = null;
}
/**
* Sets the buffer size to max-buf
*/
void resetMaxBuf() {
this.maxAllowedPacket = this.connection.getMaxAllowedPacket();
}
/**
* Send a command to the MySQL server If data is to be sent with command,
* it should be put in ExtraData Raw packets can be sent by setting
* QueryPacket to something other than null.
*
* @param command DOCUMENT ME!
* @param extraData DOCUMENT ME!
* @param queryPacket DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws Exception DOCUMENT ME!
* @throws java.sql.SQLException DOCUMENT ME!
*/
final Buffer sendCommand(int command, String extraData, Buffer queryPacket)
throws Exception {
checkForOutstandingStreamingData();
try {
if (this.clearStreamBeforeEachQuery) {
clearInputStream();
}
//
// PreparedStatements construct their own packets,
// for efficiency's sake.
//
// If this is a generic query, we need to re-use
// the sending packet.
//
if (queryPacket == null) {
int packLength = HEADER_LENGTH + COMP_HEADER_LENGTH + 1
+ ((extraData != null) ? extraData.length() : 0) + 2;
if (this.sendPacket == null) {
this.sendPacket = new Buffer(packLength);
}
this.packetSequence = -1;
this.sendPacket.clear();
// Offset different for compression
if (this.useCompression) {
this.sendPacket.setPosition(this.sendPacket.getPosition()
+ COMP_HEADER_LENGTH);
}
this.sendPacket.writeByte((byte) command);
if ((command == MysqlDefs.INIT_DB)
|| (command == MysqlDefs.CREATE_DB)
|| (command == MysqlDefs.DROP_DB)
|| (command == MysqlDefs.QUERY)) {
this.sendPacket.writeStringNoNull(extraData);
} else if (command == MysqlDefs.PROCESS_KILL) {
long id = new Long(extraData).longValue();
this.sendPacket.writeLong(id);
} else if ((command == MysqlDefs.RELOAD)
&& (this.protocolVersion > 9)) {
Debug.msg(this, "Reload");
//Packet.writeByte(reloadParam);
}
send(this.sendPacket);
} else {
this.packetSequence = -1;
send(queryPacket); // packet passed by PreparedStatement
}
} catch (SQLException sqlEx) {
// don't wrap SQLExceptions
throw sqlEx;
} catch (Exception ex) {
String underlyingMessage = ex.getMessage();
throw new java.sql.SQLException(SQLError.get(
SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE) + ": "
+ ex.getClass().getName() + ", "
+ ((underlyingMessage != null) ? underlyingMessage
: "no message given by JVM"),
SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE, 0);
}
return checkErrorPacket(command);
}
/**
* Send a query specified in the String "Query" to the MySQL server. This
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -