use of java.sql.SQLNonTransientException in project Mycat-Server by MyCATApache.
the class DruidSelectParser method setLimitIFChange.
protected void setLimitIFChange(SQLStatement stmt, RouteResultset rrs, SchemaConfig schema, SQLBinaryOpExpr one, int firstrownum, int lastrownum) {
rrs.setLimitStart(firstrownum);
rrs.setLimitSize(lastrownum - firstrownum);
LayerCachePool tableId2DataNodeCache = (LayerCachePool) MycatServer.getInstance().getCacheService().getCachePool("TableID2DataNodeCache");
try {
tryRoute(schema, rrs, tableId2DataNodeCache);
} catch (SQLNonTransientException e) {
throw new RuntimeException(e);
}
if (isNeedChangeLimit(rrs)) {
one.setRight(new SQLIntegerExpr(0));
String curentDbType = "db2".equalsIgnoreCase(this.getCurentDbType()) ? "oracle" : getCurentDbType();
String sql = SQLUtils.toSQLString(stmt, curentDbType);
;
rrs.changeNodeSqlAfterAddLimit(schema, getCurentDbType(), sql, 0, lastrownum, false);
// 设置改写后的sql
getCtx().setSql(sql);
}
}
use of java.sql.SQLNonTransientException in project Mycat-Server by MyCATApache.
the class ServerLoadDataInfileHandler method tryDirectRoute.
private RouteResultset tryDirectRoute(String sql, String[] lineList) {
RouteResultset rrs = new RouteResultset(sql, ServerParse.INSERT);
rrs.setLoadData(true);
if (tableConfig == null && schema.getDataNode() != null) {
// 走默认节点
RouteResultsetNode rrNode = new RouteResultsetNode(schema.getDataNode(), ServerParse.INSERT, sql);
rrNode.setSource(rrs);
rrs.setNodes(new RouteResultsetNode[] { rrNode });
return rrs;
} else if (tableConfig != null && tableConfig.isGlobalTable()) {
ArrayList<String> dataNodes = tableConfig.getDataNodes();
RouteResultsetNode[] rrsNodes = new RouteResultsetNode[dataNodes.size()];
for (int i = 0, dataNodesSize = dataNodes.size(); i < dataNodesSize; i++) {
String dataNode = dataNodes.get(i);
RouteResultsetNode rrNode = new RouteResultsetNode(dataNode, ServerParse.INSERT, sql);
rrsNodes[i] = rrNode;
if (rrs.getDataNodeSlotMap().containsKey(dataNode)) {
rrsNodes[i].setSlot(rrs.getDataNodeSlotMap().get(dataNode));
}
rrsNodes[i].setSource(rrs);
}
rrs.setNodes(rrsNodes);
return rrs;
} else if (tableConfig != null) {
DruidShardingParseInfo ctx = new DruidShardingParseInfo();
ctx.addTable(tableName);
if (partitionColumnIndex == -1 || partitionColumnIndex >= lineList.length) {
return null;
} else {
String value = lineList[partitionColumnIndex];
RouteCalculateUnit routeCalculateUnit = new RouteCalculateUnit();
routeCalculateUnit.addShardingExpr(tableName, getPartitionColumn(), parseFieldString(value, loadData.getEnclose()));
ctx.addRouteCalculateUnit(routeCalculateUnit);
try {
SortedSet<RouteResultsetNode> nodeSet = new TreeSet<RouteResultsetNode>();
for (RouteCalculateUnit unit : ctx.getRouteCalculateUnits()) {
RouteResultset rrsTmp = RouterUtil.tryRouteForTables(schema, ctx, unit, rrs, false, tableId2DataNodeCache);
if (rrsTmp != null) {
for (RouteResultsetNode node : rrsTmp.getNodes()) {
nodeSet.add(node);
}
}
}
RouteResultsetNode[] nodes = new RouteResultsetNode[nodeSet.size()];
int i = 0;
for (Iterator<RouteResultsetNode> iterator = nodeSet.iterator(); iterator.hasNext(); ) {
nodes[i] = (RouteResultsetNode) iterator.next();
i++;
}
rrs.setNodes(nodes);
return rrs;
} catch (SQLNonTransientException e) {
throw new RuntimeException(e);
}
}
}
return null;
}
use of java.sql.SQLNonTransientException in project Mycat-Server by MyCATApache.
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-Server by MyCATApache.
the class RouterUtil method processERChildTable.
/**
* 该方法,返回是否是ER子表
* @param schema
* @param origSQL
* @param sc
* @return
* @throws SQLNonTransientException
*
* 备注说明:
* edit by ding.w at 2017.4.28, 主要处理 CLIENT_MULTI_STATEMENTS(insert into ; insert into)的情况
* 目前仅支持mysql,并COM_QUERY请求包中的所有insert语句要么全部是er表,要么全部不是
*/
public static boolean processERChildTable(final SchemaConfig schema, final String origSQL, final ServerConnection sc) throws SQLNonTransientException {
MySqlStatementParser parser = new MySqlStatementParser(origSQL);
List<SQLStatement> statements = parser.parseStatementList();
if (statements == null || statements.isEmpty()) {
throw new SQLNonTransientException(String.format("无效的SQL语句:%s", origSQL));
}
// 是否是er表
boolean erFlag = false;
for (SQLStatement stmt : statements) {
MySqlInsertStatement insertStmt = (MySqlInsertStatement) stmt;
String tableName = insertStmt.getTableName().getSimpleName().toUpperCase();
final TableConfig tc = schema.getTables().get(tableName);
if (null != tc && tc.isChildTable()) {
erFlag = true;
String sql = insertStmt.toString();
final RouteResultset rrs = new RouteResultset(sql, ServerParse.INSERT);
String joinKey = tc.getJoinKey();
// 因为是Insert语句,用MySqlInsertStatement进行parse
// MySqlInsertStatement insertStmt = (MySqlInsertStatement) (new MySqlStatementParser(origSQL)).parseInsert();
// 判断条件完整性,取得解析后语句列中的joinkey列的index
int joinKeyIndex = getJoinKeyIndex(insertStmt.getColumns(), joinKey);
if (joinKeyIndex == -1) {
String inf = "joinKey not provided :" + tc.getJoinKey() + "," + insertStmt;
LOGGER.warn(inf);
throw new SQLNonTransientException(inf);
}
// 子表不支持批量插入
if (isMultiInsert(insertStmt)) {
String msg = "ChildTable multi insert not provided";
LOGGER.warn(msg);
throw new SQLNonTransientException(msg);
}
// 取得joinkey的值
String joinKeyVal = insertStmt.getValues().getValues().get(joinKeyIndex).toString();
// 解决bug #938,当关联字段的值为char类型时,去掉前后"'"
String realVal = joinKeyVal;
if (joinKeyVal.startsWith("'") && joinKeyVal.endsWith("'") && joinKeyVal.length() > 2) {
realVal = joinKeyVal.substring(1, joinKeyVal.length() - 1);
}
// try to route by ER parent partion key
// 如果是二级子表(父表不再有父表),并且分片字段正好是joinkey字段,调用routeByERParentKey
RouteResultset theRrs = RouterUtil.routeByERParentKey(sc, schema, ServerParse.INSERT, sql, rrs, tc, realVal);
if (theRrs != null) {
boolean processedInsert = false;
// 判断是否需要全局序列号
if (sc != null && tc.isAutoIncrement()) {
String primaryKey = tc.getPrimaryKey();
processedInsert = processInsert(sc, schema, ServerParse.INSERT, sql, tc.getName(), primaryKey);
}
if (processedInsert == false) {
rrs.setFinishedRoute(true);
sc.getSession2().execute(rrs, ServerParse.INSERT);
}
// 继续处理下一条
continue;
}
// route by sql query root parent's datanode
// 如果不是二级子表或者分片字段不是joinKey字段结果为空,则启动异步线程去后台分片查询出datanode
// 只要查询出上一级表的parentkey字段的对应值在哪个分片即可
final String findRootTBSql = tc.getLocateRTableKeySql().toLowerCase() + joinKeyVal;
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("find root parent's node sql " + findRootTBSql);
}
ListenableFuture<String> listenableFuture = MycatServer.getInstance().getListeningExecutorService().submit(new Callable<String>() {
@Override
public String call() throws Exception {
FetchStoreNodeOfChildTableHandler fetchHandler = new FetchStoreNodeOfChildTableHandler();
// return fetchHandler.execute(schema.getName(), findRootTBSql, tc.getRootParent().getDataNodes());
return fetchHandler.execute(schema.getName(), findRootTBSql, tc.getRootParent().getDataNodes(), sc);
}
});
Futures.addCallback(listenableFuture, new FutureCallback<String>() {
@Override
public void onSuccess(String result) {
// 结果为空,证明上一级表中不存在那条记录,失败
if (Strings.isNullOrEmpty(result)) {
StringBuilder s = new StringBuilder();
LOGGER.warn(s.append(sc.getSession2()).append(origSQL).toString() + " err:" + "can't find (root) parent sharding node for sql:" + origSQL);
if (!sc.isAutocommit()) {
// 处于事务下失败, 必须回滚
sc.setTxInterrupt("can't find (root) parent sharding node for sql:" + origSQL);
}
sc.writeErrMessage(ErrorCode.ER_PARSE_ERROR, "can't find (root) parent sharding node for sql:" + origSQL);
return;
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("found partion node for child table to insert " + result + " sql :" + origSQL);
}
// 找到分片,进行插入(和其他的一样,需要判断是否需要全局自增ID)
boolean processedInsert = false;
if (sc != null && tc.isAutoIncrement()) {
try {
String primaryKey = tc.getPrimaryKey();
processedInsert = processInsert(sc, schema, ServerParse.INSERT, origSQL, tc.getName(), primaryKey);
} catch (SQLNonTransientException e) {
LOGGER.warn("sequence processInsert error,", e);
sc.writeErrMessage(ErrorCode.ER_PARSE_ERROR, "sequence processInsert error," + e.getMessage());
}
}
if (processedInsert == false) {
RouteResultset executeRrs = RouterUtil.routeToSingleNode(rrs, result, origSQL);
sc.getSession2().execute(executeRrs, ServerParse.INSERT);
}
}
@Override
public void onFailure(Throwable t) {
StringBuilder s = new StringBuilder();
LOGGER.warn(s.append(sc.getSession2()).append(origSQL).toString() + " err:" + t.getMessage());
sc.writeErrMessage(ErrorCode.ER_PARSE_ERROR, t.getMessage() + " " + s.toString());
}
}, MycatServer.getInstance().getListeningExecutorService());
} else if (erFlag) {
throw new SQLNonTransientException(String.format("%s包含不是ER分片的表", origSQL));
}
}
return erFlag;
}
use of java.sql.SQLNonTransientException in project Mycat-Server by MyCATApache.
the class RouterUtil method ruleByJoinValueCalculate.
/**
* @return dataNodeIndex -> [partitionKeysValueTuple+]
*/
public static Set<String> ruleByJoinValueCalculate(RouteResultset rrs, TableConfig tc, Set<ColumnRoutePair> colRoutePairSet) throws SQLNonTransientException {
String joinValue = "";
if (colRoutePairSet.size() > 1) {
LOGGER.warn("joinKey can't have multi Value");
} else {
Iterator<ColumnRoutePair> it = colRoutePairSet.iterator();
ColumnRoutePair joinCol = it.next();
joinValue = joinCol.colValue;
}
Set<String> retNodeSet = new LinkedHashSet<String>();
Set<String> nodeSet;
if (tc.isSecondLevel() && tc.getParentTC().getPartitionColumn().equals(tc.getParentKey())) {
// using
// parent
// rule to
// find
// datanode
nodeSet = ruleCalculate(tc.getParentTC(), colRoutePairSet, rrs.getDataNodeSlotMap());
if (nodeSet.isEmpty()) {
throw new SQLNonTransientException("parent key can't find valid datanode ,expect 1 but found: " + nodeSet.size());
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("found partion node (using parent partion rule directly) for child table to insert " + nodeSet + " sql :" + rrs.getStatement());
}
retNodeSet.addAll(nodeSet);
// }
return retNodeSet;
} else {
retNodeSet.addAll(tc.getParentTC().getDataNodes());
}
return retNodeSet;
}
Aggregations