PRQL 的 Elixir 绑定:使用 Rustler NIF 在 Elixir 中编译 PRQL 查询
后端【免费下载链接】prqlPRQL is a modern language for transforming data — a simple, powerful, pipelined SQL replacement项目地址https://gitcode.com/gh_mirrors/pr/prql点击查看免费下载本指南围绕 PRQL 仓库中的 Elixir 语言绑定位于 prqlc/bindings/elixir/README.md并被文档站点收录于 web/book/src/project/bindings/elixir.md展开介绍如何在 Elixir 项目中安装、调用PRQL.compile/2将 PRQL 管道式查询编译为 SQL并结合仓库源码剖析其 Rustler NIF 桥接层的实现原理、参数语义与开发测试流程。读完本文你将能够在自己的 Elixir 应用中直接驱动prqlc编译器并理解其编译管线的每一层PRQL → PL AST → RQ → SQL对应的 Elixir API。一、什么是 PRQL 的 Elixir 绑定PRQLPipelined Relational Query Language是一种面向数据转换的现代查询语言目标是成为 SQL 的管道式替代品。PRQL 编译器的核心是 Rust crateprqlc位于本仓库的 prqlc/prqlc 目录。为了让 Elixir 生态也能使用这一编译器仓库维护了一套独立的 Elixir 绑定工程其入口即 prqlc/bindings/elixir/README.md。该绑定基于Rustler实现Rustler 是 Elixir 社区中编写 Rust NIFNative Implemented Function原生函数的标准库它把prqlc的编译能力以原生函数的形式暴露给 Erlang VMElixir 侧则通过一个PRQL模块封装调用。从绑定分级来看Elixir 目前被归类为Unsupported非官方支持层级——功能可用但尚未达到需要维护者、完整测试覆盖、发布到官方包仓库等Supported标准详见 web/book/src/project/bindings/README.md 中的分级说明。二、安装与依赖2.1 在 mix 项目中引入依赖在mix.exs的deps/0中添加依赖def deps do [ {:prql, ~ 0.1.0} ] end随后执行mix deps.get拉取依赖。当前绑定工程的版本为0.1.0对 Elixir 的要求是~ 1.15见 prqlc/bindings/elixir/mix.exs 中project/0的声明。2.2 需要 Rust 工具链需要特别注意的是在写本文时该绑定尚未发布预编译产物。README 明确说明当前在 Elixir 项目中使用该绑定需要从本仓库源码编译 Rust crateprqlc/bindings/elixir/README.md的 Development 一节。也就是说开发/运行环境必须具备 Rust 工具链且mix compile时会触发对 NIF 的本地编译。绑定侧的依赖声明位于 prqlc/bindings/elixir/native/prql/Cargo.tomlprqlc以path ../../../../prqlc指向仓库内的编译器本体版本对应0.13.15并关闭默认特性default-features falserustler 0.38.0NIF 桥接库crate 类型为cdylib即编译为可供 Erlang VM 动态加载的共享库。Elixir 侧的构建依赖同样由 mix.exs 声明{:rustler, ~ 0.38.0}与仅开发期使用的{:ex_doc, ~ 0.21}。三、基本用法把 PRQL 编译为 SQL绑定对外暴露的入口是PRQL.compile/2。以下两个示例直接取自绑定 README也是PRQL模块的 doctest 用例见 prqlc/bindings/elixir/lib/prql.ex 中的doc与 prqlc/bindings/elixir/test/prql_test.exsiex PRQL.compile(from customers, signature_comment: false) {:ok, SELECT\n *\nFROM\n customers\n} iex PRQL.compile(from customers\ntake 10, target: :mssql, signature_comment: false) {:ok, SELECT\n *\nFROM\n customers\nORDER BY\n (\n SELECT\n NULL\n ) OFFSET 0 ROWS\nFETCH FIRST\n 10 ROWS ONLY\n}可以观察到两点返回值是{:ok, sql_string}元组成功时第二个元素就是可直接交给 SQL 驱动执行的 SQL 文本方言参数影响输出take 10在默认的:generic方言与:mssql方言下会生成不同的分页语法——MSSQL 使用OFFSET 0 ROWS ... FETCH FIRST 10 ROWS ONLY表达取前 10 行这正体现了 PRQL 面向多种 SQL 方言编译的能力。四、compile/2 的完整参数语义PRQL.compile(prql_query, opts \\ [])接受两个参数待编译的 PRQL 查询字符串以及关键字选项列表。其类型约束为when is_binary(prql_query) and is_list(opts)见 lib/prql.ex并通过struct(CompileOptions, opts)将选项结构化为 NIF 侧期望的 struct。4.1 target目标 SQL 方言target决定生成的 SQL 面向哪种数据库方言支持以下 12 个原子值原子值对应 prqlc 方言典型场景:genericGeneric默认通用 SQL:mssqlMsSqlMicrosoft SQL Server:mysqlMySqlMySQL:postgresPostgresPostgreSQL:ansiAnsiANSI 标准 SQL:bigqueryBigQueryGoogle BigQuery:clickhouseClickHouseClickHouse:duckdbDuckDbDuckDB:oracleOracleOracle:redshiftRedshiftAmazon Redshift:sqliteSQLiteSQLite:snowflakeSnowflakeSnowflake该参数默认值为:generic。有两个值得注意的语义未知原子回退到:genericRust 侧的target_from_atom见 native/prql/src/lib.rs会逐一分发各方言原子落入else分支时统一使用Generic方言始终优先于查询头doc中明确说明这里的方言总是胜过查询头中的target:sql.…参数且没有可以回退到查询头的值——即无法通过查询内声明覆盖compile/2传入的target。4.2 formatSQL 格式化开关format为布尔值控制是否将生成的 SQL 交给格式化器进行多行拆分与缩进美化默认值为true。README 与 doctest 中大量使用signature_comment: false正是为了让输出更简洁、便于断言。4.3 signature_comment签名注释开关signature_comment为布尔值控制是否在生成的 SQL 后附加编译器签名注释默认值为true。以上三个选项的默认值可以在 NIF 侧的 struct 定义中确认native/prql/src/lib.rsdefstruct target: :generic, format: true, signature_comment: true而在 Elixir 侧对应的类型声明位于 lib/prql/native.ex 的PRQL.Native.CompileOptions其t/0类型包含target: target(), format: boolean(), signature_comment: boolean()三个字段。Rust 侧将CompileOptions转换为prqlc::Options的实现impl FromCompileOptions for prqlc::Options进一步印证了选项的传递链路format、target、signature_comment直接映射到prqlc::Options对应字段同时固定设置display: prqlc::DisplayOptions::Plain即不做额外的展示层格式化。五、错误处理与 compile!/25.1 错误返回结构当查询无法编译时compile/2返回{:error, reason}其中reason是一个JSON 字符串。测试用例 prql_test.exs 给出了完整的错误 JSON 结构示例——对于查询invalid返回的错误 JSON 包含inner数组每个元素含kind、code、reason、hints、span、display带源码标注的可读错误信息与location起始/结束行列坐标等字段。这得益于 Rust 侧to_result_tuple的实现prqlc::ErrorMessages会被序列化为 JSONe.to_json()作为{:error, json}元组的第二个元素返回。在应用侧你可以用任意 JSON 解码库如Jason解析该错误字符串从中提取span如1:0-7与display字段做进一步展示或定位。5.2 断言式 APIcompile!/2如果希望出错时直接抛出异常而非返回元组可以使用compile!/2spec compile!(binary(), [compile_opts()]) :: binary() def compile!(prql_query, opts \\ []) do case compile(prql_query, opts) do {:ok, result} - result {:error, reason} - raise PRQL.PRQLError, reason end endcompile!/2成功时直接返回 SQL 字符串失败时抛出PRQL.PRQLError异常。异常模块定义在 lib/prql/errors.ex它基于defexception [:message, :error]exception/1回调将message固定为Error compiling PRQL query原始错误 JSON 存放在:error字段中。六、编译器管线的逐层 API除了端到端的compile/2绑定还暴露了 PRQL 编译器内部三条管线的逐步调用函数对应prqlc库的核心编译流程Elixir 函数阶段输入输出prql_to_pl/1PRQL → PL ASTJSONPRQL 查询字符串{:ok, pl_json}或{:error, json}pl_to_rq/1PL ASTJSON → RQJSONPL 的 JSON 表示{:ok, rq_json}或{:error, json}rq_to_sql/1RQJSON → SQLRQ 的 JSON 表示{:ok, sql}或{:error, json}每个函数都有对应的!版本prql_to_pl!/1、pl_to_rq!/1、rq_to_sql!/1语义与compile!/2一致成功返回字符串失败抛出PRQL.PRQLError。Rust 侧实现native/prql/src/lib.rs揭示了这些函数与prqlc库的对应关系prql_to_plprqlc::prql_to_pl解析出 PL AST 后再经prqlc::json::from_pl序列化为 JSONpl_to_rq先prqlc::json::to_pl反序列化 PL JSON经prqlc::pl_to_rq生成 RQ再由prqlc::json::from_rq输出 JSONrq_to_sql先prqlc::json::to_rq反序列化 RQ JSON再调用prqlc::rq_to_sql生成 SQL——代码注释也指出此处目前只使用默认 Options。这套分层 API 对需要自定义编译管线例如在 PL/RQ 层做分析或转换的 Elixir 开发者非常有用可以嵌入自己的中间处理步骤。七、架构原理Elixir 如何调用 Rust 编译器绑定采用标准的 Rustler NIF 架构整体数据流如下Elixir 调用层lib/prql.ex 的PRQL模块将用户参数结构化为PRQL.Native.CompileOptions调用PRQL.Native.compile/2等 NIF 函数NIF 占位层lib/prql/native.ex 使用use Rustler, otp_app: :prql声明 NIF 宿主模块。未加载 NIF 时各函数返回:erlang.nif_error(:nif_not_loaded)保证模块在无原生库环境下仍可加载Rust 实现层native/prql/src/lib.rs 通过#[rustler::nif]标注四个导出函数并以rustler::init!(Elixir.PRQL.Native)注册到名为Elixir.PRQL.Native的模块返回值编码Rust 侧把ResultString, prqlc::ErrorMessages统一转换为Response一个NifTuple包含:ok/:error原子与结果字符串映射为 Elixir 的{:ok, binary()} | {:error, binary()}元组。值得注意的实现细节Rust 侧CompileOptions通过#[derive(NifStruct)]与#[module PRQL.Native.CompileOptions]声明与 Elixir struct 的映射关系因此 Elixir 侧struct(CompileOptions, opts)生成的 struct 可以直接作为 NIF 参数传递。另外该 crate 在wasm目标下被显式排除#![cfg(not(target_family wasm))]表明它面向原生环境运行。八、开发与测试流程README 的 Development 一节给出了本地开发的三个标准步骤mix deps.get # 安装 Elixir 依赖 mix compile # 编译工程含 Rust NIF mix test # 运行测试测试工程包含 test/prql_test.exs 与 test/test_helper.exs。其中测试覆盖了两类核心场景成功路径PRQL.compile(from customers, signature_comment: false)断言其输出与预期 SQL 完全一致错误路径PRQL.compile(invalid, ...)断言返回的{:error, json}经Jason.decode后与预期的错误结构逐字段相等。此外prql_test.exs中的doctest PRQL会直接执行PRQL模块doc中的 doctest 示例确保文档中的用法示例持续可验证。NIF 的构建说明见 native/prql/README.mdNIF 会随项目一起编译并自动加载进PRQL.Native模块。九、当前状态与未来规划绑定 README 明确标注我们正处于 Elixir 绑定的早期开发阶段We are in the early stages of developing Elixir bindings。从 web/book/src/project/bindings/README.md 的分级看Elixir 绑定当前属于Unsupported层级功能可正常工作但尚未满足 Supported 所需的条件有维护者、覆盖核心编译函数及对应测试、发布到语言官方包仓库、在Taskfile.yaml提供开发环境引导脚本等。README 提及的未来工作包括发布预编译产物届时 Elixir 项目将无需本地 Rust 工具链即可直接使用 PRQL 编译能力。在此之前任何使用该绑定的 Elixir 项目都依赖 Rust 工具链与仓库内prqlccrate 的本地编译。十、小结本文围绕 PRQL 的 Elixir 绑定完整覆盖了从依赖安装、PRQL.compile/2基本用法、三大编译选项target/format/signature_comment语义、错误处理与compile!/2、编译器逐层 API到 Rustler NIF 桥接层源码剖析与开发测试流程的全部内容。你可以基于 prqlc/bindings/elixir/lib/prql.ex 的公开 API 直接集成也可以参考 native/prql/src/lib.rs 理解底层调用链从而在 Elixir 项目中获得完整的 PRQL 编译能力。赞分享后端【免费下载链接】prqlPRQL is a modern language for transforming data — a simple, powerful, pipelined SQL replacement项目地址https://gitcode.com/gh_mirrors/pr/prql点击查看免费下载相关推荐PRQL Elixir Bindings在 Elixir 中编译 PRQL 查询为 SQL 的完整指南PRQL Elixir Bindings在 Elixir 中编译 PRQL 查询为 SQL 的完整指南 PRQLPipelined Relational Q后端使用 prql-php通过 PHP FFI 调用 PRQL 编译器将 PRQL 查询编译为 SQL使用 prql php通过 PHP FFI 调用 PRQL 编译器将 PRQL 查询编译为 SQL PRQLPipelined Relational Que后端PRQL PHP 绑定指南使用 prql-php 通过 FFI 将 PRQL 编译为 SQLPRQL PHP 绑定指南使用 prql php 通过 FFI 将 PRQL 编译为 SQL prql php 是 PRQL 编译器在 PHP 生态中的官方绑后端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Captura 命令行安装 FFmpeg 全解析:`captura-cli ffmpeg --install` 的使用与底层原理

