Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.hellojavaer.ddal.jsqlparser.JSQLParserAdapter Maven / Gradle / Ivy
/*
* #%L
* ddal-jsqlparser
* %%
* Copyright (C) 2016 - 2017 the original author or authors.
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 2.1 of the
* License, or (at your option) any later version.
*
* This program 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 Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
package org.hellojavaer.ddal.jsqlparser;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.*;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.relational.*;
import net.sf.jsqlparser.parser.CCJSqlParserManager;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Database;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.*;
import net.sf.jsqlparser.statement.update.Update;
import org.hellojavaer.ddal.ddr.datasource.exception.CrossPreparedStatementException;
import org.hellojavaer.ddal.ddr.shard.RangeShardValue;
import org.hellojavaer.ddal.ddr.shard.ShardRouteConfig;
import org.hellojavaer.ddal.ddr.shard.ShardRouteInfo;
import org.hellojavaer.ddal.ddr.shard.ShardRouter;
import org.hellojavaer.ddal.ddr.sqlparse.SQLParsedResult;
import org.hellojavaer.ddal.ddr.sqlparse.SQLParsedState;
import org.hellojavaer.ddal.ddr.sqlparse.exception.*;
import org.hellojavaer.ddal.ddr.utils.DDRJSONUtils;
import org.hellojavaer.ddal.ddr.utils.DDRStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.StringReader;
import java.util.*;
/**
*
*
* @author Kaiming Zou ,created on 12/11/2016.
*/
public class JSQLParserAdapter extends JSQLBaseVisitor {
private Logger logger = LoggerFactory.getLogger(this.getClass());
private String sql;
private ShardRouter shardRouter;
private Statement statement;
private Set schemas = new HashSet<>();
private boolean enableLimitCheck = false;
private List toBeConvertedTables = new ArrayList<>();
static {
try {
checkJSqlParserFeature();
} catch (Exception e) {
throw new RuntimeException("JSqlParser feature check failed", e);
}
}
/**
* To make ddal-jsqlparser work well, JSqlParser should include the feature of 'support getting jdbc parameter index'.
* And this feature is provided on the version of {@link 0.9.7 }.
* This method is designed to check the necessary feature.
*/
private static void checkJSqlParserFeature() throws JSQLParserException {
CCJSqlParserManager parserManager = new CCJSqlParserManager();
String sql = "SELECT * FROM tab_1 WHERE tab_1.col_1 = ? AND col_2 IN (SELECT DISTINCT col_2 FROM tab_2 WHERE col_3 LIKE ? AND col_4 > ?) LIMIT ?, ?";
Select select = (Select) parserManager.parse(new StringReader(sql));
PlainSelect selectBody = (PlainSelect) select.getSelectBody();
//
AndExpression andExpression = (AndExpression) selectBody.getWhere();
EqualsTo equalsTo = (EqualsTo) andExpression.getLeftExpression();
JdbcParameter jdbcParameter = (JdbcParameter) equalsTo.getRightExpression();
Integer index1 = jdbcParameter.getIndex();
if (index1 != 1) {
throw new IllegalStateException("Current version of JSQLParser doesn't support the feature of 'support "
+ "get jdbc parameter index'");
}
//
InExpression inExpression = (InExpression) andExpression.getRightExpression();
SubSelect subSelect = (SubSelect) inExpression.getRightItemsList();
PlainSelect subSelectBody = (PlainSelect) subSelect.getSelectBody();
AndExpression subAndExpression = (AndExpression) subSelectBody.getWhere();
LikeExpression likeExpression = (LikeExpression) subAndExpression.getLeftExpression();
if (((JdbcParameter) likeExpression.getRightExpression()).getIndex() != 2) {
throw new IllegalStateException(
"Current version of JSQLParser doesn't support the feature of 'support get jdbc parameter index'");
}
//
GreaterThan greaterThan = (GreaterThan) subAndExpression.getRightExpression();
if (((JdbcParameter) greaterThan.getRightExpression()).getIndex() != 3) {
throw new IllegalStateException(
"Current version of JSQLParser doesn't support the feature of 'support get jdbc parameter index'");
}
//
Expression offset = selectBody.getLimit().getOffset();
Expression rowCount = selectBody.getLimit().getRowCount();
if (((JdbcParameter) offset).getIndex() != 4 || ((JdbcParameter) rowCount).getIndex() != 5) {
throw new IllegalStateException(
"Current version of JSQLParser doesn't support the feature of 'support get jdbc parameter index'");
}
}
public JSQLParserAdapter(String sql, ShardRouter shardRouter, boolean enableLimitCheck) {
this.sql = sql;
this.shardRouter = shardRouter;
this.enableLimitCheck = enableLimitCheck;
try {
this.statement = CCJSqlParserUtil.parse(sql);
} catch (Throwable e) {
throw new SQLSyntaxErrorException("sql is [" + sql + "]", e);
}
if (statement instanceof Select //
|| statement instanceof Update//
|| statement instanceof Insert//
|| statement instanceof Delete) {
// ok
} else {
throw new UnsupportedSQLExpressionException(
"Sql ["
+ sql
+ "] is not supported in shard sql. Only support 'select' 'insert' 'update' and 'delete' sql statement");
}
}
private String generateSplitString(String str) {
Random random = new Random(System.currentTimeMillis());
while (true) {
long l = random.nextLong();
if (l < 0) {
l = -l;
}
String tar = "__" + l;
if (str.indexOf(tar) < 0) {
return tar;
}
}
}
public SQLParsedState parse() {
try {
statement.accept(this);
String targetSql = statement.toString();
//
String splitString = generateSplitString(targetSql);
for (int i = 0; i < toBeConvertedTables.size(); i++) {
TableWrapper tab = toBeConvertedTables.get(i);
tab.setSchemaName(null);
tab.setName("_" + i + splitString);
}
//
targetSql = statement.toString();
//
final List splitSqls = new ArrayList<>();
String[] sqls = targetSql.split(splitString);// table切分
for (int i = 0; i < sqls.length - 1; i++) {
String s = sqls[i];
int index = s.lastIndexOf('_');
splitSqls.add(s.substring(0, index));
Integer paramIndex = Integer.valueOf(s.substring(index + 1));
splitSqls.add(toBeConvertedTables.get(paramIndex));
}
splitSqls.add(sqls[sqls.length - 1]);
//
SQLParsedState parsedResult = new SQLParsedState() {
@Override
public SQLParsedResult parse(final Map jdbcParams) {
final Map convertedTables = new HashMap<>();
final Set schemas = new HashSet<>(JSQLParserAdapter.this.schemas);
final SQLParsedResult result = new SQLParsedResult() {
@Override
public void checkIfCrossPreparedStatement(Map jdbcParam)
throws CrossPreparedStatementException {
for (Map.Entry entry : convertedTables.entrySet()) {
TableWrapper tab = entry.getKey();
route1(tab, jdbcParams, entry.getValue(), this.getSql());
}
}
};
StringBuilder sb = new StringBuilder();
for (Object obj : splitSqls) {
if (obj instanceof TableWrapper) {
TableWrapper tab = (TableWrapper) obj;
ShardRouteInfo routeInfo = route1(tab, jdbcParams, tab.getRoutedFullTableName(), null);
schemas.add(routeInfo.getScName());
String routedFullTableName = routeInfo.toString();
convertedTables.put(tab, routedFullTableName);
sb.append(routedFullTableName);
} else {
sb.append(obj);
}
}
result.setSql(sb.toString());
result.setSchemas(schemas);
return result;
}
};
return parsedResult;
} finally {
// reset context
this.getStack().clear();
}
}
private ShardRouteInfo route1(TableWrapper tab, Map jdbcParams, String routedFullTableName,
String routedSql) {
ShardRouteInfo routeInfo = null;
// 1. no shard key
if (tab.getJdbcParamKeys() == null || tab.getJdbcParamKeys().isEmpty()) {
routeInfo = getRouteInfo(tab, null);
if (routeInfo != null) {
String fullTableName = routeInfo.toString();
if (tab.getRoutedFullTableName() != null) {// 多重路由
if (!tab.getRoutedFullTableName().equals(fullTableName)) {
throw new AmbiguousRouteResultException("In sql[" + sql + "], table:'"
+ tab.getOriginalConfig().toString()
+ "' has multiple routing results["
+ tab.getRoutedFullTableName() + "," + fullTableName
+ "]");
}
}
} else {
throw new GetRouteInfoException("Can't get route information for table:'"
+ tab.getOriginalConfig().toString()
+ "' 'sdValue':null and 'routeConfig':"
+ tab.getRouteConfig().toString());
}
return routeInfo;
}
// 2. jdbc param
for (Object sqlParam : tab.getJdbcParamKeys()) {// size > 0
if (sqlParam instanceof SqlParam) {
Object sdValue = null;
Object key = ((SqlParam) sqlParam).getValue();
if (jdbcParams != null) {
sdValue = jdbcParams.get(key);
}
if (sdValue == null) {// sql中指定的sdValue不能为空
throw new IllegalSQLParameterException("For jdbc parameter key " + key
+ ", jdbc parameter value is null. Jdbc parameter map is "
+ DDRJSONUtils.toJSONString(jdbcParams) + " and sql is ["
+ sql + "]");
}
routeInfo = getRouteInfo(tab, sdValue);
String next = routeInfo.toString();
if (routedFullTableName == null) {
routedFullTableName = next;
} else {
if (!routedFullTableName.equals(next)) {
throw new AmbiguousRouteResultException("In sql[" + sql + "], table:'"
+ tab.getOriginalConfig().toString()
+ "' has multiple routing results["
+ routedFullTableName + "," + next
+ "]. Jdbc parameter is "
+ DDRJSONUtils.toJSONString(jdbcParams));
}
}
} else {// range
RangeParam rangeParam = (RangeParam) sqlParam;
SqlParam begin = rangeParam.getBeginValue();
SqlParam end = rangeParam.getEndValue();
long s0 = 0;
long e0 = 0;
if (begin.isJdbcParamType()) {
Number number = (Number) jdbcParams.get(begin.getValue());
if (number == null) {
throw new IllegalSQLParameterException("Jdbc parameter can't be null. Jdbc parameter key is "
+ begin.getValue() + ", jdbc parameter is "
+ DDRJSONUtils.toJSONString(jdbcParams)
+ " and sql is [" + sql + "]");
}
s0 = number.longValue();
} else {
s0 = ((Number) begin.getValue()).longValue();
}
if (end.isJdbcParamType()) {
Number number = (Number) jdbcParams.get(end.getValue());
if (number == null) {
}
e0 = number.longValue();
} else {
e0 = ((Number) end.getValue()).longValue();
}
routeInfo = getRouteInfo(tab, new RangeShardValue(s0, e0));
String next = routeInfo.toString();
if (routedFullTableName == null) {
routedFullTableName = next;
} else {
if (!routedFullTableName.equals(next)) {
if (routedSql != null) {
throw new CrossPreparedStatementException("Sql[" + sql + "] has been routed to ["
+ routedSql + "] and table:'"
+ tab.getOriginalConfig().toString()
+ "' has been route to '" + routedFullTableName
+ "'. But current jdbc parameter:"
+ DDRJSONUtils.toJSONString(jdbcParams)
+ " require route to " + next
+ DDRJSONUtils.toJSONString(jdbcParams));
} else {
throw new AmbiguousRouteResultException("In sql[" + sql + "], table:'"
+ tab.getOriginalConfig().toString()
+ "' has multiple routing results["
+ routedFullTableName + "," + next
+ "]. Jdbc parameter is "
+ DDRJSONUtils.toJSONString(jdbcParams));
}
}
}
}
}
return routeInfo;
}
private void afterVisitBaseStatement() {
FrameContext context = this.getStack().pop();
for (Map.Entry entry : context.entrySet()) {
TableWrapper tab = entry.getValue();
if (tab == AMBIGUOUS_TABLE) {
continue;
}
if (tab.getJdbcParamKeys() != null && !tab.getJdbcParamKeys().isEmpty()) {// 含jdbc路由
toBeConvertedTables.add(tab);
} else {// 不含jdbc路由
if (tab.getRoutedFullTableName() == null) {// sql未路由
toBeConvertedTables.add(tab);
}// else ok
}
}
}
private ShardRouteInfo getRouteInfo(TableWrapper tab, Object sdValue) {
try {
ShardRouteInfo routeInfo = this.shardRouter.getRouteInfo(tab.getOriginalConfig().getSchemaName(),
tab.getOriginalConfig().getName(), sdValue);
return routeInfo;
} catch (Throwable e) {
String fullTableName = null;
if (tab.getOriginalConfig().getAlias() != null) {
fullTableName = tab.getOriginalConfig().getAlias().getName();
} else {
fullTableName = tab.getOriginalConfig().getName();
}
String sdKey = null;
if (tab.getRouteConfig().getSdKey() != null) {
sdKey = fullTableName + "." + tab.getRouteConfig().getSdKey();
}
String msg = String.format("Current state is table:'%s', sdKey:'%s', sdValue:%s, routeConfig:%s, sql:[%s]",
tab.getOriginalConfig().toString(), sdKey, sdValue,
tab.getRouteConfig().toString(), sql);
throw new GetRouteInfoException(msg, e);
}
}
private void route0(TableWrapper tab, ShardRouteInfo routeInfo) {
String fullTableName = routeInfo.toString();
if (tab.getRoutedFullTableName() != null) {// 多重路由
if (!tab.getRoutedFullTableName().equals(fullTableName)) {
throw new AmbiguousRouteResultException("In sql[" + sql + "], table:'"
+ tab.getOriginalConfig().toString()
+ "' has multiple routing results["
+ tab.getRoutedFullTableName() + "," + fullTableName + "]");
}
} else {// 是否使用alias在put的时候设置,这里只需要设置scName和tbName
tab.setRoutedFullTableName(fullTableName);//
tab.setSchemaName(routeInfo.getScName());
tab.setName(routeInfo.getTbName());
schemas.add(routeInfo.getScName());
}
}
@Override
public void visit(Insert insert) {
this.getStack().push(new FrameContext());
ShardRouteConfig routeConfig = shardRouter.getRouteConfig(insert.getTable().getSchemaName(),
insert.getTable().getName());
if (routeConfig != null) {
TableWrapper table = new TableWrapper(insert.getTable(), routeConfig);
addRoutedTableIntoContext(table, routeConfig, false);
List columns = insert.getColumns();
if (columns != null) {
ExpressionList expressionList = (ExpressionList) insert.getItemsList();
List valueList = expressionList.getExpressions();
for (int i = 0; i < columns.size(); i++) {
Column column = columns.get(i);
TableWrapper tab = getTableFromContext(column);
if (tab != null) {
Expression expression = valueList.get(i);
routeTable(tab, column, expression);
}
}
}
}
super.visit(insert);
afterVisitBaseStatement();
}
/**
* mysql 'delete' doesn't support alais
*/
@Override
public void visit(Delete delete) {
if (enableLimitCheck && delete.getLimit() == null) {
throw new IllegalStateException("no limit in sql: " + sql);
}
this.getStack().push(new FrameContext());
ShardRouteConfig routeConfig = shardRouter.getRouteConfig(delete.getTable().getSchemaName(),
delete.getTable().getName());
if (routeConfig != null) {
TableWrapper tab = new TableWrapper(delete.getTable(), routeConfig);
delete.setTable(tab);
addRoutedTableIntoContext(tab, routeConfig, false);
}
super.visit(delete);
afterVisitBaseStatement();
}
@Override
public void visit(Update update) {
if (enableLimitCheck && update.getLimit() == null) {
throw new IllegalStateException("no limit in sql: " + sql);
}
this.getStack().push(new FrameContext());
if (update.getTables() != null) {
for (Table table : update.getTables()) {
ShardRouteConfig routeConfig = shardRouter.getRouteConfig(table.getSchemaName(), table.getName());
if (routeConfig != null) {
TableWrapper tab = new TableWrapper(table, routeConfig);
addRoutedTableIntoContext(tab, routeConfig, true);
}
}
}
super.visit(update);
afterVisitBaseStatement();
}
@Override
public void visit(Select select) {
if (enableLimitCheck && select.getSelectBody() != null && select.getSelectBody() instanceof PlainSelect
&& ((PlainSelect) select.getSelectBody()).getLimit() == null) {
throw new IllegalStateException("no limit in sql: " + sql);
}
this.getStack().push(new FrameContext());
super.visit(select);
afterVisitBaseStatement();
}
@Override
public void visit(SubSelect subSelect) {
this.getStack().push(new FrameContext());
super.visit(subSelect);
afterVisitBaseStatement();
}
private TableWrapper getTableFromContext(Column col) {
FrameContext frameContext = this.getStack().peek();
String colFullName = col.toString();
colFullName = DDRStringUtils.toLowerCase(colFullName);
return frameContext.get(colFullName);
}
private void addRoutedTableIntoContext(TableWrapper table, ShardRouteConfig routeInfo) {
addRoutedTableIntoContext(table, routeInfo, true);
}
/**
* value:'scName.tbAliasName' value:table
* @param table
* @param appendAlias
*/
private void addRoutedTableIntoContext(TableWrapper table, ShardRouteConfig routeConfig, boolean appendAlias) {
FrameContext frameContext = this.getStack().peek();
String tbName = table.getName();
String tbAliasName = tbName;
if (table.getAlias() != null && table.getAlias().getName() != null) {
tbAliasName = table.getAlias().getName();
} else {
if (appendAlias) {
table.setAlias(new Alias(tbName, true));
}
}
String sdKey = DDRStringUtils.toLowerCase(routeConfig.getSdKey());// sdKey可以为null,当为null时需要通过context路由
if (table.getSchemaName() != null) {
StringBuilder sb = new StringBuilder();
sb.append(DDRStringUtils.toLowerCase(table.getSchemaName()));
sb.append('.');
sb.append(DDRStringUtils.toLowerCase(tbAliasName));
sb.append('.');
sb.append(sdKey);
String key = sb.toString();
putIntoContext(frameContext, key, table);
putIntoContext(frameContext, key.substring(table.getSchemaName().length() + 1), table);
putIntoContext(frameContext, key.substring(table.getSchemaName().length() + 2 + tbAliasName.length()),
table);
} else {
StringBuilder sb = new StringBuilder();
sb.append(DDRStringUtils.toLowerCase(tbAliasName));
sb.append('.');
sb.append(sdKey);
String key = sb.toString();
putIntoContext(frameContext, key, table);
putIntoContext(frameContext, key.substring(tbAliasName.length() + 1), table);
}
}
private Object getRouteValue(Column column, Expression obj) {
if (obj == null) {
return null;
}
if (obj instanceof LongValue) {
return ((LongValue) obj).getValue();
} else if (obj instanceof StringValue) {
return ((StringValue) obj).getValue();
} else if (obj instanceof HexValue) {
return Long.parseLong(((HexValue) obj).getValue(), 16);
} else if (obj instanceof DateValue) {
return ((DateValue) obj).getValue();
} else if (obj instanceof DoubleValue) {
return ((DoubleValue) obj).getValue();
} else if (obj instanceof TimeValue) {
return ((TimeValue) obj).getValue();
} else if (obj instanceof TimestampValue) {
return ((TimestampValue) obj).getValue();
} else {// NullValue
throw new UnsupportedSQLParameterTypeException("Type '" + obj.getClass()
+ "' is not supported for shard value '" + column.toString()
+ "'. Sql is [" + sql + "]");
}
}
@Override
public void visit(InExpression inExpression) {
if (inExpression.isNot()) {
super.visit(inExpression);
return;
}
Column column = (Column) inExpression.getLeftExpression();
if (inExpression.getRightItemsList() instanceof ExpressionList) {
TableWrapper tab = getTableFromContext(column);
if (tab == null) {
super.visit(inExpression);
return;
}
ExpressionList itemsList = (ExpressionList) inExpression.getRightItemsList();
List list = itemsList.getExpressions();
if (list == null || list.isEmpty()) {
super.visit(inExpression);
}
for (Expression exp : list) {
routeTable(tab, column, exp);
}
} else {
super.visit(inExpression);
return;
}
}
@Override
public void visit(Between between) {
if (between.isNot()) {
super.visit(between);
return;
}
Column column = (Column) between.getLeftExpression();
TableWrapper tab = getTableFromContext(column);
if (tab == null) {
super.visit(between);
return;
}
Expression begin = between.getBetweenExpressionStart();
Expression end = between.getBetweenExpressionEnd();
if (begin instanceof SubSelect || end instanceof SubSelect) {
super.visit(between);
return;
} else if ((begin instanceof JdbcParameter || begin instanceof JdbcNamedParameter) //
|| (end instanceof JdbcParameter || end instanceof JdbcNamedParameter)) {
tab.getJdbcParamKeys().add(new RangeParam(new SqlParam(column, begin), new SqlParam(column, end)));
return;
} else {
long s1 = ((Number) getRouteValue(column, begin)).longValue();
long e1 = ((Number) getRouteValue(column, end)).longValue();
if (s1 > e1) {
long temp = s1;
s1 = e1;
e1 = temp;
}
for (long l = s1; l <= e1; l++) {
routeTable(tab, column, l);
}
}
}
@Override
public void visit(EqualsTo equalsTo) {
Column column = (Column) equalsTo.getLeftExpression();
if (equalsTo.getRightExpression() instanceof SubSelect) {
super.visit(equalsTo);
return;
} else {
String fullColumnName = column.toString();
fullColumnName = DDRStringUtils.toLowerCase(fullColumnName);
TableWrapper tab = this.getStack().peek().get(fullColumnName);
if (tab != null) {// 需要路由的table
routeTable(tab, column, equalsTo.getRightExpression());
} else {// there maybe contains sub query,so we show invoke super.visit
super.visit(equalsTo);
}
}
}
private void routeTable(TableWrapper tab, Column column, Expression routeValueExpression) {
// jdbc参数
if (routeValueExpression != null && routeValueExpression instanceof JdbcParameter
|| routeValueExpression instanceof JdbcNamedParameter) {
tab.getJdbcParamKeys().add(new SqlParam(column, routeValueExpression));
return;
} else {// 普通sql参数
Object sdValue = getRouteValue(column, routeValueExpression);//
routeTable(tab, column, sdValue);
}
}
private void routeTable(TableWrapper tab, Column column, Object sdValue) {
if (tab == null) {//
return;
}
if (tab == AMBIGUOUS_TABLE) {
throw new RuntimeException("Shard value '" + column.toString() + "' in where clause is ambiguous. Sql is ["
+ sql + "]");
}
ShardRouteInfo routeInfo = getRouteInfo(tab, sdValue);
route0(tab, routeInfo);
}
@Override
public void visit(Table table) {
String tbName = table.getName();
ShardRouteConfig routeConfig = shardRouter.getRouteConfig(table.getSchemaName(), tbName);
if (routeConfig != null) {
TableWrapper tab = new TableWrapper(table, routeConfig);
addRoutedTableIntoContext(tab, routeConfig);
}
}
private void putIntoContext(FrameContext frameContext, String key, TableWrapper tab) {
TableWrapper tab0 = frameContext.get(key);
if (tab0 == null) {
frameContext.put(key, tab);
} else {
frameContext.put(key, AMBIGUOUS_TABLE);
}
}
private static final TableWrapper AMBIGUOUS_TABLE = new TableWrapper(null, null);
private ThreadLocal> context = new ThreadLocal>() {
@Override
protected Stack initialValue() {
return new Stack();
}
};
private class FrameContext extends HashMap {
}
private Stack getStack() {
return context.get();
}
private static class TableWrapper extends Table {
public TableWrapper(Table table, ShardRouteConfig routeConfig) {
this.routeConfig = routeConfig;
if (table != null) {
this.table = table;
originalConfig.setDatabase(table.getDatabase());
originalConfig.setSchemaName(table.getSchemaName());
originalConfig.setName(table.getName());
originalConfig.setAlias(table.getAlias());
originalConfig.setPivot(table.getPivot());
originalConfig.setASTNode(table.getASTNode());
}
}
private Table table;
private Table originalConfig = new Table();
private ShardRouteConfig routeConfig; // route config info
private String routedFullTableName; // 由routeInfo计算出,如果有sql路由时该字段不为空,如果该参数为空,表示需要jdbc路由
private List jdbcParamKeys = new ArrayList<>(); // table 关联的jdbc列
public ShardRouteConfig getRouteConfig() {
return routeConfig;
}
public void setRouteConfig(ShardRouteConfig routeConfig) {
this.routeConfig = routeConfig;
}
public String getRoutedFullTableName() {
return routedFullTableName;
}
public void setRoutedFullTableName(String routedFullTableName) {
this.routedFullTableName = routedFullTableName;
}
public List getJdbcParamKeys() {
return jdbcParamKeys;
}
public void setJdbcParamKeys(List jdbcParamKeys) {
this.jdbcParamKeys = jdbcParamKeys;
}
public Table getOriginalConfig() {
return originalConfig;
}
public void setOriginalConfig(Table originalConfig) {
this.originalConfig = originalConfig;
}
@Override
public Database getDatabase() {
return table.getDatabase();
}
@Override
public void setDatabase(Database database) {
table.setDatabase(database);
}
@Override
public String getSchemaName() {
return table.getSchemaName();
}
@Override
public void setSchemaName(String string) {
table.setSchemaName(string);
}
@Override
public String getName() {
return table.getName();
}
@Override
public void setName(String string) {
table.setName(string);
}
@Override
public Alias getAlias() {
return table.getAlias();
}
@Override
public void setAlias(Alias alias) {
table.setAlias(alias);
}
@Override
public String getFullyQualifiedName() {
return table.getFullyQualifiedName();
}
@Override
public void accept(FromItemVisitor fromItemVisitor) {
table.accept(fromItemVisitor);
}
@Override
public void accept(IntoTableVisitor intoTableVisitor) {
table.accept(intoTableVisitor);
}
@Override
public Pivot getPivot() {
return table.getPivot();
}
@Override
public void setPivot(Pivot pivot) {
table.setPivot(pivot);
}
}
private class RangeParam {
private SqlParam beginValue;
private SqlParam endValue;
public RangeParam(SqlParam beginValue, SqlParam endValue) {
this.beginValue = beginValue;
this.endValue = endValue;
}
public SqlParam getBeginValue() {
return beginValue;
}
public void setBeginValue(SqlParam beginValue) {
this.beginValue = beginValue;
}
public SqlParam getEndValue() {
return endValue;
}
public void setEndValue(SqlParam endValue) {
this.endValue = endValue;
}
}
private class SqlParam {
private Column column;
private Expression expression;
private Object value;
private boolean jdbcParamType = false;
public SqlParam(Column column, Expression expression) {
this.column = column;
this.expression = expression;
if (expression instanceof JdbcParameter) {
value = ((JdbcParameter) expression).getIndex();
jdbcParamType = true;
} else if (expression instanceof JdbcNamedParameter) {
value = ((JdbcNamedParameter) expression).getName();
jdbcParamType = true;
} else {
value = getRouteValue(column, expression);
jdbcParamType = false;
}
}
public Column getColumn() {
return column;
}
public void setColumn(Column column) {
this.column = column;
}
public Expression getExpression() {
return expression;
}
public void setExpression(Expression expression) {
this.expression = expression;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public boolean isJdbcParamType() {
return jdbcParamType;
}
public void setJdbcParamType(boolean jdbcParamType) {
this.jdbcParamType = jdbcParamType;
}
}
}