sqlglot
Python库,用于SQL解析和转译,支持多种方言之间的转换。
时间轴 (近 90 天)
在实现表允许列表时,需要先收集exp.CTE的别名并排除,否则每个WITH查询都会被误杀,因为CTE名在语法树中看起来像表。
sqlglot跨版本会重命名节点类,因此应使用hasattr(exp, name)过滤构建元组,并锁定测试过的sqlglot版本,升级时重跑护栏测试。
简单的字符串检查(如sql.strip().lower().startswith('select'))至少会在三种情况下失效:分号链式语句、用CTE藏数据修改语句、以及DuckDB中通过表函数读取文件。
使用sqlglot解析SQL后,应要求语句列表恰好包含一条语句,且根节点类型为exp.Select、exp.SetOperation或exp.Subquery,否则拒绝执行。
遍历整棵语法树(使用tree.walk())并检查禁用节点列表(如Insert、Update、Delete、Merge、Create、Drop等)是必要的,因为数据修改型CTE和SELECT INTO可能隐藏在深层节点中。
执行tree.sql()重新生成的SQL而非原始字符串,可以保证被审查的语法树与实际执行的语句严格对应,避免解析器与执行器理解差异。
推荐流程为先转译,仅在目标引擎执行结果与源不一致时才升级为模型重问。
sqlglot的转译流程是读取源方言生成AST,再按目标方言规则重新序列化。
确定性转译的保证来源于AST到输出的映射是纯函数式的,相同AST永远得到相同文本。
MySQL缺少与Postgres jsonb箭头操作符等价的AST节点,导致转译器只能选择近似的替代表示并静默引入语义偏差。
还有 4 条时间轴事件
全部知识事实 (14)
在实现表允许列表时,需要先收集exp.CTE的别名并排除,否则每个WITH查询都会被误杀,因为CTE名在语法树中看起来像表。
50%待验证sqlglot跨版本会重命名节点类,因此应使用hasattr(exp, name)过滤构建元组,并锁定测试过的sqlglot版本,升级时重跑护栏测试。
50%待验证简单的字符串检查(如sql.strip().lower().startswith('select'))至少会在三种情况下失效:分号链式语句、用CTE藏数据修改语句、以及DuckDB中通过表函数读取文件。
50%待验证使用sqlglot解析SQL后,应要求语句列表恰好包含一条语句,且根节点类型为exp.Select、exp.SetOperation或exp.Subquery,否则拒绝执行。
50%待验证遍历整棵语法树(使用tree.walk())并检查禁用节点列表(如Insert、Update、Delete、Merge、Create、Drop等)是必要的,因为数据修改型CTE和SELECT INTO可能隐藏在深层节点中。
50%待验证执行tree.sql()重新生成的SQL而非原始字符串,可以保证被审查的语法树与实际执行的语句严格对应,避免解析器与执行器理解差异。
50%待验证推荐流程为先转译,仅在目标引擎执行结果与源不一致时才升级为模型重问。
50%待验证sqlglot的转译流程是读取源方言生成AST,再按目标方言规则重新序列化。
50%待验证确定性转译的保证来源于AST到输出的映射是纯函数式的,相同AST永远得到相同文本。
50%待验证MySQL缺少与Postgres jsonb箭头操作符等价的AST节点,导致转译器只能选择近似的替代表示并静默引入语义偏差。
50%待验证确定性转译器只能做符号层面的替换,无法感知schema中的collation配置。
50%待验证sqlglot 的 lineage() 做的是语法层面的静态推断,遇到 SELECT *、动态 SQL 拼接或 UDF 内部逻辑时无法完全还原真实依赖。
50%待验证sqlglot 的 lineage() API 需要 schema 信息才能工作,作者通过连接 Snowflake 并执行 DESCRIBE TABLE 提前获取了表结构。
50%待验证跨平台 SQL 兼容通常通过抽象语法树(AST)转换实现,先将语义映射为方言无关的中间表示(IR),再由方言编译器翻译为目标数据库原生 SQL
50%