package org.opencloudb.route; import io.netty.buffer.ByteBuf; import java.util.concurrent.ConcurrentLinkedQueue; import org.apache.log4j.Logger; import org.opencloudb.MycatSystem; import org.opencloudb.config.ErrorCode; import org.opencloudb.net.FrontSession; import org.opencloudb.net.mysql.EOFPacket; import org.opencloudb.net.mysql.FieldPacket; import org.opencloudb.net.mysql.ResultSetHeaderPacket; import org.opencloudb.net.mysql.RowDataPacket; import org.opencloudb.parser.ExtNodeToString4SEQ; import org.opencloudb.parser.SQLParserDelegate; import org.opencloudb.util.StringUtil; import com.foundationdb.sql.parser.QueryTreeNode; import com.foundationdb.sql.unparser.NodeToString; public class MyCATSequnceProcessor { private static final Logger LOGGER = Logger .getLogger(MyCATSequnceProcessor.class); private ConcurrentLinkedQueue<SessionSQLPair> seqSQLQueue = new ConcurrentLinkedQueue<SessionSQLPair>(); public MyCATSequnceProcessor() { new ExecuteThread().start(); } public void addNewSql(SessionSQLPair pair) { seqSQLQueue.offer(pair); } private void outRawData(FrontSession session,String value) { byte packetId = 0; int fieldCount = 1; String charset= session.getConInfo().getCharset(); ByteBuf byteBuf = session.allocate(128,1024); ResultSetHeaderPacket headerPkg = new ResultSetHeaderPacket(); headerPkg.fieldCount = fieldCount; headerPkg.packetId = ++packetId; byteBuf = headerPkg.write(byteBuf); FieldPacket fieldPkg = new FieldPacket(); fieldPkg.packetId = ++packetId; fieldPkg.name = StringUtil.encode("SEQUNCE", charset); byteBuf = fieldPkg.write(byteBuf); EOFPacket eofPckg = new EOFPacket(); eofPckg.packetId = ++packetId; byteBuf = eofPckg.write(byteBuf); RowDataPacket rowDataPkg = new RowDataPacket(fieldCount); rowDataPkg.packetId = ++packetId; rowDataPkg.add(StringUtil.encode(value, charset)); byteBuf = rowDataPkg.write(byteBuf); // write last eof EOFPacket lastEof = new EOFPacket(); lastEof.packetId = ++packetId; byteBuf = lastEof.write(byteBuf); // write buffer session.write(byteBuf); } private void executeSeq(SessionSQLPair pair) { try { // @micmiu 扩展NodeToString实现自定义全局序列号 NodeToString strHandler = new ExtNodeToString4SEQ(MycatSystem .getInstance().getConfig().getSystem() .getSequnceHandlerType()); // 如果存在sequence 转化sequence为实际数值 String charset = pair.session.getConInfo().getCharset(); QueryTreeNode ast = SQLParserDelegate.parse(pair.sql, charset == null ? "utf-8" : charset); String sql = strHandler.toString(ast); if (sql.toUpperCase().startsWith("SELECT")) { String value=sql.substring("SELECT".length()).trim(); outRawData(pair.session,value); return; } pair.session.routeEndExecuteSQL(sql, pair.type, pair.schema); } catch (Exception e) { LOGGER.error(e); pair.session.writeErrMessage(ErrorCode.ER_YES, "mycat sequnce err." + e); return; } } class ExecuteThread extends Thread { public void run() { while (true) { SessionSQLPair pair = null; try { pair = seqSQLQueue.poll(); if (pair == null) { Thread.sleep(100); } else { executeSeq(pair); } } catch (Exception e) { LOGGER.error(e); } } } } }