PRQL 官方语言绑定全解析:Supported / Unsupported / Nascent 三级生态与 prqlc 核心 API 实践指南
2026/9/23 16:03:56 网站建设 项目流程

PRQL 官方语言绑定全解析:Supported / Unsupported / Nascent 三级生态与 prqlc 核心 API 实践指南

【免费下载链接】prqlPRQL is a modern language for transforming data — a simple, powerful, pipelined SQL replacement项目地址: https://gitcode.com/gh_mirrors/pr/prql

导读

本文以 PRQL 仓库中 Bindings 索引文档 为骨架,系统梳理 PRQL 编译器prqlc面向多语言生态的绑定策略与治理标准:从 Supported(JavaScript、Python、R、Rust)、Unsupported(Java、Elixir、C)到 Nascent(.NET、PHP)的三级分类,到各绑定包的安装方式、核心函数签名、错误处理与编译选项,再到仓库统一的命名规范。读完本文,你将掌握每个绑定的真实用法、它们背后的编译管线(prql_to_plpl_to_rqrq_to_sql),以及如何在你的项目里快速接入 PRQL。

一、绑定的三级生态:一张图看懂维护边界

PRQL 的编译器核心用 Rust 编写,为了让其他语言的使用者也能编译 PRQL 查询,官方维护了多个语言绑定。这些绑定并非一刀切,而是按成熟度分为三档,每档对应不同的维护承诺与 API 稳定性保证:

级别要求当前绑定
Supported(受支持)有专门维护者;实现了核心编译函数;对这些函数有测试覆盖;已发布到该语言的标准包仓库;在 Taskfile.yaml 中有可引导开发环境的脚本;代码风格检查工具(linter / formatter)已接入 pre-commit 或 MegaLinterJavaScript、Python、R、Rust
Unsupported(不受支持)功能可用,但不满足上述全部标准;编译器 API 变更不做门禁(gate);一旦失效会被降级为 NascentJava、Elixir、prqlc-c(C 绑定)
Nascent(萌芽期)仍在开发中,可能尚未完全可用.NET、PHP

从 Bindings 索引文档 可以看到一个关键治理细节:Supported 级别的绑定大多位于主 PRQL 仓库中,任何对编译器 API 的改动都必须同步保证这些绑定兼容——"We gate any changes to the compiler's API on compatible changes to the bindings"。这意味着只要你的语言绑定处于 Supported 级,编译器升级时你的使用方式不会突然失效。而 Unsupported 级绑定则没有这道门禁,属于"能用但不保证"的状态,若损坏会被降级到 Nascent。

二、核心编译管线:所有绑定共享的同一套 API

无论哪个语言绑定,其背后调用的都是同一个 Rust 编译器prqlc。在 prqlc/prqlc/src/lib.rs 中可以找到绑定必须实现的五个核心函数(也即 Supported 绑定要求的 "core compile functions"):

函数作用源码位置
compile(prql, options)将 PRQL 查询直接编译为 SQL 字符串lib.rs#L189
prql_to_pl(prql)将 PRQL 解析为 PL AST(PipeLine AST)lib.rs#L371
pl_to_rq(pl)将 PL 解析、降级为 RQ AST(Relational Query)lib.rs#L383
rq_to_sql(rq, options)将 RQ AST 生成为最终 SQLlib.rs#L399
pl_to_prql(pl)将 PL AST 重新格式化为 PRQL 文本(用于格式化/美化)lib.rs#L404

因此,各语言绑定暴露的 API 高度一致:要么是"一把梭"的compile,要么是分段式流水线prql_to_pl/pl_to_rq/rq_to_sql,后者方便你介入中间环节做自定义处理(比如检查中间 AST、注入优化)。compile本质上是这三步的串联封装,这是理解下面所有语言示例的共同前提。

三、Supported 绑定详解

3.1 JavaScript / TypeScript(prqlcnpm 包)

JavaScript 绑定源码位于 prqlc/bindings/js,通过 WebAssembly 在 Node.js、浏览器和打包器环境中运行。

安装与基础用法

npm install prqlc

Node.js 中的直接调用:

const prqlc = require("prqlc"); const sql = prqlc.compile(`from employees | select first_name`); console.log(sql);

多行查询同样支持:

const prqlc = require("prqlc"); const sql = prqlc.compile(` from employees select first_name `); console.log(sql);

编译选项CompileOptions支持指定目标方言、是否格式化输出、是否附加签名注释:

const opts = new prqlc.CompileOptions(); opts.target = "sql.mssql"; opts.format = false; opts.signature_comment = false; const sql = prqlc.compile(`from employees | take 10`, opts); console.log(sql);

