使用Calcite做Sql語法解析

2021-10-07 08:19:03 字數 2466 閱讀 7851

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 catch (sqlparseexception e)

這裡解析了乙個select的語句,那麼得到的sqlnode就是乙個sqlselect。

if(sqlkind.select.equals(sqlnode.getkind()))

if(sqlkind.less_than.equals(where.getkind()))}}

selectlist.getlist().foreach(x->

});}

乙個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->

});其內部主要就是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->

});另外一種節點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 o

sqlparsepos表示對應解析的節點在sql位置,起止行與起止列。

以上介紹了一下calcite解析sql的簡單使用方式,我們可以使用calcite來做血緣分析、flink sql維表關聯等。

sql游標的使用語法

例子 table1結構如下 id int name varchar 50 declare id int declare name varchar 50 declare cursor1 cursor for 定義游標cursor1 select from table1 使用游標的物件 跟據需要填入se...

sql特殊語法

複製表的結構 select into newtable from oldtable where 1 1 複製表達額內容 insert into new table select 列名 from oldtable datediff函式用法 作用 返回兩個日期之間的間隔。語法 datediff date...

sql 語法細節

一 left join select a.mp id,a.pc id,sum cap plan qty as preplancumqty from master plan pc a where a.cap plan date startdate and a.mp id mp id group by ...