MyCATApache/Mycat-Server · error · SQLNonTransientException
"TODO:insert into .... select .... not supported!"
Error message
"TODO:insert into .... select .... not supported!"
What it means
Mycat does not implement routing for INSERT INTO ... SELECT .... parserBatchInsert detects insertStmt.getQuery() != null and throws SQLNonTransientException with a TODO message, marking the feature as unimplemented.
Solutions
- Split into SELECT the data in the application, then batch INSERT the rows via Mycat
- Run the INSERT...SELECT directly on the backend MySQL node(s) if both tables live on the same datanode
- Precompute the SELECT into a temp staging file/table and insert from the application
- Check newer Mycat forks/versions that may add INSERT...SELECT support
Example fix
// before INSERT INTO t2 (a,b) SELECT a,b FROM t1 WHERE x > 10; // after -- app-side: rows = SELECT a,b FROM t1 WHERE x > 10 INSERT INTO t2 (a,b) VALUES (?,?),(?,?); -- batch insert of fetched rows
Defensive patterns
Strategy: try-catch
Validate before calling
// reject INSERT ... SELECT before routing
String normalized = sql.replaceAll("\\s+", " ").toUpperCase();
if (normalized.startsWith("INSERT") && normalized.contains("SELECT")) {
throw new IllegalArgumentException("INSERT ... SELECT not supported via Mycat; split it");
} Type guard
static boolean isInsertSelect(SQLStatement stmt) {
return stmt instanceof MySqlInsertStatement
&& ((MySqlInsertStatement) stmt).getQuery() != null;
} Try / catch
try {
execute(sql);
} catch (SQLNonTransientException e) {
if (e.getMessage().contains("insert into .... select .... not supported")) {
// fallback: fetch rows client-side, then batch insert
List<Row> rows = selectAll(sourceSql);
batchInsert(target, rows);
return;
}
throw e;
} Prevention
- Never use INSERT ... SELECT through Mycat; split into read + batch write
- Run ETL copy jobs directly on backend nodes when possible
- Add a SQL lint rule in CI flagging INSERT...SELECT for Mycat-routed datasources
When it happens
Trigger: Executing `INSERT INTO t1 (cols) SELECT ... FROM t2` through Mycat — the insert statement carries a query body instead of VALUES.
Common situations: Data-migration/ETL scripts copying between tables; dedup/archival jobs (INSERT INTO archive SELECT ...); porting stored-procedure-style SQL from plain MySQL to Mycat.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- "create table from other table not supported :" + stmt
- bad insert sql columnSize != valueSize:values:
- TODO:insert into .... select .... not supported!
- "can't find table define in schema " + tableName + "…
- "joinKey not provided :" + tc.getJoinKey()+ "," + insertStmt
AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11).
Data as JSON: /api/errors/556176c80b673018.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/io/mycat/route/parser/druid/impl/DruidInsertParser.java:324
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);
}
}
private String getShardingValue(SQLExpr expr) throws SQLNonTransientException {
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();
} else if (expr instanceof SQLMethodInvokeExpr) {
SQLMethodInvokeExpr methodInvokeExpr = (SQLMethodInvokeExpr)expr;
try {
shardingValue = tryInvokeSQLMethod(methodInvokeExpr);
}catch (Exception e){
LOGGER.error("",e);
}View on GitHub (pinned to 65f8d8beb7)