首页 > 数据库 >SQLSmith: Databend 如何利用随机化测试检测 Bug

SQLSmith: Databend 如何利用随机化测试检测 Bug

时间:2023-10-26 18:56:24浏览次数:50  
标签:语句 SQLSmith 生成 随机化 Databend SQL bug

作者:白 珅

Databend 研发工程师

https://github.com/b41sh

为什么需要 SQLSmith?

在数据库系统的开发和维护过程中,测试扮演着至关重要的角色。它不仅可以验证功能的正确性,还可以发现潜在的问题,确保数据库在每个变更和迭代后保持性能和稳定性。Databend 的 CI 已经支持了多种类型的测试,主要包括:

  • 单元测试(Unit Tests):用于验证代码中最小可测试单元的功能是否正常工作,主要针对函数、模块等基本功能点,确保其能够正确执行,并返回预期的结果。
  • SQL 逻辑测试(SQL Logic Tests):通过 SQL 测试用例来验证 SQL 的语法和逻辑的正确性,覆盖不同的查询场景,确保查询在各种情况下都能正常运行。
  • 性能测试(Performance Tests):测试新功能的性能变化,验证优化的有效性,防止性能回退。

这些测试能够保证系统在快速开发迭代过程中功能的正确性和稳定性,并覆盖常见的使用场景。但是它们也存在一些局限性,例如,测试中使用的 SQL 语句主要通过手工编写,通常较为简单,缺乏真实场景中会的出现复杂 SQL ,对各种边界条件和异常情况覆盖不足。

SQLSmith 是一个随机 SQL 查询生成器,它可以生成大量、多样化的 SQL 测试用例,从而在一定程度上模拟真实世界中的各种可能情况。相比于其它测试方法,SQLSmith 能够提高测试覆盖率,从而发现更多潜在的问题和 bug 。

SQLSmith 的实现

最早的 SQLSmith 灵感来自于 Csmith ,主要用于 PostgreSQL 的模糊测试。目前,已经有许多知名的开源数据库移植了各自版本的 SQLSmith 实现,如 CockroachDBTiDBRisingWave 等。

这些开源的 SQLSmith 实现使用不同的编程语言开发(包括 C++、Golang、Rust),支持的语法也各不相同,适用于各自的应用领域,我们无法直接使用它们来进行测试。为了完全支持 Databend 的语法和功能特点,我们必须用 Rust 构建自己的 SQLSmith 。

SQLSmith 主要包括三个部分,生成抽象语法树(AST)的 SQL Generator ,简化执行失败 SQL 的 SQL Reducer ,执行 SQL 并记录错误的 Runner 。

SQL Generator

SQL Generator 随机生成各种类型的抽象语法树(AST),主要包括如下几类:

  1. 生成多种数据类型,除了常见的基本数据类型之外,Databend 还支持了多种嵌套数据类型,包括 ArrayMapTuple 等,这些类型可以多层嵌套,组合出更复杂的数据类型。
  2. 生成 DDL 语句,创建并修改用于测试的表,包括 CREATE TABLEALTER TABLE, DELETE TABLE 等。
  3. 生成 DML 语句,生成随机的测试数据执行插入和修改操作,包括 INSERTUPDATEDELETEMERGE 等。
  4. 生成 Query 语句,依次随机生成其内部的各个字段,包括 WITHSelectTargetTableReferenceSubQueryORDER ``BY 等,由于 WITHSubQuery 包含嵌套的 Query,可以生成复杂的查询语句。
  5. 生成 Expression 表达式,包括 ColumnLiteralScalar FunctionAggregate Function 等,由于表达式的参数也可以是表达式,从而支持生成嵌套的表达式。

由于 AST 中的各个部分都会按照一定的概率随机生成,可以覆盖所有类型的 AST ,进而覆盖所有可能的 SQL 语句。通过递归调用生成器,我们还可以生成一些不常见的复杂嵌套语句,有利于发现一些隐藏的 bug 。同时,我们也需要适当控制嵌套的深度,避免生成过于复杂无法执行的 SQL。

