首页 > 其他分享 >如何为 Databend 添加新的系统表

如何为 Databend 添加新的系统表

时间:2023-05-06 17:33:06浏览次数:45  
标签:系统 system Databend 添加 let table new data

Databend 的绝大部分系统表都位于 query/storage 这个目录下,当然,如果因为一些特殊的构建原因无法放在这个位置的话,也可以考虑临时放到 service/databases/system 这个目录(不推荐)。

系统表的定义主要关注两个内容:一个是表的信息,会包含表名、Schema 这些;另一个就是表中数据的生成/获取。刚好可以对应到 SyncSystemTable 和 AsyncSystemTable 这两个 Trait 中的 get_table_info 和 get_full_data 。到底是同步还是异步,取决于在获取数据时,是否涉及到异步函数的调用。

实现

本文将会以 credits 表的实现为例,介绍 Databend 系统表的实现,代码位于 https://github.com/datafuselabs/databend/blob/main/src/query/storages/system/src/credits_table.rscredits 会返回 Databend 所用到的上游依赖的信息,包括名字、版本和许可三个字段。

首先,需要参考其他系统表的实现,去定义表对应的结构,只需要保有表信息的字段就可以了。

pub struct CreditsTable {
    table_info: TableInfo,
}

接下来是为 CreditsTable 表实现 create 方法,对应的函数签名如下:

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

传入的 table_id 会在创建表时由 sys_db_meta.next_table_id() 生成。

schema 用于描述表的结构,需要使用 TableSchemaRefExt 和 TableField 来创建,字段名字和类型取决于表中的数据。

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

对于字符串类数据,可以使用 TableDataType::String ,其他基础类型也类似。但如果你需要允许字段中存在空值,比如字段是可以为空的 64 位无符号整数,则可以使用 TableDataType::Nullable(Box::new(TableDataType::Number(NumberDataType::UInt64))) 的方式,TableDataType::Nullable 表示允许空值,TableDataType::Number(NumberDataType::UInt64) 表征类型是 64 位无符号整数。

接下来就是定义表的信息,基本上只需要依葫芦画瓢,把描述、表名、元数据填上就好。

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 创建,异步类型的则使用 AsyncOneBlockSystemTable 。

接下来,则是实现 SyncSystemTable ,SyncSystemTable 除了需要定义 NAME 之外,还需要实现 4 个函数 get_table_info 、get_full_dataget_partitions 和 truncate ,由于后两个有默认实现,大多数时候不需要考虑实现自己的。(AsyncSystemTable 类似,只是没有 truncate )

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

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

get_table_info 只需要返回结构体中的表信息。

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 的环境变量(参见 common-building)获取的,每条数据都用 , 进行分隔。

字符串类型的列最后是从 Vec<Vec<u8>> 转化过来,其中字符串需要转化为 Vec<u8> ,所以在迭代的时候使用 .as_bytes().to_vec() 做了处理。

在获取所有数据后,就可以按 DataBlock 的形式返回表中的数据。非空类型,使用 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()),
    ...
    }
}

测试

系统表的相关测试目前仍然位于 src/query/service/tests/it/storages/system.rs 。

对于内容不会经常动态变化的表,可以使用 Golden File 测试,其运行逻辑是将对应的表写入指定的文件中,然后对比每次测试时文件内容是否发生变化。

#[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(())
}

对于内容可能会变化的表,目前缺乏充分的测试手段。可以选择测试其中模式相对固定的部分,比如行和列的数目;也可以验证输出中是否包含特定的内容。


#[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(())
}

关于 Databend

Databend 是一款开源、弹性、低成本,基于对象存储也可以做实时分析的新式数仓。期待您的关注,一起探索云原生数仓解决方案,打造新一代开源 Data Cloud。

标签:系统,system,Databend,添加,let,table,new,data
From: https://www.cnblogs.com/databend/p/17378091.html

