/*
* Copyright (c) 2013, OpenCloudDB/MyCAT and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software;Designed and Developed mainly by many Chinese
* opensource volunteers. you can redistribute it and/or modify it under the
* terms of the GNU General Public License version 2 only, as published by the
* Free Software Foundation.
*
* This code 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 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Any questions about this component can be directed to it's project Web address
* https://code.google.com/p/opencloudb/.
*
*/
package org.opencloudb.server.response;
import static org.opencloudb.server.parser.ServerParseSet.CHARACTER_SET_CLIENT;
import static org.opencloudb.server.parser.ServerParseSet.CHARACTER_SET_CONNECTION;
import static org.opencloudb.server.parser.ServerParseSet.CHARACTER_SET_RESULTS;
import org.apache.log4j.Logger;
import org.opencloudb.config.ErrorCode;
import org.opencloudb.net.mysql.OkPacket;
import org.opencloudb.server.ServerConnection;
import org.opencloudb.server.parser.ServerParseSet;
import org.opencloudb.util.SplitUtil;
/**
* 字符集属性设置
*/
/**
* @author mycat
*/
public class CharacterSet {
private static final Logger logger = Logger.getLogger(CharacterSet.class);
public static void response(String stmt, ServerConnection c, int rs) {
if (-1 == stmt.indexOf(',')) {
/* 单个属性 */
oneSetResponse(stmt, c, rs);
} else {
/* 多个属性 ,但是只关注CHARACTER_SET_RESULTS,CHARACTER_SET_CONNECTION */
multiSetResponse(stmt, c, rs);
}
}
private static void oneSetResponse(String stmt, ServerConnection c, int rs) {
if ((rs & 0xff) == CHARACTER_SET_CLIENT) {
/* 忽略client属性设置 */
c.write(c.writeToBuffer(OkPacket.OK, c.allocate()));
} else {
String charset = stmt.substring(rs >>> 8).trim();
if (charset.endsWith(";")) {
/* 结尾为 ; 标识符 */
charset = charset.substring(0, charset.length() - 1);
}
if (charset.startsWith("'") || charset.startsWith("`")) {
/* 与mysql保持一致,引号里的字符集不做trim操作 */
charset = charset.substring(1, charset.length() - 1);
}
// 设置字符集
setCharset(charset, c);
}
}
private static void multiSetResponse(String stmt, ServerConnection c, int rs) {
String charResult = "null";
String charConnection = "null";
String[] sqlList = SplitUtil.split(stmt, ',', false);
// check first
switch (rs & 0xff) {
case CHARACTER_SET_RESULTS:
charResult = sqlList[0].substring(rs >>> 8).trim();
break;
case CHARACTER_SET_CONNECTION:
charConnection = sqlList[0].substring(rs >>> 8).trim();
break;
}
// check remaining
for (int i = 1; i < sqlList.length; i++) {
String sql = new StringBuilder("set ").append(sqlList[i]).toString();
if ((i + 1 == sqlList.length) && sql.endsWith(";")) {
/* 去掉末尾的 ‘;’ */
sql = sql.substring(0, sql.length() - 1);
}
int rs2 = ServerParseSet.parse(sql, "set".length());
switch (rs2 & 0xff) {
case CHARACTER_SET_RESULTS:
charResult = sql.substring(rs2 >>> 8).trim();
break;
case CHARACTER_SET_CONNECTION:
charConnection = sql.substring(rs2 >>> 8).trim();
break;
case CHARACTER_SET_CLIENT:
break;
default:
StringBuilder s = new StringBuilder();
logger.warn(s.append(c).append(sql).append(" is not executed").toString());
}
}
if (charResult.startsWith("'") || charResult.startsWith("`")) {
charResult = charResult.substring(1, charResult.length() - 1);
}
if (charConnection.startsWith("'") || charConnection.startsWith("`")) {
charConnection = charConnection.substring(1, charConnection.length() - 1);
}
// 如果其中一个为null,则以另一个为准。
if ("null".equalsIgnoreCase(charResult)) {
setCharset(charConnection, c);
return;
}
if ("null".equalsIgnoreCase(charConnection)) {
setCharset(charResult, c);
return;
}
if (charConnection.equalsIgnoreCase(charResult)) {
setCharset(charConnection, c);
} else {
StringBuilder sb = new StringBuilder();
sb.append("charset is not consistent:[connection=").append(charConnection);
sb.append(",results=").append(charResult).append(']');
c.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, sb.toString());
}
}
private static void setCharset(String charset, ServerConnection c) {
if ("null".equalsIgnoreCase(charset)) {
/* 忽略字符集为null的属性设置 */
c.write(c.writeToBuffer(OkPacket.OK, c.allocate()));
} else if (c.setCharset(charset)) {
c.write(c.writeToBuffer(OkPacket.OK, c.allocate()));
} else {
try {
if (c.setCharsetIndex(Integer.parseInt(charset))) {
c.write(c.writeToBuffer(OkPacket.OK, c.allocate()));
} else {
c.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown charset :" + charset);
}
} catch (RuntimeException e) {
c.writeErrMessage(ErrorCode.ER_UNKNOWN_CHARACTER_SET, "Unknown charset :" + charset);
}
}
}
}