SQL Reducer

由于 SQL Generator 生成的 SQL 语句可能会非常复杂,而造成 bug 的往往只是其中的一小部分,直接查看原始 SQL 不容易定位问题。有必要对原始 SQL 进行简化,得出能够复现该 bug 的最小 SQL,这样可以减少无关部分的干扰,方便用最简单的 SQL 复现 bug。

SQL Reducer 采用自顶向下的方法来简化 SQL,依次删除 AST 的不同组成部分,例如 WITHSubQueryExpression 等,如果删除后的 SQL 仍然可以复现出相同的 bug,我们就使用这个删除后的 SQL,否则就回退到原来的 SQL 。通过遍历 AST 的所有组成部分,最终可以得到一个最小可复现的 SQL 语句。

Runner

SQL Runner 使用 SQL Generator 按顺序不断循环生成用于测试的 SQL 语句,并连接 Databend 执行 SQL,如果执行成功则忽略,如果执行失败,说明可能存在 bug,继续按照以下流程进行处理:

  1. 判断是否是正常的报错,例如参数错误,语义错误等。
  2. 判断是否是已知的报错,例如一些未实现的功能,或已提 issue 的报错。
  3. 调用 SQL Reducer 进行简化生成最小可复现的 SQL 。
  4. 打印报错信息和简化后的 SQL 语句。

目前 Runner 已经集成到了 Databend 的 CI,在每次发布 Release 版本的时候都会执行,生成报错信息和 SQL 会被记录下来,用于进一步的分析。

SQLsmith 的效果

到目前为止,SQLSmith 已经在 Databend 运行了一个多月的时间,一共发现了 50 多个 bug,主要包括如下几类:

  1. 内部执行逻辑错误导致的 bug (17个)
  2. 函数或表达式参数校验错误导致的 bug (12个)
  3. 未执行正确的语义检查导致的 bug (9个)
  4. unwrapunreachable 处理不当导致的 bug (7个)
  5. Parser 语法解析失败的 bug (3个)
  6. 不同类型 cast 失败的 bug (4个)
  7. Parquet 数据读写错误导致的 bug (1个)

经验总结

通过分析 SQLSmith 发现的 bug,我们总结了一些常见的问题,可以帮助我们在以后的开发过程中避免出现 bug 。

  1. 函数的参数需要校验是否合法,并考虑各种情况,主要包括以下几类:

    1. 参数类型是 String 时,注意字符串为空的情况。
    2. 参数类型是 Int 时,注意值是一个大数的情况。
    3. 参数支持任意类型时,需要考虑一些不常用的类型,例如 NullEmptyArrayBitmap 等。
    4. 参数只支持特定类型时,需要考虑其它类型能不能自动转换,或者提前检查类型并返回错误。
  2. 谨慎使用 unwrap,对于 ResultOption 类型的返回值,应该尽量显式的进行处理,返回值并不总是像预期的一样返回成功的结果。

  3. 开发新的功能需要了解相关 SQL 语义规则的约束条件,例如 ORDERBYHAVING表达式中不允许出现 AggregateWindow 函数。在 Binder 阶段进行符合语义规则的检查可以避免执行时发生错误。

  4. 重要的功能模块需要增加更多的单元测试用例,避免内部执行逻辑错误导致的 bug 。

下一步的工作

目前,SQLSmith 已经支持生成绝大部分常用的 SQL 并且能够与 CI 集成自动运行。我们计划在下一步继续完善 SQLsmith 的功能。主要包括如下几个方面:

  1. 增加更多的 SQL 语法支持,包括 Computed ColumnUnion 等。
  2. 支持更多的配置项,包括表达式的嵌套深度,查询语句的复杂度等。
  3. 完善 SQL Reducer 的功能,生成更简化的 SQL 语句。
  4. 通过改进查询执行和结果分析的方法,提高 bug 发现的效率。