Captura 命令行安装 FFmpeg 全解析:`captura-cli ffmpeg --install` 的使用与底层原理

桌面应用屏幕录制音视频 【免费下载链接】Captura Capture Screen, Audio, Cursor, Mouse Clicks and Keystrokes 项目地址: https://gitcode.com/gh_mirrors/ca/Captura 点击查看 免费下载 本篇技术指南聚焦 Captura 开源截屏/录屏项目(当前仓库 gh_mi…

2026/9/23 23:22:44 阅读更多 →
疫情舆情情感分析实战:从pandas解析到朴素贝叶斯建模

疫情舆情情感分析实战:从pandas解析到朴素贝叶斯建模

简介:这是一份面向自然语言处理与舆情分析方向学习者、研究者的疫情情感分析完整项目,围绕2020年疫情期间人民日报与微博等平台话题数据,实现情感极性的两分类分析。资源整合了毕业论文文档、Python项目源码与多格式实验数据,共20…

2026/9/23 23:22:44 阅读更多 →
Python大熊猫互动拍照系统:姿态估计与图像融合技术实战解析

Python大熊猫互动拍照系统:姿态估计与图像融合技术实战解析

简介:这是一套面向毕业设计及AI图像处理学习的Python大熊猫主题互动拍照系统源码。项目围绕人工智能视觉技术,实现了动作识别、人像动漫化、风格迁移、熊猫贴纸合成、视频融合及定时拍照等完整功能,适合需要完成课程设计、毕业设计或希望实战…

