本文主要描述 Flink1.9 新提供的 create table sql 通過 Calcite 解析,校驗 並註冊到catalog的過程。
樣例SQL:
CREATE TABLE user_log (
user_id VARCHAR,
item_id VARCHAR,
category_id VARCHAR,
behavior VARCHAR,
ts TIMESTAMP
) WITH (
'connector.type' = 'kafka', -- 使用 kafka connector
'connector.version' = 'universal', -- kafka 版本,universal 支持 0.11 以上的版本
'connector.topic' = 'xc_user_behavior', -- kafka topic
'connector.startup-mode' = 'earliest-offset', -- 從起始 offset 開始讀取
'connector.properties.0.key' = 'zookeeper.connect', -- 連接信息
'connector.properties.0.value' = '172.16.8.107:2181',
'connector.properties.1.key' = 'bootstrap.servers',
'connector.properties.1.value' = '172.16.8.107:9092',
'update-mode' = 'append',
'format.type' = 'json', -- 數據源格式爲 json
'format.derive-schema' = 'true' -- 從 DDL schema 確定 json 解析規則
)
帶着兩個疑問:1:如何自定義create table 語法(之後會另外寫一篇), 2:create table 的表信息是如何註冊到catalog上的,供之後的select 語句查詢;
一:StreamTableEnvironment.create() 關注:Planner 的初始化
-
實例化一個CatalogManager(元數據管理器)
--初始化一個GenericInMemroyCatalog作爲默認的Catalog
- 實例化StreamPlanner(本文以流作爲背景,所以實例化目標爲StreamPlanner)
- 初始化StreamPlanner繼承的超類PlannerContext
- 可以看到提供了統一生成Calcite FrameworkConfig的函數createFrameworkConfig,關注其中對defaultSchema的設置,(之前實例的CatalogManager的包裝類CatalogManagerCalciteSchema作爲默認的Schema),另外ParserFactory參數也需要關注下,FlinkSqlParserImpl.FACTORY 這個是flink 基於Calcite 擴展的支持DDL的解析類;
初始化查詢優化器:
RelOptPlanner planner = new VolcanoPlanner(frameworkConfig.getCostFactory(), frameworkConfig.getContext());//基於cost的優化器
到這一步Planner環境初始化相關的操作已經完成。
二:解析Create table Sql語句:StreamTableEnvironment.sqlUpdate(createSqlStr)
-
StreamTableEnvironment 調用 之前初始化環境過程中創建的 StreamPlanner 解析create table 語句 生成 CreateTableOperation;
其中生成Operation 的部分主體是:
- 生成Planner
- PlannerContext基於統一提供的createFrameworkConfig() 生成FlinkPlannerImpl。
- FlinkPlannerImpl 解析 DDL語句 生成SqlNode(如何根據Calcite自定義Table create 這個會後會另外單獨寫一篇)。
- 調用validate() 對create table 信息進行校驗, 包括table 的column, primaryKeys,uniqueKeys,partitionKey設置是否正確,這個校驗不包括對create table 語法的校驗,create 語法的校驗在parse階段已經處理過;
- org.apache.flink.table.planner.operations.SqlToOperationConverter#convert:將SqlNode轉換爲org.apache.flink.table.operations.ddl.CreateTableOperation,當然convert()方法包含對Query, Create, Drop, Insert 的處理,本文只關注convertCreateTable模塊;
- 調用TableEnvironmentImpl#registerCatalogTableInternal 把生成的CreateTableOperation註冊到CatalogManager 上, 註冊的元數據信息之後可以被sql 查詢引用;
調用GenericInMemoryCatalog#createTable 將表的信息添加到catalog 元數據上;