package demo.catlets;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
import io.mycat.MycatServer;
import io.mycat.cache.LayerCachePool;
import io.mycat.route.RouteResultset;
import io.mycat.route.RouteResultsetNode;
import io.mycat.route.factory.RouteStrategyFactory;
import io.mycat.server.ErrorCode;
import io.mycat.server.MySQLFrontConnection;
import io.mycat.server.config.node.SchemaConfig;
import io.mycat.server.config.node.SystemConfig;
import io.mycat.server.config.node.TableConfig;
import io.mycat.server.parser.ServerParse;
import io.mycat.server.sequence.IncrSequenceMySQLHandler;
import io.mycat.server.sequence.IncrSequencePropHandler;
import io.mycat.server.sequence.SequenceHandler;
import io.mycat.sqlengine.Catlet;
import io.mycat.sqlengine.EngineCtx;
import io.mycat.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 执行批量插入sequence Id
* @author 兵临城下
* @date 2015/03/20
*/
public class BatchInsertSequence implements Catlet {
private static final Logger LOGGER = LoggerFactory
.getLogger(BatchInsertSequence.class);
private RouteResultset rrs;//路由结果集
private String executeSql;//接收执行处理任务的sql
private SequenceHandler sequenceHandler;//sequence处理对象
//重新路由使用
private SystemConfig sysConfig;
private SchemaConfig schema;
private int sqltype;
private String charset;
private MySQLFrontConnection sc;
private LayerCachePool cachePool;
@Override
public void processSQL(String sql, EngineCtx ctx) {
try {
getRoute(executeSql);
RouteResultsetNode[] nodes = rrs.getNodes();
if (nodes == null || nodes.length == 0 || nodes[0].getName() == null
|| nodes[0].getName().equals("")) {
ctx.getSession().getSource().writeErrMessage(ErrorCode.ER_NO_DB_ERROR,
"No dataNode found ,please check tables defined in schema:"
+ ctx.getSession().getSource().getSchema());
return;
}
sc.getSession2().execute(rrs, sqltype);//将路由好的数据执行入库
} catch (Exception e) {
LOGGER.error("BatchInsertSequence.processSQL(String sql, EngineCtx ctx)",e);
}
}
@Override
public void route(SystemConfig sysConfig, SchemaConfig schema, int sqlType,
String realSQL, String charset, MySQLFrontConnection sc,
LayerCachePool cachePool) {
int rs = ServerParse.parse(realSQL);
this.sqltype = rs & 0xff;
this.sysConfig=sysConfig;
this.schema=schema;
this.charset=charset;
this.sc=sc;
this.cachePool=cachePool;
try {
MySqlStatementParser parser = new MySqlStatementParser(realSQL);
SQLStatement statement = parser.parseStatement();
MySqlInsertStatement insert = (MySqlInsertStatement)statement;
if(insert.getValuesList()!=null){
String tableName = StringUtil.getTableName(realSQL).toUpperCase();
TableConfig tableConfig = schema.getTables().get(tableName);
String primaryKey = tableConfig.getPrimaryKey();//获得表的主键字段
SQLIdentifierExpr sqlIdentifierExpr = new SQLIdentifierExpr();
sqlIdentifierExpr.setName(primaryKey);
insert.getColumns().add(sqlIdentifierExpr);
if(sequenceHandler == null){
int seqHandlerType = MycatServer.getInstance().getConfig().getSystem().getSequnceHandlerType();
switch(seqHandlerType){
case SystemConfig.SEQUENCEHANDLER_MYSQLDB:
sequenceHandler = IncrSequenceMySQLHandler.getInstance();
break;
case SystemConfig.SEQUENCEHANDLER_LOCALFILE:
sequenceHandler = IncrSequencePropHandler.getInstance();
break;
default:
throw new java.lang.IllegalArgumentException("Invalid sequnce handler type "+seqHandlerType);
}
}
for(ValuesClause vc : insert.getValuesList()){
SQLIntegerExpr sqlIntegerExpr = new SQLIntegerExpr();
long value = sequenceHandler.nextId(tableName.toUpperCase());
sqlIntegerExpr.setNumber(value);//插入生成的sequence值
vc.addValue(sqlIntegerExpr);
}
String insertSql = insert.toString();
this.executeSql = insertSql;
}
} catch (Exception e) {
LOGGER.error("BatchInsertSequence.route(......)",e);
}
}
/**
* 根据sql获得路由执行结果
* @param sql
*/
private void getRoute(String sql){
try {
rrs =RouteStrategyFactory.getRouteStrategy().route(sysConfig, schema, sqltype,sql,charset, sc, cachePool);
} catch (Exception e) {
LOGGER.error("BatchInsertSequence.getRoute(String sql)",e);
}
}
}