2026/9/23 23:22:44 阅读更多 →

最新新闻

Windows系统安装全指南:从U盘启动盘制作到UEFI/GPT分区方案

Windows系统安装全指南:从U盘启动盘制作到UEFI/GPT分区方案

不管是给老电脑续命,还是给新装的机器做首次引导,Windows系统的安装都属于那种“看着简单,做起来全是细节”的活儿。我前前后后帮同事、朋友装了不下几十台机器,自己也因为手贱删错分区、改了引导方式导致安装失败过好多次&#x…

2026/9/24 0:00:20 阅读更多 →
齿轮箱故障诊断中的传递路径分析:原理、Matlab实现与工程应用

齿轮箱故障诊断中的传递路径分析:原理、Matlab实现与工程应用

前阵子有朋友拿来一组齿轮箱振动数据,说频谱图上能看到好几个啮合频率边带,但就是说不清振动到底是从啮合点直接传出来的,还是先传到轴承、再经过箱体共振放大出来的。这个问题其实特别典型——齿轮箱故障诊断里,传感器只能装在箱…

2026/9/24 0:00:20 阅读更多 →
C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

第一次在项目里被反射卡住,是在一个老旧的WinForms模块里:几十个类依赖PropertyChanged通知,运行时反射读属性、发通知,每次启动慢半拍不说,一上.NET Native/AOT裁剪模式几乎全面崩盘。后来我把这段逻辑全部改成C#源生…

