package io.mycat.route.impl; import io.mycat.MycatServer; import io.mycat.cache.LayerCachePool; import io.mycat.route.RouteResultset; import io.mycat.route.RouteStrategy; import io.mycat.route.util.RouterUtil; import io.mycat.server.MySQLFrontConnection; import io.mycat.server.config.node.SchemaConfig; import io.mycat.server.config.node.SystemConfig; import io.mycat.server.parser.ServerParse; import io.mycat.sqlengine.mpp.LoadData; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.sql.SQLNonTransientException; import java.sql.SQLSyntaxErrorException; public abstract class AbstractRouteStrategy implements RouteStrategy { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractRouteStrategy.class); @Override public RouteResultset route(SystemConfig sysConfig, SchemaConfig schema,int sqlType, String origSQL, String charset, MySQLFrontConnection sc, LayerCachePool cachePool) throws SQLNonTransientException { //process some before route logic if (beforeRouteProcess(schema, sqlType, origSQL, sc)) return null; // user handler String stmt = MycatServer.getInstance().getSqlInterceptor().interceptSQL(origSQL, sqlType); if (origSQL != stmt && LOGGER.isDebugEnabled()) { LOGGER.debug("sql intercepted to " + stmt + " from " + origSQL); } if (schema.isCheckSQLSchema()) { stmt = RouterUtil.removeSchema(stmt, schema.getName()); } RouteResultset rrs = new RouteResultset(stmt, sqlType); if ( LOGGER.isDebugEnabled()&&origSQL.startsWith(LoadData.loadDataHint)) { rrs.setCacheAble(false);//优化debug loaddata输出cache的日志会极大降低性能 } //rrs携带ServerConnection的autocommit状态用于在sql解析的时候遇到select ... for update的时候动态设定RouteResultsetNode的canRunInReadDB属性 if (sc != null ) { rrs.setAutocommit(sc.isAutocommit()); } //ddl create deal if(ServerParse.DDL==sqlType){ return RouterUtil.routeToDDLNode(rrs, sqlType, stmt,schema); } // check if there is sharding in schema if (schema.isNoSharding() && ServerParse.SHOW != sqlType) { rrs = RouterUtil.routeToSingleNode(rrs, schema.getDataNode(), stmt); // return RouterUtil.routeToSingleNode(rrs, schema.getDataNode(), stmt); } else { RouteResultset returnedSet=routeSystemInfo(schema, sqlType, stmt, rrs); if(returnedSet==null){ rrs = routeNormalSqlWithAST(schema, stmt, rrs, charset, cachePool); // return routeNormalSqlWithAST(schema, stmt, rrs, charset, cachePool); } } return rrs; } private boolean beforeRouteProcess(SchemaConfig schema, int sqlType, String origSQL, MySQLFrontConnection sc) throws SQLNonTransientException { return RouterUtil.processWithMycatSeq(schema, sqlType, origSQL, sc) || (sqlType == ServerParse.INSERT && RouterUtil.processERChildTable(schema, origSQL, sc)) || (sqlType == ServerParse.INSERT && RouterUtil.processInsert(schema, sqlType, origSQL,sc)); } /** * 通过解析AST语法树类来寻找路由 * @param schema * @param stmt * @param rrs * @param charset * @param cachePool * @return * @throws SQLNonTransientException */ public abstract RouteResultset routeNormalSqlWithAST(SchemaConfig schema,String stmt,RouteResultset rrs,String charset,LayerCachePool cachePool) throws SQLNonTransientException; /** * * @param schema * @param sqlType * @param stmt * @param rrs * @return * @throws SQLSyntaxErrorException */ public abstract RouteResultset routeSystemInfo(SchemaConfig schema,int sqlType,String stmt,RouteResultset rrs) throws SQLSyntaxErrorException; /** * show 之类的语句 * @param schema * @param rrs * @param stmt * @return * @throws SQLSyntaxErrorException */ public abstract RouteResultset analyseShowSQL(SchemaConfig schema,RouteResultset rrs, String stmt) throws SQLNonTransientException; }