/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.huawei.streaming.cql.semanticanalyzer; import java.util.HashMap; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.Lists; import com.huawei.streaming.api.streams.Column; import com.huawei.streaming.api.streams.Schema; import com.huawei.streaming.cql.exception.ExecutorException; import com.huawei.streaming.cql.exception.ParseException; import com.huawei.streaming.cql.exception.SemanticAnalyzerException; import com.huawei.streaming.cql.executor.expressioncreater.ExpressionCreatorFactory; import com.huawei.streaming.cql.semanticanalyzer.analyzecontext.AnalyzeContext; import com.huawei.streaming.cql.semanticanalyzer.analyzecontext.FilterClauseAnalzyeContext; import com.huawei.streaming.cql.semanticanalyzer.analyzecontext.FromClauseAnalyzeContext; import com.huawei.streaming.cql.semanticanalyzer.analyzecontext.LimitClauseAnalzyeContext; import com.huawei.streaming.cql.semanticanalyzer.analyzecontext.OrderByClauseAnalyzeContext; import com.huawei.streaming.cql.semanticanalyzer.analyzecontext.SelectClauseAnalyzeContext; import com.huawei.streaming.cql.semanticanalyzer.analyzecontext.SelectWithOutFromAnalyzeContext; import com.huawei.streaming.cql.semanticanalyzer.analyzecontext.expressiondesc.ExpressionDescribe; import com.huawei.streaming.cql.semanticanalyzer.parser.IParser; import com.huawei.streaming.cql.semanticanalyzer.parser.ParserFactory; import com.huawei.streaming.cql.semanticanalyzer.parser.context.ExpressionContext; import com.huawei.streaming.cql.semanticanalyzer.parser.context.MultiSelectContext; import com.huawei.streaming.cql.semanticanalyzer.parser.context.ParseContext; import com.huawei.streaming.cql.semanticanalyzer.parser.context.SelectExpressionContext; import com.huawei.streaming.cql.semanticanalyzer.parser.context.SelectItemContext; import com.huawei.streaming.cql.semanticanalyzer.parser.context.StreamAllColumnsContext; import com.huawei.streaming.exception.ErrorCode; import com.huawei.streaming.expression.IExpression; /** * 多级insert语义分析 * */ public class SelectWithOutFromAnalyzer extends BaseAnalyzer { private static final Logger LOG = LoggerFactory.getLogger(SelectWithOutFromAnalyzer.class); private SelectWithOutFromAnalyzeContext context = null; private MultiSelectContext selectContext; private FromClauseAnalyzeContext fromAnalyzeContext; /** * <默认构造函数> * */ public SelectWithOutFromAnalyzer(ParseContext parseContext) throws SemanticAnalyzerException { super(parseContext); selectContext = (MultiSelectContext)parseContext; } /** * {@inheritDoc} */ @Override public SelectWithOutFromAnalyzeContext analyze() throws SemanticAnalyzerException { selectAnalyzer(); resetOutputColumnTypes(); whereAnalyzer(); groupbyAnalyzer(); havingAnalyzer(); orderbyAnalyzer(); limitAnalyzer(); return context; } public FromClauseAnalyzeContext getFromAnalyzeContext() { return fromAnalyzeContext; } public void setFromAnalyzeContext(FromClauseAnalyzeContext fromAnalyzeContext) { this.fromAnalyzeContext = fromAnalyzeContext; } /** * {@inheritDoc} */ @Override protected void createAnalyzeContext() { context = new SelectWithOutFromAnalyzeContext(); } /** * {@inheritDoc} */ @Override protected AnalyzeContext getAnalyzeContext() { return context; } private void whereAnalyzer() throws SemanticAnalyzerException { if (selectContext.getWhere() == null) { return; } SemanticAnalyzer analyzer = SemanticAnalyzerFactory.createAnalyzer(selectContext.getWhere(), getInputSchemas()); context.setWhereClauseContext((FilterClauseAnalzyeContext)analyzer.analyze()); } private void limitAnalyzer() throws SemanticAnalyzerException { if (selectContext.getLimit() == null) { return; } SemanticAnalyzer analyzer = SemanticAnalyzerFactory.createAnalyzer(selectContext.getLimit(), null); context.setLimitClauseContext((LimitClauseAnalzyeContext)analyzer.analyze()); } private void orderbyAnalyzer() throws SemanticAnalyzerException { if (selectContext.getOrderby() == null) { return; } OrderByClauseAnalyzer analyzer = (OrderByClauseAnalyzer)SemanticAnalyzerFactory.createAnalyzer(selectContext.getOrderby(), getMixedSchemas()); analyzer.addSelectItems(getAllSelectItems()); context.setOrderbyClauseContext((OrderByClauseAnalyzeContext)analyzer.analyze()); } private void havingAnalyzer() throws SemanticAnalyzerException { if (selectContext.getHaving() == null) { return; } FilterClauseAnalyzer analyzer = (FilterClauseAnalyzer)SemanticAnalyzerFactory.createAnalyzer(selectContext.getHaving(), getMixedSchemas()); analyzer.addSelectItems(getAllSelectItems()); context.setHavingClauseContext((FilterClauseAnalzyeContext)analyzer.analyze()); } private void groupbyAnalyzer() throws SemanticAnalyzerException { if (selectContext.getGroupby() == null) { return; } SemanticAnalyzer analyzer = SemanticAnalyzerFactory.createAnalyzer(selectContext.getGroupby(), getInputSchemas()); context.setGroupbyClauseContext((SelectClauseAnalyzeContext)analyzer.analyze()); } private void selectAnalyzer() throws SemanticAnalyzerException { SemanticAnalyzer analyzer = SemanticAnalyzerFactory.createAnalyzer(selectContext.getSelect(), getInputSchemas()); context.setSelectClauseContext((SelectClauseAnalyzeContext)analyzer.analyze()); } private List<Schema> getInputSchemas() throws SemanticAnalyzerException { if (getFromAnalyzeContext() == null) { LOG.error("'{}' was not parsed.", "From clause"); SemanticAnalyzerException exception = new SemanticAnalyzerException(ErrorCode.UNKNOWN_SERVER_COMMON_ERROR); throw exception; } return getFromAnalyzeContext().getInputSchemas(); } /* * 只需要对count之类的表达式进行替换 * *号表达式不需要替换 */ private List<SelectItemContext> getAllSelectItems() throws SemanticAnalyzerException { if (context.getSelectClauseContext() == null) { LOG.error("'{}' was not parsed.", "Select clause"); SemanticAnalyzerException exception = new SemanticAnalyzerException(ErrorCode.UNKNOWN_SERVER_COMMON_ERROR); throw exception; } List<SelectItemContext> selectItems = Lists.newArrayList(); for (SelectItemContext selectItem : selectContext.getSelect().getSelectItems()) { StreamAllColumnsContext allColumns = selectItem.getExpression().getAllColumns(); if (allColumns != null) { List<SelectItemContext> allColExpressions = createNewExpressionsForAllInputSchemas(allColumns); selectItems.addAll(allColExpressions); } else { selectItems.add(selectItem); } } return selectItems; } private List<SelectItemContext> createNewExpressionsForAllInputSchemas(StreamAllColumnsContext allColumnContext) throws SemanticAnalyzerException { List<SelectItemContext> newExpressions = Lists.newArrayList(); //a.* if (allColumnContext.getStreamName() != null) { Schema schema = BaseAnalyzer.getSchemaByName(allColumnContext.getStreamName(), getInputSchemas()); newExpressions.addAll(createNewExpressionForSchema(schema)); return newExpressions; } //* List<Schema> schemas = getInputSchemas(); for (Schema schema : schemas) { newExpressions.addAll(createNewExpressionForSchema(schema)); } return newExpressions; } private List<SelectItemContext> createNewExpressionForSchema(Schema schema) throws SemanticAnalyzerException { List<SelectItemContext> asts = Lists.newArrayList(); IParser parser = ParserFactory.createApplicationParser(); for (Column column : schema.getCols()) { asts.add(createSelectItemContext(parser, column)); } return asts; } private SelectItemContext createSelectItemContext(IParser parser, Column column) throws ParseException { SelectExpressionContext selectExp = createSelectExpression(parser, column); SelectItemContext item = new SelectItemContext(); item.setExpression(selectExp); return item; } private SelectExpressionContext createSelectExpression(IParser parser, Column column) throws ParseException { ExpressionContext exp = (ExpressionContext)parser.parse(column.getName()); SelectExpressionContext selectExp = new SelectExpressionContext(); selectExp.setExpression(exp); return selectExp; } /** * 获取混合的schema * 该schema,最后面一定是输入schema * 第一位是输出schema * */ private List<Schema> getMixedSchemas() throws SemanticAnalyzerException { if (context.getSelectClauseContext() == null) { LOG.error("'{}' was not parsed.", "Select clause"); SemanticAnalyzerException exception = new SemanticAnalyzerException(ErrorCode.UNKNOWN_SERVER_COMMON_ERROR); throw exception; } List<Schema> rs = Lists.newArrayList(); rs.add(context.getSelectClauseContext().getOutputSchema()); rs.addAll(getInputSchemas()); return rs; } private void resetOutputColumnTypes() throws SemanticAnalyzerException { SelectClauseAnalyzeContext selectClause = context.getSelectClauseContext(); Schema outputSchema = selectClause.getOutputSchema(); if (outputSchema.getCols().size() != selectClause.getExpdes().size()) { SemanticAnalyzerException exception = new SemanticAnalyzerException(ErrorCode.SEMANTICANALYZE_NOTSAME_COLUMNS, String.valueOf(selectClause.getExpdes().size()), String.valueOf(outputSchema.getCols().size())); LOG.error("Select column not match ouput schema column.", exception); throw exception; } resetColumnTypes(selectClause, outputSchema); } private void resetColumnTypes(SelectClauseAnalyzeContext selectClause, Schema outputSchema) throws SemanticAnalyzerException { for (int i = 0; i < outputSchema.getCols().size(); i++) { Column c = outputSchema.getCols().get(i); ExpressionDescribe expdesc = selectClause.getExpdes().get(i); IExpression exp = createExpression(expdesc); if (exp != null) { c.setType(exp.getType().getName()); } } } private IExpression createExpression(ExpressionDescribe exp) throws SemanticAnalyzerException { try { return ExpressionCreatorFactory.createExpression(exp, new HashMap<String, String>()); } catch (ExecutorException e) { throw SemanticAnalyzerException.wrapStreamingException(e); } } }