2017-10-17 101 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