use of io.mycat.route.function.SlotFunction in project Mycat-Server by MyCATApache.
the class DruidMycatRouteStrategy method routeNormalSqlWithAST.
@Override
public RouteResultset routeNormalSqlWithAST(SchemaConfig schema, String stmt, RouteResultset rrs, String charset, LayerCachePool cachePool) throws SQLNonTransientException {
/**
* 只有mysql时只支持mysql语法
*/
SQLStatementParser parser = null;
if (schema.isNeedSupportMultiDBType()) {
parser = new MycatStatementParser(stmt);
} else {
parser = new MySqlStatementParser(stmt);
}
MycatSchemaStatVisitor visitor = null;
SQLStatement statement;
/**
* 解析出现问题统一抛SQL语法错误
*/
try {
statement = parser.parseStatement();
visitor = new MycatSchemaStatVisitor();
} catch (Exception t) {
LOGGER.error("DruidMycatRouteStrategyError", t);
throw new SQLSyntaxErrorException(t);
}
/**
* 检验unsupported statement
*/
checkUnSupportedStatement(statement);
DruidParser druidParser = DruidParserFactory.create(schema, statement, visitor);
druidParser.parser(schema, rrs, statement, stmt, cachePool, visitor);
DruidShardingParseInfo ctx = druidParser.getCtx();
rrs.setTables(ctx.getTables());
/**
* DruidParser 解析过程中已完成了路由的直接返回
*/
if (rrs.isFinishedRoute()) {
return rrs;
}
/**
* 没有from的select语句或其他
*/
if ((ctx.getTables() == null || ctx.getTables().size() == 0) && (ctx.getTableAliasMap() == null || ctx.getTableAliasMap().isEmpty())) {
return RouterUtil.routeToSingleNode(rrs, schema.getRandomDataNode(), druidParser.getCtx().getSql());
}
if (druidParser.getCtx().getRouteCalculateUnits().size() == 0) {
RouteCalculateUnit routeCalculateUnit = new RouteCalculateUnit();
druidParser.getCtx().addRouteCalculateUnit(routeCalculateUnit);
}
SortedSet<RouteResultsetNode> nodeSet = new TreeSet<RouteResultsetNode>();
for (RouteCalculateUnit unit : druidParser.getCtx().getRouteCalculateUnits()) {
RouteResultset rrsTmp = RouterUtil.tryRouteForTables(schema, druidParser.getCtx(), unit, rrs, isSelect(statement), cachePool);
if (rrsTmp != null) {
for (RouteResultsetNode node : rrsTmp.getNodes()) {
nodeSet.add(node);
}
}
}
RouteResultsetNode[] nodes = new RouteResultsetNode[nodeSet.size()];
int i = 0;
for (RouteResultsetNode aNodeSet : nodeSet) {
nodes[i] = aNodeSet;
if (statement instanceof MySqlInsertStatement && ctx.getTables().size() == 1 && schema.getTables().containsKey(ctx.getTables().get(0))) {
RuleConfig rule = schema.getTables().get(ctx.getTables().get(0)).getRule();
if (rule != null && rule.getRuleAlgorithm() instanceof SlotFunction) {
aNodeSet.setStatement(ParseUtil.changeInsertAddSlot(aNodeSet.getStatement(), aNodeSet.getSlot()));
}
}
i++;
}
rrs.setNodes(nodes);
/**
* subTables="t_order$1-2,t_order3"
*目前分表 1.6 开始支持 幵丏 dataNode 在分表条件下只能配置一个,分表条件下不支持join。
*/
if (rrs.isDistTable()) {
return this.routeDisTable(statement, rrs);
}
return rrs;
}
use of io.mycat.route.function.SlotFunction in project Mycat-Server by MyCATApache.
the class RouterUtil method routeToDDLNode.
/**
* 修复DDL路由
*
* @return RouteResultset
* @author aStoneGod
*/
public static RouteResultset routeToDDLNode(RouteResultset rrs, int sqlType, String stmt, SchemaConfig schema) throws SQLSyntaxErrorException {
stmt = getFixedSql(stmt);
String tablename = "";
final String upStmt = stmt.toUpperCase();
if (upStmt.startsWith("CREATE")) {
if (upStmt.contains("CREATE INDEX ")) {
tablename = RouterUtil.getTableName(stmt, RouterUtil.getCreateIndexPos(upStmt, 0));
} else {
tablename = RouterUtil.getTableName(stmt, RouterUtil.getCreateTablePos(upStmt, 0));
}
} else if (upStmt.startsWith("DROP")) {
if (upStmt.contains("DROP INDEX ")) {
tablename = RouterUtil.getTableName(stmt, RouterUtil.getDropIndexPos(upStmt, 0));
} else {
tablename = RouterUtil.getTableName(stmt, RouterUtil.getDropTablePos(upStmt, 0));
}
} else if (upStmt.startsWith("ALTER")) {
tablename = RouterUtil.getTableName(stmt, RouterUtil.getAlterTablePos(upStmt, 0));
} else if (upStmt.startsWith("TRUNCATE")) {
tablename = RouterUtil.getTableName(stmt, RouterUtil.getTruncateTablePos(upStmt, 0));
}
tablename = tablename.toUpperCase();
if (schema.getTables().containsKey(tablename)) {
if (ServerParse.DDL == sqlType) {
List<String> dataNodes = new ArrayList<>();
Map<String, TableConfig> tables = schema.getTables();
TableConfig tc = tables.get(tablename);
if (tables != null && (tc != null)) {
dataNodes = tc.getDataNodes();
}
boolean isSlotFunction = tc.getRule() != null && tc.getRule().getRuleAlgorithm() instanceof SlotFunction;
Iterator<String> iterator1 = dataNodes.iterator();
int nodeSize = dataNodes.size();
RouteResultsetNode[] nodes = new RouteResultsetNode[nodeSize];
if (isSlotFunction) {
stmt = changeCreateTable(schema, tablename, stmt);
}
for (int i = 0; i < nodeSize; i++) {
String name = iterator1.next();
nodes[i] = new RouteResultsetNode(name, sqlType, stmt);
nodes[i].setSource(rrs);
if (rrs.getDataNodeSlotMap().containsKey(name)) {
nodes[i].setSlot(rrs.getDataNodeSlotMap().get(name));
} else if (isSlotFunction) {
nodes[i].setSlot(-1);
}
}
rrs.setNodes(nodes);
}
return rrs;
} else if (schema.getDataNode() != null) {
//默认节点ddl
RouteResultsetNode[] nodes = new RouteResultsetNode[1];
nodes[0] = new RouteResultsetNode(schema.getDataNode(), sqlType, stmt);
nodes[0].setSource(rrs);
rrs.setNodes(nodes);
return rrs;
}
//both tablename and defaultnode null
LOGGER.error("table not in schema----" + tablename);
throw new SQLSyntaxErrorException("op table not in schema----" + tablename);
}
use of io.mycat.route.function.SlotFunction in project Mycat-Server by MyCATApache.
the class ServerLoadDataInfileHandler method start.
@Override
public void start(String sql) {
clear();
this.sql = sql;
SQLStatementParser parser = new MycatStatementParser(sql);
statement = (MySqlLoadDataInFileStatement) parser.parseStatement();
fileName = parseFileName(sql);
if (fileName == null) {
serverConnection.writeErrMessage(ErrorCode.ER_FILE_NOT_FOUND, " file name is null !");
clear();
return;
}
schema = MycatServer.getInstance().getConfig().getSchemas().get(serverConnection.getSchema());
tableId2DataNodeCache = (LayerCachePool) MycatServer.getInstance().getCacheService().getCachePool("TableID2DataNodeCache");
tableName = statement.getTableName().getSimpleName().toUpperCase();
tableConfig = schema.getTables().get(tableName);
if (tableConfig.getRule().getRuleAlgorithm() instanceof SlotFunction) {
shoudAddSlot = true;
}
tempPath = SystemConfig.getHomePath() + File.separator + "temp" + File.separator + serverConnection.getId() + File.separator;
tempFile = tempPath + "clientTemp.txt";
tempByteBuffer = new ByteArrayOutputStream();
List<SQLExpr> columns = statement.getColumns();
if (tableConfig != null) {
String pColumn = getPartitionColumn();
if (pColumn != null && columns != null && columns.size() > 0) {
for (int i = 0, columnsSize = columns.size(); i < columnsSize; i++) {
String column = StringUtil.removeBackquote(columns.get(i).toString());
if (pColumn.equalsIgnoreCase(column)) {
partitionColumnIndex = i;
}
if ("_slot".equalsIgnoreCase(column)) {
shoudAddSlot = false;
}
}
}
}
if (shoudAddSlot) {
columns.add(new SQLIdentifierExpr("_slot"));
}
parseLoadDataPram();
if (statement.isLocal()) {
isStartLoadData = true;
//向客户端请求发送文件
ByteBuffer buffer = serverConnection.allocate();
RequestFilePacket filePacket = new RequestFilePacket();
filePacket.fileName = fileName.getBytes();
filePacket.packetId = 1;
filePacket.write(buffer, serverConnection, true);
} else {
if (!new File(fileName).exists()) {
serverConnection.writeErrMessage(ErrorCode.ER_FILE_NOT_FOUND, fileName + " is not found!");
clear();
} else {
parseFileByLine(fileName, loadData.getCharset(), loadData.getLineTerminatedBy());
RouteResultset rrs = buildResultSet(routeResultMap);
if (rrs != null) {
flushDataToFile();
isStartLoadData = false;
serverConnection.getSession2().execute(rrs, ServerParse.LOAD_DATA_INFILE_SQL);
}
}
}
}
use of io.mycat.route.function.SlotFunction in project Mycat-Server by MyCATApache.
the class DruidCreateTableParser method statementParse.
@Override
public void statementParse(SchemaConfig schema, RouteResultset rrs, SQLStatement stmt) throws SQLNonTransientException {
MySqlCreateTableStatement createStmt = (MySqlCreateTableStatement) stmt;
if (createStmt.getQuery() != null) {
String msg = "create table from other table not supported :" + stmt;
LOGGER.warn(msg);
throw new SQLNonTransientException(msg);
}
String tableName = StringUtil.removeBackquote(createStmt.getTableSource().toString().toUpperCase());
if (schema.getTables().containsKey(tableName)) {
TableConfig tableConfig = schema.getTables().get(tableName);
AbstractPartitionAlgorithm algorithm = tableConfig.getRule().getRuleAlgorithm();
if (algorithm instanceof SlotFunction) {
SQLColumnDefinition column = new SQLColumnDefinition();
column.setDataType(new SQLCharacterDataType("int"));
column.setName(new SQLIdentifierExpr("_slot"));
column.setComment(new SQLCharExpr("自动迁移算法slot,禁止修改"));
((SQLCreateTableStatement) stmt).getTableElementList().add(column);
String sql = createStmt.toString();
rrs.setStatement(sql);
ctx.setSql(sql);
}
}
ctx.addTable(tableName);
}
use of io.mycat.route.function.SlotFunction in project Mycat-Server by MyCATApache.
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);
}
}
Aggregations