15 package com.cloudera.impala.analysis;
17 import java.util.ArrayList;
18 import java.util.List;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
26 import com.google.common.base.Preconditions;
27 import com.google.common.collect.Lists;
38 private final static Logger
LOG = LoggerFactory.getLogger(UnionStmt.class);
67 this.queryStmt_ = queryStmt;
68 this.qualifier_ = qualifier;
92 return ((SelectStmt)
queryStmt_).hasAnalyticInfo();
112 protected final List<UnionOperand>
allOperands_ = Lists.newArrayList();
126 ArrayList<OrderByElement> orderByElements,
LimitElement limitElement) {
127 super(orderByElements, limitElement);
128 this.operands_ = operands;
135 public boolean hasAllOps() {
return !allOperands_.isEmpty(); }
141 allOperands_.clear();
151 super.analyze(analyzer);
153 if (analyzer.getMissingTbls().isEmpty())
throw e;
155 Preconditions.checkState(operands_.size() > 0);
161 QueryStmt firstQuery = operands_.get(0).getQueryStmt();
164 operands_.get(0).
analyze(analyzer);
166 if (analyzer.getMissingTbls().isEmpty())
throw e;
169 List<List<Expr>> resultExprLists = Lists.newArrayList();
170 List<Expr> firstQueryExprs = firstQuery.getBaseTblResultExprs();
171 resultExprLists.add(firstQueryExprs);
172 for (
int i = 1; i < operands_.size(); ++i) {
173 QueryStmt query = operands_.get(i).getQueryStmt();
175 operands_.get(i).
analyze(analyzer);
176 List<Expr> exprs = query.getBaseTblResultExprs();
177 if (firstQueryExprs.size() != exprs.size()) {
180 firstQueryExprs.size() +
" column(s)\n" +
181 "'" +
queryStmtToSql(query) +
"' has " + exprs.size() +
" column(s)");
183 resultExprLists.add(exprs);
185 if (analyzer.getMissingTbls().isEmpty())
throw e;
189 if (!analyzer.getMissingTbls().isEmpty()) {
196 if (op.hasAnalyticExprs()) {
202 analyzer.castToUnionCompatibleTypes(resultExprLists);
227 slotDesc.setIsMaterialized(
true);
232 sortInfo_.materializeRequiredSlots(analyzer, null);
236 List<SlotDescriptor> outputSlots = tupleDesc.getSlots();
237 List<Expr> exprs = Lists.newArrayList();
238 for (
int i = 0; i < outputSlots.size(); ++i) {
247 distinctAggInfo_.getOutputTupleDesc().getSlots().get(i).setIsMaterialized(
true);
264 allOperands_.add(operands_.get(0));
270 int firstUnionAllIdx = operands_.size();
271 for (
int i = 1; i < operands_.size(); ++i) {
274 firstUnionAllIdx = (i == 1 ? 0 : i);
280 Preconditions.checkState(firstUnionAllIdx != 1);
283 Preconditions.checkState(distinctOperands_.isEmpty());
284 for (
int i = 0; i < firstUnionAllIdx; ++i) {
289 Preconditions.checkState(allOperands_.isEmpty());
290 for (
int i = firstUnionAllIdx; i < operands_.size(); ++i) {
306 ArrayList<Expr> groupingExprs = Expr.cloneList(
resultExprs_);
309 AggregateInfo.create(groupingExprs, null,
310 analyzer.getDescTbl().getTupleDesc(
tupleId_), analyzer);
325 operand.getSmap().clear();
326 for (
int i = 0; i < tupleDesc.getSlots().size(); ++i) {
328 operand.getSmap().put(
341 QueryStmt queryStmt = operand.getQueryStmt();
347 Preconditions.checkState(queryStmt instanceof
UnionStmt);
349 if (unionStmt.hasLimit() || unionStmt.hasOffset()) {
352 }
else if (targetQualifier ==
Qualifier.
DISTINCT || !unionStmt.hasDistinctOps()) {
355 target.addAll(unionStmt.getDistinctOperands());
356 target.addAll(unionStmt.getAllOperands());
360 target.addAll(unionStmt.getAllOperands());
361 unionStmt.removeAllOperands();
371 return queryStmt.toSql();
381 int lastDistinctPos = -1;
382 for (
int i =
operands_.size() - 1; i > 0; --i) {
384 if (lastDistinctPos != -1) {
401 TupleDescriptor tupleDesc = analyzer.getDescTbl().createTupleDescriptor(
"union");
402 tupleDesc.setIsMaterialized(
true);
404 LOG.trace(
"UnionStmt.createMetadata: tupleId=" + tupleId_.toString());
407 List<Expr> firstSelectExprs = operands_.get(0).getQueryStmt().getBaseTblResultExprs();
410 List<ColumnStats> columnStats = Lists.newArrayList();
411 for (
int i = 0; i < operands_.size(); ++i) {
412 List<Expr> selectExprs = operands_.get(i).getQueryStmt().getBaseTblResultExprs();
413 for (
int j = 0; j < selectExprs.size(); ++j) {
414 ColumnStats statsToAdd = ColumnStats.fromExpr(selectExprs.get(j));
416 columnStats.add(statsToAdd);
418 columnStats.get(j).add(statsToAdd);
424 for (
int i = 0; i < firstSelectExprs.size(); ++i) {
425 Expr expr = firstSelectExprs.get(i);
428 slotDesc.setType(expr.getType());
429 slotDesc.setStats(columnStats.get(i));
431 resultExprs_.add(outputSlotRef);
437 ambiguousAliasList_.add(aliasRef);
439 aliasSmap_.put(aliasRef, outputSlotRef);
449 slotDesc.addSourceExpr(resultExpr);
450 if (op.hasAnalyticExprs())
continue;
451 SlotRef slotRef = resultExpr.unwrapSlotRef(
true);
452 if (slotRef == null)
continue;
453 analyzer.registerValueTransfer(outputSlotRef.getSlotId(), slotRef.
getSlotId());
465 tupleIdList.add(sortInfo_.getSortTupleDescriptor().getId());
474 StringBuilder strBuilder =
new StringBuilder();
475 Preconditions.checkState(operands_.size() > 0);
478 strBuilder.append(withClause_.toSql());
479 strBuilder.append(
" ");
482 strBuilder.append(operands_.get(0).getQueryStmt().toSql());
483 for (
int i = 1; i < operands_.size() - 1; ++i) {
484 strBuilder.append(
" UNION " +
485 ((operands_.get(i).getQualifier() ==
Qualifier.ALL) ?
"ALL " :
""));
487 strBuilder.append(
"(");
489 strBuilder.append(operands_.get(i).getQueryStmt().toSql());
490 if (
operands_.get(i).getQueryStmt() instanceof UnionStmt) {
491 strBuilder.append(
")");
495 UnionOperand lastOperand = operands_.get(operands_.size() - 1);
496 QueryStmt lastQueryStmt = lastOperand.getQueryStmt();
497 strBuilder.append(
" UNION " +
498 ((lastOperand.getQualifier() ==
Qualifier.
ALL) ?
"ALL " :
""));
499 if (lastQueryStmt instanceof
UnionStmt ||
501 !lastQueryStmt.
hasLimit() && !lastQueryStmt.hasOffset() &&
503 strBuilder.append(
"(");
504 strBuilder.append(lastQueryStmt.toSql());
505 strBuilder.append(
")");
507 strBuilder.append(lastQueryStmt.toSql());
511 strBuilder.append(
" ORDER BY ");
512 for (
int i = 0; i < orderByElements_.size(); ++i) {
513 strBuilder.append(orderByElements_.get(i).
toSql());
514 strBuilder.append((i+1 != orderByElements_.size()) ?
", " :
"");
518 strBuilder.append(limitElement_.toSql());
519 return strBuilder.toString();
524 Preconditions.checkState(operands_.size() > 0);
525 return operands_.get(0).getQueryStmt().getColLabels();
530 List<UnionOperand> operandClones = Lists.newArrayList();
532 operandClones.add(operand.clone());
abstract QueryStmt clone()
boolean hasAnalyticExprs()
void unnestOperands(Analyzer analyzer)
void setOperandSmap(UnionOperand operand, Analyzer analyzer)
ArrayList< OrderByElement > cloneOrderByElements()
ArrayList< Expr > resultExprs_
void getMaterializedTupleIds(ArrayList< TupleId > tupleIdList)
List< UnionOperand > getAllOperands()
AggregateInfo distinctAggInfo_
LimitElement limitElement_
void materializeRequiredSlots(Analyzer analyzer)
boolean hasAnalyticExprs_
final List< UnionOperand > operands_
void createSortTupleInfo(Analyzer analyzer)
ArrayList< Expr > getResultExprs()
void analyze(Analyzer analyzer)
boolean containsMappingFor(Expr lhsExpr)
boolean hasAnalyticExprs()
boolean hasOrderByClause()
void createMetadata(Analyzer analyzer)
List< UnionOperand > getDistinctOperands()
UnionStmt(List< UnionOperand > operands, ArrayList< OrderByElement > orderByElements, LimitElement limitElement)
ExprSubstitutionMap getSmap()
UnionOperand(QueryStmt queryStmt, Qualifier qualifier)
void unnestOperand(List< UnionOperand > target, Qualifier targetQualifier, UnionOperand operand)
final ExprSubstitutionMap aliasSmap_
ArrayList< SlotDescriptor > getSlots()
ArrayList< Expr > baseTblResultExprs_
void setQualifier(Qualifier qualifier)
final List< UnionOperand > allOperands_
void analyze(Analyzer parent)
final ExprSubstitutionMap smap_
void materializeSlots(Analyzer analyzer, List< Expr > exprs)
String queryStmtToSql(QueryStmt queryStmt)
ArrayList< Expr > getBaseTblResultExprs()
ArrayList< OrderByElement > orderByElements_
final List< UnionOperand > distinctOperands_
WithClause cloneWithClause()
final QueryStmt queryStmt_
void createSortInfo(Analyzer analyzer)
ArrayList< String > getColLabels()
List< UnionOperand > getOperands()
AggregateInfo getDistinctAggInfo()