Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Facebook presto解析器_Java_Facebook_Parsing - Fatal编程技术网

Java 使用Facebook presto解析器

Java 使用Facebook presto解析器,java,facebook,parsing,Java,Facebook,Parsing,我正在尝试使用。我需要知道的是如何分析和提取我们创建的语句的查询体: SqlParser SQL_PARSER = new SqlParser(); Statement statement = SQL_PARSER.createStatement(query); 从语句getter/setters中似乎没有任何方法可以得到这一点。我调试了Statement对象,从debug视图中可以看到需要获取的值 见: 我需要获取由SqlParser提取的select、from、where、groupBy

我正在尝试使用。我需要知道的是如何分析和提取我们创建的
语句的查询体

SqlParser SQL_PARSER = new SqlParser();
Statement statement = SQL_PARSER.createStatement(query);
语句
getter/setters中似乎没有任何方法可以得到这一点。我调试了Statement对象,从debug视图中可以看到需要获取的值

见:


我需要获取由SqlParser提取的select、from、where、groupBy、orderBy和limit值

从sql字符串中,您可以通过向下转换
语句
来获得
查询
(它扩展了语句)
Query.getQueryBody
返回一个
QueryBody
,您可以将其转换为
QuerySpecification
(扩展了
QueryBody
)。从
QuerySpecification
,您现在可以获得所需的内容。下面是一个简单的例子:

public class PrestoParserTest {
    public static void main(String[] args) {
        SqlParser parser = new SqlParser();
        String sql = "select * from xyz where x=y group by x order by y limit 10";
        Query query = (Query)parser.createStatement(sql);
        QuerySpecification body = (QuerySpecification)query.getQueryBody();
        Select select = body.getSelect();
        System.out.println("Columns = " + select.getSelectItems());
        System.out.println("From = " + body.getFrom().get());
        Optional<Expression> where = body.getWhere();
        System.out.println("Where = " + where.get());
        System.out.println("Group by = " + body.getGroupBy());
        System.out.println("Order by = " + body.getOrderBy());
        System.out.println("Limit = " + body.getLimit().get());

    }
}

虽然给出的答案有效,但它需要在运行时进行大量类型检查和强制转换,这非常容易出错。(特别是当您有一个包含许多联接和子表达式的高度嵌套查询时)

相反,Presto的查询解析器提供了一个基本的
AstVisitor
抽象类,您可以对其进行子类化,它将为您处理所有的强制转换和分派

例如,要获取查询中使用的所有表的列表(在scala中,但同样适用于java):

