sqlc 如何处理 MySQL 枚举 DDL:从 `ALTER TYPE ... RENAME VALUE` 测试用例看 MySQL 与 PostgreSQL 枚举语义差异
开发工具代码生成数据库【免费下载链接】sqlcGenerate type-safe code from SQL项目地址https://gitcode.com/gh_mirrors/sq/sqlc点击查看免费下载本文围绕 sqlc 仓库中的端到端测试用例ddl_alter_type_rename_value展开该用例的 MySQL 侧说明 明确指出 MySQL 不支持CREATE TYPE ... AS ENUM枚举只能以内联ENUM类型直接定义在表列上。文章将解读这条文档背后的完整语义并通过仓库源码与 PostgreSQL 对照组讲清 sqlc 在两种数据库引擎下对枚举 DDL 的不同处理方式帮助你在 schema 设计时正确选择枚举声明语法。这个测试用例在验证什么在 sqlc 的端到端测试目录中ddl_alter_type_rename_value用于验证修改枚举类型取值名这一 DDL 场景对应 PostgreSQL 的ALTER TYPE ... RENAME VALUE。该目录下同时存在两套引擎的测试mysql/只有一份 README.md没有任何 schema.sql、query.sql 或生成代码postgresql/包含完整的 stdlib、pgx/v4、pgx/v5 三套 Go 生成结果以及对应的 schema.sql 与 sqlc.json。这种目录结构本身就是 sqlc 对 MySQL 枚举能力边界的声明MySQL 侧不提供对应的 DDL 测试因为该语句在 MySQL 中根本不存在。原文档核心结论MySQL 没有独立的枚举类型 DDL关联文档 mysql/README.md 的原文结论如下MySQL does not supportCREATE TYPE ... AS ENUM. Instead, enumerations are defined via theENUMtype directly in table columns.翻译并展开为两层事实不存在CREATE TYPE ... AS ENUM与 PostgreSQL 可以先用CREATE TYPE status AS ENUM (...)创建独立类型、再在表中引用不同MySQL 无法单独创建枚举类型对象枚举必须内联定义在表列上MySQL 的枚举形态是列级类型声明例如CREATE TABLE t (status ENUM(open,closed))枚举取值集合是列定义的一部分而不是一个可复用的独立数据库对象。因此ALTER TYPE status RENAME VALUE closed TO shut这类重命名枚举取值的语句在 MySQL 语法体系中不存在对应物sqlc 也就没有为其编写 MySQL 端到端用例而是用一篇简短文档说明原因并把完整的测试覆盖留给 PostgreSQL 对照组。sqlc 如何解析 MySQL 的列内联枚举尽管 MySQL 没有独立枚举类型sqlc 的 MySQL 引擎内部代号 dolphin仍能识别列上的ENUM类型并把它纳入类型系统。可以从三层源码确认这一点1. 引擎方言层enum 被识别为标量字符串类型internal/engine/dolphin/dialect/types.jsonl 中声明了{name: enum, category: S}category: S表示该类型被归入字符串string类目。这意味着在 MySQL 模式下sqlc 首先把ENUM当作一个字符串类型的列来处理。2. 代码生成层MySQL 枚举列默认映射为 Go stringGo 代码生成器在 internal/codegen/golang/mysql_type.go 中处理enum类型case enum: // TODO: Proper Enum support return string也就是说当 schema 中直接出现ENUM(open,closed)这类列定义时只要该枚举没有在 Catalog 中登记为具名枚举类型生成的 Go 字段类型就是string可空场景由上层逻辑处理为sql.NullString等。从源码中的TODO: Proper Enum support注释可以看出MySQL 内联枚举目前走的是退化为字符串的保守策略。3. 目录构建层内联枚举被合成为内部类型名当 MySQL 的列定义携带枚举取值集合Vals时sqlc 会把它们合成为一个内部枚举类型命名规则为表名_列名见 internal/sql/catalog/table.go 中的defineColumnif col.Vals ! nil { typeName : ast.TypeName{ Name: fmt.Sprintf(%s_%s, table.Name, col.Colname), } s : ast.CreateEnumStmt{TypeName: typeName, Vals: col.Vals} if err : c.createEnum(s); err ! nil { return nil, err } tc.Type typeName tc.linkedType true }这段代码揭示了 MySQL 内联枚举在 sqlc 内部的真实表示列上写的ENUM(a,b)会被转换为一次隐式的CREATE ENUM枚举名由表名与列名拼接而成列类型再指向这个合成枚举。这也解释了mysql_type.go中default分支为何还会遍历schema.Enums来匹配列类型——当枚举被登记为具名类型后生成逻辑会尝试输出枚举结构体而非纯字符串。对照组PostgreSQL 如何完整支持RENAME VALUEPostgreSQL 侧才是ddl_alter_type_rename_value真正执行测试的地方其完整链路可以一步步追踪1. 测试 schema 与生成结果postgresql/stdlib/schema.sql 给出了最小可复现 schemaCREATE TYPE status AS ENUM (open, closed); ALTER TYPE status RENAME VALUE closed TO shut;对应的生成结果 postgresql/stdlib/go/models.go 中枚举被生成为 Go 类型与常量type Status string const ( StatusOpen Status open StatusShut Status shut )注意两个关键点旧值closed在生成常量中彻底消失取而代之的是新值shutStatusShut证明 sqlc 的解析结果正确应用了重命名该测试的 query.sql 仅有一条SELECT 1占位查询说明此用例只验证 schema 解析与类型生成不涉及查询编译。pgx/v4 与 pgx/v5 的生成结果与 stdlib 完全一致枚举常量、Scan/Value方法结构相同表明RENAME VALUE的处理不依赖具体驱动。2. 解析器把 PostgreSQL 的 ALTER ENUM 拆成两类语句PostgreSQL 引擎解析器在 internal/engine/postgresql/parse.go 中处理AlterEnumStmt当语句携带旧值n.OldVal ! 时翻译为重命名取值语句否则翻译为追加取值语句case *nodes.Node_AlterEnumStmt: n : inner.AlterEnumStmt rel, err : parseRelationFromNodes(n.TypeName) if err ! nil { return nil, err } if n.OldVal ! { return ast.AlterTypeRenameValueStmt{ Type: rel.TypeName(), OldValue: makeString(n.OldVal), NewValue: makeString(n.NewVal), }, nil } else { return ast.AlterTypeAddValueStmt{ ... }, nil }3. AST 节点结构化表达重命名internal/sql/ast/alter_type_rename_value_stmt.go 定义了对应的 AST 节点携带三个字段type AlterTypeRenameValueStmt struct { Tag NodeTag[AlterTypeRenameValueStmt] json:tag Type *TypeName json:type,omitempty OldValue *string json:old_value,omitempty NewValue *string json:new_value,omitempty }4. Catalog 应用校验并原地替换取值最终落地在 internal/sql/catalog/types.go 的alterTypeRenameValue其行为值得细读for i, val : range enum.Vals { if val *stmt.OldValue { oldIndex i } if val *stmt.NewValue { newIndex i } } if oldIndex 0 { return fmt.Errorf(type %T does not have value %s, stmt.Type, *stmt.OldValue) } if newIndex 0 { return fmt.Errorf(type %T already has value %s, stmt.Type, *stmt.NewValue) } enum.Vals[oldIndex] *stmt.NewValue实现要点保留原位置只替换Vals数组中的对应元素不改变枚举值的顺序这对依赖枚举顺序的代码生成常量顺序、Valid/Values方法很重要双向校验旧值不存在、或新值与已有值冲突时都会报错保证 Catalog 中的枚举取值集合始终合法schema 作用域未显式指定 schema 时使用DefaultSchemans c.DefaultSchema与 sqlc 的默认 schema 解析策略一致。该节点在 internal/sql/catalog/catalog.go 中被分发到上述实现形成解析 → AST → Catalog 更新 → 代码生成的完整链路。实操建议两种引擎下枚举 schema 应该怎么写基于以上源码事实可以给出直接可落地的 schema 编写建议场景推荐写法sqlc 处理结果PostgreSQLCREATE TYPE status AS ENUM (open,closed); 表列引用生成具名 Go 枚举类型与常量ALTER TYPE ... RENAME VALUE可安全用于迁移MySQL列内联status ENUM(open,closed)枚举取值作为列的一部分被解析列类型在代码生成中默认映射为string源码标记为 TODO 的未完成特性若希望获得具名类型行为需依赖 Catalog 中的合成枚举路径具体生成形态受 mysql_type.go 当前实现约束关键结论不要试图在 MySQL schema 里写CREATE TYPE ... AS ENUM或ALTER TYPE ... RENAME VALUE——MySQL 方言没有这些语句dolphin 引擎的转换逻辑internal/engine/dolphin/convert.go只处理ALTER TABLE下的列操作并不会识别独立的类型级 ALTERMySQL 的枚举变更需要写成ALTER TABLE ... MODIFY COLUMN重新声明列上的 ENUM 取值集合而不是类型级语句如果希望让 MySQL 枚举列获得与 PostgreSQL 一致的具名类型生成体验目前需要在 sqlc 的 MySQL 类型映射mysql_type.go层面关注其演进现阶段应默认接受enum → string的映射结果。小结ddl_alter_type_rename_value这个测试用例用一份简短的 README 精准划出了 sqlc 对 MySQL 枚举 DDL 的能力边界MySQL 不提供CREATE TYPE ... AS ENUM枚举内联在表列中而完整的ALTER TYPE ... RENAME VALUE支持链路解析器翻译 → AST 节点 → Catalog 校验与替换 → 具名枚举生成则完整存在于 PostgreSQL 引擎中并有 stdlib、pgx/v4、pgx/v5 三套生成结果佐证。对使用者而言理解这条边界能避免写出在 MySQL 下无法解析的 schema也能在迁移到 PostgreSQL 时放心使用类型级枚举重命名。赞分享开发工具代码生成数据库【免费下载链接】sqlcGenerate type-safe code from SQL项目地址https://gitcode.com/gh_mirrors/sq/sqlc点击查看免费下载相关推荐sqlc 中枚举演进的处理PostgreSQL ALTER TYPE ... ADD VALUE 与 MySQL 列内 ENUM 的差异解析sqlc 中枚举演进的处理PostgreSQL ALTER TYPE ... ADD VALUE 与 MySQL 列内 ENUM 的差异解析 在 sqlc 的开发工具代码生成数据库ModernDive社区与支持如何参与开源项目和获取帮助的完整指南ModernDive社区与支持如何参与开源项目和获取帮助的完整指南 ModernDive是一个专注于R和Tidyverse数据科学统计推断的开源教材项目为学终极NSwag枚举处理指南如何正确配置字符串枚举与数值枚举终极NSwag枚举处理指南如何正确配置字符串枚举与数值枚举 NSwag是一个强大的Swagger/OpenAPI工具链专为.NET开发者设计能够轻松生成A开发工具代码生成API设计上一篇桌面太枯燥让DyberPet用AI桌宠伙伴为你注入温暖与活力下一篇3步搞定React Native性能监控Sentry与Flipper集成指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Ant Design Blazor Alert 警告提示组件完全指南:属性详解、源码原理与实战示例

