ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

postgres_lsp 规则详解:preferBigInt——用 BIGINT 规避整数溢出与迁移风险

postgres_lsp 规则详解:preferBigInt——用 BIGINT 规避整数溢出与迁移风险 postgres_lsp 规则详解preferBigInt——用 BIGINT 规避整数溢出与迁移风险【免费下载链接】postgres_lspA Language Server for Postgres项目地址: https://gitcode.com/GitHub_Trending/po/postgres_lsp导读preferBigInt是 postgres_lsp 项目中lint/safety类别下的一条数据库迁移安全规则用于在创建表或修改表结构时提醒开发者优先使用BIGINT/BIGSERIAL避免SMALLINT、INTEGER、SERIAL等小整数类型带来的溢出风险与后期迁移成本。本文以官方规则文档为主体结合 规则源码 与快照测试完整讲解该规则的触发条件、诊断输出、配置方式与底层实现原理读完即可在项目中直接启用并理解其工作方式。规则概览属性值诊断类别lint/safety/preferBigInt规则名称preferBigInt默认严重级别Warning警告是否默认推荐否recommended: false版本vnext灵感来源Squawk 项目的prefer-big-int规则在源码层面规则通过declare_lint_rule!宏声明见 prefer_big_int.rs其来源被标记为RuleSource::Squawk(prefer-big-int)对应仓库中的移植说明文档 agentic/port_squawk_rules.md该项目正在系统性地将 Squawk 的规则移植到自己的分析器pgls_analysercrate 中。为什么推荐 BIGINT小整数类型的溢出风险SMALLINT、INTEGER以及它们的别名int2、int4和自增序列SERIAL系列类型都有明确的数值上限SMALLINTint2范围为 −32,768 到 32,767INTEGERint4范围为 −2,147,483,648 到 2,147,483,647BIGINTint8范围为 −9,223,372,036,854,775,808 到 9,223,372,036,854,775,807。随着应用业务量增长主键、计数列、外键列等一旦超过小整数类型的上限就会发生数值溢出直接影响数据的正确性。而BIGINT提供了大得多的取值范围可以从一开始就规避这类问题。存储成本几乎可以忽略在文档与源码注释中都明确指出INTEGER4 字节与BIGINT8 字节在现代系统上的存储差异微乎其微每条记录多 4 字节而后期将列类型迁移到更大类型的成本却可能非常高昂——尤其是当表已经积累大量数据、被外键引用、或在生产环境中需要执行耗时锁表的ALTER TABLE时。触发场景与判定逻辑覆盖的语句类型从源码实现看prefer_big_int.rs该规则针对两类 AST 节点进行检查CreateStmtCREATE TABLE遍历table_elts中的所有列定义对每个ColumnDef调用check_column_defAlterTableStmtALTER TABLE遍历cmds仅当子命令类型为AtAddColumn新增列或AtAlterColumnType修改列类型时提取其中的ColumnDef进行检查。这意味着规则不仅能拦截新建表时使用小整数类型还能拦截迁移脚本中“新增小整数列”和“把某列改成小整数类型”这两种同样危险的操作。被判定为小整数的类型集合check_column_def函数prefer_big_int.rs将列类型名统一转为小写后与以下集合进行匹配smallint | integer | int2 | int4 | serial | serial2 | serial4 | smallserial也就是说无论开发者使用标准名称还是 PostgreSQL 内部别名都会被识别类别会被拦截的写法普通整数smallint、integer、int2、int4自增序列serial、serial2、serial4、smallserial合法写法bigint、bigserial不触发单次检查的多个列定义注意check_column_def对type_name.names做循环遍历且每个匹配到的名称节点都会产生一条独立诊断。在实际 PostgreSQL 语法中类型名通常只有一个 name 节点但这种遍历方式也兼容了更复杂的类型名解析场景。诊断输出示例无效写法INTEGER以下建表语句会被标记CREATE TABLE users ( id integer );CLI 检查输出code-block.sql:1:1 lint/safety/preferBigInt ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Using smaller integer types can lead to overflow issues. 1 │ CREATE TABLE users ( │ ^^^^^^^^^^^^^^^^^^^^ 2 │ id integer 3 │ ); │ ^^ 4 │ i The int4 type has a limited range that may be exceeded as your data grows. i Consider using BIGINT for integer columns to avoid future migration issues.无效写法SERIAL自增序列同样会被拦截CREATE TABLE users ( id serial );code-block.sql:1:1 lint/safety/preferBigInt ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Using smaller integer types can lead to overflow issues. 1 │ CREATE TABLE users ( │ ^^^^^^^^^^^^^^^^^^^^ 2 │ id serial 3 │ ); │ ^^ 4 │ i The serial type has a limited range that may be exceeded as your data grows. i Consider using BIGINT for integer columns to avoid future migration issues.诊断消息由三部分组成对应 prefer_big_int.rs主消息!/×Using smaller integer types can lead to overflow issues.详情iThe int4 type has a limited range...其中类型名取自 SQL 中的实际写法如integer会显示为int4别名serial显示为serial建议iConsider using BIGINT for integer columns to avoid future migration issues.合法写法以下写法不会触发规则CREATE TABLE users ( id bigint );CREATE TABLE users ( id bigserial );如何配置规则preferBigInt属于safety规则组可以在项目的postgres-language-server.jsonc配置文件中通过linter.rules.safety节点进行配置{ linter: { rules: { safety: { preferBigInt: error } } } }可选值与其他 lint 规则一致例如off关闭该规则warn以警告级别报告规则的默认严重级别即 Warningerror以错误级别报告可配合--error-on-warnings一类的 CI 严格模式使用。该规则是无参数规则源码中type Options ()因此配置时只需设置严重级别无需提供任何选项对象。仓库根目录自带的示例配置 postgres-language-server.jsonc 展示了完整的 linter 配置骨架linter.enabled、linter.rules.recommended等可作为参考。另外需要说明该规则的recommended标志为false意味着单纯开启recommended: true不会自动启用它需要像上面的示例那样显式声明preferBigInt: error。源码级实现原理规则的注册与分发postgres_lsp 的 lint 体系采用“声明 注册 分发”的架构preferBigInt贯穿了整条链路规则组声明在 crates/pgls_analyser/src/lint/safety.rs 中declare_lint_group!将PreferBigInt挂载到名为safety的规则组执行器注册在 crates/pgls_analyser/src/registry.rs 中get_linter_rule_executor将字符串规则名preferBigInt映射到具体的规则执行器文档注释表明这是一层零成本的抽象选项类型注册在 crates/pgls_analyser/src/options.rs 中定义PreferBigInt选项类型别名配置结构生成在 crates/pgls_configuration/src/linter/rules.rs 中配置结构体包含prefer_big_int: OptionRuleConfigurationpgls_analyser::options::PreferBigInt字段用于解析 JSON 配置中的preferBigInt键。值得留意的是safety.rs、options.rs、registry.rs等文件头部都标注了“Generated file, do not edit by hand, seextask/codegen”说明这些注册代码由 xtask/codegen 代码生成器自动产出新增规则时只需编写规则实现并运行代码生成流程即可。基于 libpg_query AST 的检查该规则基于pgls_querycrate 提供的 PostgreSQL 解析结果libpg_query 的 Rust 绑定完整定义见 crates/pgls_query/src/protobuf.rs进行遍历CreateStmt对应CREATE TABLE其table_elts中每一项的node若是ColumnDef就提取列定义检查类型AlterTableStmt对应ALTER TABLE通过AlterTableType::AtAddColumn与AtAlterColumnType枚举值筛选出“加列”与“改列类型”两种子命令。这种“精确匹配 AST 节点 白名单类型集合”的实现方式保证了规则误报率低只有明确使用上述八种小整数类型写法时才告警bigint、bigserial及其他数值类型如numeric、decimal完全不受影响。快照测试验证仓库为每条规则都配备了规格测试preferBigInt的测试位于 crates/pgls_analyser/tests/specs/safety/preferBigInt/basic.sql-- expect_lint/safety/preferBigInt CREATE TABLE users ( id integer );对应的快照文件 basic.sql.snap 精确记录了期望的诊断输出包含主消息、类型详情与修改建议由pgls_analysercrate 的rules_tests.rs测试入口驱动。读者若想验证或扩展该规则行为可参考该目录下的 128 组.sql/.snap测试对。与其他相关规则的配合safety规则组内还有一组与之主题相近的规则可组合使用以覆盖整数类型选择的更多维度preferBigintOverInt偏好BIGINT胜过INTEGERpreferBigintOverSmallint偏好BIGINT胜过SMALLINTpreferIdentity偏好GENERATED AS IDENTITY自增列。它们在 crates/pgls_analyser/src/lint/safety.rs 中与preferBigInt同属safety组在 docs/reference/rules 目录下也各自有对应文档如 prefer-bigint-over-int.md、prefer-bigint-over-smallint.md、prefer-identity.md。实际项目中可根据团队规范选择启用其中一条或多条。实践建议新项目直接启用在新表的自增主键与数值列上优先使用bigint/bigserial并将preferBigInt配置为error在开发与 CI 阶段就杜绝小整数类型进入 schema。迁移脚本同样受检由于规则同时覆盖ALTER TABLE ADD COLUMN与ALTER TABLE ALTER COLUMN TYPE在编写迁移文件时它同样能发挥作用避免在存量表上引入新的溢出隐患。结合preferIdentity使用若团队倾向于现代的自增写法可将preferBigInt与preferIdentity一并启用同时约束类型与自增实现方式。了解默认不推荐的前提该规则未被列入recommended集合因为“是否必须用 BIGINT”属于团队取舍——例如数据量可预期的中间表用int4完全够用。启用前建议在团队内达成一致避免产生噪音告警。总结preferBigInt是 postgres_lsp 为数据库 schema 提供的一道低成本“保险丝”它以 4 字节与 8 字节之间几乎可忽略的存储差异换取了未来完全可避免的整型溢出与高成本迁移。从规则文档、源码实现到快照测试整个链路清晰展示了 postgres_lsp 如何将 Squawk 的优秀规则以“移植 原生 AST 检查 自动代码生成注册”的方式落地值得在数据库迁移审查流程中优先启用。【免费下载链接】postgres_lspA Language Server for Postgres项目地址: https://gitcode.com/GitHub_Trending/po/postgres_lsp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表