山东大学软件工程应用与实践——PIG代码分析(五)

2021SC@SDUSC

总览

本篇为对QueryParserDriver类进行分析的第一篇,主要是对PigServer的parseQuery方法会进入QueryParserDriver的parse(query)方法,本次主要针对生成逻辑数据模型的过程进行分析。

代码分析

初始化

初始化读取pigserver所处环境,范围,将接口fileNameMap的key-value值设为importseen和macroseen,初始化pigserver为空,延迟寄存器语句实例化。

public QueryParserDriver(PigContext pigContext, String scope, Map<String, String> fileNameMap) {
    
    
        this.pigContext = pigContext;
        this.pigServer = null; // lazily instantiated for register statements
        this.scope = scope;
        this.fileNameMap = fileNameMap;
        importSeen = new HashSet<String>();
        macroSeen = new HashSet<String>();
    }

parseSchema()

根据返回值的类型不同,共有两种parseSchema()方法,一种返回抽象逻辑树,一种返回逻辑数据模型。

  • 本方法生成的是抽象语法树,抽象语法树(abstract syntax code,AST)是源代码的抽象语法结构的树状表示,树上的每个节点都表示源代码中的一种结构,这所以说是抽象的,是因为抽象语法树并不会表示出真实语法出现的每一个细节,比如说,嵌套括号被隐含在树的结构中,并没有以节点的形式呈现。抽象语法树并不依赖于源语言的语法。
private static Tree parseSchema(CommonTokenStream tokens) throws ParserException {
    
    
        QueryParser parser = QueryParserUtils.createParser(tokens);

        schema_return result = null;
        try {
    
    
            result = parser.schema();
        } catch (RecognitionException e) {
    
    
            String msg = parser.getErrorHeader(e) + " "
                    + parser.getErrorMessage(e, parser.getTokenNames());
            throw new ParserException(msg);
        } catch(RuntimeException ex) {
    
    
            throw new ParserException( ex.getMessage() );
        }

        Tree ast = (Tree)result.getTree();
        checkError( parser );

        return ast;
    }
  • 本逻辑数据模型应该基于前面概念数据模型中标识的结构,因为这描述了信息上下文的语义,逻辑模型也应该反映信息上下文的语义。尽管如此,由于逻辑数据模型预期在特定的计算系统上实现,因此对逻辑数据模型的内容进行调整以达到一定的效率。术语“逻辑数据模型”有时用作“域模型”的同义词或域模型的替代词。虽然这两个概念密切相关,并且有重叠的目标,但域模型更侧重于捕获问题域中的概念,而不是与该域相关联的数据的结构。
    public LogicalSchema parseSchema(String input) throws ParserException {
    
    
        CommonTokenStream tokenStream = tokenize( input, null );
        LogicalSchema schema = null;
        Tree ast = parseSchema( tokenStream );

        try{
    
    
            CommonTreeNodeStream nodes = new CommonTreeNodeStream( ast );
            AstValidator walker = new AstValidator( nodes );
            ast = (Tree)walker.field_def_list().getTree();
            checkError( walker );

            LogicalPlanGenerator planGenerator =
                new LogicalPlanGenerator( new CommonTreeNodeStream( ast ), pigContext, scope, fileNameMap );
            schema = planGenerator.field_def_list().schema;
            checkError( planGenerator );
        } catch(RecognitionException ex) {
    
    
            throw new ParserException( ex );
        } catch(Exception ex) {
    
    
            throw new ParserException( ex.getMessage(), ex );
        }

        return schema;
    }

parseConstant()

Parser根据lexer生成的tokens尝试解析。tokens每一个成员都会生成一个函数,其先后执行逻辑按照用户输入的1+1+2的顺序执行。注意像1和2这类constants为true的token,parser会通过constant生成需要的函数parseConstant,也就是说1+1+2中的两个1和一个2都是返回parseConstant函数.

private static Tree parseConstant(CommonTokenStream tokens) throws ParserException {
    
    
        QueryParser parser = QueryParserUtils.createParser(tokens);

        literal_return result = null;
        try {
    
    
            result = parser.literal();
        } catch (RecognitionException e) {
    
    
            String msg = parser.getErrorHeader(e) + " "
                    + parser.getErrorMessage(e, parser.getTokenNames());
            throw new ParserException(msg);
        } catch(RuntimeException ex) {
    
    
            throw new ParserException( ex.getMessage() );
        }

        Tree ast = (Tree)result.getTree();
        checkError( parser );

        return ast;
    }

    public Object parseConstant(String input) throws ParserException {
    
    
        CommonTokenStream tokenStream = tokenize( input, null );
        Object value = null;
        Tree ast = parseConstant( tokenStream );

        try{
    
    
            CommonTreeNodeStream nodes = new CommonTreeNodeStream( ast );
            AstValidator walker = new AstValidator( nodes );
            ast = (Tree)walker.literal().getTree();
            checkError( walker );

            LogicalPlanGenerator planGenerator =
                new LogicalPlanGenerator( new CommonTreeNodeStream( ast ), pigContext, scope, fileNameMap );
            value = planGenerator.literal().value;
            checkError( planGenerator );
        } catch(RecognitionException ex) {
    
    
            throw new ParserException( ex );
        } catch(Exception ex) {
    
    
            throw new ParserException( ex.getMessage(), ex );
        }

        return value;
    }

总结

本次分析主要针对的是QueryParserDriver类的一些方法进行分析,对其中一些模型进行理解。

猜你喜欢

转载自blog.csdn.net/qq_45822693/article/details/121021429