All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.hadoop.hive.ql.parse.DeleteSemanticAnalyzer Maven / Gradle / Ivy

/*
 * 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 org.apache.hadoop.hive.ql.parse;

import org.apache.hadoop.hive.common.TableName;
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.hive.ql.Context;
import org.apache.hadoop.hive.ql.QueryState;
import org.apache.hadoop.hive.ql.ddl.DDLDesc.DDLDescWithWriteId;
import org.apache.hadoop.hive.ql.ddl.DDLWork;
import org.apache.hadoop.hive.ql.ddl.table.execute.AlterTableExecuteDesc;
import org.apache.hadoop.hive.ql.exec.TableScanOperator;
import org.apache.hadoop.hive.ql.exec.TaskFactory;
import org.apache.hadoop.hive.ql.io.sarg.ConvertAstToSearchArg;
import org.apache.hadoop.hive.ql.io.sarg.SearchArgument;
import org.apache.hadoop.hive.ql.lib.Node;
import org.apache.hadoop.hive.ql.metadata.Table;
import org.apache.hadoop.hive.ql.parse.rewrite.DeleteStatement;
import org.apache.hadoop.hive.ql.parse.rewrite.RewriterFactory;
import org.apache.hadoop.hive.ql.plan.ExprNodeGenericFuncDesc;

import java.util.Collections;
import java.util.List;
import java.util.Map;

public class DeleteSemanticAnalyzer extends RewriteSemanticAnalyzer {
  private DDLDescWithWriteId acidDdlDesc;

  public DeleteSemanticAnalyzer(QueryState queryState, RewriterFactory rewriterFactory)
      throws SemanticException {
    super(queryState, rewriterFactory);
  }

  @Override
  protected ASTNode getTargetTableNode(ASTNode tree) {
    // The first child should be the table we are updating / deleting from
    ASTNode tabName = (ASTNode) tree.getChild(0);
    assert tabName.getToken().getType() == HiveParser.TOK_TABNAME :
        "Expected tablename as first child of " + Context.Operation.DELETE + " but found " + tabName.getName();
    return tabName;
  }

  @Override
  protected void analyze(ASTNode tree, Table table, ASTNode tableName) throws SemanticException {
    List children = tree.getChildren();

    ASTNode where = null;
    if (children.size() > 1) {
      where = (ASTNode) children.get(1);
      assert where.getToken().getType() == HiveParser.TOK_WHERE :
          "Expected where clause, but found " + where.getName();
    }

    boolean shouldTruncate = HiveConf.getBoolVar(conf, HiveConf.ConfVars.HIVE_OPTIMIZE_REPLACE_DELETE_WITH_TRUNCATE)
        && where == null;
    if (shouldTruncate) {
      genTruncatePlan(table, tableName);
      return;
    } else if (tryMetadataUpdate(table, tableName, where)) {
      return;
    }

    rewriteAndAnalyze(new DeleteStatement(table, where), null);

    updateOutputs(table);
  }

  private void genTruncatePlan(Table table, ASTNode tabNameNode) throws SemanticException {
    String rewrittenQueryStr = "truncate " + getFullTableNameForSQL(tabNameNode);
    ParseUtils.ReparseResult rr = ParseUtils.parseRewrittenQuery(ctx, rewrittenQueryStr);
    Context rewrittenCtx = rr.rewrittenCtx;
    ASTNode rewrittenTree = rr.rewrittenTree;

    BaseSemanticAnalyzer truncate = SemanticAnalyzerFactory.get(queryState, rewrittenTree);
    // Note: this will overwrite this.ctx with rewrittenCtx
    rewrittenCtx.setEnableUnparse(false);
    truncate.analyze(rewrittenTree, rewrittenCtx);
    acidDdlDesc = truncate.getAcidDdlDesc();
    rootTasks = truncate.getRootTasks();
    outputs = truncate.getOutputs();
    updateOutputs(table);
  }

  private boolean tryMetadataUpdate(Table table, ASTNode tabNameNode, ASTNode whereNode)
      throws SemanticException {
    // A feature flag on Hive to perform metadata delete on the source table.
    if (!HiveConf.getBoolVar(conf, HiveConf.ConfVars.HIVE_OPTIMIZE_METADATA_DELETE)) {
      return false;
    }
    if (whereNode == null || table.getStorageHandler() == null) {
      return false;
    }
    TableName tableName = getQualifiedTableName(tabNameNode);
    String whereClause = ctx.getTokenRewriteStream().toString(
        whereNode.getChild(0).getTokenStartIndex(), whereNode.getChild(0).getTokenStopIndex());
    StringBuilder sb = new StringBuilder("select * from ").append(getFullTableNameForSQL(tabNameNode))
        .append(" where ").append(whereClause);
    Context context = new Context(conf);
    ASTNode rewrittenTree;
    try {
      rewrittenTree = ParseUtils.parse(sb.toString(), context);
    } catch (ParseException pe) {
      throw new SemanticException(pe);
    }
    BaseSemanticAnalyzer sem = SemanticAnalyzerFactory.get(queryState, rewrittenTree);
    sem.analyze(rewrittenTree, context);

    SearchArgument sarg = convertFilterExpressionInTS(table, sem);
    if (sarg == null) {
      return false;
    }
    if (!table.getStorageHandler().canPerformMetadataDelete(table, tableName.getTableMetaRef(), sarg)) {
      return false;
    }

    DDLWork ddlWork = createDDLWorkOfMetadataUpdate(tableName, sarg);
    rootTasks = Collections.singletonList(TaskFactory.get(ddlWork));
    inputs = sem.getInputs();
    outputs = sem.getOutputs();
    updateOutputs(table);
    return true;
  }

  private SearchArgument convertFilterExpressionInTS(Table table, BaseSemanticAnalyzer sem) {
    Map topOps = sem.getParseContext().getTopOps();
    if (!topOps.containsKey(table.getTableName())) {
      return null;
    }
    ExprNodeGenericFuncDesc hiveFilter = topOps.get(table.getTableName()).getConf().getFilterExpr();
    if (hiveFilter == null) {
      return null;
    }
    ConvertAstToSearchArg.Result result = ConvertAstToSearchArg.createSearchArgument(ctx.getConf(), hiveFilter);
    if (result.isPartial()) {
      return null;
    }
    return result.getSearchArgument();
  }

  private DDLWork createDDLWorkOfMetadataUpdate(TableName tableName, SearchArgument sarg) throws SemanticException {
    AlterTableExecuteSpec.DeleteMetadataSpec deleteMetadataSpec =
        new AlterTableExecuteSpec.DeleteMetadataSpec(tableName.getTableMetaRef(), sarg);
    AlterTableExecuteSpec executeSpec =
        new AlterTableExecuteSpec<>(AlterTableExecuteSpec.ExecuteOperationType.DELETE_METADATA, deleteMetadataSpec);
    AlterTableExecuteDesc desc = new AlterTableExecuteDesc(tableName, null, executeSpec);
    return new DDLWork(getInputs(), getOutputs(), desc);
  }

  @Override
  protected boolean enableColumnStatsCollecting() {
    return false;
  }

  @Override
  public DDLDescWithWriteId getAcidDdlDesc() {
    return acidDdlDesc;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy