The overall planning

Based on the previous learning, we understand the main process of data sharding in ShardingSphere:

And the core modules of ShardingSphere-Infra:

In order to further master the skills of source analysis, in the following week, we will follow the order of [parse] -> [route] -> [rewrite] -> [execute] -> [merge], analyze the implementation principle of each function one by one.

Shardingsphere-infra-parser is today’s topic.

Quick start with official documentation

First, refer to the official introduction to quickly understand the general principle of Parser. In a nutshell, SQL parsing is completed in three steps:

  1. Lexical parser: split (disassemble into minimal elements), match (the dialect library corresponding to the DB type of this SQL)
  2. Syntax parsers: Converts to syntax trees
  3. Traverser Visitor: Traversal, parsed into SQLStatement

Analysis of the source code

Parsing the entrance

private SQLStatement parse0(final String sql, Final Boolean useCache) {try {/ / the default parser parsed return sqlStatementParserEngine. Parse (SQL, useCache); {} the catch (final SQLParsingException | ParseCancellationException originalEx) try {/ / exception, Go distSQL parser parsed return distSQLStatementParserEngine. Parse (SQL); } catch (final SQLParsingException ignored) { throw originalEx; }}}Copy the code

Introduced: about distSQL shardingsphere.apache.org/document/cu…

Parse into a syntax tree

public ParseTree parse(final String sql) { ParseASTNode result = twoPhaseParse(sql); // From this step, we can infer: If (result.getrootNode () instanceof ErrorNode) {throw new SQLParsingException("Unsupported SQL of `%s`", sql); } return result.getRootNode(); }Copy the code
Private ParseASTNode twoPhaseParse(final String SQL) {// According to DB type, Select the corresponding SQL parser DatabaseTypedSQLParserFacade sqlParserFacade = DatabaseTypedSQLParserFacadeRegistry. GetFacade (databaseType);  / / Parser inherited ANTLR Parser class SQLParser SQLParser. = SQLParserFactory newInstance (SQL, sqlParserFacade getLexerClass (), sqlParserFacade.getParserClass()); try { ((Parser) sqlParser).getInterpreter().setPredictionMode(PredictionMode.SLL); Return (ParseASTNode) sqlParser.parse(); } catch (final ParseCancellationException ex) { ((Parser) sqlParser).reset(); ((Parser) sqlParser).getInterpreter().setPredictionMode(PredictionMode.LL); try { return (ParseASTNode) sqlParser.parse(); } catch (final ParseCancellationException e) { throw new SQLParsingException("You have an error in your SQL syntax"); }}}Copy the code

Iterate through the syntax tree to get the sqlStatement

Public SQLStatement parse(final String SQL) {/** * parseengin.parse () returns: parseengin.parse () returns: Return visitorengine.visit (parserEngine.parse(SQL, false)); return visitorengine.visit (parserEngine.parse(SQL, false)); }Copy the code
Public <T> T visit(final ParseTree ParseTree) {// Create a visitor ParseTreeVisitor<T> visitor = SQLVisitorFactory.newInstance(databaseType, visitorType, SQLVisitorRule.valueOf(parseTree.getClass()), props); Return parsetree.accept (visitor); }Copy the code

The flow chart

conclusion

lesson

  1. At the beginning, I didn’t have a clear reading goal. I only focused on the flow of the program and didn’t think about the function of each step. As a result, I was caught in the details of parser unconsciously, and couldn’t understand it, but I didn’t get out in time, wasting a lot of time

harvest

  1. Through the source code + document form, a preliminary understanding of the implementation principle of SQL parser
  2. Have a deeper understanding of how to analyze source code and master it quickly