You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在OCaml中使用Caqti序列化运行时PostgreSQL查询?

问题场景
  • 接收用户提交的字符串形式SQL查询,执行后返回JSON格式结果
  • 使用Caqti库(支持类型安全查询),但查询类型依赖具体查询内容,而查询内容在编译时未知
  • 简化处理:假设所有列均为字符串,需要一个类型为string -> string list list的函数——输入字符串查询,返回string list list结果(string list代表单行数据,string list list代表多行数据,因无法预知返回列数)
示例说明

我做了一个需要dune构建的示例,运行步骤:

  1. 用dune init project foo初始化项目
  2. 将示例的.ml文件替换生成的bin/main.ml
  3. 用示例的dune文件替换bin/dune文件
核心问题

我需要获取用户输入的SQL查询字符串:

let query: string = Sys.argv.(1) in (* 这是用户查询 *)

然后执行查询并得到string list list类型结果,期望的函数签名是:

val do_query (query : string) : (string list list, string) Lwt_result.t

Caqti要求必须声明查询类型,比如针对todos表(列定义(id int, content text)),查询SELECT id, content FROM todos的类型声明是:

Caqti_type.(unit ->* (tup2 int string))
  "SELECT id, content FROM todos"

但用户输入的查询内容未知,我不知道在Caqti_type.( ??? ) user_query中该填写什么类型,示例中留下的函数:

let user_query q =
  Caqti_type.(unit ->* unit (* ??? 这里该填什么? *)) q

其中q是用户输入的查询字符串,替换第二个unit的类型就是当前的核心问题。

解决方案

我通过to_jsonb实现了需求,将user_query定义为:

let user_query q : (unit, string, [ `Many | `One | `Zero ]) Caqti_request.t =
  let cte = Format.sprintf {|
    WITH q AS (%s)
    SELECT to_jsonb(q.*)::text FROM q
  |} q in
  Caqti_type.(unit ->* string) cte

该方案将每一行结果输出为JSON格式,还支持逐行返回结果,无需将所有数据加载到内存中。


内容的提问来源于stack exchange,提问作者geckos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 23:53:13