首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用JSqlParser完全解析where子句

用JSqlParser完全解析where子句
EN

Stack Overflow用户
提问于 2017-10-17 22:16:41
回答 2查看 5K关注 0票数 3

我希望使用JSqlParser完全、简洁地解析SQL子句。很容易将其解析为单个条件语句,如下所示

代码语言:javascript
复制
String whereClause = "a=3 AND b=4 AND c=5";
Expression expr = CCJSqlParserUtil.parseCondExpression(whereClause);
expr.accept(new ExpressionVisitorAdapter() {

    @Override
    public void visit(AndExpression expr) {
        if (expr.getLeftExpression() instanceof AndExpression) {
            expr.getLeftExpression().accept(this);
        } else if ((expr.getLeftExpression() instanceof EqualsTo)){
            System.out.println(expr.getLeftExpression());
        }
        System.out.println(expr.getRightExpression());
    }
 });

它将产生产出:

代码语言:javascript
复制
a=3
b=4
c=5

我想要的是获取每个单独表达式的左侧、操作符和右侧,这样我就可以将这些值放入一些现有的过滤器对象中。

我知道您可以为每种类型的操作符重写访问函数,如下所示:

代码语言:javascript
复制
expr.accept(new ExpressionVisitorAdapter() {

@Override
public void visit(AndExpression expr) {
    if (expr.getLeftExpression() instanceof AndExpression) {
        expr.getLeftExpression().accept(this);
    } else if ((expr.getLeftExpression() instanceof EqualsTo)){
        expr.getLeftExpression().accept(this);
        System.out.println(expr.getLeftExpression());
    }
    expr.getRightExpression().accept(this);
    System.out.println(expr.getRightExpression());
}
@Override
public void visit(EqualsTo expr) {
    System.out.println(expr.getLeftExpression());
    System.out.println(expr.getStringExpression());
    System.out.println(expr.getRightExpression());
}

});

这将为您提供以下输出:

代码语言:javascript
复制
a
=
3
a=3
b
=
4
b=4
c
=
5
c=5

但是,这只包含EqualsTo条件语句,这些语句是ANDed一起的。如您所见,您必须为每个逻辑运算符创建一个if语句,并为每个比较运算符重写访问()函数。有更简单的方法吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-10-18 10:59:43

使用ExpressionVisitorAdapter,,您可以覆盖

代码语言:javascript
复制
protected void visitBinaryExpression(BinaryExpression expr)

每一种表达都需要用到。

操作也是BinaryExpressions。因此,您需要按ComparisonOperator.实例检查类型这将处理所有比较器,而不是像+ *这样的操作。

这样就行了。我删除了访问,并用更多的表达式扩展了您的whereClause。

代码语言:javascript
复制
    String whereClause = "a=3 AND b=4 AND c=5 AND d>5 AND x<10";
    Expression expr = CCJSqlParserUtil.parseCondExpression(whereClause);
    expr.accept(new ExpressionVisitorAdapter() {

        @Override
        protected void visitBinaryExpression(BinaryExpression expr) {
            if (expr instanceof ComparisonOperator) {
                System.out.println("left=" + expr.getLeftExpression() + "  op=" +  expr.getStringExpression() + "  right=" + expr.getRightExpression());
            }

            super.visitBinaryExpression(expr); 
        }
    });

这一产出如下:

代码语言:javascript
复制
left=a  op==  right=3
left=b  op==  right=4
left=c  op==  right=5
left=d  op=>  right=5
left=x  op=<  right=10
票数 3
EN

Stack Overflow用户

发布于 2017-10-19 15:05:47

经过更多的开发和帮助,从wumpz的回答,我有一个解决方案。函数parseWhereClauseToFilter()将使用逻辑运算符和比较来解析where子句。我还没有测试过像“中间”和“IN”这样的操作符,但是我认为解决方案也是类似的。我发现了一个这样的问题,here,这也是一个帮助。

下面的代码

代码语言:javascript
复制
public static void parseWhereClauseToFilter(String whereClause ){

    try {
        Expression expr = CCJSqlParserUtil.parseCondExpression(whereClause);
        FilterExpressionVisitorAdapter adapter = new FilterExpressionVisitorAdapter();
        expr.accept(adapter);

    } catch (JSQLParserException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
} 
public class FilterExpressionVisitorAdapter extends ExpressionVisitorAdapter{
    int depth = 0;
    public void processLogicalExpression( BinaryExpression expr, String logic){
        System.out.println(StringUtils.repeat("-", depth) + logic);

        depth++;
        expr.getLeftExpression().accept(this);
        expr.getRightExpression().accept(this);
        if(  depth != 0 ){
            depth--;
        }
    }

    @Override
    protected void visitBinaryExpression(BinaryExpression expr) {
        if (expr instanceof ComparisonOperator) {
            System.out.println(StringUtils.repeat("-", depth) + 
                "left=" + expr.getLeftExpression() + 
                "  op=" +  expr.getStringExpression() + 
                "  right=" + expr.getRightExpression() );
        } 
        super.visitBinaryExpression(expr); 
    }

    @Override
    public void visit(AndExpression expr) {
        processLogicalExpression(expr, "AND");

    }
    @Override
    public void visit(OrExpression expr) {
        processLogicalExpression(expr, "OR");
    }
    @Override
    public void visit(Parenthesis parenthesis) {
        parenthesis.getExpression().accept(this);
    }

}

将为"a=3和(b=4和c=5)和d>5“的输入字符串产生以下输出

代码语言:javascript
复制
AND
-AND
--left=a  op==  right=3
--AND
---left=b  op==  right=4
---left=c  op==  right=5
-left=d  op=>  right=5
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46800058

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档