use of java.sql.SQLNonTransientException in project Mycat_plus by coderczp.
the class RouterUtil method routeByERParentKey.
/**
* 根据 ER分片规则获取路由集合
*
* @param stmt 执行的语句
* @param rrs 数据路由集合
* @param tc 表实体
* @param joinKeyVal 连接属性
* @return RouteResultset(数据路由集合) *
* @throws SQLNonTransientException,IllegalShardingColumnValueException
* @author mycat
*/
public static RouteResultset routeByERParentKey(ServerConnection sc, SchemaConfig schema, int sqlType, String stmt, RouteResultset rrs, TableConfig tc, String joinKeyVal) throws SQLNonTransientException {
// table's partition key
if (tc.isSecondLevel() && // 判断是否为二级子表(父表不再有父表)
tc.getParentTC().getPartitionColumn().equals(tc.getParentKey())) {
// using
// parent
// rule to
// find
// datanode
Set<ColumnRoutePair> parentColVal = new HashSet<ColumnRoutePair>(1);
ColumnRoutePair pair = new ColumnRoutePair(joinKeyVal);
parentColVal.add(pair);
Set<String> dataNodeSet = ruleCalculate(tc.getParentTC(), parentColVal, rrs.getDataNodeSlotMap());
if (dataNodeSet.isEmpty() || dataNodeSet.size() > 1) {
throw new SQLNonTransientException("parent key can't find valid datanode ,expect 1 but found: " + dataNodeSet.size());
}
String dn = dataNodeSet.iterator().next();
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("found partion node (using parent partion rule directly) for child table to insert " + dn + " sql :" + stmt);
}
return RouterUtil.routeToSingleNode(rrs, dn, stmt);
}
return null;
}
use of java.sql.SQLNonTransientException in project Mycat_plus by coderczp.
the class FunctionParser method parseFunction.
public static Function parseFunction(String function) throws SQLNonTransientException {
StringBuilder buffer = new StringBuilder();
Stack<Function> functions = new Stack<>();
int flag = 0;
for (int i = 0; i < function.length(); i++) {
char current = function.charAt(i);
switch(current) {
case Commons.LEFT_BRACKET:
if (flag == 0) {
String currentIdentifier = buffer.toString().trim();
buffer = new StringBuilder();
if (!StringUtil.isEmpty(currentIdentifier)) {
Function function1 = new Function(currentIdentifier);
if (!functions.empty() && functions.peek() != null) {
functions.peek().getArguments().add(function1);
}
functions.push(function1);
}
break;
}
buffer.append(current);
break;
case Commons.ARGUMENT_SEPARATOR:
if (flag == 0 || flag == 3) {
String currentIdentifier = buffer.toString().trim();
buffer = new StringBuilder();
if (!StringUtil.isEmpty(currentIdentifier)) {
if (flag == 3) {
flag = 0;
Identifier identifier = new Identifier(currentIdentifier);
functions.peek().getArguments().add(identifier);
} else {
Field field = new Field(currentIdentifier);
functions.peek().getArguments().add(field);
}
}
break;
}
buffer.append(current);
break;
case Commons.RIGHT_BRACKET:
if (flag != 1 && flag != 2) {
String currentIdentifier = buffer.toString().trim();
buffer = new StringBuilder();
if (!StringUtil.isEmpty(currentIdentifier)) {
if (flag == 3) {
flag = 0;
Identifier identifier = new Identifier(currentIdentifier);
functions.peek().getArguments().add(identifier);
} else {
Field field = new Field(currentIdentifier);
functions.peek().getArguments().add(field);
}
}
if (flag == 0) {
if (functions.size() == 1) {
return functions.pop();
} else {
functions.pop();
}
}
break;
}
buffer.append(current);
break;
case Commons.QUOTE:
if (flag == 0) {
flag = 1;
} else if (flag == 1) {
flag = 3;
}
case Commons.DOUBLE_QUOTE:
if (flag == 0) {
flag = 2;
} else if (flag == 2) {
flag = 3;
}
default:
buffer.append(current);
}
}
throw new SQLNonTransientException("Function is not in right format!");
}
use of java.sql.SQLNonTransientException in project Mycat_plus by coderczp.
the class DruidInsertParser method parserSingleInsert.
/**
* 单条insert(非批量)
* @param schema
* @param rrs
* @param partitionColumn
* @param tableName
* @param insertStmt
* @throws SQLNonTransientException
*/
private void parserSingleInsert(SchemaConfig schema, RouteResultset rrs, String partitionColumn, String tableName, MySqlInsertStatement insertStmt) throws SQLNonTransientException {
boolean isFound = false;
for (int i = 0; i < insertStmt.getColumns().size(); i++) {
if (partitionColumn.equalsIgnoreCase(StringUtil.removeBackquote(insertStmt.getColumns().get(i).toString()))) {
// 找到分片字段
isFound = true;
String column = StringUtil.removeBackquote(insertStmt.getColumns().get(i).toString());
String value = StringUtil.removeBackquote(insertStmt.getValues().getValues().get(i).toString());
RouteCalculateUnit routeCalculateUnit = new RouteCalculateUnit();
routeCalculateUnit.addShardingExpr(tableName, column, value);
ctx.addRouteCalculateUnit(routeCalculateUnit);
// mycat是单分片键,找到了就返回
break;
}
}
if (!isFound) {
// 分片表的
String msg = "bad insert sql (sharding column:" + partitionColumn + " not provided," + insertStmt;
LOGGER.warn(msg);
throw new SQLNonTransientException(msg);
}
// INSERT INTO TABLEName (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1;
if (insertStmt.getDuplicateKeyUpdate() != null) {
List<SQLExpr> updateList = insertStmt.getDuplicateKeyUpdate();
for (SQLExpr expr : updateList) {
SQLBinaryOpExpr opExpr = (SQLBinaryOpExpr) expr;
String column = StringUtil.removeBackquote(opExpr.getLeft().toString().toUpperCase());
if (column.equals(partitionColumn)) {
String msg = "Sharding column can't be updated: " + tableName + " -> " + partitionColumn;
LOGGER.warn(msg);
throw new SQLNonTransientException(msg);
}
}
}
}
use of java.sql.SQLNonTransientException in project Mycat_plus by coderczp.
the class DruidInsertParser method parserBatchInsert.
/**
* insert into .... select .... 或insert into table() values (),(),....
* @param schema
* @param rrs
* @param insertStmt
* @throws SQLNonTransientException
*/
private void parserBatchInsert(SchemaConfig schema, RouteResultset rrs, String partitionColumn, String tableName, MySqlInsertStatement insertStmt) throws SQLNonTransientException {
// insert into table() values (),(),....
if (insertStmt.getValuesList().size() > 1) {
// 字段列数
int columnNum = insertStmt.getColumns().size();
int shardingColIndex = getShardingColIndex(insertStmt, partitionColumn);
if (shardingColIndex == -1) {
String msg = "bad insert sql (sharding column:" + partitionColumn + " not provided," + insertStmt;
LOGGER.warn(msg);
throw new SQLNonTransientException(msg);
} else {
List<ValuesClause> valueClauseList = insertStmt.getValuesList();
Map<Integer, List<ValuesClause>> nodeValuesMap = new HashMap<Integer, List<ValuesClause>>();
Map<Integer, Integer> slotsMap = new HashMap<>();
TableConfig tableConfig = schema.getTables().get(tableName);
AbstractPartitionAlgorithm algorithm = tableConfig.getRule().getRuleAlgorithm();
for (ValuesClause valueClause : valueClauseList) {
if (valueClause.getValues().size() != columnNum) {
String msg = "bad insert sql columnSize != valueSize:" + columnNum + " != " + valueClause.getValues().size() + "values:" + valueClause;
LOGGER.warn(msg);
throw new SQLNonTransientException(msg);
}
SQLExpr expr = valueClause.getValues().get(shardingColIndex);
String shardingValue = null;
if (expr instanceof SQLIntegerExpr) {
SQLIntegerExpr intExpr = (SQLIntegerExpr) expr;
shardingValue = intExpr.getNumber() + "";
} else if (expr instanceof SQLCharExpr) {
SQLCharExpr charExpr = (SQLCharExpr) expr;
shardingValue = charExpr.getText();
}
Integer nodeIndex = algorithm.calculate(shardingValue);
if (algorithm instanceof SlotFunction) {
slotsMap.put(nodeIndex, ((SlotFunction) algorithm).slotValue());
}
// 没找到插入的分片
if (nodeIndex == null) {
String msg = "can't find any valid datanode :" + tableName + " -> " + partitionColumn + " -> " + shardingValue;
LOGGER.warn(msg);
throw new SQLNonTransientException(msg);
}
if (nodeValuesMap.get(nodeIndex) == null) {
nodeValuesMap.put(nodeIndex, new ArrayList<ValuesClause>());
}
nodeValuesMap.get(nodeIndex).add(valueClause);
}
RouteResultsetNode[] nodes = new RouteResultsetNode[nodeValuesMap.size()];
int count = 0;
for (Map.Entry<Integer, List<ValuesClause>> node : nodeValuesMap.entrySet()) {
Integer nodeIndex = node.getKey();
List<ValuesClause> valuesList = node.getValue();
insertStmt.setValuesList(valuesList);
nodes[count] = new RouteResultsetNode(tableConfig.getDataNodes().get(nodeIndex), rrs.getSqlType(), insertStmt.toString());
if (algorithm instanceof SlotFunction) {
nodes[count].setSlot(slotsMap.get(nodeIndex));
nodes[count].setStatement(ParseUtil.changeInsertAddSlot(nodes[count].getStatement(), nodes[count].getSlot()));
}
nodes[count++].setSource(rrs);
}
rrs.setNodes(nodes);
rrs.setFinishedRoute(true);
}
} else if (insertStmt.getQuery() != null) {
// insert into .... select ....
String msg = "TODO:insert into .... select .... not supported!";
LOGGER.warn(msg);
throw new SQLNonTransientException(msg);
}
}
use of java.sql.SQLNonTransientException in project Mycat_plus by coderczp.
the class DruidLockTableParser method statementParse.
@Override
public void statementParse(SchemaConfig schema, RouteResultset rrs, SQLStatement stmt) throws SQLNonTransientException {
MySqlLockTableStatement lockTableStat = (MySqlLockTableStatement) stmt;
String table = lockTableStat.getTableSource().toString().toUpperCase();
TableConfig tableConfig = schema.getTables().get(table);
if (tableConfig == null) {
String msg = "can't find table define of " + table + " in schema:" + schema.getName();
LOGGER.warn(msg);
throw new SQLNonTransientException(msg);
}
LockType lockType = lockTableStat.getLockType();
if (LockType.WRITE != lockType && LockType.READ != lockType) {
String msg = "lock type must be write or read";
LOGGER.warn(msg);
throw new SQLNonTransientException(msg);
}
List<String> dataNodes = tableConfig.getDataNodes();
RouteResultsetNode[] nodes = new RouteResultsetNode[dataNodes.size()];
for (int i = 0; i < dataNodes.size(); i++) {
nodes[i] = new RouteResultsetNode(dataNodes.get(i), ServerParse.LOCK, stmt.toString());
}
rrs.setNodes(nodes);
rrs.setFinishedRoute(true);
}
Aggregations