尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Metabase Metabot 生成 SQL 查询全解析:create_sql_query 的读模式契约、模型引用语法与底层校验机制

Metabase Metabot 生成 SQL 查询全解析:create_sql_query 的读模式契约、模型引用语法与底层校验机制 Metabase Metabot 生成 SQL 查询全解析create_sql_query 的读模式契约、模型引用语法与底层校验机制【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabaseMetabase 的 AI 助手Metabot / Agent通过create_sql_query工具在内存中创建全新的原生 SQL 查询Native Query。本文以技能文档 create-sql-query.md 为骨架结合仓库中的工具实现、校验逻辑、权限作用域与测试用例系统讲解该工具的参数契约、只读 SQL 规范、Metabase 模型引用语法{{#model_id}}、底层方言校验流程以及与edit_sql_query、replace_sql_query等工具的分工边界。读完你可以完整掌握如何让 Agent 生成合规、可运行、符合权限约束的 SQL 查询。一、create-sql-query 技能在 Agent 体系中的位置在 Metabase 的 Agent 架构中技能Skill是按需加载的任务指令块以 Markdown 文件 YAML frontmatter 的形式存放在 resources/metabot/skills/ 目录下。技能注册表在 skills.clj 中实现load-skills!扫描资源目录解析 frontmatter 得到id、title、description、tools、priority等元数据正文作为:body注入提示词见 skills.clj 的技能 schema 与 skills.clj 的注册逻辑。create-sql-query 技能关联的工具是create_sql_query优先级为50。在 SQL 专属的:sqlprofile 中它被列为always-on 技能内联进系统提示词而非按需加载同时与edit-sql-query、replace-sql-query、ask-for-sql-clarification一起构成 SQL 编辑场景的完整技能集见 profiles.clj。二、何时使用 create_sql_query技能文档明确列出了该工具的使用时机见 create-sql-query.md用户请求 SQL 查询但并非在编辑一个已有查询你想使用 Metabase 模型{{#model_id}}语法或数据表来创建 SQL用户提出新的 SQL 分析或数据探索需求你需要演示某种 SQL 写法或解决方案。关键边界该工具只负责创建新查询不负责修改已有查询。修改已有查询应使用edit_sql_query小范围定向修改或replace_sql_query整体重写对应技能文档 edit-sql-query.md 与 replace-sql-query.md。在源码层面这三者被统一归类为可运行查询生成工具见 tools.clj 中的query-generation-tool-names。三、参数契约三个必填参数技能文档强调database_id、sql_query、title三者缺一不可工具会拒绝任何缺少其中一个参数的调用。这一约束在源码的 Malli schema 中得到了精确印证见 tools/sql.clj(def ^:private create-sql-schema [:map {:closed true} [:database_id :int] [:sql_query :string] [:title :string]])各参数的含义与要求参数类型说明database_idintSQL 要运行的目标数据库 ID可从模型/表的元数据表示metadata representation中获取sql_querystring完整的合法 SQL使用表名或{{#model_id}}模板语法引用模型titlestring简短、人性化的查询名称当查询以结果卡片形式交付时会显示在结果上方title并非可有可无的装饰——它直接参与结果卡片result card的渲染。包装层 sql.clj 中工具成功返回后会通过streaming/viz-part携带:title和:query将查询以可视化部件的形式流式呈现给用户。另外还有一个变体工具create_sql_query_code_edit工具名同为create_sql_query见 sql.clj当用户正停留在 SQL 编辑器code editor buffer中时它会把新查询直接写入编辑器缓冲区而非以结果卡片交付。两者的底层操作create-sql-query完全相同区别仅在于结果的呈现通道。四、只读契约Metabase 是只读分析平台技能文档规定了一个硬性约束Metabase 是只读分析read-only analytics只能写 SELECT 查询。明确禁止CREATE TABLE/CREATE VIEWINSERT/UPDATE/DELETEALTER/DROP/TRUNCATE这一约定并非仅靠提示词约束。在工具实现层创建查询时会构建原生查询结构lib/native-query并经validate-sql做方言级解析校验在权限层check-native-query-access!要求当前用户对目标数据库拥有:query-builder-and-native级别的建查询权限见 common.clj。测试用例 sql_test.clj 专门验证了对仅有:query-builder无 native权限的数据库调用该工具会被拒绝而对拥有:query-builder-and-native权限的数据库则可以成功——即权限校验是按数据库生效而非按实例全局生效。五、Metabase 模型引用{{#model_id}} 模板语法查询 Metabase 模型Model时模型的完整限定名fully qualified name形如{{#model_id}}。技能文档给出的示例SELECT * FROM {{#5}} AS mymodel要点引用必须带别名如AS mymodel否则引用无效模型的database_id可在模型元数据中获得当模型已经提供了所需的关系时优先复用已有模型而不是手动做表连接。这一语法的来源可以在 llm_shape.clj 的model-fully-qualified-name函数中找到印证模型在 LLM 表示中被格式化为{#id}-slug形式slug 由模型名小写化、非字母数字字符替换为连字符得到与 Python 侧 ai-service 的实现f{{#{self.id}}}-{slug}保持一致。也就是说{{#model_id}}正是 Agent 从模型元数据中读取到的模型引用标识。技能文档还提供了使用模型创建查询的完整语法示例SELECT * FROM {{#model_id}} AS name_alias WHERE condition;关于模板标签还有一处值得注意的实现细节SQL 校验逻辑会对包含{{或[[的 SQL跳过方言解析校验视为包含 Metabase 模板标签不做短路径校验见 validation.clj 的contains-template-tags?判断。六、标识符引用与方言要求技能文档对标识符和 SQL 方言提出三点要求含特殊字符、空格或保留字的列名必须用双引号包裹例如column name、order、group、column_name使用数据表时必须使用全限定表名包含 namespace / schema / catalogSQL 必须与目标数据库的 SQL 引擎兼容——因为工具不会替你改写方言写错方言会直接导致校验失败。第 3 点在实现上最为严格。validate-sql会将目标数据库的 driver 映射到 sqlglot 解析方言再执行同方言转译transpile作为语法校验转译成功才算合法转译失败则返回:valid? false和错误信息见 validation.clj。方言映射表dialect-mapping见 validation.clj覆盖了 PostgreSQL、MySQL/MariaDB、BigQuery、Snowflake、Redshift、Athena映射到 Trino、Presto/Trino/Starburst、ClickHouse、Databricks、SparkSQL、Oracle、SQL ServerTSQL、SQLite 等主流引擎H2 与 Vertica 因 sqlglot 缺乏对应方言或折叠大小写规则不一致而明确跳过校验映射值为nil。七、底层实现从调用到查询结构的完整链路create_sql_query工具的底层操作为create-sql-query实现在 tools/sql/create.clj其完整流程如下记录日志输出database-id与 SQL 长度:sql-length便于审计校验数据库访问validate-database-access见 create.clj先检查数据库是否存在metabot.db/database-exists?不存在则抛 Agent 错误再执行api/read-check :model/Database读取校验——403 视为终止性错误无权限无法通过重试解决404 视为可恢复错误重新列出数据库即可恢复最后调用check-native-query-access!校验 native 查询写入权限方言解析与校验database-id-dialect取得目标方言validate-sql执行语法校验并返回transpiled-sql构建查询结构校验通过时create-native-query通过lib/native-query构造 MBQL 5 原生查询再转换为 legacy MBQL 结构见 create.clj生成查询 IDu/generate-nano-id生成随机的query-id。操作结果的结构定义在 common.clj::action-result包含query-id内存/上下文中的查询 ID、query-content操作后的 SQL 文本、query包裹查询文本的查询 map和database查询所属的数据库 ID::operation-result则总是携带validation-result仅在校验成功时附带action-result。重要事实该工具并不执行 SQL只创建查询。技能文档明确说明 The tool does NOT execute the SQL, it only creates the query。这也与used_tables.clj中对工具输出挖掘表引用的设计一致——它会从create_sql_query/replace_sql_query/edit_sql_query的 tool-output 中递归展开卡片引用、解析原生 SQL 中的表名用于使用追踪见 used_tables.clj。八、失败路径校验错误与权限错误的处理当校验失败时工具不会返回查询而是返回格式化后的失败提示。包装层 sql.clj 的format-validation-error-output会输出 SQL query construction failed.并附上sql-validation-error-instructions包含方言与具体错误信息引导模型修正 SQL 后重试。create_test.clj给出了校验失败的实证用例见 create_test.clj对 PostgreSQL 数据库提交select 123abc 这类语法错误的 SQL会得到:valid? false错误信息以 Invalid expression / Unexpected token. 开头且:dialect返回 driver 名postgres。成功的用例create_test.clj则验证了SELECT 1 as test能正确生成包含query-id、query-content含正确引号的转译后 SQL和type: :native查询结构的返回。权限不足时则抛出带:agent-error?/:terminal-error?标记的异常由metabot.tools.u/handle-agent-error统一转为输出返回给模型见 sql.clj对应测试见 sql_test.clj。九、作用域与能力门控create_sql_query在作用域上受agent:sql:create约束并声明了:permission-write-sql-queries能力见 sql.clj 的工具元数据与 scope.clj 的作用域定义。Metabot 权限系统将用户权限映射为通配作用域拥有:permission/metabot-sql-generation的用户会获得agent:sql:*通配作用域从而覆盖agent:sql:create见 scope.clj 的perm-type-scopes映射。此外create_sql_query属于状态依赖工具state-dependent-tools见 tools.clj会被包装为可访问 agent 内存原子memory atom的版本在:sqlprofile 中它还是终止工具terminal tool——一次成功的create_sql_query调用即视为本轮回答完成无需再强制追加工具调用见 profiles.clj。十、变换用 CTE唯一推荐的写方式由于禁止 DDL/DML任何需要多步骤变换transformation的场景都应使用CTECommon Table Expression。技能文档给出的标准模板WITH step1 AS ( SELECT * FROM {{#model_id}} AS name_alias ), step2 AS ( SELECT ... FROM step1 ) SELECT * FROM step2其中第一步从模型引用开始注意必须带别名后续步骤在前一步结果之上继续加工。这既满足了只读契约又保持了查询的可读性与可维护性是 Agent 在 Metabase 中表达复杂分析逻辑的标准方式。十一、与周边工具的分工协作创建查询只是 SQL 工作流的一环。以create_sql_query为中心Metabase 的 SQL 工具链分工如下工具场景关键参数create_sql_query创建全新查询database_id、sql_query、titleedit_sql_query对已有查询做小范围字符串替换query_id、checklist、edits、titlereplace_sql_query整体重写已有查询query_id、checklist、new_query、titleask_for_sql_clarification请求真正存在结构性歧义时向用户提问question必填、options可选create_chart/edit_chart基于已创建的查询构建图表—技能文档特别提示如果create_chart/edit_chart可用你还可以基于新建的查询构建图表。另外要注意 ask-for-sql-clarification.md 的边界有现成查询就调用create_sql_query交付绝不要把 SQL 塞进澄清问题的question参数。而在创建查询之前Agent 通常需要先了解数据环境read_resource技能read-resource.md提供了metabase://database/{id}/schemas、metabase://model/{id}/fields等 URI 模式用于在写 SQL 之前摸清仓库布局、确认模型结构——这也是 create-sql-query 技能中database_id 可从模型/表表示中获得的前提。十二、最佳实践小结综合技能文档与源码实现使用create_sql_query时应遵循以下实践先探索后书写优先用read_resource/search确认目标数据库、表结构或模型结构获取准确的database_id优先复用模型当现成模型已提供所需关系时用SELECT * FROM {{#model_id}} AS alias引用模型而非手动 join 原始表永远给模型引用加别名{{#model_id}}之后必须AS alias坚持只读只写 SELECT变换一律用 CTE绝不触碰 DDL/DML注意方言SQL 必须适配目标引擎PostgreSQL 用 Postgres 语法、SQL Server 用 TSQL……工具会做同方言转译校验语法错误会被直接拒绝双引号处理特殊标识符列名含空格、特殊字符或保留字时用双引号包裹使用数据表时用全限定表名区分创建与编辑新查询用create_sql_query改已有查询用edit_sql_query小改或replace_sql_query重写提供友好的 title它不仅是必填参数还会显示在结果卡片上方直接决定用户看到的查询名称。【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表