
后端API网关【免费下载链接】crystal Graphiles Crystal Monorepo; home to Grafast, PostGraphile, pg-introspection, pg-sql2 and much more!项目地址https://gitcode.com/gh_mirrors/cry/crystal点击查看免费下载PostGraphile 会把你数据库中的 PostgreSQL 函数自动暴露为 GraphQL 的查询custom queries、计算字段computed columns与变更custom mutations但你并非能把任何函数都映射进 GraphQL Schema。本文聚焦官方文档 function-restrictions.md 所阐述的三类不受支持的函数——VARIADIC 函数、重载函数、以及返回无类型信息record的函数——逐一说明限制原因并给出可落地的数据库端改造方案。读完本文你将能判断自己的函数是否会被 PostGraphile 暴露、理解其背后的实现原理并掌握用CREATE TYPE组合类型化解record问题的具体写法。一、限制总览PostGraphile 支持绝大部分函数PostGraphile 对 PostgreSQL 函数的支持面非常广标量、数组、复合类型表行、SETOF集合、void返回值等都能被识别并映射为对应的 GraphQL 类型。根据仓库内配套的完整指南 functions.mdVOLATILE函数会被暴露为 custom mutationsSTABLE/IMMUTABLE函数会被暴露为 custom queries 或 computed columns而返回SETOF的函数还会进一步被映射为 GraphQL 连接connections或列表。然而以下三类函数 PostGraphile 明确不支持函数类型限制原因VARIADIC 函数可变参数无法整洁地映射到 GraphQL 的强类型参数系统重载函数overloaded当前无法在 GraphQL 上整齐地暴露同名多签名函数返回无类型信息record的函数不知道record具体包含哪些列无法转换为 GraphQL 类型说明本文所述限制来自当前仓库 postgraphile/website/postgraphile/function-restrictions.mdv5 文档v4/v5 的历史版本见 version-4/function-restrictions.md 与 version-5/function-restrictions.md。二、VARIADIC 函数可变参数与 GraphQL 类型系统的冲突PostgreSQL 支持用VARIADIC关键字声明可变参数函数调用时可以传入任意数量的同类型参数create function my_sum(variadic numbers int[]) returns int as $$ select sum(n) from unnest(numbers) as n; $$ language sql immutable strict;PostGraphile 不支持这类函数。原因在于 GraphQL 的参数系统是强类型、固定数目的Schema 中每个字段的参数列表在生成时就已确定调用方必须按声明逐个传参。而VARIADIC的语义是参数个数可变两者天然冲突PostGraphile 无法为它生成整洁neat的 GraphQL 参数定义。从仓库的 pg-introspection 源码也可以印证这一点PgProc接口utils/pg-introspection/src/introspection.ts忠实保留了 PostgreSQLpg_proc目录中的全部函数元数据其中provariadicvariadic 数组参数的元素类型若无 variadic 参数则为零见 introspection.ts与proargmodes参数模式编码中v即代表 VARIADIC 参数见 introspection.ts字段都可用于识别这类函数。也就是说底层内省机制完全有能力看见一个函数是否是 variadic 的只是由于 GraphQL 表达能力的限制PostGraphile 不会将这类函数纳入暴露范围。替代方案如果你确实需要数量不定的同类参数更推荐的做法是让函数接收一个数组参数由客户端以 GraphQL 列表的形式传参。例如把上面的my_sum改写成create function my_sum(numbers int[]) returns int as $$ select sum(n) from unnest(numbers) as n; $$ language sql immutable strict;这样numbers在 GraphQL 中就是一个[Int!]列表参数语义与 variadic 等价且完全受支持。三、重载函数同名多签名无法在 GraphQL 中区分PostgreSQL 允许函数重载多个函数可以同名只要参数签名参数类型列表不同即可例如create function get_user(id int) returns users as $$ ... $$ language sql stable; create function get_user(email text) returns users as $$ ... $$ language sql stable;PostGraphile 不支持重载函数官方文档给出的理由是当前无法在 GraphQL 上整洁地暴露它们its not currently possible to expose them neatly over GraphQL。GraphQL 字段以名字唯一标识一个类型下不能有两个同名字段虽然可以用后缀区分如getUserById、getUserByEmail但这类自动改名策略并不总能保证整洁和确定性因此 PostGraphile 选择直接不暴露重载函数。仓库中的佐证同样来自内省层面PgProc.proname只记录函数名而签名信息分布在proargtypes/proallargtypes/proargmodes等字段中introspection.ts内省查询也能把重载的同名函数都取回来——例如 pg-introspection 的 procs 查询会按pronamespace, proname, pg_get_function_identity_arguments(...)排序introspection.ts。但能取回与能映射是两回事映射环节无法在单一 GraphQL 名字空间下整洁地表达多个同名签名。替代方案为每个语义起一个独立且自解释的函数名避免重载。比如分别命名get_user_by_id(id int)与get_user_by_email(email text)PostGraphile 会按 inflector 规则生成getUserById、getUserByEmail两个清晰的 GraphQL 字段。四、返回 record 的函数缺少列信息无法定类型PostgreSQL 中存在一种特殊的匿名记录类型record。当一个函数RETURNS record且不附带任何列定义信息时PostgreSQL 自己也不知道它会返回哪些列。PostGraphile 因此无法确定该函数输出结构对应的 GraphQL 对象类型自然无法将其暴露。-- 不受支持record 没有提供任何列信息 create function get_something() returns record as $$ select 1 as a, hello as b; $$ language sql stable;官方推荐的解决方案是将record改为一个你自己用CREATE TYPE或类似方式定义的组合类型。组合类型有明确的属性名与属性类型PostGraphile 的内省与类型映射可以据此生成确定性的 GraphQL 对象类型create type my_result as ( a int, b text ); create function get_something() returns my_result as $$ select 1, hello; $$ language sql stable;改造后PostGraphile 会把返回值映射为一个包含a、b两个字段的 GraphQL 对象类型函数即可正常暴露。这个限制在源码层面有非常清晰的对应pg-introspection 的内省 SQL 在拉取pg_proc时显式排除了返回类型 OID 为2279的函数——2279正是 PostgreSQL 中record类型的内置 OIDprocs as ( select pg_proc.oid as _id, * from pg_catalog.pg_proc where pronamespace in (select namespaces._id from namespaces where ...) and prorettype operator(pg_catalog.) 2279 )该片段位于 utils/pg-introspection/src/introspection.ts它意味着所有RETURNS record的函数在内省阶段就被过滤掉根本不会进入后续的 schema 构建流程。更进一步在 dataplan-pg 的 codec 体系中组合类型的映射由recordCodec承担grafast/dataplan-pg/src/codecs.ts。recordCodec支持isAnonymous标志源码注释明确写道isAnonymous为 true 时表示匿名类型典型场景是函数或其他对象的返回值此时name与identifier会被忽略codecs.ts。在构建资源时匿名 codec 不会被当作可访问的表状资源处理grafast/dataplan-pg/src/datasource.ts 中!codec.isAnonymous的判断。这从另一个角度印证了没有明确类型信息的返回值无法参与 GraphQL 类型与资源映射而CREATE TYPE组合类型恰好提供了这份关键的类型信息。五、排查建议你的函数为什么没有被暴露当你在数据库里创建了函数但在 PostGraphile Schema 中找不到对应字段时可以按以下顺序排查确认返回类型\df 函数名查看返回类型。若为record按上文方案改用CREATE TYPE组合类型。确认是否重载\df 函数名检查是否存在多个同名函数。若有拆分命名。确认是否 variadic查看函数参数中是否有VARIADIC关键字。若有改为数组参数。确认易变性分类函数默认是VOLATILE只会出现在变更Mutation侧若你的函数只是查询逻辑应显式声明为STABLE或IMMUTABLE才会被当作 custom query / computed column 暴露详见 functions.md 的 VOLATILE (Mutation) Functions 与 STABLE/IMMUTABLE (Query) Functions 两节。确认参数命名GraphQL 只支持命名参数未命名的参数会被 PostGraphile 自动命名为arg1、arg2…… 为可读性考虑始终使用命名参数functions.md。六、总结PostGraphile 的函数支持面虽然很广但有三条明确的边界VARIADIC参数个数可变与 GraphQL 强类型参数冲突、重载同名多签名无法整洁映射、无类型信息的record缺少列结构无法生成 GraphQL 类型。前两类目前只能通过调整函数设计来规避改用数组参数、拆分命名第三类则有官方推荐的直接解法——用CREATE TYPE定义组合类型替换record。理解了这些限制及其在内省pg-introspection与 codec 映射dataplan-pg层面的成因你就能在设计数据库函数时提前规避踩坑让函数顺畅地变成 GraphQL API 的一部分。赞分享后端API网关【免费下载链接】crystal Graphiles Crystal Monorepo; home to Grafast, PostGraphile, pg-introspection, pg-sql2 and much more!项目地址https://gitcode.com/gh_mirrors/cry/crystal点击查看免费下载相关推荐PostGraphile 数据库函数限制解析VARIADIC、函数重载与匿名 record 的处理方案PostGraphile 数据库函数限制解析VARIADIC、函数重载与匿名 record 的处理方案 PostGraphile 能够从 PostgreSQL后端API网关Pixelle-Video 上手指南输入一个主题5 分钟做出 AI 短视频Pixelle Video 上手指南输入一个主题5 分钟做出 AI 短视频 Pixelle Video 是一款开源的 AI 全自动短视频引擎输入一个主题人工智能AI 应用音视频媒体生成Rome 规则详解noVoidTypeReturn —— 禁止在返回类型为 void 的函数中返回值Rome 规则详解noVoidTypeReturn —— 禁止在返回类型为 void 的函数中返回值 本指南围绕 Rome现 Biomelinter 的开发工具CLILint格式化静态分析代码质量构建工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考