如何提取PostgreSQL查询语句中的所有内置函数?
提取PostgreSQL查询中所有内置函数的解决方案
你遇到的问题是因为current_user、current_schema这类PostgreSQL系统函数属于无参数内置函数,在SQL解析树中对应的节点类型和普通函数不同,你的原代码只覆盖了Function和TableFunction节点,所以无法捕获它们。以下是基于Apache Calcite(你使用的TablesNamesFinder来自该库)的修正方案:
修正后的代码
import org.apache.calcite.sql.*; import org.apache.calcite.sql.util.TablesNamesFinder; import java.util.*; // 存储提取到的函数名 Set<String> functionNames = new HashSet<>(); TablesNamesFinder tablesNamesFinder = new TablesNamesFinder() { // 捕获所有带括号的函数调用(包括无参数的current_user()) @Override public void visit(SqlCall call) { SqlOperator operator = call.getOperator(); if (operator instanceof SqlFunction) { String funcName = operator.getName().toLowerCase(); functionNames.add(funcName); } super.visit(call); } // 处理表函数(如VALUES()) @Override public void visit(SqlTableFunction tableFunction) { String funcName = tableFunction.getFunction().getName().toLowerCase(); functionNames.add(funcName); super.visit(tableFunction); } // 捕获省略括号的PostgreSQL系统函数(如current_user、current_schema) @Override public void visit(SqlIdentifier id) { String idName = id.getName().toLowerCase(); // 可根据需求扩展PostgreSQL内置系统函数列表 Set<String> pgSystemFunctions = new HashSet<>(Arrays.asList( "current_user", "current_schema", "current_database", "current_timestamp", "now", "version", "current_role" )); if (pgSystemFunctions.contains(idName)) { functionNames.add(idName); } super.visit(id); } };
关键说明
- 覆盖
SqlCall节点:所有带括号的函数调用(包括无参数的current_user())都会被解析为SqlCall,通过SqlOperator可以直接获取函数名。 - 处理
SqlIdentifier节点:PostgreSQL允许无参数函数省略括号,这类函数会被解析为SqlIdentifier,需要通过内置函数列表匹配识别。 - 扩展函数列表:你可以根据PostgreSQL官方文档补充更多系统函数到
pgSystemFunctions集合中,确保覆盖所有需要提取的目标函数。
内容的提问来源于stack exchange,提问作者Mohamed
相关产品推荐
相关产品推荐

