跳到主要内容

结果校验

查询结果的标准校验方式是使用 query 语句,并在后面用若干个 I 表示期望列数。查询后需要写四个短横线(----),再写以制表符分隔的结果值。例如:

query II
SELECT 42, 84 UNION ALL SELECT 10, 20;
----
42 84
10 20

出于历史兼容原因,也接受 RT 表示列。

Deprecated:Goose 已弃用 sqllogictest 中的类型字母。Goose 测试执行器内部不使用也不需要它们——因此应仅使用 I 表示列。

NULL 值与空字符串

空行在 SQLLogic 执行器中有特殊含义:表示当前语句或查询结束。因此在结果校验中,空字符串和 NULL 值必须使用专门写法。NULL 应写成 NULL,空字符串应写成 (empty),例如:

query II
SELECT NULL, ''
----
NULL
(empty)

错误校验

若期望语句报错,可使用 statement error。它也支持可选期望结果——会被解释为期望错误消息。与 query 类似,期望错误写在查询后 ---- 下方。只要实际错误消息包含该文本,测试即通过——无需提供完整错误消息。建议只写关键子串,避免错误消息格式调整导致测试无谓失败。

statement error
SELECT * FROM non_existent_table;
----
Table with name non_existent_table does not exist!

Regex

有些场景下结果值很大或很复杂,我们只关心是否包含某段文本。此时可使用 <REGEX>: 修饰符并跟随正则表达式。若结果值匹配该正则,测试即通过。该方式主要用于查询计划分析。

query II
EXPLAIN SELECT tbl.a FROM 'data/parquet-testing/arrow/alltypes_plain.parquet' tbl(a) WHERE a = 1 OR a = 2
----
physical_plan <REGEX>:.*PARQUET_SCAN.*Filters: a=1 OR a=2.*

若希望结果不包含某段文本,可使用 <!REGEX>: 修饰符。

File

当结果很大、或希望跨文件复用结果时,也可通过 <FILE> 从文件读取期望结果。执行器会从给定文件读取预期输出。按约定,文件路径应相对于 GitHub 仓库根目录。

query I
PRAGMA tpch(1)
----
<FILE>:extension/tpch/dbgen/answers/sf1/q01.csv

按行 vs 按值结果顺序

查询结果可按“按行”或“按值”两种顺序提供。按行模式中同一行值以 tab 分隔;按值模式中每个值单独占一行,按行列顺序展开。示例如下:

# row-wise
query II
SELECT 42, 84 UNION ALL SELECT 10, 20;
----
42 84
10 20

# value-wise
query II
SELECT 42, 84 UNION ALL SELECT 10, 20;
----
42
84
10
20

哈希与结果输出

除直接结果校验外,sqllogic 测试也支持用 MD5 哈希做值比较。示例如下:

query I
SELECT g, string_agg(x,',') FROM strings GROUP BY g
----
200 values hashing to b8126ea73f21372cdb3f2dc483106a12

当输出行很多时,这种方式可显著缩小测试文件体积。但应谨慎使用:一旦测试失败,仅有哈希值会增加调试难度。

在确认系统输出正确后,可在测试文件中加入 mode output_hash 来生成该文件中查询的哈希。例如:

mode output_hash

query II
SELECT 42, 84 UNION ALL SELECT 10, 20;
----
42 84
10 20

随后终端会打印每条查询的期望输出哈希,如下:

================================================================================
SQL Query
SELECT 42, 84 UNION ALL SELECT 10, 20;
================================================================================
4 values hashing to 498c69da8f30c24da3bd5b322a2fd455
================================================================================

类似地,mode output_result 可强制程序将测试文件中每条查询结果都打印到终端。

结果排序

query 可带一个可选字段,表示结果需按特定方式排序。该字段位置与连接标签相同,因此连接标签与结果排序不能同时使用。

该字段可选值为 nosortrowsortvaluesort。示例如下:

query I rowsort
SELECT 'world' UNION ALL SELECT 'hello'
----
hello
world

通常我们更倾向于不使用该字段,而是通过查询里的 ORDER BY 保证结果确定性。不过历史 sqllogictest 中该字段使用很多,因此了解其存在很重要。

查询标签

用于结果校验的另一项能力是 query labels。它可用于验证不同查询是否返回同一结果,适合比较“逻辑等价但写法不同”的查询。查询标签写在连接标签或排序标记之后。

带查询标签的 query 不需要显式写结果。执行器会自动比较同标签查询之间的结果是否一致。例如下面脚本会验证 SELECT 42+1SELECT 44-1 是否得到相同结果:

query I nosort r43
SELECT 42+1;
----

query I nosort r43
SELECT 44-1;
----