2017-10-17 1723 views
0

我想完整地,简洁地使用JSqlParser解析SQL where子句。人们很容易把它解析为单独的条件语句,像这样使用JSqlParser完全解析where子句

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()); 
    } 
}); 

将产生输出:

a=3 
b=4 
c=5 

我想是让左侧,操作和右侧每一个人表达,这样的我可以将这些值放入一些现有的滤镜对象中。

我知道你可以覆盖访问功能,像这样每一个类型的操作:

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()); 
} 

});

这将让你的输出:

a 
= 
3 
a=3 
b 
= 
4 
b=4 
c 
= 
5 
c=5 

但这仅涵盖那些与运算一起EqualsTo条件语句。正如你所看到的,你将不得不为每个逻辑运算符创建一个if语句,并为每个比较运算符重写visit()函数。有没有更简单的方法来做到这一点?

回答

0

使用ExpressionVisitorAdapter,你可能会覆盖

protected void visitBinaryExpression(BinaryExpression expr) 

这就是所谓的每那些表情。

操作是BinaryExpressions以及。所以你需要通过实例来检查类型ComparisonOperator。这将处理所有的比较器,而不是像+ *这样的操作。

这应该做到这一点。我删除了AND的访问,并用更多的表达式扩展了whereClause。

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); 
     } 
    }); 

此输出:

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 
+0

致谢输入字符串下面的输出为答案。如果我可以对它投票,我会。这是一个很大的帮助。但是,您的解决方案不能完全解析where子句。它只显示比较本身。我会发布一个更完整的答案,我来。 – codering

+0

好的。我认为我的解决方案就是你想达到的。 Missinterpretation。所以我投票给你。 :) – wumpz

1

从wumpz的回答更多的发展和帮助之后,我有一个解决方案。函数parseWhereClauseToFilter()将使用逻辑运算符和比较来解析where子句。我还没有测试像BETWEEN和IN等运营商,但我认为解决方案是相似的。我发现了一个SO问题here,这也是一个帮助。

下面

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”

AND 
-AND 
--left=a op== right=3 
--AND 
---left=b op== right=4 
---left=c op== right=5 
-left=d op=> right=5