WrenAI wren-core 示例指南:用 Rust 从 MDL 语义层到可执行 SQL 的六种实战写法

发布时间:2026/9/13 23:48:54
WrenAI wren-core 示例指南:用 Rust 从 MDL 语义层到可执行 SQL 的六种实战写法 WrenAI wren-core 示例指南用 Rust 从 MDL 语义层到可执行 SQL 的六种实战写法【免费下载链接】WrenAIGenBI (Generative BI) for AI agents, an open-source, governed text-to-SQL through an open context layer that turns natural-language questions into trusted dashboards, charts, and SQL across 20 data sources, such as BigQuery, Snowflake, PostgreSQL, ClickHouse, Amazon Redshift, Databricks and more.项目地址: https://gitcode.com/GitHub_Trending/wr/WrenAI导读本文围绕 core/wren-core/wren-example/README.md 展开讲解 WrenAI 开源仓库中 wren-core 引擎的示例 cratewren-example它是向开发者展示「如何用 Rust 调用 Wren Engine 语义层 API」的最小可运行合集。读完本文你将掌握通过cargo run --example运行这些示例的方法理解 Modeling Definition LanguageMDL在 DataFusion 上的两种语义落地路径——「Unparse 模式生成 SQL」与「LocalRuntime 模式直接执行」——并通过行级访问控制Row Level Access Control与多表关系计算示例建立从语义模型到受控查询的完整认知。示例 crate 概述与工程位置wren-example是 wren-core 工作空间下的一个publish false的示例包见 Cargo.toml其全部示例都以dev-dependencies方式依赖工作空间内的wren-core、datafusion、tokio、env_logger、serde_json与async-trait。这意味着它不参与发布纯粹服务于教学与自测让你不必深入 wren-core 内部实现即可体验语义层 API 的完整调用链。从仓库顶层看wren-core 是 Wren 引擎的语义核心其作用详见 core/wren-core/README.md而本示例目录与sqllogictest、wren-example等 crate 并列共同构成引擎的测试与演示体系。示例依赖的两张核心 CSVorders.csv、customers.csv、order_items.csv实际存放于 sqllogictest/tests/resources/ecommerce/共 692 行样本数据模拟巴西电商订单场景行级访问控制示例则使用 wren-example 自带的 data/company/ 三张表模拟多租户公司数据。如何运行示例README 给出的运行方式非常直接克隆仓库后进入WrenAI/core/wren-core目录用cargo run --example加示例名执行。以datafusion-apply为例git clone https://github.com/Canner/WrenAI.git cd WrenAI/core/wren-core # Run the datafusion_apply example: # ... use the equivalent for other examples cargo run --example datafusion-apply示例命名采用连字符如datafusion-apply、plan-sql、view、calculation-invoke-calculation、to-many-calculation、row-level-access-control这与--example参数一一对应。需要说明两点示例中的 CSV 路径是相对 wren-core 根目录的如sqllogictest/tests/resources/ecommerce/orders.csv因此在 wren-core 目录下运行时无需额外调整若在其它目录运行需保证这些数据文件可被解析到。示例代码会打印原始 SQL 与转换后的 SQL配合env_logger::init()输出的日志可以清晰观察到语义层改写前后的差异这是理解 Wren Engine 工作方式的最快途径。Single Process 入门示例从 MDL 到可查询的 DataFusionREADME 中「Single Process」小节列举了两个核心示例datafusion-apply将 MDL 应用到 DataFusion 以查询本地 CSV与plan-sql基于 DataFusion 的Expr与LogicalPlan生成 SQL。这两个示例正好对应语义层在单进程内的两种消费方式。datafusion-apply把语义层“贴”到本地表上该示例的完整流程位于 examples/datafusion-apply.rs先用SessionContext注册三张 CSV 为datafusion.public.*表再通过AnalyzedWrenMDL::analyze_with_tables(manifest, register)将 manifest 与物理表绑定最后调用transform_sql_with_ctx把面向语义层的 SQL 改写为可直接执行的物理 SQL。核心调用链如下let analyzed_mdl Arc::new(AnalyzedWrenMDL::analyze_with_tables(manifest, register)?); let sql select * from wrenai.public.order_items; let sql transform_sql_with_ctx(ctx, analyzed_mdl, [], HashMap::new().into(), sql) .await?; println!(Wren engine generated SQL: \n{sql});注意这里的表绑定是显式的HashMap的 key 是物理表的全限定名datafusion.public.orders等value 是 DataFusion 的TableProvider。而在analyze之外还有一条仅依赖 manifest 的路径plan-sql、view使用两者对应AnalyzedWrenMDL的两个构造方法见 core/wren-core/core/src/mdl/mod.rsanalyze(manifest, properties, mode)不绑定物理表适合纯 SQL 生成/Unparse 场景analyze_with_tables(manifest, register_tables)绑定本地表适合在本进程内注册 CSV、Parquet 等 DataFusion 数据源并实际执行。datafusion-apply中 manifest 由init_manifest()通过 builder 构建为三个模型声明列ColumnBuilder、主键primary_key、关系列.relationship(orders_order_items)与计算列.calculated(true).expression(orders.customers.state)并用两个ManyToOne关系把orders → customers、orders → order_items连接起来。这正是 MDL 语义层的典型表达模型屏蔽物理表细节关系与计算列承载语义。plan-sql面向目标方言生成 SQLexamples/plan-sql.rs 展示了另一条路径不注册任何 CSV直接AnalyzedWrenMDL::analyze(manifest, ..., Mode::Unparse)后用create_wren_ctx(None, Some(DataSource::BigQuery))创建一个绑定了目标方言的 SessionContext再调用transform_sql_with_ctx得到改写后的 SQL 并打印不执行。它查询的是wrenai.public.orders_model上的计算列customer_state展示语义层如何把对模型的引用解析为真实 SQL。这里有两个值得注意的实现细节create_wren_ctx见 core/wren-core/core/src/mdl/mod.rs在传入DataSource时会注册对应方言的标量函数、聚合函数与窗口函数并默认把时区设为 UTC避免时间戳推断与比较的时区问题不传则注册通用函数集。因此plan-sql示例实际上演示的是「面向 BigQuery 方言生成 SQL」的能力DataSource枚举还包含 PostgreSQL、ClickHouse、Snowflake 等更多选项。Mode::Unparse表示仅改写不执行会启用专门的优化规则optimize_rule_for_unparsing并在改写时保留最贴近目标方言的表达式详见 core/wren-core/core/src/mdl/context.rs。语义层的两种运行模式Unparse 与 LocalRuntimetransform_sql_with_ctx的底层实现见 core/wren-core/core/src/mdl/mod.rs实际上把所有示例统一到了同一条调用链先注册remote_functions再调用apply_wren_on_ctx把 MDL 与模式应用到 SessionContext然后create_logical_plan生成计划并改写。apply_wren_on_ctx内部见 core/wren-core/core/src/mdl/context.rs会做几件关键事把默认 catalog/schema 切换为 MDL 声明的命名空间如wrenai.public、注册 Wren 的WrenTypePlanner、复制 catalog 快照以保证并发调用隔离并按x-wren-timezone设置会话时区。而Mode枚举见 core/wren-core/core/src/mdl/context.rs决定了两类行为Mode行为适用场景LocalRuntime用analyze_rule_for_local_runtime不叠加 Unparse 优化规则在本进程内用 DataFusion 真正执行查询to-many-calculationUnparse用analyze_rule_for_unparsing叠加optimize_rule_for_unparsing只生成目标 SQL交由远程数据库执行plan-sql、view、calculation-invoke-calculation的改写部分理解这一区分后六个示例其实可以用一句话概括它们都在回答如何把 MDL 语义层应用到一段 SQL区别只在于——用哪种模式、绑不绑本地表、面向哪种方言、要不要真正执行。view 示例语义视图的声明与展开examples/view.rs 引入了ViewBuilder在模型之上再声明一个customers_view其statement直接引用模型命名空间select * from wrenai.public.customers_model。查询wrenai.public.customers_view时语义层会把视图引用展开为其声明语句并改写为可执行 SQL。视图的存在让上层应用可以暴露语义化的表而不是让使用者直接面对模型与物理表是 MDL 面向业务隔离的又一手段。该示例同样采用Mode::Unparse只打印改写结果不执行。关系链上的计算列calculation-invoke-calculation 与 to-many-calculation这两个示例是理解计算列如何沿关系传播的最佳教材它们都基于customers → orders → order_items的三级关系链但分别演示了两种语义计算列调用计算列examples/calculation-invoke-calculation.rs 在两个方向上做了验证从customers出发查询totalpricecustomers.totalprice sum(orders.totalprice)而orders.totalprice sum(order_items.price)——计算列totalprice递归调用了另一个计算列totalprice语义层需沿着关系链逐级展开并正确生成 JOIN GROUP BY从order_items出发查询customer_state_cforder_items.customer_state_cf orders.customer_state而orders.customer_state customers.state——同样是计算列引用计算列方向变为从明细向主表回溯。该示例通过analyze_with_tables绑定三张 CSV 并用transform_sql_with_ctx改写后真正执行ctx.sql(transformed)df.show()打印出改写 SQL 与结果表直观展示语义层如何把面向模型的表达式翻译成可运行的 SQL。to-many 关系链上的聚合examples/to-many-calculation.rs 演示的是一对多关系链上的聚合customers通过orders关联到order_items其计算列定义为sum(orders.order_items.price)注意源码注释明确指出 Its a to-many-relationship chain。这段示例的最大价值在于它使用了apply_wren_on_ctx(ctx, analyzed_mdl, ..., Mode::LocalRuntime)把语义层直接应用到 SessionContext随后用普通 SQL 直接查询wrenai.public.customers并得到结果——无需显式调用transform_sql_with_ctx。也就是说一旦语义层以LocalRuntime模式挂载到 DataFusion 上create_wren_ctxapply_wren_on_ctx便足以让引擎自动完成关系展开与聚合改写。行级访问控制多租户 SQL 的安全护栏examples/row-level-access-control.rs 演示如何用 Wren Engine 为多租户应用搭建行级访问控制。它使用wren-example/data/company/下的三张表模拟公司场景tenants租户、users用户含role、department、documents文档含tenant_id、department、created_by、status。关键在 manifest 构建中对documents模型调用add_row_level_access_control.add_row_level_access_control( multitenant, vec![SessionProperty::new_required(session_tenant_id)], tenant_id session_tenant_id, ) .add_row_level_access_control( auth, vec![ SessionProperty::new_optional(session_role, Some(MEMBER.to_string())), SessionProperty::new_required(session_department), SessionProperty::new_required(session_user_id), ], session_role ADMIN OR (department session_department AND (created_by session_user_id OR status PUBLIC)), )随后在调用transform_sql_with_ctx时通过propertiesSessionPropertiesRef即HashMapString, OptionString注入会话属性let mut properties HashMap::new(); properties.insert(session_tenant_id.to_string(), Some(1acdef01-aaaa-aaaa-aaaa-aaaaaaaaaaaa.to_string())); properties.insert(session_department.to_string(), Some(engineering.to_string())); properties.insert(session_user_id.to_string(), Some(1003-u3.to_string())); properties.insert(session_role.to_string(), Some(ADMIN.to_string()));该示例通过ctx.sql(select * from wren.test.documents)验证了两层安全规则租户隔离只能看到本租户文档与基于角色的细粒度授权ADMIN 全量可见MEMBER 只能看本人创建或本部门 PUBLIC 文档。相关实现可对照 access_control.rs 中SessionProperty的解析与条件注入逻辑new_required表示该会话属性必须存在new_optional允许缺省并提供默认值如session_role缺省为MEMBER。这正是 Wren Engine 把安全策略沉淀进语义层而非应用层的体现——查询改写阶段即完成过滤物理 SQL 落地前数据已按会话收窄。小结与下一步通过六个示例可以总结出使用 wren-core 语义层 API 的固定套路构建 manifest用ManifestBuilder/ModelBuilder/ColumnBuilder/RelationshipBuilder/ViewBuilder描述模型、列、关系、视图与访问控制分析语义层AnalyzedWrenMDL::analyze纯改写或analyze_with_tables绑定本地表准备上下文SessionContext注册 CSV或create_wren_ctx绑定目标方言也可直接apply_wren_on_ctx挂载语义层改写 SQLtransform_sql_with_ctx(ctx, analyzed_mdl, [], properties, sql)得到可执行 SQL需要执行时用ctx.sql(...)df.show()查看结果。示例所使用的 ecommerce 样本数据位于 sqllogictest/tests/resources/ecommerce/多租户样本位于 wren-example/data/company/均可作为自建实验的素材。如果你希望把语义层能力接入更大体系还可以参考 Python 绑定 wren-core-py 与sqllogictest的端到端用例core/wren-core/README.md它们与这些示例共享同一套 MDL 语义模型。【免费下载链接】WrenAIGenBI (Generative BI) for AI agents, an open-source, governed text-to-SQL through an open context layer that turns natural-language questions into trusted dashboards, charts, and SQL across 20 data sources, such as BigQuery, Snowflake, PostgreSQL, ClickHouse, Amazon Redshift, Databricks and more.项目地址: https://gitcode.com/GitHub_Trending/wr/WrenAI创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考