.
public class AntlrTest {
/**
* @param args
* @throws Exception
* @see org.apache.shardingsphere.sql.parser.core.parser.SQLParserFactory#createSQLParser(java.lang.String, org.apache.shardingsphere.sql.parser.spi.SQLParserConfiguration)
*/
public static void main(String[] args) throws Exception {
String logicSql = "insert into tb_users(id,name) values(111, \"name_1\"), (?, ?)";
DataNodeRouter dataNodeRouter = new DataNodeRouter();
dataNodeRouter.createRouteContext(logicSql, null, false);
}
static class DataNodeRouter {
/**
* @see org.apache.shardingsphere.underlying.route.DataNodeRouter#createRouteContext(java.lang.String, java.util.List, boolean)
* @see org.apache.shardingsphere.sql.parser.binder.SQLStatementContextFactory#newInstance
*/
private RouteContext createRouteContext(final String sql, final List<Object> parameters, final boolean useCache) {
SQLParserEngine sQLParserEngine = new SQLParserEngine();
SQLStatement sQLStatement = sQLParserEngine.parse0(sql, false);
if (sQLStatement instanceof DMLStatement) {
DMLStatement dMLStatement = (DMLStatement) sQLStatement;
if (dMLStatement instanceof SelectStatement) {
log.info("dMLStatement instanceof SelectStatement = {}", true);
} else if (dMLStatement instanceof UpdateStatement) {
log.info("dMLStatement instanceof UpdateStatement = {}", true);
} else if (dMLStatement instanceof DeleteStatement) {
log.info("dMLStatement instanceof DeleteStatement = {}", true);
} else if (dMLStatement instanceof InsertStatement) {
InsertStatement insertStatement = (InsertStatement) dMLStatement;
/**
* @see org.apache.shardingsphere.sql.parser.binder.statement.dml.InsertStatementContext#InsertStatementContext
*/
SimpleTableSegment tableSegment = insertStatement.getTable();
String tableName = insertStatement.getTable().getTableName().getIdentifier().getValue();
List<String> columnNames = insertStatement.getColumnNames();
log.info("tableName = {}, columnNames = {}", tableName, columnNames);
log.info("dMLStatement instanceof InsertStatement = {}", true);
/**
* insert into tb_users(id,name) values(111, "name_1"), (?, ?)
*
* getAllValueExpressions() = List<List<ExpressionSegment>> [
* [
* LiteralExpressionSegment(startIndex=37, stopIndex=39, literals=111)
* CommonExpressionSegment(startIndex=42, stopIndex=49, text="name_1")
* ],
* [
* ParameterMarkerExpressionSegment(startIndex=54, stopIndex=54, parameterMarkerIndex=0)
* ParameterMarkerExpressionSegment(startIndex=57, stopIndex=57, parameterMarkerIndex=1)
* ]
* ]
*/
for (Collection<ExpressionSegment> each : insertStatement.getAllValueExpressions()) {
new InsertValueContext(each, null, 0);
}
/**
* 插入的行数
*/
int valueListCount = insertStatement.getValueListCount();
log.info("valueListCount = {}",valueListCount);
}
}
return null;
}
}
/**
* 存放的是《每一行的值列表》
*/
static class InsertValueContext {
private final int parametersCount;
private final List<ExpressionSegment> valueExpressions;
public InsertValueContext(final Collection<ExpressionSegment> assignments, final List<Object> parameters, final int parametersOffset) {
parametersCount = calculateParametersCount(assignments); // 有多少个占位符,数量就等于几
valueExpressions = getValueExpressions(assignments); // 绑定参数值列表(包括:占位符、非占位符)
log.info("parametersCount = {}, valueExpressions = {}", parametersCount, valueExpressions);
// this.parameters = getParameters(parameters, parametersOffset);
}
private int calculateParametersCount(final Collection<ExpressionSegment> assignments) {
int result = 0;
for (ExpressionSegment each : assignments) {
if (each instanceof ParameterMarkerExpressionSegment) {
result++;
}
}
return result;
}
private List<ExpressionSegment> getValueExpressions(final Collection<ExpressionSegment> assignments) {
List<ExpressionSegment> result = new ArrayList<>(assignments.size());
result.addAll(assignments);
return result;
}
}
/**
* @see org.apache.shardingsphere.underlying.rewrite.context.SQLRewriteContext#generateSQLTokens()
* @see cn.java.sphere.demo.debug.SQLTokenGeneratorsDebug.SQLRewriteContextDecorator_
*/
static class SQLRewriteContext {
public void generateSQLTokens(final SQLStatementContext sqlStatementContext) {
// 要插入的表
{
TableTokenGenerator generator = new TableTokenGenerator();
Collection<TableToken> tokens = generator.generateSQLTokens(sqlStatementContext);
}
// 如果配置了自动生成key,根据配置,那么会在sql插入一个字段
{
GeneratedKeyInsertColumnTokenGenerator generator = new GeneratedKeyInsertColumnTokenGenerator();
GeneratedKeyInsertColumnToken token = generator.generateSQLToken((InsertStatementContext) sqlStatementContext);
}
// 如果配置了自动生成key,根据配置,那么会生成一个值占位符?,用于填充如uuid、雪花id
{
GeneratedKeyAssignmentTokenGenerator generator = new GeneratedKeyAssignmentTokenGenerator();
GeneratedKeyAssignmentToken token = generator.generateSQLToken((InsertStatementContext) sqlStatementContext);
}
}
}
public static class SQLParserEngine {
/**
* @see org.apache.shardingsphere.sql.parser.SQLParserEngine#parse0(java.lang.String, boolean)
*/
SQLStatement parse0(final String sql, final boolean useCache) {
// 1、解析出抽象语法树
SQLParserExecutor sQLParserExecutor = new SQLParserExecutor(sql);
ParseASTNode parseASTNode = sQLParserExecutor.execute();
ParseTree parseTree = parseASTNode.getRootNode();
final VisitorRule visitorRule = VisitorRule.valueOf(parseTree.getClass());
// 2、遍历抽象语法树
ParseTreeVisitor parseTreeVisitor = createParseTreeVisitor(visitorRule.getType());
SQLStatement result = (SQLStatement) parseTreeVisitor.visit(parseTree);
return result;
}
/**
* 《抽象语法树》访问器
*
* @param type
* @return
* @see org.apache.shardingsphere.sql.parser.core.visitor.ParseTreeVisitorFactory#createParseTreeVisitor
*/
private static ParseTreeVisitor createParseTreeVisitor(final SQLStatementType type) {
SQLVisitorFacade visitorFacade = new MySQLVisitorFacade();
try {
switch (type) {
case DML:
/**
* @see org.apache.shardingsphere.sql.parser.mysql.visitor.impl.MySQLDMLVisitor
*/
return (ParseTreeVisitor) visitorFacade.getDMLVisitorClass().getConstructor().newInstance();
case DDL:
/**
* @see org.apache.shardingsphere.sql.parser.mysql.visitor.impl.MySQLDDLVisitor
*/
return (ParseTreeVisitor) visitorFacade.getDDLVisitorClass().getConstructor().newInstance();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return null;
}
}
/**
* @see org.apache.shardingsphere.sql.parser.core.parser.SQLParserExecutor
*/
@RequiredArgsConstructor
static class SQLParserExecutor {
private final String sql;
public ParseASTNode execute() {
ParseASTNode result = towPhaseParse();
if (result.getRootNode() instanceof ErrorNode) {
throw new SQLParsingException(String.format("Unsupported SQL of `%s`", sql));
}
return result;
}
/**
* 解析《抽象语法树》
*
* @return
* @see org.apache.shardingsphere.sql.parser.mysql.MySQLParserConfiguration
*/
private ParseASTNode towPhaseParse() {
MySQLLexer mySQLLexer = new MySQLLexer(CharStreams.fromString(sql));
MySQLParser mySQLParser = new MySQLParser(new CommonTokenStream(mySQLLexer));
{
SQLParser sqlParser = mySQLParser;
try {
((Parser) sqlParser).setErrorHandler(new BailErrorStrategy());
((Parser) sqlParser).getInterpreter().setPredictionMode(PredictionMode.SLL);
return (ParseASTNode) sqlParser.parse();
} catch (final ParseCancellationException ex) {
((Parser) sqlParser).reset();
((Parser) sqlParser).setErrorHandler(new DefaultErrorStrategy());
((Parser) sqlParser).getInterpreter().setPredictionMode(PredictionMode.LL);
return (ParseASTNode) sqlParser.parse();
}
}
}
}
}
.