验证查询结果的标准方法是使用query
语句,后面跟着字母I
乘以结果中预期的列数。在查询之后,预期会有四个破折号(----
),然后是制表符分隔的结果值。例如,
query II
SELECT 42, 84 UNION ALL SELECT 10, 20;
----
42 84
10 20
由于历史原因,字母 R
和 T
也被接受用来表示列。
已弃用 DuckDB 已弃用在 sqllogictest 中使用类型。DuckDB 测试运行器在内部不使用也不需要它们——因此,应仅使用
I
来表示列。
NULL值和空字符串
空行对SQLLogic测试运行器有特殊意义:它们表示当前语句或查询的结束。因此,空字符串和NULL值在结果验证中有特殊的语法必须使用。NULL值应使用字符串NULL
,空字符串应使用字符串(empty)
,例如:
query II
SELECT NULL, ''
----
NULL
(empty)
错误验证
为了表示预期会出现错误,可以使用statement error
指示符。statement error
还可以接受一个可选的预期结果——这被解释为预期的错误消息。与query
类似,预期的错误应放在查询后的四个破折号(----
)之后。如果错误消息包含statement error
下的文本,则测试通过——不需要提供完整的错误消息。建议您仅使用错误消息的一部分,这样如果错误消息的格式发生变化,测试不会不必要地失败。
statement error
SELECT * FROM non_existent_table;
----
Table with name non_existent_table does not exist!
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.*
如果我们希望结果不包含某段文本,我们可以使用:
修饰符。
文件
由于结果可能会变得非常大,并且我们可能希望在多个文件中重复使用结果,因此也可以使用
命令从文件中读取预期结果。预期结果从给定的文件中读取。按照惯例,文件路径应相对于GitHub仓库的根目录提供。
query I
PRAGMA tpch(1)
----
<FILE>:extension/tpch/dbgen/answers/sf1/q01.csv
行级与值级结果排序
查询的结果值可以按行顺序提供,各个值之间用制表符分隔,或者按值顺序提供。在值顺序中,查询的各个值必须按行、列顺序出现在单独的行上。考虑以下按行顺序和值顺序的示例:
# 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
可以用来强制程序在测试文件中运行的每个查询时将结果打印到终端。
结果排序
查询可以有一个可选字段,用于指示结果应按特定方式排序。此字段位于与连接标签相同的位置。因此,连接标签和结果排序不能混合使用。
此字段的可能值为 nosort
、rowsort
和 valuesort
。下面给出了如何使用此字段的示例:
query I rowsort
SELECT 'world' UNION ALL SELECT 'hello'
----
hello
world
一般来说,我们更倾向于不使用这个字段,而是依赖查询中的ORDER BY
来生成确定性的查询结果。然而,现有的sqllogictests广泛使用这个字段,因此了解它的存在是很重要的。
查询标签
另一个可以用于结果验证的功能是query labels
。这些标签可以用于验证不同的查询是否提供相同的结果。这对于比较逻辑上等效但表述不同的查询非常有用。查询标签在连接标签或排序说明符之后提供。
带有查询标签的查询不需要提供结果。相反,具有相同标签的每个查询的结果会相互比较。例如,以下脚本验证了查询 SELECT 42+1
和 SELECT 44-1
提供相同的结果:
query I nosort r43
SELECT 42+1;
----
query I nosort r43
SELECT 44-1;
----