All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.javaclub.cdl.client.matrix.router.SQLRouteEngine Maven / Gradle / Ivy

The newest version!
package com.github.javaclub.cdl.client.matrix.router;

import java.util.Collection;
import java.util.List;
import java.util.Map;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.StringUtils;

import com.github.javaclub.cdl.client.matrix.exception.SMatrixJdbcException;
import com.github.javaclub.cdl.client.matrix.exception.SQLParserException;
import com.github.javaclub.cdl.client.matrix.jdbc.DatabaseType;
import com.github.javaclub.cdl.client.matrix.parser.SQLParsedResult;
import com.github.javaclub.cdl.client.matrix.parser.SQLParserFactory;
import com.github.javaclub.cdl.client.matrix.parser.result.router.ConditionContext;
import com.github.javaclub.cdl.client.matrix.parser.result.router.SQLBuilder;
import com.github.javaclub.cdl.client.matrix.parser.result.router.Table;
import com.github.javaclub.cdl.client.matrix.router.single.SingleTableRouter;
import com.github.javaclub.cdl.client.matrix.rule.RouterStrategy;
import com.github.javaclub.cdl.client.parameter.ParameterContext;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;

@Slf4j
public class SQLRouteEngine {
	private RouterStrategy routerStrategy;
	private String logicSql;

	public SQLRouteEngine(RouterStrategy routerStrategy) {
		super();
		this.routerStrategy = routerStrategy;
	}

	/**
	 * SQL路由.
	 * 
	 * @param logicSql
	 *            逻辑SQL
	 * @return 路由结果
	 * @throws SQLParserException
	 *             SQL解析失败异常
	 */
	public SQLRouteResult route(final String logicSql, final List parameters) throws SQLParserException {
		this.logicSql = logicSql;
		return routeSQL(parseSQL(logicSql, parameters));
	}

	public SQLRouteResult route(final String logicSql, final List parameters, Map parameterSettings)
			throws SQLParserException {
		this.logicSql = logicSql;
		return routeSQL(parseSQL(logicSql, parameters, parameterSettings));
	}

	private SQLParsedResult parseSQL(final String logicSql, final List parameters) {
		SQLParsedResult result = SQLParserFactory.create(DatabaseType.MySQL, logicSql, parameters, routerStrategy.getShardingColumn())
				.parse();
		return result;
	}

	private SQLParsedResult parseSQL(final String logicSql, final List parameters, Map parameterSettings) {
		SQLParsedResult result = SQLParserFactory.create(DatabaseType.MySQL, logicSql, parameters, routerStrategy.getShardingColumn(),
				parameterSettings).parse();
		return result;
	}

	private SQLRouteResult routeSQL(final SQLParsedResult parsedResult) {
		SQLRouteResult result = new SQLRouteResult(parsedResult.getMergeContext());

		// 普通非shard表
		if (StringUtils.isNotBlank(parsedResult.getNotShardTable())) {
			result.setNotShardTable(true);
			String tableName = parsedResult.getNotShardTable();
			log.debug("{} is not shard table", tableName);
			if (routerStrategy.getAllActualTable(tableName) == null || routerStrategy.getAllActualTable(tableName).isEmpty()) {
				throw new RuntimeException(String.format("not found db group for table[{}]", tableName));
			}
			SQLExecutionUnit sQLExecutionUnit = new SQLExecutionUnit(
					routerStrategy.getAllActualTable(tableName).keySet().iterator().next(), logicSql);
			result.getExecutionUnits().add(sQLExecutionUnit);
			return result;
		}
		
		// 无表SQL,走默认dbGroup, 如:SELECT LAST_INSERT_ID()
		if(parsedResult.getRouteContext().getTables().isEmpty()){
			SQLExecutionUnit sQLExecutionUnit = new SQLExecutionUnit(routerStrategy.getDefaultGroup(),logicSql);
			result.getExecutionUnits().add(sQLExecutionUnit);
			return result;
		}

		for (ConditionContext each : parsedResult.getConditionContexts()) {
			result.getExecutionUnits().addAll(
					routeSQL(each, Collections2.transform(parsedResult.getRouteContext().getTables(), new Function() {
						@Override
						public String apply(final Table input) {
							return input.getName();
						}
					}), parsedResult.getRouteContext().getSqlBuilder()));
		}
		return result;
	}

	private Collection routeSQL(final ConditionContext conditionContext, final Collection logicTables,
			final SQLBuilder sqlBuilder) {
		RoutingResult result = null;
		if (1 == logicTables.size()) {
			result = new SingleTableRouter(routerStrategy, logicTables.iterator().next(), conditionContext).route();
		}
		if (null == result) {
			throw new SMatrixJdbcException("cannot route any result, please check your sharding rule.");
		}
		return result.getSQLExecutionUnits(sqlBuilder);
	}
}