Previously, we have talked about how to judge the sql type by Mycat, and then handle it differently for different types of sql [Mycat principle analysis - SQL statement processing] , let's take a look at the DDL statement and how Mycat handles it.
In combination with the code in ServerParse.java, let's take a look at the common DDL statements supported by Mycat.
- CREATE: create index
- DROP: drop index
- TRUNCATE: truncate table
- ALTER: alter table
For DDL statements, Mycat does not provide a special Handler, but uses the unified ServerConnection.execute() method for processing. The following figure shows a brief processing of a DDL statement.
The difference with ordinary statements lies in the routing part of DDL statements. Let's take a look at the code of the routing part of DDL statements.
public static RouteResultset routeToDDLNode(RouteResultset rrs, int sqlType, String stmt,SchemaConfig schema) throws SQLSyntaxErrorException {
stmt = getFixedSql(stmt);
String tablename = "";
final String upStmt = stmt.toUpperCase();
//CREATE statement
if(upStmt.startsWith("CREATE")){
//CREATE INDEX statement
if (upStmt.contains("CREATE INDEX ")){
tablename = RouterUtil.getTableName(stmt, RouterUtil.getCreateIndexPos(upStmt, 0));
}else {
tablename = RouterUtil.getTableName(stmt, RouterUtil.getCreateTablePos(upStmt, 0));
}
//DROP statement
}else if(upStmt.startsWith("DROP")){
//DROP INDEX statement
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){ //Default node 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);
}
The above code mainly does the following two things:
- Determine logical table name
- Construct the RouteResultset object (the construction rule is that each dataNode corresponds to a RouteResultsetNode). If the logical inventory is in this table, it is constructed according to the configuration of TableConfig. If it does not exist, it is constructed according to the default dataNode of the logical library.