calcite连接mysql_使用Calcite做Sql语法解析
Flink SQL中使用Calcite作為sql語法解析、校驗、優化工具,本篇是實操篇,介紹一下calcite做sql語法解析使用方式。
sql經過calcite解析之后,得到一棵抽象語法樹,也就是我們說的AST,這棵語法樹是由不同的節點組成,節點稱之為SqlNode,根據不同類型的dml、ddl得到不同的類型的SqlNode,例如select語句轉換為SqlSelect,delete語句轉換為SqlDelete,join語句轉換為SqlJoin。
使用方式:SqlParser.Config?config?=?SqlParser.configBuilder()?????????.setLex(Lex.MYSQL)?//使用mysql?語法?????????.build();//SqlParser?語法解析器?????????SqlParser?sqlParser?=?SqlParser???????.create("select?id,name,age?FROM?stu?where?age<20",?config);SqlNode?sqlNode?=?null;try?{???sqlNode?=?sqlParser.parseStmt();}?catch?(SqlParseException?e)?{??throw?new?RuntimeException("",?e);}這里解析了一個select的語句,那么得到的sqlNode就是一個SqlSelect。if(SqlKind.SELECT.equals(sqlNode.getKind())){SqlSelect sqlSelect = (SqlSelect) sqlNode;SqlNode from=sqlSelect.getFrom();SqlNode where=sqlSelect.getWhere();SqlNodeList selectList=sqlSelect.getSelectList();//標識符if(SqlKind.IDENTIFIER.equals(from.getKind())){System.out.println(from.toString());}if(SqlKind.LESS_THAN.equals(where.getKind())){SqlBasicCall sqlBasicCall=(SqlBasicCall)where;for(SqlNode sqlNode1: sqlBasicCall.operands){if(SqlKind.LITERAL.equals(sqlNode1.getKind())){System.out.println(sqlNode1.toString());}}}selectList.getList().forEach(x->{if(SqlKind.IDENTIFIER.equals(x.getKind())){System.out.println(x.toString());}});}一個select語句包含from部分、where部分、select部分等,每一部分都表示一個SqlNode。SqlKind是一個枚舉類型,包含了各種SqlNode類型:SqlSelect、SqlIdentifier、SqlLiteral等。SqlIdentifier表示標識符,例如表名稱、字段名;SqlLiteral表示字面常量,一些具體的數字、字符。
SqlBasicCall對比SqlSelect/SqlDelete而言,可以理解為表示的是一些基本的、簡單的調用,例如聚合函數、比較函數等,接下來看一下其如何解析sum操作:select?sum(amount)?FROM?orders?//解析的sql//解析select部分selectList.getList().forEach(x->{????if(SqlKind.SUM.equals(x.getKind())){??????SqlBasicCall?sqlBasicCall=(SqlBasicCall)x;??????System.out.println(sqlBasicCall.operands[0]);???}?});其內部主要就是operands,也是SqlNode節點,但是都是一些基本的SqlNode,例如SqlIdentifier、SqlLiteral。
SqlSelect/SqlDelete/SqlBasicCall 都稱之為SqlCall,差別是SqlSelect是復雜的SqlCall,內部可以包含其他節點,而SqlBasicCall表示簡單的SqlCall。另外兩種SqlNode:SqlDataTypeSpec與SqlNodeList,SqlDataTypeSpec代表數據類型節點,例如CHAR/VARCHAR/DOUBLE,?SqlNodeList表示包含多個同級別的SqlNode,在上面select中已經展示過,看下SqlDataTypeSpec使用實例:select?cast(amount?as?CHAR)?FROM?orders//解析的sql//解析select部分selectList.getList().forEach(x->{???if(SqlKind.CAST.equals(x.getKind())){????????SqlBasicCall?sqlBasicCall=(SqlBasicCall)x;????????System.out.println(sqlBasicCall.operands[0]);?//amount????????SqlDataTypeSpec?charType=(SqlDataTypeSpec)sqlBasicCall.operands[1];????????System.out.println(charType.getTypeName());?//CHAR??}});
另外一種節點SqlOperator,可以代表函數、運算符、語法(select)結構,例如sum解析為SqlAggFunction、select解析為SqlSelectOperator,as 作為SqlAsOperator。SqlOperator是被嵌入在SqlNode中,作為其屬性,通過SqlOperator的createCall方法可以創建對應的SqlNode,使用方式:SqlOperator?operator?=?new?SqlAsOperator();SqlParserPos?sqlParserPos?=?new?SqlParserPos(1,?1);SqlIdentifier?name?=?new?SqlIdentifier("orders",?null,?sqlParserPos);SqlIdentifier?alias?=?new?SqlIdentifier("o",?null,?sqlParserPos);SqlNode[]?sqlNodes?=?new?SqlNode[2];sqlNodes[0]?=?name;sqlNodes[1]?=?alias;SqlBasicCall?sqlBasicCall?=?(SqlBasicCall)operator.createCall(sqlParserPos,sqlNodes);System.out.println(sqlBasicCall);?//得到的就是?Order?as?oSqlParsePos表示對應解析的節點在sql位置,起止行與起止列。
以上介紹了一下calcite解析sql的簡單使用方式,我們可以使用Calcite來做血緣分析、flink sql維表關聯等。
總結
以上是生活随笔為你收集整理的calcite连接mysql_使用Calcite做Sql语法解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 消灭家中细菌异味!萤石除菌洗地机RH2发
- 下一篇: 京东方与创维合作推出Q53系列壁纸电视: