DuckPL为DuckDB引入过程式编程语言原文地址https://blobs.duckdb.org/events/duckdb-developer-meeting-1/duckpl-a-procedural-language-in-duckdb-denis-hirn.pdf在2026年1月30日的DuckDB开发者会议#1上来自蒂宾根大学的Denis Hirn长期DuckDB贡献者介绍了DuckPL——一种为DuckDB打造的原生过程式编程语言旨在填补DuckDB在用户定义函数UDF功能上的关键空白。当前DuckDB UDF的局限性DuckDB目前支持简单的宏MACRO功能CREATEMACROadd(a,b)ASab;但不支持完整的过程式编程CREATEMACRO sequence(n)ASIFn0THENdosomestuffELSEdoother stuffENDIF;现有解决方案如Python、R等外部语言UDF虽然可用但需要外部运行时环境破坏了DuckDB“单文件、零依赖数据库”的核心承诺DuckPL的核心特性DuckPL为DuckDB带来了完整的PL/pgSQL兼容性过程式编程能力简单直观的编程模型CREATEFUNCTIONcollatz(yBIGINT)RETURNSBIGINTAS$$DECLAREstepsBIGINT:0;xBIGINT:y;BEGINWHILEx1LOOPIFx%20THENx :x/2;ELSEx :3*x1;ENDIF;steps :steps1;ENDLOOP;RETURNsteps;END;$$;对比纯SQL实现需要复杂的递归CTEWITHRECURSIVE collatz_cte(x,steps)AS(...)DuckPL让过程式逻辑编写变得直观简单无需掌握高级SQL技巧。技术架构解析双重解析机制DuckPL采用两层解析架构CREATE FUNCTION语句解析扩展DuckDB原有SQL解析器PL/pgSQL函数体解析重用libpg_query库的PL/pgSQL解析器CREATE FUNCTION语句 → libpg_query解析 → AST转换 → DuckPL AST这与DuckDB 2018年构建SQL解析器的方式完全一致保证了技术一致性。统一的内部表示DuckPL ASTDuckPL设计了简洁、语法无关的中间表示IR将所有复杂结构简化为基本构建块FOR/WHILE循环 → LOOP IF BREAK组合CASE语句 → IF语句链游标循环 → 基本循环结构示例转换WHILE counter 10 LOOP counter : counter 1; END LOOP; RETURN counter;转换为DuckPL IRloop { if (counter 10) { break; } let counter counter 1; } emit counter; stop;这种设计带来三大优势简化解释器减少控制流处理复杂度支持多语言前端未来可轻松添加PL/Python、PL/Duck等便于编译优化更容易将DuckPL AST编译为SQL持久化存储DuckPL函数通过专用表duckpl_functions持久化存储CREATETABLEduckpl_functions(function_idBIGINTPRIMARYKEY,function_uuid UUID,function_num_argsINT,function_arg_namesTEXT[],function_arg_typesTEXT[],function_return_typesTEXT[],function_returns_setBOOLEAN,function_nameTEXTNOTNULL,function_srcTEXT,function_bodyBLOB-- 序列化的AST);启动时加载反序列化立即注册到目录中无需重新解析。堆栈驱动的解释器DuckPL采用显式堆栈帧管理而非递归调用状态管理执行可在任意点暂停和恢复无C递归避免栈深度限制和溢出风险完全流式处理结果逐块输出不缓冲全部数据这种设计特别适合流式场景CREATEFUNCTIONinfinite()RETURNSSETOFBIGINTAS$$DECLAREiBIGINT:0;BEGINLOOPi :(i1)%1000;RETURNNEXTi;-- 流式输出ENDLOOP;END$$;对比PostgreSQL会缓冲所有结果导致内存膨胀DuckPL的流式处理能高效配合LIMIT等操作。表达式执行优化通过ExpressionExecutor缓存机制避免每次表达式计算都触发完整SQL管道准备虚拟SELECT语句提取表达式缓存对应的ExpressionExecutor实例针对包含局部变量的DataChunk执行实测带来30倍以上的性能提升。功能支持现状已实现功能标量/表值UDF变量和赋值所有数据类型包括复合类型控制流IF、LOOP、WHILE、FOR、BREAK、CONTINUE、RETURN、RETURN NEXT游标FETCH INTO调试支持RAISE INFO规划中功能聚合/窗口UDF异常处理事务支持COMMIT、ROLLBACKUDF优化器编译为纯SQL利用递归CTE等技术大幅提升性能暂不支持动态SQL可使用query(…)替代高级游标功能SCROLL、MOVE触发器未来愿景与发展路线混合执行架构未来DuckPL将发展为解释与编译混合执行系统PL/SQL输入 → 解析 → AST转换 → 分发器 → [解释器 | SQL编译]交互式编程环境计划提供REPL式CLI体验❯ duckdb D LET y0:: BIGINT;D FOR i IN1..10: LET x(SELECTRANDOM());IF x0.5: LET yy 1;D PRINT y;5技术演进方向现代化语法添加友好型PL语法下一代解析器转向PEG-based PL/pegSQL向量化解释实现向量化执行生产就绪改进错误信息和调试支持总结DuckPL的核心价值兼容性优先为现有PL/pgSQL代码库提供迁移路径Postgres用户几乎无需学习成本与现有工具链立即兼容智能执行引擎基于堆栈的流式解释避免内存膨胀无需外部运行时保持零依赖承诺随数据库一起分发无额外依赖前瞻性设计为自动UDF编译和内联优化奠定基础支持混合执行策略为未来性能飞跃预留空间DuckPL即将开源这将为DuckDB生态系统带来真正的过程式编程能力让用户能在保持DuckDB核心优势的同时享受完整的过程式编程体验。作者Denis Hirn蒂宾根大学GitHubkryonix