SQLSmith 是一个强大的工具,它可以帮助我们发现 Databend 隐藏的 bug,提高系统的稳定性和可靠性。我们期待 SQLsmith 在未来能够发挥更大的作用。

Connect With Us

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

标签:语句,SQLSmith,生成,随机化,Databend,SQL,bug
From: https://www.cnblogs.com/databend/p/17790122.html

相关文章

  • Databend 开源周报第 116 期
    Databend是一款现代云数仓。专为弹性和高效设计,为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务:https://app.databend.cn。What'sOnInDatabend探索Databend本周新进展,遇到更贴近你心意的Databend。特性预览:使用SQL管理后台任务此前,Databend引入了......
  • Databend 开源周报第 116 期
    Databend是一款现代云数仓。专为弹性和高效设计,为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务:https://app.databend.cn。What'sOnInDatabend探索Databend本周新进展,遇到更贴近你心意的Databend。特性预览:使用SQL管理后台任务此前,Databend引入了后......
  • 使用 LF Edge eKuiper 将物联网流处理数据写入 Databend
    作者:韩山杰DatabendCloud研发工程师https://github.com/hantmacLFEdgeeKuiper是Golang实现的轻量级物联网边缘分析、流式处理开源软件,可以运行在各类资源受限的边缘设备上。eKuiper的主要目标是在边缘端提供一个流媒体软件框架(类似于ApacheFlink(opensnewwindo......
  • Databend join reorder 策略
    joinorder的重要性Joinorder是指在执行SQL查询时,决定多个表进行join的顺序。它是数据库查询优化的一个重要方面,对查询性能和效率有着重要的影响,不同的joinorder对性能可能有数量级的影响。优化器优化joinorder的核心流程joinplan枚举根据统计信息估算结果的......
  • 使用 Databend 加速 Hive 查询
    作者:尚卓燃(PsiACE)澳门科技大学在读硕士,Databend研发工程师实习生ApacheOpenDAL(Incubating)Committerhttps://github.com/PsiACE随着架构的不断迭代和更新,大数据系统的查询目标也从大吞吐量查询逐步转移转向快速的交互式查询,对于查询的及时响应提出了更高要求。许多企业......
  • 转载:孟德尔随机化(Mendelian Randomization) 统计功效(power)和样本量计算
    链接:>https://mp.weixin.qq.com/s?__biz=Mzg2MDA2MDQzMQ==&mid=2247484734&idx=1&sn=6c4a5ba21bad0058ead4f0e8d9399c72&chksm=ce2d6b5ef95ae248ae7566d87d8aa4a373ccc33082a10e37773d89a137ac4d350e591844a0bd&scene=21#wechat_redirect......
  • 将vcf文件转成孟德尔随机化分析格式
    以https://gwas.mrcieu.ac.uk/datasets/ukb-b-7330/为例:原始文件形如:转换代码library(vcfR)getwd()a_data=read.vcfR('../ukb-b-7330.vcf.gz')str(a_data)head(a_data$meta,12)head(a_data@fix)head(a_data@gt)fix=as.data.frame(a_data@fix[,(1:5)])gt=as......
  • Databend 开源周报第 111 期
    Databend是一款现代云数仓。专为弹性和高效设计,为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务:https://app.databend.cn。What'sOnInDatabend探索Databend本周新进展,遇到更贴近你心意的Databend。理解SHAREENDPOINTSHAREENDPOINT是Databend数据......
  • Databend 开源周报第 111 期
    Databend是一款现代云数仓。专为弹性和高效设计,为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务:https://app.databend.cn。What'sOnInDatabend探索Databend本周新进展,遇到更贴近你心意的Databend。理解SHAREENDPOINTSHAREENDPOINT是Databend数据......
  • Databend 开源周报第 110 期
    Databend是一款现代云数仓。专为弹性和高效设计,为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务:https://app.databend.cn。What'sOnInDatabend探索Databend本周新进展,遇到更贴近你心意的Databend。使用BendSQL管理Stage中的文件Databend推荐使用P......