Ant Design Blazor Alert 警告提示组件完全指南:属性详解、源码原理与实战示例

前端UI组件设计系统 【免费下载链接】ant-design-blazor 基于 Ant Design 与 Blazor 的前端组件库。让开发者解放生产力,实现更大价值。 项目地址: https://gitcode.com/ant-design-blazor/ant-design-blazor 点击查看 免费下载 导读:本文以…

2026/10/10 5:26:34 阅读更多 →
Cloud Custodian EBS 快照自动化实战:批量创建、标签继承与滚动清理

Cloud Custodian EBS 快照自动化实战:批量创建、标签继承与滚动清理

云原生运维安全 【免费下载链接】cloud-custodian Rules engine for cloud security, cost optimization, and governance, DSL in yaml for policies to query, filter, and take actions on resources 项目地址: https://gitcode.com/gh_mirrors/cl/cloud-custodi…

2026/10/10 5:26:33 阅读更多 →
简化 Android 的 UI 开发:基于虚拟布局与自动重渲染的纯 Java 数据绑定方案

简化 Android 的 UI 开发:基于虚拟布局与自动重渲染的纯 Java 数据绑定方案

文档教程知识库 【免费下载链接】android-tech-frontier 【停止维护】一个定期翻译国外Android优质的技术、开源库、软件架构设计、测试等文章的开源项目 项目地址: https://gitcode.com/gh_mirrors/an/android-tech-frontier 点击查看 免费下载 本文依据 android-…

