/**
* 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.builder.operatorsplitter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.huawei.streaming.api.opereators.FilterOperator;
import com.huawei.streaming.api.opereators.OperatorTransition;
import com.huawei.streaming.api.opereators.SplitterOperator;
import com.huawei.streaming.api.opereators.SplitterSubContext;
import com.huawei.streaming.api.streams.Schema;
import com.huawei.streaming.application.DistributeType;
import com.huawei.streaming.cql.builder.BuilderUtils;
import com.huawei.streaming.cql.exception.ApplicationBuildException;
import com.huawei.streaming.cql.exception.SemanticAnalyzerException;
import com.huawei.streaming.cql.semanticanalyzer.BaseAnalyzer;
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.MultiInsertAnalyzeContext;
import com.huawei.streaming.cql.semanticanalyzer.analyzecontext.MultiInsertStatementAnalyzeContext;
import com.huawei.streaming.cql.semanticanalyzer.analyzecontext.ParallelClauseAnalyzeContext;
import com.huawei.streaming.cql.semanticanalyzer.analyzecontext.expressiondesc.ExpressionDescribe;
/**
* 多级insert算子拆分
*
*/
public class MultiInsertSplitter implements Splitter
{
private static final Logger LOG = LoggerFactory.getLogger(MultiInsertSplitter.class);
private BuilderUtils bUtils;
private MultiInsertStatementAnalyzeContext context;
private SplitContext result = new SplitContext();
private int parallelNumber = 1;
/**
* <默认构造函数>
*
*/
public MultiInsertSplitter(BuilderUtils buildUtils)
{
bUtils = buildUtils;
}
/**
* {@inheritDoc}
*/
@Override
public boolean validate(AnalyzeContext parseContext)
{
return parseContext instanceof MultiInsertStatementAnalyzeContext;
}
/**
* {@inheritDoc}
*/
@Override
public SplitContext split(AnalyzeContext parseContext)
throws ApplicationBuildException
{
LOG.debug("start to split multiInsert analyze context.");
context = (MultiInsertStatementAnalyzeContext)parseContext;
setParallelNumber();
String inputStreamName = context.getFrom().getInputStreams().get(0);
FilterOperator fop = splitFiterBeforeWindow(inputStreamName);
SplitterOperator splitter = new SplitterOperator(bUtils.getNextOperatorName("Splitter"), parallelNumber);
parseSubSelect(splitter);
Schema schema = context.getFrom().getInputSchemas().get(0);
OperatorTransition transition =
new OperatorTransition(bUtils.getNextStreamName(), fop, splitter, DistributeType.SHUFFLE, null, schema);
result.getOperators().add(fop);
result.getOperators().add(splitter);
result.setParseContext(context);
result.getTransitions().add(transition);
return result;
}
public ParallelClauseAnalyzeContext getParallelClauseContext()
{
return context.getParallelClause();
}
/**
* filter before window 语句解析
*
*/
protected FilterOperator splitFiterBeforeWindow(String streamName)
throws SemanticAnalyzerException
{
FilterOperator fop = new FilterOperator(bUtils.getNextOperatorName("Filter"), parallelNumber);
fop.setFilterExpression(getFilterExpression(streamName));
fop.setOutputExpression(createFilterOutputExpression(streamName));
return fop;
}
private String getFilterExpression(String streamName)
{
FromClauseAnalyzeContext clauseContext = context.getFrom();
ExpressionDescribe expression = clauseContext.getFilterBeForeWindow().get(streamName);
if (expression == null)
{
return null;
}
return expression.toString();
}
private void parseSubSelect(SplitterOperator splitter)
{
//必须保证按照顺序循环,因为在combiner中还要使用
for (int i = 0; i < context.getMultiSelectBodyAnalyzeContexts().size(); i++)
{
MultiInsertAnalyzeContext insert = context.getMultiSelectBodyAnalyzeContexts().get(i);
SplitterSubContext subContext = new SplitterSubContext();
setFilterExpression(insert, subContext);
subContext.setOutputExpression(insert.getSelectContext().getSelectClauseContext().toString());
splitter.getSubSplitters().add(subContext);
}
}
private String createFilterOutputExpression(String streamName)
throws SemanticAnalyzerException
{
FromClauseAnalyzeContext clauseContext = context.getFrom();
Schema schema = BaseAnalyzer.getSchemaByName(streamName, clauseContext.getInputSchemas());
StringBuilder sb = new StringBuilder();
for (int i = 0; i < schema.getCols().size(); i++)
{
sb.append(schema.getId() + "." + schema.getCols().get(i).getName());
if (i != schema.getCols().size() - 1)
{
sb.append(",");
}
}
return sb.toString();
}
private void setFilterExpression(MultiInsertAnalyzeContext insert, SplitterSubContext subContext)
{
FilterClauseAnalzyeContext where = insert.getSelectContext().getWhereClauseContext();
if (where != null)
{
subContext.setFilterExpression(where.toString());
}
}
private void setParallelNumber()
{
if (getParallelClauseContext() == null || getParallelClauseContext().getParallelNumber() == null)
{
parallelNumber = bUtils.getDefaultParallelNumber();
}
else
{
parallelNumber = getParallelClauseContext().getParallelNumber();
}
}
}