下面是一个示例访问者,它不做任何有用的事情,但正确地遍历查询树。我发现弄清楚如何编写自己的:
问题有两部分

  • 访问整个AST(可能是递归的)
  • 在每个节点上执行操作(在本例中,查找表节点)
  • 以下是一个可扩展的解决方案:

    class DepthFirstVisitor<R, C> extends AstVisitor<Stream<R>, C> {
        private final AstVisitor<R, C> visitor;
    
        public DepthFirstVisitor(AstVisitor<R, C> visitor) {
            this.visitor = visitor;
        }
    
        public static <R, C> DepthFirstVisitor<R, C> by(AstVisitor<R, C> visitor) {
            return new DepthFirstVisitor<>(visitor);
        }
    
        @Override
        public final Stream<R> visitNode(Node node, C context) {
            Stream<R> nodeResult = Stream.of(visitor.process(node, context));
            Stream<R> childrenResult = node.getChildren().stream()
                    .flatMap(child -> process(child, context));
    
            return Stream.concat(nodeResult, childrenResult)
                    .filter(Objects::nonNull);
        }
    }
    
    class Extractors {
        public static AstVisitor<Table, Object> extractTables() {
            return new AstVisitor<Table, Object>() {
                @Override
                protected Table visitTable(Table node, Object context) {
                    return node;
                }
            };
        }
    }
    
        
        // Thats it folks
    DepthFirstVisitor<Table, ?> depthFirstVisitor = DepthFirstVisitor.by(Extractors.extractTables());
    
    String sql = "select * from foo tablesample system (10) join bar tablesample bernoulli (30) on not(a.id > b.id)";
    Statement statement = new SqlParser().createStatement(sql, new ParsingOptions());
    
    List<Table> tables = statement.accept(depthFirstVisitor, null)
            .collect(Collectors.toList());
    System.out.println(tables);
    
    class DepthFirstVisitor扩展了AstVisitor{
    私人最终访客;
    公共部门第一访客(AST访客){
    this.visitor=访客;
    }
    公共静态深度第一访问者(AstVisitor){
    返回新的DepthFirstVisitor(访客);
    }
    @凌驾
    公共最终流visitNode(节点,C上下文){
    Stream nodeResult=Stream.of(visitor.process(节点,上下文));
    Stream childrenResult=node.getChildren().Stream()
    .flatMap(子->进程(子,上下文));
    返回Stream.concat(nodeResult、childrenResult)
    .filter(对象::非空);
    }
    }
    类提取器{
    公共静态表{
    返回新的AstVisitor(){
    @凌驾
    受保护的表可访问(表节点、对象上下文){
    返回节点;
    }
    };
    }
    }
    //就是这样,伙计们
    DepthFirstVisitor DepthFirstVisitor=DepthFirstVisitor.by(提取器.extractTables());
    String sql=“select*from foo tablesample system(10)join bar tablesample bernoulli(30)on not(a.id>b.id)”;
    语句Statement=newsqlparser().createStatement(sql,newparsingoptions());
    List tables=statement.accept(depthFirstVisitor,null)
    .collect(Collectors.toList());
    系统输出打印LN(表格);
    
    这可以在不进行难看的类型检查的情况下完成


    打印
    [Table{foo},Table{bar}]

    关于“UPDATE”语句如何,presto解析器似乎不支持这一点?粗略地看一下代码库,它似乎不受支持。这是可能的,因为引擎并不是真正用于此目的的,但如果是这样的话,仅仅从完整性的角度来看,我仍然会感到惊讶。
    UPDATE
    是不受支持的。
    class VisitSourceTables extends AstVisitor[List[String], List[String]]{
    
      override def visitTable(node: Table, context: List[String]): List[String] = {
        List[String](
          node.getName.toString
        )
      }
    
      override def visitJoin(node: Join, context: List[String]): List[String] = {
        process(node.getLeft, context) ++ process(node.getRight, context)
      }
    
      (one method per type of thing to visit)
      ...
    }
    
    class DepthFirstVisitor<R, C> extends AstVisitor<Stream<R>, C> {
        private final AstVisitor<R, C> visitor;
    
        public DepthFirstVisitor(AstVisitor<R, C> visitor) {
            this.visitor = visitor;
        }
    
        public static <R, C> DepthFirstVisitor<R, C> by(AstVisitor<R, C> visitor) {
            return new DepthFirstVisitor<>(visitor);
        }
    
        @Override
        public final Stream<R> visitNode(Node node, C context) {
            Stream<R> nodeResult = Stream.of(visitor.process(node, context));
            Stream<R> childrenResult = node.getChildren().stream()
                    .flatMap(child -> process(child, context));
    
            return Stream.concat(nodeResult, childrenResult)
                    .filter(Objects::nonNull);
        }
    }
    
    class Extractors {
        public static AstVisitor<Table, Object> extractTables() {
            return new AstVisitor<Table, Object>() {
                @Override
                protected Table visitTable(Table node, Object context) {
                    return node;
                }
            };
        }
    }
    
        
        // Thats it folks
    DepthFirstVisitor<Table, ?> depthFirstVisitor = DepthFirstVisitor.by(Extractors.extractTables());
    
    String sql = "select * from foo tablesample system (10) join bar tablesample bernoulli (30) on not(a.id > b.id)";
    Statement statement = new SqlParser().createStatement(sql, new ParsingOptions());
    
    List<Table> tables = statement.accept(depthFirstVisitor, null)
            .collect(Collectors.toList());
    System.out.println(tables);