2026/10/10 5:25:33 阅读更多 →

最新新闻

BrowserAct YouTube Transcript Extractor API Skill:一条命令提取 YouTube 视频字幕与元数据

BrowserAct YouTube Transcript Extractor API Skill:一条命令提取 YouTube 视频字幕与元数据

【免费下载链接】skills Browser automation CLI built for AI agents. Break through anti-bot walls, hand off to humans across platforms when stuck. Parallel multi-task execution, independent multi-session operation, isolated multi-account browsing. 项目地址&a…

2026/10/10 6:07:48 阅读更多 →
Frontend Developer 进阶实战指南:developer-handbook 中 Regular 到 Senior 的完整技术能力清单

Frontend Developer 进阶实战指南:developer-handbook 中 Regular 到 Senior 的完整技术能力清单

文档教程 【免费下载链接】developer-handbook An opinionated guide on how to become a professional Web/Mobile App Developer. 项目地址: https://gitcode.com/gh_mirrors/de/developer-handbook 点击查看 免费下载 本篇指南基于 developer-handbook 仓库中 T…

2026/10/10 6:07:48 阅读更多 →
SpringBoot+Vue健康打卡评测系统:从数据库设计到部署全解析

SpringBoot+Vue健康打卡评测系统:从数据库设计到部署全解析

