如何為 Databend 添加新的系統(tǒng)表

Databend 的系統(tǒng)表位于 query/storage 目錄下,當(dāng)然标沪,如果因為一些特殊的構(gòu)建原因無法放在這個位置的話忌卤,也可以考慮臨時放到 service/databases/system 這個目錄(不推薦)淳玩。

系統(tǒng)表的定義主要關(guān)注兩個內(nèi)容:一個是表的信息苫纤,會包含表名莫绣、Schema 這些未斑;另一個就是表中數(shù)據(jù)的生成/獲取伞辛。剛好可以對應(yīng)到 SyncSystemTableAsyncSystemTable 這兩個 Trait 中的 get_table_infoget_full_data 西疤。到底是同步還是異步烦粒,取決于在獲取數(shù)據(jù)時,是否涉及到異步函數(shù)的調(diào)用代赁。

實現(xiàn)

本文將會以 credits 表的實現(xiàn)為例扰她,介紹 Databend 系統(tǒng)表的實現(xiàn),代碼位于 https://github.com/datafuselabs/databend/blob/main/src/query/storages/system/src/credits_table.rs 芭碍。credits 會返回 Databend 所用到的上游依賴的信息徒役,包括名字、版本和許可三個字段窖壕。

首先忧勿,需要參考其他系統(tǒng)表的實現(xiàn),去定義表對應(yīng)的結(jié)構(gòu)瞻讽,只需要保有表信息的字段就可以了鸳吸。

pub struct CreditsTable {
    table_info: TableInfo,
}

接下來是為 CreditsTable 表實現(xiàn) create 方法,對應(yīng)的函數(shù)簽名如下:

pub fn create(table_id: u64) -> Arc<dyn Table>

傳入的 table_id 會在創(chuàng)建表時由 sys_db_meta.next_table_id() 生成卸夕。

schema 用于描述表的結(jié)構(gòu)层释,需要使用 TableSchemaRefExtTableField 來創(chuàng)建,字段名字和類型取決于表中的數(shù)據(jù)快集。

let schema = TableSchemaRefExt::create(vec![
    TableField::new("name", TableDataType::String),
    TableField::new("version", TableDataType::String),
    TableField::new("license", TableDataType::String),
]);

對于字符串類數(shù)據(jù)贡羔,可以使用 TableDataType::String 廉白,其他基礎(chǔ)類型也類似。但如果你需要允許字段中存在空值乖寒,比如字段是可以為空的 64 位無符號整數(shù)猴蹂,則可以使用 TableDataType::Nullable(Box::new(TableDataType::Number(NumberDataType::UInt64))) 的方式,TableDataType::Nullable 表示允許空值楣嘁,TableDataType::Number(NumberDataType::UInt64) 表征類型是 64 位無符號整數(shù)磅轻。

接下來就是定義表的信息,基本上只需要依葫蘆畫瓢逐虚,把描述聋溜、表名、元數(shù)據(jù)填上就好叭爱。

let table_info = TableInfo {
    desc: "'system'.'credits'".to_string(),
    name: "credits".to_string(),
    ident: TableIdent::new(table_id, 0),
    meta: TableMeta {
        schema,
        engine: "SystemCredits".to_string(),
        ..Default::default()
    },
   ..Default::default()
};

SyncOneBlockSystemTable::create(CreditsTable { table_info })

對于同步類型的表往往使用 SyncOneBlockSystemTable 創(chuàng)建撮躁,異步類型的則使用 AsyncOneBlockSystemTable