2026/9/24 0:00:19 阅读更多 →
单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

简介:一份基于单细胞RNA测序数据的细胞类型注释算法研究Python毕业设计源码,针对计算机相关专业正在做毕设或需要项目实战的学习者,可用于课程设计与期末大作业。项目代码完整、经导师指导评审通过,可直接运行,覆盖数据…

2026/9/24 0:00:19 阅读更多 →
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为…

2026/9/24 0:00:19 阅读更多 →
水下生物目标检测实战:YOLO工程与PyTorch训练推理全流程解析

水下生物目标检测实战:YOLO工程与PyTorch训练推理全流程解析

简介:面向水下生物目标检测场景,这份基于Python与PyTorch的深度学习资源包,整合了YOLO模型训练与推理所需的数据集、脚本及预训练权重,适合有一定深度学习基础、希望快速上手目标检测项目的开发者。资源共1830个文件,压…

2026/9/23 23:59:18 阅读更多 →

日新闻

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为…

2026/9/24 0:00:19 阅读更多 →
单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

简介:一份基于单细胞RNA测序数据的细胞类型注释算法研究Python毕业设计源码,针对计算机相关专业正在做毕设或需要项目实战的学习者,可用于课程设计与期末大作业。项目代码完整、经导师指导评审通过,可直接运行,覆盖数据…

2026/9/24 0:00:19 阅读更多 →
C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

第一次在项目里被反射卡住,是在一个老旧的WinForms模块里:几十个类依赖PropertyChanged通知,运行时反射读属性、发通知,每次启动慢半拍不说,一上.NET Native/AOT裁剪模式几乎全面崩盘。后来我把这段逻辑全部改成C#源生…

2026/9/24 0:00:19 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/23 4:55:02 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/23 4:49:06 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/23 9:53:41 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/23 9:53:40 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/23 9:53:40 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/23 9:53:40 阅读更多 →