提交 c1a4cb09 编写于 作者: T terrymanu

abstract base component and mysql component

上级 dd37d83f
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package io.shardingjdbc.proxy.packet;
import lombok.Getter;
import lombok.Setter;
/**
* MySQL packet.
*
* @author zhangliang
*/
@Getter
@Setter
public abstract class MySQLPacket {
public static final int PAYLOAD_LENGTH = 3;
public static final int SEQUENCE_LENGTH = 1;
private int sequenceId;
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package io.shardingjdbc.proxy.packet;
import com.google.common.base.Strings;
import io.netty.buffer.ByteBuf;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* Payload operation for MySQL packet data types.
*
* @see <a href="https://dev.mysql.com/doc/internals/en/describing-packets.html">describing packets</a>
*
* @author zhangliang
*/
@RequiredArgsConstructor
@Getter
public final class MySQLPacketPayload {
private final ByteBuf byteBuf;
/**
* Read 1 byte fixed length integer from byte buffers.
* @see <a href="https://dev.mysql.com/doc/internals/en/integer.html#packet-Protocol::FixedLengthInteger">FixedLengthInteger</a>
*
* @return 1 byte fixed length integer
*/
public int readInt1() {
return byteBuf.readByte();
}
/**
* Write 1 byte fixed length integer to byte buffers.
* @see <a href="https://dev.mysql.com/doc/internals/en/integer.html#packet-Protocol::FixedLengthInteger">FixedLengthInteger</a>
*
* @param value 1 byte fixed length integer
*/
public void writeInt1(final int value) {
byteBuf.writeByte(value);
}
/**
* Read 2 byte fixed length integer from byte buffers.
* @see <a href="https://dev.mysql.com/doc/internals/en/integer.html#packet-Protocol::FixedLengthInteger">FixedLengthInteger</a>
*
* @return 2 byte fixed length integer
*/
public int readInt2() {
return byteBuf.readShortLE();
}
/**
* Write 2 byte fixed length integer to byte buffers.
* @see <a href="https://dev.mysql.com/doc/internals/en/integer.html#packet-Protocol::FixedLengthInteger">FixedLengthInteger</a>
*
* @param value 2 byte fixed length integer
*/
public void writeInt2(final int value) {
byteBuf.writeShortLE(value);
}
/**
* Read 3 byte fixed length integer from byte buffers.
* @see <a href="https://dev.mysql.com/doc/internals/en/integer.html#packet-Protocol::FixedLengthInteger">FixedLengthInteger</a>
*
* @return 3 byte fixed length integer
*/
public int readInt3() {
return byteBuf.readMediumLE();
}
/**
* Write 3 byte fixed length integer to byte buffers.
* @see <a href="https://dev.mysql.com/doc/internals/en/integer.html#packet-Protocol::FixedLengthInteger">FixedLengthInteger</a>
*
* @param value 3 byte fixed length integer
*/
public void writeInt3(final int value) {
byteBuf.writeMediumLE(value);
}
/**
* Read 4 byte fixed length integer from byte buffers.
* @see <a href="https://dev.mysql.com/doc/internals/en/integer.html#packet-Protocol::FixedLengthInteger">FixedLengthInteger</a>
*
* @return 4 byte fixed length integer
*/
public int readInt4() {
return byteBuf.readIntLE();
}
/**
* Write 4 byte fixed length integer to byte buffers.
* @see <a href="https://dev.mysql.com/doc/internals/en/integer.html#packet-Protocol::FixedLengthInteger">FixedLengthInteger</a>
*
* @param value 4 byte fixed length integer
*/
public void writeInt4(final int value) {
byteBuf.writeIntLE(value);
}
/**
* Read 6 byte fixed length integer from byte buffers.
* @see <a href="https://dev.mysql.com/doc/internals/en/integer.html#packet-Protocol::FixedLengthInteger">FixedLengthInteger</a>
*
* @return 6 byte fixed length integer
*/
public int readInt6() {
// TODO
return 0;
}
/**
* Write 6 byte fixed length integer to byte buffers.
* @see <a href="https://dev.mysql.com/doc/internals/en/integer.html#packet-Protocol::FixedLengthInteger">FixedLengthInteger</a>
*
* @param value 6 byte fixed length integer
*/
public void writeInt6(final int value) {
// TODO
}
/**
* Read 8 byte fixed length integer from byte buffers.
* @see <a href="https://dev.mysql.com/doc/internals/en/integer.html#packet-Protocol::FixedLengthInteger">FixedLengthInteger</a>
*
* @return 8 byte fixed length integer
*/
public long readInt8() {
return byteBuf.readLongLE();
}
/**
* Write 8 byte fixed length integer to byte buffers.
* @see <a href="https://dev.mysql.com/doc/internals/en/integer.html#packet-Protocol::FixedLengthInteger">FixedLengthInteger</a>
*
* @param value 8 byte fixed length integer
*/
public void writeInt8(final long value) {
byteBuf.writeLongLE(value);
}
/**
* Read length encoded integer from byte buffers.
* @see <a href="https://dev.mysql.com/doc/internals/en/integer.html#packet-Protocol::LengthEncodedInteger">LengthEncodedInteger</a>
*
* @return length encoded integer
*/
public long readIntLenenc() {
int firstByte = byteBuf.readByte();
if (firstByte <= 0xfb) {
return firstByte;
}
if (0xfc == firstByte) {
return byteBuf.readShortLE();
}
if (0xfd == firstByte) {
return byteBuf.readMediumLE();
}
return byteBuf.readLongLE();
}
/**
* Write length encoded integer to byte buffers.
* @see <a href="https://dev.mysql.com/doc/internals/en/integer.html#packet-Protocol::LengthEncodedInteger">LengthEncodedInteger</a>
*
* @param value length encoded integer
*/
public void writeIntLenenc(final long value) {
if (value < 251) {
byteBuf.writeByte((int) value);
return;
}
if (value >= 251 && value < Math.pow(2, 16)) {
byteBuf.writeByte(0xfc);
byteBuf.writeShortLE((int) value);
return;
}
if (value <= Math.pow(2, 16) && value < Math.pow(2, 24)) {
byteBuf.writeByte(0xfd);
byteBuf.writeInt((int) value);
return;
}
byteBuf.writeByte(0xfe);
byteBuf.writeLongLE(value);
}
/**
* Read fixed length string from byte buffers.
* @see <a href="https://dev.mysql.com/doc/internals/en/string.html#packet-Protocol::FixedLengthString">FixedLengthString</a>
*
* @return fixed length string
*/
public String readStringLenenc() {
int length = (int) readIntLenenc();
byte[] result = new byte[length];
byteBuf.readBytes(result);
return new String(result);
}
/**
* Write fixed length string to byte buffers.
* @see <a href="https://dev.mysql.com/doc/internals/en/string.html#packet-Protocol::FixedLengthString">FixedLengthString</a>
*
* @param value fixed length string
*/
public void writeStringLenenc(final String value) {
if (Strings.isNullOrEmpty(value)) {
byteBuf.writeByte(0);
return;
}
writeIntLenenc(value.getBytes().length);
byteBuf.writeBytes(value.getBytes());
}
/**
* Read fixed length string from byte buffers.
* @see <a href="https://dev.mysql.com/doc/internals/en/string.html#packet-Protocol::FixedLengthString">FixedLengthString</a>
*
* @param length length of fixed string
*
* @return fixed length string
*/
public String readStringFix(final int length) {
byte[] result = new byte[length];
byteBuf.readBytes(result);
return new String(result);
}
/**
* Write variable length string to byte buffers.
* @see <a href="https://dev.mysql.com/doc/internals/en/string.html#packet-Protocol::FixedLengthString">FixedLengthString</a>
*
* @param value fixed length string
*/
public void writeStringFix(final String value) {
byteBuf.writeBytes(value.getBytes());
}
/**
* Read variable length string from byte buffers.
* @see <a href="https://dev.mysql.com/doc/internals/en/string.html#packet-Protocol::VariableLengthString">FixedLengthString</a>
*
* @return variable length string
*/
public String readStringVar() {
// TODO
return "";
}
/**
* Write fixed length string to byte buffers.
* @see <a href="https://dev.mysql.com/doc/internals/en/string.html#packet-Protocol::VariableLengthString">FixedLengthString</a>
*
* @param value variable length string
*/
public void writeStringVar(final String value) {
// TODO
}
/**
* Read null terminated string from byte buffers.
* @see <a href="https://dev.mysql.com/doc/internals/en/string.html#packet-Protocol::NulTerminatedString">NulTerminatedString</a>
*
* @return null terminated string
*/
public String readStringNul() {
byte[] result = new byte[byteBuf.bytesBefore((byte) 0)];
byteBuf.readBytes(result);
byteBuf.skipBytes(1);
return new String(result);
}
/**
* Write null terminated string to byte buffers.
* @see <a href="https://dev.mysql.com/doc/internals/en/string.html#packet-Protocol::NulTerminatedString">NulTerminatedString</a>
*
* @param value null terminated string
*/
public void writeStringNul(final String value) {
byteBuf.writeBytes(value.getBytes());
byteBuf.writeByte(0);
}
/**
* Read rest of packet string from byte buffers.
* @see <a href="https://dev.mysql.com/doc/internals/en/string.html#packet-Protocol::RestOfPacketString">RestOfPacketString</a>
*
* @return rest of packet string
*/
public String readStringEOF() {
byte[] result = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(result);
return new String(result);
}
/**
* Write rest of packet string to byte buffers.
* @see <a href="https://dev.mysql.com/doc/internals/en/string.html#packet-Protocol::RestOfPacketString">RestOfPacketString</a>
*
* @param value rest of packet string
*/
public void writeStringEOF(final String value) {
byteBuf.writeBytes(value.getBytes());
}
/**
* Skip reserved from byte buffers.
*
* @param length length of reserved
*/
public void skipReserved(final int length) {
byteBuf.skipBytes(length);
}
/**
* Write null for reserved to byte buffers.
*
* @param length length of reserved
*/
public void writeReserved(final int length) {
for (int i = 0; i < length; i++) {
byteBuf.writeByte(0);
}
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package io.shardingjdbc.proxy.packet;
/**
* MySQL received packet.
*
* @author zhangliang
*/
public abstract class MySQLReceivedPacket extends MySQLPacket {
/**
* Read packet from byte buffer.
*
* @param mysqlPacketPayload packet payload to be read
*
* @return instance of received packet
*/
public abstract MySQLReceivedPacket read(MySQLPacketPayload mysqlPacketPayload);
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package io.shardingjdbc.proxy.packet;
/**
* MySQL send packet.
*
* @author zhangliang
*/
public abstract class MySQLSentPacket extends MySQLPacket {
/**
* Write packet to byte buffer.
*
* @param mysqlPacketPayload packet payload to be write
*/
public abstract void write(MySQLPacketPayload mysqlPacketPayload);
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package io.shardingjdbc.proxy.packet.command;
import io.shardingjdbc.proxy.constant.ColumnType;
import io.shardingjdbc.proxy.constant.ServerInfo;
import io.shardingjdbc.proxy.packet.MySQLPacketPayload;
import io.shardingjdbc.proxy.packet.MySQLSentPacket;
/**
* Column definition above MySQL 4.1 packet protocol.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-query-response.html#packet-Protocol::ColumnDefinition41">ColumnDefinition41</a>
*
* @author zhangliang
*/
public final class ColumnDefinition41Packet extends MySQLSentPacket {
private final String catalog = "def";
private final int nextLength = 0x0c;
private final int characterSet = ServerInfo.CHARSET;
private final int flags = 0;
private final String schema;
private final String table;
private final String orgTable;
private final String name;
private final String orgName;
private final int columnLength;
private final ColumnType columnType;
private final int decimals;
public ColumnDefinition41Packet(final int sequenceId, final String schema, final String table, final String orgTable,
final String name, final String orgName, final int columnLength, final ColumnType columnType, final int decimals) {
setSequenceId(sequenceId);
this.schema = schema;
this.table = table;
this.orgTable = orgTable;
this.name = name;
this.orgName = orgName;
this.columnLength = columnLength;
this.columnType = columnType;
this.decimals = decimals;
}
@Override
public void write(final MySQLPacketPayload mysqlPacketPayload) {
mysqlPacketPayload.writeStringLenenc(catalog);
mysqlPacketPayload.writeStringLenenc(schema);
mysqlPacketPayload.writeStringLenenc(table);
mysqlPacketPayload.writeStringLenenc(orgTable);
mysqlPacketPayload.writeStringLenenc(name);
mysqlPacketPayload.writeStringLenenc(orgName);
mysqlPacketPayload.writeIntLenenc(nextLength);
mysqlPacketPayload.writeInt2(characterSet);
mysqlPacketPayload.writeInt4(columnLength);
mysqlPacketPayload.writeInt1(columnType.getValue());
mysqlPacketPayload.writeInt2(flags);
mysqlPacketPayload.writeInt1(decimals);
mysqlPacketPayload.writeReserved(2);
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package io.shardingjdbc.proxy.packet.command;
import io.shardingjdbc.core.constant.ShardingConstant;
import io.shardingjdbc.proxy.backend.DataSourceManager;
import io.shardingjdbc.proxy.constant.ColumnType;
import io.shardingjdbc.proxy.constant.StatusFlag;
import io.shardingjdbc.proxy.packet.MySQLSentPacket;
import io.shardingjdbc.proxy.packet.MySQLPacketPayload;
import io.shardingjdbc.proxy.packet.ok.EofPacket;
import io.shardingjdbc.proxy.packet.ok.ErrPacket;
import lombok.extern.slf4j.Slf4j;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.LinkedList;
import java.util.List;
/**
* COM_FIELD_LIST command packet.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-field-list.html">COM_FIELD_LIST</a>
*
* @author zhangliang
*/
@Slf4j
public final class ComFieldListPacket extends CommandPacket {
private String table;
private String fieldWildcard;
@Override
public ComFieldListPacket read(final MySQLPacketPayload mysqlPacketPayload) {
table = mysqlPacketPayload.readStringNul();
fieldWildcard = mysqlPacketPayload.readStringEOF();
log.debug("table name received for Sharding-Proxy: {}", table);
log.debug("field wildcard received for Sharding-Proxy: {}", fieldWildcard);
return this;
}
@Override
public List<MySQLSentPacket> execute() {
String sql = String.format("SHOW COLUMNS FROM %s FROM %s", table, ShardingConstant.LOGIC_SCHEMA_NAME);
List<MySQLSentPacket> result = new LinkedList<>();
int currentSequenceId = getSequenceId();
try (
Connection conn = DataSourceManager.getInstance().getDataSource().getConnection();
Statement statement = conn.createStatement()) {
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()) {
String field = resultSet.getString(1);
String type = resultSet.getString(2);
int columnLength = Integer.parseInt(type.substring(type.indexOf('(', type.indexOf(')'))));
ColumnType columnType = ColumnType.valueOfDescription(type.substring(0, type.indexOf('(')));
result.add(new ColumnDefinition41Packet(++currentSequenceId, ShardingConstant.LOGIC_SCHEMA_NAME, table, table, field, field, columnLength, columnType, 0));
}
result.add(new EofPacket(++currentSequenceId, 0, StatusFlag.SERVER_STATUS_AUTOCOMMIT.getValue()));
return result;
} catch (final SQLException ex) {
result.add(new ErrPacket(++currentSequenceId, ex.getErrorCode(), "", ex.getSQLState(), ex.getMessage()));
return result;
} catch (final Exception ex) {
if (ex.getCause() instanceof SQLException) {
SQLException cause = (SQLException) ex.getCause();
result.add(new ErrPacket(++currentSequenceId, cause.getErrorCode(), "", cause.getSQLState(), cause.getMessage()));
} else {
// TODO standard ShardingJdbcException
result.add(new ErrPacket(++currentSequenceId, 99, "", "unknown", ex.getMessage()));
}
return result;
}
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package io.shardingjdbc.proxy.packet.command;
import io.shardingjdbc.core.constant.ShardingConstant;
import io.shardingjdbc.proxy.constant.StatusFlag;
import io.shardingjdbc.proxy.packet.MySQLSentPacket;
import io.shardingjdbc.proxy.packet.MySQLPacketPayload;
import io.shardingjdbc.proxy.packet.ok.ErrPacket;
import io.shardingjdbc.proxy.packet.ok.OKPacket;
import lombok.extern.slf4j.Slf4j;
import java.util.Collections;
import java.util.List;
/**
* COM_INIT_DB command packet.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-init-db.html#packet-COM_INIT_DB">COM_INIT_DB</a>
*
* @author zhangliang
*/
@Slf4j
public final class ComInitDbPacket extends CommandPacket {
private String schemaName;
@Override
public ComInitDbPacket read(final MySQLPacketPayload mysqlPacketPayload) {
schemaName = mysqlPacketPayload.readStringEOF();
log.debug("Schema name received for Sharding-Proxy: {}", schemaName);
return this;
}
@Override
public List<MySQLSentPacket> execute() {
if (ShardingConstant.LOGIC_SCHEMA_NAME.equalsIgnoreCase(schemaName)) {
return Collections.<MySQLSentPacket>singletonList(new OKPacket(getSequenceId() + 1, 0, 0, StatusFlag.SERVER_STATUS_AUTOCOMMIT.getValue(), 0, ""));
}
return Collections.<MySQLSentPacket>singletonList(new ErrPacket(getSequenceId() + 1, 1049, "", "", String.format("Unknown database '%s'", schemaName)));
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package io.shardingjdbc.proxy.packet.command;
import io.shardingjdbc.core.parsing.SQLJudgeEngine;
import io.shardingjdbc.core.parsing.parser.sql.SQLStatement;
import io.shardingjdbc.proxy.backend.DataSourceManager;
import io.shardingjdbc.proxy.constant.ColumnType;
import io.shardingjdbc.proxy.constant.StatusFlag;
import io.shardingjdbc.proxy.packet.MySQLSentPacket;
import io.shardingjdbc.proxy.packet.MySQLPacketPayload;
import io.shardingjdbc.proxy.packet.ok.EofPacket;
import io.shardingjdbc.proxy.packet.ok.ErrPacket;
import io.shardingjdbc.proxy.packet.ok.OKPacket;
import lombok.extern.slf4j.Slf4j;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.LinkedList;
import java.util.List;
/**
* COM_QUERY command packet.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-query.html">COM_QUERY</a>
*
* @author zhangliang
*/
@Slf4j
public final class ComQueryPacket extends CommandPacket {
private String sql;
@Override
public ComQueryPacket read(final MySQLPacketPayload mysqlPacketPayload) {
sql = mysqlPacketPayload.readStringEOF();
log.debug("SQL received for Sharding-Proxy: {}", sql);
return this;
}
@Override
public List<MySQLSentPacket> execute() {
List<MySQLSentPacket> result = new LinkedList<>();
int currentSequenceId = getSequenceId();
try (
Connection conn = DataSourceManager.getInstance().getDataSource().getConnection();
Statement statement = conn.createStatement()) {
SQLStatement sqlStatement = new SQLJudgeEngine(sql).judge();
ResultSet resultSet;
switch (sqlStatement.getType()) {
case DQL:
resultSet = statement.executeQuery(sql);
break;
case DML:
case DDL:
statement.executeUpdate(sql);
resultSet = statement.getResultSet();
break;
default:
statement.execute(sql);
resultSet = statement.getResultSet();
break;
}
if (null == resultSet) {
result.add(new OKPacket(++currentSequenceId, 0, 0, StatusFlag.SERVER_STATUS_AUTOCOMMIT.getValue(), 0, ""));
return result;
}
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
int columnCount = resultSetMetaData.getColumnCount();
if (0 == columnCount) {
result.add(new OKPacket(++currentSequenceId, 0, 0, StatusFlag.SERVER_STATUS_AUTOCOMMIT.getValue(), 0, ""));
return result;
}
result.add(new FieldCountPacket(++currentSequenceId, columnCount));
for (int i = 1; i <= columnCount; i++) {
result.add(new ColumnDefinition41Packet(++currentSequenceId, resultSetMetaData.getSchemaName(i), resultSetMetaData.getTableName(i),
resultSetMetaData.getTableName(i), resultSetMetaData.getColumnLabel(i), resultSetMetaData.getColumnName(i),
resultSetMetaData.getColumnDisplaySize(i), ColumnType.valueOfJDBCType(resultSetMetaData.getColumnType(i)), 0));
}
result.add(new EofPacket(++currentSequenceId, 0, StatusFlag.SERVER_STATUS_AUTOCOMMIT.getValue()));
while (resultSet.next()) {
List<Object> data = new LinkedList<>();
for (int i = 1; i <= columnCount; i++) {
data.add(resultSet.getObject(i));
}
result.add(new TextResultSetRowPacket(++currentSequenceId, data));
}
result.add(new EofPacket(++currentSequenceId, 0, StatusFlag.SERVER_STATUS_AUTOCOMMIT.getValue()));
} catch (final SQLException ex) {
result.add(new ErrPacket(++currentSequenceId, ex.getErrorCode(), "", ex.getSQLState(), ex.getMessage()));
return result;
} catch (final Exception ex) {
if (ex.getCause() instanceof SQLException) {
SQLException cause = (SQLException) ex.getCause();
result.add(new ErrPacket(++currentSequenceId, cause.getErrorCode(), "", cause.getSQLState(), cause.getMessage()));
} else {
// TODO standard ShardingJdbcException
result.add(new ErrPacket(++currentSequenceId, 99, "", "unknown", ex.getMessage()));
}
return result;
}
return result;
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package io.shardingjdbc.proxy.packet.command;
import io.shardingjdbc.proxy.constant.StatusFlag;
import io.shardingjdbc.proxy.packet.MySQLSentPacket;
import io.shardingjdbc.proxy.packet.MySQLPacketPayload;
import io.shardingjdbc.proxy.packet.ok.OKPacket;
import java.util.Collections;
import java.util.List;
/**
* COM_QUIT command packet.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-quit.html">COM_QUIT</a>
*
* @author zhangliang
*/
public final class ComQuitPacket extends CommandPacket {
@Override
public ComQuitPacket read(final MySQLPacketPayload mysqlPacketPayload) {
return this;
}
@Override
public List<MySQLSentPacket> execute() {
return Collections.<MySQLSentPacket>singletonList(new OKPacket(getSequenceId() + 1, 0, 0, StatusFlag.SERVER_STATUS_AUTOCOMMIT.getValue(), 0, ""));
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package io.shardingjdbc.proxy.packet.command;
import io.shardingjdbc.proxy.packet.MySQLReceivedPacket;
import io.shardingjdbc.proxy.packet.MySQLSentPacket;
import java.util.List;
/**
* Command packet.
*
* @author zhangliang
*/
public abstract class CommandPacket extends MySQLReceivedPacket {
/**
* Execute command.
*
* @return result packets to be sent
*/
public abstract List<MySQLSentPacket> execute();
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package io.shardingjdbc.proxy.packet.command;
/**
* Command packet factory.
*
* @author zhangliang
*/
public final class CommandPacketFactory {
/**
* Get command Packet.
*
* @param commandPacketTypeValue command packet type value
* @return Command packet
*/
public static CommandPacket getCommandPacket(final int commandPacketTypeValue) {
CommandPacketType type = CommandPacketType.valueOf(commandPacketTypeValue);
switch (type) {
case COM_QUIT:
return new ComQuitPacket();
case COM_INIT_DB:
return new ComInitDbPacket();
case COM_FIELD_LIST:
return new ComFieldListPacket();
case COM_QUERY:
return new ComQueryPacket();
case COM_SLEEP:
case COM_CREATE_DB:
case COM_DROP_DB:
case COM_REFRESH:
case COM_SHUTDOWN:
case COM_STATISTICS:
case COM_PROCESS_INFO:
case COM_CONNECT:
case COM_PROCESS_KILL:
case COM_DEBUG:
case COM_PING:
case COM_TIME:
case COM_DELAYED_INSERT:
case COM_CHANGE_USER:
case COM_BINLOG_DUMP:
case COM_TABLE_DUMP:
case COM_CONNECT_OUT:
case COM_REGISTER_SLAVE:
case COM_STMT_PREPARE:
case COM_STMT_EXECUTE:
case COM_STMT_SEND_LONG_DATA:
case COM_STMT_CLOSE:
case COM_STMT_RESET:
case COM_SET_OPTION:
case COM_STMT_FETCH:
case COM_DAEMON:
case COM_BINLOG_DUMP_GTID:
case COM_RESET_CONNECTION:
return new UnsupportedCommandPacket(type);
default:
return new UnsupportedCommandPacket(type);
}
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package io.shardingjdbc.proxy.packet.command;
import lombok.RequiredArgsConstructor;
/**
* Command packet type.
*
* @author zhangliang
*/
@RequiredArgsConstructor
public enum CommandPacketType {
/**
* COM_SLEEP.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_SLEEP">COM_SLEEP</a>
*/
COM_SLEEP(0x00),
/**
* COM_QUIT.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_QUIT">COM_QUIT</a>
*/
COM_QUIT(0x01),
/**
* COM_INIT_DB.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_INIT_DB">COM_INIT_DB</a>
*/
COM_INIT_DB(0x02),
/**
* COM_QUERY.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_QUERY">COM_QUERY</a>
*/
COM_QUERY(0x03),
/**
* COM_FIELD_LIST.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_FIELD_LIST">COM_FIELD_LIST</a>
*/
COM_FIELD_LIST(0x04),
/**
* COM_CREATE_DB.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_CREATE_DB">COM_CREATE_DB</a>
*/
COM_CREATE_DB(0x05),
/**
* COM_DROP_DB.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_DROP_DB">COM_DROP_DB</a>
*/
COM_DROP_DB(0x06),
/**
* COM_REFRESH.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_REFRESH">COM_REFRESH</a>
*/
COM_REFRESH(0x07),
/**
* COM_SHUTDOWN.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_SHUTDOWN">COM_SHUTDOWN</a>
*/
COM_SHUTDOWN(0x08),
/**
* COM_STATISTICS.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_STATISTICS">COM_STATISTICS</a>
*/
COM_STATISTICS(0x09),
/**
* COM_PROCESS_INFO.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_PROCESS_INFO">COM_PROCESS_INFO</a>
*/
COM_PROCESS_INFO(0x0a),
/**
* COM_CONNECT.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_CONNECT">COM_CONNECT</a>
*/
COM_CONNECT(0x0b),
/**
* COM_PROCESS_KILL.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_PROCESS_KILL">COM_PROCESS_KILL</a>
*/
COM_PROCESS_KILL(0x0c),
/**
* COM_DEBUG.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_DEBUG">COM_DEBUG</a>
*/
COM_DEBUG(0x0d),
/**
* COM_PING.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_PING">COM_PING</a>
*/
COM_PING(0x0e),
/**
* COM_TIME.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_TIME">COM_TIME</a>
*/
COM_TIME(0x0f),
/**
* COM_DELAYED_INSERT.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_DELAYED_INSERT">COM_DELAYED_INSERT</a>
*/
COM_DELAYED_INSERT(0x10),
/**
* COM_CHANGE_USER.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_CHANGE_USER">COM_CHANGE_USER</a>
*/
COM_CHANGE_USER(0x11),
/**
* COM_BINLOG_DUMP.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_BINLOG_DUMP">COM_BINLOG_DUMP</a>
*/
COM_BINLOG_DUMP(0x12),
/**
* COM_TABLE_DUMP.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_TABLE_DUMP">COM_TABLE_DUMP</a>
*/
COM_TABLE_DUMP(0x13),
/**
* COM_CONNECT_OUT.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_CONNECT_OUT">COM_CONNECT_OUT</a>
*/
COM_CONNECT_OUT(0x14),
/**
* COM_REGISTER_SLAVE.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_REGISTER_SLAVE">COM_REGISTER_SLAVE</a>
*/
COM_REGISTER_SLAVE(0x15),
/**
* COM_STMT_PREPARE.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_STMT_PREPARE">COM_STMT_PREPARE</a>
*/
COM_STMT_PREPARE(0x16),
/**
* COM_STMT_EXECUTE.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_STMT_EXECUTE">COM_STMT_EXECUTE</a>
*/
COM_STMT_EXECUTE(0x17),
/**
* COM_STMT_SEND_LONG_DATA.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_STMT_SEND_LONG_DATA">COM_STMT_SEND_LONG_DATA</a>
*/
COM_STMT_SEND_LONG_DATA(0x18),
/**
* COM_STMT_CLOSE.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_STMT_CLOSE">COM_STMT_CLOSE</a>
*/
COM_STMT_CLOSE(0x19),
/**
* COM_STMT_RESET.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_STMT_RESET">COM_STMT_RESET</a>
*/
COM_STMT_RESET(0x1a),
/**
* COM_SET_OPTION.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_SET_OPTION">COM_SET_OPTION</a>
*/
COM_SET_OPTION(0x1b),
/**
* COM_STMT_FETCH.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_STMT_FETCH">COM_STMT_FETCH</a>
*/
COM_STMT_FETCH(0x1c),
/**
* COM_DAEMON.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_DAEMON">COM_DAEMON</a>
*/
COM_DAEMON(0x1d),
/**
* COM_BINLOG_DUMP_GTID.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_BINLOG_DUMP_GTID">COM_BINLOG_DUMP_GTID</a>
*/
COM_BINLOG_DUMP_GTID(0x1e),
/**
* COM_RESET_CONNECTION.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-sleep.html#packet-COM_RESET_CONNECTION">COM_RESET_CONNECTION</a>
*/
COM_RESET_CONNECTION(0x1f);
private final int value;
/**
* Value of integer.
*
* @param value integer value
* @return command packet type enum
*/
public static CommandPacketType valueOf(final int value) {
for (CommandPacketType each : CommandPacketType.values()) {
if (value == each.value) {
return each;
}
}
throw new IllegalArgumentException(String.format("Cannot find '%s' in command packet type", value));
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package io.shardingjdbc.proxy.packet.command;
import io.shardingjdbc.proxy.packet.MySQLPacketPayload;
import io.shardingjdbc.proxy.packet.MySQLSentPacket;
/**
* COM_QUERY response field count packet.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-query-response.html">COM_QUERY field count</a>
*
* @author zhangliang
*/
public final class FieldCountPacket extends MySQLSentPacket {
private final long columnCount;
public FieldCountPacket(final int sequenceId, final long columnCount) {
setSequenceId(sequenceId);
this.columnCount = columnCount;
}
@Override
public void write(final MySQLPacketPayload mysqlPacketPayload) {
mysqlPacketPayload.writeIntLenenc(columnCount);
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package io.shardingjdbc.proxy.packet.command;
import io.shardingjdbc.proxy.packet.MySQLPacketPayload;
import io.shardingjdbc.proxy.packet.MySQLSentPacket;
import java.util.List;
/**
* Text result set row packet.
* @see <a href="https://dev.mysql.com/doc/internals/en/com-query-response.html#packet-ProtocolText::ResultsetRow">ResultsetRow</a>
*
* @author zhangliang
*/
public final class TextResultSetRowPacket extends MySQLSentPacket {
private static final int NULL = 0xfb;
private final List<Object> data;
public TextResultSetRowPacket(final int sequenceId, final List<Object> data) {
setSequenceId(sequenceId);
this.data = data;
}
@Override
public void write(final MySQLPacketPayload mysqlPacketPayload) {
for (Object each : data) {
if (null == each) {
mysqlPacketPayload.writeInt1(NULL);
} else {
mysqlPacketPayload.writeStringLenenc(each.toString());
}
}
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package io.shardingjdbc.proxy.packet.command;
import io.shardingjdbc.proxy.packet.MySQLPacketPayload;
import io.shardingjdbc.proxy.packet.MySQLSentPacket;
import io.shardingjdbc.proxy.packet.ok.ErrPacket;
import lombok.RequiredArgsConstructor;
import java.util.Collections;
import java.util.List;
/**
* Unsupported command packet.
*
* @author zhangliang
*/
@RequiredArgsConstructor
public final class UnsupportedCommandPacket extends CommandPacket {
private static final int ERROR_CODE = 0xcc;
private static final String SQL_STATE_MARKER = "x";
private static final String SQL_STATE = "xxxxx";
private static final String ERROR_MESSAGE = "Unsupported command packet '%s'.";
private final CommandPacketType type;
@Override
public UnsupportedCommandPacket read(final MySQLPacketPayload mysqlPacketPayload) {
return this;
}
@Override
public List<MySQLSentPacket> execute() {
return Collections.<MySQLSentPacket>singletonList(new ErrPacket(getSequenceId() + 1, ERROR_CODE, SQL_STATE_MARKER, SQL_STATE, String.format(ERROR_MESSAGE, type)));
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package io.shardingjdbc.proxy.packet.handshake;
import com.google.common.primitives.Bytes;
import lombok.Getter;
/**
* Auth plugin data.
*
* <p>
* The auth-plugin-data is the concatenation of strings auth-plugin-data-part-1 and auth-plugin-data-part-2.
* The auth-plugin-data-part-1's length is 8; The auth-plugin-data-part-2's length is 12.
* </p>
*
* @author zhangliang
*/
@Getter
public final class AuthPluginData {
private final byte[] authPluginDataPart1;
private final byte[] authPluginDataPart2;
private final byte[] authPluginData;
public AuthPluginData() {
authPluginDataPart1 = RandomGenerator.getInstance().generateRandomBytes(8);
authPluginDataPart2 = RandomGenerator.getInstance().generateRandomBytes(12);
authPluginData = Bytes.concat(authPluginDataPart1, authPluginDataPart2);
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package io.shardingjdbc.proxy.packet.handshake;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
/**
* Connection ID generator.
*
* @author zhangliang
*/
@NoArgsConstructor(access = AccessLevel.NONE)
public final class ConnectionIdGenerator {
@Getter
private static ConnectionIdGenerator instance = new ConnectionIdGenerator();
private int currentId;
/**
* Get next connection ID.
*
* @return next connection ID
*/
public synchronized int nextId() {
if (currentId >= Integer.MAX_VALUE) {
currentId = 0;
}
return ++currentId;
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package io.shardingjdbc.proxy.packet.handshake;
import io.shardingjdbc.proxy.constant.CapabilityFlag;
import io.shardingjdbc.proxy.constant.ServerInfo;
import io.shardingjdbc.proxy.constant.StatusFlag;
import io.shardingjdbc.proxy.packet.MySQLPacketPayload;
import io.shardingjdbc.proxy.packet.MySQLSentPacket;
import lombok.Getter;
/**
* Handshake packet protocol.
*
* @see <a href="https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::Handshake">Handshake</a>
*
* @author zhangliang
*/
@Getter
public class HandshakePacket extends MySQLSentPacket {
private final int protocolVersion = ServerInfo.PROTOCOL_VERSION;
private final String serverVersion = ServerInfo.SERVER_VERSION;
private final int capabilityFlagsLower = CapabilityFlag.calculateHandshakeCapabilityFlagsLower();
private final int characterSet = ServerInfo.CHARSET;
private final StatusFlag statusFlag = StatusFlag.SERVER_STATUS_AUTOCOMMIT;
private final int capabilityFlagsUpper = CapabilityFlag.calculateHandshakeCapabilityFlagsUpper();
private final int connectionId;
private final AuthPluginData authPluginData;
public HandshakePacket(final int connectionId, final AuthPluginData authPluginData) {
setSequenceId(0);
this.connectionId = connectionId;
this.authPluginData = authPluginData;
}
@Override
public void write(final MySQLPacketPayload mysqlPacketPayload) {
mysqlPacketPayload.writeInt1(protocolVersion);
mysqlPacketPayload.writeStringNul(serverVersion);
mysqlPacketPayload.writeInt4(connectionId);
mysqlPacketPayload.writeStringNul(new String(authPluginData.getAuthPluginDataPart1()));
mysqlPacketPayload.writeInt2(capabilityFlagsLower);
mysqlPacketPayload.writeInt1(ServerInfo.CHARSET);
mysqlPacketPayload.writeInt2(statusFlag.getValue());
mysqlPacketPayload.writeInt2(capabilityFlagsUpper);
mysqlPacketPayload.writeInt1(0);
mysqlPacketPayload.writeReserved(10);
mysqlPacketPayload.writeStringNul(new String(authPluginData.getAuthPluginDataPart2()));
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package io.shardingjdbc.proxy.packet.handshake;
import io.shardingjdbc.proxy.constant.CapabilityFlag;
import io.shardingjdbc.proxy.packet.MySQLPacketPayload;
import io.shardingjdbc.proxy.packet.MySQLReceivedPacket;
import lombok.Getter;
/**
* Handshake response above MySQL 4.1 packet protocol.
* @see <a href="https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::HandshakeResponse41">HandshakeResponse41</a>
*
* @author zhangliang
*/
@Getter
public final class HandshakeResponse41Packet extends MySQLReceivedPacket {
private int capabilityFlags;
private int maxPacketSize;
private int characterSet;
private String username;
private byte[] authResponse;
private String database;
@Override
public HandshakeResponse41Packet read(final MySQLPacketPayload mysqlPacketPayload) {
setSequenceId(mysqlPacketPayload.readInt1());
capabilityFlags = mysqlPacketPayload.readInt4();
maxPacketSize = mysqlPacketPayload.readInt4();
characterSet = mysqlPacketPayload.readInt1();
mysqlPacketPayload.skipReserved(23);
username = mysqlPacketPayload.readStringNul();
readAuthResponse(mysqlPacketPayload);
readDatabase(mysqlPacketPayload);
return this;
}
private void readAuthResponse(final MySQLPacketPayload mysqlPacketPayload) {
if (0 != (capabilityFlags & CapabilityFlag.CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA.getValue())) {
authResponse = mysqlPacketPayload.readStringLenenc().getBytes();
} else if (0 != (capabilityFlags & CapabilityFlag.CLIENT_SECURE_CONNECTION.getValue())) {
int length = mysqlPacketPayload.readInt1();
authResponse = mysqlPacketPayload.readStringFix(length).getBytes();
} else {
authResponse = mysqlPacketPayload.readStringNul().getBytes();
}
}
private void readDatabase(final MySQLPacketPayload mysqlPacketPayload) {
if (0 != (capabilityFlags & CapabilityFlag.CLIENT_CONNECT_WITH_DB.getValue())) {
database = mysqlPacketPayload.readStringNul();
}
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package io.shardingjdbc.proxy.packet.handshake;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.util.Random;
/**
* Random generator.
*
* @author zhangliang
*/
@NoArgsConstructor(access = AccessLevel.NONE)
public final class RandomGenerator {
@Getter
private static RandomGenerator instance = new RandomGenerator();
private static final byte[] SEED = {
'a', 'b', 'e', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', };
private Random random = new Random();
/**
* Generate random bytes.
*
* @param length length for generated bytes.
* @return generated bytes
*/
public byte[] generateRandomBytes(final int length) {
byte[] result = new byte[length];
for (int i = 0; i < length; i++) {
result[i] = SEED[random.nextInt(SEED.length)];
}
return result;
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package io.shardingjdbc.proxy.packet.ok;
import io.shardingjdbc.proxy.packet.MySQLPacketPayload;
import io.shardingjdbc.proxy.packet.MySQLSentPacket;
import lombok.Getter;
/**
* EOF packet protocol.
* @see <a href="https://dev.mysql.com/doc/internals/en/packet-EOF_Packet.html">EOF Packet</a>
*
* @author zhangliang
*/
@Getter
public class EofPacket extends MySQLSentPacket {
private static final int HEADER = 0xfe;
private final int warnings;
private final int statusFlags;
public EofPacket(final int sequenceId, final int warnings, final int statusFlags) {
setSequenceId(sequenceId);
this.warnings = warnings;
this.statusFlags = statusFlags;
}
@Override
public void write(final MySQLPacketPayload mysqlPacketPayload) {
mysqlPacketPayload.writeInt1(HEADER);
mysqlPacketPayload.writeInt2(warnings);
mysqlPacketPayload.writeInt2(statusFlags);
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package io.shardingjdbc.proxy.packet.ok;
import io.shardingjdbc.proxy.packet.MySQLPacketPayload;
import io.shardingjdbc.proxy.packet.MySQLSentPacket;
import lombok.Getter;
/**
* ERR packet protocol.
* @see <a href="https://dev.mysql.com/doc/internals/en/packet-ERR_Packet.html">ERR Packet</a>
*
* @author zhangliang
*/
@Getter
public class ErrPacket extends MySQLSentPacket {
private static final int HEADER = 0xff;
private final int errorCode;
private final String sqlStateMarker;
private final String sqlState;
private final String errorMessage;
public ErrPacket(final int sequenceId, final int errorCode, final String sqlStateMarker, final String sqlState, final String errorMessage) {
setSequenceId(sequenceId);
this.errorCode = errorCode;
this.sqlStateMarker = sqlStateMarker;
this.sqlState = sqlState;
this.errorMessage = errorMessage;
}
@Override
public void write(final MySQLPacketPayload mysqlPacketPayload) {
mysqlPacketPayload.writeInt1(HEADER);
mysqlPacketPayload.writeInt2(errorCode);
mysqlPacketPayload.writeStringFix(sqlStateMarker);
mysqlPacketPayload.writeStringFix(sqlState);
mysqlPacketPayload.writeStringEOF(errorMessage);
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package io.shardingjdbc.proxy.packet.ok;
import io.shardingjdbc.proxy.packet.MySQLPacketPayload;
import io.shardingjdbc.proxy.packet.MySQLSentPacket;
import lombok.Getter;
/**
* OK packet protocol.
* @see <a href="https://dev.mysql.com/doc/internals/en/packet-OK_Packet.html">OK Packet</a>
*
* @author zhangliang
*/
@Getter
public class OKPacket extends MySQLSentPacket {
private static final int HEADER = 0x00;
private final long affectedRows;
private final long lastInsertId;
private final int statusFlags;
private final int warnings;
private final String info;
public OKPacket(final int sequenceId, final long affectedRows, final long lastInsertId, final int statusFlags, final int warnings, final String info) {
setSequenceId(sequenceId);
this.affectedRows = affectedRows;
this.lastInsertId = lastInsertId;
this.statusFlags = statusFlags;
this.warnings = warnings;
this.info = info;
}
@Override
public void write(final MySQLPacketPayload mysqlPacketPayload) {
mysqlPacketPayload.writeInt1(HEADER);
mysqlPacketPayload.writeIntLenenc(affectedRows);
mysqlPacketPayload.writeIntLenenc(lastInsertId);
mysqlPacketPayload.writeInt2(statusFlags);
mysqlPacketPayload.writeInt2(warnings);
mysqlPacketPayload.writeStringEOF(info);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册