SQLsmith 已被證明是尋找 PostgreSQL 伺服器和其他產品(包括安全性錯誤)不同區域中錯誤的有效工具,範圍從執行器錯誤到類型和索引方法實現中的段錯誤。
然而,SQLsmith 產生的觸發某些錯誤的隨機查詢通常非常大,並且包含大量對錯誤沒有貢獻的雜訊。到目前為止,需要手動檢查查詢和繁瑣的編輯才能將範例縮減為開發人員可以用來修復問題的最小重現程序。
這個問題由 SQLreduce 解決。SQLreduce 接受任意 SQL 查詢作為輸入,然後針對 PostgreSQL 伺服器運行。應用各種簡化步驟,並在每個步驟後檢查簡化的查詢是否仍然觸發來自 PostgreSQL 的相同錯誤。最終結果是一個複雜性最小的 SQL 查詢。
SQLreduce 可以有效地將 SQLsmith 的原始錯誤報告中的查詢縮減為與手動縮減查詢相符的查詢。
有關 如何在部落格文章中運作的更多詳細資訊。
在 2018 年,SQLsmith 在 運行 Git 修訂版本 039eb6e92f 的 PostgreSQL 中發現了一個段錯誤。當時的重現程序是一個巨大的 40 行、2.2kB 查詢
select case when pg_catalog.lastval() < pg_catalog.pg_stat_get_bgwriter_maxwritten_clean() then case when pg_catalog.circle_sub_pt( cast(cast(null as circle) as circle), cast((select location from public.emp limit 1 offset 13) as point)) ~ cast(nullif(case when cast(null as box) &> (select boxcol from public.brintest limit 1 offset 2) then (select f1 from public.circle_tbl limit 1 offset 4) else (select f1 from public.circle_tbl limit 1 offset 4) end, case when (select pg_catalog.max(class) from public.f_star) ~~ ref_0.c then cast(null as circle) else cast(null as circle) end ) as circle) then ref_0.a else ref_0.a end else case when pg_catalog.circle_sub_pt( cast(cast(null as circle) as circle), cast((select location from public.emp limit 1 offset 13) as point)) ~ cast(nullif(case when cast(null as box) &> (select boxcol from public.brintest limit 1 offset 2) then (select f1 from public.circle_tbl limit 1 offset 4) else (select f1 from public.circle_tbl limit 1 offset 4) end, case when (select pg_catalog.max(class) from public.f_star) ~~ ref_0.c then cast(null as circle) else cast(null as circle) end ) as circle) then ref_0.a else ref_0.a end end as c0, case when (select intervalcol from public.brintest limit 1 offset 1) >= cast(null as "interval") then case when ((select pg_catalog.max(roomno) from public.room) !~~ ref_0.c) and (cast(null as xid) <> 100) then ref_0.b else ref_0.b end else case when ((select pg_catalog.max(roomno) from public.room) !~~ ref_0.c) and (cast(null as xid) <> 100) then ref_0.b else ref_0.b end end as c1, ref_0.a as c2, (select a from public.idxpart1 limit 1 offset 5) as c3, ref_0.b as c4, pg_catalog.stddev( cast((select pg_catalog.sum(float4col) from public.brintest) as float4)) over (partition by ref_0.a,ref_0.b,ref_0.c order by ref_0.b) as c5, cast(nullif(ref_0.b, ref_0.a) as int4) as c6, ref_0.b as c7, ref_0.c as c8 from public.mlparted3 as ref_0 where true;
SQLreduce 可以有效地將該怪物縮減為以下內容
SELECT pg_catalog.stddev(NULL) OVER () AS c5 FROM public.mlparted3 AS ref_0
SQLreduce 是在 MIT 許可下授權的開源軟體。原始程式碼位於 GitHub 上:https://github.com/credativ/sqlreduce
sqlreduce 的 Debian/Ubuntu 套件在 apt.postgresql.org 上發布。
SQLreduce 是 credativ GmbH 的開源產品。