这段时间正好在整理一个手头刚收尾的项目,就是基于SpringBoot和Vue做的健康打卡与评测系统。做的时候没少踩坑,从数据库设计到前后端联调,再到最后部署上线,每一步都有一堆细节值得拿出来聊聊。尤其是一些只会在真实业务里遇到、文…

2026/10/10 6:07:48 阅读更多 →
基于PCA9422与MKV42F256VLH16的嵌入式电源管理实战设计

基于PCA9422与MKV42F256VLH16的嵌入式电源管理实战设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 6:07:48 阅读更多 →
快速上手LingBot-VA:10分钟部署机器人视频-动作世界模型,18GB显存即可跑通推理

快速上手LingBot-VA:10分钟部署机器人视频-动作世界模型,18GB显存即可跑通推理

快速上手LingBot-VA:10分钟部署机器人视频-动作世界模型,18GB显存即可跑通推理 【免费下载链接】lingbot-va [RSS 2026] Causal video-action world model for generalist robot control 项目地址: https://gitcode.com/gh_mirrors/li/lingbot-va …

2026/10/10 6:07:48 阅读更多 →
LeetCode 2413 Smallest Even Multiple 题解:奇偶分类与位运算的 O(1) 解法(codeforces-go 仓库实战指南)

LeetCode 2413 Smallest Even Multiple 题解:奇偶分类与位运算的 O(1) 解法(codeforces-go 仓库实战指南)

科学计算 【免费下载链接】codeforces-go 算法竞赛模板库 by 灵茶山艾府 💭💡🎈 项目地址: https://gitcode.com/GitHub_Trending/co/codeforces-go 点击查看 免费下载 本篇技术指南以 codeforces-go 仓库中 LeetCode 第 311 场周…

2026/10/10 6:06:48 阅读更多 →

日新闻

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

1. 从“卫星轨道分类”这个标题说起:为什么值得花时间搞懂第一次接触“卫星轨道分类”这个概念,很多人会觉得它离自己很远——不就是天上的星星怎么转吗?但如果你正在做航天任务规划、遥感数据接收、星座设计,甚至只是准备一场航天…

2026/10/10 0:00:39 阅读更多 →
Spring AOP 核心原理与实战:从概念到日志切面落地

Spring AOP 核心原理与实战:从概念到日志切面落地

1. 从一个真实痛点说起:为什么你的代码里到处都是重复逻辑刚入行那会儿,我写过一个用户管理模块,注册、登录、改密码、注销四个接口。每个接口里都塞了几乎一样的日志打印、参数校验、事务开启和提交。当时觉得没什么,能跑就行。直…

2026/10/10 0:00:40 阅读更多 →
Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

简介:这是一套面向计算机相关专业学生与项目实战学习者的Python数据采集与分析可视化完整项目,以Boss直聘岗位数据为对象,适合用作毕业设计、课程设计或期末大作业。资源包共38个文件,约246KB,以13个py源码文件为核心&…

2026/10/10 0:00:40 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 1:36:08 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 5:23:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →