preface
In the last article, we analyzed SQL lexical parsing, mainly talking about how SQL is parsed into words one by one. Based on this, we will look at how Sharding-JDBC identifies SQL syntax and extracts table structure information for different DML statements.
Brief description of related classes
- SQLParsingEngine: a portal to parse SQL, analyze different SQL(SELECT,UPDATE etc), different SQLParser(MySQLParser etc), instantiate different parser classes (MySQLSelectParser etc).
- SQLParser: AN SQL interpreter that analyzes TABLE names, aliases, column names, and expressions in SQL and fills them with specific objects. Different databases have different implementations.
- SQLStatementParser: AbstractSelectParser AbstractSelectParser AbstractInsertParser AbstractSelectParser AbstractSelectParser AbstractInsertParser AbstractSelectParser AbstractSelectParser AbstractUpdateParser MySQLSelectParser is an implementation of AbstractSelectParser. For the parse () method, subclasses have different implementations; Analyze SQL statements by calling methods in SQLParser
- SQLStatement: the final parsing object of a SQL statement, including Table, Conditions, and Column. Different DML statements have different implementations
- SQLExpression: SQL expressions that analyze WHERE statements, mainly including expressions such as identifiers, numbers, attributes and placeholders
Sequence diagram
1, SQLParsingEngine
The entry to SQL parsing is parse(),
2, Analyze SQL semantics according to SQLParser (which type of SQL), instantiate the corresponding parsing class
/** * parse SQL. ** @returnSQL statement object */ public SQLStatementparse() {
SQLParser sqlParser = getSQLParser();
sqlParser.skipIfEqual(Symbol.SEMI);
if (sqlParser.equalAny(DefaultKeyword.WITH)) {
skipWith(sqlParser);
}
if (sqlParser.equalAny(DefaultKeyword.SELECT)) {
return SelectParserFactory.newInstance(sqlParser).parse();
}
if (sqlParser.equalAny(DefaultKeyword.INSERT)) {
return InsertParserFactory.newInstance(shardingRule, sqlParser).parse();
}
if (sqlParser.equalAny(DefaultKeyword.UPDATE)) {
return UpdateParserFactory.newInstance(sqlParser).parse();
}
if (sqlParser.equalAny(DefaultKeyword.DELETE)) {
return DeleteParserFactory.newInstance(sqlParser).parse();
}
throw new SQLParsingUnsupportedException(sqlParser.getLexer().getCurrentToken().getType());
}
Copy the code
Take SelectParserFactory as an example:
** @param sqlParser SQL parser * @returnPublic static AbstractSelectParser newInstance(final SQLParser SQLParser) {if (sqlParser instanceof MySQLParser) {
return new MySQLSelectParser(sqlParser);
}
if (sqlParser instanceof OracleParser) {
return new OracleSelectParser(sqlParser);
}
if (sqlParser instanceof SQLServerParser) {
return new SQLServerSelectParser(sqlParser);
}
if (sqlParser instanceof PostgreSQLParser) {
return new PostgreSQLSelectParser(sqlParser);
}
throw new UnsupportedOperationException(String.format("Cannot support sqlParser class [%s].", sqlParser.getClass()));
}
Copy the code
2, SQLParser:
SQL parser, mainly used to parse SQL statement objects, different databases have different implementation
** @param sqlStatement SQL statement object */ public final void parseSingleTable(final sqlStatement sqlStatement) {... / / omit sqlStatement. GetTables (). The add (table); ** @param sqlStatement SQL statement object * @returnExpression */ public final SQLExpression parseExpression(final SQLStatement SQLStatement) {int beginPosition = getLexer().getCurrentToken().getEndPosition(); SQLExpression result = parseExpression();if (result instanceof SQLPropertyExpression) {
setTableToken(sqlStatement, beginPosition, (SQLPropertyExpression) result);
}
returnresult; ** @param sqlStatement SQL statement object */ public final void parseWhere(final sqlStatement sqlStatement) { parseAlias();if(skipIfEqual(DefaultKeyword.WHERE)) { parseConditions(sqlStatement); }}Copy the code
3, SQLStatementParse
SQL statement interpreter, different DML statements have different implementation, different databases also have different implementation; Take a look at a screenshot of the implementation:
AbstractSelectParser
private final SQLParser sqlParser;
private final SelectStatement selectStatement;
Copy the code
These are two important parameters; The table structure of the SQL statement is analyzed by calling methods in SQLParser, and then the SelectStatement is constructed and returned
@Override
public final SelectStatement parse() {
query();
parseOrderBy();
customizedSelect();
appendDerivedColumns();
appendDerivedOrderBy();
return selectStatement;
}
Copy the code
4, SQLStatement:
Different DML statements have different implementations. Here is a screenshot of the implementation:
Take the SELECT statement as an example to see what the parameters are:
private boolean distinct;
private boolean containStar;
private int selectListLastPosition;
private int groupByLastPosition;
private final List<SelectItem> items = new LinkedList<>();
private final List<OrderItem> groupByItems = new LinkedList<>();
private final List<OrderItem> orderByItems = new LinkedList<>();
private Limit limit;
public SelectStatement() {
super(SQLType.SELECT);
}
Copy the code
Ok, today we will take a look at the classes and main methods used in SQL parsing. In the next article we will examine how SELECT statements are parsed
The last
Welcome to follow my public account and share your thoughts on programming, investment and life from time to time 🙂