1. 概述 select的语法解析总入口是: org.h2.command.Parser.parseSelect() 可以通过很多地方触发它, 最常见的是从org.h2.command.Parser.parsePrepared()触发它 触发调用parseSelect()的sql语法有三种情况: 分别是以"("、"select"、"from"开头的sql语法(不分大小写的) 2. 代码流程分析 如果sql是select name1 from mytable1 union select name2 from mytable2 parseSelect() =>parseSelectUnion() =>parseSelectSub() =>parseSelectSimple() =>parseSelectUnionExtension(Query, int, boolean) 对于简单的sql,如select name1 from mytable1 order by name1 parseSelectSub()负责解析select name1 from mytable1 parseSelectUnionExtension负责解析 order by name1 如果union sql是select name1 from mytable1 union select name2 from mytable2 order by name1 parseSelectSub()负责解析select name1 from mytable1 parseSelectUnionExtension负责解析 union select name2 from mytable2 order by name1 3. join分析 有6种join类型 RIGHT OUTER JOIN LEFT OUTER JOIN FULL //暂时不支持 INNER JOIN JOIN CROSS JOIN NATURAL JOIN 4.类图 org.h2.command.Prepared =>org.h2.command.dml.Query =>org.h2.command.dml.Select =>org.h2.command.dml.SelectUnion 调用顺序 =>org.h2.command.dml.Query.init()(org.h2.command.dml.Select.init()或org.h2.command.dml.SelectUnion.init()) =>org.h2.command.dml.Select.prepare() =>org.h2.command.dml.Query.query(int) init在调用完org.h2.command.Parser.parseSelect()里调用(在得到一个Query后) 或者在解析完一个子查询时org.h2.command.Parser.readTableFilter(boolean) 此时也得到一个Query, 还有一种特殊情况是org.h2.command.Parser.parseValues() 即类似VALUES(1, 'Hello'), (2, 'World')这样的语法 org.h2.command.dml.Select.init()代码分析 DROP TABLE IF EXISTS JoinTest1 CASCADE; CREATE TABLE IF NOT EXISTS JoinTest1(id int, name varchar(500), b boolean); DROP TABLE IF EXISTS JoinTest2 CASCADE; CREATE TABLE IF NOT EXISTS JoinTest2(id2 int, name2 varchar(500)); insert into JoinTest1(id, name, b) values(10, 'a1', true); insert into JoinTest1(id, name, b) values(20, 'b1', true); insert into JoinTest1(id, name, b) values(30, 'a2', false); insert into JoinTest1(id, name, b) values(40, 'b2', true); insert into JoinTest2(id2, name2) values(90, 'a11'); insert into JoinTest2(id2, name2) values(90, 'a11'); insert into JoinTest2(id2, name2) values(90, 'a11'); insert into JoinTest2(id2, name2) values(90, 'a11'); select rownum, * from JoinTest1 LEFT OUTER JOIN JoinTest2; select rownum, * from JoinTest1 RIGHT OUTER JOIN JoinTest2; select rownum, * from JoinTest1 INNER JOIN JoinTest2; select rownum, * from JoinTest1 JOIN JoinTest2; select * from JoinTest1 CROSS JOIN JoinTest2; select from JoinTest1 NATURAL JOIN JoinTest2; select * from JoinTest1 JOIN JoinTest2;