使用 JSqlParser 完全解析 where 子句
Fully parsing where clause with JSqlParser
我想使用 JSqlParser 完整而简洁地解析 SQL 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
但这只涵盖了用 AND 运算在一起的 EqualsTo 条件语句。如您所见,您必须为每个逻辑运算符创建一个 if 语句,并为每个比较运算符覆盖 visit() 函数。有更简单的方法吗?
使用ExpressionVisitorAdapter,你可以覆盖
protected void visitBinaryExpression(BinaryExpression expr)
每个表达式都会调用它。
操作也是 BinaryExpressions。所以你需要通过 instanceof 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
经过更多开发和 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 and (b=4 and c=5) and 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
我想使用 JSqlParser 完整而简洁地解析 SQL 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
但这只涵盖了用 AND 运算在一起的 EqualsTo 条件语句。如您所见,您必须为每个逻辑运算符创建一个 if 语句,并为每个比较运算符覆盖 visit() 函数。有更简单的方法吗?
使用ExpressionVisitorAdapter,你可以覆盖
protected void visitBinaryExpression(BinaryExpression expr)
每个表达式都会调用它。
操作也是 BinaryExpressions。所以你需要通过 instanceof 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
经过更多开发和 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 and (b=4 and c=5) and 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