【mysql】druid数据库连接池之sql解析原理
一、druid的sql解析包含四部分
- 词法分析器(Lexer)(单词分割,将sql语句中的关键词,标点,用户的相关信息提取出来)
- 语法分析器(Parser) (形式语言的语法解析,组装语法树)
- 抽象语法树(AST)(语法树)
- 语法树访问器(Visitor)对语法树进行遍历访问,采用访问者模式,将数据和行为进行分离的一种设计模式)
二、词法分析器(Lexer)
com.alibaba.druid.sql.parser.Lexer
com.alibaba.druid.sql.dialect.mysql.parser.Lexer
(1)词法分析的token内容
com.alibaba.druid.sql.parser.Token
com.alibaba.druid.sql.parser.Keywords
(2)词法分析的案例
/** * SELECT 关键字-select * IDENTIFIER 标识符 * COMMA 关键字-标点符"," * IDENTIFIER * COMMA * IDENTIFIER * FROM * IDENTIFIER * WHERE * IDENTIFIER * EQ 关键字-标点符"=" * QUES * AND * IDENTIFIER * EQ * LITERAL_INT * ORDER * BY * IDENTIFIER * DESC * EOF 结束符号,标识sql终结 */ public static void test03() { String sql = "select name,age,money from tb_order where id=? and status= 2 order by name desc"; Lexer lexer = new Lexer(sql); for (; ; ) { lexer.nextToken(); Token token = lexer.token(); System.out.println(token.name()); if ("EOF".equals(token.name())) { break; } } }
三、语法分析器(Parser)
com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser
com.alibaba.druid.sql.parser.SQLStatementParser
com.alibaba.druid.sql.parser.SQLParser
四、抽象语法树(AST)
com.alibaba.druid.sql.ast.statement.SQLSelectStatement (select语句)
com.alibaba.druid.sql.ast.statement.SQLUpdateStatement (update语句)
com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement (update语句)
com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement(insert语句)
com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement(delete语句)
com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateServerStatement
com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement
五、语法树访问器(Visitor)
com.alibaba.druid.sql.visitor.SQLASTVisitor
com.alibaba.druid.sql.visitor.SchemaStatVisitor
六、一个小案例
/** * sql语句的列名=>name * sql语句的列名=>age * sql语句的列名=>money * sql语句的列名=>id * sql语句的列名=>status * 条件名=>tb_order.id * 操作符=>= * 值=>123 * 条件名=>tb_order.status * 操作符=>= * 值=>2 * 表名=>tb_order */ public static void test02(){ String sql = "select name,age,money from tb_order where id=123 and status= 2 order by name desc"; List<SQLStatement> sqlStatements1=SQLUtils.parseStatements(sql,"mysql"); SQLStatement sqlStatement=sqlStatements1.get(0); SchemaStatVisitor schemaStatVisitor=new SchemaStatVisitor(); sqlStatement.accept(schemaStatVisitor); //获取列信息 Collection<TableStat.Column> columns=schemaStatVisitor.getColumns(); for(TableStat.Column column:columns){ System.out.println("sql语句的列名=>"+column.getName()); } //获取条件信息 List<TableStat.Condition> conditions=schemaStatVisitor.getConditions(); for(TableStat.Condition condition:conditions){ System.out.println("条件名=>"+condition.getColumn()); System.out.println("操作符=>"+condition.getOperator()); System.out.println("值=>"+condition.getValues().get(0)); } //获取表名 Map<TableStat.Name, TableStat> statMap= schemaStatVisitor.getTables(); for(TableStat.Name name:statMap.keySet()){ System.out.println("表名=>"+name.getName()); } }
七、语法树节点分类
com.alibaba.druid.sql.ast.SQLObject
com.alibaba.druid.sql.ast.SQLStatement
com.alibaba.druid.sql.ast.SQLExpr
com.alibaba.druid.sql.ast.statement.SQLConstraint
详细描述:https://blog.csdn.net/qq_25104587/article/details/90577646
浙公网安备 33010602011771号