@Override public void analyze(Analyzer analyzer) throws AnalysisException { if (isExplain_) analyzer.setIsExplain(); try { if (withClause_ != null) withClause_.analyze(analyzer); } catch (AnalysisException e) { // Ignore AnalysisExceptions if tables are missing to ensure the maximum number // of missing tables can be collected before failing analyze(). if (analyzer.getMissingTbls().isEmpty()) throw e; } List<Expr> selectListExprs = null; if (!needsGeneratedQueryStatement_) { try { // Use a child analyzer for the query stmt to properly scope WITH-clause // views and to ignore irrelevant ORDER BYs. Analyzer queryStmtAnalyzer = new Analyzer(analyzer); queryStmt_.analyze(queryStmtAnalyzer); if (analyzer.containsSubquery()) { Preconditions.checkState(queryStmt_ instanceof SelectStmt); StmtRewriter.rewriteStatement((SelectStmt) queryStmt_, queryStmtAnalyzer); queryStmt_ = queryStmt_.clone(); queryStmtAnalyzer = new Analyzer(analyzer); queryStmt_.analyze(queryStmtAnalyzer); } selectListExprs = Expr.cloneList(queryStmt_.getBaseTblResultExprs()); } catch (AnalysisException e) { if (analyzer.getMissingTbls().isEmpty()) throw e; } } else { selectListExprs = Lists.newArrayList(); } // Set target table and perform table-type specific analysis and auth checking. // Also checks if the target table is missing. setTargetTable(analyzer); // Abort analysis if there are any missing tables beyond this point. if (!analyzer.getMissingTbls().isEmpty()) { throw new AnalysisException("Found missing tables. Aborting analysis."); } boolean isHBaseTable = (table_ instanceof HBaseTable); int numClusteringCols = isHBaseTable ? 0 : table_.getNumClusteringCols(); // Analysis of the INSERT statement from this point is basically the act of matching // the set of output columns (which come from a column permutation, perhaps // implicitly, and the PARTITION clause) to the set of input columns (which come from // the select-list and any statically-valued columns in the PARTITION clause). // // First, we compute the set of mentioned columns, and reject statements that refer to // non-existent columns, or duplicates (we must check both the column permutation, and // the set of partition keys). Next, we check that all partition columns are // mentioned. During this process we build the map from select-list expr index to // column in the targeted table. // // Then we check that the select-list contains exactly the right number of expressions // for all mentioned columns which are not statically-valued partition columns (which // get their expressions from partitionKeyValues). // // Finally, prepareExpressions analyzes the expressions themselves, and confirms that // they are type-compatible with the target columns. Where columns are not mentioned // (and by this point, we know that missing columns are not partition columns), // prepareExpressions assigns them a NULL literal expressions. // An null permutation clause is the same as listing all non-partition columns in // order. List<String> analysisColumnPermutation = columnPermutation_; if (analysisColumnPermutation == null) { analysisColumnPermutation = Lists.newArrayList(); ArrayList<Column> tableColumns = table_.getColumns(); for (int i = numClusteringCols; i < tableColumns.size(); ++i) { analysisColumnPermutation.add(tableColumns.get(i).getName()); } } // selectExprTargetColumns maps from select expression index to a column in the target // table. It will eventually include all mentioned columns that aren't static-valued // partition columns. ArrayList<Column> selectExprTargetColumns = Lists.newArrayList(); // Tracks the name of all columns encountered in either the permutation clause or the // partition clause to detect duplicates. Set<String> mentionedColumnNames = Sets.newHashSet(); for (String columnName : analysisColumnPermutation) { Column column = table_.getColumn(columnName); if (column == null) { throw new AnalysisException("Unknown column '" + columnName + "' in column permutation"); } if (!mentionedColumnNames.add(columnName)) { throw new AnalysisException("Duplicate column '" + columnName + "' in column permutation"); } selectExprTargetColumns.add(column); } int numStaticPartitionExprs = 0; if (partitionKeyValues_ != null) { for (PartitionKeyValue pkv : partitionKeyValues_) { Column column = table_.getColumn(pkv.getColName()); if (column == null) { throw new AnalysisException( "Unknown column '" + pkv.getColName() + "' in partition clause"); } if (column.getPosition() >= numClusteringCols) { throw new AnalysisException( "Column '" + pkv.getColName() + "' is not a partition column"); } if (!mentionedColumnNames.add(pkv.getColName())) { throw new AnalysisException( "Duplicate column '" + pkv.getColName() + "' in partition clause"); } if (!pkv.isDynamic()) { numStaticPartitionExprs++; } else { selectExprTargetColumns.add(column); } } } // Checks that exactly all columns in the target table are assigned an expr. checkColumnCoverage( selectExprTargetColumns, mentionedColumnNames, selectListExprs.size(), numStaticPartitionExprs); // Make sure static partition key values only contain const exprs. if (partitionKeyValues_ != null) { for (PartitionKeyValue kv : partitionKeyValues_) { kv.analyze(analyzer); } } // Populate partitionKeyExprs from partitionKeyValues and selectExprTargetColumns prepareExpressions(selectExprTargetColumns, selectListExprs, table_, analyzer); // Analyze plan hints at the end to prefer reporting other error messages first // (e.g., the PARTITION clause is not applicable to unpartitioned and HBase tables). analyzePlanHints(analyzer); }
/** Creates resultExprs and baseTblResultExprs. */ @Override public void analyze(Analyzer analyzer) throws AnalysisException, AuthorizationException { super.analyze(analyzer); // Replace BaseTableRefs with ViewRefs. substituteViews(analyzer, tableRefs_); // start out with table refs to establish aliases TableRef leftTblRef = null; // the one to the left of tblRef for (TableRef tblRef : tableRefs_) { tblRef.setLeftTblRef(leftTblRef); try { tblRef.analyze(analyzer); } catch (AnalysisException e) { // Only re-throw the exception if no tables are missing. if (analyzer.getMissingTbls().isEmpty()) throw e; } leftTblRef = tblRef; } // All tableRefs have been analyzed, but at least one table was found missing. // There is no reason to proceed with analysis past this point. if (!analyzer.getMissingTbls().isEmpty()) { throw new AnalysisException("Found missing tables. Aborting analysis."); } // populate selectListExprs, aliasSMap, and colNames for (int i = 0; i < selectList_.getItems().size(); ++i) { SelectListItem item = selectList_.getItems().get(i); if (item.isStar()) { TableName tblName = item.getTblName(); if (tblName == null) { expandStar(analyzer); } else { expandStar(analyzer, tblName); } } else { // Analyze the resultExpr before generating a label to ensure enforcement // of expr child and depth limits (toColumn() label may call toSql()). item.getExpr().analyze(analyzer); resultExprs_.add(item.getExpr()); String label = item.toColumnLabel(i, analyzer.useHiveColLabels()); SlotRef aliasRef = new SlotRef(null, label); if (aliasSmap_.containsMappingFor(aliasRef)) { // If we have already seen this alias, it refers to more than one column and // therefore is ambiguous. ambiguousAliasList_.add(aliasRef); } aliasSmap_.addMapping(aliasRef, item.getExpr().clone(null)); colLabels_.add(label); } } if (whereClause_ != null) { whereClause_.analyze(analyzer); if (whereClause_.contains(Expr.isAggregatePredicate())) { throw new AnalysisException("aggregate function not allowed in WHERE clause"); } whereClause_.checkReturnsBool("WHERE clause", false); analyzer.registerConjuncts(whereClause_, null, true); } createSortInfo(analyzer); analyzeAggregation(analyzer); // Remember the SQL string before inline-view expression substitution. sqlString_ = toSql(); resolveInlineViewRefs(analyzer); if (aggInfo_ != null) LOG.debug("post-analysis " + aggInfo_.debugString()); }