相关文章

  • 利用Navicat的历史日志查询表的索引信息(还可以查询很多系统级别的信息)
    1、使用前提所有的能用Navicat连接的数据库都可以使用这个方法DDL/DML语句都有2、Navicat中的历史日志3、比如查询mysql的表的索引先打开“历史记录”选择一张表-设计表查看“历史记录”,点击“暂停”......
  • 华为ICT系统集成博客清单
    华为ICT系统集成博客清单本篇博客主要用于归纳Linux学习--OpenEuler发行版本,便于索引.笔记系统集成01-OpenEuler操作系统入门系统集成02-命令行基础系统集成03-文本编辑器系统集成04-用户和权限管理系统集成05-安装软件和管理服务系统集成06-管理文件系统及存储系统集......
  • 客服系统有什么功能特点?
    客服系统可以看作是一种即时通讯软件,它为网站和其他应用程序提供了一个与访问者沟通的平台,使网站与访问者间的沟通更加方便。访问者可以在不安装软件的情况之下访问企业应用程序,并获得他们想要的信息。1.渠道接入。客服系统提供了多种渠道接入方式。企业可以将客服系统连接到自......
  • 系统集成09-Samba文件共享服务器管理
    系统集成09-Samba文件共享服务器管理1Samba文件共享服务器搭建Samba文件共享服务介绍Samba是一个能让Linux系统应用Microsoft网络通讯协议的软件,SMB(ServerMessageBlock)服务器消息块。Samba最大的功能是可以用于Linux与windows系统直接的文件共享和打印共享,既可以用于Window......
  • 系统集成08-使用Shell脚本
    系统集成08-使用Shell脚本1Shell基础介绍Shell是系统的用户界面,提供了用户与内核进行交互操作的一种接口Shell将用户输入的命令并且把它们送到内核去执行,然后返回执行结果Shell是可编程的,它允许用户编写由Shell命令组成的程序查看系统默认安装的shell:cat/etc/shells1......
  • 系统集成07-系统管理
    系统集成07-系统管理1任务管理什么是任务管理?在系统运维过程中,可能需要在某个预设的时间执行特定任务比如定时发送邮件、备份并清空日志文件等任务任务的内容可以看作是一系列命令或者一个脚本,我们则需要在特定时间去执行它任务管理分为计划执行和定期执行1.1计划执行......
  • 系统集成03-文本编辑器
    系统集成03-文本编辑器文本处理是操作系统对文件管理的基础操作,文本编辑器是计算机软件中的一种,主要用来编写和查看文本文件。不同的文件编辑器有不同的辅助功能。1Linux常用文本编辑器介绍文本编辑器是操作系统基础的功能软件之一。根据使用环境的不同,Linux的文本编辑器有很......
  • ICT实战系统集成-LAB9-Samba文件共享服务器管理
    ICT实战系统集成-LAB9-Samba文件共享服务器管理实验步骤1安装samba服务端安装samba、samba-common、samba-clientyuminstallsambasamba-commonsamba-client启动samba:ststemctlstartsmb.service查看samba状态2添加系统组share,添加系统账号xiaoming、hanmeimei......
  • ICT实战系统集成-LAB6-openEuler管理文件系统及存储
    LAB6-openEuler管理文件系统及存储1实验要求1.1添加两块scsi硬盘,大小分别为10G1.2对新添加的硬盘1(如:/dev/sdb)进行MBR分区、格式化、挂载1、使用fdisk对/dev/sdb进行分区:/dev/sdb1为主分区1大小2G、/dev/sb2为扩展分区大小8G,在/dev/sb2的基础上建立扩展分区/dev/sdb5,大小......
  • ICT实战系统集成-LAB5-OpenEuler软件管理
    系统集成-LAB5-OpenEuler软件管理1实验要求任务一:使用rpm包安装zziplib工具1、完成安装2、查询zziplib工具是否安装成功3、查询zziplib工具的文件列表和完整目录4、查询zziplib工具的详细信息5、对zziplib工具进行卸载任务二:使用yum/dnf安装java-1.8.01、完成yum/dnf源......