Representation of the MERGE statement. The MERGE statement has one target table, and a source expression that is joined with an ON clause. The statement consists of WHEN MATCHED / WHEN NOT MATCHED clauses referenced as merge cases, the evaluation of these cases are following the order of their defin
| 40 | * of the target table by conditions defined by merge cases. |
| 41 | */ |
| 42 | public class MergeStmt extends DmlStatementBase { |
| 43 | private static final int MERGE_CASE_LIMIT = 1000; |
| 44 | private TableRef targetTableRef_; |
| 45 | private TableRef sourceTableRef_; |
| 46 | private final List<MergeCase> cases_; |
| 47 | private final Expr onClause_; |
| 48 | private MergeImpl impl_; |
| 49 | |
| 50 | public MergeStmt(TableRef target, TableRef source, Expr onClause, |
| 51 | List<MergeCase> cases) { |
| 52 | targetTableRef_ = target; |
| 53 | sourceTableRef_ = source; |
| 54 | onClause_ = onClause; |
| 55 | cases_ = cases; |
| 56 | } |
| 57 | |
| 58 | @Override |
| 59 | public void analyze(Analyzer analyzer) throws AnalysisException { |
| 60 | if (isAnalyzed()) return; |
| 61 | super.analyze(analyzer); |
| 62 | if (targetTableRef_ instanceof InlineViewRef) { |
| 63 | throw new AnalysisException( |
| 64 | String.format("Cannot modify view: %s", targetTableRef_.toSql())); |
| 65 | } |
| 66 | |
| 67 | if (cases_.size() > MERGE_CASE_LIMIT) { |
| 68 | String sql = toSql(); |
| 69 | String sqlSubstr = sql.substring(0, Math.min(80, sql.length())); |
| 70 | throw new AnalysisException(String.format("Exceeded the maximum number of cases " + |
| 71 | "(%s).\nStatement has %s cases:\n%s...", |
| 72 | MERGE_CASE_LIMIT, cases_.size(), sqlSubstr)); |
| 73 | } |
| 74 | |
| 75 | sourceTableRef_ = analyzer.resolveTableRef(sourceTableRef_); |
| 76 | targetTableRef_ = analyzer.resolveTableRef(targetTableRef_); |
| 77 | |
| 78 | table_ = targetTableRef_.getTable(); |
| 79 | |
| 80 | if (impl_ == null) { |
| 81 | if (table_ instanceof FeIcebergTable) { |
| 82 | impl_ = new IcebergMergeImpl(this, targetTableRef_, sourceTableRef_, onClause_); |
| 83 | setMaxTableSinks(analyzer_.getQueryOptions().getMax_fs_writers()); |
| 84 | } else { |
| 85 | throw new AnalysisException(String.format( |
| 86 | "Target table must be an Iceberg table: %s", table_.getFullName())); |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | impl_.analyze(analyzer); |
| 91 | |
| 92 | for (MergeCase mergeCase : getCases()) { |
| 93 | mergeCase.setParent(this); |
| 94 | mergeCase.analyze(analyzer); |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | @Override |
| 99 | public void collectTableRefs(List<TableRef> tblRefs) { |
nothing calls this directly
no outgoing calls
no test coverage detected