ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Squirrel处理可空查询参数的3种实用技巧:终极变通指南

Squirrel处理可空查询参数的3种实用技巧:终极变通指南

【免费下载链接】squirrel

🐿️ Type safe SQL in Gleam

项目地址:https://gitcode.com/gh_mirrors/squirrel4/squirrel
点击查看免费下载

Squirrel 是 Gleam 生态中一款出色的类型安全 SQL代码生成工具:你在*.sql文件里写查询,它自动生成带正确类型与编解码器的函数。但在处理**可空查询参数(nullable query parameters)**时,Squirrel 有一个官方承认的限制——Postgres 不会暴露参数的可空性元数据,因此 Squirrel 无法为可空列自动推断出Option类型。别担心,本文给出 3 种经过官方认可的实用变通技巧,帮你快速绕开这个限制 💡

为什么 Squirrel 无法自动推断可空参数?

先看一个典型场景。假设有这样一张表和一个更新查询:

create table if not exists recipe( id int primary key, title text not null, author uuid, -- 可能缺失 description text -- 可能缺失 ); -- update_recipe_author.sql update recipe set author = $1 where id = $2;

Squirrel 生成的函数签名会是update_recipe_author(db, arg1: Uuid, arg2: Int)——注意arg1是Uuid而非Option(Uuid)。原因是 Squirrel 通过检查 Postgres 暴露的元数据来推断类型,而参数侧($1、$2)Postgres 不提供可空信息(详见 README.md 的 FAQ 部分,以及参数解析逻辑 src/squirrel/internal/database/postgres.gleam)。

⚠️ 注意区分:返回列的可空性 Squirrel 是能自动推断的(它会检查not null约束,甚至解析查询执行计划来判断 LEFT JOIN 产生的空值),唯独参数这一侧需要变通。

技巧一:拆分为两条查询,各司其职

当可空参数很少、逻辑简单时,最推荐的做法是干脆定义两条查询:一条写入真实值,一条显式写入null:

-- set_recipe_author.sql:设置作者 update recipe set author = $1 where id = $2;
-- remove_recipe_author.sql:清除作者 update recipe set author = null where id = $2;

优点:SQL 简单直白、函数语义清晰(set_recipe_authorvsremove_recipe_author),调用方一看就懂。这是官方 FAQ 给出的首选方案,适合 90% 的简单场景 ✅

技巧二:哨兵值 + CASE WHEN 转换 null

当可空参数很多、或查询逻辑复杂不适合复制多份时,可以挑选一个"哨兵值"(sentinel value)代表null,在 SQL 内部做转换:

-- update_recipe.sql update recipe set author = case $1 when '00000000-0000-0000-0000-000000000000' then null else $1 end, description = case $2 when "" then null else $2 end where id = $3;

调用方传入"全零 UUID"或空字符串,就表示"清空该字段"。查询保持单文件、单函数,避免了查询爆炸。

技巧三:用 SQL 辅助函数封装 null 转换逻辑

技巧二的查询写多了会变得臃肿。记住一句话:SQL 也是代码,同样值得重构🛠️ 把哨兵转换抽成数据库函数:

create function string_or_null(value text) returns text language sql immutable return nullif(value, "");

查询立刻变得清爽:

-- update_recipe.sql update recipe set author = uuid_or_null($1), description = string_or_null($2) where id = $3;

优点:转换规则只写一次、处处复用,主查询回归简洁;nullif这类函数本身就是 Postgres 的标准能力。

3 种技巧选型速查表

场景推荐技巧关键考量
可空参数 ≤ 2 个、逻辑简单技巧一:拆分两条查询语义最清晰,零额外复杂度
可空参数多、查询复杂技巧二:哨兵值 + CASE单文件单函数,避免查询膨胀
多个查询都要做 null 转换技巧三:SQL 辅助函数规则复用,查询保持整洁

改完 SQL 后运行gleam run -m squirrel重新生成代码,并在 CI 中用gleam run -m squirrel check校验代码是否过期(参见 README.md 的 CLI Commands 一节)。

补充:返回列可空性 Squirrel 能自动推断

如果你的痛点其实是"返回值该不该是Option",Squirrel 已经替你解决了:它检查列的not null约束,并解析explain查询计划识别 LEFT/FULL JOIN 引入的空值(实现见 src/squirrel/internal/database/postgres.gleam 中resolve_returns的逻辑)。推断不准时还可以用别名后缀强制指定:列名以?结尾强制可空、以!结尾强制非空。更多背景可参考 CHANGELOG.md 中关于 optional 类型修复的记录。

写在最后

可空参数是 Squirrel 当前唯一需要你"多想一步"的地方,但三种变通技巧都很轻量:简单就拆查询,复杂就用哨兵值,重复就抽函数。结合check子命令,你可以放心地把这套模式固化进团队规范,继续享受 Squirrel 带来的类型安全 SQL 体验 🐿️

【免费下载链接】squirrel

🐿️ Type safe SQL in Gleam

项目地址:https://gitcode.com/gh_mirrors/squirrel4/squirrel
点击查看免费下载

相关推荐

上一篇:不到25元把普通眼镜变成AI智能眼镜:OpenGlass 完整上手攻略
下一篇:res-downloader 视频下载与视频号解密指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进