Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
InsertStmt.java
Go to the documentation of this file.
1 // Copyright 2012 Cloudera Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 package com.cloudera.impala.analysis;
16 
17 import java.io.IOException;
18 import java.util.ArrayList;
19 import java.util.List;
20 import java.util.Set;
21 
22 import org.apache.hadoop.fs.Path;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25 
37 import com.google.common.base.Joiner;
38 import com.google.common.base.Preconditions;
39 import com.google.common.collect.Lists;
40 import com.google.common.collect.Sets;
41 
46 public class InsertStmt extends StatementBase {
47  private final static Logger LOG = LoggerFactory.getLogger(InsertStmt.class);
48 
49  // List of inline views that may be referenced in queryStmt.
50  private final WithClause withClause_;
51 
52  // Target table name as seen by the parser
54 
55  // Target table into which to insert. May be qualified by analyze()
57 
58  // Differentiates between INSERT INTO and INSERT OVERWRITE.
59  private final boolean overwrite_;
60 
61  // List of column:value elements from the PARTITION (...) clause.
62  // Set to null if no partition was given.
63  private final List<PartitionKeyValue> partitionKeyValues_;
64 
65  // User-supplied hints to control hash partitioning before the table sink in the plan.
66  private final List<String> planHints_;
67 
68  // Select or union whose results are to be inserted. If null, will be set after
69  // analysis.
71 
72  // False if the original insert statement had a query statement, true if we need to
73  // auto-generate one (for insert into tbl();) during analysis.
74  private final boolean needsGeneratedQueryStatement_;
75 
76  // Set in analyze(). Contains metadata of target table to determine type of sink.
77  private Table table_;
78 
79  // Set in analyze(). Exprs corresponding to the partitionKeyValues,
80  private final List<Expr> partitionKeyExprs_ = new ArrayList<Expr>();
81 
82  // True to force re-partitioning before the table sink, false to prevent it. Set in
83  // analyze() based on planHints_. Null if no explicit hint was given (the planner
84  // should decide whether to re-partition or not).
85  private Boolean isRepartition_ = null;
86 
87  // Output expressions that produce the final results to write to the target table. May
88  // include casts, and NullLiterals where an output column isn't explicitly mentioned.
89  // Set in prepareExpressions(). The i'th expr produces the i'th column of the target
90  // table.
91  private final ArrayList<Expr> resultExprs_ = new ArrayList<Expr>();
92 
93  // The column permutation is specified by writing INSERT INTO tbl(col3, col1, col2...)
94  //
95  // It is a mapping from select-list expr index to (non-partition) output column. If
96  // null, will be set to the default permutation of all non-partition columns in Hive
97  // order.
98  //
99  // A column is said to be 'mentioned' if it occurs either in the column permutation, or
100  // the PARTITION clause. If columnPermutation is null, all non-partition columns are
101  // considered mentioned.
102  //
103  // Between them, the columnPermutation and the set of partitionKeyValues must mention to
104  // every partition column in the target table exactly once. Other columns, if not
105  // explicitly mentioned, will be assigned NULL values. Partition columns are not
106  // defaulted to NULL by design, and are not just for NULL-valued partition slots.
107  //
108  // Dynamic partition keys may occur in either the permutation or the PARTITION
109  // clause. Partition columns with static values may only be mentioned in the PARTITION
110  // clause, where the static value is specified.
111  private final List<String> columnPermutation_;
112 
113  public InsertStmt(WithClause withClause, TableName targetTable, boolean overwrite,
114  List<PartitionKeyValue> partitionKeyValues, List<String> planHints,
115  QueryStmt queryStmt, List<String> columnPermutation) {
116  withClause_ = withClause;
117  targetTableName_ = targetTable;
119  overwrite_ = overwrite;
120  partitionKeyValues_ = partitionKeyValues;
121  planHints_ = planHints;
122  queryStmt_ = queryStmt;
123  needsGeneratedQueryStatement_ = (queryStmt == null);
124  columnPermutation_ = columnPermutation;
125  table_ = null;
126  }
127 
131  public InsertStmt(InsertStmt other) {
132  withClause_ = other.withClause_ != null ? other.withClause_.clone() : null;
133  targetTableName_ = other.targetTableName_;
134  originalTableName_ = other.targetTableName_;
135  overwrite_ = other.overwrite_;
136  partitionKeyValues_ = other.partitionKeyValues_;
137  planHints_ = other.planHints_;
138  queryStmt_ = other.queryStmt_ != null ? other.queryStmt_.clone() : null;
139  needsGeneratedQueryStatement_ = other.needsGeneratedQueryStatement_;
140  columnPermutation_ = other.columnPermutation_;
141  table_ = other.table_;
142  }
143 
144  @Override
145  public InsertStmt clone() { return new InsertStmt(this); }
146 
147  @Override
148  public void analyze(Analyzer analyzer) throws AnalysisException {
149  if (isExplain_) analyzer.setIsExplain();
150  try {
151  if (withClause_ != null) withClause_.analyze(analyzer);
152  } catch (AnalysisException e) {
153  // Ignore AnalysisExceptions if tables are missing to ensure the maximum number
154  // of missing tables can be collected before failing analyze().
155  if (analyzer.getMissingTbls().isEmpty()) throw e;
156  }
157 
158  List<Expr> selectListExprs = null;
160  try {
161  // Use a child analyzer for the query stmt to properly scope WITH-clause
162  // views and to ignore irrelevant ORDER BYs.
163  Analyzer queryStmtAnalyzer = new Analyzer(analyzer);
164  queryStmt_.analyze(queryStmtAnalyzer);
165 
166  if (analyzer.containsSubquery()) {
167  StmtRewriter.rewriteQueryStatement(queryStmt_, queryStmtAnalyzer);
168  queryStmt_ = queryStmt_.clone();
169  queryStmtAnalyzer = new Analyzer(analyzer);
170  queryStmt_.analyze(queryStmtAnalyzer);
171  }
172 
173  selectListExprs = Expr.cloneList(queryStmt_.getBaseTblResultExprs());
174  } catch (AnalysisException e) {
175  if (analyzer.getMissingTbls().isEmpty()) throw e;
176  }
177  } else {
178  selectListExprs = Lists.newArrayList();
179  }
180 
181  // Set target table and perform table-type specific analysis and auth checking.
182  // Also checks if the target table is missing.
183  setTargetTable(analyzer);
184 
185  // Abort analysis if there are any missing tables beyond this point.
186  if (!analyzer.getMissingTbls().isEmpty()) {
187  throw new AnalysisException("Found missing tables. Aborting analysis.");
188  }
189 
190  boolean isHBaseTable = (table_ instanceof HBaseTable);
191  int numClusteringCols = isHBaseTable ? 0 : table_.getNumClusteringCols();
192 
193  // Analysis of the INSERT statement from this point is basically the act of matching
194  // the set of output columns (which come from a column permutation, perhaps
195  // implicitly, and the PARTITION clause) to the set of input columns (which come from
196  // the select-list and any statically-valued columns in the PARTITION clause).
197  //
198  // First, we compute the set of mentioned columns, and reject statements that refer to
199  // non-existent columns, or duplicates (we must check both the column permutation, and
200  // the set of partition keys). Next, we check that all partition columns are
201  // mentioned. During this process we build the map from select-list expr index to
202  // column in the targeted table.
203  //
204  // Then we check that the select-list contains exactly the right number of expressions
205  // for all mentioned columns which are not statically-valued partition columns (which
206  // get their expressions from partitionKeyValues).
207  //
208  // Finally, prepareExpressions analyzes the expressions themselves, and confirms that
209  // they are type-compatible with the target columns. Where columns are not mentioned
210  // (and by this point, we know that missing columns are not partition columns),
211  // prepareExpressions assigns them a NULL literal expressions.
212 
213  // An null permutation clause is the same as listing all non-partition columns in
214  // order.
215  List<String> analysisColumnPermutation = columnPermutation_;
216  if (analysisColumnPermutation == null) {
217  analysisColumnPermutation = Lists.newArrayList();
218  ArrayList<Column> tableColumns = table_.getColumns();
219  for (int i = numClusteringCols; i < tableColumns.size(); ++i) {
220  analysisColumnPermutation.add(tableColumns.get(i).getName());
221  }
222  }
223 
224  // selectExprTargetColumns maps from select expression index to a column in the target
225  // table. It will eventually include all mentioned columns that aren't static-valued
226  // partition columns.
227  ArrayList<Column> selectExprTargetColumns = Lists.newArrayList();
228 
229  // Tracks the name of all columns encountered in either the permutation clause or the
230  // partition clause to detect duplicates.
231  Set<String> mentionedColumnNames = Sets.newHashSet();
232  for (String columnName: analysisColumnPermutation) {
233  Column column = table_.getColumn(columnName);
234  if (column == null) {
235  throw new AnalysisException(
236  "Unknown column '" + columnName + "' in column permutation");
237  }
238 
239  if (!mentionedColumnNames.add(columnName)) {
240  throw new AnalysisException(
241  "Duplicate column '" + columnName + "' in column permutation");
242  }
243  selectExprTargetColumns.add(column);
244  }
245 
246  int numStaticPartitionExprs = 0;
247  if (partitionKeyValues_ != null) {
249  Column column = table_.getColumn(pkv.getColName());
250  if (column == null) {
251  throw new AnalysisException("Unknown column '" + pkv.getColName() +
252  "' in partition clause");
253  }
254 
255  if (column.getPosition() >= numClusteringCols) {
256  throw new AnalysisException(
257  "Column '" + pkv.getColName() + "' is not a partition column");
258  }
259 
260  if (!mentionedColumnNames.add(pkv.getColName())) {
261  throw new AnalysisException(
262  "Duplicate column '" + pkv.getColName() + "' in partition clause");
263  }
264  if (!pkv.isDynamic()) {
265  numStaticPartitionExprs++;
266  } else {
267  selectExprTargetColumns.add(column);
268  }
269  }
270  }
271 
272  // Checks that exactly all columns in the target table are assigned an expr.
273  checkColumnCoverage(selectExprTargetColumns, mentionedColumnNames,
274  selectListExprs.size(), numStaticPartitionExprs);
275 
276  // Make sure static partition key values only contain const exprs.
277  if (partitionKeyValues_ != null) {
279  kv.analyze(analyzer);
280  }
281  }
282 
283  // Populate partitionKeyExprs from partitionKeyValues and selectExprTargetColumns
284  prepareExpressions(selectExprTargetColumns, selectListExprs, table_, analyzer);
285  // Analyze plan hints at the end to prefer reporting other error messages first
286  // (e.g., the PARTITION clause is not applicable to unpartitioned and HBase tables).
287  analyzePlanHints(analyzer);
288  }
289 
298  private void setTargetTable(Analyzer analyzer) throws AnalysisException {
299  // If the table has not yet been set, load it from the Catalog. This allows for
300  // callers to set a table to analyze that may not actually be created in the Catalog.
301  // One example use case is CREATE TABLE AS SELECT which must run analysis on the
302  // INSERT before the table has actually been created.
303  if (table_ == null) {
306  new TableName(analyzer.getDefaultDb(), targetTableName_.getTbl());
307  }
308  table_ = analyzer.getTable(targetTableName_, Privilege.INSERT);
309  } else {
310  targetTableName_ = new TableName(table_.getDb().getName(), table_.getName());
312  analyzer.registerPrivReq(pb.onTable(table_.getDb().getName(), table_.getName())
313  .allOf(Privilege.INSERT).toRequest());
314  }
315 
316  // We do not support inserting into views.
317  if (table_ instanceof View) {
318  throw new AnalysisException(
319  String.format("Impala does not support inserting into views: %s",
320  table_.getFullName()));
321  }
322 
323 
324  boolean isHBaseTable = (table_ instanceof HBaseTable);
325  int numClusteringCols = isHBaseTable ? 0 : table_.getNumClusteringCols();
326 
327  if (partitionKeyValues_ != null && numClusteringCols == 0) {
328  if (isHBaseTable) {
329  throw new AnalysisException("PARTITION clause is not valid for INSERT into " +
330  "HBase tables. '" + targetTableName_ + "' is an HBase table");
331 
332  } else {
333  // Unpartitioned table, but INSERT has PARTITION clause
334  throw new AnalysisException("PARTITION clause is only valid for INSERT into " +
335  "partitioned table. '" + targetTableName_ + "' is not partitioned");
336  }
337  }
338 
339  if (table_ instanceof HdfsTable) {
340  HdfsTable hdfsTable = (HdfsTable) table_;
341  if (!hdfsTable.hasWriteAccess()) {
342  throw new AnalysisException(String.format("Unable to INSERT into target table " +
343  "(%s) because Impala does not have WRITE access to at least one HDFS path" +
345  }
346  if (hdfsTable.spansMultipleFileSystems()) {
347  throw new AnalysisException(String.format("Unable to INSERT into target table " +
348  "(%s) because the table spans multiple filesystems.", targetTableName_));
349  }
350  try {
351  if (!FileSystemUtil.isDistributedFileSystem(new Path(hdfsTable.getLocation()))) {
352  throw new AnalysisException(String.format("Unable to INSERT into target " +
353  "table (%s) because %s is not an HDFS filesystem.", targetTableName_,
354  hdfsTable.getLocation()));
355  }
356  } catch (IOException e) {
357  throw new AnalysisException(String.format("Unable to INSERT into target " +
358  "table (%s): %s.", targetTableName_, e.getMessage()), e);
359  }
360  for (int colIdx = 0; colIdx < numClusteringCols; ++colIdx) {
361  Column col = hdfsTable.getColumns().get(colIdx);
362  // Hive has a number of issues handling BOOLEAN partition columns (see HIVE-6590).
363  // Instead of working around the Hive bugs, INSERT is disabled for BOOLEAN
364  // partitions in Impala. Once the Hive JIRA is resolved, we can remove this
365  // analysis check.
366  if (col.getType() == Type.BOOLEAN) {
367  throw new AnalysisException(String.format("INSERT into table with BOOLEAN " +
368  "partition column (%s) is not supported: %s", col.getName(),
370  }
371  }
372  }
373 
374  if (isHBaseTable && overwrite_) {
375  throw new AnalysisException("HBase doesn't have a way to perform INSERT OVERWRITE");
376  }
377 
378  // Add target table to descriptor table.
379  analyzer.getDescTbl().addReferencedTable(table_);
380  }
381 
387  private void checkColumnCoverage(ArrayList<Column> selectExprTargetColumns,
388  Set<String> mentionedColumnNames, int numSelectListExprs,
389  int numStaticPartitionExprs) throws AnalysisException {
390  boolean isHBaseTable = (table_ instanceof HBaseTable);
391  int numClusteringCols = isHBaseTable ? 0 : table_.getNumClusteringCols();
392  // Check that all columns are mentioned by the permutation and partition clauses
393  if (selectExprTargetColumns.size() + numStaticPartitionExprs !=
394  table_.getColumns().size()) {
395  // We've already ruled out too many columns in the permutation and partition clauses
396  // by checking that there are no duplicates and that every column mentioned actually
397  // exists. So all columns aren't mentioned in the query. If the unmentioned columns
398  // include partition columns, this is an error.
399  List<String> missingColumnNames = Lists.newArrayList();
400  for (Column column: table_.getColumns()) {
401  if (!mentionedColumnNames.contains(column.getName())) {
402  // HBase tables have a single row-key column which is always in position 0. It
403  // must be mentioned, since it is invalid to set it to NULL (which would
404  // otherwise happen by default).
405  if (isHBaseTable && column.getPosition() == 0) {
406  throw new AnalysisException("Row-key column '" + column.getName() +
407  "' must be explicitly mentioned in column permutation.");
408  }
409  if (column.getPosition() < numClusteringCols) {
410  missingColumnNames.add(column.getName());
411  }
412  }
413  }
414 
415  if (!missingColumnNames.isEmpty()) {
416  throw new AnalysisException(
417  "Not enough partition columns mentioned in query. Missing columns are: " +
418  Joiner.on(", ").join(missingColumnNames));
419  }
420  }
421 
422  // Expect the selectListExpr to have entries for every target column
423  if (selectExprTargetColumns.size() != numSelectListExprs) {
424  String comparator =
425  (selectExprTargetColumns.size() < numSelectListExprs) ? "fewer" : "more";
426  String partitionClause =
427  (partitionKeyValues_ == null) ? "returns" : "and PARTITION clause return";
428 
429  // If there was no column permutation provided, the error is that the select-list
430  // has the wrong number of expressions compared to the number of columns in the
431  // table. If there was a column permutation, then the mismatch is between the
432  // select-list and the permutation itself.
433  if (columnPermutation_ == null) {
434  int totalColumnsMentioned = numSelectListExprs + numStaticPartitionExprs;
435  throw new AnalysisException(String.format(
436  "Target table '%s' has %s columns (%s) than the SELECT / VALUES clause %s" +
437  " (%s)", table_.getFullName(), comparator,
438  table_.getColumns().size(), partitionClause, totalColumnsMentioned));
439  } else {
440  String partitionPrefix =
441  (partitionKeyValues_ == null) ? "mentions" : "and PARTITION clause mention";
442  throw new AnalysisException(String.format(
443  "Column permutation %s %s columns (%s) than " +
444  "the SELECT / VALUES clause %s (%s)", partitionPrefix, comparator,
445  selectExprTargetColumns.size(), partitionClause, numSelectListExprs));
446  }
447  }
448  }
449 
467  private void prepareExpressions(List<Column> selectExprTargetColumns,
468  List<Expr> selectListExprs, Table tbl, Analyzer analyzer)
469  throws AnalysisException {
470  // Temporary lists of partition key exprs and names in an arbitrary order.
471  List<Expr> tmpPartitionKeyExprs = new ArrayList<Expr>();
472  List<String> tmpPartitionKeyNames = new ArrayList<String>();
473 
474  int numClusteringCols = (tbl instanceof HBaseTable) ? 0 : tbl.getNumClusteringCols();
475 
476  // Check dynamic partition columns for type compatibility.
477  for (int i = 0; i < selectListExprs.size(); ++i) {
478  Column targetColumn = selectExprTargetColumns.get(i);
479  Expr compatibleExpr = checkTypeCompatibility(targetColumn, selectListExprs.get(i));
480  if (targetColumn.getPosition() < numClusteringCols) {
481  // This is a dynamic clustering column
482  tmpPartitionKeyExprs.add(compatibleExpr);
483  tmpPartitionKeyNames.add(targetColumn.getName());
484  }
485  selectListExprs.set(i, compatibleExpr);
486  }
487 
488  // Check static partition columns, dynamic entries in partitionKeyValues will already
489  // be in selectExprTargetColumns and therefore are ignored in this loop
490  if (partitionKeyValues_ != null) {
492  if (pkv.isStatic()) {
493  // tableColumns is guaranteed to exist after the earlier analysis checks
494  Column tableColumn = table_.getColumn(pkv.getColName());
495  Expr compatibleExpr = checkTypeCompatibility(tableColumn, pkv.getValue());
496  tmpPartitionKeyExprs.add(compatibleExpr);
497  tmpPartitionKeyNames.add(pkv.getColName());
498  }
499  }
500  }
501 
502  // Reorder the partition key exprs and names to be consistent with the target table
503  // declaration. We need those exprs in the original order to create the corresponding
504  // Hdfs folder structure correctly.
505  for (Column c: table_.getColumns()) {
506  for (int j = 0; j < tmpPartitionKeyNames.size(); ++j) {
507  if (c.getName().equals(tmpPartitionKeyNames.get(j))) {
508  partitionKeyExprs_.add(tmpPartitionKeyExprs.get(j));
509  break;
510  }
511  }
512  }
513 
514  Preconditions.checkState(partitionKeyExprs_.size() == numClusteringCols);
515  // Make sure we have stats for partitionKeyExprs
516  for (Expr expr: partitionKeyExprs_) {
517  expr.analyze(analyzer);
518  }
519 
520  // Finally, 'undo' the permutation so that the selectListExprs are in Hive column
521  // order, and add NULL expressions to all missing columns.
522  for (Column tblColumn: table_.getColumnsInHiveOrder()) {
523  boolean matchFound = false;
524  for (int i = 0; i < selectListExprs.size(); ++i) {
525  if (selectExprTargetColumns.get(i).getName().equals(tblColumn.getName())) {
526  resultExprs_.add(selectListExprs.get(i));
527  matchFound = true;
528  break;
529  }
530  }
531  // If no match is found, either the column is a clustering column with a static
532  // value, or it was unmentioned and therefore should have a NULL select-list
533  // expression.
534  if (!matchFound) {
535  if (tblColumn.getPosition() >= numClusteringCols) {
536  // Unmentioned non-clustering columns get NULL literals with the appropriate
537  // target type because Parquet cannot handle NULL_TYPE (IMPALA-617).
538  resultExprs_.add(NullLiteral.create(tblColumn.getType()));
539  }
540  }
541  }
542  // TODO: Check that HBase row-key columns are not NULL? See IMPALA-406
544  // Build a query statement that returns NULL for every column
545  List<SelectListItem> selectListItems = Lists.newArrayList();
546  for(Expr e: resultExprs_) {
547  selectListItems.add(new SelectListItem(e, null));
548  }
549  SelectList selectList = new SelectList(selectListItems);
550  queryStmt_ = new SelectStmt(selectList, null, null, null, null, null, null);
551  queryStmt_.analyze(analyzer);
552  }
553  }
554 
559  private Expr checkTypeCompatibility(Column column, Expr expr)
560  throws AnalysisException {
561  // Check for compatible type, and add casts to the selectListExprs if necessary.
562  // We don't allow casting to a lower precision type.
563  Type colType = column.getType();
564  Type exprType = expr.getType();
565  // Trivially compatible, unless the type is complex.
566  if (colType.equals(exprType) && !colType.isComplexType()) return expr;
567 
568  Type compatibleType =
569  Type.getAssignmentCompatibleType(colType, exprType);
570  // Incompatible types.
571  if (!compatibleType.isValid()) {
572  throw new AnalysisException(
573  String.format(
574  "Target table '%s' is incompatible with SELECT / PARTITION expressions.\n" +
575  "Expression '%s' (type: %s) is not compatible with column '%s' (type: %s)",
576  targetTableName_, expr.toSql(), exprType.toSql(), column.getName(),
577  colType.toSql()));
578  }
579  // Loss of precision when inserting into the table.
580  if (!compatibleType.equals(colType) && !compatibleType.isNull()) {
581  throw new AnalysisException(
582  String.format("Possible loss of precision for target table '%s'.\n" +
583  "Expression '%s' (type: %s) would need to be cast to %s" +
584  " for column '%s'",
585  targetTableName_, expr.toSql(), exprType.toSql(),
586  colType.toSql(), column.getName()));
587  }
588  // Add a cast to the selectListExpr to the higher type.
589  return expr.castTo(compatibleType);
590  }
591 
592  private void analyzePlanHints(Analyzer analyzer) throws AnalysisException {
593  if (planHints_ == null) return;
594  if (!planHints_.isEmpty() &&
595  (partitionKeyValues_ == null || table_ instanceof HBaseTable)) {
596  throw new AnalysisException("INSERT hints are only supported for inserting into " +
597  "partitioned Hdfs tables.");
598  }
599  for (String hint: planHints_) {
600  if (hint.equalsIgnoreCase("SHUFFLE")) {
601  if (isRepartition_ != null && !isRepartition_) {
602  throw new AnalysisException("Conflicting INSERT hint: " + hint);
603  }
604  isRepartition_ = Boolean.TRUE;
605  analyzer.setHasPlanHints();
606  } else if (hint.equalsIgnoreCase("NOSHUFFLE")) {
607  if (isRepartition_ != null && isRepartition_) {
608  throw new AnalysisException("Conflicting INSERT hint: " + hint);
609  }
610  isRepartition_ = Boolean.FALSE;
611  analyzer.setHasPlanHints();
612  } else {
613  analyzer.addWarning("INSERT hint not recognized: " + hint);
614  }
615  }
616  }
617 
618  public List<String> getPlanHints() { return planHints_; }
620  public Table getTargetTable() { return table_; }
621  public void setTargetTable(Table table) { this.table_ = table; }
622  public boolean isOverwrite() { return overwrite_; }
623 
627  public QueryStmt getQueryStmt() { return queryStmt_; }
628  public void setQueryStmt(QueryStmt stmt) { queryStmt_ = stmt; }
629  public List<Expr> getPartitionKeyExprs() { return partitionKeyExprs_; }
630  public Boolean isRepartition() { return isRepartition_; }
631  public ArrayList<Expr> getResultExprs() { return resultExprs_; }
632 
634  // analyze() must have been called before.
635  Preconditions.checkState(table_ != null);
636  return DataSink.createDataSink(table_, partitionKeyExprs_, overwrite_);
637  }
638 
639  @Override
640  public String toSql() {
641  StringBuilder strBuilder = new StringBuilder();
642 
643  if (withClause_ != null) strBuilder.append(withClause_.toSql() + " ");
644 
645  strBuilder.append("INSERT ");
646  if (overwrite_) {
647  strBuilder.append("OVERWRITE ");
648  } else {
649  strBuilder.append("INTO ");
650  }
651  strBuilder.append("TABLE " + originalTableName_);
652  if (columnPermutation_ != null) {
653  strBuilder.append("(");
654  strBuilder.append(Joiner.on(", ").join(columnPermutation_));
655  strBuilder.append(")");
656  }
657  if (partitionKeyValues_ != null) {
658  List<String> values = Lists.newArrayList();
660  values.add(pkv.getColName() +
661  (pkv.getValue() != null ? ("=" + pkv.getValue().toSql()) : ""));
662  }
663  strBuilder.append(" PARTITION (" + Joiner.on(", ").join(values) + ")");
664  }
665  if (planHints_ != null) {
666  strBuilder.append(" " + ToSqlUtils.getPlanHintsSql(planHints_));
667  }
669  strBuilder.append(" " + queryStmt_.toSql());
670  }
671  return strBuilder.toString();
672  }
673 }
ArrayList< Column > getColumnsInHiveOrder()
Definition: Table.java:373
Expr checkTypeCompatibility(Column column, Expr expr)
void setTargetTable(Analyzer analyzer)
static final ScalarType BOOLEAN
Definition: Type.java:46
ArrayList< Column > getColumns()
Definition: Table.java:349
static boolean isDistributedFileSystem(FileSystem fs)
void analyzePlanHints(Analyzer analyzer)
final ArrayList< Expr > resultExprs_
Definition: InsertStmt.java:91
void checkColumnCoverage(ArrayList< Column > selectExprTargetColumns, Set< String > mentionedColumnNames, int numSelectListExprs, int numStaticPartitionExprs)
InsertStmt(WithClause withClause, TableName targetTable, boolean overwrite, List< PartitionKeyValue > partitionKeyValues, List< String > planHints, QueryStmt queryStmt, List< String > columnPermutation)
void prepareExpressions(List< Column > selectExprTargetColumns, List< Expr > selectListExprs, Table tbl, Analyzer analyzer)
final List< PartitionKeyValue > partitionKeyValues_
Definition: InsertStmt.java:63