浏览器端(ES Module 直接加载 WebAssembly)

<html> <head> <script type="module"> import init, { compile } from "./dist/web/prqlc_js.js"; await init(); const sql = compile("from employees | select first_name"); console.log(sql); </script> </head> <body></body> </html>

框架或打包器场景(如 Vite、Webpack):

import { compile } from "prqlc/dist/bundler"; const sql = compile(`from employees | select first_name`); console.log(sql);

暴露的完整函数签名(来自 prqlc/bindings/js/README.md):

function compile(prql_query: string, options?: CompileOptions): string; function prql_to_pl(prql_query: string): string; function pl_to_prql(pl_json: string): string; function pl_to_rq(pl_json: string): string; function rq_to_sql(rq_json: string): string;

可见 JS 绑定完整镜像了第二节中的 Rust 核心管线。

错误处理:编译失败时抛出错误,其message是一个 JSON 数组字符串,包含结构化错误信息(类型、错误码、原因、建议、源码位置等):

interface ErrorMessage { kind: "Error" | "Warning" | "Lint"; code: string | null; reason: string; hints: string[]; span: [number, number] | null; display: string | null; location: SourceLocation | null; } interface SourceLocation { start: [number, number]; // [行号, 列号],均从 0 开始 end: [number, number]; }

捕获方式:

try { const sql = prqlc.compile(`from employees | foo first_name`); } catch (error) { const errorMessages = JSON.parse(error.message).inner; console.log(errorMessages[0].display); console.log(errorMessages[0].location); }

本地开发npm run build会同时产出 Node、bundler、web 三种目标的dist产物;npm test运行测试。若只想快速迭代,可用PROFILE=dev npm run build跳过 WASM 优化以缩短构建时间。实现上,JS 绑定基于wasm-pack生成,并在其上包了一层 npm 构建脚本,以便用单个包同时分发nodebundlerweb三个目标。

3.2 Python(prqlcPyPI 包)

Python 绑定对应 crate 名为prqlc-python(见 prqlc/bindings/prqlc-python),发布到 PyPI 的包名同样是prqlc,基于pyo3实现,底层编译逻辑完全复用 Rust 编译器。

安装与基础用法

pip install prqlc
import prqlc prql_query = """ from employees join salaries (==emp_id) group {employees.dept_id, employees.gender} ( aggregate { avg_salary = average salaries.salary } ) """ options = prqlc.CompileOptions( format=True, signature_comment=True, target="sql.postgres" ) sql = prqlc.compile(prql_query) sql_postgres = prqlc.compile(prql_query, options)

暴露的 API 全貌(含默认值,来自 prqlc/bindings/prqlc-python/README.md):

def compile(prql_query: str, options: Optional[CompileOptions] = None) -> str: """Compiles a PRQL query into SQL.""" ... def prql_to_pl(prql_query: str) -> str: """Converts a PRQL query to PL AST in JSON format.""" ... def pl_to_prql(pl_json: str) -> str: """Converts PL AST as a JSON string into a formatted PRQL string.""" ... def pl_to_rq(pl_json: str) -> str: """Resolves and lowers PL AST (JSON) into RQ AST (JSON).""" ... def rq_to_sql(rq_json: str, options: Optional[CompileOptions] = None) -> str: """Converts RQ AST (JSON) into a SQL query.""" ... class CompileOptions: def __init__( self, *, format: bool = True, target: str = "sql.any", signature_comment: bool = True, ) -> None: ... # format:是否对生成的 SQL 进行美化排版(默认 True) # target:目标方言,默认 "sql.any",即由查询头部的 target 参数决定方言; # 可用 get_targets() 查看全部可选方言 # signature_comment:是否在 SQL 末尾附加编译器签名注释(默认 True) def get_targets() -> list[str]: """List available target dialects for compilation.""" ...

get_targets()CompileOptions在 prqlc/bindings/prqlc-python/src/lib.rs 中有对应实现:convert_options会将 Python 侧的CompileOptions转换为 Rust 编译器内部的prqlc_lib::Options,再交给prqlc_lib::compile执行。这也印证了"绑定只是薄壳,真正干活的是 Rust 编译器"这一架构事实。

调试模块prqlc.debug:额外提供列级血缘(lineage)分析能力,属于实验性 API,可能不稳定:

from prqlc import debug def prql_lineage(prql_query: str) -> str: """Computes a column-level lineage graph from a PRQL query. 返回 JSON 字符串,详见 `prqlc debug lineage` CLI 命令。""" ... def pl_to_lineage(pl_json: str) -> str: """Computes a column-level lineage graph from PL AST (JSON).""" ...

开发流程:项目使用uv管理依赖,uv run pytest运行测试、uv run ty check做类型检查,也可用task test。该包未被 pyprql、dbt-prql 等项目消费,因而保持较活跃的迭代。

3.3 Rust(prqlccrate)

Rust 绑定就是编译器本身。文档指引读者直接查阅prqlccrate 的 API 文档(rust.md),仓库内的核心入口即 prqlc/prqlc/src/lib.rs。在 Rust 项目中通过 Cargo 引入:

[dependencies] prqlc = "…" # 以 crates.io 上发布的最新版本为准

然后即可调用prqlc::compile(prql, &options)prqlc::prql_to_pl(...)prqlc::pl_to_rq(...)prqlc::rq_to_sql(...)等函数(compiler_version()位于 lib.rs#L142)。Rust 绑定天然与编译器同步演进,是其他所有绑定验证 API 兼容性的基准。

3.4 R(prqlr

R 绑定的包名为prqlr(见 r.md),安装在 CRAN 上发布,从文档可知由社区维护者 @eitsupi 在独立的 PRQL/prqlc-r 仓库中维护。

安装

install.packages("prqlr")

prqlr的一大特色是内置了knitr(R Markdown 与 Quarto)集成:你可以在 R Markdown / Quarto 文档中直接嵌入 PRQL 转换结果,让数据分析报告里的 SQL 生成过程可复现、可展示。

四、Unsupported 绑定详解

4.1 Java(prql-java

Java 绑定通过JNI调用 Rust 库(源码见 prqlc/bindings/java),在org.prql.prql4j.PrqlCompiler上暴露三个 native 方法:

public static native String toSql(String query, String target, boolean format, boolean signature) throws Exception; public static native String toJson(String query) throws Exception; public static native String format(String query) throws Exception;
  • target:方言名,如sql.mysql(完整列表见 Target and version);
  • format:是否对 SQL 进行美化排版;
  • signature:是否在末尾附加-- Generated by PRQL compiler version:...注释。

该绑定仍处于早期阶段,需要本地编译、尚未发布到 Maven。本地安装到本地 Maven 仓库

./mvnw install -Dgpg.skip=true

注:java/pom.xmlmaven-gpg-plugin绑定在verify阶段,而install会执行该阶段,因此需要-Dgpg.skip=true跳过签名。jar 不内置 native 库,只有deployprofile 的cross.sh会填充src/main/resources,所以消费者需要把工作区target/release下的libprql_java放到java.library.path上。

依赖坐标(<version>与 PRQL 发布版本独立维护):

<dependency> <groupId>org.prqllang</groupId> <artifactId>prql-java</artifactId> <version>0.5.2</version> </dependency>

使用示例

import org.prql.prql4j.PrqlCompiler; class Main { public static void main(String[] args) throws Exception { String sql = PrqlCompiler.toSql("from my_table", "sql.mysql", true, true); System.out.println(sql); } }

运行时必须把 native 库加入库路径,否则静态初始化会失败并报libprql_java-linux64.so was not found inside JAR

java -Djava.library.path=/path/to/prql/target/release Main

4.2 Elixir(prql

Elixir 绑定通过Rustler接入 Rust 编译器(见 prqlc/bindings/elixir)。安装(依赖prql ~> 0.1.0):

def deps do [ {:prql, "~> 0.1.0"} ] end

基础用法(交互式验证):

iex> 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"}

从示例可见:PRQL.compile/2返回{:ok, sql}元组,且支持通过target: :mssql指定方言(这里展示了 MSSQL 的OFFSET/FETCH分页写法)。目前使用需要本地编译 Rust crate:mix deps.getmix compilemix test。未来计划发布预编译产物,让 Elixir 项目无需 Rust 工具链即可使用。

4.3 C / C++ / Zig(prqlc-c

prqlc-c将 PRQL 编译为可供 FFI 调用的 C 库(同时生成.a静态库与.so动态库),任何支持 FFI 的语言(例如 Golang)都可以嵌入使用。完整 FFI 接口在 prqlc.h 中有内联文档,C++ 头文件为 prqlc.hpp。

链接方式(以静态库为例,来自 prqlc/bindings/prqlc-c/README.md):

CGO_LDFLAGS="-L/path/to/target/release -lprqlc_c -pthread -ldl -lm" go build

(macOS 上还需追加-framework CoreFoundation。)

示例工程

  • examples/minimal-c/main.c:覆盖compile、自定义Options、错误处理以及分段式prql_to_pl/pl_to_rq入口;
  • examples/minimal-cpp:使用生成的 C++ 头文件的等价流程;
  • examples/minimal-zig:Zig 通过@cImport引入prqlc.h的示例。

标准的链接参数可参考 examples/minimal-c/Makefile。头文件由cbindgen生成,重新生成执行task build-prqlc-c-header即可。

五、Nascent 绑定详解

5.1 .NET(prql-net

.NET 绑定以net10.0库的形式提供(见 prqlc/bindings/dotnet),核心是静态类PrqlCompiler,其CompilePrqlToPlPlToRqRqToSql方法均返回携带Output字符串与Messages列表的Result。尚未发布到 NuGet。

安装:需要将libprqlc_c.so(Linux)、libprqlc_c.dylib(macOS)或libprqlc_c.dll(Windows)与PrqlCompiler.dll一起放入项目bin目录,例如{your_project}/bin/Debug/net10.0/libprqlc_c库在运行时被动态导入。

使用示例

using Prql.Compiler; var options = new PrqlCompilerOptions { Format = false, SignatureComment = false, }; var result = PrqlCompiler.Compile("from employees", options); Console.WriteLine(result.Output);

该绑定当前版本停在 0.1.0,原因是等待prqlc-c更新到最新 API 后再对齐版本号。

5.2 PHP(prql-php

PHP 绑定通过FFI调用prqlc(见 prqlc/bindings/php),提供Compiler类,包含compileprqlToPLplToRQrqToSQL四个方法。尚未发布到 Composer。

安装:需启用 PHP FFI 扩展,在php.ini中设置:

ffi.enable = "true"

使用示例

<?php use Prql\Compiler\Compiler; $prql = new Compiler(); $result = $prql->compile("from employees"); echo $result->output;

开发环境:可以使用 nix flake 建立包含 PHP、ext-ffi 与 Composer 的环境(ext-ffi已在composer.json中声明):

mkdir -p ~/.config/nix echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf nix shell github:loophp/nix-shell#env-php81 --impure

构建与测试task build-php会依次执行 cargo 构建libprqlc_c、将libprqlc_c.*prqlc.h复制进lib;随后task test-php运行测试。代码风格用 PSR12 检查:./vendor/bin/phpcs --standard=PSR12 src tests

六、命名规范:向prqlc-$lang收敛

按 Bindings 索引文档 的说明,PRQL 团队正逐步统一各绑定的命名约定:

  • Rust crate 统一命名为prqlc-$lang(如prqlc-pythonprqlc-c);
  • 各语言包仓库中的发布名在可能的情况下统一为prqlc(如 npm 的prqlc、PyPI 的prqlc)。

这也解释了为什么你在安装时会看到"crate 名"与"包名"不完全一致的现象:Rust crate 用带语言后缀的名字区分,而对外发布的包尽量用不带后缀的prqlc,便于用户记忆和统一文档引用。

七、如何选择与上手:快速决策指南

你的技术栈推荐绑定安装命令 / 方式成熟度
Node.js / 浏览器 / 前端JavaScriptnpm install prqlcSupported
Python / 数据科学Pythonpip install prqlcSupported
Rust 原生项目RustCargo.toml引入prqlcSupported
R / R Markdown / QuartoRinstall.packages("prqlr")Supported
Java / JVMJava本地./mvnw install -Dgpg.skip=trueUnsupported
Elixir / BEAMElixirmix deps.get后本地编译Unsupported
Go / Zig / 任意支持 FFI 的语言prqlc-c链接libprqlc_cUnsupported
.NET / C#.NET拷贝libprqlc_c.*至 bin 目录Nascent
PHPPHP启用ffi.enable后加载Nascent

核心建议

  1. 追求稳定:优先选择 Supported 级绑定,因为它们有维护者、测试覆盖和 API 变更门禁;
  2. 需要中间 AST:无论哪种语言,都优先使用分段式prql_to_pl/pl_to_rq/rq_to_sql接口,方便检查或改写中间表示;
  3. 指定方言:编译前用get_targets()(Python)或查阅 target.md 确认可用方言名,并通过CompileOptions/PrqlCompilerOptionstarget参数传入;
  4. 错误排查:编译报错时优先读取结构化错误字段(kindcodereasonhintslocation),其中的display字段是带标注的代码片段,定位问题最快。

所有绑定的底层能力都来自同一个 Rust 编译器(prqlc/prqlc/src/lib.rs),因此无论你使用哪种语言,PRQL 查询的语法与编译行为都保持一致——学会一种绑定,其他绑定即可举一反三。

【免费下载链接】prqlPRQL is a modern language for transforming data — a simple, powerful, pipelined SQL replacement项目地址: https://gitcode.com/gh_mirrors/pr/prql

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询