我正在尝试使用JSQLParser开发一个SQL查询评估器,我对如何确定评估顺序感到很困惑,就像我有以下形式的查询一样

Select *
From A,B,C
Where A.id=B.id
  And B.id=C.id
  And A.id=C.id


问题是如何从中构建解析树或表达式树。我需要一些指导来解决这个问题。另外,我正在考虑使用几个堆栈(一个操作符堆栈和一个操作数堆栈)解决此问题。我需要一些确认,以了解这是否是理解此问题的一种可能方式?

最佳答案

这是一个有趣的问题。因此,我可以介绍一下JSqlParser(https://github.com/JSQLParser/JSqlParser)的另一个分支。到目前为止,我将其用于SQL的元数据分析,直到现在还不需要进行评估。

现在是我的两分钱。运算符优先级在JSqlParsers语法中部分地伪造。 (@jbaliuka:我调查了您的fork,并认为它基于旧版本的JSqlParser。sourceforge(2010?)的最新发展引入了用于加法和乘法的运算符优先级。另外,您的解析表达式解析触发了我的fork的一些更改。如果您可以尝试一下,那就太好了。)

这是一个非常简单的表达式计算器,用于使用JSqlParser V0.8.8进行加法和乘法。首先,JSqlParser从该树继承的对象层次结构提供一个解析树或更精确的a,我使用JSqlParser的visiter结构遍历该层次结构。确保完整版本尚需完成许多工作。这更是概念的证明。对我来说很有趣的是,对于我的示例,甚至括号优先级也已正确完成。

import java.util.Stack;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.operators.arithmetic.Addition;
import net.sf.jsqlparser.expression.operators.arithmetic.Multiplication;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.util.deparser.ExpressionDeParser;

public class SimpleEvaluateExpr {

    public static void main( String[] args ) throws JSQLParserException {
        //examples
        evaluate("4+5*6");
        evaluate("4*5+6");
        evaluate("4*(5+6)");
        evaluate("4*(5+6)*(2+3)");
    }

    static void evaluate(String expr) throws JSQLParserException {
        //here is the stack you mentioned ;)
        final Stack<Long> stack = new Stack<Long>();

        System.out.println("expr=" + expr);
        Expression parseExpression = CCJSqlParserUtil.parseExpression(expr);
        //Deparser traverses the complete expression hierarchy. It was mainly used
        //for SQL output but this is now done using toString but is always a useful
        //traversal tool.
        ExpressionDeParser deparser = new ExpressionDeParser() {
            @Override
            public void visit(Addition addition) {
                super.visit(addition);

                long sum1 = stack.pop();
                long sum2 = stack.pop();

                stack.push(sum1 + sum2);
            }

            @Override
            public void visit(Multiplication multiplication) {
                super.visit(multiplication);

                long fac1 = stack.pop();
                long fac2 = stack.pop();

                stack.push(fac1 * fac2);
            }

            @Override
            public void visit(LongValue longValue) {
                super.visit(longValue);
                stack.push(longValue.getValue());
            }
        };
        StringBuilder b = new StringBuilder();
        deparser.setBuffer(b);
        parseExpression.accept(deparser);

        System.out.println(expr + " = " + stack.pop() );
    }
}


这是输出:

expr=4+5*6
4+5*6 = 34
expr=4*5+6
4*5+6 = 26
expr=4*(5+6)
4*(5+6) = 44
expr=4*(5+6)*(2+3)
4*(5+6)*(2+3) = 220


因此,第一个示例表达式的解析树类似于:


加成

长值(4)
乘法

长值(5)
长值(6)




访客深度遍历第一顺序。

09-30 14:26