接下來买雾,則是實現(xiàn) SyncSystemTable 把曼,SyncSystemTable 除了需要定義 NAME 之外,還需要實現(xiàn) 4 個函數(shù) get_table_info 漓穿、get_full_data嗤军、get_partitionstruncate,由于后兩個有默認(rèn)實現(xiàn)晃危,大多數(shù)時候不需要考慮實現(xiàn)自己的叙赚。(AsyncSystemTable 類似,只是沒有 truncate

NAME 的值遵循 system.<name> 的格式山害。

const NAME: &'static str = "system.credits";

get_table_info 只需要返回結(jié)構(gòu)體中的表信息纠俭。

fn get_table_info(&self) -> &TableInfo {
    &self.table_info
}

get_full_data 是相對重要的部分,因為每個表的邏輯都不太一樣浪慌,credits 的三個字段基本類似冤荆,就只舉 license 字段為例。

let licenses: Vec<Vec<u8>> = env!("DATABEND_CREDITS_LICENSES")
    .split_terminator(',')
    .map(|x| x.trim().as_bytes().to_vec())
    .collect();

license 字段的信息是從名為 DATABEND_CREDITS_LICENSES 的環(huán)境變量(參見 common-building)獲取的权纤,每條數(shù)據(jù)都用 , 進(jìn)行分隔钓简。

字符串類型的列最后是從 Vec<Vec<u8>> 轉(zhuǎn)化過來,其中字符串需要轉(zhuǎn)化為 Vec<u8> 汹想,所以在迭代的時候使用 .as_bytes().to_vec() 做了處理外邓。

在獲取所有數(shù)據(jù)后,就可以按 DataBlock 的形式返回表中的數(shù)據(jù)古掏。非空類型损话,使用 from_data ,可空類型使用 from_opt_data

Ok(DataBlock::new_from_columns(vec![
    StringType::from_data(names),
    StringType::from_data(versions),
    StringType::from_data(licenses),
]))

最后丧枪,要想將其集成到 Databend 中光涂,還需要編輯 src/query/service/src/databases/system/system_database.rs,將其注冊到 SystemDatabase 中 拧烦。

impl SystemDatabase {
    pub fn create(sys_db_meta: &mut InMemoryMetas, config: &Config) -> Self {
    ...
        CreditsTable::create(sys_db_meta.next_table_id()),
    ...
    }
}

測試

系統(tǒng)表的相關(guān)測試位于 src/query/service/tests/it/storages/system.rs 忘闻。

對于內(nèi)容不會經(jīng)常動態(tài)變化的表,可以使用 Golden File 測試恋博,其運行邏輯是將對應(yīng)的表寫入指定的文件中齐佳,然后對比每次測試時文件內(nèi)容是否發(fā)生變化。

#[tokio::test(flavor = "multi_thread")]
async fn test_columns_table() -> Result<()> {
    let (_guard, ctx) = crate::tests::create_query_context().await?;

    let mut mint = Mint::new("tests/it/storages/testdata");
    let file = &mut mint.new_goldenfile("columns_table.txt").unwrap();
    let table = ColumnsTable::create(1);

    run_table_tests(file, ctx, table).await?;
    Ok(())
}

對于內(nèi)容可能會變化的表债沮,目前缺乏充分的測試手段炼吴。可以選擇測試其中模式相對固定的部分秦士,比如行和列的數(shù)目缺厉;也可以驗證輸出中是否包含特定的內(nèi)容永高。


#[tokio::test(flavor = "multi_thread")]
async fn test_metrics_table() -> Result<()> {
    ...
    let result = stream.try_collect::<Vec<_>>().await?;
    let block = &result[0];
    assert_eq!(block.num_columns(), 4);
    assert!(block.num_rows() >= 1);

    let output = pretty_format_blocks(result.as_slice())?;
    assert!(output.contains("test_test_metrics_table_count"));
    #[cfg(feature = "enable_histogram")]
    assert!(output.contains("test_test_metrics_table_histogram"));

    Ok(())
}

關(guān)于 Databend

Databend 是一款開源隧土、彈性、低成本命爬,基于對象存儲也可以做實時分析的新式數(shù)倉曹傀。期待您的關(guān)注,一起探索云原生數(shù)倉解決方案饲宛,打造新一代開源 Data Cloud皆愉。

???? Databend Cloud:https://databend.cn

?? Databend 文檔:https://databend.rs/

?? Wechat:Databend

? GitHub:https://github.com/datafuselabs/databend

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市艇抠,隨后出現(xiàn)的幾起案子幕庐,更是在濱河造成了極大的恐慌,老刑警劉巖家淤,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件异剥,死亡現(xiàn)場離奇詭異,居然都是意外死亡絮重,警方通過查閱死者的電腦和手機冤寿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來青伤,“玉大人督怜,你說我怎么就攤上這事『萁牵” “怎么了号杠?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長丰歌。 經(jīng)常有香客問我姨蟋,道長辣吃,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任芬探,我火速辦了婚禮神得,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘偷仿。我一直安慰自己哩簿,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布酝静。 她就那樣靜靜地躺著节榜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪别智。 梳的紋絲不亂的頭發(fā)上宗苍,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機與錄音薄榛,去河邊找鬼讳窟。 笑死,一個胖子當(dāng)著我的面吹牛敞恋,可吹牛的內(nèi)容都是我干的丽啡。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼硬猫,長吁一口氣:“原來是場噩夢啊……” “哼补箍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起啸蜜,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤坑雅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后衬横,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體裹粤,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年冕香,在試婚紗的時候發(fā)現(xiàn)自己被綠了蛹尝。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡悉尾,死狀恐怖突那,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情构眯,我是刑警寧澤愕难,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響猫缭,放射性物質(zhì)發(fā)生泄漏葱弟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一猜丹、第九天 我趴在偏房一處隱蔽的房頂上張望芝加。 院中可真熱鬧,春花似錦射窒、人聲如沸藏杖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蝌麸。三九已至,卻和暖如春艾疟,著一層夾襖步出監(jiān)牢的瞬間来吩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工蔽莱, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留弟疆,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓碾褂,卻偏偏與公主長得像兽间,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子正塌,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容