开发者社区> 问答> 正文

SchemaStatVisitor 解析query 语句,保留 * 信息

做sql 列权限校验,需要知道所有查询的列,例如这个sql: select * from table1 a left outer join table2 b on a.id=b.id 会读取两个表的所有列,columns中能够加上table1.* , table2.*

原提问者GitHub用户melin

展开
收起
山海行 2023-07-05 19:57:33 203 0
4 条回答
写回答
取消 提交回答
  • 您可以使用SchemaStatVisitor来解析SQL查询语句,并保留星号(*)的信息。

    SchemaStatVisitor是Druid中提供的一个访问者模式的工具,用于解析和遍历SQL语句的结构。通过扩展SchemaStatVisitor类并覆盖相应的方法,您可以在解析SQL时获取列、表等信息。

    以下是一个示例代码段,展示了如何使用SchemaStatVisitor解析SQL查询语句,并保留星号(*)的信息:

    import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;
    import com.alibaba.druid.sql.parser.SQLParserUtils;
    import com.alibaba.druid.sql.parser.SQLStatementParser;
    import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
    import com.alibaba.druid.util.JdbcConstants;
    
    public class QueryParserExample {
        public static void main(String[] args) {
            String sql = "SELECT * FROM table1 a LEFT OUTER JOIN table2 b ON a.id=b.id";
    
            SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, JdbcConstants.MYSQL);
            SchemaStatVisitor visitor = new MySqlSchemaStatVisitor();
            
            parser.parseStatementList().forEach(statement -> statement.accept(visitor));
    
            // 获取所有表名和列名
            System.out.println("Tables: " + visitor.getTables());
            System.out.println("Columns: " + visitor.getColumns());
            
            // 获取包含星号(*)的表名和列名
            visitor.visit(new MySqlSchemaStatVisitor.VisitorFeature() {
                @Override
                public void visit(SchemaStatVisitor visitor) {
                    if (visitor instanceof MySqlSchemaStatVisitor) {
                        MySqlSchemaStatVisitor mysqlVisitor = (MySqlSchemaStatVisitor) visitor;
                        System.out.println("Tables with *: " + mysqlVisitor.getAliasMap());
                        System.out.println("Columns with *: " + mysqlVisitor.getSelectItemCounts());
                    }
                }
            });
        }
    }
    

    在上述示例中,我们使用MySqlSchemaStatVisitor作为SchemaStatVisitor的实现,来解析MySQL语句。您可以根据具体的数据库类型选择相应的SchemaStatVisitor实现。

    通过访问visitor的getTables()方法和getColumns()方法,您可以获取所有表名和列名的信息。而对于包含星号(*)的表名和列名,您可以使用MySqlSchemaStatVisitor的getAliasMap()方法和getSelectItemCounts()方法来获取。

    请注意,这只是一个简单的示例代码,您可以根据需要进行适当的调整和扩展,以满足您的具体需求。

    2023-07-30 15:17:02
    赞同 展开评论 打赏
  • 北京阿里云ACE会长

    果您需要在SQL执行时进行列权限校验,可以在SQL中使用完整的列名,而不是使用通配符*。这样,您可以明确指定要查询的列,并进行列级别的权限校验。

    对于您提到的示例SQL语句,您可以明确指定要查询的列,例如:

    stylus
    Copy
    SELECT a.id, a.column1, a.column2, b.column1 AS b_column1, b.column2 AS b_column2
    FROM table1 a
    LEFT OUTER JOIN table2 b ON a.id=b.id
    在这个SQL语句中,我们明确指定了要查询的列,并使用了表别名来区分不同表格的列。这样,您可以对每个列进行权限校验,而不是对整个表格进行权限校验。

    如果您需要查询所有列,但仍然需要进行列级别的权限校验,您可以使用类似于您提到的通配符的方式,并带上表别名,例如:

    Copy
    SELECT a., b.
    FROM table1 a
    LEFT OUTER JOIN table2 b ON a.id=b.id
    在这个SQL语句中,我们使用了通配符来查询所有列,但是同时带上了表别名,以便进行列级别的权限校验。请注意,这种方式可能会导致性能问题,因为查询结果将包含所有列,而不是仅包含必要的列。因此,建议您明确指定要查询的列,以便提高性能并进行列级别的权限校验。

    2023-07-30 14:37:25
    赞同 展开评论 打赏
  • 更好的解决方案是在代码中进行校验,根据查询的表和列名进行验证,如果列名不在允许的范围内,就抛出异常。具体实现方式可以使用ORM框架,例如Hibernate,使用注解或者XML配置文件来限制列名。

    2023-07-11 09:59:21
    赞同 展开评论 打赏
  • 问题已修复,请用新版本 https://github.com/alibaba/druid/releases/tag/1.1.14

    原回答者GitHub用户wenshao

    2023-07-06 11:15:50
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
神龙云服务器产品及技术深度解析 立即下载
弹性创造价值:基于ECS的最佳性价比实践解析 立即下载
又快又稳:阿里云下一代虚拟交换机解析 立即下载

相关镜像