private void dropTableOrViewInternal()

in fe/src/main/java/org/apache/impala/service/CatalogOpExecutor.java [3154:3305]


  private void dropTableOrViewInternal(TDropTableOrViewParams params,
      TableName tableName, TDdlExecResponse resp, int kudu_table_reserve_seconds,
      EventSequence catalogTimeline) throws ImpalaException {
    TCatalogObject removedObject = new TCatalogObject();
    acquireMetastoreDdlLock(catalogTimeline);
    try {
      Db db = catalog_.getDb(params.getTable_name().db_name);
      if (db == null) {
        String dbNotExist = "Database does not exist: " + params.getTable_name().db_name;
        if (params.if_exists) {
          addSummary(resp, dbNotExist);
          return;
        }
        throw new CatalogException(dbNotExist);
      }
      Table existingTbl = db.getTable(params.getTable_name().table_name);
      if (existingTbl == null) {
        if (params.if_exists) {
          addSummary(resp, (params.is_table ? "Table " : "View ") + "does not exist.");
          return;
        }
        throw new CatalogException("Table/View does not exist.");
      }

      // Check to make sure we don't drop a view with "drop table" statement and
      // vice versa. is_table field is marked optional in TDropTableOrViewParams to
      // maintain catalog api compatibility.
      // TODO: Remove params.isSetIs_table() check once catalog api compatibility is
      // fixed.
      if (params.isSetIs_table() && ((params.is_table && existingTbl instanceof View)
          || (!params.is_table && !(existingTbl instanceof View)))) {
        String errorMsg = "DROP " + (params.is_table ? "TABLE " : "VIEW ") +
            "not allowed on a " + (params.is_table ? "view: " : "table: ") + tableName;
        if (params.if_exists) {
          addSummary(resp, "Drop " + (params.is_table ? "table " : "view ") +
              "is not allowed on a " + (params.is_table ? "view." : "table."));
          return;
        }
        throw new CatalogException(errorMsg);
      }

      // Retrieve the HMS table to determine if this is a Kudu or Iceberg table.
      org.apache.hadoop.hive.metastore.api.Table msTbl = existingTbl.getMetaStoreTable();
      if (msTbl == null) {
        Preconditions.checkState(existingTbl instanceof IncompleteTable);
        Stopwatch hmsLoadSW = Stopwatch.createStarted();
        long hmsLoadTime;
        try (MetaStoreClient msClient = catalog_.getMetaStoreClient(catalogTimeline)) {
          msTbl = msClient.getHiveClient().getTable(tableName.getDb(),
              tableName.getTbl());
          catalogTimeline.markEvent(FETCHED_HMS_TABLE);
        } catch (TException e) {
          LOG.error(String.format(HMS_RPC_ERROR_FORMAT_STR, "getTable") + e.getMessage());
        } finally {
          hmsLoadTime = hmsLoadSW.elapsed(TimeUnit.NANOSECONDS);
        }
        existingTbl.updateHMSLoadTableSchemaTime(hmsLoadTime);
      }
      boolean isSynchronizedKuduTable = msTbl != null &&
              KuduTable.isKuduTable(msTbl) && KuduTable.isSynchronizedTable(msTbl);
      if (isSynchronizedKuduTable) {
        KuduCatalogOpExecutor.dropTable(
            msTbl, /* if exists */ true, kudu_table_reserve_seconds, catalogTimeline);
      }

      long eventId;
      try (MetaStoreClient msClient = catalog_.getMetaStoreClient(catalogTimeline)) {
        eventId = getCurrentEventId(msClient, catalogTimeline);
      }
      boolean isSynchronizedIcebergTable = msTbl != null &&
          IcebergTable.isIcebergTable(msTbl) &&
          IcebergTable.isSynchronizedTable(msTbl);
      // When HMS integration is automatic, the table is dropped automatically. In all
      // other cases, we need to drop the HMS table entry ourselves.
      boolean isSynchronizedTable = isSynchronizedKuduTable || isSynchronizedIcebergTable;
      boolean needsHmsDropTable =
          (existingTbl instanceof IncompleteTable && isSynchronizedIcebergTable) ||
              !isSynchronizedTable ||
              !isHmsIntegrationAutomatic(msTbl);

      if (!(existingTbl instanceof IncompleteTable) && isSynchronizedIcebergTable) {
        Preconditions.checkState(existingTbl instanceof IcebergTable);
        try {
          IcebergCatalogOpExecutor.dropTable((IcebergTable)existingTbl, params.if_exists);
          catalogTimeline.markEvent("Dropped table using Iceberg");
        } catch (TableNotFoundException e) {
          // This is unusual as normally this would have already shown up as
          // (existingTbl instanceof IncompleteTable), but this can happen if
          // for example the Iceberg metadata is removed.
          if (!needsHmsDropTable) {
            // There is no more work to be done, so throw exception.
            throw e;
          }
          // Although dropTable() failed in Iceberg we need to also drop the table in
          // HMS, so we continue here.
          LOG.warn(String.format("Could not drop Iceberg table %s.%s " +
                  "proceeding to drop table in HMS", tableName.getDb(),
              tableName.getTbl()), e);
        }
      }


      if (needsHmsDropTable) {
        try (MetaStoreClient msClient = catalog_.getMetaStoreClient(catalogTimeline)) {
          msClient.getHiveClient().dropTable(
              tableName.getDb(), tableName.getTbl(), true,
              params.if_exists, params.purge);
          catalogTimeline.markEvent("Dropped table in Metastore");
        } catch (NoSuchObjectException e) {
          throw new ImpalaRuntimeException(String.format("Table %s no longer exists " +
              "in the Hive MetaStore. Run 'invalidate metadata %s' to update the " +
              "Impala catalog.", tableName, tableName));
        } catch (TException e) {
          throw new ImpalaRuntimeException(
              String.format(HMS_RPC_ERROR_FORMAT_STR, "dropTable"), e);
        }
      }
      List<NotificationEvent> events = getNextMetastoreEventsForTableIfEnabled(
          catalogTimeline, eventId, tableName.getDb(), tableName.getTbl(),
          DropTableEvent.EVENT_TYPE);
      addSummary(resp, (params.is_table ? "Table " : "View ") + "has been dropped.");
      addToDeleteEventLog(events);
      Table table = catalog_.removeTable(params.getTable_name().db_name,
          params.getTable_name().table_name);
      catalogTimeline.markEvent("Deleted table in catalog cache");
      if (table == null) {
        // Nothing was removed from the catalogd's cache.
        resp.result.setVersion(catalog_.getCatalogVersion());
        return;
      }
      resp.result.setVersion(table.getCatalogVersion());
      uncacheTable(table, catalogTimeline);
      if (table.getMetaStoreTable() != null) {
        if (authzConfig_.isEnabled()) {
          authzManager_.updateTableOwnerPrivilege(params.server_name,
              table.getDb().getName(), table.getName(),
              table.getMetaStoreTable().getOwner(),
              table.getMetaStoreTable().getOwnerType(), /* newOwner */ null,
              /* newOwnerType */ null, resp);
        }
      }
    } finally {
      getMetastoreDdlLock().unlock();
    }
    removedObject.setType(params.is_table ?
        TCatalogObjectType.TABLE : TCatalogObjectType.VIEW);
    removedObject.setTable(new TTable());
    removedObject.getTable().setTbl_name(tableName.getTbl());
    removedObject.getTable().setDb_name(tableName.getDb());
    removedObject.setCatalog_version(resp.result.getVersion());
    resp.result.addToRemoved_catalog_objects(removedObject);
  }